162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
362306a36Sopenharmony_ci * DVB-S receiver.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
662306a36Sopenharmony_ci *                    Metzler Brothers Systementwicklung GbR
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@posteo.de>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Thanks to Twinhan who kindly provided hardware and information.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * This file can be removed soon, after the DST-driver is rewritten to provice
1362306a36Sopenharmony_ci * the frontend-controlling separately.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci#include "vp702x.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct vp702x_fe_state {
2062306a36Sopenharmony_ci	struct dvb_frontend fe;
2162306a36Sopenharmony_ci	struct dvb_usb_device *d;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	struct dvb_frontend_ops ops;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	enum fe_sec_voltage voltage;
2662306a36Sopenharmony_ci	enum fe_sec_tone_mode tone_mode;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	u8 lnb_buf[8];
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	u8 lock;
3162306a36Sopenharmony_ci	u8 sig;
3262306a36Sopenharmony_ci	u8 snr;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	unsigned long next_status_check;
3562306a36Sopenharmony_ci	unsigned long status_check_interval;
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct vp702x_device_state *dst = st->d->priv;
4162306a36Sopenharmony_ci	u8 *buf;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (time_after(jiffies, st->next_status_check)) {
4462306a36Sopenharmony_ci		mutex_lock(&dst->buf_mutex);
4562306a36Sopenharmony_ci		buf = dst->buf;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci		vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
4862306a36Sopenharmony_ci		st->lock = buf[4];
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
5162306a36Sopenharmony_ci		st->snr = buf[0];
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
5462306a36Sopenharmony_ci		st->sig = buf[0];
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci		mutex_unlock(&dst->buf_mutex);
5762306a36Sopenharmony_ci		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci	return 0;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic u8 vp702x_chksum(u8 *buf,int f, int count)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	u8 s = 0;
6562306a36Sopenharmony_ci	int i;
6662306a36Sopenharmony_ci	for (i = f; i < f+count; i++)
6762306a36Sopenharmony_ci		s += buf[i];
6862306a36Sopenharmony_ci	return ~s+1;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic int vp702x_fe_read_status(struct dvb_frontend *fe,
7262306a36Sopenharmony_ci				 enum fe_status *status)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
7562306a36Sopenharmony_ci	vp702x_fe_refresh_state(st);
7662306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (st->lock == 0)
7962306a36Sopenharmony_ci		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
8062306a36Sopenharmony_ci	else
8162306a36Sopenharmony_ci		*status = 0;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (*status & FE_HAS_LOCK)
8462306a36Sopenharmony_ci		st->status_check_interval = 1000;
8562306a36Sopenharmony_ci	else
8662306a36Sopenharmony_ci		st->status_check_interval = 250;
8762306a36Sopenharmony_ci	return 0;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/* not supported by this Frontend */
9162306a36Sopenharmony_cistatic int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
9462306a36Sopenharmony_ci	vp702x_fe_refresh_state(st);
9562306a36Sopenharmony_ci	*ber = 0;
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/* not supported by this Frontend */
10062306a36Sopenharmony_cistatic int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
10362306a36Sopenharmony_ci	vp702x_fe_refresh_state(st);
10462306a36Sopenharmony_ci	*unc = 0;
10562306a36Sopenharmony_ci	return 0;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
11162306a36Sopenharmony_ci	vp702x_fe_refresh_state(st);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	*strength = (st->sig << 8) | st->sig;
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	u8 _snr;
12062306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
12162306a36Sopenharmony_ci	vp702x_fe_refresh_state(st);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	_snr = (st->snr & 0x1f) * 0xff / 0x1f;
12462306a36Sopenharmony_ci	*snr = (_snr << 8) | _snr;
12562306a36Sopenharmony_ci	return 0;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
13162306a36Sopenharmony_ci	tune->min_delay_ms = 2000;
13262306a36Sopenharmony_ci	return 0;
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic int vp702x_fe_set_frontend(struct dvb_frontend *fe)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
13862306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
13962306a36Sopenharmony_ci	struct vp702x_device_state *dst = st->d->priv;
14062306a36Sopenharmony_ci	u32 freq = fep->frequency/1000;
14162306a36Sopenharmony_ci	/*CalFrequency*/
14262306a36Sopenharmony_ci/*	u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
14362306a36Sopenharmony_ci	u64 sr;
14462306a36Sopenharmony_ci	u8 *cmd;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	mutex_lock(&dst->buf_mutex);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	cmd = dst->buf;
14962306a36Sopenharmony_ci	memset(cmd, 0, 10);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	cmd[0] = (freq >> 8) & 0x7f;
15262306a36Sopenharmony_ci	cmd[1] =  freq       & 0xff;
15362306a36Sopenharmony_ci	cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	sr = (u64) (fep->symbol_rate/1000) << 20;
15662306a36Sopenharmony_ci	do_div(sr,88000);
15762306a36Sopenharmony_ci	cmd[3] = (sr >> 12) & 0xff;
15862306a36Sopenharmony_ci	cmd[4] = (sr >> 4)  & 0xff;
15962306a36Sopenharmony_ci	cmd[5] = (sr << 4)  & 0xf0;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
16262306a36Sopenharmony_ci			fep->frequency, freq, freq, fep->symbol_rate,
16362306a36Sopenharmony_ci			(unsigned long) sr, (unsigned long) sr);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/*	if (fep->inversion == INVERSION_ON)
16662306a36Sopenharmony_ci		cmd[6] |= 0x80; */
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (st->voltage == SEC_VOLTAGE_18)
16962306a36Sopenharmony_ci		cmd[6] |= 0x40;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/*	if (fep->symbol_rate > 8000000)
17262306a36Sopenharmony_ci		cmd[6] |= 0x20;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	if (fep->frequency < 1531000)
17562306a36Sopenharmony_ci		cmd[6] |= 0x04;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	if (st->tone_mode == SEC_TONE_ON)
17862306a36Sopenharmony_ci		cmd[6] |= 0x01;*/
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	cmd[7] = vp702x_chksum(cmd,0,7);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	st->status_check_interval = 250;
18362306a36Sopenharmony_ci	st->next_status_check = jiffies;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (cmd[2] == 0 && cmd[3] == 0)
18862306a36Sopenharmony_ci		deb_fe("tuning failed.\n");
18962306a36Sopenharmony_ci	else
19062306a36Sopenharmony_ci		deb_fe("tuning succeeded.\n");
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	mutex_unlock(&dst->buf_mutex);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	return 0;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic int vp702x_fe_init(struct dvb_frontend *fe)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
20062306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
20162306a36Sopenharmony_ci	vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
20262306a36Sopenharmony_ci	return 0;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic int vp702x_fe_sleep(struct dvb_frontend *fe)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
20862306a36Sopenharmony_ci	return 0;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
21262306a36Sopenharmony_ci				    struct dvb_diseqc_master_cmd *m)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	u8 *cmd;
21562306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
21662306a36Sopenharmony_ci	struct vp702x_device_state *dst = st->d->priv;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (m->msg_len > 4)
22162306a36Sopenharmony_ci		return -EINVAL;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	mutex_lock(&dst->buf_mutex);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	cmd = dst->buf;
22662306a36Sopenharmony_ci	cmd[1] = SET_DISEQC_CMD;
22762306a36Sopenharmony_ci	cmd[2] = m->msg_len;
22862306a36Sopenharmony_ci	memcpy(&cmd[3], m->msg, m->msg_len);
22962306a36Sopenharmony_ci	cmd[7] = vp702x_chksum(cmd, 0, 7);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (cmd[2] == 0 && cmd[3] == 0)
23462306a36Sopenharmony_ci		deb_fe("diseqc cmd failed.\n");
23562306a36Sopenharmony_ci	else
23662306a36Sopenharmony_ci		deb_fe("diseqc cmd succeeded.\n");
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	mutex_unlock(&dst->buf_mutex);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	return 0;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic int vp702x_fe_send_diseqc_burst(struct dvb_frontend *fe,
24462306a36Sopenharmony_ci				       enum fe_sec_mini_cmd burst)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
24762306a36Sopenharmony_ci	return 0;
24862306a36Sopenharmony_ci}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic int vp702x_fe_set_tone(struct dvb_frontend *fe,
25162306a36Sopenharmony_ci			      enum fe_sec_tone_mode tone)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
25462306a36Sopenharmony_ci	struct vp702x_device_state *dst = st->d->priv;
25562306a36Sopenharmony_ci	u8 *buf;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	st->tone_mode = tone;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (tone == SEC_TONE_ON)
26262306a36Sopenharmony_ci		st->lnb_buf[2] = 0x02;
26362306a36Sopenharmony_ci	else
26462306a36Sopenharmony_ci		st->lnb_buf[2] = 0x00;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	mutex_lock(&dst->buf_mutex);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	buf = dst->buf;
27162306a36Sopenharmony_ci	memcpy(buf, st->lnb_buf, 8);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
27462306a36Sopenharmony_ci	if (buf[2] == 0 && buf[3] == 0)
27562306a36Sopenharmony_ci		deb_fe("set_tone cmd failed.\n");
27662306a36Sopenharmony_ci	else
27762306a36Sopenharmony_ci		deb_fe("set_tone cmd succeeded.\n");
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	mutex_unlock(&dst->buf_mutex);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	return 0;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic int vp702x_fe_set_voltage(struct dvb_frontend *fe,
28562306a36Sopenharmony_ci				 enum fe_sec_voltage voltage)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
28862306a36Sopenharmony_ci	struct vp702x_device_state *dst = st->d->priv;
28962306a36Sopenharmony_ci	u8 *buf;
29062306a36Sopenharmony_ci	deb_fe("%s\n",__func__);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	st->voltage = voltage;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	if (voltage != SEC_VOLTAGE_OFF)
29562306a36Sopenharmony_ci		st->lnb_buf[4] = 0x01;
29662306a36Sopenharmony_ci	else
29762306a36Sopenharmony_ci		st->lnb_buf[4] = 0x00;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	mutex_lock(&dst->buf_mutex);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	buf = dst->buf;
30462306a36Sopenharmony_ci	memcpy(buf, st->lnb_buf, 8);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
30762306a36Sopenharmony_ci	if (buf[2] == 0 && buf[3] == 0)
30862306a36Sopenharmony_ci		deb_fe("set_voltage cmd failed.\n");
30962306a36Sopenharmony_ci	else
31062306a36Sopenharmony_ci		deb_fe("set_voltage cmd succeeded.\n");
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	mutex_unlock(&dst->buf_mutex);
31362306a36Sopenharmony_ci	return 0;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic void vp702x_fe_release(struct dvb_frontend* fe)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	struct vp702x_fe_state *st = fe->demodulator_priv;
31962306a36Sopenharmony_ci	kfree(st);
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic const struct dvb_frontend_ops vp702x_fe_ops;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistruct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
32762306a36Sopenharmony_ci	if (s == NULL)
32862306a36Sopenharmony_ci		goto error;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	s->d = d;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
33362306a36Sopenharmony_ci	s->fe.demodulator_priv = s;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	s->lnb_buf[1] = SET_LNB_POWER;
33662306a36Sopenharmony_ci	s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	return &s->fe;
33962306a36Sopenharmony_cierror:
34062306a36Sopenharmony_ci	return NULL;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic const struct dvb_frontend_ops vp702x_fe_ops = {
34562306a36Sopenharmony_ci	.delsys = { SYS_DVBS },
34662306a36Sopenharmony_ci	.info = {
34762306a36Sopenharmony_ci		.name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
34862306a36Sopenharmony_ci		.frequency_min_hz       =  950 * MHz,
34962306a36Sopenharmony_ci		.frequency_max_hz       = 2150 * MHz,
35062306a36Sopenharmony_ci		.frequency_stepsize_hz  =    1 * MHz,
35162306a36Sopenharmony_ci		.symbol_rate_min     = 1000000,
35262306a36Sopenharmony_ci		.symbol_rate_max     = 45000000,
35362306a36Sopenharmony_ci		.symbol_rate_tolerance = 500,  /* ppm */
35462306a36Sopenharmony_ci		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
35562306a36Sopenharmony_ci		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
35662306a36Sopenharmony_ci		FE_CAN_QPSK |
35762306a36Sopenharmony_ci		FE_CAN_FEC_AUTO
35862306a36Sopenharmony_ci	},
35962306a36Sopenharmony_ci	.release = vp702x_fe_release,
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	.init  = vp702x_fe_init,
36262306a36Sopenharmony_ci	.sleep = vp702x_fe_sleep,
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	.set_frontend = vp702x_fe_set_frontend,
36562306a36Sopenharmony_ci	.get_tune_settings = vp702x_fe_get_tune_settings,
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	.read_status = vp702x_fe_read_status,
36862306a36Sopenharmony_ci	.read_ber = vp702x_fe_read_ber,
36962306a36Sopenharmony_ci	.read_signal_strength = vp702x_fe_read_signal_strength,
37062306a36Sopenharmony_ci	.read_snr = vp702x_fe_read_snr,
37162306a36Sopenharmony_ci	.read_ucblocks = vp702x_fe_read_unc_blocks,
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	.diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
37462306a36Sopenharmony_ci	.diseqc_send_burst = vp702x_fe_send_diseqc_burst,
37562306a36Sopenharmony_ci	.set_tone = vp702x_fe_set_tone,
37662306a36Sopenharmony_ci	.set_voltage = vp702x_fe_set_voltage,
37762306a36Sopenharmony_ci};
378