mxl692.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  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 <brad@nextdimension.cc>
  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. {
  1088. struct mxl692_config *config = client->dev.platform_data;
  1089. struct mxl692_dev *dev;
  1090. int ret = 0;
  1091. dev = kzalloc_obj(*dev);
  1092. if (!dev) {
  1093. ret = -ENOMEM;
  1094. dev_dbg(&client->dev, "kzalloc() failed\n");
  1095. goto err;
  1096. }
  1097. memcpy(&dev->fe.ops, &mxl692_ops, sizeof(struct dvb_frontend_ops));
  1098. dev->fe.demodulator_priv = dev;
  1099. dev->i2c_client = client;
  1100. *config->fe = &dev->fe;
  1101. mutex_init(&dev->i2c_lock);
  1102. i2c_set_clientdata(client, dev);
  1103. dev_info(&client->dev, "MaxLinear mxl692 successfully attached\n");
  1104. return 0;
  1105. err:
  1106. dev_dbg(&client->dev, "failed %d\n", ret);
  1107. return -ENODEV;
  1108. }
  1109. static void mxl692_remove(struct i2c_client *client)
  1110. {
  1111. struct mxl692_dev *dev = i2c_get_clientdata(client);
  1112. dev->fe.demodulator_priv = NULL;
  1113. i2c_set_clientdata(client, NULL);
  1114. kfree(dev);
  1115. }
  1116. static const struct i2c_device_id mxl692_id_table[] = {
  1117. { "mxl692" },
  1118. {}
  1119. };
  1120. MODULE_DEVICE_TABLE(i2c, mxl692_id_table);
  1121. static struct i2c_driver mxl692_driver = {
  1122. .driver = {
  1123. .name = "mxl692",
  1124. },
  1125. .probe = mxl692_probe,
  1126. .remove = mxl692_remove,
  1127. .id_table = mxl692_id_table,
  1128. };
  1129. module_i2c_driver(mxl692_driver);
  1130. MODULE_AUTHOR("Brad Love <brad@nextdimension.cc>");
  1131. MODULE_DESCRIPTION("MaxLinear MxL692 demodulator/tuner driver");
  1132. MODULE_FIRMWARE(MXL692_FIRMWARE);
  1133. MODULE_LICENSE("GPL");