1/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0 2 * DVB-S receiver. 3 * 4 * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de> 5 * Metzler Brothers Systementwicklung GbR 6 * 7 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> 8 * 9 * Thanks to Twinhan who kindly provided hardware and information. 10 * 11 * This file can be removed soon, after the DST-driver is rewritten to provice 12 * the frontend-controlling separately. 13 * 14 * This program is free software; you can redistribute it and/or modify it 15 * under the terms of the GNU General Public License as published by the Free 16 * Software Foundation, version 2. 17 * 18 * see Documentation/dvb/README.dvb-usb for more information 19 * 20 */ 21#include "vp702x.h" 22 23struct vp702x_fe_state { 24 struct dvb_frontend fe; 25 struct dvb_usb_device *d; 26 27 struct dvb_frontend_ops ops; 28 29 fe_sec_voltage_t voltage; 30 fe_sec_tone_mode_t tone_mode; 31 32 u8 lnb_buf[8]; 33 34 u8 lock; 35 u8 sig; 36 u8 snr; 37 38 unsigned long next_status_check; 39 unsigned long status_check_interval; 40}; 41 42static int vp702x_fe_refresh_state(struct vp702x_fe_state *st) 43{ 44 struct vp702x_device_state *dst = st->d->priv; 45 u8 *buf; 46 47 if (time_after(jiffies, st->next_status_check)) { 48 mutex_lock(&dst->buf_mutex); 49 buf = dst->buf; 50 51 vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10); 52 st->lock = buf[4]; 53 54 vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1); 55 st->snr = buf[0]; 56 57 vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1); 58 st->sig = buf[0]; 59 60 mutex_unlock(&dst->buf_mutex); 61 st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; 62 } 63 return 0; 64} 65 66static u8 vp702x_chksum(u8 *buf,int f, int count) 67{ 68 u8 s = 0; 69 int i; 70 for (i = f; i < f+count; i++) 71 s += buf[i]; 72 return ~s+1; 73} 74 75static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) 76{ 77 struct vp702x_fe_state *st = fe->demodulator_priv; 78 vp702x_fe_refresh_state(st); 79 deb_fe("%s\n",__func__); 80 81 if (st->lock == 0) 82 *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; 83 else 84 *status = 0; 85 86 if (*status & FE_HAS_LOCK) 87 st->status_check_interval = 1000; 88 else 89 st->status_check_interval = 250; 90 return 0; 91} 92 93/* not supported by this Frontend */ 94static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber) 95{ 96 struct vp702x_fe_state *st = fe->demodulator_priv; 97 vp702x_fe_refresh_state(st); 98 *ber = 0; 99 return 0; 100} 101 102/* not supported by this Frontend */ 103static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) 104{ 105 struct vp702x_fe_state *st = fe->demodulator_priv; 106 vp702x_fe_refresh_state(st); 107 *unc = 0; 108 return 0; 109} 110 111static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) 112{ 113 struct vp702x_fe_state *st = fe->demodulator_priv; 114 vp702x_fe_refresh_state(st); 115 116 *strength = (st->sig << 8) | st->sig; 117 return 0; 118} 119 120static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr) 121{ 122 u8 _snr; 123 struct vp702x_fe_state *st = fe->demodulator_priv; 124 vp702x_fe_refresh_state(st); 125 126 _snr = (st->snr & 0x1f) * 0xff / 0x1f; 127 *snr = (_snr << 8) | _snr; 128 return 0; 129} 130 131static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 132{ 133 deb_fe("%s\n",__func__); 134 tune->min_delay_ms = 2000; 135 return 0; 136} 137 138static int vp702x_fe_set_frontend(struct dvb_frontend *fe) 139{ 140 struct dtv_frontend_properties *fep = &fe->dtv_property_cache; 141 struct vp702x_fe_state *st = fe->demodulator_priv; 142 struct vp702x_device_state *dst = st->d->priv; 143 u32 freq = fep->frequency/1000; 144 /*CalFrequency*/ 145/* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */ 146 u64 sr; 147 u8 *cmd; 148 149 mutex_lock(&dst->buf_mutex); 150 151 cmd = dst->buf; 152 memset(cmd, 0, 10); 153 154 cmd[0] = (freq >> 8) & 0x7f; 155 cmd[1] = freq & 0xff; 156 cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */ 157 158 sr = (u64) (fep->symbol_rate/1000) << 20; 159 do_div(sr,88000); 160 cmd[3] = (sr >> 12) & 0xff; 161 cmd[4] = (sr >> 4) & 0xff; 162 cmd[5] = (sr << 4) & 0xf0; 163 164 deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n", 165 fep->frequency, freq, freq, fep->symbol_rate, 166 (unsigned long) sr, (unsigned long) sr); 167 168/* if (fep->inversion == INVERSION_ON) 169 cmd[6] |= 0x80; */ 170 171 if (st->voltage == SEC_VOLTAGE_18) 172 cmd[6] |= 0x40; 173 174/* if (fep->symbol_rate > 8000000) 175 cmd[6] |= 0x20; 176 177 if (fep->frequency < 1531000) 178 cmd[6] |= 0x04; 179 180 if (st->tone_mode == SEC_TONE_ON) 181 cmd[6] |= 0x01;*/ 182 183 cmd[7] = vp702x_chksum(cmd,0,7); 184 185 st->status_check_interval = 250; 186 st->next_status_check = jiffies; 187 188 vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); 189 190 if (cmd[2] == 0 && cmd[3] == 0) 191 deb_fe("tuning failed.\n"); 192 else 193 deb_fe("tuning succeeded.\n"); 194 195 mutex_unlock(&dst->buf_mutex); 196 197 return 0; 198} 199 200static int vp702x_fe_init(struct dvb_frontend *fe) 201{ 202 struct vp702x_fe_state *st = fe->demodulator_priv; 203 deb_fe("%s\n",__func__); 204 vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0); 205 return 0; 206} 207 208static int vp702x_fe_sleep(struct dvb_frontend *fe) 209{ 210 deb_fe("%s\n",__func__); 211 return 0; 212} 213 214static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, 215 struct dvb_diseqc_master_cmd *m) 216{ 217 u8 *cmd; 218 struct vp702x_fe_state *st = fe->demodulator_priv; 219 struct vp702x_device_state *dst = st->d->priv; 220 221 deb_fe("%s\n",__func__); 222 223 if (m->msg_len > 4) 224 return -EINVAL; 225 226 mutex_lock(&dst->buf_mutex); 227 228 cmd = dst->buf; 229 cmd[1] = SET_DISEQC_CMD; 230 cmd[2] = m->msg_len; 231 memcpy(&cmd[3], m->msg, m->msg_len); 232 cmd[7] = vp702x_chksum(cmd, 0, 7); 233 234 vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); 235 236 if (cmd[2] == 0 && cmd[3] == 0) 237 deb_fe("diseqc cmd failed.\n"); 238 else 239 deb_fe("diseqc cmd succeeded.\n"); 240 241 mutex_unlock(&dst->buf_mutex); 242 243 return 0; 244} 245 246static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) 247{ 248 deb_fe("%s\n",__func__); 249 return 0; 250} 251 252static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 253{ 254 struct vp702x_fe_state *st = fe->demodulator_priv; 255 struct vp702x_device_state *dst = st->d->priv; 256 u8 *buf; 257 258 deb_fe("%s\n",__func__); 259 260 st->tone_mode = tone; 261 262 if (tone == SEC_TONE_ON) 263 st->lnb_buf[2] = 0x02; 264 else 265 st->lnb_buf[2] = 0x00; 266 267 st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); 268 269 mutex_lock(&dst->buf_mutex); 270 271 buf = dst->buf; 272 memcpy(buf, st->lnb_buf, 8); 273 274 vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); 275 if (buf[2] == 0 && buf[3] == 0) 276 deb_fe("set_tone cmd failed.\n"); 277 else 278 deb_fe("set_tone cmd succeeded.\n"); 279 280 mutex_unlock(&dst->buf_mutex); 281 282 return 0; 283} 284 285static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t 286 voltage) 287{ 288 struct vp702x_fe_state *st = fe->demodulator_priv; 289 struct vp702x_device_state *dst = st->d->priv; 290 u8 *buf; 291 deb_fe("%s\n",__func__); 292 293 st->voltage = voltage; 294 295 if (voltage != SEC_VOLTAGE_OFF) 296 st->lnb_buf[4] = 0x01; 297 else 298 st->lnb_buf[4] = 0x00; 299 300 st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); 301 302 mutex_lock(&dst->buf_mutex); 303 304 buf = dst->buf; 305 memcpy(buf, st->lnb_buf, 8); 306 307 vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); 308 if (buf[2] == 0 && buf[3] == 0) 309 deb_fe("set_voltage cmd failed.\n"); 310 else 311 deb_fe("set_voltage cmd succeeded.\n"); 312 313 mutex_unlock(&dst->buf_mutex); 314 return 0; 315} 316 317static void vp702x_fe_release(struct dvb_frontend* fe) 318{ 319 struct vp702x_fe_state *st = fe->demodulator_priv; 320 kfree(st); 321} 322 323static struct dvb_frontend_ops vp702x_fe_ops; 324 325struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d) 326{ 327 struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL); 328 if (s == NULL) 329 goto error; 330 331 s->d = d; 332 333 memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops)); 334 s->fe.demodulator_priv = s; 335 336 s->lnb_buf[1] = SET_LNB_POWER; 337 s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */ 338 339 return &s->fe; 340error: 341 return NULL; 342} 343 344 345static struct dvb_frontend_ops vp702x_fe_ops = { 346 .delsys = { SYS_DVBS }, 347 .info = { 348 .name = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S", 349 .frequency_min = 950000, 350 .frequency_max = 2150000, 351 .frequency_stepsize = 1000, /* kHz for QPSK frontends */ 352 .frequency_tolerance = 0, 353 .symbol_rate_min = 1000000, 354 .symbol_rate_max = 45000000, 355 .symbol_rate_tolerance = 500, /* ppm */ 356 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 357 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | 358 FE_CAN_QPSK | 359 FE_CAN_FEC_AUTO 360 }, 361 .release = vp702x_fe_release, 362 363 .init = vp702x_fe_init, 364 .sleep = vp702x_fe_sleep, 365 366 .set_frontend = vp702x_fe_set_frontend, 367 .get_tune_settings = vp702x_fe_get_tune_settings, 368 369 .read_status = vp702x_fe_read_status, 370 .read_ber = vp702x_fe_read_ber, 371 .read_signal_strength = vp702x_fe_read_signal_strength, 372 .read_snr = vp702x_fe_read_snr, 373 .read_ucblocks = vp702x_fe_read_unc_blocks, 374 375 .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg, 376 .diseqc_send_burst = vp702x_fe_send_diseqc_burst, 377 .set_tone = vp702x_fe_set_tone, 378 .set_voltage = vp702x_fe_set_voltage, 379}; 380