1 /* 2 * This file is part of wl12xx 3 * 4 * Copyright (C) 2009-2010 Nokia Corporation 5 * Copyright (C) 2011 Texas Instruments Inc. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * version 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * 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., 51 Franklin St, Fifth Floor, Boston, MA 19 * 02110-1301 USA 20 * 21 */ 22 23 #include "../wlcore/cmd.h" 24 #include "../wlcore/debug.h" 25 26 #include "wl12xx.h" 27 #include "cmd.h" 28 29 int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) 30 { 31 struct wl1271_ext_radio_parms_cmd *ext_radio_parms; 32 struct wl12xx_priv *priv = wl->priv; 33 struct wl12xx_conf_rf *rf = &priv->conf.rf; 34 int ret; 35 36 if (!wl->nvs) 37 return -ENODEV; 38 39 ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); 40 if (!ext_radio_parms) 41 return -ENOMEM; 42 43 ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; 44 45 memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, 46 rf->tx_per_channel_power_compensation_2, 47 CONF_TX_PWR_COMPENSATION_LEN_2); 48 memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, 49 rf->tx_per_channel_power_compensation_5, 50 CONF_TX_PWR_COMPENSATION_LEN_5); 51 52 wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", 53 ext_radio_parms, sizeof(*ext_radio_parms)); 54 55 ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); 56 if (ret < 0) 57 wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); 58 59 kfree(ext_radio_parms); 60 return ret; 61 } 62 63 int wl1271_cmd_general_parms(struct wl1271 *wl) 64 { 65 struct wl1271_general_parms_cmd *gen_parms; 66 struct wl1271_ini_general_params *gp = 67 &((struct wl1271_nvs_file *)wl->nvs)->general_params; 68 struct wl12xx_priv *priv = wl->priv; 69 bool answer = false; 70 int ret; 71 72 if (!wl->nvs) 73 return -ENODEV; 74 75 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { 76 wl1271_warning("FEM index from INI out of bounds"); 77 return -EINVAL; 78 } 79 80 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 81 if (!gen_parms) 82 return -ENOMEM; 83 84 gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 85 86 memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 87 88 if (gp->tx_bip_fem_auto_detect) 89 answer = true; 90 91 /* Override the REF CLK from the NVS with the one from platform data */ 92 gen_parms->general_params.ref_clock = priv->ref_clock; 93 94 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); 95 if (ret < 0) { 96 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 97 goto out; 98 } 99 100 gp->tx_bip_fem_manufacturer = 101 gen_parms->general_params.tx_bip_fem_manufacturer; 102 103 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { 104 wl1271_warning("FEM index from FW out of bounds"); 105 ret = -EINVAL; 106 goto out; 107 } 108 109 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 110 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 111 112 out: 113 kfree(gen_parms); 114 return ret; 115 } 116 117 int wl128x_cmd_general_parms(struct wl1271 *wl) 118 { 119 struct wl128x_general_parms_cmd *gen_parms; 120 struct wl128x_ini_general_params *gp = 121 &((struct wl128x_nvs_file *)wl->nvs)->general_params; 122 struct wl12xx_priv *priv = wl->priv; 123 bool answer = false; 124 int ret; 125 126 if (!wl->nvs) 127 return -ENODEV; 128 129 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { 130 wl1271_warning("FEM index from ini out of bounds"); 131 return -EINVAL; 132 } 133 134 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 135 if (!gen_parms) 136 return -ENOMEM; 137 138 gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 139 140 memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 141 142 if (gp->tx_bip_fem_auto_detect) 143 answer = true; 144 145 /* Replace REF and TCXO CLKs with the ones from platform data */ 146 gen_parms->general_params.ref_clock = priv->ref_clock; 147 gen_parms->general_params.tcxo_ref_clock = priv->tcxo_clock; 148 149 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); 150 if (ret < 0) { 151 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 152 goto out; 153 } 154 155 gp->tx_bip_fem_manufacturer = 156 gen_parms->general_params.tx_bip_fem_manufacturer; 157 158 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { 159 wl1271_warning("FEM index from FW out of bounds"); 160 ret = -EINVAL; 161 goto out; 162 } 163 164 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 165 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 166 167 out: 168 kfree(gen_parms); 169 return ret; 170 } 171 172 int wl1271_cmd_radio_parms(struct wl1271 *wl) 173 { 174 struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; 175 struct wl1271_radio_parms_cmd *radio_parms; 176 struct wl1271_ini_general_params *gp = &nvs->general_params; 177 int ret, fem_idx; 178 179 if (!wl->nvs) 180 return -ENODEV; 181 182 radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 183 if (!radio_parms) 184 return -ENOMEM; 185 186 radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 187 188 fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); 189 190 /* 2.4GHz parameters */ 191 memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, 192 sizeof(struct wl1271_ini_band_params_2)); 193 memcpy(&radio_parms->dyn_params_2, 194 &nvs->dyn_radio_params_2[fem_idx].params, 195 sizeof(struct wl1271_ini_fem_params_2)); 196 197 /* 5GHz parameters */ 198 memcpy(&radio_parms->static_params_5, 199 &nvs->stat_radio_params_5, 200 sizeof(struct wl1271_ini_band_params_5)); 201 memcpy(&radio_parms->dyn_params_5, 202 &nvs->dyn_radio_params_5[fem_idx].params, 203 sizeof(struct wl1271_ini_fem_params_5)); 204 205 wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 206 radio_parms, sizeof(*radio_parms)); 207 208 ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 209 if (ret < 0) 210 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 211 212 kfree(radio_parms); 213 return ret; 214 } 215 216 int wl128x_cmd_radio_parms(struct wl1271 *wl) 217 { 218 struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; 219 struct wl128x_radio_parms_cmd *radio_parms; 220 struct wl128x_ini_general_params *gp = &nvs->general_params; 221 int ret, fem_idx; 222 223 if (!wl->nvs) 224 return -ENODEV; 225 226 radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 227 if (!radio_parms) 228 return -ENOMEM; 229 230 radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 231 232 fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); 233 234 /* 2.4GHz parameters */ 235 memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, 236 sizeof(struct wl128x_ini_band_params_2)); 237 memcpy(&radio_parms->dyn_params_2, 238 &nvs->dyn_radio_params_2[fem_idx].params, 239 sizeof(struct wl128x_ini_fem_params_2)); 240 241 /* 5GHz parameters */ 242 memcpy(&radio_parms->static_params_5, 243 &nvs->stat_radio_params_5, 244 sizeof(struct wl128x_ini_band_params_5)); 245 memcpy(&radio_parms->dyn_params_5, 246 &nvs->dyn_radio_params_5[fem_idx].params, 247 sizeof(struct wl128x_ini_fem_params_5)); 248 249 radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; 250 251 wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 252 radio_parms, sizeof(*radio_parms)); 253 254 ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 255 if (ret < 0) 256 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 257 258 kfree(radio_parms); 259 return ret; 260 } 261