aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2012-07-27 20:57:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-08-10 15:17:14 -0400
commit9bc63816be9bf504414d350e605a4b30f857907d (patch)
tree67fd903805199135fd7dbb8a85be615ce6a584b1
parent57f784fed3b9a33084c0cd0f6d08d98f87d2193f (diff)
p54: parse output power table
For the upcoming tpc changes, the driver needs to provide sensible max output values for each supported channel. And while the eeprom always had a output_limit table, which defines the upper limit for each frequency and modulation, it was never really useful for anything... until now. Note: For anyone wondering about what your card is calibrated for: check "iw list". * 2412 MHz [1] (18.0 dBm) * 2437 MHz [6] (19.0 dBm) [...] * 5180 MHz [36] (18.0 dBm) * 5260 MHz [52] (17.0 dBm) (radar detection) * 5680 MHz [136] (19.0 dBm) (radar detection) (for a Dell Wireless 1450 USB Adapter) Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/p54/eeprom.c104
-rw-r--r--drivers/net/wireless/p54/eeprom.h12
2 files changed, 92 insertions, 24 deletions
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 14037092ba89..d4d86107e05a 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -76,6 +76,7 @@ struct p54_channel_entry {
76 u16 freq; 76 u16 freq;
77 u16 data; 77 u16 data;
78 int index; 78 int index;
79 int max_power;
79 enum ieee80211_band band; 80 enum ieee80211_band band;
80}; 81};
81 82
@@ -173,6 +174,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
173 for (i = 0, j = 0; (j < list->band_channel_num[band]) && 174 for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
174 (i < list->entries); i++) { 175 (i < list->entries); i++) {
175 struct p54_channel_entry *chan = &list->channels[i]; 176 struct p54_channel_entry *chan = &list->channels[i];
177 struct ieee80211_channel *dest = &tmp->channels[j];
176 178
177 if (chan->band != band) 179 if (chan->band != band)
178 continue; 180 continue;
@@ -190,14 +192,15 @@ static int p54_generate_band(struct ieee80211_hw *dev,
190 continue; 192 continue;
191 } 193 }
192 194
193 tmp->channels[j].band = chan->band; 195 dest->band = chan->band;
194 tmp->channels[j].center_freq = chan->freq; 196 dest->center_freq = chan->freq;
197 dest->max_power = chan->max_power;
195 priv->survey[*chan_num].channel = &tmp->channels[j]; 198 priv->survey[*chan_num].channel = &tmp->channels[j];
196 priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | 199 priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
197 SURVEY_INFO_CHANNEL_TIME | 200 SURVEY_INFO_CHANNEL_TIME |
198 SURVEY_INFO_CHANNEL_TIME_BUSY | 201 SURVEY_INFO_CHANNEL_TIME_BUSY |
199 SURVEY_INFO_CHANNEL_TIME_TX; 202 SURVEY_INFO_CHANNEL_TIME_TX;
200 tmp->channels[j].hw_value = (*chan_num); 203 dest->hw_value = (*chan_num);
201 j++; 204 j++;
202 (*chan_num)++; 205 (*chan_num)++;
203 } 206 }
@@ -229,10 +232,11 @@ err_out:
229 return ret; 232 return ret;
230} 233}
231 234
232static void p54_update_channel_param(struct p54_channel_list *list, 235static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list,
233 u16 freq, u16 data) 236 u16 freq, u16 data)
234{ 237{
235 int band, i; 238 int i;
239 struct p54_channel_entry *entry = NULL;
236 240
237 /* 241 /*
238 * usually all lists in the eeprom are mostly sorted. 242 * usually all lists in the eeprom are mostly sorted.
@@ -241,30 +245,74 @@ static void p54_update_channel_param(struct p54_channel_list *list,
241 */ 245 */
242 for (i = list->entries; i >= 0; i--) { 246 for (i = list->entries; i >= 0; i--) {
243 if (freq == list->channels[i].freq) { 247 if (freq == list->channels[i].freq) {
244 list->channels[i].data |= data; 248 entry = &list->channels[i];
245 break; 249 break;
246 } 250 }
247 } 251 }
248 252
249 if ((i < 0) && (list->entries < list->max_entries)) { 253 if ((i < 0) && (list->entries < list->max_entries)) {
250 /* entry does not exist yet. Initialize a new one. */ 254 /* entry does not exist yet. Initialize a new one. */
251 band = p54_get_band_from_freq(freq); 255 int band = p54_get_band_from_freq(freq);
252 256
253 /* 257 /*
254 * filter out frequencies which don't belong into 258 * filter out frequencies which don't belong into
255 * any supported band. 259 * any supported band.
256 */ 260 */
257 if (band < 0) 261 if (band >= 0) {
258 return ; 262 i = list->entries++;
263 list->band_channel_num[band]++;
264
265 entry = &list->channels[i];
266 entry->freq = freq;
267 entry->band = band;
268 entry->index = ieee80211_frequency_to_channel(freq);
269 entry->max_power = 0;
270 entry->data = 0;
271 }
272 }
259 273
260 i = list->entries++; 274 if (entry)
261 list->band_channel_num[band]++; 275 entry->data |= data;
262 276
263 list->channels[i].freq = freq; 277 return entry;
264 list->channels[i].data = data; 278}
265 list->channels[i].band = band; 279
266 list->channels[i].index = ieee80211_frequency_to_channel(freq); 280static int p54_get_maxpower(struct p54_common *priv, void *data)
267 /* TODO: parse output_limit and fill max_power */ 281{
282 switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) {
283 case PDR_SYNTH_FRONTEND_LONGBOW: {
284 struct pda_channel_output_limit_longbow *pda = data;
285 int j;
286 u16 rawpower = 0;
287 pda = data;
288 for (j = 0; j < ARRAY_SIZE(pda->point); j++) {
289 struct pda_channel_output_limit_point_longbow *point =
290 &pda->point[j];
291 rawpower = max(rawpower, le16_to_cpu(point->val_qpsk));
292 rawpower = max(rawpower, le16_to_cpu(point->val_bpsk));
293 rawpower = max(rawpower, le16_to_cpu(point->val_16qam));
294 rawpower = max(rawpower, le16_to_cpu(point->val_64qam));
295 }
296 /* longbow seems to use 1/16 dBm units */
297 return rawpower / 16;
298 }
299
300 case PDR_SYNTH_FRONTEND_DUETTE3:
301 case PDR_SYNTH_FRONTEND_DUETTE2:
302 case PDR_SYNTH_FRONTEND_FRISBEE:
303 case PDR_SYNTH_FRONTEND_XBOW: {
304 struct pda_channel_output_limit *pda = data;
305 u8 rawpower = 0;
306 rawpower = max(rawpower, pda->val_qpsk);
307 rawpower = max(rawpower, pda->val_bpsk);
308 rawpower = max(rawpower, pda->val_16qam);
309 rawpower = max(rawpower, pda->val_64qam);
310 /* raw values are in 1/4 dBm units */
311 return rawpower / 4;
312 }
313
314 default:
315 return 20;
268 } 316 }
269} 317}
270 318
@@ -315,12 +363,19 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
315 } 363 }
316 364
317 if (i < priv->output_limit->entries) { 365 if (i < priv->output_limit->entries) {
318 freq = le16_to_cpup((__le16 *) (i * 366 struct p54_channel_entry *tmp;
319 priv->output_limit->entry_size + 367
320 priv->output_limit->offset + 368 void *data = (void *) ((unsigned long) i *
321 priv->output_limit->data)); 369 priv->output_limit->entry_size +
322 370 priv->output_limit->offset +
323 p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); 371 priv->output_limit->data);
372
373 freq = le16_to_cpup((__le16 *) data);
374 tmp = p54_update_channel_param(list, freq,
375 CHAN_HAS_LIMIT);
376 if (tmp) {
377 tmp->max_power = p54_get_maxpower(priv, data);
378 }
324 } 379 }
325 380
326 if (i < priv->curve_data->entries) { 381 if (i < priv->curve_data->entries) {
@@ -834,11 +889,12 @@ good_eeprom:
834 goto err; 889 goto err;
835 } 890 }
836 891
892 priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
893
837 err = p54_generate_channel_lists(dev); 894 err = p54_generate_channel_lists(dev);
838 if (err) 895 if (err)
839 goto err; 896 goto err;
840 897
841 priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
842 if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) 898 if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
843 p54_init_xbow_synth(priv); 899 p54_init_xbow_synth(priv);
844 if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) 900 if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h
index afde72b84606..20ebe39a3f4e 100644
--- a/drivers/net/wireless/p54/eeprom.h
+++ b/drivers/net/wireless/p54/eeprom.h
@@ -57,6 +57,18 @@ struct pda_channel_output_limit {
57 u8 rate_set_size; 57 u8 rate_set_size;
58} __packed; 58} __packed;
59 59
60struct pda_channel_output_limit_point_longbow {
61 __le16 val_bpsk;
62 __le16 val_qpsk;
63 __le16 val_16qam;
64 __le16 val_64qam;
65} __packed;
66
67struct pda_channel_output_limit_longbow {
68 __le16 freq;
69 struct pda_channel_output_limit_point_longbow point[3];
70} __packed;
71
60struct pda_pa_curve_data_sample_rev0 { 72struct pda_pa_curve_data_sample_rev0 {
61 u8 rf_power; 73 u8 rf_power;
62 u8 pa_detector; 74 u8 pa_detector;