root/drivers/media/usb/dvb-usb/vp702x-fe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vp702x_fe_refresh_state
  2. vp702x_chksum
  3. vp702x_fe_read_status
  4. vp702x_fe_read_ber
  5. vp702x_fe_read_unc_blocks
  6. vp702x_fe_read_signal_strength
  7. vp702x_fe_read_snr
  8. vp702x_fe_get_tune_settings
  9. vp702x_fe_set_frontend
  10. vp702x_fe_init
  11. vp702x_fe_sleep
  12. vp702x_fe_send_diseqc_msg
  13. vp702x_fe_send_diseqc_burst
  14. vp702x_fe_set_tone
  15. vp702x_fe_set_voltage
  16. vp702x_fe_release
  17. vp702x_fe_attach

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

/* [<][>][^][v][top][bottom][index][help] */