/*
 * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved.
 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include <qdf_types.h>
#include "wlan_dfs_ioctl.h"
#include <spectral_ioctl.h>

#ifndef __KERNEL__
#include <math.h>
#endif /*  __KERNEL__  */

#ifndef _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_
#define _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_

#ifndef AH_MAX_CHAINS
#define AH_MAX_CHAINS 3
#endif

#define MAX_NUM_CHANNELS             255
#define SPECTRAL_PHYERR_PARAM_NOVAL  65535

#ifdef SPECTRAL_USE_EMU_DEFAULTS
/* Use defaults from emulation */
#define SPECTRAL_SCAN_ACTIVE_DEFAULT           (0x0)
#define SPECTRAL_SCAN_ENABLE_DEFAULT           (0x0)
#define SPECTRAL_SCAN_COUNT_DEFAULT            (0x0)
#define SPECTRAL_SCAN_PERIOD_DEFAULT           (250)
#define SPECTRAL_SCAN_PRIORITY_DEFAULT         (0x1)
#define SPECTRAL_SCAN_FFT_SIZE_DEFAULT         (0x7)
#define SPECTRAL_SCAN_GC_ENA_DEFAULT           (0x1)
#define SPECTRAL_SCAN_RESTART_ENA_DEFAULT      (0x0)
#define SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT  (0xa0)
#define SPECTRAL_SCAN_INIT_DELAY_DEFAULT       (0x50)
#define SPECTRAL_SCAN_NB_TONE_THR_DEFAULT      (0xc)
#define SPECTRAL_SCAN_STR_BIN_THR_DEFAULT      (0x7)
#define SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT      (0x0)
#define SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT    (0x1)
#define SPECTRAL_SCAN_RSSI_THR_DEFAULT         (0xf)
#define SPECTRAL_SCAN_PWR_FORMAT_DEFAULT       (0x1)
#define SPECTRAL_SCAN_RPT_MODE_DEFAULT         (0x2)
#define SPECTRAL_SCAN_BIN_SCALE_DEFAULT        (0x1)
#define SPECTRAL_SCAN_DBM_ADJ_DEFAULT          (0x0)
#define SPECTRAL_SCAN_CHN_MASK_DEFAULT         (0x1)
#else
/*
 * Static default values for spectral state and configuration.
 * These definitions should be treated as temporary. Ideally,
 * we should get the defaults from firmware - this will be discussed.
 *
 * Use defaults from Spectral Hardware Micro-Architecture
 * document (v1.0)
 */
#define SPECTRAL_SCAN_ACTIVE_DEFAULT           (0)
#define SPECTRAL_SCAN_ENABLE_DEFAULT           (0)
#define SPECTRAL_SCAN_COUNT_DEFAULT            (0)
#define SPECTRAL_SCAN_PERIOD_GEN_I_DEFAULT     (35)
#define SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT    (35)
#define SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT   (224)
#define SPECTRAL_SCAN_PRIORITY_DEFAULT         (1)
#define SPECTRAL_SCAN_FFT_SIZE_DEFAULT         (7)
#define SPECTRAL_SCAN_GC_ENA_DEFAULT           (1)
#define SPECTRAL_SCAN_RESTART_ENA_DEFAULT      (0)
#define SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT  (-96)
#define SPECTRAL_SCAN_INIT_DELAY_DEFAULT       (80)
#define SPECTRAL_SCAN_NB_TONE_THR_DEFAULT      (12)
#define SPECTRAL_SCAN_STR_BIN_THR_DEFAULT      (8)
#define SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT      (0)
#define SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT    (0)
#define SPECTRAL_SCAN_RSSI_THR_DEFAULT         (0xf0)
#define SPECTRAL_SCAN_PWR_FORMAT_DEFAULT       (0)
#define SPECTRAL_SCAN_RPT_MODE_DEFAULT         (2)
#define SPECTRAL_SCAN_BIN_SCALE_DEFAULT        (1)
#define SPECTRAL_SCAN_DBM_ADJ_DEFAULT          (1)
#define SPECTRAL_SCAN_CHN_MASK_DEFAULT         (1)
#define SPECTRAL_SCAN_FREQUENCY_DEFAULT        (0)
#define SPECTRAL_FFT_RECAPTURE_DEFAULT         (0)
#endif				/* SPECTRAL_USE_EMU_DEFAULTS */

/* The below two definitions apply only to pre-11ac chipsets */
#define SPECTRAL_SCAN_SHORT_REPORT_DEFAULT     (1)
#define SPECTRAL_SCAN_FFT_PERIOD_DEFAULT       (1)

