tuner_r82xx.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253
  1. /*
  2. * Rafael Micro R820T/R828D driver
  3. *
  4. * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
  5. * Copyright (C) 2013 Steve Markgraf <steve@steve-m.de>
  6. *
  7. * This driver is a heavily modified version of the driver found in the
  8. * Linux kernel:
  9. * http://git.linuxtv.org/linux-2.6.git/history/HEAD:/drivers/media/tuners/r820t.c
  10. *
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation, either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. #include <stdio.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include "rtlsdr_i2c.h"
  28. #include "tuner_r82xx.h"
  29. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  30. #define MHZ(x) ((x)*1000*1000)
  31. #define KHZ(x) ((x)*1000)
  32. /*
  33. * Static constants
  34. */
  35. /* Those initial values start from REG_SHADOW_START */
  36. static const uint8_t r82xx_init_array[NUM_REGS] = {
  37. 0x83, 0x32, 0x75, /* 05 to 07 */
  38. 0xc0, 0x40, 0xd6, 0x6c, /* 08 to 0b */
  39. 0xf5, 0x63, 0x75, 0x68, /* 0c to 0f */
  40. 0x6c, 0x83, 0x80, 0x00, /* 10 to 13 */
  41. 0x0f, 0x00, 0xc0, 0x30, /* 14 to 17 */
  42. 0x48, 0xcc, 0x60, 0x00, /* 18 to 1b */
  43. 0x54, 0xae, 0x4a, 0xc0 /* 1c to 1f */
  44. };
  45. /* Tuner frequency ranges */
  46. static const struct r82xx_freq_range freq_ranges[] = {
  47. {
  48. /* .freq = */ 0, /* Start freq, in MHz */
  49. /* .open_d = */ 0x08, /* low */
  50. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  51. /* .tf_c = */ 0xdf, /* R27[7:0] band2,band0 */
  52. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  53. /* .xtal_cap10p = */ 0x01,
  54. /* .xtal_cap0p = */ 0x00,
  55. }, {
  56. /* .freq = */ 50, /* Start freq, in MHz */
  57. /* .open_d = */ 0x08, /* low */
  58. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  59. /* .tf_c = */ 0xbe, /* R27[7:0] band4,band1 */
  60. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  61. /* .xtal_cap10p = */ 0x01,
  62. /* .xtal_cap0p = */ 0x00,
  63. }, {
  64. /* .freq = */ 55, /* Start freq, in MHz */
  65. /* .open_d = */ 0x08, /* low */
  66. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  67. /* .tf_c = */ 0x8b, /* R27[7:0] band7,band4 */
  68. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  69. /* .xtal_cap10p = */ 0x01,
  70. /* .xtal_cap0p = */ 0x00,
  71. }, {
  72. /* .freq = */ 60, /* Start freq, in MHz */
  73. /* .open_d = */ 0x08, /* low */
  74. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  75. /* .tf_c = */ 0x7b, /* R27[7:0] band8,band4 */
  76. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  77. /* .xtal_cap10p = */ 0x01,
  78. /* .xtal_cap0p = */ 0x00,
  79. }, {
  80. /* .freq = */ 65, /* Start freq, in MHz */
  81. /* .open_d = */ 0x08, /* low */
  82. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  83. /* .tf_c = */ 0x69, /* R27[7:0] band9,band6 */
  84. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  85. /* .xtal_cap10p = */ 0x01,
  86. /* .xtal_cap0p = */ 0x00,
  87. }, {
  88. /* .freq = */ 70, /* Start freq, in MHz */
  89. /* .open_d = */ 0x08, /* low */
  90. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  91. /* .tf_c = */ 0x58, /* R27[7:0] band10,band7 */
  92. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  93. /* .xtal_cap10p = */ 0x01,
  94. /* .xtal_cap0p = */ 0x00,
  95. }, {
  96. /* .freq = */ 75, /* Start freq, in MHz */
  97. /* .open_d = */ 0x00, /* high */
  98. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  99. /* .tf_c = */ 0x44, /* R27[7:0] band11,band11 */
  100. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  101. /* .xtal_cap10p = */ 0x01,
  102. /* .xtal_cap0p = */ 0x00,
  103. }, {
  104. /* .freq = */ 80, /* Start freq, in MHz */
  105. /* .open_d = */ 0x00, /* high */
  106. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  107. /* .tf_c = */ 0x44, /* R27[7:0] band11,band11 */
  108. /* .xtal_cap20p = */ 0x02, /* R16[1:0] 20pF (10) */
  109. /* .xtal_cap10p = */ 0x01,
  110. /* .xtal_cap0p = */ 0x00,
  111. }, {
  112. /* .freq = */ 90, /* Start freq, in MHz */
  113. /* .open_d = */ 0x00, /* high */
  114. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  115. /* .tf_c = */ 0x34, /* R27[7:0] band12,band11 */
  116. /* .xtal_cap20p = */ 0x01, /* R16[1:0] 10pF (01) */
  117. /* .xtal_cap10p = */ 0x01,
  118. /* .xtal_cap0p = */ 0x00,
  119. }, {
  120. /* .freq = */ 100, /* Start freq, in MHz */
  121. /* .open_d = */ 0x00, /* high */
  122. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  123. /* .tf_c = */ 0x34, /* R27[7:0] band12,band11 */
  124. /* .xtal_cap20p = */ 0x01, /* R16[1:0] 10pF (01) */
  125. /* .xtal_cap10p = */ 0x01,
  126. /* .xtal_cap0p = */ 0x00,
  127. }, {
  128. /* .freq = */ 110, /* Start freq, in MHz */
  129. /* .open_d = */ 0x00, /* high */
  130. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  131. /* .tf_c = */ 0x24, /* R27[7:0] band13,band11 */
  132. /* .xtal_cap20p = */ 0x01, /* R16[1:0] 10pF (01) */
  133. /* .xtal_cap10p = */ 0x01,
  134. /* .xtal_cap0p = */ 0x00,
  135. }, {
  136. /* .freq = */ 120, /* Start freq, in MHz */
  137. /* .open_d = */ 0x00, /* high */
  138. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  139. /* .tf_c = */ 0x24, /* R27[7:0] band13,band11 */
  140. /* .xtal_cap20p = */ 0x01, /* R16[1:0] 10pF (01) */
  141. /* .xtal_cap10p = */ 0x01,
  142. /* .xtal_cap0p = */ 0x00,
  143. }, {
  144. /* .freq = */ 140, /* Start freq, in MHz */
  145. /* .open_d = */ 0x00, /* high */
  146. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  147. /* .tf_c = */ 0x14, /* R27[7:0] band14,band11 */
  148. /* .xtal_cap20p = */ 0x01, /* R16[1:0] 10pF (01) */
  149. /* .xtal_cap10p = */ 0x01,
  150. /* .xtal_cap0p = */ 0x00,
  151. }, {
  152. /* .freq = */ 180, /* Start freq, in MHz */
  153. /* .open_d = */ 0x00, /* high */
  154. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  155. /* .tf_c = */ 0x13, /* R27[7:0] band14,band12 */
  156. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  157. /* .xtal_cap10p = */ 0x00,
  158. /* .xtal_cap0p = */ 0x00,
  159. }, {
  160. /* .freq = */ 220, /* Start freq, in MHz */
  161. /* .open_d = */ 0x00, /* high */
  162. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  163. /* .tf_c = */ 0x13, /* R27[7:0] band14,band12 */
  164. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  165. /* .xtal_cap10p = */ 0x00,
  166. /* .xtal_cap0p = */ 0x00,
  167. }, {
  168. /* .freq = */ 250, /* Start freq, in MHz */
  169. /* .open_d = */ 0x00, /* high */
  170. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  171. /* .tf_c = */ 0x11, /* R27[7:0] highest,highest */
  172. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  173. /* .xtal_cap10p = */ 0x00,
  174. /* .xtal_cap0p = */ 0x00,
  175. }, {
  176. /* .freq = */ 280, /* Start freq, in MHz */
  177. /* .open_d = */ 0x00, /* high */
  178. /* .rf_mux_ploy = */ 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
  179. /* .tf_c = */ 0x00, /* R27[7:0] highest,highest */
  180. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  181. /* .xtal_cap10p = */ 0x00,
  182. /* .xtal_cap0p = */ 0x00,
  183. }, {
  184. /* .freq = */ 310, /* Start freq, in MHz */
  185. /* .open_d = */ 0x00, /* high */
  186. /* .rf_mux_ploy = */ 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
  187. /* .tf_c = */ 0x00, /* R27[7:0] highest,highest */
  188. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  189. /* .xtal_cap10p = */ 0x00,
  190. /* .xtal_cap0p = */ 0x00,
  191. }, {
  192. /* .freq = */ 450, /* Start freq, in MHz */
  193. /* .open_d = */ 0x00, /* high */
  194. /* .rf_mux_ploy = */ 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
  195. /* .tf_c = */ 0x00, /* R27[7:0] highest,highest */
  196. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  197. /* .xtal_cap10p = */ 0x00,
  198. /* .xtal_cap0p = */ 0x00,
  199. }, {
  200. /* .freq = */ 588, /* Start freq, in MHz */
  201. /* .open_d = */ 0x00, /* high */
  202. /* .rf_mux_ploy = */ 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
  203. /* .tf_c = */ 0x00, /* R27[7:0] highest,highest */
  204. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  205. /* .xtal_cap10p = */ 0x00,
  206. /* .xtal_cap0p = */ 0x00,
  207. }, {
  208. /* .freq = */ 650, /* Start freq, in MHz */
  209. /* .open_d = */ 0x00, /* high */
  210. /* .rf_mux_ploy = */ 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
  211. /* .tf_c = */ 0x00, /* R27[7:0] highest,highest */
  212. /* .xtal_cap20p = */ 0x00, /* R16[1:0] 0pF (00) */
  213. /* .xtal_cap10p = */ 0x00,
  214. /* .xtal_cap0p = */ 0x00,
  215. }
  216. };
  217. static int r82xx_xtal_capacitor[][2] = {
  218. { 0x0b, XTAL_LOW_CAP_30P },
  219. { 0x02, XTAL_LOW_CAP_20P },
  220. { 0x01, XTAL_LOW_CAP_10P },
  221. { 0x00, XTAL_LOW_CAP_0P },
  222. { 0x10, XTAL_HIGH_CAP_0P },
  223. };
  224. /*
  225. * I2C read/write code and shadow registers logic
  226. */
  227. static void shadow_store(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
  228. int len)
  229. {
  230. int r = reg - REG_SHADOW_START;
  231. if (r < 0) {
  232. len += r;
  233. r = 0;
  234. }
  235. if (len <= 0)
  236. return;
  237. if (len > NUM_REGS - r)
  238. len = NUM_REGS - r;
  239. memcpy(&priv->regs[r], val, len);
  240. }
  241. static int r82xx_write(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
  242. unsigned int len)
  243. {
  244. int rc, size, pos = 0;
  245. /* Store the shadow registers */
  246. shadow_store(priv, reg, val, len);
  247. do {
  248. if (len > priv->cfg->max_i2c_msg_len - 1)
  249. size = priv->cfg->max_i2c_msg_len - 1;
  250. else
  251. size = len;
  252. /* Fill I2C buffer */
  253. priv->buf[0] = reg;
  254. memcpy(&priv->buf[1], &val[pos], size);
  255. rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr,
  256. priv->buf, size + 1);
  257. if (rc != size + 1) {
  258. fprintf(stderr, "%s: i2c wr failed=%d reg=%02x len=%d\n",
  259. __FUNCTION__, rc, reg, size);
  260. if (rc < 0)
  261. return rc;
  262. return -1;
  263. }
  264. reg += size;
  265. len -= size;
  266. pos += size;
  267. } while (len > 0);
  268. return 0;
  269. }
  270. static int r82xx_write_reg(struct r82xx_priv *priv, uint8_t reg, uint8_t val)
  271. {
  272. return r82xx_write(priv, reg, &val, 1);
  273. }
  274. static int r82xx_read_cache_reg(struct r82xx_priv *priv, int reg)
  275. {
  276. reg -= REG_SHADOW_START;
  277. if (reg >= 0 && reg < NUM_REGS)
  278. return priv->regs[reg];
  279. else
  280. return -1;
  281. }
  282. static int r82xx_write_reg_mask(struct r82xx_priv *priv, uint8_t reg, uint8_t val,
  283. uint8_t bit_mask)
  284. {
  285. int rc = r82xx_read_cache_reg(priv, reg);
  286. if (rc < 0)
  287. return rc;
  288. val = (rc & ~bit_mask) | (val & bit_mask);
  289. return r82xx_write(priv, reg, &val, 1);
  290. }
  291. static uint8_t r82xx_bitrev(uint8_t byte)
  292. {
  293. const uint8_t lut[16] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
  294. 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
  295. return (lut[byte & 0xf] << 4) | lut[byte >> 4];
  296. }
  297. static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int len)
  298. {
  299. int rc, i;
  300. uint8_t *p = &priv->buf[1];
  301. priv->buf[0] = reg;
  302. rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr, priv->buf, 1);
  303. if (rc < 1)
  304. return rc;
  305. rc = rtlsdr_i2c_read_fn(priv->rtl_dev, priv->cfg->i2c_addr, p, len);
  306. if (rc != len) {
  307. fprintf(stderr, "%s: i2c rd failed=%d reg=%02x len=%d\n",
  308. __FUNCTION__, rc, reg, len);
  309. if (rc < 0)
  310. return rc;
  311. return -1;
  312. }
  313. /* Copy data to the output buffer */
  314. for (i = 0; i < len; i++)
  315. val[i] = r82xx_bitrev(p[i]);
  316. return 0;
  317. }
  318. /*
  319. * r82xx tuning logic
  320. */
  321. static int r82xx_set_mux(struct r82xx_priv *priv, uint32_t freq)
  322. {
  323. const struct r82xx_freq_range *range;
  324. int rc;
  325. unsigned int i;
  326. uint8_t val;
  327. /* Get the proper frequency range */
  328. freq = freq / 1000000;
  329. for (i = 0; i < ARRAY_SIZE(freq_ranges) - 1; i++) {
  330. if (freq < freq_ranges[i + 1].freq)
  331. break;
  332. }
  333. range = &freq_ranges[i];
  334. /* Open Drain */
  335. rc = r82xx_write_reg_mask(priv, 0x17, range->open_d, 0x08);
  336. if (rc < 0)
  337. return rc;
  338. /* RF_MUX,Polymux */
  339. rc = r82xx_write_reg_mask(priv, 0x1a, range->rf_mux_ploy, 0xc3);
  340. if (rc < 0)
  341. return rc;
  342. /* TF BAND */
  343. rc = r82xx_write_reg(priv, 0x1b, range->tf_c);
  344. if (rc < 0)
  345. return rc;
  346. /* XTAL CAP & Drive */
  347. switch (priv->xtal_cap_sel) {
  348. case XTAL_LOW_CAP_30P:
  349. case XTAL_LOW_CAP_20P:
  350. val = range->xtal_cap20p | 0x08;
  351. break;
  352. case XTAL_LOW_CAP_10P:
  353. val = range->xtal_cap10p | 0x08;
  354. break;
  355. case XTAL_HIGH_CAP_0P:
  356. val = range->xtal_cap0p | 0x00;
  357. break;
  358. default:
  359. case XTAL_LOW_CAP_0P:
  360. val = range->xtal_cap0p | 0x08;
  361. break;
  362. }
  363. rc = r82xx_write_reg_mask(priv, 0x10, val, 0x0b);
  364. if (rc < 0)
  365. return rc;
  366. rc = r82xx_write_reg_mask(priv, 0x08, 0x00, 0x3f);
  367. if (rc < 0)
  368. return rc;
  369. rc = r82xx_write_reg_mask(priv, 0x09, 0x00, 0x3f);
  370. return rc;
  371. }
  372. static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
  373. {
  374. int rc, i;
  375. unsigned sleep_time = 10000;
  376. uint64_t vco_freq;
  377. uint32_t vco_fra; /* VCO contribution by SDM (kHz) */
  378. uint32_t vco_min = 1770000;
  379. uint32_t vco_max = vco_min * 2;
  380. uint32_t freq_khz, pll_ref, pll_ref_khz;
  381. uint16_t n_sdm = 2;
  382. uint16_t sdm = 0;
  383. uint8_t mix_div = 2;
  384. uint8_t div_buf = 0;
  385. uint8_t div_num = 0;
  386. uint8_t vco_power_ref = 2;
  387. uint8_t refdiv2 = 0;
  388. uint8_t ni, si, nint, vco_fine_tune, val;
  389. uint8_t data[5];
  390. /* Frequency in kHz */
  391. freq_khz = (freq + 500) / 1000;
  392. pll_ref = priv->cfg->xtal;
  393. pll_ref_khz = (priv->cfg->xtal + 500) / 1000;
  394. rc = r82xx_write_reg_mask(priv, 0x10, refdiv2, 0x10);
  395. if (rc < 0)
  396. return rc;
  397. /* set pll autotune = 128kHz */
  398. rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
  399. if (rc < 0)
  400. return rc;
  401. /* set VCO current = 100 */
  402. rc = r82xx_write_reg_mask(priv, 0x12, 0x80, 0xe0);
  403. if (rc < 0)
  404. return rc;
  405. /* Calculate divider */
  406. while (mix_div <= 64) {
  407. if (((freq_khz * mix_div) >= vco_min) &&
  408. ((freq_khz * mix_div) < vco_max)) {
  409. div_buf = mix_div;
  410. while (div_buf > 2) {
  411. div_buf = div_buf >> 1;
  412. div_num++;
  413. }
  414. break;
  415. }
  416. mix_div = mix_div << 1;
  417. }
  418. rc = r82xx_read(priv, 0x00, data, sizeof(data));
  419. if (rc < 0)
  420. return rc;
  421. if (priv->cfg->rafael_chip == CHIP_R828D)
  422. vco_power_ref = 1;
  423. vco_fine_tune = (data[4] & 0x30) >> 4;
  424. if (vco_fine_tune > vco_power_ref)
  425. div_num = div_num - 1;
  426. else if (vco_fine_tune < vco_power_ref)
  427. div_num = div_num + 1;
  428. rc = r82xx_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);
  429. if (rc < 0)
  430. return rc;
  431. vco_freq = (uint64_t)freq * (uint64_t)mix_div;
  432. nint = vco_freq / (2 * pll_ref);
  433. vco_fra = (vco_freq - 2 * pll_ref * nint) / 1000;
  434. if (nint > ((128 / vco_power_ref) - 1)) {
  435. fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq);
  436. return -1;
  437. }
  438. ni = (nint - 13) / 4;
  439. si = nint - 4 * ni - 13;
  440. rc = r82xx_write_reg(priv, 0x14, ni + (si << 6));
  441. if (rc < 0)
  442. return rc;
  443. /* pw_sdm */
  444. if (!vco_fra)
  445. val = 0x08;
  446. else
  447. val = 0x00;
  448. rc = r82xx_write_reg_mask(priv, 0x12, val, 0x08);
  449. if (rc < 0)
  450. return rc;
  451. /* sdm calculator */
  452. while (vco_fra > 1) {
  453. if (vco_fra > (2 * pll_ref_khz / n_sdm)) {
  454. sdm = sdm + 32768 / (n_sdm / 2);
  455. vco_fra = vco_fra - 2 * pll_ref_khz / n_sdm;
  456. if (n_sdm >= 0x8000)
  457. break;
  458. }
  459. n_sdm <<= 1;
  460. }
  461. rc = r82xx_write_reg(priv, 0x16, sdm >> 8);
  462. if (rc < 0)
  463. return rc;
  464. rc = r82xx_write_reg(priv, 0x15, sdm & 0xff);
  465. if (rc < 0)
  466. return rc;
  467. for (i = 0; i < 2; i++) {
  468. // usleep_range(sleep_time, sleep_time + 1000);
  469. /* Check if PLL has locked */
  470. rc = r82xx_read(priv, 0x00, data, 3);
  471. if (rc < 0)
  472. return rc;
  473. if (data[2] & 0x40)
  474. break;
  475. if (!i) {
  476. /* Didn't lock. Increase VCO current */
  477. rc = r82xx_write_reg_mask(priv, 0x12, 0x60, 0xe0);
  478. if (rc < 0)
  479. return rc;
  480. }
  481. }
  482. if (!(data[2] & 0x40)) {
  483. printf("[R82XX] PLL not locked!\n");
  484. priv->has_lock = 0;
  485. return 0;
  486. }
  487. priv->has_lock = 1;
  488. /* set pll autotune = 8kHz */
  489. rc = r82xx_write_reg_mask(priv, 0x1a, 0x08, 0x08);
  490. return rc;
  491. }
  492. static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq,
  493. enum r82xx_tuner_type type,
  494. uint32_t delsys)
  495. {
  496. int rc;
  497. uint8_t mixer_top, lna_top, cp_cur, div_buf_cur, lna_vth_l, mixer_vth_l;
  498. uint8_t air_cable1_in, cable2_in, pre_dect, lna_discharge, filter_cur;
  499. switch (delsys) {
  500. case SYS_DVBT:
  501. if ((freq == 506000000) || (freq == 666000000) ||
  502. (freq == 818000000)) {
  503. mixer_top = 0x14; /* mixer top:14 , top-1, low-discharge */
  504. lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
  505. cp_cur = 0x28; /* 101, 0.2 */
  506. div_buf_cur = 0x20; /* 10, 200u */
  507. } else {
  508. mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
  509. lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
  510. cp_cur = 0x38; /* 111, auto */
  511. div_buf_cur = 0x30; /* 11, 150u */
  512. }
  513. lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
  514. mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
  515. air_cable1_in = 0x00;
  516. cable2_in = 0x00;
  517. pre_dect = 0x40;
  518. lna_discharge = 14;
  519. filter_cur = 0x40; /* 10, low */
  520. break;
  521. case SYS_DVBT2:
  522. mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
  523. lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
  524. lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
  525. mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
  526. air_cable1_in = 0x00;
  527. cable2_in = 0x00;
  528. pre_dect = 0x40;
  529. lna_discharge = 14;
  530. cp_cur = 0x38; /* 111, auto */
  531. div_buf_cur = 0x30; /* 11, 150u */
  532. filter_cur = 0x40; /* 10, low */
  533. break;
  534. case SYS_ISDBT:
  535. mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
  536. lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
  537. lna_vth_l = 0x75; /* lna vth 1.04 , vtl 0.84 */
  538. mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
  539. air_cable1_in = 0x00;
  540. cable2_in = 0x00;
  541. pre_dect = 0x40;
  542. lna_discharge = 14;
  543. cp_cur = 0x38; /* 111, auto */
  544. div_buf_cur = 0x30; /* 11, 150u */
  545. filter_cur = 0x40; /* 10, low */
  546. break;
  547. default: /* DVB-T 8M */
  548. mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
  549. lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
  550. lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
  551. mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
  552. air_cable1_in = 0x00;
  553. cable2_in = 0x00;
  554. pre_dect = 0x40;
  555. lna_discharge = 14;
  556. cp_cur = 0x38; /* 111, auto */
  557. div_buf_cur = 0x30; /* 11, 150u */
  558. filter_cur = 0x40; /* 10, low */
  559. break;
  560. }
  561. if (priv->cfg->use_predetect) {
  562. rc = r82xx_write_reg_mask(priv, 0x06, pre_dect, 0x40);
  563. if (rc < 0)
  564. return rc;
  565. }
  566. rc = r82xx_write_reg_mask(priv, 0x1d, lna_top, 0xc7);
  567. if (rc < 0)
  568. return rc;
  569. rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0xf8);
  570. if (rc < 0)
  571. return rc;
  572. rc = r82xx_write_reg(priv, 0x0d, lna_vth_l);
  573. if (rc < 0)
  574. return rc;
  575. rc = r82xx_write_reg(priv, 0x0e, mixer_vth_l);
  576. if (rc < 0)
  577. return rc;
  578. priv->input = air_cable1_in;
  579. /* Air-IN only for Astrometa */
  580. rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
  581. if (rc < 0)
  582. return rc;
  583. rc = r82xx_write_reg_mask(priv, 0x06, cable2_in, 0x08);
  584. if (rc < 0)
  585. return rc;
  586. rc = r82xx_write_reg_mask(priv, 0x11, cp_cur, 0x38);
  587. if (rc < 0)
  588. return rc;
  589. rc = r82xx_write_reg_mask(priv, 0x17, div_buf_cur, 0x30);
  590. if (rc < 0)
  591. return rc;
  592. rc = r82xx_write_reg_mask(priv, 0x0a, filter_cur, 0x60);
  593. if (rc < 0)
  594. return rc;
  595. /*
  596. * Set LNA
  597. */
  598. if (type != TUNER_ANALOG_TV) {
  599. /* LNA TOP: lowest */
  600. rc = r82xx_write_reg_mask(priv, 0x1d, 0, 0x38);
  601. if (rc < 0)
  602. return rc;
  603. /* 0: normal mode */
  604. rc = r82xx_write_reg_mask(priv, 0x1c, 0, 0x04);
  605. if (rc < 0)
  606. return rc;
  607. /* 0: PRE_DECT off */
  608. rc = r82xx_write_reg_mask(priv, 0x06, 0, 0x40);
  609. if (rc < 0)
  610. return rc;
  611. /* agc clk 250hz */
  612. rc = r82xx_write_reg_mask(priv, 0x1a, 0x30, 0x30);
  613. if (rc < 0)
  614. return rc;
  615. // msleep(250);
  616. /* write LNA TOP = 3 */
  617. rc = r82xx_write_reg_mask(priv, 0x1d, 0x18, 0x38);
  618. if (rc < 0)
  619. return rc;
  620. /*
  621. * write discharge mode
  622. * FIXME: IMHO, the mask here is wrong, but it matches
  623. * what's there at the original driver
  624. */
  625. rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
  626. if (rc < 0)
  627. return rc;
  628. /* LNA discharge current */
  629. rc = r82xx_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
  630. if (rc < 0)
  631. return rc;
  632. /* agc clk 60hz */
  633. rc = r82xx_write_reg_mask(priv, 0x1a, 0x20, 0x30);
  634. if (rc < 0)
  635. return rc;
  636. } else {
  637. /* PRE_DECT off */
  638. rc = r82xx_write_reg_mask(priv, 0x06, 0, 0x40);
  639. if (rc < 0)
  640. return rc;
  641. /* write LNA TOP */
  642. rc = r82xx_write_reg_mask(priv, 0x1d, lna_top, 0x38);
  643. if (rc < 0)
  644. return rc;
  645. /*
  646. * write discharge mode
  647. * FIXME: IMHO, the mask here is wrong, but it matches
  648. * what's there at the original driver
  649. */
  650. rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
  651. if (rc < 0)
  652. return rc;
  653. /* LNA discharge current */
  654. rc = r82xx_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
  655. if (rc < 0)
  656. return rc;
  657. /* agc clk 1Khz, external det1 cap 1u */
  658. rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x30);
  659. if (rc < 0)
  660. return rc;
  661. rc = r82xx_write_reg_mask(priv, 0x10, 0x00, 0x04);
  662. if (rc < 0)
  663. return rc;
  664. }
  665. return 0;
  666. }
  667. static int r82xx_set_tv_standard(struct r82xx_priv *priv,
  668. unsigned bw,
  669. enum r82xx_tuner_type type,
  670. uint32_t delsys)
  671. {
  672. int rc, i;
  673. uint32_t if_khz, filt_cal_lo;
  674. uint8_t data[5];
  675. uint8_t filt_gain, img_r, filt_q, hp_cor, ext_enable, loop_through;
  676. uint8_t lt_att, flt_ext_widest, polyfil_cur;
  677. int need_calibration;
  678. if (delsys == SYS_ISDBT) {
  679. if_khz = 4063;
  680. filt_cal_lo = 59000;
  681. filt_gain = 0x10; /* +3db, 6mhz on */
  682. img_r = 0x00; /* image negative */
  683. filt_q = 0x10; /* r10[4]:low q(1'b1) */
  684. hp_cor = 0x6a; /* 1.7m disable, +2cap, 1.25mhz */
  685. ext_enable = 0x40; /* r30[6], ext enable; r30[5]:0 ext at lna max */
  686. loop_through = 0x00; /* r5[7], lt on */
  687. lt_att = 0x00; /* r31[7], lt att enable */
  688. flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
  689. polyfil_cur = 0x60; /* r25[6:5]:min */
  690. } else {
  691. if (bw <= 6) {
  692. if_khz = 3570;
  693. filt_cal_lo = 56000; /* 52000->56000 */
  694. filt_gain = 0x10; /* +3db, 6mhz on */
  695. img_r = 0x00; /* image negative */
  696. filt_q = 0x10; /* r10[4]:low q(1'b1) */
  697. hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */
  698. ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
  699. loop_through = 0x00; /* r5[7], lt on */
  700. lt_att = 0x00; /* r31[7], lt att enable */
  701. flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
  702. polyfil_cur = 0x60; /* r25[6:5]:min */
  703. } else if (bw == 7) {
  704. #if 0
  705. /*
  706. * There are two 7 MHz tables defined on the original
  707. * driver, but just the second one seems to be visible
  708. * by rtl2832. Keep this one here commented, as it
  709. * might be needed in the future
  710. */
  711. if_khz = 4070;
  712. filt_cal_lo = 60000;
  713. filt_gain = 0x10; /* +3db, 6mhz on */
  714. img_r = 0x00; /* image negative */
  715. filt_q = 0x10; /* r10[4]:low q(1'b1) */
  716. hp_cor = 0x2b; /* 1.7m disable, +1cap, 1.0mhz */
  717. ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
  718. loop_through = 0x00; /* r5[7], lt on */
  719. lt_att = 0x00; /* r31[7], lt att enable */
  720. flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
  721. polyfil_cur = 0x60; /* r25[6:5]:min */
  722. #endif
  723. /* 7 MHz, second table */
  724. if_khz = 4570;
  725. filt_cal_lo = 63000;
  726. filt_gain = 0x10; /* +3db, 6mhz on */
  727. img_r = 0x00; /* image negative */
  728. filt_q = 0x10; /* r10[4]:low q(1'b1) */
  729. hp_cor = 0x2a; /* 1.7m disable, +1cap, 1.25mhz */
  730. ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
  731. loop_through = 0x00; /* r5[7], lt on */
  732. lt_att = 0x00; /* r31[7], lt att enable */
  733. flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
  734. polyfil_cur = 0x60; /* r25[6:5]:min */
  735. } else {
  736. if_khz = 4570;
  737. filt_cal_lo = 68500;
  738. filt_gain = 0x10; /* +3db, 6mhz on */
  739. img_r = 0x00; /* image negative */
  740. filt_q = 0x10; /* r10[4]:low q(1'b1) */
  741. hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */
  742. ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
  743. loop_through = 0x00; /* r5[7], lt on */
  744. lt_att = 0x00; /* r31[7], lt att enable */
  745. flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
  746. polyfil_cur = 0x60; /* r25[6:5]:min */
  747. }
  748. }
  749. /* Initialize the shadow registers */
  750. memcpy(priv->regs, r82xx_init_array, sizeof(r82xx_init_array));
  751. /* Init Flag & Xtal_check Result (inits VGA gain, needed?)*/
  752. rc = r82xx_write_reg_mask(priv, 0x0c, 0x00, 0x0f);
  753. if (rc < 0)
  754. return rc;
  755. /* version */
  756. rc = r82xx_write_reg_mask(priv, 0x13, VER_NUM, 0x3f);
  757. if (rc < 0)
  758. return rc;
  759. /* for LT Gain test */
  760. if (type != TUNER_ANALOG_TV) {
  761. rc = r82xx_write_reg_mask(priv, 0x1d, 0x00, 0x38);
  762. if (rc < 0)
  763. return rc;
  764. // usleep_range(1000, 2000);
  765. }
  766. priv->int_freq = if_khz * 1000;
  767. /* Check if standard changed. If so, filter calibration is needed */
  768. /* as we call this function only once in rtlsdr, force calibration */
  769. need_calibration = 1;
  770. if (need_calibration) {
  771. for (i = 0; i < 2; i++) {
  772. /* Set filt_cap */
  773. rc = r82xx_write_reg_mask(priv, 0x0b, hp_cor, 0x60);
  774. if (rc < 0)
  775. return rc;
  776. /* set cali clk =on */
  777. rc = r82xx_write_reg_mask(priv, 0x0f, 0x04, 0x04);
  778. if (rc < 0)
  779. return rc;
  780. /* X'tal cap 0pF for PLL */
  781. rc = r82xx_write_reg_mask(priv, 0x10, 0x00, 0x03);
  782. if (rc < 0)
  783. return rc;
  784. rc = r82xx_set_pll(priv, filt_cal_lo * 1000);
  785. if (rc < 0 || !priv->has_lock)
  786. return rc;
  787. /* Start Trigger */
  788. rc = r82xx_write_reg_mask(priv, 0x0b, 0x10, 0x10);
  789. if (rc < 0)
  790. return rc;
  791. // usleep_range(1000, 2000);
  792. /* Stop Trigger */
  793. rc = r82xx_write_reg_mask(priv, 0x0b, 0x00, 0x10);
  794. if (rc < 0)
  795. return rc;
  796. /* set cali clk =off */
  797. rc = r82xx_write_reg_mask(priv, 0x0f, 0x00, 0x04);
  798. if (rc < 0)
  799. return rc;
  800. /* Check if calibration worked */
  801. rc = r82xx_read(priv, 0x00, data, sizeof(data));
  802. if (rc < 0)
  803. return rc;
  804. priv->fil_cal_code = data[4] & 0x0f;
  805. if (priv->fil_cal_code && priv->fil_cal_code != 0x0f)
  806. break;
  807. }
  808. /* narrowest */
  809. if (priv->fil_cal_code == 0x0f)
  810. priv->fil_cal_code = 0;
  811. }
  812. rc = r82xx_write_reg_mask(priv, 0x0a,
  813. filt_q | priv->fil_cal_code, 0x1f);
  814. if (rc < 0)
  815. return rc;
  816. /* Set BW, Filter_gain, & HP corner */
  817. rc = r82xx_write_reg_mask(priv, 0x0b, hp_cor, 0xef);
  818. if (rc < 0)
  819. return rc;
  820. /* Set Img_R */
  821. rc = r82xx_write_reg_mask(priv, 0x07, img_r, 0x80);
  822. if (rc < 0)
  823. return rc;
  824. /* Set filt_3dB, V6MHz */
  825. rc = r82xx_write_reg_mask(priv, 0x06, filt_gain, 0x30);
  826. if (rc < 0)
  827. return rc;
  828. /* channel filter extension */
  829. rc = r82xx_write_reg_mask(priv, 0x1e, ext_enable, 0x60);
  830. if (rc < 0)
  831. return rc;
  832. /* Loop through */
  833. rc = r82xx_write_reg_mask(priv, 0x05, loop_through, 0x80);
  834. if (rc < 0)
  835. return rc;
  836. /* Loop through attenuation */
  837. rc = r82xx_write_reg_mask(priv, 0x1f, lt_att, 0x80);
  838. if (rc < 0)
  839. return rc;
  840. /* filter extension widest */
  841. rc = r82xx_write_reg_mask(priv, 0x0f, flt_ext_widest, 0x80);
  842. if (rc < 0)
  843. return rc;
  844. /* RF poly filter current */
  845. rc = r82xx_write_reg_mask(priv, 0x19, polyfil_cur, 0x60);
  846. if (rc < 0)
  847. return rc;
  848. /* Store current standard. If it changes, re-calibrate the tuner */
  849. priv->delsys = delsys;
  850. priv->type = type;
  851. priv->bw = bw;
  852. return 0;
  853. }
  854. static int r82xx_read_gain(struct r82xx_priv *priv)
  855. {
  856. uint8_t data[4];
  857. int rc;
  858. rc = r82xx_read(priv, 0x00, data, sizeof(data));
  859. if (rc < 0)
  860. return rc;
  861. return ((data[3] & 0x0f) << 1) + ((data[3] & 0xf0) >> 4);
  862. }
  863. /* measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm
  864. * input power, for raw results see:
  865. * http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/
  866. */
  867. #define VGA_BASE_GAIN -47
  868. static const int r82xx_vga_gain_steps[] = {
  869. 0, 26, 26, 30, 42, 35, 24, 13, 14, 32, 36, 34, 35, 37, 35, 36
  870. };
  871. static const int r82xx_lna_gain_steps[] = {
  872. 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13
  873. };
  874. static const int r82xx_mixer_gain_steps[] = {
  875. 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8
  876. };
  877. int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain)
  878. {
  879. int rc;
  880. if (set_manual_gain) {
  881. int i, total_gain = 0;
  882. uint8_t mix_index = 0, lna_index = 0;
  883. uint8_t data[4];
  884. /* LNA auto off */
  885. rc = r82xx_write_reg_mask(priv, 0x05, 0x10, 0x10);
  886. if (rc < 0)
  887. return rc;
  888. /* Mixer auto off */
  889. rc = r82xx_write_reg_mask(priv, 0x07, 0, 0x10);
  890. if (rc < 0)
  891. return rc;
  892. rc = r82xx_read(priv, 0x00, data, sizeof(data));
  893. if (rc < 0)
  894. return rc;
  895. /* set fixed VGA gain for now (16.3 dB) */
  896. rc = r82xx_write_reg_mask(priv, 0x0c, 0x08, 0x9f);
  897. if (rc < 0)
  898. return rc;
  899. for (i = 0; i < 15; i++) {
  900. if (total_gain >= gain)
  901. break;
  902. total_gain += r82xx_lna_gain_steps[++lna_index];
  903. if (total_gain >= gain)
  904. break;
  905. total_gain += r82xx_mixer_gain_steps[++mix_index];
  906. }
  907. /* set LNA gain */
  908. rc = r82xx_write_reg_mask(priv, 0x05, lna_index, 0x0f);
  909. if (rc < 0)
  910. return rc;
  911. /* set Mixer gain */
  912. rc = r82xx_write_reg_mask(priv, 0x07, mix_index, 0x0f);
  913. if (rc < 0)
  914. return rc;
  915. } else {
  916. /* LNA */
  917. rc = r82xx_write_reg_mask(priv, 0x05, 0, 0x10);
  918. if (rc < 0)
  919. return rc;
  920. /* Mixer */
  921. rc = r82xx_write_reg_mask(priv, 0x07, 0x10, 0x10);
  922. if (rc < 0)
  923. return rc;
  924. /* set fixed VGA gain for now (26.5 dB) */
  925. rc = r82xx_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);
  926. if (rc < 0)
  927. return rc;
  928. }
  929. return 0;
  930. }
  931. int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
  932. {
  933. int rc = -1;
  934. uint32_t lo_freq = freq + priv->int_freq;
  935. uint8_t air_cable1_in;
  936. rc = r82xx_set_mux(priv, lo_freq);
  937. if (rc < 0)
  938. goto err;
  939. rc = r82xx_set_pll(priv, lo_freq);
  940. if (rc < 0 || !priv->has_lock)
  941. goto err;
  942. /* switch between 'Cable1' and 'Air-In' inputs on sticks with
  943. * R828D tuner. We switch at 345 MHz, because that's where the
  944. * noise-floor has about the same level with identical LNA
  945. * settings. The original driver used 320 MHz. */
  946. air_cable1_in = (freq > MHZ(345)) ? 0x00 : 0x60;
  947. if ((priv->cfg->rafael_chip == CHIP_R828D) &&
  948. (air_cable1_in != priv->input)) {
  949. priv->input = air_cable1_in;
  950. rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
  951. }
  952. err:
  953. if (rc < 0)
  954. fprintf(stderr, "%s: failed=%d\n", __FUNCTION__, rc);
  955. return rc;
  956. }
  957. /*
  958. * r82xx standby logic
  959. */
  960. int r82xx_standby(struct r82xx_priv *priv)
  961. {
  962. int rc;
  963. /* If device was not initialized yet, don't need to standby */
  964. if (!priv->init_done)
  965. return 0;
  966. rc = r82xx_write_reg(priv, 0x06, 0xb1);
  967. if (rc < 0)
  968. return rc;
  969. rc = r82xx_write_reg(priv, 0x05, 0x03);
  970. if (rc < 0)
  971. return rc;
  972. rc = r82xx_write_reg(priv, 0x07, 0x3a);
  973. if (rc < 0)
  974. return rc;
  975. rc = r82xx_write_reg(priv, 0x08, 0x40);
  976. if (rc < 0)
  977. return rc;
  978. rc = r82xx_write_reg(priv, 0x09, 0xc0);
  979. if (rc < 0)
  980. return rc;
  981. rc = r82xx_write_reg(priv, 0x0a, 0x36);
  982. if (rc < 0)
  983. return rc;
  984. rc = r82xx_write_reg(priv, 0x0c, 0x35);
  985. if (rc < 0)
  986. return rc;
  987. rc = r82xx_write_reg(priv, 0x0f, 0x68);
  988. if (rc < 0)
  989. return rc;
  990. rc = r82xx_write_reg(priv, 0x11, 0x03);
  991. if (rc < 0)
  992. return rc;
  993. rc = r82xx_write_reg(priv, 0x17, 0xf4);
  994. if (rc < 0)
  995. return rc;
  996. rc = r82xx_write_reg(priv, 0x19, 0x0c);
  997. /* Force initial calibration */
  998. priv->type = -1;
  999. return rc;
  1000. }
  1001. /*
  1002. * r82xx device init logic
  1003. */
  1004. static int r82xx_xtal_check(struct r82xx_priv *priv)
  1005. {
  1006. int rc;
  1007. unsigned int i;
  1008. uint8_t data[3], val;
  1009. /* Initialize the shadow registers */
  1010. memcpy(priv->regs, r82xx_init_array, sizeof(r82xx_init_array));
  1011. /* cap 30pF & Drive Low */
  1012. rc = r82xx_write_reg_mask(priv, 0x10, 0x0b, 0x0b);
  1013. if (rc < 0)
  1014. return rc;
  1015. /* set pll autotune = 128kHz */
  1016. rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
  1017. if (rc < 0)
  1018. return rc;
  1019. /* set manual initial reg = 111111; */
  1020. rc = r82xx_write_reg_mask(priv, 0x13, 0x7f, 0x7f);
  1021. if (rc < 0)
  1022. return rc;
  1023. /* set auto */
  1024. rc = r82xx_write_reg_mask(priv, 0x13, 0x00, 0x40);
  1025. if (rc < 0)
  1026. return rc;
  1027. /* Try several xtal capacitor alternatives */
  1028. for (i = 0; i < ARRAY_SIZE(r82xx_xtal_capacitor); i++) {
  1029. rc = r82xx_write_reg_mask(priv, 0x10,
  1030. r82xx_xtal_capacitor[i][0], 0x1b);
  1031. if (rc < 0)
  1032. return rc;
  1033. // usleep_range(5000, 6000);
  1034. rc = r82xx_read(priv, 0x00, data, sizeof(data));
  1035. if (rc < 0)
  1036. return rc;
  1037. if (!(data[2] & 0x40))
  1038. continue;
  1039. val = data[2] & 0x3f;
  1040. if (priv->cfg->xtal == 16000000 && (val > 29 || val < 23))
  1041. break;
  1042. if (val != 0x3f)
  1043. break;
  1044. }
  1045. if (i == ARRAY_SIZE(r82xx_xtal_capacitor))
  1046. return -1;
  1047. return r82xx_xtal_capacitor[i][1];
  1048. }
  1049. int r82xx_init(struct r82xx_priv *priv)
  1050. {
  1051. int rc;
  1052. /* TODO: R828D might need r82xx_xtal_check() */
  1053. priv->xtal_cap_sel = XTAL_HIGH_CAP_0P;
  1054. /* Initialize registers */
  1055. rc = r82xx_write(priv, 0x05,
  1056. r82xx_init_array, sizeof(r82xx_init_array));
  1057. rc = r82xx_set_tv_standard(priv, 3, TUNER_DIGITAL_TV, 0);
  1058. if (rc < 0)
  1059. goto err;
  1060. rc = r82xx_sysfreq_sel(priv, 0, TUNER_DIGITAL_TV, SYS_DVBT);
  1061. priv->init_done = 1;
  1062. err:
  1063. if (rc < 0)
  1064. fprintf(stderr, "%s: failed=%d\n", __FUNCTION__, rc);
  1065. return rc;
  1066. }
  1067. #if 0
  1068. /* Not used, for now */
  1069. static int r82xx_gpio(struct r82xx_priv *priv, int enable)
  1070. {
  1071. return r82xx_write_reg_mask(priv, 0x0f, enable ? 1 : 0, 0x01);
  1072. }
  1073. #endif