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