Hi, here's another version of the patch. I copied some initial register settings from the (preliminary) SU1278 specs, which improved my signal strength and SNR a bit. Note that this version may break/worsen the functionality for non-SU1278 users. Is there a chance to get the final SU1278 specs from Philips, TechnoTrend or Hauppauge? Does anybody have a contact? Regards, -- Steffen Beyer <sbeyer@reactor.de> GnuPG key fingerprint: 6C9B 2844 AF75 AC7A C38C 9FFD 06CB A788 398B D2D9 Public key available upon request or at http://wwwkeys.pgp.net
--- stv0299.c 31 Jul 2003 23:15:45 -0000 1.8 +++ stv0299.c 20 Nov 2003 20:03:06 -0000 @@ -40,6 +40,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> +#include <asm/div64.h> #include "dvb_frontend.h" #include "compat.h" @@ -89,8 +90,8 @@ u8 init_tab [] = { /* clock registers */ 0x01, 0x15, /* K = 0, DIRCLK = 0, M = 0x15 */ - 0x02, 0x30, /* STDBY = 0, VCO = 0 (ON), SERCLK = 0, P = 0 */ - /* f_VCO = 4MHz * 4 * (M+1) / (K+1) = 352 MHz */ + 0x02, 0x00, /* M-CLK = 88 MHz, doesn't fit STV0299 specs */ + /* taken from SU1278 specs */ 0x03, 0x00, /* auxiliary clock not used */ 0x04, 0x7d, /* F22FR = 0x7d */ /* F22 = f_VCO / 128 / 0x7d = 22 kHz */ @@ -99,28 +100,30 @@ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ /* general purpose DAC registers */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x06, 0x00, /* DAC not used */ + /* taken from SU1278 specs */ 0x07, 0x00, /* DAC LSB */ /* DiSEqC registers */ - 0x08, 0x40, /* DiSEqC off */ + 0x08, 0x00, /* DiSEqC off */ 0x09, 0x00, /* FIFO */ /* Input/Output configuration register */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0c, 0x50, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ /* OP0 ctl = Normal, OP0 val = 1 (18 V) */ /* Nyquist filter = 00, QPSK reverse = 0 */ /* AGC1 control register */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0d, 0x81, /* DC offset compensation = ON, beta_agc1 = 1 */ + /* taken from SU1278 specs */ /* Timing loop register */ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d + 0x10, 0x39, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on - 0x13, 0xb6, // alpha_car b:4 a:0 noise est:256ks derot:on + 0x12, 0x39, // CFD, taken from SU1278 specs + 0x13, 0xb5, // ACLC, taken from SU1278 specs 0x14, 0x93, // beat carc:0 d:0 e:0xf phase detect algo: 1 0x15, 0xc9, // lock detector threshold @@ -151,7 +154,6 @@ 0x2b, 0x0f, // 3/4 threshold 0x2c, 0x09, // 5/6 threshold 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, 0x31, 0x1f, // test all FECs @@ -161,6 +163,7 @@ 0x0b, 0x00, 0x27, 0x00, + 0x2e, 0x00, 0x2f, 0x00, 0x30, 0x00, 0x35, 0x00, @@ -189,7 +192,6 @@ 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, - 0x4f, 0x00 }; @@ -254,20 +256,21 @@ int pll_write (struct dvb_i2c_bus *i2c, u8 data [4], int ftype) { int ret; - u8 rpt1 [] = { 0x05, 0xb5 }; /* enable i2c repeater on stv0299 */ /* TSA5059 i2c-bus address */ u8 addr = (ftype == PHILIPS_SU1278SH) ? 0x60 : 0x61; - struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 }, - { addr: addr, flags: 0, buf: data, len: 4 }}; + struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = 4 }; dprintk ("%s\n", __FUNCTION__); - ret = i2c->xfer (i2c, msg, 2); + stv0299_writereg(i2c, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - if (ret != 2) + ret = i2c->xfer (i2c, &msg, 1); + + if (ret != 1) dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); + stv0299_writereg(i2c, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - return (ret != 2) ? -1 : 0; + return (ret != 1) ? -1 : 0; } @@ -303,31 +306,54 @@ * reference clock comparision frequency of 125 kHz. */ static -int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) +int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) { - u32 div = freq / 125; - - u8 buf[4] = { (div >> 8) & 0x7f, div & 0xff, 0x84 }; + u32 div; + u8 buf[4]; - if (ftype == PHILIPS_SU1278SH) - /* activate f_xtal/f_comp signal output */ - /* charge pump current C0/C1 = 00 */ - buf[3] = 0x20; - else - buf[3] = freq > 1530000 ? 0xc0 : 0xc4; + if ((freq < 950000) || (freq > 2150000)) return -EINVAL; + // setup frequency divisor + div = freq / 1000; + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x81 | ((div & 0x18000) >> 10); + buf[3] = 0; + + // tuner-specific settings + switch(ftype) { + case PHILIPS_SU1278SH: + buf[3] |= 0x20; + + if (srate < 4000000) buf[3] |= 1; + + if (freq <= 1250000) buf[3] |= 0; + else if (freq <= 1550000) buf[3] |= 0x40; + // violates the SU1278 specs, but seems to work better + // else if (freq <= 2050000) buf[3] |= 0x80; + else if (freq <= 2150000) buf[3] |= 0xC0; + break; + + case ALPS_BSRU6: + buf[3] |= 0xC0; + break; + + default: + return -EINVAL; + } + dprintk ("%s\n", __FUNCTION__); return pll_write (i2c, buf, ftype); } static -int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) +int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) { if (ftype == LG_TDQF_S001F) return sl1935_set_tv_freq(i2c, freq, ftype); else - return tsa5059_set_tv_freq(i2c, freq, ftype); + return tsa5059_set_tv_freq(i2c, freq, ftype, srate); } #if 0 @@ -365,7 +391,7 @@ /* AGC1 reference register setup */ if (ftype == PHILIPS_SU1278SH) - stv0299_writereg (i2c, 0x0f, 0xd2); /* Iagc = Inverse, m1 = 18 */ + stv0299_writereg (i2c, 0x0f, 0x92); /* Iagc = Inverse, m1 = 18 */ else stv0299_writereg (i2c, 0x0f, 0x52); /* Iagc = Normal, m1 = 18 */ @@ -593,39 +619,63 @@ static -int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int ftype) { + u64 big = srate; u32 ratio; - u32 tmp; - u8 aclk = 0xb4, bclk = 0x51; + u8 aclk = 0; + u8 bclk = 0; + u8 m1; + + if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + + switch (ftype) { + case PHILIPS_SU1278SH: + aclk = 0xb5; + if (srate < 2000000) bclk = 0x86; + else if (srate < 5000000) bclk = 0x89; + else if (srate < 15000000) bclk = 0x8f; + else if (srate < 45000000) bclk = 0x95; - if (srate > M_CLK) - srate = M_CLK; - if (srate < 500000) - srate = 500000; - - if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + m1 = 0x14; + if (srate < 4000000) m1 = 0x10; + break; + + case ALPS_BSRU6: + default: + if (srate <= 1500000) { aclk = 0xb7; bclk = 0x87; } + else if (srate <= 3000000) { aclk = 0xb7; bclk = 0x8b; } + else if (srate <= 7000000) { aclk = 0xb7; bclk = 0x8f; } + else if (srate <= 14000000) { aclk = 0xb7; bclk = 0x93; } + else if (srate <= 30000000) { aclk = 0xb6; bclk = 0x93; } + else if (srate <= 45000000) { aclk = 0xb4; bclk = 0x91; } + + m1 = 0x12; + break; + } -#define FIN (M_CLK >> 4) - tmp = srate << 4; - ratio = tmp / FIN; - - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - stv0299_writereg (i2c, 0x13, aclk); stv0299_writereg (i2c, 0x14, bclk); + + dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); + + big = big << 20; + + dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); + + do_div(big, M_CLK); + + dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); + + ratio = big << 4; + + dprintk("%s : ratio = %i\n", __FUNCTION__, ratio); + stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); + stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1); return 0; } @@ -740,9 +790,9 @@ { struct dvb_frontend_parameters *p = arg; - pll_set_tv_freq (i2c, p->frequency, tuner_type); + pll_set_tv_freq (i2c, p->frequency, tuner_type, p->u.qpsk.symbol_rate); stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); - stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate); + stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, tuner_type); stv0299_writereg (i2c, 0x22, 0x00); stv0299_writereg (i2c, 0x23, 0x00); stv0299_readreg (i2c, 0x23);
Attachment:
pgp00004.pgp
Description: PGP signature