blob: bb154449a2cfd0d997cc46584b07c0731a60bfff [file] [log] [blame]
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001/*
2 * Rafael Micro R820T driver
3 *
4 * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
5 *
6 * This driver was written from scratch, based on an existing driver
7 * that it is part of rtl-sdr git tree, released under GPLv2:
8 * https://groups.google.com/forum/#!topic/ultra-cheap-sdr/Y3rBEOFtHug
9 * https://github.com/n1gp/gr-baz
10 *
11 * From what I understood from the threads, the original driver was converted
12 * to userspace from a Realtek tree. I couldn't find the original tree.
13 * However, the original driver look awkward on my eyes. So, I decided to
14 * write a new version from it from the scratch, while trying to reproduce
15 * everything found there.
16 *
17 * TODO:
18 * After locking, the original driver seems to have some routines to
19 * improve reception. This was not implemented here yet.
20 *
21 * RF Gain set/get is not implemented.
22 *
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 */
34
35#include <linux/videodev2.h>
36#include <linux/mutex.h>
37#include <linux/slab.h>
Mauro Carvalho Chehab103fe2f2013-04-10 07:08:17 -030038#include <linux/bitrev.h>
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -030039#include <asm/div64.h>
Mauro Carvalho Chehab103fe2f2013-04-10 07:08:17 -030040
41#include "tuner-i2c.h"
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -030042#include "r820t.h"
43
44/*
45 * FIXME: I think that there are only 32 registers, but better safe than
46 * sorry. After finishing the driver, we may review it.
47 */
48#define REG_SHADOW_START 5
49#define NUM_REGS 27
50
51#define VER_NUM 49
52
53static int debug;
54module_param(debug, int, 0644);
55MODULE_PARM_DESC(debug, "enable verbose debug messages");
56
57/*
58 * enums and structures
59 */
60
61enum xtal_cap_value {
62 XTAL_LOW_CAP_30P = 0,
63 XTAL_LOW_CAP_20P,
64 XTAL_LOW_CAP_10P,
65 XTAL_LOW_CAP_0P,
66 XTAL_HIGH_CAP_0P
67};
68
69struct r820t_priv {
70 struct list_head hybrid_tuner_instance_list;
71 const struct r820t_config *cfg;
72 struct tuner_i2c_props i2c_props;
73 struct mutex lock;
74
75 u8 regs[NUM_REGS];
76 u8 buf[NUM_REGS + 1];
77 enum xtal_cap_value xtal_cap_sel;
78 u16 pll; /* kHz */
79 u32 int_freq;
80 u8 fil_cal_code;
81 bool imr_done;
82
83 /* Store current mode */
84 u32 delsys;
85 enum v4l2_tuner_type type;
86 v4l2_std_id std;
87 u32 bw; /* in MHz */
88
89 bool has_lock;
90};
91
92struct r820t_freq_range {
93 u32 freq;
94 u8 open_d;
95 u8 rf_mux_ploy;
96 u8 tf_c;
97 u8 xtal_cap20p;
98 u8 xtal_cap10p;
99 u8 xtal_cap0p;
100 u8 imr_mem; /* Not used, currently */
101};
102
103#define VCO_POWER_REF 0x02
104
105/*
106 * Static constants
107 */
108
109static LIST_HEAD(hybrid_tuner_instance_list);
110static DEFINE_MUTEX(r820t_list_mutex);
111
112/* Those initial values start from REG_SHADOW_START */
113static const u8 r820t_init_array[NUM_REGS] = {
114 0x83, 0x32, 0x75, /* 05 to 07 */
115 0xc0, 0x40, 0xd6, 0x6c, /* 08 to 0b */
116 0xf5, 0x63, 0x75, 0x68, /* 0c to 0f */
117 0x6c, 0x83, 0x80, 0x00, /* 10 to 13 */
118 0x0f, 0x00, 0xc0, 0x30, /* 14 to 17 */
119 0x48, 0xcc, 0x60, 0x00, /* 18 to 1b */
120 0x54, 0xae, 0x4a, 0xc0 /* 1c to 1f */
121};
122
123/* Tuner frequency ranges */
124static const struct r820t_freq_range freq_ranges[] = {
125 {
126 .freq = 0,
127 .open_d = 0x08, /* low */
128 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
129 .tf_c = 0xdf, /* R27[7:0] band2,band0 */
130 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
131 .xtal_cap10p = 0x01,
132 .xtal_cap0p = 0x00,
133 .imr_mem = 0,
134 }, {
135 .freq = 50, /* Start freq, in MHz */
136 .open_d = 0x08, /* low */
137 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
138 .tf_c = 0xbe, /* R27[7:0] band4,band1 */
139 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
140 .xtal_cap10p = 0x01,
141 .xtal_cap0p = 0x00,
142 .imr_mem = 0,
143 }, {
144 .freq = 55, /* Start freq, in MHz */
145 .open_d = 0x08, /* low */
146 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
147 .tf_c = 0x8b, /* R27[7:0] band7,band4 */
148 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
149 .xtal_cap10p = 0x01,
150 .xtal_cap0p = 0x00,
151 .imr_mem = 0,
152 }, {
153 .freq = 60, /* Start freq, in MHz */
154 .open_d = 0x08, /* low */
155 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
156 .tf_c = 0x7b, /* R27[7:0] band8,band4 */
157 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
158 .xtal_cap10p = 0x01,
159 .xtal_cap0p = 0x00,
160 .imr_mem = 0,
161 }, {
162 .freq = 65, /* Start freq, in MHz */
163 .open_d = 0x08, /* low */
164 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
165 .tf_c = 0x69, /* R27[7:0] band9,band6 */
166 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
167 .xtal_cap10p = 0x01,
168 .xtal_cap0p = 0x00,
169 .imr_mem = 0,
170 }, {
171 .freq = 70, /* Start freq, in MHz */
172 .open_d = 0x08, /* low */
173 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
174 .tf_c = 0x58, /* R27[7:0] band10,band7 */
175 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
176 .xtal_cap10p = 0x01,
177 .xtal_cap0p = 0x00,
178 .imr_mem = 0,
179 }, {
180 .freq = 75, /* Start freq, in MHz */
181 .open_d = 0x00, /* high */
182 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
183 .tf_c = 0x44, /* R27[7:0] band11,band11 */
184 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
185 .xtal_cap10p = 0x01,
186 .xtal_cap0p = 0x00,
187 .imr_mem = 0,
188 }, {
189 .freq = 80, /* Start freq, in MHz */
190 .open_d = 0x00, /* high */
191 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
192 .tf_c = 0x44, /* R27[7:0] band11,band11 */
193 .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
194 .xtal_cap10p = 0x01,
195 .xtal_cap0p = 0x00,
196 .imr_mem = 0,
197 }, {
198 .freq = 90, /* Start freq, in MHz */
199 .open_d = 0x00, /* high */
200 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
201 .tf_c = 0x34, /* R27[7:0] band12,band11 */
202 .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
203 .xtal_cap10p = 0x01,
204 .xtal_cap0p = 0x00,
205 .imr_mem = 0,
206 }, {
207 .freq = 100, /* Start freq, in MHz */
208 .open_d = 0x00, /* high */
209 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
210 .tf_c = 0x34, /* R27[7:0] band12,band11 */
211 .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
212 .xtal_cap10p = 0x01,
213 .xtal_cap0p = 0x00,
214 .imr_mem = 0,
215 }, {
216 .freq = 110, /* Start freq, in MHz */
217 .open_d = 0x00, /* high */
218 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
219 .tf_c = 0x24, /* R27[7:0] band13,band11 */
220 .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
221 .xtal_cap10p = 0x01,
222 .xtal_cap0p = 0x00,
223 .imr_mem = 1,
224 }, {
225 .freq = 120, /* Start freq, in MHz */
226 .open_d = 0x00, /* high */
227 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
228 .tf_c = 0x24, /* R27[7:0] band13,band11 */
229 .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
230 .xtal_cap10p = 0x01,
231 .xtal_cap0p = 0x00,
232 .imr_mem = 1,
233 }, {
234 .freq = 140, /* Start freq, in MHz */
235 .open_d = 0x00, /* high */
236 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
237 .tf_c = 0x14, /* R27[7:0] band14,band11 */
238 .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
239 .xtal_cap10p = 0x01,
240 .xtal_cap0p = 0x00,
241 .imr_mem = 1,
242 }, {
243 .freq = 180, /* Start freq, in MHz */
244 .open_d = 0x00, /* high */
245 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
246 .tf_c = 0x13, /* R27[7:0] band14,band12 */
247 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
248 .xtal_cap10p = 0x00,
249 .xtal_cap0p = 0x00,
250 .imr_mem = 1,
251 }, {
252 .freq = 220, /* Start freq, in MHz */
253 .open_d = 0x00, /* high */
254 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
255 .tf_c = 0x13, /* R27[7:0] band14,band12 */
256 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
257 .xtal_cap10p = 0x00,
258 .xtal_cap0p = 0x00,
259 .imr_mem = 2,
260 }, {
261 .freq = 250, /* Start freq, in MHz */
262 .open_d = 0x00, /* high */
263 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
264 .tf_c = 0x11, /* R27[7:0] highest,highest */
265 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
266 .xtal_cap10p = 0x00,
267 .xtal_cap0p = 0x00,
268 .imr_mem = 2,
269 }, {
270 .freq = 280, /* Start freq, in MHz */
271 .open_d = 0x00, /* high */
272 .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
273 .tf_c = 0x00, /* R27[7:0] highest,highest */
274 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
275 .xtal_cap10p = 0x00,
276 .xtal_cap0p = 0x00,
277 .imr_mem = 2,
278 }, {
279 .freq = 310, /* Start freq, in MHz */
280 .open_d = 0x00, /* high */
281 .rf_mux_ploy = 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
282 .tf_c = 0x00, /* R27[7:0] highest,highest */
283 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
284 .xtal_cap10p = 0x00,
285 .xtal_cap0p = 0x00,
286 .imr_mem = 2,
287 }, {
288 .freq = 450, /* Start freq, in MHz */
289 .open_d = 0x00, /* high */
290 .rf_mux_ploy = 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
291 .tf_c = 0x00, /* R27[7:0] highest,highest */
292 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
293 .xtal_cap10p = 0x00,
294 .xtal_cap0p = 0x00,
295 .imr_mem = 3,
296 }, {
297 .freq = 588, /* Start freq, in MHz */
298 .open_d = 0x00, /* high */
299 .rf_mux_ploy = 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
300 .tf_c = 0x00, /* R27[7:0] highest,highest */
301 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
302 .xtal_cap10p = 0x00,
303 .xtal_cap0p = 0x00,
304 .imr_mem = 3,
305 }, {
306 .freq = 650, /* Start freq, in MHz */
307 .open_d = 0x00, /* high */
308 .rf_mux_ploy = 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
309 .tf_c = 0x00, /* R27[7:0] highest,highest */
310 .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
311 .xtal_cap10p = 0x00,
312 .xtal_cap0p = 0x00,
313 .imr_mem = 4,
314 }
315};
316
317static int r820t_xtal_capacitor[][2] = {
318 { 0x0b, XTAL_LOW_CAP_30P },
319 { 0x02, XTAL_LOW_CAP_20P },
320 { 0x01, XTAL_LOW_CAP_10P },
321 { 0x00, XTAL_LOW_CAP_0P },
322 { 0x10, XTAL_HIGH_CAP_0P },
323};
324
325/*
Mauro Carvalho Chehab50786dd2013-04-07 18:33:13 -0300326 * measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm
327 * input power, for raw results see:
328 * http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/
329 */
330
331static const int r820t_lna_gain_steps[] = {
332 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13
333};
334
335static const int r820t_mixer_gain_steps[] = {
336 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8
337};
338
339/*
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300340 * I2C read/write code and shadow registers logic
341 */
342static void shadow_store(struct r820t_priv *priv, u8 reg, const u8 *val,
343 int len)
344{
345 int r = reg - REG_SHADOW_START;
346
347 if (r < 0) {
348 len += r;
349 r = 0;
350 }
351 if (len <= 0)
352 return;
353 if (len > NUM_REGS)
354 len = NUM_REGS;
355
356 tuner_dbg("%s: prev reg=%02x len=%d: %*ph\n",
357 __func__, r + REG_SHADOW_START, len, len, val);
358
359 memcpy(&priv->regs[r], val, len);
360}
361
362static int r820t_write(struct r820t_priv *priv, u8 reg, const u8 *val,
363 int len)
364{
365 int rc, size, pos = 0;
366
367 /* Store the shadow registers */
368 shadow_store(priv, reg, val, len);
369
370 do {
371 if (len > priv->cfg->max_i2c_msg_len - 1)
372 size = priv->cfg->max_i2c_msg_len - 1;
373 else
374 size = len;
375
376 /* Fill I2C buffer */
377 priv->buf[0] = reg;
378 memcpy(&priv->buf[1], &val[pos], size);
379
380 rc = tuner_i2c_xfer_send(&priv->i2c_props, priv->buf, size + 1);
381 if (rc != size + 1) {
382 tuner_info("%s: i2c wr failed=%d reg=%02x len=%d: %*ph\n",
383 __func__, rc, reg, size, size, &priv->buf[1]);
384 if (rc < 0)
385 return rc;
386 return -EREMOTEIO;
387 }
388 tuner_dbg("%s: i2c wr reg=%02x len=%d: %*ph\n",
389 __func__, reg, size, size, &priv->buf[1]);
390
391 reg += size;
392 len -= size;
393 pos += size;
394 } while (len > 0);
395
396 return 0;
397}
398
399static int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val)
400{
401 return r820t_write(priv, reg, &val, 1);
402}
403
404static int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val,
405 u8 bit_mask)
406{
407 int r = reg - REG_SHADOW_START;
408
409 if (r >= 0 && r < NUM_REGS)
410 val = (priv->regs[r] & ~bit_mask) | (val & bit_mask);
411 else
412 return -EINVAL;
413
414 return r820t_write(priv, reg, &val, 1);
415}
416
417static int r820_read(struct r820t_priv *priv, u8 reg, u8 *val, int len)
418{
Mauro Carvalho Chehab103fe2f2013-04-10 07:08:17 -0300419 int rc, i;
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300420 u8 *p = &priv->buf[1];
421
422 priv->buf[0] = reg;
423
424 rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, priv->buf, 1, p, len);
425 if (rc != len) {
426 tuner_info("%s: i2c rd failed=%d reg=%02x len=%d: %*ph\n",
427 __func__, rc, reg, len, len, p);
428 if (rc < 0)
429 return rc;
430 return -EREMOTEIO;
431 }
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300432
433 /* Copy data to the output buffer */
Mauro Carvalho Chehab103fe2f2013-04-10 07:08:17 -0300434 for (i = 0; i < len; i++)
435 val[i] = bitrev8(p[i]);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300436
Mauro Carvalho Chehab6b8c2302013-04-10 07:43:10 -0300437 tuner_dbg("%s: i2c rd reg=%02x len=%d: %*ph\n",
438 __func__, reg, len, len, val);
439
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300440 return 0;
441}
442
443/*
444 * r820t tuning logic
445 */
446
447static int r820t_set_mux(struct r820t_priv *priv, u32 freq)
448{
449 const struct r820t_freq_range *range;
450 int i, rc;
451 u8 val;
452
453 /* Get the proper frequency range */
454 freq = freq / 1000000;
455 for (i = 0; i < ARRAY_SIZE(freq_ranges) - 1; i++) {
456 if (freq < freq_ranges[i + 1].freq)
457 break;
458 }
459 range = &freq_ranges[i];
460
461 tuner_dbg("set r820t range#%d for frequency %d MHz\n", i, freq);
462
463 /* Open Drain */
464 rc = r820t_write_reg_mask(priv, 0x17, range->open_d, 0x08);
465 if (rc < 0)
466 return rc;
467
468 /* RF_MUX,Polymux */
469 rc = r820t_write_reg_mask(priv, 0x1a, range->rf_mux_ploy, 0xc3);
470 if (rc < 0)
471 return rc;
472
473 /* TF BAND */
474 rc = r820t_write_reg(priv, 0x1b, range->tf_c);
475 if (rc < 0)
476 return rc;
477
478 /* XTAL CAP & Drive */
479 switch (priv->xtal_cap_sel) {
480 case XTAL_LOW_CAP_30P:
481 case XTAL_LOW_CAP_20P:
482 val = range->xtal_cap20p | 0x08;
483 break;
484 case XTAL_LOW_CAP_10P:
485 val = range->xtal_cap10p | 0x08;
486 break;
487 case XTAL_HIGH_CAP_0P:
488 val = range->xtal_cap0p | 0x00;
489 break;
490 default:
491 case XTAL_LOW_CAP_0P:
492 val = range->xtal_cap0p | 0x08;
493 break;
494 }
495 rc = r820t_write_reg_mask(priv, 0x10, val, 0x0b);
496 if (rc < 0)
497 return rc;
498
499 /*
500 * FIXME: the original driver has a logic there with preserves
501 * gain/phase from registers 8 and 9 reading the data from the
502 * registers before writing, if "IMF done". That code was sort of
503 * commented there, as the flag is always false.
504 */
505 rc = r820t_write_reg_mask(priv, 0x08, 0, 0x3f);
506 if (rc < 0)
507 return rc;
508
509 rc = r820t_write_reg_mask(priv, 0x09, 0, 0x3f);
510
511 return rc;
512}
513
514static int r820t_set_pll(struct r820t_priv *priv, u32 freq)
515{
516 u64 tmp64, vco_freq;
517 int rc, i;
518 u32 vco_fra; /* VCO contribution by SDM (kHz) */
519 u32 vco_min = 1770000;
520 u32 vco_max = vco_min * 2;
521 u32 pll_ref;
522 u16 n_sdm = 2;
523 u16 sdm = 0;
524 u8 mix_div = 2;
525 u8 div_buf = 0;
526 u8 div_num = 0;
527 u8 ni, si, nint, vco_fine_tune, val;
528 u8 data[5];
529
530 freq = freq / 1000; /* Frequency in kHz */
531
532 pll_ref = priv->cfg->xtal / 1000;
533
534 tuner_dbg("set r820t pll for frequency %d kHz = %d\n", freq, pll_ref);
535
536 /* FIXME: this seems to be a hack - probably it can be removed */
537 rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x00);
538 if (rc < 0)
539 return rc;
540
541 /* set pll autotune = 128kHz */
542 rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
543 if (rc < 0)
544 return rc;
545
546 /* set VCO current = 100 */
547 rc = r820t_write_reg_mask(priv, 0x12, 0x80, 0xe0);
548 if (rc < 0)
549 return rc;
550
551 /* Calculate divider */
552 while (mix_div <= 64) {
553 if (((freq * mix_div) >= vco_min) &&
554 ((freq * mix_div) < vco_max)) {
555 div_buf = mix_div;
556 while (div_buf > 2) {
557 div_buf = div_buf >> 1;
558 div_num++;
559 }
560 break;
561 }
562 mix_div = mix_div << 1;
563 }
564
565 rc = r820_read(priv, 0x00, data, sizeof(data));
566 if (rc < 0)
567 return rc;
568
569 vco_fine_tune = (data[4] & 0x30) >> 4;
570
571 if (vco_fine_tune > VCO_POWER_REF)
572 div_num = div_num - 1;
573 else if (vco_fine_tune < VCO_POWER_REF)
574 div_num = div_num + 1;
575
576 rc = r820t_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);
577 if (rc < 0)
578 return rc;
579
580 vco_freq = (u64)(freq * (u64)mix_div);
581
582 tmp64 = vco_freq;
583 do_div(tmp64, 2 * pll_ref);
584 nint = (u8)tmp64;
585
586 tmp64 = vco_freq - ((u64)2) * pll_ref * nint;
587 do_div(tmp64, 1000);
588 vco_fra = (u16)(tmp64);
589
590 pll_ref /= 1000;
591
592 /* boundary spur prevention */
593 if (vco_fra < pll_ref / 64) {
594 vco_fra = 0;
595 } else if (vco_fra > pll_ref * 127 / 64) {
596 vco_fra = 0;
597 nint++;
598 } else if ((vco_fra > pll_ref * 127 / 128) && (vco_fra < pll_ref)) {
599 vco_fra = pll_ref * 127 / 128;
600 } else if ((vco_fra > pll_ref) && (vco_fra < pll_ref * 129 / 128)) {
601 vco_fra = pll_ref * 129 / 128;
602 }
603
604 if (nint > 63) {
605 tuner_info("No valid PLL values for %u kHz!\n", freq);
606 return -EINVAL;
607 }
608
609 ni = (nint - 13) / 4;
610 si = nint - 4 * ni - 13;
611
612 rc = r820t_write_reg(priv, 0x14, ni + (si << 6));
613 if (rc < 0)
614 return rc;
615
616 /* pw_sdm */
617 if (!vco_fra)
618 val = 0x08;
619 else
620 val = 0x00;
621
622 rc = r820t_write_reg_mask(priv, 0x12, val, 0x08);
623 if (rc < 0)
624 return rc;
625
626 /* sdm calculator */
627 while (vco_fra > 1) {
628 if (vco_fra > (2 * pll_ref / n_sdm)) {
629 sdm = sdm + 32768 / (n_sdm / 2);
630 vco_fra = vco_fra - 2 * pll_ref / n_sdm;
631 if (n_sdm >= 0x8000)
632 break;
633 }
634 n_sdm = n_sdm << 1;
635 }
636
637 rc = r820t_write_reg_mask(priv, 0x16, sdm >> 8, 0x08);
638 if (rc < 0)
639 return rc;
640 rc = r820t_write_reg_mask(priv, 0x15, sdm & 0xff, 0x08);
641 if (rc < 0)
642 return rc;
643
644 for (i = 0; i < 2; i++) {
645 /*
646 * FIXME: Rafael chips R620D, R828D and R828 seems to
647 * need 20 ms for analog TV
648 */
649 msleep(10);
650
651 /* Check if PLL has locked */
652 rc = r820_read(priv, 0x00, data, 3);
653 if (rc < 0)
654 return rc;
655 if (data[2] & 0x40)
656 break;
657
658 if (!i) {
659 /* Didn't lock. Increase VCO current */
660 rc = r820t_write_reg_mask(priv, 0x12, 0x60, 0xe0);
661 if (rc < 0)
662 return rc;
663 }
664 }
665
666 if (!(data[2] & 0x40)) {
667 priv->has_lock = false;
668 return 0;
669 }
670
671 priv->has_lock = true;
672 tuner_dbg("tuner has lock at frequency %d kHz\n", freq);
673
674 /* set pll autotune = 8kHz */
675 rc = r820t_write_reg_mask(priv, 0x1a, 0x08, 0x08);
676
677 return rc;
678}
679
680static int r820t_sysfreq_sel(struct r820t_priv *priv, u32 freq,
681 enum v4l2_tuner_type type,
682 v4l2_std_id std,
683 u32 delsys)
684{
685 int rc;
686 u8 mixer_top, lna_top, cp_cur, div_buf_cur, lna_vth_l, mixer_vth_l;
687 u8 air_cable1_in, cable2_in, pre_dect, lna_discharge, filter_cur;
688
689 tuner_dbg("adjusting tuner parameters for the standard\n");
690
691 switch (delsys) {
692 case SYS_DVBT:
693 if ((freq == 506000000) || (freq == 666000000) ||
694 (freq == 818000000)) {
695 mixer_top = 0x14; /* mixer top:14 , top-1, low-discharge */
696 lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
697 cp_cur = 0x28; /* 101, 0.2 */
698 div_buf_cur = 0x20; /* 10, 200u */
699 } else {
700 mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
701 lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
702 cp_cur = 0x38; /* 111, auto */
703 div_buf_cur = 0x30; /* 11, 150u */
704 }
705 lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
706 mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
707 air_cable1_in = 0x00;
708 cable2_in = 0x00;
709 pre_dect = 0x40;
710 lna_discharge = 14;
711 filter_cur = 0x40; /* 10, low */
712 break;
713 case SYS_DVBT2:
714 mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
715 lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
716 lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
717 mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
718 air_cable1_in = 0x00;
719 cable2_in = 0x00;
720 pre_dect = 0x40;
721 lna_discharge = 14;
722 cp_cur = 0x38; /* 111, auto */
723 div_buf_cur = 0x30; /* 11, 150u */
724 filter_cur = 0x40; /* 10, low */
725 break;
726 case SYS_ISDBT:
727 mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
728 lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
729 lna_vth_l = 0x75; /* lna vth 1.04 , vtl 0.84 */
730 mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
731 air_cable1_in = 0x00;
732 cable2_in = 0x00;
733 pre_dect = 0x40;
734 lna_discharge = 14;
735 cp_cur = 0x38; /* 111, auto */
736 div_buf_cur = 0x30; /* 11, 150u */
737 filter_cur = 0x40; /* 10, low */
738 break;
739 default: /* DVB-T 8M */
740 mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
741 lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
742 lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
743 mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
744 air_cable1_in = 0x00;
745 cable2_in = 0x00;
746 pre_dect = 0x40;
747 lna_discharge = 14;
748 cp_cur = 0x38; /* 111, auto */
749 div_buf_cur = 0x30; /* 11, 150u */
750 filter_cur = 0x40; /* 10, low */
751 break;
752 }
753
754 rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0xc7);
755 if (rc < 0)
756 return rc;
757 rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0xf8);
758 if (rc < 0)
759 return rc;
760 rc = r820t_write_reg(priv, 0x0d, lna_vth_l);
761 if (rc < 0)
762 return rc;
763 rc = r820t_write_reg(priv, 0x0e, mixer_vth_l);
764 if (rc < 0)
765 return rc;
766
767 /* Air-IN only for Astrometa */
768 rc = r820t_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
769 if (rc < 0)
770 return rc;
771 rc = r820t_write_reg_mask(priv, 0x06, cable2_in, 0x08);
772 if (rc < 0)
773 return rc;
774
775 rc = r820t_write_reg_mask(priv, 0x11, cp_cur, 0x38);
776 if (rc < 0)
777 return rc;
778 rc = r820t_write_reg_mask(priv, 0x17, div_buf_cur, 0x30);
779 if (rc < 0)
780 return rc;
781 rc = r820t_write_reg_mask(priv, 0x0a, filter_cur, 0x60);
782 if (rc < 0)
783 return rc;
784 /*
785 * Original driver initializes regs 0x05 and 0x06 with the
786 * same value again on this point. Probably, it is just an
787 * error there
788 */
789
790 /*
791 * Set LNA
792 */
793
794 tuner_dbg("adjusting LNA parameters\n");
795 if (type != V4L2_TUNER_ANALOG_TV) {
796 /* LNA TOP: lowest */
797 rc = r820t_write_reg_mask(priv, 0x1d, 0, 0x38);
798 if (rc < 0)
799 return rc;
800
801 /* 0: normal mode */
802 rc = r820t_write_reg_mask(priv, 0x1c, 0, 0x04);
803 if (rc < 0)
804 return rc;
805
806 /* 0: PRE_DECT off */
807 rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);
808 if (rc < 0)
809 return rc;
810
811 /* agc clk 250hz */
812 rc = r820t_write_reg_mask(priv, 0x1a, 0x30, 0x30);
813 if (rc < 0)
814 return rc;
815
816 msleep(250);
817
818 /* write LNA TOP = 3 */
819 rc = r820t_write_reg_mask(priv, 0x1d, 0x18, 0x38);
820 if (rc < 0)
821 return rc;
822
823 /*
824 * write discharge mode
825 * FIXME: IMHO, the mask here is wrong, but it matches
826 * what's there at the original driver
827 */
828 rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
829 if (rc < 0)
830 return rc;
831
832 /* LNA discharge current */
833 rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
834 if (rc < 0)
835 return rc;
836
837 /* agc clk 60hz */
838 rc = r820t_write_reg_mask(priv, 0x1a, 0x20, 0x30);
839 if (rc < 0)
840 return rc;
841 } else {
842 /* PRE_DECT off */
843 rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);
844 if (rc < 0)
845 return rc;
846
847 /* write LNA TOP */
848 rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0x38);
849 if (rc < 0)
850 return rc;
851
852 /*
853 * write discharge mode
854 * FIXME: IMHO, the mask here is wrong, but it matches
855 * what's there at the original driver
856 */
857 rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
858 if (rc < 0)
859 return rc;
860
861 /* LNA discharge current */
862 rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
863 if (rc < 0)
864 return rc;
865
866 /* agc clk 1Khz, external det1 cap 1u */
867 rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x30);
868 if (rc < 0)
869 return rc;
870
871 rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x04);
872 if (rc < 0)
873 return rc;
874 }
875 return 0;
876}
877
878static int r820t_set_tv_standard(struct r820t_priv *priv,
879 unsigned bw,
880 enum v4l2_tuner_type type,
881 v4l2_std_id std, u32 delsys)
882
883{
884 int rc, i;
885 u32 if_khz, filt_cal_lo;
886 u8 data[5], val;
887 u8 filt_gain, img_r, filt_q, hp_cor, ext_enable, loop_through;
888 u8 lt_att, flt_ext_widest, polyfil_cur;
889 bool need_calibration;
890
891 tuner_dbg("selecting the delivery system\n");
892
893 if (delsys == SYS_ISDBT) {
894 if_khz = 4063;
895 filt_cal_lo = 59000;
896 filt_gain = 0x10; /* +3db, 6mhz on */
897 img_r = 0x00; /* image negative */
898 filt_q = 0x10; /* r10[4]:low q(1'b1) */
899 hp_cor = 0x6a; /* 1.7m disable, +2cap, 1.25mhz */
900 ext_enable = 0x40; /* r30[6], ext enable; r30[5]:0 ext at lna max */
901 loop_through = 0x00; /* r5[7], lt on */
902 lt_att = 0x00; /* r31[7], lt att enable */
903 flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
904 polyfil_cur = 0x60; /* r25[6:5]:min */
905 } else {
906 if (bw <= 6) {
907 if_khz = 3570;
908 filt_cal_lo = 56000; /* 52000->56000 */
909 filt_gain = 0x10; /* +3db, 6mhz on */
910 img_r = 0x00; /* image negative */
911 filt_q = 0x10; /* r10[4]:low q(1'b1) */
912 hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */
913 ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
914 loop_through = 0x00; /* r5[7], lt on */
915 lt_att = 0x00; /* r31[7], lt att enable */
916 flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
917 polyfil_cur = 0x60; /* r25[6:5]:min */
918 } else if (bw == 7) {
Mauro Carvalho Chehab6189f802013-04-10 07:33:23 -0300919#if 0
920 /*
921 * There are two 7 MHz tables defined on the original
922 * driver, but just the second one seems to be visible
923 * by rtl2832. Keep this one here commented, as it
924 * might be needed in the future
925 */
926
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300927 if_khz = 4070;
928 filt_cal_lo = 60000;
929 filt_gain = 0x10; /* +3db, 6mhz on */
930 img_r = 0x00; /* image negative */
931 filt_q = 0x10; /* r10[4]:low q(1'b1) */
932 hp_cor = 0x2b; /* 1.7m disable, +1cap, 1.0mhz */
933 ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
934 loop_through = 0x00; /* r5[7], lt on */
935 lt_att = 0x00; /* r31[7], lt att enable */
936 flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
937 polyfil_cur = 0x60; /* r25[6:5]:min */
Mauro Carvalho Chehab6189f802013-04-10 07:33:23 -0300938#endif
939 /* 7 MHz, second table */
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300940 if_khz = 4570;
941 filt_cal_lo = 63000;
942 filt_gain = 0x10; /* +3db, 6mhz on */
943 img_r = 0x00; /* image negative */
944 filt_q = 0x10; /* r10[4]:low q(1'b1) */
945 hp_cor = 0x2a; /* 1.7m disable, +1cap, 1.25mhz */
946 ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
947 loop_through = 0x00; /* r5[7], lt on */
948 lt_att = 0x00; /* r31[7], lt att enable */
949 flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
950 polyfil_cur = 0x60; /* r25[6:5]:min */
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300951 } else {
952 if_khz = 4570;
953 filt_cal_lo = 68500;
954 filt_gain = 0x10; /* +3db, 6mhz on */
955 img_r = 0x00; /* image negative */
956 filt_q = 0x10; /* r10[4]:low q(1'b1) */
957 hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */
958 ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
959 loop_through = 0x00; /* r5[7], lt on */
960 lt_att = 0x00; /* r31[7], lt att enable */
961 flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
962 polyfil_cur = 0x60; /* r25[6:5]:min */
963 }
964 }
965
966 /* Initialize the shadow registers */
967 memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
968
969 /* Init Flag & Xtal_check Result */
970 if (priv->imr_done)
971 val = 1 | priv->xtal_cap_sel << 1;
972 else
973 val = 0;
974 rc = r820t_write_reg_mask(priv, 0x0c, val, 0x0f);
975 if (rc < 0)
976 return rc;
977
978 /* version */
979 rc = r820t_write_reg_mask(priv, 0x13, VER_NUM, 0x3f);
980 if (rc < 0)
981 return rc;
982
983 /* for LT Gain test */
984 if (type != V4L2_TUNER_ANALOG_TV) {
985 rc = r820t_write_reg_mask(priv, 0x1d, 0x00, 0x38);
986 if (rc < 0)
987 return rc;
988 msleep(1);
989 }
Mauro Carvalho Chehabf60f5bc2013-04-09 18:46:10 -0300990 priv->int_freq = if_khz * 1000;
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -0300991
992 /* Check if standard changed. If so, filter calibration is needed */
993 if (type != priv->type)
994 need_calibration = true;
995 else if ((type == V4L2_TUNER_ANALOG_TV) && (std != priv->std))
996 need_calibration = true;
997 else if ((type == V4L2_TUNER_DIGITAL_TV) &&
998 ((delsys != priv->delsys) || bw != priv->bw))
999 need_calibration = true;
1000 else
1001 need_calibration = false;
1002
1003 if (need_calibration) {
1004 tuner_dbg("calibrating the tuner\n");
1005 for (i = 0; i < 2; i++) {
1006 /* Set filt_cap */
1007 rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0x60);
1008 if (rc < 0)
1009 return rc;
1010
1011 /* set cali clk =on */
1012 rc = r820t_write_reg_mask(priv, 0x0f, 0x04, 0x04);
1013 if (rc < 0)
1014 return rc;
1015
1016 /* X'tal cap 0pF for PLL */
1017 rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x03);
1018 if (rc < 0)
1019 return rc;
1020
1021 rc = r820t_set_pll(priv, filt_cal_lo);
1022 if (rc < 0 || !priv->has_lock)
1023 return rc;
1024
1025 /* Start Trigger */
1026 rc = r820t_write_reg_mask(priv, 0x0b, 0x10, 0x10);
1027 if (rc < 0)
1028 return rc;
1029
1030 msleep(1);
1031
1032 /* Stop Trigger */
1033 rc = r820t_write_reg_mask(priv, 0x0b, 0x00, 0x10);
1034 if (rc < 0)
1035 return rc;
1036
1037 /* set cali clk =off */
1038 rc = r820t_write_reg_mask(priv, 0x0f, 0x00, 0x04);
1039 if (rc < 0)
1040 return rc;
1041
1042 /* Check if calibration worked */
1043 rc = r820_read(priv, 0x00, data, sizeof(data));
1044 if (rc < 0)
1045 return rc;
1046
1047 priv->fil_cal_code = data[4] & 0x0f;
1048 if (priv->fil_cal_code && priv->fil_cal_code != 0x0f)
1049 break;
1050 }
1051 /* narrowest */
1052 if (priv->fil_cal_code == 0x0f)
1053 priv->fil_cal_code = 0;
1054 }
1055
1056 rc = r820t_write_reg_mask(priv, 0x0a,
1057 filt_q | priv->fil_cal_code, 0x1f);
1058 if (rc < 0)
1059 return rc;
1060
1061 /* Set BW, Filter_gain, & HP corner */
1062 rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0x10);
1063 if (rc < 0)
1064 return rc;
1065
1066
1067 /* Set Img_R */
1068 rc = r820t_write_reg_mask(priv, 0x07, img_r, 0x80);
1069 if (rc < 0)
1070 return rc;
1071
1072 /* Set filt_3dB, V6MHz */
1073 rc = r820t_write_reg_mask(priv, 0x06, filt_gain, 0x30);
1074 if (rc < 0)
1075 return rc;
1076
1077 /* channel filter extension */
1078 rc = r820t_write_reg_mask(priv, 0x1e, ext_enable, 0x60);
1079 if (rc < 0)
1080 return rc;
1081
1082 /* Loop through */
1083 rc = r820t_write_reg_mask(priv, 0x05, loop_through, 0x80);
1084 if (rc < 0)
1085 return rc;
1086
1087 /* Loop through attenuation */
1088 rc = r820t_write_reg_mask(priv, 0x1f, lt_att, 0x80);
1089 if (rc < 0)
1090 return rc;
1091
1092 /* filter extension widest */
1093 rc = r820t_write_reg_mask(priv, 0x0f, flt_ext_widest, 0x80);
1094 if (rc < 0)
1095 return rc;
1096
1097 /* RF poly filter current */
1098 rc = r820t_write_reg_mask(priv, 0x19, polyfil_cur, 0x60);
1099 if (rc < 0)
1100 return rc;
1101
1102 /* Store current standard. If it changes, re-calibrate the tuner */
1103 priv->delsys = delsys;
1104 priv->type = type;
1105 priv->std = std;
1106 priv->bw = bw;
1107
1108 return 0;
1109}
1110
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001111static int r820t_read_gain(struct r820t_priv *priv)
1112{
1113 u8 data[4];
1114 int rc;
1115
1116 rc = r820_read(priv, 0x00, data, sizeof(data));
1117 if (rc < 0)
1118 return rc;
1119
1120 return ((data[3] & 0x0f) << 1) + ((data[3] & 0xf0) >> 4);
1121}
1122
Mauro Carvalho Chehab50786dd2013-04-07 18:33:13 -03001123static int r820t_set_gain_mode(struct r820t_priv *priv,
1124 bool set_manual_gain,
1125 int gain)
1126{
1127 int rc;
1128
1129 if (set_manual_gain) {
1130 int i, total_gain = 0;
1131 uint8_t mix_index = 0, lna_index = 0;
1132 u8 data[4];
1133
1134 /* LNA auto off */
1135 rc = r820t_write_reg_mask(priv, 0x05, 0x10, 0x10);
1136 if (rc < 0)
1137 return rc;
1138
1139 /* Mixer auto off */
1140 rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);
1141 if (rc < 0)
1142 return rc;
1143
1144 rc = r820_read(priv, 0x00, data, sizeof(data));
1145 if (rc < 0)
1146 return rc;
1147
1148 /* set fixed VGA gain for now (16.3 dB) */
1149 rc = r820t_write_reg_mask(priv, 0x0c, 0x08, 0x9f);
1150 if (rc < 0)
1151 return rc;
1152
1153 for (i = 0; i < 15; i++) {
1154 if (total_gain >= gain)
1155 break;
1156
1157 total_gain += r820t_lna_gain_steps[++lna_index];
1158
1159 if (total_gain >= gain)
1160 break;
1161
1162 total_gain += r820t_mixer_gain_steps[++mix_index];
1163 }
1164
1165 /* set LNA gain */
1166 rc = r820t_write_reg_mask(priv, 0x05, lna_index, 0x0f);
1167 if (rc < 0)
1168 return rc;
1169
1170 /* set Mixer gain */
1171 rc = r820t_write_reg_mask(priv, 0x07, mix_index, 0x0f);
1172 if (rc < 0)
1173 return rc;
1174 } else {
1175 /* LNA */
1176 rc = r820t_write_reg_mask(priv, 0x05, 0, 0xef);
1177 if (rc < 0)
1178 return rc;
1179
1180 /* Mixer */
1181 rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0xef);
1182 if (rc < 0)
1183 return rc;
1184
1185 /* set fixed VGA gain for now (26.5 dB) */
1186 rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);
1187 if (rc < 0)
1188 return rc;
1189 }
1190
1191 return 0;
1192}
1193
1194
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001195static int generic_set_freq(struct dvb_frontend *fe,
1196 u32 freq /* in HZ */,
1197 unsigned bw,
1198 enum v4l2_tuner_type type,
1199 v4l2_std_id std, u32 delsys)
1200{
1201 struct r820t_priv *priv = fe->tuner_priv;
1202 int rc = -EINVAL;
1203 u32 lo_freq;
1204
1205 tuner_dbg("should set frequency to %d kHz, bw %d MHz\n",
1206 freq / 1000, bw);
1207
Mauro Carvalho Chehaba7dd0652013-04-09 21:29:40 -03001208 rc = r820t_set_tv_standard(priv, bw, type, std, delsys);
1209 if (rc < 0)
1210 goto err;
1211
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001212 if ((type == V4L2_TUNER_ANALOG_TV) && (std == V4L2_STD_SECAM_LC))
1213 lo_freq = freq - priv->int_freq;
1214 else
1215 lo_freq = freq + priv->int_freq;
1216
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001217 rc = r820t_set_mux(priv, lo_freq);
1218 if (rc < 0)
1219 goto err;
Mauro Carvalho Chehab50786dd2013-04-07 18:33:13 -03001220
1221 rc = r820t_set_gain_mode(priv, true, 0);
1222 if (rc < 0)
1223 goto err;
1224
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001225 rc = r820t_set_pll(priv, lo_freq);
1226 if (rc < 0 || !priv->has_lock)
1227 goto err;
1228
1229 rc = r820t_sysfreq_sel(priv, freq, type, std, delsys);
Mauro Carvalho Chehabda319342013-04-07 19:47:49 -03001230 if (rc < 0)
1231 goto err;
1232
1233 tuner_dbg("%s: PLL locked on frequency %d Hz, gain=%d\n",
1234 __func__, freq, r820t_read_gain(priv));
1235
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001236err:
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001237
1238 if (rc < 0)
1239 tuner_dbg("%s: failed=%d\n", __func__, rc);
1240 return rc;
1241}
1242
1243/*
1244 * r820t standby logic
1245 */
1246
1247static int r820t_standby(struct r820t_priv *priv)
1248{
1249 int rc;
1250
1251 rc = r820t_write_reg(priv, 0x06, 0xb1);
1252 if (rc < 0)
1253 return rc;
1254 rc = r820t_write_reg(priv, 0x05, 0x03);
1255 if (rc < 0)
1256 return rc;
1257 rc = r820t_write_reg(priv, 0x07, 0x3a);
1258 if (rc < 0)
1259 return rc;
1260 rc = r820t_write_reg(priv, 0x08, 0x40);
1261 if (rc < 0)
1262 return rc;
1263 rc = r820t_write_reg(priv, 0x09, 0xc0);
1264 if (rc < 0)
1265 return rc;
1266 rc = r820t_write_reg(priv, 0x0a, 0x36);
1267 if (rc < 0)
1268 return rc;
1269 rc = r820t_write_reg(priv, 0x0c, 0x35);
1270 if (rc < 0)
1271 return rc;
1272 rc = r820t_write_reg(priv, 0x0f, 0x68);
1273 if (rc < 0)
1274 return rc;
1275 rc = r820t_write_reg(priv, 0x11, 0x03);
1276 if (rc < 0)
1277 return rc;
1278 rc = r820t_write_reg(priv, 0x17, 0xf4);
1279 if (rc < 0)
1280 return rc;
1281 rc = r820t_write_reg(priv, 0x19, 0x0c);
1282
1283 /* Force initial calibration */
1284 priv->type = -1;
1285
1286 return rc;
1287}
1288
1289/*
1290 * r820t device init logic
1291 */
1292
1293static int r820t_xtal_check(struct r820t_priv *priv)
1294{
1295 int rc, i;
1296 u8 data[3], val;
1297
1298 /* Initialize the shadow registers */
1299 memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
1300
1301 /* cap 30pF & Drive Low */
1302 rc = r820t_write_reg_mask(priv, 0x10, 0x0b, 0x0b);
1303 if (rc < 0)
1304 return rc;
1305
1306 /* set pll autotune = 128kHz */
1307 rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
1308 if (rc < 0)
1309 return rc;
1310
1311 /* set manual initial reg = 111111; */
1312 rc = r820t_write_reg_mask(priv, 0x13, 0x7f, 0x7f);
1313 if (rc < 0)
1314 return rc;
1315
1316 /* set auto */
1317 rc = r820t_write_reg_mask(priv, 0x13, 0x00, 0x40);
1318 if (rc < 0)
1319 return rc;
1320
1321 /* Try several xtal capacitor alternatives */
1322 for (i = 0; i < ARRAY_SIZE(r820t_xtal_capacitor); i++) {
1323 rc = r820t_write_reg_mask(priv, 0x10,
1324 r820t_xtal_capacitor[i][0], 0x1b);
1325 if (rc < 0)
1326 return rc;
1327
1328 msleep(5);
1329
1330 rc = r820_read(priv, 0x00, data, sizeof(data));
1331 if (rc < 0)
1332 return rc;
1333 if ((!data[2]) & 0x40)
1334 continue;
1335
1336 val = data[2] & 0x3f;
1337
1338 if (priv->cfg->xtal == 16000000 && (val > 29 || val < 23))
1339 break;
1340
1341 if (val != 0x3f)
1342 break;
1343 }
1344
1345 if (i == ARRAY_SIZE(r820t_xtal_capacitor))
1346 return -EINVAL;
1347
1348 return r820t_xtal_capacitor[i][1];
1349}
1350
1351/*
1352 * r820t frontend operations and tuner attach code
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001353 *
1354 * All driver locks and i2c control are only in this part of the code
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001355 */
1356
1357static int r820t_init(struct dvb_frontend *fe)
1358{
1359 struct r820t_priv *priv = fe->tuner_priv;
1360 int rc, i;
1361 int xtal_cap = 0;
1362
1363 tuner_dbg("%s:\n", __func__);
1364
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001365 mutex_lock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001366 if (fe->ops.i2c_gate_ctrl)
1367 fe->ops.i2c_gate_ctrl(fe, 1);
1368
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001369 if ((priv->cfg->rafael_chip == CHIP_R820T) ||
1370 (priv->cfg->rafael_chip == CHIP_R828S) ||
1371 (priv->cfg->rafael_chip == CHIP_R820C)) {
1372 priv->xtal_cap_sel = XTAL_HIGH_CAP_0P;
1373 } else {
1374 for (i = 0; i < 3; i++) {
1375 rc = r820t_xtal_check(priv);
1376 if (rc < 0)
1377 goto err;
1378 if (!i || rc > xtal_cap)
1379 xtal_cap = rc;
1380 }
1381 priv->xtal_cap_sel = xtal_cap;
1382 }
1383
1384 /* Initialize registers */
1385 rc = r820t_write(priv, 0x05,
1386 r820t_init_array, sizeof(r820t_init_array));
1387
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001388err:
1389 if (fe->ops.i2c_gate_ctrl)
1390 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001391 mutex_unlock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001392
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001393 if (rc < 0)
1394 tuner_dbg("%s: failed=%d\n", __func__, rc);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001395 return rc;
1396}
1397
1398static int r820t_sleep(struct dvb_frontend *fe)
1399{
1400 struct r820t_priv *priv = fe->tuner_priv;
1401 int rc;
1402
1403 tuner_dbg("%s:\n", __func__);
1404
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001405 mutex_lock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001406 if (fe->ops.i2c_gate_ctrl)
1407 fe->ops.i2c_gate_ctrl(fe, 1);
1408
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001409 rc = r820t_standby(priv);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001410
1411 if (fe->ops.i2c_gate_ctrl)
1412 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001413 mutex_unlock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001414
1415 tuner_dbg("%s: failed=%d\n", __func__, rc);
1416 return rc;
1417}
1418
1419static int r820t_set_analog_freq(struct dvb_frontend *fe,
1420 struct analog_parameters *p)
1421{
1422 struct r820t_priv *priv = fe->tuner_priv;
1423 unsigned bw;
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001424 int rc;
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001425
1426 tuner_dbg("%s called\n", __func__);
1427
1428 /* if std is not defined, choose one */
1429 if (!p->std)
1430 p->std = V4L2_STD_MN;
1431
1432 if ((p->std == V4L2_STD_PAL_M) || (p->std == V4L2_STD_NTSC))
1433 bw = 6;
1434 else
1435 bw = 8;
1436
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001437 mutex_lock(&priv->lock);
1438 if (fe->ops.i2c_gate_ctrl)
1439 fe->ops.i2c_gate_ctrl(fe, 1);
1440
1441 rc = generic_set_freq(fe, 62500l * p->frequency, bw,
1442 V4L2_TUNER_ANALOG_TV, p->std, SYS_UNDEFINED);
1443
1444 if (fe->ops.i2c_gate_ctrl)
1445 fe->ops.i2c_gate_ctrl(fe, 0);
1446 mutex_unlock(&priv->lock);
1447
1448 return rc;
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001449}
1450
1451static int r820t_set_params(struct dvb_frontend *fe)
1452{
1453 struct r820t_priv *priv = fe->tuner_priv;
1454 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1455 int rc;
1456 unsigned bw;
1457
1458 tuner_dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
1459 __func__, c->delivery_system, c->frequency, c->bandwidth_hz);
1460
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001461 mutex_lock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001462 if (fe->ops.i2c_gate_ctrl)
1463 fe->ops.i2c_gate_ctrl(fe, 1);
1464
1465 bw = (c->bandwidth_hz + 500000) / 1000000;
1466 if (!bw)
1467 bw = 8;
1468
1469 rc = generic_set_freq(fe, c->frequency, bw,
1470 V4L2_TUNER_DIGITAL_TV, 0, c->delivery_system);
1471
1472 if (fe->ops.i2c_gate_ctrl)
1473 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001474 mutex_unlock(&priv->lock);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001475
1476 if (rc)
1477 tuner_dbg("%s: failed=%d\n", __func__, rc);
1478 return rc;
1479}
1480
1481static int r820t_signal(struct dvb_frontend *fe, u16 *strength)
1482{
1483 struct r820t_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001484 int rc = 0;
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001485
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001486 mutex_lock(&priv->lock);
1487 if (fe->ops.i2c_gate_ctrl)
1488 fe->ops.i2c_gate_ctrl(fe, 1);
1489
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001490 if (priv->has_lock) {
1491 rc = r820t_read_gain(priv);
1492 if (rc < 0)
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001493 goto err;
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001494
1495 /* A higher gain at LNA means a lower signal strength */
1496 *strength = (45 - rc) << 4 | 0xff;
1497 } else {
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001498 *strength = 0;
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001499 }
1500
Mauro Carvalho Chehab7a5ef302013-04-07 19:32:55 -03001501err:
1502 if (fe->ops.i2c_gate_ctrl)
1503 fe->ops.i2c_gate_ctrl(fe, 0);
1504 mutex_unlock(&priv->lock);
1505
Mauro Carvalho Chehabf8fde0e2013-04-07 18:12:56 -03001506 tuner_dbg("%s: %s, gain=%d strength=%d\n",
1507 __func__,
1508 priv->has_lock ? "PLL locked" : "no signal",
1509 rc, *strength);
Mauro Carvalho Chehaba80abc52013-04-05 14:35:18 -03001510
1511 return 0;
1512}
1513
1514static int r820t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
1515{
1516 struct r820t_priv *priv = fe->tuner_priv;
1517
1518 tuner_dbg("%s:\n", __func__);
1519
1520 *frequency = priv->int_freq;
1521
1522 return 0;
1523}
1524
1525static int r820t_release(struct dvb_frontend *fe)
1526{
1527 struct r820t_priv *priv = fe->tuner_priv;
1528
1529 tuner_dbg("%s:\n", __func__);
1530
1531 mutex_lock(&r820t_list_mutex);
1532
1533 if (priv)
1534 hybrid_tuner_release_state(priv);
1535
1536 mutex_unlock(&r820t_list_mutex);
1537
1538 fe->tuner_priv = NULL;
1539
1540 kfree(fe->tuner_priv);
1541
1542 return 0;
1543}
1544
1545static const struct dvb_tuner_ops r820t_tuner_ops = {
1546 .info = {
1547 .name = "Rafael Micro R820T",
1548 .frequency_min = 42000000,
1549 .frequency_max = 1002000000,
1550 },
1551 .init = r820t_init,
1552 .release = r820t_release,
1553 .sleep = r820t_sleep,
1554 .set_params = r820t_set_params,
1555 .set_analog_params = r820t_set_analog_freq,
1556 .get_if_frequency = r820t_get_if_frequency,
1557 .get_rf_strength = r820t_signal,
1558};
1559
1560struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
1561 struct i2c_adapter *i2c,
1562 const struct r820t_config *cfg)
1563{
1564 struct r820t_priv *priv;
1565 int rc = -ENODEV;
1566 u8 data[5];
1567 int instance;
1568
1569 mutex_lock(&r820t_list_mutex);
1570
1571 instance = hybrid_tuner_request_state(struct r820t_priv, priv,
1572 hybrid_tuner_instance_list,
1573 i2c, cfg->i2c_addr,
1574 "r820t");
1575 switch (instance) {
1576 case 0:
1577 /* memory allocation failure */
1578 goto err_no_gate;
1579 break;
1580 case 1:
1581 /* new tuner instance */
1582 priv->cfg = cfg;
1583
1584 mutex_init(&priv->lock);
1585
1586 fe->tuner_priv = priv;
1587 break;
1588 case 2:
1589 /* existing tuner instance */
1590 fe->tuner_priv = priv;
1591 break;
1592 }
1593
1594 memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, sizeof(r820t_tuner_ops));
1595
1596 if (fe->ops.i2c_gate_ctrl)
1597 fe->ops.i2c_gate_ctrl(fe, 1);
1598
1599 /* check if the tuner is there */
1600 rc = r820_read(priv, 0x00, data, sizeof(data));
1601 if (rc < 0)
1602 goto err;
1603
1604 rc = r820t_sleep(fe);
1605 if (rc < 0)
1606 goto err;
1607
1608 tuner_info("Rafael Micro r820t successfully identified\n");
1609
1610 fe->tuner_priv = priv;
1611 memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops,
1612 sizeof(struct dvb_tuner_ops));
1613
1614 if (fe->ops.i2c_gate_ctrl)
1615 fe->ops.i2c_gate_ctrl(fe, 0);
1616
1617 mutex_unlock(&r820t_list_mutex);
1618
1619 return fe;
1620err:
1621 if (fe->ops.i2c_gate_ctrl)
1622 fe->ops.i2c_gate_ctrl(fe, 0);
1623
1624err_no_gate:
1625 mutex_unlock(&r820t_list_mutex);
1626
1627 tuner_info("%s: failed=%d\n", __func__, rc);
1628 r820t_release(fe);
1629 return NULL;
1630}
1631EXPORT_SYMBOL_GPL(r820t_attach);
1632
1633MODULE_DESCRIPTION("Rafael Micro r820t silicon tuner driver");
1634MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1635MODULE_LICENSE("GPL");