xref: /linux/drivers/media/firewire/firedtv-fe.c (revision 616300bd)
1*616300bdSMauro Carvalho Chehab /*
2*616300bdSMauro Carvalho Chehab  * FireDTV driver (formerly known as FireSAT)
3*616300bdSMauro Carvalho Chehab  *
4*616300bdSMauro Carvalho Chehab  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5*616300bdSMauro Carvalho Chehab  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
6*616300bdSMauro Carvalho Chehab  *
7*616300bdSMauro Carvalho Chehab  *	This program is free software; you can redistribute it and/or
8*616300bdSMauro Carvalho Chehab  *	modify it under the terms of the GNU General Public License as
9*616300bdSMauro Carvalho Chehab  *	published by the Free Software Foundation; either version 2 of
10*616300bdSMauro Carvalho Chehab  *	the License, or (at your option) any later version.
11*616300bdSMauro Carvalho Chehab  */
12*616300bdSMauro Carvalho Chehab 
13*616300bdSMauro Carvalho Chehab #include <linux/device.h>
14*616300bdSMauro Carvalho Chehab #include <linux/errno.h>
15*616300bdSMauro Carvalho Chehab #include <linux/kernel.h>
16*616300bdSMauro Carvalho Chehab #include <linux/string.h>
17*616300bdSMauro Carvalho Chehab #include <linux/types.h>
18*616300bdSMauro Carvalho Chehab 
19*616300bdSMauro Carvalho Chehab #include <dvb_frontend.h>
20*616300bdSMauro Carvalho Chehab 
21*616300bdSMauro Carvalho Chehab #include "firedtv.h"
22*616300bdSMauro Carvalho Chehab 
23*616300bdSMauro Carvalho Chehab static int fdtv_dvb_init(struct dvb_frontend *fe)
24*616300bdSMauro Carvalho Chehab {
25*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
26*616300bdSMauro Carvalho Chehab 	int err;
27*616300bdSMauro Carvalho Chehab 
28*616300bdSMauro Carvalho Chehab 	/* FIXME - allocate free channel at IRM */
29*616300bdSMauro Carvalho Chehab 	fdtv->isochannel = fdtv->adapter.num;
30*616300bdSMauro Carvalho Chehab 
31*616300bdSMauro Carvalho Chehab 	err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
32*616300bdSMauro Carvalho Chehab 					  fdtv->isochannel);
33*616300bdSMauro Carvalho Chehab 	if (err) {
34*616300bdSMauro Carvalho Chehab 		dev_err(fdtv->device,
35*616300bdSMauro Carvalho Chehab 			"could not establish point to point connection\n");
36*616300bdSMauro Carvalho Chehab 		return err;
37*616300bdSMauro Carvalho Chehab 	}
38*616300bdSMauro Carvalho Chehab 
39*616300bdSMauro Carvalho Chehab 	return fdtv_start_iso(fdtv);
40*616300bdSMauro Carvalho Chehab }
41*616300bdSMauro Carvalho Chehab 
42*616300bdSMauro Carvalho Chehab static int fdtv_sleep(struct dvb_frontend *fe)
43*616300bdSMauro Carvalho Chehab {
44*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
45*616300bdSMauro Carvalho Chehab 
46*616300bdSMauro Carvalho Chehab 	fdtv_stop_iso(fdtv);
47*616300bdSMauro Carvalho Chehab 	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
48*616300bdSMauro Carvalho Chehab 	fdtv->isochannel = -1;
49*616300bdSMauro Carvalho Chehab 	return 0;
50*616300bdSMauro Carvalho Chehab }
51*616300bdSMauro Carvalho Chehab 
52*616300bdSMauro Carvalho Chehab #define LNBCONTROL_DONTCARE 0xff
53*616300bdSMauro Carvalho Chehab 
54*616300bdSMauro Carvalho Chehab static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
55*616300bdSMauro Carvalho Chehab 				       struct dvb_diseqc_master_cmd *cmd)
56*616300bdSMauro Carvalho Chehab {
57*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
58*616300bdSMauro Carvalho Chehab 
59*616300bdSMauro Carvalho Chehab 	return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
60*616300bdSMauro Carvalho Chehab 			       LNBCONTROL_DONTCARE, 1, cmd);
61*616300bdSMauro Carvalho Chehab }
62*616300bdSMauro Carvalho Chehab 
63*616300bdSMauro Carvalho Chehab static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
64*616300bdSMauro Carvalho Chehab 				  fe_sec_mini_cmd_t minicmd)
65*616300bdSMauro Carvalho Chehab {
66*616300bdSMauro Carvalho Chehab 	return 0;
67*616300bdSMauro Carvalho Chehab }
68*616300bdSMauro Carvalho Chehab 
69*616300bdSMauro Carvalho Chehab static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
70*616300bdSMauro Carvalho Chehab {
71*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
72*616300bdSMauro Carvalho Chehab 
73*616300bdSMauro Carvalho Chehab 	fdtv->tone = tone;
74*616300bdSMauro Carvalho Chehab 	return 0;
75*616300bdSMauro Carvalho Chehab }
76*616300bdSMauro Carvalho Chehab 
77*616300bdSMauro Carvalho Chehab static int fdtv_set_voltage(struct dvb_frontend *fe,
78*616300bdSMauro Carvalho Chehab 			    fe_sec_voltage_t voltage)
79*616300bdSMauro Carvalho Chehab {
80*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
81*616300bdSMauro Carvalho Chehab 
82*616300bdSMauro Carvalho Chehab 	fdtv->voltage = voltage;
83*616300bdSMauro Carvalho Chehab 	return 0;
84*616300bdSMauro Carvalho Chehab }
85*616300bdSMauro Carvalho Chehab 
86*616300bdSMauro Carvalho Chehab static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
87*616300bdSMauro Carvalho Chehab {
88*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
89*616300bdSMauro Carvalho Chehab 	struct firedtv_tuner_status stat;
90*616300bdSMauro Carvalho Chehab 
91*616300bdSMauro Carvalho Chehab 	if (avc_tuner_status(fdtv, &stat))
92*616300bdSMauro Carvalho Chehab 		return -EINVAL;
93*616300bdSMauro Carvalho Chehab 
94*616300bdSMauro Carvalho Chehab 	if (stat.no_rf)
95*616300bdSMauro Carvalho Chehab 		*status = 0;
96*616300bdSMauro Carvalho Chehab 	else
97*616300bdSMauro Carvalho Chehab 		*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
98*616300bdSMauro Carvalho Chehab 			  FE_HAS_CARRIER | FE_HAS_LOCK;
99*616300bdSMauro Carvalho Chehab 	return 0;
100*616300bdSMauro Carvalho Chehab }
101*616300bdSMauro Carvalho Chehab 
102*616300bdSMauro Carvalho Chehab static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
103*616300bdSMauro Carvalho Chehab {
104*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
105*616300bdSMauro Carvalho Chehab 	struct firedtv_tuner_status stat;
106*616300bdSMauro Carvalho Chehab 
107*616300bdSMauro Carvalho Chehab 	if (avc_tuner_status(fdtv, &stat))
108*616300bdSMauro Carvalho Chehab 		return -EINVAL;
109*616300bdSMauro Carvalho Chehab 
110*616300bdSMauro Carvalho Chehab 	*ber = stat.ber;
111*616300bdSMauro Carvalho Chehab 	return 0;
112*616300bdSMauro Carvalho Chehab }
113*616300bdSMauro Carvalho Chehab 
114*616300bdSMauro Carvalho Chehab static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
115*616300bdSMauro Carvalho Chehab {
116*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
117*616300bdSMauro Carvalho Chehab 	struct firedtv_tuner_status stat;
118*616300bdSMauro Carvalho Chehab 
119*616300bdSMauro Carvalho Chehab 	if (avc_tuner_status(fdtv, &stat))
120*616300bdSMauro Carvalho Chehab 		return -EINVAL;
121*616300bdSMauro Carvalho Chehab 
122*616300bdSMauro Carvalho Chehab 	*strength = stat.signal_strength << 8;
123*616300bdSMauro Carvalho Chehab 	return 0;
124*616300bdSMauro Carvalho Chehab }
125*616300bdSMauro Carvalho Chehab 
126*616300bdSMauro Carvalho Chehab static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
127*616300bdSMauro Carvalho Chehab {
128*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
129*616300bdSMauro Carvalho Chehab 	struct firedtv_tuner_status stat;
130*616300bdSMauro Carvalho Chehab 
131*616300bdSMauro Carvalho Chehab 	if (avc_tuner_status(fdtv, &stat))
132*616300bdSMauro Carvalho Chehab 		return -EINVAL;
133*616300bdSMauro Carvalho Chehab 
134*616300bdSMauro Carvalho Chehab 	/* C/N[dB] = -10 * log10(snr / 65535) */
135*616300bdSMauro Carvalho Chehab 	*snr = stat.carrier_noise_ratio * 257;
136*616300bdSMauro Carvalho Chehab 	return 0;
137*616300bdSMauro Carvalho Chehab }
138*616300bdSMauro Carvalho Chehab 
139*616300bdSMauro Carvalho Chehab static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
140*616300bdSMauro Carvalho Chehab {
141*616300bdSMauro Carvalho Chehab 	return -EOPNOTSUPP;
142*616300bdSMauro Carvalho Chehab }
143*616300bdSMauro Carvalho Chehab 
144*616300bdSMauro Carvalho Chehab static int fdtv_set_frontend(struct dvb_frontend *fe)
145*616300bdSMauro Carvalho Chehab {
146*616300bdSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
147*616300bdSMauro Carvalho Chehab 	struct firedtv *fdtv = fe->sec_priv;
148*616300bdSMauro Carvalho Chehab 
149*616300bdSMauro Carvalho Chehab 	return avc_tuner_dsd(fdtv, p);
150*616300bdSMauro Carvalho Chehab }
151*616300bdSMauro Carvalho Chehab 
152*616300bdSMauro Carvalho Chehab void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
153*616300bdSMauro Carvalho Chehab {
154*616300bdSMauro Carvalho Chehab 	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
155*616300bdSMauro Carvalho Chehab 	struct dvb_frontend_info *fi = &ops->info;
156*616300bdSMauro Carvalho Chehab 
157*616300bdSMauro Carvalho Chehab 	ops->init			= fdtv_dvb_init;
158*616300bdSMauro Carvalho Chehab 	ops->sleep			= fdtv_sleep;
159*616300bdSMauro Carvalho Chehab 
160*616300bdSMauro Carvalho Chehab 	ops->set_frontend		= fdtv_set_frontend;
161*616300bdSMauro Carvalho Chehab 
162*616300bdSMauro Carvalho Chehab 	ops->read_status		= fdtv_read_status;
163*616300bdSMauro Carvalho Chehab 	ops->read_ber			= fdtv_read_ber;
164*616300bdSMauro Carvalho Chehab 	ops->read_signal_strength	= fdtv_read_signal_strength;
165*616300bdSMauro Carvalho Chehab 	ops->read_snr			= fdtv_read_snr;
166*616300bdSMauro Carvalho Chehab 	ops->read_ucblocks		= fdtv_read_uncorrected_blocks;
167*616300bdSMauro Carvalho Chehab 
168*616300bdSMauro Carvalho Chehab 	ops->diseqc_send_master_cmd 	= fdtv_diseqc_send_master_cmd;
169*616300bdSMauro Carvalho Chehab 	ops->diseqc_send_burst		= fdtv_diseqc_send_burst;
170*616300bdSMauro Carvalho Chehab 	ops->set_tone			= fdtv_set_tone;
171*616300bdSMauro Carvalho Chehab 	ops->set_voltage		= fdtv_set_voltage;
172*616300bdSMauro Carvalho Chehab 
173*616300bdSMauro Carvalho Chehab 	switch (fdtv->type) {
174*616300bdSMauro Carvalho Chehab 	case FIREDTV_DVB_S:
175*616300bdSMauro Carvalho Chehab 		ops->delsys[0]		= SYS_DVBS;
176*616300bdSMauro Carvalho Chehab 
177*616300bdSMauro Carvalho Chehab 		fi->frequency_min	= 950000;
178*616300bdSMauro Carvalho Chehab 		fi->frequency_max	= 2150000;
179*616300bdSMauro Carvalho Chehab 		fi->frequency_stepsize	= 125;
180*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_min	= 1000000;
181*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_max	= 40000000;
182*616300bdSMauro Carvalho Chehab 
183*616300bdSMauro Carvalho Chehab 		fi->caps		= FE_CAN_INVERSION_AUTO |
184*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_1_2	|
185*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_2_3	|
186*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_3_4	|
187*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_5_6	|
188*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_7_8	|
189*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_AUTO	|
190*616300bdSMauro Carvalho Chehab 					  FE_CAN_QPSK;
191*616300bdSMauro Carvalho Chehab 		break;
192*616300bdSMauro Carvalho Chehab 
193*616300bdSMauro Carvalho Chehab 	case FIREDTV_DVB_S2:
194*616300bdSMauro Carvalho Chehab 		ops->delsys[0]		= SYS_DVBS;
195*616300bdSMauro Carvalho Chehab 		ops->delsys[1]		= SYS_DVBS2;
196*616300bdSMauro Carvalho Chehab 
197*616300bdSMauro Carvalho Chehab 		fi->frequency_min	= 950000;
198*616300bdSMauro Carvalho Chehab 		fi->frequency_max	= 2150000;
199*616300bdSMauro Carvalho Chehab 		fi->frequency_stepsize	= 125;
200*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_min	= 1000000;
201*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_max	= 40000000;
202*616300bdSMauro Carvalho Chehab 
203*616300bdSMauro Carvalho Chehab 		fi->caps		= FE_CAN_INVERSION_AUTO |
204*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_1_2        |
205*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_2_3        |
206*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_3_4        |
207*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_5_6        |
208*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_7_8        |
209*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_AUTO       |
210*616300bdSMauro Carvalho Chehab 					  FE_CAN_QPSK           |
211*616300bdSMauro Carvalho Chehab 					  FE_CAN_2G_MODULATION;
212*616300bdSMauro Carvalho Chehab 		break;
213*616300bdSMauro Carvalho Chehab 
214*616300bdSMauro Carvalho Chehab 	case FIREDTV_DVB_C:
215*616300bdSMauro Carvalho Chehab 		ops->delsys[0]		= SYS_DVBC_ANNEX_A;
216*616300bdSMauro Carvalho Chehab 
217*616300bdSMauro Carvalho Chehab 		fi->frequency_min	= 47000000;
218*616300bdSMauro Carvalho Chehab 		fi->frequency_max	= 866000000;
219*616300bdSMauro Carvalho Chehab 		fi->frequency_stepsize	= 62500;
220*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_min	= 870000;
221*616300bdSMauro Carvalho Chehab 		fi->symbol_rate_max	= 6900000;
222*616300bdSMauro Carvalho Chehab 
223*616300bdSMauro Carvalho Chehab 		fi->caps 		= FE_CAN_INVERSION_AUTO |
224*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_16		|
225*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_32		|
226*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_64		|
227*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_128	|
228*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_256	|
229*616300bdSMauro Carvalho Chehab 					  FE_CAN_QAM_AUTO;
230*616300bdSMauro Carvalho Chehab 		break;
231*616300bdSMauro Carvalho Chehab 
232*616300bdSMauro Carvalho Chehab 	case FIREDTV_DVB_T:
233*616300bdSMauro Carvalho Chehab 		ops->delsys[0]		= SYS_DVBT;
234*616300bdSMauro Carvalho Chehab 
235*616300bdSMauro Carvalho Chehab 		fi->frequency_min	= 49000000;
236*616300bdSMauro Carvalho Chehab 		fi->frequency_max	= 861000000;
237*616300bdSMauro Carvalho Chehab 		fi->frequency_stepsize	= 62500;
238*616300bdSMauro Carvalho Chehab 
239*616300bdSMauro Carvalho Chehab 		fi->caps 		= FE_CAN_INVERSION_AUTO		|
240*616300bdSMauro Carvalho Chehab 					  FE_CAN_FEC_2_3		|
241*616300bdSMauro Carvalho Chehab 					  FE_CAN_TRANSMISSION_MODE_AUTO |
242*616300bdSMauro Carvalho Chehab 					  FE_CAN_GUARD_INTERVAL_AUTO	|
243*616300bdSMauro Carvalho Chehab 					  FE_CAN_HIERARCHY_AUTO;
244*616300bdSMauro Carvalho Chehab 		break;
245*616300bdSMauro Carvalho Chehab 
246*616300bdSMauro Carvalho Chehab 	default:
247*616300bdSMauro Carvalho Chehab 		dev_err(fdtv->device, "no frontend for model type %d\n",
248*616300bdSMauro Carvalho Chehab 			fdtv->type);
249*616300bdSMauro Carvalho Chehab 	}
250*616300bdSMauro Carvalho Chehab 	strcpy(fi->name, name);
251*616300bdSMauro Carvalho Chehab 
252*616300bdSMauro Carvalho Chehab 	fdtv->fe.dvb = &fdtv->adapter;
253*616300bdSMauro Carvalho Chehab 	fdtv->fe.sec_priv = fdtv;
254*616300bdSMauro Carvalho Chehab }
255