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