Project

General

Profile

Download (23.5 KB) Statistics
| Branch: | Tag: | Revision:
1 d5c4d1ed Harald Welte
/* (C) 2011-2012 by Harald Welte <laforge@gnumonks.org>
2
 *
3
 * All Rights Reserved
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19 d5be5374 Harald Welte
#include <limits.h>
20
#include <stdint.h>
21
#include <errno.h>
22
#include <string.h>
23
24 2a2c03a7 Harald Welte
#include <reg_field.h>
25 d5be5374 Harald Welte
#include <tuner_e4k.h>
26
27 180193ce Christian Daniel
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
28
29 bab0eb62 Harald Welte
/* If this is defined, the limits are somewhat relaxed compared to what the
30
 * vendor claims is possible */
31
#define OUT_OF_SPEC
32
33 d5be5374 Harald Welte
#define MHZ(x)	((x)*1000*1000)
34
#define KHZ(x)	((x)*1000)
35
36
uint32_t unsigned_delta(uint32_t a, uint32_t b)
37
{
38
	if (a > b)
39
		return a - b;
40
	else
41
		return b - a;
42
}
43
44
/* look-up table bit-width -> mask */
45
static const uint8_t width2mask[] = {
46
	0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
47
};
48
49 180193ce Christian Daniel
/***********************************************************************
50 d5be5374 Harald Welte
 * Register Access */
51
52
#if 0
53
/*! \brief Write a register of the tuner chip
54
 *  \param[in] e4k reference to the tuner
55
 *  \param[in] reg number of the register
56
 *  \param[in] val value to be written
57
 *  \returns 0 on success, negative in case of error
58
 */
59
int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val)
60
{
61
	/* FIXME */
62
	return 0;
63
}
64
65
/*! \brief Read a register of the tuner chip
66
 *  \param[in] e4k reference to the tuner
67
 *  \param[in] reg number of the register
68
 *  \returns positive 8bit register contents on success, negative in case of error
69
 */
70
int e4k_reg_read(struct e4k_state *e4k, uint8_t reg)
71
{
72
	/* FIXME */
73
	return 0;
74
}
75
#endif
76
77
/*! \brief Set or clear some (masked) bits inside a register
78
 *  \param[in] e4k reference to the tuner
79
 *  \param[in] reg number of the register
80
 *  \param[in] mask bit-mask of the value
81
 *  \param[in] val data value to be written to register
82
 *  \returns 0 on success, negative in case of error
83
 */
84
static int e4k_reg_set_mask(struct e4k_state *e4k, uint8_t reg,
85
		     uint8_t mask, uint8_t val)
86
{
87
	uint8_t tmp = e4k_reg_read(e4k, reg);
88
89
	if ((tmp & mask) == val)
90
		return 0;
91
92
	return e4k_reg_write(e4k, reg, (tmp & ~mask) | (val & mask));
93
}
94
95
/*! \brief Write a given field inside a register
96
 *  \param[in] e4k reference to the tuner
97
 *  \param[in] field structure describing the field
98
 *  \param[in] val value to be written
99
 *  \returns 0 on success, negative in case of error
100
 */
101
static int e4k_field_write(struct e4k_state *e4k, const struct reg_field *field, uint8_t val)
102
{
103
	int rc;
104
	uint8_t mask;
105
106
	rc = e4k_reg_read(e4k, field->reg);
107
	if (rc < 0)
108
		return rc;
109
110
	mask = width2mask[field->width] << field->shift;
111
112
	return e4k_reg_set_mask(e4k, field->reg, mask, val << field->shift);
113
}
114
115
/*! \brief Read a given field inside a register
116
 *  \param[in] e4k reference to the tuner
117
 *  \param[in] field structure describing the field
118
 *  \returns positive value of the field, negative in case of error
119
 */
120
static int e4k_field_read(struct e4k_state *e4k, const struct reg_field *field)
121
{
122
	int rc;
123
124
	rc = e4k_reg_read(e4k, field->reg);
125
	if (rc < 0)
126
		return rc;
127
128
	rc = (rc >> field->shift) & width2mask[field->width];
129
130
	return rc;
131
}
132
133 180193ce Christian Daniel
/***********************************************************************
134 d5be5374 Harald Welte
 * Filter Control */