/*
 * Definitions to help in scaling of gen3 linear format Spectral bins to values
 * similar to those from gen2 chipsets.
 */

/*
 * Max gain for QCA9984. Since this chipset is a prime representative of gen2
 * chipsets, it is chosen for this value.
 */
#define SPECTRAL_QCA9984_MAX_GAIN                               (78)

/* Temporary section for hard-coded values. These need to come from FW. */

/* Max gain for IPQ8074 */
#define SPECTRAL_IPQ8074_DEFAULT_MAX_GAIN_HARDCODE              (62)

/*
 * Section for values needing tuning per customer platform. These too may need
 * to come from FW. To be considered as hard-coded for now.
 */

/*
 * If customers have a different gain line up than QCA reference designs for
 * IPQ8074 and/or QCA9984, they may have to tune the low level threshold and
 * the RSSI threshold.
 */
#define SPECTRAL_SCALING_LOW_LEVEL_OFFSET                       (7)
#define SPECTRAL_SCALING_RSSI_THRESH                            (5)

/*
 * If customers set the AGC backoff differently, they may have to tune the high
 * level threshold.
 */
#define SPECTRAL_SCALING_HIGH_LEVEL_OFFSET                      (5)

/* End of section for values needing fine tuning. */
/* End of temporary section for hard-coded values */

/**
 * enum spectral_msg_buf_type - Spectral message buffer type
 * @SPECTRAL_MSG_BUF_NEW: Allocate new buffer
 * @SPECTRAL_MSG_BUF_SAVED: Reuse last buffer, used for secondary segment report
 *                          in case of 160 MHz.
 * @SPECTRAL_MSG_BUF_TYPE_MAX: Max enumeration
 */
enum spectral_msg_buf_type {
	SPECTRAL_MSG_BUF_NEW,
	SPECTRAL_MSG_BUF_SAVED,
	SPECTRAL_MSG_BUF_TYPE_MAX,
};

/**
 * enum spectral_msg_type - Spectral SAMP message type
 * @SPECTRAL_MSG_NORMAL_MODE: Normal mode Spectral SAMP message
 * @SPECTRAL_MSG_AGILE_MODE: Agile mode Spectral SAMP message
 * @SPECTRAL_MSG_INTERFERENCE_NOTIFICATION: Interference notification to
 *                                          external auto channel selection
 *                                          entity
 * @SPECTRAL_MSG_TYPE_MAX: Spectral SAMP message type max
 */
enum spectral_msg_type {
	SPECTRAL_MSG_NORMAL_MODE,
	SPECTRAL_MSG_AGILE_MODE,
	SPECTRAL_MSG_INTERFERENCE_NOTIFICATION,
	SPECTRAL_MSG_TYPE_MAX,
};

/**
 * enum spectral_debug - Spectral debug level
 * @DEBUG_SPECTRAL:  Minimal SPECTRAL debug
 * @DEBUG_SPECTRAL1: Normal SPECTRAL debug
 * @DEBUG_SPECTRAL2: Maximal SPECTRAL debug
 * @DEBUG_SPECTRAL3: Matched filterID display
 * @DEBUG_SPECTRAL4: One time dump of FFT report
 */
enum spectral_debug {
	DEBUG_SPECTRAL = 0x00000100,
	DEBUG_SPECTRAL1 = 0x00000200,
	DEBUG_SPECTRAL2 = 0x00000400,
	DEBUG_SPECTRAL3 = 0x00000800,
	DEBUG_SPECTRAL4 = 0x00001000,
};

/**
 * enum spectral_capability_type - Spectral capability type
 * @SPECTRAL_CAP_PHYDIAG:              Phydiag capability
 * @SPECTRAL_CAP_RADAR:                Radar detection capability
 * @SPECTRAL_CAP_SPECTRAL_SCAN:        Spectral capability
 * @SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN: Advanced spectral capability
 */
enum spectral_capability_type {
	SPECTRAL_CAP_PHYDIAG,
	SPECTRAL_CAP_RADAR,
	SPECTRAL_CAP_SPECTRAL_SCAN,
	SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN,
};

/**
 * enum spectral_cp_error_code - Spectral control path response code
 * @SPECTRAL_SCAN_ERR_INVALID: Invalid error identifier
 * @SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED: parameter unsupported
 * @SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED: mode unsupported
 * @SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE: invalid parameter value
 * @SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED: parameter uninitialized
 */
