diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index 67589b607c4e..a756e4562fe2 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -10,18 +10,21 @@ * adr: I2C Address of the DRX-K * single_master: Device is on the single master mode * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner - * antenna_uses_gpio: Use GPIO to control the antenna - * antenna_dvbc: GPIO for changing antenna to DVB-C - * antenna_dvbt: GPIO for changing antenna to DVB-T + * antenna_gpio: GPIO bit used to control the antenna + * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 + * means that 1=DVBC, 0 = DVBT. Zero means the opposite. * microcode_name: Name of the firmware file with the microcode + * + * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is + * UIO-3. */ struct drxk_config { u8 adr; bool single_master; bool no_i2c_bridge; - bool antenna_uses_gpio; - u16 antenna_dvbc, antenna_dvbt; + bool antenna_dvbt; + u16 antenna_gpio; const char *microcode_name; }; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 0d288a7f0163..aaef8e35698b 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -856,7 +856,6 @@ static int init_state(struct drxk_state *state) state->m_agcFastClipCtrlDelay = 0; state->m_GPIOCfg = (ulGPIOCfg); - state->m_GPIO = (ulGPIO == 0 ? 0 : 1); state->m_bPowerDown = false; state->m_currentPowerMode = DRX_POWER_DOWN; @@ -5795,24 +5794,63 @@ static int WriteGPIO(struct drxk_state *state) goto error; if (state->m_hasSAWSW) { - /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); - if (status < 0) - goto error; + if (state->UIO_mask & 0x0001) { /* UIO-1 */ + /* write to io pad configuration register - output mode */ + status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; - /* use corresponding bit in io data output registar */ - status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); - if (status < 0) - goto error; - if (state->m_GPIO == 0) - value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ - else - value |= 0x8000; /* write one to 15th bit - 1st UIO */ - /* write back to io data output register */ - status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); - if (status < 0) - goto error; + /* use corresponding bit in io data output registar */ + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; + if ((state->m_GPIO & 0x0001) == 0) + value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ + else + value |= 0x8000; /* write one to 15th bit - 1st UIO */ + /* write back to io data output register */ + status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); + if (status < 0) + goto error; + } + if (state->UIO_mask & 0x0002) { /* UIO-2 */ + /* write to io pad configuration register - output mode */ + status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; + /* use corresponding bit in io data output registar */ + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; + if ((state->m_GPIO & 0x0002) == 0) + value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ + else + value |= 0x4000; /* write one to 14th bit - 2st UIO */ + /* write back to io data output register */ + status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); + if (status < 0) + goto error; + } + if (state->UIO_mask & 0x0004) { /* UIO-3 */ + /* write to io pad configuration register - output mode */ + status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; + + /* use corresponding bit in io data output registar */ + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; + if ((state->m_GPIO & 0x0004) == 0) + value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ + else + value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ + /* write back to io data output register */ + status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); + if (status < 0) + goto error; + } } /* Write magic word to disable pdr reg write */ status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); @@ -5825,14 +5863,22 @@ error: static int SwitchAntennaToQAM(struct drxk_state *state) { int status = 0; + bool gpio_state; dprintk(1, "\n"); - if (state->m_AntennaSwitchDVBTDVBC != 0) { - if (state->m_GPIO != state->m_AntennaDVBC) { - state->m_GPIO = state->m_AntennaDVBC; - status = WriteGPIO(state); - } + if (!state->antenna_gpio) + return 0; + + gpio_state = state->m_GPIO & state->antenna_gpio; + + if (state->antenna_dvbt ^ gpio_state) { + /* Antenna is on DVB-T mode. Switch */ + if (state->antenna_dvbt) + state->m_GPIO &= ~state->antenna_gpio; + else + state->m_GPIO |= state->antenna_gpio; + status = WriteGPIO(state); } if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -5842,13 +5888,22 @@ static int SwitchAntennaToQAM(struct drxk_state *state) static int SwitchAntennaToDVBT(struct drxk_state *state) { int status = 0; + bool gpio_state; dprintk(1, "\n"); - if (state->m_AntennaSwitchDVBTDVBC != 0) { - if (state->m_GPIO != state->m_AntennaDVBT) { - state->m_GPIO = state->m_AntennaDVBT; - status = WriteGPIO(state); - } + + if (!state->antenna_gpio) + return 0; + + gpio_state = state->m_GPIO & state->antenna_gpio; + + if (!(state->antenna_dvbt ^ gpio_state)) { + /* Antenna is on DVB-C mode. Switch */ + if (state->antenna_dvbt) + state->m_GPIO |= state->antenna_gpio; + else + state->m_GPIO &= ~state->antenna_gpio; + status = WriteGPIO(state); } if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -6350,9 +6405,17 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->single_master = config->single_master; state->microcode_name = config->microcode_name; state->no_i2c_bridge = config->no_i2c_bridge; - state->m_AntennaSwitchDVBTDVBC = config->antenna_uses_gpio; - state->m_AntennaDVBC = config->antenna_dvbc; - state->m_AntennaDVBT = config->antenna_dvbt; + state->antenna_gpio = config->antenna_gpio; + state->antenna_dvbt = config->antenna_dvbt; + + /* NOTE: as more UIO bits will be used, add them to the mask */ + state->UIO_mask = config->antenna_gpio; + + /* Default gpio to DVB-C */ + if (!state->antenna_dvbt && state->antenna_gpio) + state->m_GPIO |= state->antenna_gpio; + else + state->m_GPIO &= ~state->antenna_gpio; mutex_init(&state->mutex); mutex_init(&state->ctlock); diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h index 8b29dc89f58b..a20a19d9aff6 100644 --- a/drivers/media/dvb/frontends/drxk_hard.h +++ b/drivers/media/dvb/frontends/drxk_hard.h @@ -323,17 +323,19 @@ struct drxk_state { enum DRXPowerMode m_currentPowerMode; - /* Configurable parameters at the driver */ + /* + * Configurable parameters at the driver. They stores the values found + * at struct drxk_config. + */ - bool m_AntennaSwitchDVBTDVBC; - u16 m_AntennaDVBC; - u16 m_AntennaDVBT; + u16 UIO_mask; /* Bits used by UIO */ - u32 single_master : 1; /* Use single master i2c mode */ - u32 no_i2c_bridge : 1; /* Tuner is not on port 1, don't use I2C bridge */ + bool single_master; + bool no_i2c_bridge; + bool antenna_dvbt; + u16 antenna_gpio; const char *microcode_name; - }; #define NEVER_LOCK 0