135
136
static const uint32_t rf_filt_center_uhf[] = {
137
	MHZ(360), MHZ(380), MHZ(405), MHZ(425),
138
	MHZ(450), MHZ(475), MHZ(505), MHZ(540),
139
	MHZ(575), MHZ(615), MHZ(670), MHZ(720),
140
	MHZ(760), MHZ(840), MHZ(890), MHZ(970)
141
};
142
143
static const uint32_t rf_filt_center_l[] = {
144
	MHZ(1300), MHZ(1320), MHZ(1360), MHZ(1410),
145
	MHZ(1445), MHZ(1460), MHZ(1490), MHZ(1530),
146
	MHZ(1560), MHZ(1590), MHZ(1640), MHZ(1660),
147
	MHZ(1680), MHZ(1700), MHZ(1720), MHZ(1750)
148
};
149
150
static int closest_arr_idx(const uint32_t *arr, unsigned int arr_size, uint32_t freq)
151
{
152 180193ce Christian Daniel
	unsigned int i, bi = 0;
153 60d88b6e Sylvain Munaut
	uint32_t best_delta = 0xffffffff;
154 d5be5374 Harald Welte
155 60d88b6e Sylvain Munaut
	/* iterate over the array containing a list of the center
156 d5be5374 Harald Welte
	 * frequencies, selecting the closest one */
157
	for (i = 0; i < arr_size; i++) {
158
		uint32_t delta = unsigned_delta(freq, arr[i]);
159 60d88b6e Sylvain Munaut
		if (delta < best_delta) {
160
			best_delta = delta;
161
			bi = i;
162
		}
163 d5be5374 Harald Welte
	}
164
165 60d88b6e Sylvain Munaut
	return bi;
166 d5be5374 Harald Welte
}
167
168
/* return 4-bit index as to which RF filter to select */
169
static int choose_rf_filter(enum e4k_band band, uint32_t freq)
170
{
171
	int rc;
172
173
	switch (band) {
174 180193ce Christian Daniel
		case E4K_BAND_VHF2:
175
		case E4K_BAND_VHF3:
176 d5be5374 Harald Welte
			rc = 0;
177 180193ce Christian Daniel
			break;
178
		case E4K_BAND_UHF:
179
			rc = closest_arr_idx(rf_filt_center_uhf,
180
						 ARRAY_SIZE(rf_filt_center_uhf),
181
						 freq);
182
			break;
183
		case E4K_BAND_L:
184
			rc = closest_arr_idx(rf_filt_center_l,
185
						 ARRAY_SIZE(rf_filt_center_l),
186
						 freq);
187
			break;
188
		default:
189
			rc = -EINVAL;
190
			break;
191 d5be5374 Harald Welte
	}
192
193
	return rc;
194
}
195
196
/* \brief Automatically select apropriate RF filter based on e4k state */
197
int e4k_rf_filter_set(struct e4k_state *e4k)
198
{
199
	int rc;
200
201
	rc = choose_rf_filter(e4k->band, e4k->vco.flo);
202
	if (rc < 0)
203
		return rc;
204
205
	return e4k_reg_set_mask(e4k, E4K_REG_FILT1, 0xF, rc);
206
}
207
208
/* Mixer Filter */
209
static const uint32_t mix_filter_bw[] = {
210
	KHZ(27000), KHZ(27000), KHZ(27000), KHZ(27000),
211
	KHZ(27000), KHZ(27000), KHZ(27000), KHZ(27000),
212
	KHZ(4600), KHZ(4200), KHZ(3800), KHZ(3400),
213
	KHZ(3300), KHZ(2700), KHZ(2300), KHZ(1900)
214
};
215
216
/* IF RC Filter */
217
static const uint32_t ifrc_filter_bw[] = {
218
	KHZ(21400), KHZ(21000), KHZ(17600), KHZ(14700),
219
	KHZ(12400), KHZ(10600), KHZ(9000), KHZ(7700),
220
	KHZ(6400), KHZ(5300), KHZ(4400), KHZ(3400),
221
	KHZ(2600), KHZ(1800), KHZ(1200), KHZ(1000)
222
};
223
224
/* IF Channel Filter */
225
static const uint32_t ifch_filter_bw[] = {
226
	KHZ(5500), KHZ(5300), KHZ(5000), KHZ(4800),
227
	KHZ(4600), KHZ(4400), KHZ(4300), KHZ(4100),
228
	KHZ(3900), KHZ(3800), KHZ(3700), KHZ(3600),
229
	KHZ(3400), KHZ(3300), KHZ(3200), KHZ(3100),
230
	KHZ(3000), KHZ(2950), KHZ(2900), KHZ(2800),
231
	KHZ(2750), KHZ(2700), KHZ(2600), KHZ(2550),
232
	KHZ(2500), KHZ(2450), KHZ(2400), KHZ(2300),
233
	KHZ(2280), KHZ(2240), KHZ(2200), KHZ(2150)
234
};
235
236
static const uint32_t *if_filter_bw[] = {
237 180193ce Christian Daniel
	mix_filter_bw,
238
	ifch_filter_bw,
239
	ifrc_filter_bw,
240 d5be5374 Harald Welte
};
241
242
static const uint32_t if_filter_bw_len[] = {
243 180193ce Christian Daniel
	ARRAY_SIZE(mix_filter_bw),
244
	ARRAY_SIZE(ifch_filter_bw),
245
	ARRAY_SIZE(ifrc_filter_bw),
246 d5be5374 Harald Welte
};
247
248
static const struct reg_field if_filter_fields[] = {
249 180193ce Christian Daniel
	{
250
		E4K_REG_FILT2, 4, 4,
251 d5be5374 Harald Welte
	},
252 180193ce Christian Daniel
	{
253
		E4K_REG_FILT3, 0, 5,
254 d5be5374 Harald Welte
	},
255 180193ce Christian Daniel
	{
256
		E4K_REG_FILT2, 0, 4,
257 d5be5374 Harald Welte
	}
258
};
259
260
static int find_if_bw(enum e4k_if_filter filter, uint32_t bw)
261
{
262
	if (filter >= ARRAY_SIZE(if_filter_bw))
263
		return -EINVAL;
264
265
	return closest_arr_idx(if_filter_bw[filter],
266
			       if_filter_bw_len[filter], bw);
267
}
268
269
/*! \brief Set the filter band-width of any of the IF filters
270
 *  \param[in] e4k reference to the tuner chip
271
 *  \param[in] filter filter to be configured
272
 *  \param[in] bandwidth bandwidth to be configured
273
 *  \returns positive actual filter band-width, negative in case of error
274
 */
