drx397xD.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505
  1. /*
  2. * Driver for Micronas drx397xD demodulator
  3. *
  4. * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #define DEBUG /* uncomment if you want debugging output */
  20. #include <linux/kernel.h>
  21. #include <linux/module.h>
  22. #include <linux/moduleparam.h>
  23. #include <linux/init.h>
  24. #include <linux/device.h>
  25. #include <linux/delay.h>
  26. #include <linux/string.h>
  27. #include <linux/firmware.h>
  28. #include "dvb_frontend.h"
  29. #include "drx397xD.h"
  30. static const char mod_name[] = "drx397xD";
  31. #define MAX_CLOCK_DRIFT 200 /* maximal 200 PPM allowed */
  32. #define F_SET_0D0h 1
  33. #define F_SET_0D4h 2
  34. typedef enum fw_ix {
  35. #define _FW_ENTRY(a, b) b
  36. #include "drx397xD_fw.h"
  37. } fw_ix_t;
  38. /* chip specifics */
  39. struct drx397xD_state {
  40. struct i2c_adapter *i2c;
  41. struct dvb_frontend frontend;
  42. struct drx397xD_config config;
  43. fw_ix_t chip_rev;
  44. int flags;
  45. u32 bandwidth_parm; /* internal bandwidth conversions */
  46. u32 f_osc; /* w90: actual osc frequency [Hz] */
  47. };
  48. /*******************************************************************************
  49. * Firmware
  50. ******************************************************************************/
  51. static const char *blob_name[] = {
  52. #define _BLOB_ENTRY(a, b) a
  53. #include "drx397xD_fw.h"
  54. };
  55. typedef enum blob_ix {
  56. #define _BLOB_ENTRY(a, b) b
  57. #include "drx397xD_fw.h"
  58. } blob_ix_t;
  59. static struct {
  60. const char *name;
  61. const struct firmware *file;
  62. rwlock_t lock;
  63. int refcnt;
  64. u8 *data[ARRAY_SIZE(blob_name)];
  65. } fw[] = {
  66. #define _FW_ENTRY(a, b) { \
  67. .name = a, \
  68. .file = 0, \
  69. .lock = RW_LOCK_UNLOCKED, \
  70. .refcnt = 0, \
  71. .data = { } }
  72. #include "drx397xD_fw.h"
  73. };
  74. /* use only with writer lock aquired */
  75. static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
  76. {
  77. memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
  78. if (fw[ix].file)
  79. release_firmware(fw[ix].file);
  80. }
  81. static void drx_release_fw(struct drx397xD_state *s)
  82. {
  83. fw_ix_t ix = s->chip_rev;
  84. pr_debug("%s\n", __FUNCTION__);
  85. write_lock(&fw[ix].lock);
  86. if (fw[ix].refcnt) {
  87. fw[ix].refcnt--;
  88. if (fw[ix].refcnt == 0)
  89. _drx_release_fw(s, ix);
  90. }
  91. write_unlock(&fw[ix].lock);
  92. }
  93. static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
  94. {
  95. u8 *data;
  96. size_t size, len;
  97. int i = 0, j, rc = -EINVAL;
  98. pr_debug("%s\n", __FUNCTION__);
  99. if (ix < 0 || ix >= ARRAY_SIZE(fw))
  100. return -EINVAL;
  101. s->chip_rev = ix;
  102. write_lock(&fw[ix].lock);
  103. if (fw[ix].file) {
  104. rc = 0;
  105. goto exit_ok;
  106. }
  107. memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
  108. if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
  109. printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
  110. mod_name, fw[ix].name);
  111. rc = -ENOENT;
  112. goto exit_err;
  113. }
  114. if (!fw[ix].file->data || fw[ix].file->size < 10)
  115. goto exit_corrupt;
  116. data = fw[ix].file->data;
  117. size = fw[ix].file->size;
  118. if (data[i++] != 2) /* check firmware version */
  119. goto exit_corrupt;
  120. do {
  121. switch (data[i++]) {
  122. case 0x00: /* bytecode */
  123. if (i >= size)
  124. break;
  125. i += data[i];
  126. case 0x01: /* reset */
  127. case 0x02: /* sleep */
  128. i++;
  129. break;
  130. case 0xfe: /* name */
  131. len = strnlen(&data[i], size - i);
  132. if (i + len + 1 >= size)
  133. goto exit_corrupt;
  134. if (data[i + len + 1] != 0)
  135. goto exit_corrupt;
  136. for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
  137. if (strcmp(blob_name[j], &data[i]) == 0) {
  138. fw[ix].data[j] = &data[i + len + 1];
  139. pr_debug("Loading %s\n", blob_name[j]);
  140. }
  141. }
  142. i += len + 1;
  143. break;
  144. case 0xff: /* file terminator */
  145. if (i == size) {
  146. rc = 0;
  147. goto exit_ok;
  148. }
  149. default:
  150. goto exit_corrupt;
  151. }
  152. } while (i < size);
  153. exit_corrupt:
  154. printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
  155. exit_err:
  156. _drx_release_fw(s, ix);
  157. fw[ix].refcnt--;
  158. exit_ok:
  159. fw[ix].refcnt++;
  160. write_unlock(&fw[ix].lock);
  161. return rc;
  162. }
  163. /*******************************************************************************
  164. * i2c bus IO
  165. ******************************************************************************/
  166. static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
  167. {
  168. struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
  169. u8 *data;
  170. int len, rc = 0, i = 0;
  171. if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
  172. pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
  173. return -EINVAL;
  174. }
  175. pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
  176. read_lock(&fw[s->chip_rev].lock);
  177. data = fw[s->chip_rev].data[ix];
  178. if (!data) {
  179. rc = -EINVAL;
  180. goto exit_rc;
  181. }
  182. for (;;) {
  183. switch (data[i++]) {
  184. case 0: /* bytecode */
  185. len = data[i++];
  186. msg.len = len;
  187. msg.buf = &data[i];
  188. if (i2c_transfer(s->i2c, &msg, 1) != 1) {
  189. rc = -EIO;
  190. goto exit_rc;
  191. }
  192. i += len;
  193. break;
  194. case 1: /* reset */
  195. case 2: /* sleep */
  196. i++;
  197. break;
  198. default:
  199. goto exit_rc;
  200. }
  201. }
  202. exit_rc:
  203. read_unlock(&fw[s->chip_rev].lock);
  204. return 0;
  205. }
  206. /* Function is not endian safe, use the RD16 wrapper below */
  207. static int _read16(struct drx397xD_state *s, u32 i2c_adr)
  208. {
  209. int rc;
  210. u8 a[4];
  211. u16 v;
  212. struct i2c_msg msg[2] = {
  213. {
  214. .addr = s->config.demod_address,
  215. .flags = 0,
  216. .buf = a,
  217. .len = sizeof(a)
  218. }
  219. , {
  220. .addr = s->config.demod_address,
  221. .flags = I2C_M_RD,
  222. .buf = (u8 *) & v,
  223. .len = sizeof(v)
  224. }
  225. };
  226. *(u32 *) a = i2c_adr;
  227. rc = i2c_transfer(s->i2c, msg, 2);
  228. if (rc != 2)
  229. return -EIO;
  230. return le16_to_cpu(v);
  231. }
  232. /* Function is not endian safe, use the WR16.. wrappers below */
  233. static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
  234. {
  235. u8 a[6];
  236. int rc;
  237. struct i2c_msg msg = {
  238. .addr = s->config.demod_address,
  239. .flags = 0,
  240. .buf = a,
  241. .len = sizeof(a)
  242. };
  243. *(u32 *) a = i2c_adr;
  244. *(u16 *) & a[4] = val;
  245. rc = i2c_transfer(s->i2c, &msg, 1);
  246. if (rc != 1)
  247. return -EIO;
  248. return 0;
  249. }
  250. #define WR16(ss,adr, val) \
  251. _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
  252. #define WR16_E0(ss,adr, val) \
  253. _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
  254. #define RD16(ss,adr) \
  255. _read16(ss, I2C_ADR_C0(adr))
  256. #define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
  257. /*******************************************************************************
  258. * Tuner callback
  259. ******************************************************************************/
  260. static int PLL_Set(struct drx397xD_state *s,
  261. struct dvb_frontend_parameters *fep, int *df_tuner)
  262. {
  263. struct dvb_frontend *fe = &s->frontend;
  264. u32 f_tuner, f = fep->frequency;
  265. int rc;
  266. pr_debug("%s\n", __FUNCTION__);
  267. if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
  268. (f < s->frontend.ops.tuner_ops.info.frequency_min))
  269. return -EINVAL;
  270. *df_tuner = 0;
  271. if (!s->frontend.ops.tuner_ops.set_params ||
  272. !s->frontend.ops.tuner_ops.get_frequency)
  273. return -ENOSYS;
  274. rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
  275. if (rc < 0)
  276. return rc;
  277. rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
  278. if (rc < 0)
  279. return rc;
  280. *df_tuner = f_tuner - f;
  281. pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
  282. f_tuner);
  283. return 0;
  284. }
  285. /*******************************************************************************
  286. * Demodulator helper functions
  287. ******************************************************************************/
  288. static int SC_WaitForReady(struct drx397xD_state *s)
  289. {
  290. int cnt = 1000;
  291. int rc;
  292. pr_debug("%s\n", __FUNCTION__);
  293. while (cnt--) {
  294. rc = RD16(s, 0x820043);
  295. if (rc == 0)
  296. return 0;
  297. }
  298. return -1;
  299. }
  300. static int SC_SendCommand(struct drx397xD_state *s, int cmd)
  301. {
  302. int rc;
  303. pr_debug("%s\n", __FUNCTION__);
  304. WR16(s, 0x820043, cmd);
  305. SC_WaitForReady(s);
  306. rc = RD16(s, 0x820042);
  307. if ((rc & 0xffff) == 0xffff)
  308. return -1;
  309. return 0;
  310. }
  311. static int HI_Command(struct drx397xD_state *s, u16 cmd)
  312. {
  313. int rc, cnt = 1000;
  314. pr_debug("%s\n", __FUNCTION__);
  315. rc = WR16(s, 0x420032, cmd);
  316. if (rc < 0)
  317. return rc;
  318. do {
  319. rc = RD16(s, 0x420032);
  320. if (rc == 0) {
  321. rc = RD16(s, 0x420031);
  322. return rc;
  323. }
  324. if (rc < 0)
  325. return rc;
  326. } while (--cnt);
  327. return rc;
  328. }
  329. static int HI_CfgCommand(struct drx397xD_state *s)
  330. {
  331. pr_debug("%s\n", __FUNCTION__);
  332. WR16(s, 0x420033, 0x3973);
  333. WR16(s, 0x420034, s->config.w50); // code 4, log 4
  334. WR16(s, 0x420035, s->config.w52); // code 15, log 9
  335. WR16(s, 0x420036, s->config.demod_address << 1);
  336. WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1
  337. // WR16(s, 0x420033, 0x3973);
  338. if ((s->config.w56 & 8) == 0)
  339. return HI_Command(s, 3);
  340. return WR16(s, 0x420032, 0x3);
  341. }
  342. static const u8 fastIncrDecLUT_15273[] = {
  343. 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
  344. 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
  345. };
  346. static const u8 slowIncrDecLUT_15272[] = {
  347. 3, 4, 4, 5, 6
  348. };
  349. static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
  350. {
  351. u16 w06 = agc->w06;
  352. u16 w08 = agc->w08;
  353. u16 w0A = agc->w0A;
  354. u16 w0C = agc->w0C;
  355. int quot, rem, i, rc = -EINVAL;
  356. pr_debug("%s\n", __FUNCTION__);
  357. if (agc->w04 > 0x3ff)
  358. goto exit_rc;
  359. if (agc->d00 == 1) {
  360. EXIT_RC(RD16(s, 0x0c20010));
  361. rc &= ~0x10;
  362. EXIT_RC(WR16(s, 0x0c20010, rc));
  363. return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
  364. }
  365. if (agc->d00 != 0)
  366. goto exit_rc;
  367. if (w0A < w08)
  368. goto exit_rc;
  369. if (w0A > 0x3ff)
  370. goto exit_rc;
  371. if (w0C > 0x3ff)
  372. goto exit_rc;
  373. if (w06 > 0x3ff)
  374. goto exit_rc;
  375. EXIT_RC(RD16(s, 0x0c20010));
  376. rc |= 0x10;
  377. EXIT_RC(WR16(s, 0x0c20010, rc));
  378. EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
  379. EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
  380. EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
  381. quot = w0C / 113;
  382. rem = w0C % 113;
  383. if (quot <= 8) {
  384. quot = 8 - quot;
  385. } else {
  386. quot = 0;
  387. rem += 113;
  388. }
  389. EXIT_RC(WR16(s, 0x0c20024, quot));
  390. i = fastIncrDecLUT_15273[rem / 8];
  391. EXIT_RC(WR16(s, 0x0c2002d, i));
  392. EXIT_RC(WR16(s, 0x0c2002e, i));
  393. i = slowIncrDecLUT_15272[rem / 28];
  394. EXIT_RC(WR16(s, 0x0c2002b, i));
  395. rc = WR16(s, 0x0c2002c, i);
  396. exit_rc:
  397. return rc;
  398. }
  399. static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
  400. {
  401. u16 w04 = agc->w04;
  402. u16 w06 = agc->w06;
  403. int rc = -1;
  404. pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
  405. if (w04 > 0x3ff)
  406. goto exit_rc;
  407. switch (agc->d00) {
  408. case 1:
  409. if (w04 == 0x3ff)
  410. w04 = 0x400;
  411. EXIT_RC(WR16(s, 0x0c20036, w04));
  412. s->config.w9C &= ~2;
  413. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  414. EXIT_RC(RD16(s, 0x0c20010));
  415. rc &= 0xbfdf;
  416. EXIT_RC(WR16(s, 0x0c20010, rc));
  417. EXIT_RC(RD16(s, 0x0c20013));
  418. rc &= ~2;
  419. break;
  420. case 0:
  421. // loc_8000659
  422. s->config.w9C &= ~2;
  423. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  424. EXIT_RC(RD16(s, 0x0c20010));
  425. rc &= 0xbfdf;
  426. rc |= 0x4000;
  427. EXIT_RC(WR16(s, 0x0c20010, rc));
  428. EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
  429. EXIT_RC(RD16(s, 0x0c20013));
  430. rc &= ~2;
  431. break;
  432. default:
  433. s->config.w9C |= 2;
  434. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  435. EXIT_RC(RD16(s, 0x0c20010));
  436. rc &= 0xbfdf;
  437. EXIT_RC(WR16(s, 0x0c20010, rc));
  438. EXIT_RC(WR16(s, 0x0c20036, 0));
  439. EXIT_RC(RD16(s, 0x0c20013));
  440. rc |= 2;
  441. }
  442. rc = WR16(s, 0x0c20013, rc);
  443. exit_rc:
  444. return rc;
  445. }
  446. static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
  447. {
  448. int rc;
  449. *lockstat = 0;
  450. rc = RD16(s, 0x082004b);
  451. if (rc < 0)
  452. return rc;
  453. if (s->config.d60 != 2)
  454. return 0;
  455. if ((rc & 7) == 7)
  456. *lockstat |= 1;
  457. if ((rc & 3) == 3)
  458. *lockstat |= 2;
  459. if (rc & 1)
  460. *lockstat |= 4;
  461. return 0;
  462. }
  463. static int CorrectSysClockDeviation(struct drx397xD_state *s)
  464. {
  465. int rc = -EINVAL;
  466. int lockstat;
  467. u32 clk, clk_limit;
  468. pr_debug("%s\n", __FUNCTION__);
  469. if (s->config.d5C == 0) {
  470. EXIT_RC(WR16(s, 0x08200e8, 0x010));
  471. EXIT_RC(WR16(s, 0x08200e9, 0x113));
  472. s->config.d5C = 1;
  473. return rc;
  474. }
  475. if (s->config.d5C != 1)
  476. goto exit_rc;
  477. rc = RD16(s, 0x0820048);
  478. rc = GetLockStatus(s, &lockstat);
  479. if (rc < 0)
  480. goto exit_rc;
  481. if ((lockstat & 1) == 0)
  482. goto exit_rc;
  483. EXIT_RC(WR16(s, 0x0420033, 0x200));
  484. EXIT_RC(WR16(s, 0x0420034, 0xc5));
  485. EXIT_RC(WR16(s, 0x0420035, 0x10));
  486. EXIT_RC(WR16(s, 0x0420036, 0x1));
  487. EXIT_RC(WR16(s, 0x0420037, 0xa));
  488. EXIT_RC(HI_Command(s, 6));
  489. EXIT_RC(RD16(s, 0x0420040));
  490. clk = rc;
  491. EXIT_RC(RD16(s, 0x0420041));
  492. clk |= rc << 16;
  493. if (clk <= 0x26ffff)
  494. goto exit_rc;
  495. if (clk > 0x610000)
  496. goto exit_rc;
  497. if (!s->bandwidth_parm)
  498. return -EINVAL;
  499. /* round & convert to Hz */
  500. clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
  501. clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
  502. if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
  503. s->f_osc = clk;
  504. pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
  505. s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
  506. }
  507. rc = WR16(s, 0x08200e8, 0);
  508. exit_rc:
  509. return rc;
  510. }
  511. static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
  512. {
  513. int rc, si, bp;
  514. pr_debug("%s\n", __FUNCTION__);
  515. si = s->config.wA0;
  516. if (s->config.w98 == 0) {
  517. si |= 1;
  518. bp = 0;
  519. } else {
  520. si &= ~1;
  521. bp = 0x200;
  522. }
  523. if (s->config.w9A == 0) {
  524. si |= 0x80;
  525. } else {
  526. si &= ~0x80;
  527. }
  528. EXIT_RC(WR16(s, 0x2150045, 0));
  529. EXIT_RC(WR16(s, 0x2150010, si));
  530. EXIT_RC(WR16(s, 0x2150011, bp));
  531. rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
  532. exit_rc:
  533. return rc;
  534. }
  535. static int drx_tune(struct drx397xD_state *s,
  536. struct dvb_frontend_parameters *fep)
  537. {
  538. u16 v22 = 0;
  539. u16 v1C = 0;
  540. u16 v1A = 0;
  541. u16 v18 = 0;
  542. u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
  543. u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
  544. int rc, df_tuner;
  545. int a, b, c, d;
  546. pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
  547. if (s->config.d60 != 2)
  548. goto set_tuner;
  549. rc = CorrectSysClockDeviation(s);
  550. if (rc < 0)
  551. goto set_tuner;
  552. s->config.d60 = 1;
  553. rc = ConfigureMPEGOutput(s, 0);
  554. if (rc < 0)
  555. goto set_tuner;
  556. set_tuner:
  557. rc = PLL_Set(s, fep, &df_tuner);
  558. if (rc < 0) {
  559. printk(KERN_ERR "Error in pll_set\n");
  560. goto exit_rc;
  561. }
  562. msleep(200);
  563. a = rc = RD16(s, 0x2150016);
  564. if (rc < 0)
  565. goto exit_rc;
  566. b = rc = RD16(s, 0x2150010);
  567. if (rc < 0)
  568. goto exit_rc;
  569. c = rc = RD16(s, 0x2150034);
  570. if (rc < 0)
  571. goto exit_rc;
  572. d = rc = RD16(s, 0x2150035);
  573. if (rc < 0)
  574. goto exit_rc;
  575. rc = WR16(s, 0x2150014, c);
  576. rc = WR16(s, 0x2150015, d);
  577. rc = WR16(s, 0x2150010, 0);
  578. rc = WR16(s, 0x2150000, 2);
  579. rc = WR16(s, 0x2150036, 0x0fff);
  580. rc = WR16(s, 0x2150016, a);
  581. rc = WR16(s, 0x2150010, 2);
  582. rc = WR16(s, 0x2150007, 0);
  583. rc = WR16(s, 0x2150000, 1);
  584. rc = WR16(s, 0x2110000, 0);
  585. rc = WR16(s, 0x0800000, 0);
  586. rc = WR16(s, 0x2800000, 0);
  587. rc = WR16(s, 0x2110010, 0x664);
  588. rc = write_fw(s, DRXD_ResetECRAM);
  589. rc = WR16(s, 0x2110000, 1);
  590. rc = write_fw(s, DRXD_InitSC);
  591. if (rc < 0)
  592. goto exit_rc;
  593. rc = SetCfgIfAgc(s, &s->config.ifagc);
  594. if (rc < 0)
  595. goto exit_rc;
  596. rc = SetCfgRfAgc(s, &s->config.rfagc);
  597. if (rc < 0)
  598. goto exit_rc;
  599. if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
  600. v22 = 1;
  601. switch (fep->u.ofdm.transmission_mode) {
  602. case TRANSMISSION_MODE_8K:
  603. edi = 1;
  604. if (s->chip_rev == DRXD_FW_B1)
  605. break;
  606. rc = WR16(s, 0x2010010, 0);
  607. if (rc < 0)
  608. break;
  609. v1C = 0x63;
  610. v1A = 0x53;
  611. v18 = 0x43;
  612. break;
  613. default:
  614. edi = 0;
  615. if (s->chip_rev == DRXD_FW_B1)
  616. break;
  617. rc = WR16(s, 0x2010010, 1);
  618. if (rc < 0)
  619. break;
  620. v1C = 0x61;
  621. v1A = 0x47;
  622. v18 = 0x41;
  623. }
  624. switch (fep->u.ofdm.guard_interval) {
  625. case GUARD_INTERVAL_1_4:
  626. edi |= 0x0c;
  627. break;
  628. case GUARD_INTERVAL_1_8:
  629. edi |= 0x08;
  630. break;
  631. case GUARD_INTERVAL_1_16:
  632. edi |= 0x04;
  633. break;
  634. case GUARD_INTERVAL_1_32:
  635. break;
  636. default:
  637. v22 |= 2;
  638. }
  639. ebx = 0;
  640. ebp = 0;
  641. v20 = 0;
  642. v1E = 0;
  643. v16 = 0;
  644. v14 = 0;
  645. v12 = 0;
  646. v10 = 0;
  647. v0E = 0;
  648. switch (fep->u.ofdm.hierarchy_information) {
  649. case HIERARCHY_1:
  650. edi |= 0x40;
  651. if (s->chip_rev == DRXD_FW_B1)
  652. break;
  653. rc = WR16(s, 0x1c10047, 1);
  654. if (rc < 0)
  655. goto exit_rc;
  656. rc = WR16(s, 0x2010012, 1);
  657. if (rc < 0)
  658. goto exit_rc;
  659. ebx = 0x19f;
  660. ebp = 0x1fb;
  661. v20 = 0x0c0;
  662. v1E = 0x195;
  663. v16 = 0x1d6;
  664. v14 = 0x1ef;
  665. v12 = 4;
  666. v10 = 5;
  667. v0E = 5;
  668. break;
  669. case HIERARCHY_2:
  670. edi |= 0x80;
  671. if (s->chip_rev == DRXD_FW_B1)
  672. break;
  673. rc = WR16(s, 0x1c10047, 2);
  674. if (rc < 0)
  675. goto exit_rc;
  676. rc = WR16(s, 0x2010012, 2);
  677. if (rc < 0)
  678. goto exit_rc;
  679. ebx = 0x08f;
  680. ebp = 0x12f;
  681. v20 = 0x0c0;
  682. v1E = 0x11e;
  683. v16 = 0x1d6;
  684. v14 = 0x15e;
  685. v12 = 4;
  686. v10 = 5;
  687. v0E = 5;
  688. break;
  689. case HIERARCHY_4:
  690. edi |= 0xc0;
  691. if (s->chip_rev == DRXD_FW_B1)
  692. break;
  693. rc = WR16(s, 0x1c10047, 3);
  694. if (rc < 0)
  695. goto exit_rc;
  696. rc = WR16(s, 0x2010012, 3);
  697. if (rc < 0)
  698. goto exit_rc;
  699. ebx = 0x14d;
  700. ebp = 0x197;
  701. v20 = 0x0c0;
  702. v1E = 0x1ce;
  703. v16 = 0x1d6;
  704. v14 = 0x11a;
  705. v12 = 4;
  706. v10 = 6;
  707. v0E = 5;
  708. break;
  709. default:
  710. v22 |= 8;
  711. if (s->chip_rev == DRXD_FW_B1)
  712. break;
  713. rc = WR16(s, 0x1c10047, 0);
  714. if (rc < 0)
  715. goto exit_rc;
  716. rc = WR16(s, 0x2010012, 0);
  717. if (rc < 0)
  718. goto exit_rc;
  719. // QPSK QAM16 QAM64
  720. ebx = 0x19f; // 62
  721. ebp = 0x1fb; // 15
  722. v20 = 0x16a; // 62
  723. v1E = 0x195; // 62
  724. v16 = 0x1bb; // 15
  725. v14 = 0x1ef; // 15
  726. v12 = 5; // 16
  727. v10 = 5; // 16
  728. v0E = 5; // 16
  729. }
  730. switch (fep->u.ofdm.constellation) {
  731. default:
  732. v22 |= 4;
  733. case QPSK:
  734. if (s->chip_rev == DRXD_FW_B1)
  735. break;
  736. rc = WR16(s, 0x1c10046, 0);
  737. if (rc < 0)
  738. goto exit_rc;
  739. rc = WR16(s, 0x2010011, 0);
  740. if (rc < 0)
  741. goto exit_rc;
  742. rc = WR16(s, 0x201001a, 0x10);
  743. if (rc < 0)
  744. goto exit_rc;
  745. rc = WR16(s, 0x201001b, 0);
  746. if (rc < 0)
  747. goto exit_rc;
  748. rc = WR16(s, 0x201001c, 0);
  749. if (rc < 0)
  750. goto exit_rc;
  751. rc = WR16(s, 0x1c10062, v20);
  752. if (rc < 0)
  753. goto exit_rc;
  754. rc = WR16(s, 0x1c1002a, v1C);
  755. if (rc < 0)
  756. goto exit_rc;
  757. rc = WR16(s, 0x1c10015, v16);
  758. if (rc < 0)
  759. goto exit_rc;
  760. rc = WR16(s, 0x1c10016, v12);
  761. if (rc < 0)
  762. goto exit_rc;
  763. break;
  764. case QAM_16:
  765. edi |= 0x10;
  766. if (s->chip_rev == DRXD_FW_B1)
  767. break;
  768. rc = WR16(s, 0x1c10046, 1);
  769. if (rc < 0)
  770. goto exit_rc;
  771. rc = WR16(s, 0x2010011, 1);
  772. if (rc < 0)
  773. goto exit_rc;
  774. rc = WR16(s, 0x201001a, 0x10);
  775. if (rc < 0)
  776. goto exit_rc;
  777. rc = WR16(s, 0x201001b, 4);
  778. if (rc < 0)
  779. goto exit_rc;
  780. rc = WR16(s, 0x201001c, 0);
  781. if (rc < 0)
  782. goto exit_rc;
  783. rc = WR16(s, 0x1c10062, v1E);
  784. if (rc < 0)
  785. goto exit_rc;
  786. rc = WR16(s, 0x1c1002a, v1A);
  787. if (rc < 0)
  788. goto exit_rc;
  789. rc = WR16(s, 0x1c10015, v14);
  790. if (rc < 0)
  791. goto exit_rc;
  792. rc = WR16(s, 0x1c10016, v10);
  793. if (rc < 0)
  794. goto exit_rc;
  795. break;
  796. case QAM_64:
  797. edi |= 0x20;
  798. rc = WR16(s, 0x1c10046, 2);
  799. if (rc < 0)
  800. goto exit_rc;
  801. rc = WR16(s, 0x2010011, 2);
  802. if (rc < 0)
  803. goto exit_rc;
  804. rc = WR16(s, 0x201001a, 0x20);
  805. if (rc < 0)
  806. goto exit_rc;
  807. rc = WR16(s, 0x201001b, 8);
  808. if (rc < 0)
  809. goto exit_rc;
  810. rc = WR16(s, 0x201001c, 2);
  811. if (rc < 0)
  812. goto exit_rc;
  813. rc = WR16(s, 0x1c10062, ebx);
  814. if (rc < 0)
  815. goto exit_rc;
  816. rc = WR16(s, 0x1c1002a, v18);
  817. if (rc < 0)
  818. goto exit_rc;
  819. rc = WR16(s, 0x1c10015, ebp);
  820. if (rc < 0)
  821. goto exit_rc;
  822. rc = WR16(s, 0x1c10016, v0E);
  823. if (rc < 0)
  824. goto exit_rc;
  825. break;
  826. }
  827. if (s->config.s20d24 == 1) {
  828. rc = WR16(s, 0x2010013, 0);
  829. } else {
  830. rc = WR16(s, 0x2010013, 1);
  831. edi |= 0x1000;
  832. }
  833. switch (fep->u.ofdm.code_rate_HP) {
  834. default:
  835. v22 |= 0x10;
  836. case FEC_1_2:
  837. if (s->chip_rev == DRXD_FW_B1)
  838. break;
  839. rc = WR16(s, 0x2090011, 0);
  840. break;
  841. case FEC_2_3:
  842. edi |= 0x200;
  843. if (s->chip_rev == DRXD_FW_B1)
  844. break;
  845. rc = WR16(s, 0x2090011, 1);
  846. break;
  847. case FEC_3_4:
  848. edi |= 0x400;
  849. if (s->chip_rev == DRXD_FW_B1)
  850. break;
  851. rc = WR16(s, 0x2090011, 2);
  852. break;
  853. case FEC_5_6: /* 5 */
  854. edi |= 0x600;
  855. if (s->chip_rev == DRXD_FW_B1)
  856. break;
  857. rc = WR16(s, 0x2090011, 3);
  858. break;
  859. case FEC_7_8: /* 7 */
  860. edi |= 0x800;
  861. if (s->chip_rev == DRXD_FW_B1)
  862. break;
  863. rc = WR16(s, 0x2090011, 4);
  864. break;
  865. };
  866. if (rc < 0)
  867. goto exit_rc;
  868. switch (fep->u.ofdm.bandwidth) {
  869. default:
  870. rc = -EINVAL;
  871. goto exit_rc;
  872. case BANDWIDTH_8_MHZ: /* 0 */
  873. case BANDWIDTH_AUTO:
  874. rc = WR16(s, 0x0c2003f, 0x32);
  875. s->bandwidth_parm = ebx = 0x8b8249; // 9142857
  876. edx = 0;
  877. break;
  878. case BANDWIDTH_7_MHZ:
  879. rc = WR16(s, 0x0c2003f, 0x3b);
  880. s->bandwidth_parm = ebx = 0x7a1200; // 8000000
  881. edx = 0x4807;
  882. break;
  883. case BANDWIDTH_6_MHZ:
  884. rc = WR16(s, 0x0c2003f, 0x47);
  885. s->bandwidth_parm = ebx = 0x68a1b6; // 6857142
  886. edx = 0x0f07;
  887. break;
  888. };
  889. if (rc < 0)
  890. goto exit_rc;
  891. rc = WR16(s, 0x08200ec, edx);
  892. if (rc < 0)
  893. goto exit_rc;
  894. rc = RD16(s, 0x0820050);
  895. if (rc < 0)
  896. goto exit_rc;
  897. rc = WR16(s, 0x0820050, rc);
  898. {
  899. long dummy;
  900. /* Configure bandwidth specific factor */
  901. ebx = div_ll_X_l_rem(((u64) (s->f_osc) << 21) + (ebx >> 1),
  902. ebx, &dummy) - 0x800000;
  903. EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
  904. EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
  905. /* drx397xD oscillator calibration */
  906. ebx = div_ll_X_l_rem(((u64) (s->config.f_if + df_tuner) << 28) +
  907. (s->f_osc >> 1), s->f_osc, &dummy);
  908. }
  909. ebx &= 0xfffffff;
  910. if (fep->inversion == INVERSION_ON)
  911. ebx = 0x10000000 - ebx;
  912. EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
  913. EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
  914. EXIT_RC(WR16(s, 0x0800000, 1));
  915. EXIT_RC(RD16(s, 0x0800000));
  916. EXIT_RC(SC_WaitForReady(s));
  917. EXIT_RC(WR16(s, 0x0820042, 0));
  918. EXIT_RC(WR16(s, 0x0820041, v22));
  919. EXIT_RC(WR16(s, 0x0820040, edi));
  920. EXIT_RC(SC_SendCommand(s, 3));
  921. rc = RD16(s, 0x0800000);
  922. SC_WaitForReady(s);
  923. WR16(s, 0x0820042, 0);
  924. WR16(s, 0x0820041, 1);
  925. WR16(s, 0x0820040, 1);
  926. SC_SendCommand(s, 1);
  927. // rc = WR16(s, 0x2150000, 1);
  928. // if (rc < 0) goto exit_rc;
  929. rc = WR16(s, 0x2150000, 2);
  930. rc = WR16(s, 0x2150016, a);
  931. rc = WR16(s, 0x2150010, 4);
  932. rc = WR16(s, 0x2150036, 0);
  933. rc = WR16(s, 0x2150000, 1);
  934. s->config.d60 = 2;
  935. exit_rc:
  936. return rc;
  937. }
  938. /*******************************************************************************
  939. * DVB interface
  940. ******************************************************************************/
  941. static int drx397x_init(struct dvb_frontend *fe)
  942. {
  943. struct drx397xD_state *s = fe->demodulator_priv;
  944. int rc;
  945. pr_debug("%s\n", __FUNCTION__);
  946. s->config.rfagc.d00 = 2; /* 0x7c */
  947. s->config.rfagc.w04 = 0;
  948. s->config.rfagc.w06 = 0x3ff;
  949. s->config.ifagc.d00 = 0; /* 0x68 */
  950. s->config.ifagc.w04 = 0;
  951. s->config.ifagc.w06 = 140;
  952. s->config.ifagc.w08 = 0;
  953. s->config.ifagc.w0A = 0x3ff;
  954. s->config.ifagc.w0C = 0x388;
  955. /* for signal strenght calculations */
  956. s->config.ss76 = 820;
  957. s->config.ss78 = 2200;
  958. s->config.ss7A = 150;
  959. /* HI_CfgCommand */
  960. s->config.w50 = 4;
  961. s->config.w52 = 9; // 0xf;
  962. s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */
  963. s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */
  964. s->config.w92 = 12000; // 20000;
  965. s->config.w9C = 0x000e;
  966. s->config.w9E = 0x0000;
  967. /* ConfigureMPEGOutput params */
  968. s->config.wA0 = 4;
  969. s->config.w98 = 1; // 0;
  970. s->config.w9A = 1;
  971. /* get chip revision */
  972. rc = RD16(s, 0x2410019);
  973. if (rc < 0)
  974. return -ENODEV;
  975. if (rc == 0) {
  976. printk(KERN_INFO "%s: chip revision A2\n", mod_name);
  977. rc = drx_load_fw(s, DRXD_FW_A2);
  978. } else {
  979. rc = (rc >> 12) - 3;
  980. switch (rc) {
  981. case 1:
  982. s->flags |= F_SET_0D4h;
  983. case 0:
  984. case 4:
  985. s->flags |= F_SET_0D0h;
  986. break;
  987. case 2:
  988. case 5:
  989. break;
  990. case 3:
  991. s->flags |= F_SET_0D4h;
  992. break;
  993. default:
  994. return -ENODEV;
  995. };
  996. printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
  997. rc = drx_load_fw(s, DRXD_FW_B1);
  998. }
  999. if (rc < 0)
  1000. goto error;
  1001. rc = WR16(s, 0x0420033, 0x3973);
  1002. if (rc < 0)
  1003. goto error;
  1004. rc = HI_Command(s, 2);
  1005. msleep(1);
  1006. if (s->chip_rev == DRXD_FW_A2) {
  1007. rc = WR16(s, 0x043012d, 0x47F);
  1008. if (rc < 0)
  1009. goto error;
  1010. }
  1011. rc = WR16_E0(s, 0x0400000, 0);
  1012. if (rc < 0)
  1013. goto error;
  1014. if (s->config.w92 > 20000 || s->config.w92 % 4000) {
  1015. printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
  1016. rc = -1;
  1017. goto error;
  1018. }
  1019. rc = WR16(s, 0x2410010, 1);
  1020. if (rc < 0)
  1021. goto error;
  1022. rc = WR16(s, 0x2410011, 0x15);
  1023. if (rc < 0)
  1024. goto error;
  1025. rc = WR16(s, 0x2410012, s->config.w92 / 4000);
  1026. if (rc < 0)
  1027. goto error;
  1028. #ifdef ORIG_FW
  1029. rc = WR16(s, 0x2410015, 2);
  1030. if (rc < 0)
  1031. goto error;
  1032. #endif
  1033. rc = WR16(s, 0x2410017, 0x3973);
  1034. if (rc < 0)
  1035. goto error;
  1036. s->f_osc = s->config.f_osc * 1000; /* initial estimator */
  1037. s->config.w56 = 1;
  1038. rc = HI_CfgCommand(s);
  1039. if (rc < 0)
  1040. goto error;
  1041. rc = write_fw(s, DRXD_InitAtomicRead);
  1042. if (rc < 0)
  1043. goto error;
  1044. if (s->chip_rev == DRXD_FW_A2) {
  1045. rc = WR16(s, 0x2150013, 0);
  1046. if (rc < 0)
  1047. goto error;
  1048. }
  1049. rc = WR16_E0(s, 0x0400002, 0);
  1050. if (rc < 0)
  1051. goto error;
  1052. rc = WR16(s, 0x0400002, 0);
  1053. if (rc < 0)
  1054. goto error;
  1055. if (s->chip_rev == DRXD_FW_A2) {
  1056. rc = write_fw(s, DRXD_ResetCEFR);
  1057. if (rc < 0)
  1058. goto error;
  1059. }
  1060. rc = write_fw(s, DRXD_microcode);
  1061. if (rc < 0)
  1062. goto error;
  1063. s->config.w9C = 0x0e;
  1064. if (s->flags & F_SET_0D0h) {
  1065. s->config.w9C = 0;
  1066. rc = RD16(s, 0x0c20010);
  1067. if (rc < 0)
  1068. goto write_DRXD_InitFE_1;
  1069. rc &= ~0x1000;
  1070. rc = WR16(s, 0x0c20010, rc);
  1071. if (rc < 0)
  1072. goto write_DRXD_InitFE_1;
  1073. rc = RD16(s, 0x0c20011);
  1074. if (rc < 0)
  1075. goto write_DRXD_InitFE_1;
  1076. rc &= ~0x8;
  1077. rc = WR16(s, 0x0c20011, rc);
  1078. if (rc < 0)
  1079. goto write_DRXD_InitFE_1;
  1080. rc = WR16(s, 0x0c20012, 1);
  1081. }
  1082. write_DRXD_InitFE_1:
  1083. rc = write_fw(s, DRXD_InitFE_1);
  1084. if (rc < 0)
  1085. goto error;
  1086. rc = 1;
  1087. if (s->chip_rev == DRXD_FW_B1) {
  1088. if (s->flags & F_SET_0D0h)
  1089. rc = 0;
  1090. } else {
  1091. if (s->flags & F_SET_0D0h)
  1092. rc = 4;
  1093. }
  1094. rc = WR16(s, 0x0C20012, rc);
  1095. if (rc < 0)
  1096. goto error;
  1097. rc = WR16(s, 0x0C20013, s->config.w9E);
  1098. if (rc < 0)
  1099. goto error;
  1100. rc = WR16(s, 0x0C20015, s->config.w9C);
  1101. if (rc < 0)
  1102. goto error;
  1103. rc = write_fw(s, DRXD_InitFE_2);
  1104. if (rc < 0)
  1105. goto error;
  1106. rc = write_fw(s, DRXD_InitFT);
  1107. if (rc < 0)
  1108. goto error;
  1109. rc = write_fw(s, DRXD_InitCP);
  1110. if (rc < 0)
  1111. goto error;
  1112. rc = write_fw(s, DRXD_InitCE);
  1113. if (rc < 0)
  1114. goto error;
  1115. rc = write_fw(s, DRXD_InitEQ);
  1116. if (rc < 0)
  1117. goto error;
  1118. rc = write_fw(s, DRXD_InitEC);
  1119. if (rc < 0)
  1120. goto error;
  1121. rc = write_fw(s, DRXD_InitSC);
  1122. if (rc < 0)
  1123. goto error;
  1124. rc = SetCfgIfAgc(s, &s->config.ifagc);
  1125. if (rc < 0)
  1126. goto error;
  1127. rc = SetCfgRfAgc(s, &s->config.rfagc);
  1128. if (rc < 0)
  1129. goto error;
  1130. rc = ConfigureMPEGOutput(s, 1);
  1131. rc = WR16(s, 0x08201fe, 0x0017);
  1132. rc = WR16(s, 0x08201ff, 0x0101);
  1133. s->config.d5C = 0;
  1134. s->config.d60 = 1;
  1135. s->config.d48 = 1;
  1136. error:
  1137. return rc;
  1138. }
  1139. static int drx397x_get_frontend(struct dvb_frontend *fe,
  1140. struct dvb_frontend_parameters *params)
  1141. {
  1142. return 0;
  1143. }
  1144. static int drx397x_set_frontend(struct dvb_frontend *fe,
  1145. struct dvb_frontend_parameters *params)
  1146. {
  1147. struct drx397xD_state *s = fe->demodulator_priv;
  1148. s->config.s20d24 = 1; // 0;
  1149. return drx_tune(s, params);
  1150. }
  1151. static int drx397x_get_tune_settings(struct dvb_frontend *fe,
  1152. struct dvb_frontend_tune_settings
  1153. *fe_tune_settings)
  1154. {
  1155. fe_tune_settings->min_delay_ms = 10000;
  1156. fe_tune_settings->step_size = 0;
  1157. fe_tune_settings->max_drift = 0;
  1158. return 0;
  1159. }
  1160. static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
  1161. {
  1162. struct drx397xD_state *s = fe->demodulator_priv;
  1163. int lockstat;
  1164. GetLockStatus(s, &lockstat);
  1165. /* TODO */
  1166. // if (lockstat & 1)
  1167. // CorrectSysClockDeviation(s);
  1168. *status = 0;
  1169. if (lockstat & 2) {
  1170. CorrectSysClockDeviation(s);
  1171. ConfigureMPEGOutput(s, 1);
  1172. *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
  1173. }
  1174. if (lockstat & 4) {
  1175. *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
  1176. }
  1177. return 0;
  1178. }
  1179. static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
  1180. {
  1181. *ber = 0;
  1182. return 0;
  1183. }
  1184. static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
  1185. {
  1186. *snr = 0;
  1187. return 0;
  1188. }
  1189. static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
  1190. {
  1191. struct drx397xD_state *s = fe->demodulator_priv;
  1192. int rc;
  1193. if (s->config.ifagc.d00 == 2) {
  1194. *strength = 0xffff;
  1195. return 0;
  1196. }
  1197. rc = RD16(s, 0x0c20035);
  1198. if (rc < 0) {
  1199. *strength = 0;
  1200. return 0;
  1201. }
  1202. rc &= 0x3ff;
  1203. /* Signal strength is calculated using the following formula:
  1204. *
  1205. * a = 2200 * 150 / (2200 + 150);
  1206. * a = a * 3300 / (a + 820);
  1207. * b = 2200 * 3300 / (2200 + 820);
  1208. * c = (((b-a) * rc) >> 10 + a) << 4;
  1209. * strength = ~c & 0xffff;
  1210. *
  1211. * The following does the same but with less rounding errors:
  1212. */
  1213. *strength = ~(7720 + (rc * 30744 >> 10));
  1214. return 0;
  1215. }
  1216. static int drx397x_read_ucblocks(struct dvb_frontend *fe,
  1217. unsigned int *ucblocks)
  1218. {
  1219. *ucblocks = 0;
  1220. return 0;
  1221. }
  1222. static int drx397x_sleep(struct dvb_frontend *fe)
  1223. {
  1224. return 0;
  1225. }
  1226. static void drx397x_release(struct dvb_frontend *fe)
  1227. {
  1228. struct drx397xD_state *s = fe->demodulator_priv;
  1229. printk(KERN_INFO "%s: release demodulator\n", mod_name);
  1230. if (s) {
  1231. drx_release_fw(s);
  1232. kfree(s);
  1233. }
  1234. }
  1235. static struct dvb_frontend_ops drx397x_ops = {
  1236. .info = {
  1237. .name = "Micronas DRX397xD DVB-T Frontend",
  1238. .type = FE_OFDM,
  1239. .frequency_min = 47125000,
  1240. .frequency_max = 855250000,
  1241. .frequency_stepsize = 166667,
  1242. .frequency_tolerance = 0,
  1243. .caps = /* 0x0C01B2EAE */
  1244. FE_CAN_FEC_1_2 | // = 0x2,
  1245. FE_CAN_FEC_2_3 | // = 0x4,
  1246. FE_CAN_FEC_3_4 | // = 0x8,
  1247. FE_CAN_FEC_5_6 | // = 0x20,
  1248. FE_CAN_FEC_7_8 | // = 0x80,
  1249. FE_CAN_FEC_AUTO | // = 0x200,
  1250. FE_CAN_QPSK | // = 0x400,
  1251. FE_CAN_QAM_16 | // = 0x800,
  1252. FE_CAN_QAM_64 | // = 0x2000,
  1253. FE_CAN_QAM_AUTO | // = 0x10000,
  1254. FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000,
  1255. FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000,
  1256. FE_CAN_HIERARCHY_AUTO | // = 0x100000,
  1257. FE_CAN_RECOVER | // = 0x40000000,
  1258. FE_CAN_MUTE_TS // = 0x80000000
  1259. },
  1260. .release = drx397x_release,
  1261. .init = drx397x_init,
  1262. .sleep = drx397x_sleep,
  1263. .set_frontend = drx397x_set_frontend,
  1264. .get_tune_settings = drx397x_get_tune_settings,
  1265. .get_frontend = drx397x_get_frontend,
  1266. .read_status = drx397x_read_status,
  1267. .read_snr = drx397x_read_snr,
  1268. .read_signal_strength = drx397x_read_signal_strength,
  1269. .read_ber = drx397x_read_ber,
  1270. .read_ucblocks = drx397x_read_ucblocks,
  1271. };
  1272. struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
  1273. struct i2c_adapter *i2c)
  1274. {
  1275. struct drx397xD_state *s = NULL;
  1276. /* allocate memory for the internal state */
  1277. s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
  1278. if (s == NULL)
  1279. goto error;
  1280. /* setup the state */
  1281. s->i2c = i2c;
  1282. memcpy(&s->config, config, sizeof(struct drx397xD_config));
  1283. /* check if the demod is there */
  1284. if (RD16(s, 0x2410019) < 0)
  1285. goto error;
  1286. /* create dvb_frontend */
  1287. memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
  1288. s->frontend.demodulator_priv = s;
  1289. return &s->frontend;
  1290. error:
  1291. kfree(s);
  1292. return NULL;
  1293. }
  1294. MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
  1295. MODULE_AUTHOR("Henk Vergonet");
  1296. MODULE_LICENSE("GPL");
  1297. EXPORT_SYMBOL(drx397xD_attach);