diff options
Diffstat (limited to 'drivers/net/wireless/p54/eeprom.c')
| -rw-r--r-- | drivers/net/wireless/p54/eeprom.c | 106 | 
1 files changed, 83 insertions, 23 deletions
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 14037092ba8..1ef1bfe6a9d 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -76,6 +76,7 @@ struct p54_channel_entry {  	u16 freq;  	u16 data;  	int index; +	int max_power;  	enum ieee80211_band band;  }; @@ -173,6 +174,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,  	for (i = 0, j = 0; (j < list->band_channel_num[band]) &&  			   (i < list->entries); i++) {  		struct p54_channel_entry *chan = &list->channels[i]; +		struct ieee80211_channel *dest = &tmp->channels[j];  		if (chan->band != band)  			continue; @@ -190,14 +192,15 @@ static int p54_generate_band(struct ieee80211_hw *dev,  			continue;  		} -		tmp->channels[j].band = chan->band; -		tmp->channels[j].center_freq = chan->freq; +		dest->band = chan->band; +		dest->center_freq = chan->freq; +		dest->max_power = chan->max_power;  		priv->survey[*chan_num].channel = &tmp->channels[j];  		priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |  			SURVEY_INFO_CHANNEL_TIME |  			SURVEY_INFO_CHANNEL_TIME_BUSY |  			SURVEY_INFO_CHANNEL_TIME_TX; -		tmp->channels[j].hw_value = (*chan_num); +		dest->hw_value = (*chan_num);  		j++;  		(*chan_num)++;  	} @@ -229,10 +232,11 @@ err_out:  	return ret;  } -static void p54_update_channel_param(struct p54_channel_list *list, -				     u16 freq, u16 data) +static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list, +							  u16 freq, u16 data)  { -	int band, i; +	int i; +	struct p54_channel_entry *entry = NULL;  	/*  	 * usually all lists in the eeprom are mostly sorted. @@ -241,30 +245,78 @@ static void p54_update_channel_param(struct p54_channel_list *list,  	 */  	for (i = list->entries; i >= 0; i--) {  		if (freq == list->channels[i].freq) { -			list->channels[i].data |= data; +			entry = &list->channels[i];  			break;  		}  	}  	if ((i < 0) && (list->entries < list->max_entries)) {  		/* entry does not exist yet. Initialize a new one. */ -		band = p54_get_band_from_freq(freq); +		int band = p54_get_band_from_freq(freq);  		/*  		 * filter out frequencies which don't belong into  		 * any supported band.  		 */ -		if (band < 0) -			return ; +		if (band >= 0) { +			i = list->entries++; +			list->band_channel_num[band]++; -		i = list->entries++; -		list->band_channel_num[band]++; +			entry = &list->channels[i]; +			entry->freq = freq; +			entry->band = band; +			entry->index = ieee80211_frequency_to_channel(freq); +			entry->max_power = 0; +			entry->data = 0; +		} +	} + +	if (entry) +		entry->data |= data; + +	return entry; +} + +static int p54_get_maxpower(struct p54_common *priv, void *data) +{ +	switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) { +	case PDR_SYNTH_FRONTEND_LONGBOW: { +		struct pda_channel_output_limit_longbow *pda = data; +		int j; +		u16 rawpower = 0; +		pda = data; +		for (j = 0; j < ARRAY_SIZE(pda->point); j++) { +			struct pda_channel_output_limit_point_longbow *point = +				&pda->point[j]; +			rawpower = max_t(u16, +				rawpower, le16_to_cpu(point->val_qpsk)); +			rawpower = max_t(u16, +				rawpower, le16_to_cpu(point->val_bpsk)); +			rawpower = max_t(u16, +				rawpower, le16_to_cpu(point->val_16qam)); +			rawpower = max_t(u16, +				rawpower, le16_to_cpu(point->val_64qam)); +		} +		/* longbow seems to use 1/16 dBm units */ +		return rawpower / 16; +		} -		list->channels[i].freq = freq; -		list->channels[i].data = data; -		list->channels[i].band = band; -		list->channels[i].index = ieee80211_frequency_to_channel(freq); -		/* TODO: parse output_limit and fill max_power */ +	case PDR_SYNTH_FRONTEND_DUETTE3: +	case PDR_SYNTH_FRONTEND_DUETTE2: +	case PDR_SYNTH_FRONTEND_FRISBEE: +	case PDR_SYNTH_FRONTEND_XBOW: { +		struct pda_channel_output_limit *pda = data; +		u8 rawpower = 0; +		rawpower = max(rawpower, pda->val_qpsk); +		rawpower = max(rawpower, pda->val_bpsk); +		rawpower = max(rawpower, pda->val_16qam); +		rawpower = max(rawpower, pda->val_64qam); +		/* raw values are in 1/4 dBm units */ +		return rawpower / 4; +		} + +	default: +		return 20;  	}  } @@ -315,12 +367,19 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)  		}  		if (i < priv->output_limit->entries) { -			freq = le16_to_cpup((__le16 *) (i * -					    priv->output_limit->entry_size + -					    priv->output_limit->offset + -					    priv->output_limit->data)); +			struct p54_channel_entry *tmp; + +			void *data = (void *) ((unsigned long) i * +				priv->output_limit->entry_size + +				priv->output_limit->offset + +				priv->output_limit->data); -			p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); +			freq = le16_to_cpup((__le16 *) data); +			tmp = p54_update_channel_param(list, freq, +						       CHAN_HAS_LIMIT); +			if (tmp) { +				tmp->max_power = p54_get_maxpower(priv, data); +			}  		}  		if (i < priv->curve_data->entries) { @@ -834,11 +893,12 @@ good_eeprom:  		goto err;  	} +	priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; +  	err = p54_generate_channel_lists(dev);  	if (err)  		goto err; -	priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;  	if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)  		p54_init_xbow_synth(priv);  	if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))  |