drx397xD.c 30 KB

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