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