tuner-xc2028.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. /* tuner-xc2028
  2. *
  3. * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
  4. *
  5. * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
  6. * - frontend interface
  7. *
  8. * This code is placed under the terms of the GNU General Public License v2
  9. */
  10. #include <linux/i2c.h>
  11. #include <asm/div64.h>
  12. #include <linux/firmware.h>
  13. #include <linux/videodev2.h>
  14. #include <linux/delay.h>
  15. #include <media/tuner.h>
  16. #include <linux/mutex.h>
  17. #include "tuner-i2c.h"
  18. #include "tuner-xc2028.h"
  19. #include "tuner-xc2028-types.h"
  20. #include <linux/dvb/frontend.h>
  21. #include "dvb_frontend.h"
  22. #define PREFIX "xc2028"
  23. static LIST_HEAD(xc2028_list);
  24. /* struct for storing firmware table */
  25. struct firmware_description {
  26. unsigned int type;
  27. v4l2_std_id id;
  28. unsigned char *ptr;
  29. unsigned int size;
  30. };
  31. struct xc2028_data {
  32. struct list_head xc2028_list;
  33. struct tuner_i2c_props i2c_props;
  34. int (*tuner_callback) (void *dev,
  35. int command, int arg);
  36. struct device *dev;
  37. void *video_dev;
  38. int count;
  39. __u32 frequency;
  40. struct firmware_description *firm;
  41. int firm_size;
  42. __u16 version;
  43. struct xc2028_ctrl ctrl;
  44. v4l2_std_id firm_type; /* video stds supported
  45. by current firmware */
  46. fe_bandwidth_t bandwidth; /* Firmware bandwidth:
  47. 6M, 7M or 8M */
  48. int need_load_generic; /* The generic firmware
  49. were loaded? */
  50. int max_len; /* Max firmware chunk */
  51. enum tuner_mode mode;
  52. struct i2c_client *i2c_client;
  53. struct mutex lock;
  54. };
  55. #define i2c_send(rc, priv, buf, size) do { \
  56. rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \
  57. if (size != rc) \
  58. tuner_info("i2c output error: rc = %d (should be %d)\n",\
  59. rc, (int)size); \
  60. } while (0)
  61. #define i2c_rcv(rc, priv, buf, size) do { \
  62. rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \
  63. if (size != rc) \
  64. tuner_info("i2c input error: rc = %d (should be %d)\n", \
  65. rc, (int)size); \
  66. } while (0)
  67. #define send_seq(priv, data...) do { \
  68. int rc; \
  69. static u8 _val[] = data; \
  70. if (sizeof(_val) != \
  71. (rc = tuner_i2c_xfer_send(&priv->i2c_props, \
  72. _val, sizeof(_val)))) { \
  73. tuner_info("Error on line %d: %d\n", __LINE__, rc); \
  74. return -EINVAL; \
  75. } \
  76. msleep(10); \
  77. } while (0)
  78. static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
  79. {
  80. int rc;
  81. unsigned char buf[2];
  82. tuner_info("%s called\n", __FUNCTION__);
  83. buf[0] = reg>>8;
  84. buf[1] = (unsigned char) reg;
  85. i2c_send(rc, priv, buf, 2);
  86. if (rc < 0)
  87. return rc;
  88. i2c_rcv(rc, priv, buf, 2);
  89. if (rc < 0)
  90. return rc;
  91. return (buf[1]) | (buf[0] << 8);
  92. }
  93. static void free_firmware(struct xc2028_data *priv)
  94. {
  95. int i;
  96. if (!priv->firm)
  97. return;
  98. for (i = 0; i < priv->firm_size; i++)
  99. kfree(priv->firm[i].ptr);
  100. kfree(priv->firm);
  101. priv->firm = NULL;
  102. priv->need_load_generic = 1;
  103. }
  104. static int load_all_firmwares(struct dvb_frontend *fe)
  105. {
  106. struct xc2028_data *priv = fe->tuner_priv;
  107. const struct firmware *fw = NULL;
  108. unsigned char *p, *endp;
  109. int rc = 0;
  110. int n, n_array;
  111. char name[33];
  112. tuner_info("%s called\n", __FUNCTION__);
  113. tuner_info("Loading firmware %s\n", priv->ctrl.fname);
  114. rc = request_firmware(&fw, priv->ctrl.fname, priv->dev);
  115. if (rc < 0) {
  116. if (rc == -ENOENT)
  117. tuner_info("Error: firmware %s not found.\n",
  118. priv->ctrl.fname);
  119. else
  120. tuner_info("Error %d while requesting firmware %s \n",
  121. rc, priv->ctrl.fname);
  122. return rc;
  123. }
  124. p = fw->data;
  125. endp = p + fw->size;
  126. if (fw->size < sizeof(name) - 1 + 2) {
  127. tuner_info("Error: firmware size is zero!\n");
  128. rc = -EINVAL;
  129. goto done;
  130. }
  131. memcpy(name, p, sizeof(name) - 1);
  132. name[sizeof(name) - 1] = 0;
  133. p += sizeof(name) - 1;
  134. priv->version = le16_to_cpu(*(__u16 *) p);
  135. p += 2;
  136. tuner_info("firmware: %s, ver %d.%d\n", name,
  137. priv->version >> 8, priv->version & 0xff);
  138. if (p + 2 > endp)
  139. goto corrupt;
  140. n_array = le16_to_cpu(*(__u16 *) p);
  141. p += 2;
  142. tuner_info("there are %d firmwares at %s\n", n_array, priv->ctrl.fname);
  143. priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
  144. if (!fw) {
  145. tuner_info("Not enough memory for loading firmware.\n");
  146. rc = -ENOMEM;
  147. goto done;
  148. }
  149. priv->firm_size = n_array;
  150. n = -1;
  151. while (p < endp) {
  152. __u32 type, size;
  153. v4l2_std_id id;
  154. n++;
  155. if (n >= n_array) {
  156. tuner_info("Too much firmwares at the file\n");
  157. goto corrupt;
  158. }
  159. /* Checks if there's enough bytes to read */
  160. if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
  161. tuner_info("Lost firmware!\n");
  162. goto corrupt;
  163. }
  164. type = le32_to_cpu(*(__u32 *) p);
  165. p += sizeof(type);
  166. id = le64_to_cpu(*(v4l2_std_id *) p);
  167. p += sizeof(id);
  168. size = le32_to_cpu(*(v4l2_std_id *) p);
  169. p += sizeof(size);
  170. if ((!size) || (size + p > endp)) {
  171. tuner_info("Firmware type %x, id %lx corrupt\n",
  172. type, (unsigned long)id);
  173. goto corrupt;
  174. }
  175. priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
  176. if (!priv->firm[n].ptr) {
  177. tuner_info("Not enough memory.\n");
  178. rc = -ENOMEM;
  179. goto err;
  180. }
  181. tuner_info("Loading firmware type %x, id %lx, size=%d.\n",
  182. type, (unsigned long)id, size);
  183. memcpy(priv->firm[n].ptr, p, size);
  184. priv->firm[n].type = type;
  185. priv->firm[n].id = id;
  186. priv->firm[n].size = size;
  187. p += size;
  188. }
  189. if (n + 1 != priv->firm_size) {
  190. tuner_info("Firmware file is incomplete!\n");
  191. goto corrupt;
  192. }
  193. goto done;
  194. corrupt:
  195. rc = -EINVAL;
  196. tuner_info("Error: firmware file is corrupted!\n");
  197. err:
  198. tuner_info("Releasing loaded firmware file.\n");
  199. free_firmware(priv);
  200. done:
  201. release_firmware(fw);
  202. tuner_info("Firmware files loaded.\n");
  203. return rc;
  204. }
  205. static int load_firmware(struct dvb_frontend *fe, unsigned int type,
  206. v4l2_std_id * id)
  207. {
  208. struct xc2028_data *priv = fe->tuner_priv;
  209. int i, rc;
  210. unsigned char *p, *endp, buf[priv->max_len];
  211. tuner_info("%s called\n", __FUNCTION__);
  212. if (!priv->firm) {
  213. printk(KERN_ERR PREFIX "Error! firmware not loaded\n");
  214. return -EINVAL;
  215. }
  216. if ((type == 0) && (*id == 0))
  217. *id = V4L2_STD_PAL;
  218. /* Seek for exact match */
  219. for (i = 0; i < priv->firm_size; i++) {
  220. if ((type == priv->firm[i].type) && (*id == priv->firm[i].id))
  221. goto found;
  222. }
  223. /* Seek for generic video standard match */
  224. for (i = 0; i < priv->firm_size; i++) {
  225. if ((type == priv->firm[i].type) && (*id & priv->firm[i].id))
  226. goto found;
  227. }
  228. /*FIXME: Would make sense to seek for type "hint" match ? */
  229. tuner_info("Can't find firmware for type=%x, id=%lx\n", type,
  230. (long int)*id);
  231. return -EINVAL;
  232. found:
  233. *id = priv->firm[i].id;
  234. tuner_info("Found firmware for type=%x, id=%lx\n", type, (long int)*id);
  235. p = priv->firm[i].ptr;
  236. if (!p) {
  237. printk(KERN_ERR PREFIX "Firmware pointer were freed!");
  238. return -EINVAL;
  239. }
  240. endp = p + priv->firm[i].size;
  241. while (p < endp) {
  242. __u16 size;
  243. /* Checks if there's enough bytes to read */
  244. if (p + sizeof(size) > endp) {
  245. tuner_info("missing bytes\n");
  246. return -EINVAL;
  247. }
  248. size = le16_to_cpu(*(__u16 *) p);
  249. p += sizeof(size);
  250. if (size == 0xffff)
  251. return 0;
  252. if (!size) {
  253. /* Special callback command received */
  254. rc = priv->tuner_callback(priv->video_dev,
  255. XC2028_TUNER_RESET, 0);
  256. if (rc < 0) {
  257. tuner_info("Error at RESET code %d\n",
  258. (*p) & 0x7f);
  259. return -EINVAL;
  260. }
  261. continue;
  262. }
  263. /* Checks for a sleep command */
  264. if (size & 0x8000) {
  265. msleep(size & 0x7fff);
  266. continue;
  267. }
  268. if ((size + p > endp)) {
  269. tuner_info("missing bytes: need %d, have %d\n",
  270. size, (int)(endp - p));
  271. return -EINVAL;
  272. }
  273. buf[0] = *p;
  274. p++;
  275. size--;
  276. /* Sends message chunks */
  277. while (size > 0) {
  278. int len = (size < priv->max_len - 1) ?
  279. size : priv->max_len - 1;
  280. memcpy(buf + 1, p, len);
  281. i2c_send(rc, priv, buf, len + 1);
  282. if (rc < 0) {
  283. tuner_info("%d returned from send\n", rc);
  284. return -EINVAL;
  285. }
  286. p += len;
  287. size -= len;
  288. }
  289. }
  290. return -EINVAL;
  291. }
  292. static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
  293. v4l2_std_id std, fe_bandwidth_t bandwidth)
  294. {
  295. struct xc2028_data *priv = fe->tuner_priv;
  296. int rc, version, hwmodel;
  297. v4l2_std_id std0 = 0;
  298. unsigned int type0 = 0, type = 0;
  299. int change_digital_bandwidth;
  300. tuner_info("%s called\n", __FUNCTION__);
  301. if (!priv->firm) {
  302. if (!priv->ctrl.fname)
  303. return -EINVAL;
  304. rc = load_all_firmwares(fe);
  305. if (rc < 0)
  306. return rc;
  307. }
  308. tuner_info("I am in mode %u and I should switch to mode %i\n",
  309. priv->mode, new_mode);
  310. /* first of all, determine whether we have switched the mode */
  311. if (new_mode != priv->mode) {
  312. priv->mode = new_mode;
  313. priv->need_load_generic = 1;
  314. }
  315. change_digital_bandwidth = (priv->mode == T_DIGITAL_TV
  316. && bandwidth != priv->bandwidth) ? 1 : 0;
  317. tuner_info("old bandwidth %u, new bandwidth %u\n", priv->bandwidth,
  318. bandwidth);
  319. if (priv->need_load_generic) {
  320. /* Reset is needed before loading firmware */
  321. rc = priv->tuner_callback(priv->video_dev,
  322. XC2028_TUNER_RESET, 0);
  323. if (rc < 0)
  324. return rc;
  325. type0 = BASE;
  326. if (priv->ctrl.type == XC2028_FIRM_MTS)
  327. type0 |= MTS;
  328. if (priv->bandwidth == 8)
  329. type0 |= F8MHZ;
  330. /* FIXME: How to load FM and FM|INPUT1 firmwares? */
  331. rc = load_firmware(fe, type0, &std0);
  332. if (rc < 0) {
  333. tuner_info("Error %d while loading generic firmware\n",
  334. rc);
  335. return rc;
  336. }
  337. priv->need_load_generic = 0;
  338. priv->firm_type = 0;
  339. if (priv->mode == T_DIGITAL_TV)
  340. change_digital_bandwidth = 1;
  341. }
  342. tuner_info("I should change bandwidth %u\n", change_digital_bandwidth);
  343. if (change_digital_bandwidth) {
  344. /*FIXME: Should allow selecting between D2620 and D2633 */
  345. type |= D2620;
  346. /* FIXME: When should select a DTV78 firmware?
  347. */
  348. switch (bandwidth) {
  349. case BANDWIDTH_8_MHZ:
  350. type |= DTV8;
  351. break;
  352. case BANDWIDTH_7_MHZ:
  353. type |= DTV7;
  354. break;
  355. case BANDWIDTH_6_MHZ:
  356. /* FIXME: Should allow select also ATSC */
  357. type |= DTV6_QAM;
  358. break;
  359. default:
  360. tuner_info("error: bandwidth not supported.\n");
  361. };
  362. priv->bandwidth = bandwidth;
  363. }
  364. /* Load INIT1, if needed */
  365. tuner_info("Trying to load init1 firmware\n");
  366. type0 = BASE | INIT1 | priv->ctrl.type;
  367. if (priv->ctrl.type == XC2028_FIRM_MTS)
  368. type0 |= MTS;
  369. /* FIXME: Should handle errors - if INIT1 found */
  370. rc = load_firmware(fe, type0, &std0);
  371. /* FIXME: Should add support for FM radio
  372. */
  373. if (priv->ctrl.type == XC2028_FIRM_MTS)
  374. type |= MTS;
  375. tuner_info("firmware standard to load: %08lx\n", (unsigned long)std);
  376. if (priv->firm_type & std) {
  377. tuner_info("no need to load a std-specific firmware.\n");
  378. return 0;
  379. }
  380. rc = load_firmware(fe, type, &std);
  381. if (rc < 0)
  382. return rc;
  383. version = xc2028_get_reg(priv, 0x0004);
  384. hwmodel = xc2028_get_reg(priv, 0x0008);
  385. tuner_info("Device is Xceive %d version %d.%d, "
  386. "firmware version %d.%d\n",
  387. hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
  388. (version & 0xf0) >> 4, version & 0xf);
  389. priv->firm_type = std;
  390. return 0;
  391. }
  392. static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
  393. {
  394. struct xc2028_data *priv = fe->tuner_priv;
  395. int frq_lock, signal = 0;
  396. tuner_info("%s called\n", __FUNCTION__);
  397. mutex_lock(&priv->lock);
  398. *strength = 0;
  399. /* Sync Lock Indicator */
  400. frq_lock = xc2028_get_reg(priv, 0x0002);
  401. if (frq_lock <= 0)
  402. goto ret;
  403. /* Frequency is locked. Return signal quality */
  404. /* Get SNR of the video signal */
  405. signal = xc2028_get_reg(priv, 0x0040);
  406. if (signal <= 0)
  407. signal = frq_lock;
  408. ret:
  409. mutex_unlock(&priv->lock);
  410. *strength = signal;
  411. return 0;
  412. }
  413. #define DIV 15625
  414. static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
  415. enum tuner_mode new_mode,
  416. v4l2_std_id std, fe_bandwidth_t bandwidth)
  417. {
  418. struct xc2028_data *priv = fe->tuner_priv;
  419. int rc = -EINVAL;
  420. unsigned char buf[5];
  421. u32 div, offset = 0;
  422. tuner_info("%s called\n", __FUNCTION__);
  423. mutex_lock(&priv->lock);
  424. /* HACK: It seems that specific firmware need to be reloaded
  425. when freq is changed */
  426. priv->firm_type = 0;
  427. /* Reset GPIO 1 */
  428. rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, 0);
  429. if (rc < 0)
  430. goto ret;
  431. msleep(10);
  432. tuner_info("should set frequency %d kHz)\n", freq / 1000);
  433. if (check_firmware(fe, new_mode, std, bandwidth) < 0)
  434. goto ret;
  435. if (new_mode == T_DIGITAL_TV)
  436. offset = 2750000;
  437. div = (freq - offset + DIV / 2) / DIV;
  438. /* CMD= Set frequency */
  439. if (priv->version < 0x0202) {
  440. send_seq(priv, {0x00, 0x02, 0x00, 0x00});
  441. } else {
  442. send_seq(priv, {0x80, 0x02, 0x00, 0x00});
  443. }
  444. rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
  445. if (rc < 0)
  446. goto ret;
  447. msleep(10);
  448. buf[0] = 0xff & (div >> 24);
  449. buf[1] = 0xff & (div >> 16);
  450. buf[2] = 0xff & (div >> 8);
  451. buf[3] = 0xff & (div);
  452. buf[4] = 0;
  453. i2c_send(rc, priv, buf, sizeof(buf));
  454. if (rc < 0)
  455. goto ret;
  456. msleep(100);
  457. priv->frequency = freq;
  458. printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n",
  459. buf[1], buf[2], buf[3], buf[4],
  460. freq / 1000000, (freq % 1000000) / 10000);
  461. rc = 0;
  462. ret:
  463. mutex_unlock(&priv->lock);
  464. return rc;
  465. }
  466. static int xc2028_set_tv_freq(struct dvb_frontend *fe,
  467. struct analog_parameters *p)
  468. {
  469. struct xc2028_data *priv = fe->tuner_priv;
  470. tuner_info("%s called\n", __FUNCTION__);
  471. return generic_set_tv_freq(fe, 62500l * p->frequency, T_ANALOG_TV,
  472. p->std, BANDWIDTH_8_MHZ /* NOT USED */);
  473. }
  474. static int xc2028_set_params(struct dvb_frontend *fe,
  475. struct dvb_frontend_parameters *p)
  476. {
  477. struct xc2028_data *priv = fe->tuner_priv;
  478. tuner_info("%s called\n", __FUNCTION__);
  479. /* FIXME: Only OFDM implemented */
  480. if (fe->ops.info.type != FE_OFDM) {
  481. tuner_info("DTV type not implemented.\n");
  482. return -EINVAL;
  483. }
  484. return generic_set_tv_freq(fe, p->frequency, T_DIGITAL_TV,
  485. 0 /* NOT USED */,
  486. p->u.ofdm.bandwidth);
  487. }
  488. static int xc2028_dvb_release(struct dvb_frontend *fe)
  489. {
  490. struct xc2028_data *priv = fe->tuner_priv;
  491. tuner_info("%s called\n", __FUNCTION__);
  492. priv->count--;
  493. if (!priv->count) {
  494. list_del(&priv->xc2028_list);
  495. kfree(priv->ctrl.fname);
  496. free_firmware(priv);
  497. kfree(priv);
  498. }
  499. return 0;
  500. }
  501. static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
  502. {
  503. struct xc2028_data *priv = fe->tuner_priv;
  504. tuner_info("%s called\n", __FUNCTION__);
  505. *frequency = priv->frequency;
  506. return 0;
  507. }
  508. static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
  509. {
  510. struct xc2028_data *priv = fe->tuner_priv;
  511. struct xc2028_ctrl *p = priv_cfg;
  512. tuner_info("%s called\n", __FUNCTION__);
  513. priv->ctrl.type = p->type;
  514. if (p->fname) {
  515. kfree(priv->ctrl.fname);
  516. priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL);
  517. if (!priv->ctrl.fname)
  518. return -ENOMEM;
  519. free_firmware(priv);
  520. strcpy(priv->ctrl.fname, p->fname);
  521. }
  522. if (p->max_len > 0)
  523. priv->max_len = p->max_len;
  524. tuner_info("%s OK\n", __FUNCTION__);
  525. return 0;
  526. }
  527. static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
  528. .info = {
  529. .name = "Xceive XC3028",
  530. .frequency_min = 42000000,
  531. .frequency_max = 864000000,
  532. .frequency_step = 50000,
  533. },
  534. .set_config = xc2028_set_config,
  535. .set_analog_params = xc2028_set_tv_freq,
  536. .release = xc2028_dvb_release,
  537. .get_frequency = xc2028_get_frequency,
  538. .get_rf_strength = xc2028_signal,
  539. .set_params = xc2028_set_params,
  540. };
  541. int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap,
  542. u8 i2c_addr, struct device *dev, void *video_dev,
  543. int (*tuner_callback) (void *dev, int command, int arg))
  544. {
  545. struct xc2028_data *priv;
  546. printk(KERN_INFO PREFIX "Xcv2028/3028 init called!\n");
  547. if (NULL == dev)
  548. return -ENODEV;
  549. if (NULL == video_dev)
  550. return -ENODEV;
  551. if (!tuner_callback) {
  552. printk(KERN_ERR PREFIX "No tuner callback!\n");
  553. return -EINVAL;
  554. }
  555. list_for_each_entry(priv, &xc2028_list, xc2028_list) {
  556. if (priv->dev == dev)
  557. dev = NULL;
  558. }
  559. if (dev) {
  560. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  561. if (priv == NULL)
  562. return -ENOMEM;
  563. fe->tuner_priv = priv;
  564. priv->bandwidth = BANDWIDTH_6_MHZ;
  565. priv->need_load_generic = 1;
  566. priv->mode = T_UNINITIALIZED;
  567. priv->i2c_props.addr = i2c_addr;
  568. priv->i2c_props.adap = i2c_adap;
  569. priv->dev = dev;
  570. priv->video_dev = video_dev;
  571. priv->tuner_callback = tuner_callback;
  572. priv->max_len = 13;
  573. mutex_init(&priv->lock);
  574. list_add_tail(&priv->xc2028_list, &xc2028_list);
  575. }
  576. priv->count++;
  577. memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
  578. sizeof(xc2028_dvb_tuner_ops));
  579. tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
  580. return 0;
  581. }
  582. EXPORT_SYMBOL(xc2028_attach);
  583. MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
  584. MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
  585. MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
  586. MODULE_LICENSE("GPL");