drx397xD.c 30 KB

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