275
int e4k_if_filter_bw_set(struct e4k_state *e4k, enum e4k_if_filter filter,
276
		         uint32_t bandwidth)
277
{
278
	int bw_idx;
279
	const struct reg_field *field;
280
281
	if (filter >= ARRAY_SIZE(if_filter_bw))
282
		return -EINVAL;
283
284
	bw_idx = find_if_bw(filter, bandwidth);
285
286
	field = &if_filter_fields[filter];
287
288
	return e4k_field_write(e4k, field, bw_idx);
289
}
290
291 088d5312 Sylvain Munaut
/*! \brief Enables / Disables the channel filter
292
 *  \param[in] e4k reference to the tuner chip
293
 *  \param[in] on 1=filter enabled, 0=filter disabled
294
 *  \returns 0 success, negative errors
295
 */
296
int e4k_if_filter_chan_enable(struct e4k_state *e4k, int on)
297
{
298
	return e4k_reg_set_mask(e4k, E4K_REG_FILT3, E4K_FILT3_DISABLE,
299
	                        on ? 0 : E4K_FILT3_DISABLE);
300
}
301
302 d5be5374 Harald Welte
int e4k_if_filter_bw_get(struct e4k_state *e4k, enum e4k_if_filter filter)
303
{
304
	const uint32_t *arr;
305
	int rc;
306
	const struct reg_field *field;
307
308
	if (filter >= ARRAY_SIZE(if_filter_bw))
309
		return -EINVAL;
310
311
	field = &if_filter_fields[filter];
312
313
	rc = e4k_field_read(e4k, field);
314
	if (rc < 0)
315
		return rc;
316
317
	arr = if_filter_bw[filter];
318
319
	return arr[rc];
320
}
321
322
323 180193ce Christian Daniel
/***********************************************************************
324 d5be5374 Harald Welte
 * Frequency Control */
325
326
#define E4K_FVCO_MIN_KHZ	2600000	/* 2.6 GHz */
327 585c6d37 Sylvain Munaut
#define E4K_FVCO_MAX_KHZ	3900000	/* 3.9 GHz */
328 31d11c2b Harald Welte
#define E4K_PLL_Y		65536
329 d5be5374 Harald Welte
330 bab0eb62 Harald Welte
#ifdef OUT_OF_SPEC
331
#define E4K_FLO_MIN_MHZ		50
332 180193ce Christian Daniel
#define E4K_FLO_MAX_MHZ		2200UL
333 bab0eb62 Harald Welte
#else
334
#define E4K_FLO_MIN_MHZ		64
335
#define E4K_FLO_MAX_MHZ		1700
336
#endif
337
338 180193ce Christian Daniel
struct pll_settings {
339
	uint32_t freq;
340
	uint8_t reg_synth7;
341
	uint8_t mult;
342
};
343
344
static const struct pll_settings pll_vars[] = {
345
	{KHZ(72400),	(1 << 3) | 7,	48},
346
	{KHZ(81200),	(1 << 3) | 6,	40},
347
	{KHZ(108300),	(1 << 3) | 5,	32},
348
	{KHZ(162500),	(1 << 3) | 4,	24},
349
	{KHZ(216600),	(1 << 3) | 3,	16},
350
	{KHZ(325000),	(1 << 3) | 2,	12},
351
	{KHZ(350000),	(1 << 3) | 1,	8},
352
	{KHZ(432000),	(0 << 3) | 3,	8},
353
	{KHZ(667000),	(0 << 3) | 2,	6},
354
	{KHZ(1200000),	(0 << 3) | 1,	4}
355 d5be5374 Harald Welte
};
356
357
static int is_fvco_valid(uint32_t fvco_z)
358
{
359
	/* check if the resulting fosc is valid */
360
	if (fvco_z/1000 < E4K_FVCO_MIN_KHZ ||
361
	    fvco_z/1000 > E4K_FVCO_MAX_KHZ) {
362 180193ce Christian Daniel
		printf("Fvco %u invalid\n\r", fvco_z);
363 d5be5374 Harald Welte
		return 0;
364
	}
365
366
	return 1;
367
}
368
369
static int is_fosc_valid(uint32_t fosc)
370
{
371
	if (fosc < MHZ(16) || fosc > MHZ(30)) {
372 180193ce Christian Daniel
		printf("Fosc %u invalid\n\r", fosc);
373 d5be5374 Harald Welte
		return 0;
374
	}
375
376
	return 1;
377
}
378
379
static int is_z_valid(uint32_t z)
380
{
381
	if (z > 255) {
382 180193ce Christian Daniel
		printf("Z %u invalid\n\r", z);
383 d5be5374 Harald Welte
		return 0;
384
	}
385
386
	return 1;
387
}
388
389
/*! \brief Determine if 3-phase mixing shall be used or not */
390
static int use_3ph_mixing(uint32_t flo)
391
{
392
	/* this is a magic number somewhre between VHF and UHF */
393 180193ce Christian Daniel
	if (flo < MHZ(350))
394 d5be5374 Harald Welte
		return 1;
395
396
	return 0;
397
}
398
399
/* \brief compute Fvco based on Fosc, Z and X
400
 * \returns positive value (Fvco in Hz), 0 in case of error */
