]> Pileus Git - ~andy/linux/blob - drivers/staging/media/as102/as10x_cmd.c
Merge remote-tracking branch 'regulator/fix/dbx500' into regulator-linus
[~andy/linux] / drivers / staging / media / as102 / as10x_cmd.c
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  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <linux/kernel.h>
22 #include "as102_drv.h"
23 #include "as10x_types.h"
24 #include "as10x_cmd.h"
25
26 /**
27  * as10x_cmd_turn_on - send turn on command to AS10x
28  * @adap:   pointer to AS10x bus adapter
29  *
30  * Return 0 when no error, < 0 in case of error.
31  */
32 int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
33 {
34         int error = AS10X_CMD_ERROR;
35         struct as10x_cmd_t *pcmd, *prsp;
36
37         ENTER();
38
39         pcmd = adap->cmd;
40         prsp = adap->rsp;
41
42         /* prepare command */
43         as10x_cmd_build(pcmd, (++adap->cmd_xid),
44                         sizeof(pcmd->body.turn_on.req));
45
46         /* fill command */
47         pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
48
49         /* send command */
50         if (adap->ops->xfer_cmd) {
51                 error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
52                                             sizeof(pcmd->body.turn_on.req) +
53                                             HEADER_SIZE,
54                                             (uint8_t *) prsp,
55                                             sizeof(prsp->body.turn_on.rsp) +
56                                             HEADER_SIZE);
57         }
58
59         if (error < 0)
60                 goto out;
61
62         /* parse response */
63         error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
64
65 out:
66         LEAVE();
67         return error;
68 }
69
70 /**
71  * as10x_cmd_turn_off - send turn off command to AS10x
72  * @adap:   pointer to AS10x bus adapter
73  *
74  * Return 0 on success or negative value in case of error.
75  */
76 int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
77 {
78         int error = AS10X_CMD_ERROR;
79         struct as10x_cmd_t *pcmd, *prsp;
80
81         ENTER();
82
83         pcmd = adap->cmd;
84         prsp = adap->rsp;
85
86         /* prepare command */
87         as10x_cmd_build(pcmd, (++adap->cmd_xid),
88                         sizeof(pcmd->body.turn_off.req));
89
90         /* fill command */
91         pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
92
93         /* send command */
94         if (adap->ops->xfer_cmd) {
95                 error = adap->ops->xfer_cmd(
96                         adap, (uint8_t *) pcmd,
97                         sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
98                         (uint8_t *) prsp,
99                         sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
100         }
101
102         if (error < 0)
103                 goto out;
104
105         /* parse response */
106         error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
107
108 out:
109         LEAVE();
110         return error;
111 }
112
113 /**
114  * as10x_cmd_set_tune - send set tune command to AS10x
115  * @adap:    pointer to AS10x bus adapter
116  * @ptune:   tune parameters
117  *
118  * Return 0 on success or negative value in case of error.
119  */
120 int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
121                        struct as10x_tune_args *ptune)
122 {
123         int error = AS10X_CMD_ERROR;
124         struct as10x_cmd_t *preq, *prsp;
125
126         ENTER();
127
128         preq = adap->cmd;
129         prsp = adap->rsp;
130
131         /* prepare command */
132         as10x_cmd_build(preq, (++adap->cmd_xid),
133                         sizeof(preq->body.set_tune.req));
134
135         /* fill command */
136         preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
137         preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
138         preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
139         preq->body.set_tune.req.args.hier_select = ptune->hier_select;
140         preq->body.set_tune.req.args.modulation = ptune->modulation;
141         preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
142         preq->body.set_tune.req.args.interleaving_mode  =
143                 ptune->interleaving_mode;
144         preq->body.set_tune.req.args.code_rate  = ptune->code_rate;
145         preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
146         preq->body.set_tune.req.args.transmission_mode  =
147                 ptune->transmission_mode;
148
149         /* send command */
150         if (adap->ops->xfer_cmd) {
151                 error = adap->ops->xfer_cmd(adap,
152                                             (uint8_t *) preq,
153                                             sizeof(preq->body.set_tune.req)
154                                             + HEADER_SIZE,
155                                             (uint8_t *) prsp,
156                                             sizeof(prsp->body.set_tune.rsp)
157                                             + HEADER_SIZE);
158         }
159
160         if (error < 0)
161                 goto out;
162
163         /* parse response */
164         error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
165
166 out:
167         LEAVE();
168         return error;
169 }
170
171 /**
172  * as10x_cmd_get_tune_status - send get tune status command to AS10x
173  * @adap: pointer to AS10x bus adapter
174  * @pstatus: pointer to updated status structure of the current tune
175  *
176  * Return 0 on success or negative value in case of error.
177  */
178 int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
179                               struct as10x_tune_status *pstatus)
180 {
181         int error = AS10X_CMD_ERROR;
182         struct as10x_cmd_t  *preq, *prsp;
183
184         ENTER();
185
186         preq = adap->cmd;
187         prsp = adap->rsp;
188
189         /* prepare command */
190         as10x_cmd_build(preq, (++adap->cmd_xid),
191                         sizeof(preq->body.get_tune_status.req));
192
193         /* fill command */
194         preq->body.get_tune_status.req.proc_id =
195                 cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
196
197         /* send command */
198         if (adap->ops->xfer_cmd) {
199                 error = adap->ops->xfer_cmd(
200                         adap,
201                         (uint8_t *) preq,
202                         sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
203                         (uint8_t *) prsp,
204                         sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
205         }
206
207         if (error < 0)
208                 goto out;
209
210         /* parse response */
211         error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
212         if (error < 0)
213                 goto out;
214
215         /* Response OK -> get response data */
216         pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
217         pstatus->signal_strength  =
218                 le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength);
219         pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER);
220         pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER);
221
222 out:
223         LEAVE();
224         return error;
225 }
226
227 /**
228  * as10x_cmd_get_tps - send get TPS command to AS10x
229  * @adap:      pointer to AS10x handle
230  * @ptps:      pointer to TPS parameters structure
231  *
232  * Return 0 on success or negative value in case of error.
233  */
234 int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
235 {
236         int error = AS10X_CMD_ERROR;
237         struct as10x_cmd_t *pcmd, *prsp;
238
239         ENTER();
240
241         pcmd = adap->cmd;
242         prsp = adap->rsp;
243
244         /* prepare command */
245         as10x_cmd_build(pcmd, (++adap->cmd_xid),
246                         sizeof(pcmd->body.get_tps.req));
247
248         /* fill command */
249         pcmd->body.get_tune_status.req.proc_id =
250                 cpu_to_le16(CONTROL_PROC_GETTPS);
251
252         /* send command */
253         if (adap->ops->xfer_cmd) {
254                 error = adap->ops->xfer_cmd(adap,
255                                             (uint8_t *) pcmd,
256                                             sizeof(pcmd->body.get_tps.req) +
257                                             HEADER_SIZE,
258                                             (uint8_t *) prsp,
259                                             sizeof(prsp->body.get_tps.rsp) +
260                                             HEADER_SIZE);
261         }
262
263         if (error < 0)
264                 goto out;
265
266         /* parse response */
267         error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
268         if (error < 0)
269                 goto out;
270
271         /* Response OK -> get response data */
272         ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
273         ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
274         ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
275         ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
276         ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
277         ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
278         ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;
279         ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
280         ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
281         ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID);
282
283 out:
284         LEAVE();
285         return error;
286 }
287
288 /**
289  * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
290  * @adap:          pointer to AS10x bus adapter
291  * @pdemod_stats:  pointer to demod stats parameters structure
292  *
293  * Return 0 on success or negative value in case of error.
294  */
295 int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
296                               struct as10x_demod_stats *pdemod_stats)
297 {
298         int error = AS10X_CMD_ERROR;
299         struct as10x_cmd_t *pcmd, *prsp;
300
301         ENTER();
302
303         pcmd = adap->cmd;
304         prsp = adap->rsp;
305
306         /* prepare command */
307         as10x_cmd_build(pcmd, (++adap->cmd_xid),
308                         sizeof(pcmd->body.get_demod_stats.req));
309
310         /* fill command */
311         pcmd->body.get_demod_stats.req.proc_id =
312                 cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
313
314         /* send command */
315         if (adap->ops->xfer_cmd) {
316                 error = adap->ops->xfer_cmd(adap,
317                                 (uint8_t *) pcmd,
318                                 sizeof(pcmd->body.get_demod_stats.req)
319                                 + HEADER_SIZE,
320                                 (uint8_t *) prsp,
321                                 sizeof(prsp->body.get_demod_stats.rsp)
322                                 + HEADER_SIZE);
323         }
324
325         if (error < 0)
326                 goto out;
327
328         /* parse response */
329         error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
330         if (error < 0)
331                 goto out;
332
333         /* Response OK -> get response data */
334         pdemod_stats->frame_count =
335                 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count);
336         pdemod_stats->bad_frame_count =
337                 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
338         pdemod_stats->bytes_fixed_by_rs =
339                 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
340         pdemod_stats->mer =
341                 le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer);
342         pdemod_stats->has_started =
343                 prsp->body.get_demod_stats.rsp.stats.has_started;
344
345 out:
346         LEAVE();
347         return error;
348 }
349
350 /**
351  * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
352  * @adap:     pointer to AS10x bus adapter
353  * @is_ready: pointer to value indicating when impulse
354  *            response data is ready
355  *
356  * Return 0 on success or negative value in case of error.
357  */
358 int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
359                                uint8_t *is_ready)
360 {
361         int error = AS10X_CMD_ERROR;
362         struct as10x_cmd_t *pcmd, *prsp;
363
364         ENTER();
365
366         pcmd = adap->cmd;
367         prsp = adap->rsp;
368
369         /* prepare command */
370         as10x_cmd_build(pcmd, (++adap->cmd_xid),
371                         sizeof(pcmd->body.get_impulse_rsp.req));
372
373         /* fill command */
374         pcmd->body.get_impulse_rsp.req.proc_id =
375                 cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
376
377         /* send command */
378         if (adap->ops->xfer_cmd) {
379                 error = adap->ops->xfer_cmd(adap,
380                                         (uint8_t *) pcmd,
381                                         sizeof(pcmd->body.get_impulse_rsp.req)
382                                         + HEADER_SIZE,
383                                         (uint8_t *) prsp,
384                                         sizeof(prsp->body.get_impulse_rsp.rsp)
385                                         + HEADER_SIZE);
386         }
387
388         if (error < 0)
389                 goto out;
390
391         /* parse response */
392         error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
393         if (error < 0)
394                 goto out;
395
396         /* Response OK -> get response data */
397         *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
398
399 out:
400         LEAVE();
401         return error;
402 }
403
404 /**
405  * as10x_cmd_build - build AS10x command header
406  * @pcmd:     pointer to AS10x command buffer
407  * @xid:      sequence id of the command
408  * @cmd_len:  length of the command
409  */
410 void as10x_cmd_build(struct as10x_cmd_t *pcmd,
411                      uint16_t xid, uint16_t cmd_len)
412 {
413         pcmd->header.req_id = cpu_to_le16(xid);
414         pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
415         pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
416         pcmd->header.data_len = cpu_to_le16(cmd_len);
417 }
418
419 /**
420  * as10x_rsp_parse - Parse command response
421  * @prsp:       pointer to AS10x command buffer
422  * @proc_id:    id of the command
423  *
424  * Return 0 on success or negative value in case of error.
425  */
426 int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
427 {
428         int error;
429
430         /* extract command error code */
431         error = prsp->body.common.rsp.error;
432
433         if ((error == 0) &&
434             (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
435                 return 0;
436         }
437
438         return AS10X_CMD_ERROR;
439 }