enum spectral_cp_error_code {
	SPECTRAL_SCAN_ERR_INVALID,
	SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED,
	SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED,
	SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE,
	SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED,
};

/**
 * enum spectral_dma_debug -   Spectral DMA debug
 * @SPECTRAL_DMA_RING_DEBUG:   Spectral DMA ring debug
 * @SPECTRAL_DMA_BUFFER_DEBUG: Spectral DMA buffer debug
 */
enum spectral_dma_debug {
	SPECTRAL_DMA_RING_DEBUG,
	SPECTRAL_DMA_BUFFER_DEBUG,
};

struct wiphy;
struct wlan_objmgr_pdev;
struct wlan_objmgr_vdev;
/**
 * struct spectral_cfg80211_vendor_cmd_handlers - Spectral vendor command
 * handlers
 * @wlan_cfg80211_spectral_scan_start: start scan handler
 * @wlan_cfg80211_spectral_scan_stop: stop scan handler
 * @wlan_cfg80211_spectral_scan_get_config: get config handler
 * @wlan_cfg80211_spectral_scan_get_diag_stats: get diag stats handler
 * @wlan_cfg80211_spectral_scan_get_cap: get capability handler
 * @wlan_cfg80211_spectral_scan_get_status: get status handler
 */
struct spectral_cfg80211_vendor_cmd_handlers {
	int (*wlan_cfg80211_spectral_scan_start)(struct wiphy *wiphy,
						 struct wlan_objmgr_pdev *pdev,
						 struct wlan_objmgr_vdev *vdev,
						 const void *data,
						 int data_len);
	int (*wlan_cfg80211_spectral_scan_stop)(struct wiphy *wiphy,
						struct wlan_objmgr_pdev *pdev,
						struct wlan_objmgr_vdev *vdev,
						const void *data,
						int data_len);
	int (*wlan_cfg80211_spectral_scan_get_config)(
						struct wiphy *wiphy,
						struct wlan_objmgr_pdev *pdev,
						struct wlan_objmgr_vdev *vdev,
						const void *data,
						int data_len);
	int (*wlan_cfg80211_spectral_scan_get_diag_stats)(
						struct wiphy *wiphy,
						struct wlan_objmgr_pdev *pdev,
						struct wlan_objmgr_vdev *vdev,
						const void *data,
						int data_len);
	int (*wlan_cfg80211_spectral_scan_get_cap)(
						struct wiphy *wiphy,
						struct wlan_objmgr_pdev *pdev,
						struct wlan_objmgr_vdev *vdev,
						const void *data,
						int data_len);
	int (*wlan_cfg80211_spectral_scan_get_status)(
						struct wiphy *wiphy,
						struct wlan_objmgr_pdev *pdev,
						struct wlan_objmgr_vdev *vdev,
						const void *data,
						int data_len);
};

/**
 * struct spectral_cp_param - Spectral control path data structure which
 * contains parameter and its value
 * @id: Parameter ID
 * @value: Single parameter value
 * @freq: Spectral scan frequency
 */
struct spectral_cp_param {
	uint32_t id;
	union {
		uint32_t value;
		struct spectral_config_frequency freq;
	};
};

/**
 * struct spectral_chan_stats - channel status info
 * @cycle_count:         Cycle count
 * @channel_load:        Channel load
 * @per:                 Period
 * @noisefloor:          Noise floor
 * @comp_usablity:       Computed usability
 * @maxregpower:         Maximum allowed regulatory power
 * @comp_usablity_sec80: Computed usability of secondary 80 Mhz
 * @maxregpower_sec80:   Max regulatory power of secondary 80 Mhz
 */
struct spectral_chan_stats {
	int cycle_count;
	int channel_load;
	int per;
	int noisefloor;
	uint16_t comp_usablity;
	int8_t maxregpower;
	uint16_t comp_usablity_sec80;
	int8_t maxregpower_sec80;
};

/**
 * struct spectral_diag_stats - spectral diag stats
 * @spectral_mismatch:             Spectral TLV signature mismatches
 * @spectral_sec80_sfft_insufflen: Insufficient length when parsing for
 *                                 Secondary 80 Search FFT report
 * @spectral_no_sec80_sfft:        Secondary 80 Search FFT report
 *                                 TLV not found
 * @spectral_vhtseg1id_mismatch:   VHT Operation Segment 1 ID
 *                                 mismatches in Search FFT report
 * @spectral_vhtseg2id_mismatch:   VHT Operation Segment 2 ID
 *                                 mismatches in Search FFT report
 * @spectral_invalid_detector_id:  Invalid detector id
 */