401 180193ce Christian Daniel
static uint64_t compute_fvco(uint32_t f_osc, uint8_t z, uint16_t x)
402 d5be5374 Harald Welte
{
403
	uint64_t fvco_z, fvco_x, fvco;
404
405
	/* We use the following transformation in order to
406
	 * handle the fractional part with integer arithmetic:
407
	 *  Fvco = Fosc * (Z + X/Y) <=> Fvco = Fosc * Z + (Fosc * X)/Y
408
	 * This avoids X/Y = 0.  However, then we would overflow a 32bit
409 31188544 Sylvain Munaut
	 * integer, as we cannot hold e.g. 26 MHz * 65536 either.
410 d5be5374 Harald Welte
	 */
411
	fvco_z = (uint64_t)f_osc * z;
412
413 180193ce Christian Daniel
#if 0
414 d5be5374 Harald Welte
	if (!is_fvco_valid(fvco_z))
415
		return 0;
416 180193ce Christian Daniel
#endif
417 d5be5374 Harald Welte
418
	fvco_x = ((uint64_t)f_osc * x) / E4K_PLL_Y;
419
420
	fvco = fvco_z + fvco_x;
421
422
	return fvco;
423
}
424
425 180193ce Christian Daniel
static uint32_t compute_flo(uint32_t f_osc, uint8_t z, uint16_t x, uint8_t r)
426 d5be5374 Harald Welte
{
427 180193ce Christian Daniel
	uint64_t fvco = compute_fvco(f_osc, z, x);
428 d5be5374 Harald Welte
	if (fvco == 0)
429
		return -EINVAL;
430
431
	return fvco / r;
432
}
433
434
static int e4k_band_set(struct e4k_state *e4k, enum e4k_band band)
435
{
436
	int rc;
437
438
	switch (band) {
439
	case E4K_BAND_VHF2:
440
	case E4K_BAND_VHF3:
441
	case E4K_BAND_UHF:
442
		e4k_reg_write(e4k, E4K_REG_BIAS, 3);
443
		break;
444
	case E4K_BAND_L:
445
		e4k_reg_write(e4k, E4K_REG_BIAS, 0);
446
		break;
447
	}
448 dda6e9c4 Christian Daniel
	/* workaround: if we don't reset this register before writing to it,
449
	 * we get a gap between 325-350 MHz */
450
	rc = e4k_reg_set_mask(e4k, E4K_REG_SYNTH1, 0x06, 0);
451 bdb4f8e5 Sylvain Munaut
	rc = e4k_reg_set_mask(e4k, E4K_REG_SYNTH1, 0x06, band << 1);
452 d5be5374 Harald Welte
	if (rc >= 0)
453
		e4k->band = band;
454
455
	return rc;
456
}
457
458
/*! \brief Compute PLL parameters for givent target frequency
459
 *  \param[out] oscp Oscillator parameters, if computation successful
460
 *  \param[in] fosc Clock input frequency applied to the chip (Hz)
461
 *  \param[in] intended_flo target tuning frequency (Hz)
462
 *  \returns actual PLL frequency, as close as possible to intended_flo,
463 180193ce Christian Daniel
 *	     0 in case of error
464 d5be5374 Harald Welte
 */
