lgdt3305.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. /*
  2. * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
  3. *
  4. * Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
  5. *
  6. * LGDT3304 support by Jarod Wilson <jarod@redhat.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. *
  22. */
  23. #include <asm/div64.h>
  24. #include <linux/dvb/frontend.h>
  25. #include <linux/slab.h>
  26. #include "dvb_math.h"
  27. #include "lgdt3305.h"
  28. static int debug;
  29. module_param(debug, int, 0644);
  30. MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
  31. #define DBG_INFO 1
  32. #define DBG_REG 2
  33. #define lg_printk(kern, fmt, arg...) \
  34. printk(kern "%s: " fmt, __func__, ##arg)
  35. #define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3305: " fmt, ##arg)
  36. #define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)
  37. #define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)
  38. #define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \
  39. lg_printk(KERN_DEBUG, fmt, ##arg)
  40. #define lg_reg(fmt, arg...) if (debug & DBG_REG) \
  41. lg_printk(KERN_DEBUG, fmt, ##arg)
  42. #define lg_fail(ret) \
  43. ({ \
  44. int __ret; \
  45. __ret = (ret < 0); \
  46. if (__ret) \
  47. lg_err("error %d on line %d\n", ret, __LINE__); \
  48. __ret; \
  49. })
  50. struct lgdt3305_state {
  51. struct i2c_adapter *i2c_adap;
  52. const struct lgdt3305_config *cfg;
  53. struct dvb_frontend frontend;
  54. fe_modulation_t current_modulation;
  55. u32 current_frequency;
  56. u32 snr;
  57. };
  58. /* ------------------------------------------------------------------------ */
  59. /* FIXME: verify & document the LGDT3304 registers */
  60. #define LGDT3305_GEN_CTRL_1 0x0000
  61. #define LGDT3305_GEN_CTRL_2 0x0001
  62. #define LGDT3305_GEN_CTRL_3 0x0002
  63. #define LGDT3305_GEN_STATUS 0x0003
  64. #define LGDT3305_GEN_CONTROL 0x0007
  65. #define LGDT3305_GEN_CTRL_4 0x000a
  66. #define LGDT3305_DGTL_AGC_REF_1 0x0012
  67. #define LGDT3305_DGTL_AGC_REF_2 0x0013
  68. #define LGDT3305_CR_CTR_FREQ_1 0x0106
  69. #define LGDT3305_CR_CTR_FREQ_2 0x0107
  70. #define LGDT3305_CR_CTR_FREQ_3 0x0108
  71. #define LGDT3305_CR_CTR_FREQ_4 0x0109
  72. #define LGDT3305_CR_MSE_1 0x011b
  73. #define LGDT3305_CR_MSE_2 0x011c
  74. #define LGDT3305_CR_LOCK_STATUS 0x011d
  75. #define LGDT3305_CR_CTRL_7 0x0126
  76. #define LGDT3305_AGC_POWER_REF_1 0x0300
  77. #define LGDT3305_AGC_POWER_REF_2 0x0301
  78. #define LGDT3305_AGC_DELAY_PT_1 0x0302
  79. #define LGDT3305_AGC_DELAY_PT_2 0x0303
  80. #define LGDT3305_RFAGC_LOOP_FLTR_BW_1 0x0306
  81. #define LGDT3305_RFAGC_LOOP_FLTR_BW_2 0x0307
  82. #define LGDT3305_IFBW_1 0x0308
  83. #define LGDT3305_IFBW_2 0x0309
  84. #define LGDT3305_AGC_CTRL_1 0x030c
  85. #define LGDT3305_AGC_CTRL_4 0x0314
  86. #define LGDT3305_EQ_MSE_1 0x0413
  87. #define LGDT3305_EQ_MSE_2 0x0414
  88. #define LGDT3305_EQ_MSE_3 0x0415
  89. #define LGDT3305_PT_MSE_1 0x0417
  90. #define LGDT3305_PT_MSE_2 0x0418
  91. #define LGDT3305_PT_MSE_3 0x0419
  92. #define LGDT3305_FEC_BLOCK_CTRL 0x0504
  93. #define LGDT3305_FEC_LOCK_STATUS 0x050a
  94. #define LGDT3305_FEC_PKT_ERR_1 0x050c
  95. #define LGDT3305_FEC_PKT_ERR_2 0x050d
  96. #define LGDT3305_TP_CTRL_1 0x050e
  97. #define LGDT3305_BERT_PERIOD 0x0801
  98. #define LGDT3305_BERT_ERROR_COUNT_1 0x080a
  99. #define LGDT3305_BERT_ERROR_COUNT_2 0x080b
  100. #define LGDT3305_BERT_ERROR_COUNT_3 0x080c
  101. #define LGDT3305_BERT_ERROR_COUNT_4 0x080d
  102. static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 val)
  103. {
  104. int ret;
  105. u8 buf[] = { reg >> 8, reg & 0xff, val };
  106. struct i2c_msg msg = {
  107. .addr = state->cfg->i2c_addr, .flags = 0,
  108. .buf = buf, .len = 3,
  109. };
  110. lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
  111. ret = i2c_transfer(state->i2c_adap, &msg, 1);
  112. if (ret != 1) {
  113. lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
  114. msg.buf[0], msg.buf[1], msg.buf[2], ret);
  115. if (ret < 0)
  116. return ret;
  117. else
  118. return -EREMOTEIO;
  119. }
  120. return 0;
  121. }
  122. static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val)
  123. {
  124. int ret;
  125. u8 reg_buf[] = { reg >> 8, reg & 0xff };
  126. struct i2c_msg msg[] = {
  127. { .addr = state->cfg->i2c_addr,
  128. .flags = 0, .buf = reg_buf, .len = 2 },
  129. { .addr = state->cfg->i2c_addr,
  130. .flags = I2C_M_RD, .buf = val, .len = 1 },
  131. };
  132. lg_reg("reg: 0x%04x\n", reg);
  133. ret = i2c_transfer(state->i2c_adap, msg, 2);
  134. if (ret != 2) {
  135. lg_err("error (addr %02x reg %04x error (ret == %i)\n",
  136. state->cfg->i2c_addr, reg, ret);
  137. if (ret < 0)
  138. return ret;
  139. else
  140. return -EREMOTEIO;
  141. }
  142. return 0;
  143. }
  144. #define read_reg(state, reg) \
  145. ({ \
  146. u8 __val; \
  147. int ret = lgdt3305_read_reg(state, reg, &__val); \
  148. if (lg_fail(ret)) \
  149. __val = 0; \
  150. __val; \
  151. })
  152. static int lgdt3305_set_reg_bit(struct lgdt3305_state *state,
  153. u16 reg, int bit, int onoff)
  154. {
  155. u8 val;
  156. int ret;
  157. lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
  158. ret = lgdt3305_read_reg(state, reg, &val);
  159. if (lg_fail(ret))
  160. goto fail;
  161. val &= ~(1 << bit);
  162. val |= (onoff & 1) << bit;
  163. ret = lgdt3305_write_reg(state, reg, val);
  164. fail:
  165. return ret;
  166. }
  167. struct lgdt3305_reg {
  168. u16 reg;
  169. u8 val;
  170. };
  171. static int lgdt3305_write_regs(struct lgdt3305_state *state,
  172. struct lgdt3305_reg *regs, int len)
  173. {
  174. int i, ret;
  175. lg_reg("writing %d registers...\n", len);
  176. for (i = 0; i < len - 1; i++) {
  177. ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val);
  178. if (lg_fail(ret))
  179. return ret;
  180. }
  181. return 0;
  182. }
  183. /* ------------------------------------------------------------------------ */
  184. static int lgdt3305_soft_reset(struct lgdt3305_state *state)
  185. {
  186. int ret;
  187. lg_dbg("\n");
  188. ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0);
  189. if (lg_fail(ret))
  190. goto fail;
  191. msleep(20);
  192. ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1);
  193. fail:
  194. return ret;
  195. }
  196. static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
  197. enum lgdt3305_mpeg_mode mode)
  198. {
  199. lg_dbg("(%d)\n", mode);
  200. return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
  201. }
  202. static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
  203. enum lgdt3305_tp_clock_edge edge,
  204. enum lgdt3305_tp_valid_polarity valid)
  205. {
  206. u8 val;
  207. int ret;
  208. lg_dbg("edge = %d, valid = %d\n", edge, valid);
  209. ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val);
  210. if (lg_fail(ret))
  211. goto fail;
  212. val &= ~0x09;
  213. if (edge)
  214. val |= 0x08;
  215. if (valid)
  216. val |= 0x01;
  217. ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val);
  218. if (lg_fail(ret))
  219. goto fail;
  220. ret = lgdt3305_soft_reset(state);
  221. fail:
  222. return ret;
  223. }
  224. static int lgdt3305_set_modulation(struct lgdt3305_state *state,
  225. struct dvb_frontend_parameters *param)
  226. {
  227. u8 opermode;
  228. int ret;
  229. lg_dbg("\n");
  230. ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode);
  231. if (lg_fail(ret))
  232. goto fail;
  233. opermode &= ~0x03;
  234. switch (param->u.vsb.modulation) {
  235. case VSB_8:
  236. opermode |= 0x03;
  237. break;
  238. case QAM_64:
  239. opermode |= 0x00;
  240. break;
  241. case QAM_256:
  242. opermode |= 0x01;
  243. break;
  244. default:
  245. return -EINVAL;
  246. }
  247. ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode);
  248. fail:
  249. return ret;
  250. }
  251. static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
  252. struct dvb_frontend_parameters *param)
  253. {
  254. int val;
  255. switch (param->u.vsb.modulation) {
  256. case VSB_8:
  257. val = 0;
  258. break;
  259. case QAM_64:
  260. case QAM_256:
  261. val = 1;
  262. break;
  263. default:
  264. return -EINVAL;
  265. }
  266. lg_dbg("val = %d\n", val);
  267. return lgdt3305_set_reg_bit(state, 0x043f, 2, val);
  268. }
  269. /* ------------------------------------------------------------------------ */
  270. static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
  271. struct dvb_frontend_parameters *param)
  272. {
  273. u16 agc_ref;
  274. switch (param->u.vsb.modulation) {
  275. case VSB_8:
  276. agc_ref = 0x32c4;
  277. break;
  278. case QAM_64:
  279. agc_ref = 0x2a00;
  280. break;
  281. case QAM_256:
  282. agc_ref = 0x2a80;
  283. break;
  284. default:
  285. return -EINVAL;
  286. }
  287. lg_dbg("agc ref: 0x%04x\n", agc_ref);
  288. lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8);
  289. lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff);
  290. return 0;
  291. }
  292. static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
  293. struct dvb_frontend_parameters *param)
  294. {
  295. u16 ifbw, rfbw, agcdelay;
  296. switch (param->u.vsb.modulation) {
  297. case VSB_8:
  298. agcdelay = 0x04c0;
  299. rfbw = 0x8000;
  300. ifbw = 0x8000;
  301. break;
  302. case QAM_64:
  303. case QAM_256:
  304. agcdelay = 0x046b;
  305. rfbw = 0x8889;
  306. /* FIXME: investigate optimal ifbw & rfbw values for the
  307. * DT3304 and re-write this switch..case block */
  308. if (state->cfg->demod_chip == LGDT3304)
  309. ifbw = 0x6666;
  310. else /* (state->cfg->demod_chip == LGDT3305) */
  311. ifbw = 0x8888;
  312. break;
  313. default:
  314. return -EINVAL;
  315. }
  316. if (state->cfg->rf_agc_loop) {
  317. lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw);
  318. /* rf agc loop filter bandwidth */
  319. lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1,
  320. agcdelay >> 8);
  321. lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2,
  322. agcdelay & 0xff);
  323. lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1,
  324. rfbw >> 8);
  325. lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2,
  326. rfbw & 0xff);
  327. } else {
  328. lg_dbg("ifbw: 0x%04x\n", ifbw);
  329. /* if agc loop filter bandwidth */
  330. lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8);
  331. lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff);
  332. }
  333. return 0;
  334. }
  335. static int lgdt3305_agc_setup(struct lgdt3305_state *state,
  336. struct dvb_frontend_parameters *param)
  337. {
  338. int lockdten, acqen;
  339. switch (param->u.vsb.modulation) {
  340. case VSB_8:
  341. lockdten = 0;
  342. acqen = 0;
  343. break;
  344. case QAM_64:
  345. case QAM_256:
  346. lockdten = 1;
  347. acqen = 1;
  348. break;
  349. default:
  350. return -EINVAL;
  351. }
  352. lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
  353. /* control agc function */
  354. switch (state->cfg->demod_chip) {
  355. case LGDT3304:
  356. lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
  357. lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
  358. break;
  359. case LGDT3305:
  360. lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
  361. lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
  362. break;
  363. default:
  364. return -EINVAL;
  365. }
  366. return lgdt3305_rfagc_loop(state, param);
  367. }
  368. static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
  369. struct dvb_frontend_parameters *param)
  370. {
  371. u16 usref = 0;
  372. switch (param->u.vsb.modulation) {
  373. case VSB_8:
  374. if (state->cfg->usref_8vsb)
  375. usref = state->cfg->usref_8vsb;
  376. break;
  377. case QAM_64:
  378. if (state->cfg->usref_qam64)
  379. usref = state->cfg->usref_qam64;
  380. break;
  381. case QAM_256:
  382. if (state->cfg->usref_qam256)
  383. usref = state->cfg->usref_qam256;
  384. break;
  385. default:
  386. return -EINVAL;
  387. }
  388. if (usref) {
  389. lg_dbg("set manual mode: 0x%04x\n", usref);
  390. lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1);
  391. lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1,
  392. 0xff & (usref >> 8));
  393. lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2,
  394. 0xff & (usref >> 0));
  395. }
  396. return 0;
  397. }
  398. /* ------------------------------------------------------------------------ */
  399. static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
  400. struct dvb_frontend_parameters *param,
  401. int inversion)
  402. {
  403. int ret;
  404. lg_dbg("(%d)\n", inversion);
  405. switch (param->u.vsb.modulation) {
  406. case VSB_8:
  407. ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
  408. inversion ? 0xf9 : 0x79);
  409. break;
  410. case QAM_64:
  411. case QAM_256:
  412. ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL,
  413. inversion ? 0xfd : 0xff);
  414. break;
  415. default:
  416. ret = -EINVAL;
  417. }
  418. return ret;
  419. }
  420. static int lgdt3305_set_if(struct lgdt3305_state *state,
  421. struct dvb_frontend_parameters *param)
  422. {
  423. u16 if_freq_khz;
  424. u8 nco1, nco2, nco3, nco4;
  425. u64 nco;
  426. switch (param->u.vsb.modulation) {
  427. case VSB_8:
  428. if_freq_khz = state->cfg->vsb_if_khz;
  429. break;
  430. case QAM_64:
  431. case QAM_256:
  432. if_freq_khz = state->cfg->qam_if_khz;
  433. break;
  434. default:
  435. return -EINVAL;
  436. }
  437. nco = if_freq_khz / 10;
  438. switch (param->u.vsb.modulation) {
  439. case VSB_8:
  440. nco <<= 24;
  441. do_div(nco, 625);
  442. break;
  443. case QAM_64:
  444. case QAM_256:
  445. nco <<= 28;
  446. do_div(nco, 625);
  447. break;
  448. default:
  449. return -EINVAL;
  450. }
  451. nco1 = (nco >> 24) & 0x3f;
  452. nco1 |= 0x40;
  453. nco2 = (nco >> 16) & 0xff;
  454. nco3 = (nco >> 8) & 0xff;
  455. nco4 = nco & 0xff;
  456. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1);
  457. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2);
  458. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3);
  459. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4);
  460. lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n",
  461. if_freq_khz, nco1, nco2, nco3, nco4);
  462. return 0;
  463. }
  464. /* ------------------------------------------------------------------------ */
  465. static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
  466. {
  467. struct lgdt3305_state *state = fe->demodulator_priv;
  468. if (state->cfg->deny_i2c_rptr)
  469. return 0;
  470. lg_dbg("(%d)\n", enable);
  471. return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5,
  472. enable ? 0 : 1);
  473. }
  474. static int lgdt3305_sleep(struct dvb_frontend *fe)
  475. {
  476. struct lgdt3305_state *state = fe->demodulator_priv;
  477. u8 gen_ctrl_3, gen_ctrl_4;
  478. lg_dbg("\n");
  479. gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3);
  480. gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4);
  481. /* hold in software reset while sleeping */
  482. gen_ctrl_3 &= ~0x01;
  483. /* tristate the IF-AGC pin */
  484. gen_ctrl_3 |= 0x02;
  485. /* tristate the RF-AGC pin */
  486. gen_ctrl_3 |= 0x04;
  487. /* disable vsb/qam module */
  488. gen_ctrl_4 &= ~0x01;
  489. /* disable adc module */
  490. gen_ctrl_4 &= ~0x02;
  491. lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3);
  492. lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4);
  493. return 0;
  494. }
  495. static int lgdt3305_init(struct dvb_frontend *fe)
  496. {
  497. struct lgdt3305_state *state = fe->demodulator_priv;
  498. int ret;
  499. static struct lgdt3305_reg lgdt3304_init_data[] = {
  500. { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
  501. { .reg = 0x000d, .val = 0x02, },
  502. { .reg = 0x000e, .val = 0x02, },
  503. { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
  504. { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
  505. { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
  506. { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
  507. { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
  508. { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
  509. { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
  510. { .reg = 0x0112, .val = 0x17, },
  511. { .reg = 0x0113, .val = 0x15, },
  512. { .reg = 0x0114, .val = 0x18, },
  513. { .reg = 0x0115, .val = 0xff, },
  514. { .reg = 0x0116, .val = 0x3c, },
  515. { .reg = 0x0214, .val = 0x67, },
  516. { .reg = 0x0424, .val = 0x8d, },
  517. { .reg = 0x0427, .val = 0x12, },
  518. { .reg = 0x0428, .val = 0x4f, },
  519. { .reg = LGDT3305_IFBW_1, .val = 0x80, },
  520. { .reg = LGDT3305_IFBW_2, .val = 0x00, },
  521. { .reg = 0x030a, .val = 0x08, },
  522. { .reg = 0x030b, .val = 0x9b, },
  523. { .reg = 0x030d, .val = 0x00, },
  524. { .reg = 0x030e, .val = 0x1c, },
  525. { .reg = 0x0314, .val = 0xe1, },
  526. { .reg = 0x000d, .val = 0x82, },
  527. { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
  528. { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
  529. };
  530. static struct lgdt3305_reg lgdt3305_init_data[] = {
  531. { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
  532. { .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, },
  533. { .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, },
  534. { .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, },
  535. { .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, },
  536. { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
  537. { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
  538. { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
  539. { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
  540. { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
  541. { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
  542. { .reg = LGDT3305_CR_CTRL_7, .val = 0x79, },
  543. { .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, },
  544. { .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, },
  545. { .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, },
  546. { .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, },
  547. { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },
  548. { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },
  549. { .reg = LGDT3305_IFBW_1, .val = 0x80, },
  550. { .reg = LGDT3305_IFBW_2, .val = 0x00, },
  551. { .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, },
  552. { .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, },
  553. { .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, },
  554. { .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, },
  555. };
  556. lg_dbg("\n");
  557. switch (state->cfg->demod_chip) {
  558. case LGDT3304:
  559. ret = lgdt3305_write_regs(state, lgdt3304_init_data,
  560. ARRAY_SIZE(lgdt3304_init_data));
  561. break;
  562. case LGDT3305:
  563. ret = lgdt3305_write_regs(state, lgdt3305_init_data,
  564. ARRAY_SIZE(lgdt3305_init_data));
  565. break;
  566. default:
  567. ret = -EINVAL;
  568. }
  569. if (lg_fail(ret))
  570. goto fail;
  571. ret = lgdt3305_soft_reset(state);
  572. fail:
  573. return ret;
  574. }
  575. static int lgdt3304_set_parameters(struct dvb_frontend *fe,
  576. struct dvb_frontend_parameters *param)
  577. {
  578. struct lgdt3305_state *state = fe->demodulator_priv;
  579. int ret;
  580. lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
  581. if (fe->ops.tuner_ops.set_params) {
  582. ret = fe->ops.tuner_ops.set_params(fe, param);
  583. if (fe->ops.i2c_gate_ctrl)
  584. fe->ops.i2c_gate_ctrl(fe, 0);
  585. if (lg_fail(ret))
  586. goto fail;
  587. state->current_frequency = param->frequency;
  588. }
  589. ret = lgdt3305_set_modulation(state, param);
  590. if (lg_fail(ret))
  591. goto fail;
  592. ret = lgdt3305_passband_digital_agc(state, param);
  593. if (lg_fail(ret))
  594. goto fail;
  595. ret = lgdt3305_agc_setup(state, param);
  596. if (lg_fail(ret))
  597. goto fail;
  598. /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
  599. switch (param->u.vsb.modulation) {
  600. case VSB_8:
  601. lgdt3305_write_reg(state, 0x030d, 0x00);
  602. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
  603. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
  604. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
  605. lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
  606. break;
  607. case QAM_64:
  608. case QAM_256:
  609. lgdt3305_write_reg(state, 0x030d, 0x14);
  610. ret = lgdt3305_set_if(state, param);
  611. if (lg_fail(ret))
  612. goto fail;
  613. break;
  614. default:
  615. return -EINVAL;
  616. }
  617. ret = lgdt3305_spectral_inversion(state, param,
  618. state->cfg->spectral_inversion
  619. ? 1 : 0);
  620. if (lg_fail(ret))
  621. goto fail;
  622. state->current_modulation = param->u.vsb.modulation;
  623. ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
  624. if (lg_fail(ret))
  625. goto fail;
  626. /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
  627. ret = lgdt3305_mpeg_mode_polarity(state,
  628. state->cfg->tpclk_edge,
  629. state->cfg->tpvalid_polarity);
  630. fail:
  631. return ret;
  632. }
  633. static int lgdt3305_set_parameters(struct dvb_frontend *fe,
  634. struct dvb_frontend_parameters *param)
  635. {
  636. struct lgdt3305_state *state = fe->demodulator_priv;
  637. int ret;
  638. lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
  639. if (fe->ops.tuner_ops.set_params) {
  640. ret = fe->ops.tuner_ops.set_params(fe, param);
  641. if (fe->ops.i2c_gate_ctrl)
  642. fe->ops.i2c_gate_ctrl(fe, 0);
  643. if (lg_fail(ret))
  644. goto fail;
  645. state->current_frequency = param->frequency;
  646. }
  647. ret = lgdt3305_set_modulation(state, param);
  648. if (lg_fail(ret))
  649. goto fail;
  650. ret = lgdt3305_passband_digital_agc(state, param);
  651. if (lg_fail(ret))
  652. goto fail;
  653. ret = lgdt3305_set_agc_power_ref(state, param);
  654. if (lg_fail(ret))
  655. goto fail;
  656. ret = lgdt3305_agc_setup(state, param);
  657. if (lg_fail(ret))
  658. goto fail;
  659. /* low if */
  660. ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f);
  661. if (lg_fail(ret))
  662. goto fail;
  663. ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1);
  664. if (lg_fail(ret))
  665. goto fail;
  666. ret = lgdt3305_set_if(state, param);
  667. if (lg_fail(ret))
  668. goto fail;
  669. ret = lgdt3305_spectral_inversion(state, param,
  670. state->cfg->spectral_inversion
  671. ? 1 : 0);
  672. if (lg_fail(ret))
  673. goto fail;
  674. ret = lgdt3305_set_filter_extension(state, param);
  675. if (lg_fail(ret))
  676. goto fail;
  677. state->current_modulation = param->u.vsb.modulation;
  678. ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
  679. if (lg_fail(ret))
  680. goto fail;
  681. /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
  682. ret = lgdt3305_mpeg_mode_polarity(state,
  683. state->cfg->tpclk_edge,
  684. state->cfg->tpvalid_polarity);
  685. fail:
  686. return ret;
  687. }
  688. static int lgdt3305_get_frontend(struct dvb_frontend *fe,
  689. struct dvb_frontend_parameters *param)
  690. {
  691. struct lgdt3305_state *state = fe->demodulator_priv;
  692. lg_dbg("\n");
  693. param->u.vsb.modulation = state->current_modulation;
  694. param->frequency = state->current_frequency;
  695. return 0;
  696. }
  697. /* ------------------------------------------------------------------------ */
  698. static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state,
  699. int *locked)
  700. {
  701. u8 val;
  702. int ret;
  703. char *cr_lock_state = "";
  704. *locked = 0;
  705. ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val);
  706. if (lg_fail(ret))
  707. goto fail;
  708. switch (state->current_modulation) {
  709. case QAM_256:
  710. case QAM_64:
  711. if (val & (1 << 1))
  712. *locked = 1;
  713. switch (val & 0x07) {
  714. case 0:
  715. cr_lock_state = "QAM UNLOCK";
  716. break;
  717. case 4:
  718. cr_lock_state = "QAM 1stLock";
  719. break;
  720. case 6:
  721. cr_lock_state = "QAM 2ndLock";
  722. break;
  723. case 7:
  724. cr_lock_state = "QAM FinalLock";
  725. break;
  726. default:
  727. cr_lock_state = "CLOCKQAM-INVALID!";
  728. break;
  729. }
  730. break;
  731. case VSB_8:
  732. if (val & (1 << 7)) {
  733. *locked = 1;
  734. cr_lock_state = "CLOCKVSB";
  735. }
  736. break;
  737. default:
  738. ret = -EINVAL;
  739. }
  740. lg_dbg("(%d) %s\n", *locked, cr_lock_state);
  741. fail:
  742. return ret;
  743. }
  744. static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state,
  745. int *locked)
  746. {
  747. u8 val;
  748. int ret, mpeg_lock, fec_lock, viterbi_lock;
  749. *locked = 0;
  750. switch (state->current_modulation) {
  751. case QAM_256:
  752. case QAM_64:
  753. ret = lgdt3305_read_reg(state,
  754. LGDT3305_FEC_LOCK_STATUS, &val);
  755. if (lg_fail(ret))
  756. goto fail;
  757. mpeg_lock = (val & (1 << 0)) ? 1 : 0;
  758. fec_lock = (val & (1 << 2)) ? 1 : 0;
  759. viterbi_lock = (val & (1 << 3)) ? 1 : 0;
  760. *locked = mpeg_lock && fec_lock && viterbi_lock;
  761. lg_dbg("(%d) %s%s%s\n", *locked,
  762. mpeg_lock ? "mpeg lock " : "",
  763. fec_lock ? "fec lock " : "",
  764. viterbi_lock ? "viterbi lock" : "");
  765. break;
  766. case VSB_8:
  767. default:
  768. ret = -EINVAL;
  769. }
  770. fail:
  771. return ret;
  772. }
  773. static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
  774. {
  775. struct lgdt3305_state *state = fe->demodulator_priv;
  776. u8 val;
  777. int ret, signal, inlock, nofecerr, snrgood,
  778. cr_lock, fec_lock, sync_lock;
  779. *status = 0;
  780. ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val);
  781. if (lg_fail(ret))
  782. goto fail;
  783. signal = (val & (1 << 4)) ? 1 : 0;
  784. inlock = (val & (1 << 3)) ? 0 : 1;
  785. sync_lock = (val & (1 << 2)) ? 1 : 0;
  786. nofecerr = (val & (1 << 1)) ? 1 : 0;
  787. snrgood = (val & (1 << 0)) ? 1 : 0;
  788. lg_dbg("%s%s%s%s%s\n",
  789. signal ? "SIGNALEXIST " : "",
  790. inlock ? "INLOCK " : "",
  791. sync_lock ? "SYNCLOCK " : "",
  792. nofecerr ? "NOFECERR " : "",
  793. snrgood ? "SNRGOOD " : "");
  794. ret = lgdt3305_read_cr_lock_status(state, &cr_lock);
  795. if (lg_fail(ret))
  796. goto fail;
  797. if (signal)
  798. *status |= FE_HAS_SIGNAL;
  799. if (cr_lock)
  800. *status |= FE_HAS_CARRIER;
  801. if (nofecerr)
  802. *status |= FE_HAS_VITERBI;
  803. if (sync_lock)
  804. *status |= FE_HAS_SYNC;
  805. switch (state->current_modulation) {
  806. case QAM_256:
  807. case QAM_64:
  808. /* signal bit is unreliable on the DT3304 in QAM mode */
  809. if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
  810. *status |= FE_HAS_SIGNAL;
  811. ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
  812. if (lg_fail(ret))
  813. goto fail;
  814. if (fec_lock)
  815. *status |= FE_HAS_LOCK;
  816. break;
  817. case VSB_8:
  818. if (inlock)
  819. *status |= FE_HAS_LOCK;
  820. break;
  821. default:
  822. ret = -EINVAL;
  823. }
  824. fail:
  825. return ret;
  826. }
  827. /* ------------------------------------------------------------------------ */
  828. /* borrowed from lgdt330x.c */
  829. static u32 calculate_snr(u32 mse, u32 c)
  830. {
  831. if (mse == 0) /* no signal */
  832. return 0;
  833. mse = intlog10(mse);
  834. if (mse > c) {
  835. /* Negative SNR, which is possible, but realisticly the
  836. demod will lose lock before the signal gets this bad. The
  837. API only allows for unsigned values, so just return 0 */
  838. return 0;
  839. }
  840. return 10*(c - mse);
  841. }
  842. static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr)
  843. {
  844. struct lgdt3305_state *state = fe->demodulator_priv;
  845. u32 noise; /* noise value */
  846. u32 c; /* per-modulation SNR calculation constant */
  847. switch (state->current_modulation) {
  848. case VSB_8:
  849. #ifdef USE_PTMSE
  850. /* Use Phase Tracker Mean-Square Error Register */
  851. /* SNR for ranges from -13.11 to +44.08 */
  852. noise = ((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) |
  853. (read_reg(state, LGDT3305_PT_MSE_2) << 8) |
  854. (read_reg(state, LGDT3305_PT_MSE_3) & 0xff);
  855. c = 73957994; /* log10(25*32^2)*2^24 */
  856. #else
  857. /* Use Equalizer Mean-Square Error Register */
  858. /* SNR for ranges from -16.12 to +44.08 */
  859. noise = ((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) |
  860. (read_reg(state, LGDT3305_EQ_MSE_2) << 8) |
  861. (read_reg(state, LGDT3305_EQ_MSE_3) & 0xff);
  862. c = 73957994; /* log10(25*32^2)*2^24 */
  863. #endif
  864. break;
  865. case QAM_64:
  866. case QAM_256:
  867. noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) |
  868. (read_reg(state, LGDT3305_CR_MSE_2) & 0xff);
  869. c = (state->current_modulation == QAM_64) ?
  870. 97939837 : 98026066;
  871. /* log10(688128)*2^24 and log10(696320)*2^24 */
  872. break;
  873. default:
  874. return -EINVAL;
  875. }
  876. state->snr = calculate_snr(noise, c);
  877. /* report SNR in dB * 10 */
  878. *snr = (state->snr / ((1 << 24) / 10));
  879. lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise,
  880. state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
  881. return 0;
  882. }
  883. static int lgdt3305_read_signal_strength(struct dvb_frontend *fe,
  884. u16 *strength)
  885. {
  886. /* borrowed from lgdt330x.c
  887. *
  888. * Calculate strength from SNR up to 35dB
  889. * Even though the SNR can go higher than 35dB,
  890. * there is some comfort factor in having a range of
  891. * strong signals that can show at 100%
  892. */
  893. struct lgdt3305_state *state = fe->demodulator_priv;
  894. u16 snr;
  895. int ret;
  896. *strength = 0;
  897. ret = fe->ops.read_snr(fe, &snr);
  898. if (lg_fail(ret))
  899. goto fail;
  900. /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
  901. /* scale the range 0 - 35*2^24 into 0 - 65535 */
  902. if (state->snr >= 8960 * 0x10000)
  903. *strength = 0xffff;
  904. else
  905. *strength = state->snr / 8960;
  906. fail:
  907. return ret;
  908. }
  909. /* ------------------------------------------------------------------------ */
  910. static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber)
  911. {
  912. *ber = 0;
  913. return 0;
  914. }
  915. static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
  916. {
  917. struct lgdt3305_state *state = fe->demodulator_priv;
  918. *ucblocks =
  919. (read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) |
  920. (read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff);
  921. return 0;
  922. }
  923. static int lgdt3305_get_tune_settings(struct dvb_frontend *fe,
  924. struct dvb_frontend_tune_settings
  925. *fe_tune_settings)
  926. {
  927. fe_tune_settings->min_delay_ms = 500;
  928. lg_dbg("\n");
  929. return 0;
  930. }
  931. static void lgdt3305_release(struct dvb_frontend *fe)
  932. {
  933. struct lgdt3305_state *state = fe->demodulator_priv;
  934. lg_dbg("\n");
  935. kfree(state);
  936. }
  937. static struct dvb_frontend_ops lgdt3304_ops;
  938. static struct dvb_frontend_ops lgdt3305_ops;
  939. struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
  940. struct i2c_adapter *i2c_adap)
  941. {
  942. struct lgdt3305_state *state = NULL;
  943. int ret;
  944. u8 val;
  945. lg_dbg("(%d-%04x)\n",
  946. i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
  947. config ? config->i2c_addr : 0);
  948. state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL);
  949. if (state == NULL)
  950. goto fail;
  951. state->cfg = config;
  952. state->i2c_adap = i2c_adap;
  953. switch (config->demod_chip) {
  954. case LGDT3304:
  955. memcpy(&state->frontend.ops, &lgdt3304_ops,
  956. sizeof(struct dvb_frontend_ops));
  957. break;
  958. case LGDT3305:
  959. memcpy(&state->frontend.ops, &lgdt3305_ops,
  960. sizeof(struct dvb_frontend_ops));
  961. break;
  962. default:
  963. goto fail;
  964. }
  965. state->frontend.demodulator_priv = state;
  966. /* verify that we're talking to a lg dt3304/5 */
  967. ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
  968. if ((lg_fail(ret)) | (val == 0))
  969. goto fail;
  970. ret = lgdt3305_write_reg(state, 0x0808, 0x80);
  971. if (lg_fail(ret))
  972. goto fail;
  973. ret = lgdt3305_read_reg(state, 0x0808, &val);
  974. if ((lg_fail(ret)) | (val != 0x80))
  975. goto fail;
  976. ret = lgdt3305_write_reg(state, 0x0808, 0x00);
  977. if (lg_fail(ret))
  978. goto fail;
  979. state->current_frequency = -1;
  980. state->current_modulation = -1;
  981. return &state->frontend;
  982. fail:
  983. lg_warn("unable to detect %s hardware\n",
  984. config->demod_chip ? "LGDT3304" : "LGDT3305");
  985. kfree(state);
  986. return NULL;
  987. }
  988. EXPORT_SYMBOL(lgdt3305_attach);
  989. static struct dvb_frontend_ops lgdt3304_ops = {
  990. .info = {
  991. .name = "LG Electronics LGDT3304 VSB/QAM Frontend",
  992. .type = FE_ATSC,
  993. .frequency_min = 54000000,
  994. .frequency_max = 858000000,
  995. .frequency_stepsize = 62500,
  996. .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
  997. },
  998. .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
  999. .init = lgdt3305_init,
  1000. .set_frontend = lgdt3304_set_parameters,
  1001. .get_frontend = lgdt3305_get_frontend,
  1002. .get_tune_settings = lgdt3305_get_tune_settings,
  1003. .read_status = lgdt3305_read_status,
  1004. .read_ber = lgdt3305_read_ber,
  1005. .read_signal_strength = lgdt3305_read_signal_strength,
  1006. .read_snr = lgdt3305_read_snr,
  1007. .read_ucblocks = lgdt3305_read_ucblocks,
  1008. .release = lgdt3305_release,
  1009. };
  1010. static struct dvb_frontend_ops lgdt3305_ops = {
  1011. .info = {
  1012. .name = "LG Electronics LGDT3305 VSB/QAM Frontend",
  1013. .type = FE_ATSC,
  1014. .frequency_min = 54000000,
  1015. .frequency_max = 858000000,
  1016. .frequency_stepsize = 62500,
  1017. .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
  1018. },
  1019. .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
  1020. .init = lgdt3305_init,
  1021. .sleep = lgdt3305_sleep,
  1022. .set_frontend = lgdt3305_set_parameters,
  1023. .get_frontend = lgdt3305_get_frontend,
  1024. .get_tune_settings = lgdt3305_get_tune_settings,
  1025. .read_status = lgdt3305_read_status,
  1026. .read_ber = lgdt3305_read_ber,
  1027. .read_signal_strength = lgdt3305_read_signal_strength,
  1028. .read_snr = lgdt3305_read_snr,
  1029. .read_ucblocks = lgdt3305_read_ucblocks,
  1030. .release = lgdt3305_release,
  1031. };
  1032. MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
  1033. MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
  1034. MODULE_LICENSE("GPL");
  1035. MODULE_VERSION("0.2");
  1036. /*
  1037. * Local variables:
  1038. * c-basic-offset: 8
  1039. * End:
  1040. */