mxl692.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for the MaxLinear MxL69x family of combo tuners/demods
  4. *
  5. * Copyright (C) 2020 Brad Love <[email protected]>
  6. *
  7. * based on code:
  8. * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
  9. * which was released under GPL V2
  10. */
  11. #include <linux/mutex.h>
  12. #include <linux/i2c-mux.h>
  13. #include <linux/string.h>
  14. #include <linux/firmware.h>
  15. #include "mxl692.h"
  16. #include "mxl692_defs.h"
  17. static const struct dvb_frontend_ops mxl692_ops;
  18. struct mxl692_dev {
  19. struct dvb_frontend fe;
  20. struct i2c_client *i2c_client;
  21. struct mutex i2c_lock; /* i2c command mutex */
  22. enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
  23. enum MXL_EAGLE_POWER_MODE_E power_mode;
  24. u32 current_frequency;
  25. int device_type;
  26. int seqnum;
  27. int init_done;
  28. };
  29. static int mxl692_i2c_write(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
  30. {
  31. int ret = 0;
  32. struct i2c_msg msg = {
  33. .addr = dev->i2c_client->addr,
  34. .flags = 0,
  35. .buf = buffer,
  36. .len = buf_len
  37. };
  38. ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
  39. if (ret != 1)
  40. dev_dbg(&dev->i2c_client->dev, "i2c write error!\n");
  41. return ret;
  42. }
  43. static int mxl692_i2c_read(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
  44. {
  45. int ret = 0;
  46. struct i2c_msg msg = {
  47. .addr = dev->i2c_client->addr,
  48. .flags = I2C_M_RD,
  49. .buf = buffer,
  50. .len = buf_len
  51. };
  52. ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
  53. if (ret != 1)
  54. dev_dbg(&dev->i2c_client->dev, "i2c read error!\n");
  55. return ret;
  56. }
  57. static int convert_endian(u32 size, u8 *d)
  58. {
  59. u32 i;
  60. for (i = 0; i < (size & ~3); i += 4) {
  61. d[i + 0] ^= d[i + 3];
  62. d[i + 3] ^= d[i + 0];
  63. d[i + 0] ^= d[i + 3];
  64. d[i + 1] ^= d[i + 2];
  65. d[i + 2] ^= d[i + 1];
  66. d[i + 1] ^= d[i + 2];
  67. }
  68. switch (size & 3) {
  69. case 0:
  70. case 1:
  71. /* do nothing */
  72. break;
  73. case 2:
  74. d[i + 0] ^= d[i + 1];
  75. d[i + 1] ^= d[i + 0];
  76. d[i + 0] ^= d[i + 1];
  77. break;
  78. case 3:
  79. d[i + 0] ^= d[i + 2];
  80. d[i + 2] ^= d[i + 0];
  81. d[i + 0] ^= d[i + 2];
  82. break;
  83. }
  84. return size;
  85. }
  86. static int convert_endian_n(int n, u32 size, u8 *d)
  87. {
  88. int i, count = 0;
  89. for (i = 0; i < n; i += size)
  90. count += convert_endian(size, d + i);
  91. return count;
  92. }
  93. static void mxl692_tx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
  94. {
  95. #ifdef __BIG_ENDIAN
  96. return;
  97. #endif
  98. buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
  99. switch (opcode) {
  100. case MXL_EAGLE_OPCODE_DEVICE_INTR_MASK_SET:
  101. case MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET:
  102. case MXL_EAGLE_OPCODE_SMA_TRANSMIT_SET:
  103. buffer += convert_endian(sizeof(u32), buffer);
  104. break;
  105. case MXL_EAGLE_OPCODE_QAM_PARAMS_SET:
  106. buffer += 5;
  107. buffer += convert_endian(2 * sizeof(u32), buffer);
  108. break;
  109. default:
  110. /* no swapping - all get opcodes */
  111. /* ATSC/OOB no swapping */
  112. break;
  113. }
  114. }
  115. static void mxl692_rx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
  116. {
  117. #ifdef __BIG_ENDIAN
  118. return;
  119. #endif
  120. buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
  121. switch (opcode) {
  122. case MXL_EAGLE_OPCODE_TUNER_AGC_STATUS_GET:
  123. buffer++;
  124. buffer += convert_endian(2 * sizeof(u16), buffer);
  125. break;
  126. case MXL_EAGLE_OPCODE_ATSC_STATUS_GET:
  127. buffer += convert_endian_n(2, sizeof(u16), buffer);
  128. buffer += convert_endian(sizeof(u32), buffer);
  129. break;
  130. case MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET:
  131. buffer += convert_endian(3 * sizeof(u32), buffer);
  132. break;
  133. case MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_FFE_TAPS_GET:
  134. buffer += convert_endian_n(24, sizeof(u16), buffer);
  135. break;
  136. case MXL_EAGLE_OPCODE_QAM_STATUS_GET:
  137. buffer += 8;
  138. buffer += convert_endian_n(2, sizeof(u16), buffer);
  139. buffer += convert_endian(sizeof(u32), buffer);
  140. break;
  141. case MXL_EAGLE_OPCODE_QAM_ERROR_COUNTERS_GET:
  142. buffer += convert_endian(7 * sizeof(u32), buffer);
  143. break;
  144. case MXL_EAGLE_OPCODE_QAM_CONSTELLATION_VALUE_GET:
  145. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_START_GET:
  146. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_MIDDLE_GET:
  147. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_END_GET:
  148. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_START_GET:
  149. buffer += convert_endian_n(24, sizeof(u16), buffer);
  150. break;
  151. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_END_GET:
  152. buffer += convert_endian_n(8, sizeof(u16), buffer);
  153. break;
  154. case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_FFE_GET:
  155. buffer += convert_endian_n(17, sizeof(u16), buffer);
  156. break;
  157. case MXL_EAGLE_OPCODE_OOB_ERROR_COUNTERS_GET:
  158. buffer += convert_endian(3 * sizeof(u32), buffer);
  159. break;
  160. case MXL_EAGLE_OPCODE_OOB_STATUS_GET:
  161. buffer += convert_endian_n(2, sizeof(u16), buffer);
  162. buffer += convert_endian(sizeof(u32), buffer);
  163. break;
  164. case MXL_EAGLE_OPCODE_SMA_RECEIVE_GET:
  165. buffer += convert_endian(sizeof(u32), buffer);
  166. break;
  167. default:
  168. /* no swapping - all set opcodes */
  169. break;
  170. }
  171. }
  172. static u32 mxl692_checksum(u8 *buffer, u32 size)
  173. {
  174. u32 ix, div_size;
  175. u32 cur_cksum = 0;
  176. __be32 *buf;
  177. div_size = DIV_ROUND_UP(size, 4);
  178. buf = (__be32 *)buffer;
  179. for (ix = 0; ix < div_size; ix++)
  180. cur_cksum += be32_to_cpu(buf[ix]);
  181. cur_cksum ^= 0xDEADBEEF;
  182. return cur_cksum;
  183. }
  184. static int mxl692_validate_fw_header(struct mxl692_dev *dev,
  185. const u8 *buffer, u32 buf_len)
  186. {
  187. int status = 0;
  188. u32 ix, temp;
  189. __be32 *local_buf = NULL;
  190. u8 temp_cksum = 0;
  191. static const u8 fw_hdr[] = {
  192. 0x4D, 0x31, 0x10, 0x02, 0x40, 0x00, 0x00, 0x80
  193. };
  194. if (memcmp(buffer, fw_hdr, 8) != 0) {
  195. status = -EINVAL;
  196. goto err_finish;
  197. }
  198. local_buf = (__be32 *)(buffer + 8);
  199. temp = be32_to_cpu(*local_buf);
  200. if ((buf_len - 16) != temp >> 8) {
  201. status = -EINVAL;
  202. goto err_finish;
  203. }
  204. for (ix = 16; ix < buf_len; ix++)
  205. temp_cksum += buffer[ix];
  206. if (temp_cksum != buffer[11])
  207. status = -EINVAL;
  208. err_finish:
  209. if (status)
  210. dev_dbg(&dev->i2c_client->dev, "failed\n");
  211. return status;
  212. }
  213. static int mxl692_write_fw_block(struct mxl692_dev *dev, const u8 *buffer,
  214. u32 buf_len, u32 *index)
  215. {
  216. int status = 0;
  217. u32 ix = 0, total_len = 0, addr = 0, chunk_len = 0, prevchunk_len = 0;
  218. u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
  219. int payload_max = MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE;
  220. ix = *index;
  221. if (buffer[ix] == 0x53) {
  222. total_len = buffer[ix + 1] << 16 | buffer[ix + 2] << 8 | buffer[ix + 3];
  223. total_len = (total_len + 3) & ~3;
  224. addr = buffer[ix + 4] << 24 | buffer[ix + 5] << 16 |
  225. buffer[ix + 6] << 8 | buffer[ix + 7];
  226. ix += MXL_EAGLE_FW_SEGMENT_HEADER_SIZE;
  227. while ((total_len > 0) && (status == 0)) {
  228. plocal_buf = local_buf;
  229. chunk_len = (total_len < payload_max) ? total_len : payload_max;
  230. *plocal_buf++ = 0xFC;
  231. *plocal_buf++ = chunk_len + sizeof(u32);
  232. *(u32 *)plocal_buf = addr + prevchunk_len;
  233. #ifdef __BIG_ENDIAN
  234. convert_endian(sizeof(u32), plocal_buf);
  235. #endif
  236. plocal_buf += sizeof(u32);
  237. memcpy(plocal_buf, &buffer[ix], chunk_len);
  238. convert_endian(chunk_len, plocal_buf);
  239. if (mxl692_i2c_write(dev, local_buf,
  240. (chunk_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
  241. status = -EREMOTEIO;
  242. break;
  243. }
  244. prevchunk_len += chunk_len;
  245. total_len -= chunk_len;
  246. ix += chunk_len;
  247. }
  248. *index = ix;
  249. } else {
  250. status = -EINVAL;
  251. }
  252. if (status)
  253. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  254. return status;
  255. }
  256. static int mxl692_memwrite(struct mxl692_dev *dev, u32 addr,
  257. u8 *buffer, u32 size)
  258. {
  259. int status = 0, total_len = 0;
  260. u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
  261. total_len = size;
  262. total_len = (total_len + 3) & ~3; /* 4 byte alignment */
  263. if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE))
  264. dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
  265. plocal_buf = local_buf;
  266. *plocal_buf++ = 0xFC;
  267. *plocal_buf++ = total_len + sizeof(u32);
  268. *(u32 *)plocal_buf = addr;
  269. plocal_buf += sizeof(u32);
  270. memcpy(plocal_buf, buffer, total_len);
  271. #ifdef __BIG_ENDIAN
  272. convert_endian(sizeof(u32) + total_len, local_buf + 2);
  273. #endif
  274. if (mxl692_i2c_write(dev, local_buf,
  275. (total_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
  276. status = -EREMOTEIO;
  277. goto err_finish;
  278. }
  279. return status;
  280. err_finish:
  281. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  282. return status;
  283. }
  284. static int mxl692_memread(struct mxl692_dev *dev, u32 addr,
  285. u8 *buffer, u32 size)
  286. {
  287. int status = 0;
  288. u8 local_buf[MXL_EAGLE_I2C_MHEADER_SIZE] = {}, *plocal_buf = NULL;
  289. plocal_buf = local_buf;
  290. *plocal_buf++ = 0xFB;
  291. *plocal_buf++ = sizeof(u32);
  292. *(u32 *)plocal_buf = addr;
  293. #ifdef __BIG_ENDIAN
  294. convert_endian(sizeof(u32), plocal_buf);
  295. #endif
  296. mutex_lock(&dev->i2c_lock);
  297. if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_MHEADER_SIZE) > 0) {
  298. size = (size + 3) & ~3; /* 4 byte alignment */
  299. status = mxl692_i2c_read(dev, buffer, (u16)size) < 0 ? -EREMOTEIO : 0;
  300. #ifdef __BIG_ENDIAN
  301. if (status == 0)
  302. convert_endian(size, buffer);
  303. #endif
  304. } else {
  305. status = -EREMOTEIO;
  306. }
  307. mutex_unlock(&dev->i2c_lock);
  308. if (status)
  309. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  310. return status;
  311. }
  312. static const char *mxl692_opcode_string(u8 opcode)
  313. {
  314. if (opcode <= MXL_EAGLE_OPCODE_INTERNAL)
  315. return MXL_EAGLE_OPCODE_STRING[opcode];
  316. return "invalid opcode";
  317. }
  318. static int mxl692_opwrite(struct mxl692_dev *dev, u8 *buffer,
  319. u32 size)
  320. {
  321. int status = 0, total_len = 0;
  322. u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
  323. struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_hdr = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)buffer;
  324. total_len = size;
  325. total_len = (total_len + 3) & ~3; /* 4 byte alignment */
  326. if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE))
  327. dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
  328. plocal_buf = local_buf;
  329. *plocal_buf++ = 0xFE;
  330. *plocal_buf++ = (u8)total_len;
  331. memcpy(plocal_buf, buffer, total_len);
  332. convert_endian(total_len, plocal_buf);
  333. if (mxl692_i2c_write(dev, local_buf,
  334. (total_len + MXL_EAGLE_I2C_PHEADER_SIZE)) < 0) {
  335. status = -EREMOTEIO;
  336. goto err_finish;
  337. }
  338. err_finish:
  339. if (status)
  340. dev_dbg(&dev->i2c_client->dev, "opcode %s err %d\n",
  341. mxl692_opcode_string(tx_hdr->opcode), status);
  342. return status;
  343. }
  344. static int mxl692_opread(struct mxl692_dev *dev, u8 *buffer,
  345. u32 size)
  346. {
  347. int status = 0;
  348. u32 ix = 0;
  349. u8 local_buf[MXL_EAGLE_I2C_PHEADER_SIZE] = {};
  350. local_buf[0] = 0xFD;
  351. local_buf[1] = 0;
  352. if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_PHEADER_SIZE) > 0) {
  353. size = (size + 3) & ~3; /* 4 byte alignment */
  354. /* Read in 4 byte chunks */
  355. for (ix = 0; ix < size; ix += 4) {
  356. if (mxl692_i2c_read(dev, buffer + ix, 4) < 0) {
  357. dev_dbg(&dev->i2c_client->dev, "ix=%d size=%d\n", ix, size);
  358. status = -EREMOTEIO;
  359. goto err_finish;
  360. }
  361. }
  362. convert_endian(size, buffer);
  363. } else {
  364. status = -EREMOTEIO;
  365. }
  366. err_finish:
  367. if (status)
  368. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  369. return status;
  370. }
  371. static int mxl692_i2c_writeread(struct mxl692_dev *dev,
  372. u8 opcode,
  373. u8 *tx_payload,
  374. u8 tx_payload_size,
  375. u8 *rx_payload,
  376. u8 rx_payload_expected)
  377. {
  378. int status = 0, timeout = 40;
  379. u8 tx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  380. u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  381. u32 resp_checksum = 0, resp_checksum_tmp = 0;
  382. struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_header;
  383. struct MXL_EAGLE_HOST_MSG_HEADER_T *rx_header;
  384. mutex_lock(&dev->i2c_lock);
  385. if ((tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE) >
  386. (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE)) {
  387. status = -EINVAL;
  388. goto err_finish;
  389. }
  390. tx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)tx_buf;
  391. tx_header->opcode = opcode;
  392. tx_header->seqnum = dev->seqnum++;
  393. tx_header->payload_size = tx_payload_size;
  394. tx_header->checksum = 0;
  395. if (dev->seqnum == 0)
  396. dev->seqnum = 1;
  397. if (tx_payload && tx_payload_size > 0)
  398. memcpy(&tx_buf[MXL_EAGLE_HOST_MSG_HEADER_SIZE], tx_payload, tx_payload_size);
  399. mxl692_tx_swap(opcode, tx_buf);
  400. tx_header->checksum = 0;
  401. tx_header->checksum = mxl692_checksum(tx_buf,
  402. MXL_EAGLE_HOST_MSG_HEADER_SIZE + tx_payload_size);
  403. #ifdef __LITTLE_ENDIAN
  404. convert_endian(4, (u8 *)&tx_header->checksum); /* cksum is big endian */
  405. #endif
  406. /* send Tx message */
  407. status = mxl692_opwrite(dev, tx_buf,
  408. tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
  409. if (status) {
  410. status = -EREMOTEIO;
  411. goto err_finish;
  412. }
  413. /* receive Rx message (polling) */
  414. rx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)rx_buf;
  415. do {
  416. status = mxl692_opread(dev, rx_buf,
  417. rx_payload_expected + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
  418. usleep_range(1000, 2000);
  419. timeout--;
  420. } while ((timeout > 0) && (status == 0) &&
  421. (rx_header->seqnum == 0) &&
  422. (rx_header->checksum == 0));
  423. if (timeout == 0 || status) {
  424. dev_dbg(&dev->i2c_client->dev, "timeout=%d status=%d\n",
  425. timeout, status);
  426. status = -ETIMEDOUT;
  427. goto err_finish;
  428. }
  429. if (rx_header->status) {
  430. dev_dbg(&dev->i2c_client->dev, "rx header status code: %d\n", rx_header->status);
  431. status = -EREMOTEIO;
  432. goto err_finish;
  433. }
  434. if (rx_header->seqnum != tx_header->seqnum ||
  435. rx_header->opcode != tx_header->opcode ||
  436. rx_header->payload_size != rx_payload_expected) {
  437. dev_dbg(&dev->i2c_client->dev, "Something failed seq=%s opcode=%s pSize=%s\n",
  438. rx_header->seqnum != tx_header->seqnum ? "X" : "0",
  439. rx_header->opcode != tx_header->opcode ? "X" : "0",
  440. rx_header->payload_size != rx_payload_expected ? "X" : "0");
  441. if (rx_header->payload_size != rx_payload_expected)
  442. dev_dbg(&dev->i2c_client->dev,
  443. "rx_header->payloadSize=%d rx_payload_expected=%d\n",
  444. rx_header->payload_size, rx_payload_expected);
  445. status = -EREMOTEIO;
  446. goto err_finish;
  447. }
  448. resp_checksum = rx_header->checksum;
  449. rx_header->checksum = 0;
  450. resp_checksum_tmp = mxl692_checksum(rx_buf,
  451. MXL_EAGLE_HOST_MSG_HEADER_SIZE + rx_header->payload_size);
  452. #ifdef __LITTLE_ENDIAN
  453. convert_endian(4, (u8 *)&resp_checksum_tmp); /* cksum is big endian */
  454. #endif
  455. if (resp_checksum != resp_checksum_tmp) {
  456. dev_dbg(&dev->i2c_client->dev, "rx checksum failure\n");
  457. status = -EREMOTEIO;
  458. goto err_finish;
  459. }
  460. mxl692_rx_swap(rx_header->opcode, rx_buf);
  461. if (rx_header->payload_size > 0) {
  462. if (!rx_payload) {
  463. dev_dbg(&dev->i2c_client->dev, "no rx payload?!?\n");
  464. status = -EREMOTEIO;
  465. goto err_finish;
  466. }
  467. memcpy(rx_payload, rx_buf + MXL_EAGLE_HOST_MSG_HEADER_SIZE,
  468. rx_header->payload_size);
  469. }
  470. err_finish:
  471. if (status)
  472. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  473. mutex_unlock(&dev->i2c_lock);
  474. return status;
  475. }
  476. static int mxl692_fwdownload(struct mxl692_dev *dev,
  477. const u8 *firmware_buf, u32 buf_len)
  478. {
  479. int status = 0;
  480. u32 ix, reg_val = 0x1;
  481. u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  482. struct MXL_EAGLE_DEV_STATUS_T *dev_status;
  483. if (buf_len < MXL_EAGLE_FW_HEADER_SIZE ||
  484. buf_len > MXL_EAGLE_FW_MAX_SIZE_IN_KB * 1000)
  485. return -EINVAL;
  486. mutex_lock(&dev->i2c_lock);
  487. dev_dbg(&dev->i2c_client->dev, "\n");
  488. status = mxl692_validate_fw_header(dev, firmware_buf, buf_len);
  489. if (status)
  490. goto err_finish;
  491. ix = 16;
  492. status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* DRAM */
  493. if (status)
  494. goto err_finish;
  495. status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* IRAM */
  496. if (status)
  497. goto err_finish;
  498. /* release CPU from reset */
  499. status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
  500. if (status)
  501. goto err_finish;
  502. mutex_unlock(&dev->i2c_lock);
  503. if (status == 0) {
  504. /* verify FW is alive */
  505. usleep_range(MXL_EAGLE_FW_LOAD_TIME * 1000, (MXL_EAGLE_FW_LOAD_TIME + 5) * 1000);
  506. dev_status = (struct MXL_EAGLE_DEV_STATUS_T *)&rx_buf;
  507. status = mxl692_i2c_writeread(dev,
  508. MXL_EAGLE_OPCODE_DEVICE_STATUS_GET,
  509. NULL,
  510. 0,
  511. (u8 *)dev_status,
  512. sizeof(struct MXL_EAGLE_DEV_STATUS_T));
  513. }
  514. return status;
  515. err_finish:
  516. mutex_unlock(&dev->i2c_lock);
  517. if (status)
  518. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  519. return status;
  520. }
  521. static int mxl692_get_versions(struct mxl692_dev *dev)
  522. {
  523. int status = 0;
  524. struct MXL_EAGLE_DEV_VER_T dev_ver = {};
  525. static const char * const chip_id[] = {"N/A", "691", "248", "692"};
  526. status = mxl692_i2c_writeread(dev, MXL_EAGLE_OPCODE_DEVICE_VERSION_GET,
  527. NULL,
  528. 0,
  529. (u8 *)&dev_ver,
  530. sizeof(struct MXL_EAGLE_DEV_VER_T));
  531. if (status)
  532. return status;
  533. dev_info(&dev->i2c_client->dev, "MxL692_DEMOD Chip ID: %s\n",
  534. chip_id[dev_ver.chip_id]);
  535. dev_info(&dev->i2c_client->dev,
  536. "MxL692_DEMOD FW Version: %d.%d.%d.%d_RC%d\n",
  537. dev_ver.firmware_ver[0],
  538. dev_ver.firmware_ver[1],
  539. dev_ver.firmware_ver[2],
  540. dev_ver.firmware_ver[3],
  541. dev_ver.firmware_ver[4]);
  542. return status;
  543. }
  544. static int mxl692_reset(struct mxl692_dev *dev)
  545. {
  546. int status = 0;
  547. u32 dev_type = MXL_EAGLE_DEVICE_MAX, reg_val = 0x2;
  548. dev_dbg(&dev->i2c_client->dev, "\n");
  549. /* legacy i2c override */
  550. status = mxl692_memwrite(dev, 0x80000100, (u8 *)&reg_val, sizeof(u32));
  551. if (status)
  552. goto err_finish;
  553. /* verify sku */
  554. status = mxl692_memread(dev, 0x70000188, (u8 *)&dev_type, sizeof(u32));
  555. if (status)
  556. goto err_finish;
  557. if (dev_type != dev->device_type)
  558. goto err_finish;
  559. err_finish:
  560. if (status)
  561. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  562. return status;
  563. }
  564. static int mxl692_config_regulators(struct mxl692_dev *dev,
  565. enum MXL_EAGLE_POWER_SUPPLY_SOURCE_E power_supply)
  566. {
  567. int status = 0;
  568. u32 reg_val;
  569. dev_dbg(&dev->i2c_client->dev, "\n");
  570. /* configure main regulator according to the power supply source */
  571. status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  572. if (status)
  573. goto err_finish;
  574. reg_val &= 0x00FFFFFF;
  575. reg_val |= (power_supply == MXL_EAGLE_POWER_SUPPLY_SOURCE_SINGLE) ?
  576. 0x14000000 : 0x10000000;
  577. status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  578. if (status)
  579. goto err_finish;
  580. /* configure digital regulator to high current mode */
  581. status = mxl692_memread(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
  582. if (status)
  583. goto err_finish;
  584. reg_val |= 0x800;
  585. status = mxl692_memwrite(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
  586. err_finish:
  587. if (status)
  588. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  589. return status;
  590. }
  591. static int mxl692_config_xtal(struct mxl692_dev *dev,
  592. struct MXL_EAGLE_DEV_XTAL_T *dev_xtal)
  593. {
  594. int status = 0;
  595. u32 reg_val, reg_val1;
  596. dev_dbg(&dev->i2c_client->dev, "\n");
  597. status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  598. if (status)
  599. goto err_finish;
  600. /* set XTAL capacitance */
  601. reg_val &= 0xFFFFFFE0;
  602. reg_val |= dev_xtal->xtal_cap;
  603. /* set CLK OUT */
  604. reg_val = dev_xtal->clk_out_enable ? (reg_val | 0x0100) : (reg_val & 0xFFFFFEFF);
  605. status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  606. if (status)
  607. goto err_finish;
  608. /* set CLK OUT divider */
  609. reg_val = dev_xtal->clk_out_div_enable ? (reg_val | 0x0200) : (reg_val & 0xFFFFFDFF);
  610. status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  611. if (status)
  612. goto err_finish;
  613. /* set XTAL sharing */
  614. reg_val = dev_xtal->xtal_sharing_enable ? (reg_val | 0x010400) : (reg_val & 0xFFFEFBFF);
  615. status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
  616. if (status)
  617. goto err_finish;
  618. /* enable/disable XTAL calibration, based on master/slave device */
  619. status = mxl692_memread(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
  620. if (status)
  621. goto err_finish;
  622. if (dev_xtal->xtal_calibration_enable) {
  623. /* enable XTAL calibration and set XTAL amplitude to a higher value */
  624. reg_val1 &= 0xFFFFFFFD;
  625. reg_val1 |= 0x30;
  626. status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
  627. if (status)
  628. goto err_finish;
  629. } else {
  630. /* disable XTAL calibration */
  631. reg_val1 |= 0x2;
  632. status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
  633. if (status)
  634. goto err_finish;
  635. /* set XTAL bias value */
  636. status = mxl692_memread(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
  637. if (status)
  638. goto err_finish;
  639. reg_val &= 0xC0FFFFFF;
  640. reg_val |= 0xA000000;
  641. status = mxl692_memwrite(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
  642. if (status)
  643. goto err_finish;
  644. }
  645. /* start XTAL calibration */
  646. status = mxl692_memread(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
  647. if (status)
  648. goto err_finish;
  649. reg_val |= 0x8;
  650. status = mxl692_memwrite(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
  651. if (status)
  652. goto err_finish;
  653. status = mxl692_memread(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
  654. if (status)
  655. goto err_finish;
  656. reg_val |= 0x10;
  657. status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
  658. if (status)
  659. goto err_finish;
  660. status = mxl692_memread(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
  661. if (status)
  662. goto err_finish;
  663. reg_val &= 0xFFFFEFFF;
  664. status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
  665. if (status)
  666. goto err_finish;
  667. reg_val |= 0x1000;
  668. status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
  669. if (status)
  670. goto err_finish;
  671. usleep_range(45000, 55000);
  672. err_finish:
  673. if (status)
  674. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  675. return status;
  676. }
  677. static int mxl692_powermode(struct mxl692_dev *dev,
  678. enum MXL_EAGLE_POWER_MODE_E power_mode)
  679. {
  680. int status = 0;
  681. u8 mode = power_mode;
  682. dev_dbg(&dev->i2c_client->dev, "%s\n",
  683. power_mode == MXL_EAGLE_POWER_MODE_SLEEP ? "sleep" : "active");
  684. status = mxl692_i2c_writeread(dev,
  685. MXL_EAGLE_OPCODE_DEVICE_POWERMODE_SET,
  686. &mode,
  687. sizeof(u8),
  688. NULL,
  689. 0);
  690. if (status) {
  691. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  692. return status;
  693. }
  694. dev->power_mode = power_mode;
  695. return status;
  696. }
  697. static int mxl692_init(struct dvb_frontend *fe)
  698. {
  699. struct mxl692_dev *dev = fe->demodulator_priv;
  700. struct i2c_client *client = dev->i2c_client;
  701. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  702. int status = 0;
  703. const struct firmware *firmware;
  704. struct MXL_EAGLE_DEV_XTAL_T xtal_config = {};
  705. dev_dbg(&dev->i2c_client->dev, "\n");
  706. if (dev->init_done)
  707. goto warm;
  708. dev->seqnum = 1;
  709. status = mxl692_reset(dev);
  710. if (status)
  711. goto err;
  712. usleep_range(50 * 1000, 60 * 1000); /* was 1000! */
  713. status = mxl692_config_regulators(dev, MXL_EAGLE_POWER_SUPPLY_SOURCE_DUAL);
  714. if (status)
  715. goto err;
  716. xtal_config.xtal_cap = 26;
  717. xtal_config.clk_out_div_enable = 0;
  718. xtal_config.clk_out_enable = 0;
  719. xtal_config.xtal_calibration_enable = 0;
  720. xtal_config.xtal_sharing_enable = 1;
  721. status = mxl692_config_xtal(dev, &xtal_config);
  722. if (status)
  723. goto err;
  724. status = request_firmware(&firmware, MXL692_FIRMWARE, &client->dev);
  725. if (status) {
  726. dev_dbg(&dev->i2c_client->dev, "firmware missing? %s\n",
  727. MXL692_FIRMWARE);
  728. goto err;
  729. }
  730. status = mxl692_fwdownload(dev, firmware->data, firmware->size);
  731. if (status)
  732. goto err_release_firmware;
  733. release_firmware(firmware);
  734. status = mxl692_get_versions(dev);
  735. if (status)
  736. goto err;
  737. dev->power_mode = MXL_EAGLE_POWER_MODE_SLEEP;
  738. warm:
  739. /* Config Device Power Mode */
  740. if (dev->power_mode != MXL_EAGLE_POWER_MODE_ACTIVE) {
  741. status = mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_ACTIVE);
  742. if (status)
  743. goto err;
  744. usleep_range(50 * 1000, 60 * 1000); /* was 500! */
  745. }
  746. /* Init stats here to indicate which stats are supported */
  747. c->cnr.len = 1;
  748. c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  749. c->post_bit_error.len = 1;
  750. c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  751. c->post_bit_count.len = 1;
  752. c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  753. c->block_error.len = 1;
  754. c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  755. dev->init_done = 1;
  756. return 0;
  757. err_release_firmware:
  758. release_firmware(firmware);
  759. err:
  760. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  761. return status;
  762. }
  763. static int mxl692_sleep(struct dvb_frontend *fe)
  764. {
  765. struct mxl692_dev *dev = fe->demodulator_priv;
  766. if (dev->power_mode != MXL_EAGLE_POWER_MODE_SLEEP)
  767. mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_SLEEP);
  768. return 0;
  769. }
  770. static int mxl692_set_frontend(struct dvb_frontend *fe)
  771. {
  772. struct dtv_frontend_properties *p = &fe->dtv_property_cache;
  773. struct mxl692_dev *dev = fe->demodulator_priv;
  774. int status = 0;
  775. enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
  776. struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params = {};
  777. enum MXL_EAGLE_QAM_DEMOD_ANNEX_TYPE_E qam_annex = MXL_EAGLE_QAM_DEMOD_ANNEX_B;
  778. struct MXL_EAGLE_QAM_DEMOD_PARAMS_T qam_params = {};
  779. struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T tuner_params = {};
  780. u8 op_param = 0;
  781. dev_dbg(&dev->i2c_client->dev, "\n");
  782. switch (p->modulation) {
  783. case VSB_8:
  784. demod_type = MXL_EAGLE_DEMOD_TYPE_ATSC;
  785. break;
  786. case QAM_AUTO:
  787. case QAM_64:
  788. case QAM_128:
  789. case QAM_256:
  790. demod_type = MXL_EAGLE_DEMOD_TYPE_QAM;
  791. break;
  792. default:
  793. return -EINVAL;
  794. }
  795. if (dev->current_frequency == p->frequency && dev->demod_type == demod_type) {
  796. dev_dbg(&dev->i2c_client->dev, "already set up\n");
  797. return 0;
  798. }
  799. dev->current_frequency = -1;
  800. dev->demod_type = -1;
  801. op_param = demod_type;
  802. status = mxl692_i2c_writeread(dev,
  803. MXL_EAGLE_OPCODE_DEVICE_DEMODULATOR_TYPE_SET,
  804. &op_param,
  805. sizeof(u8),
  806. NULL,
  807. 0);
  808. if (status) {
  809. dev_dbg(&dev->i2c_client->dev,
  810. "DEVICE_DEMODULATOR_TYPE_SET...FAIL err 0x%x\n", status);
  811. goto err;
  812. }
  813. usleep_range(20 * 1000, 30 * 1000); /* was 500! */
  814. mpeg_params.mpeg_parallel = 0;
  815. mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_MSB_1ST;
  816. mpeg_params.mpeg_sync_pulse_width = MXL_EAGLE_DATA_SYNC_WIDTH_BIT;
  817. mpeg_params.mpeg_valid_pol = MXL_EAGLE_CLOCK_POSITIVE;
  818. mpeg_params.mpeg_sync_pol = MXL_EAGLE_CLOCK_POSITIVE;
  819. mpeg_params.mpeg_clk_pol = MXL_EAGLE_CLOCK_NEGATIVE;
  820. mpeg_params.mpeg3wire_mode_enable = 0;
  821. mpeg_params.mpeg_clk_freq = MXL_EAGLE_MPEG_CLOCK_27MHZ;
  822. switch (demod_type) {
  823. case MXL_EAGLE_DEMOD_TYPE_ATSC:
  824. status = mxl692_i2c_writeread(dev,
  825. MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
  826. (u8 *)&mpeg_params,
  827. sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
  828. NULL,
  829. 0);
  830. if (status)
  831. goto err;
  832. break;
  833. case MXL_EAGLE_DEMOD_TYPE_QAM:
  834. if (qam_annex == MXL_EAGLE_QAM_DEMOD_ANNEX_A)
  835. mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_LSB_1ST;
  836. status = mxl692_i2c_writeread(dev,
  837. MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
  838. (u8 *)&mpeg_params,
  839. sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
  840. NULL,
  841. 0);
  842. if (status)
  843. goto err;
  844. qam_params.annex_type = qam_annex;
  845. qam_params.qam_type = MXL_EAGLE_QAM_DEMOD_AUTO;
  846. qam_params.iq_flip = MXL_EAGLE_DEMOD_IQ_AUTO;
  847. if (p->modulation == QAM_64)
  848. qam_params.symbol_rate_hz = 5057000;
  849. else
  850. qam_params.symbol_rate_hz = 5361000;
  851. qam_params.symbol_rate_256qam_hz = 5361000;
  852. status = mxl692_i2c_writeread(dev,
  853. MXL_EAGLE_OPCODE_QAM_PARAMS_SET,
  854. (u8 *)&qam_params,
  855. sizeof(struct MXL_EAGLE_QAM_DEMOD_PARAMS_T),
  856. NULL, 0);
  857. if (status)
  858. goto err;
  859. break;
  860. default:
  861. break;
  862. }
  863. usleep_range(20 * 1000, 30 * 1000); /* was 500! */
  864. tuner_params.freq_hz = p->frequency;
  865. tuner_params.bandwidth = MXL_EAGLE_TUNER_BW_6MHZ;
  866. tuner_params.tune_mode = MXL_EAGLE_TUNER_CHANNEL_TUNE_MODE_VIEW;
  867. dev_dbg(&dev->i2c_client->dev, " Tuning Freq: %d %s\n", tuner_params.freq_hz,
  868. demod_type == MXL_EAGLE_DEMOD_TYPE_ATSC ? "ATSC" : "QAM");
  869. status = mxl692_i2c_writeread(dev,
  870. MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET,
  871. (u8 *)&tuner_params,
  872. sizeof(struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T),
  873. NULL,
  874. 0);
  875. if (status)
  876. goto err;
  877. usleep_range(20 * 1000, 30 * 1000); /* was 500! */
  878. switch (demod_type) {
  879. case MXL_EAGLE_DEMOD_TYPE_ATSC:
  880. status = mxl692_i2c_writeread(dev,
  881. MXL_EAGLE_OPCODE_ATSC_INIT_SET,
  882. NULL, 0, NULL, 0);
  883. if (status)
  884. goto err;
  885. break;
  886. case MXL_EAGLE_DEMOD_TYPE_QAM:
  887. status = mxl692_i2c_writeread(dev,
  888. MXL_EAGLE_OPCODE_QAM_RESTART_SET,
  889. NULL, 0, NULL, 0);
  890. if (status)
  891. goto err;
  892. break;
  893. default:
  894. break;
  895. }
  896. dev->demod_type = demod_type;
  897. dev->current_frequency = p->frequency;
  898. return 0;
  899. err:
  900. dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
  901. return status;
  902. }
  903. static int mxl692_get_frontend(struct dvb_frontend *fe,
  904. struct dtv_frontend_properties *p)
  905. {
  906. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  907. p->modulation = c->modulation;
  908. p->frequency = c->frequency;
  909. return 0;
  910. }
  911. static int mxl692_read_snr(struct dvb_frontend *fe, u16 *snr)
  912. {
  913. struct mxl692_dev *dev = fe->demodulator_priv;
  914. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  915. u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  916. struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *atsc_status;
  917. struct MXL_EAGLE_QAM_DEMOD_STATUS_T *qam_status;
  918. enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
  919. int mxl_status = 0;
  920. *snr = 0;
  921. dev_dbg(&dev->i2c_client->dev, "\n");
  922. atsc_status = (struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *)&rx_buf;
  923. qam_status = (struct MXL_EAGLE_QAM_DEMOD_STATUS_T *)&rx_buf;
  924. switch (demod_type) {
  925. case MXL_EAGLE_DEMOD_TYPE_ATSC:
  926. mxl_status = mxl692_i2c_writeread(dev,
  927. MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
  928. NULL,
  929. 0,
  930. rx_buf,
  931. sizeof(struct MXL_EAGLE_ATSC_DEMOD_STATUS_T));
  932. if (!mxl_status) {
  933. *snr = (u16)(atsc_status->snr_db_tenths / 10);
  934. c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
  935. c->cnr.stat[0].svalue = *snr;
  936. }
  937. break;
  938. case MXL_EAGLE_DEMOD_TYPE_QAM:
  939. mxl_status = mxl692_i2c_writeread(dev,
  940. MXL_EAGLE_OPCODE_QAM_STATUS_GET,
  941. NULL,
  942. 0,
  943. rx_buf,
  944. sizeof(struct MXL_EAGLE_QAM_DEMOD_STATUS_T));
  945. if (!mxl_status)
  946. *snr = (u16)(qam_status->snr_db_tenths / 10);
  947. break;
  948. case MXL_EAGLE_DEMOD_TYPE_OOB:
  949. default:
  950. break;
  951. }
  952. if (mxl_status)
  953. dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
  954. return mxl_status;
  955. }
  956. static int mxl692_read_ber_ucb(struct dvb_frontend *fe)
  957. {
  958. struct mxl692_dev *dev = fe->demodulator_priv;
  959. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  960. u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  961. struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T *atsc_errors;
  962. enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
  963. int mxl_status = 0;
  964. u32 utmp;
  965. dev_dbg(&dev->i2c_client->dev, "\n");
  966. atsc_errors = (struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T *)&rx_buf;
  967. switch (demod_type) {
  968. case MXL_EAGLE_DEMOD_TYPE_ATSC:
  969. mxl_status = mxl692_i2c_writeread(dev,
  970. MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET,
  971. NULL,
  972. 0,
  973. rx_buf,
  974. sizeof(struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T));
  975. if (!mxl_status) {
  976. if (atsc_errors->error_packets == 0)
  977. utmp = 0;
  978. else
  979. utmp = ((atsc_errors->error_bytes / atsc_errors->error_packets) *
  980. atsc_errors->total_packets);
  981. /* ber */
  982. c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
  983. c->post_bit_error.stat[0].uvalue += atsc_errors->error_bytes;
  984. c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
  985. c->post_bit_count.stat[0].uvalue += utmp;
  986. /* ucb */
  987. c->block_error.stat[0].scale = FE_SCALE_COUNTER;
  988. c->block_error.stat[0].uvalue += atsc_errors->error_packets;
  989. dev_dbg(&dev->i2c_client->dev, "%llu %llu\n",
  990. c->post_bit_count.stat[0].uvalue, c->block_error.stat[0].uvalue);
  991. }
  992. break;
  993. case MXL_EAGLE_DEMOD_TYPE_QAM:
  994. case MXL_EAGLE_DEMOD_TYPE_OOB:
  995. default:
  996. break;
  997. }
  998. if (mxl_status)
  999. dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
  1000. return mxl_status;
  1001. }
  1002. static int mxl692_read_status(struct dvb_frontend *fe,
  1003. enum fe_status *status)
  1004. {
  1005. struct mxl692_dev *dev = fe->demodulator_priv;
  1006. struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1007. u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
  1008. struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *atsc_status;
  1009. struct MXL_EAGLE_QAM_DEMOD_STATUS_T *qam_status;
  1010. enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
  1011. int mxl_status = 0;
  1012. *status = 0;
  1013. dev_dbg(&dev->i2c_client->dev, "\n");
  1014. atsc_status = (struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *)&rx_buf;
  1015. qam_status = (struct MXL_EAGLE_QAM_DEMOD_STATUS_T *)&rx_buf;
  1016. switch (demod_type) {
  1017. case MXL_EAGLE_DEMOD_TYPE_ATSC:
  1018. mxl_status = mxl692_i2c_writeread(dev,
  1019. MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
  1020. NULL,
  1021. 0,
  1022. rx_buf,
  1023. sizeof(struct MXL_EAGLE_ATSC_DEMOD_STATUS_T));
  1024. if (!mxl_status && atsc_status->atsc_lock) {
  1025. *status |= FE_HAS_SIGNAL;
  1026. *status |= FE_HAS_CARRIER;
  1027. *status |= FE_HAS_VITERBI;
  1028. *status |= FE_HAS_SYNC;
  1029. *status |= FE_HAS_LOCK;
  1030. c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
  1031. c->cnr.stat[0].svalue = atsc_status->snr_db_tenths / 10;
  1032. }
  1033. break;
  1034. case MXL_EAGLE_DEMOD_TYPE_QAM:
  1035. mxl_status = mxl692_i2c_writeread(dev,
  1036. MXL_EAGLE_OPCODE_QAM_STATUS_GET,
  1037. NULL,
  1038. 0,
  1039. rx_buf,
  1040. sizeof(struct MXL_EAGLE_QAM_DEMOD_STATUS_T));
  1041. if (!mxl_status && qam_status->qam_locked) {
  1042. *status |= FE_HAS_SIGNAL;
  1043. *status |= FE_HAS_CARRIER;
  1044. *status |= FE_HAS_VITERBI;
  1045. *status |= FE_HAS_SYNC;
  1046. *status |= FE_HAS_LOCK;
  1047. c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
  1048. c->cnr.stat[0].svalue = qam_status->snr_db_tenths / 10;
  1049. }
  1050. break;
  1051. case MXL_EAGLE_DEMOD_TYPE_OOB:
  1052. default:
  1053. break;
  1054. }
  1055. if ((*status & FE_HAS_LOCK) == 0) {
  1056. /* No lock, reset all statistics */
  1057. c->cnr.len = 1;
  1058. c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  1059. c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  1060. c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  1061. c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  1062. return 0;
  1063. }
  1064. if (mxl_status)
  1065. dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
  1066. else
  1067. mxl_status = mxl692_read_ber_ucb(fe);
  1068. return mxl_status;
  1069. }
  1070. static const struct dvb_frontend_ops mxl692_ops = {
  1071. .delsys = { SYS_ATSC },
  1072. .info = {
  1073. .name = "MaxLinear MxL692 VSB tuner-demodulator",
  1074. .frequency_min_hz = 54000000,
  1075. .frequency_max_hz = 858000000,
  1076. .frequency_stepsize_hz = 62500,
  1077. .caps = FE_CAN_8VSB
  1078. },
  1079. .init = mxl692_init,
  1080. .sleep = mxl692_sleep,
  1081. .set_frontend = mxl692_set_frontend,
  1082. .get_frontend = mxl692_get_frontend,
  1083. .read_status = mxl692_read_status,
  1084. .read_snr = mxl692_read_snr,
  1085. };
  1086. static int mxl692_probe(struct i2c_client *client,
  1087. const struct i2c_device_id *id)
  1088. {
  1089. struct mxl692_config *config = client->dev.platform_data;
  1090. struct mxl692_dev *dev;
  1091. int ret = 0;
  1092. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  1093. if (!dev) {
  1094. ret = -ENOMEM;
  1095. dev_dbg(&client->dev, "kzalloc() failed\n");
  1096. goto err;
  1097. }
  1098. memcpy(&dev->fe.ops, &mxl692_ops, sizeof(struct dvb_frontend_ops));
  1099. dev->fe.demodulator_priv = dev;
  1100. dev->i2c_client = client;
  1101. *config->fe = &dev->fe;
  1102. mutex_init(&dev->i2c_lock);
  1103. i2c_set_clientdata(client, dev);
  1104. dev_info(&client->dev, "MaxLinear mxl692 successfully attached\n");
  1105. return 0;
  1106. err:
  1107. dev_dbg(&client->dev, "failed %d\n", ret);
  1108. return -ENODEV;
  1109. }
  1110. static void mxl692_remove(struct i2c_client *client)
  1111. {
  1112. struct mxl692_dev *dev = i2c_get_clientdata(client);
  1113. dev->fe.demodulator_priv = NULL;
  1114. i2c_set_clientdata(client, NULL);
  1115. kfree(dev);
  1116. }
  1117. static const struct i2c_device_id mxl692_id_table[] = {
  1118. {"mxl692", 0},
  1119. {}
  1120. };
  1121. MODULE_DEVICE_TABLE(i2c, mxl692_id_table);
  1122. static struct i2c_driver mxl692_driver = {
  1123. .driver = {
  1124. .name = "mxl692",
  1125. },
  1126. .probe = mxl692_probe,
  1127. .remove = mxl692_remove,
  1128. .id_table = mxl692_id_table,
  1129. };
  1130. module_i2c_driver(mxl692_driver);
  1131. MODULE_AUTHOR("Brad Love <[email protected]>");
  1132. MODULE_DESCRIPTION("MaxLinear MxL692 demodulator/tuner driver");
  1133. MODULE_FIRMWARE(MXL692_FIRMWARE);
  1134. MODULE_LICENSE("GPL");