465 180193ce Christian Daniel
uint32_t e4k_compute_pll_params(struct e4k_pll_params *oscp, uint32_t fosc, uint32_t intended_flo)
466 d5be5374 Harald Welte
{
467 180193ce Christian Daniel
	uint32_t i;
468
	uint8_t r = 2;
469
	uint64_t intended_fvco, remainder;
470
	uint64_t z = 0;
471
	uint32_t x;
472
	int flo;
473
	int three_phase_mixing = 0;
474
	oscp->r_idx = 0;
475 d5be5374 Harald Welte
476
	if (!is_fosc_valid(fosc))
477 180193ce Christian Daniel
		return 0;
478 d5be5374 Harald Welte
479 180193ce Christian Daniel
	for(i = 0; i < ARRAY_SIZE(pll_vars); ++i) {
480
		if(intended_flo < pll_vars[i].freq) {
481
			three_phase_mixing = (pll_vars[i].reg_synth7 & 0x08) ? 1 : 0;
482
			oscp->r_idx = pll_vars[i].reg_synth7;
483
			r = pll_vars[i].mult;
484
			break;
485
		}
486
	}
487 d5be5374 Harald Welte
488 180193ce Christian Daniel
	printf("Fint=%u, R=%u\n\r", intended_flo, r);
489 d5be5374 Harald Welte
490 180193ce Christian Daniel
	/* flo(max) = 1700MHz, R(max) = 48, we need 64bit! */
491
	intended_fvco = (uint64_t)intended_flo * r;
492 d5be5374 Harald Welte
493 180193ce Christian Daniel
	/* compute integral component of multiplier */
494
	z = intended_fvco / fosc;
495 d5be5374 Harald Welte
496 180193ce Christian Daniel
	/* compute fractional part.  this will not overflow,
497
	* as fosc(max) = 30MHz and z(max) = 255 */
498
	remainder = intended_fvco - (fosc * z);
499
	/* remainder(max) = 30MHz, E4K_PLL_Y = 65536 -> 64bit! */
500
	x = (remainder * E4K_PLL_Y) / fosc;
501
	/* x(max) as result of this computation is 65536 */
502 d5be5374 Harald Welte
503 180193ce Christian Daniel
	flo = compute_flo(fosc, z, x, r);
504 d5be5374 Harald Welte
505 180193ce Christian Daniel
	oscp->fosc = fosc;
506
	oscp->flo = flo;
507
	oscp->intended_flo = intended_flo;
508
	oscp->r = r;
509
//	oscp->r_idx = pll_vars[i].reg_synth7 & 0x0;
510
	oscp->threephase = three_phase_mixing;
511
	oscp->x = x;
512
	oscp->z = z;
513
514
	return flo;
515 d5be5374 Harald Welte
}
516
517
int e4k_tune_params(struct e4k_state *e4k, struct e4k_pll_params *p)
518
{
519
	uint8_t val;
520
521 180193ce Christian Daniel
	/* program R + 3phase/2phase */
522
	e4k_reg_write(e4k, E4K_REG_SYNTH7, p->r_idx);
523 d5be5374 Harald Welte
	/* program Z */
524
	e4k_reg_write(e4k, E4K_REG_SYNTH3, p->z);
525
	/* program X */
526
	e4k_reg_write(e4k, E4K_REG_SYNTH4, p->x & 0xff);
527
	e4k_reg_write(e4k, E4K_REG_SYNTH5, p->x >> 8);
528
529
	/* we're in auto calibration mode, so there's no need to trigger it */
530
531
	memcpy(&e4k->vco, p, sizeof(e4k->vco));
532
533
	/* set the band */
534 180193ce Christian Daniel
	if (e4k->vco.flo < MHZ(140))
535 975c9813 Sylvain Munaut
		e4k_band_set(e4k, E4K_BAND_VHF2);
536
	else if (e4k->vco.flo < MHZ(350))
537
		e4k_band_set(e4k, E4K_BAND_VHF3);
538
	else if (e4k->vco.flo < MHZ(1135))
539
		e4k_band_set(e4k, E4K_BAND_UHF);
540
	else
541
		e4k_band_set(e4k, E4K_BAND_L);
542 d5be5374 Harald Welte
543
	/* select and set proper RF filter */
544
	e4k_rf_filter_set(e4k);
545
546
	return e4k->vco.flo;
547
}
548
549
/*! \brief High-level tuning API, just specify frquency
550
 *
551
 *  This function will compute matching PLL parameters, program them into the
552
 *  hardware and set the band as well as RF filter.
553
 *
554
 *  \param[in] e4k reference to tuner
555
 *  \param[in] freq frequency in Hz
556
 *  \returns actual tuned frequency, negative in case of error
557
 */
558
int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq)
559
{
560 180193ce Christian Daniel
	uint32_t rc;
561 d5be5374 Harald Welte
	struct e4k_pll_params p;
562
563
	/* determine PLL parameters */
564
	rc = e4k_compute_pll_params(&p, e4k->vco.fosc, freq);
565 180193ce Christian Daniel
	if (!rc)
566
		return -EINVAL;
567 d5be5374 Harald Welte
568
	/* actually tune to those parameters */
569 180193ce Christian Daniel
	rc = e4k_tune_params(e4k, &p);
570
571
	/* check PLL lock */
572
	rc = e4k_reg_read(e4k, E4K_REG_SYNTH1);
573
	if (!(rc & 0x01)) {
574
		printf("[E4K] PLL not locked!\n\r");
575
		return -1;
576
	}
577
578
	return 0;
579 d5be5374 Harald Welte
}
580
581 180193ce Christian Daniel
/***********************************************************************
582 d5be5374 Harald Welte
 * Gain Control */
583
584
static const int8_t if_stage1_gain[] = {
585
	-3, 6
586
};
587
588
static const int8_t if_stage23_gain[] = {
589
	0, 3, 6, 9
590
};
591
592
static const int8_t if_stage4_gain[] = {
593
	0, 1, 2, 2
594
};
595
596
static const int8_t if_stage56_gain[] = {
597
	3, 6, 9, 12, 15, 15, 15, 15
598
};
599
600
static const int8_t *if_stage_gain[] = {
601 180193ce Christian Daniel
	0,
602
	if_stage1_gain,
603
	if_stage23_gain,
604
	if_stage23_gain,
605
	if_stage4_gain,
606
	if_stage56_gain,
607
	if_stage56_gain
608 d5be5374 Harald Welte
};
609
610
static const uint8_t if_stage_gain_len[] = {
611 180193ce Christian Daniel
	0,
612
	ARRAY_SIZE(if_stage1_gain),
613
	ARRAY_SIZE(if_stage23_gain),
614
	ARRAY_SIZE(if_stage23_gain),
615
	ARRAY_SIZE(if_stage4_gain),
616
	ARRAY_SIZE(if_stage56_gain),
617
	ARRAY_SIZE(if_stage56_gain)
618 d5be5374 Harald Welte
};
619
620
static const struct reg_field if_stage_gain_regs[] = {
621 180193ce Christian Daniel
	{ 0, 0, 0 },
622
	{ E4K_REG_GAIN3, 0, 1 },
623
	{ E4K_REG_GAIN3, 1, 2 },
624
	{ E4K_REG_GAIN3, 3, 2 },
625
	{ E4K_REG_GAIN3, 5, 2 },
626
	{ E4K_REG_GAIN4, 0, 3 },
627
	{ E4K_REG_GAIN4, 3, 3 }
628
};
629
630
static const int32_t lnagain[] = {
631
	-50,	0,
632
	-25,	1,
633
	0,	4,
634
	25,	5,
635
	50,	6,
636
	75,	7,
637
	100,	8,
638
	125,	9,
639
	150,	10,
640
	175,	11,
641
	200,	12,
642
	250,	13,
643
	300,	14,
644 d5be5374 Harald Welte
};
645
646 180193ce Christian Daniel
static const int32_t enhgain[] = {
647
	10, 30, 50, 70
648
};
649
650
int e4k_set_lna_gain(struct e4k_state *e4k, int32_t gain)
651
{
652
	uint32_t i;
653
	for(i = 0; i < ARRAY_SIZE(lnagain)/2; ++i) {
654
		if(lnagain[i*2] == gain) {
655
			e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, lnagain[i*2+1]);
656
			return gain;
657
		}
658
	}
