Project

General

Profile

Download (23.5 KB) Statistics
| Branch: | Tag: | Revision:
1
/* (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
#include <limits.h>
20
#include <stdint.h>
21
#include <errno.h>
22
#include <string.h>
23

    
24
#include <reg_field.h>
25
#include <tuner_e4k.h>
26

    
27
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
28

    
29
/* 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
#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
/***********************************************************************
50
 * 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
/***********************************************************************
134
 * 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
	unsigned int i, bi = 0;
153
	uint32_t best_delta = 0xffffffff;
154

    
155
	/* iterate over the array containing a list of the center
156
	 * frequencies, selecting the closest one */
157
	for (i = 0; i < arr_size; i++) {
158
		uint32_t delta = unsigned_delta(freq, arr[i]);
159
		if (delta < best_delta) {
160
			best_delta = delta;
161
			bi = i;
162
		}
163
	}
164

    
165
	return bi;
166
}
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
		case E4K_BAND_VHF2:
175
		case E4K_BAND_VHF3:
176
			rc = 0;
177
			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
	}
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
	mix_filter_bw,
238
	ifch_filter_bw,
239
	ifrc_filter_bw,
240
};
241

    
242
static const uint32_t if_filter_bw_len[] = {
243
	ARRAY_SIZE(mix_filter_bw),
244
	ARRAY_SIZE(ifch_filter_bw),
245
	ARRAY_SIZE(ifrc_filter_bw),
246
};
247

    
248
static const struct reg_field if_filter_fields[] = {
249
	{
250
		E4K_REG_FILT2, 4, 4,
251
	},
252
	{
253
		E4K_REG_FILT3, 0, 5,
254
	},
255
	{
256
		E4K_REG_FILT2, 0, 4,
257
	}
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
/*! \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
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
/***********************************************************************
324
 * Frequency Control */
325

    
326
#define E4K_FVCO_MIN_KHZ	2600000	/* 2.6 GHz */
327
#define E4K_FVCO_MAX_KHZ	3900000	/* 3.9 GHz */
328
#define E4K_PLL_Y		65536
329

    
330
#ifdef OUT_OF_SPEC
331
#define E4K_FLO_MIN_MHZ		50
332
#define E4K_FLO_MAX_MHZ		2200UL
333
#else
334
#define E4K_FLO_MIN_MHZ		64
335
#define E4K_FLO_MAX_MHZ		1700
336
#endif
337

    
338
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
};
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
		printf("Fvco %u invalid\n\r", fvco_z);
363
		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
		printf("Fosc %u invalid\n\r", fosc);
373
		return 0;
374
	}
375

    
376
	return 1;
