1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Abilis Systems Single DVB-T Receiver
4 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
5 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
8 #include <linux/kernel.h>
10 #include "as10x_cmd.h"
13 * as10x_cmd_turn_on - send turn on command to AS10x
14 * @adap: pointer to AS10x bus adapter
16 * Return 0 when no error, < 0 in case of error.
18 int as10x_cmd_turn_on(struct as10x_bus_adapter_t
*adap
)
20 int error
= AS10X_CMD_ERROR
;
21 struct as10x_cmd_t
*pcmd
, *prsp
;
27 as10x_cmd_build(pcmd
, (++adap
->cmd_xid
),
28 sizeof(pcmd
->body
.turn_on
.req
));
31 pcmd
->body
.turn_on
.req
.proc_id
= cpu_to_le16(CONTROL_PROC_TURNON
);
34 if (adap
->ops
->xfer_cmd
) {
35 error
= adap
->ops
->xfer_cmd(adap
, (uint8_t *) pcmd
,
36 sizeof(pcmd
->body
.turn_on
.req
) +
39 sizeof(prsp
->body
.turn_on
.rsp
) +
47 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_TURNON_RSP
);
54 * as10x_cmd_turn_off - send turn off command to AS10x
55 * @adap: pointer to AS10x bus adapter
57 * Return 0 on success or negative value in case of error.
59 int as10x_cmd_turn_off(struct as10x_bus_adapter_t
*adap
)
61 int error
= AS10X_CMD_ERROR
;
62 struct as10x_cmd_t
*pcmd
, *prsp
;
68 as10x_cmd_build(pcmd
, (++adap
->cmd_xid
),
69 sizeof(pcmd
->body
.turn_off
.req
));
72 pcmd
->body
.turn_off
.req
.proc_id
= cpu_to_le16(CONTROL_PROC_TURNOFF
);
75 if (adap
->ops
->xfer_cmd
) {
76 error
= adap
->ops
->xfer_cmd(
77 adap
, (uint8_t *) pcmd
,
78 sizeof(pcmd
->body
.turn_off
.req
) + HEADER_SIZE
,
80 sizeof(prsp
->body
.turn_off
.rsp
) + HEADER_SIZE
);
87 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_TURNOFF_RSP
);
94 * as10x_cmd_set_tune - send set tune command to AS10x
95 * @adap: pointer to AS10x bus adapter
96 * @ptune: tune parameters
98 * Return 0 on success or negative value in case of error.
100 int as10x_cmd_set_tune(struct as10x_bus_adapter_t
*adap
,
101 struct as10x_tune_args
*ptune
)
103 int error
= AS10X_CMD_ERROR
;
104 struct as10x_cmd_t
*preq
, *prsp
;
109 /* prepare command */
110 as10x_cmd_build(preq
, (++adap
->cmd_xid
),
111 sizeof(preq
->body
.set_tune
.req
));
114 preq
->body
.set_tune
.req
.proc_id
= cpu_to_le16(CONTROL_PROC_SETTUNE
);
115 preq
->body
.set_tune
.req
.args
.freq
= (__force __u32
)cpu_to_le32(ptune
->freq
);
116 preq
->body
.set_tune
.req
.args
.bandwidth
= ptune
->bandwidth
;
117 preq
->body
.set_tune
.req
.args
.hier_select
= ptune
->hier_select
;
118 preq
->body
.set_tune
.req
.args
.modulation
= ptune
->modulation
;
119 preq
->body
.set_tune
.req
.args
.hierarchy
= ptune
->hierarchy
;
120 preq
->body
.set_tune
.req
.args
.interleaving_mode
=
121 ptune
->interleaving_mode
;
122 preq
->body
.set_tune
.req
.args
.code_rate
= ptune
->code_rate
;
123 preq
->body
.set_tune
.req
.args
.guard_interval
= ptune
->guard_interval
;
124 preq
->body
.set_tune
.req
.args
.transmission_mode
=
125 ptune
->transmission_mode
;
128 if (adap
->ops
->xfer_cmd
) {
129 error
= adap
->ops
->xfer_cmd(adap
,
131 sizeof(preq
->body
.set_tune
.req
)
134 sizeof(prsp
->body
.set_tune
.rsp
)
142 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_SETTUNE_RSP
);
149 * as10x_cmd_get_tune_status - send get tune status command to AS10x
150 * @adap: pointer to AS10x bus adapter
151 * @pstatus: pointer to updated status structure of the current tune
153 * Return 0 on success or negative value in case of error.
155 int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t
*adap
,
156 struct as10x_tune_status
*pstatus
)
158 int error
= AS10X_CMD_ERROR
;
159 struct as10x_cmd_t
*preq
, *prsp
;
164 /* prepare command */
165 as10x_cmd_build(preq
, (++adap
->cmd_xid
),
166 sizeof(preq
->body
.get_tune_status
.req
));
169 preq
->body
.get_tune_status
.req
.proc_id
=
170 cpu_to_le16(CONTROL_PROC_GETTUNESTAT
);
173 if (adap
->ops
->xfer_cmd
) {
174 error
= adap
->ops
->xfer_cmd(
177 sizeof(preq
->body
.get_tune_status
.req
) + HEADER_SIZE
,
179 sizeof(prsp
->body
.get_tune_status
.rsp
) + HEADER_SIZE
);
186 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_GETTUNESTAT_RSP
);
190 /* Response OK -> get response data */
191 pstatus
->tune_state
= prsp
->body
.get_tune_status
.rsp
.sts
.tune_state
;
192 pstatus
->signal_strength
=
193 le16_to_cpu((__force __le16
)prsp
->body
.get_tune_status
.rsp
.sts
.signal_strength
);
194 pstatus
->PER
= le16_to_cpu((__force __le16
)prsp
->body
.get_tune_status
.rsp
.sts
.PER
);
195 pstatus
->BER
= le16_to_cpu((__force __le16
)prsp
->body
.get_tune_status
.rsp
.sts
.BER
);
202 * as10x_cmd_get_tps - send get TPS command to AS10x
203 * @adap: pointer to AS10x handle
204 * @ptps: pointer to TPS parameters structure
206 * Return 0 on success or negative value in case of error.
208 int as10x_cmd_get_tps(struct as10x_bus_adapter_t
*adap
, struct as10x_tps
*ptps
)
210 int error
= AS10X_CMD_ERROR
;
211 struct as10x_cmd_t
*pcmd
, *prsp
;
216 /* prepare command */
217 as10x_cmd_build(pcmd
, (++adap
->cmd_xid
),
218 sizeof(pcmd
->body
.get_tps
.req
));
221 pcmd
->body
.get_tune_status
.req
.proc_id
=
222 cpu_to_le16(CONTROL_PROC_GETTPS
);
225 if (adap
->ops
->xfer_cmd
) {
226 error
= adap
->ops
->xfer_cmd(adap
,
228 sizeof(pcmd
->body
.get_tps
.req
) +
231 sizeof(prsp
->body
.get_tps
.rsp
) +
239 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_GETTPS_RSP
);
243 /* Response OK -> get response data */
244 ptps
->modulation
= prsp
->body
.get_tps
.rsp
.tps
.modulation
;
245 ptps
->hierarchy
= prsp
->body
.get_tps
.rsp
.tps
.hierarchy
;
246 ptps
->interleaving_mode
= prsp
->body
.get_tps
.rsp
.tps
.interleaving_mode
;
247 ptps
->code_rate_HP
= prsp
->body
.get_tps
.rsp
.tps
.code_rate_HP
;
248 ptps
->code_rate_LP
= prsp
->body
.get_tps
.rsp
.tps
.code_rate_LP
;
249 ptps
->guard_interval
= prsp
->body
.get_tps
.rsp
.tps
.guard_interval
;
250 ptps
->transmission_mode
= prsp
->body
.get_tps
.rsp
.tps
.transmission_mode
;
251 ptps
->DVBH_mask_HP
= prsp
->body
.get_tps
.rsp
.tps
.DVBH_mask_HP
;
252 ptps
->DVBH_mask_LP
= prsp
->body
.get_tps
.rsp
.tps
.DVBH_mask_LP
;
253 ptps
->cell_ID
= le16_to_cpu((__force __le16
)prsp
->body
.get_tps
.rsp
.tps
.cell_ID
);
260 * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
261 * @adap: pointer to AS10x bus adapter
262 * @pdemod_stats: pointer to demod stats parameters structure
264 * Return 0 on success or negative value in case of error.
266 int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t
*adap
,
267 struct as10x_demod_stats
*pdemod_stats
)
269 int error
= AS10X_CMD_ERROR
;
270 struct as10x_cmd_t
*pcmd
, *prsp
;
275 /* prepare command */
276 as10x_cmd_build(pcmd
, (++adap
->cmd_xid
),
277 sizeof(pcmd
->body
.get_demod_stats
.req
));
280 pcmd
->body
.get_demod_stats
.req
.proc_id
=
281 cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS
);
284 if (adap
->ops
->xfer_cmd
) {
285 error
= adap
->ops
->xfer_cmd(adap
,
287 sizeof(pcmd
->body
.get_demod_stats
.req
)
290 sizeof(prsp
->body
.get_demod_stats
.rsp
)
298 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_GET_DEMOD_STATS_RSP
);
302 /* Response OK -> get response data */
303 pdemod_stats
->frame_count
=
304 le32_to_cpu((__force __le32
)prsp
->body
.get_demod_stats
.rsp
.stats
.frame_count
);
305 pdemod_stats
->bad_frame_count
=
306 le32_to_cpu((__force __le32
)prsp
->body
.get_demod_stats
.rsp
.stats
.bad_frame_count
);
307 pdemod_stats
->bytes_fixed_by_rs
=
308 le32_to_cpu((__force __le32
)prsp
->body
.get_demod_stats
.rsp
.stats
.bytes_fixed_by_rs
);
310 le16_to_cpu((__force __le16
)prsp
->body
.get_demod_stats
.rsp
.stats
.mer
);
311 pdemod_stats
->has_started
=
312 prsp
->body
.get_demod_stats
.rsp
.stats
.has_started
;
319 * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
320 * @adap: pointer to AS10x bus adapter
321 * @is_ready: pointer to value indicating when impulse
322 * response data is ready
324 * Return 0 on success or negative value in case of error.
326 int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t
*adap
,
329 int error
= AS10X_CMD_ERROR
;
330 struct as10x_cmd_t
*pcmd
, *prsp
;
335 /* prepare command */
336 as10x_cmd_build(pcmd
, (++adap
->cmd_xid
),
337 sizeof(pcmd
->body
.get_impulse_rsp
.req
));
340 pcmd
->body
.get_impulse_rsp
.req
.proc_id
=
341 cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP
);
344 if (adap
->ops
->xfer_cmd
) {
345 error
= adap
->ops
->xfer_cmd(adap
,
347 sizeof(pcmd
->body
.get_impulse_rsp
.req
)
350 sizeof(prsp
->body
.get_impulse_rsp
.rsp
)
358 error
= as10x_rsp_parse(prsp
, CONTROL_PROC_GET_IMPULSE_RESP_RSP
);
362 /* Response OK -> get response data */
363 *is_ready
= prsp
->body
.get_impulse_rsp
.rsp
.is_ready
;
370 * as10x_cmd_build - build AS10x command header
371 * @pcmd: pointer to AS10x command buffer
372 * @xid: sequence id of the command
373 * @cmd_len: length of the command
375 void as10x_cmd_build(struct as10x_cmd_t
*pcmd
,
376 uint16_t xid
, uint16_t cmd_len
)
378 pcmd
->header
.req_id
= cpu_to_le16(xid
);
379 pcmd
->header
.prog
= cpu_to_le16(SERVICE_PROG_ID
);
380 pcmd
->header
.version
= cpu_to_le16(SERVICE_PROG_VERSION
);
381 pcmd
->header
.data_len
= cpu_to_le16(cmd_len
);
385 * as10x_rsp_parse - Parse command response
386 * @prsp: pointer to AS10x command buffer
387 * @proc_id: id of the command
389 * Return 0 on success or negative value in case of error.
391 int as10x_rsp_parse(struct as10x_cmd_t
*prsp
, uint16_t proc_id
)
395 /* extract command error code */
396 error
= prsp
->body
.common
.rsp
.error
;
399 (le16_to_cpu(prsp
->body
.common
.rsp
.proc_id
) == proc_id
)) {
403 return AS10X_CMD_ERROR
;