1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Abilis Systems Single DVB-T Receiver |
4 | * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> |
5 | */ |
6 | |
7 | #include <linux/kernel.h> |
8 | #include "as102_drv.h" |
9 | #include "as10x_cmd.h" |
10 | |
11 | /***************************/ |
12 | /* FUNCTION DEFINITION */ |
13 | /***************************/ |
14 | |
15 | /** |
16 | * as10x_cmd_get_context - Send get context command to AS10x |
17 | * @adap: pointer to AS10x bus adapter |
18 | * @tag: context tag |
19 | * @pvalue: pointer where to store context value read |
20 | * |
21 | * Return 0 on success or negative value in case of error. |
22 | */ |
23 | int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, |
24 | uint32_t *pvalue) |
25 | { |
26 | int error; |
27 | struct as10x_cmd_t *pcmd, *prsp; |
28 | |
29 | pcmd = adap->cmd; |
30 | prsp = adap->rsp; |
31 | |
32 | /* prepare command */ |
33 | as10x_cmd_build(pcmd, proc_id: (++adap->cmd_xid), |
34 | cmd_len: sizeof(pcmd->body.context.req)); |
35 | |
36 | /* fill command */ |
37 | pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); |
38 | pcmd->body.context.req.tag = cpu_to_le16(tag); |
39 | pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA); |
40 | |
41 | /* send command */ |
42 | if (adap->ops->xfer_cmd) { |
43 | error = adap->ops->xfer_cmd(adap, |
44 | (uint8_t *) pcmd, |
45 | sizeof(pcmd->body.context.req) |
46 | + HEADER_SIZE, |
47 | (uint8_t *) prsp, |
48 | sizeof(prsp->body.context.rsp) |
49 | + HEADER_SIZE); |
50 | } else { |
51 | error = AS10X_CMD_ERROR; |
52 | } |
53 | |
54 | if (error < 0) |
55 | goto out; |
56 | |
57 | /* parse response: context command do not follow the common response */ |
58 | /* structure -> specific handling response parse required */ |
59 | error = as10x_context_rsp_parse(prsp, proc_id: CONTROL_PROC_CONTEXT_RSP); |
60 | |
61 | if (error == 0) { |
62 | /* Response OK -> get response data */ |
63 | *pvalue = le32_to_cpu((__force __le32)prsp->body.context.rsp.reg_val.u.value32); |
64 | /* value returned is always a 32-bit value */ |
65 | } |
66 | |
67 | out: |
68 | return error; |
69 | } |
70 | |
71 | /** |
72 | * as10x_cmd_set_context - send set context command to AS10x |
73 | * @adap: pointer to AS10x bus adapter |
74 | * @tag: context tag |
75 | * @value: value to set in context |
76 | * |
77 | * Return 0 on success or negative value in case of error. |
78 | */ |
79 | int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, |
80 | uint32_t value) |
81 | { |
82 | int error; |
83 | struct as10x_cmd_t *pcmd, *prsp; |
84 | |
85 | pcmd = adap->cmd; |
86 | prsp = adap->rsp; |
87 | |
88 | /* prepare command */ |
89 | as10x_cmd_build(pcmd, proc_id: (++adap->cmd_xid), |
90 | cmd_len: sizeof(pcmd->body.context.req)); |
91 | |
92 | /* fill command */ |
93 | pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); |
94 | /* pcmd->body.context.req.reg_val.mode initialization is not required */ |
95 | pcmd->body.context.req.reg_val.u.value32 = (__force u32)cpu_to_le32(value); |
96 | pcmd->body.context.req.tag = cpu_to_le16(tag); |
97 | pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA); |
98 | |
99 | /* send command */ |
100 | if (adap->ops->xfer_cmd) { |
101 | error = adap->ops->xfer_cmd(adap, |
102 | (uint8_t *) pcmd, |
103 | sizeof(pcmd->body.context.req) |
104 | + HEADER_SIZE, |
105 | (uint8_t *) prsp, |
106 | sizeof(prsp->body.context.rsp) |
107 | + HEADER_SIZE); |
108 | } else { |
109 | error = AS10X_CMD_ERROR; |
110 | } |
111 | |
112 | if (error < 0) |
113 | goto out; |
114 | |
115 | /* parse response: context command do not follow the common response */ |
116 | /* structure -> specific handling response parse required */ |
117 | error = as10x_context_rsp_parse(prsp, proc_id: CONTROL_PROC_CONTEXT_RSP); |
118 | |
119 | out: |
120 | return error; |
121 | } |
122 | |
123 | /** |
124 | * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x |
125 | * @adap: pointer to AS10x bus adapter |
126 | * @mode: mode selected: |
127 | * - ON : 0x0 => eLNA always ON |
128 | * - OFF : 0x1 => eLNA always OFF |
129 | * - AUTO : 0x2 => eLNA follow hysteresis parameters |
130 | * to be ON or OFF |
131 | * |
132 | * Return 0 on success or negative value in case of error. |
133 | */ |
134 | int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode) |
135 | { |
136 | int error; |
137 | struct as10x_cmd_t *pcmd, *prsp; |
138 | |
139 | pcmd = adap->cmd; |
140 | prsp = adap->rsp; |
141 | |
142 | /* prepare command */ |
143 | as10x_cmd_build(pcmd, proc_id: (++adap->cmd_xid), |
144 | cmd_len: sizeof(pcmd->body.cfg_change_mode.req)); |
145 | |
146 | /* fill command */ |
147 | pcmd->body.cfg_change_mode.req.proc_id = |
148 | cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE); |
149 | pcmd->body.cfg_change_mode.req.mode = mode; |
150 | |
151 | /* send command */ |
152 | if (adap->ops->xfer_cmd) { |
153 | error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, |
154 | sizeof(pcmd->body.cfg_change_mode.req) |
155 | + HEADER_SIZE, (uint8_t *) prsp, |
156 | sizeof(prsp->body.cfg_change_mode.rsp) |
157 | + HEADER_SIZE); |
158 | } else { |
159 | error = AS10X_CMD_ERROR; |
160 | } |
161 | |
162 | if (error < 0) |
163 | goto out; |
164 | |
165 | /* parse response */ |
166 | error = as10x_rsp_parse(r: prsp, proc_id: CONTROL_PROC_ELNA_CHANGE_MODE_RSP); |
167 | |
168 | out: |
169 | return error; |
170 | } |
171 | |
172 | /** |
173 | * as10x_context_rsp_parse - Parse context command response |
174 | * @prsp: pointer to AS10x command response buffer |
175 | * @proc_id: id of the command |
176 | * |
177 | * Since the contex command response does not follow the common |
178 | * response, a specific parse function is required. |
179 | * Return 0 on success or negative value in case of error. |
180 | */ |
181 | int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id) |
182 | { |
183 | int err; |
184 | |
185 | err = prsp->body.context.rsp.error; |
186 | |
187 | if ((err == 0) && |
188 | (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) { |
189 | return 0; |
190 | } |
191 | return AS10X_CMD_ERROR; |
192 | } |
193 | |