From 45a9b83fe4cf91b13900dc665f526f7fd94d484c Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Thu, 19 Oct 2006 08:15:40 -0300 Subject: V4L/DVB (4777): Correct AVerMedia Volar USB ID correct AVerMedia Volar USB ID Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4d6b069536c..967d1026960 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -97,7 +97,7 @@ #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 -#define USB_PID_AVERMEDIA_VOLAR 0x1234 +#define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 -- cgit v1.2.3 From 91bb9be6ff4101652bb104f9f083f340e73ba6dd Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 2 Dec 2006 21:15:51 -0200 Subject: V4L/DVB (4524): Initial commit for the DiB7000M-demod Initial commit for the driver for the DiB7000M COFDM demodulator. Signed-off-by: Francois KANOUNNIKOFF Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/dvb/dvb-usb/dib0700_devices.c | 1 + drivers/media/dvb/frontends/dib7000m.c | 242 ++++++++++++++++++++++++++++ drivers/media/dvb/frontends/dib7000m.h | 50 ++++++ 4 files changed, 294 insertions(+) create mode 100644 drivers/media/dvb/frontends/dib7000m.c create mode 100644 drivers/media/dvb/frontends/dib7000m.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index a263b3f3c21..a0aeaf4bbb3 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -69,6 +69,7 @@ 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_DIB7000M select DVB_DIB3000MC select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e473bfed226..b4e339df72e 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -9,6 +9,7 @@ #include "dib0700.h" #include "dib3000mc.h" +#include "dib7000m.h" #include "mt2060.h" static int force_lna_activation; diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c new file mode 100644 index 00000000000..c9a57678fa3 --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -0,0 +1,242 @@ +/* + * Linux-DVB Driver for DiBcom's DiB7000M and + * first generation DiB7000P-demodulator-family. + * + * Copyright (C) 2005-6 DiBcom (http://www.dibcom.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 Free Software Foundation, version 2. + */ +#include +#include + +#include "dvb_frontend.h" + +#include "dib7000m.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) + +struct dib7000m_state { + struct dvb_frontend demod; + struct dib7000m_config cfg; + + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + + struct dibx000_i2c_master i2c_master; + +/* offset is 1 in case of the 7000MC */ + u8 reg_offs; + + u16 wbd_ref; + + u8 current_band; + fe_bandwidth_t current_bandwidth; + struct dibx000_agc_config *current_agc; + u32 timf[9]; + + u16 revision; +}; + +static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) +{ + u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; + u8 rb[2]; + struct i2c_msg msg[2] = { + { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + + if (i2c_transfer(state->i2c_adap, msg, 2) != 2) + dprintk("i2c read error on %d\n",reg); + + return (rb[0] << 8) | rb[1]; +} + +/* +static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) +{ + u8 b[4] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg = { + .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 + }; + return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; +} +*/ + +static int dib7000m_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib7000m_state *state = fe->demodulator_priv; + u16 tps = dib7000m_read_word(state,480); + + fep->inversion = INVERSION_AUTO; + + fep->u.ofdm.bandwidth = state->current_bandwidth; + + switch ((tps >> 8) & 0x2) { + case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; + /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ + } + + switch (tps & 0x3) { + case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; + case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; + case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; + case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; + } + + switch ((tps >> 14) & 0x3) { + case 0: fep->u.ofdm.constellation = QPSK; break; + case 1: fep->u.ofdm.constellation = QAM_16; break; + case 2: + default: fep->u.ofdm.constellation = QAM_64; break; + } + + /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ + /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ + + fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; + switch ((tps >> 5) & 0x7) { + case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; + + } + + switch ((tps >> 2) & 0x7) { + case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; + } + + /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */ + + return 0; +} + +static int dib7000m_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + return 0; +} + +static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) +{ + struct dib7000m_state *state = fe->demodulator_priv; + u16 lock = dib7000m_read_word(state, 509); + + *stat = 0; + + if (lock & 0x8000) + *stat |= FE_HAS_SIGNAL; + if (lock & 0x3000) + *stat |= FE_HAS_CARRIER; + if (lock & 0x0100) + *stat |= FE_HAS_VITERBI; + if (lock & 0x0010) + *stat |= FE_HAS_SYNC; + if (lock & 0x0008) + *stat |= FE_HAS_LOCK; + + return 0; +} + +static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct dib7000m_state *state = fe->demodulator_priv; + *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527); + return 0; +} + +static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) +{ + struct dib7000m_state *state = fe->demodulator_priv; + *unc = dib7000m_read_word(state, 534); + return 0; +} + +static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct dib7000m_state *state = fe->demodulator_priv; + u16 val = dib7000m_read_word(state, 390); + *strength = 65535 - val; + return 0; +} + +static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) +{ + *snr = 0x0000; + return 0; +} + +static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static int dib7000m_init(struct dvb_frontend *fe) +{ + return 0; +} + +static int dib7000m_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +static void dib7000m_release(struct dvb_frontend *fe) +{ } + +static struct dvb_frontend_ops dib7000m_ops = { + .info = { + .name = "DiBcom 7000MA/MB/PA/PB/MC", + .type = FE_OFDM, + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dib7000m_release, + + .init = dib7000m_init, + .sleep = dib7000m_sleep, + + .set_frontend = dib7000m_set_frontend, + .get_tune_settings = dib7000m_fe_get_tune_settings, + .get_frontend = dib7000m_get_frontend, + + .read_status = dib7000m_read_status, + .read_ber = dib7000m_read_ber, + .read_signal_strength = dib7000m_read_signal_strength, + .read_snr = dib7000m_read_snr, + .read_ucblocks = dib7000m_read_unc_blocks, +}; + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h new file mode 100644 index 00000000000..45990e3a5ce --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.h @@ -0,0 +1,50 @@ +#ifndef DIB7000M_H +#define DIB7000M_H + +#include "dibx000_common.h" + +struct dib7000m_config { + u8 dvbt_mode; + u8 output_mpeg2_in_188_bytes; + u8 hostbus_diversity; + u8 tuner_is_baseband; + u8 mobile_mode; + int (*update_lna) (struct dvb_frontend *, u16 agc_global); + + u8 agc_config_count; + struct dibx000_agc_config *agc; + + struct dibx000_bandwidth_config *bw; + +#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff + u16 gpio_dir; +#define DIB7000M_GPIO_DEFAULT_VALUES 0x0000 + u16 gpio_val; +#define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12) +#define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) +#define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) +#define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf) +#define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff + u16 gpio_pwm_pos; + + u16 pwm_freq_div; + + u8 quartz_direct; + + u8 input_clk_is_div_2; +}; + +#define DEFAULT_DIB7000M_I2C_ADDRESS 18 + +extern int dib7000m_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr , u8 do_i2c_enum, struct dib7000m_config[], struct dvb_frontend*[]); + +extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); + +/* TODO +extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); +extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod); +extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); +extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod); +*/ + +#endif -- cgit v1.2.3 From 01451e722793f191f6e13c5150dd8664f4439d17 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Fri, 13 Oct 2006 11:34:46 -0300 Subject: V4L/DVB (4749): Fixed DVB-USB-Adapter indention While converting everything to DVB-USB-Adapter, there was a wrong indention. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/a800.c | 36 ++++----- drivers/media/dvb/dvb-usb/cxusb.c | 130 ++++++++++++++++---------------- drivers/media/dvb/dvb-usb/dibusb-mb.c | 113 +++++++++++++-------------- drivers/media/dvb/dvb-usb/dibusb-mc.c | 26 +++---- drivers/media/dvb/dvb-usb/digitv.c | 22 +++--- drivers/media/dvb/dvb-usb/dtt200u.c | 24 +++--- drivers/media/dvb/dvb-usb/gp8psk.c | 22 +++--- drivers/media/dvb/dvb-usb/nova-t-usb2.c | 34 ++++----- drivers/media/dvb/dvb-usb/umt-010.c | 24 +++--- drivers/media/dvb/dvb-usb/vp702x.c | 20 ++--- drivers/media/dvb/dvb-usb/vp7045.c | 20 ++--- 11 files changed, 236 insertions(+), 235 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index 2ed3eb62d78..a6c5f19f680 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c @@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 43f39069ef3..e05200b6110 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -529,20 +529,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_cx22702_frontend_attach, - .tuner_attach = cxusb_fmd1216me_tuner_attach, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_cx22702_frontend_attach, + .tuner_attach = cxusb_fmd1216me_tuner_attach, + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -575,21 +575,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_lgdt3303_frontend_attach, - .tuner_attach = cxusb_lgdt3303_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_lgdt3303_frontend_attach, + .tuner_attach = cxusb_lgdt3303_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -627,20 +627,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_dee1601_frontend_attach, - .tuner_attach = cxusb_dee1601_tuner_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_dee1601_frontend_attach, + .tuner_attach = cxusb_dee1601_tuner_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -686,21 +686,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .num_adapters = 2, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_lgz201_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_lgz201_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, @@ -736,21 +736,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_dtt7579_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_dtt7579_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 4fe363e4835..7a6ae8f482e 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, }, @@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_thomson_tuner_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_thomson_tuner_attach, + + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index a0fd37efc04..e7ea3e753d6 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 8fb34375c1f..4a198d4755b 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = digitv_frontend_attach, - .tuner_attach = digitv_tuner_attach, + .frontend_attach = digitv_frontend_attach, + .tuner_attach = digitv_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .identify_state = digitv_identify_state, diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index fa43a41d753..7dbe1432101 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, .pid_filter_count = 15, - .streaming_ctrl = dtt200u_streaming_ctrl, - .pid_filter = dtt200u_pid_filter, - .frontend_attach = dtt200u_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dtt200u_streaming_ctrl, + .pid_filter = dtt200u_pid_filter, + .frontend_attach = dtt200u_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = dtt200u_power_ctrl, diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 7375eb20166..518d67fca5e 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = gp8psk_streaming_ctrl, - .frontend_attach = gp8psk_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = gp8psk_streaming_ctrl, + .frontend_attach = gp8psk_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 7, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, } }, .power_ctrl = gp8psk_power_ctrl, diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index a58874c790b..d48622e76b1 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index f9941ea88b3..f77b48f7658 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c @@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .frontend_attach = umt_mt352_frontend_attach, - .tuner_attach = umt_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .frontend_attach = umt_mt352_frontend_attach, + .tuner_attach = umt_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 20, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, + .count = 20, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 02bd61aaac6..16533b31a82 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = { .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, .streaming_ctrl = vp702x_streaming_ctrl, - .frontend_attach = vp702x_frontend_attach, + .frontend_attach = vp702x_frontend_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 10, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct vp702x_state), } - }, + }, .read_mac_address = vp702x_read_mac_addr, .rc_key_map = vp702x_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index b4cf002703a..297806225f8 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -217,18 +217,18 @@ static struct dvb_usb_device_properties vp7045_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = vp7045_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .frontend_attach = vp7045_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = vp7045_power_ctrl, -- cgit v1.2.3 From f71a56c17225392c873225f2d567f5caddc6b963 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 13 Oct 2006 21:55:57 -0300 Subject: V4L/DVB (4753): Cxusb: rename cxusb_lgdt3303_tuner_attach cxusb_lgdt3303_tuner_attach were renamed to cxusb_lgh064f_tuner_attach Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index e05200b6110..ef542b6bd6f 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -396,7 +396,7 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap) +static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; return 0; @@ -577,7 +577,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { { .streaming_ctrl = cxusb_streaming_ctrl, .frontend_attach = cxusb_lgdt3303_frontend_attach, - .tuner_attach = cxusb_lgdt3303_tuner_attach, + .tuner_attach = cxusb_lgh064f_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { -- cgit v1.2.3 From 5b9ed286759eb1c805f344398ee2c57191d7e2bd Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 15 Oct 2006 14:51:08 -0300 Subject: V4L/DVB (4754): Cxusb: update copyright and author email address Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index ef542b6bd6f..4e2eef86eca 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -14,7 +14,7 @@ * TODO: Use the cx25840-driver for the analogue part * * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) - * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) + * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) * * This program is free software; you can redistribute it and/or modify it @@ -802,7 +802,7 @@ module_init (cxusb_module_init); module_exit (cxusb_module_exit); MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Michael Krufky "); +MODULE_AUTHOR("Michael Krufky "); MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); MODULE_VERSION("1.0-alpha"); -- cgit v1.2.3 From 3cc2e4c3a137075ee66e2d4ce95a95ba153bd7b9 Mon Sep 17 00:00:00 2001 From: Luke Deller Date: Tue, 17 Oct 2006 18:28:10 -0300 Subject: V4L/DVB (4765): Dvb-usb/vp7045.c patch for extra key Add support for more keys on the remote control included with the DigitalNow tinyUSB2 DVB-T Receiver. Signed-off-by: Luke Deller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/vp7045.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 297806225f8..69a46b3607a 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = { { 0x00, 0x00, KEY_TAB }, /* Tab */ { 0x00, 0x48, KEY_INFO }, /* Preview */ { 0x00, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0x0f, KEY_TEXT } /* Teletext */ + { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ + { 0x00, 0x41, KEY_PREVIOUSSONG }, + { 0x00, 0x42, KEY_NEXTSONG }, + { 0x00, 0x4b, KEY_UP }, + { 0x00, 0x51, KEY_DOWN }, + { 0x00, 0x4e, KEY_LEFT }, + { 0x00, 0x52, KEY_RIGHT }, + { 0x00, 0x4f, KEY_ENTER }, + { 0x00, 0x13, KEY_CANCEL }, + { 0x00, 0x4a, KEY_CLEAR }, + { 0x00, 0x54, KEY_PRINT }, /* Capture */ + { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ + { 0x00, 0x08, KEY_VIDEO }, /* A/V */ + { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ + { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ + { 0x00, 0x18, KEY_RED}, + { 0x00, 0x53, KEY_GREEN}, + { 0x00, 0x5e, KEY_YELLOW}, + { 0x00, 0x5f, KEY_BLUE} }; static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) -- cgit v1.2.3 From 69ea31e7debdefcf1412e8d590ae9bd90cf9253f Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 17 Oct 2006 18:28:14 -0300 Subject: V4L/DVB (4766): Add working dib7000m-module First working version of the dib7000m-driver. This commit also makes the Hauppauge NOVA-T Stick working. Signed-off-by: Francois Kanounnikoff Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 95 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dib7000m.c | 976 ++++++++++++++++++++++++++- drivers/media/dvb/frontends/dib7000m.h | 5 +- drivers/media/dvb/frontends/dibx000_common.c | 2 +- drivers/media/dvb/frontends/dibx000_common.h | 13 +- 8 files changed, 1073 insertions(+), 28 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index b4e339df72e..305dd35a102 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -96,29 +96,97 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) } /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ -/* -static struct mt2060_config stk7000p_mt2060_config = { - 0x60 +static struct dibx000_agc_config stk7700p_dib7000m_agc_config = { + BAND_UHF | BAND_VHF, // band_caps + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup + + 712, // inv_gain + 41, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 4095, // wbd_ref + 0, // wbd_sel + 0, // wbd_alpha + + 42598, // agc1_max + 17694, // agc1_min + 45875, // agc2_max + 2621, // agc2_min + 0, // agc1_pt1 + 76, // agc1_pt2 + 139, // agc1_pt3 + 52, // agc1_slope1 + 59, // agc1_slope2 + 107, // agc2_pt1 + 172, // agc2_pt2 + 57, // agc2_slope1 + 70, // agc2_slope2 + + 21, // alpha_mant + 25, // alpha_exp + 28, // beta_mant + 48, // beta_exp + + 1, // perform_agc_softsplit + { 0, // split_min + 107, // split_max + 51800, // global_split_min + 24700 // global_split_max + }, +}; + +static struct dibx000_bandwidth_config stk7700p_dib7000m_mt2060_config = { + 60000, 30000, // internal, sampling + 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass + 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo + (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k + 60258167, // ifreq + 20452225, // timf +}; + +static struct dib7000m_config stk7700p_dib7000m_config = { + .dvbt_mode = 1, + .output_mpeg2_in_188_bytes = 1, + .quartz_direct = 1, + + .agc_config_count = 1, + .agc = &stk7700p_dib7000m_agc_config, + .bw = &stk7700p_dib7000m_mt2060_config, + + .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, }; -*/ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) { + struct dib0700_state *st = adap->dev->priv; /* unless there is no real power management in DVB - we leave the device on GPIO6 */ - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); - dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); -// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); - return 0; + st->mt2060_if1[0] = 1220; + return (adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config)) == NULL ? -ENODEV : 0; } +static struct mt2060_config stk7700p_mt2060_config = { + 0x60 +}; + static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) { -// tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); -// return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); - return 0; + struct dib0700_state *st = adap->dev->priv; + struct i2c_adapter *tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &stk7700p_mt2060_config, + st->mt2060_if1[0]) == NULL ? -ENODEV : 0; } struct usb_device_id dib0700_usb_id_table[] = { @@ -127,6 +195,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -171,7 +240,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_device_descs = 3, .devices = { { "DiBcom STK7700P reference design", - { &dib0700_usb_id_table[0], NULL }, + { &dib0700_usb_id_table[0], &dib0700_usb_id_table[5] }, { NULL }, }, { "Hauppauge Nova-T Stick", diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 967d1026960..fd8ba2535c0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -53,6 +53,7 @@ #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 #define USB_PID_DIBCOM_STK7700P 0x1e14 +#define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index aebb8d6f26f..093c7695883 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -172,6 +172,14 @@ config DVB_DIB3000MC A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. +config DVB_DIB7000M + tristate "DiBcom 7000MA/MB/PA/PB/MC" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index dce9cf0c75c..244e87417b0 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o +obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index c9a57678fa3..a85190319cf 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -19,7 +19,7 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) struct dib7000m_state { struct dvb_frontend demod; @@ -38,11 +38,21 @@ struct dib7000m_state { u8 current_band; fe_bandwidth_t current_bandwidth; struct dibx000_agc_config *current_agc; - u32 timf[9]; + u32 timf; u16 revision; }; +enum dib7000m_power_mode { + DIB7000M_POWER_ALL = 0, + + DIB7000M_POWER_NO, + DIB7000M_POWER_INTERF_ANALOG_AGC, + DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, + DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, + DIB7000M_POWER_INTERFACE_ONLY, +}; + static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) { u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; @@ -58,7 +68,6 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) return (rb[0] << 8) | rb[1]; } -/* static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) { u8 b[4] = { @@ -70,7 +79,835 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) }; return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; } -*/ +static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) +{ + int ret = 0; + u16 outreg, fifo_threshold, smo_mode, + sram = 0x0005; /* by default SRAM output is disabled */ + + outreg = 0; + fifo_threshold = 1792; + smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); + + dprintk("-I- Setting output mode for demod %p to %d\n", + &state->demod, mode); + + switch (mode) { + case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock + outreg = (1 << 10); /* 0x0400 */ + break; + case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock + outreg = (1 << 10) | (1 << 6); /* 0x0440 */ + break; + case OUTMODE_MPEG2_SERIAL: // STBs with serial input + outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ + break; + case OUTMODE_DIVERSITY: + if (state->cfg.hostbus_diversity) + outreg = (1 << 10) | (4 << 6); /* 0x0500 */ + else + sram |= 0x0c00; + break; + case OUTMODE_MPEG2_FIFO: // e.g. USB feeding + smo_mode |= (3 << 1); + fifo_threshold = 512; + outreg = (1 << 10) | (5 << 6); + break; + case OUTMODE_HIGH_Z: // disable + outreg = 0; + break; + default: + dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); + break; + } + + if (state->cfg.output_mpeg2_in_188_bytes) + smo_mode |= (1 << 5) ; + + ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); + ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ + ret |= dib7000m_write_word(state, 1795, outreg); + ret |= dib7000m_write_word(state, 1805, sram); + + return ret; +} + +static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) +{ + /* by default everything is going to be powered off */ + u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; + + /* now, depending on the requested mode, we power on */ + switch (mode) { + /* power up everything in the demod */ + case DIB7000M_POWER_ALL: + reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; + break; + + /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ + case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ + reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); + break; + + case DIB7000M_POWER_INTERF_ANALOG_AGC: + reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); + reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); + reg_906 &= ~((1 << 0)); + break; + + case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: + reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; + break; + + case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: + reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; + break; + case DIB7000M_POWER_NO: + break; + } + + /* always power down unused parts */ + if (!state->cfg.mobile_mode) + reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); + + /* P_sdio_select_clk = 0 on MC */ + if (state->revision != 0x4000) + reg_906 <<= 1; + + dib7000m_write_word(state, 903, reg_903); + dib7000m_write_word(state, 904, reg_904); + dib7000m_write_word(state, 905, reg_905); + dib7000m_write_word(state, 906, reg_906); + + return 0; +} + +static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) +{ + int ret = 0; + u16 reg_913 = dib7000m_read_word(state, 913), + reg_914 = dib7000m_read_word(state, 914); + + switch (no) { + case DIBX000_SLOW_ADC_ON: + reg_914 |= (1 << 1) | (1 << 0); + ret |= dib7000m_write_word(state, 914, reg_914); + reg_914 &= ~(1 << 1); + break; + + case DIBX000_SLOW_ADC_OFF: + reg_914 |= (1 << 1) | (1 << 0); + break; + + case DIBX000_ADC_ON: + if (state->revision == 0x4000) { // workaround for PA/MA + // power-up ADC + dib7000m_write_word(state, 913, 0); + dib7000m_write_word(state, 914, reg_914 & 0x3); + // power-down bandgag + dib7000m_write_word(state, 913, (1 << 15)); + dib7000m_write_word(state, 914, reg_914 & 0x3); + } + + reg_913 &= 0x0fff; + reg_914 &= 0x0003; + break; + + case DIBX000_ADC_OFF: // leave the VBG voltage on + reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); + reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); + break; + + case DIBX000_VBG_ENABLE: + reg_913 &= ~(1 << 15); + break; + + case DIBX000_VBG_DISABLE: + reg_913 |= (1 << 15); + break; + + default: + break; + } + +// dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); + + ret |= dib7000m_write_word(state, 913, reg_913); + ret |= dib7000m_write_word(state, 914, reg_914); + + return ret; +} + +static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) +{ + struct dib7000m_state *state = demod->demodulator_priv; + u32 timf; + + // store the current bandwidth for later use + state->current_bandwidth = bw_idx; + + if (state->timf == 0) { + dprintk("-D- Using default timf\n"); + timf = state->cfg.bw->timf; + } else { + dprintk("-D- Using updated timf\n"); + timf = state->timf; + } + + timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; + + dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); + dib7000m_write_word(state, 24, (timf ) & 0xffff); + + return 0; +} + +static int dib7000m_sad_calib(struct dib7000m_state *state) +{ + +/* internal */ +// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth + dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); + dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 + + /* do the calibration */ + dib7000m_write_word(state, 929, (1 << 0)); + dib7000m_write_word(state, 929, (0 << 0)); + + msleep(1); + + return 0; +} + +static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) +{ + dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); + dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); + dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); + dib7000m_write_word(state, 22, bw->ifreq & 0xffff); + + dib7000m_write_word(state, 928, bw->sad_cfg); +} + +static void dib7000m_reset_pll(struct dib7000m_state *state) +{ + const struct dibx000_bandwidth_config *bw = state->cfg.bw; + u16 reg_907,reg_910; + + /* default */ + reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | + (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | + (bw->enable_refdiv << 1) | (0 << 0); + reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; + + // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) + // this is only working only for 30 MHz crystals + if (!state->cfg.quartz_direct) { + reg_910 |= (1 << 5); // forcing the predivider to 1 + + // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) + if(state->cfg.input_clk_is_div_2) + reg_907 |= (16 << 9); + else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary + reg_907 |= (8 << 9); + } else { + reg_907 |= (bw->pll_ratio & 0x3f) << 9; + reg_910 |= (bw->pll_prediv << 5); + } + + dib7000m_write_word(state, 910, reg_910); // pll cfg + dib7000m_write_word(state, 907, reg_907); // clk cfg0 + dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 + + dib7000m_reset_pll_common(state, bw); +} + +static void dib7000mc_reset_pll(struct dib7000m_state *state) +{ + const struct dibx000_bandwidth_config *bw = state->cfg.bw; + + // clk_cfg0 + dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); + + // clk_cfg1 + //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | + dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | + (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | + (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); + + // smpl_cfg + dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); + + dib7000m_reset_pll_common(state, bw); +} + +static int dib7000m_reset_gpio(struct dib7000m_state *st) +{ + /* reset the GPIOs */ + dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", + st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); + + dib7000m_write_word(st, 773, st->cfg.gpio_dir); + dib7000m_write_word(st, 774, st->cfg.gpio_val); + + /* TODO 782 is P_gpio_od */ + + dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); + + dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); + return 0; +} + +static int dib7000m_demod_reset(struct dib7000m_state *state) +{ + dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); + + /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ + dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); + + /* restart all parts */ + dib7000m_write_word(state, 898, 0xffff); + dib7000m_write_word(state, 899, 0xffff); + dib7000m_write_word(state, 900, 0xff0f); + dib7000m_write_word(state, 901, 0xfffc); + + dib7000m_write_word(state, 898, 0); + dib7000m_write_word(state, 899, 0); + dib7000m_write_word(state, 900, 0); + dib7000m_write_word(state, 901, 0); + + if (state->revision == 0x4000) + dib7000m_reset_pll(state); + else + dib7000mc_reset_pll(state); + + if (dib7000m_reset_gpio(state) != 0) + dprintk("-E- GPIO reset was not successful.\n"); + + if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) + dprintk("-E- OUTPUT_MODE could not be resetted.\n"); + + /* unforce divstr regardless whether i2c enumeration was done or not */ + dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); + + dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); + + dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); + dib7000m_sad_calib(state); + dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); + + dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); + + return 0; +} + +static void dib7000m_restart_agc(struct dib7000m_state *state) +{ + // P_restart_iqc & P_restart_agc + dib7000m_write_word(state, 898, 0x0c00); + dib7000m_write_word(state, 898, 0x0000); +} + +static int dib7000m_agc_soft_split(struct dib7000m_state *state) +{ + u16 agc,split_offset; + + if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) + return 0; + + // n_agc_global + agc = dib7000m_read_word(state, 390); + + if (agc > state->current_agc->split.min_thres) + split_offset = state->current_agc->split.min; + else if (agc < state->current_agc->split.max_thres) + split_offset = state->current_agc->split.max; + else + split_offset = state->current_agc->split.max * + (agc - state->current_agc->split.min_thres) / + (state->current_agc->split.max_thres - state->current_agc->split.min_thres); + + dprintk("AGC split_offset: %d\n",split_offset); + + // P_agc_force_split and P_agc_split_offset + return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); +} + +static int dib7000m_update_lna(struct dib7000m_state *state) +{ + int i; + u16 dyn_gain; + + // when there is no LNA to program return immediatly + if (state->cfg.update_lna == NULL) + return 0; + + msleep(60); + for (i = 0; i < 20; i++) { + // read dyn_gain here (because it is demod-dependent and not tuner) + dyn_gain = dib7000m_read_word(state, 390); + + dprintk("agc global: %d\n", dyn_gain); + + if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed + dib7000m_restart_agc(state); + msleep(60); + } else + break; + } + return 0; +} + +static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) +{ + struct dibx000_agc_config *agc = NULL; + int i; + if (state->current_band == band) + return; + state->current_band = band; + + for (i = 0; i < state->cfg.agc_config_count; i++) + if (state->cfg.agc[i].band_caps & band) { + agc = &state->cfg.agc[i]; + break; + } + + if (agc == NULL) { + dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); + return; + } + + state->current_agc = agc; + + /* AGC */ + dib7000m_write_word(state, 72 , agc->setup); + dib7000m_write_word(state, 73 , agc->inv_gain); + dib7000m_write_word(state, 74 , agc->time_stabiliz); + dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); + + // Demod AGC loop configuration + dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); + dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); + + dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", + state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); + + /* AGC continued */ + if (state->wbd_ref != 0) + dib7000m_write_word(state, 102, state->wbd_ref); + else // use default + dib7000m_write_word(state, 102, agc->wbd_ref); + + dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); + dib7000m_write_word(state, 104, agc->agc1_max); + dib7000m_write_word(state, 105, agc->agc1_min); + dib7000m_write_word(state, 106, agc->agc2_max); + dib7000m_write_word(state, 107, agc->agc2_min); + dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); + dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); + dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); + dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); + + if (state->revision > 0x4000) { // settings for the MC + dib7000m_write_word(state, 71, agc->agc1_pt3); +// dprintk("-D- 929: %x %d %d\n", +// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); + dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); + } else { + // wrong default values + u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; + for (i = 0; i < 9; i++) + dib7000m_write_word(state, 88 + i, b[i]); + } +} + +static void dib7000m_update_timf_freq(struct dib7000m_state *state) +{ + u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); + state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); + dib7000m_write_word(state, 23, (u16) (timf >> 16)); + dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); + dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); +} + +static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) +{ + u16 value, est[4]; + + dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); + + /* nfft, guard, qam, alpha */ + dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); + dib7000m_write_word(state, 5, (seq << 4)); + + /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ + value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); + if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) + value |= (ch->vit_code_rate_hp << 1); + else + value |= (ch->vit_code_rate_lp << 1); + dib7000m_write_word(state, 267 + state->reg_offs, value); + + /* offset loop parameters */ + + /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ + dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); + + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ + dib7000m_write_word(state, 32, (0 << 4) | 0x3); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ + dib7000m_write_word(state, 33, (0 << 4) | 0x5); + + /* P_dvsy_sync_wait */ + switch (ch->nfft) { + case 1: value = 256; break; + case 2: value = 128; break; + case 0: + default: value = 64; break; + } + value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin + value <<= 4; + + /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ + /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ + if (ch->intlv_native || state->revision > 0x4000) + value |= (1 << 2) | (2 << 0); + else + value |= 0; + dib7000m_write_word(state, 266 + state->reg_offs, value); + + /* channel estimation fine configuration */ + switch (ch->nqam) { + case 2: + est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ + est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ + break; + case 1: + est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ + est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ + break; + default: + est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ + est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ + est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ + break; + } + for (value = 0; value < 4; value++) + dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); + + // set power-up level: interf+analog+AGC + dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); + dib7000m_set_adc_state(state, DIBX000_ADC_ON); + + msleep(7); + + //AGC initialization + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 1); + + dib7000m_restart_agc(state); + + // wait AGC rough lock time + msleep(5); + + dib7000m_update_lna(state); + dib7000m_agc_soft_split(state); + + // wait AGC accurate lock time + msleep(7); + + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 0); + + // set power-up level: autosearch + dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); +} + +static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000m_state *state = demod->demodulator_priv; + struct dibx000_ofdm_channel auto_ch; + int ret = 0; + u8 seq; + u32 value; + + INIT_OFDM_CHANNEL(&auto_ch); + auto_ch.RF_kHz = ch->RF_kHz; + auto_ch.Bw = ch->Bw; + auto_ch.nqam = 2; + auto_ch.guard = ch->guard == GUARD_INTERVAL_AUTO ? 0 : ch->guard; + auto_ch.nfft = ch->nfft == -1 ? 1 : ch->nfft; + auto_ch.vit_alpha = 1; + auto_ch.vit_select_hp = 1; + auto_ch.vit_code_rate_hp = 2; + auto_ch.vit_code_rate_lp = 3; + auto_ch.vit_hrch = 0; + auto_ch.intlv_native = 1; + + seq = 0; + if (ch->nfft == -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 7; + if (ch->nfft == -1 && ch->guard != GUARD_INTERVAL_AUTO) seq = 2; + if (ch->nfft != -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 3; + dib7000m_set_channel(state, &auto_ch, seq); + + // always use the setting for 8MHz here lock_time for 7,6 MHz are longer + value = 30 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time + ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time + value = 100 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time + ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time + value = 500 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time + ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time + + // start search + value = dib7000m_read_word(state, 0); + ret |= dib7000m_write_word(state, 0, value | (1 << 9)); + + /* clear n_irq_pending */ + if (state->revision == 0x4000) + dib7000m_write_word(state, 1793, 0); + else + dib7000m_read_word(state, 537); + + ret |= dib7000m_write_word(state, 0, (u16) value); + + return ret; +} + +static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) +{ + u16 irq_pending = dib7000m_read_word(state, reg); + + if (irq_pending & 0x1) { // failed + dprintk("#\n"); + return 1; + } + + if (irq_pending & 0x2) { // succeeded + dprintk("!\n"); + return 2; + } + return 0; // still pending +} + +static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) +{ + struct dib7000m_state *state = demod->demodulator_priv; + if (state->revision == 0x4000) + return dib7000m_autosearch_irq(state, 1793); + else + return dib7000m_autosearch_irq(state, 537); +} + +static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000m_state *state = demod->demodulator_priv; + int ret = 0; + u16 value; + + // we are already tuned - just resuming from suspend + if (ch != NULL) + dib7000m_set_channel(state, ch, 0); + else + return -EINVAL; + + // restart demod + ret |= dib7000m_write_word(state, 898, 0x4000); + ret |= dib7000m_write_word(state, 898, 0x0000); + msleep(45); + + ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + // never achieved a lock with that bandwidth so far - wait for timfreq to update + if (state->timf == 0) + msleep(200); + + //dump_reg(state); + /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ + value = (6 << 8) | 0x80; + switch (ch->nfft) { + case 0: value |= (7 << 12); break; + case 1: value |= (9 << 12); break; + case 2: value |= (8 << 12); break; + } + ret |= dib7000m_write_word(state, 26, value); + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ + value = (0 << 4); + switch (ch->nfft) { + case 0: value |= 0x6; break; + case 1: value |= 0x8; break; + case 2: value |= 0x7; break; + } + ret |= dib7000m_write_word(state, 32, value); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ + value = (0 << 4); + switch (ch->nfft) { + case 0: value |= 0x6; break; + case 1: value |= 0x8; break; + case 2: value |= 0x7; break; + } + ret |= dib7000m_write_word(state, 33, value); + + // we achieved a lock - it's time to update the osc freq + if ((dib7000m_read_word(state, 535) >> 6) & 0x1) + dib7000m_update_timf_freq(state); + + return ret; +} + +static int dib7000m_init(struct dvb_frontend *demod) +{ + struct dib7000m_state *state = demod->demodulator_priv; + int ret = 0; + u8 o = state->reg_offs; + + dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); + + if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) + dprintk("-E- could not start Slow ADC\n"); + + if (state->cfg.dvbt_mode) + dib7000m_write_word(state, 1796, 0x0); // select DVB-T output + + if (state->cfg.mobile_mode) + ret |= dib7000m_write_word(state, 261 + o, 2); + else + ret |= dib7000m_write_word(state, 224 + o, 1); + + ret |= dib7000m_write_word(state, 173 + o, 0); + ret |= dib7000m_write_word(state, 174 + o, 0); + ret |= dib7000m_write_word(state, 175 + o, 0); + ret |= dib7000m_write_word(state, 176 + o, 0); + ret |= dib7000m_write_word(state, 177 + o, 0); + ret |= dib7000m_write_word(state, 178 + o, 0); + ret |= dib7000m_write_word(state, 179 + o, 0); + ret |= dib7000m_write_word(state, 180 + o, 0); + + // P_corm_thres Lock algorithms configuration + ret |= dib7000m_write_word(state, 26, 0x6680); + + // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on + ret |= dib7000m_write_word(state, 170 + o, 0x0410); + // P_fft_nb_to_cut + ret |= dib7000m_write_word(state, 182 + o, 8192); + // P_pha3_thres + ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); + // P_cti_use_cpe, P_cti_use_prog + ret |= dib7000m_write_word(state, 196 + o, 0); + // P_cspu_regul, P_cspu_win_cut + ret |= dib7000m_write_word(state, 205 + o, 0x200f); + // P_adp_regul_cnt + ret |= dib7000m_write_word(state, 214 + o, 0x023d); + // P_adp_noise_cnt + ret |= dib7000m_write_word(state, 215 + o, 0x00a4); + // P_adp_regul_ext + ret |= dib7000m_write_word(state, 216 + o, 0x00a4); + // P_adp_noise_ext + ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); + // P_adp_fil + ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); + + // P_2d_byp_ti_num + ret |= dib7000m_write_word(state, 226 + o, 0); + + // P_fec_* + ret |= dib7000m_write_word(state, 281 + o, 0x0010); + // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard + ret |= dib7000m_write_word(state, 294 + o,0x0062); + + // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... + if(state->cfg.tuner_is_baseband) + ret |= dib7000m_write_word(state, 36, 0x0755); + else + ret |= dib7000m_write_word(state, 36, 0x1f55); + + // auto search configuration + ret |= dib7000m_write_word(state, 2, 0x0004); + ret |= dib7000m_write_word(state, 3, 0x1000); + ret |= dib7000m_write_word(state, 4, 0x0814); + ret |= dib7000m_write_word(state, 6, 0x001b); + ret |= dib7000m_write_word(state, 7, 0x7740); + ret |= dib7000m_write_word(state, 8, 0x005b); + ret |= dib7000m_write_word(state, 9, 0x8d80); + ret |= dib7000m_write_word(state, 10, 0x01c9); + ret |= dib7000m_write_word(state, 11, 0xc380); + ret |= dib7000m_write_word(state, 12, 0x0000); + ret |= dib7000m_write_word(state, 13, 0x0080); + ret |= dib7000m_write_word(state, 14, 0x0000); + ret |= dib7000m_write_word(state, 15, 0x0090); + ret |= dib7000m_write_word(state, 16, 0x0001); + ret |= dib7000m_write_word(state, 17, 0xd4c0); + ret |= dib7000m_write_word(state, 263 + o,0x0001); + + // P_divclksel=3 P_divbitsel=1 + if (state->revision == 0x4000) + dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); + else + dib7000m_write_word(state, 909, (3 << 4) | 1); + + // Tuner IO bank: max drive (14mA) + ret |= dib7000m_write_word(state, 912 ,0x2c8a); + + ret |= dib7000m_write_word(state, 1817, 1); + + return ret; +} + +static int dib7000m_sleep(struct dvb_frontend *demod) +{ + struct dib7000m_state *st = demod->demodulator_priv; + dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); + return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | + dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | + dib7000m_set_adc_state(st, DIBX000_ADC_OFF); +} + +static int dib7000m_identify(struct dib7000m_state *state) +{ + u16 value; + if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { + dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); + return -EREMOTEIO; + } + + state->revision = dib7000m_read_word(state, 897); + if (state->revision != 0x4000 && + state->revision != 0x4001 && + state->revision != 0x4002) { + dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); + return -EREMOTEIO; + } + + /* protect this driver to be used with 7000PC */ + if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { + dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); + return -EREMOTEIO; + } + + switch (state->revision) { + case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; + case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; + case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; + } + + return 0; +} + static int dib7000m_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) @@ -133,13 +970,48 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe, static int dib7000m_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) { - return 0; + struct dib7000m_state *state = fe->demodulator_priv; + struct dibx000_ofdm_channel ch; + + INIT_OFDM_CHANNEL(&ch); + FEP2DIB(fep,&ch); + + state->current_bandwidth = fep->u.ofdm.bandwidth; + dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); + + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, fep); + + if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || + fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || + fep->u.ofdm.constellation == QAM_AUTO || + fep->u.ofdm.code_rate_HP == FEC_AUTO) { + int i = 800, found; + + dib7000m_autosearch_start(fe, &ch); + do { + msleep(1); + found = dib7000m_autosearch_is_irq(fe); + } while (found == 0 && i--); + + dprintk("autosearch returns: %d\n",found); + if (found == 0 || found == 1) + return 0; // no channel found + + dib7000m_get_frontend(fe, fep); + FEP2DIB(fep, &ch); + } + + /* make this a config parameter */ + dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); + + return dib7000m_tune(fe, &ch); } static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) { struct dib7000m_state *state = fe->demodulator_priv; - u16 lock = dib7000m_read_word(state, 509); + u16 lock = dib7000m_read_word(state, 535); *stat = 0; @@ -191,18 +1063,100 @@ static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fro return 0; } -static int dib7000m_init(struct dvb_frontend *fe) +static void dib7000m_release(struct dvb_frontend *demod) { - return 0; + struct dib7000m_state *st = demod->demodulator_priv; + dibx000_exit_i2c_master(&st->i2c_master); + kfree(st); +} + +struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) +{ + struct dib7000m_state *st = demod->demodulator_priv; + return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); } +EXPORT_SYMBOL(dib7000m_get_i2c_master); -static int dib7000m_sleep(struct dvb_frontend *fe) +int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) { + struct dib7000m_state st = { .i2c_adap = i2c }; + int k = 0; + u8 new_addr = 0; + + for (k = no_of_demods-1; k >= 0; k--) { + st.cfg = cfg[k]; + + /* designated i2c address */ + new_addr = (0x40 + k) << 1; + st.i2c_addr = new_addr; + if (dib7000m_identify(&st) != 0) { + st.i2c_addr = default_addr; + if (dib7000m_identify(&st) != 0) { + dprintk("DiB7000M #%d: not identified\n", k); + return -EIO; + } + } + + /* start diversity to pull_down div_str - just for i2c-enumeration */ + dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); + + dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output + + /* set new i2c address and force divstart */ + dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); + + dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); + } + + for (k = 0; k < no_of_demods; k++) { + st.cfg = cfg[k]; + st.i2c_addr = (0x40 + k) << 1; + + // unforce divstr + dib7000m_write_word(&st,1794, st.i2c_addr << 2); + + /* deactivate div - it was just for i2c-enumeration */ + dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); + } + return 0; } +EXPORT_SYMBOL(dib7000m_i2c_enumeration); -static void dib7000m_release(struct dvb_frontend *fe) -{ } +static struct dvb_frontend_ops dib7000m_ops; +struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) +{ + struct dvb_frontend *demod; + struct dib7000m_state *st; + st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); + if (st == NULL) + return NULL; + + memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); + st->i2c_adap = i2c_adap; + st->i2c_addr = i2c_addr; + + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); + + if (dib7000m_identify(st) != 0) + goto error; + + if (st->revision == 0x4000) + dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); + else + dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); + + dib7000m_demod_reset(st); + + return demod; + +error: + kfree(st); + return NULL; +} +EXPORT_SYMBOL(dib7000m_attach); static struct dvb_frontend_ops dib7000m_ops = { .info = { diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h index 45990e3a5ce..597e9cc2da6 100644 --- a/drivers/media/dvb/frontends/dib7000m.h +++ b/drivers/media/dvb/frontends/dib7000m.h @@ -32,12 +32,13 @@ struct dib7000m_config { u8 quartz_direct; u8 input_clk_is_div_2; + + int (*agc_control) (struct dvb_frontend *, u8 before); }; #define DEFAULT_DIB7000M_I2C_ADDRESS 18 -extern int dib7000m_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr , u8 do_i2c_enum, struct dib7000m_config[], struct dvb_frontend*[]); - +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); /* TODO diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index a18c8f45a2e..61d28de3030 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c @@ -63,7 +63,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c struct i2c_msg m[2 + num]; u8 tx_open[4], tx_close[4]; - memset(m,0, sizeof(struct i2c_msg) * (2 + num)); + memset(m,0, sizeof(struct i2c_msg) * (2 + num)), dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index bb0c65f8aee..a1df604366c 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h @@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); #define BAND_LBAND 0x01 #define BAND_UHF 0x02 #define BAND_VHF 0x04 +#define BAND_SBAND 0x08 +#define BAND_FM 0x10 + +#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ + (freq_kHz) <= 250000 ? BAND_VHF : \ + (freq_kHz) <= 863000 ? BAND_UHF : \ + (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) struct dibx000_agc_config { /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ @@ -129,6 +136,7 @@ enum dibx000_adc_states { /* I hope I can get rid of the following kludge in the near future */ struct dibx000_ofdm_channel { + u32 RF_kHz; u8 Bw; s16 nfft; s16 guard; @@ -138,9 +146,11 @@ struct dibx000_ofdm_channel { s16 vit_alpha; s16 vit_code_rate_hp; s16 vit_code_rate_lp; + u8 intlv_native; }; #define FEP2DIB(fep,ch) \ + (ch)->RF_kHz = (fep)->frequency / 1000; \ (ch)->Bw = (fep)->u.ofdm.bandwidth; \ (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ @@ -149,7 +159,8 @@ struct dibx000_ofdm_channel { (ch)->vit_select_hp = 1; \ (ch)->vit_alpha = 1; \ (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ - (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; + (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ + (ch)->intlv_native = 1; #define INIT_OFDM_CHANNEL(ch) do {\ (ch)->Bw = 0; \ -- cgit v1.2.3 From a75763ffff4175bd8c115c217a39fbf445612aae Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 18 Oct 2006 08:34:16 -0300 Subject: V4L/DVB (4772): Add support for DiBcom DiB7000PC This patch contains support for the DiB7000PC-driver. Signed-off-by: Francois KANOUNNIKOFF Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/dvb/dvb-usb/dib0700.h | 5 + drivers/media/dvb/dvb-usb/dib0700_core.c | 40 +- drivers/media/dvb/dvb-usb/dib0700_devices.c | 96 ++- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dib7000p.c | 1019 +++++++++++++++++++++++++++ drivers/media/dvb/frontends/dib7000p.h | 46 ++ 8 files changed, 1203 insertions(+), 13 deletions(-) create mode 100644 drivers/media/dvb/frontends/dib7000p.c create mode 100644 drivers/media/dvb/frontends/dib7000p.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index a0aeaf4bbb3..dfd53d5e792 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -69,6 +69,7 @@ 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_TUNER_MT2060 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index ac84347f9d4..cda3adea24f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug; #define REQUEST_I2C_WRITE 0x3 #define REQUEST_POLL_RC 0x4 #define REQUEST_JUMPRAM 0x8 +#define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_GPIO 0xC #define REQUEST_ENABLE_VIDEO 0xF // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) +#define REQUEST_GET_VERSION 0x15 struct dib0700_state { u8 channel_state; u16 mt2060_if1[2]; + + u8 is_dib7000pc; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); +extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dca6c698566..6a4d150784a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = { int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { - u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C - *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3; + u8 b[16]; + s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); + + deb_info("FW GET_VERSION length: %d\n",ret); + + *cold = ret <= 0; deb_info("cold: %d\n", *cold); return 0; } +static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, + u16 pll_loopdiv, u16 free_div, u16 dsuScaler) +{ + u8 b[10]; + b[0] = REQUEST_SET_CLOCK; + b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); + b[2] = (pll_prediv >> 8) & 0xff; // MSB + b[3] = pll_prediv & 0xff; // LSB + b[4] = (pll_loopdiv >> 8) & 0xff; // MSB + b[5] = pll_loopdiv & 0xff; // LSB + b[6] = (free_div >> 8) & 0xff; // MSB + b[7] = free_div & 0xff; // LSB + b[8] = (dsuScaler >> 8) & 0xff; // MSB + b[9] = dsuScaler & 0xff; // LSB + + return dib0700_ctrl_wr(d, b, 10); +} + +int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) +{ + switch (clk_MHz) { + case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; + default: return -EINVAL; + } + return 0; +} + static int dib0700_jumpram(struct usb_device *udev, u32 address) { int ret, actlen; @@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw /* start the firmware */ if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { info("firmware started successfully."); - msleep(100); + msleep(500); } } else ret = -EIO; diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 305dd35a102..c231a1e5204 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -10,6 +10,7 @@ #include "dib3000mc.h" #include "dib7000m.h" +#include "dib7000p.h" #include "mt2060.h" static int force_lna_activation; @@ -96,7 +97,7 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) } /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ -static struct dibx000_agc_config stk7700p_dib7000m_agc_config = { +static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { BAND_UHF | BAND_VHF, // band_caps /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, @@ -141,7 +142,52 @@ static struct dibx000_agc_config stk7700p_dib7000m_agc_config = { }, }; -static struct dibx000_bandwidth_config stk7700p_dib7000m_mt2060_config = { +static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { + BAND_UHF | BAND_VHF, + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup + + 712, // inv_gain + 41, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 4095, // wbd_ref + 0, // wbd_sel + 0, // wbd_alpha + + 42598, // agc1_max + 16384, // agc1_min + 42598, // agc2_max + 0, // agc2_min + + 0, // agc1_pt1 + 137, // agc1_pt2 + 255, // agc1_pt3 + + 0, // agc1_slope1 + 255, // agc1_slope2 + + 0, // agc2_pt1 + 0, // agc2_pt2 + + 0, // agc2_slope1 + 41, // agc2_slope2 + + 15, // alpha_mant + 25, // alpha_exp + + 28, // beta_mant + 48, // beta_exp + + 0, // perform_agc_softsplit +}; + +static struct dibx000_bandwidth_config stk7700p_pll_config = { 60000, 30000, // internal, sampling 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo @@ -156,8 +202,19 @@ static struct dib7000m_config stk7700p_dib7000m_config = { .quartz_direct = 1, .agc_config_count = 1, - .agc = &stk7700p_dib7000m_agc_config, - .bw = &stk7700p_dib7000m_mt2060_config, + .agc = &stk7700p_7000m_mt2060_agc_config, + .bw = &stk7700p_pll_config, + + .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, +}; + +static struct dib7000p_config stk7700p_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc = &stk7700p_7000p_mt2060_agc_config, + .bw = &stk7700p_pll_config, .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, @@ -168,13 +225,28 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) { struct dib0700_state *st = adap->dev->priv; /* unless there is no real power management in DVB - we leave the device on GPIO6 */ - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); + + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); - dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); + dib0700_ctrl_clock(adap->dev, 72, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); + + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); st->mt2060_if1[0] = 1220; - return (adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config)) == NULL ? -ENODEV : 0; + + if (dib7000pc_detection(&adap->dev->i2c_adap)) { + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); + st->is_dib7000pc = 1; + } else + adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); + + return adap->fe == NULL ? -ENODEV : 0; } static struct mt2060_config stk7700p_mt2060_config = { @@ -184,8 +256,14 @@ static struct mt2060_config stk7700p_mt2060_config = { static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_state *st = adap->dev->priv; - struct i2c_adapter *tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); - return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &stk7700p_mt2060_config, + struct i2c_adapter *tun_i2c; + + if (st->is_dib7000pc) + tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + else + tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + + return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, st->mt2060_if1[0]) == NULL ? -ENODEV : 0; } diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 093c7695883..7279e587e14 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -180,6 +180,14 @@ config DVB_DIB7000M A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. +config DVB_DIB7000P + tristate "DiBcom 7000PC" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 244e87417b0..593152ecf7e 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o +obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c new file mode 100644 index 00000000000..0349a4b5da3 --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -0,0 +1,1019 @@ +/* + * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). + * + * Copyright (C) 2005-6 DiBcom (http://www.dibcom.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 Free Software Foundation, version 2. + */ +#include +#include + +#include "dvb_frontend.h" + +#include "dib7000p.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) + +struct dib7000p_state { + struct dvb_frontend demod; + struct dib7000p_config cfg; + + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + + struct dibx000_i2c_master i2c_master; + + u16 wbd_ref; + + u8 current_band; + fe_bandwidth_t current_bandwidth; + struct dibx000_agc_config *current_agc; + u32 timf; + + u16 gpio_dir; + u16 gpio_val; +}; + +enum dib7000p_power_mode { + DIB7000P_POWER_ALL = 0, + DIB7000P_POWER_INTERFACE_ONLY, +}; + +static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) +{ + u8 wb[2] = { reg >> 8, reg & 0xff }; + u8 rb[2]; + struct i2c_msg msg[2] = { + { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + + if (i2c_transfer(state->i2c_adap, msg, 2) != 2) + dprintk("i2c read error on %d\n",reg); + + return (rb[0] << 8) | rb[1]; +} + +static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) +{ + u8 b[4] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg = { + .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 + }; + return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; +} +static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) +{ + int ret = 0; + u16 outreg, fifo_threshold, smo_mode; + + outreg = 0; + fifo_threshold = 1792; + smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); + + dprintk("-I- Setting output mode for demod %p to %d\n", + &state->demod, mode); + + switch (mode) { + case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock + outreg = (1 << 10); /* 0x0400 */ + break; + case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock + outreg = (1 << 10) | (1 << 6); /* 0x0440 */ + break; + case OUTMODE_MPEG2_SERIAL: // STBs with serial input + outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */ + break; + case OUTMODE_DIVERSITY: + if (state->cfg.hostbus_diversity) + outreg = (1 << 10) | (4 << 6); /* 0x0500 */ + else + outreg = (1 << 11); + break; + case OUTMODE_MPEG2_FIFO: // e.g. USB feeding + smo_mode |= (3 << 1); + fifo_threshold = 512; + outreg = (1 << 10) | (5 << 6); + break; + case OUTMODE_HIGH_Z: // disable + outreg = 0; + break; + default: + dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); + break; + } + + if (state->cfg.output_mpeg2_in_188_bytes) + smo_mode |= (1 << 5) ; + + ret |= dib7000p_write_word(state, 235, smo_mode); + ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ + ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */ + + return ret; +} + +static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) +{ + /* by default everything is powered off */ + u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, + reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff); + + /* now, depending on the requested mode, we power on */ + switch (mode) { + /* power up everything in the demod */ + case DIB7000P_POWER_ALL: + reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; + break; + /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ + case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ + reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); + break; +/* TODO following stuff is just converted from the dib7000-driver - check when is used what */ + } + + dib7000p_write_word(state, 774, reg_774); + dib7000p_write_word(state, 775, reg_775); + dib7000p_write_word(state, 776, reg_776); + dib7000p_write_word(state, 899, reg_899); + dib7000p_write_word(state, 1280, reg_1280); + + return 0; +} + +static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) +{ + u16 reg_908 = dib7000p_read_word(state, 908), + reg_909 = dib7000p_read_word(state, 909); + + switch (no) { + case DIBX000_SLOW_ADC_ON: + reg_909 |= (1 << 1) | (1 << 0); + dib7000p_write_word(state, 909, reg_909); + reg_909 &= ~(1 << 1); + break; + + case DIBX000_SLOW_ADC_OFF: + reg_909 |= (1 << 1) | (1 << 0); + break; + + case DIBX000_ADC_ON: + reg_908 &= 0x0fff; + reg_909 &= 0x0003; + break; + + case DIBX000_ADC_OFF: // leave the VBG voltage on + reg_908 |= (1 << 14) | (1 << 13) | (1 << 12); + reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); + break; + + case DIBX000_VBG_ENABLE: + reg_908 &= ~(1 << 15); + break; + + case DIBX000_VBG_DISABLE: + reg_908 |= (1 << 15); + break; + + default: + break; + } + +// dprintk("908: %x, 909: %x\n", reg_908, reg_909); + + dib7000p_write_word(state, 908, reg_908); + dib7000p_write_word(state, 909, reg_909); +} + +static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u32 timf; + + // store the current bandwidth for later use + state->current_bandwidth = BW_Idx; + + if (state->timf == 0) { + dprintk("-D- Using default timf\n"); + timf = state->cfg.bw->timf; + } else { + dprintk("-D- Using updated timf\n"); + timf = state->timf; + } + + timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; + + dprintk("timf: %d\n",timf); + + dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); + dib7000p_write_word(state, 24, (timf ) & 0xffff); + + return 0; +} + +static int dib7000p_sad_calib(struct dib7000p_state *state) +{ +/* internal */ +// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth + dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); + dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 + + /* do the calibration */ + dib7000p_write_word(state, 73, (1 << 0)); + dib7000p_write_word(state, 73, (0 << 0)); + + msleep(1); + + return 0; +} + +static void dib7000p_reset_pll(struct dib7000p_state *state) +{ + struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; + + dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); + dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | + (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); + + dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); + dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); + dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); + dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); + + dib7000p_write_word(state, 72, bw->sad_cfg); +} + +static int dib7000p_reset_gpio(struct dib7000p_state *st) +{ + /* reset the GPIOs */ + dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); + + dib7000p_write_word(st, 1029, st->gpio_dir); + dib7000p_write_word(st, 1030, st->gpio_val); + + /* TODO 1031 is P_gpio_od */ + + dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos); + + dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div); + return 0; +} + +static int dib7000p_demod_reset(struct dib7000p_state *state) +{ + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + + dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); + + /* restart all parts */ + dib7000p_write_word(state, 770, 0xffff); + dib7000p_write_word(state, 771, 0xffff); + dib7000p_write_word(state, 772, 0x001f); + dib7000p_write_word(state, 898, 0x0003); + /* except i2c, sdio, gpio - control interfaces */ + dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); + + dib7000p_write_word(state, 770, 0); + dib7000p_write_word(state, 771, 0); + dib7000p_write_word(state, 772, 0); + dib7000p_write_word(state, 898, 0); + dib7000p_write_word(state, 1280, 0); + + /* default */ + dib7000p_reset_pll(state); + + if (dib7000p_reset_gpio(state) != 0) + dprintk("-E- GPIO reset was not successful.\n"); + + if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) + dprintk("-E- OUTPUT_MODE could not be resetted.\n"); + + /* unforce divstr regardless whether i2c enumeration was done or not */ + dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); + + dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); + + return 0; +} + +static void dib7000p_restart_agc(struct dib7000p_state *state) +{ + // P_restart_iqc & P_restart_agc + dib7000p_write_word(state, 770, 0x0c00); + dib7000p_write_word(state, 770, 0x0000); +} + +static void dib7000p_update_lna(struct dib7000p_state *state) +{ + int i; + u16 dyn_gain; + + // when there is no LNA to program return immediatly + if (state->cfg.update_lna == NULL) + return; + + for (i = 0; i < 5; i++) { + // read dyn_gain here (because it is demod-dependent and not tuner) + dyn_gain = dib7000p_read_word(state, 394); + + if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed + dib7000p_restart_agc(state); + msleep(5); + } else + break; + } +} + +static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) +{ + u16 tmp = 0; + tmp = dib7000p_read_word(state, 903); + dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll + tmp = dib7000p_read_word(state, 900); + dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock +} + +static void dib7000p_update_timf_freq(struct dib7000p_state *state) +{ + u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); + state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); + dib7000p_write_word(state, 23, (u16) (timf >> 16)); + dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); + dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); +} + +static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) +{ + u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; + + /* nfft, guard, qam, alpha */ + dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); + dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ + + /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ + tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); + if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) + tmp |= (ch->vit_code_rate_hp << 1); + else + tmp |= (ch->vit_code_rate_lp << 1); + dib7000p_write_word(state, 208, tmp); + + /* P_dvsy_sync_wait */ + switch (ch->nfft) { + case 1: tmp = 256; break; + case 2: tmp = 128; break; + case 0: + default: tmp = 64; break; + } + tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin + tmp <<= 4; + + /* deactive the possibility of diversity reception if extended interleave */ + /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ + if (ch->intlv_native || ch->nfft == 1) + tmp |= (1 << 2) | (2 << 0); + dib7000p_write_word(state, 207, tmp); + + dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) + dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 + dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) + dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) + + /* channel estimation fine configuration */ + switch (ch->nqam) { + case 2: + est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ + est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ + break; + case 1: + est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ + est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ + break; + default: + est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ + est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ + est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ + break; + } + for (tmp = 0; tmp < 4; tmp++) + dib7000p_write_word(state, 187 + tmp, est[tmp]); + + // set power-up level: interf+analog+AGC + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + dib7000p_set_adc_state(state, DIBX000_ADC_ON); + dib7000p_pll_clk_cfg(state); + msleep(7); + + // AGC initialization + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 1); + + dib7000p_restart_agc(state); + + // wait AGC rough lock time + msleep(5); + + dib7000p_update_lna(state); + + // wait AGC accurate lock time + msleep(7); + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 0); +} + +static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000p_state *state = demod->demodulator_priv; + struct dibx000_ofdm_channel auto_ch; + u32 value; + + INIT_OFDM_CHANNEL(&auto_ch); + auto_ch.RF_kHz = ch->RF_kHz; + auto_ch.Bw = ch->Bw; + auto_ch.nqam = 2; + auto_ch.guard = 0; + auto_ch.nfft = 1; + auto_ch.vit_alpha = 1; + auto_ch.vit_select_hp = 1; + auto_ch.vit_code_rate_hp = 2; + auto_ch.vit_code_rate_lp = 3; + auto_ch.vit_hrch = 0; + auto_ch.intlv_native = 1; + + dib7000p_set_channel(state, &auto_ch, 7); + + // always use the setting for 8MHz here lock_time for 7,6 MHz are longer + value = 30 * state->cfg.bw->internal; + dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time + dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time + value = 100 * state->cfg.bw->internal; + dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time + dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time + value = 500 * state->cfg.bw->internal; + dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time + dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time + + value = dib7000p_read_word(state, 0); + dib7000p_write_word(state, 0, (1 << 9) | value); + dib7000p_read_word(state, 1284); + dib7000p_write_word(state, 0, (u16) value); + + return 0; +} + +static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u16 irq_pending = dib7000p_read_word(state, 1284); + + if (irq_pending & 0x1) // failed + return 1; + + if (irq_pending & 0x2) // succeeded + return 2; + + return 0; // still pending +} + +static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u16 tmp = 0; + + if (ch != NULL) + dib7000p_set_channel(state, ch, 0); + else + return -EINVAL; + + // restart demod + dib7000p_write_word(state, 770, 0x4000); + dib7000p_write_word(state, 770, 0x0000); + msleep(45); + + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + // never achieved a lock with that bandwidth so far - wait for osc-freq to update + if (state->timf == 0) + msleep(200); + + /* offset loop parameters */ + + /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ + tmp = (6 << 8) | 0x80; + switch (ch->nfft) { + case 0: tmp |= (7 << 12); break; + case 1: tmp |= (9 << 12); break; + case 2: tmp |= (8 << 12); break; + } + dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ + tmp = (0 << 4); + switch (ch->nfft) { + case 0: tmp |= 0x6; break; + case 1: tmp |= 0x8; break; + case 2: tmp |= 0x7; break; + } + dib7000p_write_word(state, 32, tmp); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ + tmp = (0 << 4); + switch (ch->nfft) { + case 0: tmp |= 0x6; break; + case 1: tmp |= 0x8; break; + case 2: tmp |= 0x7; break; + } + dib7000p_write_word(state, 33, tmp); + + tmp = dib7000p_read_word(state,509); + if (!((tmp >> 6) & 0x1)) { + /* restart the fec */ + tmp = dib7000p_read_word(state,771); + dib7000p_write_word(state, 771, tmp | (1 << 1)); + dib7000p_write_word(state, 771, tmp); + msleep(10); + tmp = dib7000p_read_word(state,509); + } + + // we achieved a lock - it's time to update the osc freq + if ((tmp >> 6) & 0x1) + dib7000p_update_timf_freq(state); + + return 0; +} + +static int dib7000p_init(struct dvb_frontend *demod) +{ + struct dibx000_agc_config *agc; + struct dib7000p_state *state = demod->demodulator_priv; + int ret = 0; + + // Demodulator default configuration + agc = state->cfg.agc; + + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); + + /* AGC */ + ret |= dib7000p_write_word(state, 75 , agc->setup ); + ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); + ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); + ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); + + // Demod AGC loop configuration + ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); + ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); + + /* AGC continued */ + dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", + state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); + + if (state->wbd_ref != 0) + ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); + else + ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); + + ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); + + ret |= dib7000p_write_word(state, 107, agc->agc1_max); + ret |= dib7000p_write_word(state, 108, agc->agc1_min); + ret |= dib7000p_write_word(state, 109, agc->agc2_max); + ret |= dib7000p_write_word(state, 110, agc->agc2_min); + ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); + ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); + ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); + ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); + ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); + + /* disable power smoothing */ + ret |= dib7000p_write_word(state, 145, 0); + ret |= dib7000p_write_word(state, 146, 0); + ret |= dib7000p_write_word(state, 147, 0); + ret |= dib7000p_write_word(state, 148, 0); + ret |= dib7000p_write_word(state, 149, 0); + ret |= dib7000p_write_word(state, 150, 0); + ret |= dib7000p_write_word(state, 151, 0); + ret |= dib7000p_write_word(state, 152, 0); + + // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 + ret |= dib7000p_write_word(state, 26 ,0x6680); + + // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 + ret |= dib7000p_write_word(state, 142,0x0410); + // P_fft_freq_dir=1, P_fft_nb_to_cut=0 + ret |= dib7000p_write_word(state, 154,1 << 13); + // P_pha3_thres, default 0x3000 + ret |= dib7000p_write_word(state, 168,0x0ccd); + // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 + //ret |= dib7000p_write_word(state, 169,0x0010); + // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 + ret |= dib7000p_write_word(state, 183,0x200f); + // P_adp_regul_cnt=573, default: 410 + ret |= dib7000p_write_word(state, 187,0x023d); + // P_adp_noise_cnt= + ret |= dib7000p_write_word(state, 188,0x00a4); + // P_adp_regul_ext + ret |= dib7000p_write_word(state, 189,0x00a4); + // P_adp_noise_ext + ret |= dib7000p_write_word(state, 190,0x7ff0); + // P_adp_fil + ret |= dib7000p_write_word(state, 191,0x3ccc); + + ret |= dib7000p_write_word(state, 222,0x0010); + // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard + ret |= dib7000p_write_word(state, 235,0x0062); + + // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... + if(state->cfg.tuner_is_baseband) + ret |= dib7000p_write_word(state, 36,0x0755); + else + ret |= dib7000p_write_word(state, 36,0x1f55); + + // auto search configuration + ret |= dib7000p_write_word(state, 2 ,0x0004); + ret |= dib7000p_write_word(state, 3 ,0x1000); + + /* Equal Lock */ + ret |= dib7000p_write_word(state, 4 ,0x0814); + + ret |= dib7000p_write_word(state, 6 ,0x001b); + ret |= dib7000p_write_word(state, 7 ,0x7740); + ret |= dib7000p_write_word(state, 8 ,0x005b); + ret |= dib7000p_write_word(state, 9 ,0x8d80); + ret |= dib7000p_write_word(state, 10 ,0x01c9); + ret |= dib7000p_write_word(state, 11 ,0xc380); + ret |= dib7000p_write_word(state, 12 ,0x0000); + ret |= dib7000p_write_word(state, 13 ,0x0080); + ret |= dib7000p_write_word(state, 14 ,0x0000); + ret |= dib7000p_write_word(state, 15 ,0x0090); + ret |= dib7000p_write_word(state, 16 ,0x0001); + ret |= dib7000p_write_word(state, 17 ,0xd4c0); + + // P_clk_cfg1 + ret |= dib7000p_write_word(state, 901, 0x0006); + + // P_divclksel=3 P_divbitsel=1 + ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); + + // Tuner IO bank: max drive (14mA) + divout pads max drive + ret |= dib7000p_write_word(state, 905, 0x2c8e); + + ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); + dib7000p_sad_calib(state); + + return ret; +} + +static int dib7000p_sleep(struct dvb_frontend *demod) +{ + struct dib7000p_state *state = demod->demodulator_priv; + return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); +} + +static int dib7000p_identify(struct dib7000p_state *st) +{ + u16 value; + dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", + st->i2c_addr, st->i2c_addr); + + if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { + dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); + return -EREMOTEIO; + } + + if ((value = dib7000p_read_word(st, 769)) != 0x4000) { + dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); + return -EREMOTEIO; + } + + return 0; +} + + +static int dib7000p_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 tps = dib7000p_read_word(state,463); + + fep->inversion = INVERSION_AUTO; + + fep->u.ofdm.bandwidth = state->current_bandwidth; + + switch ((tps >> 8) & 0x3) { + case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; + /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ + } + + switch (tps & 0x3) { + case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; + case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; + case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; + case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; + } + + switch ((tps >> 14) & 0x3) { + case 0: fep->u.ofdm.constellation = QPSK; break; + case 1: fep->u.ofdm.constellation = QAM_16; break; + case 2: + default: fep->u.ofdm.constellation = QAM_64; break; + } + + /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ + /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ + + fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; + switch ((tps >> 5) & 0x7) { + case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; + + } + + switch ((tps >> 2) & 0x7) { + case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; + } + + /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */ + + return 0; +} + +static int dib7000p_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib7000p_state *state = fe->demodulator_priv; + struct dibx000_ofdm_channel ch; + + INIT_OFDM_CHANNEL(&ch); + FEP2DIB(fep,&ch); + + state->current_bandwidth = fep->u.ofdm.bandwidth; + dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); + + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, fep); + + if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || + fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || + fep->u.ofdm.constellation == QAM_AUTO || + fep->u.ofdm.code_rate_HP == FEC_AUTO) { + int i = 800, found; + + dib7000p_autosearch_start(fe, &ch); + do { + msleep(1); + found = dib7000p_autosearch_is_irq(fe); + } while (found == 0 && i--); + + dprintk("autosearch returns: %d\n",found); + if (found == 0 || found == 1) + return 0; // no channel found + + dib7000p_get_frontend(fe, fep); + FEP2DIB(fep, &ch); + } + + /* make this a config parameter */ + dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); + + return dib7000p_tune(fe, &ch); +} + +static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 lock = dib7000p_read_word(state, 509); + + *stat = 0; + + if (lock & 0x8000) + *stat |= FE_HAS_SIGNAL; + if (lock & 0x3000) + *stat |= FE_HAS_CARRIER; + if (lock & 0x0100) + *stat |= FE_HAS_VITERBI; + if (lock & 0x0010) + *stat |= FE_HAS_SYNC; + if (lock & 0x0008) + *stat |= FE_HAS_LOCK; + + return 0; +} + +static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct dib7000p_state *state = fe->demodulator_priv; + *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501); + return 0; +} + +static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) +{ + struct dib7000p_state *state = fe->demodulator_priv; + *unc = dib7000p_read_word(state, 506); + return 0; +} + +static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 val = dib7000p_read_word(state, 394); + *strength = 65535 - val; + return 0; +} + +static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) +{ + *snr = 0x0000; + return 0; +} + +static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static void dib7000p_release(struct dvb_frontend *demod) +{ + struct dib7000p_state *st = demod->demodulator_priv; + dibx000_exit_i2c_master(&st->i2c_master); + kfree(st); +} + +int dib7000pc_detection(struct i2c_adapter *i2c_adap) +{ + u8 tx[2], rx[2]; + struct i2c_msg msg[2] = { + { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 }, + { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 }, + }; + + tx[0] = 0x03; + tx[1] = 0x00; + + if (i2c_transfer(i2c_adap, msg, 2) == 2) + if (rx[0] == 0x01 && rx[1] == 0xb3) { + dprintk("-D- DiB7000PC detected\n"); + return 1; + } + + msg[0].addr = msg[1].addr = 0x40; + + if (i2c_transfer(i2c_adap, msg, 2) == 2) + if (rx[0] == 0x01 && rx[1] == 0xb3) { + dprintk("-D- DiB7000PC detected\n"); + return 1; + } + + dprintk("-D- DiB7000PC not detected\n"); + return 0; +} +EXPORT_SYMBOL(dib7000pc_detection); + +struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) +{ + struct dib7000p_state *st = demod->demodulator_priv; + return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); +} +EXPORT_SYMBOL(dib7000p_get_i2c_master); + +int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) +{ + struct dib7000p_state st = { .i2c_adap = i2c }; + int k = 0; + u8 new_addr = 0; + + for (k = no_of_demods-1; k >= 0; k--) { + st.cfg = cfg[k]; + + /* designated i2c address */ + new_addr = (0x40 + k) << 1; + st.i2c_addr = new_addr; + if (dib7000p_identify(&st) != 0) { + st.i2c_addr = default_addr; + if (dib7000p_identify(&st) != 0) { + dprintk("DiB7000P #%d: not identified\n", k); + return -EIO; + } + } + + /* start diversity to pull_down div_str - just for i2c-enumeration */ + dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); + + /* set new i2c address and force divstart */ + dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); + + dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); + } + + for (k = 0; k < no_of_demods; k++) { + st.cfg = cfg[k]; + st.i2c_addr = (0x40 + k) << 1; + + // unforce divstr + dib7000p_write_word(&st, 1285, st.i2c_addr << 2); + + /* deactivate div - it was just for i2c-enumeration */ + dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); + } + + return 0; +} +EXPORT_SYMBOL(dib7000p_i2c_enumeration); + +static struct dvb_frontend_ops dib7000p_ops; +struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) +{ + struct dvb_frontend *demod; + struct dib7000p_state *st; + st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); + if (st == NULL) + return NULL; + + memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config)); + st->i2c_adap = i2c_adap; + st->i2c_addr = i2c_addr; + st->gpio_val = cfg->gpio_val; + st->gpio_dir = cfg->gpio_dir; + + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); + + if (dib7000p_identify(st) != 0) + goto error; + + dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); + + dib7000p_demod_reset(st); + + return demod; + +error: + kfree(st); + return NULL; +} +EXPORT_SYMBOL(dib7000p_attach); + +static struct dvb_frontend_ops dib7000p_ops = { + .info = { + .name = "DiBcom 7000PC", + .type = FE_OFDM, + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dib7000p_release, + + .init = dib7000p_init, + .sleep = dib7000p_sleep, + + .set_frontend = dib7000p_set_frontend, + .get_tune_settings = dib7000p_fe_get_tune_settings, + .get_frontend = dib7000p_get_frontend, + + .read_status = dib7000p_read_status, + .read_ber = dib7000p_read_ber, + .read_signal_strength = dib7000p_read_signal_strength, + .read_snr = dib7000p_read_snr, + .read_ucblocks = dib7000p_read_unc_blocks, +}; + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h new file mode 100644 index 00000000000..79465cf1ace --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -0,0 +1,46 @@ +#ifndef DIB7000P_H +#define DIB7000P_H + +#include "dibx000_common.h" + +struct dib7000p_config { + u8 output_mpeg2_in_188_bytes; + u8 hostbus_diversity; + u8 tuner_is_baseband; + int (*update_lna) (struct dvb_frontend *, u16 agc_global); + + struct dibx000_agc_config *agc; + struct dibx000_bandwidth_config *bw; + +#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff + u16 gpio_dir; +#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000 + u16 gpio_val; +#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12) +#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) +#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) +#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf) +#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff + u16 gpio_pwm_pos; + + u16 pwm_freq_div; + + u8 quartz_direct; + + int (*agc_control) (struct dvb_frontend *, u8 before); +}; + +#define DEFAULT_DIB7000P_I2C_ADDRESS 18 + +extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); +extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); +extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); + +/* TODO +extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); +extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); +extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); +extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); +*/ + +#endif -- cgit v1.2.3 From d92532d9860663cb39828e18a3e6aed27821f2bf Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 18 Oct 2006 08:35:16 -0300 Subject: V4L/DVB (4773): Misc fixes for DiB3000 and DiB7000 This patch contains several fixes for the autosearch algorithm and other small ones. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib3000mc.c | 7 +------ drivers/media/dvb/frontends/dib7000m.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 3561a777568..5da66178006 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c @@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000 /* a channel for autosearch */ - reg = 0; - if (chan->nfft == -1 && chan->guard == -1) reg = 7; - if (chan->nfft == -1 && chan->guard != -1) reg = 2; - if (chan->nfft != -1 && chan->guard == -1) reg = 3; - fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; fchan.vit_hrch = 0; fchan.vit_select_hp = 1; - dib3000mc_set_channel_cfg(state, &fchan, reg); + dib3000mc_set_channel_cfg(state, &fchan, 7); reg = dib3000mc_read_word(state, 0); dib3000mc_write_word(state, 0, reg | (1 << 8)); diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index a85190319cf..f5d40aa3d27 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -637,15 +637,14 @@ static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ struct dib7000m_state *state = demod->demodulator_priv; struct dibx000_ofdm_channel auto_ch; int ret = 0; - u8 seq; u32 value; INIT_OFDM_CHANNEL(&auto_ch); auto_ch.RF_kHz = ch->RF_kHz; auto_ch.Bw = ch->Bw; auto_ch.nqam = 2; - auto_ch.guard = ch->guard == GUARD_INTERVAL_AUTO ? 0 : ch->guard; - auto_ch.nfft = ch->nfft == -1 ? 1 : ch->nfft; + auto_ch.guard = 0; + auto_ch.nfft = 1; auto_ch.vit_alpha = 1; auto_ch.vit_select_hp = 1; auto_ch.vit_code_rate_hp = 2; @@ -653,20 +652,16 @@ static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ auto_ch.vit_hrch = 0; auto_ch.intlv_native = 1; - seq = 0; - if (ch->nfft == -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 7; - if (ch->nfft == -1 && ch->guard != GUARD_INTERVAL_AUTO) seq = 2; - if (ch->nfft != -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 3; - dib7000m_set_channel(state, &auto_ch, seq); + dib7000m_set_channel(state, &auto_ch, 7); // always use the setting for 8MHz here lock_time for 7,6 MHz are longer - value = 30 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + value = 30 * state->cfg.bw->internal; ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time - value = 100 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + value = 100 * state->cfg.bw->internal; ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time - value = 500 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; + value = 500 * state->cfg.bw->internal; ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time @@ -919,7 +914,7 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe, fep->u.ofdm.bandwidth = state->current_bandwidth; - switch ((tps >> 8) & 0x2) { + switch ((tps >> 8) & 0x3) { case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ -- cgit v1.2.3 From 49a1376cf47b644f31d0fb2532054183fcec6fc8 Mon Sep 17 00:00:00 2001 From: Tomi Koivulahti Date: Thu, 19 Oct 2006 07:27:19 -0300 Subject: V4L/DVB (4775): [patch] Add Compro USB IDs This patch adds Compro Videomate U500 to supported devices. Signed-off-by: Tomi Koivulahti Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 18 ++++++++++++------ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 5 +++-- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index c231a1e5204..fe305f4430e 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -269,11 +269,13 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, - { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -315,20 +317,24 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "DiBcom STK7700P reference design", - { &dib0700_usb_id_table[0], &dib0700_usb_id_table[5] }, + { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, { NULL }, }, { "Hauppauge Nova-T Stick", - { &dib0700_usb_id_table[3], NULL }, + { &dib0700_usb_id_table[4], NULL }, { NULL }, }, { "AVerMedia AVerTV DVB-T Volar", - { &dib0700_usb_id_table[4], NULL }, + { &dib0700_usb_id_table[5], NULL }, { NULL }, }, + { "Compro Videomate U500", + { &dib0700_usb_id_table[6], NULL }, + { NULL }, + } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -350,7 +356,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_device_descs = 1, .devices = { { "Hauppauge Nova-T 500 Dual DVB-T", - { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL }, + { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, { NULL }, }, } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index fd8ba2535c0..036fb143320 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -46,6 +46,7 @@ #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d +#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 @@ -111,8 +112,8 @@ #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 #define USB_PID_MEDION_MD95700 0x0932 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f -- cgit v1.2.3 From 0ce215e1f0d40702d6233029d234293754610fd7 Mon Sep 17 00:00:00 2001 From: Henning Schroeer Date: Thu, 19 Oct 2006 07:58:22 -0300 Subject: V4L/DVB (4776): Adding USB IDs for Uniwill STK7700P-ref-design Adding USB IDs for Uniwill STK7700P-ref-design Signed-off-by: Henning Schroeer Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 5 +++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index fe305f4430e..92cf071ee97 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -276,6 +276,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, + { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -334,6 +335,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Compro Videomate U500", { &dib0700_usb_id_table[6], NULL }, { NULL }, + }, + { "Uniwill STK7700P based (Hama and others)", + { &dib0700_usb_id_table[7], NULL }, + { NULL }, } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 036fb143320..58e1a449b42 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -32,6 +32,7 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 +#define USB_VID_UNIWILL 0x1584 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_WIDEVIEW 0x14aa @@ -56,6 +57,7 @@ #define USB_PID_DIBCOM_STK7700P 0x1e14 #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 +#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_KWORLD_VSTREAM_COLD 0x17de @@ -130,4 +132,5 @@ #define USB_PID_GENPIX_8PSK_COLD 0x0200 #define USB_PID_GENPIX_8PSK_WARM 0x0201 + #endif -- cgit v1.2.3 From bf11f5e944b3bb7d310aff041a1664fb80a82078 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Thu, 19 Oct 2006 08:17:43 -0300 Subject: V4L/DVB (4778): Fixed device count Forgot to increase the device count for the STK7700P-devices Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 92cf071ee97..1b1598d087b 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -318,7 +318,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 4, + .num_device_descs = 5, .devices = { { "DiBcom STK7700P reference design", { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, -- cgit v1.2.3 From dbb2e6392b4fe350e549cdc2d42cebf3b3574a6a Mon Sep 17 00:00:00 2001 From: Christoph Haubrich Date: Tue, 31 Oct 2006 00:29:30 -0300 Subject: V4L/DVB (4788): Tda8083: support for uncorrectable blocks and bit error rate Copied routines for uc blocks and BER from the removed tda80xx.c into tda8083.c. Signed-off-by: Christoph Haubrich Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda8083.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 3aa45ebbac3..67415c9db6f 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c @@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status) if (sync & 0x10) *status |= FE_HAS_SYNC; + if (sync & 0x20) /* frontend can not lock */ + *status |= FE_TIMEDOUT; + if ((sync & 0x1f) == 0x1f) *status |= FE_HAS_LOCK; return 0; } +static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct tda8083_state* state = fe->demodulator_priv; + int ret; + u8 buf[3]; + + if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf)))) + return ret; + + *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; + + return 0; +} + static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) { struct tda8083_state* state = fe->demodulator_priv; @@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr) return 0; } +static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct tda8083_state* state = fe->demodulator_priv; + + *ucblocks = tda8083_readreg(state, 0x0f); + if (*ucblocks == 0xff) + *ucblocks = 0xffffffff; + + return 0; +} + static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct tda8083_state* state = fe->demodulator_priv; @@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = { .read_status = tda8083_read_status, .read_signal_strength = tda8083_read_signal_strength, .read_snr = tda8083_read_snr, + .read_ber = tda8083_read_ber, + .read_ucblocks = tda8083_read_ucblocks, .diseqc_send_master_cmd = tda8083_send_diseqc_msg, .diseqc_send_burst = tda8083_diseqc_send_burst, -- cgit v1.2.3 From 19be685a4a5475ecdbbbb579458eeda890d27a96 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sun, 29 Oct 2006 13:35:39 -0300 Subject: V4L/DVB (4789): Lgdt330x: SNR and signal strength reporting Update the SNR calculations to use the new dvb_math log function, and add SNR calculations for all supported modulations for both lg dt3302 and dt3303. The QAM equations don't appear in the dt3302 datasheet, so the ones from the dt3303 datasheet were used. SNR returned is the actual value in dB as 8.8 fixed point. Reporting of real signal strength isn't supported, so rather than return 0, which confuses some software and users, a re-scaled SNR value is returned. Code originally by Rusty Scott. Signed-off-by: Trent Piepho Signed-off-by: Rusty Scott Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt330x.c | 243 ++++++++++++++-------------- drivers/media/dvb/frontends/lgdt330x_priv.h | 15 +- 2 files changed, 132 insertions(+), 126 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 9a354708bd2..db3ef58dafb 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -31,9 +31,6 @@ * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) * pcHDTV HD5500 * - * TODO: - * signal strength always returns 0. - * */ #include @@ -46,9 +43,13 @@ #include #include "dvb_frontend.h" +#include "dvb_math.h" #include "lgdt330x_priv.h" #include "lgdt330x.h" +/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ +/* #define USE_EQMSE */ + static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); @@ -68,6 +69,7 @@ struct lgdt330x_state /* Demodulator private data */ fe_modulation_t current_modulation; + u32 snr; /* Result of last SNR calculation */ /* Tuner private data */ u32 current_frequency; @@ -543,151 +545,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) +/* Calculate SNR estimation (scaled by 2^24) + + 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM + equations from LGDT3303 datasheet. VSB is the same between the '02 + and '03, so maybe QAM is too? Perhaps someone with a newer datasheet + that has QAM information could verify? + + For 8-VSB: (two ways, take your pick) + LGDT3302: + SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE) + LGDT3303: + SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE) + LGDT3302 & LGDT3303: + SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one) + For 64-QAM: + SNR = 10 * log10( 688128 / MSEQAM) + For 256-QAM: + SNR = 10 * log10( 696320 / MSEQAM) + + We re-write the snr equation as: + SNR * 2^24 = 10*(c - intlog10(MSE)) + Where for 256-QAM, c = log10(696320) * 2^24, and so on. */ + +static u32 calculate_snr(u32 mse, u32 c) { - /* not directly available. */ - *strength = 0; - return 0; + 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 lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) { -#ifdef SNR_IN_DB - /* - * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise) - * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker - * respectively. The following tables are built on these formulas. - * The usual definition is SNR = 20 log10(signal/noise) - * If the specification is wrong the value retuned is 1/2 the actual SNR in db. - * - * This table is a an ordered list of noise values computed by the - * formula from the spec sheet such that the index into the table - * starting at 43 or 45 is the SNR value in db. There are duplicate noise - * value entries at the beginning because the SNR varies more than - * 1 db for a change of 1 digit in noise at very small values of noise. - * - * Examples from SNR_EQ table: - * noise SNR - * 0 43 - * 1 42 - * 2 39 - * 3 37 - * 4 36 - * 5 35 - * 6 34 - * 7 33 - * 8 33 - * 9 32 - * 10 32 - * 11 31 - * 12 31 - * 13 30 - */ - - static const u32 SNR_EQ[] = - { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7, - 9, 11, 13, 17, 21, 26, 33, 41, 52, 65, - 81, 102, 129, 162, 204, 257, 323, 406, 511, 644, - 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433, - 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323, - 80978, 101945, 128341, 161571, 203406, 256073, 0x40000 - }; - - static const u32 SNR_PH[] = - { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8, - 10, 12, 15, 19, 23, 29, 37, 46, 58, 73, - 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, - 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, - 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, - 90833, 114351, 143960, 181235, 228161, 0x080000 - }; - - static u8 buf[5];/* read data buffer */ - static u32 noise; /* noise value */ - static u32 snr_db; /* index into SNR_EQ[] */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + u8 buf[5]; /* read data buffer */ + u32 noise; /* noise value */ + u32 c; /* per-modulation SNR calculation constant */ - /* read both equalizer and phase tracker noise data */ - i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); - - if (state->current_modulation == VSB_8) { - /* Equalizer Mean-Square Error Register for VSB */ + switch(state->current_modulation) { + case VSB_8: + i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5); +#ifdef USE_EQMSE + /* Use Equalizer Mean-Square Error Register */ + /* SNR for ranges from -15.61 to +41.58 */ noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; - - /* - * Look up noise value in table. - * A better search algorithm could be used... - * watch out there are duplicate entries. - */ - for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) { - if (noise < SNR_EQ[snr_db]) { - *snr = 43 - snr_db; - break; - } - } - } else { - /* Phase Tracker Mean-Square Error Register for QAM */ - noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; - - /* Look up noise value in table. */ - for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) { - if (noise < SNR_PH[snr_db]) { - *snr = 45 - snr_db; - break; - } - } - } + c = 69765745; /* log10(25*24^2)*2^24 */ #else - /* Return the raw noise value */ - static u8 buf[5];/* read data buffer */ - static u32 noise; /* noise value */ - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - - /* read both equalizer and pase tracker noise data */ - i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); - - if (state->current_modulation == VSB_8) { - /* Phase Tracker Mean-Square Error Register for VSB */ + /* Use Phase Tracker Mean-Square Error Register */ + /* SNR for ranges from -13.11 to +44.08 */ noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; - } else { - - /* Carrier Recovery Mean-Square Error for QAM */ - i2c_read_demod_bytes(state, 0x1a, buf, 2); + c = 73957994; /* log10(25*32^2)*2^24 */ +#endif + break; + case QAM_64: + case QAM_256: + i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); noise = ((buf[0] & 3) << 8) | buf[1]; + c = state->current_modulation == QAM_64 ? 97939837 : 98026066; + /* log10(688128)*2^24 and log10(696320)*2^24 */ + break; + default: + printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", + __FUNCTION__); + return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } - /* Small values for noise mean signal is better so invert noise */ - *snr = ~noise; -#endif + state->snr = calculate_snr(noise, c); + *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ - dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; } static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) { - /* Return the raw noise value */ - static u8 buf[5];/* read data buffer */ - static u32 noise; /* noise value */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + u8 buf[5]; /* read data buffer */ + u32 noise; /* noise value */ + u32 c; /* per-modulation SNR calculation constant */ - if (state->current_modulation == VSB_8) { - - i2c_read_demod_bytes(state, 0x6e, buf, 5); - /* Phase Tracker Mean-Square Error Register for VSB */ + switch(state->current_modulation) { + case VSB_8: + i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5); +#ifdef USE_EQMSE + /* Use Equalizer Mean-Square Error Register */ + /* SNR for ranges from -16.12 to +44.08 */ + noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2]; + c = 73957994; /* log10(25*32^2)*2^24 */ +#else + /* Use Phase Tracker Mean-Square Error Register */ + /* SNR for ranges from -13.11 to +44.08 */ noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; - } else { - - /* Carrier Recovery Mean-Square Error for QAM */ - i2c_read_demod_bytes(state, 0x1a, buf, 2); + c = 73957994; /* log10(25*32^2)*2^24 */ +#endif + break; + case QAM_64: + case QAM_256: + i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); noise = (buf[0] << 8) | buf[1]; + c = state->current_modulation == QAM_64 ? 97939837 : 98026066; + /* log10(688128)*2^24 and log10(696320)*2^24 */ + break; + default: + printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", + __FUNCTION__); + return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } - /* Small values for noise mean signal is better so invert noise */ - *snr = ~noise; + state->snr = calculate_snr(noise, c); + *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ + + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); + + return 0; +} + +static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) +{ + /* 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 lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + u16 snr; + int ret; - dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); + ret = fe->ops.read_snr(fe, &snr); + if (ret != 0) + return ret; + /* 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; return 0; } diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h index 59b7c5b9012..38c76695abf 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb/frontends/lgdt330x_priv.h @@ -51,14 +51,19 @@ enum I2C_REG { AGC_RFIF_ACC2= 0x3b, AGC_STATUS= 0x3f, SYNC_STATUS_VSB= 0x43, - EQPH_ERR0= 0x47, - EQ_ERR1= 0x48, - EQ_ERR2= 0x49, - PH_ERR1= 0x4a, - PH_ERR2= 0x4b, DEMUX_CONTROL= 0x66, + LGDT3302_EQPH_ERR0= 0x47, + LGDT3302_EQ_ERR1= 0x48, + LGDT3302_EQ_ERR2= 0x49, + LGDT3302_PH_ERR1= 0x4a, + LGDT3302_PH_ERR2= 0x4b, LGDT3302_PACKET_ERR_COUNTER1= 0x6a, LGDT3302_PACKET_ERR_COUNTER2= 0x6b, + LGDT3303_EQPH_ERR0= 0x6e, + LGDT3303_EQ_ERR1= 0x6f, + LGDT3303_EQ_ERR2= 0x70, + LGDT3303_PH_ERR1= 0x71, + LGDT3303_PH_ERR2= 0x72, LGDT3303_PACKET_ERR_COUNTER1= 0x8b, LGDT3303_PACKET_ERR_COUNTER2= 0x8c, }; -- cgit v1.2.3 From 589d069cfe7f2bb37c4836641ddffe9e2b51e74e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 19:45:13 -0300 Subject: V4L/DVB (4794): Dvb: dibx000_common-fix Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dibx000_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index 61d28de3030..a18c8f45a2e 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c @@ -63,7 +63,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c struct i2c_msg m[2 + num]; u8 tx_open[4], tx_close[4]; - memset(m,0, sizeof(struct i2c_msg) * (2 + num)), + memset(m,0, sizeof(struct i2c_msg) * (2 + num)); dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); -- cgit v1.2.3 From 8637a8759585b97ec1d54ff4a4f33f34be4f5b1c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 8 Nov 2006 16:47:32 -0300 Subject: V4L/DVB (4805): Dib0700: Add support for Leadtek Winfast DTV Dongle (STK7700P based) This patch adds support for the new, STK7700-based revision of the Leadtek Winfast DTV Dongle. Signed-off-by: Michal CIJOML Semler Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 1b1598d087b..1c3546d6c03 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -277,6 +277,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, + { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -318,7 +319,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 5, + .num_device_descs = 6, .devices = { { "DiBcom STK7700P reference design", { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, @@ -339,6 +340,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Uniwill STK7700P based (Hama and others)", { &dib0700_usb_id_table[7], NULL }, { NULL }, + }, + { "Leadtek Winfast DTV Dongle (STK7700P based)", + { &dib0700_usb_id_table[8], NULL }, + { NULL }, } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 58e1a449b42..727d5003997 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -129,6 +129,7 @@ #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 #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_GENPIX_8PSK_COLD 0x0200 #define USB_PID_GENPIX_8PSK_WARM 0x0201 -- cgit v1.2.3 From f9aeba45000423cdf1211736592cb02c25f28437 Mon Sep 17 00:00:00 2001 From: Stefan Traby Date: Sun, 12 Nov 2006 13:02:51 -0300 Subject: V4L/DVB (4819): Dib0700: Add support for new revision of Nova-T Stick Added support for Nova-T Stick with USB-pid: 0x7060 Signed-off-by: Stefan Traby Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 3 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 1c3546d6c03..4428ab32262 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -278,6 +278,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -326,7 +327,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { { NULL }, }, { "Hauppauge Nova-T Stick", - { &dib0700_usb_id_table[4], NULL }, + { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, { NULL }, }, { "AVerMedia AVerTV DVB-T Volar", diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 727d5003997..ec1f3b31c54 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -101,6 +101,7 @@ #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 +#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 #define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 -- cgit v1.2.3 From ced8fecaecba6aa6b092abeb0c9e51deeeac9247 Mon Sep 17 00:00:00 2001 From: Jose Carlos Garcia Sogo Date: Tue, 14 Nov 2006 05:01:47 -0300 Subject: V4L/DVB (4823): Add alternative device ID (0xb808) for AverMedia AverTV Volar dongles. Add alternative device ID (0xb808) for AverMedia AverTV Volar dongles. Signed-off-by: Jose Carlos Garcia Sogo Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 3 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 4428ab32262..2208757d901 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -279,6 +279,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -331,7 +332,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { { NULL }, }, { "AVerMedia AVerTV DVB-T Volar", - { &dib0700_usb_id_table[5], NULL }, + { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, { NULL }, }, { "Compro Videomate U500", diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index ec1f3b31c54..6a55ea22216 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -103,6 +103,7 @@ #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 #define USB_PID_AVERMEDIA_VOLAR 0xa807 +#define USB_PID_AVERMEDIA_VOLAR_2 0xb808 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 -- cgit v1.2.3 From c01d1e486a0fc489a495ea304616484bcbcf0018 Mon Sep 17 00:00:00 2001 From: Thomas Hamm Date: Fri, 17 Nov 2006 07:12:58 -0300 Subject: V4L/DVB (4833): Patch for SATELCO EasyWatch PCI (DVB-C) Add support for Satelco EasyWatch PCI DVBC cards Signed-off-by: Thomas Hamm Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 2235ff8b8a1..c7312420c37 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -914,6 +914,7 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBS_TV_STAR_CI 0x0016 #define SUBID_DVBS_EASYWATCH_1 0x001a #define SUBID_DVBS_EASYWATCH 0x001e +#define SUBID_DVBC_EASYWATCH 0x002a #define SUBID_DVBC_KNC1 0x0020 #define SUBID_DVBC_KNC1_PLUS 0x0021 #define SUBID_DVBC_CINERGY1200 0x1156 @@ -952,6 +953,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: + case SUBID_DVBC_EASYWATCH: saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -1006,6 +1008,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_KNC1: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBC_CINERGY1200: + case SUBID_DVBC_EASYWATCH: budget_av->reinitialise_demod = 1; fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, @@ -1242,6 +1245,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); +MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); @@ -1260,6 +1264,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), + MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), -- cgit v1.2.3 From 550a9a5e5f8086ae410832f134a5d80b9bd7fdb6 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 15 Nov 2006 21:31:54 -0300 Subject: V4L/DVB (4835): Added support for the Terratec Cinergy HT PCMCIA module This is a hybrid cardbus module. Besides the card support, i modified the definition names for AGC and GPIO of the tda10046. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 10 ++++++++-- drivers/media/dvb/frontends/tda1004x.h | 5 +++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 11e0dca9a2d..00e4bcd9f1a 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities break; - case TDA10046_AGC_TDA827X: + case TDA10046_AGC_TDA827X_GP11: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities break; - case TDA10046_AGC_TDA827X_GPL: + case TDA10046_AGC_TDA827X_GP00: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities break; + case TDA10046_AGC_TDA827X_GP01: + tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup + tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold + tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize + tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities + break; } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 605ad2dfc09..ec502d71b83 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -35,8 +35,9 @@ enum tda10046_agc { TDA10046_AGC_DEFAULT, /* original configuration */ TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ - TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ - TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ + TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */ + TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/ }; enum tda10046_if { -- cgit v1.2.3 From 76db93d03f1e9a9a3371f787ae30780cdf10400c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 19 Nov 2006 19:45:26 -0300 Subject: V4L/DVB (4846): Create new lgh06xf atsc tuner module This patch creates a new atsc tuner module for the LG TDVS-H06xF ATSC tuners, called lgh06xf. The purpose of this change is to reduce some duplicated code, and to allow the lgh06xf tuner code to take advantage of dvb_attach(). As a side effect, the dependency of dvb-bt8xx on dvb-pll has been removed, since the lgh06xf module itself will use dvb-pll, while remaining optional for the dvb-bt8xx driver through the use of DVB_FE_CUSTOMISE Acked-by: Andrew de Quincey Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 1 + drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 10 +-- drivers/media/dvb/bt8xx/Kconfig | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 9 +- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 2 +- drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/dvb/dvb-usb/cxusb.c | 11 +-- drivers/media/dvb/frontends/Kconfig | 8 ++ drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/lg_h06xf.h | 64 -------------- drivers/media/dvb/frontends/lgh06xf.c | 139 ++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/lgh06xf.h | 35 ++++++++ 12 files changed, 192 insertions(+), 91 deletions(-) delete mode 100644 drivers/media/dvb/frontends/lg_h06xf.h create mode 100644 drivers/media/dvb/frontends/lgh06xf.c create mode 100644 drivers/media/dvb/frontends/lgh06xf.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index a0dcd59da76..79875958930 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index b8ba8786345..c2b35e36624 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -14,7 +14,7 @@ #include "stv0297.h" #include "mt312.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "dvb-pll.h" /* lnb control */ @@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir return request_firmware(fw, name, fc->dev); } -static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) -{ - struct flexcop_device *fc = fe->dvb->priv; - return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); -} - static struct lgdt330x_config air2pc_atsc_hd5000_config = { .demod_address = 0x59, .demod_chip = LGDT3303, @@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) /* try the air atsc 3nd generation (lgdt3303) */ if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; - fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index ae2ff5dc238..dd66b60fbc9 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -1,13 +1,13 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 - select DVB_PLL select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_SP887X if !DVB_FE_CUSTOMISE select DVB_NXT6000 if !DVB_FE_CUSTOMISE select DVB_CX24110 if !DVB_FE_CUSTOMISE select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select FW_LOADER help diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 14e69a736ed..80a85cb4975 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -34,7 +34,6 @@ #include "dvb_frontend.h" #include "dvb-bt8xx.h" #include "bt878.h" -#include "dvb-pll.h" static int debug; @@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = { .demod_init = digitv_alps_tded4_demod_init, }; -static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) -{ - struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; - return lg_h06xf_pll_set(fe, card->i2c_adapter, params); -} - static struct lgdt330x_config tdvs_tua6034_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, @@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) lgdt330x_reset(card); card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) { - card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; + dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); dprintk ("dvb_bt8xx: lgdt330x detected\n"); } break; diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 4745a9017a1..e75f4173c05 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,7 +37,7 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "zl10353.h" struct dvb_bt8xx_card { diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index dfd53d5e792..bfe5691dde1 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -98,6 +98,7 @@ config DVB_USB_CXUSB depends on DVB_USB select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 4e2eef86eca..ae039b9cb72 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -27,7 +27,7 @@ #include "cx22702.h" #include "lgdt330x.h" -#include "lg_h06xf.h" +#include "lgh06xf.h" #include "mt352.h" #include "mt352_priv.h" #include "zl10353.h" @@ -324,13 +324,6 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) return 0; } -static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *fep) -{ - struct dvb_usb_adapter *adap = fe->dvb->priv; - return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep); -} - static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, @@ -398,7 +391,7 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { - adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; + dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); return 0; } diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7279e587e14..af314bb1dca 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -297,6 +297,14 @@ config DVB_TUNER_MT2060 help A driver for the silicon IF tuner MT2060 from Microtune. +config DVB_TUNER_LGH06XF + tristate "LG TDVS-H06xF ATSC tuner" + depends on DVB_CORE && I2C + select DVB_PLL + default m if DVB_FE_CUSTOMISE + help + A driver for the LG TDVS-H06xF ATSC tuner family. + comment "Miscellaneous devices" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 593152ecf7e..3fa6e5d32a9 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o +obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h deleted file mode 100644 index 754d51d1112..00000000000 --- a/drivers/media/dvb/frontends/lg_h06xf.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF - * - * 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 _LG_H06XF_H_ -#define _LG_H06XF_H_ -#include "dvb-pll.h" - -static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, - struct dvb_frontend_parameters* params) -{ - u8 buf[4]; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, - .buf = buf, .len = sizeof(buf) }; - int err; - - dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lg_h06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - /* Set the Auxiliary Byte. */ - buf[0] = buf[2]; - buf[0] &= ~0x20; - buf[0] |= 0x18; - buf[1] = 0x50; - msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lg_h06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} -#endif diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c new file mode 100644 index 00000000000..badbea8ad82 --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.c @@ -0,0 +1,139 @@ +/* + * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF + * + * 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 "dvb-pll.h" +#include "lgh06xf.h" + +#define LG_H06XF_PLL_I2C_ADDR 0x61 + +struct lgh06xf_priv { + struct i2c_adapter *i2c; + u32 frequency; +}; + +static int lgh06xf_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int lgh06xf_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct lgh06xf_priv *priv = fe->tuner_priv; + u8 buf[4]; + struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + u32 div; + int i; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + printk(KERN_WARNING "lgh06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + printk(KERN_WARNING "lgh06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + // calculate the frequency we set it to + for (i = 0; i < dvb_pll_lg_tdvs_h06xf.count; i++) { + if (params->frequency > dvb_pll_lg_tdvs_h06xf.entries[i].limit) + continue; + break; + } + div = (params->frequency + dvb_pll_lg_tdvs_h06xf.entries[i].offset) / + dvb_pll_lg_tdvs_h06xf.entries[i].stepsize; + priv->frequency = (div * dvb_pll_lg_tdvs_h06xf.entries[i].stepsize) - + dvb_pll_lg_tdvs_h06xf.entries[i].offset; + + return 0; +} + +static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct lgh06xf_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static struct dvb_tuner_ops lgh06xf_tuner_ops = { + .release = lgh06xf_release, + .set_params = lgh06xf_set_params, + .get_frequency = lgh06xf_get_frequency, +}; + +struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c) +{ + struct lgh06xf_priv *priv = NULL; + + priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c = i2c; + + memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name, + sizeof(fe->ops.tuner_ops.info.name)); + + fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min; + fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max; + + fe->tuner_priv = priv; + return fe; +} + +EXPORT_SYMBOL(lgh06xf_attach); + +MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support"); +MODULE_AUTHOR("Michael Krufky"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h new file mode 100644 index 00000000000..41c41fc59be --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.h @@ -0,0 +1,35 @@ +/* + * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF + * + * 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 _LGH06XF_H_ +#define _LGH06XF_H_ +#include "dvb_frontend.h" + +#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE)) +extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, + struct i2c_adapter *i2c); +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_TUNER_LGH06XF */ + +#endif /* _LGH06XF_H_ */ -- cgit v1.2.3 From 2213918a99d6292767b6d4aae3e3f4b0520528a5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 19 Nov 2006 19:49:11 -0300 Subject: V4L/DVB (4847): Drivers/media/dvb/frontends: kfree() cleanups We don't have to check for NULL before kfree() Acked-by: Andrew de Quincey Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 3 +-- drivers/media/dvb/frontends/tda826x.c | 3 +-- drivers/media/dvb/frontends/tua6100.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b7e7108ee5b..78114fc2672 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -478,8 +478,7 @@ EXPORT_SYMBOL(dvb_pll_configure); static int dvb_pll_release(struct dvb_frontend *fe) { - if (fe->tuner_priv) - kfree(fe->tuner_priv); + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 34815b0b97e..4f01d7b47cd 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -42,8 +42,7 @@ struct tda826x_priv { static int tda826x_release(struct dvb_frontend *fe) { - if (fe->tuner_priv) - kfree(fe->tuner_priv); + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c index 88554393a9b..6ba0029dcf2 100644 --- a/drivers/media/dvb/frontends/tua6100.c +++ b/drivers/media/dvb/frontends/tua6100.c @@ -43,8 +43,7 @@ struct tua6100_priv { static int tua6100_release(struct dvb_frontend *fe) { - if (fe->tuner_priv) - kfree(fe->tuner_priv); + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } -- cgit v1.2.3 From fa4cdd0dc4c066a1a4df19005912bf453dc37b6d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 19 Nov 2006 22:58:19 -0300 Subject: V4L/DVB (4850): Lgh06xf: fix compiler error when not selected fix build error: lgh06xf.h:29: error: syntax error before '{' token Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgh06xf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h index 41c41fc59be..510b4bedfb2 100644 --- a/drivers/media/dvb/frontends/lgh06xf.h +++ b/drivers/media/dvb/frontends/lgh06xf.h @@ -25,7 +25,7 @@ extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, struct i2c_adapter *i2c); #else static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, - struct i2c_adapter *i2c); + struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; -- cgit v1.2.3 From b07b4783fb30dee8c542fc76ed8993108d46d6aa Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 20 Nov 2006 10:23:04 -0300 Subject: V4L/DVB (4854): Handle errors from input_register_device() Also sprinkled some input_sync() throughout the code. Acked-by: Ricardo Cerqueira Acked-by: Oliver Endriss Acked-by: Andrew de Quincey Signed-off-by: Dmitry Torokhov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/cinergyT2/cinergyT2.c | 13 +++++++-- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 37 ++++++++++++++++---------- drivers/media/dvb/ttpci/av7110_ir.c | 25 ++++++++++++------ drivers/media/dvb/ttpci/budget-ci.c | 42 ++++++++++++++++++------------ drivers/media/dvb/ttusb-dec/ttusb_dec.c | 11 ++++++-- 5 files changed, 85 insertions(+), 43 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 9123147e376..d64b96cb0c4 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work) dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); input_report_key(cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0); + input_sync(cinergyt2->rc_input_dev); cinergyt2->rc_input_event = KEY_MAX; } cinergyt2->rc_last_code = ~0; @@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work) dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); input_report_key(cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1); + input_sync(cinergyt2->rc_input_dev); cinergyt2->rc_last_code = rc_events[n].value; } } @@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { struct input_dev *input_dev; int i; + int err; - cinergyt2->rc_input_dev = input_dev = input_allocate_device(); + input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; @@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) input_dev->keycodesize = 0; input_dev->keycodemax = 0; - input_register_device(cinergyt2->rc_input_dev); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } + + cinergyt2->rc_input_dev = input_dev; schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); return 0; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 794e4471561..19ff5978bc9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -90,7 +90,9 @@ schedule: int dvb_usb_remote_init(struct dvb_usb_device *d) { + struct input_dev *input_dev; int i; + int err; if (d->props.rc_key_map == NULL || d->props.rc_query == NULL || @@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); - d->rc_input_dev = input_allocate_device(); - if (!d->rc_input_dev) + input_dev = input_allocate_device(); + if (!input_dev) return -ENOMEM; - d->rc_input_dev->evbit[0] = BIT(EV_KEY); - d->rc_input_dev->keycodesize = sizeof(unsigned char); - d->rc_input_dev->keycodemax = KEY_MAX; - d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver"; - d->rc_input_dev->phys = d->rc_phys; - usb_to_input_id(d->udev, &d->rc_input_dev->id); - d->rc_input_dev->cdev.dev = &d->udev->dev; + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = KEY_MAX; + input_dev->name = "IR-receiver inside an USB DVB receiver"; + input_dev->phys = d->rc_phys; + usb_to_input_id(d->udev, &input_dev->id); + input_dev->cdev.dev = &d->udev->dev; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc_key_map_size); for (i = 0; i < d->props.rc_key_map_size; i++) { - deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); - set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit); + deb_rc("setting bit for event %d item %d\n", + d->props.rc_key_map[i].event, i); + set_bit(d->props.rc_key_map[i].event, input_dev->keybit); } /* Start the remote-control polling. */ @@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) d->props.rc_interval = 100; /* default */ /* setting these two values to non-zero, we have to manage key repeats */ - d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval; - d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; + input_dev->rep[REP_PERIOD] = d->props.rc_interval; + input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; - input_register_device(d->rc_input_dev); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } + + d->rc_input_dev = input_dev; INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index d54bbcdde2c..e4544ea2b89 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data) if (!data || !test_bit(data, input_dev->key)) return; - input_event(input_dev, EV_KEY, data, !!0); + input_report_key(input_dev, data, 0); + input_sync(input_dev); } @@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm) del_timer(&keyup_timer); if (keyup_timer.data != keycode || new_toggle != old_toggle) { delay_timer_finished = 0; - input_event(input_dev, EV_KEY, keyup_timer.data, !!0); - input_event(input_dev, EV_KEY, keycode, !0); - } else - if (delay_timer_finished) - input_event(input_dev, EV_KEY, keycode, 2); + input_event(input_dev, EV_KEY, keyup_timer.data, 0); + input_event(input_dev, EV_KEY, keycode, 1); + input_sync(input_dev); + } else if (delay_timer_finished) { + input_event(input_dev, EV_KEY, keycode, 2); + input_sync(input_dev); + } } else { delay_timer_finished = 0; - input_event(input_dev, EV_KEY, keycode, !0); + input_event(input_dev, EV_KEY, keycode, 1); + input_sync(input_dev); } keyup_timer.expires = jiffies + UP_TIMEOUT; @@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) int __devinit av7110_ir_init(struct av7110 *av7110) { static struct proc_dir_entry *e; + int err; if (av_cnt >= sizeof av_list/sizeof av_list[0]) return -ENOSPC; @@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110) set_bit(EV_KEY, input_dev->evbit); set_bit(EV_REP, input_dev->evbit); input_register_keys(); - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } input_dev->timer.function = input_repeat_key; e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index cd5ec489af1..25d0dfc1f58 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -143,14 +143,14 @@ static void msp430_ir_debounce(unsigned long data) struct input_dev *dev = (struct input_dev *) data; if (dev->rep[0] == 0 || dev->rep[0] == ~0) { - input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); - return; + input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); + } else { + dev->rep[0] = 0; + dev->timer.expires = jiffies + HZ * 350 / 1000; + add_timer(&dev->timer); + input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ } - - dev->rep[0] = 0; - dev->timer.expires = jiffies + HZ * 350 / 1000; - add_timer(&dev->timer); - input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ + input_sync(dev); } static void msp430_ir_interrupt(unsigned long data) @@ -169,7 +169,7 @@ static void msp430_ir_interrupt(unsigned long data) return; } del_timer(&dev->timer); - input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); + input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); } if (!key_map[code]) { @@ -177,15 +177,14 @@ static void msp430_ir_interrupt(unsigned long data) return; } + input_event(dev, EV_KEY, key_map[code], 1); + input_sync(dev); + /* initialize debounce and repeat */ dev->repeat_key = code; /* Zenith remote _always_ sends 2 sequences */ dev->rep[0] = ~0; - /* 350 milliseconds */ - dev->timer.expires = jiffies + HZ * 350 / 1000; - /* MAKE */ - input_event(dev, EV_KEY, key_map[code], !0); - add_timer(&dev->timer); + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(350)); } } @@ -194,8 +193,9 @@ static int msp430_ir_init(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *input_dev; int i; + int err; - budget_ci->input_dev = input_dev = input_allocate_device(); + input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; @@ -208,10 +208,16 @@ static int msp430_ir_init(struct budget_ci *budget_ci) if (key_map[i]) set_bit(key_map[i], input_dev->keybit); - input_register_device(budget_ci->input_dev); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } input_dev->timer.function = msp430_ir_debounce; + budget_ci->input_dev = input_dev; + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); @@ -226,8 +232,10 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); - if (del_timer(&dev->timer)) - input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); + if (del_timer(&dev->timer)) { + input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); + input_sync(dev); + } input_unregister_device(dev); } diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 10b121ada83..bd6e7baae2e 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) * for now lets report each signal as a key down and up*/ dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); + input_sync(dec->rc_input_dev); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); input_sync(dec->rc_input_dev); } @@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec) struct input_dev *input_dev; u8 b[] = { 0x00, 0x01 }; int i; + int err; usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); - dec->rc_input_dev = input_dev = input_allocate_device(); + input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; @@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec) for (i = 0; i < ARRAY_SIZE(rc_keys); i++) set_bit(rc_keys[i], input_dev->keybit); - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } + dec->rc_input_dev = input_dev; if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) printk("%s: usb_submit_urb failed\n",__FUNCTION__); /* enable irq pipe */ -- cgit v1.2.3 From 61cebe9db7992c2c6ccb91f179f56008e74c2de1 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Sun, 19 Nov 2006 14:10:59 -0300 Subject: V4L/DVB (4855): Support KNC1 DVBC cards with alternative tda10021 i2c address For some reason, some of these cards have the tda10021 configured to a different address. This adds support for such cards Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index c7312420c37..461e8d75b63 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = { .demod_address = 0x0c, }; +static struct tda10021_config philips_cu1216_config_altaddress = { + .demod_address = 0x0d, +}; + @@ -1013,6 +1017,10 @@ static void frontend_init(struct budget_av *budget_av) fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (fe == NULL) + fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress, + &budget_av->budget.i2c_adap, + read_pwm(budget_av)); if (fe) { budget_av->tda10021_poclkp = 1; budget_av->tda10021_set_frontend = fe->ops.set_frontend; -- cgit v1.2.3 From 8949f1a2424a38a4080a2a3561a2698f215a7c4a Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 21 Nov 2006 05:35:10 -0300 Subject: V4L/DVB (4864): TDA826x I2C read with 2 messages Added a dump I2C message to the TDA826x-driver to fix I2C read for identification with ttusb2-driver. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda826x.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 4f01d7b47cd..79f971dc52b 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -132,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2 { struct tda826x_priv *priv = NULL; u8 b1 [] = { 0, 0 }; - struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }; + struct i2c_msg msg[2] = { + { .addr = addr, .flags = 0, .buf = NULL, .len = 0 }, + { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } + }; int ret; dprintk("%s:\n", __FUNCTION__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - ret = i2c_transfer (i2c, &msg, 1); + ret = i2c_transfer (i2c, msg, 2); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - if (ret != 1) + if (ret != 2) return NULL; if (!(b1[1] & 0x80)) return NULL; -- cgit v1.2.3 From bc2e3913c786d7387e21ee0818c1a3b66a571703 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 2 Dec 2006 21:16:04 -0200 Subject: V4L/DVB (4863): Adding support for Pinnacle PCTV 400e DVB-S Adding support for Pinnacle PCTV 400e DVB-S. The module name is called ttusb2, because it this device (and other Pinnacle devices) is using the USB-protocol originally used by Technotrend device. I'm suspecting Technotrend as the device-designer. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 11 ++ drivers/media/dvb/dvb-usb/Makefile | 3 + drivers/media/dvb/dvb-usb/ttusb2.c | 270 +++++++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/ttusb2.h | 70 ++++++++++ 4 files changed, 354 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/ttusb2.c create mode 100644 drivers/media/dvb/dvb-usb/ttusb2.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index bfe5691dde1..ad52143602c 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -160,6 +160,17 @@ config DVB_USB_NOVA_T_USB2 help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. +config DVB_USB_TTUSB2 + tristate "Pinnacle 400e DVB-S USB2.0 support" + depends on DVB_USB + select DVB_TDA10086 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_TDA826X if !DVB_FE_CUSTOMISE + 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. + config DVB_USB_DTT200U tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" depends on DVB_USB diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e239107998e..154d593bbb0 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o dvb-usb-cxusb-objs = cxusb.o obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o +dvb-usb-ttusb2-objs = ttusb2.o +obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o + dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c new file mode 100644 index 00000000000..95d29976ed7 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -0,0 +1,270 @@ +/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones + * (e.g. Pinnacle 400e DVB-S USB2.0). + * + * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. + * + * TDA8263 + TDA10086 + * + * I2C addresses: + * 0x08 - LNBP21PD - LNB power supply + * 0x0e - TDA10086 - Demodulator + * 0x50 - FX2 eeprom + * 0x60 - TDA8263 - Tuner + * 0x78 ??? + * + * Copyright (c) 2002 Holger Waechtler + * Copyright (c) 2003 Felix Domke + * Copyright (C) 2005-6 Patrick Boettcher + * + * 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. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#define DVB_USB_LOG_PREFIX "ttusb2" +#include "dvb-usb.h" + +#include "ttusb2.h" + +#include "tda826x.h" +#include "tda10086.h" +#include "lnbp21.h" + +/* debug */ +static int dvb_usb_ttusb2_debug; +#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) +module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); + +struct ttusb2_state { + u8 id; +}; + +static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, + u8 *wbuf, int wlen, u8 *rbuf, int rlen) +{ + struct ttusb2_state *st = d->priv; + u8 s[wlen+4],r[64] = { 0 }; + int ret = 0; + + memset(s,0,wlen+4); + + s[0] = 0xaa; + s[1] = ++st->id; + s[2] = cmd; + s[3] = wlen; + memcpy(&s[4],wbuf,wlen); + + ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); + + if (ret != 0 || + r[0] != 0x55 || + r[1] != s[1] || + r[2] != cmd || + (rlen > 0 && r[3] != rlen)) { + warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); + return -EIO; + } + + if (rlen > 0) + memcpy(rbuf, &r[4], rlen); + + return 0; +} + +static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + static u8 obuf[60], ibuf[60]; + int i,read; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if (num > 2) + warn("more than 2 i2c messages at a time is not handled yet. TODO."); + + for (i = 0; i < num; i++) { + read = i+1 < num && (msg[i+1].flags & I2C_M_RD); + + obuf[0] = (msg[i].addr << 1) | read; + obuf[1] = msg[i].len; + + /* read request */ + if (read) + obuf[2] = msg[i+1].len; + else + obuf[2] = 0; + + memcpy(&obuf[3],msg[i].buf,msg[i].len); + + if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { + err("i2c transfer failed."); + break; + } + + if (read) { + memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); + i++; + } + } + + mutex_unlock(&d->i2c_mutex); + return i; +} + +static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm ttusb2_i2c_algo = { + .master_xfer = ttusb2_i2c_xfer, + .functionality = ttusb2_i2c_func, +}; + +/* Callbacks for DVB USB */ +static int ttusb2_identify_state (struct usb_device *udev, struct + dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, + int *cold) +{ + *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; + return 0; +} + +static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 b = onoff; + ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); + return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); +} + + +static struct tda10086_config tda10086_config = { + .demod_address = 0x0e, + .invert = 0, +}; + +static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) +{ + if (usb_set_interface(adap->dev->udev,0,3) < 0) + err("set interface to alts=3 failed"); + + if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { + deb_info("TDA10086 attach failed\n"); + return -ENODEV; + } + + return 0; +} + +static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) +{ + if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { + deb_info("TDA8263 attach failed\n"); + return -ENODEV; + } + + if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { + deb_info("LNBP21 attach failed\n"); + return -ENODEV; + } + return 0; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties ttusb2_properties; + +static int ttusb2_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); +} + +static struct usb_device_id ttusb2_table [] = { + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, + {} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE (usb, ttusb2_table); + +static struct dvb_usb_device_properties ttusb2_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + .firmware = "dvb-usb-pctv-400e-01.fw", + + .size_of_priv = sizeof(struct ttusb2_state), + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, + + .frontend_attach = ttusb2_frontend_attach, + .tuner_attach = ttusb2_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_ISOC, + .count = 5, + .endpoint = 0x02, + .u = { + .isoc = { + .framesperurb = 4, + .framesize = 940, + .interval = 1, + } + } + } + } + }, + + .power_ctrl = ttusb2_power_ctrl, + .identify_state = ttusb2_identify_state, + + .i2c_algo = &ttusb2_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .num_device_descs = 1, + .devices = { + { "Pinnacle 400e DVB-S USB2.0", + { &ttusb2_table[0], NULL }, + { NULL }, + }, + } +}; + +static struct usb_driver ttusb2_driver = { + .name = "dvb_usb_ttusb2", + .probe = ttusb2_probe, + .disconnect = dvb_usb_device_exit, + .id_table = ttusb2_table, +}; + +/* module stuff */ +static int __init ttusb2_module_init(void) +{ + int result; + if ((result = usb_register(&ttusb2_driver))) { + err("usb_register failed. Error number %d",result); + return result; + } + + return 0; +} + +static void __exit ttusb2_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&ttusb2_driver); +} + +module_init (ttusb2_module_init); +module_exit (ttusb2_module_exit); + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h new file mode 100644 index 00000000000..52a63af4089 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.h @@ -0,0 +1,70 @@ +/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones + * (e.g. Pinnacle 400e DVB-S USB2.0). + * + * Copyright (c) 2002 Holger Waechtler + * Copyright (c) 2003 Felix Domke + * Copyright (C) 2005-6 Patrick Boettcher + * + * 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. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#ifndef _DVB_USB_TTUSB2_H_ +#define _DVB_USB_TTUSB2_H_ + +/* TTUSB protocol + * + * always to messages (out/in) + * out message: + * 0xaa + * + * in message (complete block is always 0x40 bytes long) + * 0x55 + * + * id is incremented for each transaction + */ + +#define CMD_DSP_DOWNLOAD 0x13 +/* out data: [28] + * last block must be empty */ + +#define CMD_DSP_BOOT 0x14 +/* out data: nothing */ + +#define CMD_POWER 0x15 +/* out data: */ + +#define CMD_LNB 0x16 +/* out data: <18V=0,13V=1> */ + +#define CMD_GET_VERSION 0x17 +/* in data: [5] */ + +#define CMD_DISEQC 0x18 +/* out data: [cmdlen] */ + +#define CMD_PID_ENABLE 0x22 +/* out data: */ + +#define CMD_PID_DISABLE 0x23 +/* out data: */ + +#define CMD_FILTER_ENABLE 0x24 +/* out data: [12] [12] */ + +#define CMD_FILTER_DISABLE 0x25 +/* out data: */ + +#define CMD_GET_DSP_VERSION 0x26 +/* in data: [28] */ + +#define CMD_I2C_XFER 0x31 +/* out data: [sndlen] + * in data: [rcvlen] */ + +#define CMD_I2C_BITRATE 0x32 +/* out data: */ + +#endif -- cgit v1.2.3 From 47ae9ae895a5228e7a3ca47b1c9ab00a3f641923 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 20 Nov 2006 16:38:42 -0300 Subject: V4L/DVB (4867): Whitespace cleanup - adhere to 80-column limit - replace some spaces with tabs Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 42 ++++++++++++++++++++++++----------- drivers/media/dvb/frontends/dvb-pll.h | 7 ++++-- drivers/media/dvb/ttpci/budget-av.c | 2 +- 3 files changed, 35 insertions(+), 16 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 78114fc2672..b0785d542f0 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -488,7 +488,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) struct dvb_pll_priv *priv = fe->tuner_priv; u8 buf[4]; struct i2c_msg msg = - { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; + { .addr = priv->pll_i2c_address, .flags = 0, + .buf = buf, .len = sizeof(buf) }; int i; int result; @@ -516,12 +517,14 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) return 0; } -static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int dvb_pll_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { struct dvb_pll_priv *priv = fe->tuner_priv; u8 buf[4]; struct i2c_msg msg = - { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; + { .addr = priv->pll_i2c_address, .flags = 0, + .buf = buf, .len = sizeof(buf) }; int result; u32 div; int i; @@ -535,7 +538,8 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param bandwidth = params->u.ofdm.bandwidth; } - if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0) + if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, + bandwidth)) != 0) return result; if (fe->ops.i2c_gate_ctrl) @@ -550,14 +554,18 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param continue; break; } - div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; - priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; + div = (params->frequency + priv->pll_desc->entries[i].offset) / + priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - + priv->pll_desc->entries[i].offset; priv->bandwidth = bandwidth; return 0; } -static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +static int dvb_pll_calc_regs(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *buf, int buf_len) { struct dvb_pll_priv *priv = fe->tuner_priv; int result; @@ -573,7 +581,8 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame bandwidth = params->u.ofdm.bandwidth; } - if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0) + if ((result = dvb_pll_configure(priv->pll_desc, buf+1, + params->frequency, bandwidth)) != 0) return result; buf[0] = priv->pll_i2c_address; @@ -583,8 +592,10 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame continue; break; } - div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; - priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; + div = (params->frequency + priv->pll_desc->entries[i].offset) / + priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - + priv->pll_desc->entries[i].offset; priv->bandwidth = bandwidth; return 5; @@ -613,10 +624,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { .get_bandwidth = dvb_pll_get_bandwidth, }; -struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) +struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, + struct i2c_adapter *i2c, + struct dvb_pll_desc *desc) { u8 b1 [] = { 0 }; - struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, + .buf = b1, .len = 1 }; struct dvb_pll_priv *priv = NULL; int ret; @@ -639,7 +653,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc priv->i2c = i2c; priv->pll_desc = desc; - memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); + memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, + sizeof(struct dvb_tuner_ops)); + strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); fe->ops.tuner_ops.info.frequency_min = desc->min; fe->ops.tuner_ops.info.frequency_min = desc->max; diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index ed5ac5a361a..681186a5e5e 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316; extern struct dvb_pll_desc dvb_pll_thomson_fe6600; extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, - u32 freq, int bandwidth); + u32 freq, int bandwidth); /** * Attach a dvb-pll to the supplied frontend structure. @@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, * @param desc dvb_pll_desc to use. * @return Frontend pointer on success, NULL on failure */ -extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); +extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, + int pll_addr, + struct i2c_adapter *i2c, + struct dvb_pll_desc *desc); #endif diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 461e8d75b63..8bdc90a70c2 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -835,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, return -EINVAL; rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, - params->frequency, 0); + params->frequency, 0); if(rc < 0) return rc; if (fe->ops.i2c_gate_ctrl) -- cgit v1.2.3 From 89faeefcf875c16d8923eaed50bd57731c221bcc Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 20 Nov 2006 16:45:29 -0300 Subject: V4L/DVB (4868): Dvb-pll: return frequency set by dvb_pll_configure() This patch removes some duplicated code by returning the frequency set by dvb_pll_configure(), instead of recalculating it again in dvb_pll_set_params() and dvb_pll_calc_regs(). If the return value of dvb_pll_configure is less than zero, it is an error code. Otherwise, the return value is the frequency actually set by the function. Signed-off-by: Michael Krufky Acked-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 44 +++++++++++------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b0785d542f0..62de760c844 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -472,7 +472,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", desc->name, div, buf[0], buf[1], buf[2], buf[3]); - return 0; + // calculate the frequency we set it to + return (div * desc->entries[i].stepsize) - desc->entries[i].offset; } EXPORT_SYMBOL(dvb_pll_configure); @@ -526,9 +527,7 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; int result; - u32 div; - int i; - u32 bandwidth = 0; + u32 bandwidth = 0, frequency = 0; if (priv->i2c == NULL) return -EINVAL; @@ -538,9 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, bandwidth = params->u.ofdm.bandwidth; } - if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, - bandwidth)) != 0) + if ((result = dvb_pll_configure(priv->pll_desc, buf, + params->frequency, bandwidth)) < 0) return result; + else + frequency = result; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -548,16 +549,7 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, return result; } - // calculate the frequency we set it to - for (i = 0; i < priv->pll_desc->count; i++) { - if (params->frequency > priv->pll_desc->entries[i].limit) - continue; - break; - } - div = (params->frequency + priv->pll_desc->entries[i].offset) / - priv->pll_desc->entries[i].stepsize; - priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - - priv->pll_desc->entries[i].offset; + priv->frequency = frequency; priv->bandwidth = bandwidth; return 0; @@ -569,9 +561,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, { struct dvb_pll_priv *priv = fe->tuner_priv; int result; - u32 div; - int i; - u32 bandwidth = 0; + u32 bandwidth = 0, frequency = 0; if (buf_len < 5) return -EINVAL; @@ -582,20 +572,14 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, } if ((result = dvb_pll_configure(priv->pll_desc, buf+1, - params->frequency, bandwidth)) != 0) + params->frequency, bandwidth)) < 0) return result; + else + frequency = result; + buf[0] = priv->pll_i2c_address; - // calculate the frequency we set it to - for (i = 0; i < priv->pll_desc->count; i++) { - if (params->frequency > priv->pll_desc->entries[i].limit) - continue; - break; - } - div = (params->frequency + priv->pll_desc->entries[i].offset) / - priv->pll_desc->entries[i].stepsize; - priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - - priv->pll_desc->entries[i].offset; + priv->frequency = frequency; priv->bandwidth = bandwidth; return 5; -- cgit v1.2.3 From fd83e2487e9149d8cd7c8b1e7d6f0e5231b79f8a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 20 Nov 2006 17:03:48 -0300 Subject: V4L/DVB (4869): Lgh06xf: use return value of dvb_pll_configure() Use return value of dvb_pll_configure() to fill priv->frequency In lgh06xf_set_params: Rename int variable "err" to "result". Remove needless calculation of the set frequency, since this value is now being returned by dvb_pll_configure(). Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgh06xf.c | 43 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c index badbea8ad82..2202d0cc878 100644 --- a/drivers/media/dvb/frontends/lgh06xf.c +++ b/drivers/media/dvb/frontends/lgh06xf.c @@ -40,19 +40,23 @@ static int lgh06xf_set_params(struct dvb_frontend* fe, u8 buf[4]; struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, .buf = buf, .len = sizeof(buf) }; - u32 div; - int i; - int err; + u32 frequency; + int result; + + if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, + params->frequency, 0)) < 0) + return result; + else + frequency = result; - dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; + "(addr %02x <- %02x, result = %i)\n", + __FUNCTION__, buf[0], buf[1], result); + if (result < 0) + return result; else return -EREMOTEIO; } @@ -65,26 +69,17 @@ static int lgh06xf_set_params(struct dvb_frontend* fe, msg.len = 2; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; + "(addr %02x <- %02x, result = %i)\n", + __FUNCTION__, buf[0], buf[1], result); + if (result < 0) + return result; else return -EREMOTEIO; } - // calculate the frequency we set it to - for (i = 0; i < dvb_pll_lg_tdvs_h06xf.count; i++) { - if (params->frequency > dvb_pll_lg_tdvs_h06xf.entries[i].limit) - continue; - break; - } - div = (params->frequency + dvb_pll_lg_tdvs_h06xf.entries[i].offset) / - dvb_pll_lg_tdvs_h06xf.entries[i].stepsize; - priv->frequency = (div * dvb_pll_lg_tdvs_h06xf.entries[i].stepsize) - - dvb_pll_lg_tdvs_h06xf.entries[i].offset; + priv->frequency = frequency; return 0; } -- cgit v1.2.3 From dd2f398ccb73530a99582e972aa57e3ed2fd73c6 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4875): budget-ci IR: groundwork for following patches This patch lays down some groundwork for later budget-ci patches. The bulk of this consists of moving a few members into a new struct and renaming a few of them. It also allocates extra space for the device name (the "name" field in /proc/bus/input/devices and in the relevant sysfs dir) to avoid truncation and uses snprintf rather than sprintf in case the extra space shouldn't be enough. Taken from Darren Salt's dvb-ir patchset Signed-off-by: Darren Salt Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 25d0dfc1f58..2893e752745 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -72,15 +72,19 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) +struct budget_ci_ir { + struct input_dev *dev; + struct tasklet_struct msp430_irq_tasklet; + char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ +}; + struct budget_ci { struct budget budget; - struct input_dev *input_dev; - struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; int slot_status; int ci_irq; struct dvb_ca_en50221 ca; - char ir_dev_name[50]; + struct budget_ci_ir ir; u8 tuner_pll_address; /* used for philips_tdm1316l configs */ }; @@ -156,7 +160,7 @@ static void msp430_ir_debounce(unsigned long data) static void msp430_ir_interrupt(unsigned long data) { struct budget_ci *budget_ci = (struct budget_ci *) data; - struct input_dev *dev = budget_ci->input_dev; + struct input_dev *dev = budget_ci->ir.dev; unsigned int code = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; @@ -191,17 +195,17 @@ static void msp430_ir_interrupt(unsigned long data) static int msp430_ir_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *input_dev; + struct input_dev *input_dev = budget_ci->ir.dev; int i; int err; - input_dev = input_allocate_device(); + budget_ci->ir.dev = input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; - sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name); - - input_dev->name = budget_ci->ir_dev_name; + snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), + "Budget-CI dvb ir receiver %s", saa->name); + input_dev->name = budget_ci->ir.name; set_bit(EV_KEY, input_dev->evbit); for (i = 0; i < ARRAY_SIZE(key_map); i++) @@ -214,9 +218,9 @@ static int msp430_ir_init(struct budget_ci *budget_ci) return err; } - input_dev->timer.function = msp430_ir_debounce; + input_register_device(budget_ci->ir.dev); - budget_ci->input_dev = input_dev; + input_dev->timer.function = msp430_ir_debounce; saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); @@ -227,7 +231,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) static void msp430_ir_deinit(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *dev = budget_ci->input_dev; + struct input_dev *dev = budget_ci->ir.dev; saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); @@ -548,7 +552,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); if (*isr & MASK_06) - tasklet_schedule(&budget_ci->msp430_irq_tasklet); + tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet); if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); @@ -1105,7 +1109,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio return err; } - tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, + tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); msp430_ir_init(budget_ci); @@ -1134,7 +1138,7 @@ static int budget_ci_detach(struct saa7146_dev *dev) } err = ttpci_budget_deinit(&budget_ci->budget); - tasklet_kill(&budget_ci->msp430_irq_tasklet); + tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); msp430_ir_deinit(budget_ci); -- cgit v1.2.3 From 5cc8ae000233e8dad667edcdbb921668c317b627 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4876): budget-ci IR: support EVIOCGPHYS This patch adds a 'phys' string, of the same form as used by various other DVB cards' IR drivers, for access by any program which uses the EVIOCPHYS ioctl or may read /sys/class/input/*/phys (e.g. udev) to identify input device nodes. Taken from Darren Salt's dvb-ir patchset. Signed-off-by: Darren Salt Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 2893e752745..0809fb90c26 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -76,6 +76,7 @@ struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ + char phys[32]; }; struct budget_ci { @@ -205,8 +206,27 @@ static int msp430_ir_init(struct budget_ci *budget_ci) snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), "Budget-CI dvb ir receiver %s", saa->name); + snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), + "pci-%s/ir0", pci_name(saa->pci)); + input_dev->name = budget_ci->ir.name; + input_dev->phys = budget_ci->ir.phys; + input_dev->id.bustype = BUS_PCI; + input_dev->id.version = 1; + if (saa->pci->subsystem_vendor) { + input_dev->id.vendor = saa->pci->subsystem_vendor; + input_dev->id.product = saa->pci->subsystem_device; + } else { + input_dev->id.vendor = saa->pci->vendor; + input_dev->id.product = saa->pci->device; + } +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) + input_dev->cdev.dev = &saa->pci->dev; +# else + input_dev->dev = &saa->pci->dev; +# endif + set_bit(EV_KEY, input_dev->evbit); for (i = 0; i < ARRAY_SIZE(key_map); i++) if (key_map[i]) -- cgit v1.2.3 From 8cc532ef5bf1230ed6345aebe5bd11ea8567ba52 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4877): budget-ci IR: improve error checking in init and deinit functions Improve the error checking in the IR init and deinit functions. Based on Darren Salt's dvb-ir patchset. Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 60 +++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 0809fb90c26..b2869ab8b7b 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -198,11 +198,13 @@ static int msp430_ir_init(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *input_dev = budget_ci->ir.dev; int i; - int err; + int error; budget_ci->ir.dev = input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; + if (!input_dev) { + error = -ENOMEM; + goto out1; + } snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), "Budget-CI dvb ir receiver %s", saa->name); @@ -232,20 +234,26 @@ static int msp430_ir_init(struct budget_ci *budget_ci) if (key_map[i]) set_bit(key_map[i], input_dev->keybit); - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; + error = input_register_device(input_dev); + if (error) { + printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); + goto out2; } - input_register_device(budget_ci->ir.dev); - input_dev->timer.function = msp430_ir_debounce; + tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, + (unsigned long) budget_ci); + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); return 0; + +out2: + input_free_device(input_dev); +out1: + return error; } static void msp430_ir_deinit(struct budget_ci *budget_ci) @@ -255,6 +263,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); + tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); if (del_timer(&dev->timer)) { input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); @@ -1115,8 +1124,11 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio struct budget_ci *budget_ci; int err; - if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL))) - return -ENOMEM; + budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL); + if (!budget_ci) { + err = -ENOMEM; + goto out1; + } dprintk(2, "budget_ci: %p\n", budget_ci); @@ -1124,15 +1136,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio dev->ext_priv = budget_ci; - if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { - kfree(budget_ci); - return err; - } + err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); + if (err) + goto out2; - tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, - (unsigned long) budget_ci); - - msp430_ir_init(budget_ci); + err = msp430_ir_init(budget_ci); + if (err) + goto out3; ciintf_init(budget_ci); @@ -1142,6 +1152,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ttpci_budget_init_hooks(&budget_ci->budget); return 0; + +out3: + ttpci_budget_deinit(&budget_ci->budget); +out2: + kfree(budget_ci); +out1: + return err; } static int budget_ci_detach(struct saa7146_dev *dev) @@ -1152,16 +1169,13 @@ static int budget_ci_detach(struct saa7146_dev *dev) if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); + msp430_ir_deinit(budget_ci); if (budget_ci->budget.dvb_frontend) { dvb_unregister_frontend(budget_ci->budget.dvb_frontend); dvb_frontend_detach(budget_ci->budget.dvb_frontend); } err = ttpci_budget_deinit(&budget_ci->budget); - tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); - - msp430_ir_deinit(budget_ci); - // disable frontend and CI interface saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); -- cgit v1.2.3 From ee579bc9332ef8a67e20f512e7bc91e3efb92225 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4878): budget-ci IR: be more verbose in case of init failure Trivial change to help the user understand what went wrong. Taken from Darren Salt's dvb-ir patchset. Signed-off-by: Darren Salt Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index b2869ab8b7b..c34b5d3bdde 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -202,6 +202,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.dev = input_dev = input_allocate_device(); if (!input_dev) { + printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); error = -ENOMEM; goto out1; } @@ -1124,7 +1125,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio struct budget_ci *budget_ci; int err; - budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL); + budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL); if (!budget_ci) { err = -ENOMEM; goto out1; @@ -1132,8 +1133,6 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio dprintk(2, "budget_ci: %p\n", budget_ci); - budget_ci->budget.ci_present = 0; - dev->ext_priv = budget_ci; err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); -- cgit v1.2.3 From 2520fffd8b7a312e77009414d3201c9751d6448c Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4879): budget-ci IR: integrate with ir-common This converts the budget-ci driver so that it uses ir-common for some of its IR processing. In particular, the keymap for the Nova-T (sub 13c2:1011) is switched to the Hauppauge grey/black keymap, of which the keys on the supplied R808 remote control form a subset. The old budget-ci keymap is moved to ir-keymaps.c and is used for other remotes. The debounce logic for buggy remotes (i.e. Zenith) is made conditional the new debounce parameter and defaults to off (so that repeat keypresses aren't ignored for all working remotes). Some parts are based on Darren Salt's dvb-ir patchset. Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/Kconfig | 1 + drivers/media/dvb/ttpci/budget-ci.c | 138 ++++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 61 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 95531a62499..eec7ccf41f8 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -92,6 +92,7 @@ config DVB_BUDGET_CI select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select VIDEO_IR help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index c34b5d3bdde..d1b5402cd6f 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "dvb_ca_en50221.h" #include "stv0299.h" @@ -72,11 +73,24 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) +/* Milliseconds during which key presses are regarded as key repeat and during + * which the debounce logic is active + */ +#define IR_REPEAT_TIMEOUT 350 + +/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), + * this setting allows the superflous sequences to be ignored + */ +static int debounce = 0; +module_param(debounce, int, 0644); +MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); + struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; + struct ir_input_state state; }; struct budget_ci { @@ -89,59 +103,44 @@ struct budget_ci { u8 tuner_pll_address; /* used for philips_tdm1316l configs */ }; -/* from reading the following remotes: - Zenith Universal 7 / TV Mode 807 / VCR Mode 837 - Hauppauge (from NOVA-CI-s box product) - i've taken a "middle of the road" approach and note the differences -*/ -static u16 key_map[64] = { - /* 0x0X */ - KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, - KEY_9, - KEY_ENTER, - KEY_RED, - KEY_POWER, /* RADIO on Hauppauge */ - KEY_MUTE, - 0, - KEY_A, /* TV on Hauppauge */ - /* 0x1X */ - KEY_VOLUMEUP, KEY_VOLUMEDOWN, - 0, 0, - KEY_B, - 0, 0, 0, 0, 0, 0, 0, - KEY_UP, KEY_DOWN, - KEY_OPTION, /* RESERVED on Hauppauge */ - KEY_BREAK, - /* 0x2X */ - KEY_CHANNELUP, KEY_CHANNELDOWN, - KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ - 0, KEY_RESTART, KEY_OK, - KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - 0, - KEY_ENTER, /* VCR mode on Zenith */ - KEY_PAUSE, - 0, - KEY_RIGHT, KEY_LEFT, - 0, - KEY_MENU, /* FULL SCREEN on Hauppauge */ - 0, - /* 0x3X */ - KEY_SLOW, - KEY_PREVIOUS, /* VCR mode on Zenith */ - KEY_REWIND, - 0, - KEY_FASTFORWARD, - KEY_PLAY, KEY_STOP, - KEY_RECORD, - KEY_TUNER, /* TV/VCR on Zenith */ - 0, - KEY_C, - 0, - KEY_EXIT, - KEY_POWER2, - KEY_TUNER, /* VCR mode on Zenith */ - 0, -}; +static void msp430_ir_keyup(unsigned long data) +{ + struct budget_ci_ir *ir = (struct budget_ci_ir *) data; + ir_input_nokey(ir->dev, &ir->state); +} + +static void msp430_ir_interrupt(unsigned long data) +{ + struct budget_ci *budget_ci = (struct budget_ci *) data; + struct input_dev *dev = budget_ci->ir.dev; + static int bounces = 0; + u32 ir_key; + u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; + + if (command & 0x40) { + ir_key = command & 0x3f; + + if (ir_key != dev->repeat_key && del_timer(&dev->timer)) + /* We were still waiting for a keyup event but this is a new key */ + ir_input_nokey(dev, &budget_ci->ir.state); + + if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { + /* Ignore repeated key sequences if requested */ + bounces--; + return; + } + + if (!timer_pending(&dev->timer)) + /* New keypress */ + bounces = debounce; + + /* Prepare a keyup event sometime in the future */ + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); + + /* Generate a new or repeated keypress */ + ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command); + } +} static void msp430_ir_debounce(unsigned long data) { @@ -197,7 +196,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *input_dev = budget_ci->ir.dev; - int i; int error; budget_ci->ir.dev = input_dev = input_allocate_device(); @@ -230,10 +228,30 @@ static int msp430_ir_init(struct budget_ci *budget_ci) input_dev->dev = &saa->pci->dev; # endif - set_bit(EV_KEY, input_dev->evbit); - for (i = 0; i < ARRAY_SIZE(key_map); i++) - if (key_map[i]) - set_bit(key_map[i], input_dev->keybit); + /* Select keymap */ + switch (budget_ci->budget.dev->pci->subsystem_device) { + case 0x100c: + case 0x100f: + case 0x1010: + case 0x1011: + case 0x1012: + case 0x1017: + /* The hauppauge keymap is a superset of these remotes */ + ir_input_init(input_dev, &budget_ci->ir.state, + IR_TYPE_RC5, ir_codes_hauppauge_new); + break; + default: + /* unknown remote */ + ir_input_init(input_dev, &budget_ci->ir.state, + IR_TYPE_RC5, ir_codes_budget_ci_old); + break; + } + + /* initialise the key-up timeout handler */ + input_dev->timer.function = msp430_ir_keyup; + input_dev->timer.data = (unsigned long) &budget_ci->ir; + input_dev->rep[REP_DELAY] = 1; + input_dev->rep[REP_PERIOD] = 1; error = input_register_device(input_dev); if (error) { @@ -241,8 +259,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) goto out2; } - input_dev->timer.function = msp430_ir_debounce; - tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); @@ -267,7 +283,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); if (del_timer(&dev->timer)) { - input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); + ir_input_nokey(dev, &budget_ci->ir.state); input_sync(dev); } -- cgit v1.2.3 From 64741b70cf2030ffe017e5ed731620b4a4570f77 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4880): budget-ci IR: decode rc5 device byte Decode the RC5 device byte as well as the command byte. Introduce a parameter to set the device events to listen for. Default to try to auto-detect the proper device code, otherwise, listen to any device as the old code did. Based on Darren Salt's dvb-ir patchset. Signed-off-by: Darren Salt Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 76 ++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 17 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index d1b5402cd6f..76d3b6694bc 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -78,6 +78,9 @@ */ #define IR_REPEAT_TIMEOUT 350 +/* RC5 device wildcard */ +#define IR_DEVICE_ANY 255 + /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), * this setting allows the superflous sequences to be ignored */ @@ -85,12 +88,17 @@ static int debounce = 0; module_param(debounce, int, 0644); MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); +static int rc5_device = -1; +module_param(rc5_device, int, 0644); +MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); + struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; struct ir_input_state state; + int rc5_device; }; struct budget_ci { @@ -114,32 +122,56 @@ static void msp430_ir_interrupt(unsigned long data) struct budget_ci *budget_ci = (struct budget_ci *) data; struct input_dev *dev = budget_ci->ir.dev; static int bounces = 0; - u32 ir_key; + int device; + int toggle; + static int prev_toggle = -1; + static u32 ir_key; u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; + /* + * The msp430 chip can generate two different bytes, command and device + * + * type1: X1CCCCCC, C = command bits (0 - 63) + * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit + * + * More than one command byte may be generated before the device byte + * Only when we have both, a correct keypress is generated + */ + + /* Is this a RC5 command byte? */ if (command & 0x40) { ir_key = command & 0x3f; + return; + } - if (ir_key != dev->repeat_key && del_timer(&dev->timer)) - /* We were still waiting for a keyup event but this is a new key */ - ir_input_nokey(dev, &budget_ci->ir.state); + /* It's a RC5 device byte */ + device = command & 0x1f; + toggle = command & 0x20; - if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { - /* Ignore repeated key sequences if requested */ - bounces--; - return; - } + if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) + return; - if (!timer_pending(&dev->timer)) - /* New keypress */ - bounces = debounce; + /* Are we still waiting for a keyup event while this is a new key? */ + if ((ir_key != dev->repeat_key || toggle != prev_toggle) && del_timer(&dev->timer)) + ir_input_nokey(dev, &budget_ci->ir.state); - /* Prepare a keyup event sometime in the future */ - mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); + prev_toggle = toggle; - /* Generate a new or repeated keypress */ - ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command); + /* Ignore repeated key sequences if requested */ + if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { + bounces--; + return; } + + /* New keypress? */ + if (!timer_pending(&dev->timer)) + bounces = debounce; + + /* Prepare a keyup event sometime in the future */ + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); + + /* Generate a new or repeated keypress */ + ir_input_keydown(dev, &budget_ci->ir.state, ir_key, ((device << 8) | command)); } static void msp430_ir_debounce(unsigned long data) @@ -228,7 +260,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) input_dev->dev = &saa->pci->dev; # endif - /* Select keymap */ + /* Select keymap and address */ switch (budget_ci->budget.dev->pci->subsystem_device) { case 0x100c: case 0x100f: @@ -239,11 +271,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci) /* The hauppauge keymap is a superset of these remotes */ ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, ir_codes_hauppauge_new); + + if (rc5_device < 0) + budget_ci->ir.rc5_device = 0x1f; + else + budget_ci->ir.rc5_device = rc5_device; break; default: /* unknown remote */ ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, ir_codes_budget_ci_old); + + if (rc5_device < 0) + budget_ci->ir.rc5_device = IR_DEVICE_ANY; + else + budget_ci->ir.rc5_device = rc5_device; break; } -- cgit v1.2.3 From b5471a27b48801507c5bd0eadd83730230515016 Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:05 -0200 Subject: V4L/DVB (4881): budget-ci IR: add IR debugging information This adds a ir_debug parameter which is useful in tracking down IR decoding problems. Based on Darren Salt's dvb-ir patchset. Signed-off-by: Darren Salt Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 76d3b6694bc..2a3707c8794 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -92,6 +92,10 @@ static int rc5_device = -1; module_param(rc5_device, int, 0644); MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); +static int ir_debug = 0; +module_param(ir_debug, int, 0644); +MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); + struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; @@ -140,11 +144,15 @@ static void msp430_ir_interrupt(unsigned long data) /* Is this a RC5 command byte? */ if (command & 0x40) { + if (ir_debug) + printk("budget_ci: received command byte 0x%02x\n", command); ir_key = command & 0x3f; return; } /* It's a RC5 device byte */ + if (ir_debug) + printk("budget_ci: received device byte 0x%02x\n", command); device = command & 0x1f; toggle = command & 0x20; -- cgit v1.2.3 From 59236d46dab429646b023026ac92d9e8c732c18a Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 2 Dec 2006 21:16:06 -0200 Subject: V4L/DVB (4882): budget-ci IR: make debounce logic conditional Change the debounce logic so that it is not used at all unless the debounce parameter has been set. This makes for a much "snappier" remote for most users as there is no timeout to wait for (the debounce logic has a 350ms timer for the next repeat, but with the RC5 protocol, one event per ~110ms is possible) Signed-off-by: David Hardeman Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 2a3707c8794..83a1c5f44a0 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -159,27 +159,32 @@ static void msp430_ir_interrupt(unsigned long data) if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) return; - /* Are we still waiting for a keyup event while this is a new key? */ - if ((ir_key != dev->repeat_key || toggle != prev_toggle) && del_timer(&dev->timer)) - ir_input_nokey(dev, &budget_ci->ir.state); - - prev_toggle = toggle; - /* Ignore repeated key sequences if requested */ - if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { + if (toggle == prev_toggle && ir_key == dev->repeat_key && + bounces > 0 && timer_pending(&dev->timer)) { + if (ir_debug) + printk("budget_ci: debounce logic ignored IR command\n"); bounces--; return; } + prev_toggle = toggle; - /* New keypress? */ - if (!timer_pending(&dev->timer)) - bounces = debounce; + /* Are we still waiting for a keyup event? */ + if (del_timer(&dev->timer)) + ir_input_nokey(dev, &budget_ci->ir.state); - /* Prepare a keyup event sometime in the future */ - mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); + /* Generate keypress */ + if (ir_debug) + printk("budget_ci: generating keypress 0x%02x\n", ir_key); + ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8))); - /* Generate a new or repeated keypress */ - ir_input_keydown(dev, &budget_ci->ir.state, ir_key, ((device << 8) | command)); + /* Do we want to delay the keyup event? */ + if (debounce) { + bounces = debounce; + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); + } else { + ir_input_nokey(dev, &budget_ci->ir.state); + } } static void msp430_ir_debounce(unsigned long data) @@ -297,11 +302,9 @@ static int msp430_ir_init(struct budget_ci *budget_ci) break; } - /* initialise the key-up timeout handler */ + /* initialise the key-up debounce timeout handler */ input_dev->timer.function = msp430_ir_keyup; input_dev->timer.data = (unsigned long) &budget_ci->ir; - input_dev->rep[REP_DELAY] = 1; - input_dev->rep[REP_PERIOD] = 1; error = input_register_device(input_dev); if (error) { -- cgit v1.2.3 From 9abec6189aa8b6659222544bf893158fc96e8822 Mon Sep 17 00:00:00 2001 From: Thomas Kaiser Date: Wed, 22 Nov 2006 18:15:19 -0300 Subject: V4L/DVB (4883): Fix TD1316 tuner for DVBC If your device is using the philips tda1316 tuner, i think there is a problem in setting the correct Band. 162 MHz and above should be band 2 (Mid-Band). But in dvbc_philips_tdm1316l_tuner_set_params band 1 is set for frequencies below 200 MHz. Signed-off-by: Thomas Kaiser Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 83a1c5f44a0..a68f5bf0125 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -946,7 +946,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc band = 1; } else if (tuner_frequency < 200000000) { cp = 6; - band = 1; + band = 2; } else if (tuner_frequency < 290000000) { cp = 3; band = 2; -- cgit v1.2.3 From e457579079642924da621e92cb39d8fb90a4d5a7 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Fri, 24 Nov 2006 12:58:42 -0300 Subject: V4L/DVB (4884): Remove stray IR code left from patchset This caused compilation to fail - completely replaced by new style functions, so can be removed. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 50 ------------------------------------- 1 file changed, 50 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index a68f5bf0125..8f71124099b 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -187,56 +187,6 @@ static void msp430_ir_interrupt(unsigned long data) } } -static void msp430_ir_debounce(unsigned long data) -{ - struct input_dev *dev = (struct input_dev *) data; - - if (dev->rep[0] == 0 || dev->rep[0] == ~0) { - input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); - } else { - dev->rep[0] = 0; - dev->timer.expires = jiffies + HZ * 350 / 1000; - add_timer(&dev->timer); - input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ - } - input_sync(dev); -} - -static void msp430_ir_interrupt(unsigned long data) -{ - struct budget_ci *budget_ci = (struct budget_ci *) data; - struct input_dev *dev = budget_ci->ir.dev; - unsigned int code = - ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; - - if (code & 0x40) { - code &= 0x3f; - - if (timer_pending(&dev->timer)) { - if (code == dev->repeat_key) { - ++dev->rep[0]; - return; - } - del_timer(&dev->timer); - input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); - } - - if (!key_map[code]) { - printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); - return; - } - - input_event(dev, EV_KEY, key_map[code], 1); - input_sync(dev); - - /* initialize debounce and repeat */ - dev->repeat_key = code; - /* Zenith remote _always_ sends 2 sequences */ - dev->rep[0] = ~0; - mod_timer(&dev->timer, jiffies + msecs_to_jiffies(350)); - } -} - static int msp430_ir_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; -- cgit v1.2.3 From 1b5b32bf877d6f77d7eb6580d43623cc113a3b60 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 28 Nov 2006 02:16:20 -0300 Subject: V4L/DVB (4890): Lgdt330x: fix signal / lock status detection bug In some cases when using VSB, the AGC status register has been known to falsely report "no signal" when in fact there is a carrier lock. The datasheet labels these status flags as QAM only, yet the lgdt330x module is using these flags for both QAM and VSB. This patch allows for the carrier recovery lock status register to be tested, even if the agc signal status register falsely reports no signal. Thanks to jcrews from #linuxtv in irc, for initially reporting this bug. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt330x.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index db3ef58dafb..75be6e4aa17 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -437,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Test signal does not exist flag */ /* as well as the AGC lock flag. */ *status |= FE_HAS_SIGNAL; - } else { - /* Without a signal all other status bits are meaningless */ - return 0; } /* @@ -502,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Test input signal does not exist flag */ /* as well as the AGC lock flag. */ *status |= FE_HAS_SIGNAL; - } else { - /* Without a signal all other status bits are meaningless */ - return 0; } /* Carrier Recovery Lock Status Register */ -- cgit v1.2.3 From 0b6389ff16d57d8706bb516bde0211207aae73af Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 28 Nov 2006 02:35:02 -0300 Subject: V4L/DVB (4891): Lgdt330x: fix broken whitespace Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt330x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 75be6e4aa17..68aad0f6519 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -304,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, static u8 lgdt3303_8vsb_44_data[] = { 0x04, 0x00, 0x0d, 0x40, - 0x0e, 0x87, - 0x0f, 0x8e, - 0x10, 0x01, - 0x47, 0x8b }; + 0x0e, 0x87, + 0x0f, 0x8e, + 0x10, 0x01, + 0x47, 0x8b }; /* * Array of byte pairs -- cgit v1.2.3 From 036171e75ef866b4fd8650c5b890359482ba2a4c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Nov 2006 05:09:22 -0300 Subject: V4L/DVB: Dvb-budget ci fix drivers/media/dvb/ttpci/budget-ci.c:220:6: warning: "LINUX_VERSION_CODE" is not defined drivers/media/dvb/ttpci/budget-ci.c:220:28: warning: "KERNEL_VERSION" is not defined drivers/media/dvb/ttpci/budget-ci.c:220:42: error: missing binary operator before token "(" Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 8f71124099b..f793a2741e2 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -217,11 +217,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) input_dev->id.vendor = saa->pci->vendor; input_dev->id.product = saa->pci->device; } -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) input_dev->cdev.dev = &saa->pci->dev; -# else - input_dev->dev = &saa->pci->dev; -# endif /* Select keymap and address */ switch (budget_ci->budget.dev->pci->subsystem_device) { -- cgit v1.2.3 From 4be3276a66c09e68a539253ce660913bb2585984 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 24 Nov 2006 17:04:24 -0300 Subject: V4L/DVB (4896): Dvb-usb: fix vendor ID ordering The vendor IDs in this file were all in alphabetical order except for this one. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 6a55ea22216..299382dcb81 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -32,8 +32,8 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 -#define USB_VID_UNIWILL 0x1584 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 +#define USB_VID_UNIWILL 0x1584 #define USB_VID_WIDEVIEW 0x14aa /* Product IDs */ -- cgit v1.2.3 From 00c4cc67512ada1d195b8bf3ef1db1d6b3951605 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 1 Nov 2006 13:09:51 -0300 Subject: V4L/DVB (4916): Av7110,budget,budget-ci,budget-av: Use interrupt mode for I2C transfers Use interrupt mode for I2C transfers. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 2 +- drivers/media/dvb/ttpci/budget-av.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttpci/budget.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index bba23bcd1b1..366c1371ee9 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension av7110_extension = { .name = "dvb", - .flags = SAA7146_I2C_SHORT_DELAY, + .flags = SAA7146_USE_I2C_IRQ, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8bdc90a70c2..9478d5957b9 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1290,7 +1290,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget_av", - .flags = SAA7146_I2C_SHORT_DELAY, + .flags = SAA7146_USE_I2C_IRQ, .pci_tbl = pci_tbl, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index f793a2741e2..0a11b551440 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1222,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget_ci dvb", - .flags = SAA7146_I2C_SHORT_DELAY, + .flags = SAA7146_USE_I2C_IRQ, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 56f1c80defc..9268a82bada 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget dvb", - .flags = SAA7146_I2C_SHORT_DELAY, + .flags = SAA7146_USE_I2C_IRQ, .module = THIS_MODULE, .pci_tbl = pci_tbl, -- cgit v1.2.3 From 740cf9e15e5b2274841ee9e6d6d717e37b3f31cf Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Fri, 3 Nov 2006 15:34:18 -0300 Subject: V4L/DVB (4918): Budget-av: Add delay for frontend power-on Added a delay to give the frontend a little bit time for power-on. Signed-off-by: Hartmut Birr Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 9478d5957b9..4d1954072bb 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -952,6 +952,9 @@ static void frontend_init(struct budget_av *budget_av) /* Enable / PowerON Frontend */ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + /* Wait for PowerON */ + msleep(100); + /* additional setup necessary for the PLUS cards */ switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1_PLUS: -- cgit v1.2.3 From 97a2cf05c409f0f73346d3d258b643c782879c77 Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sun, 3 Dec 2006 10:49:47 -0300 Subject: V4L/DVB (4919): Budget-ci: Use SAA7146_IER_ENABLE/DISABLE to enable or disable a hardware interrupt Use SAA7146_IER_ENABLE/DISABLE to enable or disable a hardware interrupt. Signed-off-by: Hartmut Birr Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 0a11b551440..0dc52918ce6 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -261,7 +261,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); + SAA7146_IER_ENABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); return 0; @@ -277,7 +277,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *dev = budget_ci->ir.dev; - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); + SAA7146_IER_DISABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); @@ -537,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci) } else { saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); } - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); + SAA7146_IER_ENABLE(saa, MASK_03); } // enable interface @@ -569,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) // disable CI interrupts if (budget_ci->ci_irq) { - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); + SAA7146_IER_DISABLE(saa, MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ciintf_irq_tasklet); } -- cgit v1.2.3 From 2a893dea0f186efc2eb4bcdaee145b20c87d239d Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sun, 3 Dec 2006 21:08:08 -0300 Subject: V4L/DVB (4921): Budget-av, budget-ci: Fix MC1 register programming Remove bogus read during MC1 programming. A '1' bit could never be cleared using the old code. Use MASK_xx macros. Signed-off-by: Hartmut Birr Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 6 +++--- drivers/media/dvb/ttpci/budget-ci.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 4d1954072bb..89ab4b59155 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av) saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); /* Enable DEBI pins */ - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); + saa7146_write(saa, MC1, MASK_27 | MASK_11); /* register CI interface */ budget_av->ca.owner = THIS_MODULE; @@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av) return 0; error: - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + saa7146_write(saa, MC1, MASK_27); return result; } @@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av) dvb_ca_en50221_release(&budget_av->ca); /* disable DEBI pins */ - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + saa7146_write(saa, MC1, MASK_27); } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 0dc52918ce6..f2066b47bae 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -485,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci) memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); // enable DEBI pins - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); + saa7146_write(saa, MC1, MASK_27 | MASK_11); // test if it is there ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); @@ -559,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci) return 0; error: - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + saa7146_write(saa, MC1, MASK_27); return result; } @@ -587,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) dvb_ca_en50221_release(&budget_ci->ca); // disable DEBI pins - saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + saa7146_write(saa, MC1, MASK_27); } static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) -- cgit v1.2.3 From b2fb7f55a1837e39a9f74e2fd7be990ccba90eb4 Mon Sep 17 00:00:00 2001 From: Rusty Scott Date: Mon, 4 Dec 2006 18:04:15 -0300 Subject: V4L/DVB (4939): Or51132: Changed SNR and signal strength reporting Removes embedded log functions and makes use of the DVB math functions to provide SNR in dB. The changes are modeled after recent changes made to the LGDT330x frontends in lgdt330x.c Signed-off-by: Rusty Scott Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/or51132.c | 176 ++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 85 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index d20ab30c1e8..5a3a6e53cda 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -40,6 +40,7 @@ #include #include +#include "dvb_math.h" #include "dvb_frontend.h" #include "dvb-pll.h" #include "or51132.h" @@ -62,6 +63,7 @@ struct or51132_state /* Demodulator private data */ fe_modulation_t current_modulation; + u32 snr; /* Result of last SNR calculation */ /* Tuner private data */ u32 current_frequency; @@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -/* log10-1 table at .5 increments from 1 to 100.5 */ -static unsigned int i100x20log10[] = { - 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, - 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, - 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, - 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, - 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, - 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, - 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, - 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, - 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, - 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, - 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, - 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, - 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, - 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, - 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, - 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, - 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, - 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, - 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, - 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, -}; +/* Calculate SNR estimation (scaled by 2^24) -static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; + 8-VSB SNR and QAM equations from Oren datasheets -static unsigned int i20Log10(unsigned short val) -{ - unsigned int rntval = 100; - unsigned int tmp = val; - unsigned int exp = 1; + For 8-VSB: + SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K + + Where K = 0 if NTSC rejection filter is OFF; and + K = 3 if NTSC rejection filter is ON + + For QAM64: + SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - while(tmp > 100) {tmp /= 100; exp++;} + For QAM256: + SNR[dB] = 10 * log10(907832426.314266 / MSE^2 ) - val = (2 * val)/denom[exp]; - if (exp > 1) rntval = 2000*exp; + We re-write the snr equation as: + SNR * 2^24 = 10*(c - 2*intlog10(MSE)) + Where for QAM256, c = log10(907832426.314266) * 2^24 + and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */ - rntval += i100x20log10[val]; - return rntval; +static u32 calculate_snr(u32 mse, u32 c) +{ + if (mse == 0) /* No signal */ + return 0; + + mse = 2*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 or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) +static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) { struct or51132_state* state = fe->demodulator_priv; - unsigned char rec_buf[2]; - unsigned char snd_buf[2]; - u8 rcvr_stat; - u16 snr_equ; - u32 signal_strength; - int usK; + u8 rec_buf[2]; + u8 snd_buf[2]; + u32 noise; + u32 c; + u32 usK; + /* Register is same for VSB or QAM firmware */ snd_buf[0]=0x04; snd_buf[1]=0x02; /* SNR after Equalizer */ msleep(30); /* 30ms */ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - printk(KERN_WARNING "or51132: read_status write error\n"); - return -1; + printk(KERN_WARNING "or51132: snr write error\n"); + return -EREMOTEIO; } msleep(30); /* 30ms */ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: read_status read error\n"); - return -1; + printk(KERN_WARNING "or51132: snr read error\n"); + return -EREMOTEIO; } - snr_equ = rec_buf[0] | (rec_buf[1] << 8); - dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); + noise = rec_buf[0] | (rec_buf[1] << 8); + dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise); - /* Receiver Status */ + /* Read status, contains modulation type for QAM_AUTO and + NTSC filter for VSB */ snd_buf[0]=0x04; - snd_buf[1]=0x00; + snd_buf[1]=0x00; /* Status register */ msleep(30); /* 30ms */ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); - return -1; + printk(KERN_WARNING "or51132: status write error\n"); + return -EREMOTEIO; } msleep(30); /* 30ms */ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); - return -1; + printk(KERN_WARNING "or51132: status read error\n"); + return -EREMOTEIO; } - dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]); - rcvr_stat = rec_buf[1]; - usK = (rcvr_stat & 0x10) ? 3 : 0; - /* The value reported back from the frontend will be FFFF=100% 0000=0% */ - signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; - if (signal_strength > 0xffff) - *strength = 0xffff; - else - *strength = signal_strength; - dprintk("read_signal_strength %i\n",*strength); + usK = 0; + switch (rec_buf[0]) { + case 0x06: + usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0; + /* Fall through to QAM64 case */ + case 0x43: + c = 150204167; + break; + case 0x45: + c = 150290396; + break; + default: + printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]); + return -EREMOTEIO; + } + dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, + rec_buf[0], rec_buf[1]&0x10?"n":"ff"); + + /* Calculate SNR using noise, c, and NTSC rejection correction */ + state->snr = calculate_snr(noise, c) - usK; + *snr = (state->snr) >> 16; + + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; } -static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) +static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - struct or51132_state* state = fe->demodulator_priv; - unsigned char rec_buf[2]; - unsigned char snd_buf[2]; - u16 snr_equ; - - snd_buf[0]=0x04; - snd_buf[1]=0x02; /* SNR after Equalizer */ - msleep(30); /* 30ms */ - if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - printk(KERN_WARNING "or51132: read_snr write error\n"); - return -1; - } - msleep(30); /* 30ms */ - if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: read_snr dvr read error\n"); - return -1; - } - snr_equ = rec_buf[0] | (rec_buf[1] << 8); - dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); + /* 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 or51132_state* state = (struct or51132_state*) fe->demodulator_priv; + u16 snr; + int ret; - *snr = 0xFFFF - snr_equ; - dprintk("read_snr %i\n",*snr); + ret = fe->ops.read_snr(fe, &snr); + if (ret != 0) + return ret; + /* 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; return 0; } -- cgit v1.2.3 From 1444e5f591b8c68d7a326f5b0ad6c63a984d56dd Mon Sep 17 00:00:00 2001 From: Rusty Scott Date: Mon, 4 Dec 2006 18:04:16 -0300 Subject: V4L/DVB (4940): Or51211: Changed SNR and signal strength calculations Removes embedded log functions and makes use of the DVB math functions to provide SNR in dB. The changes are modeled after recent changes made to the LGDT330x frontends in lgdt330x.c Signed-off-by: Rusty Scott Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/or51211.c | 124 ++++++++++++++-------------------- 1 file changed, 50 insertions(+), 74 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 2bf124b5368..048d7cfe12d 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -39,6 +39,7 @@ #include #include +#include "dvb_math.h" #include "dvb_frontend.h" #include "or51211.h" @@ -63,6 +64,7 @@ struct or51211_state { /* Demodulator private data */ u8 initialized:1; + u32 snr; /* Result of last SNR claculation */ /* Tuner private data */ u32 current_frequency; @@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -/* log10-1 table at .5 increments from 1 to 100.5 */ -static unsigned int i100x20log10[] = { - 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, - 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, - 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, - 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, - 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, - 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, - 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, - 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, - 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, - 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, - 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, - 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, - 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, - 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, - 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, - 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, - 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, - 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, - 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, - 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, -}; - -static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; +/* Calculate SNR estimation (scaled by 2^24) -static unsigned int i20Log10(unsigned short val) -{ - unsigned int rntval = 100; - unsigned int tmp = val; - unsigned int exp = 1; + 8-VSB SNR equation from Oren datasheets - while(tmp > 100) {tmp /= 100; exp++;} + For 8-VSB: + SNR[dB] = 10 * log10(219037.9454 / MSE^2 ) - val = (2 * val)/denom[exp]; - if (exp > 1) rntval = 2000*exp; + We re-write the snr equation as: + SNR * 2^24 = 10*(c - 2*intlog10(MSE)) + Where for 8-VSB, c = log10(219037.9454) * 2^24 */ - rntval += i100x20log10[val]; - return rntval; +static u32 calculate_snr(u32 mse, u32 c) +{ + if (mse == 0) /* No signal */ + return 0; + + mse = 2*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 or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) +static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) { struct or51211_state* state = fe->demodulator_priv; u8 rec_buf[2]; - u8 snd_buf[4]; - u8 snr_equ; - u32 signal_strength; + u8 snd_buf[3]; /* SNR after Equalizer */ snd_buf[0] = 0x04; snd_buf[1] = 0x00; snd_buf[2] = 0x04; - snd_buf[3] = 0x00; if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { - printk(KERN_WARNING "or51211: read_status write error\n"); + printk(KERN_WARNING "%s: error writing snr reg\n", + __FUNCTION__); return -1; } - msleep(3); if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51211: read_status read error\n"); + printk(KERN_WARNING "%s: read_status read error\n", + __FUNCTION__); return -1; } - snr_equ = rec_buf[0] & 0xff; - /* The value reported back from the frontend will be FFFF=100% 0000=0% */ - signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; - if (signal_strength > 0xffff) - *strength = 0xffff; - else - *strength = signal_strength; - dprintk("read_signal_strength %i\n",*strength); + state->snr = calculate_snr(rec_buf[0], 89599047); + *snr = (state->snr) >> 16; + + dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0], + state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; } -static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) +static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - struct or51211_state* state = fe->demodulator_priv; - u8 rec_buf[2]; - u8 snd_buf[4]; - - /* SNR after Equalizer */ - snd_buf[0] = 0x04; - snd_buf[1] = 0x00; - snd_buf[2] = 0x04; - snd_buf[3] = 0x00; - - if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { - printk(KERN_WARNING "or51211: read_status write error\n"); - return -1; - } - msleep(3); - if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51211: read_status read error\n"); - return -1; - } - *snr = rec_buf[0] & 0xff; - - dprintk("read_snr %i\n",*snr); + /* 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 or51211_state* state = (struct or51211_state*)fe->demodulator_priv; + u16 snr; + int ret; + + ret = fe->ops.read_snr(fe, &snr); + if (ret != 0) + return ret; + /* 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; return 0; } -- cgit v1.2.3 From 79a54cbd73afe05d807b2128fa41a92cb4acd637 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 5 Dec 2006 14:20:06 -0300 Subject: V4L/DVB (4948): Cxusb: Convert tuner functions to use dvb_pll_attach Converted dee1601, lgz201 and dtt8579 to use dvb_pll_attach in dvb-usb-cxusb. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index ae039b9cb72..ee39ebea997 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -367,25 +367,21 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) { - adap->pll_addr = 0x61; - adap->pll_desc = &dvb_pll_thomson_dtt7579; - adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; + dvb_attach(dvb_pll_attach, adap->fe, 0x61, + NULL, &dvb_pll_thomson_dtt7579); return 0; } static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) { - adap->pll_addr = 0x61; - adap->pll_desc = &dvb_pll_lg_z201; - adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; + dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201); return 0; } static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) { - adap->pll_addr = 0x60; - adap->pll_desc = &dvb_pll_thomson_dtt7579; - adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; + dvb_attach(dvb_pll_attach, adap->fe, 0x60, + NULL, &dvb_pll_thomson_dtt7579); return 0; } -- cgit v1.2.3 From f35db23c1b1c4da0642e932a7035b5c577377974 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 5 Dec 2006 14:53:39 -0300 Subject: V4L/DVB (4949): Cxusb: codingstyle cleanups Trivial whitespace / 80-column limit cleanups Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 110 +++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 50 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index ee39ebea997..15d12fce34d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -17,9 +17,9 @@ * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) * - * 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 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. * * see Documentation/dvb/README.dvb-usb for more information */ @@ -34,22 +34,22 @@ /* debug */ int dvb_usb_cxusb_debug; -module_param_named(debug,dvb_usb_cxusb_debug, int, 0644); +module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); static int cxusb_ctrl_msg(struct dvb_usb_device *d, - u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) + u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 sndbuf[1+wlen]; - memset(sndbuf,0,1+wlen); + memset(sndbuf, 0, 1+wlen); sndbuf[0] = cmd; - memcpy(&sndbuf[1],wbuf,wlen); + memcpy(&sndbuf[1], wbuf, wlen); if (wo) - dvb_usb_generic_write(d,sndbuf,1+wlen); + dvb_usb_generic_write(d, sndbuf, 1+wlen); else - dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0); + dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); return 0; } @@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) { struct cxusb_state *st = d->priv; - u8 o[2],i; + u8 o[2], i; if (st->gpio_write_state[GPIO_TUNER] == onoff) return; o[0] = GPIO_TUNER; o[1] = onoff; - cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1); + cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); if (i != 0x01) deb_info("gpio_write failed.\n"); @@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) } /* I2C */ -static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; @@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) if (d->udev->descriptor.idVendor == USB_VID_MEDION) switch (msg[i].addr) { - case 0x63: - cxusb_gpio_tuner(d,0); - break; - default: - cxusb_gpio_tuner(d,1); - break; + case 0x63: + cxusb_gpio_tuner(d, 0); + break; + default: + cxusb_gpio_tuner(d, 1); + break; } /* read request */ @@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) obuf[0] = msg[i].len; obuf[1] = msg[i+1].len; obuf[2] = msg[i].addr; - memcpy(&obuf[3],msg[i].buf,msg[i].len); + memcpy(&obuf[3], msg[i].buf, msg[i].len); if (cxusb_ctrl_msg(d, CMD_I2C_READ, - obuf, 3+msg[i].len, - ibuf, 1+msg[i+1].len) < 0) + obuf, 3+msg[i].len, + ibuf, 1+msg[i+1].len) < 0) break; if (ibuf[0] != 0x08) deb_i2c("i2c read may have failed\n"); - memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); + memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); i++; } else { /* write */ u8 obuf[2+msg[i].len], ibuf; obuf[0] = msg[i].addr; obuf[1] = msg[i].len; - memcpy(&obuf[2],msg[i].buf,msg[i].len); + memcpy(&obuf[2], msg[i].buf, msg[i].len); - if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) + if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, + 2+msg[i].len, &ibuf,1) < 0) break; if (ibuf != 0x08) deb_i2c("i2c write may have failed\n"); @@ -326,7 +328,6 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, - .output_mode = CX22702_PARALLEL_OUTPUT, }; @@ -399,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); - if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, + &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -412,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, + &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -426,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, + &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -439,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) || - ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL)) + if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, + &adap->dev->i2c_adap)) != NULL) || + ((adap->fe = dvb_attach(zl10353_attach, + &cxusb_zl10353_dee1601_config, + &adap->dev->i2c_adap)) != NULL)) return 0; return -EIO; @@ -452,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) */ #define BLUEBIRD_01_ID_OFFSET 6638 -static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw) +static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, + const struct firmware *fw) { if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) return -EINVAL; @@ -460,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { - fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; - fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; + fw->data[BLUEBIRD_01_ID_OFFSET + 2] = + udev->descriptor.idProduct + 1; + fw->data[BLUEBIRD_01_ID_OFFSET + 3] = + udev->descriptor.idProduct >> 8; - return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2); + return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); } return -EINVAL; @@ -477,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; static int cxusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || @@ -491,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf, } static struct usb_device_id cxusb_table [] = { - { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, - {} /* Terminating entry */ + { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -765,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = dvb_usb_device_exit, .id_table = cxusb_table, }; -- cgit v1.2.3