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