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