141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet/*
241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * Abilis Systems Single DVB-T Receiver
341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *
641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * This program is free software; you can redistribute it and/or modify
741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * it under the terms of the GNU General Public License as published by
841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * the Free Software Foundation; either version 2, or (at your option)
941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * any later version.
1041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *
1141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * This program is distributed in the hope that it will be useful,
1241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * but WITHOUT ANY WARRANTY; without even the implied warranty of
1341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * GNU General Public License for more details.
1541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *
1641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * You should have received a copy of the GNU General Public License
1741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * along with this program; if not, write to the Free Software
1841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet */
2041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#include <linux/version.h>
2141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
2241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#include "as102_drv.h"
2341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#include "as10x_types.h"
2441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#include "as10x_cmd.h"
2541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
26dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehabstatic void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *dst,
2741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet					 struct as10x_tps *src);
2841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
2941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoetstatic void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
30dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab					  struct dtv_frontend_properties *src);
3141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
32dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehabstatic int as102_fe_set_frontend(struct dvb_frontend *fe)
3387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
34dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
3541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	int ret = 0;
3641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
3741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as10x_tune_args tune_args = { 0 };
3841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
3941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
4041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
4187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
4287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
4341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
4441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
4541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (mutex_lock_interruptible(&dev->bus_adap.lock))
4641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EBUSY;
4741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
48dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	as102_fe_copy_tune_parameters(&tune_args, p);
4941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
5041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* send abilis command: SET_TUNE */
5141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ret =  as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
5287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (ret != 0)
5341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		dprintk(debug, "as10x_cmd_set_tune failed. (err = %d)\n", ret);
5441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
5541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	mutex_unlock(&dev->bus_adap.lock);
5641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
5741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
5841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return (ret < 0) ? -EINVAL : 0;
5941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
6041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
6153c91373bdd74f7e11d2726046a90b986c1ed650Mauro Carvalho Chehabstatic int as102_fe_get_frontend(struct dvb_frontend *fe)
62dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab{
6353c91373bdd74f7e11d2726046a90b986c1ed650Mauro Carvalho Chehab	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
6441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	int ret = 0;
6541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
6641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as10x_tps tps = { 0 };
6741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
6841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
6941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
7087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
7187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
7241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EINVAL;
7341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
7441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (mutex_lock_interruptible(&dev->bus_adap.lock))
7541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EBUSY;
7641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
7741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* send abilis command: GET_TPS */
7841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ret = as10x_cmd_get_tps(&dev->bus_adap, &tps);
7941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
8041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (ret == 0)
8141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		as10x_fe_copy_tps_parameters(p, &tps);
8241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
8341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	mutex_unlock(&dev->bus_adap.lock);
8441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
8541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
8641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return (ret < 0) ? -EINVAL : 0;
8741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
8841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
8941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoetstatic int as102_fe_get_tune_settings(struct dvb_frontend *fe,
9041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			struct dvb_frontend_tune_settings *settings) {
9141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
9241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
9341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#if 0
9441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dprintk(debug, "step_size    = %d\n", settings->step_size);
9541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dprintk(debug, "max_drift    = %d\n", settings->max_drift);
9687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dprintk(debug, "min_delay_ms = %d -> %d\n", settings->min_delay_ms,
9787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		1000);
9841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet#endif
9941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
10041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	settings->min_delay_ms = 1000;
10141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
10241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
10341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
10441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
10541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
10641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
10787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
10887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
10941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	int ret = 0;
11041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
11141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as10x_tune_status tstate = { 0 };
11241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
11341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
11441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
11587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
11687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
11741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
11841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
11941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (mutex_lock_interruptible(&dev->bus_adap.lock))
12041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EBUSY;
12141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
12241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* send abilis command: GET_TUNE_STATUS */
12341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate);
12441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (ret < 0) {
12587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		dprintk(debug, "as10x_cmd_get_tune_status failed (err = %d)\n",
12687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			ret);
12741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		goto out;
12841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
12941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
13041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dev->signal_strength  = tstate.signal_strength;
13141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dev->ber  = tstate.BER;
13241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
13387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (tstate.tune_state) {
13487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TUNE_STATUS_SIGNAL_DVB_OK:
13587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
13687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
13787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TUNE_STATUS_STREAM_DETECTED:
13887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC;
13987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
14087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TUNE_STATUS_STREAM_TUNED:
14187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
14287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			FE_HAS_LOCK;
14387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
14487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
14587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		*status = TUNE_STATUS_NOT_TUNED;
14641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
14741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
14887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dprintk(debug, "tuner status: 0x%02x, strength %d, per: %d, ber: %d\n",
14941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tstate.tune_state, tstate.signal_strength,
15041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tstate.PER, tstate.BER);
15141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
15241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (*status & FE_HAS_LOCK) {
15341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		if (as10x_cmd_get_demod_stats(&dev->bus_adap,
15487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			(struct as10x_demod_stats *) &dev->demod_stats) < 0) {
15541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
15687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			dprintk(debug, "as10x_cmd_get_demod_stats failed "
15787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				"(probably not tuned)\n");
15841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		} else {
15987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			dprintk(debug,
16087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				"demod status: fc: 0x%08x, bad fc: 0x%08x, "
16187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				"bytes corrected: 0x%08x , MER: 0x%04x\n",
16287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				dev->demod_stats.frame_count,
16387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				dev->demod_stats.bad_frame_count,
16487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				dev->demod_stats.bytes_fixed_by_rs,
16587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller				dev->demod_stats.mer);
16641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		}
16741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	} else {
16841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
16941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
17041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
17141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoetout:
17241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	mutex_unlock(&dev->bus_adap.lock);
17341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
17441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return ret;
17541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
17641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
17741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet/*
17841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * Note:
17941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet * - in AS102 SNR=MER
18041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *   - the SNR will be returned in linear terms, i.e. not in dB
18141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *   - the accuracy equals ±2dB for a SNR range from 4dB to 30dB
18241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet *   - the accuracy is >2dB for SNR values outside this range
18341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet */
18487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
18587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
18641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
18741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
18841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
18941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
19087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
19187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
19241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
19341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
19441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	*snr = dev->demod_stats.mer;
19541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
19641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
19741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
19841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
19941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
20087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
20187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
20241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
20341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
20441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
20541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
20687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
20787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
20841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
20941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
21041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	*ber = dev->ber;
21141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
21241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
21341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
21441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
21541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
21687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_read_signal_strength(struct dvb_frontend *fe,
21787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller					 u16 *strength)
21887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
21941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
22041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
22141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
22241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
22387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
22487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
22541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
22641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
22741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	*strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2);
22841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
22941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
23041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
23141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
23241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
23387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
23487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
23541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
23641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
23741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
23841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
23987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
24087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
24141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
24241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
24341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (dev->demod_stats.has_started)
24441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		*ucblocks = dev->demod_stats.bad_frame_count;
24541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	else
24641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		*ucblocks = 0;
24741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
24841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
24941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
25041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
25141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
25287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
25387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
25441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct as102_dev_t *dev;
25541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	int ret;
25641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
25741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	ENTER();
25841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
25987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	dev = (struct as102_dev_t *) fe->tuner_priv;
26087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (dev == NULL)
26141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -ENODEV;
26241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
26341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (mutex_lock_interruptible(&dev->bus_adap.lock))
26441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EBUSY;
26541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
26641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if (acquire) {
26741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		if (elna_enable)
268abfac0b64876294aaf1aab01df56041a3995a91fGianluca Gennari			as10x_cmd_set_context(&dev->bus_adap, CONTEXT_LNA, dev->elna_cfg);
26941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
27041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		ret = as10x_cmd_turn_on(&dev->bus_adap);
27141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	} else {
27241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		ret = as10x_cmd_turn_off(&dev->bus_adap);
27341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
27441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
27541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	mutex_unlock(&dev->bus_adap.lock);
27641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
27741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	LEAVE();
27841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return ret;
27941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
28041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
28141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoetstatic struct dvb_frontend_ops as102_fe_ops = {
282dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	.delsys = { SYS_DVBT },
28341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.info = {
2844f7b7c01fd2ca12c6c2d9eaa2a63e1c534f372aeDevin Heitmueller		.name			= "Unknown AS102 device",
28541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		.frequency_min		= 174000000,
28641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		.frequency_max		= 862000000,
28741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		.frequency_stepsize	= 166667,
28841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		.caps = FE_CAN_INVERSION_AUTO
28941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
29041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
29141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
29241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_QAM_AUTO
29341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_TRANSMISSION_MODE_AUTO
29441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_GUARD_INTERVAL_AUTO
29541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_HIERARCHY_AUTO
29641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_RECOVER
29741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			| FE_CAN_MUTE_TS
29841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	},
29941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
300dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	.set_frontend		= as102_fe_set_frontend,
301dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	.get_frontend		= as102_fe_get_frontend,
30241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.get_tune_settings	= as102_fe_get_tune_settings,
30341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
30441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.read_status		= as102_fe_read_status,
30541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.read_snr		= as102_fe_read_snr,
30641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.read_ber		= as102_fe_read_ber,
30741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.read_signal_strength	= as102_fe_read_signal_strength,
30841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.read_ucblocks		= as102_fe_read_ucblocks,
30941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	.ts_bus_ctrl		= as102_fe_ts_bus_ctrl,
31041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet};
31141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
31287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerint as102_dvb_unregister_fe(struct dvb_frontend *fe)
31387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
31441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* unregister frontend */
31541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dvb_unregister_frontend(fe);
31641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
31741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* detach frontend */
31841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dvb_frontend_detach(fe);
31992e9d1b70f7dd41576b9a890bc34a14f4cc2185bSylwester Nawrocki
32041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return 0;
32141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
32241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
32387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerint as102_dvb_register_fe(struct as102_dev_t *as102_dev,
32487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			  struct dvb_frontend *dvb_fe)
32587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
32641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	int errno;
32741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	struct dvb_adapter *dvb_adap;
32841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
32987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (as102_dev == NULL)
33041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		return -EINVAL;
33141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
33241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract dvb_adapter */
33341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dvb_adap = &as102_dev->dvb_adap;
33441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
33541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* init frontend callback ops */
33641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
3374f7b7c01fd2ca12c6c2d9eaa2a63e1c534f372aeDevin Heitmueller	strncpy(dvb_fe->ops.info.name, as102_dev->name,
3384f7b7c01fd2ca12c6c2d9eaa2a63e1c534f372aeDevin Heitmueller		sizeof(dvb_fe->ops.info.name));
33941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
340b47acf2a161b2f3001bf50dfa740477db6d32327Justin P. Mattock	/* register dvb frontend */
34141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	errno = dvb_register_frontend(dvb_adap, dvb_fe);
34287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	if (errno == 0)
34341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		dvb_fe->tuner_priv = as102_dev;
34441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
34541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return errno;
34641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
34741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
348dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehabstatic void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps,
34987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller					 struct as10x_tps *as10x_tps)
35087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
35141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
352b47acf2a161b2f3001bf50dfa740477db6d32327Justin P. Mattock	/* extract constellation */
353dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (as10x_tps->modulation) {
35487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CONST_QPSK:
355dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->modulation = QPSK;
35687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
35787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CONST_QAM16:
358dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->modulation = QAM_16;
35987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
36087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CONST_QAM64:
361dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->modulation = QAM_64;
36287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
36341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
36441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
36541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract hierarchy */
36687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (as10x_tps->hierarchy) {
36787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIER_NONE:
368dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->hierarchy = HIERARCHY_NONE;
36987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
37087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIER_ALPHA_1:
371dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->hierarchy = HIERARCHY_1;
37287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
37387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIER_ALPHA_2:
374dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->hierarchy = HIERARCHY_2;
37587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
37687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIER_ALPHA_4:
377dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		fe_tps->hierarchy = HIERARCHY_4;
37887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
37941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
38041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
38141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract code rate HP */
38287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (as10x_tps->code_rate_HP) {
38387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_1_2:
38487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_HP = FEC_1_2;
38587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
38687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_2_3:
38787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_HP = FEC_2_3;
38887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
38987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_3_4:
39087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_HP = FEC_3_4;
39187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
39287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_5_6:
39387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_HP = FEC_5_6;
39487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
39587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_7_8:
39687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_HP = FEC_7_8;
39787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
39841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
39941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
40041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract code rate LP */
40187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (as10x_tps->code_rate_LP) {
40287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_1_2:
40387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_LP = FEC_1_2;
40487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
40587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_2_3:
40687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_LP = FEC_2_3;
40787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
40887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_3_4:
40987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_LP = FEC_3_4;
41087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
41187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_5_6:
41287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_LP = FEC_5_6;
41387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
41487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case CODE_RATE_7_8:
41587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->code_rate_LP = FEC_7_8;
41687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
41741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
41841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
41941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract guard interval */
42087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (as10x_tps->guard_interval) {
42187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INT_1_32:
42287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->guard_interval = GUARD_INTERVAL_1_32;
42387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
42487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INT_1_16:
42587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->guard_interval = GUARD_INTERVAL_1_16;
42687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
42787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INT_1_8:
42887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->guard_interval = GUARD_INTERVAL_1_8;
42987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
43087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INT_1_4:
43187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->guard_interval = GUARD_INTERVAL_1_4;
43287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
43341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
43441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
43541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* extract transmission mode */
43687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (as10x_tps->transmission_mode) {
43787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TRANS_MODE_2K:
43887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->transmission_mode = TRANSMISSION_MODE_2K;
43987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
44087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TRANS_MODE_8K:
44187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		fe_tps->transmission_mode = TRANSMISSION_MODE_8K;
44287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
44341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
44441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
44541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
44687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmuellerstatic uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
44787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
44841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	uint8_t c;
44941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
45087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	switch (arg) {
45187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case FEC_1_2:
45287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_1_2;
45387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
45487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case FEC_2_3:
45587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_2_3;
45687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
45787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case FEC_3_4:
45887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_3_4;
45987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
46087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case FEC_5_6:
46187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_5_6;
46287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
46387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case FEC_7_8:
46487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_7_8;
46587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
46687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
46787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		c = CODE_RATE_UNKNOWN;
46887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
46941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
47041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
47141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	return c;
47241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
47341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
47441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoetstatic void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
475dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab			  struct dtv_frontend_properties *params)
47687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller{
47741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
47841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* set frequency */
47941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	tune_args->freq = params->frequency / 1000;
48041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
48141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/* fix interleaving_mode */
48241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	tune_args->interleaving_mode = INTLV_NATIVE;
48341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
484dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (params->bandwidth_hz) {
485dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	case 8000000:
48687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->bandwidth = BW_8_MHZ;
48787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
488dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	case 7000000:
48987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->bandwidth = BW_7_MHZ;
49087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
491dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	case 6000000:
49287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->bandwidth = BW_6_MHZ;
49387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
49487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
49587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->bandwidth = BW_8_MHZ;
49641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
49741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
498dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (params->guard_interval) {
49987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INTERVAL_1_32:
50087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->guard_interval = GUARD_INT_1_32;
50187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
50287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INTERVAL_1_16:
50387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->guard_interval = GUARD_INT_1_16;
50487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
50587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INTERVAL_1_8:
50687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->guard_interval = GUARD_INT_1_8;
50787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
50887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INTERVAL_1_4:
50987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->guard_interval = GUARD_INT_1_4;
51087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
51187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case GUARD_INTERVAL_AUTO:
51287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
51387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->guard_interval = GUARD_UNKNOWN;
51487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
51541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
51641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
517dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (params->modulation) {
51887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case QPSK:
519dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		tune_args->modulation = CONST_QPSK;
52087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
52187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case QAM_16:
522dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		tune_args->modulation = CONST_QAM16;
52387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
52487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case QAM_64:
525dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		tune_args->modulation = CONST_QAM64;
52687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
52787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
528dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		tune_args->modulation = CONST_UNKNOWN;
52987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
53041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
53141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
532dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (params->transmission_mode) {
53387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TRANSMISSION_MODE_2K:
53487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->transmission_mode = TRANS_MODE_2K;
53587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
53687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case TRANSMISSION_MODE_8K:
53787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->transmission_mode = TRANS_MODE_8K;
53887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
53987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	default:
54087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
54141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
54241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
543dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab	switch (params->hierarchy) {
54487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIERARCHY_NONE:
54587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->hierarchy = HIER_NONE;
54687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
54787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIERARCHY_1:
54887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->hierarchy = HIER_ALPHA_1;
54987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
55087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIERARCHY_2:
55187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->hierarchy = HIER_ALPHA_2;
55287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
55387ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIERARCHY_4:
55487ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->hierarchy = HIER_ALPHA_4;
55587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
55687ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller	case HIERARCHY_AUTO:
55787ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->hierarchy = HIER_UNKNOWN;
55887ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		break;
55941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
56041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
56141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	dprintk(debug, "tuner parameters: freq: %d  bw: 0x%02x  gi: 0x%02x\n",
56241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			params->frequency,
56341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->bandwidth,
56441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->guard_interval);
56541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
56641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	/*
56741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	 * Detect a hierarchy selection
56841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	 * if HP/LP are both set to FEC_NONE, HP will be selected.
56941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	 */
57041b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	if ((tune_args->hierarchy != HIER_NONE) &&
571dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		       ((params->code_rate_LP == FEC_NONE) ||
572dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab			(params->code_rate_HP == FEC_NONE))) {
57341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
574dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		if (params->code_rate_LP == FEC_NONE) {
57541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->hier_select = HIER_HIGH_PRIORITY;
57641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->code_rate =
577dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab			   as102_fe_get_code_rate(params->code_rate_HP);
57841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		}
57941b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
580dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab		if (params->code_rate_HP == FEC_NONE) {
58141b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->hier_select = HIER_LOW_PRIORITY;
58241b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->code_rate =
583dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab			   as102_fe_get_code_rate(params->code_rate_LP);
58441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		}
58541b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet
58641b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet		dprintk(debug, "\thierarchy: 0x%02x  "
58741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet				"selected: %s  code_rate_%s: 0x%02x\n",
58841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->hierarchy,
58987ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			tune_args->hier_select == HIER_HIGH_PRIORITY ?
59087ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			"HP" : "LP",
59187ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			tune_args->hier_select == HIER_HIGH_PRIORITY ?
59287ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller			"HP" : "LP",
59341b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet			tune_args->code_rate);
59441b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	} else {
59587ad567e257523ea8857507eaaed866ba5d20d5dDevin Heitmueller		tune_args->code_rate =
596dfc6438410ebe2b9858aaf41376f35a0a68eeb4bMauro Carvalho Chehab			as102_fe_get_code_rate(params->code_rate_HP);
59741b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet	}
59841b44e0418112e694f9b7beb8088efbb8c9c0053Pierrick Hascoet}
599