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