module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable verbose debug messages");
+#define TUNER_SIMPLE_MAX 64
+static unsigned int simple_devcount;
+
static int offset;
module_param(offset, int, 0664);
MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
+static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
+ { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
+ { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+module_param_array(atv_input, int, NULL, 0644);
+module_param_array(dtv_input, int, NULL, 0644);
+MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
+MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
+
/* ---------------------------------------------------------------------- */
/* tv standard selection for Temic 4046 FM5
static LIST_HEAD(hybrid_tuner_instance_list);
struct tuner_simple_priv {
+ unsigned int nr;
u16 last_div;
struct tuner_i2c_props i2c_props;
/* ---------------------------------------------------------------------- */
+static void simple_set_rf_input(struct dvb_frontend *fe,
+ u8 *config, u8 *cb, unsigned int rf)
+{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+
+ switch (priv->type) {
+ case TUNER_PHILIPS_TUV1236D:
+ switch (rf) {
+ case 1:
+ *cb |= 0x08;
+ break;
+ default:
+ *cb &= ~0x08;
+ break;
+ }
+ break;
+ case TUNER_PHILIPS_FCV1236D:
+ switch (rf) {
+ case 1:
+ *cb |= 0x01;
+ break;
+ default:
+ *cb &= ~0x01;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
static int simple_std_setup(struct dvb_frontend *fe,
struct analog_parameters *params,
u8 *config, u8 *cb)
}
break;
- case TUNER_PHILIPS_ATSC:
+ case TUNER_PHILIPS_FCV1236D:
/* 0x00 -> ATSC antenna input 1 */
/* 0x01 -> ATSC antenna input 2 */
/* 0x02 -> NTSC antenna input 1 */
*cb &= ~0x03;
if (!(params->std & V4L2_STD_ATSC))
*cb |= 2;
- /* FIXME: input */
break;
case TUNER_MICROTUNE_4042FI5:
tuner_warn("i2c i/o error: rc == %d "
"(should be 2)\n", rc);
priv->i2c_props.addr = tuneraddr;
- /* FIXME: input */
break;
}
}
+ if (atv_input[priv->nr])
+ simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
return 0;
}
params->frequency >= 158870000)
buf[3] |= 0x08;
break;
+ case TUNER_PHILIPS_TD1316:
+ /* determine band */
+ buf[3] |= (params->frequency < 161000000) ? 1 :
+ (params->frequency < 444000000) ? 2 : 4;
+
+ /* setup PLL filter */
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ buf[3] |= 1 << 3;
+ break;
+ case TUNER_PHILIPS_TUV1236D:
+ case TUNER_PHILIPS_FCV1236D:
+ {
+ unsigned int new_rf;
+
+ if (dtv_input[priv->nr])
+ new_rf = dtv_input[priv->nr];
+ else
+ switch (params->u.vsb.modulation) {
+ case QAM_64:
+ case QAM_256:
+ new_rf = 1;
+ break;
+ case VSB_8:
+ default:
+ new_rf = 0;
+ break;
+ }
+ simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
+ break;
+ }
default:
break;
}
}
-static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
+static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
const struct dvb_frontend_parameters *params)
{
+ /* This function returns the tuned frequency on success, 0 on error */
struct tuner_simple_priv *priv = fe->tuner_priv;
struct tunertype *tun = priv->tun;
static struct tuner_params *t_params;
t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
if (ret < 0)
- return ret;
+ return 0; /* failure */
div = ((frequency + t_params->iffreq) * 62500 + offset +
tun->stepsize/2) / tun->stepsize;
u8 *buf, int buf_len)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
- int ret;
u32 frequency;
if (buf_len < 5)
return -EINVAL;
- ret = simple_dvb_configure(fe, buf+1, params);
- if (ret < 0)
- return ret;
- else
- frequency = ret;
+ frequency = simple_dvb_configure(fe, buf+1, params);
+ if (frequency == 0)
+ return -EINVAL;
buf[0] = priv->i2c_props.addr;
if (type >= tuner_count) {
printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
- __FUNCTION__, type, tuner_count-1);
+ __func__, type, tuner_count-1);
return NULL;
}
+ /* If i2c_adap is set, check that the tuner is at the correct address.
+ * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
+ * by the digital demod via calc_regs.
+ */
+ if (i2c_adap != NULL) {
+ u8 b[1];
+ struct i2c_msg msg = {
+ .addr = i2c_addr, .flags = I2C_M_RD,
+ .buf = b, .len = 1,
+ };
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (1 != i2c_transfer(i2c_adap, &msg, 1))
+ tuner_warn("unable to probe %s, proceeding anyway.",
+ tuners[type].name);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
mutex_lock(&tuner_simple_list_mutex);
instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
priv->type = type;
priv->tun = &tuners[type];
+ priv->nr = simple_devcount++;
break;
default:
fe->tuner_priv = priv;
tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+ if ((debug) || ((atv_input[priv->nr] > 0) ||
+ (dtv_input[priv->nr] > 0))) {
+ if (0 == atv_input[priv->nr])
+ tuner_info("tuner %d atv rf input will be "
+ "autoselected\n", priv->nr);
+ else
+ tuner_info("tuner %d atv rf input will be "
+ "set to input %d (insmod option)\n",
+ priv->nr, atv_input[priv->nr]);
+ if (0 == dtv_input[priv->nr])
+ tuner_info("tuner %d dtv rf input will be "
+ "autoselected\n", priv->nr);
+ else
+ tuner_info("tuner %d dtv rf input will be "
+ "set to input %d (insmod option)\n",
+ priv->nr, dtv_input[priv->nr]);
+ }
+
strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
sizeof(fe->ops.tuner_ops.info.name));