162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2013 Qualcomm Atheros, Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#ifndef SPECTRAL_H 1862306a36Sopenharmony_ci#define SPECTRAL_H 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "../spectral_common.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* enum spectral_mode: 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * @SPECTRAL_DISABLED: spectral mode is disabled 2562306a36Sopenharmony_ci * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with 2662306a36Sopenharmony_ci * something else. 2762306a36Sopenharmony_ci * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples 2862306a36Sopenharmony_ci * is performed manually. 2962306a36Sopenharmony_ci * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels 3062306a36Sopenharmony_ci * during a channel scan. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_cienum spectral_mode { 3362306a36Sopenharmony_ci SPECTRAL_DISABLED = 0, 3462306a36Sopenharmony_ci SPECTRAL_BACKGROUND, 3562306a36Sopenharmony_ci SPECTRAL_MANUAL, 3662306a36Sopenharmony_ci SPECTRAL_CHANSCAN, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define SPECTRAL_SCAN_BITMASK 0x10 4062306a36Sopenharmony_ci/* Radar info packet format, used for DFS and spectral formats. */ 4162306a36Sopenharmony_cistruct ath_radar_info { 4262306a36Sopenharmony_ci u8 pulse_length_pri; 4362306a36Sopenharmony_ci u8 pulse_length_ext; 4462306a36Sopenharmony_ci u8 pulse_bw_info; 4562306a36Sopenharmony_ci} __packed; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* The HT20 spectral data has 4 bytes of additional information at it's end. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} 5062306a36Sopenharmony_ci * [7:0]: all bins max_magnitude[9:2] 5162306a36Sopenharmony_ci * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} 5262306a36Sopenharmony_ci * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistruct ath_ht20_mag_info { 5562306a36Sopenharmony_ci u8 all_bins[3]; 5662306a36Sopenharmony_ci u8 max_exp; 5762306a36Sopenharmony_ci} __packed; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* WARNING: don't actually use this struct! MAC may vary the amount of 6062306a36Sopenharmony_ci * data by -1/+2. This struct is for reference only. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistruct ath_ht20_fft_packet { 6362306a36Sopenharmony_ci u8 data[SPECTRAL_HT20_NUM_BINS]; 6462306a36Sopenharmony_ci struct ath_ht20_mag_info mag_info; 6562306a36Sopenharmony_ci struct ath_radar_info radar_info; 6662306a36Sopenharmony_ci} __packed; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) 6962306a36Sopenharmony_ci#define SPECTRAL_HT20_SAMPLE_LEN (sizeof(struct ath_ht20_mag_info) +\ 7062306a36Sopenharmony_ci SPECTRAL_HT20_NUM_BINS) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* Dynamic 20/40 mode: 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} 7562306a36Sopenharmony_ci * [7:0]: lower bins max_magnitude[9:2] 7662306a36Sopenharmony_ci * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} 7762306a36Sopenharmony_ci * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} 7862306a36Sopenharmony_ci * [7:0]: upper bins max_magnitude[9:2] 7962306a36Sopenharmony_ci * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} 8062306a36Sopenharmony_ci * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cistruct ath_ht20_40_mag_info { 8362306a36Sopenharmony_ci u8 lower_bins[3]; 8462306a36Sopenharmony_ci u8 upper_bins[3]; 8562306a36Sopenharmony_ci u8 max_exp; 8662306a36Sopenharmony_ci} __packed; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* WARNING: don't actually use this struct! MAC may vary the amount of 8962306a36Sopenharmony_ci * data. This struct is for reference only. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistruct ath_ht20_40_fft_packet { 9262306a36Sopenharmony_ci u8 data[SPECTRAL_HT20_40_NUM_BINS]; 9362306a36Sopenharmony_ci struct ath_ht20_40_mag_info mag_info; 9462306a36Sopenharmony_ci struct ath_radar_info radar_info; 9562306a36Sopenharmony_ci} __packed; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistruct ath_spec_scan_priv { 9862306a36Sopenharmony_ci struct ath_hw *ah; 9962306a36Sopenharmony_ci /* relay(fs) channel for spectral scan */ 10062306a36Sopenharmony_ci struct rchan *rfs_chan_spec_scan; 10162306a36Sopenharmony_ci enum spectral_mode spectral_mode; 10262306a36Sopenharmony_ci struct ath_spec_scan spec_config; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) 10662306a36Sopenharmony_ci#define SPECTRAL_HT20_40_SAMPLE_LEN (sizeof(struct ath_ht20_40_mag_info) +\ 10762306a36Sopenharmony_ci SPECTRAL_HT20_40_NUM_BINS) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define SPECTRAL_SAMPLE_MAX_LEN SPECTRAL_HT20_40_SAMPLE_LEN 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* grabs the max magnitude from the all/upper/lower bins */ 11262306a36Sopenharmony_cistatic inline u16 spectral_max_magnitude(u8 *bins) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci return (bins[0] & 0xc0) >> 6 | 11562306a36Sopenharmony_ci (bins[1] & 0xff) << 2 | 11662306a36Sopenharmony_ci (bins[2] & 0x03) << 10; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* return the max magnitude from the all/upper/lower bins */ 12062306a36Sopenharmony_cistatic inline u8 spectral_max_index(u8 *bins, int num_bins) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci s8 m = (bins[2] & 0xfc) >> 2; 12362306a36Sopenharmony_ci u8 zero_idx = num_bins / 2; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* It's a 5 bit signed int, remove its sign and use one's 12662306a36Sopenharmony_ci * complement interpretation to add the sign back to the 8 12762306a36Sopenharmony_ci * bit int 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci if (m & 0x20) { 13062306a36Sopenharmony_ci m &= ~0x20; 13162306a36Sopenharmony_ci m |= 0xe0; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* Bring the zero point to the beginning 13562306a36Sopenharmony_ci * instead of the middle so that we can use 13662306a36Sopenharmony_ci * it for array lookup and that we don't deal 13762306a36Sopenharmony_ci * with negative values later 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci m += zero_idx; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Sanity check to make sure index is within bounds */ 14262306a36Sopenharmony_ci if (m < 0 || m > num_bins - 1) 14362306a36Sopenharmony_ci m = 0; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return m; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic inline u8 spectral_max_index_ht40(u8 *bins) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci u8 idx; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci idx = spectral_max_index(bins, SPECTRAL_HT20_40_NUM_BINS); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* positive values and zero are starting at the beginning 15562306a36Sopenharmony_ci * of the data field. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci return idx % (SPECTRAL_HT20_40_NUM_BINS / 2); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic inline u8 spectral_max_index_ht20(u8 *bins) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci return spectral_max_index(bins, SPECTRAL_HT20_NUM_BINS); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* return the bitmap weight from the all/upper/lower bins */ 16662306a36Sopenharmony_cistatic inline u8 spectral_bitmap_weight(u8 *bins) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci return bins[0] & 0x3f; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_SPECTRAL 17262306a36Sopenharmony_civoid ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); 17362306a36Sopenharmony_civoid ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_civoid ath9k_cmn_spectral_scan_trigger(struct ath_common *common, 17662306a36Sopenharmony_ci struct ath_spec_scan_priv *spec_priv); 17762306a36Sopenharmony_ciint ath9k_cmn_spectral_scan_config(struct ath_common *common, 17862306a36Sopenharmony_ci struct ath_spec_scan_priv *spec_priv, 17962306a36Sopenharmony_ci enum spectral_mode spectral_mode); 18062306a36Sopenharmony_ciint ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, 18162306a36Sopenharmony_ci struct ath_rx_status *rs, u64 tsf); 18262306a36Sopenharmony_ci#else 18362306a36Sopenharmony_cistatic inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, 18462306a36Sopenharmony_ci struct dentry *debugfs_phy) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic inline void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic inline void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, 19362306a36Sopenharmony_ci struct ath_spec_scan_priv *spec_priv) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, 19862306a36Sopenharmony_ci struct ieee80211_hdr *hdr, 19962306a36Sopenharmony_ci struct ath_rx_status *rs, u64 tsf) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci return 0; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci#endif /* CONFIG_ATH9K_COMMON_SPECTRAL */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci#endif /* SPECTRAL_H */ 206