659
	return -EINVAL;
660
}
661
662
int e4k_set_enh_gain(struct e4k_state *e4k, int32_t gain)
663
{
664
	uint32_t i;
665
	for(i = 0; i < ARRAY_SIZE(enhgain); ++i) {
666
		if(enhgain[i] == gain) {
667
			e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, E4K_AGC11_LNA_GAIN_ENH | (i << 1));
668
			return gain;
669
		}
670
	}
671
	e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, 0);
672
673
	/* special case: 0 = off*/
674
	if(0 == gain)
675
		return 0;
676
	else
677
		return -EINVAL;
678
}
679
680
int e4k_enable_manual_gain(struct e4k_state *e4k, uint8_t manual)
681
{
682
	if (manual) {
683
		/* Set LNA mode to manual */
684
		e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, E4K_AGC_MOD_SERIAL);
685
686
		/* Set Mixer Gain Control to manual */
687
		e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0);
688
	} else {
689
		/* Set LNA mode to auto */
690
		e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, E4K_AGC_MOD_IF_SERIAL_LNA_AUTON);
691
		/* Set Mixer Gain Control to auto */
692
		e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 1);
693
694
		e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, 0);
695
	}
696
697
	return 0;
698
}
699
700 d5be5374 Harald Welte
static int find_stage_gain(uint8_t stage, int8_t val)
701
{
702
	const int8_t *arr;
703
	int i;
704
705
	if (stage >= ARRAY_SIZE(if_stage_gain))
706
		return -EINVAL;
707
708
	arr = if_stage_gain[stage];
709
710
	for (i = 0; i < if_stage_gain_len[stage]; i++) {
711
		if (arr[i] == val)
712
			return i;
713
	}
714
	return -EINVAL;
715
}
716
717
/*! \brief Set the gain of one of the IF gain stages
718
 *  \param[e4k] handle to the tuner chip
719
 *  \param [stage] numbere of the stage (1..6)
720
 *  \param [value] gain value in dBm
721
 *  \returns 0 on success, negative in case of error
722
 */
723
int e4k_if_gain_set(struct e4k_state *e4k, uint8_t stage, int8_t value)
724
{
725
	int rc;
726
	uint8_t mask;
727
	const struct reg_field *field;
728
729
	rc = find_stage_gain(stage, value);
730
	if (rc < 0)
731
		return rc;
732
733
	/* compute the bit-mask for the given gain field */
734
	field = &if_stage_gain_regs[stage];
735
	mask = width2mask[field->width] << field->shift;
736
737
	return e4k_reg_set_mask(e4k, field->reg, mask, rc << field->shift);
738
}
739
740 9ce29d79 Harald Welte
int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value)
741
{
742
	uint8_t bit;
743
744
	switch (value) {
745 0bcf409c Sylvain Munaut
	case 4:
746 9ce29d79 Harald Welte
		bit = 0;
747
		break;
748
	case 12:
749
		bit = 1;
750
		break;
751
	default:
752
		return -EINVAL;
753
	}
754
755
	return e4k_reg_set_mask(e4k, E4K_REG_GAIN2, 1, bit);
756
}
757
758 463a3f9c Christian Daniel
int e4k_commonmode_set(struct e4k_state *e4k, int8_t value)
759
{
760
	if(value < 0)
761
		return -EINVAL;
762
	else if(value > 7)
763
		return -EINVAL;
764
765
	return e4k_reg_set_mask(e4k, E4K_REG_DC7, 7, value);
766
}
767
768 180193ce Christian Daniel
/***********************************************************************
769 c4c7c6ad Harald Welte
 * DC Offset */
