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-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Abilis Systems Single DVB-T Receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include "as102_fe.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) struct as102_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 	struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	struct as10x_demod_stats demod_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	const struct as102_fe_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	uint8_t elna_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	/* signal strength */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	uint16_t signal_strength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	/* bit error rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	uint32_t ber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static uint8_t as102_fe_get_code_rate(enum fe_code_rate arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	uint8_t c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	switch (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	case FEC_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		c = CODE_RATE_1_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	case FEC_2_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		c = CODE_RATE_2_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	case FEC_3_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		c = CODE_RATE_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	case FEC_5_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		c = CODE_RATE_5_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	case FEC_7_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		c = CODE_RATE_7_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		c = CODE_RATE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static int as102_fe_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct as10x_tune_args tune_args = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	/* set frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	tune_args.freq = c->frequency / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	/* fix interleaving_mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	tune_args.interleaving_mode = INTLV_NATIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	switch (c->bandwidth_hz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	case 8000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		tune_args.bandwidth = BW_8_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	case 7000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		tune_args.bandwidth = BW_7_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	case 6000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		tune_args.bandwidth = BW_6_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		tune_args.bandwidth = BW_8_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	switch (c->guard_interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	case GUARD_INTERVAL_1_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		tune_args.guard_interval = GUARD_INT_1_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	case GUARD_INTERVAL_1_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		tune_args.guard_interval = GUARD_INT_1_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	case GUARD_INTERVAL_1_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		tune_args.guard_interval = GUARD_INT_1_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	case GUARD_INTERVAL_1_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		tune_args.guard_interval = GUARD_INT_1_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	case GUARD_INTERVAL_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		tune_args.guard_interval = GUARD_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	switch (c->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	case QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		tune_args.modulation = CONST_QPSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	case QAM_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		tune_args.modulation = CONST_QAM16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		tune_args.modulation = CONST_QAM64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		tune_args.modulation = CONST_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	switch (c->transmission_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	case TRANSMISSION_MODE_2K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		tune_args.transmission_mode = TRANS_MODE_2K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	case TRANSMISSION_MODE_8K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		tune_args.transmission_mode = TRANS_MODE_8K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		tune_args.transmission_mode = TRANS_MODE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	switch (c->hierarchy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	case HIERARCHY_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		tune_args.hierarchy = HIER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	case HIERARCHY_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		tune_args.hierarchy = HIER_ALPHA_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	case HIERARCHY_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		tune_args.hierarchy = HIER_ALPHA_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	case HIERARCHY_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		tune_args.hierarchy = HIER_ALPHA_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	case HIERARCHY_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		tune_args.hierarchy = HIER_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	pr_debug("as102: tuner parameters: freq: %d  bw: 0x%02x  gi: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			c->frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			tune_args.bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			tune_args.guard_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	 * Detect a hierarchy selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 * if HP/LP are both set to FEC_NONE, HP will be selected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if ((tune_args.hierarchy != HIER_NONE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		       ((c->code_rate_LP == FEC_NONE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			(c->code_rate_HP == FEC_NONE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		if (c->code_rate_LP == FEC_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			tune_args.hier_select = HIER_HIGH_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			tune_args.code_rate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			   as102_fe_get_code_rate(c->code_rate_HP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		if (c->code_rate_HP == FEC_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			tune_args.hier_select = HIER_LOW_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			tune_args.code_rate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			   as102_fe_get_code_rate(c->code_rate_LP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		pr_debug("as102: \thierarchy: 0x%02x  selected: %s  code_rate_%s: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			tune_args.hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			tune_args.hier_select == HIER_HIGH_PRIORITY ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			"HP" : "LP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			tune_args.hier_select == HIER_HIGH_PRIORITY ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			"HP" : "LP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			tune_args.code_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		tune_args.code_rate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			as102_fe_get_code_rate(c->code_rate_HP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	/* Set frontend arguments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return state->ops->set_tune(state->priv, &tune_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int as102_fe_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 				 struct dtv_frontend_properties *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	struct as10x_tps tps = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	/* send abilis command: GET_TPS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	ret = state->ops->get_tps(state->priv, &tps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	/* extract constellation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	switch (tps.modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	case CONST_QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		c->modulation = QPSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	case CONST_QAM16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		c->modulation = QAM_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	case CONST_QAM64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		c->modulation = QAM_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	/* extract hierarchy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	switch (tps.hierarchy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	case HIER_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		c->hierarchy = HIERARCHY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	case HIER_ALPHA_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		c->hierarchy = HIERARCHY_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	case HIER_ALPHA_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		c->hierarchy = HIERARCHY_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	case HIER_ALPHA_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		c->hierarchy = HIERARCHY_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	/* extract code rate HP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	switch (tps.code_rate_HP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	case CODE_RATE_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		c->code_rate_HP = FEC_1_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	case CODE_RATE_2_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		c->code_rate_HP = FEC_2_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	case CODE_RATE_3_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		c->code_rate_HP = FEC_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	case CODE_RATE_5_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		c->code_rate_HP = FEC_5_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	case CODE_RATE_7_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		c->code_rate_HP = FEC_7_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	/* extract code rate LP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	switch (tps.code_rate_LP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	case CODE_RATE_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		c->code_rate_LP = FEC_1_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	case CODE_RATE_2_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		c->code_rate_LP = FEC_2_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	case CODE_RATE_3_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		c->code_rate_LP = FEC_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	case CODE_RATE_5_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		c->code_rate_LP = FEC_5_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	case CODE_RATE_7_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		c->code_rate_LP = FEC_7_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	/* extract guard interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	switch (tps.guard_interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	case GUARD_INT_1_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		c->guard_interval = GUARD_INTERVAL_1_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	case GUARD_INT_1_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		c->guard_interval = GUARD_INTERVAL_1_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	case GUARD_INT_1_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		c->guard_interval = GUARD_INTERVAL_1_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	case GUARD_INT_1_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		c->guard_interval = GUARD_INTERVAL_1_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	/* extract transmission mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	switch (tps.transmission_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	case TRANS_MODE_2K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		c->transmission_mode = TRANSMISSION_MODE_2K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	case TRANS_MODE_8K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		c->transmission_mode = TRANSMISSION_MODE_8K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			struct dvb_frontend_tune_settings *settings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	settings->min_delay_ms = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int as102_fe_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	struct as10x_tune_status tstate = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	/* send abilis command: GET_TUNE_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	ret = state->ops->get_status(state->priv, &tstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	state->signal_strength  = tstate.signal_strength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	state->ber  = tstate.BER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	switch (tstate.tune_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	case TUNE_STATUS_SIGNAL_DVB_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	case TUNE_STATUS_STREAM_DETECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			  FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	case TUNE_STATUS_STREAM_TUNED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 			  FE_HAS_LOCK | FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		*status = TUNE_STATUS_NOT_TUNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	pr_debug("as102: tuner status: 0x%02x, strength %d, per: %d, ber: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		 tstate.tune_state, tstate.signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		 tstate.PER, tstate.BER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	if (!(*status & FE_HAS_LOCK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		memset(&state->demod_stats, 0, sizeof(state->demod_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	ret = state->ops->get_stats(state->priv, &state->demod_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		memset(&state->demod_stats, 0, sizeof(state->demod_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)  * - in AS102 SNR=MER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)  *   - the SNR will be returned in linear terms, i.e. not in dB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)  *   - the accuracy equals ±2dB for a SNR range from 4dB to 30dB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)  *   - the accuracy is >2dB for SNR values outside this range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	*snr = state->demod_stats.mer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	*ber = state->ber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int as102_fe_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 					 u16 *strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	*strength = (((0xffff * 400) * state->signal_strength + 41000) * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (state->demod_stats.has_started)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		*ucblocks = state->demod_stats.bad_frame_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		*ucblocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	return state->ops->stream_ctrl(state->priv, acquire,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 				      state->elna_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static void as102_fe_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	struct as102_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static const struct dvb_frontend_ops as102_fe_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	.delsys = { SYS_DVBT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	.info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		.name			= "Abilis AS102 DVB-T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		.frequency_min_hz	= 174 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		.frequency_max_hz	= 862 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		.frequency_stepsize_hz	= 166667,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		.caps = FE_CAN_INVERSION_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			| FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			| FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			| FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			| FE_CAN_QAM_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			| FE_CAN_TRANSMISSION_MODE_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			| FE_CAN_GUARD_INTERVAL_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 			| FE_CAN_HIERARCHY_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			| FE_CAN_RECOVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			| FE_CAN_MUTE_TS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	.set_frontend		= as102_fe_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	.get_frontend		= as102_fe_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	.get_tune_settings	= as102_fe_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	.read_status		= as102_fe_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	.read_snr		= as102_fe_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	.read_ber		= as102_fe_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	.read_signal_strength	= as102_fe_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	.read_ucblocks		= as102_fe_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	.ts_bus_ctrl		= as102_fe_ts_bus_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	.release		= as102_fe_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct dvb_frontend *as102_attach(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 				  const struct as102_fe_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 				  void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 				  uint8_t elna_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	struct as102_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	struct dvb_frontend *fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	fe = &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	fe->demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	state->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	state->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	state->elna_cfg = elna_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	/* init frontend callback ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	strscpy(fe->ops.info.name, name, sizeof(fe->ops.info.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) EXPORT_SYMBOL_GPL(as102_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) MODULE_DESCRIPTION("as102-fe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");