struct spectral_diag_stats {
	uint64_t spectral_mismatch;
	uint64_t spectral_sec80_sfft_insufflen;
	uint64_t spectral_no_sec80_sfft;
	uint64_t spectral_vhtseg1id_mismatch;
	uint64_t spectral_vhtseg2id_mismatch;
	uint64_t spectral_invalid_detector_id;
};

/**
 * struct spectral_scan_state - State of spectral scan
 * @is_active:  Is spectral scan active
 * @is_enabled: Is spectral scan enabled
 */
struct spectral_scan_state {
	uint8_t is_active;
	uint8_t is_enabled;
};

/* Forward declarations */
struct wlan_objmgr_pdev;

/**
 * struct spectral_nl_cb - Spectral Netlink callbacks
 * @get_sbuff:      Get the socket buffer to send the data to the application
 * @send_nl_bcast:  Send data to the application using netlink broadcast
 * @send_nl_unicast:  Send data to the application using netlink unicast
 * @free_sbuff: Free the socket buffer for a particular message type
 * @convert_to_nl_ch_width:
 * @convert_to_phy_ch_width:
 */
struct spectral_nl_cb {
	void *(*get_sbuff)(struct wlan_objmgr_pdev *pdev,
			   enum spectral_msg_type smsg_type,
			   enum spectral_msg_buf_type buf_type);
	int (*send_nl_bcast)(struct wlan_objmgr_pdev *pdev,
			     enum spectral_msg_type smsg_type);
	int (*send_nl_unicast)(struct wlan_objmgr_pdev *pdev,
			       enum spectral_msg_type smsg_type);
	void (*free_sbuff)(struct wlan_objmgr_pdev *pdev,
			   enum spectral_msg_type smsg_type);
	int (*convert_to_nl_ch_width)(uint8_t phy_chwidth);
	uint8_t (*convert_to_phy_ch_width)(uint8_t nl_chwidth);
};

/**
 * struct spectral_scan_config_request - Config request
 * @sscan_config: Spectral parameters
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_config_request {
	struct spectral_config sscan_config;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_action_request - Action request
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_action_request {
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_get_caps_request - Get caps request
 * @sscan_caps: Spectral capabilities
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_get_caps_request {
	struct spectral_caps sscan_caps;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_get_diag_request - Get diag request
 * @sscan_diag: Spectral diag stats
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_get_diag_request {
	struct spectral_diag_stats sscan_diag;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_get_chan_width_request - Get channel width request
 * @chan_width: Channel width
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_get_chan_width_request {
	uint32_t chan_width;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_get_status_request - Get status request
 * @is_active: is Spectral scan active
 * @is_enabled: is Spectral scan enabled
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_get_status_request {
	bool is_active;
	bool is_enabled;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_debug_request - Get/set debug level request
 * @spectral_dbg_level: Spectral debug level
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_debug_request {
	uint32_t spectral_dbg_level;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_scan_dma_debug_request - DMA debug request
 * @dma_debug_enable: Enable/disable @dma_debug_type
 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
 * @sscan_err_code: Spectral scan error code
 */
struct spectral_scan_dma_debug_request {
	bool dma_debug_enable;
	enum spectral_dma_debug dma_debug_type;
	enum spectral_cp_error_code sscan_err_code;
};

/**
 * struct spectral_cp_request - Spectral control path request
 *                              Creating request and extracting response has to
 *                              be atomic.
 * @ss_mode: Spectral scan mode
 * @req_id: Request identifier
 * @vdev_id: VDEV id
 * @config_req: Spectral scan config request
 * @action_req: Spectral scan action request
 * @caps_req: Spectral scan get caps request
 * @diag_req: Spectral scan get diag request
 * @chan_width_req:Spectral scan get chan width request
 * @status_req: Spectral scan get status request
 * @debug_req: Spectral scan debug request
 * @dma_debug_req: Spectral DMA debug request
 */
struct spectral_cp_request {
	enum spectral_scan_mode ss_mode;
	uint8_t req_id;
	uint8_t vdev_id;
	union {
		struct spectral_scan_config_request config_req;
		struct spectral_scan_action_request action_req;
		struct spectral_scan_get_caps_request caps_req;
		struct spectral_scan_get_diag_request diag_req;
		struct spectral_scan_get_chan_width_request chan_width_req;
		struct spectral_scan_get_status_request status_req;
		struct spectral_scan_debug_request debug_req;
		struct spectral_scan_dma_debug_request dma_debug_req;
	};
};

