xref: /openbmc/linux/drivers/net/wireless/ath/ath9k/common-spectral.h (revision 3eb66e91a25497065c5322b1268cbc3953642227)
167dc74f1SOleksij Rempel /*
267dc74f1SOleksij Rempel  * Copyright (c) 2013 Qualcomm Atheros, Inc.
367dc74f1SOleksij Rempel  *
467dc74f1SOleksij Rempel  * Permission to use, copy, modify, and/or distribute this software for any
567dc74f1SOleksij Rempel  * purpose with or without fee is hereby granted, provided that the above
667dc74f1SOleksij Rempel  * copyright notice and this permission notice appear in all copies.
767dc74f1SOleksij Rempel  *
867dc74f1SOleksij Rempel  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
967dc74f1SOleksij Rempel  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1067dc74f1SOleksij Rempel  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1167dc74f1SOleksij Rempel  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1267dc74f1SOleksij Rempel  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1367dc74f1SOleksij Rempel  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1467dc74f1SOleksij Rempel  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1567dc74f1SOleksij Rempel  */
1667dc74f1SOleksij Rempel 
1767dc74f1SOleksij Rempel #ifndef SPECTRAL_H
1867dc74f1SOleksij Rempel #define SPECTRAL_H
1967dc74f1SOleksij Rempel 
2067dc74f1SOleksij Rempel #include "../spectral_common.h"
2167dc74f1SOleksij Rempel 
2267dc74f1SOleksij Rempel /* enum spectral_mode:
2367dc74f1SOleksij Rempel  *
2467dc74f1SOleksij Rempel  * @SPECTRAL_DISABLED: spectral mode is disabled
2567dc74f1SOleksij Rempel  * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
2667dc74f1SOleksij Rempel  *	something else.
2767dc74f1SOleksij Rempel  * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
2867dc74f1SOleksij Rempel  *	is performed manually.
2967dc74f1SOleksij Rempel  * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
3067dc74f1SOleksij Rempel  *	during a channel scan.
3167dc74f1SOleksij Rempel  */
3267dc74f1SOleksij Rempel enum spectral_mode {
3367dc74f1SOleksij Rempel 	SPECTRAL_DISABLED = 0,
3467dc74f1SOleksij Rempel 	SPECTRAL_BACKGROUND,
3567dc74f1SOleksij Rempel 	SPECTRAL_MANUAL,
3667dc74f1SOleksij Rempel 	SPECTRAL_CHANSCAN,
3767dc74f1SOleksij Rempel };
3867dc74f1SOleksij Rempel 
3967dc74f1SOleksij Rempel #define SPECTRAL_SCAN_BITMASK		0x10
4067dc74f1SOleksij Rempel /* Radar info packet format, used for DFS and spectral formats. */
4167dc74f1SOleksij Rempel struct ath_radar_info {
4267dc74f1SOleksij Rempel 	u8 pulse_length_pri;
4367dc74f1SOleksij Rempel 	u8 pulse_length_ext;
4467dc74f1SOleksij Rempel 	u8 pulse_bw_info;
4567dc74f1SOleksij Rempel } __packed;
4667dc74f1SOleksij Rempel 
4767dc74f1SOleksij Rempel /* The HT20 spectral data has 4 bytes of additional information at it's end.
4867dc74f1SOleksij Rempel  *
4967dc74f1SOleksij Rempel  * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
5067dc74f1SOleksij Rempel  * [7:0]: all bins  max_magnitude[9:2]
5167dc74f1SOleksij Rempel  * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
5267dc74f1SOleksij Rempel  * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
5367dc74f1SOleksij Rempel  */
5467dc74f1SOleksij Rempel struct ath_ht20_mag_info {
5567dc74f1SOleksij Rempel 	u8 all_bins[3];
5667dc74f1SOleksij Rempel 	u8 max_exp;
5767dc74f1SOleksij Rempel } __packed;
5867dc74f1SOleksij Rempel 
5967dc74f1SOleksij Rempel /* WARNING: don't actually use this struct! MAC may vary the amount of
6067dc74f1SOleksij Rempel  * data by -1/+2. This struct is for reference only.
6167dc74f1SOleksij Rempel  */
6267dc74f1SOleksij Rempel struct ath_ht20_fft_packet {
6367dc74f1SOleksij Rempel 	u8 data[SPECTRAL_HT20_NUM_BINS];
6467dc74f1SOleksij Rempel 	struct ath_ht20_mag_info mag_info;
6567dc74f1SOleksij Rempel 	struct ath_radar_info radar_info;
6667dc74f1SOleksij Rempel } __packed;
6767dc74f1SOleksij Rempel 
6867dc74f1SOleksij Rempel #define SPECTRAL_HT20_TOTAL_DATA_LEN	(sizeof(struct ath_ht20_fft_packet))
6958b5e4c7SNick Kossifidis #define	SPECTRAL_HT20_SAMPLE_LEN	(sizeof(struct ath_ht20_mag_info) +\
7058b5e4c7SNick Kossifidis 					SPECTRAL_HT20_NUM_BINS)
7167dc74f1SOleksij Rempel 
7267dc74f1SOleksij Rempel /* Dynamic 20/40 mode:
7367dc74f1SOleksij Rempel  *
7467dc74f1SOleksij Rempel  * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
7567dc74f1SOleksij Rempel  * [7:0]: lower bins  max_magnitude[9:2]
7667dc74f1SOleksij Rempel  * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
7767dc74f1SOleksij Rempel  * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
7867dc74f1SOleksij Rempel  * [7:0]: upper bins  max_magnitude[9:2]
7967dc74f1SOleksij Rempel  * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
8067dc74f1SOleksij Rempel  * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
8167dc74f1SOleksij Rempel  */
8267dc74f1SOleksij Rempel struct ath_ht20_40_mag_info {
8367dc74f1SOleksij Rempel 	u8 lower_bins[3];
8467dc74f1SOleksij Rempel 	u8 upper_bins[3];
8567dc74f1SOleksij Rempel 	u8 max_exp;
8667dc74f1SOleksij Rempel } __packed;
8767dc74f1SOleksij Rempel 
8867dc74f1SOleksij Rempel /* WARNING: don't actually use this struct! MAC may vary the amount of
8967dc74f1SOleksij Rempel  * data. This struct is for reference only.
9067dc74f1SOleksij Rempel  */
9167dc74f1SOleksij Rempel struct ath_ht20_40_fft_packet {
9267dc74f1SOleksij Rempel 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
9367dc74f1SOleksij Rempel 	struct ath_ht20_40_mag_info mag_info;
9467dc74f1SOleksij Rempel 	struct ath_radar_info radar_info;
9567dc74f1SOleksij Rempel } __packed;
9667dc74f1SOleksij Rempel 
9767dc74f1SOleksij Rempel struct ath_spec_scan_priv {
9867dc74f1SOleksij Rempel 	struct ath_hw *ah;
9967dc74f1SOleksij Rempel 	/* relay(fs) channel for spectral scan */
10067dc74f1SOleksij Rempel 	struct rchan *rfs_chan_spec_scan;
10167dc74f1SOleksij Rempel 	enum spectral_mode spectral_mode;
10267dc74f1SOleksij Rempel 	struct ath_spec_scan spec_config;
10367dc74f1SOleksij Rempel };
10467dc74f1SOleksij Rempel 
10567dc74f1SOleksij Rempel #define SPECTRAL_HT20_40_TOTAL_DATA_LEN	(sizeof(struct ath_ht20_40_fft_packet))
10658b5e4c7SNick Kossifidis #define	SPECTRAL_HT20_40_SAMPLE_LEN	(sizeof(struct ath_ht20_40_mag_info) +\
10758b5e4c7SNick Kossifidis 					SPECTRAL_HT20_40_NUM_BINS)
10858b5e4c7SNick Kossifidis 
10958b5e4c7SNick Kossifidis #define	SPECTRAL_SAMPLE_MAX_LEN		SPECTRAL_HT20_40_SAMPLE_LEN
11067dc74f1SOleksij Rempel 
11167dc74f1SOleksij Rempel /* grabs the max magnitude from the all/upper/lower bins */
spectral_max_magnitude(u8 * bins)11267dc74f1SOleksij Rempel static inline u16 spectral_max_magnitude(u8 *bins)
11367dc74f1SOleksij Rempel {
11467dc74f1SOleksij Rempel 	return (bins[0] & 0xc0) >> 6 |
11567dc74f1SOleksij Rempel 	       (bins[1] & 0xff) << 2 |
11667dc74f1SOleksij Rempel 	       (bins[2] & 0x03) << 10;
11767dc74f1SOleksij Rempel }
11867dc74f1SOleksij Rempel 
11967dc74f1SOleksij Rempel /* return the max magnitude from the all/upper/lower bins */
spectral_max_index(u8 * bins,int num_bins)120e33f855dSNick Kossifidis static inline u8 spectral_max_index(u8 *bins, int num_bins)
12167dc74f1SOleksij Rempel {
12267dc74f1SOleksij Rempel 	s8 m = (bins[2] & 0xfc) >> 2;
123e33f855dSNick Kossifidis 	u8 zero_idx = num_bins / 2;
12467dc74f1SOleksij Rempel 
125e33f855dSNick Kossifidis 	/* It's a 5 bit signed int, remove its sign and use one's
126e33f855dSNick Kossifidis 	 * complement interpretation to add the sign back to the 8
127e33f855dSNick Kossifidis 	 * bit int
128e33f855dSNick Kossifidis 	 */
129e33f855dSNick Kossifidis 	if (m & 0x20) {
130e33f855dSNick Kossifidis 		m &= ~0x20;
13167dc74f1SOleksij Rempel 		m |= 0xe0;
132e33f855dSNick Kossifidis 	}
13367dc74f1SOleksij Rempel 
134e33f855dSNick Kossifidis 	/* Bring the zero point to the beginning
135e33f855dSNick Kossifidis 	 * instead of the middle so that we can use
136e33f855dSNick Kossifidis 	 * it for array lookup and that we don't deal
137e33f855dSNick Kossifidis 	 * with negative values later
138e33f855dSNick Kossifidis 	 */
139e33f855dSNick Kossifidis 	m += zero_idx;
140e33f855dSNick Kossifidis 
141e33f855dSNick Kossifidis 	/* Sanity check to make sure index is within bounds */
142e33f855dSNick Kossifidis 	if (m < 0 || m > num_bins - 1)
143e33f855dSNick Kossifidis 		m = 0;
144e33f855dSNick Kossifidis 
145e33f855dSNick Kossifidis 	return m;
14667dc74f1SOleksij Rempel }
14767dc74f1SOleksij Rempel 
spectral_max_index_ht40(u8 * bins)148*2f85786bSSimon Wunderlich static inline u8 spectral_max_index_ht40(u8 *bins)
149*2f85786bSSimon Wunderlich {
150*2f85786bSSimon Wunderlich 	u8 idx;
151*2f85786bSSimon Wunderlich 
152*2f85786bSSimon Wunderlich 	idx = spectral_max_index(bins, SPECTRAL_HT20_40_NUM_BINS);
153*2f85786bSSimon Wunderlich 
154*2f85786bSSimon Wunderlich 	/* positive values and zero are starting at the beginning
155*2f85786bSSimon Wunderlich 	 * of the data field.
156*2f85786bSSimon Wunderlich 	 */
157*2f85786bSSimon Wunderlich 	return idx % (SPECTRAL_HT20_40_NUM_BINS / 2);
158*2f85786bSSimon Wunderlich }
159*2f85786bSSimon Wunderlich 
spectral_max_index_ht20(u8 * bins)160*2f85786bSSimon Wunderlich static inline u8 spectral_max_index_ht20(u8 *bins)
161*2f85786bSSimon Wunderlich {
162*2f85786bSSimon Wunderlich 	return spectral_max_index(bins, SPECTRAL_HT20_NUM_BINS);
163*2f85786bSSimon Wunderlich }
164*2f85786bSSimon Wunderlich 
16567dc74f1SOleksij Rempel /* return the bitmap weight from the all/upper/lower bins */
spectral_bitmap_weight(u8 * bins)16667dc74f1SOleksij Rempel static inline u8 spectral_bitmap_weight(u8 *bins)
16767dc74f1SOleksij Rempel {
16867dc74f1SOleksij Rempel 	return bins[0] & 0x3f;
16967dc74f1SOleksij Rempel }
17067dc74f1SOleksij Rempel 
1719df7ddc3SMatthias Schiffer #ifdef CONFIG_ATH9K_COMMON_SPECTRAL
17267dc74f1SOleksij Rempel void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
17367dc74f1SOleksij Rempel void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
17467dc74f1SOleksij Rempel 
17567dc74f1SOleksij Rempel void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
17667dc74f1SOleksij Rempel 				 struct ath_spec_scan_priv *spec_priv);
17767dc74f1SOleksij Rempel int ath9k_cmn_spectral_scan_config(struct ath_common *common,
17867dc74f1SOleksij Rempel 			       struct ath_spec_scan_priv *spec_priv,
17967dc74f1SOleksij Rempel 			       enum spectral_mode spectral_mode);
18067dc74f1SOleksij Rempel int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
18167dc74f1SOleksij Rempel 		    struct ath_rx_status *rs, u64 tsf);
1821077ec47SChristian Lamparter #else
ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv * spec_priv,struct dentry * debugfs_phy)1831077ec47SChristian Lamparter static inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
1841077ec47SChristian Lamparter 						 struct dentry *debugfs_phy)
1851077ec47SChristian Lamparter {
1861077ec47SChristian Lamparter }
1871077ec47SChristian Lamparter 
ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv * spec_priv)1881077ec47SChristian Lamparter static inline void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
1891077ec47SChristian Lamparter {
1901077ec47SChristian Lamparter }
1911077ec47SChristian Lamparter 
ath9k_cmn_spectral_scan_trigger(struct ath_common * common,struct ath_spec_scan_priv * spec_priv)1921077ec47SChristian Lamparter static inline void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
1931077ec47SChristian Lamparter 						   struct ath_spec_scan_priv *spec_priv)
1941077ec47SChristian Lamparter {
1951077ec47SChristian Lamparter }
1961077ec47SChristian Lamparter 
ath_cmn_process_fft(struct ath_spec_scan_priv * spec_priv,struct ieee80211_hdr * hdr,struct ath_rx_status * rs,u64 tsf)1971077ec47SChristian Lamparter static inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv,
1981077ec47SChristian Lamparter 				      struct ieee80211_hdr *hdr,
1991077ec47SChristian Lamparter 				      struct ath_rx_status *rs, u64 tsf)
2001077ec47SChristian Lamparter {
2011077ec47SChristian Lamparter 	return 0;
2021077ec47SChristian Lamparter }
2039df7ddc3SMatthias Schiffer #endif /* CONFIG_ATH9K_COMMON_SPECTRAL */
20467dc74f1SOleksij Rempel 
20567dc74f1SOleksij Rempel #endif /* SPECTRAL_H */
206