162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci	Frontend/Card driver for TwinHan DST Frontend
462306a36Sopenharmony_ci	Copyright (C) 2003 Jamie Honan
562306a36Sopenharmony_ci	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci*/
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/string.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/vmalloc.h>
1762306a36Sopenharmony_ci#include <linux/delay.h>
1862306a36Sopenharmony_ci#include <asm/div64.h>
1962306a36Sopenharmony_ci#include <media/dvb_frontend.h>
2062306a36Sopenharmony_ci#include "dst_priv.h"
2162306a36Sopenharmony_ci#include "dst_common.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic unsigned int verbose;
2462306a36Sopenharmony_cimodule_param(verbose, int, 0644);
2562306a36Sopenharmony_ciMODULE_PARM_DESC(verbose, "verbosity level (0 to 3)");
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic unsigned int dst_addons;
2862306a36Sopenharmony_cimodule_param(dst_addons, int, 0644);
2962306a36Sopenharmony_ciMODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic unsigned int dst_algo;
3262306a36Sopenharmony_cimodule_param(dst_algo, int, 0644);
3362306a36Sopenharmony_ciMODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define HAS_LOCK		1
3662306a36Sopenharmony_ci#define ATTEMPT_TUNE		2
3762306a36Sopenharmony_ci#define HAS_POWER		4
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define dprintk(level, fmt, arg...) do {				\
4062306a36Sopenharmony_ci	if (level >= verbose)						\
4162306a36Sopenharmony_ci		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
4262306a36Sopenharmony_ci		       __func__, ##arg);				\
4362306a36Sopenharmony_ci} while(0)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic int dst_command(struct dst_state *state, u8 *data, u8 len);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic void dst_packsize(struct dst_state *state, int psize)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	union dst_gpio_packet bits;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	bits.psize = psize;
5262306a36Sopenharmony_ci	bt878_device_control(state->bt, DST_IG_TS, &bits);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
5662306a36Sopenharmony_ci			 u32 outhigh, int delay)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	union dst_gpio_packet enb;
5962306a36Sopenharmony_ci	union dst_gpio_packet bits;
6062306a36Sopenharmony_ci	int err;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	enb.enb.mask = mask;
6362306a36Sopenharmony_ci	enb.enb.enable = enbb;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	dprintk(2, "mask=[%04x], enbb=[%04x], outhigh=[%04x]\n",
6662306a36Sopenharmony_ci		mask, enbb, outhigh);
6762306a36Sopenharmony_ci	if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
6862306a36Sopenharmony_ci		dprintk(2, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n",
6962306a36Sopenharmony_ci			err, mask, enbb);
7062306a36Sopenharmony_ci		return -EREMOTEIO;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	udelay(1000);
7362306a36Sopenharmony_ci	/* because complete disabling means no output, no need to do output packet */
7462306a36Sopenharmony_ci	if (enbb == 0)
7562306a36Sopenharmony_ci		return 0;
7662306a36Sopenharmony_ci	if (delay)
7762306a36Sopenharmony_ci		msleep(10);
7862306a36Sopenharmony_ci	bits.outp.mask = enbb;
7962306a36Sopenharmony_ci	bits.outp.highvals = outhigh;
8062306a36Sopenharmony_ci	if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
8162306a36Sopenharmony_ci		dprintk(2, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n",
8262306a36Sopenharmony_ci			err, enbb, outhigh);
8362306a36Sopenharmony_ci		return -EREMOTEIO;
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	return 0;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic int dst_gpio_inb(struct dst_state *state, u8 *result)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	union dst_gpio_packet rd_packet;
9262306a36Sopenharmony_ci	int err;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	*result = 0;
9562306a36Sopenharmony_ci	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
9662306a36Sopenharmony_ci		pr_err("dst_gpio_inb error (err == %i)\n", err);
9762306a36Sopenharmony_ci		return -EREMOTEIO;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci	*result = (u8) rd_packet.rd.value;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return 0;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciint rdc_reset_state(struct dst_state *state)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	dprintk(2, "Resetting state machine\n");
10762306a36Sopenharmony_ci	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
10862306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
10962306a36Sopenharmony_ci		return -1;
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci	msleep(10);
11262306a36Sopenharmony_ci	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
11362306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
11462306a36Sopenharmony_ci		msleep(10);
11562306a36Sopenharmony_ci		return -1;
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	return 0;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ciEXPORT_SYMBOL(rdc_reset_state);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic int rdc_8820_reset(struct dst_state *state)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	dprintk(3, "Resetting DST\n");
12562306a36Sopenharmony_ci	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
12662306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
12762306a36Sopenharmony_ci		return -1;
12862306a36Sopenharmony_ci	}
12962306a36Sopenharmony_ci	udelay(1000);
13062306a36Sopenharmony_ci	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
13162306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
13262306a36Sopenharmony_ci		return -1;
13362306a36Sopenharmony_ci	}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return 0;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic int dst_pio_enable(struct dst_state *state)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
14162306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
14262306a36Sopenharmony_ci		return -1;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci	udelay(1000);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ciint dst_pio_disable(struct dst_state *state)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
15262306a36Sopenharmony_ci		pr_err("dst_gpio_outb ERROR !\n");
15362306a36Sopenharmony_ci		return -1;
15462306a36Sopenharmony_ci	}
15562306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_FW_1)
15662306a36Sopenharmony_ci		udelay(1000);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return 0;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ciEXPORT_SYMBOL(dst_pio_disable);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciint dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	u8 reply;
16562306a36Sopenharmony_ci	int i;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	for (i = 0; i < 200; i++) {
16862306a36Sopenharmony_ci		if (dst_gpio_inb(state, &reply) < 0) {
16962306a36Sopenharmony_ci			pr_err("dst_gpio_inb ERROR !\n");
17062306a36Sopenharmony_ci			return -1;
17162306a36Sopenharmony_ci		}
17262306a36Sopenharmony_ci		if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
17362306a36Sopenharmony_ci			dprintk(2, "dst wait ready after %d\n", i);
17462306a36Sopenharmony_ci			return 1;
17562306a36Sopenharmony_ci		}
17662306a36Sopenharmony_ci		msleep(10);
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci	dprintk(1, "dst wait NOT ready after %d\n", i);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	return 0;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ciEXPORT_SYMBOL(dst_wait_dst_ready);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ciint dst_error_recovery(struct dst_state *state)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	dprintk(1, "Trying to return from previous errors.\n");
18762306a36Sopenharmony_ci	dst_pio_disable(state);
18862306a36Sopenharmony_ci	msleep(10);
18962306a36Sopenharmony_ci	dst_pio_enable(state);
19062306a36Sopenharmony_ci	msleep(10);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	return 0;
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ciEXPORT_SYMBOL(dst_error_recovery);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ciint dst_error_bailout(struct dst_state *state)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	dprintk(2, "Trying to bailout from previous error.\n");
19962306a36Sopenharmony_ci	rdc_8820_reset(state);
20062306a36Sopenharmony_ci	dst_pio_disable(state);
20162306a36Sopenharmony_ci	msleep(10);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	return 0;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ciEXPORT_SYMBOL(dst_error_bailout);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ciint dst_comm_init(struct dst_state *state)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	dprintk(2, "Initializing DST.\n");
21062306a36Sopenharmony_ci	if ((dst_pio_enable(state)) < 0) {
21162306a36Sopenharmony_ci		pr_err("PIO Enable Failed\n");
21262306a36Sopenharmony_ci		return -1;
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci	if ((rdc_reset_state(state)) < 0) {
21562306a36Sopenharmony_ci		pr_err("RDC 8820 State RESET Failed.\n");
21662306a36Sopenharmony_ci		return -1;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_FW_1)
21962306a36Sopenharmony_ci		msleep(100);
22062306a36Sopenharmony_ci	else
22162306a36Sopenharmony_ci		msleep(5);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	return 0;
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ciEXPORT_SYMBOL(dst_comm_init);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ciint write_dst(struct dst_state *state, u8 *data, u8 len)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	struct i2c_msg msg = {
23062306a36Sopenharmony_ci		.addr = state->config->demod_address,
23162306a36Sopenharmony_ci		.flags = 0,
23262306a36Sopenharmony_ci		.buf = data,
23362306a36Sopenharmony_ci		.len = len
23462306a36Sopenharmony_ci	};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	int err;
23762306a36Sopenharmony_ci	u8 cnt;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	dprintk(1, "writing [ %*ph ]\n", len, data);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	for (cnt = 0; cnt < 2; cnt++) {
24262306a36Sopenharmony_ci		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
24362306a36Sopenharmony_ci			dprintk(2, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n",
24462306a36Sopenharmony_ci				err, len, data[0]);
24562306a36Sopenharmony_ci			dst_error_recovery(state);
24662306a36Sopenharmony_ci			continue;
24762306a36Sopenharmony_ci		} else
24862306a36Sopenharmony_ci			break;
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci	if (cnt >= 2) {
25162306a36Sopenharmony_ci		dprintk(2, "RDC 8820 RESET\n");
25262306a36Sopenharmony_ci		dst_error_bailout(state);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		return -1;
25562306a36Sopenharmony_ci	}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return 0;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ciEXPORT_SYMBOL(write_dst);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ciint read_dst(struct dst_state *state, u8 *ret, u8 len)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	struct i2c_msg msg = {
26462306a36Sopenharmony_ci		.addr = state->config->demod_address,
26562306a36Sopenharmony_ci		.flags = I2C_M_RD,
26662306a36Sopenharmony_ci		.buf = ret,
26762306a36Sopenharmony_ci		.len = len
26862306a36Sopenharmony_ci	};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	int err;
27162306a36Sopenharmony_ci	int cnt;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	for (cnt = 0; cnt < 2; cnt++) {
27462306a36Sopenharmony_ci		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
27562306a36Sopenharmony_ci			dprintk(2, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n",
27662306a36Sopenharmony_ci				err, len, ret[0]);
27762306a36Sopenharmony_ci			dst_error_recovery(state);
27862306a36Sopenharmony_ci			continue;
27962306a36Sopenharmony_ci		} else
28062306a36Sopenharmony_ci			break;
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci	if (cnt >= 2) {
28362306a36Sopenharmony_ci		dprintk(2, "RDC 8820 RESET\n");
28462306a36Sopenharmony_ci		dst_error_bailout(state);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci		return -1;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	dprintk(3, "reply is %*ph\n", len, ret);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return 0;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ciEXPORT_SYMBOL(read_dst);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic int dst_set_polarization(struct dst_state *state)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	switch (state->voltage) {
29762306a36Sopenharmony_ci	case SEC_VOLTAGE_13:	/*	Vertical	*/
29862306a36Sopenharmony_ci		dprintk(2, "Polarization=[Vertical]\n");
29962306a36Sopenharmony_ci		state->tx_tuna[8] &= ~0x40;
30062306a36Sopenharmony_ci		break;
30162306a36Sopenharmony_ci	case SEC_VOLTAGE_18:	/*	Horizontal	*/
30262306a36Sopenharmony_ci		dprintk(2, "Polarization=[Horizontal]\n");
30362306a36Sopenharmony_ci		state->tx_tuna[8] |= 0x40;
30462306a36Sopenharmony_ci		break;
30562306a36Sopenharmony_ci	case SEC_VOLTAGE_OFF:
30662306a36Sopenharmony_ci		break;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	return 0;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic int dst_set_freq(struct dst_state *state, u32 freq)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	state->frequency = freq;
31562306a36Sopenharmony_ci	dprintk(2, "set Frequency %u\n", freq);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT) {
31862306a36Sopenharmony_ci		freq = freq / 1000;
31962306a36Sopenharmony_ci		if (freq < 950 || freq > 2150)
32062306a36Sopenharmony_ci			return -EINVAL;
32162306a36Sopenharmony_ci		state->tx_tuna[2] = (freq >> 8);
32262306a36Sopenharmony_ci		state->tx_tuna[3] = (u8) freq;
32362306a36Sopenharmony_ci		state->tx_tuna[4] = 0x01;
32462306a36Sopenharmony_ci		state->tx_tuna[8] &= ~0x04;
32562306a36Sopenharmony_ci		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
32662306a36Sopenharmony_ci			if (freq < 1531)
32762306a36Sopenharmony_ci				state->tx_tuna[8] |= 0x04;
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_TERR) {
33062306a36Sopenharmony_ci		freq = freq / 1000;
33162306a36Sopenharmony_ci		if (freq < 137000 || freq > 858000)
33262306a36Sopenharmony_ci			return -EINVAL;
33362306a36Sopenharmony_ci		state->tx_tuna[2] = (freq >> 16) & 0xff;
33462306a36Sopenharmony_ci		state->tx_tuna[3] = (freq >> 8) & 0xff;
33562306a36Sopenharmony_ci		state->tx_tuna[4] = (u8) freq;
33662306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
33762306a36Sopenharmony_ci		freq = freq / 1000;
33862306a36Sopenharmony_ci		state->tx_tuna[2] = (freq >> 16) & 0xff;
33962306a36Sopenharmony_ci		state->tx_tuna[3] = (freq >> 8) & 0xff;
34062306a36Sopenharmony_ci		state->tx_tuna[4] = (u8) freq;
34162306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_ATSC) {
34262306a36Sopenharmony_ci		freq = freq / 1000;
34362306a36Sopenharmony_ci		if (freq < 51000 || freq > 858000)
34462306a36Sopenharmony_ci			return -EINVAL;
34562306a36Sopenharmony_ci		state->tx_tuna[2] = (freq >> 16) & 0xff;
34662306a36Sopenharmony_ci		state->tx_tuna[3] = (freq >>  8) & 0xff;
34762306a36Sopenharmony_ci		state->tx_tuna[4] = (u8) freq;
34862306a36Sopenharmony_ci		state->tx_tuna[5] = 0x00;		/*	ATSC	*/
34962306a36Sopenharmony_ci		state->tx_tuna[6] = 0x00;
35062306a36Sopenharmony_ci		if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
35162306a36Sopenharmony_ci			state->tx_tuna[7] = 0x00;	/*	Digital	*/
35262306a36Sopenharmony_ci	} else
35362306a36Sopenharmony_ci		return -EINVAL;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	return 0;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	state->bandwidth = bandwidth;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_TERR)
36362306a36Sopenharmony_ci		return -EOPNOTSUPP;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	switch (bandwidth) {
36662306a36Sopenharmony_ci	case 6000000:
36762306a36Sopenharmony_ci		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
36862306a36Sopenharmony_ci			state->tx_tuna[7] = 0x06;
36962306a36Sopenharmony_ci		else {
37062306a36Sopenharmony_ci			state->tx_tuna[6] = 0x06;
37162306a36Sopenharmony_ci			state->tx_tuna[7] = 0x00;
37262306a36Sopenharmony_ci		}
37362306a36Sopenharmony_ci		break;
37462306a36Sopenharmony_ci	case 7000000:
37562306a36Sopenharmony_ci		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
37662306a36Sopenharmony_ci			state->tx_tuna[7] = 0x07;
37762306a36Sopenharmony_ci		else {
37862306a36Sopenharmony_ci			state->tx_tuna[6] = 0x07;
37962306a36Sopenharmony_ci			state->tx_tuna[7] = 0x00;
38062306a36Sopenharmony_ci		}
38162306a36Sopenharmony_ci		break;
38262306a36Sopenharmony_ci	case 8000000:
38362306a36Sopenharmony_ci		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
38462306a36Sopenharmony_ci			state->tx_tuna[7] = 0x08;
38562306a36Sopenharmony_ci		else {
38662306a36Sopenharmony_ci			state->tx_tuna[6] = 0x08;
38762306a36Sopenharmony_ci			state->tx_tuna[7] = 0x00;
38862306a36Sopenharmony_ci		}
38962306a36Sopenharmony_ci		break;
39062306a36Sopenharmony_ci	default:
39162306a36Sopenharmony_ci		return -EINVAL;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	return 0;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic int dst_set_inversion(struct dst_state *state,
39862306a36Sopenharmony_ci			     enum fe_spectral_inversion inversion)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	state->inversion = inversion;
40162306a36Sopenharmony_ci	switch (inversion) {
40262306a36Sopenharmony_ci	case INVERSION_OFF:	/*	Inversion = Normal	*/
40362306a36Sopenharmony_ci		state->tx_tuna[8] &= ~0x80;
40462306a36Sopenharmony_ci		break;
40562306a36Sopenharmony_ci	case INVERSION_ON:
40662306a36Sopenharmony_ci		state->tx_tuna[8] |= 0x80;
40762306a36Sopenharmony_ci		break;
40862306a36Sopenharmony_ci	default:
40962306a36Sopenharmony_ci		return -EINVAL;
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	return 0;
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cistatic int dst_set_fec(struct dst_state *state, enum fe_code_rate fec)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	state->fec = fec;
41862306a36Sopenharmony_ci	return 0;
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic enum fe_code_rate dst_get_fec(struct dst_state *state)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	return state->fec;
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic int dst_set_symbolrate(struct dst_state *state, u32 srate)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	u32 symcalc;
42962306a36Sopenharmony_ci	u64 sval;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	state->symbol_rate = srate;
43262306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_TERR) {
43362306a36Sopenharmony_ci		return -EOPNOTSUPP;
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci	dprintk(2, "set symrate %u\n", srate);
43662306a36Sopenharmony_ci	srate /= 1000;
43762306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT) {
43862306a36Sopenharmony_ci		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
43962306a36Sopenharmony_ci			sval = srate;
44062306a36Sopenharmony_ci			sval <<= 20;
44162306a36Sopenharmony_ci			do_div(sval, 88000);
44262306a36Sopenharmony_ci			symcalc = (u32) sval;
44362306a36Sopenharmony_ci			dprintk(2, "set symcalc %u\n", symcalc);
44462306a36Sopenharmony_ci			state->tx_tuna[5] = (u8) (symcalc >> 12);
44562306a36Sopenharmony_ci			state->tx_tuna[6] = (u8) (symcalc >> 4);
44662306a36Sopenharmony_ci			state->tx_tuna[7] = (u8) (symcalc << 4);
44762306a36Sopenharmony_ci		} else {
44862306a36Sopenharmony_ci			state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
44962306a36Sopenharmony_ci			state->tx_tuna[6] = (u8) (srate >> 8);
45062306a36Sopenharmony_ci			state->tx_tuna[7] = (u8) srate;
45162306a36Sopenharmony_ci		}
45262306a36Sopenharmony_ci		state->tx_tuna[8] &= ~0x20;
45362306a36Sopenharmony_ci		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
45462306a36Sopenharmony_ci			if (srate > 8000)
45562306a36Sopenharmony_ci				state->tx_tuna[8] |= 0x20;
45662306a36Sopenharmony_ci		}
45762306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
45862306a36Sopenharmony_ci		dprintk(3, "%s\n", state->fw_name);
45962306a36Sopenharmony_ci		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
46062306a36Sopenharmony_ci			state->tx_tuna[5] = (u8) (srate >> 8);
46162306a36Sopenharmony_ci			state->tx_tuna[6] = (u8) srate;
46262306a36Sopenharmony_ci			state->tx_tuna[7] = 0x00;
46362306a36Sopenharmony_ci		} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
46462306a36Sopenharmony_ci			state->tx_tuna[5] = 0x00;
46562306a36Sopenharmony_ci			state->tx_tuna[6] = (u8) (srate >> 8);
46662306a36Sopenharmony_ci			state->tx_tuna[7] = (u8) srate;
46762306a36Sopenharmony_ci		}
46862306a36Sopenharmony_ci	}
46962306a36Sopenharmony_ci	return 0;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic int dst_set_modulation(struct dst_state *state,
47362306a36Sopenharmony_ci			      enum fe_modulation modulation)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_CABLE)
47662306a36Sopenharmony_ci		return -EOPNOTSUPP;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	state->modulation = modulation;
47962306a36Sopenharmony_ci	switch (modulation) {
48062306a36Sopenharmony_ci	case QAM_16:
48162306a36Sopenharmony_ci		state->tx_tuna[8] = 0x10;
48262306a36Sopenharmony_ci		break;
48362306a36Sopenharmony_ci	case QAM_32:
48462306a36Sopenharmony_ci		state->tx_tuna[8] = 0x20;
48562306a36Sopenharmony_ci		break;
48662306a36Sopenharmony_ci	case QAM_64:
48762306a36Sopenharmony_ci		state->tx_tuna[8] = 0x40;
48862306a36Sopenharmony_ci		break;
48962306a36Sopenharmony_ci	case QAM_128:
49062306a36Sopenharmony_ci		state->tx_tuna[8] = 0x80;
49162306a36Sopenharmony_ci		break;
49262306a36Sopenharmony_ci	case QAM_256:
49362306a36Sopenharmony_ci		if (!strncmp(state->fw_name, "DCTNEW", 6))
49462306a36Sopenharmony_ci			state->tx_tuna[8] = 0xff;
49562306a36Sopenharmony_ci		else if (!strncmp(state->fw_name, "DCT-CI", 6))
49662306a36Sopenharmony_ci			state->tx_tuna[8] = 0x00;
49762306a36Sopenharmony_ci		break;
49862306a36Sopenharmony_ci	case QPSK:
49962306a36Sopenharmony_ci	case QAM_AUTO:
50062306a36Sopenharmony_ci	case VSB_8:
50162306a36Sopenharmony_ci	case VSB_16:
50262306a36Sopenharmony_ci	default:
50362306a36Sopenharmony_ci		return -EINVAL;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	return 0;
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic enum fe_modulation dst_get_modulation(struct dst_state *state)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	return state->modulation;
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ciu8 dst_check_sum(u8 *buf, u32 len)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	u32 i;
51962306a36Sopenharmony_ci	u8 val = 0;
52062306a36Sopenharmony_ci	if (!len)
52162306a36Sopenharmony_ci		return 0;
52262306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
52362306a36Sopenharmony_ci		val += buf[i];
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci	return ((~val) + 1);
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ciEXPORT_SYMBOL(dst_check_sum);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic void dst_type_flags_print(struct dst_state *state)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	u32 type_flags = state->type_flags;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	pr_err("DST type flags :\n");
53462306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_TS188)
53562306a36Sopenharmony_ci		pr_err(" 0x%x newtuner\n", DST_TYPE_HAS_TS188);
53662306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
53762306a36Sopenharmony_ci		pr_err(" 0x%x newtuner 2\n", DST_TYPE_HAS_NEWTUNE_2);
53862306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_TS204)
53962306a36Sopenharmony_ci		pr_err(" 0x%x ts204\n", DST_TYPE_HAS_TS204);
54062306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_VLF)
54162306a36Sopenharmony_ci		pr_err(" 0x%x VLF\n", DST_TYPE_HAS_VLF);
54262306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_SYMDIV)
54362306a36Sopenharmony_ci		pr_err(" 0x%x symdiv\n", DST_TYPE_HAS_SYMDIV);
54462306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_FW_1)
54562306a36Sopenharmony_ci		pr_err(" 0x%x firmware version = 1\n", DST_TYPE_HAS_FW_1);
54662306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_FW_2)
54762306a36Sopenharmony_ci		pr_err(" 0x%x firmware version = 2\n", DST_TYPE_HAS_FW_2);
54862306a36Sopenharmony_ci	if (type_flags & DST_TYPE_HAS_FW_3)
54962306a36Sopenharmony_ci		pr_err(" 0x%x firmware version = 3\n", DST_TYPE_HAS_FW_3);
55062306a36Sopenharmony_ci	pr_err("\n");
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic int dst_type_print(struct dst_state *state, u8 type)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	char *otype;
55762306a36Sopenharmony_ci	switch (type) {
55862306a36Sopenharmony_ci	case DST_TYPE_IS_SAT:
55962306a36Sopenharmony_ci		otype = "satellite";
56062306a36Sopenharmony_ci		break;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	case DST_TYPE_IS_TERR:
56362306a36Sopenharmony_ci		otype = "terrestrial";
56462306a36Sopenharmony_ci		break;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	case DST_TYPE_IS_CABLE:
56762306a36Sopenharmony_ci		otype = "cable";
56862306a36Sopenharmony_ci		break;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	case DST_TYPE_IS_ATSC:
57162306a36Sopenharmony_ci		otype = "atsc";
57262306a36Sopenharmony_ci		break;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	default:
57562306a36Sopenharmony_ci		dprintk(2, "invalid dst type %d\n", type);
57662306a36Sopenharmony_ci		return -EINVAL;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci	dprintk(2, "DST type: %s\n", otype);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	return 0;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_cistatic struct tuner_types tuner_list[] = {
58462306a36Sopenharmony_ci	{
58562306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_L64724,
58662306a36Sopenharmony_ci		.tuner_name = "L 64724",
58762306a36Sopenharmony_ci		.board_name = "UNKNOWN",
58862306a36Sopenharmony_ci		.fw_name    = "UNKNOWN"
58962306a36Sopenharmony_ci	},
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	{
59262306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_STV0299,
59362306a36Sopenharmony_ci		.tuner_name = "STV 0299",
59462306a36Sopenharmony_ci		.board_name = "VP1020",
59562306a36Sopenharmony_ci		.fw_name    = "DST-MOT"
59662306a36Sopenharmony_ci	},
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	{
59962306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_STV0299,
60062306a36Sopenharmony_ci		.tuner_name = "STV 0299",
60162306a36Sopenharmony_ci		.board_name = "VP1020",
60262306a36Sopenharmony_ci		.fw_name    = "DST-03T"
60362306a36Sopenharmony_ci	},
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	{
60662306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_MB86A15,
60762306a36Sopenharmony_ci		.tuner_name = "MB 86A15",
60862306a36Sopenharmony_ci		.board_name = "VP1022",
60962306a36Sopenharmony_ci		.fw_name    = "DST-03T"
61062306a36Sopenharmony_ci	},
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	{
61362306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_MB86A15,
61462306a36Sopenharmony_ci		.tuner_name = "MB 86A15",
61562306a36Sopenharmony_ci		.board_name = "VP1025",
61662306a36Sopenharmony_ci		.fw_name    = "DST-03T"
61762306a36Sopenharmony_ci	},
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	{
62062306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_STV0299,
62162306a36Sopenharmony_ci		.tuner_name = "STV 0299",
62262306a36Sopenharmony_ci		.board_name = "VP1030",
62362306a36Sopenharmony_ci		.fw_name    = "DST-CI"
62462306a36Sopenharmony_ci	},
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	{
62762306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_STV0299,
62862306a36Sopenharmony_ci		.tuner_name = "STV 0299",
62962306a36Sopenharmony_ci		.board_name = "VP1030",
63062306a36Sopenharmony_ci		.fw_name    = "DSTMCI"
63162306a36Sopenharmony_ci	},
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	{
63462306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
63562306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
63662306a36Sopenharmony_ci		.board_name = "VP2021",
63762306a36Sopenharmony_ci		.fw_name    = "DCTNEW"
63862306a36Sopenharmony_ci	},
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	{
64162306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
64262306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
64362306a36Sopenharmony_ci		.board_name = "VP2030",
64462306a36Sopenharmony_ci		.fw_name    = "DCT-CI"
64562306a36Sopenharmony_ci	},
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	{
64862306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
64962306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
65062306a36Sopenharmony_ci		.board_name = "VP2031",
65162306a36Sopenharmony_ci		.fw_name    = "DCT-CI"
65262306a36Sopenharmony_ci	},
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	{
65562306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
65662306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
65762306a36Sopenharmony_ci		.board_name = "VP2040",
65862306a36Sopenharmony_ci		.fw_name    = "DCT-CI"
65962306a36Sopenharmony_ci	},
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	{
66262306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
66362306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
66462306a36Sopenharmony_ci		.board_name = "VP3020",
66562306a36Sopenharmony_ci		.fw_name    = "DTTFTA"
66662306a36Sopenharmony_ci	},
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	{
66962306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
67062306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
67162306a36Sopenharmony_ci		.board_name = "VP3021",
67262306a36Sopenharmony_ci		.fw_name    = "DTTFTA"
67362306a36Sopenharmony_ci	},
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	{
67662306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_TDA10046,
67762306a36Sopenharmony_ci		.tuner_name = "TDA10046",
67862306a36Sopenharmony_ci		.board_name = "VP3040",
67962306a36Sopenharmony_ci		.fw_name    = "DTT-CI"
68062306a36Sopenharmony_ci	},
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	{
68362306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_UNKNOWN,
68462306a36Sopenharmony_ci		.tuner_name = "UNKNOWN",
68562306a36Sopenharmony_ci		.board_name = "VP3051",
68662306a36Sopenharmony_ci		.fw_name    = "DTTNXT"
68762306a36Sopenharmony_ci	},
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	{
69062306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_NXT200x,
69162306a36Sopenharmony_ci		.tuner_name = "NXT200x",
69262306a36Sopenharmony_ci		.board_name = "VP3220",
69362306a36Sopenharmony_ci		.fw_name    = "ATSCDI"
69462306a36Sopenharmony_ci	},
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	{
69762306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_NXT200x,
69862306a36Sopenharmony_ci		.tuner_name = "NXT200x",
69962306a36Sopenharmony_ci		.board_name = "VP3250",
70062306a36Sopenharmony_ci		.fw_name    = "ATSCAD"
70162306a36Sopenharmony_ci	},
70262306a36Sopenharmony_ci};
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci/*
70562306a36Sopenharmony_ci	Known cards list
70662306a36Sopenharmony_ci	Satellite
70762306a36Sopenharmony_ci	-------------------
70862306a36Sopenharmony_ci		  200103A
70962306a36Sopenharmony_ci	VP-1020   DST-MOT	LG(old), TS=188
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	VP-1020   DST-03T	LG(new), TS=204
71262306a36Sopenharmony_ci	VP-1022   DST-03T	LG(new), TS=204
71362306a36Sopenharmony_ci	VP-1025   DST-03T	LG(new), TS=204
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	VP-1030   DSTMCI,	LG(new), TS=188
71662306a36Sopenharmony_ci	VP-1032   DSTMCI,	LG(new), TS=188
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	Cable
71962306a36Sopenharmony_ci	-------------------
72062306a36Sopenharmony_ci	VP-2030   DCT-CI,	Samsung, TS=204
72162306a36Sopenharmony_ci	VP-2021   DCT-CI,	Unknown, TS=204
72262306a36Sopenharmony_ci	VP-2031   DCT-CI,	Philips, TS=188
72362306a36Sopenharmony_ci	VP-2040   DCT-CI,	Philips, TS=188, with CA daughter board
72462306a36Sopenharmony_ci	VP-2040   DCT-CI,	Philips, TS=204, without CA daughter board
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	Terrestrial
72762306a36Sopenharmony_ci	-------------------
72862306a36Sopenharmony_ci	VP-3050  DTTNXT			 TS=188
72962306a36Sopenharmony_ci	VP-3040  DTT-CI,	Philips, TS=188
73062306a36Sopenharmony_ci	VP-3040  DTT-CI,	Philips, TS=204
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	ATSC
73362306a36Sopenharmony_ci	-------------------
73462306a36Sopenharmony_ci	VP-3220  ATSCDI,		 TS=188
73562306a36Sopenharmony_ci	VP-3250  ATSCAD,		 TS=188
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci*/
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cistatic struct dst_types dst_tlist[] = {
74062306a36Sopenharmony_ci	{
74162306a36Sopenharmony_ci		.device_id = "200103A",
74262306a36Sopenharmony_ci		.offset = 0,
74362306a36Sopenharmony_ci		.dst_type =  DST_TYPE_IS_SAT,
74462306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
74562306a36Sopenharmony_ci		.dst_feature = 0,
74662306a36Sopenharmony_ci		.tuner_type = 0
74762306a36Sopenharmony_ci	},	/*	obsolete	*/
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	{
75062306a36Sopenharmony_ci		.device_id = "DST-020",
75162306a36Sopenharmony_ci		.offset = 0,
75262306a36Sopenharmony_ci		.dst_type =  DST_TYPE_IS_SAT,
75362306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
75462306a36Sopenharmony_ci		.dst_feature = 0,
75562306a36Sopenharmony_ci		.tuner_type = 0
75662306a36Sopenharmony_ci	},	/*	obsolete	*/
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	{
75962306a36Sopenharmony_ci		.device_id = "DST-030",
76062306a36Sopenharmony_ci		.offset =  0,
76162306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
76262306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
76362306a36Sopenharmony_ci		.dst_feature = 0,
76462306a36Sopenharmony_ci		.tuner_type = 0
76562306a36Sopenharmony_ci	},	/*	obsolete	*/
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	{
76862306a36Sopenharmony_ci		.device_id = "DST-03T",
76962306a36Sopenharmony_ci		.offset = 0,
77062306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
77162306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
77262306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
77362306a36Sopenharmony_ci							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
77462306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_MULTI
77562306a36Sopenharmony_ci	 },
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	{
77862306a36Sopenharmony_ci		.device_id = "DST-MOT",
77962306a36Sopenharmony_ci		.offset =  0,
78062306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
78162306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
78262306a36Sopenharmony_ci		.dst_feature = 0,
78362306a36Sopenharmony_ci		.tuner_type = 0
78462306a36Sopenharmony_ci	},	/*	obsolete	*/
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	{
78762306a36Sopenharmony_ci		.device_id = "DST-CI",
78862306a36Sopenharmony_ci		.offset = 1,
78962306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
79062306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
79162306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_CA,
79262306a36Sopenharmony_ci		.tuner_type = 0
79362306a36Sopenharmony_ci	},	/*	An OEM board	*/
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	{
79662306a36Sopenharmony_ci		.device_id = "DSTMCI",
79762306a36Sopenharmony_ci		.offset = 1,
79862306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
79962306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
80062306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
80162306a36Sopenharmony_ci							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
80262306a36Sopenharmony_ci		.tuner_type = TUNER_TYPE_MULTI
80362306a36Sopenharmony_ci	},
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	{
80662306a36Sopenharmony_ci		.device_id = "DSTFCI",
80762306a36Sopenharmony_ci		.offset = 1,
80862306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_SAT,
80962306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
81062306a36Sopenharmony_ci		.dst_feature = 0,
81162306a36Sopenharmony_ci		.tuner_type = 0
81262306a36Sopenharmony_ci	},	/* unknown to vendor	*/
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	{
81562306a36Sopenharmony_ci		.device_id = "DCT-CI",
81662306a36Sopenharmony_ci		.offset = 1,
81762306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_CABLE,
81862306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1	| DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
81962306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_CA,
82062306a36Sopenharmony_ci		.tuner_type = 0
82162306a36Sopenharmony_ci	},
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	{
82462306a36Sopenharmony_ci		.device_id = "DCTNEW",
82562306a36Sopenharmony_ci		.offset = 1,
82662306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_CABLE,
82762306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
82862306a36Sopenharmony_ci		.dst_feature = 0,
82962306a36Sopenharmony_ci		.tuner_type = 0
83062306a36Sopenharmony_ci	},
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	{
83362306a36Sopenharmony_ci		.device_id = "DTT-CI",
83462306a36Sopenharmony_ci		.offset = 1,
83562306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_TERR,
83662306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
83762306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_CA,
83862306a36Sopenharmony_ci		.tuner_type = 0
83962306a36Sopenharmony_ci	},
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	{
84262306a36Sopenharmony_ci		.device_id = "DTTDIG",
84362306a36Sopenharmony_ci		.offset = 1,
84462306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_TERR,
84562306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_FW_2,
84662306a36Sopenharmony_ci		.dst_feature = 0,
84762306a36Sopenharmony_ci		.tuner_type = 0
84862306a36Sopenharmony_ci	},
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	{
85162306a36Sopenharmony_ci		.device_id = "DTTNXT",
85262306a36Sopenharmony_ci		.offset = 1,
85362306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_TERR,
85462306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_FW_2,
85562306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_ANALOG,
85662306a36Sopenharmony_ci		.tuner_type = 0
85762306a36Sopenharmony_ci	},
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	{
86062306a36Sopenharmony_ci		.device_id = "ATSCDI",
86162306a36Sopenharmony_ci		.offset = 1,
86262306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_ATSC,
86362306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_FW_2,
86462306a36Sopenharmony_ci		.dst_feature = 0,
86562306a36Sopenharmony_ci		.tuner_type = 0
86662306a36Sopenharmony_ci	},
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	{
86962306a36Sopenharmony_ci		.device_id = "ATSCAD",
87062306a36Sopenharmony_ci		.offset = 1,
87162306a36Sopenharmony_ci		.dst_type = DST_TYPE_IS_ATSC,
87262306a36Sopenharmony_ci		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
87362306a36Sopenharmony_ci		.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
87462306a36Sopenharmony_ci		.tuner_type = 0
87562306a36Sopenharmony_ci	},
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	{ }
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci};
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_cistatic int dst_get_mac(struct dst_state *state)
88262306a36Sopenharmony_ci{
88362306a36Sopenharmony_ci	u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
88462306a36Sopenharmony_ci	get_mac[7] = dst_check_sum(get_mac, 7);
88562306a36Sopenharmony_ci	if (dst_command(state, get_mac, 8) < 0) {
88662306a36Sopenharmony_ci		dprintk(2, "Unsupported Command\n");
88762306a36Sopenharmony_ci		return -1;
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci	memset(&state->mac_address, '\0', 8);
89062306a36Sopenharmony_ci	memcpy(&state->mac_address, &state->rxbuffer, 6);
89162306a36Sopenharmony_ci	pr_err("MAC Address=[%pM]\n", state->mac_address);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	return 0;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic int dst_fw_ver(struct dst_state *state)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
89962306a36Sopenharmony_ci	get_ver[7] = dst_check_sum(get_ver, 7);
90062306a36Sopenharmony_ci	if (dst_command(state, get_ver, 8) < 0) {
90162306a36Sopenharmony_ci		dprintk(2, "Unsupported Command\n");
90262306a36Sopenharmony_ci		return -1;
90362306a36Sopenharmony_ci	}
90462306a36Sopenharmony_ci	memcpy(&state->fw_version, &state->rxbuffer, 8);
90562306a36Sopenharmony_ci	pr_err("Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x\n",
90662306a36Sopenharmony_ci		state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
90762306a36Sopenharmony_ci		state->fw_version[1],
90862306a36Sopenharmony_ci		state->fw_version[5], state->fw_version[6],
90962306a36Sopenharmony_ci		state->fw_version[4], state->fw_version[3], state->fw_version[2]);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	return 0;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic int dst_card_type(struct dst_state *state)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	int j;
91762306a36Sopenharmony_ci	struct tuner_types *p_tuner_list = NULL;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
92062306a36Sopenharmony_ci	get_type[7] = dst_check_sum(get_type, 7);
92162306a36Sopenharmony_ci	if (dst_command(state, get_type, 8) < 0) {
92262306a36Sopenharmony_ci		dprintk(2, "Unsupported Command\n");
92362306a36Sopenharmony_ci		return -1;
92462306a36Sopenharmony_ci	}
92562306a36Sopenharmony_ci	memset(&state->card_info, '\0', 8);
92662306a36Sopenharmony_ci	memcpy(&state->card_info, &state->rxbuffer, 7);
92762306a36Sopenharmony_ci	pr_err("Device Model=[%s]\n", &state->card_info[0]);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
93062306a36Sopenharmony_ci		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
93162306a36Sopenharmony_ci			state->tuner_type = p_tuner_list->tuner_type;
93262306a36Sopenharmony_ci			pr_err("DST has [%s] tuner, tuner type=[%d]\n",
93362306a36Sopenharmony_ci				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
93462306a36Sopenharmony_ci		}
93562306a36Sopenharmony_ci	}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	return 0;
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic int dst_get_vendor(struct dst_state *state)
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
94362306a36Sopenharmony_ci	get_vendor[7] = dst_check_sum(get_vendor, 7);
94462306a36Sopenharmony_ci	if (dst_command(state, get_vendor, 8) < 0) {
94562306a36Sopenharmony_ci		dprintk(2, "Unsupported Command\n");
94662306a36Sopenharmony_ci		return -1;
94762306a36Sopenharmony_ci	}
94862306a36Sopenharmony_ci	memset(&state->vendor, '\0', 8);
94962306a36Sopenharmony_ci	memcpy(&state->vendor, &state->rxbuffer, 7);
95062306a36Sopenharmony_ci	pr_err("Vendor=[%s]\n", &state->vendor[0]);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	return 0;
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic void debug_dst_buffer(struct dst_state *state)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	dprintk(3, "%s: [ %*ph ]\n", __func__, 8, state->rxbuffer);
95862306a36Sopenharmony_ci}
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_cistatic int dst_check_stv0299(struct dst_state *state)
96162306a36Sopenharmony_ci{
96262306a36Sopenharmony_ci	u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
96562306a36Sopenharmony_ci	if (dst_command(state, check_stv0299, 8) < 0) {
96662306a36Sopenharmony_ci		pr_err("Cmd=[0x04] failed\n");
96762306a36Sopenharmony_ci		return -1;
96862306a36Sopenharmony_ci	}
96962306a36Sopenharmony_ci	debug_dst_buffer(state);
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
97262306a36Sopenharmony_ci		pr_err("Found a STV0299 NIM\n");
97362306a36Sopenharmony_ci		state->tuner_type = TUNER_TYPE_STV0299;
97462306a36Sopenharmony_ci		return 0;
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	return -1;
97862306a36Sopenharmony_ci}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic int dst_check_mb86a15(struct dst_state *state)
98162306a36Sopenharmony_ci{
98262306a36Sopenharmony_ci	u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
98562306a36Sopenharmony_ci	if (dst_command(state, check_mb86a15, 8) < 0) {
98662306a36Sopenharmony_ci		pr_err("Cmd=[0x10], failed\n");
98762306a36Sopenharmony_ci		return -1;
98862306a36Sopenharmony_ci	}
98962306a36Sopenharmony_ci	debug_dst_buffer(state);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
99262306a36Sopenharmony_ci		pr_err("Found a MB86A15 NIM\n");
99362306a36Sopenharmony_ci		state->tuner_type = TUNER_TYPE_MB86A15;
99462306a36Sopenharmony_ci		return 0;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	return -1;
99862306a36Sopenharmony_ci}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_cistatic int dst_get_tuner_info(struct dst_state *state)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
100362306a36Sopenharmony_ci	u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
100662306a36Sopenharmony_ci	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
100762306a36Sopenharmony_ci	pr_err("DST TYpe = MULTI FE\n");
100862306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
100962306a36Sopenharmony_ci		if (dst_command(state, get_tuner_1, 8) < 0) {
101062306a36Sopenharmony_ci			dprintk(2, "Cmd=[0x13], Unsupported\n");
101162306a36Sopenharmony_ci			goto force;
101262306a36Sopenharmony_ci		}
101362306a36Sopenharmony_ci	} else {
101462306a36Sopenharmony_ci		if (dst_command(state, get_tuner_2, 8) < 0) {
101562306a36Sopenharmony_ci			dprintk(2, "Cmd=[0xb], Unsupported\n");
101662306a36Sopenharmony_ci			goto force;
101762306a36Sopenharmony_ci		}
101862306a36Sopenharmony_ci	}
101962306a36Sopenharmony_ci	memcpy(&state->board_info, &state->rxbuffer, 8);
102062306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
102162306a36Sopenharmony_ci		pr_err("DST type has TS=188\n");
102262306a36Sopenharmony_ci	}
102362306a36Sopenharmony_ci	if (state->board_info[0] == 0xbc) {
102462306a36Sopenharmony_ci		if (state->dst_type != DST_TYPE_IS_ATSC)
102562306a36Sopenharmony_ci			state->type_flags |= DST_TYPE_HAS_TS188;
102662306a36Sopenharmony_ci		else
102762306a36Sopenharmony_ci			state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci		if (state->board_info[1] == 0x01) {
103062306a36Sopenharmony_ci			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
103162306a36Sopenharmony_ci			pr_err("DST has Daughterboard\n");
103262306a36Sopenharmony_ci		}
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	return 0;
103662306a36Sopenharmony_ciforce:
103762306a36Sopenharmony_ci	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
103862306a36Sopenharmony_ci		state->type_flags |= DST_TYPE_HAS_TS204;
103962306a36Sopenharmony_ci		pr_err("Forcing [%s] to TS188\n", state->fw_name);
104062306a36Sopenharmony_ci	}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	return -1;
104362306a36Sopenharmony_ci}
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_cistatic int dst_get_device_id(struct dst_state *state)
104662306a36Sopenharmony_ci{
104762306a36Sopenharmony_ci	u8 reply;
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	int i, j;
105062306a36Sopenharmony_ci	struct dst_types *p_dst_type = NULL;
105162306a36Sopenharmony_ci	struct tuner_types *p_tuner_list = NULL;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	u8 use_dst_type = 0;
105462306a36Sopenharmony_ci	u32 use_type_flags = 0;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	state->tuner_type = 0;
105962306a36Sopenharmony_ci	device_type[7] = dst_check_sum(device_type, 7);
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	if (write_dst(state, device_type, FIXED_COMM))
106262306a36Sopenharmony_ci		return -1;		/*	Write failed		*/
106362306a36Sopenharmony_ci	if ((dst_pio_disable(state)) < 0)
106462306a36Sopenharmony_ci		return -1;
106562306a36Sopenharmony_ci	if (read_dst(state, &reply, GET_ACK))
106662306a36Sopenharmony_ci		return -1;		/*	Read failure		*/
106762306a36Sopenharmony_ci	if (reply != ACK) {
106862306a36Sopenharmony_ci		dprintk(2, "Write not Acknowledged! [Reply=0x%02x]\n", reply);
106962306a36Sopenharmony_ci		return -1;		/*	Unack'd write		*/
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci	if (!dst_wait_dst_ready(state, DEVICE_INIT))
107262306a36Sopenharmony_ci		return -1;		/*	DST not ready yet	*/
107362306a36Sopenharmony_ci	if (read_dst(state, state->rxbuffer, FIXED_COMM))
107462306a36Sopenharmony_ci		return -1;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	dst_pio_disable(state);
107762306a36Sopenharmony_ci	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
107862306a36Sopenharmony_ci		dprintk(2, "Checksum failure!\n");
107962306a36Sopenharmony_ci		return -1;		/*	Checksum failure	*/
108062306a36Sopenharmony_ci	}
108162306a36Sopenharmony_ci	state->rxbuffer[7] = '\0';
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
108462306a36Sopenharmony_ci		if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
108562306a36Sopenharmony_ci			use_type_flags = p_dst_type->type_flags;
108662306a36Sopenharmony_ci			use_dst_type = p_dst_type->dst_type;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci			/*	Card capabilities	*/
108962306a36Sopenharmony_ci			state->dst_hw_cap = p_dst_type->dst_feature;
109062306a36Sopenharmony_ci			pr_err("Recognise [%s]\n", p_dst_type->device_id);
109162306a36Sopenharmony_ci			strscpy(state->fw_name, p_dst_type->device_id,
109262306a36Sopenharmony_ci			        sizeof(state->fw_name));
109362306a36Sopenharmony_ci			/*	Multiple tuners		*/
109462306a36Sopenharmony_ci			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
109562306a36Sopenharmony_ci				switch (use_dst_type) {
109662306a36Sopenharmony_ci				case DST_TYPE_IS_SAT:
109762306a36Sopenharmony_ci					/*	STV0299 check	*/
109862306a36Sopenharmony_ci					if (dst_check_stv0299(state) < 0) {
109962306a36Sopenharmony_ci						pr_err("Unsupported\n");
110062306a36Sopenharmony_ci						state->tuner_type = TUNER_TYPE_MB86A15;
110162306a36Sopenharmony_ci					}
110262306a36Sopenharmony_ci					break;
110362306a36Sopenharmony_ci				default:
110462306a36Sopenharmony_ci					break;
110562306a36Sopenharmony_ci				}
110662306a36Sopenharmony_ci				if (dst_check_mb86a15(state) < 0)
110762306a36Sopenharmony_ci					pr_err("Unsupported\n");
110862306a36Sopenharmony_ci			/*	Single tuner		*/
110962306a36Sopenharmony_ci			} else {
111062306a36Sopenharmony_ci				state->tuner_type = p_dst_type->tuner_type;
111162306a36Sopenharmony_ci			}
111262306a36Sopenharmony_ci			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
111362306a36Sopenharmony_ci				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
111462306a36Sopenharmony_ci					p_tuner_list->tuner_type == state->tuner_type) {
111562306a36Sopenharmony_ci					pr_err("[%s] has a [%s]\n",
111662306a36Sopenharmony_ci						p_dst_type->device_id, p_tuner_list->tuner_name);
111762306a36Sopenharmony_ci				}
111862306a36Sopenharmony_ci			}
111962306a36Sopenharmony_ci			break;
112062306a36Sopenharmony_ci		}
112162306a36Sopenharmony_ci	}
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	if (i >= ARRAY_SIZE(dst_tlist)) {
112462306a36Sopenharmony_ci		pr_err("Unable to recognize %s or %s\n", &state->rxbuffer[0], &state->rxbuffer[1]);
112562306a36Sopenharmony_ci		pr_err("please email linux-dvb@linuxtv.org with this type in");
112662306a36Sopenharmony_ci		use_dst_type = DST_TYPE_IS_SAT;
112762306a36Sopenharmony_ci		use_type_flags = DST_TYPE_HAS_SYMDIV;
112862306a36Sopenharmony_ci	}
112962306a36Sopenharmony_ci	dst_type_print(state, use_dst_type);
113062306a36Sopenharmony_ci	state->type_flags = use_type_flags;
113162306a36Sopenharmony_ci	state->dst_type = use_dst_type;
113262306a36Sopenharmony_ci	dst_type_flags_print(state);
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	return 0;
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_cistatic int dst_probe(struct dst_state *state)
113862306a36Sopenharmony_ci{
113962306a36Sopenharmony_ci	mutex_init(&state->dst_mutex);
114062306a36Sopenharmony_ci	if (dst_addons & DST_TYPE_HAS_CA) {
114162306a36Sopenharmony_ci		if ((rdc_8820_reset(state)) < 0) {
114262306a36Sopenharmony_ci			pr_err("RDC 8820 RESET Failed.\n");
114362306a36Sopenharmony_ci			return -1;
114462306a36Sopenharmony_ci		}
114562306a36Sopenharmony_ci		msleep(4000);
114662306a36Sopenharmony_ci	} else {
114762306a36Sopenharmony_ci		msleep(100);
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci	if ((dst_comm_init(state)) < 0) {
115062306a36Sopenharmony_ci		pr_err("DST Initialization Failed.\n");
115162306a36Sopenharmony_ci		return -1;
115262306a36Sopenharmony_ci	}
115362306a36Sopenharmony_ci	msleep(100);
115462306a36Sopenharmony_ci	if (dst_get_device_id(state) < 0) {
115562306a36Sopenharmony_ci		pr_err("unknown device.\n");
115662306a36Sopenharmony_ci		return -1;
115762306a36Sopenharmony_ci	}
115862306a36Sopenharmony_ci	if (dst_get_mac(state) < 0) {
115962306a36Sopenharmony_ci		dprintk(2, "MAC: Unsupported command\n");
116062306a36Sopenharmony_ci	}
116162306a36Sopenharmony_ci	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
116262306a36Sopenharmony_ci		if (dst_get_tuner_info(state) < 0)
116362306a36Sopenharmony_ci			dprintk(2, "Tuner: Unsupported command\n");
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_TS204) {
116662306a36Sopenharmony_ci		dst_packsize(state, 204);
116762306a36Sopenharmony_ci	}
116862306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
116962306a36Sopenharmony_ci		if (dst_fw_ver(state) < 0) {
117062306a36Sopenharmony_ci			dprintk(2, "FW: Unsupported command\n");
117162306a36Sopenharmony_ci			return 0;
117262306a36Sopenharmony_ci		}
117362306a36Sopenharmony_ci		if (dst_card_type(state) < 0) {
117462306a36Sopenharmony_ci			dprintk(2, "Card: Unsupported command\n");
117562306a36Sopenharmony_ci			return 0;
117662306a36Sopenharmony_ci		}
117762306a36Sopenharmony_ci		if (dst_get_vendor(state) < 0) {
117862306a36Sopenharmony_ci			dprintk(2, "Vendor: Unsupported command\n");
117962306a36Sopenharmony_ci			return 0;
118062306a36Sopenharmony_ci		}
118162306a36Sopenharmony_ci	}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	return 0;
118462306a36Sopenharmony_ci}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_cistatic int dst_command(struct dst_state *state, u8 *data, u8 len)
118762306a36Sopenharmony_ci{
118862306a36Sopenharmony_ci	u8 reply;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	mutex_lock(&state->dst_mutex);
119162306a36Sopenharmony_ci	if ((dst_comm_init(state)) < 0) {
119262306a36Sopenharmony_ci		dprintk(1, "DST Communication Initialization Failed.\n");
119362306a36Sopenharmony_ci		goto error;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci	if (write_dst(state, data, len)) {
119662306a36Sopenharmony_ci		dprintk(2, "Trying to recover..\n");
119762306a36Sopenharmony_ci		if ((dst_error_recovery(state)) < 0) {
119862306a36Sopenharmony_ci			pr_err("Recovery Failed.\n");
119962306a36Sopenharmony_ci			goto error;
120062306a36Sopenharmony_ci		}
120162306a36Sopenharmony_ci		goto error;
120262306a36Sopenharmony_ci	}
120362306a36Sopenharmony_ci	if ((dst_pio_disable(state)) < 0) {
120462306a36Sopenharmony_ci		pr_err("PIO Disable Failed.\n");
120562306a36Sopenharmony_ci		goto error;
120662306a36Sopenharmony_ci	}
120762306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_FW_1)
120862306a36Sopenharmony_ci		mdelay(3);
120962306a36Sopenharmony_ci	if (read_dst(state, &reply, GET_ACK)) {
121062306a36Sopenharmony_ci		dprintk(3, "Trying to recover..\n");
121162306a36Sopenharmony_ci		if ((dst_error_recovery(state)) < 0) {
121262306a36Sopenharmony_ci			dprintk(2, "Recovery Failed.\n");
121362306a36Sopenharmony_ci			goto error;
121462306a36Sopenharmony_ci		}
121562306a36Sopenharmony_ci		goto error;
121662306a36Sopenharmony_ci	}
121762306a36Sopenharmony_ci	if (reply != ACK) {
121862306a36Sopenharmony_ci		dprintk(2, "write not acknowledged 0x%02x\n", reply);
121962306a36Sopenharmony_ci		goto error;
122062306a36Sopenharmony_ci	}
122162306a36Sopenharmony_ci	if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
122262306a36Sopenharmony_ci		goto error;
122362306a36Sopenharmony_ci	if (state->type_flags & DST_TYPE_HAS_FW_1)
122462306a36Sopenharmony_ci		mdelay(3);
122562306a36Sopenharmony_ci	else
122662306a36Sopenharmony_ci		udelay(2000);
122762306a36Sopenharmony_ci	if (!dst_wait_dst_ready(state, NO_DELAY))
122862306a36Sopenharmony_ci		goto error;
122962306a36Sopenharmony_ci	if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
123062306a36Sopenharmony_ci		dprintk(3, "Trying to recover..\n");
123162306a36Sopenharmony_ci		if ((dst_error_recovery(state)) < 0) {
123262306a36Sopenharmony_ci			dprintk(2, "Recovery failed.\n");
123362306a36Sopenharmony_ci			goto error;
123462306a36Sopenharmony_ci		}
123562306a36Sopenharmony_ci		goto error;
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
123862306a36Sopenharmony_ci		dprintk(2, "checksum failure\n");
123962306a36Sopenharmony_ci		goto error;
124062306a36Sopenharmony_ci	}
124162306a36Sopenharmony_ci	mutex_unlock(&state->dst_mutex);
124262306a36Sopenharmony_ci	return 0;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cierror:
124562306a36Sopenharmony_ci	mutex_unlock(&state->dst_mutex);
124662306a36Sopenharmony_ci	return -EIO;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_cistatic int dst_get_signal(struct dst_state *state)
125162306a36Sopenharmony_ci{
125262306a36Sopenharmony_ci	int retval;
125362306a36Sopenharmony_ci	u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
125462306a36Sopenharmony_ci	//dprintk("%s: Getting Signal strength and other parameters\n", __func__);
125562306a36Sopenharmony_ci	if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
125662306a36Sopenharmony_ci		state->decode_lock = state->decode_strength = state->decode_snr = 0;
125762306a36Sopenharmony_ci		return 0;
125862306a36Sopenharmony_ci	}
125962306a36Sopenharmony_ci	if (0 == (state->diseq_flags & HAS_LOCK)) {
126062306a36Sopenharmony_ci		state->decode_lock = state->decode_strength = state->decode_snr = 0;
126162306a36Sopenharmony_ci		return 0;
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci	if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
126462306a36Sopenharmony_ci		retval = dst_command(state, get_signal, 8);
126562306a36Sopenharmony_ci		if (retval < 0)
126662306a36Sopenharmony_ci			return retval;
126762306a36Sopenharmony_ci		if (state->dst_type == DST_TYPE_IS_SAT) {
126862306a36Sopenharmony_ci			state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
126962306a36Sopenharmony_ci			state->decode_strength = state->rxbuffer[5] << 8;
127062306a36Sopenharmony_ci			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
127162306a36Sopenharmony_ci		} else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
127262306a36Sopenharmony_ci			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
127362306a36Sopenharmony_ci			state->decode_strength = state->rxbuffer[4] << 8;
127462306a36Sopenharmony_ci			state->decode_snr = state->rxbuffer[3] << 8;
127562306a36Sopenharmony_ci		} else if (state->dst_type == DST_TYPE_IS_ATSC) {
127662306a36Sopenharmony_ci			state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
127762306a36Sopenharmony_ci			state->decode_strength = state->rxbuffer[4] << 8;
127862306a36Sopenharmony_ci			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
127962306a36Sopenharmony_ci		}
128062306a36Sopenharmony_ci		state->cur_jiff = jiffies;
128162306a36Sopenharmony_ci	}
128262306a36Sopenharmony_ci	return 0;
128362306a36Sopenharmony_ci}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_cistatic int dst_tone_power_cmd(struct dst_state *state)
128662306a36Sopenharmony_ci{
128762306a36Sopenharmony_ci	u8 packet[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_SAT)
129062306a36Sopenharmony_ci		return -EOPNOTSUPP;
129162306a36Sopenharmony_ci	packet[4] = state->tx_tuna[4];
129262306a36Sopenharmony_ci	packet[2] = state->tx_tuna[2];
129362306a36Sopenharmony_ci	packet[3] = state->tx_tuna[3];
129462306a36Sopenharmony_ci	packet[7] = dst_check_sum (packet, 7);
129562306a36Sopenharmony_ci	return dst_command(state, packet, 8);
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cistatic int dst_get_tuna(struct dst_state *state)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	int retval;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
130362306a36Sopenharmony_ci		return 0;
130462306a36Sopenharmony_ci	state->diseq_flags &= ~(HAS_LOCK);
130562306a36Sopenharmony_ci	if (!dst_wait_dst_ready(state, NO_DELAY))
130662306a36Sopenharmony_ci		return -EIO;
130762306a36Sopenharmony_ci	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
130862306a36Sopenharmony_ci		!(state->dst_type == DST_TYPE_IS_ATSC))
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci		retval = read_dst(state, state->rx_tuna, 10);
131162306a36Sopenharmony_ci	else
131262306a36Sopenharmony_ci		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
131362306a36Sopenharmony_ci	if (retval < 0) {
131462306a36Sopenharmony_ci		dprintk(3, "read not successful\n");
131562306a36Sopenharmony_ci		return retval;
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
131862306a36Sopenharmony_ci	   !(state->dst_type == DST_TYPE_IS_ATSC)) {
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
132162306a36Sopenharmony_ci			dprintk(2, "checksum failure ?\n");
132262306a36Sopenharmony_ci			return -EIO;
132362306a36Sopenharmony_ci		}
132462306a36Sopenharmony_ci	} else {
132562306a36Sopenharmony_ci		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
132662306a36Sopenharmony_ci			dprintk(2, "checksum failure?\n");
132762306a36Sopenharmony_ci			return -EIO;
132862306a36Sopenharmony_ci		}
132962306a36Sopenharmony_ci	}
133062306a36Sopenharmony_ci	if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
133162306a36Sopenharmony_ci		return 0;
133262306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT) {
133362306a36Sopenharmony_ci		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
133462306a36Sopenharmony_ci	} else {
133562306a36Sopenharmony_ci		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
133662306a36Sopenharmony_ci	}
133762306a36Sopenharmony_ci	state->decode_freq = state->decode_freq * 1000;
133862306a36Sopenharmony_ci	state->decode_lock = 1;
133962306a36Sopenharmony_ci	state->diseq_flags |= HAS_LOCK;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	return 1;
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic int dst_set_voltage(struct dvb_frontend *fe,
134562306a36Sopenharmony_ci			   enum fe_sec_voltage voltage);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_cistatic int dst_write_tuna(struct dvb_frontend *fe)
134862306a36Sopenharmony_ci{
134962306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
135062306a36Sopenharmony_ci	int retval;
135162306a36Sopenharmony_ci	u8 reply;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	dprintk(2, "type_flags 0x%x\n", state->type_flags);
135462306a36Sopenharmony_ci	state->decode_freq = 0;
135562306a36Sopenharmony_ci	state->decode_lock = state->decode_strength = state->decode_snr = 0;
135662306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT) {
135762306a36Sopenharmony_ci		if (!(state->diseq_flags & HAS_POWER))
135862306a36Sopenharmony_ci			dst_set_voltage(fe, SEC_VOLTAGE_13);
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci	state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
136162306a36Sopenharmony_ci	mutex_lock(&state->dst_mutex);
136262306a36Sopenharmony_ci	if ((dst_comm_init(state)) < 0) {
136362306a36Sopenharmony_ci		dprintk(3, "DST Communication initialization failed.\n");
136462306a36Sopenharmony_ci		goto error;
136562306a36Sopenharmony_ci	}
136662306a36Sopenharmony_ci//	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
136762306a36Sopenharmony_ci	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
136862306a36Sopenharmony_ci		(!(state->dst_type == DST_TYPE_IS_ATSC))) {
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
137162306a36Sopenharmony_ci		retval = write_dst(state, &state->tx_tuna[0], 10);
137262306a36Sopenharmony_ci	} else {
137362306a36Sopenharmony_ci		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
137462306a36Sopenharmony_ci		retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
137562306a36Sopenharmony_ci	}
137662306a36Sopenharmony_ci	if (retval < 0) {
137762306a36Sopenharmony_ci		dst_pio_disable(state);
137862306a36Sopenharmony_ci		dprintk(3, "write not successful\n");
137962306a36Sopenharmony_ci		goto werr;
138062306a36Sopenharmony_ci	}
138162306a36Sopenharmony_ci	if ((dst_pio_disable(state)) < 0) {
138262306a36Sopenharmony_ci		dprintk(3, "DST PIO disable failed !\n");
138362306a36Sopenharmony_ci		goto error;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci	if ((read_dst(state, &reply, GET_ACK) < 0)) {
138662306a36Sopenharmony_ci		dprintk(3, "read verify not successful.\n");
138762306a36Sopenharmony_ci		goto error;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci	if (reply != ACK) {
139062306a36Sopenharmony_ci		dprintk(3, "write not acknowledged 0x%02x\n", reply);
139162306a36Sopenharmony_ci		goto error;
139262306a36Sopenharmony_ci	}
139362306a36Sopenharmony_ci	state->diseq_flags |= ATTEMPT_TUNE;
139462306a36Sopenharmony_ci	retval = dst_get_tuna(state);
139562306a36Sopenharmony_ciwerr:
139662306a36Sopenharmony_ci	mutex_unlock(&state->dst_mutex);
139762306a36Sopenharmony_ci	return retval;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_cierror:
140062306a36Sopenharmony_ci	mutex_unlock(&state->dst_mutex);
140162306a36Sopenharmony_ci	return -EIO;
140262306a36Sopenharmony_ci}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci/*
140562306a36Sopenharmony_ci * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
140662306a36Sopenharmony_ci * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
140762306a36Sopenharmony_ci * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
140862306a36Sopenharmony_ci * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
140962306a36Sopenharmony_ci * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
141062306a36Sopenharmony_ci * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
141162306a36Sopenharmony_ci * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
141262306a36Sopenharmony_ci * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
141362306a36Sopenharmony_ci * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
141462306a36Sopenharmony_ci * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
141562306a36Sopenharmony_ci * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
141662306a36Sopenharmony_ci */
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_cistatic int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
142162306a36Sopenharmony_ci	u8 packet[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_SAT)
142462306a36Sopenharmony_ci		return -EOPNOTSUPP;
142562306a36Sopenharmony_ci	if (cmd->msg_len > 0 && cmd->msg_len < 5)
142662306a36Sopenharmony_ci		memcpy(&packet[3], cmd->msg, cmd->msg_len);
142762306a36Sopenharmony_ci	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
142862306a36Sopenharmony_ci		memcpy(&packet[2], cmd->msg, cmd->msg_len);
142962306a36Sopenharmony_ci	else
143062306a36Sopenharmony_ci		return -EINVAL;
143162306a36Sopenharmony_ci	packet[7] = dst_check_sum(&packet[0], 7);
143262306a36Sopenharmony_ci	return dst_command(state, packet, 8);
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic int dst_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	int need_cmd, retval = 0;
143862306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	state->voltage = voltage;
144162306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_SAT)
144262306a36Sopenharmony_ci		return -EOPNOTSUPP;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	need_cmd = 0;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	switch (voltage) {
144762306a36Sopenharmony_ci	case SEC_VOLTAGE_13:
144862306a36Sopenharmony_ci	case SEC_VOLTAGE_18:
144962306a36Sopenharmony_ci		if ((state->diseq_flags & HAS_POWER) == 0)
145062306a36Sopenharmony_ci			need_cmd = 1;
145162306a36Sopenharmony_ci		state->diseq_flags |= HAS_POWER;
145262306a36Sopenharmony_ci		state->tx_tuna[4] = 0x01;
145362306a36Sopenharmony_ci		break;
145462306a36Sopenharmony_ci	case SEC_VOLTAGE_OFF:
145562306a36Sopenharmony_ci		need_cmd = 1;
145662306a36Sopenharmony_ci		state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
145762306a36Sopenharmony_ci		state->tx_tuna[4] = 0x00;
145862306a36Sopenharmony_ci		break;
145962306a36Sopenharmony_ci	default:
146062306a36Sopenharmony_ci		return -EINVAL;
146162306a36Sopenharmony_ci	}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	if (need_cmd)
146462306a36Sopenharmony_ci		retval = dst_tone_power_cmd(state);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	return retval;
146762306a36Sopenharmony_ci}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_cistatic int dst_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
147062306a36Sopenharmony_ci{
147162306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	state->tone = tone;
147462306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_SAT)
147562306a36Sopenharmony_ci		return -EOPNOTSUPP;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	switch (tone) {
147862306a36Sopenharmony_ci	case SEC_TONE_OFF:
147962306a36Sopenharmony_ci		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
148062306a36Sopenharmony_ci		    state->tx_tuna[2] = 0x00;
148162306a36Sopenharmony_ci		else
148262306a36Sopenharmony_ci		    state->tx_tuna[2] = 0xff;
148362306a36Sopenharmony_ci		break;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	case SEC_TONE_ON:
148662306a36Sopenharmony_ci		state->tx_tuna[2] = 0x02;
148762306a36Sopenharmony_ci		break;
148862306a36Sopenharmony_ci	default:
148962306a36Sopenharmony_ci		return -EINVAL;
149062306a36Sopenharmony_ci	}
149162306a36Sopenharmony_ci	return dst_tone_power_cmd(state);
149262306a36Sopenharmony_ci}
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_cistatic int dst_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd)
149562306a36Sopenharmony_ci{
149662306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	if (state->dst_type != DST_TYPE_IS_SAT)
149962306a36Sopenharmony_ci		return -EOPNOTSUPP;
150062306a36Sopenharmony_ci	state->minicmd = minicmd;
150162306a36Sopenharmony_ci	switch (minicmd) {
150262306a36Sopenharmony_ci	case SEC_MINI_A:
150362306a36Sopenharmony_ci		state->tx_tuna[3] = 0x02;
150462306a36Sopenharmony_ci		break;
150562306a36Sopenharmony_ci	case SEC_MINI_B:
150662306a36Sopenharmony_ci		state->tx_tuna[3] = 0xff;
150762306a36Sopenharmony_ci		break;
150862306a36Sopenharmony_ci	}
150962306a36Sopenharmony_ci	return dst_tone_power_cmd(state);
151062306a36Sopenharmony_ci}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_cistatic int bt8xx_dst_init(struct dvb_frontend *fe)
151462306a36Sopenharmony_ci{
151562306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
151862306a36Sopenharmony_ci	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
151962306a36Sopenharmony_ci	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
152062306a36Sopenharmony_ci	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
152162306a36Sopenharmony_ci	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
152262306a36Sopenharmony_ci	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
152362306a36Sopenharmony_ci	static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	state->inversion = INVERSION_OFF;
152662306a36Sopenharmony_ci	state->voltage = SEC_VOLTAGE_13;
152762306a36Sopenharmony_ci	state->tone = SEC_TONE_OFF;
152862306a36Sopenharmony_ci	state->diseq_flags = 0;
152962306a36Sopenharmony_ci	state->k22 = 0x02;
153062306a36Sopenharmony_ci	state->bandwidth = 7000000;
153162306a36Sopenharmony_ci	state->cur_jiff = jiffies;
153262306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT)
153362306a36Sopenharmony_ci		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
153462306a36Sopenharmony_ci	else if (state->dst_type == DST_TYPE_IS_TERR)
153562306a36Sopenharmony_ci		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
153662306a36Sopenharmony_ci	else if (state->dst_type == DST_TYPE_IS_CABLE)
153762306a36Sopenharmony_ci		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
153862306a36Sopenharmony_ci	else if (state->dst_type == DST_TYPE_IS_ATSC)
153962306a36Sopenharmony_ci		memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	return 0;
154262306a36Sopenharmony_ci}
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_cistatic int dst_read_status(struct dvb_frontend *fe, enum fe_status *status)
154562306a36Sopenharmony_ci{
154662306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	*status = 0;
154962306a36Sopenharmony_ci	if (state->diseq_flags & HAS_LOCK) {
155062306a36Sopenharmony_ci//		dst_get_signal(state);	// don't require(?) to ask MCU
155162306a36Sopenharmony_ci		if (state->decode_lock)
155262306a36Sopenharmony_ci			*status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
155362306a36Sopenharmony_ci	}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	return 0;
155662306a36Sopenharmony_ci}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_cistatic int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
155962306a36Sopenharmony_ci{
156062306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	int retval = dst_get_signal(state);
156362306a36Sopenharmony_ci	*strength = state->decode_strength;
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	return retval;
156662306a36Sopenharmony_ci}
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_cistatic int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
156962306a36Sopenharmony_ci{
157062306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	int retval = dst_get_signal(state);
157362306a36Sopenharmony_ci	*snr = state->decode_snr;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	return retval;
157662306a36Sopenharmony_ci}
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_cistatic int dst_set_frontend(struct dvb_frontend *fe)
157962306a36Sopenharmony_ci{
158062306a36Sopenharmony_ci	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
158162306a36Sopenharmony_ci	int retval = -EINVAL;
158262306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	if (p != NULL) {
158562306a36Sopenharmony_ci		retval = dst_set_freq(state, p->frequency);
158662306a36Sopenharmony_ci		if(retval != 0)
158762306a36Sopenharmony_ci			return retval;
158862306a36Sopenharmony_ci		dprintk(3, "Set Frequency=[%d]\n", p->frequency);
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci		if (state->dst_type == DST_TYPE_IS_SAT) {
159162306a36Sopenharmony_ci			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
159262306a36Sopenharmony_ci				dst_set_inversion(state, p->inversion);
159362306a36Sopenharmony_ci			dst_set_fec(state, p->fec_inner);
159462306a36Sopenharmony_ci			dst_set_symbolrate(state, p->symbol_rate);
159562306a36Sopenharmony_ci			dst_set_polarization(state);
159662306a36Sopenharmony_ci			dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci		} else if (state->dst_type == DST_TYPE_IS_TERR)
159962306a36Sopenharmony_ci			dst_set_bandwidth(state, p->bandwidth_hz);
160062306a36Sopenharmony_ci		else if (state->dst_type == DST_TYPE_IS_CABLE) {
160162306a36Sopenharmony_ci			dst_set_fec(state, p->fec_inner);
160262306a36Sopenharmony_ci			dst_set_symbolrate(state, p->symbol_rate);
160362306a36Sopenharmony_ci			dst_set_modulation(state, p->modulation);
160462306a36Sopenharmony_ci		}
160562306a36Sopenharmony_ci		retval = dst_write_tuna(fe);
160662306a36Sopenharmony_ci	}
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	return retval;
160962306a36Sopenharmony_ci}
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_cistatic int dst_tune_frontend(struct dvb_frontend* fe,
161262306a36Sopenharmony_ci			    bool re_tune,
161362306a36Sopenharmony_ci			    unsigned int mode_flags,
161462306a36Sopenharmony_ci			    unsigned int *delay,
161562306a36Sopenharmony_ci			    enum fe_status *status)
161662306a36Sopenharmony_ci{
161762306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
161862306a36Sopenharmony_ci	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	if (re_tune) {
162162306a36Sopenharmony_ci		dst_set_freq(state, p->frequency);
162262306a36Sopenharmony_ci		dprintk(3, "Set Frequency=[%d]\n", p->frequency);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci		if (state->dst_type == DST_TYPE_IS_SAT) {
162562306a36Sopenharmony_ci			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
162662306a36Sopenharmony_ci				dst_set_inversion(state, p->inversion);
162762306a36Sopenharmony_ci			dst_set_fec(state, p->fec_inner);
162862306a36Sopenharmony_ci			dst_set_symbolrate(state, p->symbol_rate);
162962306a36Sopenharmony_ci			dst_set_polarization(state);
163062306a36Sopenharmony_ci			dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate);
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci		} else if (state->dst_type == DST_TYPE_IS_TERR)
163362306a36Sopenharmony_ci			dst_set_bandwidth(state, p->bandwidth_hz);
163462306a36Sopenharmony_ci		else if (state->dst_type == DST_TYPE_IS_CABLE) {
163562306a36Sopenharmony_ci			dst_set_fec(state, p->fec_inner);
163662306a36Sopenharmony_ci			dst_set_symbolrate(state, p->symbol_rate);
163762306a36Sopenharmony_ci			dst_set_modulation(state, p->modulation);
163862306a36Sopenharmony_ci		}
163962306a36Sopenharmony_ci		dst_write_tuna(fe);
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
164362306a36Sopenharmony_ci		dst_read_status(fe, status);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	*delay = HZ/10;
164662306a36Sopenharmony_ci	return 0;
164762306a36Sopenharmony_ci}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_cistatic enum dvbfe_algo dst_get_tuning_algo(struct dvb_frontend *fe)
165062306a36Sopenharmony_ci{
165162306a36Sopenharmony_ci	return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
165262306a36Sopenharmony_ci}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_cistatic int dst_get_frontend(struct dvb_frontend *fe,
165562306a36Sopenharmony_ci			    struct dtv_frontend_properties *p)
165662306a36Sopenharmony_ci{
165762306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	p->frequency = state->decode_freq;
166062306a36Sopenharmony_ci	if (state->dst_type == DST_TYPE_IS_SAT) {
166162306a36Sopenharmony_ci		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
166262306a36Sopenharmony_ci			p->inversion = state->inversion;
166362306a36Sopenharmony_ci		p->symbol_rate = state->symbol_rate;
166462306a36Sopenharmony_ci		p->fec_inner = dst_get_fec(state);
166562306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_TERR) {
166662306a36Sopenharmony_ci		p->bandwidth_hz = state->bandwidth;
166762306a36Sopenharmony_ci	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
166862306a36Sopenharmony_ci		p->symbol_rate = state->symbol_rate;
166962306a36Sopenharmony_ci		p->fec_inner = dst_get_fec(state);
167062306a36Sopenharmony_ci		p->modulation = dst_get_modulation(state);
167162306a36Sopenharmony_ci	}
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	return 0;
167462306a36Sopenharmony_ci}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_cistatic void bt8xx_dst_release(struct dvb_frontend *fe)
167762306a36Sopenharmony_ci{
167862306a36Sopenharmony_ci	struct dst_state *state = fe->demodulator_priv;
167962306a36Sopenharmony_ci	if (state->dst_ca) {
168062306a36Sopenharmony_ci		dvb_unregister_device(state->dst_ca);
168162306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_ATTACH
168262306a36Sopenharmony_ci		symbol_put(dst_ca_attach);
168362306a36Sopenharmony_ci#endif
168462306a36Sopenharmony_ci	}
168562306a36Sopenharmony_ci	kfree(state);
168662306a36Sopenharmony_ci}
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbt_ops;
168962306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbs_ops;
169062306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbc_ops;
169162306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_atsc_ops;
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_cistruct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
169462306a36Sopenharmony_ci{
169562306a36Sopenharmony_ci	/* check if the ASIC is there */
169662306a36Sopenharmony_ci	if (dst_probe(state) < 0) {
169762306a36Sopenharmony_ci		kfree(state);
169862306a36Sopenharmony_ci		return NULL;
169962306a36Sopenharmony_ci	}
170062306a36Sopenharmony_ci	/* determine settings based on type */
170162306a36Sopenharmony_ci	/* create dvb_frontend */
170262306a36Sopenharmony_ci	switch (state->dst_type) {
170362306a36Sopenharmony_ci	case DST_TYPE_IS_TERR:
170462306a36Sopenharmony_ci		memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
170562306a36Sopenharmony_ci		break;
170662306a36Sopenharmony_ci	case DST_TYPE_IS_CABLE:
170762306a36Sopenharmony_ci		memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
170862306a36Sopenharmony_ci		break;
170962306a36Sopenharmony_ci	case DST_TYPE_IS_SAT:
171062306a36Sopenharmony_ci		memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
171162306a36Sopenharmony_ci		break;
171262306a36Sopenharmony_ci	case DST_TYPE_IS_ATSC:
171362306a36Sopenharmony_ci		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
171462306a36Sopenharmony_ci		break;
171562306a36Sopenharmony_ci	default:
171662306a36Sopenharmony_ci		pr_err("unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n");
171762306a36Sopenharmony_ci		kfree(state);
171862306a36Sopenharmony_ci		return NULL;
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci	state->frontend.demodulator_priv = state;
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	return state;				/*	Manu (DST is a card not a frontend)	*/
172362306a36Sopenharmony_ci}
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dst_attach);
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbt_ops = {
172862306a36Sopenharmony_ci	.delsys = { SYS_DVBT },
172962306a36Sopenharmony_ci	.info = {
173062306a36Sopenharmony_ci		.name = "DST DVB-T",
173162306a36Sopenharmony_ci		.frequency_min_hz = 137 * MHz,
173262306a36Sopenharmony_ci		.frequency_max_hz = 858 * MHz,
173362306a36Sopenharmony_ci		.frequency_stepsize_hz = 166667,
173462306a36Sopenharmony_ci		.caps = FE_CAN_FEC_AUTO			|
173562306a36Sopenharmony_ci			FE_CAN_QAM_AUTO			|
173662306a36Sopenharmony_ci			FE_CAN_QAM_16			|
173762306a36Sopenharmony_ci			FE_CAN_QAM_32			|
173862306a36Sopenharmony_ci			FE_CAN_QAM_64			|
173962306a36Sopenharmony_ci			FE_CAN_QAM_128			|
174062306a36Sopenharmony_ci			FE_CAN_QAM_256			|
174162306a36Sopenharmony_ci			FE_CAN_TRANSMISSION_MODE_AUTO	|
174262306a36Sopenharmony_ci			FE_CAN_GUARD_INTERVAL_AUTO
174362306a36Sopenharmony_ci	},
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	.release = bt8xx_dst_release,
174662306a36Sopenharmony_ci	.init = bt8xx_dst_init,
174762306a36Sopenharmony_ci	.tune = dst_tune_frontend,
174862306a36Sopenharmony_ci	.set_frontend = dst_set_frontend,
174962306a36Sopenharmony_ci	.get_frontend = dst_get_frontend,
175062306a36Sopenharmony_ci	.get_frontend_algo = dst_get_tuning_algo,
175162306a36Sopenharmony_ci	.read_status = dst_read_status,
175262306a36Sopenharmony_ci	.read_signal_strength = dst_read_signal_strength,
175362306a36Sopenharmony_ci	.read_snr = dst_read_snr,
175462306a36Sopenharmony_ci};
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbs_ops = {
175762306a36Sopenharmony_ci	.delsys = { SYS_DVBS },
175862306a36Sopenharmony_ci	.info = {
175962306a36Sopenharmony_ci		.name = "DST DVB-S",
176062306a36Sopenharmony_ci		.frequency_min_hz   =  950 * MHz,
176162306a36Sopenharmony_ci		.frequency_max_hz   = 2150 * MHz,
176262306a36Sopenharmony_ci		.frequency_stepsize_hz = 1 * MHz,
176362306a36Sopenharmony_ci		.frequency_tolerance_hz = 29500 * kHz,
176462306a36Sopenharmony_ci		.symbol_rate_min = 1000000,
176562306a36Sopenharmony_ci		.symbol_rate_max = 45000000,
176662306a36Sopenharmony_ci	/*     . symbol_rate_tolerance	=	???,*/
176762306a36Sopenharmony_ci		.caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
176862306a36Sopenharmony_ci	},
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	.release = bt8xx_dst_release,
177162306a36Sopenharmony_ci	.init = bt8xx_dst_init,
177262306a36Sopenharmony_ci	.tune = dst_tune_frontend,
177362306a36Sopenharmony_ci	.set_frontend = dst_set_frontend,
177462306a36Sopenharmony_ci	.get_frontend = dst_get_frontend,
177562306a36Sopenharmony_ci	.get_frontend_algo = dst_get_tuning_algo,
177662306a36Sopenharmony_ci	.read_status = dst_read_status,
177762306a36Sopenharmony_ci	.read_signal_strength = dst_read_signal_strength,
177862306a36Sopenharmony_ci	.read_snr = dst_read_snr,
177962306a36Sopenharmony_ci	.diseqc_send_burst = dst_send_burst,
178062306a36Sopenharmony_ci	.diseqc_send_master_cmd = dst_set_diseqc,
178162306a36Sopenharmony_ci	.set_voltage = dst_set_voltage,
178262306a36Sopenharmony_ci	.set_tone = dst_set_tone,
178362306a36Sopenharmony_ci};
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbc_ops = {
178662306a36Sopenharmony_ci	.delsys = { SYS_DVBC_ANNEX_A },
178762306a36Sopenharmony_ci	.info = {
178862306a36Sopenharmony_ci		.name = "DST DVB-C",
178962306a36Sopenharmony_ci		.frequency_min_hz =  51 * MHz,
179062306a36Sopenharmony_ci		.frequency_max_hz = 858 * MHz,
179162306a36Sopenharmony_ci		.frequency_stepsize_hz = 62500,
179262306a36Sopenharmony_ci		.symbol_rate_min = 1000000,
179362306a36Sopenharmony_ci		.symbol_rate_max = 45000000,
179462306a36Sopenharmony_ci		.caps = FE_CAN_FEC_AUTO |
179562306a36Sopenharmony_ci			FE_CAN_QAM_AUTO |
179662306a36Sopenharmony_ci			FE_CAN_QAM_16	|
179762306a36Sopenharmony_ci			FE_CAN_QAM_32	|
179862306a36Sopenharmony_ci			FE_CAN_QAM_64	|
179962306a36Sopenharmony_ci			FE_CAN_QAM_128	|
180062306a36Sopenharmony_ci			FE_CAN_QAM_256
180162306a36Sopenharmony_ci	},
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	.release = bt8xx_dst_release,
180462306a36Sopenharmony_ci	.init = bt8xx_dst_init,
180562306a36Sopenharmony_ci	.tune = dst_tune_frontend,
180662306a36Sopenharmony_ci	.set_frontend = dst_set_frontend,
180762306a36Sopenharmony_ci	.get_frontend = dst_get_frontend,
180862306a36Sopenharmony_ci	.get_frontend_algo = dst_get_tuning_algo,
180962306a36Sopenharmony_ci	.read_status = dst_read_status,
181062306a36Sopenharmony_ci	.read_signal_strength = dst_read_signal_strength,
181162306a36Sopenharmony_ci	.read_snr = dst_read_snr,
181262306a36Sopenharmony_ci};
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_cistatic const struct dvb_frontend_ops dst_atsc_ops = {
181562306a36Sopenharmony_ci	.delsys = { SYS_ATSC },
181662306a36Sopenharmony_ci	.info = {
181762306a36Sopenharmony_ci		.name = "DST ATSC",
181862306a36Sopenharmony_ci		.frequency_min_hz = 510 * MHz,
181962306a36Sopenharmony_ci		.frequency_max_hz = 858 * MHz,
182062306a36Sopenharmony_ci		.frequency_stepsize_hz = 62500,
182162306a36Sopenharmony_ci		.symbol_rate_min = 1000000,
182262306a36Sopenharmony_ci		.symbol_rate_max = 45000000,
182362306a36Sopenharmony_ci		.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
182462306a36Sopenharmony_ci	},
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	.release = bt8xx_dst_release,
182762306a36Sopenharmony_ci	.init = bt8xx_dst_init,
182862306a36Sopenharmony_ci	.tune = dst_tune_frontend,
182962306a36Sopenharmony_ci	.set_frontend = dst_set_frontend,
183062306a36Sopenharmony_ci	.get_frontend = dst_get_frontend,
183162306a36Sopenharmony_ci	.get_frontend_algo = dst_get_tuning_algo,
183262306a36Sopenharmony_ci	.read_status = dst_read_status,
183362306a36Sopenharmony_ci	.read_signal_strength = dst_read_signal_strength,
183462306a36Sopenharmony_ci	.read_snr = dst_read_snr,
183562306a36Sopenharmony_ci};
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ciMODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
183862306a36Sopenharmony_ciMODULE_AUTHOR("Jamie Honan, Manu Abraham");
183962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1840