/**
 * struct spectral_data_stats - Spectral data stats
 * @spectral_rx_events: Number of Spectral rx events
 * @consume_spectral_calls: Number of consume_spectral_report() invocations
 * @fill_samp_msg_calls: Number of fill_samp_msg() invocations
 * @msgs_ready_for_user: Number of SAMP messages that are ready to be sent to
 * user-space
 * @msgs_queued_to_user: Number of SAMP messages queued to the user-space
 */
struct spectral_data_stats {
	uint32_t spectral_rx_events;
	uint32_t consume_spectral_calls;
	uint32_t fill_samp_msg_calls;
	uint32_t msgs_ready_for_user;
	uint32_t msgs_queued_to_user;
};

#ifndef __KERNEL__

static inline int16_t
spectral_pwfactor_max(int16_t pwfactor1,
		      int16_t pwfactor2)
{
	return ((pwfactor1 > pwfactor2) ? pwfactor1 : pwfactor2);
}

/**
 * get_spectral_scale_rssi_corr() - Compute RSSI correction factor for scaling
 * @agc_total_gain_db: AGC total gain in dB steps
 * @gen3_defmaxgain: Default max gain value of the gen III chipset
 * @gen2_maxgain: Max gain value used by the reference gen II chipset
 * @lowlevel_offset: Low level offset for scaling
 * @inband_pwr: In band power in dB steps
 * @rssi_thr: RSSI threshold for scaling
 *
 * Helper function to compute RSSI correction factor for Gen III linear format
 * Spectral scaling. It is the responsibility of the caller to ensure that
 * correct values are passed.
 *
 * Return: RSSI correction factor
 */
static inline int16_t
get_spectral_scale_rssi_corr(u_int8_t agc_total_gain_db,
			     u_int8_t gen3_defmaxgain, u_int8_t gen2_maxgain,
			     int16_t lowlevel_offset, int16_t inband_pwr,
			     int16_t rssi_thr)
{
	return ((agc_total_gain_db < gen3_defmaxgain) ?
		(gen2_maxgain - gen3_defmaxgain + lowlevel_offset) :
		spectral_pwfactor_max((inband_pwr - rssi_thr), 0));
}

/**
 * spectral_scale_linear_to_gen2() - Scale linear bin value to gen II equivalent
 * @gen3_binmag: Captured FFT bin value from the Spectral Search FFT report
 * generated by the Gen III chipset
 * @gen2_maxgain: Max gain value used by the reference gen II chipset
 * @gen3_defmaxgain: Default max gain value of the gen III chipset
 * @lowlevel_offset: Low level offset for scaling
 * @inband_pwr: In band power in dB steps
 * @rssi_thr: RSSI threshold for scaling
 * @agc_total_gain_db: AGC total gain in dB steps
 * @highlevel_offset: High level offset for scaling
 * @gen2_bin_scale: Bin scale value used on reference gen II chipset
 * @gen3_bin_scale: Bin scale value used on gen III chipset
 *
 * Helper function to scale a given gen III linear format bin value into an
 * approximately equivalent gen II value. The scaled value can possibly be
 * higher than 8 bits.  If the caller is incapable of handling values larger
 * than 8 bits, the caller can saturate the value at 255. This function does not
 * carry out this saturation for the sake of flexibility so that callers
 * interested in the larger values can avail of this. Also note it is the
 * responsibility of the caller to ensure that correct values are passed.
 *
 * Return: Scaled bin value
 */
static inline u_int32_t
spectral_scale_linear_to_gen2(u_int8_t gen3_binmag,
			      u_int8_t gen2_maxgain, u_int8_t gen3_defmaxgain,
			      int16_t lowlevel_offset, int16_t inband_pwr,
			      int16_t rssi_thr, u_int8_t agc_total_gain_db,
			      int16_t highlevel_offset, u_int8_t gen2_bin_scale,
			      u_int8_t gen3_bin_scale)
{
	return (gen3_binmag *
		sqrt(pow(10, (((double)spectral_pwfactor_max(gen2_maxgain -
			gen3_defmaxgain + lowlevel_offset -
			get_spectral_scale_rssi_corr(agc_total_gain_db,
						     gen3_defmaxgain,
						     gen2_maxgain,
						     lowlevel_offset,
						     inband_pwr,
						     rssi_thr),
			(agc_total_gain_db < gen3_defmaxgain) *
				highlevel_offset)) / 10))) *
		 pow(2, (gen3_bin_scale - gen2_bin_scale)));
}

#endif /*  __KERNEL__  */

#endif				/* _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_ */