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