Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * DVB-T receiver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Thanks to Twinhan who kindly provided hardware and information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "vp7045.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) /* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * Programming is hidden inside the firmware, so set_frontend is very easy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * Even though there is a Firmware command that one can use to access the demod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * via its registers. This is used for status information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) struct vp7045_fe_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	struct dvb_frontend fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct dvb_usb_device *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static int vp7045_fe_read_status(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 				 enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	u8 s0 = vp7045_read_reg(state->d,0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	   s1 = vp7045_read_reg(state->d,0x01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	   s3 = vp7045_read_reg(state->d,0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	*status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	if (s0 & (1 << 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		*status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (s0 & (1 << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		*status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (s0 & (1 << 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		*status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	if (s1 & (1 << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		*status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	if (s3 & (1 << 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		*status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 			(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		*status &= ~FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	*ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	       (vp7045_read_reg(state->d, 0x0E) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		vp7045_read_reg(state->d, 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	*unc = (vp7045_read_reg(state->d, 0x10) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		    vp7045_read_reg(state->d, 0x11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		vp7045_read_reg(state->d, 0x15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	*strength = ~signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	u8 _snr = vp7045_read_reg(state->d, 0x09);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	*snr = (_snr << 8) | _snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static int vp7045_fe_init(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) static int vp7045_fe_sleep(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	tune->min_delay_ms = 800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int vp7045_fe_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	u8 buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	u32 freq = fep->frequency / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	buf[0] = (freq >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	buf[1] = (freq >>  8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	buf[2] =  freq        & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	buf[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	switch (fep->bandwidth_hz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	case 8000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		buf[4] = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	case 7000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		buf[4] = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	case 6000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		buf[4] = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void vp7045_fe_release(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	struct vp7045_fe_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static const struct dvb_frontend_ops vp7045_fe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (s == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	s->d = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	s->fe.demodulator_priv = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return &s->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static const struct dvb_frontend_ops vp7045_fe_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	.delsys = { SYS_DVBT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	.info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		.name			= "Twinhan VP7045/46 USB DVB-T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		.frequency_min_hz	=  44250 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		.frequency_max_hz	= 867250 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		.frequency_stepsize_hz	=      1 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		.caps = FE_CAN_INVERSION_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				FE_CAN_TRANSMISSION_MODE_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				FE_CAN_GUARD_INTERVAL_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				FE_CAN_RECOVER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				FE_CAN_HIERARCHY_AUTO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	.release = vp7045_fe_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	.init = vp7045_fe_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	.sleep = vp7045_fe_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	.set_frontend = vp7045_fe_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	.get_tune_settings = vp7045_fe_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	.read_status = vp7045_fe_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	.read_ber = vp7045_fe_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	.read_signal_strength = vp7045_fe_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	.read_snr = vp7045_fe_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	.read_ucblocks = vp7045_fe_read_unc_blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };