0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "vp7045.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020 struct vp7045_fe_state {
0021 struct dvb_frontend fe;
0022 struct dvb_usb_device *d;
0023 };
0024
0025 static int vp7045_fe_read_status(struct dvb_frontend *fe,
0026 enum fe_status *status)
0027 {
0028 struct vp7045_fe_state *state = fe->demodulator_priv;
0029 u8 s0 = vp7045_read_reg(state->d,0x00),
0030 s1 = vp7045_read_reg(state->d,0x01),
0031 s3 = vp7045_read_reg(state->d,0x03);
0032
0033 *status = 0;
0034 if (s0 & (1 << 4))
0035 *status |= FE_HAS_CARRIER;
0036 if (s0 & (1 << 1))
0037 *status |= FE_HAS_VITERBI;
0038 if (s0 & (1 << 5))
0039 *status |= FE_HAS_LOCK;
0040 if (s1 & (1 << 1))
0041 *status |= FE_HAS_SYNC;
0042 if (s3 & (1 << 6))
0043 *status |= FE_HAS_SIGNAL;
0044
0045 if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
0046 (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
0047 *status &= ~FE_HAS_LOCK;
0048
0049 return 0;
0050 }
0051
0052 static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
0053 {
0054 struct vp7045_fe_state *state = fe->demodulator_priv;
0055 *ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
0056 (vp7045_read_reg(state->d, 0x0E) << 8) |
0057 vp7045_read_reg(state->d, 0x0F);
0058 return 0;
0059 }
0060
0061 static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
0062 {
0063 struct vp7045_fe_state *state = fe->demodulator_priv;
0064 *unc = (vp7045_read_reg(state->d, 0x10) << 8) |
0065 vp7045_read_reg(state->d, 0x11);
0066 return 0;
0067 }
0068
0069 static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
0070 {
0071 struct vp7045_fe_state *state = fe->demodulator_priv;
0072 u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
0073 vp7045_read_reg(state->d, 0x15);
0074
0075 *strength = ~signal;
0076 return 0;
0077 }
0078
0079 static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
0080 {
0081 struct vp7045_fe_state *state = fe->demodulator_priv;
0082 u8 _snr = vp7045_read_reg(state->d, 0x09);
0083 *snr = (_snr << 8) | _snr;
0084 return 0;
0085 }
0086
0087 static int vp7045_fe_init(struct dvb_frontend* fe)
0088 {
0089 return 0;
0090 }
0091
0092 static int vp7045_fe_sleep(struct dvb_frontend* fe)
0093 {
0094 return 0;
0095 }
0096
0097 static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
0098 {
0099 tune->min_delay_ms = 800;
0100 return 0;
0101 }
0102
0103 static int vp7045_fe_set_frontend(struct dvb_frontend *fe)
0104 {
0105 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
0106 struct vp7045_fe_state *state = fe->demodulator_priv;
0107 u8 buf[5];
0108 u32 freq = fep->frequency / 1000;
0109
0110 buf[0] = (freq >> 16) & 0xff;
0111 buf[1] = (freq >> 8) & 0xff;
0112 buf[2] = freq & 0xff;
0113 buf[3] = 0;
0114
0115 switch (fep->bandwidth_hz) {
0116 case 8000000:
0117 buf[4] = 8;
0118 break;
0119 case 7000000:
0120 buf[4] = 7;
0121 break;
0122 case 6000000:
0123 buf[4] = 6;
0124 break;
0125 default:
0126 return -EINVAL;
0127 }
0128
0129 vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
0130 return 0;
0131 }
0132
0133 static void vp7045_fe_release(struct dvb_frontend* fe)
0134 {
0135 struct vp7045_fe_state *state = fe->demodulator_priv;
0136 kfree(state);
0137 }
0138
0139 static const struct dvb_frontend_ops vp7045_fe_ops;
0140
0141 struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
0142 {
0143 struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
0144 if (s == NULL)
0145 goto error;
0146
0147 s->d = d;
0148 memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
0149 s->fe.demodulator_priv = s;
0150
0151 return &s->fe;
0152 error:
0153 return NULL;
0154 }
0155
0156
0157 static const struct dvb_frontend_ops vp7045_fe_ops = {
0158 .delsys = { SYS_DVBT },
0159 .info = {
0160 .name = "Twinhan VP7045/46 USB DVB-T",
0161 .frequency_min_hz = 44250 * kHz,
0162 .frequency_max_hz = 867250 * kHz,
0163 .frequency_stepsize_hz = 1 * kHz,
0164 .caps = FE_CAN_INVERSION_AUTO |
0165 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0166 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
0167 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
0168 FE_CAN_TRANSMISSION_MODE_AUTO |
0169 FE_CAN_GUARD_INTERVAL_AUTO |
0170 FE_CAN_RECOVER |
0171 FE_CAN_HIERARCHY_AUTO,
0172 },
0173
0174 .release = vp7045_fe_release,
0175
0176 .init = vp7045_fe_init,
0177 .sleep = vp7045_fe_sleep,
0178
0179 .set_frontend = vp7045_fe_set_frontend,
0180 .get_tune_settings = vp7045_fe_get_tune_settings,
0181
0182 .read_status = vp7045_fe_read_status,
0183 .read_ber = vp7045_fe_read_ber,
0184 .read_signal_strength = vp7045_fe_read_signal_strength,
0185 .read_snr = vp7045_fe_read_snr,
0186 .read_ucblocks = vp7045_fe_read_unc_blocks,
0187 };