From acf2821282bdd912f9ca46780879a21679429f85 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Apr 2007 12:31:06 -0300 Subject: V4L/DVB (5297): Fix identation on tda10021.c Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10021.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 5b9c5bb29b23..9348e76fe2e0 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -447,7 +447,7 @@ static struct dvb_frontend_ops tda10021_ops = { .frequency_max = 858000000, .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ -#if 0 + #if 0 .frequency_tolerance = ???, .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ #endif -- cgit v1.2.3 From 1bb0e8667fab773d6c5a3d7caf506001deaeb7f5 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 27 Apr 2007 12:31:10 -0300 Subject: V4L/DVB (5311): Tda1004x driver updates There are the following changes: - separate configuration of IF and GPIOs. - set GPIOs before firmware load. This helps to avoid I2C address collisions. - if desired invert GPIOs at sleep (automatic return to analog mode of card). - added 3 tuner configuration bytes to config stuct. - added i2c gate address to config struct. - moved _state struct declaration to header file to make it accessible on board layer. - added "conf_probed" to the state struct to allow i.e. probing for correct tuner version. - changed firmware load mechanism to always: + check if already loaded + try to boot from eeprom + try downlad from host - corrected name of tda10046 firmware image (backward compatible). Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 86 ++++++++++++++----------------- drivers/media/dvb/frontends/tda1004x.h | 49 ++++++++++++++++-- drivers/media/video/saa7134/saa7134-dvb.c | 48 ++++++++++------- 3 files changed, 112 insertions(+), 71 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index f4a9cf9d26d0..c47501ae8b0e 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -40,20 +40,6 @@ #include "dvb_frontend.h" #include "tda1004x.h" -enum tda1004x_demod { - TDA1004X_DEMOD_TDA10045, - TDA1004X_DEMOD_TDA10046, -}; - -struct tda1004x_state { - struct i2c_adapter* i2c; - const struct tda1004x_config* config; - struct dvb_frontend frontend; - - /* private demod data */ - enum tda1004x_demod demod_type; -}; - static int debug; #define dprintk(args...) \ do { \ @@ -507,8 +493,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); } tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); + /* set GPIO 1 and 3 */ + if (state->config->gpio_config != TDA10046_GPTRI) { + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33); + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f); + } /* let the clocks recover from sleep */ - msleep(5); + msleep(10); /* The PLLs need to be reprogrammed after sleep */ tda10046_init_plls(fe); @@ -517,25 +508,29 @@ static int tda10046_fwupload(struct dvb_frontend* fe) if (tda1004x_check_upload_ok(state) == 0) return 0; - if (state->config->request_firmware != NULL) { - /* request the firmware, this will block until someone uploads it */ - printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); - ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); + printk(KERN_INFO "tda1004x: trying to boot from eeprom\n"); + tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); + msleep(300); + /* don't re-upload unless necessary */ + if (tda1004x_check_upload_ok(state) == 0) + return 0; + + /* request the firmware, this will block until someone uploads it */ + printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); + ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); + if (ret) { + /* remain compatible to old bug: try to load with tda10045 image name */ + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); if (ret) { printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); return ret; - } - tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST - ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); - release_firmware(fw); - if (ret) - return ret; - } else { - /* boot from firmware eeprom */ - printk(KERN_INFO "tda1004x: booting from eeprom\n"); - tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); - msleep(300); + } else + printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", + TDA10046_DEFAULT_FIRMWARE); } + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST + ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); + release_firmware(fw); return tda1004x_check_upload_ok(state); } @@ -638,37 +633,25 @@ static int tda10046_init(struct dvb_frontend* fe) switch (state->config->agc_config) { case TDA10046_AGC_DEFAULT: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup - tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities break; case TDA10046_AGC_IFO_AUTO_NEG: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup - tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities break; case TDA10046_AGC_IFO_AUTO_POS: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup - tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00); // set AGC polarities break; - case TDA10046_AGC_TDA827X_GP11: + case TDA10046_AGC_TDA827X: 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_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 + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities break; } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); - tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x79); // Turn IF AGC output on tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } @@ -1165,6 +1148,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) static int tda1004x_sleep(struct dvb_frontend* fe) { struct tda1004x_state* state = fe->demodulator_priv; + int gpio_conf; switch (state->demod_type) { case TDA1004X_DEMOD_TDA10045: @@ -1174,6 +1158,12 @@ static int tda1004x_sleep(struct dvb_frontend* fe) case TDA1004X_DEMOD_TDA10046: /* set outputs to tristate */ tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); + /* invert GPIO 1 and 3 if desired*/ + gpio_conf = state->config->gpio_config; + if (gpio_conf >= TDA10046_GP00_I) + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, + (gpio_conf & 0x0f) ^ 0x0a); + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index ec502d71b83c..886db3f75d56 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -35,9 +35,23 @@ 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_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*/ + TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ +}; + +/* Many (hybrid) boards use GPIO 1 and 3 + GPIO1 analog - dvb switch + GPIO3 firmware eeprom address switch +*/ +enum tda10046_gpio { + TDA10046_GPTRI = 0x00, /* All GPIOs tristate */ + TDA10046_GP00 = 0x40, /* GPIO3=0, GPIO1=0 */ + TDA10046_GP01 = 0x42, /* GPIO3=0, GPIO1=1 */ + TDA10046_GP10 = 0x48, /* GPIO3=1, GPIO1=0 */ + TDA10046_GP11 = 0x4a, /* GPIO3=1, GPIO1=1 */ + TDA10046_GP00_I = 0x80, /* GPIO3=0, GPIO1=0, invert in sleep mode*/ + TDA10046_GP01_I = 0x82, /* GPIO3=0, GPIO1=1, invert in sleep mode */ + TDA10046_GP10_I = 0x88, /* GPIO3=1, GPIO1=0, invert in sleep mode */ + TDA10046_GP11_I = 0x8a, /* GPIO3=1, GPIO1=1, invert in sleep mode */ }; enum tda10046_if { @@ -67,11 +81,38 @@ struct tda1004x_config /* AGC configuration */ enum tda10046_agc agc_config; + /* setting of GPIO1 and 3 */ + enum tda10046_gpio gpio_config; + + /* slave address and configuration of the tuner */ + u8 tuner_address; + u8 tuner_config; + u8 antenna_switch; + + /* if the board uses another I2c Bridge (tda8290), its address */ + u8 i2c_gate; + /* request firmware for device */ - /* set this to NULL if the card has a firmware EEPROM */ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; +enum tda1004x_demod { + TDA1004X_DEMOD_TDA10045, + TDA1004X_DEMOD_TDA10046, +}; + +struct tda1004x_state { + struct i2c_adapter* i2c; + const struct tda1004x_config* config; + struct dvb_frontend frontend; + + /* this allows to store probed board information */ + int conf_probed; + + /* private demod data */ + enum tda1004x_demod demod_type; +}; + #if defined(CONFIG_DVB_TDA1004X) || (defined(CONFIG_DVB_TDA1004X_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e3059fd33951..6d148a7601ac 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -416,7 +416,7 @@ static struct tda1004x_config philips_europa_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_IFO_AUTO_POS, .if_freq = TDA10046_FREQ_052, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -548,7 +548,7 @@ static struct tda1004x_config medion_cardbus = { .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_IFO_AUTO_NEG, .if_freq = TDA10046_FREQ_3613, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -681,9 +681,10 @@ static struct tda1004x_config tda827x_lifeview_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -885,9 +886,10 @@ static struct tda1004x_config philips_tiger_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -918,9 +920,10 @@ static struct tda1004x_config cinergy_ht_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP01, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP01_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -930,7 +933,8 @@ static struct tda1004x_config pinnacle_pctv_310i_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, .request_firmware = philips_tda1004x_request_firmware, }; @@ -942,7 +946,8 @@ static struct tda1004x_config hauppauge_hvr_1110_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, .request_firmware = philips_tda1004x_request_firmware, }; @@ -954,7 +959,8 @@ static struct tda1004x_config asus_p7131_dual_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, .request_firmware = philips_tda1004x_request_firmware, }; @@ -1006,9 +1012,10 @@ static struct tda1004x_config lifeview_trio_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP00, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP00_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -1043,9 +1050,10 @@ static struct tda1004x_config ads_tech_duo_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP00, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP00_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -1068,9 +1076,10 @@ static struct tda1004x_config tevion_dvbt220rf_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -1113,9 +1122,10 @@ static struct tda1004x_config md8800_dvbt_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, + .request_firmware = philips_tda1004x_request_firmware, }; static struct tda10086_config flydvbs = { -- cgit v1.2.3 From f4546e702a89d2e483570f0f16c5155bb781cc38 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 27 Apr 2007 12:31:13 -0300 Subject: V4L/DVB (5315): Tda1004x: check request firmware for NULL ponter again In older versions, this was used to decide whether to boot from eeprom or file. This is no longer necessary but the check helps to avoid an oops with misconfigured cards. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index c47501ae8b0e..dbfc94a9c3f7 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -515,18 +515,24 @@ static int tda10046_fwupload(struct dvb_frontend* fe) if (tda1004x_check_upload_ok(state) == 0) return 0; - /* request the firmware, this will block until someone uploads it */ - printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); - ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); - if (ret) { - /* remain compatible to old bug: try to load with tda10045 image name */ - ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); + if (state->config->request_firmware != NULL) { + /* request the firmware, this will block until someone uploads it */ + printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); + ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); if (ret) { - printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); - return ret; - } else - printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", - TDA10046_DEFAULT_FIRMWARE); + /* remain compatible to old bug: try to load with tda10045 image name */ + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); + if (ret) { + printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); + return ret; + } else { + printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", + TDA10046_DEFAULT_FIRMWARE); + } + } + } else { + printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n"); + return -EIO; } tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); -- cgit v1.2.3 From 8ce47dad8e2b9fcb899a67e6537337fa9c18c1f5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 27 Apr 2007 12:31:14 -0300 Subject: V4L/DVB (5317): Create tda827x dvb tuner module The patch moves the tda827x dvb tuning code to a separate module Signed-off-by: Michael Krufky Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda1004x.h | 3 - drivers/media/dvb/frontends/tda827x.c | 476 ++++++++++++++++++++++++++++ drivers/media/dvb/frontends/tda827x.h | 62 ++++ drivers/media/video/saa7134/Kconfig | 1 + drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 375 ++-------------------- 8 files changed, 568 insertions(+), 359 deletions(-) create mode 100644 drivers/media/dvb/frontends/tda827x.c create mode 100644 drivers/media/dvb/frontends/tda827x.h (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 22c2cf2cea98..a205e0b45a54 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -290,6 +290,13 @@ config DVB_TDA826X help A DVB-S silicon tuner module. Say Y when you want to support this tuner. +config DVB_TDA827X + tristate "Philips TDA827X silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-T silicon tuner module. Say Y when you want to support this tuner. + config DVB_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index a646d9969b71..e038942a1d8a 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o +obj-$(CONFIG_DVB_TDA827X) += tda827x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 886db3f75d56..6badc81d4c33 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -106,9 +106,6 @@ struct tda1004x_state { const struct tda1004x_config* config; struct dvb_frontend frontend; - /* this allows to store probed board information */ - int conf_probed; - /* private demod data */ enum tda1004x_demod demod_type; }; diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c new file mode 100644 index 000000000000..cff2d1fa4094 --- /dev/null +++ b/drivers/media/dvb/frontends/tda827x.c @@ -0,0 +1,476 @@ +/* + * + * (c) 2005 Hartmut Hackmann + * (c) 2007 Michael Krufky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include "tda827x.h" + +static int debug = 0; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "tda827x: " args); \ + } while (0) + +struct tda827x_priv { + int i2c_addr; + struct i2c_adapter *i2c_adap; + struct tda827x_config *cfg; + u32 frequency; + u32 bandwidth; +}; + +struct tda827x_data { + u32 lomax; + u8 spd; + u8 bs; + u8 bp; + u8 cp; + u8 gc3; + u8 div1p5; +}; + +static const struct tda827x_data tda827x_dvbt[] = { + { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, + { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, + { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, + { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, + { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, + { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, + { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, + { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, + { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, + { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, + { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, + { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, + { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} +}; + +static int tda827xo_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + u8 buf[14]; + + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + int i, tuner_freq, if_freq; + u32 N; + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + if_freq = 4000000; + break; + case BANDWIDTH_7_MHZ: + if_freq = 4500000; + break; + default: /* 8 MHz or Auto */ + if_freq = 5000000; + break; + } + tuner_freq = params->frequency + if_freq; + + i = 0; + while (tda827x_dvbt[i].lomax < tuner_freq) { + if(tda827x_dvbt[i + 1].lomax == 0) + break; + i++; + } + + N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2); + buf[0] = 0; + buf[1] = (N>>8) | 0x40; + buf[2] = N & 0xff; + buf[3] = 0; + buf[4] = 0x52; + buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) + + (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp; + buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f; + buf[7] = 0xbf; + buf[8] = 0x2a; + buf[9] = 0x05; + buf[10] = 0xff; + buf[11] = 0x00; + buf[12] = 0x00; + buf[13] = 0x40; + + msg.len = 14; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { + printk("%s: could not write to tuner at addr: 0x%02x\n", + __FUNCTION__, priv->i2c_addr << 1); + return -EIO; + } + msleep(500); + /* correct CP value */ + buf[0] = 0x30; + buf[1] = 0x50 + tda827x_dvbt[i].cp; + msg.len = 2; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + priv->frequency = tuner_freq - if_freq; // FIXME + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; + + return 0; +} + +static int tda827xo_sleep(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + static u8 buf[] = { 0x30, 0xd0 }; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + if (priv->cfg && priv->cfg->sleep) + priv->cfg->sleep(fe); + + return 0; +} + +/* ------------------------------------------------------------------ */ + +struct tda827xa_data { + u32 lomax; + u8 svco; + u8 spd; + u8 scr; + u8 sbs; + u8 gc3; +}; + +static const struct tda827xa_data tda827xa_dvbt[] = { + { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, + { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} +}; + +static int tda827xa_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + u8 buf[10]; + + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + int i, tuner_freq, if_freq; + u32 N; + + if (priv->cfg && priv->cfg->lna_gain) + priv->cfg->lna_gain(fe, 1); + msleep(20); + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + if_freq = 4000000; + break; + case BANDWIDTH_7_MHZ: + if_freq = 4500000; + break; + default: /* 8 MHz or Auto */ + if_freq = 5000000; + break; + } + tuner_freq = params->frequency + if_freq; + + i = 0; + while (tda827xa_dvbt[i].lomax < tuner_freq) { + if(tda827xa_dvbt[i + 1].lomax == 0) + break; + i++; + } + + N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; + buf[0] = 0; // subaddress + buf[1] = N >> 8; + buf[2] = N & 0xff; + buf[3] = 0; + buf[4] = 0x16; + buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + + tda827xa_dvbt[i].sbs; + buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); + buf[7] = 0x1c; + buf[8] = 0x06; + buf[9] = 0x24; + buf[10] = 0x00; + msg.len = 11; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { + printk("%s: could not write to tuner at addr: 0x%02x\n", + __FUNCTION__, priv->i2c_addr << 1); + return -EIO; + } + buf[0] = 0x90; + buf[1] = 0xff; + buf[2] = 0x60; + buf[3] = 0x00; + buf[4] = 0x59; // lpsel, for 6MHz + 2 + msg.len = 5; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + buf[0] = 0xa0; + buf[1] = 0x40; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(11); + msg.flags = I2C_M_RD; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + msg.flags = 0; + + buf[1] >>= 4; + dprintk("tda8275a AGC2 gain is: %d\n", buf[1]); + if ((buf[1]) < 2) { + if (priv->cfg && priv->cfg->lna_gain) + priv->cfg->lna_gain(fe, 0); + buf[0] = 0x60; + buf[1] = 0x0c; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + } + + buf[0] = 0xc0; + buf[1] = 0x99; // lpsel, for 6MHz + 2 + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + buf[0] = 0x60; + buf[1] = 0x3c; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + /* correct CP value */ + buf[0] = 0x30; + buf[1] = 0x10 + tda827xa_dvbt[i].scr; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(163); + buf[0] = 0xc0; + buf[1] = 0x39; // lpsel, for 6MHz + 2 + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + msleep(3); + /* freeze AGC1 */ + buf[0] = 0x50; + buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(priv->i2c_adap, &msg, 1); + + priv->frequency = tuner_freq - if_freq; // FIXME + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; + + return 0; +} + +static int tda827xa_sleep(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + static u8 buf[] = { 0x30, 0x90 }; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + i2c_transfer(priv->i2c_adap, &msg, 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (priv->cfg && priv->cfg->sleep) + priv->cfg->sleep(fe); + + return 0; +} + +static int tda827x_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda827x_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct tda827x_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static int tda827x_init(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + + if (priv->cfg && priv->cfg->init) + priv->cfg->init(fe); + + return 0; +} + + +static struct dvb_tuner_ops tda827xo_tuner_ops = { + .info = { + .name = "Philips TDA827X", + }, + .release = tda827x_release, + .init = tda827x_init, + .sleep = tda827xo_sleep, + .set_params = tda827xo_set_params, + .get_frequency = tda827x_get_frequency, + .get_bandwidth = tda827x_get_bandwidth, +}; + +static struct dvb_tuner_ops tda827xa_tuner_ops = { + .info = { + .name = "Philips TDA827XA", + }, + .release = tda827x_release, + .init = tda827x_init, + .sleep = tda827xa_sleep, + .set_params = tda827xa_set_params, + .get_frequency = tda827x_get_frequency, + .get_bandwidth = tda827x_get_bandwidth, +}; + +struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, + struct i2c_adapter *i2c, + struct tda827x_config *cfg) +{ + struct tda827x_priv *priv = NULL; + u8 data; + struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, + .buf = &data, .len = 1 }; + dprintk("%s:\n", __FUNCTION__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(i2c, &msg, 1) != 1) { + printk("%s: could not read from tuner at addr: 0x%02x\n", + __FUNCTION__, addr << 1); + return NULL; + } + + priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c_addr = addr; + priv->i2c_adap = i2c; + priv->cfg = cfg; + if ((data & 0x3c) == 0) { + dprintk("tda827x tuner found\n"); + memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); + } else { + dprintk("tda827xa tuner found\n"); + memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); + } + fe->tuner_priv = priv; + + return fe; +} +EXPORT_SYMBOL(tda827x_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("DVB TDA827x driver"); +MODULE_AUTHOR("Hartmut Hackmann"); +MODULE_AUTHOR("Michael Krufky"); +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h new file mode 100644 index 000000000000..69e8263d6d59 --- /dev/null +++ b/drivers/media/dvb/frontends/tda827x.h @@ -0,0 +1,62 @@ + /* + DVB Driver for Philips tda827x / tda827xa Silicon tuners + + (c) 2005 Hartmut Hackmann + (c) 2007 Michael Krufky + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#ifndef __DVB_TDA827X_H__ +#define __DVB_TDA827X_H__ + +#include +#include "dvb_frontend.h" + +struct tda827x_config +{ + void (*lna_gain) (struct dvb_frontend *fe, int high); + int (*init) (struct dvb_frontend *fe); + int (*sleep) (struct dvb_frontend *fe); +}; + + +/** + * Attach a tda827x tuner to the supplied frontend structure. + * + * @param fe Frontend to attach to. + * @param addr i2c address of the tuner. + * @param i2c i2c adapter to use. + * @param cfg optional callback function pointers. + * @return FE pointer on success, NULL on failure. + */ +#if defined(CONFIG_DVB_TDA827X) || (defined(CONFIG_DVB_TDA827X_MODULE) && defined(MODULE)) +extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr, + struct i2c_adapter *i2c, + struct tda827x_config *cfg); +#else +static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, + int addr, + struct i2c_adapter *i2c, + struct tda827x_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA827X + +#endif // __DVB_TDA827X_H__ diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 59da79ce2efd..309dca368f4a 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -46,6 +46,7 @@ config VIDEO_SAA7134_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE + select DVB_TDA827X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3f972ad3e443..f44e7c7e18a5 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1785,7 +1785,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x00200000, - .mpeg = SAA7134_MPEG_DVB, + .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, .vmux = 1, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 61a68c67c4ad..7985d9e860e9 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -41,7 +41,9 @@ #include "tda10086.h" #include "tda826x.h" +#include "tda827x.h" #include "isl6421.h" + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -654,337 +656,11 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable) /* ------------------------------------------------------------------ */ -struct tda827x_data { - u32 lomax; - u8 spd; - u8 bs; - u8 bp; - u8 cp; - u8 gc3; - u8 div1p5; -}; - -static struct tda827x_data tda827x_dvbt[] = { - { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, - { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, - { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, - { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, - { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, - { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, - { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, - { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, - { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, - { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, - { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, - { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, - { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} -}; - -static int philips_tda827xo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - u8 tuner_buf[14]; - - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; - int i, tuner_freq, if_freq; - u32 N; - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - if_freq = 4000000; - break; - case BANDWIDTH_7_MHZ: - if_freq = 4500000; - break; - default: /* 8 MHz or Auto */ - if_freq = 5000000; - break; - } - tuner_freq = params->frequency + if_freq; - - i = 0; - while (tda827x_dvbt[i].lomax < tuner_freq) { - if(tda827x_dvbt[i + 1].lomax == 0) - break; - i++; - } - - N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2); - tuner_buf[0] = 0; - tuner_buf[1] = (N>>8) | 0x40; - tuner_buf[2] = N & 0xff; - tuner_buf[3] = 0; - tuner_buf[4] = 0x52; - tuner_buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) + - (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp; - tuner_buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f; - tuner_buf[7] = 0xbf; - tuner_buf[8] = 0x2a; - tuner_buf[9] = 0x05; - tuner_buf[10] = 0xff; - tuner_buf[11] = 0x00; - tuner_buf[12] = 0x00; - tuner_buf[13] = 0x40; - - tuner_msg.len = 14; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) { - printk("%s/dvb: could not write to tuner at addr: 0x%02x\n",dev->name, addr << 1); - return -EIO; - } - msleep(500); - /* correct CP value */ - tuner_buf[0] = 0x30; - tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp; - tuner_msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - - return 0; -} - -static int philips_tda827xo_tuner_sleep(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - static u8 tda827x_sleep[] = { 0x30, 0xd0}; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - return 0; -} - -/* ------------------------------------------------------------------ */ - -struct tda827xa_data { - u32 lomax; - u8 svco; - u8 spd; - u8 scr; - u8 sbs; - u8 gc3; -}; - -static struct tda827xa_data tda827xa_dvbt[] = { - { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, - { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, - { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, - { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, - { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, - { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, - { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, - { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, - { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, - { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, - { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, - { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, - { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, - { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, - { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, - { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, - { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, - { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, - { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, - { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, - { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, - { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, - { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, - { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, - { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, - { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, - { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}}; - -static int philips_tda827xa_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - u8 tuner_buf[10]; - - struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = tuner_buf}; - int i, tuner_freq, if_freq; - u32 N; - - philips_tda827x_lna_gain( fe, 1); - msleep(20); - - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - if_freq = 4000000; - break; - case BANDWIDTH_7_MHZ: - if_freq = 4500000; - break; - default: /* 8 MHz or Auto */ - if_freq = 5000000; - break; - } - tuner_freq = params->frequency + if_freq; - - i = 0; - while (tda827xa_dvbt[i].lomax < tuner_freq) { - if(tda827xa_dvbt[i + 1].lomax == 0) - break; - i++; - } - - N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; - tuner_buf[0] = 0; // subaddress - tuner_buf[1] = N >> 8; - tuner_buf[2] = N & 0xff; - tuner_buf[3] = 0; - tuner_buf[4] = 0x16; - tuner_buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + - tda827xa_dvbt[i].sbs; - tuner_buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); - tuner_buf[7] = 0x1c; - tuner_buf[8] = 0x06; - tuner_buf[9] = 0x24; - tuner_buf[10] = 0x00; - msg.len = 11; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { - printk("%s/dvb: could not write to tuner at addr: 0x%02x\n",dev->name, addr << 1); - return -EIO; - } - tuner_buf[0] = 0x90; - tuner_buf[1] = 0xff; - tuner_buf[2] = 0x60; - tuner_buf[3] = 0x00; - tuner_buf[4] = 0x59; // lpsel, for 6MHz + 2 - msg.len = 5; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - tuner_buf[0] = 0xa0; - tuner_buf[1] = 0x40; - msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - msleep(11); - msg.flags = I2C_M_RD; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - msg.flags = 0; - - tuner_buf[1] >>= 4; - dprintk("tda8275a AGC2 gain is: %d\n", tuner_buf[1]); - if ((tuner_buf[1]) < 2) { - philips_tda827x_lna_gain(fe, 0); - tuner_buf[0] = 0x60; - tuner_buf[1] = 0x0c; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - } - - tuner_buf[0] = 0xc0; - tuner_buf[1] = 0x99; // lpsel, for 6MHz + 2 - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - tuner_buf[0] = 0x60; - tuner_buf[1] = 0x3c; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - /* correct CP value */ - tuner_buf[0] = 0x30; - tuner_buf[1] = 0x10 + tda827xa_dvbt[i].scr; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - msleep(163); - tuner_buf[0] = 0xc0; - tuner_buf[1] = 0x39; // lpsel, for 6MHz + 2 - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - msleep(3); - /* freeze AGC1 */ - tuner_buf[0] = 0x50; - tuner_buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &msg, 1); - - return 0; - -} - -static int philips_tda827xa_tuner_sleep(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - static u8 tda827xa_sleep[] = { 0x30, 0x90}; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - return 0; -} - -/* ------------------------------------------------------------------ - * upper layer: distinguish the silicon tuner versions - */ - static int philips_tda827x_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - u8 data; - struct i2c_msg tuner_msg = {.addr = addr,.flags = I2C_M_RD,.buf = &data, .len = 1}; - state->conf_probed = 0; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) { - printk("%s/dvb: could not read from tuner at addr: 0x%02x\n",dev->name, addr << 1); - return -EIO; - } - if ((data & 0x3c) == 0) { - dprintk("tda827x tuner found\n"); - state->conf_probed = 1; - } else { - dprintk("tda827xa tuner found\n"); - state->conf_probed = 2; - } + switch (state->config->antenna_switch) { case 0: break; case 1: dprintk("setting GPIO21 to 0 (TV antenna?)\n"); @@ -1001,14 +677,7 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; struct tda1004x_state *state = fe->demodulator_priv; - switch (state->conf_probed) { - case 1: philips_tda827xo_tuner_sleep(fe); - break; - case 2: philips_tda827xa_tuner_sleep(fe); - break; - default: dprintk("Huh? unknown tda827x version!\n"); - return -EIO; - } + switch (state->config->antenna_switch) { case 0: break; case 1: dprintk("setting GPIO21 to 1 (Radio antenna?)\n"); @@ -1021,20 +690,11 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) return 0; } -static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - switch (state->conf_probed) { - case 1: philips_tda827xo_pll_set(fe, params); - break; - case 2: philips_tda827xa_pll_set(fe, params); - break; - default: dprintk("Huh? unknown tda827x version!\n"); - return -EIO; - } - return 0; -} +static struct tda827x_config tda827x_cfg = { + .lna_gain = philips_tda827x_lna_gain, + .init = philips_tda827x_tuner_init, + .sleep = philips_tda827x_tuner_sleep +}; static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf, char *board_name) @@ -1043,9 +703,8 @@ static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config if (dev->dvb.frontend) { if (tda_conf->i2c_gate) dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_pll_set; + dvb_attach(tda827x_attach,dev->dvb.frontend, + tda_conf->tuner_address,&dev->i2c_adap,&tda827x_cfg); } philips_tda1004x_set_board_name(dev->dvb.frontend, board_name); } @@ -1223,6 +882,12 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) return 0; } +static struct tda827x_config ads_duo_cfg = { + .lna_gain = philips_tda827x_lna_gain, + .init = ads_duo_tuner_init, + .sleep = ads_duo_tuner_sleep +}; + static struct tda1004x_config ads_tech_duo_config = { .demod_address = 0x08, .invert = 1, @@ -1393,9 +1058,9 @@ static int dvb_init(struct saa7134_dev *dev) &ads_tech_duo_config, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_pll_set; + dvb_attach(tda827x_attach,dev->dvb.frontend, + ads_tech_duo_config.tuner_address, + &dev->i2c_adap,&ads_duo_cfg); if (dev->board == SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331) board_name = "DVB-T ADS DUO Cardbus PTV331"; else -- cgit v1.2.3 From 68717583557341874b2eea4dea36635256e932b6 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 27 Apr 2007 12:31:15 -0300 Subject: V4L/DVB (5319): Set tda827x to sleep mode after attach This change sets the tda827x to sleep mode right after attach in dvb mode. It is just to save power. For the same reason, the ADC of the tda10046 gets turned off in sleep mode. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 2 ++ drivers/media/dvb/frontends/tda827x.c | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index dbfc94a9c3f7..3de729b3b4bf 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -503,6 +503,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe) /* The PLLs need to be reprogrammed after sleep */ tda10046_init_plls(fe); + tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0); /* don't re-upload unless necessary */ if (tda1004x_check_upload_ok(state) == 0) @@ -1170,6 +1171,7 @@ static int tda1004x_sleep(struct dvb_frontend* fe) tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, (gpio_conf & 0x0f) ^ 0x0a); + tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0); tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; } diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index cff2d1fa4094..1fa58c5dac0f 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -426,6 +426,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, { struct tda827x_priv *priv = NULL; u8 data; + u8 sb_msg[] = { 0x30, 0xd0 }; struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = &data, .len = 1 }; dprintk("%s:\n", __FUNCTION__); @@ -446,15 +447,21 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, priv->i2c_addr = addr; priv->i2c_adap = i2c; priv->cfg = cfg; + + msg.flags = 0; + msg.buf = sb_msg; + msg.len = sizeof(sb_msg); + if ((data & 0x3c) == 0) { dprintk("tda827x tuner found\n"); memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); } else { dprintk("tda827xa tuner found\n"); memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); + sb_msg[1] = 0x90; } fe->tuner_priv = priv; - + i2c_transfer(i2c, &msg, 1); return fe; } EXPORT_SYMBOL(tda827x_attach); -- cgit v1.2.3 From 11f65106adb25a9ef5b6d8911267b2365c97a759 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 27 Apr 2007 12:31:15 -0300 Subject: V4L/DVB (5320): Filled in limiting values in tda827x.c The parameters for minimum and maximum frequency were missing. Also added mail addresses of the module authors. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda827x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 1fa58c5dac0f..edf7a0a902ba 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -399,6 +399,9 @@ static int tda827x_init(struct dvb_frontend *fe) static struct dvb_tuner_ops tda827xo_tuner_ops = { .info = { .name = "Philips TDA827X", + .frequency_min = 55000000, + .frequency_max = 860000000, + .frequency_step = 250000 }, .release = tda827x_release, .init = tda827x_init, @@ -411,6 +414,9 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = { static struct dvb_tuner_ops tda827xa_tuner_ops = { .info = { .name = "Philips TDA827XA", + .frequency_min = 44000000, + .frequency_max = 906000000, + .frequency_step = 62500 }, .release = tda827x_release, .init = tda827x_init, @@ -461,6 +467,8 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, sb_msg[1] = 0x90; } fe->tuner_priv = priv; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(i2c, &msg, 1); return fe; } @@ -470,8 +478,8 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("DVB TDA827x driver"); -MODULE_AUTHOR("Hartmut Hackmann"); -MODULE_AUTHOR("Michael Krufky"); +MODULE_AUTHOR("Hartmut Hackmann "); +MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); /* -- cgit v1.2.3 From 982dd1bdaab39185ccd55cafd3c099b7fee5f2dd Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 27 Apr 2007 12:31:27 -0300 Subject: V4L/DVB (5360): Dvb-pll: Use sizeof() to get name length Better to use sizeof() to get the size of the output buffer for the tuner name, instead of just hard coding 128. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 62de760c844f..43084bfc0f18 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -640,7 +640,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); - strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); + strncpy(fe->ops.tuner_ops.info.name, desc->name, + sizeof(fe->ops.tuner_ops.info.name)); fe->ops.tuner_ops.info.frequency_min = desc->min; fe->ops.tuner_ops.info.frequency_min = desc->max; -- cgit v1.2.3 From 9ab1ba38e6a25a480234f196aa26239e28ac2407 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 27 Apr 2007 12:31:28 -0300 Subject: V4L/DVB (5361): Dvb-pll: Fix Kconfig files and allow dvb-pll to be optional A number of drivers selected DVB_PLL when they did not need it, and some that did need it did not select it. The DVB_PLL option is given a name and help text, so that it will show up in the config menu. DVB_PLL support can be turned on if an out-of-tree driver needs it. The standard dvb fe customization support is added to dvb-pll.h. Since all modules which select DVB_PLL do so unconditionally, it is not possible to turn dvb-pll off when an enabled module selects it, unlike most of the other frontend/tuner drivers. This is because the users of dvb-pll have static references to dvb-pll symbols other than the attach function. If these references are removed, then dvb-pll will be disablable as the other frontend/tuner drivers are. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 4 ++++ drivers/media/dvb/frontends/Kconfig | 6 +++++- drivers/media/dvb/frontends/dvb-pll.h | 11 +++++++++++ drivers/media/dvb/pluto2/Kconfig | 1 - drivers/media/dvb/ttpci/Kconfig | 4 ---- drivers/media/dvb/ttusb-budget/Kconfig | 1 - 6 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 80f67a51b908..cb727b812692 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -33,6 +33,7 @@ config DVB_USB_A800 config DVB_USB_DIBUSB_MB tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" depends on DVB_USB + select DVB_PLL select DVB_DIB3000MB select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help @@ -88,6 +89,7 @@ config DVB_USB_DIB0700 config DVB_USB_UMT_010 tristate "HanfTek UMT-010 DVB-T USB2.0 support" depends on DVB_USB + select DVB_PLL select DVB_DIB3000MC select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help @@ -96,6 +98,7 @@ config DVB_USB_UMT_010 config DVB_USB_CXUSB tristate "Conexant USB2.0 hybrid reference design support" depends on DVB_USB + select DVB_PLL select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE @@ -140,6 +143,7 @@ config DVB_USB_AU6610 config DVB_USB_DIGITV tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" depends on DVB_USB + select DVB_PLL select DVB_NXT6000 if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a205e0b45a54..b255cbe3a99d 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -280,8 +280,12 @@ comment "Tuners/PLL support" depends on DVB_CORE config DVB_PLL - tristate + tristate "Generic I2C PLL based tuners" depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + This module driver a number of tuners based on PLL chips with a + common I2C interface. Say Y when you want to support these tuners. config DVB_TDA826X tristate "Philips TDA826X silicon tuner" diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 681186a5e5eb..a5bd928d4202 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -59,9 +59,20 @@ 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 */ +#if defined(CONFIG_DVB_PLL) || (defined(CONFIG_DVB_PLL_MODULE) && defined(MODULE)) extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); +#else +static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, + int pll_addr, + struct i2c_adapter *i2c, + struct dvb_pll_desc *desc) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif #endif diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig index 9b84b1bdc313..7d8e6e87bdbb 100644 --- a/drivers/media/dvb/pluto2/Kconfig +++ b/drivers/media/dvb/pluto2/Kconfig @@ -2,7 +2,6 @@ config DVB_PLUTO2 tristate "Pluto2 cards" depends on DVB_CORE && PCI && I2C select I2C_ALGOBIT - select DVB_PLL select DVB_TDA1004X help Support for PCI cards based on the Pluto2 FPGA like the Satelco diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index eec7ccf41f8b..3cd319ff0e68 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -3,7 +3,6 @@ config DVB_AV7110 depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select FW_LOADER if !DVB_AV7110_FIRMWARE select VIDEO_SAA7146_VV - select DVB_PLL select DVB_VES1820 if !DVB_FE_CUSTOMISE select DVB_VES1X93 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE @@ -62,7 +61,6 @@ config DVB_BUDGET tristate "Budget cards" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_PLL select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_VES1X93 if !DVB_FE_CUSTOMISE select DVB_VES1820 if !DVB_FE_CUSTOMISE @@ -87,7 +85,6 @@ config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_PLL select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE @@ -130,7 +127,6 @@ config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 - select DVB_PLL select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_VES1X93 if !DVB_FE_CUSTOMISE select DVB_TDA8083 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig index e78ea9227b0e..f546bccdb997 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/dvb/ttusb-budget/Kconfig @@ -1,7 +1,6 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" depends on DVB_CORE && USB && I2C - select DVB_PLL select DVB_CX22700 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_VES1820 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From 26aed92289ae8caffeedebb3f841a9e0371119a9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 27 Apr 2007 12:31:29 -0300 Subject: V4L/DVB (5362): Dvb-pll: add code for doing tuner initialization Some tuners need or benefit from initialization, to change certain settings from their power on default values. Typically, tuners with TUA603x PLLs can benefit from setting the AGC TOP value to something else. This patch includes code to set the AGC TOP to 103 dBuV for the Thomson DTT-761x tuners, which I have experimentally verified gives the best SNR readings, increasing SNR by about 0.19 dB over the default value. Other tuners can make use of this as well. For example, the separate LG TDVS-H06xF driver's only difference from dvb-pll is this same setting of AGC TOP value. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 39 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 40 insertions(+) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 43084bfc0f18..e7978442fbe9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -27,6 +27,17 @@ /* ----------------------------------------------------------- */ /* descriptions */ +/* Set AGC TOP value to 103 dBuV: + 0x80 = Control Byte + 0x40 = 250 uA charge pump (irrelevant) + 0x18 = Aux Byte to follow + 0x06 = 64.5 kHz divider (irrelevant) + 0x01 = Disable Vt (aka sleep) + + 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) + 0x50 = AGC Take over point = 103 dBuV */ +static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; + struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .name = "Thomson dtt7579", .min = 177000000, @@ -113,6 +124,7 @@ struct dvb_pll_desc dvb_pll_thomson_dtt761x = { .min = 57000000, .max = 863000000, .count = 3, + .initdata = tua603x_agc103, .entries = { { 147000000, 44000000, 62500, 0x8e, 0x39 }, { 417000000, 44000000, 62500, 0x8e, 0x3a }, @@ -599,6 +611,31 @@ static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int dvb_pll_init(struct dvb_frontend *fe) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + + if (priv->i2c == NULL) + return -EINVAL; + + if (priv->pll_desc->initdata) { + struct i2c_msg msg = { .flags = 0, + .addr = priv->pll_i2c_address, + .buf = priv->pll_desc->initdata + 1, + .len = priv->pll_desc->initdata[0] }; + + int result; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + return result; + } + return 0; + } + /* Shouldn't be called when initdata is NULL, maybe BUG()? */ + return -EINVAL; +} + static struct dvb_tuner_ops dvb_pll_tuner_ops = { .release = dvb_pll_release, .sleep = dvb_pll_sleep, @@ -644,6 +681,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, sizeof(fe->ops.tuner_ops.info.name)); fe->ops.tuner_ops.info.frequency_min = desc->min; fe->ops.tuner_ops.info.frequency_min = desc->max; + if (desc->initdata) + fe->ops.tuner_ops.init = dvb_pll_init; fe->tuner_priv = priv; return fe; diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index a5bd928d4202..bb79a78151f5 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -13,6 +13,7 @@ struct dvb_pll_desc { u32 min; u32 max; void (*setbw)(u8 *buf, u32 freq, int bandwidth); + u8 *initdata; int count; struct { u32 limit; -- cgit v1.2.3 From 6bdcc6e6dbab8daffd05e5026486f34ba41a6c72 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 27 Apr 2007 12:31:30 -0300 Subject: V4L/DVB (5363): Dvb: Remove lgh06xf driver The code of the dvb-pll driver and the lgh06xf driver is nearly identical. The main difference is that the lgh06xf driver would set the AGC TOP value on every tune call. The dvb-pll driver now has the ability to set the AGC TOP when the front-end device is opened, which is a better way to go about it. By using this ability of dvb-pll, the lgh06xf driver is made unnecessary. There is one other difference. dvb-pll will probe for the presence of an I2C pll chip by doing a one byte read, the lgh06xf driver did not do this. In some devices the PLL is not reachable over I2C at the timer the tuner is attached. Some more initialization, such as firmware loading, must take place first. None of the devices using a LG-H06xF should have this problem. Signed-off-by: Trent Piepho Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 1 - drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 3 +- drivers/media/dvb/bt8xx/Kconfig | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 3 +- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 2 +- drivers/media/dvb/dvb-usb/Kconfig | 1 - drivers/media/dvb/dvb-usb/cxusb.c | 4 +- drivers/media/dvb/frontends/Kconfig | 8 -- drivers/media/dvb/frontends/Makefile | 1 - drivers/media/dvb/frontends/dvb-pll.c | 1 + drivers/media/dvb/frontends/lgh06xf.c | 134 ------------------------------ drivers/media/dvb/frontends/lgh06xf.h | 35 -------- drivers/media/video/cx88/Kconfig | 1 - drivers/media/video/cx88/cx88-dvb.c | 11 +-- 14 files changed, 14 insertions(+), 193 deletions(-) delete mode 100644 drivers/media/dvb/frontends/lgh06xf.c delete mode 100644 drivers/media/dvb/frontends/lgh06xf.h (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 79875958930e..a0dcd59da76e 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -9,7 +9,6 @@ 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 752cf79c532f..b02c2fd65baa 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -14,7 +14,6 @@ #include "stv0297.h" #include "mt312.h" #include "lgdt330x.h" -#include "lgh06xf.h" #include "dvb-pll.h" /* lnb control */ @@ -507,7 +506,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; - dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); + dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_lg_tdvs_h06xf); 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 dd66b60fbc98..cfd6fb729a61 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -7,7 +7,7 @@ config DVB_BT8XX 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_PLL 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 58f69f6ae391..4f1c09bee538 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -610,7 +610,8 @@ 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) { - dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); + dvb_attach(dvb_pll_attach, card->fe, 0x61, + card->i2c_adapter, &dvb_pll_lg_tdvs_h06xf); 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 e75f4173c059..436880e68672 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,8 +37,8 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" -#include "lgh06xf.h" #include "zl10353.h" +#include "dvb-pll.h" struct dvb_bt8xx_card { struct mutex lock; diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index cb727b812692..8aa12722cbd6 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -101,7 +101,6 @@ config DVB_USB_CXUSB select DVB_PLL 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 127a94b9a1b5..bac2ae3b4a1f 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -27,7 +27,6 @@ #include "cx22702.h" #include "lgdt330x.h" -#include "lgh06xf.h" #include "mt352.h" #include "mt352_priv.h" #include "zl10353.h" @@ -388,7 +387,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); + dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap, + &dvb_pll_lg_tdvs_h06xf); return 0; } diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index b255cbe3a99d..10c4e7bdde78 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -315,14 +315,6 @@ 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 e038942a1d8a..905fcfc8732a 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -41,4 +41,3 @@ obj-$(CONFIG_DVB_TDA827X) += tda827x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o -obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index e7978442fbe9..abc08f0ae197 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -245,6 +245,7 @@ struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { .name = "LG TDVS-H06xF", .min = 54000000, .max = 863000000, + .initdata = tua603x_agc103, .count = 3, .entries = { { 165000000, 44000000, 62500, 0xce, 0x01 }, diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c deleted file mode 100644 index 2202d0cc878b..000000000000 --- a/drivers/media/dvb/frontends/lgh06xf.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 frequency; - int result; - - if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, - params->frequency, 0)) < 0) - return result; - else - frequency = result; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, result = %i)\n", - __FUNCTION__, buf[0], buf[1], result); - if (result < 0) - return result; - 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 ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, result = %i)\n", - __FUNCTION__, buf[0], buf[1], result); - if (result < 0) - return result; - else - return -EREMOTEIO; - } - - priv->frequency = frequency; - - 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 deleted file mode 100644 index 510b4bedfb24..000000000000 --- a/drivers/media/dvb/frontends/lgh06xf.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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_ */ diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index b2a66ba625f9..0f9d96963618 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -53,7 +53,6 @@ config VIDEO_CX88_DVB select DVB_OR51132 if !DVB_FE_CUSTOMISE select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 4f5560285770..07ec81f57cdd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -42,7 +42,6 @@ #include "cx22702.h" #include "or51132.h" #include "lgdt330x.h" -#include "lgh06xf.h" #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" @@ -631,8 +630,9 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_5_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(lgh06xf_attach, dev->dvb.frontend, - &dev->core->i2c_adap); + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_lg_tdvs_h06xf); } } break; @@ -650,8 +650,9 @@ static int dvb_register(struct cx8802_dev *dev) &pchdtv_hd5500, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(lgh06xf_attach, dev->dvb.frontend, - &dev->core->i2c_adap); + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_lg_tdvs_h06xf); } } break; -- cgit v1.2.3 From ede2200d79777d461cf2f0fd19cf7a17f633d3a4 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 27 Apr 2007 12:31:32 -0300 Subject: V4L/DVB (5369): Fixed 1 byte too short buffer in tda827x.c - The i2c data buffer in tda827xa_set_params was 1 byte too short - saa7134-dvb now gives an error mesage if tda827x could not be attached - coding style fix in tda1004x.c Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 3 ++- drivers/media/dvb/frontends/tda827x.c | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 14 ++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 3de729b3b4bf..f4882457d021 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -695,7 +695,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, // set frequency if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, fe_params); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } // Hardcoded to use auto as much as possible on the TDA10045 as it diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index edf7a0a902ba..8176a9b5898f 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -214,7 +214,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct tda827x_priv *priv = fe->tuner_priv; - u8 buf[10]; + u8 buf[11]; struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 659fd1b43c25..3887f04cc60a 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -692,8 +692,11 @@ static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config if (dev->dvb.frontend) { if (tda_conf->i2c_gate) dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - dvb_attach(tda827x_attach,dev->dvb.frontend, - tda_conf->tuner_address,&dev->i2c_adap,&tda827x_cfg); + if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address, + &dev->i2c_adap,&tda827x_cfg) == NULL) { + printk ("saa7134/dvb: no tda827x tuner found at addr: %02x\n", + tda_conf->tuner_address); + } } } @@ -1038,9 +1041,12 @@ static int dvb_init(struct saa7134_dev *dev) &ads_tech_duo_config, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_attach(tda827x_attach,dev->dvb.frontend, + if (dvb_attach(tda827x_attach,dev->dvb.frontend, ads_tech_duo_config.tuner_address, - &dev->i2c_adap,&ads_duo_cfg); + &dev->i2c_adap,&ads_duo_cfg) == NULL) { + printk ("saa7134/dvb: no tda827x tuner found at addr: %02x\n", + ads_tech_duo_config.tuner_address); + } } break; case SAA7134_BOARD_TEVION_DVBT_220RF: -- cgit v1.2.3 From d9e54324d03add27990ac27fcb34a1ae7a0f97ef Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Fri, 2 Mar 2007 19:42:21 -0300 Subject: V4L/DVB (5374): Or51132: refactor i2c code, improve error resilience The code the i2c transactions was leftover from the old V4L-based ATSC driver. It did too little with too much code. It is re-written to remove unnecessary parameters and be more efficient. A demod register can now be read with one function call, instead of repeating a dozen line block of code each time. There were msleep()'s, which appear to be unnecessary, spread around all the I2C transactions. These have been removed. Reading SNR used to take about 130 ms, now it's down to 1.8 ms. Reads from the demodulator's registers do not return correct results sometimes. Adding or removing the delays in the I2C transactions did not appear to effect the probability of failure. If anything, the transactions without delays were less likely to fail, but since far more transactions could be made per second the number of failures per hour was greater. To increase reliability, the SNR and get_params functions will now retry once if they get bad data back. This appears to have reduced the probability of failure to effectively zero. Some error messages are cleaned up or given KERN_* levels when they were missing. or51132_setmode() wasn't returning correct error codes, which is fixed as well. CC: Rusty Scott Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/or51132.c | 305 ++++++++++++++-------------------- 1 file changed, 127 insertions(+), 178 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 5a3a6e53cda2..4e0aca7c67aa 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -1,6 +1,9 @@ /* * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM * + * + * Copyright (C) 2007 Trent Piepho + * * Copyright (C) 2005 Kirk Lapray * * Based on code from Jack Kelliher (kelliher@xmission.com) @@ -69,46 +72,70 @@ struct or51132_state u32 current_frequency; }; -static int i2c_writebytes (struct or51132_state* state, u8 reg, u8 *buf, int len) + +/* Write buffer to demod */ +static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len) { int err; - struct i2c_msg msg; - msg.addr = reg; - msg.flags = 0; - msg.len = len; - msg.buf = buf; + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = 0, .buf = (u8*)buf, .len = len }; + /* msleep(20); */ /* doesn't appear to be necessary */ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "or51132: i2c_writebytes error (addr %02x, err == %i)\n", reg, err); + printk(KERN_WARNING "or51132: I2C write (addr 0x%02x len %d) error: %d\n", + msg.addr, msg.len, err); return -EREMOTEIO; } - return 0; } -static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len) +/* Write constant bytes, e.g. or51132_writebytes(state, 0x04, 0x42, 0x00); + Less code and more efficient that loading a buffer on the stack with + the bytes to send and then calling or51132_writebuf() on that. */ +#define or51132_writebytes(state, data...) \ + ({ const static u8 _data[] = {data}; \ + or51132_writebuf(state, _data, sizeof(_data)); }) + +/* Read data from demod into buffer. Returns 0 on success. */ +static int or51132_readbuf(struct or51132_state *state, u8 *buf, int len) { int err; - struct i2c_msg msg; - msg.addr = reg; - msg.flags = I2C_M_RD; - msg.len = len; - msg.buf = buf; + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = I2C_M_RD, .buf = buf, .len = len }; + /* msleep(20); */ /* doesn't appear to be necessary */ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "or51132: i2c_readbytes error (addr %02x, err == %i)\n", reg, err); + printk(KERN_WARNING "or51132: I2C read (addr 0x%02x len %d) error: %d\n", + msg.addr, msg.len, err); return -EREMOTEIO; } - return 0; } +/* Reads a 16-bit demod register. Returns <0 on error. */ +static int or51132_readreg(struct or51132_state *state, u8 reg) +{ + u8 buf[2] = { 0x04, reg }; + struct i2c_msg msg[2] = { + {.addr = state->config->demod_address, .flags = 0, + .buf = buf, .len = 2 }, + {.addr = state->config->demod_address, .flags = I2C_M_RD, + .buf = buf, .len = 2 }}; + int err; + + if ((err = i2c_transfer(state->i2c, msg, 2)) != 2) { + printk(KERN_WARNING "or51132: I2C error reading register %d: %d\n", + reg, err); + return -EREMOTEIO; + } + return le16_to_cpup((u16*)buf); +} + static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) { struct or51132_state* state = fe->demodulator_priv; - static u8 run_buf[] = {0x7F,0x01}; + const static u8 run_buf[] = {0x7F,0x01}; u8 rec_buf[8]; - u8 cmd_buf[3]; u32 firmwareAsize, firmwareBsize; int i,ret; @@ -121,30 +148,21 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware dprintk("FirmwareB is %i bytes\n",firmwareBsize); /* Upload firmware */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - &fw->data[8],firmwareAsize))) { + if ((ret = or51132_writebuf(state, &fw->data[8], firmwareAsize))) { printk(KERN_WARNING "or51132: load_firmware error 1\n"); return ret; } - msleep(1); /* 1ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - &fw->data[8+firmwareAsize],firmwareBsize))) { + if ((ret = or51132_writebuf(state, &fw->data[8+firmwareAsize], + firmwareBsize))) { printk(KERN_WARNING "or51132: load_firmware error 2\n"); return ret; } - msleep(1); /* 1ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - run_buf,2))) { + if ((ret = or51132_writebuf(state, run_buf, 2))) { printk(KERN_WARNING "or51132: load_firmware error 3\n"); return ret; } - - /* Wait at least 5 msec */ - msleep(20); /* 10ms */ - - if ((ret = i2c_writebytes(state,state->config->demod_address, - run_buf,2))) { + if ((ret = or51132_writebuf(state, run_buf, 2))) { printk(KERN_WARNING "or51132: load_firmware error 4\n"); return ret; } @@ -154,43 +172,25 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware /* Read back ucode version to besure we loaded correctly and are really up and running */ /* Get uCode version */ - cmd_buf[0] = 0x10; - cmd_buf[1] = 0x10; - cmd_buf[2] = 0x00; - msleep(20); /* 20ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - cmd_buf,3))) { + if ((ret = or51132_writebytes(state, 0x10, 0x10, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error a\n"); return ret; } - - cmd_buf[0] = 0x04; - cmd_buf[1] = 0x17; - msleep(20); /* 20ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - cmd_buf,2))) { + if ((ret = or51132_writebytes(state, 0x04, 0x17))) { printk(KERN_WARNING "or51132: load_firmware error b\n"); return ret; } - - cmd_buf[0] = 0x00; - cmd_buf[1] = 0x00; - msleep(20); /* 20ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - cmd_buf,2))) { + if ((ret = or51132_writebytes(state, 0x00, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error c\n"); return ret; } - - for(i=0;i<4;i++) { - msleep(20); /* 20ms */ + for (i=0;i<4;i++) { /* Once upon a time, this command might have had something to do with getting the firmware version, but it's not used anymore: {0x04,0x00,0x30,0x00,i+1} */ /* Read 8 bytes, two bytes at a time */ - if ((ret = i2c_readbytes(state,state->config->demod_address, - &rec_buf[i*2],2))) { + if ((ret = or51132_readbuf(state, &rec_buf[i*2], 2))) { printk(KERN_WARNING "or51132: load_firmware error d - %d\n",i); return ret; @@ -204,12 +204,7 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f, rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f); - cmd_buf[0] = 0x10; - cmd_buf[1] = 0x00; - cmd_buf[2] = 0x00; - msleep(20); /* 20ms */ - if ((ret = i2c_writebytes(state,state->config->demod_address, - cmd_buf,3))) { + if ((ret = or51132_writebytes(state, 0x10, 0x00, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error e\n"); return ret; } @@ -241,70 +236,55 @@ static int or51132_sleep(struct dvb_frontend* fe) static int or51132_setmode(struct dvb_frontend* fe) { struct or51132_state* state = fe->demodulator_priv; - unsigned char cmd_buf[3]; + u8 cmd_buf1[3] = {0x04, 0x01, 0x5f}; + u8 cmd_buf2[3] = {0x1c, 0x00, 0 }; dprintk("setmode %d\n",(int)state->current_modulation); - /* set operation mode in Receiver 1 register; */ - cmd_buf[0] = 0x04; - cmd_buf[1] = 0x01; + switch (state->current_modulation) { - case QAM_256: - case QAM_64: - case QAM_AUTO: - /* Auto-deinterleave; MPEG ser, MPEG2tr, phase noise-high*/ - cmd_buf[2] = 0x5F; - break; case VSB_8: - /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high*/ - cmd_buf[2] = 0x50; + /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high */ + cmd_buf1[2] = 0x50; + /* REC MODE inv IF spectrum, Normal */ + cmd_buf2[1] = 0x03; + /* Channel MODE ATSC/VSB8 */ + cmd_buf2[2] = 0x06; break; - default: - printk("setmode:Modulation set to unsupported value\n"); - }; - if (i2c_writebytes(state,state->config->demod_address, - cmd_buf,3)) { - printk(KERN_WARNING "or51132: set_mode error 1\n"); - return -1; - } - dprintk("or51132: set #1 to %02x\n", cmd_buf[2]); - - /* Set operation mode in Receiver 6 register */ - cmd_buf[0] = 0x1C; - switch (state->current_modulation) { + /* All QAM modes are: + Auto-deinterleave; MPEGser, MPEG2tr, phase noise-high + REC MODE Normal Carrier Lock */ case QAM_AUTO: - /* REC MODE Normal Carrier Lock */ - cmd_buf[1] = 0x00; /* Channel MODE Auto QAM64/256 */ - cmd_buf[2] = 0x4f; + cmd_buf2[2] = 0x4f; break; case QAM_256: - /* REC MODE Normal Carrier Lock */ - cmd_buf[1] = 0x00; /* Channel MODE QAM256 */ - cmd_buf[2] = 0x45; + cmd_buf2[2] = 0x45; break; case QAM_64: - /* REC MODE Normal Carrier Lock */ - cmd_buf[1] = 0x00; /* Channel MODE QAM64 */ - cmd_buf[2] = 0x43; - break; - case VSB_8: - /* REC MODE inv IF spectrum, Normal */ - cmd_buf[1] = 0x03; - /* Channel MODE ATSC/VSB8 */ - cmd_buf[2] = 0x06; + cmd_buf2[2] = 0x43; break; default: - printk("setmode: Modulation set to unsupported value\n"); - }; - msleep(20); /* 20ms */ - if (i2c_writebytes(state,state->config->demod_address, - cmd_buf,3)) { + printk(KERN_WARNING + "or51132: setmode: Modulation set to unsupported value (%d)\n", + state->current_modulation); + return -EINVAL; + } + + /* Set Receiver 1 register */ + if (or51132_writebuf(state, cmd_buf1, 3)) { + printk(KERN_WARNING "or51132: set_mode error 1\n"); + return -EREMOTEIO; + } + dprintk("set #1 to %02x\n", cmd_buf1[2]); + + /* Set operation mode in Receiver 6 register */ + if (or51132_writebuf(state, cmd_buf2, 3)) { printk(KERN_WARNING "or51132: set_mode error 2\n"); - return -1; + return -EREMOTEIO; } - dprintk("or51132: set #6 to 0x%02x%02x\n", cmd_buf[1], cmd_buf[2]); + dprintk("set #6 to 0x%02x%02x\n", cmd_buf2[1], cmd_buf2[2]); return 0; } @@ -401,28 +381,23 @@ static int or51132_get_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { struct or51132_state* state = fe->demodulator_priv; - u8 buf[2]; + int status; + int retry = 1; +start: /* Receiver Status */ - buf[0]=0x04; - buf[1]=0x00; - msleep(30); /* 30ms */ - if (i2c_writebytes(state,state->config->demod_address,buf,2)) { - printk(KERN_WARNING "or51132: get_parameters write error\n"); - return -EREMOTEIO; - } - msleep(30); /* 30ms */ - if (i2c_readbytes(state,state->config->demod_address,buf,2)) { - printk(KERN_WARNING "or51132: get_parameters read error\n"); + if ((status = or51132_readreg(state, 0x00)) < 0) { + printk(KERN_WARNING "or51132: get_parameters: error reading receiver status\n"); return -EREMOTEIO; } - switch(buf[0]) { + switch(status&0xff) { case 0x06: param->u.vsb.modulation = VSB_8; break; case 0x43: param->u.vsb.modulation = QAM_64; break; case 0x45: param->u.vsb.modulation = QAM_256; break; default: + if (retry--) goto start; printk(KERN_WARNING "or51132: unknown status 0x%02x\n", - buf[0]); + status&0xff); return -EREMOTEIO; } @@ -438,32 +413,21 @@ static int or51132_get_parameters(struct dvb_frontend* fe, static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct or51132_state* state = fe->demodulator_priv; - unsigned char rec_buf[2]; - unsigned char snd_buf[2]; - *status = 0; + int reg; /* Receiver Status */ - snd_buf[0]=0x04; - snd_buf[1]=0x00; - 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; - } - 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; - } - dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]); - - if (rec_buf[1] & 0x01) { /* Receiver Lock */ - *status |= FE_HAS_SIGNAL; - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_LOCK; + if ((reg = or51132_readreg(state, 0x00)) < 0) { + printk(KERN_WARNING "or51132: read_status: error reading receiver status: %d\n", reg); + *status = 0; + return -EREMOTEIO; } + dprintk("%s: read_status %04x\n", __FUNCTION__, reg); + + if (reg & 0x0100) /* Receiver Lock */ + *status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI| + FE_HAS_SYNC|FE_HAS_LOCK; + else + *status = 0; return 0; } @@ -506,47 +470,30 @@ static u32 calculate_snr(u32 mse, u32 c) static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) { struct or51132_state* state = fe->demodulator_priv; - 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: snr write error\n"); - return -EREMOTEIO; - } - msleep(30); /* 30ms */ - if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: snr read error\n"); + int noise, reg; + u32 c, usK = 0; + int retry = 1; + +start: + /* SNR after Equalizer */ + noise = or51132_readreg(state, 0x02); + if (noise < 0) { + printk(KERN_WARNING "or51132: read_snr: error reading equalizer\n"); return -EREMOTEIO; } - noise = rec_buf[0] | (rec_buf[1] << 8); - dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise); + dprintk("read_snr noise (%d)\n", noise); /* Read status, contains modulation type for QAM_AUTO and NTSC filter for VSB */ - snd_buf[0]=0x04; - snd_buf[1]=0x00; /* Status register */ - msleep(30); /* 30ms */ - if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - 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: status read error\n"); + reg = or51132_readreg(state, 0x00); + if (reg < 0) { + printk(KERN_WARNING "or51132: read_snr: error reading receiver status\n"); return -EREMOTEIO; } - usK = 0; - switch (rec_buf[0]) { + switch (reg&0xff) { case 0x06: - usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0; + if (reg & 0x1000) usK = 3 << 24; /* Fall through to QAM64 case */ case 0x43: c = 150204167; @@ -555,11 +502,12 @@ static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) c = 150290396; break; default: - printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]); + printk(KERN_WARNING "or51132: unknown status 0x%02x\n", reg&0xff); + if (retry--) goto start; return -EREMOTEIO; } dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, - rec_buf[0], rec_buf[1]&0x10?"n":"ff"); + reg&0xff, reg&0x1000?"n":"ff"); /* Calculate SNR using noise, c, and NTSC rejection correction */ state->snr = calculate_snr(noise, c) - usK; @@ -671,6 +619,7 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver"); MODULE_AUTHOR("Kirk Lapray"); +MODULE_AUTHOR("Trent Piepho"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(or51132_attach); -- cgit v1.2.3 From 0fd17d6da8154e1a6391440a268b0620ab339122 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 19 Mar 2007 02:23:59 -0300 Subject: V4L/DVB (5455): Dvb-pll: Adjust rounding to be consistent Some PLLs had one half the step size added to the offset, so that the divisor would be rounded to the nearest integer. Some didn't and so would always be rounded down. This makes dvb-pll round to the nearest when calculating the divisor, without the offset needing to be fudged. PLLs that had a fudged offset have the offset changed to be just the IF frequency. The satellite PLL dvb_pll_philips_sd1878_tda8261 was rounding up for some reason, and I've kept it that way. In addition, frequencies that were rounded to the nearest kHz are extended to full Hz resolution. One sixth MHz step sizes that were listed as 166,666 Hz are changed to 166,667 Hz, which is slightly closer. PLLs that were already rounding: dvb_pll_tda665x, offset was 36 1/6 (to nearest kHz) + step/2 dvb_pll_fmd1216me, offset was 36 1/8 (to two digits) + step/2 dvb_pll_thomson_fe6600, offset was 36 1/8 (to two digits) + step/2 dvb_pll_env57h1xd5, offset was 36 1/8 + step Note that the last PLL, dvb_pll_env57h1xd5, appears to have had a bug in the offset. Rather than adding stepsize/2, it was adding a full stepsize. The PLL definition originally came from the dibusb driver, which used 36 1/8 + step/2. The change to 36 1/8 + step was probably a mistake added when the tuner was converted to dvb-pll. Signed-off-by: Trent Piepho Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 148 +++++++++++++++++----------------- 1 file changed, 75 insertions(+), 73 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index abc08f0ae197..35973e7faac3 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -44,11 +44,11 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .max = 858000000, .count = 5, .entries = { - { 0, 36166667, 166666, 0xb4, 0x03 }, /* go sleep */ - { 443250000, 36166667, 166666, 0xb4, 0x02 }, - { 542000000, 36166667, 166666, 0xb4, 0x08 }, - { 771000000, 36166667, 166666, 0xbc, 0x08 }, - { 999999999, 36166667, 166666, 0xf4, 0x08 }, + { 0, 36166667, 166667, 0xb4, 0x03 }, /* go sleep */ + { 443250000, 36166667, 166667, 0xb4, 0x02 }, + { 542000000, 36166667, 166667, 0xb4, 0x08 }, + { 771000000, 36166667, 166667, 0xbc, 0x08 }, + { 999999999, 36166667, 166667, 0xf4, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt7579); @@ -79,12 +79,12 @@ struct dvb_pll_desc dvb_pll_thomson_dtt759x = { .setbw = thomson_dtt759x_bw, .count = 6, .entries = { - { 0, 36166667, 166666, 0x84, 0x03 }, - { 264000000, 36166667, 166666, 0xb4, 0x02 }, - { 470000000, 36166667, 166666, 0xbc, 0x02 }, - { 735000000, 36166667, 166666, 0xbc, 0x08 }, - { 835000000, 36166667, 166666, 0xf4, 0x08 }, - { 999999999, 36166667, 166666, 0xfc, 0x08 }, + { 0, 36166667, 166667, 0x84, 0x03 }, + { 264000000, 36166667, 166667, 0xb4, 0x02 }, + { 470000000, 36166667, 166667, 0xbc, 0x02 }, + { 735000000, 36166667, 166667, 0xbc, 0x08 }, + { 835000000, 36166667, 166667, 0xf4, 0x08 }, + { 999999999, 36166667, 166667, 0xfc, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt759x); @@ -95,12 +95,12 @@ struct dvb_pll_desc dvb_pll_lg_z201 = { .max = 862000000, .count = 6, .entries = { - { 0, 36166667, 166666, 0xbc, 0x03 }, - { 157500000, 36166667, 166666, 0xbc, 0x01 }, - { 443250000, 36166667, 166666, 0xbc, 0x02 }, - { 542000000, 36166667, 166666, 0xbc, 0x04 }, - { 830000000, 36166667, 166666, 0xf4, 0x04 }, - { 999999999, 36166667, 166666, 0xfc, 0x04 }, + { 0, 36166667, 166667, 0xbc, 0x03 }, + { 157500000, 36166667, 166667, 0xbc, 0x01 }, + { 443250000, 36166667, 166667, 0xbc, 0x02 }, + { 542000000, 36166667, 166667, 0xbc, 0x04 }, + { 830000000, 36166667, 166667, 0xf4, 0x04 }, + { 999999999, 36166667, 166667, 0xfc, 0x04 }, }, }; EXPORT_SYMBOL(dvb_pll_lg_z201); @@ -139,15 +139,15 @@ struct dvb_pll_desc dvb_pll_unknown_1 = { .max = 862000000, .count = 9, .entries = { - { 150000000, 36166667, 166666, 0xb4, 0x01 }, - { 173000000, 36166667, 166666, 0xbc, 0x01 }, - { 250000000, 36166667, 166666, 0xb4, 0x02 }, - { 400000000, 36166667, 166666, 0xbc, 0x02 }, - { 420000000, 36166667, 166666, 0xf4, 0x02 }, - { 470000000, 36166667, 166666, 0xfc, 0x02 }, - { 600000000, 36166667, 166666, 0xbc, 0x08 }, - { 730000000, 36166667, 166666, 0xf4, 0x08 }, - { 999999999, 36166667, 166666, 0xfc, 0x08 }, + { 150000000, 36166667, 166667, 0xb4, 0x01 }, + { 173000000, 36166667, 166667, 0xbc, 0x01 }, + { 250000000, 36166667, 166667, 0xb4, 0x02 }, + { 400000000, 36166667, 166667, 0xbc, 0x02 }, + { 420000000, 36166667, 166667, 0xf4, 0x02 }, + { 470000000, 36166667, 166667, 0xfc, 0x02 }, + { 600000000, 36166667, 166667, 0xbc, 0x08 }, + { 730000000, 36166667, 166667, 0xf4, 0x08 }, + { 999999999, 36166667, 166667, 0xfc, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_unknown_1); @@ -175,10 +175,10 @@ struct dvb_pll_desc dvb_pll_env57h1xd5 = { .max = 858000000, .count = 4, .entries = { - { 153000000, 36291666, 166666, 0xc2, 0x41 }, - { 470000000, 36291666, 166666, 0xc2, 0x42 }, - { 526000000, 36291666, 166666, 0xc2, 0x84 }, - { 999999999, 36291666, 166666, 0xc2, 0xa4 }, + { 153000000, 36125000, 166667, 0xc2, 0x41 }, + { 470000000, 36125000, 166667, 0xc2, 0x42 }, + { 526000000, 36125000, 166667, 0xc2, 0x84 }, + { 999999999, 36125000, 166667, 0xc2, 0xa4 }, }, }; EXPORT_SYMBOL(dvb_pll_env57h1xd5); @@ -199,18 +199,18 @@ struct dvb_pll_desc dvb_pll_tda665x = { .setbw = tda665x_bw, .count = 12, .entries = { - { 93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, - { 123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, - { 161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, - { 163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, - { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, - { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, - { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, - { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, + { 93834000, 36166667, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, + { 123834000, 36166667, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, + { 161000000, 36166667, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, + { 163834000, 36166667, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, + { 253834000, 36166667, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, + { 383834000, 36166667, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, + { 443834000, 36166667, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, + { 444000000, 36166667, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 583834000, 36166667, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, + { 793834000, 36166667, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, + { 444834000, 36166667, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 861000000, 36166667, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, } }; EXPORT_SYMBOL(dvb_pll_tda665x); @@ -271,13 +271,13 @@ struct dvb_pll_desc dvb_pll_fmd1216me = { .setbw = fmd1216me_bw, .count = 7, .entries = { - { 143870000, 36213333, 166667, 0xbc, 0x41 }, - { 158870000, 36213333, 166667, 0xf4, 0x41 }, - { 329870000, 36213333, 166667, 0xbc, 0x42 }, - { 441870000, 36213333, 166667, 0xf4, 0x42 }, - { 625870000, 36213333, 166667, 0xbc, 0x44 }, - { 803870000, 36213333, 166667, 0xf4, 0x44 }, - { 999999999, 36213333, 166667, 0xfc, 0x44 }, + { 143870000, 36125000, 166667, 0xbc, 0x41 }, + { 158870000, 36125000, 166667, 0xf4, 0x41 }, + { 329870000, 36125000, 166667, 0xbc, 0x42 }, + { 441870000, 36125000, 166667, 0xf4, 0x42 }, + { 625870000, 36125000, 166667, 0xbc, 0x44 }, + { 803870000, 36125000, 166667, 0xf4, 0x44 }, + { 999999999, 36125000, 166667, 0xfc, 0x44 }, } }; EXPORT_SYMBOL(dvb_pll_fmd1216me); @@ -348,12 +348,12 @@ struct dvb_pll_desc dvb_pll_samsung_tbmv = { .max = 860000000, .count = 6, .entries = { - { 172000000, 44000000, 166666, 0xb4, 0x01 }, - { 214000000, 44000000, 166666, 0xb4, 0x02 }, - { 467000000, 44000000, 166666, 0xbc, 0x02 }, - { 721000000, 44000000, 166666, 0xbc, 0x08 }, - { 841000000, 44000000, 166666, 0xf4, 0x08 }, - { 999999999, 44000000, 166666, 0xfc, 0x02 }, + { 172000000, 44000000, 166667, 0xb4, 0x01 }, + { 214000000, 44000000, 166667, 0xb4, 0x02 }, + { 467000000, 44000000, 166667, 0xbc, 0x02 }, + { 721000000, 44000000, 166667, 0xbc, 0x08 }, + { 841000000, 44000000, 166667, 0xf4, 0x08 }, + { 999999999, 44000000, 166667, 0xfc, 0x02 }, } }; EXPORT_SYMBOL(dvb_pll_samsung_tbmv); @@ -367,10 +367,11 @@ struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { .max = 2150000, .count = 4, .entries = { - { 1250000, 499, 500, 0xc4, 0x00}, - { 1550000, 499, 500, 0xc4, 0x40}, - { 2050000, 499, 500, 0xc4, 0x80}, - { 2150000, 499, 500, 0xc4, 0xc0}, + /* zero-IF, offset 249 is to round up */ + { 1250000, 249, 500, 0xc4, 0x00}, + { 1550000, 249, 500, 0xc4, 0x40}, + { 2050000, 249, 500, 0xc4, 0x80}, + { 2150000, 249, 500, 0xc4, 0xc0}, }, }; EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261); @@ -404,15 +405,15 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { .setbw = td1316_bw, .count = 9, .entries = { - { 93834000, 36166000, 166666, 0xca, 0x60}, - { 123834000, 36166000, 166666, 0xca, 0xa0}, - { 163834000, 36166000, 166666, 0xca, 0xc0}, - { 253834000, 36166000, 166666, 0xca, 0x60}, - { 383834000, 36166000, 166666, 0xca, 0xa0}, - { 443834000, 36166000, 166666, 0xca, 0xc0}, - { 583834000, 36166000, 166666, 0xca, 0x60}, - { 793834000, 36166000, 166666, 0xca, 0xa0}, - { 858834000, 36166000, 166666, 0xca, 0xe0}, + { 93834000, 36166667, 166667, 0xca, 0x60}, + { 123834000, 36166667, 166667, 0xca, 0xa0}, + { 163834000, 36166667, 166667, 0xca, 0xc0}, + { 253834000, 36166667, 166667, 0xca, 0x60}, + { 383834000, 36166667, 166667, 0xca, 0xa0}, + { 443834000, 36166667, 166667, 0xca, 0xc0}, + { 583834000, 36166667, 166667, 0xca, 0x60}, + { 793834000, 36166667, 166667, 0xca, 0xa0}, + { 858834000, 36166667, 166667, 0xca, 0xe0}, }, }; EXPORT_SYMBOL(dvb_pll_philips_td1316); @@ -424,10 +425,10 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = { .max = 858000000, .count = 4, .entries = { - { 250000000, 36213333, 166667, 0xb4, 0x12 }, - { 455000000, 36213333, 166667, 0xfe, 0x11 }, - { 775500000, 36213333, 166667, 0xbc, 0x18 }, - { 999999999, 36213333, 166667, 0xf4, 0x18 }, + { 250000000, 36125000, 166667, 0xb4, 0x12 }, + { 455000000, 36125000, 166667, 0xfe, 0x11 }, + { 775500000, 36125000, 166667, 0xbc, 0x18 }, + { 999999999, 36125000, 166667, 0xf4, 0x18 }, } }; EXPORT_SYMBOL(dvb_pll_thomson_fe6600); @@ -472,7 +473,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, if (i == desc->count) return -EINVAL; - div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize; + div = (freq + desc->entries[i].offset + desc->entries[i].stepsize/2) / + desc->entries[i].stepsize; buf[0] = div >> 8; buf[1] = div & 0xff; buf[2] = desc->entries[i].config; -- cgit v1.2.3 From df78cb0a1870703b7622fe8c63e5bcb6563197fd Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 19 Mar 2007 02:24:04 -0300 Subject: V4L/DVB (5456): Dvb-pll: Move IF frequency from per-band data to per-tuner data The IF frequency was specified for each band, but it's not something that changes from band to band. None of the tuner definitions had a different IF frequency (called offset) from one band to another. Acked-by: Michael Krufky Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 227 ++++++++++++++++++---------------- drivers/media/dvb/frontends/dvb-pll.h | 2 +- 2 files changed, 124 insertions(+), 105 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 35973e7faac3..c6651a12eb67 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -42,13 +42,14 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .name = "Thomson dtt7579", .min = 177000000, .max = 858000000, + .iffreq= 36166667, .count = 5, .entries = { - { 0, 36166667, 166667, 0xb4, 0x03 }, /* go sleep */ - { 443250000, 36166667, 166667, 0xb4, 0x02 }, - { 542000000, 36166667, 166667, 0xb4, 0x08 }, - { 771000000, 36166667, 166667, 0xbc, 0x08 }, - { 999999999, 36166667, 166667, 0xf4, 0x08 }, + { 0, 166667, 0xb4, 0x03 }, /* go sleep */ + { 443250000, 166667, 0xb4, 0x02 }, + { 542000000, 166667, 0xb4, 0x08 }, + { 771000000, 166667, 0xbc, 0x08 }, + { 999999999, 166667, 0xf4, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt7579); @@ -57,11 +58,12 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7610 = { .name = "Thomson dtt7610", .min = 44000000, .max = 958000000, + .iffreq= 44000000, .count = 3, .entries = { - { 157250000, 44000000, 62500, 0x8e, 0x39 }, - { 454000000, 44000000, 62500, 0x8e, 0x3a }, - { 999999999, 44000000, 62500, 0x8e, 0x3c }, + { 157250000, 62500, 0x8e, 0x39 }, + { 454000000, 62500, 0x8e, 0x3a }, + { 999999999, 62500, 0x8e, 0x3c }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt7610); @@ -77,14 +79,15 @@ struct dvb_pll_desc dvb_pll_thomson_dtt759x = { .min = 177000000, .max = 896000000, .setbw = thomson_dtt759x_bw, + .iffreq= 36166667, .count = 6, .entries = { - { 0, 36166667, 166667, 0x84, 0x03 }, - { 264000000, 36166667, 166667, 0xb4, 0x02 }, - { 470000000, 36166667, 166667, 0xbc, 0x02 }, - { 735000000, 36166667, 166667, 0xbc, 0x08 }, - { 835000000, 36166667, 166667, 0xf4, 0x08 }, - { 999999999, 36166667, 166667, 0xfc, 0x08 }, + { 0, 166667, 0x84, 0x03 }, + { 264000000, 166667, 0xb4, 0x02 }, + { 470000000, 166667, 0xbc, 0x02 }, + { 735000000, 166667, 0xbc, 0x08 }, + { 835000000, 166667, 0xf4, 0x08 }, + { 999999999, 166667, 0xfc, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt759x); @@ -93,14 +96,15 @@ struct dvb_pll_desc dvb_pll_lg_z201 = { .name = "LG z201", .min = 174000000, .max = 862000000, + .iffreq= 36166667, .count = 6, .entries = { - { 0, 36166667, 166667, 0xbc, 0x03 }, - { 157500000, 36166667, 166667, 0xbc, 0x01 }, - { 443250000, 36166667, 166667, 0xbc, 0x02 }, - { 542000000, 36166667, 166667, 0xbc, 0x04 }, - { 830000000, 36166667, 166667, 0xf4, 0x04 }, - { 999999999, 36166667, 166667, 0xfc, 0x04 }, + { 0, 166667, 0xbc, 0x03 }, + { 157500000, 166667, 0xbc, 0x01 }, + { 443250000, 166667, 0xbc, 0x02 }, + { 542000000, 166667, 0xbc, 0x04 }, + { 830000000, 166667, 0xf4, 0x04 }, + { 999999999, 166667, 0xfc, 0x04 }, }, }; EXPORT_SYMBOL(dvb_pll_lg_z201); @@ -109,11 +113,12 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = { .name = "Microtune 4042 FI5", .min = 57000000, .max = 858000000, + .iffreq= 44000000, .count = 3, .entries = { - { 162000000, 44000000, 62500, 0x8e, 0xa1 }, - { 457000000, 44000000, 62500, 0x8e, 0x91 }, - { 999999999, 44000000, 62500, 0x8e, 0x31 }, + { 162000000, 62500, 0x8e, 0xa1 }, + { 457000000, 62500, 0x8e, 0x91 }, + { 999999999, 62500, 0x8e, 0x31 }, }, }; EXPORT_SYMBOL(dvb_pll_microtune_4042); @@ -123,12 +128,13 @@ struct dvb_pll_desc dvb_pll_thomson_dtt761x = { .name = "Thomson dtt761x", .min = 57000000, .max = 863000000, + .iffreq= 44000000, .count = 3, .initdata = tua603x_agc103, .entries = { - { 147000000, 44000000, 62500, 0x8e, 0x39 }, - { 417000000, 44000000, 62500, 0x8e, 0x3a }, - { 999999999, 44000000, 62500, 0x8e, 0x3c }, + { 147000000, 62500, 0x8e, 0x39 }, + { 417000000, 62500, 0x8e, 0x3a }, + { 999999999, 62500, 0x8e, 0x3c }, }, }; EXPORT_SYMBOL(dvb_pll_thomson_dtt761x); @@ -137,17 +143,18 @@ struct dvb_pll_desc dvb_pll_unknown_1 = { .name = "unknown 1", /* used by dntv live dvb-t */ .min = 174000000, .max = 862000000, + .iffreq= 36166667, .count = 9, .entries = { - { 150000000, 36166667, 166667, 0xb4, 0x01 }, - { 173000000, 36166667, 166667, 0xbc, 0x01 }, - { 250000000, 36166667, 166667, 0xb4, 0x02 }, - { 400000000, 36166667, 166667, 0xbc, 0x02 }, - { 420000000, 36166667, 166667, 0xf4, 0x02 }, - { 470000000, 36166667, 166667, 0xfc, 0x02 }, - { 600000000, 36166667, 166667, 0xbc, 0x08 }, - { 730000000, 36166667, 166667, 0xf4, 0x08 }, - { 999999999, 36166667, 166667, 0xfc, 0x08 }, + { 150000000, 166667, 0xb4, 0x01 }, + { 173000000, 166667, 0xbc, 0x01 }, + { 250000000, 166667, 0xb4, 0x02 }, + { 400000000, 166667, 0xbc, 0x02 }, + { 420000000, 166667, 0xf4, 0x02 }, + { 470000000, 166667, 0xfc, 0x02 }, + { 600000000, 166667, 0xbc, 0x08 }, + { 730000000, 166667, 0xf4, 0x08 }, + { 999999999, 166667, 0xfc, 0x08 }, }, }; EXPORT_SYMBOL(dvb_pll_unknown_1); @@ -159,11 +166,12 @@ struct dvb_pll_desc dvb_pll_tua6010xs = { .name = "Infineon TUA6010XS", .min = 44250000, .max = 858000000, + .iffreq= 36125000, .count = 3, .entries = { - { 115750000, 36125000, 62500, 0x8e, 0x03 }, - { 403250000, 36125000, 62500, 0x8e, 0x06 }, - { 999999999, 36125000, 62500, 0x8e, 0x85 }, + { 115750000, 62500, 0x8e, 0x03 }, + { 403250000, 62500, 0x8e, 0x06 }, + { 999999999, 62500, 0x8e, 0x85 }, }, }; EXPORT_SYMBOL(dvb_pll_tua6010xs); @@ -173,12 +181,13 @@ struct dvb_pll_desc dvb_pll_env57h1xd5 = { .name = "Panasonic ENV57H1XD5", .min = 44250000, .max = 858000000, + .iffreq= 36125000, .count = 4, .entries = { - { 153000000, 36125000, 166667, 0xc2, 0x41 }, - { 470000000, 36125000, 166667, 0xc2, 0x42 }, - { 526000000, 36125000, 166667, 0xc2, 0x84 }, - { 999999999, 36125000, 166667, 0xc2, 0xa4 }, + { 153000000, 166667, 0xc2, 0x41 }, + { 470000000, 166667, 0xc2, 0x42 }, + { 526000000, 166667, 0xc2, 0x84 }, + { 999999999, 166667, 0xc2, 0xa4 }, }, }; EXPORT_SYMBOL(dvb_pll_env57h1xd5); @@ -197,20 +206,21 @@ struct dvb_pll_desc dvb_pll_tda665x = { .min = 44250000, .max = 858000000, .setbw = tda665x_bw, + .iffreq= 36166667, .count = 12, .entries = { - { 93834000, 36166667, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, - { 123834000, 36166667, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, - { 161000000, 36166667, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, - { 163834000, 36166667, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 253834000, 36166667, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, - { 383834000, 36166667, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, - { 443834000, 36166667, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 444000000, 36166667, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 583834000, 36166667, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, - { 793834000, 36166667, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, - { 444834000, 36166667, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 861000000, 36166667, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, + { 93834000, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, + { 123834000, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, + { 161000000, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, + { 163834000, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, + { 253834000, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, + { 383834000, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, + { 443834000, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, + { 444000000, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 583834000, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, + { 793834000, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, + { 444834000, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 861000000, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, } }; EXPORT_SYMBOL(dvb_pll_tda665x); @@ -228,12 +238,13 @@ struct dvb_pll_desc dvb_pll_tua6034 = { .name = "Infineon TUA6034", .min = 44250000, .max = 858000000, + .iffreq= 36166667, .count = 3, .setbw = tua6034_bw, .entries = { - { 174500000, 36166667, 62500, 0xce, 0x01 }, - { 230000000, 36166667, 62500, 0xce, 0x02 }, - { 999999999, 36166667, 62500, 0xce, 0x04 }, + { 174500000, 62500, 0xce, 0x01 }, + { 230000000, 62500, 0xce, 0x02 }, + { 999999999, 62500, 0xce, 0x04 }, }, }; EXPORT_SYMBOL(dvb_pll_tua6034); @@ -245,12 +256,13 @@ struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { .name = "LG TDVS-H06xF", .min = 54000000, .max = 863000000, + .iffreq= 44000000, .initdata = tua603x_agc103, .count = 3, .entries = { - { 165000000, 44000000, 62500, 0xce, 0x01 }, - { 450000000, 44000000, 62500, 0xce, 0x02 }, - { 999999999, 44000000, 62500, 0xce, 0x04 }, + { 165000000, 62500, 0xce, 0x01 }, + { 450000000, 62500, 0xce, 0x02 }, + { 999999999, 62500, 0xce, 0x04 }, }, }; EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf); @@ -268,16 +280,17 @@ struct dvb_pll_desc dvb_pll_fmd1216me = { .name = "Philips FMD1216ME", .min = 50870000, .max = 858000000, + .iffreq= 36125000, .setbw = fmd1216me_bw, .count = 7, .entries = { - { 143870000, 36125000, 166667, 0xbc, 0x41 }, - { 158870000, 36125000, 166667, 0xf4, 0x41 }, - { 329870000, 36125000, 166667, 0xbc, 0x42 }, - { 441870000, 36125000, 166667, 0xf4, 0x42 }, - { 625870000, 36125000, 166667, 0xbc, 0x44 }, - { 803870000, 36125000, 166667, 0xf4, 0x44 }, - { 999999999, 36125000, 166667, 0xfc, 0x44 }, + { 143870000, 166667, 0xbc, 0x41 }, + { 158870000, 166667, 0xf4, 0x41 }, + { 329870000, 166667, 0xbc, 0x42 }, + { 441870000, 166667, 0xf4, 0x42 }, + { 625870000, 166667, 0xbc, 0x44 }, + { 803870000, 166667, 0xf4, 0x44 }, + { 999999999, 166667, 0xfc, 0x44 }, } }; EXPORT_SYMBOL(dvb_pll_fmd1216me); @@ -295,13 +308,14 @@ struct dvb_pll_desc dvb_pll_tded4 = { .name = "ALPS TDED4", .min = 47000000, .max = 863000000, + .iffreq= 36166667, .setbw = tded4_bw, .count = 4, .entries = { - { 153000000, 36166667, 166667, 0x85, 0x01 }, - { 470000000, 36166667, 166667, 0x85, 0x02 }, - { 823000000, 36166667, 166667, 0x85, 0x08 }, - { 999999999, 36166667, 166667, 0x85, 0x88 }, + { 153000000, 166667, 0x85, 0x01 }, + { 470000000, 166667, 0x85, 0x02 }, + { 823000000, 166667, 0x85, 0x08 }, + { 999999999, 166667, 0x85, 0x88 }, } }; EXPORT_SYMBOL(dvb_pll_tded4); @@ -313,12 +327,13 @@ struct dvb_pll_desc dvb_pll_tdhu2 = { .name = "ALPS TDHU2", .min = 54000000, .max = 864000000, + .iffreq= 44000000, .count = 4, .entries = { - { 162000000, 44000000, 62500, 0x85, 0x01 }, - { 426000000, 44000000, 62500, 0x85, 0x02 }, - { 782000000, 44000000, 62500, 0x85, 0x08 }, - { 999999999, 44000000, 62500, 0x85, 0x88 }, + { 162000000, 62500, 0x85, 0x01 }, + { 426000000, 62500, 0x85, 0x02 }, + { 782000000, 62500, 0x85, 0x08 }, + { 999999999, 62500, 0x85, 0x88 }, } }; EXPORT_SYMBOL(dvb_pll_tdhu2); @@ -330,11 +345,12 @@ struct dvb_pll_desc dvb_pll_tuv1236d = { .name = "Philips TUV1236D", .min = 54000000, .max = 864000000, + .iffreq= 44000000, .count = 3, .entries = { - { 157250000, 44000000, 62500, 0xc6, 0x41 }, - { 454000000, 44000000, 62500, 0xc6, 0x42 }, - { 999999999, 44000000, 62500, 0xc6, 0x44 }, + { 157250000, 62500, 0xc6, 0x41 }, + { 454000000, 62500, 0xc6, 0x42 }, + { 999999999, 62500, 0xc6, 0x44 }, }, }; EXPORT_SYMBOL(dvb_pll_tuv1236d); @@ -346,14 +362,15 @@ struct dvb_pll_desc dvb_pll_samsung_tbmv = { .name = "Samsung TBMV30111IN / TBMV30712IN1", .min = 54000000, .max = 860000000, + .iffreq= 44000000, .count = 6, .entries = { - { 172000000, 44000000, 166667, 0xb4, 0x01 }, - { 214000000, 44000000, 166667, 0xb4, 0x02 }, - { 467000000, 44000000, 166667, 0xbc, 0x02 }, - { 721000000, 44000000, 166667, 0xbc, 0x08 }, - { 841000000, 44000000, 166667, 0xf4, 0x08 }, - { 999999999, 44000000, 166667, 0xfc, 0x02 }, + { 172000000, 166667, 0xb4, 0x01 }, + { 214000000, 166667, 0xb4, 0x02 }, + { 467000000, 166667, 0xbc, 0x02 }, + { 721000000, 166667, 0xbc, 0x08 }, + { 841000000, 166667, 0xf4, 0x08 }, + { 999999999, 166667, 0xfc, 0x02 }, } }; EXPORT_SYMBOL(dvb_pll_samsung_tbmv); @@ -365,13 +382,13 @@ struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { .name = "Philips SD1878", .min = 950000, .max = 2150000, + .iffreq= 249, /* zero-IF, offset 249 is to round up */ .count = 4, .entries = { - /* zero-IF, offset 249 is to round up */ - { 1250000, 249, 500, 0xc4, 0x00}, - { 1550000, 249, 500, 0xc4, 0x40}, - { 2050000, 249, 500, 0xc4, 0x80}, - { 2150000, 249, 500, 0xc4, 0xc0}, + { 1250000, 500, 0xc4, 0x00}, + { 1550000, 500, 0xc4, 0x40}, + { 2050000, 500, 0xc4, 0x80}, + { 2150000, 500, 0xc4, 0xc0}, }, }; EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261); @@ -402,18 +419,19 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { .name = "Philips TD1316", .min = 87000000, .max = 895000000, + .iffreq= 36166667, .setbw = td1316_bw, .count = 9, .entries = { - { 93834000, 36166667, 166667, 0xca, 0x60}, - { 123834000, 36166667, 166667, 0xca, 0xa0}, - { 163834000, 36166667, 166667, 0xca, 0xc0}, - { 253834000, 36166667, 166667, 0xca, 0x60}, - { 383834000, 36166667, 166667, 0xca, 0xa0}, - { 443834000, 36166667, 166667, 0xca, 0xc0}, - { 583834000, 36166667, 166667, 0xca, 0x60}, - { 793834000, 36166667, 166667, 0xca, 0xa0}, - { 858834000, 36166667, 166667, 0xca, 0xe0}, + { 93834000, 166667, 0xca, 0x60}, + { 123834000, 166667, 0xca, 0xa0}, + { 163834000, 166667, 0xca, 0xc0}, + { 253834000, 166667, 0xca, 0x60}, + { 383834000, 166667, 0xca, 0xa0}, + { 443834000, 166667, 0xca, 0xc0}, + { 583834000, 166667, 0xca, 0x60}, + { 793834000, 166667, 0xca, 0xa0}, + { 858834000, 166667, 0xca, 0xe0}, }, }; EXPORT_SYMBOL(dvb_pll_philips_td1316); @@ -423,12 +441,13 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = { .name = "Thomson FE6600", .min = 44250000, .max = 858000000, + .iffreq= 36125000, .count = 4, .entries = { - { 250000000, 36125000, 166667, 0xb4, 0x12 }, - { 455000000, 36125000, 166667, 0xfe, 0x11 }, - { 775500000, 36125000, 166667, 0xbc, 0x18 }, - { 999999999, 36125000, 166667, 0xf4, 0x18 }, + { 250000000, 166667, 0xb4, 0x12 }, + { 455000000, 166667, 0xfe, 0x11 }, + { 775500000, 166667, 0xbc, 0x18 }, + { 999999999, 166667, 0xf4, 0x18 }, } }; EXPORT_SYMBOL(dvb_pll_thomson_fe6600); @@ -473,7 +492,7 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, if (i == desc->count) return -EINVAL; - div = (freq + desc->entries[i].offset + desc->entries[i].stepsize/2) / + div = (freq + desc->iffreq + desc->entries[i].stepsize/2) / desc->entries[i].stepsize; buf[0] = div >> 8; buf[1] = div & 0xff; @@ -488,7 +507,7 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, desc->name, div, buf[0], buf[1], buf[2], buf[3]); // calculate the frequency we set it to - return (div * desc->entries[i].stepsize) - desc->entries[i].offset; + return (div * desc->entries[i].stepsize) - desc->iffreq; } EXPORT_SYMBOL(dvb_pll_configure); diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index bb79a78151f5..40b2dca1bd51 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -12,12 +12,12 @@ struct dvb_pll_desc { char *name; u32 min; u32 max; + u32 iffreq; void (*setbw)(u8 *buf, u32 freq, int bandwidth); u8 *initdata; int count; struct { u32 limit; - u32 offset; u32 stepsize; u8 config; u8 cb; -- cgit v1.2.3 From d519dcf61ed55bcfb947a31122cea068a73ad974 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 19 Mar 2007 02:24:09 -0300 Subject: V4L/DVB (5457): Dvb-pll: Replace sleep function with a more capable one The dvb-pll sleep function could only send a 2-byte sequence to the PLL. This isn't enough in some cases, for example fmd1216me will need to send a 4-byte command to set both BB and AB to the correct values. Instead of using a fake band with a frequency of 0 to store the sleep data (which has room for only two bytes), the new sleep function works like the init function. A new pointer is added to the pll description, and when non-NULL points to a buffer with the length and data to send. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 55 ++++++++++++++++------------------- drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 26 insertions(+), 30 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index c6651a12eb67..d29e0ae23ee6 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -43,9 +43,9 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .min = 177000000, .max = 858000000, .iffreq= 36166667, - .count = 5, + .sleepdata = (u8[]){ 2, 0xb4, 0x03 }, + .count = 4, .entries = { - { 0, 166667, 0xb4, 0x03 }, /* go sleep */ { 443250000, 166667, 0xb4, 0x02 }, { 542000000, 166667, 0xb4, 0x08 }, { 771000000, 166667, 0xbc, 0x08 }, @@ -80,9 +80,9 @@ struct dvb_pll_desc dvb_pll_thomson_dtt759x = { .max = 896000000, .setbw = thomson_dtt759x_bw, .iffreq= 36166667, - .count = 6, + .sleepdata = (u8[]){ 2, 0x84, 0x03 }, + .count = 5, .entries = { - { 0, 166667, 0x84, 0x03 }, { 264000000, 166667, 0xb4, 0x02 }, { 470000000, 166667, 0xbc, 0x02 }, { 735000000, 166667, 0xbc, 0x08 }, @@ -97,9 +97,9 @@ struct dvb_pll_desc dvb_pll_lg_z201 = { .min = 174000000, .max = 862000000, .iffreq= 36166667, - .count = 6, + .sleepdata = (u8[]){ 2, 0xbc, 0x03 }, + .count = 5, .entries = { - { 0, 166667, 0xbc, 0x03 }, { 157500000, 166667, 0xbc, 0x01 }, { 443250000, 166667, 0xbc, 0x02 }, { 542000000, 166667, 0xbc, 0x04 }, @@ -521,35 +521,27 @@ static int dvb_pll_release(struct dvb_frontend *fe) 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) }; - int i; - int result; if (priv->i2c == NULL) return -EINVAL; - for (i = 0; i < priv->pll_desc->count; i++) { - if (priv->pll_desc->entries[i].limit == 0) - break; - } - if (i == priv->pll_desc->count) - return 0; + if (priv->pll_desc->sleepdata) { + struct i2c_msg msg = { .flags = 0, + .addr = priv->pll_i2c_address, + .buf = priv->pll_desc->sleepdata + 1, + .len = priv->pll_desc->sleepdata[0] }; - buf[0] = 0; - buf[1] = 0; - buf[2] = priv->pll_desc->entries[i].config; - buf[3] = priv->pll_desc->entries[i].cb; + int result; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { - return result; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + return result; + } + return 0; } - - return 0; + /* Shouldn't be called when initdata is NULL, maybe BUG()? */ + return -EINVAL; } static int dvb_pll_set_params(struct dvb_frontend *fe, @@ -661,6 +653,7 @@ static int dvb_pll_init(struct dvb_frontend *fe) static struct dvb_tuner_ops dvb_pll_tuner_ops = { .release = dvb_pll_release, .sleep = dvb_pll_sleep, + .init = dvb_pll_init, .set_params = dvb_pll_set_params, .calc_regs = dvb_pll_calc_regs, .get_frequency = dvb_pll_get_frequency, @@ -703,8 +696,10 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, sizeof(fe->ops.tuner_ops.info.name)); fe->ops.tuner_ops.info.frequency_min = desc->min; fe->ops.tuner_ops.info.frequency_min = desc->max; - if (desc->initdata) - fe->ops.tuner_ops.init = dvb_pll_init; + if (!desc->initdata) + fe->ops.tuner_ops.init = NULL; + if (!desc->sleepdata) + fe->ops.tuner_ops.sleep = NULL; fe->tuner_priv = priv; return fe; diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 40b2dca1bd51..d13a1c01c541 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -15,6 +15,7 @@ struct dvb_pll_desc { u32 iffreq; void (*setbw)(u8 *buf, u32 freq, int bandwidth); u8 *initdata; + u8 *sleepdata; int count; struct { u32 limit; -- cgit v1.2.3 From 08cdf94c076121cd0214ef9ea18ae3fbb9ace684 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Sun, 18 Mar 2007 19:23:20 -0300 Subject: V4L/DVB (5458): Tda1004x: add ts_mode option to config struct The struct tda1004x_config has a new entry: .ts_mode Possible values are TDA10046_TS_PARALLEL or TDA10046_TS_SERIAL There always is only one interface active, default is parallel. Signed-off-by: Hartmut Hackmann Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 11 +++++++++-- drivers/media/dvb/frontends/tda1004x.h | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index f4882457d021..33a84372c9e6 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -657,8 +657,16 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities break; } + if (state->config->ts_mode == 0) { + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40); + tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); + } else { + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80); + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10, + state->config->invert_oclk << 4); + } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); - tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x79); // Turn IF AGC output on + tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } @@ -668,7 +676,6 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes - tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); return 0; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 6badc81d4c33..abae84350142 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -61,6 +61,11 @@ enum tda10046_if { TDA10046_FREQ_052, /* low IF, 5.1667 MHZ for tda9889 */ }; +enum tda10046_tsout { + TDA10046_TS_PARALLEL = 0x00, /* parallel transport stream, default */ + TDA10046_TS_SERIAL = 0x01, /* serial transport stream */ +}; + struct tda1004x_config { /* the demodulator's i2c address */ @@ -72,6 +77,9 @@ struct tda1004x_config /* Does the OCLK signal need inverted? */ u8 invert_oclk; + /* parallel or serial transport stream */ + enum tda10046_tsout ts_mode; + /* Xtal frequency, 4 or 16MHz*/ enum tda10046_xtal xtal_freq; -- cgit v1.2.3 From 9971f4f1d3d71a5b6654ba226976ba82d2e047a4 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 23 Mar 2007 21:00:07 -0300 Subject: V4L/DVB (5485): Tda827x: delayed probing of tuner version When the tuner is attached, the tda10046 is not initilized yet, so it is searching for its firmware. If the tuner is attached to the tda10046 silent i2c port, a bus collision can occur. Now the version is probed during the first init or sleep call. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda827x.c | 85 +++++++++++++++++++------------ drivers/media/video/saa7134/saa7134-dvb.c | 2 + 2 files changed, 55 insertions(+), 32 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 8176a9b5898f..256fc4bf500b 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -91,6 +91,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe, int i, tuner_freq, if_freq; u32 N; + dprintk("%s:\n", __FUNCTION__); switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: if_freq = 4000000; @@ -159,6 +160,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe) struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; + dprintk("%s:\n", __FUNCTION__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(priv->i2c_adap, &msg, 1); @@ -222,6 +224,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, int i, tuner_freq, if_freq; u32 N; + dprintk("%s:\n", __FUNCTION__); if (priv->cfg && priv->cfg->lna_gain) priv->cfg->lna_gain(fe, 1); msleep(20); @@ -350,6 +353,7 @@ static int tda827xa_sleep(struct dvb_frontend *fe) struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; + dprintk("%s:\n", __FUNCTION__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -388,13 +392,32 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) static int tda827x_init(struct dvb_frontend *fe) { struct tda827x_priv *priv = fe->tuner_priv; - + dprintk("%s:\n", __FUNCTION__); if (priv->cfg && priv->cfg->init) priv->cfg->init(fe); return 0; } +static int tda827x_probe_version(struct dvb_frontend *fe); + +static int tda827x_initial_init(struct dvb_frontend *fe) +{ + int ret; + ret = tda827x_probe_version(fe); + if (ret) + return ret; + return fe->ops.tuner_ops.init(fe); +} + +static int tda827x_initial_sleep(struct dvb_frontend *fe) +{ + int ret; + ret = tda827x_probe_version(fe); + if (ret) + return ret; + return fe->ops.tuner_ops.sleep(fe); +} static struct dvb_tuner_ops tda827xo_tuner_ops = { .info = { @@ -404,8 +427,8 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = { .frequency_step = 250000 }, .release = tda827x_release, - .init = tda827x_init, - .sleep = tda827xo_sleep, + .init = tda827x_initial_init, + .sleep = tda827x_initial_sleep, .set_params = tda827xo_set_params, .get_frequency = tda827x_get_frequency, .get_bandwidth = tda827x_get_bandwidth, @@ -426,26 +449,36 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = { .get_bandwidth = tda827x_get_bandwidth, }; -struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, - struct i2c_adapter *i2c, - struct tda827x_config *cfg) -{ - struct tda827x_priv *priv = NULL; - u8 data; - u8 sb_msg[] = { 0x30, 0xd0 }; - struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, +static int tda827x_probe_version(struct dvb_frontend *fe) +{ u8 data; + struct tda827x_priv *priv = fe->tuner_priv; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD, .buf = &data, .len = 1 }; - dprintk("%s:\n", __FUNCTION__); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - - if (i2c_transfer(i2c, &msg, 1) != 1) { + if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { printk("%s: could not read from tuner at addr: 0x%02x\n", - __FUNCTION__, addr << 1); - return NULL; + __FUNCTION__, msg.addr << 1); + return -EIO; + } + if ((data & 0x3c) == 0) { + dprintk("tda827x tuner found\n"); + fe->ops.tuner_ops.init = tda827x_init; + fe->ops.tuner_ops.sleep = tda827xo_sleep; + } else { + dprintk("tda827xa tuner found\n"); + memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); } + return 0; +} + +struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, + struct i2c_adapter *i2c, + struct tda827x_config *cfg) +{ + struct tda827x_priv *priv = NULL; + dprintk("%s:\n", __FUNCTION__); priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL); if (priv == NULL) return NULL; @@ -453,25 +486,13 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, priv->i2c_addr = addr; priv->i2c_adap = i2c; priv->cfg = cfg; + memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); - msg.flags = 0; - msg.buf = sb_msg; - msg.len = sizeof(sb_msg); - - if ((data & 0x3c) == 0) { - dprintk("tda827x tuner found\n"); - memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); - } else { - dprintk("tda827xa tuner found\n"); - memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); - sb_msg[1] = 0x90; - } fe->tuner_priv = priv; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(i2c, &msg, 1); + return fe; } + EXPORT_SYMBOL(tda827x_attach); module_param(debug, int, 0644); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 71c32b311654..65aec881bbde 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1177,6 +1177,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.init(dev->dvb.frontend); if (dev->dvb.frontend->ops.sleep) dev->dvb.frontend->ops.sleep(dev->dvb.frontend); + if (dev->dvb.frontend->ops.tuner_ops.sleep) + dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); } return ret; } -- cgit v1.2.3 From 4b9d4e7dba102c8ab5ef651e538e9d0c79c80cab Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sun, 1 Apr 2007 18:29:04 -0300 Subject: V4L/DVB (5494): Lgdt330x: Fix some warnings It's KERN_WARNING "lgdt....", not "KERN_WARNING lgdt...." Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt330x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 68aad0f6519f..e25286e2d431 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -475,7 +475,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) *status |= FE_HAS_CARRIER; break; default: - printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); } return 0; @@ -534,7 +534,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) } break; default: - printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); } return 0; } -- cgit v1.2.3 From 941491f3a52c34506137060716ce73e642ee326e Mon Sep 17 00:00:00 2001 From: Marco Gittler Date: Thu, 19 Apr 2007 11:26:47 -0300 Subject: V4L/DVB (5532): Add support for Opera S1- DVB-USB This patch adds support for DVB-Opera S1 USB 2.0 BOX. Signed-off-by: Marco Gittler Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 7 + drivers/media/dvb/dvb-usb/Makefile | 4 + drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 + drivers/media/dvb/dvb-usb/opera1.c | 563 ++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/opera1.h | 9 + drivers/media/dvb/frontends/dvb-pll.c | 25 ++ drivers/media/dvb/frontends/dvb-pll.h | 1 + 7 files changed, 612 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/opera1.c create mode 100644 drivers/media/dvb/dvb-usb/opera1.h (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 8aa12722cbd6..54488737a08f 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -211,3 +211,10 @@ config DVB_USB_DTT200U The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). The WT-220U and its clones are pen-sized. + +config DVB_USB_OPERA1 + tristate "Opera1 DVB-S USB2.0 receiver" + depends on DVB_USB + select DVB_STV0299 if !DVB_FE_CUSTOMISE + help + Say Y here to support the Opera DVB-S USB2.0 receiver. diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 40f28f559b54..976f840cc904 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -51,4 +51,8 @@ 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 +dvb-usb-opera-objs = opera1.o +obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o + + EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index dda636af29fb..e4e60619421e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -38,6 +38,7 @@ #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_UNIWILL 0x1584 #define USB_VID_WIDEVIEW 0x14aa +#define USB_VID_OPERA1 0x695c /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -142,6 +143,8 @@ #define USB_PID_GENPIX_8PSK_WARM 0x0201 #define USB_PID_SIGMATEK_DVB_110 0x6610 #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 +#define USB_PID_OPERA1_COLD 0x2830 +#define USB_PID_OPERA1_WARM 0x3829 #endif diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c new file mode 100644 index 000000000000..67c2aa59f74c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -0,0 +1,563 @@ +/* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card +* +* Copyright (C) 2006 Mario Hlawitschka (dh1pa@amsat.org) +* Copyright (C) 2006 Marco Gittler (g.marco@freenet.de) +* +* 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 +*/ + +#include "opera1.h" +#include "stv0299.h" + +#define OPERA_READ_MSG 0 +#define OPERA_WRITE_MSG 1 +#define OPERA_I2C_TUNER 0xd1 + +#define READ_FX2_REG_REQ 0xba +#define READ_MAC_ADDR 0x08 +#define OPERA_WRITE_FX2 0xbb +#define OPERA_TUNER_REQ 0xb1 +#define REG_1F_SYMBOLRATE_BYTE0 0x1f +#define REG_20_SYMBOLRATE_BYTE1 0x20 +#define REG_21_SYMBOLRATE_BYTE2 0x21 + +struct opera1_state { + u32 last_key_pressed; +}; +struct opera_rc_keys { + u32 keycode; + u32 event; +}; + +int dvb_usb_opera1_debug; +module_param_named(debug, dvb_usb_opera1_debug, int, 0644); +MODULE_PARM_DESC(debug, + "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." + DVB_USB_DEBUG_STATUS); + +static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, + u8 * data, u16 len, int flags) +{ + int ret; + u8 r; + u8 u8buf[len]; + + unsigned int pipe = (flags == OPERA_READ_MSG) ? + usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0); + u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; + + if (flags == OPERA_WRITE_MSG) + memcpy(u8buf, data, len); + ret = + usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, + value, 0x0, u8buf, len, 2000); + + if (request == OPERA_TUNER_REQ) { + if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, + 0x01, 0x0, &r, 1, 2000)<1 || r!=0x08) + return 0; + } + if (flags == OPERA_READ_MSG) + memcpy(data, u8buf, len); + return ret; +} + +/* I2C */ + +static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr, + u8 * buf, u16 len, int flag) +{ + int ret = 0; + u8 request; + u16 value; + + if (!dev) { + info("no usb_device"); + return -EINVAL; + } + if (mutex_lock_interruptible(&dev->usb_mutex) < 0) + return -EAGAIN; + + request = (addr & 0xff00) >> 8; + if (!request) + request = 0xb1; + value = (addr & 0xff); + if (flag & OPERA_READ_MSG) { + value |= 0x01; + } + if (request == 0xa0) + value = 0xe600; + ret = opera1_xilinx_rw(dev->udev, request, value, buf, len, flag); + + mutex_unlock(&dev->usb_mutex); + return ret; +} + +static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i = 0, tmp = 0; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + for (i = 0; i < num; i++) { + if ((tmp = opera1_usb_i2c_msgxfer(d, + msg[i].addr, + msg[i].buf, + msg[i].len, + (msg[i].flags == + I2C_M_RD ? + OPERA_READ_MSG : + OPERA_WRITE_MSG))!= msg[i].len)) { + break; + } + if (dvb_usb_opera1_debug & 0x10) + info("sending i2c mesage %d %d", tmp, msg[i].len); + } + mutex_unlock(&d->i2c_mutex); + return num; +} + +static u32 opera1_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm opera1_i2c_algo = { + .master_xfer = opera1_i2c_xfer, + .functionality = opera1_i2c_func, +}; + +static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + static u8 command_13v[1]={0x00}; + static u8 command_18v[1]={0x01}; + struct i2c_msg msg[] = { + {.addr = 0xb600,.flags = 0,.buf = command_13v,.len = 1}, + }; + struct dvb_usb_adapter *udev_adap = + (struct dvb_usb_adapter *)(fe->dvb->priv); + if (voltage == SEC_VOLTAGE_18) { + msg[0].addr = 0xb601; + msg[0].buf = command_18v; + } + i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); + return 0; +} + +static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, + u32 ratio) +{ + stv0299_writereg(fe, 0x13, 0x98); + stv0299_writereg(fe, 0x14, 0x95); + stv0299_writereg(fe, REG_1F_SYMBOLRATE_BYTE0, (ratio >> 16) & 0xff); + stv0299_writereg(fe, REG_20_SYMBOLRATE_BYTE1, (ratio >> 8) & 0xff); + stv0299_writereg(fe, REG_21_SYMBOLRATE_BYTE2, (ratio) & 0xf0); + return 0; + +} +static u8 opera1_inittab[] = { + 0x00, 0xa1, + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, + 0x05, 0x05, + 0x06, 0x02, + 0x07, 0x00, + 0x0b, 0x00, + 0x0c, 0x01, + 0x0d, 0x81, + 0x0e, 0x44, + 0x0f, 0x19, + 0x10, 0x3f, + 0x11, 0x84, + 0x12, 0xda, + 0x13, 0x98, + 0x14, 0x95, + 0x15, 0xc9, + 0x16, 0xeb, + 0x17, 0x00, + 0x18, 0x19, + 0x19, 0x8b, + 0x1a, 0x00, + 0x1b, 0x82, + 0x1c, 0x7f, + 0x1d, 0x00, + 0x1e, 0x00, + REG_1F_SYMBOLRATE_BYTE0, 0x06, + REG_20_SYMBOLRATE_BYTE1, 0x50, + REG_21_SYMBOLRATE_BYTE2, 0x10, + 0x22, 0x00, + 0x23, 0x00, + 0x24, 0x37, + 0x25, 0xbc, + 0x26, 0x00, + 0x27, 0x00, + 0x28, 0x00, + 0x29, 0x1e, + 0x2a, 0x14, + 0x2b, 0x1f, + 0x2c, 0x09, + 0x2d, 0x0a, + 0x2e, 0x00, + 0x2f, 0x00, + 0x30, 0x00, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x13, + 0xff, 0xff, +}; + +static struct stv0299_config opera1_stv0299_config = { + .demod_address = 0xd0, + .min_delay_ms = 100, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .inittab = opera1_inittab, + .set_symbol_rate = opera1_stv0299_set_symbol_rate, +}; + +static int opera1_frontend_attach(struct dvb_usb_adapter *d) +{ + if ((d->fe = + dvb_attach(stv0299_attach, &opera1_stv0299_config, + &d->dev->i2c_adap)) != NULL) { + d->fe->ops.set_voltage = opera1_set_voltage; + return 0; + } + info("not attached stv0299"); + return -EIO; +} + +static int opera1_tuner_attach(struct dvb_usb_adapter *adap) +{ + adap->pll_addr = 0xc0; + adap->pll_desc = &dvb_pll_opera1; + adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; + return 0; +} + +static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int addr = onoff ? 0xb701 : 0xb700; + u8 val = onoff ? 0x01 : 0x00; + if (dvb_usb_opera1_debug) + info("power %s", onoff ? "on" : "off"); + return opera1_usb_i2c_msgxfer(d, addr, &val, 1, OPERA_WRITE_MSG); +} + +static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + static u8 buf_start[2] = { 0xff, 0x03 }; + static u8 buf_stop[2] = { 0xff, 0x00 }; + struct i2c_msg start_tuner[] = { + {.addr = 0xb1a6,.buf = onoff ? buf_start : buf_stop,.len = 2}, + }; + if (dvb_usb_opera1_debug) + info("streaming %s", onoff ? "on" : "off"); + i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1); + return 0; +} + +static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + int onoff) +{ + u8 b_pid[3]; + struct i2c_msg msg[] = { + {.addr = 0xb1a6,.buf = b_pid,.len = 3}, + }; + if (dvb_usb_opera1_debug) + info("pidfilter index: %d pid: %d %s", index, pid, + onoff ? "on" : "off"); + b_pid[0] = (2 * index) + 4; + b_pid[1] = onoff ? (pid & 0xff) : (0x00); + b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00); + i2c_transfer(&adap->dev->i2c_adap, msg, 1); + return 0; +} + +static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) +{ + int u = 0x04; + u8 b_pid[3]; + struct i2c_msg msg[] = { + {.addr = 0xb1a6,.buf = b_pid,.len = 3}, + }; + if (dvb_usb_opera1_debug) + info("%s hw-pidfilter", onoff ? "enable" : "disable"); + for (; u < 0x7e; u += 2) { + b_pid[0] = u; + b_pid[1] = 0; + b_pid[2] = 0x80; + i2c_transfer(&adap->dev->i2c_adap, msg, 1); + } + return 0; +} + +static struct dvb_usb_rc_key opera1_rc_keys[] = { + {0x5f, 0xa0, KEY_1}, + {0x51, 0xaf, KEY_2}, + {0x5d, 0xa2, KEY_3}, + {0x41, 0xbe, KEY_4}, + {0x0b, 0xf5, KEY_5}, + {0x43, 0xbd, KEY_6}, + {0x47, 0xb8, KEY_7}, + {0x49, 0xb6, KEY_8}, + {0x05, 0xfa, KEY_9}, + {0x45, 0xba, KEY_0}, + {0x09, 0xf6, KEY_UP}, /*chanup */ + {0x1b, 0xe5, KEY_DOWN}, /*chandown */ + {0x5d, 0xa3, KEY_LEFT}, /*voldown */ + {0x5f, 0xa1, KEY_RIGHT}, /*volup */ + {0x07, 0xf8, KEY_SPACE}, /*tab */ + {0x1f, 0xe1, KEY_ENTER}, /*play ok */ + {0x1b, 0xe4, KEY_Z}, /*zoom */ + {0x59, 0xa6, KEY_M}, /*mute */ + {0x5b, 0xa5, KEY_F}, /*tv/f */ + {0x19, 0xe7, KEY_R}, /*rec */ + {0x01, 0xfe, KEY_S}, /*Stop */ + {0x03, 0xfd, KEY_P}, /*pause */ + {0x03, 0xfc, KEY_W}, /*<- -> */ + {0x07, 0xf9, KEY_C}, /*capture */ + {0x47, 0xb9, KEY_Q}, /*exit */ + {0x43, 0xbc, KEY_O}, /*power */ + +}; + +static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) +{ + struct opera1_state *opst = dev->priv; + u8 rcbuffer[32]; + const u16 startmarker1 = 0x10ed; + const u16 startmarker2 = 0x11ec; + struct i2c_msg read_remote[] = { + {.addr = 0xb880,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32}, + }; + int i = 0; + u32 send_key = 0; + + if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) { + for (i = 0; i < 32; i++) { + if (rcbuffer[i]) + send_key |= 1; + if (i < 31) + send_key = send_key << 1; + } + if (send_key & 0x8000) + send_key = (send_key << 1) | (send_key >> 15 & 0x01); + + if (send_key == 0xffff && opst->last_key_pressed != 0) { + *state = REMOTE_KEY_REPEAT; + *event = opst->last_key_pressed; + return 0; + } + for (; send_key != 0;) { + if (send_key >> 16 == startmarker2) { + break; + } else if (send_key >> 16 == startmarker1) { + send_key = + (send_key & 0xfffeffff) | (startmarker1 << 16); + break; + } else + send_key >>= 1; + } + + if (send_key == 0) + return 0; + + send_key = (send_key & 0xffff) | 0x0100; + + for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) { + if ((opera1_rc_keys[i].custom * 256 + + opera1_rc_keys[i].data) == (send_key & 0xffff)) { + *state = REMOTE_KEY_PRESSED; + *event = opera1_rc_keys[i].event; + opst->last_key_pressed = + opera1_rc_keys[i].event; + break; + } + opst->last_key_pressed = 0; + } + } else + *state = REMOTE_NO_KEY_PRESSED; + return 0; +} + +static struct usb_device_id opera1_table[] = { + {USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD)}, + {USB_DEVICE(USB_VID_OPERA1, USB_PID_OPERA1_WARM)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, opera1_table); + +static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +{ + u8 command[] = { READ_MAC_ADDR }; + opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG); + opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG); + return 0; +} +static int opera1_xilinx_load_firmware(struct usb_device *dev, + const char *filename) +{ + const struct firmware *fw = NULL; + u8 *b, *p; + int ret = 0, i; + u8 testval; + info("start downloading fpga firmware"); + + if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) { + err("did not find the firmware file. (%s) " + "Please see linux/Documentation/dvb/ for more details on firmware-problems.", + filename); + return ret; + } else { + p = kmalloc(fw->size, GFP_KERNEL); + opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG); + if (p != NULL && testval != 0x67) { + + u8 reset = 0, fpga_command = 0; + memcpy(p, fw->data, fw->size); + /* clear fpga ? */ + opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1, + OPERA_WRITE_MSG); + for (i = 0; p[i] != 0 && i < fw->size;) { + b = (u8 *) p + i; + if (opera1_xilinx_rw + (dev, OPERA_WRITE_FX2, 0x0, b + 1, b[0], + OPERA_WRITE_MSG) != b[0] + ) { + err("error while transferring firmware"); + ret = -EINVAL; + break; + } + i = i + 1 + b[0]; + } + /* restart the CPU */ + if (ret || opera1_xilinx_rw + (dev, 0xa0, 0xe600, &reset, 1, + OPERA_WRITE_MSG) != 1) { + err("could not restart the USB controller CPU."); + ret = -EINVAL; + } + kfree(p); + } + } + if (fw) { + release_firmware(fw); + } + return ret; +} + +static struct dvb_usb_device_properties opera1_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = CYPRESS_FX2, + .firmware = "opera.fw", + .size_of_priv = sizeof(struct opera1_state), + + .power_ctrl = opera1_power_ctrl, + .i2c_algo = &opera1_i2c_algo, + + .rc_key_map = opera1_rc_keys, + .rc_key_map_size = ARRAY_SIZE(opera1_rc_keys), + .rc_interval = 200, + .rc_query = opera1_rc_query, + .read_mac_address = opera1_read_mac_address, + .generic_bulk_ctrl_endpoint = 0x00, + /* parameter for the MPEG2-data transfer */ + .num_adapters = 1, + .adapter = { + { + .frontend_attach = opera1_frontend_attach, + .streaming_ctrl = opera1_streaming_ctrl, + .tuner_attach = opera1_tuner_attach, + .caps = + DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter = opera1_pid_filter, + .pid_filter_ctrl = opera1_pid_filter_control, + .pid_filter_count = 252, + .stream = { + .type = USB_BULK, + .count = 10, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + .num_device_descs = 1, + .devices = { + {"Opera1 DVB-S USB2.0", + {&opera1_table[0], NULL}, + {&opera1_table[1], NULL}, + }, + } +}; + +static int opera1_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct dvb_usb_device *d; + struct usb_device *udev = interface_to_usbdev(intf); + + if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM && + udev->descriptor.idVendor == USB_VID_OPERA1 && + (d == NULL + || opera1_xilinx_load_firmware(udev, "opera1-fpga.fw") != 0) + ) { + return -EINVAL; + } + + if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, &d) != 0) + return -EINVAL; + return 0; +} + +static struct usb_driver opera1_driver = { + .name = "opera1", + .probe = opera1_probe, + .disconnect = dvb_usb_device_exit, + .id_table = opera1_table, +}; + +static int __init opera1_module_init(void) +{ + int result = 0; + if ((result = usb_register(&opera1_driver))) { + err("usb_register failed. Error number %d", result); + } + return result; +} + +static void __exit opera1_module_exit(void) +{ + usb_deregister(&opera1_driver); +} + +module_init(opera1_module_init); +module_exit(opera1_module_exit); + +MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@amsat.org"); +MODULE_AUTHOR("Marco Gittler (c) g.marco@freenet.de"); +MODULE_DESCRIPTION("Driver for Opera1 DVB-S device"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/opera1.h b/drivers/media/dvb/dvb-usb/opera1.h new file mode 100644 index 000000000000..53174427902d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/opera1.h @@ -0,0 +1,9 @@ +#ifndef _OPERA1_H_ +#define _OPERA1_H_ + +#define DVB_USB_LOG_PREFIX "opera" +#include "dvb-usb.h" + +extern int dvb_usb_opera1_debug; +#define deb_xfer(args...) dprintk(dvb_usb_opera1_debug,0x02,args) +#endif diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index d29e0ae23ee6..5f96ffda91ad 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -451,6 +451,31 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = { } }; EXPORT_SYMBOL(dvb_pll_thomson_fe6600); +static void opera1_bw(u8 *buf, u32 freq, int bandwidth) +{ + if (bandwidth == BANDWIDTH_8_MHZ) + buf[2] |= 0x08; +} + +struct dvb_pll_desc dvb_pll_opera1 = { + .name = "Opera Tuner", + .min = 900000, + .max = 2250000, + .iffreq= 0, + .setbw = opera1_bw, + .count = 8, + .entries = { + { 1064000, 500, 0xe5, 0xc6 }, + { 1169000, 500, 0xe5, 0xe6 }, + { 1299000, 500, 0xe5, 0x24 }, + { 1444000, 500, 0xe5, 0x44 }, + { 1606000, 500, 0xe5, 0x64 }, + { 1777000, 500, 0xe5, 0x84 }, + { 1941000, 500, 0xe5, 0xa4 }, + { 2250000, 500, 0xe5, 0xc4 }, + } +}; +EXPORT_SYMBOL(dvb_pll_opera1); struct dvb_pll_priv { /* i2c details */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index d13a1c01c541..5209f46f0893 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -48,6 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_td1316; extern struct dvb_pll_desc dvb_pll_thomson_fe6600; +extern struct dvb_pll_desc dvb_pll_opera1; extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); -- cgit v1.2.3 From fd9c66e269a44bd3c6c615957c79b21f3dde69af Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sat, 21 Apr 2007 19:17:49 -0300 Subject: V4L/DVB (5542): Budget-av: Remove polarity switching of the clock for DVB-C Remove the polarity switching of the clock for the DVB-C cards in budget-av.c. This hack is no longer necessary because the saa7146 can do the job to remove the additional FEC bytes from the TS. Signed-off-by: Hartmut Birr Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10021.c | 13 +---------- drivers/media/dvb/frontends/tda10021.h | 8 ------- drivers/media/dvb/ttpci/budget-av.c | 40 -------------------------------- drivers/media/dvb/ttpci/budget-core.c | 42 ++++++++++++++++++++++++++++------ 4 files changed, 36 insertions(+), 67 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 9348e76fe2e0..ef9159f8c3fa 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -64,7 +64,7 @@ static u8 tda10021_inittab[0x40]= { 0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a, 0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40, - 0xb8, 0x3f, 0xa0, 0x00, 0xcd, 0x01, 0x00, 0xff, + 0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff, 0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58, @@ -201,16 +201,6 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate return 0; } -static int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len) -{ - struct tda10021_state* state = fe->demodulator_priv; - - if (len != 2) - return -EINVAL; - - return _tda10021_writereg(state, buf[0], buf[1]); -} - static int tda10021_init (struct dvb_frontend *fe) { struct tda10021_state* state = fe->demodulator_priv; @@ -461,7 +451,6 @@ static struct dvb_frontend_ops tda10021_ops = { .init = tda10021_init, .sleep = tda10021_sleep, - .write = tda10021_write, .i2c_gate_ctrl = tda10021_i2c_gate_ctrl, .set_frontend = tda10021_set_parameters, diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h index e3da780108f6..b8efd498d4bf 100644 --- a/drivers/media/dvb/frontends/tda10021.h +++ b/drivers/media/dvb/frontends/tda10021.h @@ -44,12 +44,4 @@ static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* } #endif // CONFIG_DVB_TDA10021 -static inline int tda10021_writereg(struct dvb_frontend *fe, u8 reg, u8 val) { - int r = 0; - u8 buf[] = {reg, val}; - if (fe->ops.write) - r = fe->ops.write(fe, buf, 2); - return r; -} - #endif // TDA10021_H diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 3035b224c7a3..54ca3a3288e7 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -66,9 +66,6 @@ struct budget_av { int slot_status; struct dvb_ca_en50221 ca; u8 reinitialise_demod:1; - u8 tda10021_poclkp:1; - u8 tda10021_ts_enabled; - int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); }; static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); @@ -234,12 +231,6 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) if (budget_av->reinitialise_demod) dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); - /* set tda10021 back to original clock configuration on reset */ - if (budget_av->tda10021_poclkp) { - tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); - budget_av->tda10021_ts_enabled = 0; - } - return 0; } @@ -256,11 +247,6 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); budget_av->slot_status = SLOTSTATUS_NONE; - /* set tda10021 back to original clock configuration when cam removed */ - if (budget_av->tda10021_poclkp) { - tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); - budget_av->tda10021_ts_enabled = 0; - } return 0; } @@ -276,12 +262,6 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); - /* tda10021 seems to need a different TS clock config when data is routed to the CAM */ - if (budget_av->tda10021_poclkp) { - tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1); - budget_av->tda10021_ts_enabled = 1; - } - return 0; } @@ -927,23 +907,6 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBT_KNC1 0x0030 #define SUBID_DVBT_CINERGY1200 0x1157 - -static int tda10021_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) -{ - struct budget_av* budget_av = fe->dvb->priv; - int result; - - result = budget_av->tda10021_set_frontend(fe, p); - if (budget_av->tda10021_ts_enabled) { - tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1); - } else { - tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); - } - - return result; -} - static void frontend_init(struct budget_av *budget_av) { struct saa7146_dev * saa = budget_av->budget.dev; @@ -1025,9 +988,6 @@ static void frontend_init(struct budget_av *budget_av) &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; - fe->ops.set_frontend = tda10021_set_frontend; fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; } break; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index e15562f81664..cef9d8d8a122 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -41,11 +41,14 @@ #define TS_WIDTH (2 * TS_SIZE) #define TS_WIDTH_ACTIVY TS_SIZE +#define TS_WIDTH_DVBC TS_SIZE #define TS_HEIGHT_MASK 0xf00 #define TS_HEIGHT_MASK_ACTIVY 0xc00 +#define TS_HEIGHT_MASK_DVBC 0xe00 #define TS_MIN_BUFSIZE_K 188 #define TS_MAX_BUFSIZE_K 1410 #define TS_MAX_BUFSIZE_K_ACTIVY 564 +#define TS_MAX_BUFSIZE_K_DVBC 1316 #define BUFFER_WARNING_WAIT (30*HZ) int budget_debug; @@ -122,7 +125,13 @@ static int start_ts_capture(struct budget *budget) mdelay(10); saa7146_write(dev, BASE_ODD3, 0); - saa7146_write(dev, BASE_EVEN3, 0); + if (budget->buffer_size > budget->buffer_height * budget->buffer_width) { + // using odd/even buffers + saa7146_write(dev, BASE_EVEN3, budget->buffer_height * budget->buffer_width); + } else { + // using a single buffer + saa7146_write(dev, BASE_EVEN3, 0); + } saa7146_write(dev, PROT_ADDR3, budget->buffer_size); saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90); @@ -399,11 +408,22 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, budget->card = bi; budget->dev = (struct saa7146_dev *) dev; - if (budget->card->type == BUDGET_FS_ACTIVY) { + switch(budget->card->type) { + case BUDGET_FS_ACTIVY: budget->buffer_width = TS_WIDTH_ACTIVY; max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY; height_mask = TS_HEIGHT_MASK_ACTIVY; - } else { + break; + + case BUDGET_KNC1C: + case BUDGET_KNC1CP: + case BUDGET_CIN1200C: + budget->buffer_width = TS_WIDTH_DVBC; + max_bufsize = TS_MAX_BUFSIZE_K_DVBC; + height_mask = TS_HEIGHT_MASK_DVBC; + break; + + default: budget->buffer_width = TS_WIDTH; max_bufsize = TS_MAX_BUFSIZE_K; height_mask = TS_HEIGHT_MASK; @@ -415,14 +435,22 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, dma_buffer_size = max_bufsize; budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width; - budget->buffer_height &= height_mask; - budget->buffer_size = budget->buffer_height * budget->buffer_width; + if (budget->buffer_height > 0xfff) { + budget->buffer_height /= 2; + budget->buffer_height &= height_mask; + budget->buffer_size = 2 * budget->buffer_height * budget->buffer_width; + } else { + budget->buffer_height &= height_mask; + budget->buffer_size = budget->buffer_height * budget->buffer_width; + } budget->buffer_warning_threshold = budget->buffer_size * 80/100; budget->buffer_warnings = 0; budget->buffer_warning_time = jiffies; - dprintk(2, "%s: width = %d, height = %d\n", - budget->dev->name, budget->buffer_width, budget->buffer_height); + dprintk(2, "%s: buffer type = %s, width = %d, height = %d\n", + budget->dev->name, + budget->buffer_size > budget->buffer_width * budget->buffer_height ? "odd/even" : "single", + budget->buffer_width, budget->buffer_height); printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) { -- cgit v1.2.3 From aa323ac89c5724de89656fcf31590d19e74594ec Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sat, 21 Apr 2007 19:37:17 -0300 Subject: V4L/DVB (5543): Tda10023: Add support for frontend TDA10023 Add support for the frontend TDA10023 and add cards that need the tda10023. Signed-off-by: Hartmut Birr Signed-off-by: Georg Acher Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda10021.c | 6 +- drivers/media/dvb/frontends/tda10021.h | 47 --- drivers/media/dvb/frontends/tda10023.c | 540 +++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/tda1002x.h | 59 ++++ drivers/media/dvb/ttpci/Kconfig | 2 + drivers/media/dvb/ttpci/budget-av.c | 105 +++++-- drivers/media/dvb/ttpci/budget-core.c | 16 + drivers/media/dvb/ttpci/budget.h | 3 + 10 files changed, 709 insertions(+), 77 deletions(-) delete mode 100644 drivers/media/dvb/frontends/tda10021.h create mode 100644 drivers/media/dvb/frontends/tda10023.c create mode 100644 drivers/media/dvb/frontends/tda1002x.h (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 10c4e7bdde78..ff448761dcef 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -205,6 +205,13 @@ config DVB_TDA10021 help A DVB-C tuner module. Say Y when you want to support this frontend. +config DVB_TDA10023 + tristate "Philips TDA10023 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-C tuner module. Say Y when you want to support this frontend. + config DVB_STV0297 tristate "ST STV0297 based" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 905fcfc8732a..27f386585d43 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o +obj-$(CONFIG_DVB_TDA10023) += tda10023.o obj-$(CONFIG_DVB_STV0297) += stv0297.o obj-$(CONFIG_DVB_NXT200X) += nxt200x.o obj-$(CONFIG_DVB_OR51211) += or51211.o diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index ef9159f8c3fa..304f1f9b8008 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -30,13 +30,13 @@ #include #include "dvb_frontend.h" -#include "tda10021.h" +#include "tda1002x.h" struct tda10021_state { struct i2c_adapter* i2c; /* configuration settings */ - const struct tda10021_config* config; + const struct tda1002x_config* config; struct dvb_frontend frontend; u8 pwm; @@ -398,7 +398,7 @@ static void tda10021_release(struct dvb_frontend* fe) static struct dvb_frontend_ops tda10021_ops; -struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, +struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, struct i2c_adapter* i2c, u8 pwm) { diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h deleted file mode 100644 index b8efd498d4bf..000000000000 --- a/drivers/media/dvb/frontends/tda10021.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - TDA10021 - Single Chip Cable Channel Receiver driver module - used on the the Siemens DVB-C cards - - Copyright (C) 1999 Convergence Integrated Media GmbH - Copyright (C) 2004 Markus Schulz - Support for TDA10021 - - 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 TDA10021_H -#define TDA10021_H - -#include - -struct tda10021_config -{ - /* the demodulator's i2c address */ - u8 demod_address; -}; - -#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) -extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, - struct i2c_adapter* i2c, u8 pwm); -#else -static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, - struct i2c_adapter* i2c, u8 pwm) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); - return NULL; -} -#endif // CONFIG_DVB_TDA10021 - -#endif // TDA10021_H diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c new file mode 100644 index 000000000000..da796e784be3 --- /dev/null +++ b/drivers/media/dvb/frontends/tda10023.c @@ -0,0 +1,540 @@ +/* + TDA10023 - DVB-C decoder + (as used in Philips CU1216-3 NIM and the Reelbox DVB-C tuner card) + + Copyright (C) 2005 Georg Acher, BayCom GmbH (acher at baycom dot de) + Copyright (c) 2006 Hartmut Birr (e9hack at gmail dot com) + + Remotely based on tda10021.c + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2004 Markus Schulz + Support for TDA10021 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dvb_frontend.h" +#include "tda1002x.h" + + +struct tda10023_state { + struct i2c_adapter* i2c; + /* configuration settings */ + const struct tda1002x_config* config; + struct dvb_frontend frontend; + + u8 pwm; + u8 reg0; +}; + + +#define dprintk(x...) + +static int verbose; + +#define XTAL 28920000UL +#define PLL_M 8UL +#define PLL_P 4UL +#define PLL_N 1UL +#define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P)) // -> 57840000 + +static u8 tda10023_inittab[]={ + // reg mask val + 0x2a,0xff,0x02, // PLL3, Bypass, Power Down + 0xff,0x64,0x00, // Sleep 100ms + 0x2a,0xff,0x03, // PLL3, Bypass, Power Down + 0xff,0x64,0x00, // Sleep 100ms + 0x28,0xff,PLL_M-1, // PLL1 M=8 + 0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1), // PLL2 + 0x00,0xff,0x23, // GPR FSAMPLING=1 + 0x2a,0xff,0x08, // PLL3 PSACLK=1 + 0xff,0x64,0x00, // Sleep 100ms + 0x1f,0xff,0x00, // RESET + 0xff,0x64,0x00, // Sleep 100ms + 0xe6,0x0c,0x04, // RSCFG_IND + 0x10,0xc0,0x80, // DECDVBCFG1 PBER=1 + + 0x0e,0xff,0x82, // GAIN1 + 0x03,0x08,0x08, // CLKCONF DYN=1 + 0x2e,0xbf,0x30, // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0 + 0x01,0xff,0x30, // AGCREF + 0x1e,0x84,0x84, // CONTROL SACLK_ON=1 + 0x1b,0xff,0xc8, // ADC TWOS=1 + 0x3b,0xff,0xff, // IFMAX + 0x3c,0xff,0x00, // IFMIN + 0x34,0xff,0x00, // PWMREF + 0x35,0xff,0xff, // TUNMAX + 0x36,0xff,0x00, // TUNMIN + 0x06,0xff,0x7f, // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 // 0x77 + 0x1c,0x30,0x30, // EQCONF2 STEPALGO=SGNALGO=1 + 0x37,0xff,0xf6, // DELTAF_LSB + 0x38,0xff,0xff, // DELTAF_MSB + 0x02,0xff,0x93, // AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 + 0x2d,0xff,0xf6, // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 + 0x04,0x10,0x00, // SWRAMP=1 + 0x12,0xff,0xa1, // INTP1 POCLKP=1 FEL=1 MFS=0 + 0x2b,0x01,0xa1, // INTS1 + 0x20,0xff,0x04, // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? + 0x2c,0xff,0x0d, // INTP/S TRIP=0 TRIS=0 + 0xc4,0xff,0x00, + 0xc3,0x30,0x00, + 0xb5,0xff,0x19, // ERAGC_THD + 0x00,0x03,0x01, // GPR, CLBS soft reset + 0x00,0x03,0x03, // GPR, CLBS soft reset + 0xff,0x64,0x00, // Sleep 100ms + 0xff,0xff,0xff +}; + +static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) +{ + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + int ret; + + ret = i2c_transfer (state->i2c, msg, 2); + if (ret != 2) + printk("DVB: TDA10023: %s: readreg error (ret == %i)\n", + __FUNCTION__, ret); + return b1[0]; +} + +static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; + int ret; + + ret = i2c_transfer (state->i2c, &msg, 1); + if (ret != 1) + printk("DVB: TDA10023(%d): %s, writereg error " + "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", + state->frontend.dvb->num, __FUNCTION__, reg, data, ret); + + return (ret != 1) ? -EREMOTEIO : 0; +} + + +static int tda10023_writebit (struct tda10023_state* state, u8 reg, u8 mask,u8 data) +{ + if (mask==0xff) + return tda10023_writereg(state, reg, data); + else { + u8 val; + val=tda10023_readreg(state,reg); + val&=~mask; + val|=(data&mask); + return tda10023_writereg(state, reg, val); + } +} + +static void tda10023_writetab(struct tda10023_state* state, u8* tab) +{ + u8 r,m,v; + while (1) { + r=*tab++; + m=*tab++; + v=*tab++; + if (r==0xff) { + if (m==0xff) + break; + else + msleep(m); + } + else + tda10023_writebit(state,r,m,v); + } +} + +//get access to tuner +static int lock_tuner(struct tda10023_state* state) +{ + u8 buf[2] = { 0x0f, 0xc0 }; + struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2}; + + if(i2c_transfer(state->i2c, &msg, 1) != 1) + { + printk("tda10023: lock tuner fails\n"); + return -EREMOTEIO; + } + return 0; +} + +//release access from tuner +static int unlock_tuner(struct tda10023_state* state) +{ + u8 buf[2] = { 0x0f, 0x40 }; + struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2}; + + if(i2c_transfer(state->i2c, &msg_post, 1) != 1) + { + printk("tda10023: unlock tuner fails\n"); + return -EREMOTEIO; + } + return 0; +} + +static int tda10023_setup_reg0 (struct tda10023_state* state, u8 reg0) +{ + reg0 |= state->reg0 & 0x63; + + tda10023_writereg (state, 0x00, reg0 & 0xfe); + tda10023_writereg (state, 0x00, reg0 | 0x01); + + state->reg0 = reg0; + return 0; +} + +static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr) +{ + s32 BDR; + s32 BDRI; + s16 SFIL=0; + u16 NDEC = 0; + + if (sr > (SYSCLK/(2*4))) + sr=SYSCLK/(2*4); + + if (sr<870000) + sr=870000; + + if (sr < (u32)(SYSCLK/98.40)) { + NDEC=3; + SFIL=1; + } else if (sr<(u32)(SYSCLK/64.0)) { + NDEC=3; + SFIL=0; + } else if (sr<(u32)(SYSCLK/49.2)) { + NDEC=2; + SFIL=1; + } else if (sr<(u32)(SYSCLK/32.0)) { + NDEC=2; + SFIL=0; + } else if (sr<(u32)(SYSCLK/24.6)) { + NDEC=1; + SFIL=1; + } else if (sr<(u32)(SYSCLK/16.0)) { + NDEC=1; + SFIL=0; + } else if (sr<(u32)(SYSCLK/12.3)) { + NDEC=0; + SFIL=1; + } + + BDRI=SYSCLK*16; + BDRI>>=NDEC; + BDRI +=sr/2; + BDRI /=sr; + + if (BDRI>255) + BDRI=255; + + { + u64 BDRX; + + BDRX=1<<(24+NDEC); + BDRX*=sr; + do_div(BDRX,SYSCLK); // BDRX/=SYSCLK; + + BDR=(s32)BDRX; + } +// printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC); + tda10023_writebit (state, 0x03, 0xc0, NDEC<<6); + tda10023_writereg (state, 0x0a, BDR&255); + tda10023_writereg (state, 0x0b, (BDR>>8)&255); + tda10023_writereg (state, 0x0c, (BDR>>16)&31); + tda10023_writereg (state, 0x0d, BDRI); + tda10023_writereg (state, 0x3d, (SFIL<<7)); + return 0; +} + +static int tda10023_init (struct dvb_frontend *fe) +{ + struct tda10023_state* state = fe->demodulator_priv; + + dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num); + + tda10023_writetab(state, tda10023_inittab); + + return 0; +} + +static int tda10023_set_parameters (struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct tda10023_state* state = fe->demodulator_priv; + + static int qamvals[6][6] = { + // QAM LOCKTHR MSETH AREF AGCREFNYQ ERAGCNYQ_THD + { (5<<2), 0x78, 0x8c, 0x96, 0x78, 0x4c }, // 4 QAM + { (0<<2), 0x87, 0xa2, 0x91, 0x8c, 0x57 }, // 16 QAM + { (1<<2), 0x64, 0x74, 0x96, 0x8c, 0x57 }, // 32 QAM + { (2<<2), 0x46, 0x43, 0x6a, 0x6a, 0x44 }, // 64 QAM + { (3<<2), 0x36, 0x34, 0x7e, 0x78, 0x4c }, // 128 QAM + { (4<<2), 0x26, 0x23, 0x6c, 0x5c, 0x3c }, // 256 QAM + }; + + int qam = p->u.qam.modulation; + + if (qam < 0 || qam > 5) + return -EINVAL; + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + + tda10023_set_symbolrate (state, p->u.qam.symbol_rate); + tda10023_writereg (state, 0x05, qamvals[qam][1]); + tda10023_writereg (state, 0x08, qamvals[qam][2]); + tda10023_writereg (state, 0x09, qamvals[qam][3]); + tda10023_writereg (state, 0xb4, qamvals[qam][4]); + tda10023_writereg (state, 0xb6, qamvals[qam][5]); + +// tda10023_writereg (state, 0x04, (p->inversion?0x12:0x32)); +// tda10023_writebit (state, 0x04, 0x60, (p->inversion?0:0x20)); + tda10023_writebit (state, 0x04, 0x40, 0x40); + tda10023_setup_reg0 (state, qamvals[qam][0]); + + return 0; +} + +static int tda10023_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct tda10023_state* state = fe->demodulator_priv; + int sync; + + *status = 0; + + //0x11[1] == CARLOCK -> Carrier locked + //0x11[2] == FSYNC -> Frame synchronisation + //0x11[3] == FEL -> Front End locked + //0x11[6] == NODVB -> DVB Mode Information + sync = tda10023_readreg (state, 0x11); + + if (sync & 2) + *status |= FE_HAS_SIGNAL|FE_HAS_CARRIER; + + if (sync & 4) + *status |= FE_HAS_SYNC|FE_HAS_VITERBI; + + if (sync & 8) + *status |= FE_HAS_LOCK; + + return 0; +} + +static int tda10023_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct tda10023_state* state = fe->demodulator_priv; + u8 a,b,c; + a=tda10023_readreg(state, 0x14); + b=tda10023_readreg(state, 0x15); + c=tda10023_readreg(state, 0x16)&0xf; + tda10023_writebit (state, 0x10, 0xc0, 0x00); + + *ber = a | (b<<8)| (c<<16); + return 0; +} + +static int tda10023_read_signal_strength(struct dvb_frontend* fe, u16* strength) +{ + struct tda10023_state* state = fe->demodulator_priv; + u8 ifgain=tda10023_readreg(state, 0x2f); + + u16 gain = ((255-tda10023_readreg(state, 0x17))) + (255-ifgain)/16; + // Max raw value is about 0xb0 -> Normalize to >0xf0 after 0x90 + if (gain>0x90) + gain=gain+2*(gain-0x90); + if (gain>255) + gain=255; + + *strength = (gain<<8)|gain; + return 0; +} + +static int tda10023_read_snr(struct dvb_frontend* fe, u16* snr) +{ + struct tda10023_state* state = fe->demodulator_priv; + + u8 quality = ~tda10023_readreg(state, 0x18); + *snr = (quality << 8) | quality; + return 0; +} + +static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct tda10023_state* state = fe->demodulator_priv; + u8 a,b,c,d; + a= tda10023_readreg (state, 0x74); + b= tda10023_readreg (state, 0x75); + c= tda10023_readreg (state, 0x76); + d= tda10023_readreg (state, 0x77); + *ucblocks = a | (b<<8)|(c<<16)|(d<<24); + + tda10023_writebit (state, 0x10, 0x20,0x00); + tda10023_writebit (state, 0x10, 0x20,0x20); + tda10023_writebit (state, 0x13, 0x01, 0x00); + + return 0; +} + +static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct tda10023_state* state = fe->demodulator_priv; + int sync,inv; + s8 afc = 0; + + sync = tda10023_readreg(state, 0x11); + afc = tda10023_readreg(state, 0x19); + inv = tda10023_readreg(state, 0x04); + + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" : + "DVB: TDA10023(%d): [AFC (%d) %dHz]\n", + state->frontend.dvb->num, afc, + -((s32)p->u.qam.symbol_rate * afc) >> 10); + } + + p->inversion = (inv&0x20?0:1); + p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; + + p->u.qam.fec_inner = FEC_NONE; + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + + if (sync & 2) + p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; + + return 0; +} + +static int tda10023_sleep(struct dvb_frontend* fe) +{ + struct tda10023_state* state = fe->demodulator_priv; + + tda10023_writereg (state, 0x1b, 0x02); /* pdown ADC */ + tda10023_writereg (state, 0x00, 0x80); /* standby */ + + return 0; +} + +static int tda10023_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct tda10023_state* state = fe->demodulator_priv; + + if (enable) { + lock_tuner(state); + } else { + unlock_tuner(state); + } + return 0; +} + +static void tda10023_release(struct dvb_frontend* fe) +{ + struct tda10023_state* state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops tda10023_ops; + +struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, + struct i2c_adapter* i2c, + u8 pwm) +{ + struct tda10023_state* state = NULL; + int i; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); + state->pwm = pwm; + for (i=0; i < sizeof(tda10023_inittab)/sizeof(*tda10023_inittab);i+=3) { + if (tda10023_inittab[i] == 0x00) { + state->reg0 = tda10023_inittab[i+2]; + break; + } + } + + // Wakeup if in standby + tda10023_writereg (state, 0x00, 0x33); + /* check if the demod is there */ + if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops tda10023_ops = { + + .info = { + .name = "Philips TDA10023 DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */ + .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */ + .caps = 0x400 | //FE_CAN_QAM_4 + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | + FE_CAN_QAM_128 | FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO + }, + + .release = tda10023_release, + + .init = tda10023_init, + .sleep = tda10023_sleep, + .i2c_gate_ctrl = tda10023_i2c_gate_ctrl, + + .set_frontend = tda10023_set_parameters, + .get_frontend = tda10023_get_frontend, + + .read_status = tda10023_read_status, + .read_ber = tda10023_read_ber, + .read_signal_strength = tda10023_read_signal_strength, + .read_snr = tda10023_read_snr, + .read_ucblocks = tda10023_read_ucblocks, +}; + + +MODULE_DESCRIPTION("Philips TDA10023 DVB-C demodulator driver"); +MODULE_AUTHOR("Georg Acher, Hartmut Birr"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(tda10023_attach); diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h new file mode 100644 index 000000000000..484935986c54 --- /dev/null +++ b/drivers/media/dvb/frontends/tda1002x.h @@ -0,0 +1,59 @@ +/* + TDA10021/TDA10023 - Single Chip Cable Channel Receiver driver module + used on the the Siemens DVB-C cards + + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2004 Markus Schulz + Support for TDA10021 + + 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 TDA1002x_H +#define TDA1002x_H + +#include + +struct tda1002x_config +{ + /* the demodulator's i2c address */ + u8 demod_address; +}; + +#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) +extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, + struct i2c_adapter* i2c, u8 pwm); +#else +static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, + struct i2c_adapter* i2c, u8 pwm) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA10021 + +#if defined(CONFIG_DVB_TDA10023) || (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE)) +extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, + struct i2c_adapter* i2c, u8 pwm); +#else +static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, + struct i2c_adapter* i2c, u8 pwm) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA10023 + +#endif // TDA1002x_H diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 3cd319ff0e68..7751628e1415 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -67,6 +67,7 @@ config DVB_BUDGET select DVB_L64781 if !DVB_FE_CUSTOMISE select DVB_TDA8083 if !DVB_FE_CUSTOMISE select DVB_TDA10021 if !DVB_FE_CUSTOMISE + select DVB_TDA10023 if !DVB_FE_CUSTOMISE select DVB_S5H1420 if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE @@ -111,6 +112,7 @@ config DVB_BUDGET_AV select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_TDA10021 if !DVB_FE_CUSTOMISE + select DVB_TDA10023 if !DVB_FE_CUSTOMISE select DVB_TUA6100 if !DVB_FE_CUSTOMISE select FW_LOADER help diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 54ca3a3288e7..5680aa57c93e 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -35,7 +35,7 @@ #include "budget.h" #include "stv0299.h" -#include "tda10021.h" +#include "tda1002x.h" #include "tda1004x.h" #include "tua6100.h" #include "dvb-pll.h" @@ -611,37 +611,60 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = { static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget *budget = (struct budget *) fe->dvb->priv; - u8 buf[4]; + u8 buf[6]; struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + int i; +#define CU1216_IF 36125000 #define TUNER_MUL 62500 - u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x86; + buf[2] = 0xce; buf[3] = (params->frequency < 150000000 ? 0x01 : params->frequency < 445000000 ? 0x02 : 0x04); + buf[4] = 0xde; + buf[5] = 0x20; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; + + /* wait for the pll lock */ + msg.flags = I2C_M_RD; + msg.len = 1; + for (i = 0; i < 20; i++) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40)) + break; + msleep(10); + } + + /* switch the charge pump to the lower current */ + msg.flags = 0; + msg.len = 2; + msg.buf = &buf[2]; + buf[2] &= ~0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; } -static struct tda10021_config philips_cu1216_config = { +static struct tda1002x_config philips_cu1216_config = { .demod_address = 0x0c, }; -static struct tda10021_config philips_cu1216_config_altaddress = { +static struct tda1002x_config philips_cu1216_config_altaddress = { .demod_address = 0x0d, }; - - - static int philips_tu1216_tuner_init(struct dvb_frontend *fe) { struct budget *budget = (struct budget *) fe->dvb->priv; @@ -888,24 +911,28 @@ static u8 read_pwm(struct budget_av *budget_av) return pwm; } -#define SUBID_DVBS_KNC1 0x0010 -#define SUBID_DVBS_KNC1_PLUS 0x0011 -#define SUBID_DVBS_TYPHOON 0x4f56 -#define SUBID_DVBS_CINERGY1200 0x1154 -#define SUBID_DVBS_CYNERGY1200N 0x1155 - -#define SUBID_DVBS_TV_STAR 0x0014 -#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 - -#define SUBID_DVBT_KNC1_PLUS 0x0031 -#define SUBID_DVBT_KNC1 0x0030 -#define SUBID_DVBT_CINERGY1200 0x1157 +#define SUBID_DVBS_KNC1 0x0010 +#define SUBID_DVBS_KNC1_PLUS 0x0011 +#define SUBID_DVBS_TYPHOON 0x4f56 +#define SUBID_DVBS_CINERGY1200 0x1154 +#define SUBID_DVBS_CYNERGY1200N 0x1155 +#define SUBID_DVBS_TV_STAR 0x0014 +#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_EASYWATCH_MK3 0x002c +#define SUBID_DVBC_KNC1 0x0020 +#define SUBID_DVBC_KNC1_PLUS 0x0021 +#define SUBID_DVBC_KNC1_MK3 0x0022 +#define SUBID_DVBC_KNC1_PLUS_MK3 0x0023 +#define SUBID_DVBC_CINERGY1200 0x1156 +#define SUBID_DVBC_CINERGY1200_MK3 0x1176 + +#define SUBID_DVBT_KNC1_PLUS 0x0031 +#define SUBID_DVBT_KNC1 0x0030 +#define SUBID_DVBT_CINERGY1200 0x1157 static void frontend_init(struct budget_av *budget_av) { @@ -924,6 +951,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: case SUBID_DVBC_EASYWATCH: + case SUBID_DVBC_KNC1_PLUS_MK3: saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -980,6 +1008,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_CINERGY1200: case SUBID_DVBC_EASYWATCH: budget_av->reinitialise_demod = 1; + budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); @@ -992,6 +1021,20 @@ static void frontend_init(struct budget_av *budget_av) } break; + case SUBID_DVBC_EASYWATCH_MK3: + case SUBID_DVBC_CINERGY1200_MK3: + case SUBID_DVBC_KNC1_MK3: + case SUBID_DVBC_KNC1_PLUS_MK3: + budget_av->reinitialise_demod = 1; + budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; + fe = dvb_attach(tda10023_attach, &philips_cu1216_config, + &budget_av->budget.i2c_adap, + read_pwm(budget_av)); + if (fe) { + fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; + } + break; + case SUBID_DVBT_KNC1: case SUBID_DVBT_KNC1_PLUS: case SUBID_DVBT_CINERGY1200: @@ -1220,12 +1263,16 @@ 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(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); +MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3); +MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3); MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S); MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S); MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C); +MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3); MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T); static struct pci_device_id pci_tbl[] = { @@ -1239,13 +1286,17 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), + MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), + MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022), + MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023), MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031), MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154), MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155), MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156), + MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176), MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157), { .vendor = 0, diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index cef9d8d8a122..6b97dc1e6b65 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -109,6 +109,19 @@ static int start_ts_capture(struct budget *budget) saa7146_write(dev, MC2, (MASK_10 | MASK_26)); saa7146_write(dev, BRS_CTRL, 0x60000000); break; + case BUDGET_CIN1200C_MK3: + case BUDGET_KNC1C_MK3: + case BUDGET_KNC1CP_MK3: + if (budget->video_port == BUDGET_VIDEO_PORTA) { + saa7146_write(dev, DD1_INIT, 0x06000200); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + saa7146_write(dev, BRS_CTRL, 0x00000000); + } else { + saa7146_write(dev, DD1_INIT, 0x00000600); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + saa7146_write(dev, BRS_CTRL, 0x60000000); + } + break; default: if (budget->video_port == BUDGET_VIDEO_PORTA) { saa7146_write(dev, DD1_INIT, 0x06000200); @@ -418,6 +431,9 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, case BUDGET_KNC1C: case BUDGET_KNC1CP: case BUDGET_CIN1200C: + case BUDGET_KNC1C_MK3: + case BUDGET_KNC1CP_MK3: + case BUDGET_CIN1200C_MK3: budget->buffer_width = TS_WIDTH_DVBC; max_bufsize = TS_MAX_BUFSIZE_K_DVBC; height_mask = TS_HEIGHT_MASK_DVBC; diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index e8a5c79178e1..d764ffa728b0 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -99,6 +99,9 @@ static struct saa7146_pci_extension_data x_var = { \ #define BUDGET_KNC1CP 12 #define BUDGET_KNC1TP 13 #define BUDGET_TVSTAR 14 +#define BUDGET_CIN1200C_MK3 15 +#define BUDGET_KNC1C_MK3 16 +#define BUDGET_KNC1CP_MK3 17 #define BUDGET_VIDEO_PORTA 0 #define BUDGET_VIDEO_PORTB 1 -- cgit v1.2.3 From dc120b0734fcc6a4c42c73790a02f2fa74a7a326 Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sat, 21 Apr 2007 19:44:10 -0300 Subject: V4L/DVB (5544): Budget-av: Make inversion setting configurable, add KNC ONE V1.0 card Make the inversion setting configurable. The KNC ONE V1.0 uses non inverted setting for the inversion and add the KNC ONE V1.0 card. Signed-off-by: Hartmut Birr Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10021.c | 26 ++++++++++++++++---------- drivers/media/dvb/frontends/tda1002x.h | 1 + drivers/media/dvb/ttpci/budget-av.c | 2 ++ 3 files changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/media/dvb/frontends') diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 304f1f9b8008..110536843e8e 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -53,9 +53,6 @@ struct tda10021_state { static int verbose; #define XIN 57840000UL -#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) -#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) -#define HAS_INVERSION(reg0) (!(reg0 & 0x20)) #define FIN (XIN >> 4) @@ -97,7 +94,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) int ret; ret = i2c_transfer (state->i2c, msg, 2); - if (ret != 2) + // Don't print an error message if the id is read. + if (ret != 2 && reg != 0x1a) printk("DVB: TDA10021: %s: readreg error (ret == %i)\n", __FUNCTION__, ret); return b1[0]; @@ -136,10 +134,10 @@ static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0, { reg0 |= state->reg0 & 0x63; - if (INVERSION_ON == inversion) - ENABLE_INVERSION(reg0); - else if (INVERSION_OFF == inversion) - DISABLE_INVERSION(reg0); + if ((INVERSION_ON == inversion) ^ (state->config->invert == 0)) + reg0 &= ~0x20; + else + reg0 |= 0x20; _tda10021_writereg (state, 0x00, reg0 & 0xfe); _tda10021_writereg (state, 0x00, reg0 | 0x01); @@ -248,6 +246,9 @@ static int tda10021_set_parameters (struct dvb_frontend *fe, if (qam < 0 || qam > 5) return -EINVAL; + if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF) + return -EINVAL; + //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); if (fe->ops.tuner_ops.set_params) { @@ -356,7 +357,7 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa -((s32)p->u.qam.symbol_rate * afc) >> 10); } - p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF; + p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF; p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; p->u.qam.fec_inner = FEC_NONE; @@ -403,6 +404,7 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, u8 pwm) { struct tda10021_state* state = NULL; + u8 id; /* allocate memory for the internal state */ state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL); @@ -415,7 +417,11 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, state->reg0 = tda10021_inittab[0]; /* check if the demod is there */ - if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; + id = tda10021_readreg(state, 0x1a); + if ((id & 0xf0) != 0x70) goto error; + + printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n", + state->config->demod_address, id); /* create dvb_frontend */ memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops)); diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h index 484935986c54..e9094d8123f6 100644 --- a/drivers/media/dvb/frontends/tda1002x.h +++ b/drivers/media/dvb/frontends/tda1002x.h @@ -30,6 +30,7 @@ struct tda1002x_config { /* the demodulator's i2c address */ u8 demod_address; + u8 invert; }; #if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 5680aa57c93e..0e817d6f1ce5 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -659,10 +659,12 @@ static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f static struct tda1002x_config philips_cu1216_config = { .demod_address = 0x0c, + .invert = 1, }; static struct tda1002x_config philips_cu1216_config_altaddress = { .demod_address = 0x0d, + .invert = 0, }; static int philips_tu1216_tuner_init(struct dvb_frontend *fe) -- cgit v1.2.3