Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     Driver for Philips TDA8083 based QPSK Demodulator
0004 
0005     Copyright (C) 2001 Convergence Integrated Media GmbH
0006 
0007     written by Ralph Metzler <ralph@convergence.de>
0008 
0009     adoption to the new DVB frontend API and diagnostic ioctl's
0010     by Holger Waechtler <holger@convergence.de>
0011 
0012 
0013 */
0014 
0015 #include <linux/init.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/string.h>
0019 #include <linux/slab.h>
0020 #include <linux/jiffies.h>
0021 #include <media/dvb_frontend.h>
0022 #include "tda8083.h"
0023 
0024 
0025 struct tda8083_state {
0026     struct i2c_adapter* i2c;
0027     /* configuration settings */
0028     const struct tda8083_config* config;
0029     struct dvb_frontend frontend;
0030 };
0031 
0032 static int debug;
0033 #define dprintk(args...) \
0034     do { \
0035         if (debug) printk(KERN_DEBUG "tda8083: " args); \
0036     } while (0)
0037 
0038 
0039 static u8 tda8083_init_tab [] = {
0040     0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
0041     0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
0042     0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
0043     0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
0044     0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
0045     0x00, 0x00, 0x00, 0x00
0046 };
0047 
0048 
0049 static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
0050 {
0051     int ret;
0052     u8 buf [] = { reg, data };
0053     struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
0054 
0055     ret = i2c_transfer(state->i2c, &msg, 1);
0056 
0057     if (ret != 1)
0058         dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
0059             __func__, reg, ret);
0060 
0061     return (ret != 1) ? -1 : 0;
0062 }
0063 
0064 static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
0065 {
0066     int ret;
0067     struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
0068                { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
0069 
0070     ret = i2c_transfer(state->i2c, msg, 2);
0071 
0072     if (ret != 2)
0073         dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
0074             __func__, reg1, ret);
0075 
0076     return ret == 2 ? 0 : -1;
0077 }
0078 
0079 static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
0080 {
0081     u8 val;
0082 
0083     tda8083_readregs (state, reg, &val, 1);
0084 
0085     return val;
0086 }
0087 
0088 static int tda8083_set_inversion(struct tda8083_state *state,
0089                  enum fe_spectral_inversion inversion)
0090 {
0091     /*  XXX FIXME: implement other modes than FEC_AUTO */
0092     if (inversion == INVERSION_AUTO)
0093         return 0;
0094 
0095     return -EINVAL;
0096 }
0097 
0098 static int tda8083_set_fec(struct tda8083_state *state, enum fe_code_rate fec)
0099 {
0100     if (fec == FEC_AUTO)
0101         return tda8083_writereg (state, 0x07, 0xff);
0102 
0103     if (fec >= FEC_1_2 && fec <= FEC_8_9)
0104         return tda8083_writereg (state, 0x07, 1 << (FEC_8_9 - fec));
0105 
0106     return -EINVAL;
0107 }
0108 
0109 static enum fe_code_rate tda8083_get_fec(struct tda8083_state *state)
0110 {
0111     u8 index;
0112     static enum fe_code_rate fec_tab[] = {
0113         FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
0114         FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8
0115     };
0116 
0117     index = tda8083_readreg(state, 0x0e) & 0x07;
0118 
0119     return fec_tab [index];
0120 }
0121 
0122 static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
0123 {
0124     u32 ratio;
0125     u32 tmp;
0126     u8 filter;
0127 
0128     if (srate > 32000000)
0129         srate = 32000000;
0130     if (srate < 500000)
0131         srate = 500000;
0132 
0133     filter = 0;
0134     if (srate < 24000000)
0135         filter = 2;
0136     if (srate < 16000000)
0137         filter = 3;
0138 
0139     tmp = 31250 << 16;
0140     ratio = tmp / srate;
0141 
0142     tmp = (tmp % srate) << 8;
0143     ratio = (ratio << 8) + tmp / srate;
0144 
0145     tmp = (tmp % srate) << 8;
0146     ratio = (ratio << 8) + tmp / srate;
0147 
0148     dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio);
0149 
0150     tda8083_writereg (state, 0x05, filter);
0151     tda8083_writereg (state, 0x02, (ratio >> 16) & 0xff);
0152     tda8083_writereg (state, 0x03, (ratio >>  8) & 0xff);
0153     tda8083_writereg (state, 0x04, (ratio      ) & 0xff);
0154 
0155     tda8083_writereg (state, 0x00, 0x3c);
0156     tda8083_writereg (state, 0x00, 0x04);
0157 
0158     return 1;
0159 }
0160 
0161 static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
0162 {
0163     unsigned long start = jiffies;
0164 
0165     while (time_is_after_jiffies(start + timeout) &&
0166            !(tda8083_readreg(state, 0x02) & 0x80))
0167     {
0168         msleep(50);
0169     }
0170 }
0171 
0172 static int tda8083_set_tone(struct tda8083_state *state,
0173                 enum fe_sec_tone_mode tone)
0174 {
0175     tda8083_writereg (state, 0x26, 0xf1);
0176 
0177     switch (tone) {
0178     case SEC_TONE_OFF:
0179         return tda8083_writereg (state, 0x29, 0x00);
0180     case SEC_TONE_ON:
0181         return tda8083_writereg (state, 0x29, 0x80);
0182     default:
0183         return -EINVAL;
0184     }
0185 }
0186 
0187 static int tda8083_set_voltage(struct tda8083_state *state,
0188                    enum fe_sec_voltage voltage)
0189 {
0190     switch (voltage) {
0191     case SEC_VOLTAGE_13:
0192         return tda8083_writereg (state, 0x20, 0x00);
0193     case SEC_VOLTAGE_18:
0194         return tda8083_writereg (state, 0x20, 0x11);
0195     default:
0196         return -EINVAL;
0197     }
0198 }
0199 
0200 static int tda8083_send_diseqc_burst(struct tda8083_state *state,
0201                      enum fe_sec_mini_cmd burst)
0202 {
0203     switch (burst) {
0204     case SEC_MINI_A:
0205         tda8083_writereg (state, 0x29, (5 << 2));  /* send burst A */
0206         break;
0207     case SEC_MINI_B:
0208         tda8083_writereg (state, 0x29, (7 << 2));  /* send B */
0209         break;
0210     default:
0211         return -EINVAL;
0212     }
0213 
0214     tda8083_wait_diseqc_fifo (state, 100);
0215 
0216     return 0;
0217 }
0218 
0219 static int tda8083_send_diseqc_msg(struct dvb_frontend *fe,
0220                    struct dvb_diseqc_master_cmd *m)
0221 {
0222     struct tda8083_state* state = fe->demodulator_priv;
0223     int i;
0224 
0225     tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
0226 
0227     for (i=0; i<m->msg_len; i++)
0228         tda8083_writereg (state, 0x23 + i, m->msg[i]);
0229 
0230     tda8083_writereg (state, 0x29, (m->msg_len - 3) | (3 << 2)); /* send!! */
0231 
0232     tda8083_wait_diseqc_fifo (state, 100);
0233 
0234     return 0;
0235 }
0236 
0237 static int tda8083_read_status(struct dvb_frontend *fe,
0238                    enum fe_status *status)
0239 {
0240     struct tda8083_state* state = fe->demodulator_priv;
0241 
0242     u8 signal = ~tda8083_readreg (state, 0x01);
0243     u8 sync = tda8083_readreg (state, 0x02);
0244 
0245     *status = 0;
0246 
0247     if (signal > 10)
0248         *status |= FE_HAS_SIGNAL;
0249 
0250     if (sync & 0x01)
0251         *status |= FE_HAS_CARRIER;
0252 
0253     if (sync & 0x02)
0254         *status |= FE_HAS_VITERBI;
0255 
0256     if (sync & 0x10)
0257         *status |= FE_HAS_SYNC;
0258 
0259     if (sync & 0x20) /* frontend can not lock */
0260         *status |= FE_TIMEDOUT;
0261 
0262     if ((sync & 0x1f) == 0x1f)
0263         *status |= FE_HAS_LOCK;
0264 
0265     return 0;
0266 }
0267 
0268 static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
0269 {
0270     struct tda8083_state* state = fe->demodulator_priv;
0271     int ret;
0272     u8 buf[3];
0273 
0274     if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
0275         return ret;
0276 
0277     *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
0278 
0279     return 0;
0280 }
0281 
0282 static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
0283 {
0284     struct tda8083_state* state = fe->demodulator_priv;
0285 
0286     u8 signal = ~tda8083_readreg (state, 0x01);
0287     *strength = (signal << 8) | signal;
0288 
0289     return 0;
0290 }
0291 
0292 static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
0293 {
0294     struct tda8083_state* state = fe->demodulator_priv;
0295 
0296     u8 _snr = tda8083_readreg (state, 0x08);
0297     *snr = (_snr << 8) | _snr;
0298 
0299     return 0;
0300 }
0301 
0302 static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
0303 {
0304     struct tda8083_state* state = fe->demodulator_priv;
0305 
0306     *ucblocks = tda8083_readreg(state, 0x0f);
0307     if (*ucblocks == 0xff)
0308         *ucblocks = 0xffffffff;
0309 
0310     return 0;
0311 }
0312 
0313 static int tda8083_set_frontend(struct dvb_frontend *fe)
0314 {
0315     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0316     struct tda8083_state* state = fe->demodulator_priv;
0317 
0318     if (fe->ops.tuner_ops.set_params) {
0319         fe->ops.tuner_ops.set_params(fe);
0320         if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
0321     }
0322 
0323     tda8083_set_inversion (state, p->inversion);
0324     tda8083_set_fec(state, p->fec_inner);
0325     tda8083_set_symbolrate(state, p->symbol_rate);
0326 
0327     tda8083_writereg (state, 0x00, 0x3c);
0328     tda8083_writereg (state, 0x00, 0x04);
0329 
0330     return 0;
0331 }
0332 
0333 static int tda8083_get_frontend(struct dvb_frontend *fe,
0334                 struct dtv_frontend_properties *p)
0335 {
0336     struct tda8083_state* state = fe->demodulator_priv;
0337 
0338     /*  FIXME: get symbolrate & frequency offset...*/
0339     /*p->frequency = ???;*/
0340     p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
0341             INVERSION_ON : INVERSION_OFF;
0342     p->fec_inner = tda8083_get_fec(state);
0343     /*p->symbol_rate = tda8083_get_symbolrate (state);*/
0344 
0345     return 0;
0346 }
0347 
0348 static int tda8083_sleep(struct dvb_frontend* fe)
0349 {
0350     struct tda8083_state* state = fe->demodulator_priv;
0351 
0352     tda8083_writereg (state, 0x00, 0x02);
0353     return 0;
0354 }
0355 
0356 static int tda8083_init(struct dvb_frontend* fe)
0357 {
0358     struct tda8083_state* state = fe->demodulator_priv;
0359     int i;
0360 
0361     for (i=0; i<44; i++)
0362         tda8083_writereg (state, i, tda8083_init_tab[i]);
0363 
0364     tda8083_writereg (state, 0x00, 0x3c);
0365     tda8083_writereg (state, 0x00, 0x04);
0366 
0367     return 0;
0368 }
0369 
0370 static int tda8083_diseqc_send_burst(struct dvb_frontend *fe,
0371                      enum fe_sec_mini_cmd burst)
0372 {
0373     struct tda8083_state* state = fe->demodulator_priv;
0374 
0375     tda8083_send_diseqc_burst (state, burst);
0376     tda8083_writereg (state, 0x00, 0x3c);
0377     tda8083_writereg (state, 0x00, 0x04);
0378 
0379     return 0;
0380 }
0381 
0382 static int tda8083_diseqc_set_tone(struct dvb_frontend *fe,
0383                    enum fe_sec_tone_mode tone)
0384 {
0385     struct tda8083_state* state = fe->demodulator_priv;
0386 
0387     tda8083_set_tone (state, tone);
0388     tda8083_writereg (state, 0x00, 0x3c);
0389     tda8083_writereg (state, 0x00, 0x04);
0390 
0391     return 0;
0392 }
0393 
0394 static int tda8083_diseqc_set_voltage(struct dvb_frontend *fe,
0395                       enum fe_sec_voltage voltage)
0396 {
0397     struct tda8083_state* state = fe->demodulator_priv;
0398 
0399     tda8083_set_voltage (state, voltage);
0400     tda8083_writereg (state, 0x00, 0x3c);
0401     tda8083_writereg (state, 0x00, 0x04);
0402 
0403     return 0;
0404 }
0405 
0406 static void tda8083_release(struct dvb_frontend* fe)
0407 {
0408     struct tda8083_state* state = fe->demodulator_priv;
0409     kfree(state);
0410 }
0411 
0412 static const struct dvb_frontend_ops tda8083_ops;
0413 
0414 struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
0415                     struct i2c_adapter* i2c)
0416 {
0417     struct tda8083_state* state = NULL;
0418 
0419     /* allocate memory for the internal state */
0420     state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
0421     if (state == NULL) goto error;
0422 
0423     /* setup the state */
0424     state->config = config;
0425     state->i2c = i2c;
0426 
0427     /* check if the demod is there */
0428     if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
0429 
0430     /* create dvb_frontend */
0431     memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
0432     state->frontend.demodulator_priv = state;
0433     return &state->frontend;
0434 
0435 error:
0436     kfree(state);
0437     return NULL;
0438 }
0439 
0440 static const struct dvb_frontend_ops tda8083_ops = {
0441     .delsys = { SYS_DVBS },
0442     .info = {
0443         .name           = "Philips TDA8083 DVB-S",
0444         .frequency_min_hz   =  920 * MHz,     /* TDA8060 */
0445         .frequency_max_hz   = 2200 * MHz,    /* TDA8060 */
0446         .frequency_stepsize_hz  =  125 * kHz,
0447         .symbol_rate_min    = 12000000,
0448         .symbol_rate_max    = 30000000,
0449     /*      .symbol_rate_tolerance  = ???,*/
0450         .caps = FE_CAN_INVERSION_AUTO |
0451             FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0452             FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
0453             FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
0454             FE_CAN_QPSK | FE_CAN_MUTE_TS
0455     },
0456 
0457     .release = tda8083_release,
0458 
0459     .init = tda8083_init,
0460     .sleep = tda8083_sleep,
0461 
0462     .set_frontend = tda8083_set_frontend,
0463     .get_frontend = tda8083_get_frontend,
0464 
0465     .read_status = tda8083_read_status,
0466     .read_signal_strength = tda8083_read_signal_strength,
0467     .read_snr = tda8083_read_snr,
0468     .read_ber = tda8083_read_ber,
0469     .read_ucblocks = tda8083_read_ucblocks,
0470 
0471     .diseqc_send_master_cmd = tda8083_send_diseqc_msg,
0472     .diseqc_send_burst = tda8083_diseqc_send_burst,
0473     .set_tone = tda8083_diseqc_set_tone,
0474     .set_voltage = tda8083_diseqc_set_voltage,
0475 };
0476 
0477 module_param(debug, int, 0644);
0478 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
0479 
0480 MODULE_DESCRIPTION("Philips TDA8083 DVB-S Demodulator");
0481 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
0482 MODULE_LICENSE("GPL");
0483 
0484 EXPORT_SYMBOL(tda8083_attach);