1 /* 2 * Abilis Systems Single DVB-T Receiver 3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2, or (at your option) 8 * any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20 #include <linux/kernel.h> 21 #include "as102_drv.h" 22 #include "as10x_types.h" 23 #include "as10x_cmd.h" 24 25 /***************************/ 26 /* FUNCTION DEFINITION */ 27 /***************************/ 28 29 /** 30 * as10x_cmd_get_context - Send get context command to AS10x 31 * @adap: pointer to AS10x bus adapter 32 * @tag: context tag 33 * @pvalue: pointer where to store context value read 34 * 35 * Return 0 on success or negative value in case of error. 36 */ 37 int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, 38 uint32_t *pvalue) 39 { 40 int error; 41 struct as10x_cmd_t *pcmd, *prsp; 42 43 pcmd = adap->cmd; 44 prsp = adap->rsp; 45 46 /* prepare command */ 47 as10x_cmd_build(pcmd, (++adap->cmd_xid), 48 sizeof(pcmd->body.context.req)); 49 50 /* fill command */ 51 pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); 52 pcmd->body.context.req.tag = cpu_to_le16(tag); 53 pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA); 54 55 /* send command */ 56 if (adap->ops->xfer_cmd) { 57 error = adap->ops->xfer_cmd(adap, 58 (uint8_t *) pcmd, 59 sizeof(pcmd->body.context.req) 60 + HEADER_SIZE, 61 (uint8_t *) prsp, 62 sizeof(prsp->body.context.rsp) 63 + HEADER_SIZE); 64 } else { 65 error = AS10X_CMD_ERROR; 66 } 67 68 if (error < 0) 69 goto out; 70 71 /* parse response: context command do not follow the common response */ 72 /* structure -> specific handling response parse required */ 73 error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP); 74 75 if (error == 0) { 76 /* Response OK -> get response data */ 77 *pvalue = le32_to_cpu(prsp->body.context.rsp.reg_val.u.value32); 78 /* value returned is always a 32-bit value */ 79 } 80 81 out: 82 return error; 83 } 84 85 /** 86 * as10x_cmd_set_context - send set context command to AS10x 87 * @adap: pointer to AS10x bus adapter 88 * @tag: context tag 89 * @value: value to set in context 90 * 91 * Return 0 on success or negative value in case of error. 92 */ 93 int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, 94 uint32_t value) 95 { 96 int error; 97 struct as10x_cmd_t *pcmd, *prsp; 98 99 pcmd = adap->cmd; 100 prsp = adap->rsp; 101 102 /* prepare command */ 103 as10x_cmd_build(pcmd, (++adap->cmd_xid), 104 sizeof(pcmd->body.context.req)); 105 106 /* fill command */ 107 pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); 108 /* pcmd->body.context.req.reg_val.mode initialization is not required */ 109 pcmd->body.context.req.reg_val.u.value32 = cpu_to_le32(value); 110 pcmd->body.context.req.tag = cpu_to_le16(tag); 111 pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA); 112 113 /* send command */ 114 if (adap->ops->xfer_cmd) { 115 error = adap->ops->xfer_cmd(adap, 116 (uint8_t *) pcmd, 117 sizeof(pcmd->body.context.req) 118 + HEADER_SIZE, 119 (uint8_t *) prsp, 120 sizeof(prsp->body.context.rsp) 121 + HEADER_SIZE); 122 } else { 123 error = AS10X_CMD_ERROR; 124 } 125 126 if (error < 0) 127 goto out; 128 129 /* parse response: context command do not follow the common response */ 130 /* structure -> specific handling response parse required */ 131 error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP); 132 133 out: 134 return error; 135 } 136 137 /** 138 * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x 139 * @adap: pointer to AS10x bus adapter 140 * @mode: mode selected: 141 * - ON : 0x0 => eLNA always ON 142 * - OFF : 0x1 => eLNA always OFF 143 * - AUTO : 0x2 => eLNA follow hysteresis parameters 144 * to be ON or OFF 145 * 146 * Return 0 on success or negative value in case of error. 147 */ 148 int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode) 149 { 150 int error; 151 struct as10x_cmd_t *pcmd, *prsp; 152 153 pcmd = adap->cmd; 154 prsp = adap->rsp; 155 156 /* prepare command */ 157 as10x_cmd_build(pcmd, (++adap->cmd_xid), 158 sizeof(pcmd->body.cfg_change_mode.req)); 159 160 /* fill command */ 161 pcmd->body.cfg_change_mode.req.proc_id = 162 cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE); 163 pcmd->body.cfg_change_mode.req.mode = mode; 164 165 /* send command */ 166 if (adap->ops->xfer_cmd) { 167 error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, 168 sizeof(pcmd->body.cfg_change_mode.req) 169 + HEADER_SIZE, (uint8_t *) prsp, 170 sizeof(prsp->body.cfg_change_mode.rsp) 171 + HEADER_SIZE); 172 } else { 173 error = AS10X_CMD_ERROR; 174 } 175 176 if (error < 0) 177 goto out; 178 179 /* parse response */ 180 error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP); 181 182 out: 183 return error; 184 } 185 186 /** 187 * as10x_context_rsp_parse - Parse context command response 188 * @prsp: pointer to AS10x command response buffer 189 * @proc_id: id of the command 190 * 191 * Since the contex command response does not follow the common 192 * response, a specific parse function is required. 193 * Return 0 on success or negative value in case of error. 194 */ 195 int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id) 196 { 197 int err; 198 199 err = prsp->body.context.rsp.error; 200 201 if ((err == 0) && 202 (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) { 203 return 0; 204 } 205 return AS10X_CMD_ERROR; 206 } 207