|
@@ -234,6 +234,76 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
|
|
|
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
|
|
|
}
|
|
|
|
|
|
+void ath9k_spectral_scan_trigger(struct ath_common *common,
|
|
|
+ struct ath_spec_scan_priv *spec_priv)
|
|
|
+{
|
|
|
+ struct ath_hw *ah = spec_priv->ah;
|
|
|
+ u32 rxfilter;
|
|
|
+
|
|
|
+ if (config_enabled(CONFIG_ATH9K_TX99))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
|
|
+ ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ath_ps_ops(common)->wakeup(common);
|
|
|
+ rxfilter = ath9k_hw_getrxfilter(ah);
|
|
|
+ ath9k_hw_setrxfilter(ah, rxfilter |
|
|
|
+ ATH9K_RX_FILTER_PHYRADAR |
|
|
|
+ ATH9K_RX_FILTER_PHYERR);
|
|
|
+
|
|
|
+ /* TODO: usually this should not be neccesary, but for some reason
|
|
|
+ * (or in some mode?) the trigger must be called after the
|
|
|
+ * configuration, otherwise the register will have its values reset
|
|
|
+ * (on my ar9220 to value 0x01002310)
|
|
|
+ */
|
|
|
+ ath9k_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode);
|
|
|
+ ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
|
|
|
+ ath_ps_ops(common)->restore(common);
|
|
|
+}
|
|
|
+
|
|
|
+int ath9k_spectral_scan_config(struct ath_common *common,
|
|
|
+ struct ath_spec_scan_priv *spec_priv,
|
|
|
+ enum spectral_mode spectral_mode)
|
|
|
+{
|
|
|
+ struct ath_hw *ah = spec_priv->ah;
|
|
|
+
|
|
|
+ if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
|
|
+ ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (spectral_mode) {
|
|
|
+ case SPECTRAL_DISABLED:
|
|
|
+ spec_priv->spec_config.enabled = 0;
|
|
|
+ break;
|
|
|
+ case SPECTRAL_BACKGROUND:
|
|
|
+ /* send endless samples.
|
|
|
+ * TODO: is this really useful for "background"?
|
|
|
+ */
|
|
|
+ spec_priv->spec_config.endless = 1;
|
|
|
+ spec_priv->spec_config.enabled = 1;
|
|
|
+ break;
|
|
|
+ case SPECTRAL_CHANSCAN:
|
|
|
+ case SPECTRAL_MANUAL:
|
|
|
+ spec_priv->spec_config.endless = 0;
|
|
|
+ spec_priv->spec_config.enabled = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ath_ps_ops(common)->wakeup(common);
|
|
|
+ ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config);
|
|
|
+ ath_ps_ops(common)->restore(common);
|
|
|
+
|
|
|
+ spec_priv->spectral_mode = spectral_mode;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t write_file_spec_scan_ctl(struct file *file,
|
|
|
const char __user *user_buf,
|
|
|
size_t count, loff_t *ppos)
|