drx397xD.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  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. typedef enum fw_ix {
  36. #define _FW_ENTRY(a, b) b
  37. #include "drx397xD_fw.h"
  38. } fw_ix_t;
  39. /* chip specifics */
  40. struct drx397xD_state {
  41. struct i2c_adapter *i2c;
  42. struct dvb_frontend frontend;
  43. struct drx397xD_config config;
  44. fw_ix_t chip_rev;
  45. int flags;
  46. u32 bandwidth_parm; /* internal bandwidth conversions */
  47. u32 f_osc; /* w90: actual osc frequency [Hz] */
  48. };
  49. /*******************************************************************************
  50. * Firmware
  51. ******************************************************************************/
  52. static const char *blob_name[] = {
  53. #define _BLOB_ENTRY(a, b) a
  54. #include "drx397xD_fw.h"
  55. };
  56. typedef enum blob_ix {
  57. #define _BLOB_ENTRY(a, b) b
  58. #include "drx397xD_fw.h"
  59. } blob_ix_t;
  60. static struct {
  61. const char *name;
  62. const struct firmware *file;
  63. rwlock_t lock;
  64. int refcnt;
  65. u8 *data[ARRAY_SIZE(blob_name)];
  66. } fw[] = {
  67. #define _FW_ENTRY(a, b) { \
  68. .name = a, \
  69. .file = 0, \
  70. .lock = RW_LOCK_UNLOCKED, \
  71. .refcnt = 0, \
  72. .data = { } }
  73. #include "drx397xD_fw.h"
  74. };
  75. /* use only with writer lock aquired */
  76. static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
  77. {
  78. memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
  79. if (fw[ix].file)
  80. release_firmware(fw[ix].file);
  81. }
  82. static void drx_release_fw(struct drx397xD_state *s)
  83. {
  84. fw_ix_t ix = s->chip_rev;
  85. pr_debug("%s\n", __FUNCTION__);
  86. write_lock(&fw[ix].lock);
  87. if (fw[ix].refcnt) {
  88. fw[ix].refcnt--;
  89. if (fw[ix].refcnt == 0)
  90. _drx_release_fw(s, ix);
  91. }
  92. write_unlock(&fw[ix].lock);
  93. }
  94. static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
  95. {
  96. u8 *data;
  97. size_t size, len;
  98. int i = 0, j, rc = -EINVAL;
  99. pr_debug("%s\n", __FUNCTION__);
  100. if (ix < 0 || ix >= ARRAY_SIZE(fw))
  101. return -EINVAL;
  102. s->chip_rev = ix;
  103. write_lock(&fw[ix].lock);
  104. if (fw[ix].file) {
  105. rc = 0;
  106. goto exit_ok;
  107. }
  108. memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
  109. if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
  110. printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
  111. mod_name, fw[ix].name);
  112. rc = -ENOENT;
  113. goto exit_err;
  114. }
  115. if (!fw[ix].file->data || fw[ix].file->size < 10)
  116. goto exit_corrupt;
  117. data = fw[ix].file->data;
  118. size = fw[ix].file->size;
  119. if (data[i++] != 2) /* check firmware version */
  120. goto exit_corrupt;
  121. do {
  122. switch (data[i++]) {
  123. case 0x00: /* bytecode */
  124. if (i >= size)
  125. break;
  126. i += data[i];
  127. case 0x01: /* reset */
  128. case 0x02: /* sleep */
  129. i++;
  130. break;
  131. case 0xfe: /* name */
  132. len = strnlen(&data[i], size - i);
  133. if (i + len + 1 >= size)
  134. goto exit_corrupt;
  135. if (data[i + len + 1] != 0)
  136. goto exit_corrupt;
  137. for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
  138. if (strcmp(blob_name[j], &data[i]) == 0) {
  139. fw[ix].data[j] = &data[i + len + 1];
  140. pr_debug("Loading %s\n", blob_name[j]);
  141. }
  142. }
  143. i += len + 1;
  144. break;
  145. case 0xff: /* file terminator */
  146. if (i == size) {
  147. rc = 0;
  148. goto exit_ok;
  149. }
  150. default:
  151. goto exit_corrupt;
  152. }
  153. } while (i < size);
  154. exit_corrupt:
  155. printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
  156. exit_err:
  157. _drx_release_fw(s, ix);
  158. fw[ix].refcnt--;
  159. exit_ok:
  160. fw[ix].refcnt++;
  161. write_unlock(&fw[ix].lock);
  162. return rc;
  163. }
  164. /*******************************************************************************
  165. * i2c bus IO
  166. ******************************************************************************/
  167. static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
  168. {
  169. struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
  170. u8 *data;
  171. int len, rc = 0, i = 0;
  172. if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
  173. pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
  174. return -EINVAL;
  175. }
  176. pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
  177. read_lock(&fw[s->chip_rev].lock);
  178. data = fw[s->chip_rev].data[ix];
  179. if (!data) {
  180. rc = -EINVAL;
  181. goto exit_rc;
  182. }
  183. for (;;) {
  184. switch (data[i++]) {
  185. case 0: /* bytecode */
  186. len = data[i++];
  187. msg.len = len;
  188. msg.buf = &data[i];
  189. if (i2c_transfer(s->i2c, &msg, 1) != 1) {
  190. rc = -EIO;
  191. goto exit_rc;
  192. }
  193. i += len;
  194. break;
  195. case 1: /* reset */
  196. case 2: /* sleep */
  197. i++;
  198. break;
  199. default:
  200. goto exit_rc;
  201. }
  202. }
  203. exit_rc:
  204. read_unlock(&fw[s->chip_rev].lock);
  205. return 0;
  206. }
  207. /* Function is not endian safe, use the RD16 wrapper below */
  208. static int _read16(struct drx397xD_state *s, u32 i2c_adr)
  209. {
  210. int rc;
  211. u8 a[4];
  212. u16 v;
  213. struct i2c_msg msg[2] = {
  214. {
  215. .addr = s->config.demod_address,
  216. .flags = 0,
  217. .buf = a,
  218. .len = sizeof(a)
  219. }
  220. , {
  221. .addr = s->config.demod_address,
  222. .flags = I2C_M_RD,
  223. .buf = (u8 *) & v,
  224. .len = sizeof(v)
  225. }
  226. };
  227. *(u32 *) a = i2c_adr;
  228. rc = i2c_transfer(s->i2c, msg, 2);
  229. if (rc != 2)
  230. return -EIO;
  231. return le16_to_cpu(v);
  232. }
  233. /* Function is not endian safe, use the WR16.. wrappers below */
  234. static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
  235. {
  236. u8 a[6];
  237. int rc;
  238. struct i2c_msg msg = {
  239. .addr = s->config.demod_address,
  240. .flags = 0,
  241. .buf = a,
  242. .len = sizeof(a)
  243. };
  244. *(u32 *) a = i2c_adr;
  245. *(u16 *) & a[4] = val;
  246. rc = i2c_transfer(s->i2c, &msg, 1);
  247. if (rc != 1)
  248. return -EIO;
  249. return 0;
  250. }
  251. #define WR16(ss,adr, val) \
  252. _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
  253. #define WR16_E0(ss,adr, val) \
  254. _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
  255. #define RD16(ss,adr) \
  256. _read16(ss, I2C_ADR_C0(adr))
  257. #define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
  258. /*******************************************************************************
  259. * Tuner callback
  260. ******************************************************************************/
  261. static int PLL_Set(struct drx397xD_state *s,
  262. struct dvb_frontend_parameters *fep, int *df_tuner)
  263. {
  264. struct dvb_frontend *fe = &s->frontend;
  265. u32 f_tuner, f = fep->frequency;
  266. int rc;
  267. pr_debug("%s\n", __FUNCTION__);
  268. if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
  269. (f < s->frontend.ops.tuner_ops.info.frequency_min))
  270. return -EINVAL;
  271. *df_tuner = 0;
  272. if (!s->frontend.ops.tuner_ops.set_params ||
  273. !s->frontend.ops.tuner_ops.get_frequency)
  274. return -ENOSYS;
  275. rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
  276. if (rc < 0)
  277. return rc;
  278. rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
  279. if (rc < 0)
  280. return rc;
  281. *df_tuner = f_tuner - f;
  282. pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
  283. f_tuner);
  284. return 0;
  285. }
  286. /*******************************************************************************
  287. * Demodulator helper functions
  288. ******************************************************************************/
  289. static int SC_WaitForReady(struct drx397xD_state *s)
  290. {
  291. int cnt = 1000;
  292. int rc;
  293. pr_debug("%s\n", __FUNCTION__);
  294. while (cnt--) {
  295. rc = RD16(s, 0x820043);
  296. if (rc == 0)
  297. return 0;
  298. }
  299. return -1;
  300. }
  301. static int SC_SendCommand(struct drx397xD_state *s, int cmd)
  302. {
  303. int rc;
  304. pr_debug("%s\n", __FUNCTION__);
  305. WR16(s, 0x820043, cmd);
  306. SC_WaitForReady(s);
  307. rc = RD16(s, 0x820042);
  308. if ((rc & 0xffff) == 0xffff)
  309. return -1;
  310. return 0;
  311. }
  312. static int HI_Command(struct drx397xD_state *s, u16 cmd)
  313. {
  314. int rc, cnt = 1000;
  315. pr_debug("%s\n", __FUNCTION__);
  316. rc = WR16(s, 0x420032, cmd);
  317. if (rc < 0)
  318. return rc;
  319. do {
  320. rc = RD16(s, 0x420032);
  321. if (rc == 0) {
  322. rc = RD16(s, 0x420031);
  323. return rc;
  324. }
  325. if (rc < 0)
  326. return rc;
  327. } while (--cnt);
  328. return rc;
  329. }
  330. static int HI_CfgCommand(struct drx397xD_state *s)
  331. {
  332. pr_debug("%s\n", __FUNCTION__);
  333. WR16(s, 0x420033, 0x3973);
  334. WR16(s, 0x420034, s->config.w50); // code 4, log 4
  335. WR16(s, 0x420035, s->config.w52); // code 15, log 9
  336. WR16(s, 0x420036, s->config.demod_address << 1);
  337. WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1
  338. // WR16(s, 0x420033, 0x3973);
  339. if ((s->config.w56 & 8) == 0)
  340. return HI_Command(s, 3);
  341. return WR16(s, 0x420032, 0x3);
  342. }
  343. static const u8 fastIncrDecLUT_15273[] = {
  344. 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
  345. 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
  346. };
  347. static const u8 slowIncrDecLUT_15272[] = {
  348. 3, 4, 4, 5, 6
  349. };
  350. static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
  351. {
  352. u16 w06 = agc->w06;
  353. u16 w08 = agc->w08;
  354. u16 w0A = agc->w0A;
  355. u16 w0C = agc->w0C;
  356. int quot, rem, i, rc = -EINVAL;
  357. pr_debug("%s\n", __FUNCTION__);
  358. if (agc->w04 > 0x3ff)
  359. goto exit_rc;
  360. if (agc->d00 == 1) {
  361. EXIT_RC(RD16(s, 0x0c20010));
  362. rc &= ~0x10;
  363. EXIT_RC(WR16(s, 0x0c20010, rc));
  364. return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
  365. }
  366. if (agc->d00 != 0)
  367. goto exit_rc;
  368. if (w0A < w08)
  369. goto exit_rc;
  370. if (w0A > 0x3ff)
  371. goto exit_rc;
  372. if (w0C > 0x3ff)
  373. goto exit_rc;
  374. if (w06 > 0x3ff)
  375. goto exit_rc;
  376. EXIT_RC(RD16(s, 0x0c20010));
  377. rc |= 0x10;
  378. EXIT_RC(WR16(s, 0x0c20010, rc));
  379. EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
  380. EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
  381. EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
  382. quot = w0C / 113;
  383. rem = w0C % 113;
  384. if (quot <= 8) {
  385. quot = 8 - quot;
  386. } else {
  387. quot = 0;
  388. rem += 113;
  389. }
  390. EXIT_RC(WR16(s, 0x0c20024, quot));
  391. i = fastIncrDecLUT_15273[rem / 8];
  392. EXIT_RC(WR16(s, 0x0c2002d, i));
  393. EXIT_RC(WR16(s, 0x0c2002e, i));
  394. i = slowIncrDecLUT_15272[rem / 28];
  395. EXIT_RC(WR16(s, 0x0c2002b, i));
  396. rc = WR16(s, 0x0c2002c, i);
  397. exit_rc:
  398. return rc;
  399. }
  400. static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
  401. {
  402. u16 w04 = agc->w04;
  403. u16 w06 = agc->w06;
  404. int rc = -1;
  405. pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
  406. if (w04 > 0x3ff)
  407. goto exit_rc;
  408. switch (agc->d00) {
  409. case 1:
  410. if (w04 == 0x3ff)
  411. w04 = 0x400;
  412. EXIT_RC(WR16(s, 0x0c20036, w04));
  413. s->config.w9C &= ~2;
  414. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  415. EXIT_RC(RD16(s, 0x0c20010));
  416. rc &= 0xbfdf;
  417. EXIT_RC(WR16(s, 0x0c20010, rc));
  418. EXIT_RC(RD16(s, 0x0c20013));
  419. rc &= ~2;
  420. break;
  421. case 0:
  422. // loc_8000659
  423. s->config.w9C &= ~2;
  424. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  425. EXIT_RC(RD16(s, 0x0c20010));
  426. rc &= 0xbfdf;
  427. rc |= 0x4000;
  428. EXIT_RC(WR16(s, 0x0c20010, rc));
  429. EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
  430. EXIT_RC(RD16(s, 0x0c20013));
  431. rc &= ~2;
  432. break;
  433. default:
  434. s->config.w9C |= 2;
  435. EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
  436. EXIT_RC(RD16(s, 0x0c20010));
  437. rc &= 0xbfdf;
  438. EXIT_RC(WR16(s, 0x0c20010, rc));
  439. EXIT_RC(WR16(s, 0x0c20036, 0));
  440. EXIT_RC(RD16(s, 0x0c20013));
  441. rc |= 2;
  442. }
  443. rc = WR16(s, 0x0c20013, rc);
  444. exit_rc:
  445. return rc;
  446. }
  447. static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
  448. {
  449. int rc;
  450. *lockstat = 0;
  451. rc = RD16(s, 0x082004b);
  452. if (rc < 0)
  453. return rc;
  454. if (s->config.d60 != 2)
  455. return 0;
  456. if ((rc & 7) == 7)
  457. *lockstat |= 1;
  458. if ((rc & 3) == 3)
  459. *lockstat |= 2;
  460. if (rc & 1)
  461. *lockstat |= 4;
  462. return 0;
  463. }
  464. static int CorrectSysClockDeviation(struct drx397xD_state *s)
  465. {
  466. int rc = -EINVAL;
  467. int lockstat;
  468. u32 clk, clk_limit;
  469. pr_debug("%s\n", __FUNCTION__);
  470. if (s->config.d5C == 0) {
  471. EXIT_RC(WR16(s, 0x08200e8, 0x010));
  472. EXIT_RC(WR16(s, 0x08200e9, 0x113));
  473. s->config.d5C = 1;
  474. return rc;
  475. }
  476. if (s->config.d5C != 1)
  477. goto exit_rc;
  478. rc = RD16(s, 0x0820048);
  479. rc = GetLockStatus(s, &lockstat);
  480. if (rc < 0)
  481. goto exit_rc;
  482. if ((lockstat & 1) == 0)
  483. goto exit_rc;
  484. EXIT_RC(WR16(s, 0x0420033, 0x200));
  485. EXIT_RC(WR16(s, 0x0420034, 0xc5));
  486. EXIT_RC(WR16(s, 0x0420035, 0x10));
  487. EXIT_RC(WR16(s, 0x0420036, 0x1));
  488. EXIT_RC(WR16(s, 0x0420037, 0xa));
  489. EXIT_RC(HI_Command(s, 6));
  490. EXIT_RC(RD16(s, 0x0420040));
  491. clk = rc;
  492. EXIT_RC(RD16(s, 0x0420041));
  493. clk |= rc << 16;
  494. if (clk <= 0x26ffff)
  495. goto exit_rc;
  496. if (clk > 0x610000)
  497. goto exit_rc;
  498. if (!s->bandwidth_parm)
  499. return -EINVAL;
  500. /* round & convert to Hz */
  501. clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
  502. clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
  503. if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
  504. s->f_osc = clk;
  505. pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
  506. s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
  507. }
  508. rc = WR16(s, 0x08200e8, 0);
  509. exit_rc:
  510. return rc;
  511. }
  512. static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
  513. {
  514. int rc, si, bp;
  515. pr_debug("%s\n", __FUNCTION__);
  516. si = s->config.wA0;
  517. if (s->config.w98 == 0) {
  518. si |= 1;
  519. bp = 0;
  520. } else {
  521. si &= ~1;
  522. bp = 0x200;
  523. }
  524. if (s->config.w9A == 0) {
  525. si |= 0x80;
  526. } else {
  527. si &= ~0x80;
  528. }
  529. EXIT_RC(WR16(s, 0x2150045, 0));
  530. EXIT_RC(WR16(s, 0x2150010, si));
  531. EXIT_RC(WR16(s, 0x2150011, bp));
  532. rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
  533. exit_rc:
  534. return rc;
  535. }
  536. static int drx_tune(struct drx397xD_state *s,
  537. struct dvb_frontend_parameters *fep)
  538. {
  539. u16 v22 = 0;
  540. u16 v1C = 0;
  541. u16 v1A = 0;
  542. u16 v18 = 0;
  543. u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
  544. u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
  545. int rc, df_tuner;
  546. int a, b, c, d;
  547. pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
  548. if (s->config.d60 != 2)
  549. goto set_tuner;
  550. rc = CorrectSysClockDeviation(s);
  551. if (rc < 0)
  552. goto set_tuner;
  553. s->config.d60 = 1;
  554. rc = ConfigureMPEGOutput(s, 0);
  555. if (rc < 0)
  556. goto set_tuner;
  557. set_tuner:
  558. rc = PLL_Set(s, fep, &df_tuner);
  559. if (rc < 0) {
  560. printk(KERN_ERR "Error in pll_set\n");
  561. goto exit_rc;
  562. }
  563. msleep(200);
  564. a = rc = RD16(s, 0x2150016);
  565. if (rc < 0)
  566. goto exit_rc;
  567. b = rc = RD16(s, 0x2150010);
  568. if (rc < 0)
  569. goto exit_rc;
  570. c = rc = RD16(s, 0x2150034);
  571. if (rc < 0)
  572. goto exit_rc;
  573. d = rc = RD16(s, 0x2150035);
  574. if (rc < 0)
  575. goto exit_rc;
  576. rc = WR16(s, 0x2150014, c);
  577. rc = WR16(s, 0x2150015, d);
  578. rc = WR16(s, 0x2150010, 0);
  579. rc = WR16(s, 0x2150000, 2);
  580. rc = WR16(s, 0x2150036, 0x0fff);
  581. rc = WR16(s, 0x2150016, a);
  582. rc = WR16(s, 0x2150010, 2);
  583. rc = WR16(s, 0x2150007, 0);
  584. rc = WR16(s, 0x2150000, 1);
  585. rc = WR16(s, 0x2110000, 0);
  586. rc = WR16(s, 0x0800000, 0);
  587. rc = WR16(s, 0x2800000, 0);
  588. rc = WR16(s, 0x2110010, 0x664);
  589. rc = write_fw(s, DRXD_ResetECRAM);
  590. rc = WR16(s, 0x2110000, 1);
  591. rc = write_fw(s, DRXD_InitSC);
  592. if (rc < 0)
  593. goto exit_rc;
  594. rc = SetCfgIfAgc(s, &s->config.ifagc);
  595. if (rc < 0)
  596. goto exit_rc;
  597. rc = SetCfgRfAgc(s, &s->config.rfagc);
  598. if (rc < 0)
  599. goto exit_rc;
  600. if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
  601. v22 = 1;
  602. switch (fep->u.ofdm.transmission_mode) {
  603. case TRANSMISSION_MODE_8K:
  604. edi = 1;
  605. if (s->chip_rev == DRXD_FW_B1)
  606. break;
  607. rc = WR16(s, 0x2010010, 0);
  608. if (rc < 0)
  609. break;
  610. v1C = 0x63;
  611. v1A = 0x53;
  612. v18 = 0x43;
  613. break;
  614. default:
  615. edi = 0;
  616. if (s->chip_rev == DRXD_FW_B1)
  617. break;
  618. rc = WR16(s, 0x2010010, 1);
  619. if (rc < 0)
  620. break;
  621. v1C = 0x61;
  622. v1A = 0x47;
  623. v18 = 0x41;
  624. }
  625. switch (fep->u.ofdm.guard_interval) {
  626. case GUARD_INTERVAL_1_4:
  627. edi |= 0x0c;
  628. break;
  629. case GUARD_INTERVAL_1_8:
  630. edi |= 0x08;
  631. break;
  632. case GUARD_INTERVAL_1_16:
  633. edi |= 0x04;
  634. break;
  635. case GUARD_INTERVAL_1_32:
  636. break;
  637. default:
  638. v22 |= 2;
  639. }
  640. ebx = 0;
  641. ebp = 0;
  642. v20 = 0;
  643. v1E = 0;
  644. v16 = 0;
  645. v14 = 0;
  646. v12 = 0;
  647. v10 = 0;
  648. v0E = 0;
  649. switch (fep->u.ofdm.hierarchy_information) {
  650. case HIERARCHY_1:
  651. edi |= 0x40;
  652. if (s->chip_rev == DRXD_FW_B1)
  653. break;
  654. rc = WR16(s, 0x1c10047, 1);
  655. if (rc < 0)
  656. goto exit_rc;
  657. rc = WR16(s, 0x2010012, 1);
  658. if (rc < 0)
  659. goto exit_rc;
  660. ebx = 0x19f;
  661. ebp = 0x1fb;
  662. v20 = 0x0c0;
  663. v1E = 0x195;
  664. v16 = 0x1d6;
  665. v14 = 0x1ef;
  666. v12 = 4;
  667. v10 = 5;
  668. v0E = 5;
  669. break;
  670. case HIERARCHY_2:
  671. edi |= 0x80;
  672. if (s->chip_rev == DRXD_FW_B1)
  673. break;
  674. rc = WR16(s, 0x1c10047, 2);
  675. if (rc < 0)
  676. goto exit_rc;
  677. rc = WR16(s, 0x2010012, 2);
  678. if (rc < 0)
  679. goto exit_rc;
  680. ebx = 0x08f;
  681. ebp = 0x12f;
  682. v20 = 0x0c0;
  683. v1E = 0x11e;
  684. v16 = 0x1d6;
  685. v14 = 0x15e;
  686. v12 = 4;
  687. v10 = 5;
  688. v0E = 5;
  689. break;
  690. case HIERARCHY_4:
  691. edi |= 0xc0;
  692. if (s->chip_rev == DRXD_FW_B1)
  693. break;
  694. rc = WR16(s, 0x1c10047, 3);
  695. if (rc < 0)
  696. goto exit_rc;
  697. rc = WR16(s, 0x2010012, 3);
  698. if (rc < 0)
  699. goto exit_rc;
  700. ebx = 0x14d;
  701. ebp = 0x197;
  702. v20 = 0x0c0;
  703. v1E = 0x1ce;
  704. v16 = 0x1d6;
  705. v14 = 0x11a;
  706. v12 = 4;
  707. v10 = 6;
  708. v0E = 5;
  709. break;
  710. default:
  711. v22 |= 8;
  712. if (s->chip_rev == DRXD_FW_B1)
  713. break;
  714. rc = WR16(s, 0x1c10047, 0);
  715. if (rc < 0)
  716. goto exit_rc;
  717. rc = WR16(s, 0x2010012, 0);
  718. if (rc < 0)
  719. goto exit_rc;
  720. // QPSK QAM16 QAM64
  721. ebx = 0x19f; // 62
  722. ebp = 0x1fb; // 15
  723. v20 = 0x16a; // 62
  724. v1E = 0x195; // 62
  725. v16 = 0x1bb; // 15
  726. v14 = 0x1ef; // 15
  727. v12 = 5; // 16
  728. v10 = 5; // 16
  729. v0E = 5; // 16
  730. }
  731. switch (fep->u.ofdm.constellation) {
  732. default:
  733. v22 |= 4;
  734. case QPSK:
  735. if (s->chip_rev == DRXD_FW_B1)
  736. break;
  737. rc = WR16(s, 0x1c10046, 0);
  738. if (rc < 0)
  739. goto exit_rc;
  740. rc = WR16(s, 0x2010011, 0);
  741. if (rc < 0)
  742. goto exit_rc;
  743. rc = WR16(s, 0x201001a, 0x10);
  744. if (rc < 0)
  745. goto exit_rc;
  746. rc = WR16(s, 0x201001b, 0);
  747. if (rc < 0)
  748. goto exit_rc;
  749. rc = WR16(s, 0x201001c, 0);
  750. if (rc < 0)
  751. goto exit_rc;
  752. rc = WR16(s, 0x1c10062, v20);
  753. if (rc < 0)
  754. goto exit_rc;
  755. rc = WR16(s, 0x1c1002a, v1C);
  756. if (rc < 0)
  757. goto exit_rc;
  758. rc = WR16(s, 0x1c10015, v16);
  759. if (rc < 0)
  760. goto exit_rc;
  761. rc = WR16(s, 0x1c10016, v12);
  762. if (rc < 0)
  763. goto exit_rc;
  764. break;
  765. case QAM_16:
  766. edi |= 0x10;
  767. if (s->chip_rev == DRXD_FW_B1)
  768. break;
  769. rc = WR16(s, 0x1c10046, 1);
  770. if (rc < 0)
  771. goto exit_rc;
  772. rc = WR16(s, 0x2010011, 1);
  773. if (rc < 0)
  774. goto exit_rc;
  775. rc = WR16(s, 0x201001a, 0x10);
  776. if (rc < 0)
  777. goto exit_rc;
  778. rc = WR16(s, 0x201001b, 4);
  779. if (rc < 0)
  780. goto exit_rc;
  781. rc = WR16(s, 0x201001c, 0);
  782. if (rc < 0)
  783. goto exit_rc;
  784. rc = WR16(s, 0x1c10062, v1E);
  785. if (rc < 0)
  786. goto exit_rc;
  787. rc = WR16(s, 0x1c1002a, v1A);
  788. if (rc < 0)
  789. goto exit_rc;
  790. rc = WR16(s, 0x1c10015, v14);
  791. if (rc < 0)
  792. goto exit_rc;
  793. rc = WR16(s, 0x1c10016, v10);
  794. if (rc < 0)
  795. goto exit_rc;
  796. break;
  797. case QAM_64:
  798. edi |= 0x20;
  799. rc = WR16(s, 0x1c10046, 2);
  800. if (rc < 0)
  801. goto exit_rc;
  802. rc = WR16(s, 0x2010011, 2);
  803. if (rc < 0)
  804. goto exit_rc;
  805. rc = WR16(s, 0x201001a, 0x20);
  806. if (rc < 0)
  807. goto exit_rc;
  808. rc = WR16(s, 0x201001b, 8);
  809. if (rc < 0)
  810. goto exit_rc;
  811. rc = WR16(s, 0x201001c, 2);
  812. if (rc < 0)
  813. goto exit_rc;
  814. rc = WR16(s, 0x1c10062, ebx);
  815. if (rc < 0)
  816. goto exit_rc;
  817. rc = WR16(s, 0x1c1002a, v18);
  818. if (rc < 0)
  819. goto exit_rc;
  820. rc = WR16(s, 0x1c10015, ebp);
  821. if (rc < 0)
  822. goto exit_rc;
  823. rc = WR16(s, 0x1c10016, v0E);
  824. if (rc < 0)
  825. goto exit_rc;
  826. break;
  827. }
  828. if (s->config.s20d24 == 1) {
  829. rc = WR16(s, 0x2010013, 0);
  830. } else {
  831. rc = WR16(s, 0x2010013, 1);
  832. edi |= 0x1000;
  833. }
  834. switch (fep->u.ofdm.code_rate_HP) {
  835. default:
  836. v22 |= 0x10;
  837. case FEC_1_2:
  838. if (s->chip_rev == DRXD_FW_B1)
  839. break;
  840. rc = WR16(s, 0x2090011, 0);
  841. break;
  842. case FEC_2_3:
  843. edi |= 0x200;
  844. if (s->chip_rev == DRXD_FW_B1)
  845. break;
  846. rc = WR16(s, 0x2090011, 1);
  847. break;
  848. case FEC_3_4:
  849. edi |= 0x400;
  850. if (s->chip_rev == DRXD_FW_B1)
  851. break;
  852. rc = WR16(s, 0x2090011, 2);
  853. break;
  854. case FEC_5_6: /* 5 */
  855. edi |= 0x600;
  856. if (s->chip_rev == DRXD_FW_B1)
  857. break;
  858. rc = WR16(s, 0x2090011, 3);
  859. break;
  860. case FEC_7_8: /* 7 */
  861. edi |= 0x800;
  862. if (s->chip_rev == DRXD_FW_B1)
  863. break;
  864. rc = WR16(s, 0x2090011, 4);
  865. break;
  866. };
  867. if (rc < 0)
  868. goto exit_rc;
  869. switch (fep->u.ofdm.bandwidth) {
  870. default:
  871. rc = -EINVAL;
  872. goto exit_rc;
  873. case BANDWIDTH_8_MHZ: /* 0 */
  874. case BANDWIDTH_AUTO:
  875. rc = WR16(s, 0x0c2003f, 0x32);
  876. s->bandwidth_parm = ebx = 0x8b8249; // 9142857
  877. edx = 0;
  878. break;
  879. case BANDWIDTH_7_MHZ:
  880. rc = WR16(s, 0x0c2003f, 0x3b);
  881. s->bandwidth_parm = ebx = 0x7a1200; // 8000000
  882. edx = 0x4807;
  883. break;
  884. case BANDWIDTH_6_MHZ:
  885. rc = WR16(s, 0x0c2003f, 0x47);
  886. s->bandwidth_parm = ebx = 0x68a1b6; // 6857142
  887. edx = 0x0f07;
  888. break;
  889. };
  890. if (rc < 0)
  891. goto exit_rc;
  892. rc = WR16(s, 0x08200ec, edx);
  893. if (rc < 0)
  894. goto exit_rc;
  895. rc = RD16(s, 0x0820050);
  896. if (rc < 0)
  897. goto exit_rc;
  898. rc = WR16(s, 0x0820050, rc);
  899. {
  900. /* Configure bandwidth specific factor */
  901. ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
  902. (u64)ebx) - 0x800000;
  903. EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
  904. EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
  905. /* drx397xD oscillator calibration */
  906. ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
  907. (s->f_osc >> 1), (u64)s->f_osc);
  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);