return stv090x_write_regs(state, reg, &data, 1);
}
-static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
{
- struct stv090x_state *state = fe->demodulator_priv;
u32 reg;
+ /*
+ * NOTE! A lock is used as a FSM to control the state in which
+ * access is serialized between two tuners on the same demod.
+ * This has nothing to do with a lock to protect a critical section
+ * which may in some other cases be confused with protecting I/O
+ * access to the demodulator gate.
+ * In case of any error, the lock is unlocked and exit within the
+ * relevant operations themselves.
+ */
if (enable)
mutex_lock(&state->internal->tuner_lock);
freq -= cur_step * car_step;
/* Setup tuner */
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_set_frequency) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
msleep(50);
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_get_status) {
else
dprintk(FE_DEBUG, 1, "Tuner unlocked");
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
}
return srate_coarse;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
freq -= cur_step * car_step;
/* Setup tuner */
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_set_frequency) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
msleep(50);
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_get_status) {
else
dprintk(FE_DEBUG, 1, "Tuner unlocked");
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
return lock;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
state->delsys = stv090x_get_std(state);
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_get_frequency) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000;
if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_get_frequency) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
return STV090x_OUTOFRANGE;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
if (state->algo != STV090x_WARM_SEARCH) {
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_set_bandwidth) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
}
return 0;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
/* Setup tuner */
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_set_bbgain) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
msleep(50);
if (state->config->tuner_get_status) {
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (state->config->tuner_get_status(fe, ®) < 0)
goto err_gateoff;
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
if (reg)
return signal_state;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
struct stv090x_state *state = fe->demodulator_priv;
u32 reg;
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_sleep) {
+ if (state->config->tuner_sleep(fe) < 0)
+ goto err_gateoff;
+ }
+
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+ goto err;
+
dprintk(FE_DEBUG, 1, "Set %s to sleep",
state->device == STV0900 ? "STV0900" : "STV0903");
goto err;
return 0;
+
+err_gateoff:
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
u32 reg;
if (state->internal->mclk == 0) {
+ /* call tuner init to configure the tuner's clock output
+ divider directly before setting up the master clock of
+ the stv090x. */
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+ goto err;
+
+ if (config->tuner_init) {
+ if (config->tuner_init(fe) < 0)
+ goto err_gateoff;
+ }
+
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+ goto err;
+
stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
msleep(5);
if (stv090x_write_reg(state, STV090x_SYNTCTRL,
if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
goto err;
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
goto err;
if (config->tuner_set_mode) {
goto err_gateoff;
}
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
goto err;
if (stv090x_set_tspath(state) < 0)
return 0;
err_gateoff:
- stv090x_i2c_gate_ctrl(fe, 0);
+ stv090x_i2c_gate_ctrl(state, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
.sleep = stv090x_sleep,
.get_frontend_algo = stv090x_frontend_algo,
- .i2c_gate_ctrl = stv090x_i2c_gate_ctrl,
-
.diseqc_send_master_cmd = stv090x_send_diseqc_msg,
.diseqc_send_burst = stv090x_send_diseqc_burst,
.diseqc_recv_slave_reply = stv090x_recv_slave_reply,