770
771 4683c1c2 Christian Daniel
int e4k_manual_dc_offset(struct e4k_state *e4k, int8_t iofs, int8_t irange, int8_t qofs, int8_t qrange)
772
{
773
	int res;
774
775
	if((iofs < 0x00) || (iofs > 0x3f))
776
		return -EINVAL;
777
	if((irange < 0x00) || (irange > 0x03))
778
		return -EINVAL;
779
	if((qofs < 0x00) || (qofs > 0x3f))
780
		return -EINVAL;
781
	if((qrange < 0x00) || (qrange > 0x03))
782
		return -EINVAL;
783
784
	res = e4k_reg_set_mask(e4k, E4K_REG_DC2, 0x3f, iofs);
785
	if(res < 0)
786
		return res;
787
788
	res = e4k_reg_set_mask(e4k, E4K_REG_DC3, 0x3f, qofs);
789
	if(res < 0)
790
		return res;
791
792
	res = e4k_reg_set_mask(e4k, E4K_REG_DC4, 0x33, (qrange << 4) | irange);
793
	return res;
794
}
795
796 c4c7c6ad Harald Welte
/*! \brief Perform a DC offset calibration right now
797
 *  \param[e4k] handle to the tuner chip
798
 */
799
int e4k_dc_offset_calibrate(struct e4k_state *e4k)
800
{
801
	/* make sure the DC range detector is enabled */
802
	e4k_reg_set_mask(e4k, E4K_REG_DC5, E4K_DC5_RANGE_DET_EN, E4K_DC5_RANGE_DET_EN);
803
804
	return e4k_reg_write(e4k, E4K_REG_DC1, 0x01);
805
}
806
807
808
static const int8_t if_gains_max[] = {
809
	0, 6, 9, 9, 2, 15, 15
810
};
811
812
struct gain_comb {
813
	int8_t mixer_gain;
814 a99f1b53 Sylvain Munaut
	int8_t if1_gain;
815 c4c7c6ad Harald Welte
	uint8_t reg;
816
};
817
818
static const struct gain_comb dc_gain_comb[] = {
819 180193ce Christian Daniel
	{ 4,  -3, 0x50 },
820
	{ 4,   6, 0x51 },
821 c4c7c6ad Harald Welte
	{ 12, -3, 0x52 },
822 180193ce Christian Daniel
	{ 12,  6, 0x53 },
823 c4c7c6ad Harald Welte
};
824
825
#define TO_LUT(offset, range)	(offset | (range << 6))
826
827
int e4k_dc_offset_gen_table(struct e4k_state *e4k)
828
{
829 180193ce Christian Daniel
	uint32_t i;
830 c4c7c6ad Harald Welte
831
	/* FIXME: read ont current gain values and write them back
832
	 * before returning to the caller */
833
834 6593b2be Sylvain Munaut
	/* disable auto mixer gain */
835
	e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0);
836
837
	/* set LNA/IF gain to full manual */
838
	e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK,
839
			 E4K_AGC_MOD_SERIAL);
840
841 c4c7c6ad Harald Welte
	/* set all 'other' gains to maximum */
842
	for (i = 2; i <= 6; i++)
843
		e4k_if_gain_set(e4k, i, if_gains_max[i]);
844
845
	/* iterate over all mixer + if_stage_1 gain combinations */
846
	for (i = 0; i < ARRAY_SIZE(dc_gain_comb); i++) {
847 f1939647 Sylvain Munaut
		uint8_t offs_i, offs_q, range, range_i, range_q;
848 c4c7c6ad Harald Welte
849
		/* set the combination of mixer / if1 gain */
850 9ce29d79 Harald Welte
		e4k_mixer_gain_set(e4k, dc_gain_comb[i].mixer_gain);
851 c4c7c6ad Harald Welte
		e4k_if_gain_set(e4k, 1, dc_gain_comb[i].if1_gain);
852
853
		/* perform actual calibration */
854
		e4k_dc_offset_calibrate(e4k);
855
856
		/* extract I/Q offset and range values */
857 180193ce Christian Daniel
		offs_i = e4k_reg_read(e4k, E4K_REG_DC2) & 0x3f;
858
		offs_q = e4k_reg_read(e4k, E4K_REG_DC3) & 0x3f;
859 f1939647 Sylvain Munaut
		range  = e4k_reg_read(e4k, E4K_REG_DC4);
860
		range_i = range & 0x3;
861
		range_q = (range >> 4) & 0x3;
862 180193ce Christian Daniel
/*
863
		fprintf(stderr, "Table %u I=%u/%u, Q=%u/%u\n",
864 9ce29d79 Harald Welte
			i, range_i, offs_i, range_q, offs_q);
865 180193ce Christian Daniel
*/
866 c4c7c6ad Harald Welte
		/* write into the table */
867
		e4k_reg_write(e4k, dc_gain_comb[i].reg,
868
			      TO_LUT(offs_q, range_q));
869 180193ce Christian Daniel
		e4k_reg_write(e4k, dc_gain_comb[i].reg + 0x10,
870 c4c7c6ad Harald Welte
			      TO_LUT(offs_i, range_i));
871
	}
872
873
	return 0;
874
}
875
876 180193ce Christian Daniel
/***********************************************************************
877 d5be5374 Harald Welte
 * Initialization */
878
879
static int magic_init(struct e4k_state *e4k)
880
{
881
	e4k_reg_write(e4k, 0x7e, 0x01);
882
	e4k_reg_write(e4k, 0x7f, 0xfe);
883 ca53c221 Sylvain Munaut
	e4k_reg_write(e4k, 0x82, 0x00);
884 d5be5374 Harald Welte
	e4k_reg_write(e4k, 0x86, 0x50);	/* polarity A */
885
	e4k_reg_write(e4k, 0x87, 0x20);
886
	e4k_reg_write(e4k, 0x88, 0x01);
887
	e4k_reg_write(e4k, 0x9f, 0x7f);
888
	e4k_reg_write(e4k, 0xa0, 0x07);
889 c4c7c6ad Harald Welte
890
	return 0;
891 d5be5374 Harald Welte
}
892
893
/*! \brief Initialize the E4K tuner
894
 */
