linux/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
<<
>>
Prefs
   1/*
   2 *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
   3 *
   4 *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include "mxl111sf-tuner.h"
  22#include "mxl111sf-phy.h"
  23#include "mxl111sf-reg.h"
  24
  25/* debug */
  26static int mxl111sf_tuner_debug;
  27module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
  28MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
  29
  30#define mxl_dbg(fmt, arg...) \
  31        if (mxl111sf_tuner_debug) \
  32                mxl_printk(KERN_DEBUG, fmt, ##arg)
  33
  34/* ------------------------------------------------------------------------ */
  35
  36struct mxl111sf_tuner_state {
  37        struct mxl111sf_state *mxl_state;
  38
  39        const struct mxl111sf_tuner_config *cfg;
  40
  41        enum mxl_if_freq if_freq;
  42
  43        u32 frequency;
  44        u32 bandwidth;
  45};
  46
  47static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
  48                                   u8 addr, u8 *data)
  49{
  50        return (state->cfg->read_reg) ?
  51                state->cfg->read_reg(state->mxl_state, addr, data) :
  52                -EINVAL;
  53}
  54
  55static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
  56                                    u8 addr, u8 data)
  57{
  58        return (state->cfg->write_reg) ?
  59                state->cfg->write_reg(state->mxl_state, addr, data) :
  60                -EINVAL;
  61}
  62
  63static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
  64                               struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
  65{
  66        return (state->cfg->program_regs) ?
  67                state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
  68                -EINVAL;
  69}
  70
  71static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
  72                                          int onoff)
  73{
  74        return (state->cfg->top_master_ctrl) ?
  75                state->cfg->top_master_ctrl(state->mxl_state, onoff) :
  76                -EINVAL;
  77}
  78
  79/* ------------------------------------------------------------------------ */
  80
  81static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
  82        {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
  83                               DIG_MODEINDEX, _A, _CSF, */
  84        {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
  85        {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
  86        {0,    0,    0}
  87};
  88
  89/* ------------------------------------------------------------------------ */
  90
  91static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
  92                                                                  u8 bw)
  93{
  94        u8 filt_bw;
  95
  96        /* set channel bandwidth */
  97        switch (bw) {
  98        case 0: /* ATSC */
  99                filt_bw = 25;
 100                break;
 101        case 1: /* QAM */
 102                filt_bw = 69;
 103                break;
 104        case 6:
 105                filt_bw = 21;
 106                break;
 107        case 7:
 108                filt_bw = 42;
 109                break;
 110        case 8:
 111                filt_bw = 63;
 112                break;
 113        default:
 114                pr_err("%s: invalid bandwidth setting!", __func__);
 115                return NULL;
 116        }
 117
 118        /* calculate RF channel */
 119        freq /= 1000000;
 120
 121        freq *= 64;
 122#if 0
 123        /* do round */
 124        freq += 0.5;
 125#endif
 126        /* set bandwidth */
 127        mxl_phy_tune_rf[0].data = filt_bw;
 128
 129        /* set RF */
 130        mxl_phy_tune_rf[1].data = (freq & 0xff);
 131        mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
 132
 133        /* start tune */
 134        return mxl_phy_tune_rf;
 135}
 136
 137static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
 138{
 139        int ret;
 140        u8 ctrl;
 141#if 0
 142        u16 iffcw;
 143        u32 if_freq;
 144#endif
 145        mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
 146                state->cfg->invert_spectrum, state->cfg->if_freq);
 147
 148        /* set IF polarity */
 149        ctrl = state->cfg->invert_spectrum;
 150
 151        ctrl |= state->cfg->if_freq;
 152
 153        ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
 154        if (mxl_fail(ret))
 155                goto fail;
 156
 157#if 0
 158        if_freq /= 1000000;
 159
 160        /* do round */
 161        if_freq += 0.5;
 162
 163        if (MXL_IF_LO == state->cfg->if_freq) {
 164                ctrl = 0x08;
 165                iffcw = (u16)(if_freq / (108 * 4096));
 166        } else if (MXL_IF_HI == state->cfg->if_freq) {
 167                ctrl = 0x08;
 168                iffcw = (u16)(if_freq / (216 * 4096));
 169        } else {
 170                ctrl = 0;
 171                iffcw = 0;
 172        }
 173
 174        ctrl |= (iffcw >> 8);
 175#endif
 176        ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
 177        if (mxl_fail(ret))
 178                goto fail;
 179
 180        ctrl &= 0xf0;
 181        ctrl |= 0x90;
 182
 183        ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
 184        if (mxl_fail(ret))
 185                goto fail;
 186
 187#if 0
 188        ctrl = iffcw & 0x00ff;
 189#endif
 190        ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
 191        if (mxl_fail(ret))
 192                goto fail;
 193
 194        state->if_freq = state->cfg->if_freq;
 195fail:
 196        return ret;
 197}
 198
 199static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
 200{
 201        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 202        static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
 203        int ret;
 204        u8 mxl_mode;
 205
 206        mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
 207
 208        /* stop tune */
 209        ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
 210        if (mxl_fail(ret))
 211                goto fail;
 212
 213        /* check device mode */
 214        ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
 215        if (mxl_fail(ret))
 216                goto fail;
 217
 218        /* Fill out registers for channel tune */
 219        reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
 220        if (!reg_ctrl_array)
 221                return -EINVAL;
 222
 223        ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
 224        if (mxl_fail(ret))
 225                goto fail;
 226
 227        if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
 228                /* IF tuner mode only */
 229                mxl1x1sf_tuner_top_master_ctrl(state, 0);
 230                mxl1x1sf_tuner_top_master_ctrl(state, 1);
 231                mxl1x1sf_tuner_set_if_output_freq(state);
 232        }
 233
 234        ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
 235        if (mxl_fail(ret))
 236                goto fail;
 237
 238        if (state->cfg->ant_hunt)
 239                state->cfg->ant_hunt(fe);
 240fail:
 241        return ret;
 242}
 243
 244static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
 245                                          int *rf_synth_lock,
 246                                          int *ref_synth_lock)
 247{
 248        int ret;
 249        u8 data;
 250
 251        *rf_synth_lock = 0;
 252        *ref_synth_lock = 0;
 253
 254        ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
 255        if (mxl_fail(ret))
 256                goto fail;
 257
 258        *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
 259        *rf_synth_lock  = ((data & 0x0c) == 0x0c) ? 1 : 0;
 260fail:
 261        return ret;
 262}
 263
 264#if 0
 265static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
 266                                         int onoff)
 267{
 268        return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
 269                                        onoff ? 1 : 0);
 270}
 271#endif
 272
 273/* ------------------------------------------------------------------------ */
 274
 275static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
 276{
 277        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 278        u32 delsys  = c->delivery_system;
 279        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 280        int ret;
 281        u8 bw;
 282
 283        mxl_dbg("()");
 284
 285        switch (delsys) {
 286        case SYS_ATSC:
 287        case SYS_ATSCMH:
 288                bw = 0; /* ATSC */
 289                break;
 290        case SYS_DVBC_ANNEX_B:
 291                bw = 1; /* US CABLE */
 292                break;
 293        case SYS_DVBT:
 294                switch (c->bandwidth_hz) {
 295                case 6000000:
 296                        bw = 6;
 297                        break;
 298                case 7000000:
 299                        bw = 7;
 300                        break;
 301                case 8000000:
 302                        bw = 8;
 303                        break;
 304                default:
 305                        pr_err("%s: bandwidth not set!", __func__);
 306                        return -EINVAL;
 307                }
 308                break;
 309        default:
 310                pr_err("%s: modulation type not supported!", __func__);
 311                return -EINVAL;
 312        }
 313        ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
 314        if (mxl_fail(ret))
 315                goto fail;
 316
 317        state->frequency = c->frequency;
 318        state->bandwidth = c->bandwidth_hz;
 319fail:
 320        return ret;
 321}
 322
 323/* ------------------------------------------------------------------------ */
 324
 325#if 0
 326static int mxl111sf_tuner_init(struct dvb_frontend *fe)
 327{
 328        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 329        int ret;
 330
 331        /* wake from standby handled by usb driver */
 332
 333        return ret;
 334}
 335
 336static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
 337{
 338        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 339        int ret;
 340
 341        /* enter standby mode handled by usb driver */
 342
 343        return ret;
 344}
 345#endif
 346
 347/* ------------------------------------------------------------------------ */
 348
 349static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
 350{
 351        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 352        int rf_locked, ref_locked, ret;
 353
 354        *status = 0;
 355
 356        ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
 357        if (mxl_fail(ret))
 358                goto fail;
 359        mxl_info("%s%s", rf_locked ? "rf locked " : "",
 360                 ref_locked ? "ref locked" : "");
 361
 362        if ((rf_locked) || (ref_locked))
 363                *status |= TUNER_STATUS_LOCKED;
 364fail:
 365        return ret;
 366}
 367
 368static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 369{
 370        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 371        u8 val1, val2;
 372        int ret;
 373
 374        *strength = 0;
 375
 376        ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
 377        if (mxl_fail(ret))
 378                goto fail;
 379        ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
 380        if (mxl_fail(ret))
 381                goto fail;
 382        ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
 383        if (mxl_fail(ret))
 384                goto fail;
 385
 386        *strength = val1 | ((val2 & 0x07) << 8);
 387fail:
 388        ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
 389        mxl_fail(ret);
 390
 391        return ret;
 392}
 393
 394/* ------------------------------------------------------------------------ */
 395
 396static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 397{
 398        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 399        *frequency = state->frequency;
 400        return 0;
 401}
 402
 403static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 404{
 405        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 406        *bandwidth = state->bandwidth;
 407        return 0;
 408}
 409
 410static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
 411                                           u32 *frequency)
 412{
 413        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 414
 415        *frequency = 0;
 416
 417        switch (state->if_freq) {
 418        case MXL_IF_4_0:   /* 4.0   MHz */
 419                *frequency = 4000000;
 420                break;
 421        case MXL_IF_4_5:   /* 4.5   MHz */
 422                *frequency = 4500000;
 423                break;
 424        case MXL_IF_4_57:  /* 4.57  MHz */
 425                *frequency = 4570000;
 426                break;
 427        case MXL_IF_5_0:   /* 5.0   MHz */
 428                *frequency = 5000000;
 429                break;
 430        case MXL_IF_5_38:  /* 5.38  MHz */
 431                *frequency = 5380000;
 432                break;
 433        case MXL_IF_6_0:   /* 6.0   MHz */
 434                *frequency = 6000000;
 435                break;
 436        case MXL_IF_6_28:  /* 6.28  MHz */
 437                *frequency = 6280000;
 438                break;
 439        case MXL_IF_7_2:   /* 7.2   MHz */
 440                *frequency = 7200000;
 441                break;
 442        case MXL_IF_35_25: /* 35.25 MHz */
 443                *frequency = 35250000;
 444                break;
 445        case MXL_IF_36:    /* 36    MHz */
 446                *frequency = 36000000;
 447                break;
 448        case MXL_IF_36_15: /* 36.15 MHz */
 449                *frequency = 36150000;
 450                break;
 451        case MXL_IF_44:    /* 44    MHz */
 452                *frequency = 44000000;
 453                break;
 454        }
 455        return 0;
 456}
 457
 458static int mxl111sf_tuner_release(struct dvb_frontend *fe)
 459{
 460        struct mxl111sf_tuner_state *state = fe->tuner_priv;
 461        mxl_dbg("()");
 462        kfree(state);
 463        fe->tuner_priv = NULL;
 464        return 0;
 465}
 466
 467/* ------------------------------------------------------------------------- */
 468
 469static const struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
 470        .info = {
 471                .name = "MaxLinear MxL111SF",
 472#if 0
 473                .frequency_min  = ,
 474                .frequency_max  = ,
 475                .frequency_step = ,
 476#endif
 477        },
 478#if 0
 479        .init              = mxl111sf_tuner_init,
 480        .sleep             = mxl111sf_tuner_sleep,
 481#endif
 482        .set_params        = mxl111sf_tuner_set_params,
 483        .get_status        = mxl111sf_tuner_get_status,
 484        .get_rf_strength   = mxl111sf_get_rf_strength,
 485        .get_frequency     = mxl111sf_tuner_get_frequency,
 486        .get_bandwidth     = mxl111sf_tuner_get_bandwidth,
 487        .get_if_frequency  = mxl111sf_tuner_get_if_frequency,
 488        .release           = mxl111sf_tuner_release,
 489};
 490
 491struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
 492                                struct mxl111sf_state *mxl_state,
 493                                const struct mxl111sf_tuner_config *cfg)
 494{
 495        struct mxl111sf_tuner_state *state = NULL;
 496
 497        mxl_dbg("()");
 498
 499        state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
 500        if (state == NULL)
 501                return NULL;
 502
 503        state->mxl_state = mxl_state;
 504        state->cfg = cfg;
 505
 506        memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
 507               sizeof(struct dvb_tuner_ops));
 508
 509        fe->tuner_priv = state;
 510        return fe;
 511}
 512EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
 513
 514MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
 515MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 516MODULE_LICENSE("GPL");
 517MODULE_VERSION("0.1");
 518