diff options
Diffstat (limited to 'linux')
30 files changed, 883 insertions, 451 deletions
diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index ceb277543..dbc19ca9e 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207] + 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/linux/drivers/media/Makefile b/linux/drivers/media/Makefile index 8fa19939c..8cf91353b 100644 --- a/linux/drivers/media/Makefile +++ b/linux/drivers/media/Makefile @@ -3,6 +3,6 @@ # obj-y := common/ -obj-$(CONFIG_VIDEO_DEV) += video/ +obj-y += video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index 188bcb247..29ec9ac8f 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -42,6 +42,7 @@ struct s5h1409_state { fe_modulation_t current_modulation; u32 current_frequency; + int if_freq; u32 is_qam_locked; u32 qam_state; @@ -107,7 +108,7 @@ static struct vsb_snr_tab { u16 val; u16 data; } vsb_snr_tab[] = { - { 1023, 770, }, + { 924, 300, }, { 923, 300, }, { 918, 295, }, { 915, 290, }, @@ -154,6 +155,7 @@ static struct qam64_snr_tab { u16 val; u16 data; } qam64_snr_tab[] = { + { 1, 0, }, { 12, 300, }, { 15, 290, }, { 18, 280, }, @@ -217,6 +219,7 @@ static struct qam64_snr_tab { { 95, 202, }, { 96, 201, }, { 104, 200, }, + { 255, 0, }, }; /* QAM256 SNR lookup table */ @@ -224,6 +227,7 @@ static struct qam256_snr_tab { u16 val; u16 data; } qam256_snr_tab[] = { + { 1, 0, }, { 12, 400, }, { 13, 390, }, { 15, 380, }, @@ -292,6 +296,7 @@ static struct qam256_snr_tab { { 105, 262, }, { 106, 261, }, { 110, 260, }, + { 255, 0, }, }; /* 8 bit registers, 16 bit values */ @@ -344,28 +349,32 @@ static int s5h1409_softreset(struct dvb_frontend* fe) return 0; } +#define S5H1409_VSB_IF_FREQ 5380 +#define S5H1409_QAM_IF_FREQ state->config->qam_if + static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) { struct s5h1409_state* state = fe->demodulator_priv; - int ret = 0; dprintk("%s(%d KHz)\n", __FUNCTION__, KHz); - if( (KHz == 44000) || (KHz == 5380) ) { - s5h1409_writereg(state, 0x87, 0x01be); - s5h1409_writereg(state, 0x88, 0x0436); - s5h1409_writereg(state, 0x89, 0x054d); - } else - if (KHz == 4000) { + switch (KHz) { + case 4000: s5h1409_writereg(state, 0x87, 0x014b); s5h1409_writereg(state, 0x88, 0x0cb5); s5h1409_writereg(state, 0x89, 0x03e2); - } else { - printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz); - ret = -1; + break; + case 5380: + case 44000: + default: + s5h1409_writereg(state, 0x87, 0x01be); + s5h1409_writereg(state, 0x88, 0x0436); + s5h1409_writereg(state, 0x89, 0x054d); + break; } + state->if_freq = KHz; - return ret; + return 0; } static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) @@ -390,11 +399,15 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe, switch(m) { case VSB_8: dprintk("%s() VSB_8\n", __FUNCTION__); + if (state->if_freq != S5H1409_VSB_IF_FREQ) + s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ); s5h1409_writereg(state, 0xf4, 0); break; case QAM_64: case QAM_256: dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__); + if (state->if_freq != S5H1409_QAM_IF_FREQ) + s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ); s5h1409_writereg(state, 0xf4, 1); s5h1409_writereg(state, 0x85, 0x110); break; @@ -567,7 +580,7 @@ static int s5h1409_init (struct dvb_frontend* fe) s5h1409_writereg(state, 0xab, 0x0); /* Parallel */ s5h1409_set_spectralinversion(fe, state->config->inversion); - s5h1409_set_if_freq(fe, state->config->if_freq); + s5h1409_set_if_freq(fe, state->if_freq); s5h1409_set_gpio(fe, state->config->gpio); s5h1409_softreset(fe); @@ -670,14 +683,15 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr) u16 reg; dprintk("%s()\n", __FUNCTION__); - reg = s5h1409_readreg(state, 0xf1) & 0x1ff; - switch(state->current_modulation) { case QAM_64: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam64_lookup_snr(fe, snr, reg); case QAM_256: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam256_lookup_snr(fe, snr, reg); case VSB_8: + reg = s5h1409_readreg(state, 0xf1) & 0x3ff; return s5h1409_vsb_lookup_snr(fe, snr, reg); default: break; @@ -746,6 +760,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, state->config = config; state->i2c = i2c; state->current_modulation = 0; + state->if_freq = S5H1409_VSB_IF_FREQ; /* check if the demod exists */ if (s5h1409_readreg(state, 0x04) != 0x0066) diff --git a/linux/drivers/media/dvb/frontends/s5h1409.h b/linux/drivers/media/dvb/frontends/s5h1409.h index 20f9af1af..b1f433906 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.h +++ b/linux/drivers/media/dvb/frontends/s5h1409.h @@ -39,8 +39,8 @@ struct s5h1409_config #define S5H1409_GPIO_ON 1 u8 gpio; - /* IF Freq in KHz */ - u16 if_freq; + /* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */ + u16 qam_if; /* Spectral Inversion */ #define S5H1409_INVERSION_OFF 0 diff --git a/linux/drivers/media/dvb/frontends/tda18271.h b/linux/drivers/media/dvb/frontends/tda18271.h index d84003372..b98a9331c 100644 --- a/linux/drivers/media/dvb/frontends/tda18271.h +++ b/linux/drivers/media/dvb/frontends/tda18271.h @@ -38,7 +38,7 @@ extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct i2c_adapter *i2c, - enum tda18271_i2c_gate gate); + enum tda18271_i2c_gate gate) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 276612e00..79802e023 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -37,6 +37,8 @@ struct zl10353_state { struct dvb_frontend frontend; struct zl10353_config config; + + enum fe_bandwidth bandwidth; }; static int debug; @@ -149,7 +151,8 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, break; } - value = (bw * (u64)10 * (1 << 23) / 7 * 125 + adc_clock / 2); + value = (u64)10 * (1 << 23) / 7 * 125; + value = (bw * value) + adc_clock / 2; do_div(value, adc_clock); *nominal_rate = value; @@ -199,27 +202,156 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, { struct zl10353_state *state = fe->demodulator_priv; u16 nominal_rate, input_freq; - u8 pllbuf[6] = { 0x67 }; + u8 pllbuf[6] = { 0x67 }, acq_ctl = 0; + u16 tps = 0; + struct dvb_ofdm_parameters *op = ¶m->u.ofdm; - /* These settings set "auto-everything" and start the FSM. */ - zl10353_single_write(fe, 0x55, 0x80); + zl10353_single_write(fe, RESET, 0x80); udelay(200); zl10353_single_write(fe, 0xEA, 0x01); udelay(200); zl10353_single_write(fe, 0xEA, 0x00); - zl10353_single_write(fe, 0x56, 0x28); - zl10353_single_write(fe, 0x89, 0x20); - zl10353_single_write(fe, 0x5E, 0x00); + zl10353_single_write(fe, AGC_TARGET, 0x28); + + if (op->transmission_mode != TRANSMISSION_MODE_AUTO) + acq_ctl |= (1 << 0); + if (op->guard_interval != GUARD_INTERVAL_AUTO) + acq_ctl |= (1 << 1); + zl10353_single_write(fe, ACQ_CTL, acq_ctl); - zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate); + switch (op->bandwidth) { + case BANDWIDTH_6_MHZ: + /* These are extrapolated from the 7 and 8MHz values */ + zl10353_single_write(fe, MCLK_RATIO, 0x97); + zl10353_single_write(fe, 0x64, 0x34); + break; + case BANDWIDTH_7_MHZ: + zl10353_single_write(fe, MCLK_RATIO, 0x86); + zl10353_single_write(fe, 0x64, 0x35); + break; + case BANDWIDTH_8_MHZ: + default: + zl10353_single_write(fe, MCLK_RATIO, 0x75); + zl10353_single_write(fe, 0x64, 0x36); + } + + zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate); zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate)); zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate)); + state->bandwidth = op->bandwidth; zl10353_calc_input_freq(fe, &input_freq); zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq)); zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq)); + /* Hint at TPS settings */ + switch (op->code_rate_HP) { + case FEC_2_3: + tps |= (1 << 7); + break; + case FEC_3_4: + tps |= (2 << 7); + break; + case FEC_5_6: + tps |= (3 << 7); + break; + case FEC_7_8: + tps |= (4 << 7); + break; + case FEC_1_2: + case FEC_AUTO: + break; + default: + return -EINVAL; + } + + switch (op->code_rate_LP) { + case FEC_2_3: + tps |= (1 << 4); + break; + case FEC_3_4: + tps |= (2 << 4); + break; + case FEC_5_6: + tps |= (3 << 4); + break; + case FEC_7_8: + tps |= (4 << 4); + break; + case FEC_1_2: + case FEC_AUTO: + break; + case FEC_NONE: + if (op->hierarchy_information == HIERARCHY_AUTO || + op->hierarchy_information == HIERARCHY_NONE) + break; + default: + return -EINVAL; + } + + switch (op->constellation) { + case QPSK: + break; + case QAM_AUTO: + case QAM_16: + tps |= (1 << 13); + break; + case QAM_64: + tps |= (2 << 13); + break; + default: + return -EINVAL; + } + + switch (op->transmission_mode) { + case TRANSMISSION_MODE_2K: + case TRANSMISSION_MODE_AUTO: + break; + case TRANSMISSION_MODE_8K: + tps |= (1 << 0); + break; + default: + return -EINVAL; + } + + switch (op->guard_interval) { + case GUARD_INTERVAL_1_32: + case GUARD_INTERVAL_AUTO: + break; + case GUARD_INTERVAL_1_16: + tps |= (1 << 2); + break; + case GUARD_INTERVAL_1_8: + tps |= (2 << 2); + break; + case GUARD_INTERVAL_1_4: + tps |= (3 << 2); + break; + default: + return -EINVAL; + } + + switch (op->hierarchy_information) { + case HIERARCHY_AUTO: + case HIERARCHY_NONE: + break; + case HIERARCHY_1: + tps |= (1 << 10); + break; + case HIERARCHY_2: + tps |= (2 << 10); + break; + case HIERARCHY_4: + tps |= (3 << 10); + break; + default: + return -EINVAL; + } + + zl10353_single_write(fe, TPS_GIVEN_1, msb(tps)); + zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps)); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -248,12 +380,97 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, else zl10353_single_write(fe, TUNER_GO, 0x01); - udelay(250); - zl10353_single_write(fe, 0xE4, 0x00); - zl10353_single_write(fe, 0xE5, 0x2A); - zl10353_single_write(fe, 0xE9, 0x02); - zl10353_single_write(fe, 0xE7, 0x40); - zl10353_single_write(fe, 0xE8, 0x10); + return 0; +} + +static int zl10353_get_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct zl10353_state *state = fe->demodulator_priv; + struct dvb_ofdm_parameters *op = ¶m->u.ofdm; + int s6, s9; + u16 tps; + static const u8 tps_fec_to_api[8] = { + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_5_6, + FEC_7_8, + FEC_AUTO, + FEC_AUTO, + FEC_AUTO + }; + + s6 = zl10353_read_register(state, STATUS_6); + s9 = zl10353_read_register(state, STATUS_9); + if (s6 < 0 || s9 < 0) + return -EREMOTEIO; + if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0) + return -EINVAL; /* no FE or TPS lock */ + + tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 | + zl10353_read_register(state, TPS_RECEIVED_0); + + op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7]; + op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7]; + + switch ((tps >> 13) & 3) { + case 0: + op->constellation = QPSK; + break; + case 1: + op->constellation = QAM_16; + break; + case 2: + op->constellation = QAM_64; + break; + default: + op->constellation = QAM_AUTO; + break; + } + + op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K : + TRANSMISSION_MODE_2K; + + switch ((tps >> 2) & 3) { + case 0: + op->guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + op->guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + op->guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + op->guard_interval = GUARD_INTERVAL_1_4; + break; + default: + op->guard_interval = GUARD_INTERVAL_AUTO; + break; + } + + switch ((tps >> 10) & 7) { + case 0: + op->hierarchy_information = HIERARCHY_NONE; + break; + case 1: + op->hierarchy_information = HIERARCHY_1; + break; + case 2: + op->hierarchy_information = HIERARCHY_2; + break; + case 3: + op->hierarchy_information = HIERARCHY_4; + break; + default: + op->hierarchy_information = HIERARCHY_AUTO; + break; + } + + param->frequency = 0; + op->bandwidth = state->bandwidth; + param->inversion = INVERSION_AUTO; return 0; } @@ -448,6 +665,7 @@ static struct dvb_frontend_ops zl10353_ops = { .write = zl10353_write, .set_frontend = zl10353_set_parameters, + .get_frontend = zl10353_get_parameters, .get_tune_settings = zl10353_get_tune_settings, .read_status = zl10353_read_status, diff --git a/linux/drivers/media/dvb/frontends/zl10353_priv.h b/linux/drivers/media/dvb/frontends/zl10353_priv.h index fcad92219..055ff1f7e 100644 --- a/linux/drivers/media/dvb/frontends/zl10353_priv.h +++ b/linux/drivers/media/dvb/frontends/zl10353_priv.h @@ -46,13 +46,28 @@ enum zl10353_reg_addr { RS_ERR_CNT_0 = 0x13, RS_UBC_1 = 0x14, RS_UBC_0 = 0x15, + TPS_RECEIVED_1 = 0x1D, + TPS_RECEIVED_0 = 0x1E, + TPS_CURRENT_1 = 0x1F, + TPS_CURRENT_0 = 0x20, + RESET = 0x55, + AGC_TARGET = 0x56, + MCLK_RATIO = 0x5C, + ACQ_CTL = 0x5E, TRL_NOMINAL_RATE_1 = 0x65, TRL_NOMINAL_RATE_0 = 0x66, INPUT_FREQ_1 = 0x6C, INPUT_FREQ_0 = 0x6D, + TPS_GIVEN_1 = 0x6E, + TPS_GIVEN_0 = 0x6F, TUNER_GO = 0x70, FSM_GO = 0x71, CHIP_ID = 0x7F, + CHAN_STEP_1 = 0xE4, + CHAN_STEP_0 = 0xE5, + OFDM_LOCK_TIME = 0xE7, + FEC_LOCK_TIME = 0xE8, + ACQ_DELAY = 0xE9, }; #endif /* _ZL10353_PRIV_ */ diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 1f9efb8b3..89161e867 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -301,7 +301,6 @@ static struct i2c_client bt866_client_tmpl = .addr = 0, .adapter = NULL, .driver = &i2c_driver_bt866, - .usage_count = 0 }; static int bt866_found_proc(struct i2c_adapter *adapter, diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 3efc9465b..494afcbe6 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4481,7 +4481,11 @@ static int __init bttv_init_module(void) return ret; } #endif - return pci_register_driver(&bttv_pci_driver); + ret = pci_register_driver(&bttv_pci_driver); + if (ret < 0) + bus_unregister(&bttv_sub_bus_type); + + return ret; } static void __exit bttv_cleanup_module(void) @@ -4490,7 +4494,6 @@ static void __exit bttv_cleanup_module(void) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) bus_unregister(&bttv_sub_bus_type); #endif - return; } module_init(bttv_init_module); diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c21d21511..36e5dd22a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -86,7 +86,7 @@ static struct s5h1409_config hauppauge_generic_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_ON, - .if_freq = 44000, + .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING }; @@ -95,7 +95,7 @@ static struct s5h1409_config hauppauge_hvr1800lp_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_OFF, - .if_freq = 44000, + .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING }; diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 6e9a89da6..0ac3b6793 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -38,8 +38,10 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) +#define dprintk(level, fmt, arg...) do { \ + if (i2c_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg); \ + } while (0) #define I2C_WAIT_DELAY 32 #define I2C_WAIT_RETRY 64 @@ -78,14 +80,18 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap) } static int i2c_sendbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int last) + const struct i2c_msg *msg, int joined_rlen) { struct cx23885_i2c *bus = i2c_adap->algo_data; struct cx23885_dev *dev = bus->dev; u32 wdata, addr, ctrl; int retval, cnt; - dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); + if (joined_rlen) + dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__, + msg->len, joined_rlen); + else + dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -108,6 +114,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (msg->len > 1) ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; cx_write(bus->reg_addr, addr); cx_write(bus->reg_wdata, wdata); @@ -131,6 +139,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (cnt < msg->len - 1) ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; cx_write(bus->reg_addr, addr); cx_write(bus->reg_wdata, wdata); @@ -152,19 +162,22 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; err: - printk(" ERR: %d\n", retval); + if (i2c_debug) + printk(" ERR: %d\n", retval); return retval; } static int i2c_readbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int last) + const struct i2c_msg *msg, int joined) { struct cx23885_i2c *bus = i2c_adap->algo_data; struct cx23885_dev *dev = bus->dev; u32 ctrl, cnt; int retval; - dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); + + if (i2c_debug && !joined) + dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -180,8 +193,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, return 0; } - if (i2c_debug) - printk(" <R %02x", (msg->addr << 1) + 1); + if (i2c_debug) { + if (joined) + printk(" R"); + else + printk(" <R %02x", (msg->addr << 1) + 1); + } for(cnt = 0; cnt < msg->len; cnt++) { @@ -210,7 +227,8 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; err: - printk(" ERR: %d\n", retval); + if (i2c_debug) + printk(" ERR: %d\n", retval); return retval; } @@ -228,15 +246,22 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, __FUNCTION__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read */ - retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num); + retval = i2c_readbytes(i2c_adap, &msgs[i], 0); + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) { + /* write then read from same address */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], + msgs[i + 1].len); if (retval < 0) goto err; + i++; + retval = i2c_readbytes(i2c_adap, &msgs[i], 1); } else { /* write */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num); - if (retval < 0) - goto err; + retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); } + if (retval < 0) + goto err; } return num; diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index ceb31d4a2..49d3813a9 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -8,6 +8,7 @@ config VIDEO_CX88 select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR + select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Conexant 2388x based TV cards. diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 0440a5603..8ef0ee322 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -546,11 +546,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) dprintk(1,"Initialize codec\n"); retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { + + dev->mpeg_active = 0; + /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ - msleep(1); cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ - msleep(1); retval = blackbird_load_firmware(dev); if (retval < 0) return retval; @@ -572,7 +573,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) } dprintk(0, "Firmware version is 0x%08x\n", version); } - msleep(1); cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ @@ -580,40 +580,68 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ blackbird_codec_settings(dev); - msleep(1); - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); - blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); - blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115 ); - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - /* initialize the video input */ - blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); + return 0; +} - msleep(1); +static int blackbird_start_codec(struct file *file, void *priv) +{ + struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; + struct cx88_core *core = dev->core; + /* start capturing to the host interface */ + u32 reg; - blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); - msleep(1); - blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); - msleep(1); + int i; + int lastchange = -1; + int lastval = 0; + + for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) { + reg = cx_read(AUD_STATUS); + + dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg); + if ((reg & 0x0F) != lastval) { + lastval = reg & 0x0F; + lastchange = i; + } + msleep(100); + } + + /* unmute audio source */ + cx_clear(AUD_VOL_CTL, (1 << 6)); + + blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0); + + /* initialize the video input */ + blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); /* start capturing to the host interface */ - /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */ blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); - msleep(10); - blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); + dev->mpeg_active = 1; + return 0; +} + +static int blackbird_stop_codec(struct cx8802_dev *dev) +{ + blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + BLACKBIRD_END_NOW, + BLACKBIRD_MPEG_CAPTURE, + BLACKBIRD_RAW_BITS_NONE + ); + + dev->mpeg_active = 0; return 0; } @@ -859,6 +887,10 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; + + if (dev->mpeg_active) + blackbird_stop_codec(dev); + p = dev->params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); if (!err) { @@ -890,10 +922,9 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; - blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - BLACKBIRD_END_NOW, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE); + if (dev->mpeg_active) + blackbird_stop_codec(dev); + cx88_set_freq (core,f); blackbird_initialize_codec(dev); cx88_set_scale(dev->core, dev->width, dev->height, @@ -1099,15 +1130,11 @@ static int mpeg_open(struct inode *inode, struct file *file) static int mpeg_release(struct inode *inode, struct file *file) { struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = NULL; + struct cx8802_dev *dev = fh->dev; struct cx8802_driver *drv = NULL; - /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ - blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - BLACKBIRD_END_NOW, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE - ); + if (dev->mpeg_active) + blackbird_stop_codec(dev); cx8802_cancel_buffers(fh->dev); /* stop mpeg capture */ @@ -1133,6 +1160,10 @@ static ssize_t mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { struct cx8802_fh *fh = file->private_data; + struct cx8802_dev *dev = fh->dev; + + if (!dev->mpeg_active) + blackbird_start_codec(file, fh); return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); @@ -1311,6 +1342,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) core->name); host_setup(dev->core); + blackbird_initialize_codec(dev); blackbird_register_video(dev); /* initial device configuration: needed ? */ diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 9c76afeb8..ec4133254 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -316,22 +316,22 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000bde2, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x0000bde6, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000bde6, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x0000bd62, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -392,7 +392,7 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, @@ -563,7 +563,7 @@ static const struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .extadc = 1, + .audioroute = 1, }}, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -686,22 +686,22 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x00009d80, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00009d76, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x00009d76, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x00009d00, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -840,23 +840,23 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 0, .gpio0 = 0x0000cd73, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 1, .gpio0 = 0x0000cd73, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_TELEVISION, .vmux = 3, .gpio0 = 0x0000cdb3, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .vmux = 2, .gpio0 = 0x0000cdf3, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -1124,12 +1124,12 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x3de6, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x3de6, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, @@ -1386,17 +1386,17 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 2, }}, /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 14b026820..ef795d353 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -408,13 +408,41 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) break; } - if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { - /* sets sound input from external adc */ - if (INPUT(input).extadc) + /* if there are audioroutes defined, we have an external + ADC to deal with audio */ + + if (INPUT(input).audioroute) { + + /* cx2388's C-ADC is connected to the tuner only. + When used with S-Video, that ADC is busy dealing with + chroma, so an external must be used for baseband audio */ + + if (INPUT(input).type != CX88_VMUX_TELEVISION && + INPUT(input).type != CX88_RADIO) { + /* "ADC mode" */ + cx_write(AUD_I2SCNTL, 0x1); cx_set(AUD_CTL, EN_I2SIN_ENABLE); - else + } else { + /* Normal mode */ + cx_write(AUD_I2SCNTL, 0x0); cx_clear(AUD_CTL, EN_I2SIN_ENABLE); + } + + /* The wm8775 module has the "2" route hardwired into + the initialization. Some boards may use different + routes for different inputs. HVR-1300 surely does */ + if (core->board.audio_chip && + core->board.audio_chip == AUDIO_CHIP_WM8775) { + struct v4l2_routing route; + + route.input = INPUT(input).audioroute; + cx88_call_i2c_clients(core, + VIDIOC_INT_S_AUDIO_ROUTING, &route); + + } + } + return 0; } EXPORT_SYMBOL(cx88_video_mux); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 1f294c70d..0f32cbfbb 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -231,7 +231,7 @@ struct cx88_input { enum cx88_itype type; u32 gpio0, gpio1, gpio2, gpio3; unsigned int vmux:2; - unsigned int extadc:1; + unsigned int audioroute:2; }; struct cx88_board { @@ -494,6 +494,7 @@ struct cx8802_dev { u32 mailbox; int width; int height; + unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ /* mpeg params */ struct cx2341x_mpeg_params params; diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 7bca01008..809cc0a4a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -330,7 +330,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90", + .name = "Pinnacle Dazzle DVC 90/DVC 100", .vchannels = 3, .has_tuner = 0, .decoder = EM28XX_SAA7113, @@ -417,6 +417,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, + { USB_DEVICE(0x2304, 0x021a), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x2040, 0x6513), diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c index 43ba5e63d..466e80b7f 100644 --- a/linux/drivers/media/video/et61x251/et61x251_core.c +++ b/linux/drivers/media/video/et61x251/et61x251_core.c @@ -268,72 +268,6 @@ et61x251_i2c_wait(struct et61x251_device* cam, } -static int et61x251_i2c_try_read(struct et61x251_device* cam, - const struct et61x251_sensor* sensor, - u8 address) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x10; - data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - if (err) - DBG(3, "I2C read failed for %s image sensor", sensor->name); - - PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); - - return err ? -1 : (int)data[0]; -} - - -static int et61x251_i2c_try_write(struct et61x251_device* cam, - const struct et61x251_sensor* sensor, - u8 address, u8 value) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x12; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - data[0] = value; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); - - return err ? -1 : 0; -} - - int et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, @@ -386,18 +320,6 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, } -static int et61x251_i2c_read(struct et61x251_device* cam, u8 address) -{ - return et61x251_i2c_try_read(cam, &cam->sensor, address); -} - - -static int et61x251_i2c_write(struct et61x251_device* cam, - u8 address, u8 value) -{ - return et61x251_i2c_try_write(cam, &cam->sensor, address, value); -} - /*****************************************************************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) @@ -679,6 +601,83 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) /*****************************************************************************/ #ifdef CONFIG_VIDEO_ADV_DEBUG + +static int et61x251_i2c_try_read(struct et61x251_device* cam, + const struct et61x251_sensor* sensor, + u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x10; + data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C read failed for %s image sensor", sensor->name); + + PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); + + return err ? -1 : (int)data[0]; +} + + +static int et61x251_i2c_try_write(struct et61x251_device* cam, + const struct et61x251_sensor* sensor, + u8 address, u8 value) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x12; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = value; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + if (err) + DBG(3, "I2C write failed for %s image sensor", sensor->name); + + PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); + + return err ? -1 : 0; +} + +static int et61x251_i2c_read(struct et61x251_device* cam, u8 address) +{ + return et61x251_i2c_try_read(cam, &cam->sensor, address); +} + +static int et61x251_i2c_write(struct et61x251_device* cam, + u8 address, u8 value) +{ + return et61x251_i2c_try_write(cam, &cam->sensor, address, value); +} + static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) { char str[5]; diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index bd4173e41..8377facca 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -13,6 +13,7 @@ #endif #include <media/v4l2-common.h> #include <media/tuner.h> +#include "tuner-driver.h" #include "tuner-i2c.h" #include "tda9887.h" @@ -25,25 +26,20 @@ Used as part of several tuners */ -static int tda9887_debug; -module_param_named(debug, tda9887_debug, int, 0644); +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ - i2c_adapter_id(priv->t->i2c->adapter), \ - priv->t->i2c->addr, ##arg); } while (0) -#define tda9887_dbg(fmt, arg...) do {\ - if (tda9887_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ - i2c_adapter_id(priv->t->i2c->adapter), \ - priv->t->i2c->addr, ##arg); } while (0) +#define PREFIX "tda9887" struct tda9887_priv { struct tuner_i2c_props i2c_props; unsigned char data[4]; - - struct tuner *t; + unsigned int config; + unsigned int mode; + unsigned int audmode; + v4l2_std_id std; }; /* ---------------------------------------------------------------------- */ @@ -296,12 +292,12 @@ static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf) "+ 37.5 kHz", "+ 12.5 kHz", }; - tda9887_info("read: 0x%2x\n", buf[0]); - tda9887_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); - tda9887_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); - tda9887_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); - tda9887_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); - tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); + tuner_info("read: 0x%2x\n", buf[0]); + tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); + tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); + tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); + tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); + tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) @@ -346,58 +342,60 @@ static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) "44 MHz", }; - tda9887_info("write: byte B 0x%02x\n",buf[1]); - tda9887_info(" B0 video mode : %s\n", - (buf[1] & 0x01) ? "video trap" : "sound trap"); - tda9887_info(" B1 auto mute fm : %s\n", - (buf[1] & 0x02) ? "yes" : "no"); - tda9887_info(" B2 carrier mode : %s\n", - (buf[1] & 0x04) ? "QSS" : "Intercarrier"); - tda9887_info(" B3-4 tv sound/radio : %s\n", - sound[(buf[1] & 0x18) >> 3]); - tda9887_info(" B5 force mute audio: %s\n", - (buf[1] & 0x20) ? "yes" : "no"); - tda9887_info(" B6 output port 1 : %s\n", - (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); - tda9887_info(" B7 output port 2 : %s\n", - (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); - - tda9887_info("write: byte C 0x%02x\n",buf[2]); - tda9887_info(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]); - tda9887_info(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]); - tda9887_info(" C7 audio gain : %s\n", - (buf[2] & 0x80) ? "-6" : "0"); - - tda9887_info("write: byte E 0x%02x\n",buf[3]); - tda9887_info(" E0-1 sound carrier : %s\n", - carrier[(buf[3] & 0x03)]); - tda9887_info(" E6 l pll gating : %s\n", - (buf[3] & 0x40) ? "36" : "13"); + tuner_info("write: byte B 0x%02x\n", buf[1]); + tuner_info(" B0 video mode : %s\n", + (buf[1] & 0x01) ? "video trap" : "sound trap"); + tuner_info(" B1 auto mute fm : %s\n", + (buf[1] & 0x02) ? "yes" : "no"); + tuner_info(" B2 carrier mode : %s\n", + (buf[1] & 0x04) ? "QSS" : "Intercarrier"); + tuner_info(" B3-4 tv sound/radio : %s\n", + sound[(buf[1] & 0x18) >> 3]); + tuner_info(" B5 force mute audio: %s\n", + (buf[1] & 0x20) ? "yes" : "no"); + tuner_info(" B6 output port 1 : %s\n", + (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); + tuner_info(" B7 output port 2 : %s\n", + (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); + + tuner_info("write: byte C 0x%02x\n", buf[2]); + tuner_info(" C0-4 top adjustment : %s dB\n", + adjust[buf[2] & 0x1f]); + tuner_info(" C5-6 de-emphasis : %s\n", + deemph[(buf[2] & 0x60) >> 5]); + tuner_info(" C7 audio gain : %s\n", + (buf[2] & 0x80) ? "-6" : "0"); + + tuner_info("write: byte E 0x%02x\n", buf[3]); + tuner_info(" E0-1 sound carrier : %s\n", + carrier[(buf[3] & 0x03)]); + tuner_info(" E6 l pll gating : %s\n", + (buf[3] & 0x40) ? "36" : "13"); if (buf[1] & 0x08) { /* radio */ - tda9887_info(" E2-4 video if : %s\n", - rif[(buf[3] & 0x0c) >> 2]); - tda9887_info(" E7 vif agc output : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio") - : "fm radio carrier afc"); + tuner_info(" E2-4 video if : %s\n", + rif[(buf[3] & 0x0c) >> 2]); + tuner_info(" E7 vif agc output : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x10) ? "fm-agc radio" : + "sif-agc radio") + : "fm radio carrier afc"); } else { /* video */ - tda9887_info(" E2-4 video if : %s\n", - vif[(buf[3] & 0x1c) >> 2]); - tda9887_info(" E5 tuner gain : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x20) ? "external" : "normal") - : ((buf[3] & 0x20) ? "minimum" : "normal")); - tda9887_info(" E7 vif agc output : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x20) - ? "pin3 port, pin22 vif agc out" - : "pin22 port, pin3 vif acg ext in") - : "pin3+pin22 port"); + tuner_info(" E2-4 video if : %s\n", + vif[(buf[3] & 0x1c) >> 2]); + tuner_info(" E5 tuner gain : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x20) ? "external" : "normal") + : ((buf[3] & 0x20) ? "minimum" : "normal")); + tuner_info(" E7 vif agc output : %s\n", + (buf[3] & 0x80) ? ((buf[3] & 0x20) + ? "pin3 port, pin22 vif agc out" + : "pin22 port, pin3 vif acg ext in") + : "pin3+pin22 port"); } - tda9887_info("--\n"); + tuner_info("--\n"); } /* ---------------------------------------------------------------------- */ @@ -405,30 +403,29 @@ static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) static int tda9887_set_tvnorm(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; struct tvnorm *norm = NULL; char *buf = priv->data; int i; - if (t->mode == V4L2_TUNER_RADIO) { - if (t->audmode == V4L2_TUNER_MODE_MONO) + if (priv->mode == V4L2_TUNER_RADIO) { + if (priv->audmode == V4L2_TUNER_MODE_MONO) norm = &radio_mono; else norm = &radio_stereo; } else { for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { - if (tvnorms[i].std & t->std) { + if (tvnorms[i].std & priv->std) { norm = tvnorms+i; break; } } } if (NULL == norm) { - tda9887_dbg("Unsupported tvnorm entry - audio muted\n"); + tuner_dbg("Unsupported tvnorm entry - audio muted\n"); return -1; } - tda9887_dbg("configure for: %s\n",norm->name); + tuner_dbg("configure for: %s\n", norm->name); buf[1] = norm->b; buf[2] = norm->c; buf[3] = norm->e; @@ -484,31 +481,30 @@ static int tda9887_set_insmod(struct dvb_frontend *fe) return 0; } -static int tda9887_set_config(struct dvb_frontend *fe) +static int tda9887_do_config(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; char *buf = priv->data; - if (t->tda9887_config & TDA9887_PORT1_ACTIVE) + if (priv->config & TDA9887_PORT1_ACTIVE) buf[1] &= ~cOutputPort1Inactive; - if (t->tda9887_config & TDA9887_PORT1_INACTIVE) + if (priv->config & TDA9887_PORT1_INACTIVE) buf[1] |= cOutputPort1Inactive; - if (t->tda9887_config & TDA9887_PORT2_ACTIVE) + if (priv->config & TDA9887_PORT2_ACTIVE) buf[1] &= ~cOutputPort2Inactive; - if (t->tda9887_config & TDA9887_PORT2_INACTIVE) + if (priv->config & TDA9887_PORT2_INACTIVE) buf[1] |= cOutputPort2Inactive; - if (t->tda9887_config & TDA9887_QSS) + if (priv->config & TDA9887_QSS) buf[1] |= cQSS; - if (t->tda9887_config & TDA9887_INTERCARRIER) + if (priv->config & TDA9887_INTERCARRIER) buf[1] &= ~cQSS; - if (t->tda9887_config & TDA9887_AUTOMUTE) + if (priv->config & TDA9887_AUTOMUTE) buf[1] |= cAutoMuteFmActive; - if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { + if (priv->config & TDA9887_DEEMPHASIS_MASK) { buf[2] &= ~0x60; - switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { + switch (priv->config & TDA9887_DEEMPHASIS_MASK) { case TDA9887_DEEMPHASIS_NONE: buf[2] |= cDeemphasisOFF; break; @@ -520,21 +516,22 @@ static int tda9887_set_config(struct dvb_frontend *fe) break; } } - if (t->tda9887_config & TDA9887_TOP_SET) { + if (priv->config & TDA9887_TOP_SET) { buf[2] &= ~cTopMask; - buf[2] |= (t->tda9887_config >> 8) & cTopMask; + buf[2] |= (priv->config >> 8) & cTopMask; } - if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) + if ((priv->config & TDA9887_INTERCARRIER_NTSC) && + (priv->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; - if (t->tda9887_config & TDA9887_GATING_18) + if (priv->config & TDA9887_GATING_18) buf[3] &= ~cGating_36; - if (t->mode == V4L2_TUNER_RADIO) { - if (t->tda9887_config & TDA9887_RIF_41_3) { + if (priv->mode == V4L2_TUNER_RADIO) { + if (priv->config & TDA9887_RIF_41_3) { buf[3] &= ~cVideoIFMask; buf[3] |= cRadioIF_41_30; } - if (t->tda9887_config & TDA9887_GAIN_NORMAL) + if (priv->config & TDA9887_GAIN_NORMAL) buf[3] &= ~cTunerGainLow; } @@ -551,7 +548,7 @@ static int tda9887_status(struct dvb_frontend *fe) memset(buf,0,sizeof(buf)); if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) - tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc); dump_read_message(fe, buf); return 0; } @@ -559,7 +556,6 @@ static int tda9887_status(struct dvb_frontend *fe) static void tda9887_configure(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; int rc; memset(priv->data,0,sizeof(priv->data)); @@ -581,22 +577,21 @@ static void tda9887_configure(struct dvb_frontend *fe) priv->data[1] |= cOutputPort1Inactive; priv->data[1] |= cOutputPort2Inactive; - tda9887_set_config(fe); + tda9887_do_config(fe); tda9887_set_insmod(fe); - if (t->mode == T_STANDBY) { + if (priv->mode == T_STANDBY) priv->data[1] |= cForcedMuteAudioON; - } - tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - priv->data[1],priv->data[2],priv->data[3]); - if (tda9887_debug > 1) + tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", + priv->data[1], priv->data[2], priv->data[3]); + if (debug > 1) dump_write_message(fe, priv->data); if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) - tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); + tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc); - if (tda9887_debug > 2) { + if (debug > 2) { msleep_interruptible(1000); tda9887_status(fe); } @@ -607,8 +602,8 @@ static void tda9887_configure(struct dvb_frontend *fe) static void tda9887_tuner_status(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", - priv->data[1], priv->data[2], priv->data[3]); + tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", + priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct dvb_frontend *fe) @@ -631,15 +626,34 @@ static int tda9887_get_afc(struct dvb_frontend *fe) static void tda9887_standby(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->mode = T_STANDBY; + tda9887_configure(fe); } static void tda9887_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->mode = params->mode; + priv->audmode = params->audmode; + priv->std = params->std; tda9887_configure(fe); } +static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->config = *(unsigned int *)priv_cfg; + tda9887_configure(fe); + + return 0; +} + static void tda9887_release(struct dvb_frontend *fe) { kfree(fe->analog_demod_priv); @@ -655,29 +669,29 @@ static struct analog_tuner_ops tda9887_tuner_ops = { .tuner_status = tda9887_tuner_status, .get_afc = tda9887_get_afc, .release = tda9887_release, + .set_config = tda9887_set_config, }; -int tda9887_attach(struct tuner *t) +struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr) { struct tda9887_priv *priv = NULL; priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); if (priv == NULL) - return -ENOMEM; - t->fe.analog_demod_priv = priv; + return NULL; + fe->analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c->addr; - priv->i2c_props.adap = t->i2c->adapter; - priv->t = t; + priv->i2c_props.addr = i2c_addr; + priv->i2c_props.adap = i2c_adap; + priv->mode = T_STANDBY; - strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name)); + tuner_info("tda988[5/6/7] found\n"); - tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c->addr, - t->i2c->driver->driver.name); + fe->ops.analog_demod_ops = &tda9887_tuner_ops; - t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; - - return 0; + return fe; } EXPORT_SYMBOL_GPL(tda9887_attach); diff --git a/linux/drivers/media/video/tda9887.h b/linux/drivers/media/video/tda9887.h index b879f0ec2..8f873a8e6 100644 --- a/linux/drivers/media/video/tda9887.h +++ b/linux/drivers/media/video/tda9887.h @@ -17,16 +17,21 @@ #ifndef __TDA9887_H__ #define __TDA9887_H__ -#include "tuner-driver.h" +#include <linux/i2c.h> +#include "dvb_frontend.h" /* ------------------------------------------------------------------------ */ #if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE)) -extern int tda9887_attach(struct tuner *t); +extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr); #else -static inline int tda9887_attach(struct tuner *t) +static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); - return -EINVAL; + return NULL; } #endif diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 479afb1f6..73976746b 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -41,6 +41,27 @@ #define PREFIX t->i2c->driver->driver.name #endif +struct tuner { + /* device */ + struct dvb_frontend fe; + struct i2c_client *i2c; + struct list_head list; + unsigned int using_v4l2:1; + + /* keep track of the current settings */ + v4l2_std_id std; + unsigned int tv_freq; + unsigned int radio_freq; + unsigned int audmode; + + unsigned int mode; + unsigned int mode_mask; /* Combination of allowable modes */ + + unsigned int type; /* chip type id */ + unsigned int config; + int (*tuner_callback) (void *dev, int command, int arg); +}; + /* standard i2c insmod options */ static unsigned short normal_i2c[] = { #if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) @@ -183,6 +204,19 @@ static int fe_has_signal(struct dvb_frontend *fe) return strength; } +static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; + struct tuner *t = fe->analog_demod_priv; + + if (fe_tuner_ops->set_config) + return fe_tuner_ops->set_config(fe, priv_cfg); + + tuner_warn("Tuner frontend module has no way to set config\n"); + + return 0; +} + static void tuner_status(struct dvb_frontend *fe); static struct analog_tuner_ops tuner_core_ops = { @@ -190,6 +224,7 @@ static struct analog_tuner_ops tuner_core_ops = { .standby = fe_standby, .release = fe_release, .has_signal = fe_has_signal, + .set_config = fe_set_config, .tuner_status = tuner_status }; @@ -423,7 +458,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TDA9887: - tda9887_attach(t); + tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr); break; default: attach_simple_tuner(t); @@ -863,25 +898,19 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) #endif case TUNER_SET_CONFIG: { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; struct v4l2_priv_tun_config *cfg = arg; if (t->type != cfg->tuner) break; - if (t->type == TUNER_TDA9887) { - t->tda9887_config = *(unsigned int *)cfg->priv; - set_freq(client, t->tv_freq); - break; - } - - if (NULL == fe_tuner_ops->set_config) { + if ((NULL == ops) || (NULL == ops->set_config)) { tuner_warn("Tuner frontend module has no way to " "set config\n"); break; } - fe_tuner_ops->set_config(&t->fe, cfg->priv); + ops->set_config(&t->fe, cfg->priv); break; } /* --- v4l ioctls --- */ diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 65ced4350..5eaa30ccb 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -22,8 +22,6 @@ #ifndef __TUNER_DRIVER_H__ #define __TUNER_DRIVER_H__ -#include <linux/videodev2.h> -#include <linux/i2c.h> #include "dvb_frontend.h" extern unsigned const int tuner_count; @@ -45,32 +43,9 @@ struct analog_tuner_ops { void (*standby)(struct dvb_frontend *fe); void (*release)(struct dvb_frontend *fe); int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable); -}; - -struct tuner { - /* device */ - struct i2c_client *i2c; - struct list_head list; /* list of tuners */ - - unsigned int type; /* chip type */ - - unsigned int mode; - unsigned int mode_mask; /* Combination of allowable modes */ - - unsigned int tv_freq; /* keep track of the current settings */ - unsigned int radio_freq; - unsigned int audmode; - v4l2_std_id std; - - int using_v4l2; - - struct dvb_frontend fe; - - /* used by tda9887 */ - unsigned int tda9887_config; - unsigned int config; - int (*tuner_callback) (void *dev, int command,int arg); + /** This is to allow setting tuner-specific configuration */ + int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); }; #endif /* __TUNER_DRIVER_H__ */ diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 745673be6..133ab1cfe 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -159,7 +159,8 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) return 0; } -void dump_firm_type(unsigned int type) +#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) +void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) { if (type & BASE) printk("BASE "); @@ -221,6 +222,8 @@ void dump_firm_type(unsigned int type) printk("INPUT2 "); if (type & SCODE) printk("SCODE "); + if (type & HAS_IF) + printk("HAS_IF_%d ", int_freq); } static v4l2_std_id parse_audio_std_option(void) @@ -365,9 +368,9 @@ static int load_all_firmwares(struct dvb_frontend *fe) } tuner_dbg("Reading firmware type "); if (debug) { - dump_firm_type(type); + dump_firm_type_and_int_freq(type, int_freq); printk("(%x), id %llx, size=%d.\n", - type, (unsigned long long)id, size); + type, (unsigned long long)id, size); } memcpy(priv->firm[n].ptr, p, size); @@ -604,7 +607,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, } else { for (pos = 0; pos < priv->firm_size; pos++) { if ((priv->firm[pos].int_freq == int_freq) && - (type & HAS_IF)) + (priv->firm[pos].type & HAS_IF)) break; } if (pos == priv->firm_size) @@ -613,7 +616,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, p = priv->firm[pos].ptr; - if (type & HAS_IF) { + if (priv->firm[pos].type & HAS_IF) { if (priv->firm[pos].size != 12 * 16 || scode >= 16) return -EINVAL; p += 12 * scode; @@ -627,7 +630,8 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, } tuner_info("Loading SCODE for type="); - dump_firm_type(priv->firm[pos].type); + dump_firm_type_and_int_freq(priv->firm[pos].type, + priv->firm[pos].int_freq); printk("(%x), id %016llx.\n", priv->firm[pos].type, (unsigned long long)*id); @@ -685,11 +689,15 @@ retry: tuner_dbg("checking firmware, user requested type="); if (debug) { dump_firm_type(new_fw.type); - printk("(%x), id %016llx, scode_tbl ", new_fw.type, + printk("(%x), id %016llx, ", new_fw.type, (unsigned long long)new_fw.std_req); - dump_firm_type(priv->ctrl.scode_table); - printk("(%x), scode_nr %d\n", priv->ctrl.scode_table, - new_fw.scode_nr); + if (!int_freq) { + printk("scode_tbl "); + dump_firm_type(priv->ctrl.scode_table); + printk("(%x), ", priv->ctrl.scode_table); + } else + printk("int_freq %d, ", new_fw.int_freq); + printk("scode_nr %d\n", new_fw.scode_nr); } /* No need to reload base firmware if it matches */ @@ -880,9 +888,18 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, */ if (new_mode == T_ANALOG_TV) { rc = send_seq(priv, {0x00, 0x00}); - } else { + } else if (!(priv->cur_fw.type & ATSC)) { offset = 2750000; - if (priv->cur_fw.type & DTV7) + /* + * 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. + */ + if (((priv->cur_fw.type & DTV7) && + (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) || + ((priv->cur_fw.type & DTV78) && freq < 470000000)) offset -= 500000; } @@ -963,6 +980,7 @@ static int xc2028_set_params(struct dvb_frontend *fe, struct xc2028_data *priv = fe->tuner_priv; unsigned int type=0; fe_bandwidth_t bw = BANDWIDTH_8_MHZ; + u16 demod = 0; tuner_dbg("%s called\n", __FUNCTION__); @@ -985,27 +1003,37 @@ static int xc2028_set_params(struct dvb_frontend *fe, break; case FE_ATSC: bw = BANDWIDTH_6_MHZ; + /* The only ATSC firmware (at least on v2.7) is D2633, + so overrides ctrl->d2633 */ type |= ATSC| D2633; + type &= ~D2620; break; /* DVB-S is not supported */ default: return -EINVAL; } - /* FIXME: - There are two Scodes that will never be selected: - DTV78 ZARLINK456, DTV78 DIBCOM52 - When it should opt for DTV78 instead of DTV7 or DTV8? - */ switch (bw) { case BANDWIDTH_8_MHZ: - type |= DTV8 | F8MHZ; + if (p->frequency < 470000000) + priv->ctrl.vhfbw7 = 0; + else + priv->ctrl.uhfbw8 = 1; + type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8; + type |= F8MHZ; break; case BANDWIDTH_7_MHZ: - type |= DTV7 | F8MHZ; + if (p->frequency < 470000000) + priv->ctrl.vhfbw7 = 1; + else + priv->ctrl.uhfbw8 = 0; + type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7; + type |= F8MHZ; break; case BANDWIDTH_6_MHZ: - type |= DTV6 ; + type |= DTV6; + priv->ctrl.vhfbw7 = 0; + priv->ctrl.uhfbw8 = 0; break; default: tuner_err("error: bandwidth not supported.\n"); @@ -1013,10 +1041,10 @@ static int xc2028_set_params(struct dvb_frontend *fe, /* All S-code tables need a 200kHz shift */ if (priv->ctrl.demod) - priv->ctrl.demod += 200; + demod = priv->ctrl.demod + 200; return generic_set_freq(fe, p->frequency, - T_DIGITAL_TV, type, 0, priv->ctrl.demod); + T_DIGITAL_TV, type, 0, demod); } static int xc2028_sleep(struct dvb_frontend *fe) diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h index 1fe8b1959..7462629b9 100644 --- a/linux/drivers/media/video/tuner-xc2028.h +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -30,6 +30,8 @@ struct xc2028_ctrl { unsigned int mts :1; unsigned int d2633 :1; unsigned int input1:1; + unsigned int vhfbw7:1; + unsigned int uhfbw8:1; unsigned int demod; }; diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 996203969..96fcd5987 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -1611,13 +1611,10 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, if (len > 8) { return -EFAULT; } -// down(&usbvision->ctrlUrbLock); if (usbvision->ctrlUrbBusy) { -// up(&usbvision->ctrlUrbLock); return -EBUSY; } usbvision->ctrlUrbBusy = 1; -// up(&usbvision->ctrlUrbLock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) usbvision->ctrlUrbSetup.requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 04a38c355..385b4709a 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1339,7 +1339,8 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) errCode = usbvision_set_alternate(usbvision); if (errCode < 0) { usbvision->last_error = errCode; - return -EBUSY; + errCode = -EBUSY; + goto out; } // If so far no errors then we shall start the radio @@ -1359,6 +1360,7 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) usbvision->initialized = 0; } } +out: mutex_unlock(&usbvision->lock); return errCode; } @@ -1806,7 +1808,6 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) goto err_exit; } init_waitqueue_head(&usbvision->ctrlUrb_wq); - init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ usbvision_init_powerOffTimer(usbvision); @@ -1964,6 +1965,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->num_alt,GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { err("usbvision: out of memory!\n"); + mutex_unlock(&usbvision->lock); return -ENOMEM; } diff --git a/linux/drivers/media/video/usbvision/usbvision.h b/linux/drivers/media/video/usbvision/usbvision.h index 3b3f1ca0e..9f4c40dbf 100644 --- a/linux/drivers/media/video/usbvision/usbvision.h +++ b/linux/drivers/media/video/usbvision/usbvision.h @@ -373,7 +373,6 @@ struct usb_usbvision { int ctrlUrbBusy; struct usb_ctrlrequest ctrlUrbSetup; wait_queue_head_t ctrlUrb_wq; // Processes waiting - struct semaphore ctrlUrbLock; /* configuration part */ int have_tuner; diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index a85b22147..1f6f20f46 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -813,7 +813,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* Locking: Caller holds q->lock */ -int __videobuf_read_start(struct videobuf_queue *q) +static int __videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; unsigned long flags = 0; @@ -916,7 +916,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->streaming) goto done; if (!q->reading) { - retval = videobuf_read_start(q); + retval = __videobuf_read_start(q); if (retval < 0) goto done; } @@ -989,7 +989,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer, stream); } else { if (!q->reading) - videobuf_read_start(q); + __videobuf_read_start(q); if (!q->reading) { rc = POLLERR; } else if (NULL == q->read_buf) { diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c index c3858dc82..7aed73ee4 100644 --- a/linux/drivers/media/video/videodev.c +++ b/linux/drivers/media/video/videodev.c @@ -1010,7 +1010,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, *id = vfd->current_norm; - dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); ret=0; break; @@ -1019,7 +1019,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, { v4l2_std_id *id = arg,norm; - dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); norm = (*id) & vfd->tvnorms; if ( vfd->tvnorms && !norm) /* Check if std is supported */ @@ -1045,7 +1045,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, break; ret=vfd->vidioc_querystd(file, fh, arg); if (!ret) - dbgarg (cmd, "detected std=%Lu\n", + dbgarg (cmd, "detected std=%08Lx\n", (unsigned long long)*p); break; } @@ -1065,7 +1065,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, if (!ret) dbgarg (cmd, "index=%d, name=%s, type=%d, " "audioset=%d, " - "tuner=%d, std=%Ld, status=%d\n", + "tuner=%d, std=%08Lx, status=%d\n", p->index,p->name,p->type,p->audioset, p->tuner, (unsigned long long)p->std, diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 02e44ab91..0305589d1 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -63,7 +63,6 @@ /* Declare static vars that will be used as parameters */ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static struct video_device vivi; /* Video device */ static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ static int n_devs = 1; /* Number of virtual devices */ @@ -119,9 +118,9 @@ static struct v4l2_queryctrl vivi_qctrl[] = { static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -#define dprintk(level, fmt, arg...) \ +#define dprintk(dev, level, fmt, arg...) \ do { \ - if (vivi.debug >= (level)) \ + if (dev->vfd->debug >= (level)) \ printk(KERN_DEBUG "vivi: " fmt , ## arg); \ } while (0) @@ -181,6 +180,7 @@ struct vivi_dev { #else struct semaphore lock; #endif + spinlock_t slock; int users; @@ -355,7 +355,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) dev->timestr); /* FIXME: replacing to __copy_to_user */ if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0) - dprintk(2, "vivifill copy_to_user failed.\n"); + dprintk(dev, 2, "vivifill copy_to_user failed.\n"); pos += wmax*2; } @@ -384,8 +384,8 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) sprintf(dev->timestr, "%02d:%02d:%02d:%03d", dev->h, dev->m, dev->s, (dev->us + 500) / 1000); - dprintk(2, "vivifill at %s: Buffer 0x%08lx size= %d\n", dev->timestr, - (unsigned long)tmpbuf, pos); + dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", + dev->timestr, (unsigned long)tmpbuf, pos); /* Advice that buffer was filled */ buf->vb.state = VIDEOBUF_DONE; @@ -406,10 +406,11 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) int bc; + spin_lock(&dev->slock); /* Announces videobuf that all went ok */ for (bc = 0;; bc++) { if (list_empty(&dma_q->active)) { - dprintk(1, "No active queue to serve\n"); + dprintk(dev, 1, "No active queue to serve\n"); break; } @@ -419,11 +420,12 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) /* Nobody is waiting something to be done, just return */ if (!waitqueue_active(&buf->vb.done)) { mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + spin_unlock(&dev->slock); return; } do_gettimeofday(&buf->vb.ts); - dprintk(2, "[%p/%d] wakeup\n", buf, buf->vb. i); + dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); /* Fill buffer */ vivi_fillbuff(dev, buf); @@ -435,53 +437,67 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) } } if (bc != 1) - dprintk(1, "%s: %d buffers handled (should be 1)\n", + dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n", __FUNCTION__, bc); + spin_unlock(&dev->slock); } +#define frames_to_ms(frames) \ + ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) + static void vivi_sleep(struct vivi_dmaqueue *dma_q) { - int timeout; + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + int timeout, running_time; DECLARE_WAITQUEUE(wait, current); - dprintk(1, "%s dma_q=0x%08lx\n", __FUNCTION__, (unsigned long)dma_q); + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, + (unsigned long)dma_q); add_wait_queue(&dma_q->wq, &wait); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) - if (!(q->rmmod || signal_pending(current))) { + if ((q->rmmod || signal_pending(current))) + goto stop_task; #else - if (!kthread_should_stop()) { + if (kthread_should_stop()) + goto stop_task; #endif - dma_q->frame++; - - /* Calculate time to wake up */ - timeout = dma_q->ini_jiffies+ - msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR * 1000) - / WAKE_DENOMINATOR) - jiffies; - - if (timeout <= 0) { - int old = dma_q->frame; - dma_q->frame = (jiffies_to_msecs(jiffies - - dma_q->ini_jiffies) * - WAKE_DENOMINATOR) / - (WAKE_NUMERATOR * 1000) + 1; - - timeout = dma_q->ini_jiffies+ - msecs_to_jiffies((dma_q->frame * - WAKE_NUMERATOR * 1000) - / WAKE_DENOMINATOR) - jiffies; - - dprintk(1, "underrun, losed %d frames. " - "Now, frame is %d. Waking on %d jiffies\n", - dma_q->frame-old, dma_q->frame, timeout); - } else - dprintk(1, "will sleep for %i jiffies\n", timeout); - - vivi_thread_tick(dma_q); - - schedule_timeout_interruptible(timeout); - } + running_time = jiffies - dma_q->ini_jiffies; + dma_q->frame++; + + /* Calculate time to wake up */ + timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time; + + if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) { + int old = dma_q->frame; + int nframes; + + dma_q->frame = (jiffies_to_msecs(running_time) / + frames_to_ms(1)) + 1; + + timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) + - running_time; + + if (unlikely (timeout <= 0)) + timeout = 1; + + nframes = (dma_q->frame > old)? + dma_q->frame - old : old - dma_q->frame; + + dprintk(dev, 1, "%ld: %s %d frames. " + "Current frame is %d. Will sleep for %d jiffies\n", + jiffies, + (dma_q->frame > old)? "Underrun, losed" : "Overrun of", + nframes, dma_q->frame, timeout); + } else + dprintk(dev, 1, "will sleep for %d jiffies\n", timeout); + + vivi_thread_tick(dma_q); + + schedule_timeout_interruptible(timeout); + +stop_task: remove_wait_queue(&dma_q->wq, &wait); try_to_freeze(); } @@ -489,6 +505,7 @@ static void vivi_sleep(struct vivi_dmaqueue *dma_q) static int vivi_thread(void *data) { struct vivi_dmaqueue *dma_q = data; + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) daemonize(); @@ -504,7 +521,7 @@ static int vivi_thread(void *data) if (dma_q->notify != NULL) up(dma_q->notify); #endif - dprintk(1, "thread started\n"); + dprintk(dev, 1, "thread started\n"); mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); set_freezable(); @@ -519,7 +536,7 @@ static int vivi_thread(void *data) #endif break; } - dprintk(1, "thread: exit\n"); + dprintk(dev, 1, "thread: exit\n"); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) dma_q->kthread = NULL; @@ -531,10 +548,12 @@ static int vivi_thread(void *data) static int vivi_start_thread(struct vivi_dmaqueue *dma_q) { + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + dma_q->frame = 0; dma_q->ini_jiffies = jiffies; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); @@ -561,13 +580,15 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q) /* Wakes thread */ wake_up_interruptible(&dma_q->wq); - dprintk(1, "returning from %s\n", __FUNCTION__); + dprintk(dev, 1, "returning from %s\n", __FUNCTION__); return 0; } static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) { - dprintk(1, "%s\n", __FUNCTION__); + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + + dprintk(dev, 1, "%s\n", __FUNCTION__); /* shutdown control thread */ if (dma_q->kthread) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) @@ -589,17 +610,19 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) static int restart_video_queue(struct vivi_dmaqueue *dma_q) { + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); struct vivi_buffer *buf, *prev; - dprintk(1, "%s dma_q=0x%08lx\n", __FUNCTION__, (unsigned long)dma_q); + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, + (unsigned long)dma_q); if (!list_empty(&dma_q->active)) { buf = list_entry(dma_q->active.next, struct vivi_buffer, vb.queue); - dprintk(2, "restart_queue [%p/%d]: restart dma\n", + dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); - dprintk(1, "Restarting video dma\n"); + dprintk(dev, 1, "Restarting video dma\n"); vivi_stop_thread(dma_q); /* cancel all outstanding capture / vbi requests */ @@ -623,13 +646,14 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q) list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue, &dma_q->active); - dprintk(1, "Restarting video dma\n"); + dprintk(dev, 1, "Restarting video dma\n"); vivi_stop_thread(dma_q); vivi_start_thread(dma_q); buf->vb.state = VIDEOBUF_ACTIVE; mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] restart_queue - first active\n", + dprintk(dev, 2, + "[%p/%d] restart_queue - first active\n", buf, buf->vb.i); } else if (prev->vb.width == buf->vb.width && @@ -638,7 +662,8 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q) list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue, &dma_q->active); buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(2, "[%p/%d] restart_queue - move to active\n", + dprintk(dev, 2, + "[%p/%d] restart_queue - move to active\n", buf, buf->vb.i); } else { return 0; @@ -653,6 +678,8 @@ static void vivi_vid_timeout(unsigned long data) struct vivi_dmaqueue *vidq = &dev->vidq; struct vivi_buffer *buf; + spin_lock(&dev->slock); + while (!list_empty(&vidq->active)) { buf = list_entry(vidq->active.next, struct vivi_buffer, vb.queue); @@ -661,8 +688,9 @@ static void vivi_vid_timeout(unsigned long data) wake_up(&buf->vb.done); printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i); } - restart_video_queue(vidq); + + spin_unlock(&dev->slock); } /* ------------------------------------------------------------------ @@ -671,7 +699,8 @@ static void vivi_vid_timeout(unsigned long data) static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { - struct vivi_fh *fh = vq->priv_data; + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; *size = fh->width*fh->height*2; @@ -681,14 +710,18 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) while (*size * *count > vid_limit * 1024 * 1024) (*count)--; - dprintk(1, "%s, count=%d, size=%d\n", __FUNCTION__, *count, *size); + dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__, + *count, *size); return 0; } static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) { - dprintk(1, "%s\n", __FUNCTION__); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; + + dprintk(dev, 1, "%s\n", __FUNCTION__); if (in_interrupt()) BUG(); @@ -705,10 +738,11 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); int rc, init_buffer = 0; - dprintk(1, "%s, field=%d\n", __FUNCTION__, field); + dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field); BUG_ON(NULL == fh->fmt); if (fh->width < 48 || fh->width > norm_maxw() || @@ -754,18 +788,18 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct vivi_buffer *prev; if (!list_empty(&vidq->queued)) { - dprintk(1, "adding vb queue=0x%08lx\n", + dprintk(dev, 1, "adding vb queue=0x%08lx\n", (unsigned long)&buf->vb.queue); list_add_tail(&buf->vb.queue, &vidq->queued); buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", + dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&vidq->active)) { list_add_tail(&buf->vb.queue, &vidq->active); buf->vb.state = VIDEOBUF_ACTIVE; mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active\n", + dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n", buf, buf->vb.i); vivi_start_thread(vidq); @@ -777,13 +811,15 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) prev->fmt == buf->fmt) { list_add_tail(&buf->vb.queue, &vidq->active); buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(2, "[%p/%d] buffer_queue - append to active\n", + dprintk(dev, 2, + "[%p/%d] buffer_queue - append to active\n", buf, buf->vb.i); } else { list_add_tail(&buf->vb.queue, &vidq->queued); buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", + dprintk(dev, 2, + "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); } } @@ -797,7 +833,7 @@ static void buffer_release(struct videobuf_queue *vq, struct vivi_dev *dev = (struct vivi_dev *)fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); vivi_stop_thread(vidq); @@ -857,13 +893,16 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv, static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; struct vivi_fmt *fmt; enum v4l2_field field; unsigned int maxw, maxh; if (format.fourcc != f->fmt.pix.pixelformat) { - dprintk(1, "Fourcc format (0x%08x) invalid. Driver accepts " - "only 0x%08x\n", f->fmt.pix.pixelformat, format.fourcc); + dprintk(dev, 1, "Fourcc format (0x%08x) invalid. " + "Driver accepts only 0x%08x\n", + f->fmt.pix.pixelformat, format.fourcc); return -EINVAL; } fmt = &format; @@ -873,7 +912,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv, if (field == V4L2_FIELD_ANY) { field = V4L2_FIELD_INTERLACED; } else if (V4L2_FIELD_INTERLACED != field) { - dprintk(1, "Field type invalid.\n"); + dprintk(dev, 1, "Field type invalid.\n"); return -EINVAL; } @@ -992,7 +1031,7 @@ static int vidioc_enum_input(struct file *file, void *priv, return -EINVAL; inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_NTSC_M; + inp->std = V4L2_STD_525_60; strcpy(inp->name, "Camera"); return (0); @@ -1082,7 +1121,7 @@ found: /* If more than one user, mutex should be added */ dev->users++; - dprintk(1, "open minor=%d type=%s users=%d\n", minor, + dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); /* allocate + initialize per filehandle data */ @@ -1115,7 +1154,7 @@ found: dev->h, dev->m, dev->s, (dev->us + 500) / 1000); videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, - NULL, NULL, fh->type, V4L2_FIELD_INTERLACED, + NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, sizeof(struct vivi_buffer), fh); return 0; @@ -1137,9 +1176,10 @@ static unsigned int vivi_poll(struct file *file, struct poll_table_struct *wait) { struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; struct videobuf_queue *q = &fh->vb_vidq; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; @@ -1163,7 +1203,8 @@ static int vivi_close(struct inode *inode, struct file *file) dev->users--; - dprintk(1, "close called (minor=%d, users=%d)\n", minor, dev->users); + dprintk(dev, 1, "close called (minor=%d, users=%d)\n", + minor, dev->users); return 0; } @@ -1191,14 +1232,15 @@ static int vivi_release(void) static int vivi_mmap(struct file *file, struct vm_area_struct *vma) { - struct vivi_fh *fh = file->private_data; + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; int ret; - dprintk(1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); - dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n", + dprintk(dev, 1, "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); @@ -1245,7 +1287,7 @@ static struct video_device vivi_template = { #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif - .tvnorms = V4L2_STD_NTSC_M, + .tvnorms = V4L2_STD_525_60, .current_norm = V4L2_STD_NTSC_M, }; /* ----------------------------------------------------------------- @@ -1272,6 +1314,7 @@ static int __init vivi_init(void) /* initialize locks */ mutex_init(&dev->lock); + spin_lock_init(&dev->slock); dev->vidq.timeout.function = vivi_vid_timeout; dev->vidq.timeout.data = (unsigned long)dev; @@ -1323,7 +1366,7 @@ MODULE_PARM_DESC(video_nr, "video iminor start number"); module_param(n_devs, int, 0); MODULE_PARM_DESC(n_devs, "number of video devices to create"); -module_param_named(debug, vivi.debug, int, 0644); +module_param_named(debug, vivi_template.debug, int, 0444); MODULE_PARM_DESC(debug, "activates debug info"); module_param(vid_limit, int, 0644); |