18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2013 Qualcomm Atheros, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#ifndef SPECTRAL_H 188c2ecf20Sopenharmony_ci#define SPECTRAL_H 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "../spectral_common.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* enum spectral_mode: 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * @SPECTRAL_DISABLED: spectral mode is disabled 258c2ecf20Sopenharmony_ci * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with 268c2ecf20Sopenharmony_ci * something else. 278c2ecf20Sopenharmony_ci * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples 288c2ecf20Sopenharmony_ci * is performed manually. 298c2ecf20Sopenharmony_ci * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels 308c2ecf20Sopenharmony_ci * during a channel scan. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_cienum spectral_mode { 338c2ecf20Sopenharmony_ci SPECTRAL_DISABLED = 0, 348c2ecf20Sopenharmony_ci SPECTRAL_BACKGROUND, 358c2ecf20Sopenharmony_ci SPECTRAL_MANUAL, 368c2ecf20Sopenharmony_ci SPECTRAL_CHANSCAN, 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define SPECTRAL_SCAN_BITMASK 0x10 408c2ecf20Sopenharmony_ci/* Radar info packet format, used for DFS and spectral formats. */ 418c2ecf20Sopenharmony_cistruct ath_radar_info { 428c2ecf20Sopenharmony_ci u8 pulse_length_pri; 438c2ecf20Sopenharmony_ci u8 pulse_length_ext; 448c2ecf20Sopenharmony_ci u8 pulse_bw_info; 458c2ecf20Sopenharmony_ci} __packed; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* The HT20 spectral data has 4 bytes of additional information at it's end. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} 508c2ecf20Sopenharmony_ci * [7:0]: all bins max_magnitude[9:2] 518c2ecf20Sopenharmony_ci * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} 528c2ecf20Sopenharmony_ci * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_cistruct ath_ht20_mag_info { 558c2ecf20Sopenharmony_ci u8 all_bins[3]; 568c2ecf20Sopenharmony_ci u8 max_exp; 578c2ecf20Sopenharmony_ci} __packed; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* WARNING: don't actually use this struct! MAC may vary the amount of 608c2ecf20Sopenharmony_ci * data by -1/+2. This struct is for reference only. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistruct ath_ht20_fft_packet { 638c2ecf20Sopenharmony_ci u8 data[SPECTRAL_HT20_NUM_BINS]; 648c2ecf20Sopenharmony_ci struct ath_ht20_mag_info mag_info; 658c2ecf20Sopenharmony_ci struct ath_radar_info radar_info; 668c2ecf20Sopenharmony_ci} __packed; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) 698c2ecf20Sopenharmony_ci#define SPECTRAL_HT20_SAMPLE_LEN (sizeof(struct ath_ht20_mag_info) +\ 708c2ecf20Sopenharmony_ci SPECTRAL_HT20_NUM_BINS) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* Dynamic 20/40 mode: 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} 758c2ecf20Sopenharmony_ci * [7:0]: lower bins max_magnitude[9:2] 768c2ecf20Sopenharmony_ci * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} 778c2ecf20Sopenharmony_ci * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} 788c2ecf20Sopenharmony_ci * [7:0]: upper bins max_magnitude[9:2] 798c2ecf20Sopenharmony_ci * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} 808c2ecf20Sopenharmony_ci * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_cistruct ath_ht20_40_mag_info { 838c2ecf20Sopenharmony_ci u8 lower_bins[3]; 848c2ecf20Sopenharmony_ci u8 upper_bins[3]; 858c2ecf20Sopenharmony_ci u8 max_exp; 868c2ecf20Sopenharmony_ci} __packed; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* WARNING: don't actually use this struct! MAC may vary the amount of 898c2ecf20Sopenharmony_ci * data. This struct is for reference only. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistruct ath_ht20_40_fft_packet { 928c2ecf20Sopenharmony_ci u8 data[SPECTRAL_HT20_40_NUM_BINS]; 938c2ecf20Sopenharmony_ci struct ath_ht20_40_mag_info mag_info; 948c2ecf20Sopenharmony_ci struct ath_radar_info radar_info; 958c2ecf20Sopenharmony_ci} __packed; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistruct ath_spec_scan_priv { 988c2ecf20Sopenharmony_ci struct ath_hw *ah; 998c2ecf20Sopenharmony_ci /* relay(fs) channel for spectral scan */ 1008c2ecf20Sopenharmony_ci struct rchan *rfs_chan_spec_scan; 1018c2ecf20Sopenharmony_ci enum spectral_mode spectral_mode; 1028c2ecf20Sopenharmony_ci struct ath_spec_scan spec_config; 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) 1068c2ecf20Sopenharmony_ci#define SPECTRAL_HT20_40_SAMPLE_LEN (sizeof(struct ath_ht20_40_mag_info) +\ 1078c2ecf20Sopenharmony_ci SPECTRAL_HT20_40_NUM_BINS) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define SPECTRAL_SAMPLE_MAX_LEN SPECTRAL_HT20_40_SAMPLE_LEN 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* grabs the max magnitude from the all/upper/lower bins */ 1128c2ecf20Sopenharmony_cistatic inline u16 spectral_max_magnitude(u8 *bins) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci return (bins[0] & 0xc0) >> 6 | 1158c2ecf20Sopenharmony_ci (bins[1] & 0xff) << 2 | 1168c2ecf20Sopenharmony_ci (bins[2] & 0x03) << 10; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* return the max magnitude from the all/upper/lower bins */ 1208c2ecf20Sopenharmony_cistatic inline u8 spectral_max_index(u8 *bins, int num_bins) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci s8 m = (bins[2] & 0xfc) >> 2; 1238c2ecf20Sopenharmony_ci u8 zero_idx = num_bins / 2; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* It's a 5 bit signed int, remove its sign and use one's 1268c2ecf20Sopenharmony_ci * complement interpretation to add the sign back to the 8 1278c2ecf20Sopenharmony_ci * bit int 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci if (m & 0x20) { 1308c2ecf20Sopenharmony_ci m &= ~0x20; 1318c2ecf20Sopenharmony_ci m |= 0xe0; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* Bring the zero point to the beginning 1358c2ecf20Sopenharmony_ci * instead of the middle so that we can use 1368c2ecf20Sopenharmony_ci * it for array lookup and that we don't deal 1378c2ecf20Sopenharmony_ci * with negative values later 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci m += zero_idx; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Sanity check to make sure index is within bounds */ 1428c2ecf20Sopenharmony_ci if (m < 0 || m > num_bins - 1) 1438c2ecf20Sopenharmony_ci m = 0; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci return m; 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic inline u8 spectral_max_index_ht40(u8 *bins) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci u8 idx; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci idx = spectral_max_index(bins, SPECTRAL_HT20_40_NUM_BINS); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* positive values and zero are starting at the beginning 1558c2ecf20Sopenharmony_ci * of the data field. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci return idx % (SPECTRAL_HT20_40_NUM_BINS / 2); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic inline u8 spectral_max_index_ht20(u8 *bins) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci return spectral_max_index(bins, SPECTRAL_HT20_NUM_BINS); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* return the bitmap weight from the all/upper/lower bins */ 1668c2ecf20Sopenharmony_cistatic inline u8 spectral_bitmap_weight(u8 *bins) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci return bins[0] & 0x3f; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_SPECTRAL 1728c2ecf20Sopenharmony_civoid ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); 1738c2ecf20Sopenharmony_civoid ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_civoid ath9k_cmn_spectral_scan_trigger(struct ath_common *common, 1768c2ecf20Sopenharmony_ci struct ath_spec_scan_priv *spec_priv); 1778c2ecf20Sopenharmony_ciint ath9k_cmn_spectral_scan_config(struct ath_common *common, 1788c2ecf20Sopenharmony_ci struct ath_spec_scan_priv *spec_priv, 1798c2ecf20Sopenharmony_ci enum spectral_mode spectral_mode); 1808c2ecf20Sopenharmony_ciint ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, 1818c2ecf20Sopenharmony_ci struct ath_rx_status *rs, u64 tsf); 1828c2ecf20Sopenharmony_ci#else 1838c2ecf20Sopenharmony_cistatic inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, 1848c2ecf20Sopenharmony_ci struct dentry *debugfs_phy) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic inline void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic inline void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, 1938c2ecf20Sopenharmony_ci struct ath_spec_scan_priv *spec_priv) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, 1988c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr, 1998c2ecf20Sopenharmony_ci struct ath_rx_status *rs, u64 tsf) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci return 0; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci#endif /* CONFIG_ATH9K_COMMON_SPECTRAL */ 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#endif /* SPECTRAL_H */ 206