895
int e4k_init(struct e4k_state *e4k)
896
{
897
	/* make a dummy i2c read or write command, will not be ACKed! */
898
	e4k_reg_read(e4k, 0);
899
900 180193ce Christian Daniel
	/* Make sure we reset everything and clear POR indicator */
901
	e4k_reg_write(e4k, E4K_REG_MASTER1,
902
		E4K_MASTER1_RESET |
903
		E4K_MASTER1_NORM_STBY |
904
		E4K_MASTER1_POR_DET
905
	);
906
907
	/* Configure clock input */
908
	e4k_reg_write(e4k, E4K_REG_CLK_INP, 0x00);
909
910
	/* Disable clock output */
911
	e4k_reg_write(e4k, E4K_REG_REF_CLK, 0x00);
912
	e4k_reg_write(e4k, E4K_REG_CLKOUT_PWDN, 0x96);
913
914
	/* Write some magic values into registers */
915 d5be5374 Harald Welte
	magic_init(e4k);
916 180193ce Christian Daniel
#if 0
917
	/* Set common mode voltage a bit higher for more margin 850 mv */
918
	e4k_commonmode_set(e4k, 4);
919
920
	/* Initialize DC offset lookup tables */
921
	e4k_dc_offset_gen_table(e4k);
922
923
	/* Enable time variant DC correction */
924
	e4k_reg_write(e4k, E4K_REG_DCTIME1, 0x01);
925
	e4k_reg_write(e4k, E4K_REG_DCTIME2, 0x01);
926
#endif
927
928
	/* Set LNA mode to manual */
929
	e4k_reg_write(e4k, E4K_REG_AGC4, 0x10); /* High threshold */
930
	e4k_reg_write(e4k, E4K_REG_AGC5, 0x04);	/* Low threshold */
931
	e4k_reg_write(e4k, E4K_REG_AGC6, 0x1a);	/* LNA calib + loop rate */
932 d5be5374 Harald Welte
933
	e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK,
934 180193ce Christian Daniel
		E4K_AGC_MOD_SERIAL);
935 d5be5374 Harald Welte
936 180193ce Christian Daniel
	/* Set Mixer Gain Control to manual */
937
	e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0);
938 d5be5374 Harald Welte
939 180193ce Christian Daniel
#if 0
940 d5be5374 Harald Welte
	/* Enable LNA Gain enhancement */
941
	e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7,
942
			 E4K_AGC11_LNA_GAIN_ENH | (2 << 1));
943
944
	/* Enable automatic IF gain mode switching */
945
	e4k_reg_set_mask(e4k, E4K_REG_AGC8, 0x1, E4K_AGC8_SENS_LIN_AUTO);
946 180193ce Christian Daniel
#endif
947 d5be5374 Harald Welte
948 180193ce Christian Daniel
	/* Use auto-gain as default */
949
	e4k_enable_manual_gain(e4k, 0);
950 d5be5374 Harald Welte
951 180193ce Christian Daniel
	/* Select moderate gain levels */
952
	e4k_if_gain_set(e4k, 1, 6);
953
	e4k_if_gain_set(e4k, 2, 0);
954
	e4k_if_gain_set(e4k, 3, 0);
955
	e4k_if_gain_set(e4k, 4, 0);
956
	e4k_if_gain_set(e4k, 5, 9);
957
	e4k_if_gain_set(e4k, 6, 9);
958 d5be5374 Harald Welte
959 cc42e4df Harald Welte
	/* Set the most narrow filter we can possibly use */
960
	e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_MIX, KHZ(1900));
961
	e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_RC, KHZ(1000));
962
	e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_CHAN, KHZ(2150));
963 180193ce Christian Daniel
	e4k_if_filter_chan_enable(e4k, 1);
964
965
	/* Disable time variant DC correction and LUT */
966
	e4k_reg_set_mask(e4k, E4K_REG_DC5, 0x03, 0);
967
	e4k_reg_set_mask(e4k, E4K_REG_DCTIME1, 0x03, 0);
968
	e4k_reg_set_mask(e4k, E4K_REG_DCTIME2, 0x03, 0);
969
970
	return 0;
971 d5be5374 Harald Welte
}
972 b93708ed Christian Daniel
973
int e4k_dump(struct e4k_state *e4k)
974
{
975
	int i;
976
977
	for(i = 0; i < 64; i++)
978
		printf("0x%02x: 0x%02x    0x%02x: 0x%02x    0x%02x: 0x%02x    0x%02x: 0x%02x\n\r",
979
			i, e4k_reg_read(e4k, i),
980
			i + 64, e4k_reg_read(e4k, i + 64),
981
			i + 128, e4k_reg_read(e4k, i + 128),
982
			i + 192, e4k_reg_read(e4k, i + 192)
983
	);
984 2dd49188 Christian Daniel
	return 0;
985 b93708ed Christian Daniel
}
Add picture from clipboard (Maximum size: 48.8 MB)