dvb-dibusb-fe-i2c.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
  3. * based on reference design made by DiBcom (http://www.dibcom.fr/)
  4. *
  5. * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
  6. *
  7. * see dvb-dibusb-core.c for more copyright details.
  8. *
  9. * This file contains functions for attaching, initializing of an appropriate
  10. * demodulator/frontend. I2C-stuff is also located here.
  11. *
  12. */
  13. #include "dvb-dibusb.h"
  14. #include <linux/usb.h>
  15. static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
  16. u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
  17. {
  18. u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
  19. /* write only ? */
  20. int wo = (rbuf == NULL || rlen == 0),
  21. len = 2 + wlen + (wo ? 0 : 2);
  22. sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
  23. sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
  24. memcpy(&sndbuf[2],wbuf,wlen);
  25. if (!wo) {
  26. sndbuf[wlen+2] = (rlen >> 8) & 0xff;
  27. sndbuf[wlen+3] = rlen & 0xff;
  28. }
  29. return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
  30. }
  31. /*
  32. * I2C master xfer function
  33. */
  34. static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
  35. {
  36. struct usb_dibusb *dib = i2c_get_adapdata(adap);
  37. int i;
  38. if (down_interruptible(&dib->i2c_sem) < 0)
  39. return -EAGAIN;
  40. if (num > 2)
  41. warn("more than 2 i2c messages at a time is not handled yet. TODO.");
  42. for (i = 0; i < num; i++) {
  43. /* write/read request */
  44. if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
  45. if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,
  46. msg[i+1].buf,msg[i+1].len) < 0)
  47. break;
  48. i++;
  49. } else
  50. if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
  51. break;
  52. }
  53. up(&dib->i2c_sem);
  54. return i;
  55. }
  56. static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
  57. {
  58. return I2C_FUNC_I2C;
  59. }
  60. static struct i2c_algorithm dibusb_algo = {
  61. .name = "DiBcom USB i2c algorithm",
  62. .id = I2C_ALGO_BIT,
  63. .master_xfer = dibusb_i2c_xfer,
  64. .functionality = dibusb_i2c_func,
  65. };
  66. static int dibusb_general_demod_init(struct dvb_frontend *fe);
  67. static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);
  68. static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);
  69. static int dibusb_general_pll_set(struct dvb_frontend *fe,
  70. struct dvb_frontend_parameters* params, u8 pll_buf[5]);
  71. static struct mt352_config mt352_hanftek_umt_010_config = {
  72. .demod_address = 0x1e,
  73. .demod_init = dibusb_general_demod_init,
  74. .pll_set = dibusb_general_pll_set,
  75. };
  76. static int dibusb_tuner_quirk(struct usb_dibusb *dib)
  77. {
  78. switch (dib->dibdev->dev_cl->id) {
  79. case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
  80. case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */
  81. struct dibusb_tuner *t;
  82. u8 b[2] = { 0,0 } ,b2[1];
  83. struct i2c_msg msg[2] = {
  84. { .flags = 0, .buf = b, .len = 2 },
  85. { .flags = I2C_M_RD, .buf = b2, .len = 1},
  86. };
  87. t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];
  88. msg[0].addr = msg[1].addr = t->pll_addr;
  89. if (dib->xfer_ops.tuner_pass_ctrl != NULL)
  90. dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);
  91. dibusb_i2c_xfer(&dib->i2c_adap,msg,2);
  92. if (dib->xfer_ops.tuner_pass_ctrl != NULL)
  93. dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr);
  94. if (b2[0] == 0xfe)
  95. info("this device has the Thomson Cable onboard. Which is default.");
  96. else {
  97. dib->tuner = t;
  98. info("this device has the Panasonic ENV77H11D5 onboard.");
  99. }
  100. break;
  101. }
  102. default:
  103. break;
  104. }
  105. return 0;
  106. }
  107. int dibusb_fe_init(struct usb_dibusb* dib)
  108. {
  109. struct dib3000_config demod_cfg;
  110. int i;
  111. if (dib->init_state & DIBUSB_STATE_I2C) {
  112. for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
  113. dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {
  114. demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
  115. demod_cfg.pll_addr = dibusb_general_pll_addr;
  116. demod_cfg.pll_set = dibusb_general_pll_set;
  117. demod_cfg.pll_init = dibusb_general_pll_init;
  118. deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE);
  119. switch (dib->dibdev->dev_cl->demod->id) {
  120. case DIBUSB_DIB3000MB:
  121. dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
  122. break;
  123. case DIBUSB_DIB3000MC:
  124. dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
  125. break;
  126. case DIBUSB_MT352:
  127. mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
  128. dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);
  129. break;
  130. case DTT200U_FE:
  131. dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops);
  132. break;
  133. }
  134. if (dib->fe != NULL) {
  135. info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]);
  136. break;
  137. }
  138. }
  139. /* if a frontend was found */
  140. if (dib->fe != NULL) {
  141. if (dib->fe->ops->sleep != NULL)
  142. dib->fe_sleep = dib->fe->ops->sleep;
  143. dib->fe->ops->sleep = dibusb_hw_sleep;
  144. if (dib->fe->ops->init != NULL )
  145. dib->fe_init = dib->fe->ops->init;
  146. dib->fe->ops->init = dibusb_hw_wakeup;
  147. /* setting the default tuner */
  148. dib->tuner = dib->dibdev->dev_cl->tuner;
  149. /* check which tuner is mounted on this device, in case this is unsure */
  150. dibusb_tuner_quirk(dib);
  151. }
  152. }
  153. if (dib->fe == NULL) {
  154. err("A frontend driver was not found for device '%s'.",
  155. dib->dibdev->name);
  156. return -ENODEV;
  157. } else {
  158. if (dvb_register_frontend(&dib->adapter, dib->fe)) {
  159. err("Frontend registration failed.");
  160. if (dib->fe->ops->release)
  161. dib->fe->ops->release(dib->fe);
  162. dib->fe = NULL;
  163. return -ENODEV;
  164. }
  165. }
  166. return 0;
  167. }
  168. int dibusb_fe_exit(struct usb_dibusb *dib)
  169. {
  170. if (dib->fe != NULL)
  171. dvb_unregister_frontend(dib->fe);
  172. return 0;
  173. }
  174. int dibusb_i2c_init(struct usb_dibusb *dib)
  175. {
  176. int ret = 0;
  177. dib->adapter.priv = dib;
  178. strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
  179. #ifdef I2C_ADAP_CLASS_TV_DIGITAL
  180. dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
  181. #else
  182. dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
  183. #endif
  184. dib->i2c_adap.algo = &dibusb_algo;
  185. dib->i2c_adap.algo_data = NULL;
  186. dib->i2c_adap.id = I2C_ALGO_BIT;
  187. i2c_set_adapdata(&dib->i2c_adap, dib);
  188. if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
  189. err("could not add i2c adapter");
  190. dib->init_state |= DIBUSB_STATE_I2C;
  191. return ret;
  192. }
  193. int dibusb_i2c_exit(struct usb_dibusb *dib)
  194. {
  195. if (dib->init_state & DIBUSB_STATE_I2C)
  196. i2c_del_adapter(&dib->i2c_adap);
  197. dib->init_state &= ~DIBUSB_STATE_I2C;
  198. return 0;
  199. }
  200. /* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
  201. static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
  202. {
  203. u32 tfreq = (fep->frequency + 36125000) / 62500;
  204. int vu,p0,p1,p2;
  205. if (fep->frequency > 403250000)
  206. vu = 1, p2 = 1, p1 = 0, p0 = 1;
  207. else if (fep->frequency > 115750000)
  208. vu = 0, p2 = 1, p1 = 1, p0 = 0;
  209. else if (fep->frequency > 44250000)
  210. vu = 0, p2 = 0, p1 = 1, p0 = 1;
  211. else
  212. return -EINVAL;
  213. pllbuf[0] = (tfreq >> 8) & 0x7f;
  214. pllbuf[1] = tfreq & 0xff;
  215. pllbuf[2] = 0x8e;
  216. pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
  217. return 0;
  218. }
  219. static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
  220. {
  221. u32 freq_khz = fep->frequency / 1000;
  222. u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000;
  223. u8 TA, T210, R210, ctrl1, cp210, p4321;
  224. if (freq_khz > 858000) {
  225. err("frequency cannot be larger than 858 MHz.");
  226. return -EINVAL;
  227. }
  228. // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
  229. TA = 1;
  230. T210 = 0;
  231. R210 = 0x2;
  232. ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
  233. // ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
  234. if (freq_khz < 470000)
  235. cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
  236. else if (freq_khz < 526000)
  237. cp210 = 4; // UHF band Ch E21 to E27
  238. else // if (freq < 862000000)
  239. cp210 = 5; // UHF band ch E28 to E69
  240. //********************* BW select *******************************
  241. if (freq_khz < 153000)
  242. p4321 = 1; // BW selected for VHF low
  243. else if (freq_khz < 470000)
  244. p4321 = 2; // BW selected for VHF high E5 to E12
  245. else // if (freq < 862000000)
  246. p4321 = 4; // BW selection for UHF E21 to E69
  247. pllbuf[0] = (tfreq >> 8) & 0xff;
  248. pllbuf[1] = (tfreq >> 0) & 0xff;
  249. pllbuf[2] = 0xff & ctrl1;
  250. pllbuf[3] = (cp210 << 5) | (p4321);
  251. return 0;
  252. }
  253. /*
  254. * 7 6 5 4 3 2 1 0
  255. * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
  256. *
  257. * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
  258. * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
  259. *
  260. * Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0
  261. * 1 T/A=0 0 0 ATC AL2 AL1 AL0
  262. *
  263. * Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1
  264. *
  265. * MA0/1 = programmable address bits
  266. * R/~W = read/write bit (0 for writing)
  267. * N14-0 = programmable LO frequency
  268. *
  269. * T/A = test AGC bit (0 = next 6 bits AGC setting,
  270. * 1 = next 6 bits test and reference divider ratio settings)
  271. * T2-0 = test bits
  272. * R2-0 = reference divider ratio and programmable frequency step
  273. * ATC = AGC current setting and time constant
  274. * ATC = 0: AGC current = 220nA, AGC time constant = 2s
  275. * ATC = 1: AGC current = 9uA, AGC time constant = 50ms
  276. * AL2-0 = AGC take-over point bits
  277. * CP2-0 = charge pump current
  278. * BS5-1 = PMOS ports control bits;
  279. * BSn = 0 corresponding port is off, high-impedance state (at power-on)
  280. * BSn = 1 corresponding port is on
  281. */
  282. static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4])
  283. {
  284. pllbuf[0] = 0x0b;
  285. pllbuf[1] = 0xf5;
  286. pllbuf[2] = 0x85;
  287. pllbuf[3] = 0xab;
  288. return 0;
  289. }
  290. static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4])
  291. {
  292. int tuner_frequency = 0;
  293. u8 band, cp, filter;
  294. // determine charge pump
  295. tuner_frequency = fep->frequency + 36166000;
  296. if (tuner_frequency < 87000000)
  297. return -EINVAL;
  298. else if (tuner_frequency < 130000000)
  299. cp = 3;
  300. else if (tuner_frequency < 160000000)
  301. cp = 5;
  302. else if (tuner_frequency < 200000000)
  303. cp = 6;
  304. else if (tuner_frequency < 290000000)
  305. cp = 3;
  306. else if (tuner_frequency < 420000000)
  307. cp = 5;
  308. else if (tuner_frequency < 480000000)
  309. cp = 6;
  310. else if (tuner_frequency < 620000000)
  311. cp = 3;
  312. else if (tuner_frequency < 830000000)
  313. cp = 5;
  314. else if (tuner_frequency < 895000000)
  315. cp = 7;
  316. else
  317. return -EINVAL;
  318. // determine band
  319. if (fep->frequency < 49000000)
  320. return -EINVAL;
  321. else if (fep->frequency < 161000000)
  322. band = 1;
  323. else if (fep->frequency < 444000000)
  324. band = 2;
  325. else if (fep->frequency < 861000000)
  326. band = 4;
  327. else
  328. return -EINVAL;
  329. // setup PLL filter
  330. switch (fep->u.ofdm.bandwidth) {
  331. case BANDWIDTH_6_MHZ:
  332. case BANDWIDTH_7_MHZ:
  333. filter = 0;
  334. break;
  335. case BANDWIDTH_8_MHZ:
  336. filter = 1;
  337. break;
  338. default:
  339. return -EINVAL;
  340. }
  341. // calculate divisor
  342. // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
  343. tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000;
  344. // setup tuner buffer
  345. pllbuf[0] = (tuner_frequency >> 8) & 0x7f;
  346. pllbuf[1] = tuner_frequency & 0xff;
  347. pllbuf[2] = 0xca;
  348. pllbuf[3] = (cp << 5) | (filter << 3) | band;
  349. return 0;
  350. }
  351. /*
  352. * 7 6 5 4 3 2 1 0
  353. * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
  354. *
  355. * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
  356. * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
  357. *
  358. * Control byte 1 CP T2 T1 T0 RSA RSB OS
  359. *
  360. * Band Switch byte X X X P4 P3 P2 P1 P0
  361. *
  362. * Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0
  363. *
  364. * Address: MA1 MA0 Address
  365. * 0 0 c0
  366. * 0 1 c2 (always valid)
  367. * 1 0 c4
  368. * 1 1 c6
  369. */
  370. static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
  371. {
  372. u32 div;
  373. u8 p210, p3;
  374. #define TUNER_MUL 62500
  375. div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
  376. // div = ((fep->frequency/1000 + 36166) * 6) / 1000;
  377. if (fep->frequency < 174500000)
  378. p210 = 1; // not supported by the tdtp_e102p
  379. else if (fep->frequency < 230000000) // VHF
  380. p210 = 2;
  381. else
  382. p210 = 4;
  383. if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
  384. p3 = 0;
  385. else
  386. p3 = 1;
  387. pllbuf[0] = (div >> 8) & 0x7f;
  388. pllbuf[1] = div & 0xff;
  389. pllbuf[2] = 0xce;
  390. // pllbuf[2] = 0xcc;
  391. pllbuf[3] = (p3 << 3) | p210;
  392. return 0;
  393. }
  394. static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe)
  395. {
  396. static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
  397. static u8 mt352_reset[] = { 0x50, 0x80 };
  398. static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
  399. static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
  400. static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
  401. static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
  402. static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
  403. static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
  404. static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
  405. static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
  406. static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
  407. static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
  408. mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
  409. udelay(2000);
  410. mt352_write(fe, mt352_reset, sizeof(mt352_reset));
  411. mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
  412. mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
  413. mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
  414. mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
  415. mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
  416. mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
  417. mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
  418. mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
  419. mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
  420. mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
  421. return 0;
  422. }
  423. static int dibusb_general_demod_init(struct dvb_frontend *fe)
  424. {
  425. struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
  426. switch (dib->dibdev->dev_cl->id) {
  427. case UMT2_0:
  428. return lg_tdtp_e102p_mt352_demod_init(fe);
  429. default: /* other device classes do not have device specific demod inits */
  430. break;
  431. }
  432. return 0;
  433. }
  434. static u8 dibusb_general_pll_addr(struct dvb_frontend *fe)
  435. {
  436. struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
  437. return dib->tuner->pll_addr;
  438. }
  439. static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4])
  440. {
  441. if (pll_buf == NULL) {
  442. struct i2c_msg msg = {
  443. .addr = dib->tuner->pll_addr,
  444. .flags = 0,
  445. .buf = buf,
  446. .len = sizeof(buf)
  447. };
  448. if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
  449. return -EIO;
  450. msleep(1);
  451. } else {
  452. pll_buf[0] = dib->tuner->pll_addr << 1;
  453. memcpy(&pll_buf[1],buf,4);
  454. }
  455. return 0;
  456. }
  457. static int dibusb_general_pll_init(struct dvb_frontend *fe,
  458. u8 pll_buf[5])
  459. {
  460. struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
  461. u8 buf[4];
  462. int ret=0;
  463. switch (dib->tuner->id) {
  464. case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
  465. ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf);
  466. break;
  467. default:
  468. break;
  469. }
  470. if (ret)
  471. return ret;
  472. return dibusb_pll_i2c_helper(dib,pll_buf,buf);
  473. }
  474. static int dibusb_general_pll_set(struct dvb_frontend *fe,
  475. struct dvb_frontend_parameters *fep, u8 pll_buf[5])
  476. {
  477. struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
  478. u8 buf[4];
  479. int ret=0;
  480. switch (dib->tuner->id) {
  481. case DIBUSB_TUNER_CABLE_THOMSON:
  482. ret = thomson_cable_eu_pll_set(fep, buf);
  483. break;
  484. case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5:
  485. ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf);
  486. break;
  487. case DIBUSB_TUNER_CABLE_LG_TDTP_E102P:
  488. ret = lg_tdtp_e102p_tua6034(fep, buf);
  489. break;
  490. case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
  491. ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf);
  492. break;
  493. default:
  494. warn("no pll programming routine found for tuner %d.\n",dib->tuner->id);
  495. ret = -ENODEV;
  496. break;
  497. }
  498. if (ret)
  499. return ret;
  500. return dibusb_pll_i2c_helper(dib,pll_buf,buf);
  501. }