as10x_cmd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * Abilis Systems Single DVB-T Receiver
  3. * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
  4. * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2, or (at your option)
  9. * any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/kernel.h>
  17. #include "as102_drv.h"
  18. #include "as10x_cmd.h"
  19. /**
  20. * as10x_cmd_turn_on - send turn on command to AS10x
  21. * @adap: pointer to AS10x bus adapter
  22. *
  23. * Return 0 when no error, < 0 in case of error.
  24. */
  25. int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
  26. {
  27. int error = AS10X_CMD_ERROR;
  28. struct as10x_cmd_t *pcmd, *prsp;
  29. pcmd = adap->cmd;
  30. prsp = adap->rsp;
  31. /* prepare command */
  32. as10x_cmd_build(pcmd, (++adap->cmd_xid),
  33. sizeof(pcmd->body.turn_on.req));
  34. /* fill command */
  35. pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
  36. /* send command */
  37. if (adap->ops->xfer_cmd) {
  38. error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
  39. sizeof(pcmd->body.turn_on.req) +
  40. HEADER_SIZE,
  41. (uint8_t *) prsp,
  42. sizeof(prsp->body.turn_on.rsp) +
  43. HEADER_SIZE);
  44. }
  45. if (error < 0)
  46. goto out;
  47. /* parse response */
  48. error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
  49. out:
  50. return error;
  51. }
  52. /**
  53. * as10x_cmd_turn_off - send turn off command to AS10x
  54. * @adap: pointer to AS10x bus adapter
  55. *
  56. * Return 0 on success or negative value in case of error.
  57. */
  58. int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
  59. {
  60. int error = AS10X_CMD_ERROR;
  61. struct as10x_cmd_t *pcmd, *prsp;
  62. pcmd = adap->cmd;
  63. prsp = adap->rsp;
  64. /* prepare command */
  65. as10x_cmd_build(pcmd, (++adap->cmd_xid),
  66. sizeof(pcmd->body.turn_off.req));
  67. /* fill command */
  68. pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
  69. /* send command */
  70. if (adap->ops->xfer_cmd) {
  71. error = adap->ops->xfer_cmd(
  72. adap, (uint8_t *) pcmd,
  73. sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
  74. (uint8_t *) prsp,
  75. sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
  76. }
  77. if (error < 0)
  78. goto out;
  79. /* parse response */
  80. error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
  81. out:
  82. return error;
  83. }
  84. /**
  85. * as10x_cmd_set_tune - send set tune command to AS10x
  86. * @adap: pointer to AS10x bus adapter
  87. * @ptune: tune parameters
  88. *
  89. * Return 0 on success or negative value in case of error.
  90. */
  91. int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
  92. struct as10x_tune_args *ptune)
  93. {
  94. int error = AS10X_CMD_ERROR;
  95. struct as10x_cmd_t *preq, *prsp;
  96. preq = adap->cmd;
  97. prsp = adap->rsp;
  98. /* prepare command */
  99. as10x_cmd_build(preq, (++adap->cmd_xid),
  100. sizeof(preq->body.set_tune.req));
  101. /* fill command */
  102. preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
  103. preq->body.set_tune.req.args.freq = (__force __u32)cpu_to_le32(ptune->freq);
  104. preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
  105. preq->body.set_tune.req.args.hier_select = ptune->hier_select;
  106. preq->body.set_tune.req.args.modulation = ptune->modulation;
  107. preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
  108. preq->body.set_tune.req.args.interleaving_mode =
  109. ptune->interleaving_mode;
  110. preq->body.set_tune.req.args.code_rate = ptune->code_rate;
  111. preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
  112. preq->body.set_tune.req.args.transmission_mode =
  113. ptune->transmission_mode;
  114. /* send command */
  115. if (adap->ops->xfer_cmd) {
  116. error = adap->ops->xfer_cmd(adap,
  117. (uint8_t *) preq,
  118. sizeof(preq->body.set_tune.req)
  119. + HEADER_SIZE,
  120. (uint8_t *) prsp,
  121. sizeof(prsp->body.set_tune.rsp)
  122. + HEADER_SIZE);
  123. }
  124. if (error < 0)
  125. goto out;
  126. /* parse response */
  127. error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
  128. out:
  129. return error;
  130. }
  131. /**
  132. * as10x_cmd_get_tune_status - send get tune status command to AS10x
  133. * @adap: pointer to AS10x bus adapter
  134. * @pstatus: pointer to updated status structure of the current tune
  135. *
  136. * Return 0 on success or negative value in case of error.
  137. */
  138. int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
  139. struct as10x_tune_status *pstatus)
  140. {
  141. int error = AS10X_CMD_ERROR;
  142. struct as10x_cmd_t *preq, *prsp;
  143. preq = adap->cmd;
  144. prsp = adap->rsp;
  145. /* prepare command */
  146. as10x_cmd_build(preq, (++adap->cmd_xid),
  147. sizeof(preq->body.get_tune_status.req));
  148. /* fill command */
  149. preq->body.get_tune_status.req.proc_id =
  150. cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
  151. /* send command */
  152. if (adap->ops->xfer_cmd) {
  153. error = adap->ops->xfer_cmd(
  154. adap,
  155. (uint8_t *) preq,
  156. sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
  157. (uint8_t *) prsp,
  158. sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
  159. }
  160. if (error < 0)
  161. goto out;
  162. /* parse response */
  163. error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
  164. if (error < 0)
  165. goto out;
  166. /* Response OK -> get response data */
  167. pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
  168. pstatus->signal_strength =
  169. le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.signal_strength);
  170. pstatus->PER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.PER);
  171. pstatus->BER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.BER);
  172. out:
  173. return error;
  174. }
  175. /**
  176. * as10x_cmd_get_tps - send get TPS command to AS10x
  177. * @adap: pointer to AS10x handle
  178. * @ptps: pointer to TPS parameters structure
  179. *
  180. * Return 0 on success or negative value in case of error.
  181. */
  182. int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
  183. {
  184. int error = AS10X_CMD_ERROR;
  185. struct as10x_cmd_t *pcmd, *prsp;
  186. pcmd = adap->cmd;
  187. prsp = adap->rsp;
  188. /* prepare command */
  189. as10x_cmd_build(pcmd, (++adap->cmd_xid),
  190. sizeof(pcmd->body.get_tps.req));
  191. /* fill command */
  192. pcmd->body.get_tune_status.req.proc_id =
  193. cpu_to_le16(CONTROL_PROC_GETTPS);
  194. /* send command */
  195. if (adap->ops->xfer_cmd) {
  196. error = adap->ops->xfer_cmd(adap,
  197. (uint8_t *) pcmd,
  198. sizeof(pcmd->body.get_tps.req) +
  199. HEADER_SIZE,
  200. (uint8_t *) prsp,
  201. sizeof(prsp->body.get_tps.rsp) +
  202. HEADER_SIZE);
  203. }
  204. if (error < 0)
  205. goto out;
  206. /* parse response */
  207. error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
  208. if (error < 0)
  209. goto out;
  210. /* Response OK -> get response data */
  211. ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
  212. ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
  213. ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
  214. ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
  215. ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
  216. ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
  217. ptps->transmission_mode = prsp->body.get_tps.rsp.tps.transmission_mode;
  218. ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
  219. ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
  220. ptps->cell_ID = le16_to_cpu((__force __le16)prsp->body.get_tps.rsp.tps.cell_ID);
  221. out:
  222. return error;
  223. }
  224. /**
  225. * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
  226. * @adap: pointer to AS10x bus adapter
  227. * @pdemod_stats: pointer to demod stats parameters structure
  228. *
  229. * Return 0 on success or negative value in case of error.
  230. */
  231. int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
  232. struct as10x_demod_stats *pdemod_stats)
  233. {
  234. int error = AS10X_CMD_ERROR;
  235. struct as10x_cmd_t *pcmd, *prsp;
  236. pcmd = adap->cmd;
  237. prsp = adap->rsp;
  238. /* prepare command */
  239. as10x_cmd_build(pcmd, (++adap->cmd_xid),
  240. sizeof(pcmd->body.get_demod_stats.req));
  241. /* fill command */
  242. pcmd->body.get_demod_stats.req.proc_id =
  243. cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
  244. /* send command */
  245. if (adap->ops->xfer_cmd) {
  246. error = adap->ops->xfer_cmd(adap,
  247. (uint8_t *) pcmd,
  248. sizeof(pcmd->body.get_demod_stats.req)
  249. + HEADER_SIZE,
  250. (uint8_t *) prsp,
  251. sizeof(prsp->body.get_demod_stats.rsp)
  252. + HEADER_SIZE);
  253. }
  254. if (error < 0)
  255. goto out;
  256. /* parse response */
  257. error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
  258. if (error < 0)
  259. goto out;
  260. /* Response OK -> get response data */
  261. pdemod_stats->frame_count =
  262. le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.frame_count);
  263. pdemod_stats->bad_frame_count =
  264. le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
  265. pdemod_stats->bytes_fixed_by_rs =
  266. le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
  267. pdemod_stats->mer =
  268. le16_to_cpu((__force __le16)prsp->body.get_demod_stats.rsp.stats.mer);
  269. pdemod_stats->has_started =
  270. prsp->body.get_demod_stats.rsp.stats.has_started;
  271. out:
  272. return error;
  273. }
  274. /**
  275. * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
  276. * @adap: pointer to AS10x bus adapter
  277. * @is_ready: pointer to value indicating when impulse
  278. * response data is ready
  279. *
  280. * Return 0 on success or negative value in case of error.
  281. */
  282. int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
  283. uint8_t *is_ready)
  284. {
  285. int error = AS10X_CMD_ERROR;
  286. struct as10x_cmd_t *pcmd, *prsp;
  287. pcmd = adap->cmd;
  288. prsp = adap->rsp;
  289. /* prepare command */
  290. as10x_cmd_build(pcmd, (++adap->cmd_xid),
  291. sizeof(pcmd->body.get_impulse_rsp.req));
  292. /* fill command */
  293. pcmd->body.get_impulse_rsp.req.proc_id =
  294. cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
  295. /* send command */
  296. if (adap->ops->xfer_cmd) {
  297. error = adap->ops->xfer_cmd(adap,
  298. (uint8_t *) pcmd,
  299. sizeof(pcmd->body.get_impulse_rsp.req)
  300. + HEADER_SIZE,
  301. (uint8_t *) prsp,
  302. sizeof(prsp->body.get_impulse_rsp.rsp)
  303. + HEADER_SIZE);
  304. }
  305. if (error < 0)
  306. goto out;
  307. /* parse response */
  308. error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
  309. if (error < 0)
  310. goto out;
  311. /* Response OK -> get response data */
  312. *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
  313. out:
  314. return error;
  315. }
  316. /**
  317. * as10x_cmd_build - build AS10x command header
  318. * @pcmd: pointer to AS10x command buffer
  319. * @xid: sequence id of the command
  320. * @cmd_len: length of the command
  321. */
  322. void as10x_cmd_build(struct as10x_cmd_t *pcmd,
  323. uint16_t xid, uint16_t cmd_len)
  324. {
  325. pcmd->header.req_id = cpu_to_le16(xid);
  326. pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
  327. pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
  328. pcmd->header.data_len = cpu_to_le16(cmd_len);
  329. }
  330. /**
  331. * as10x_rsp_parse - Parse command response
  332. * @prsp: pointer to AS10x command buffer
  333. * @proc_id: id of the command
  334. *
  335. * Return 0 on success or negative value in case of error.
  336. */
  337. int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
  338. {
  339. int error;
  340. /* extract command error code */
  341. error = prsp->body.common.rsp.error;
  342. if ((error == 0) &&
  343. (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
  344. return 0;
  345. }
  346. return AS10X_CMD_ERROR;
  347. }