linux/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c
<<
>>
Prefs
   1/*
   2 *  mxl111sf-phy.c - driver for the MaxLinear MXL111SF
   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
  17#include "mxl111sf-phy.h"
  18#include "mxl111sf-reg.h"
  19
  20int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
  21{
  22        struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
  23                {0x07, 0xff, 0x0c},
  24                {0x58, 0xff, 0x9d},
  25                {0x09, 0xff, 0x00},
  26                {0x06, 0xff, 0x06},
  27                {0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
  28                {0x8d, 0x01, 0x01}, /* NEGATE_Q */
  29                {0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
  30                {0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
  31                {0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
  32                {0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
  33                {0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
  34                {0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
  35                {0x88, 0xff, 0xf0}, /* INF_THD = 240 */
  36                {0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
  37                {0x00, 0xff, 0x01}, /* Change to page 1 */
  38                {0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
  39                {0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
  40                {0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
  41                {0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
  42                {0x00, 0xff, 0x00}, /* Change to page 0 */
  43                {0,    0,    0}
  44        };
  45
  46        mxl_debug("()");
  47
  48        return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
  49}
  50
  51int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
  52{
  53        int ret;
  54        mxl_debug("()");
  55
  56        ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
  57        if (mxl_fail(ret))
  58                goto fail;
  59        ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
  60        mxl_fail(ret);
  61fail:
  62        return ret;
  63}
  64
  65int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
  66{
  67        int ret;
  68
  69        mxl_debug("(%s)", MXL_SOC_MODE == mode ?
  70                "MXL_SOC_MODE" : "MXL_TUNER_MODE");
  71
  72        /* set device mode */
  73        ret = mxl111sf_write_reg(state, 0x03,
  74                                 MXL_SOC_MODE == mode ? 0x01 : 0x00);
  75        if (mxl_fail(ret))
  76                goto fail;
  77
  78        ret = mxl111sf_write_reg_mask(state,
  79                                      0x7d, 0x40, MXL_SOC_MODE == mode ?
  80                                      0x00 : /* enable impulse noise filter,
  81                                                INF_BYP = 0 */
  82                                      0x40); /* disable impulse noise filter,
  83                                                INF_BYP = 1 */
  84        if (mxl_fail(ret))
  85                goto fail;
  86
  87        state->device_mode = mode;
  88fail:
  89        return ret;
  90}
  91
  92/* power up tuner */
  93int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
  94{
  95        mxl_debug("(%d)", onoff);
  96
  97        return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
  98}
  99
 100int mxl111sf_disable_656_port(struct mxl111sf_state *state)
 101{
 102        mxl_debug("()");
 103
 104        return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
 105}
 106
 107int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
 108{
 109        mxl_debug("()");
 110
 111        return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
 112}
 113
 114/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
 115int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
 116                            unsigned int parallel_serial,
 117                            unsigned int msb_lsb_1st,
 118                            unsigned int clock_phase,
 119                            unsigned int mpeg_valid_pol,
 120                            unsigned int mpeg_sync_pol)
 121{
 122        int ret;
 123        u8 mode, tmp;
 124
 125        mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
 126                  clock_phase, mpeg_valid_pol, mpeg_sync_pol);
 127
 128        /* Enable PIN MUX */
 129        ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
 130        mxl_fail(ret);
 131
 132        /* Configure MPEG Clock phase */
 133        mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
 134
 135        if (clock_phase == TSIF_NORMAL)
 136                mode &= ~V6_INVERTED_CLK_PHASE;
 137        else
 138                mode |= V6_INVERTED_CLK_PHASE;
 139
 140        ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
 141        mxl_fail(ret);
 142
 143        /* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
 144         * Get current configuration */
 145        ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
 146        mxl_fail(ret);
 147
 148        /* Data Input mode */
 149        if (parallel_serial == TSIF_INPUT_PARALLEL) {
 150                /* Disable serial mode */
 151                mode &= ~V6_MPEG_IN_DATA_SERIAL;
 152
 153                /* Enable Parallel mode */
 154                mode |= V6_MPEG_IN_DATA_PARALLEL;
 155        } else {
 156                /* Disable Parallel mode */
 157                mode &= ~V6_MPEG_IN_DATA_PARALLEL;
 158
 159                /* Enable Serial Mode */
 160                mode |= V6_MPEG_IN_DATA_SERIAL;
 161
 162                /* If serial interface is chosen, configure
 163                   MSB or LSB order in transmission */
 164                ret = mxl111sf_read_reg(state,
 165                                        V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
 166                                        &tmp);
 167                mxl_fail(ret);
 168
 169                if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
 170                        tmp |= V6_MPEG_SER_MSB_FIRST;
 171                else
 172                        tmp &= ~V6_MPEG_SER_MSB_FIRST;
 173
 174                ret = mxl111sf_write_reg(state,
 175                                         V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
 176                                         tmp);
 177                mxl_fail(ret);
 178        }
 179
 180        /* MPEG Sync polarity */
 181        if (mpeg_sync_pol == TSIF_NORMAL)
 182                mode &= ~V6_INVERTED_MPEG_SYNC;
 183        else
 184                mode |= V6_INVERTED_MPEG_SYNC;
 185
 186        /* MPEG Valid polarity */
 187        if (mpeg_valid_pol == 0)
 188                mode &= ~V6_INVERTED_MPEG_VALID;
 189        else
 190                mode |= V6_INVERTED_MPEG_VALID;
 191
 192        ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
 193        mxl_fail(ret);
 194
 195        return ret;
 196}
 197
 198int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
 199{
 200        static struct mxl111sf_reg_ctrl_info init_i2s[] = {
 201                {0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
 202                {0x15, 0x60, 0x60}, /* Enable I2S */
 203                {0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
 204                                       Inverted 656 Clock, I2S_SOFT_RESET,
 205                                       0 : Normal operation, 1 : Reset State */
 206#if 0
 207                {0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
 208#endif
 209                {0x00, 0xff, 0x02}, /* Change to Control Page */
 210                {0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
 211                {0x00, 0xff, 0x00},
 212                {0,    0,    0}
 213        };
 214        int ret;
 215
 216        mxl_debug("(0x%02x)", sample_size);
 217
 218        ret = mxl111sf_ctrl_program_regs(state, init_i2s);
 219        if (mxl_fail(ret))
 220                goto fail;
 221
 222        ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
 223        mxl_fail(ret);
 224fail:
 225        return ret;
 226}
 227
 228int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
 229{
 230        static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
 231                {0x15, 0x40, 0x00},
 232                {0,    0,    0}
 233        };
 234
 235        mxl_debug("()");
 236
 237        return mxl111sf_ctrl_program_regs(state, disable_i2s);
 238}
 239
 240int mxl111sf_config_i2s(struct mxl111sf_state *state,
 241                        u8 msb_start_pos, u8 data_width)
 242{
 243        int ret;
 244        u8 tmp;
 245
 246        mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
 247
 248        ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
 249        if (mxl_fail(ret))
 250                goto fail;
 251
 252        tmp &= 0xe0;
 253        tmp |= msb_start_pos;
 254        ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
 255        if (mxl_fail(ret))
 256                goto fail;
 257
 258        ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
 259        if (mxl_fail(ret))
 260                goto fail;
 261
 262        tmp &= 0xe0;
 263        tmp |= data_width;
 264        ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
 265        mxl_fail(ret);
 266fail:
 267        return ret;
 268}
 269
 270int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
 271{
 272        u8 val;
 273        int ret;
 274
 275        mxl_debug("(%d)", onoff);
 276
 277        ret = mxl111sf_write_reg(state, 0x00, 0x02);
 278        if (mxl_fail(ret))
 279                goto fail;
 280
 281        ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
 282        if (mxl_fail(ret))
 283                goto fail;
 284
 285        if (onoff)
 286                val |= 0x04;
 287        else
 288                val &= ~0x04;
 289
 290        ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
 291        if (mxl_fail(ret))
 292                goto fail;
 293
 294        ret = mxl111sf_write_reg(state, 0x00, 0x00);
 295        mxl_fail(ret);
 296fail:
 297        return ret;
 298}
 299
 300int mxl111sf_idac_config(struct mxl111sf_state *state,
 301                         u8 control_mode, u8 current_setting,
 302                         u8 current_value, u8 hysteresis_value)
 303{
 304        int ret;
 305        u8 val;
 306        /* current value will be set for both automatic & manual IDAC control */
 307        val = current_value;
 308
 309        if (control_mode == IDAC_MANUAL_CONTROL) {
 310                /* enable manual control of IDAC */
 311                val |= IDAC_MANUAL_CONTROL_BIT_MASK;
 312
 313                if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
 314                        /* enable current sinking in manual mode */
 315                        val |= IDAC_CURRENT_SINKING_BIT_MASK;
 316                else
 317                        /* disable current sinking in manual mode */
 318                        val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
 319        } else {
 320                /* disable manual control of IDAC */
 321                val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
 322
 323                /* set hysteresis value  reg: 0x0B<5:0> */
 324                ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
 325                                         (hysteresis_value & 0x3F));
 326                mxl_fail(ret);
 327        }
 328
 329        ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
 330        mxl_fail(ret);
 331
 332        return ret;
 333}
 334