tuner-xc2028.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /* tuner-xc2028
  2. *
  3. * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
  4. * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
  5. * - frontend interface
  6. * This code is placed under the terms of the GNU General Public License v2
  7. */
  8. #include <linux/i2c.h>
  9. #include <asm/div64.h>
  10. #include <linux/firmware.h>
  11. #include <linux/videodev.h>
  12. #include <linux/delay.h>
  13. #include <media/tuner.h>
  14. #include "tuner-driver.h"
  15. #include "tuner-xc2028.h"
  16. #include <linux/dvb/frontend.h>
  17. #include "dvb_frontend.h"
  18. /* digital TV standards */
  19. #define V4L2_STD_DTV_6MHZ ((v4l2_std_id)0x04000000)
  20. #define V4L2_STD_DTV_7MHZ ((v4l2_std_id)0x08000000)
  21. #define V4L2_STD_DTV_8MHZ ((v4l2_std_id)0x10000000)
  22. /* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */
  23. static const char *firmware_6M = "tm6000_xc3028_DTV_6M.fw";
  24. // static const char *firmware_78M = "tm6000_xc3028_78M.fw";
  25. static const char *firmware_7M = "tm6000_xc3028_7M.fw";
  26. static const char *firmware_8M = "tm6000_xc3028_8M.fw";
  27. static const char *firmware_B = "tm6000_xc3028_B_PAL.fw";
  28. static const char *firmware_DK = "tm6000_xc3028_DK_PAL_MTS.fw";
  29. static const char *firmware_MN = "tm6000_xc3028_MN_BTSC.fw";
  30. static const char *firmware_INIT0 = "tm6000_xc3028_INIT0.fw";
  31. static const char *firmware_8MHZ_INIT0 = "tm6000_xc3028_8MHZ_INIT0.fw";
  32. struct xc2028_data {
  33. v4l2_std_id firm_type; /* video stds supported
  34. by current firmware */
  35. fe_bandwidth_t bandwidth; /* Firmware bandwidth:
  36. 6M, 7M or 8M */
  37. int need_load_generic; /* The generic firmware
  38. were loaded? */
  39. enum tuner_mode mode;
  40. struct i2c_client *i2c_client;
  41. };
  42. #define i2c_send(rc,c,buf,size) \
  43. if (size != (rc = i2c_master_send(c, buf, size))) \
  44. tuner_warn("i2c output error: rc = %d (should be %d)\n", \
  45. rc, (int)size);
  46. #define i2c_rcv(rc,c,buf,size) \
  47. if (size != (rc = i2c_master_recv(c, buf, size))) \
  48. tuner_warn("i2c input error: rc = %d (should be %d)\n", \
  49. rc, (int)size);
  50. #define send_seq(c, data...) \
  51. { int rc; \
  52. const static u8 _val[] = data; \
  53. if (sizeof(_val) != \
  54. (rc = i2c_master_send \
  55. (c, _val, sizeof(_val)))) { \
  56. printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc); \
  57. return; \
  58. } \
  59. msleep (10); \
  60. }
  61. static int xc2028_get_reg(struct i2c_client *c, u16 reg)
  62. {
  63. int rc;
  64. unsigned char buf[1];
  65. struct tuner *t = i2c_get_clientdata(c);
  66. buf[0]= reg;
  67. i2c_send(rc, c, buf, sizeof(buf));
  68. if (rc<0)
  69. return rc;
  70. if (t->tuner_callback) {
  71. rc = t->tuner_callback( c->adapter->algo_data,
  72. XC2028_RESET_CLK, 0);
  73. if (rc<0)
  74. return rc;
  75. }
  76. i2c_rcv(rc, c, buf, 2);
  77. if (rc<0)
  78. return rc;
  79. return (buf[1])|(buf[0]<<8);
  80. }
  81. static int load_firmware (struct i2c_client *c, const char *name)
  82. {
  83. const struct firmware *fw=NULL;
  84. struct tuner *t = i2c_get_clientdata(c);
  85. unsigned char *p, *endp;
  86. int len=0, rc=0;
  87. static const char firmware_ver[] = "tm6000/xcv v1";
  88. tuner_info("xc2028: Loading firmware %s\n", name);
  89. rc = request_firmware(&fw, name, &c->dev);
  90. if (rc < 0) {
  91. tuner_info("Error %d while requesting firmware\n", rc);
  92. return rc;
  93. }
  94. p=fw->data;
  95. endp=p+fw->size;
  96. if(fw->size==0) {
  97. tuner_info("Error: firmware size is zero!\n");
  98. rc=-EINVAL;
  99. goto err;
  100. }
  101. if (fw->size<sizeof(firmware_ver)-1) {
  102. /* Firmware is incorrect */
  103. tuner_info("Error: firmware size is less than header (%d<%d)!\n",
  104. (int)fw->size,(int)sizeof(firmware_ver)-1);
  105. rc=-EINVAL;
  106. goto err;
  107. }
  108. if (memcmp(p,firmware_ver,sizeof(firmware_ver)-1)) {
  109. /* Firmware is incorrect */
  110. tuner_info("Error: firmware is not for tm5600/6000 + Xcv2028/3028!\n");
  111. rc=-EINVAL;
  112. goto err;
  113. }
  114. p+=sizeof(firmware_ver)-1;
  115. while(p<endp) {
  116. if ((*p) & 0x80) {
  117. /* Special callback command received */
  118. rc = t->tuner_callback(c->adapter->algo_data,
  119. XC2028_TUNER_RESET, (*p)&0x7f);
  120. if (rc<0) {
  121. tuner_info("Error at RESET code %d\n",
  122. (*p)&0x7f);
  123. goto err;
  124. }
  125. p++;
  126. continue;
  127. }
  128. len=*p;
  129. p++;
  130. if (p+len+1>endp) {
  131. /* Firmware is incorrect */
  132. tuner_info("Error: firmware is truncated!\n");
  133. rc=-EINVAL;
  134. goto err;
  135. }
  136. if (len<=0) {
  137. tuner_info("Error: firmware file is corrupted!\n");
  138. rc=-EINVAL;
  139. goto err;
  140. }
  141. i2c_send(rc, c, p, len);
  142. if (rc<0)
  143. goto err;
  144. p+=len;
  145. if (*p)
  146. msleep(*p);
  147. p++;
  148. }
  149. err:
  150. release_firmware(fw);
  151. return rc;
  152. }
  153. static int check_firmware(struct i2c_client *c, enum tuner_mode new_mode,
  154. fe_bandwidth_t bandwidth)
  155. {
  156. int rc, version;
  157. struct tuner *t = i2c_get_clientdata(c);
  158. struct xc2028_data *xc2028 = t->priv;
  159. const char *name;
  160. int change_digital_bandwidth;
  161. if (!t->tuner_callback) {
  162. printk(KERN_ERR "xc2028: need tuner_callback to load firmware\n");
  163. return -EINVAL;
  164. }
  165. printk(KERN_INFO "xc2028: I am in mode %u and I should switch to mode %i\n",
  166. xc2028->mode, new_mode);
  167. /* first of all, determine whether we have switched the mode */
  168. if(new_mode != xc2028->mode) {
  169. xc2028->mode = new_mode;
  170. xc2028->need_load_generic = 1;
  171. }
  172. change_digital_bandwidth = (xc2028->mode == T_DIGITAL_TV
  173. && bandwidth != xc2028->bandwidth) ? 1 : 0;
  174. tuner_info("xc2028: old bandwidth %u, new bandwidth %u\n", xc2028->bandwidth,
  175. bandwidth);
  176. if (xc2028->need_load_generic) {
  177. if (xc2028->bandwidth==6)
  178. name = firmware_INIT0;
  179. else
  180. name = firmware_8MHZ_INIT0;
  181. /* Reset is needed before loading firmware */
  182. rc = t->tuner_callback(c->adapter->algo_data,
  183. XC2028_TUNER_RESET, 0);
  184. if (rc<0)
  185. return rc;
  186. rc = load_firmware(c,name);
  187. if (rc<0)
  188. return rc;
  189. xc2028->need_load_generic=0;
  190. xc2028->firm_type=0;
  191. if(xc2028->mode == T_DIGITAL_TV) {
  192. change_digital_bandwidth=1;
  193. }
  194. }
  195. tuner_info("xc2028: I should change bandwidth %u\n",
  196. change_digital_bandwidth);
  197. if (change_digital_bandwidth) {
  198. switch(bandwidth) {
  199. case BANDWIDTH_8_MHZ:
  200. t->std = V4L2_STD_DTV_8MHZ;
  201. break;
  202. case BANDWIDTH_7_MHZ:
  203. t->std = V4L2_STD_DTV_7MHZ;
  204. break;
  205. case BANDWIDTH_6_MHZ:
  206. t->std = V4L2_STD_DTV_6MHZ;
  207. break;
  208. default:
  209. tuner_info("error: bandwidth not supported.\n");
  210. };
  211. xc2028->bandwidth = bandwidth;
  212. }
  213. if (xc2028->firm_type & t->std)
  214. return 0;
  215. if (t->std & V4L2_STD_MN)
  216. name=firmware_MN;
  217. else if (t->std & V4L2_STD_DTV_6MHZ)
  218. name=firmware_6M;
  219. else if (t->std & V4L2_STD_DTV_7MHZ)
  220. name=firmware_7M;
  221. else if (t->std & V4L2_STD_DTV_8MHZ)
  222. name=firmware_8M;
  223. else if (t->std & V4L2_STD_PAL_B)
  224. name=firmware_B;
  225. else
  226. name=firmware_DK;
  227. tuner_info("xc2028: loading firmware named %s.\n", name);
  228. rc = load_firmware(c, name);
  229. if (rc<0)
  230. return rc;
  231. version = xc2028_get_reg(c, 0x4);
  232. tuner_info("Firmware version is %d.%d\n",
  233. (version>>4)&0x0f,(version)&0x0f);
  234. xc2028->firm_type=t->std;
  235. return 0;
  236. }
  237. static int xc2028_signal(struct i2c_client *c)
  238. {
  239. int lock, signal;
  240. printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__);
  241. lock = xc2028_get_reg(c, 0x2);
  242. if (lock<=0)
  243. return lock;
  244. /* Frequency is locked. Return signal quality */
  245. signal = xc2028_get_reg(c, 0x40);
  246. if(signal<=0)
  247. return lock;
  248. return signal;
  249. }
  250. #define DIV 15625
  251. static void generic_set_tv_freq(struct i2c_client *c, u32 freq /* in Hz */,
  252. enum tuner_mode new_mode, fe_bandwidth_t bandwidth)
  253. {
  254. int rc;
  255. unsigned char buf[5];
  256. struct tuner *t = i2c_get_clientdata(c);
  257. u32 div, offset = 0;
  258. printk("xc3028: should set frequency %d kHz)\n", freq / 1000);
  259. if (check_firmware(c, new_mode, bandwidth)<0)
  260. return;
  261. if(new_mode == T_DIGITAL_TV) {
  262. switch(bandwidth) {
  263. case BANDWIDTH_8_MHZ:
  264. offset = 2750000;
  265. break;
  266. case BANDWIDTH_7_MHZ:
  267. offset = 2750000;
  268. break;
  269. case BANDWIDTH_6_MHZ:
  270. default:
  271. printk(KERN_ERR "xc2028: bandwidth not implemented!\n");
  272. }
  273. }
  274. div = (freq - offset + DIV/2)/DIV;
  275. /* Reset GPIO 1 */
  276. if (t->tuner_callback) {
  277. rc = t->tuner_callback( c->adapter->algo_data,
  278. XC2028_TUNER_RESET, 0);
  279. if (rc<0)
  280. return;
  281. }
  282. msleep(10);
  283. /* CMD= Set frequency */
  284. send_seq(c, {0x00, 0x02, 0x00, 0x00});
  285. if (t->tuner_callback) {
  286. rc = t->tuner_callback( c->adapter->algo_data,
  287. XC2028_RESET_CLK, 1);
  288. if (rc<0)
  289. return;
  290. }
  291. msleep(10);
  292. // send_seq(c, {0x00, 0x00, 0x10, 0xd0, 0x00});
  293. // msleep(100);
  294. buf[0]= 0xff & (div>>24);
  295. buf[1]= 0xff & (div>>16);
  296. buf[2]= 0xff & (div>>8);
  297. buf[3]= 0xff & (div);
  298. buf[4]= 0;
  299. i2c_send(rc, c, buf, sizeof(buf));
  300. if (rc<0)
  301. return;
  302. msleep(100);
  303. printk("divider= %02x %02x %02x %02x (freq=%d.%02d)\n",
  304. buf[1],buf[2],buf[3],buf[4],
  305. freq / 16, freq % 16 * 100 / 16);
  306. // printk("signal=%d\n",xc2028_signal(c));
  307. }
  308. static void set_tv_freq(struct i2c_client *c, unsigned int freq)
  309. {
  310. printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__);
  311. generic_set_tv_freq(c, freq * 62500l, T_ANALOG_TV,
  312. BANDWIDTH_8_MHZ /* unimportant */);
  313. }
  314. static void xc2028_release(struct i2c_client *c)
  315. {
  316. struct tuner *t = i2c_get_clientdata(c);
  317. kfree(t->priv);
  318. t->priv = NULL;
  319. }
  320. static struct tuner_operations tea5767_tuner_ops = {
  321. .set_tv_freq = set_tv_freq,
  322. .has_signal = xc2028_signal,
  323. .release = xc2028_release,
  324. // .is_stereo = xc2028_stereo,
  325. };
  326. static int init=0;
  327. int xc2028_tuner_init(struct i2c_client *c)
  328. {
  329. struct tuner *t = i2c_get_clientdata(c);
  330. int version = xc2028_get_reg(c, 0x4);
  331. int prd_id = xc2028_get_reg(c, 0x8);
  332. struct xc2028_data *xc2028;
  333. tuner_info("Xcv2028/3028 init called!\n");
  334. if (init) {
  335. printk (KERN_ERR "Module already initialized!\n");
  336. return 0;
  337. }
  338. init++;
  339. xc2028 = kzalloc(sizeof(*xc2028), GFP_KERNEL);
  340. if (!xc2028)
  341. return -ENOMEM;
  342. t->priv = xc2028;
  343. xc2028->bandwidth=BANDWIDTH_6_MHZ;
  344. xc2028->need_load_generic=1;
  345. xc2028->mode = T_UNINITIALIZED;
  346. /* FIXME: Check where t->priv will be freed */
  347. if (version<0)
  348. version=0;
  349. if (prd_id<0)
  350. prd_id=0;
  351. strlcpy(c->name, "xc2028", sizeof(c->name));
  352. tuner_info("type set to %d (%s, hw ver=%d.%d, fw ver=%d.%d, id=0x%04x)\n",
  353. t->type, c->name,
  354. (version>>12)&0x0f,(version>>8)&0x0f,
  355. (version>>4)&0x0f,(version)&0x0f, prd_id);
  356. memcpy(&t->ops, &tea5767_tuner_ops, sizeof(struct tuner_operations));
  357. return 0;
  358. }
  359. static int xc3028_set_params(struct dvb_frontend *fe,
  360. struct dvb_frontend_parameters *p)
  361. {
  362. struct i2c_client *c = fe->tuner_priv;
  363. printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__);
  364. generic_set_tv_freq(c, p->frequency, T_DIGITAL_TV,
  365. p->u.ofdm.bandwidth);
  366. return 0;
  367. }
  368. static int xc3028_dvb_release(struct dvb_frontend *fe)
  369. {
  370. printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__);
  371. fe->tuner_priv = NULL;
  372. return 0;
  373. }
  374. static int xc3028_dvb_init(struct dvb_frontend *fe)
  375. {
  376. printk(KERN_INFO "xc2028: %s called\n", __FUNCTION__);
  377. return 0;
  378. }
  379. static const struct dvb_tuner_ops xc3028_dvb_tuner_ops = {
  380. .info = {
  381. .name = "Xceive XC3028",
  382. .frequency_min = 42000000,
  383. .frequency_max = 864000000,
  384. .frequency_step = 50000,
  385. },
  386. .release = xc3028_dvb_release,
  387. .init = xc3028_dvb_init,
  388. // int (*sleep)(struct dvb_frontend *fe);
  389. /** This is for simple PLLs - set all parameters in one go. */
  390. .set_params = xc3028_set_params,
  391. /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
  392. // int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
  393. // int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
  394. // int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
  395. // int (*get_status)(struct dvb_frontend *fe, u32 *status);
  396. };
  397. int xc2028_attach(struct i2c_client *c, struct dvb_frontend *fe)
  398. {
  399. fe->tuner_priv = c;
  400. memcpy(&fe->ops.tuner_ops, &xc3028_dvb_tuner_ops, sizeof(fe->ops.tuner_ops));
  401. return 0;
  402. }
  403. EXPORT_SYMBOL(xc2028_attach);