Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
0003  * DVB-S receiver.
0004  *
0005  * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
0006  *                    Metzler Brothers Systementwicklung GbR
0007  *
0008  * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@posteo.de>
0009  *
0010  * Thanks to Twinhan who kindly provided hardware and information.
0011  *
0012  * This file can be removed soon, after the DST-driver is rewritten to provice
0013  * the frontend-controlling separately.
0014  *
0015  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
0016  */
0017 #include "vp702x.h"
0018 
0019 struct vp702x_fe_state {
0020     struct dvb_frontend fe;
0021     struct dvb_usb_device *d;
0022 
0023     struct dvb_frontend_ops ops;
0024 
0025     enum fe_sec_voltage voltage;
0026     enum fe_sec_tone_mode tone_mode;
0027 
0028     u8 lnb_buf[8];
0029 
0030     u8 lock;
0031     u8 sig;
0032     u8 snr;
0033 
0034     unsigned long next_status_check;
0035     unsigned long status_check_interval;
0036 };
0037 
0038 static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
0039 {
0040     struct vp702x_device_state *dst = st->d->priv;
0041     u8 *buf;
0042 
0043     if (time_after(jiffies, st->next_status_check)) {
0044         mutex_lock(&dst->buf_mutex);
0045         buf = dst->buf;
0046 
0047         vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
0048         st->lock = buf[4];
0049 
0050         vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
0051         st->snr = buf[0];
0052 
0053         vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
0054         st->sig = buf[0];
0055 
0056         mutex_unlock(&dst->buf_mutex);
0057         st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
0058     }
0059     return 0;
0060 }
0061 
0062 static u8 vp702x_chksum(u8 *buf,int f, int count)
0063 {
0064     u8 s = 0;
0065     int i;
0066     for (i = f; i < f+count; i++)
0067         s += buf[i];
0068     return ~s+1;
0069 }
0070 
0071 static int vp702x_fe_read_status(struct dvb_frontend *fe,
0072                  enum fe_status *status)
0073 {
0074     struct vp702x_fe_state *st = fe->demodulator_priv;
0075     vp702x_fe_refresh_state(st);
0076     deb_fe("%s\n",__func__);
0077 
0078     if (st->lock == 0)
0079         *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
0080     else
0081         *status = 0;
0082 
0083     if (*status & FE_HAS_LOCK)
0084         st->status_check_interval = 1000;
0085     else
0086         st->status_check_interval = 250;
0087     return 0;
0088 }
0089 
0090 /* not supported by this Frontend */
0091 static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
0092 {
0093     struct vp702x_fe_state *st = fe->demodulator_priv;
0094     vp702x_fe_refresh_state(st);
0095     *ber = 0;
0096     return 0;
0097 }
0098 
0099 /* not supported by this Frontend */
0100 static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
0101 {
0102     struct vp702x_fe_state *st = fe->demodulator_priv;
0103     vp702x_fe_refresh_state(st);
0104     *unc = 0;
0105     return 0;
0106 }
0107 
0108 static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
0109 {
0110     struct vp702x_fe_state *st = fe->demodulator_priv;
0111     vp702x_fe_refresh_state(st);
0112 
0113     *strength = (st->sig << 8) | st->sig;
0114     return 0;
0115 }
0116 
0117 static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
0118 {
0119     u8 _snr;
0120     struct vp702x_fe_state *st = fe->demodulator_priv;
0121     vp702x_fe_refresh_state(st);
0122 
0123     _snr = (st->snr & 0x1f) * 0xff / 0x1f;
0124     *snr = (_snr << 8) | _snr;
0125     return 0;
0126 }
0127 
0128 static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
0129 {
0130     deb_fe("%s\n",__func__);
0131     tune->min_delay_ms = 2000;
0132     return 0;
0133 }
0134 
0135 static int vp702x_fe_set_frontend(struct dvb_frontend *fe)
0136 {
0137     struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
0138     struct vp702x_fe_state *st = fe->demodulator_priv;
0139     struct vp702x_device_state *dst = st->d->priv;
0140     u32 freq = fep->frequency/1000;
0141     /*CalFrequency*/
0142 /*  u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
0143     u64 sr;
0144     u8 *cmd;
0145 
0146     mutex_lock(&dst->buf_mutex);
0147 
0148     cmd = dst->buf;
0149     memset(cmd, 0, 10);
0150 
0151     cmd[0] = (freq >> 8) & 0x7f;
0152     cmd[1] =  freq       & 0xff;
0153     cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
0154 
0155     sr = (u64) (fep->symbol_rate/1000) << 20;
0156     do_div(sr,88000);
0157     cmd[3] = (sr >> 12) & 0xff;
0158     cmd[4] = (sr >> 4)  & 0xff;
0159     cmd[5] = (sr << 4)  & 0xf0;
0160 
0161     deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
0162             fep->frequency, freq, freq, fep->symbol_rate,
0163             (unsigned long) sr, (unsigned long) sr);
0164 
0165 /*  if (fep->inversion == INVERSION_ON)
0166         cmd[6] |= 0x80; */
0167 
0168     if (st->voltage == SEC_VOLTAGE_18)
0169         cmd[6] |= 0x40;
0170 
0171 /*  if (fep->symbol_rate > 8000000)
0172         cmd[6] |= 0x20;
0173 
0174     if (fep->frequency < 1531000)
0175         cmd[6] |= 0x04;
0176 
0177     if (st->tone_mode == SEC_TONE_ON)
0178         cmd[6] |= 0x01;*/
0179 
0180     cmd[7] = vp702x_chksum(cmd,0,7);
0181 
0182     st->status_check_interval = 250;
0183     st->next_status_check = jiffies;
0184 
0185     vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
0186 
0187     if (cmd[2] == 0 && cmd[3] == 0)
0188         deb_fe("tuning failed.\n");
0189     else
0190         deb_fe("tuning succeeded.\n");
0191 
0192     mutex_unlock(&dst->buf_mutex);
0193 
0194     return 0;
0195 }
0196 
0197 static int vp702x_fe_init(struct dvb_frontend *fe)
0198 {
0199     struct vp702x_fe_state *st = fe->demodulator_priv;
0200     deb_fe("%s\n",__func__);
0201     vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
0202     return 0;
0203 }
0204 
0205 static int vp702x_fe_sleep(struct dvb_frontend *fe)
0206 {
0207     deb_fe("%s\n",__func__);
0208     return 0;
0209 }
0210 
0211 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
0212                     struct dvb_diseqc_master_cmd *m)
0213 {
0214     u8 *cmd;
0215     struct vp702x_fe_state *st = fe->demodulator_priv;
0216     struct vp702x_device_state *dst = st->d->priv;
0217 
0218     deb_fe("%s\n",__func__);
0219 
0220     if (m->msg_len > 4)
0221         return -EINVAL;
0222 
0223     mutex_lock(&dst->buf_mutex);
0224 
0225     cmd = dst->buf;
0226     cmd[1] = SET_DISEQC_CMD;
0227     cmd[2] = m->msg_len;
0228     memcpy(&cmd[3], m->msg, m->msg_len);
0229     cmd[7] = vp702x_chksum(cmd, 0, 7);
0230 
0231     vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
0232 
0233     if (cmd[2] == 0 && cmd[3] == 0)
0234         deb_fe("diseqc cmd failed.\n");
0235     else
0236         deb_fe("diseqc cmd succeeded.\n");
0237 
0238     mutex_unlock(&dst->buf_mutex);
0239 
0240     return 0;
0241 }
0242 
0243 static int vp702x_fe_send_diseqc_burst(struct dvb_frontend *fe,
0244                        enum fe_sec_mini_cmd burst)
0245 {
0246     deb_fe("%s\n",__func__);
0247     return 0;
0248 }
0249 
0250 static int vp702x_fe_set_tone(struct dvb_frontend *fe,
0251                   enum fe_sec_tone_mode tone)
0252 {
0253     struct vp702x_fe_state *st = fe->demodulator_priv;
0254     struct vp702x_device_state *dst = st->d->priv;
0255     u8 *buf;
0256 
0257     deb_fe("%s\n",__func__);
0258 
0259     st->tone_mode = tone;
0260 
0261     if (tone == SEC_TONE_ON)
0262         st->lnb_buf[2] = 0x02;
0263     else
0264         st->lnb_buf[2] = 0x00;
0265 
0266     st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
0267 
0268     mutex_lock(&dst->buf_mutex);
0269 
0270     buf = dst->buf;
0271     memcpy(buf, st->lnb_buf, 8);
0272 
0273     vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
0274     if (buf[2] == 0 && buf[3] == 0)
0275         deb_fe("set_tone cmd failed.\n");
0276     else
0277         deb_fe("set_tone cmd succeeded.\n");
0278 
0279     mutex_unlock(&dst->buf_mutex);
0280 
0281     return 0;
0282 }
0283 
0284 static int vp702x_fe_set_voltage(struct dvb_frontend *fe,
0285                  enum fe_sec_voltage voltage)
0286 {
0287     struct vp702x_fe_state *st = fe->demodulator_priv;
0288     struct vp702x_device_state *dst = st->d->priv;
0289     u8 *buf;
0290     deb_fe("%s\n",__func__);
0291 
0292     st->voltage = voltage;
0293 
0294     if (voltage != SEC_VOLTAGE_OFF)
0295         st->lnb_buf[4] = 0x01;
0296     else
0297         st->lnb_buf[4] = 0x00;
0298 
0299     st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
0300 
0301     mutex_lock(&dst->buf_mutex);
0302 
0303     buf = dst->buf;
0304     memcpy(buf, st->lnb_buf, 8);
0305 
0306     vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
0307     if (buf[2] == 0 && buf[3] == 0)
0308         deb_fe("set_voltage cmd failed.\n");
0309     else
0310         deb_fe("set_voltage cmd succeeded.\n");
0311 
0312     mutex_unlock(&dst->buf_mutex);
0313     return 0;
0314 }
0315 
0316 static void vp702x_fe_release(struct dvb_frontend* fe)
0317 {
0318     struct vp702x_fe_state *st = fe->demodulator_priv;
0319     kfree(st);
0320 }
0321 
0322 static const struct dvb_frontend_ops vp702x_fe_ops;
0323 
0324 struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
0325 {
0326     struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
0327     if (s == NULL)
0328         goto error;
0329 
0330     s->d = d;
0331 
0332     memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
0333     s->fe.demodulator_priv = s;
0334 
0335     s->lnb_buf[1] = SET_LNB_POWER;
0336     s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
0337 
0338     return &s->fe;
0339 error:
0340     return NULL;
0341 }
0342 
0343 
0344 static const struct dvb_frontend_ops vp702x_fe_ops = {
0345     .delsys = { SYS_DVBS },
0346     .info = {
0347         .name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
0348         .frequency_min_hz       =  950 * MHz,
0349         .frequency_max_hz       = 2150 * MHz,
0350         .frequency_stepsize_hz  =    1 * MHz,
0351         .symbol_rate_min     = 1000000,
0352         .symbol_rate_max     = 45000000,
0353         .symbol_rate_tolerance = 500,  /* ppm */
0354         .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0355         FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
0356         FE_CAN_QPSK |
0357         FE_CAN_FEC_AUTO
0358     },
0359     .release = vp702x_fe_release,
0360 
0361     .init  = vp702x_fe_init,
0362     .sleep = vp702x_fe_sleep,
0363 
0364     .set_frontend = vp702x_fe_set_frontend,
0365     .get_tune_settings = vp702x_fe_get_tune_settings,
0366 
0367     .read_status = vp702x_fe_read_status,
0368     .read_ber = vp702x_fe_read_ber,
0369     .read_signal_strength = vp702x_fe_read_signal_strength,
0370     .read_snr = vp702x_fe_read_snr,
0371     .read_ucblocks = vp702x_fe_read_unc_blocks,
0372 
0373     .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
0374     .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
0375     .set_tone = vp702x_fe_set_tone,
0376     .set_voltage = vp702x_fe_set_voltage,
0377 };