1/* 2 * mxl111sf-gpio.c - driver for the MaxLinear MXL111SF 3 * 4 * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> 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 759/* 760 * Local variables: 761 * c-basic-offset: 8 762 * End: 763 */ 764