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 <dvb_frontend.h> 20 21#include "firedtv.h" 22 23static int fdtv_dvb_init(struct dvb_frontend *fe) 24{ 25 struct firedtv *fdtv = fe->sec_priv; 26 int err; 27 28 fdtv->isochannel = fdtv->adapter.num; 29 30 err = cmp_establish_pp_connection(fdtv, fdtv->subunit, 31 fdtv->isochannel); 32 if (err) { 33 dev_err(fdtv->device, 34 "could not establish point to point connection\n"); 35 return err; 36 } 37 38 return fdtv->backend->start_iso(fdtv); 39} 40 41static int fdtv_sleep(struct dvb_frontend *fe) 42{ 43 struct firedtv *fdtv = fe->sec_priv; 44 45 fdtv->backend->stop_iso(fdtv); 46 cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel); 47 fdtv->isochannel = -1; 48 return 0; 49} 50 51#define LNBCONTROL_DONTCARE 0xff 52 53static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe, 54 struct dvb_diseqc_master_cmd *cmd) 55{ 56 struct firedtv *fdtv = fe->sec_priv; 57 58 return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 59 LNBCONTROL_DONTCARE, 1, cmd); 60} 61 62static int fdtv_diseqc_send_burst(struct dvb_frontend *fe, 63 fe_sec_mini_cmd_t minicmd) 64{ 65 return 0; 66} 67 68static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) 69{ 70 struct firedtv *fdtv = fe->sec_priv; 71 72 fdtv->tone = tone; 73 return 0; 74} 75 76static int fdtv_set_voltage(struct dvb_frontend *fe, 77 fe_sec_voltage_t voltage) 78{ 79 struct firedtv *fdtv = fe->sec_priv; 80 81 fdtv->voltage = voltage; 82 return 0; 83} 84 85static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status) 86{ 87 struct firedtv *fdtv = fe->sec_priv; 88 struct firedtv_tuner_status stat; 89 90 if (avc_tuner_status(fdtv, &stat)) 91 return -EINVAL; 92 93 if (stat.no_rf) 94 *status = 0; 95 else 96 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | 97 FE_HAS_CARRIER | FE_HAS_LOCK; 98 return 0; 99} 100 101static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber) 102{ 103 struct firedtv *fdtv = fe->sec_priv; 104 struct firedtv_tuner_status stat; 105 106 if (avc_tuner_status(fdtv, &stat)) 107 return -EINVAL; 108 109 *ber = stat.ber; 110 return 0; 111} 112 113static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 114{ 115 struct firedtv *fdtv = fe->sec_priv; 116 struct firedtv_tuner_status stat; 117 118 if (avc_tuner_status(fdtv, &stat)) 119 return -EINVAL; 120 121 *strength = stat.signal_strength << 8; 122 return 0; 123} 124 125static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr) 126{ 127 struct firedtv *fdtv = fe->sec_priv; 128 struct firedtv_tuner_status stat; 129 130 if (avc_tuner_status(fdtv, &stat)) 131 return -EINVAL; 132 133 /* C/N[dB] = -10 * log10(snr / 65535) */ 134 *snr = stat.carrier_noise_ratio * 257; 135 return 0; 136} 137 138static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks) 139{ 140 return -EOPNOTSUPP; 141} 142 143static int fdtv_set_frontend(struct dvb_frontend *fe, 144 struct dvb_frontend_parameters *params) 145{ 146 struct firedtv *fdtv = fe->sec_priv; 147 148 return avc_tuner_dsd(fdtv, params); 149} 150 151static int fdtv_get_frontend(struct dvb_frontend *fe, 152 struct dvb_frontend_parameters *params) 153{ 154 return -EOPNOTSUPP; 155} 156 157void fdtv_frontend_init(struct firedtv *fdtv) 158{ 159 struct dvb_frontend_ops *ops = &fdtv->fe.ops; 160 struct dvb_frontend_info *fi = &ops->info; 161 162 ops->init = fdtv_dvb_init; 163 ops->sleep = fdtv_sleep; 164 165 ops->set_frontend = fdtv_set_frontend; 166 ops->get_frontend = fdtv_get_frontend; 167 168 ops->read_status = fdtv_read_status; 169 ops->read_ber = fdtv_read_ber; 170 ops->read_signal_strength = fdtv_read_signal_strength; 171 ops->read_snr = fdtv_read_snr; 172 ops->read_ucblocks = fdtv_read_uncorrected_blocks; 173 174 ops->diseqc_send_master_cmd = fdtv_diseqc_send_master_cmd; 175 ops->diseqc_send_burst = fdtv_diseqc_send_burst; 176 ops->set_tone = fdtv_set_tone; 177 ops->set_voltage = fdtv_set_voltage; 178 179 switch (fdtv->type) { 180 case FIREDTV_DVB_S: 181 case FIREDTV_DVB_S2: 182 fi->type = FE_QPSK; 183 184 fi->frequency_min = 950000; 185 fi->frequency_max = 2150000; 186 fi->frequency_stepsize = 125; 187 fi->symbol_rate_min = 1000000; 188 fi->symbol_rate_max = 40000000; 189 190 fi->caps = FE_CAN_INVERSION_AUTO | 191 FE_CAN_FEC_1_2 | 192 FE_CAN_FEC_2_3 | 193 FE_CAN_FEC_3_4 | 194 FE_CAN_FEC_5_6 | 195 FE_CAN_FEC_7_8 | 196 FE_CAN_FEC_AUTO | 197 FE_CAN_QPSK; 198 break; 199 200 case FIREDTV_DVB_C: 201 fi->type = FE_QAM; 202 203 fi->frequency_min = 47000000; 204 fi->frequency_max = 866000000; 205 fi->frequency_stepsize = 62500; 206 fi->symbol_rate_min = 870000; 207 fi->symbol_rate_max = 6900000; 208 209 fi->caps = FE_CAN_INVERSION_AUTO | 210 FE_CAN_QAM_16 | 211 FE_CAN_QAM_32 | 212 FE_CAN_QAM_64 | 213 FE_CAN_QAM_128 | 214 FE_CAN_QAM_256 | 215 FE_CAN_QAM_AUTO; 216 break; 217 218 case FIREDTV_DVB_T: 219 fi->type = FE_OFDM; 220 221 fi->frequency_min = 49000000; 222 fi->frequency_max = 861000000; 223 fi->frequency_stepsize = 62500; 224 225 fi->caps = FE_CAN_INVERSION_AUTO | 226 FE_CAN_FEC_2_3 | 227 FE_CAN_TRANSMISSION_MODE_AUTO | 228 FE_CAN_GUARD_INTERVAL_AUTO | 229 FE_CAN_HIERARCHY_AUTO; 230 break; 231 232 default: 233 dev_err(fdtv->device, "no frontend for model type %d\n", 234 fdtv->type); 235 } 236 strcpy(fi->name, fdtv_model_names[fdtv->type]); 237 238 fdtv->fe.dvb = &fdtv->adapter; 239 fdtv->fe.sec_priv = fdtv; 240} 241