377
}
378

    
379
static int is_z_valid(uint32_t z)
380
{
381
	if (z > 255) {
382
		printf("Z %u invalid\n\r", z);
383
		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
	if (flo < MHZ(350))
394
		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
static uint64_t compute_fvco(uint32_t f_osc, uint8_t z, uint16_t x)
402
{
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
	 * integer, as we cannot hold e.g. 26 MHz * 65536 either.
410
	 */
411
	fvco_z = (uint64_t)f_osc * z;
412

    
413
#if 0
414
	if (!is_fvco_valid(fvco_z))
415
		return 0;
416
#endif
417

    
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
static uint32_t compute_flo(uint32_t f_osc, uint8_t z, uint16_t x, uint8_t r)
426
{
427
	uint64_t fvco = compute_fvco(f_osc, z, x);
428
	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
	/* 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
	rc = e4k_reg_set_mask(e4k, E4K_REG_SYNTH1, 0x06, band << 1);
452
	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
 *	     0 in case of error
464
 */
465
uint32_t e4k_compute_pll_params(struct e4k_pll_params *oscp, uint32_t fosc, uint32_t intended_flo)
466
{
467
	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

    
476
	if (!is_fosc_valid(fosc))
477
		return 0;
478

    
479
	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

    
488
	printf("Fint=%u, R=%u\n\r", intended_flo, r);
489

    
490
	/* flo(max) = 1700MHz, R(max) = 48, we need 64bit! */
491
	intended_fvco = (uint64_t)intended_flo * r;
492

    
493
	/* compute integral component of multiplier */
494
	z = intended_fvco / fosc;
495

    
496
	/* 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

    
503
	flo = compute_flo(fosc, z, x, r);
504

    
505
	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
}
516

    
517
int e4k_tune_params(struct e4k_state *e4k, struct e4k_pll_params *p)
518
{
519
	uint8_t val;
520

    
521
	/* program R + 3phase/2phase */
522
	e4k_reg_write(e4k, E4K_REG_SYNTH7, p->r_idx);
523
	/* 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
	if (e4k->vco.flo < MHZ(140))
535
		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

    
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
	uint32_t rc;
561
	struct e4k_pll_params p;
562

    
563
	/* determine PLL parameters */
564
	rc = e4k_compute_pll_params(&p, e4k->vco.fosc, freq);
565
	if (!rc)
566
		return -EINVAL;
567

    
568
	/* actually tune to those parameters */
569
	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
}
580

    
581
/***********************************************************************
582
 * 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
	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
};
609

    
610
static const uint8_t if_stage_gain_len[] = {
611
	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
};
619

    
620
static const struct reg_field if_stage_gain_regs[] = {
621
	{ 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
};
645

    
646
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
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
int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value)
741
{
742
	uint8_t bit;
743

    
744
	switch (value) {
745
	case 4:
746
		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
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
/***********************************************************************
769
 * DC Offset */
770

    
771
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
/*! \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
	int8_t if1_gain;
815
	uint8_t reg;
816
};
817

    
818
static const struct gain_comb dc_gain_comb[] = {
819
	{ 4,  -3, 0x50 },
820
	{ 4,   6, 0x51 },
821
	{ 12, -3, 0x52 },
822
	{ 12,  6, 0x53 },
823
};
824

    
825
#define TO_LUT(offset, range)	(offset | (range << 6))
826

    
827
int e4k_dc_offset_gen_table(struct e4k_state *e4k)
828
{
829
	uint32_t i;
830

    
831
	/* FIXME: read ont current gain values and write them back
832
	 * before returning to the caller */
833

    
834
	/* 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
	/* 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
		uint8_t offs_i, offs_q, range, range_i, range_q;
848

    
849
		/* set the combination of mixer / if1 gain */
850
		e4k_mixer_gain_set(e4k, dc_gain_comb[i].mixer_gain);
851
		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
		offs_i = e4k_reg_read(e4k, E4K_REG_DC2) & 0x3f;
858
		offs_q = e4k_reg_read(e4k, E4K_REG_DC3) & 0x3f;
859
		range  = e4k_reg_read(e4k, E4K_REG_DC4);
860
		range_i = range & 0x3;
861
		range_q = (range >> 4) & 0x3;
862
/*
863
		fprintf(stderr, "Table %u I=%u/%u, Q=%u/%u\n",
864
			i, range_i, offs_i, range_q, offs_q);
865
*/
866
		/* write into the table */
867
		e4k_reg_write(e4k, dc_gain_comb[i].reg,
868
			      TO_LUT(offs_q, range_q));
869
		e4k_reg_write(e4k, dc_gain_comb[i].reg + 0x10,
870
			      TO_LUT(offs_i, range_i));
871
	}
872

    
873
	return 0;
874
}
875

    
876
/***********************************************************************
877
 * 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
	e4k_reg_write(e4k, 0x82, 0x00);
884
	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

    
890
	return 0;
891
}
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
	/* 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
	magic_init(e4k);
916
#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

    
933
	e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK,
934
		E4K_AGC_MOD_SERIAL);
935

    
936
	/* Set Mixer Gain Control to manual */
937
	e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0);
938

    
939
#if 0
940
	/* 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
#endif
947

    
948
	/* Use auto-gain as default */
949
	e4k_enable_manual_gain(e4k, 0);
950

    
951
	/* 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

    
959
	/* 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
	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
}
972

    
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
	return 0;
985
}
(9-9/11)
Add picture from clipboard (Maximum size: 48.8 MB)