linux/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c
<<
>>
Prefs
   1/*
   2 *  mxl111sf-gpio.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-gpio.h"
  18#include "mxl111sf-i2c.h"
  19#include "mxl111sf.h"
  20
  21/* ------------------------------------------------------------------------- */
  22
  23#define MXL_GPIO_MUX_REG_0 0x84
  24#define MXL_GPIO_MUX_REG_1 0x89
  25#define MXL_GPIO_MUX_REG_2 0x82
  26
  27#define MXL_GPIO_DIR_INPUT  0
  28#define MXL_GPIO_DIR_OUTPUT 1
  29
  30
  31static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
  32{
  33        int ret;
  34        u8 tmp;
  35
  36        mxl_debug_adv("(%d, %d)", pin, val);
  37
  38        if ((pin > 0) && (pin < 8)) {
  39                ret = mxl111sf_read_reg(state, 0x19, &tmp);
  40                if (mxl_fail(ret))
  41                        goto fail;
  42                tmp &= ~(1 << (pin - 1));
  43                tmp |= (val << (pin - 1));
  44                ret = mxl111sf_write_reg(state, 0x19, tmp);
  45                if (mxl_fail(ret))
  46                        goto fail;
  47        } else if (pin <= 10) {
  48                if (pin == 0)
  49                        pin += 7;
  50                ret = mxl111sf_read_reg(state, 0x30, &tmp);
  51                if (mxl_fail(ret))
  52                        goto fail;
  53                tmp &= ~(1 << (pin - 3));
  54                tmp |= (val << (pin - 3));
  55                ret = mxl111sf_write_reg(state, 0x30, tmp);
  56                if (mxl_fail(ret))
  57                        goto fail;
  58        } else
  59                ret = -EINVAL;
  60fail:
  61        return ret;
  62}
  63
  64static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
  65{
  66        int ret;
  67        u8 tmp;
  68
  69        mxl_debug("(0x%02x)", pin);
  70
  71        *val = 0;
  72
  73        switch (pin) {
  74        case 0:
  75        case 1:
  76        case 2:
  77        case 3:
  78                ret = mxl111sf_read_reg(state, 0x23, &tmp);
  79                if (mxl_fail(ret))
  80                        goto fail;
  81                *val = (tmp >> (pin + 4)) & 0x01;
  82                break;
  83        case 4:
  84        case 5:
  85        case 6:
  86        case 7:
  87                ret = mxl111sf_read_reg(state, 0x2f, &tmp);
  88                if (mxl_fail(ret))
  89                        goto fail;
  90                *val = (tmp >> pin) & 0x01;
  91                break;
  92        case 8:
  93        case 9:
  94        case 10:
  95                ret = mxl111sf_read_reg(state, 0x22, &tmp);
  96                if (mxl_fail(ret))
  97                        goto fail;
  98                *val = (tmp >> (pin - 3)) & 0x01;
  99                break;
 100        default:
 101                return -EINVAL; /* invalid pin */
 102        }
 103fail:
 104        return ret;
 105}
 106
 107struct mxl_gpio_cfg {
 108        u8 pin;
 109        u8 dir;
 110        u8 val;
 111};
 112
 113static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
 114                                     struct mxl_gpio_cfg *gpio_cfg)
 115{
 116        int ret;
 117        u8 tmp;
 118
 119        mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
 120
 121        switch (gpio_cfg->pin) {
 122        case 0:
 123        case 1:
 124        case 2:
 125        case 3:
 126                ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
 127                if (mxl_fail(ret))
 128                        goto fail;
 129                tmp &= ~(1 << (gpio_cfg->pin + 4));
 130                tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
 131                ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
 132                if (mxl_fail(ret))
 133                        goto fail;
 134                break;
 135        case 4:
 136        case 5:
 137        case 6:
 138        case 7:
 139                ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
 140                if (mxl_fail(ret))
 141                        goto fail;
 142                tmp &= ~(1 << gpio_cfg->pin);
 143                tmp |= (gpio_cfg->dir << gpio_cfg->pin);
 144                ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
 145                if (mxl_fail(ret))
 146                        goto fail;
 147                break;
 148        case 8:
 149        case 9:
 150        case 10:
 151                ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
 152                if (mxl_fail(ret))
 153                        goto fail;
 154                tmp &= ~(1 << (gpio_cfg->pin - 3));
 155                tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
 156                ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
 157                if (mxl_fail(ret))
 158                        goto fail;
 159                break;
 160        default:
 161                return -EINVAL; /* invalid pin */
 162        }
 163
 164        ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
 165                mxl111sf_set_gpo_state(state,
 166                                       gpio_cfg->pin, gpio_cfg->val) :
 167                mxl111sf_get_gpi_state(state,
 168                                       gpio_cfg->pin, &gpio_cfg->val);
 169        mxl_fail(ret);
 170fail:
 171        return ret;
 172}
 173
 174static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
 175                                   int gpio, int direction, int val)
 176{
 177        struct mxl_gpio_cfg gpio_config = {
 178                .pin = gpio,
 179                .dir = direction,
 180                .val = val,
 181        };
 182
 183        mxl_debug("(%d, %d, %d)", gpio, direction, val);
 184
 185        return mxl111sf_config_gpio_pins(state, &gpio_config);
 186}
 187
 188/* ------------------------------------------------------------------------- */
 189
 190#define PIN_MUX_MPEG_MODE_MASK          0x40   /* 0x17 <6> */
 191#define PIN_MUX_MPEG_PAR_EN_MASK        0x01   /* 0x18 <0> */
 192#define PIN_MUX_MPEG_SER_EN_MASK        0x02   /* 0x18 <1> */
 193#define PIN_MUX_MPG_IN_MUX_MASK         0x80   /* 0x3D <7> */
 194#define PIN_MUX_BT656_ENABLE_MASK       0x04   /* 0x12 <2> */
 195#define PIN_MUX_I2S_ENABLE_MASK         0x40   /* 0x15 <6> */
 196#define PIN_MUX_SPI_MODE_MASK           0x10   /* 0x3D <4> */
 197#define PIN_MUX_MCLK_EN_CTRL_MASK       0x10   /* 0x82 <4> */
 198#define PIN_MUX_MPSYN_EN_CTRL_MASK      0x20   /* 0x82 <5> */
 199#define PIN_MUX_MDVAL_EN_CTRL_MASK      0x40   /* 0x82 <6> */
 200#define PIN_MUX_MPERR_EN_CTRL_MASK      0x80   /* 0x82 <7> */
 201#define PIN_MUX_MDAT_EN_0_MASK          0x10   /* 0x84 <4> */
 202#define PIN_MUX_MDAT_EN_1_MASK          0x20   /* 0x84 <5> */
 203#define PIN_MUX_MDAT_EN_2_MASK          0x40   /* 0x84 <6> */
 204#define PIN_MUX_MDAT_EN_3_MASK          0x80   /* 0x84 <7> */
 205#define PIN_MUX_MDAT_EN_4_MASK          0x10   /* 0x89 <4> */
 206#define PIN_MUX_MDAT_EN_5_MASK          0x20   /* 0x89 <5> */
 207#define PIN_MUX_MDAT_EN_6_MASK          0x40   /* 0x89 <6> */
 208#define PIN_MUX_MDAT_EN_7_MASK          0x80   /* 0x89 <7> */
 209
 210int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
 211                                  enum mxl111sf_mux_config pin_mux_config)
 212{
 213        u8 r12, r15, r17, r18, r3D, r82, r84, r89;
 214        int ret;
 215
 216        mxl_debug("(%d)", pin_mux_config);
 217
 218        ret = mxl111sf_read_reg(state, 0x17, &r17);
 219        if (mxl_fail(ret))
 220                goto fail;
 221        ret = mxl111sf_read_reg(state, 0x18, &r18);
 222        if (mxl_fail(ret))
 223                goto fail;
 224        ret = mxl111sf_read_reg(state, 0x12, &r12);
 225        if (mxl_fail(ret))
 226                goto fail;
 227        ret = mxl111sf_read_reg(state, 0x15, &r15);
 228        if (mxl_fail(ret))
 229                goto fail;
 230        ret = mxl111sf_read_reg(state, 0x82, &r82);
 231        if (mxl_fail(ret))
 232                goto fail;
 233        ret = mxl111sf_read_reg(state, 0x84, &r84);
 234        if (mxl_fail(ret))
 235                goto fail;
 236        ret = mxl111sf_read_reg(state, 0x89, &r89);
 237        if (mxl_fail(ret))
 238                goto fail;
 239        ret = mxl111sf_read_reg(state, 0x3D, &r3D);
 240        if (mxl_fail(ret))
 241                goto fail;
 242
 243        switch (pin_mux_config) {
 244        case PIN_MUX_TS_OUT_PARALLEL:
 245                /* mpeg_mode = 1 */
 246                r17 |= PIN_MUX_MPEG_MODE_MASK;
 247                /* mpeg_par_en = 1 */
 248                r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
 249                /* mpeg_ser_en = 0 */
 250                r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
 251                /* mpg_in_mux = 0 */
 252                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 253                /* bt656_enable = 0 */
 254                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 255                /* i2s_enable = 0 */
 256                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 257                /* spi_mode = 0 */
 258                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 259                /* mclk_en_ctrl = 1 */
 260                r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
 261                /* mperr_en_ctrl = 1 */
 262                r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
 263                /* mdval_en_ctrl = 1 */
 264                r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
 265                /* mpsyn_en_ctrl = 1 */
 266                r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
 267                /* mdat_en_ctrl[3:0] = 0xF */
 268                r84 |= 0xF0;
 269                /* mdat_en_ctrl[7:4] = 0xF */
 270                r89 |= 0xF0;
 271                break;
 272        case PIN_MUX_TS_OUT_SERIAL:
 273                /* mpeg_mode = 1 */
 274                r17 |= PIN_MUX_MPEG_MODE_MASK;
 275                /* mpeg_par_en = 0 */
 276                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 277                /* mpeg_ser_en = 1 */
 278                r18 |= PIN_MUX_MPEG_SER_EN_MASK;
 279                /* mpg_in_mux = 0 */
 280                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 281                /* bt656_enable = 0 */
 282                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 283                /* i2s_enable = 0 */
 284                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 285                /* spi_mode = 0 */
 286                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 287                /* mclk_en_ctrl = 1 */
 288                r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
 289                /* mperr_en_ctrl = 1 */
 290                r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
 291                /* mdval_en_ctrl = 1 */
 292                r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
 293                /* mpsyn_en_ctrl = 1 */
 294                r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
 295                /* mdat_en_ctrl[3:0] = 0xF */
 296                r84 |= 0xF0;
 297                /* mdat_en_ctrl[7:4] = 0xF */
 298                r89 |= 0xF0;
 299                break;
 300        case PIN_MUX_GPIO_MODE:
 301                /* mpeg_mode = 0 */
 302                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 303                /* mpeg_par_en = 0 */
 304                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 305                /* mpeg_ser_en = 0 */
 306                r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
 307                /* mpg_in_mux = 0 */
 308                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 309                /* bt656_enable = 0 */
 310                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 311                /* i2s_enable = 0 */
 312                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 313                /* spi_mode = 0 */
 314                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 315                /* mclk_en_ctrl = 0 */
 316                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 317                /* mperr_en_ctrl = 0 */
 318                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 319                /* mdval_en_ctrl = 0 */
 320                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 321                /* mpsyn_en_ctrl = 0 */
 322                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 323                /* mdat_en_ctrl[3:0] = 0x0 */
 324                r84 &= 0x0F;
 325                /* mdat_en_ctrl[7:4] = 0x0 */
 326                r89 &= 0x0F;
 327                break;
 328        case PIN_MUX_TS_SERIAL_IN_MODE_0:
 329                /* mpeg_mode = 0 */
 330                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 331                /* mpeg_par_en = 0 */
 332                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 333                /* mpeg_ser_en = 1 */
 334                r18 |= PIN_MUX_MPEG_SER_EN_MASK;
 335                /* mpg_in_mux = 0 */
 336                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 337                /* bt656_enable = 0 */
 338                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 339                /* i2s_enable = 0 */
 340                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 341                /* spi_mode = 0 */
 342                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 343                /* mclk_en_ctrl = 0 */
 344                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 345                /* mperr_en_ctrl = 0 */
 346                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 347                /* mdval_en_ctrl = 0 */
 348                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 349                /* mpsyn_en_ctrl = 0 */
 350                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 351                /* mdat_en_ctrl[3:0] = 0x0 */
 352                r84 &= 0x0F;
 353                /* mdat_en_ctrl[7:4] = 0x0 */
 354                r89 &= 0x0F;
 355                break;
 356        case PIN_MUX_TS_SERIAL_IN_MODE_1:
 357                /* mpeg_mode = 0 */
 358                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 359                /* mpeg_par_en = 0 */
 360                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 361                /* mpeg_ser_en = 1 */
 362                r18 |= PIN_MUX_MPEG_SER_EN_MASK;
 363                /* mpg_in_mux = 1 */
 364                r3D |= PIN_MUX_MPG_IN_MUX_MASK;
 365                /* bt656_enable = 0 */
 366                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 367                /* i2s_enable = 0 */
 368                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 369                /* spi_mode = 0 */
 370                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 371                /* mclk_en_ctrl = 0 */
 372                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 373                /* mperr_en_ctrl = 0 */
 374                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 375                /* mdval_en_ctrl = 0 */
 376                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 377                /* mpsyn_en_ctrl = 0 */
 378                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 379                /* mdat_en_ctrl[3:0] = 0x0 */
 380                r84 &= 0x0F;
 381                /* mdat_en_ctrl[7:4] = 0x0 */
 382                r89 &= 0x0F;
 383                break;
 384        case PIN_MUX_TS_SPI_IN_MODE_1:
 385                /* mpeg_mode = 0 */
 386                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 387                /* mpeg_par_en = 0 */
 388                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 389                /* mpeg_ser_en = 1 */
 390                r18 |= PIN_MUX_MPEG_SER_EN_MASK;
 391                /* mpg_in_mux = 1 */
 392                r3D |= PIN_MUX_MPG_IN_MUX_MASK;
 393                /* bt656_enable = 0 */
 394                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 395                /* i2s_enable = 1 */
 396                r15 |= PIN_MUX_I2S_ENABLE_MASK;
 397                /* spi_mode = 1 */
 398                r3D |= PIN_MUX_SPI_MODE_MASK;
 399                /* mclk_en_ctrl = 0 */
 400                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 401                /* mperr_en_ctrl = 0 */
 402                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 403                /* mdval_en_ctrl = 0 */
 404                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 405                /* mpsyn_en_ctrl = 0 */
 406                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 407                /* mdat_en_ctrl[3:0] = 0x0 */
 408                r84 &= 0x0F;
 409                /* mdat_en_ctrl[7:4] = 0x0 */
 410                r89 &= 0x0F;
 411                break;
 412        case PIN_MUX_TS_SPI_IN_MODE_0:
 413                /* mpeg_mode = 0 */
 414                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 415                /* mpeg_par_en = 0 */
 416                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 417                /* mpeg_ser_en = 1 */
 418                r18 |= PIN_MUX_MPEG_SER_EN_MASK;
 419                /* mpg_in_mux = 0 */
 420                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 421                /* bt656_enable = 0 */
 422                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 423                /* i2s_enable = 1 */
 424                r15 |= PIN_MUX_I2S_ENABLE_MASK;
 425                /* spi_mode = 1 */
 426                r3D |= PIN_MUX_SPI_MODE_MASK;
 427                /* mclk_en_ctrl = 0 */
 428                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 429                /* mperr_en_ctrl = 0 */
 430                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 431                /* mdval_en_ctrl = 0 */
 432                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 433                /* mpsyn_en_ctrl = 0 */
 434                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 435                /* mdat_en_ctrl[3:0] = 0x0 */
 436                r84 &= 0x0F;
 437                /* mdat_en_ctrl[7:4] = 0x0 */
 438                r89 &= 0x0F;
 439                break;
 440        case PIN_MUX_TS_PARALLEL_IN:
 441                /* mpeg_mode = 0 */
 442                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 443                /* mpeg_par_en = 1 */
 444                r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
 445                /* mpeg_ser_en = 0 */
 446                r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
 447                /* mpg_in_mux = 0 */
 448                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 449                /* bt656_enable = 0 */
 450                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 451                /* i2s_enable = 0 */
 452                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 453                /* spi_mode = 0 */
 454                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 455                /* mclk_en_ctrl = 0 */
 456                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 457                /* mperr_en_ctrl = 0 */
 458                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 459                /* mdval_en_ctrl = 0 */
 460                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 461                /* mpsyn_en_ctrl = 0 */
 462                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 463                /* mdat_en_ctrl[3:0] = 0x0 */
 464                r84 &= 0x0F;
 465                /* mdat_en_ctrl[7:4] = 0x0 */
 466                r89 &= 0x0F;
 467                break;
 468        case PIN_MUX_BT656_I2S_MODE:
 469                /* mpeg_mode = 0 */
 470                r17 &= ~PIN_MUX_MPEG_MODE_MASK;
 471                /* mpeg_par_en = 0 */
 472                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 473                /* mpeg_ser_en = 0 */
 474                r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
 475                /* mpg_in_mux = 0 */
 476                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 477                /* bt656_enable = 1 */
 478                r12 |= PIN_MUX_BT656_ENABLE_MASK;
 479                /* i2s_enable = 1 */
 480                r15 |= PIN_MUX_I2S_ENABLE_MASK;
 481                /* spi_mode = 0 */
 482                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 483                /* mclk_en_ctrl = 0 */
 484                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 485                /* mperr_en_ctrl = 0 */
 486                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 487                /* mdval_en_ctrl = 0 */
 488                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 489                /* mpsyn_en_ctrl = 0 */
 490                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 491                /* mdat_en_ctrl[3:0] = 0x0 */
 492                r84 &= 0x0F;
 493                /* mdat_en_ctrl[7:4] = 0x0 */
 494                r89 &= 0x0F;
 495                break;
 496        case PIN_MUX_DEFAULT:
 497        default:
 498                /* mpeg_mode = 1 */
 499                r17 |= PIN_MUX_MPEG_MODE_MASK;
 500                /* mpeg_par_en = 0 */
 501                r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
 502                /* mpeg_ser_en = 0 */
 503                r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
 504                /* mpg_in_mux = 0 */
 505                r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
 506                /* bt656_enable = 0 */
 507                r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
 508                /* i2s_enable = 0 */
 509                r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
 510                /* spi_mode = 0 */
 511                r3D &= ~PIN_MUX_SPI_MODE_MASK;
 512                /* mclk_en_ctrl = 0 */
 513                r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
 514                /* mperr_en_ctrl = 0 */
 515                r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
 516                /* mdval_en_ctrl = 0 */
 517                r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
 518                /* mpsyn_en_ctrl = 0 */
 519                r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
 520                /* mdat_en_ctrl[3:0] = 0x0 */
 521                r84 &= 0x0F;
 522                /* mdat_en_ctrl[7:4] = 0x0 */
 523                r89 &= 0x0F;
 524                break;
 525        }
 526
 527        ret = mxl111sf_write_reg(state, 0x17, r17);
 528        if (mxl_fail(ret))
 529                goto fail;
 530        ret = mxl111sf_write_reg(state, 0x18, r18);
 531        if (mxl_fail(ret))
 532                goto fail;
 533        ret = mxl111sf_write_reg(state, 0x12, r12);
 534        if (mxl_fail(ret))
 535                goto fail;
 536        ret = mxl111sf_write_reg(state, 0x15, r15);
 537        if (mxl_fail(ret))
 538                goto fail;
 539        ret = mxl111sf_write_reg(state, 0x82, r82);
 540        if (mxl_fail(ret))
 541                goto fail;
 542        ret = mxl111sf_write_reg(state, 0x84, r84);
 543        if (mxl_fail(ret))
 544                goto fail;
 545        ret = mxl111sf_write_reg(state, 0x89, r89);
 546        if (mxl_fail(ret))
 547                goto fail;
 548        ret = mxl111sf_write_reg(state, 0x3D, r3D);
 549        if (mxl_fail(ret))
 550                goto fail;
 551fail:
 552        return ret;
 553}
 554
 555/* ------------------------------------------------------------------------- */
 556
 557static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
 558{
 559        return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
 560}
 561
 562static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
 563{
 564        u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
 565        int i, ret;
 566
 567        mxl_debug("()");
 568
 569        for (i = 3; i < 8; i++) {
 570                ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
 571                if (mxl_fail(ret))
 572                        break;
 573        }
 574
 575        return ret;
 576}
 577
 578#define PCA9534_I2C_ADDR (0x40 >> 1)
 579static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
 580{
 581        u8 w[2] = { 1, 0 };
 582        u8 r = 0;
 583        struct i2c_msg msg[] = {
 584                { .addr = PCA9534_I2C_ADDR,
 585                  .flags = 0, .buf = w, .len = 1 },
 586                { .addr = PCA9534_I2C_ADDR,
 587                  .flags = I2C_M_RD, .buf = &r, .len = 1 },
 588        };
 589
 590        mxl_debug("(%d, %d)", gpio, val);
 591
 592        /* read current GPIO levels from flip-flop */
 593        i2c_transfer(&state->d->i2c_adap, msg, 2);
 594
 595        /* prepare write buffer with current GPIO levels */
 596        msg[0].len = 2;
 597#if 0
 598        w[0] = 1;
 599#endif
 600        w[1] = r;
 601
 602        /* clear the desired GPIO */
 603        w[1] &= ~(1 << gpio);
 604
 605        /* set the desired GPIO value */
 606        w[1] |= ((val ? 1 : 0) << gpio);
 607
 608        /* write new GPIO levels to flip-flop */
 609        i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
 610
 611        return 0;
 612}
 613
 614static int pca9534_init_port_expander(struct mxl111sf_state *state)
 615{
 616        u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
 617
 618        struct i2c_msg msg = {
 619                .addr = PCA9534_I2C_ADDR,
 620                .flags = 0, .buf = w, .len = 2
 621        };
 622
 623        mxl_debug("()");
 624
 625        i2c_transfer(&state->d->i2c_adap, &msg, 1);
 626
 627        /* configure all pins as outputs */
 628        w[0] = 3;
 629        w[1] = 0;
 630
 631        i2c_transfer(&state->d->i2c_adap, &msg, 1);
 632
 633        return 0;
 634}
 635
 636int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
 637{
 638        mxl_debug("(%d, %d)", gpio, val);
 639
 640        switch (state->gpio_port_expander) {
 641        default:
 642                mxl_printk(KERN_ERR,
 643                           "gpio_port_expander undefined, assuming PCA9534");
 644                /* fall-thru */
 645        case mxl111sf_PCA9534:
 646                return pca9534_set_gpio(state, gpio, val);
 647        case mxl111sf_gpio_hw:
 648                return mxl111sf_hw_set_gpio(state, gpio, val);
 649        }
 650}
 651
 652static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
 653{
 654        int ret;
 655        u8 w = 1;
 656        u8 r = 0;
 657        struct i2c_msg msg[] = {
 658                { .flags = 0,        .buf = &w, .len = 1 },
 659                { .flags = I2C_M_RD, .buf = &r, .len = 1 },
 660        };
 661
 662        mxl_debug("()");
 663
 664        msg[0].addr = 0x70 >> 1;
 665        msg[1].addr = 0x70 >> 1;
 666
 667        /* read current GPIO levels from flip-flop */
 668        ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
 669        if (ret == 2) {
 670                state->port_expander_addr = msg[0].addr;
 671                state->gpio_port_expander = mxl111sf_PCA9534;
 672                mxl_debug("found port expander at 0x%02x",
 673                          state->port_expander_addr);
 674                return 0;
 675        }
 676
 677        msg[0].addr = 0x40 >> 1;
 678        msg[1].addr = 0x40 >> 1;
 679
 680        ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
 681        if (ret == 2) {
 682                state->port_expander_addr = msg[0].addr;
 683                state->gpio_port_expander = mxl111sf_PCA9534;
 684                mxl_debug("found port expander at 0x%02x",
 685                          state->port_expander_addr);
 686                return 0;
 687        }
 688        state->port_expander_addr = 0xff;
 689        state->gpio_port_expander = mxl111sf_gpio_hw;
 690        mxl_debug("using hardware gpio");
 691        return 0;
 692}
 693
 694int mxl111sf_init_port_expander(struct mxl111sf_state *state)
 695{
 696        mxl_debug("()");
 697
 698        if (0x00 == state->port_expander_addr)
 699                mxl111sf_probe_port_expander(state);
 700
 701        switch (state->gpio_port_expander) {
 702        default:
 703                mxl_printk(KERN_ERR,
 704                           "gpio_port_expander undefined, assuming PCA9534");
 705                /* fall-thru */
 706        case mxl111sf_PCA9534:
 707                return pca9534_init_port_expander(state);
 708        case mxl111sf_gpio_hw:
 709                return mxl111sf_hw_gpio_initialize(state);
 710        }
 711}
 712
 713/* ------------------------------------------------------------------------ */
 714
 715int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
 716{
 717/*      GPO:
 718 *      3 - ATSC/MH#   | 1 = ATSC transport, 0 = MH transport      | default 0
 719 *      4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset           | default 0
 720 *      5 - ATSC_EN    | 1 = ATSC power enable, 0 = ATSC power off | default 0
 721 *      6 - MH_RESET#  | 1 = MH enable, 0 = MH Reset               | default 0
 722 *      7 - MH_EN      | 1 = MH power enable, 0 = MH power off     | default 0
 723 */
 724        mxl_debug("(%d)", mode);
 725
 726        switch (mode) {
 727        case MXL111SF_GPIO_MOD_MH:
 728                mxl111sf_set_gpio(state, 4, 0);
 729                mxl111sf_set_gpio(state, 5, 0);
 730                msleep(50);
 731                mxl111sf_set_gpio(state, 7, 1);
 732                msleep(50);
 733                mxl111sf_set_gpio(state, 6, 1);
 734                msleep(50);
 735
 736                mxl111sf_set_gpio(state, 3, 0);
 737                break;
 738        case MXL111SF_GPIO_MOD_ATSC:
 739                mxl111sf_set_gpio(state, 6, 0);
 740                mxl111sf_set_gpio(state, 7, 0);
 741                msleep(50);
 742                mxl111sf_set_gpio(state, 5, 1);
 743                msleep(50);
 744                mxl111sf_set_gpio(state, 4, 1);
 745                msleep(50);
 746                mxl111sf_set_gpio(state, 3, 1);
 747                break;
 748        default: /* DVBT / STANDBY */
 749                mxl111sf_init_port_expander(state);
 750                break;
 751        }
 752        return 0;
 753}
 754