static int tda18271_tune(struct dvb_frontend *fe,
			 struct tda18271_std_map_item *map, u32 freq, u32 bw)
{
	struct tda18271_priv *priv = fe->tuner_priv;
	int ret;

	tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
		freq, map->if_freq, bw, map->agc_mode, map->std);

	ret = tda18271_agc(fe);
	if (tda_fail(ret))
		tda_warn("failed to configure agc\n");

	ret = tda18271_init(fe);
	if (tda_fail(ret))
		goto fail;

	mutex_lock(&priv->lock);

	switch (priv->id) {
	case TDA18271HDC1:
		tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
		break;
	case TDA18271HDC2:
		tda18271c2_rf_tracking_filters_correction(fe, freq);
		break;
	}
	ret = tda18271_channel_configuration(fe, map, freq, bw);

	mutex_unlock(&priv->lock);
fail:
	return ret;
}
static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg)
{
	struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg;

	tda18271_setup_configuration(fe, cfg);

	if (tda18271_need_cal_on_startup(cfg))
		tda18271_init(fe);

	/* override default std map with values in config struct */
	if ((cfg) && (cfg->std_map))
		tda18271_update_std_map(fe, cfg->std_map);

	return 0;
}
struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
				     struct i2c_adapter *i2c,
				     struct tda18271_config *cfg)
{
	struct tda18271_priv *priv = NULL;
	int instance, ret;

	mutex_lock(&tda18271_list_mutex);

	instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
					      hybrid_tuner_instance_list,
					      i2c, addr, "tda18271");
	switch (instance) {
	case 0:
		goto fail;
	case 1:
		/* new tuner instance */
		fe->tuner_priv = priv;

		tda18271_setup_configuration(fe, cfg);

		priv->cal_initialized = false;
		mutex_init(&priv->lock);

		ret = tda18271_get_id(fe);
		if (tda_fail(ret))
			goto fail;

		ret = tda18271_assign_map_layout(fe);
		if (tda_fail(ret))
			goto fail;

		/* if delay_cal is set, delay IR & RF calibration until init()
		 * module option 'cal' overrides this delay */
		if ((cfg->delay_cal) && (!tda18271_need_cal_on_startup(cfg)))
			break;

		mutex_lock(&priv->lock);
		tda18271_init_regs(fe);

		if ((tda18271_need_cal_on_startup(cfg)) &&
		    (priv->id == TDA18271HDC2))
			tda18271c2_rf_cal_init(fe);

		/* enter standby mode, with required output features enabled */
		ret = tda18271_toggle_output(fe, 1);
		tda_fail(ret);

		mutex_unlock(&priv->lock);
		break;
	default:
		/* existing tuner instance */
		fe->tuner_priv = priv;

		/* allow dvb driver to override configuration settings */
		if (cfg) {
			if (cfg->gate != TDA18271_GATE_ANALOG)
				priv->gate = cfg->gate;
			if (cfg->role)
				priv->role = cfg->role;
			if (cfg->config)
				priv->config = cfg->config;
			if (cfg->small_i2c)
				priv->small_i2c = cfg->small_i2c;
			if (cfg->output_opt)
				priv->output_opt = cfg->output_opt;
			if (cfg->std_map)
				tda18271_update_std_map(fe, cfg->std_map);
		}
		if (tda18271_need_cal_on_startup(cfg))
			tda18271_init(fe);
		break;
	}

	/* override default std map with values in config struct */
	if ((cfg) && (cfg->std_map))
		tda18271_update_std_map(fe, cfg->std_map);

	mutex_unlock(&tda18271_list_mutex);

	memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
	       sizeof(struct dvb_tuner_ops));

	if (tda18271_debug & (DBG_MAP | DBG_ADV))
		tda18271_dump_std_map(fe);

	return fe;
fail:
	mutex_unlock(&tda18271_list_mutex);

	tda18271_release(fe);
	return NULL;
}
struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
				     struct i2c_adapter *i2c,
				     struct tda18271_config *cfg)
{
	struct tda18271_priv *priv = NULL;
	int instance, ret;

	mutex_lock(&tda18271_list_mutex);

	instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
					      hybrid_tuner_instance_list,
					      i2c, addr, "tda18271");
	switch (instance) {
	case 0:
		goto fail;
	case 1:
		/*                    */
		fe->tuner_priv = priv;

		tda18271_setup_configuration(fe, cfg);

		priv->cal_initialized = false;
		mutex_init(&priv->lock);

		ret = tda18271_get_id(fe);
		if (tda_fail(ret))
			goto fail;

		ret = tda18271_assign_map_layout(fe);
		if (tda_fail(ret))
			goto fail;

		mutex_lock(&priv->lock);
		tda18271_init_regs(fe);

		if ((tda18271_need_cal_on_startup(cfg)) &&
		    (priv->id == TDA18271HDC2))
			tda18271c2_rf_cal_init(fe);

		mutex_unlock(&priv->lock);
		break;
	default:
		/*                         */
		fe->tuner_priv = priv;

		/*                                                     */
		if (cfg) {
			if (cfg->gate != TDA18271_GATE_ANALOG)
				priv->gate = cfg->gate;
			if (cfg->role)
				priv->role = cfg->role;
			if (cfg->config)
				priv->config = cfg->config;
			if (cfg->small_i2c)
				priv->small_i2c = cfg->small_i2c;
			if (cfg->output_opt)
				priv->output_opt = cfg->output_opt;
			if (cfg->std_map)
				tda18271_update_std_map(fe, cfg->std_map);
		}
		if (tda18271_need_cal_on_startup(cfg))
			tda18271_init(fe);
		break;
	}

	/*                                                       */
	if ((cfg) && (cfg->std_map))
		tda18271_update_std_map(fe, cfg->std_map);

	mutex_unlock(&tda18271_list_mutex);

	memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
	       sizeof(struct dvb_tuner_ops));

	if (tda18271_debug & (DBG_MAP | DBG_ADV))
		tda18271_dump_std_map(fe);

	return fe;
fail:
	mutex_unlock(&tda18271_list_mutex);

	tda18271_release(fe);
	return NULL;
}