18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci  Broadcom B43 wireless driver
58c2ecf20Sopenharmony_ci  IEEE 802.11a/g LP-PHY driver
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci  Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
88c2ecf20Sopenharmony_ci  Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci*/
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/cordic.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "b43.h"
178c2ecf20Sopenharmony_ci#include "main.h"
188c2ecf20Sopenharmony_ci#include "phy_lp.h"
198c2ecf20Sopenharmony_ci#include "phy_common.h"
208c2ecf20Sopenharmony_ci#include "tables_lpphy.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic inline u16 channel2freq_lp(u8 channel)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	if (channel < 14)
268c2ecf20Sopenharmony_ci		return (2407 + 5 * channel);
278c2ecf20Sopenharmony_ci	else if (channel == 14)
288c2ecf20Sopenharmony_ci		return 2484;
298c2ecf20Sopenharmony_ci	else if (channel < 184)
308c2ecf20Sopenharmony_ci		return (5000 + 5 * channel);
318c2ecf20Sopenharmony_ci	else
328c2ecf20Sopenharmony_ci		return (4000 + 5 * channel);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
388c2ecf20Sopenharmony_ci		return 1;
398c2ecf20Sopenharmony_ci	return 36;
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic int b43_lpphy_op_allocate(struct b43_wldev *dev)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	lpphy = kzalloc(sizeof(*lpphy), GFP_KERNEL);
478c2ecf20Sopenharmony_ci	if (!lpphy)
488c2ecf20Sopenharmony_ci		return -ENOMEM;
498c2ecf20Sopenharmony_ci	dev->phy.lp = lpphy;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return 0;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
578c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = phy->lp;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	memset(lpphy, 0, sizeof(*lpphy));
608c2ecf20Sopenharmony_ci	lpphy->antenna = B43_ANTENNA_DEFAULT;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	//TODO
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic void b43_lpphy_op_free(struct b43_wldev *dev)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	kfree(lpphy);
708c2ecf20Sopenharmony_ci	dev->phy.lp = NULL;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
748c2ecf20Sopenharmony_cistatic void lpphy_read_band_sprom(struct b43_wldev *dev)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
778c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
788c2ecf20Sopenharmony_ci	u16 cckpo, maxpwr;
798c2ecf20Sopenharmony_ci	u32 ofdmpo;
808c2ecf20Sopenharmony_ci	int i;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
838c2ecf20Sopenharmony_ci		lpphy->tx_isolation_med_band = sprom->tri2g;
848c2ecf20Sopenharmony_ci		lpphy->bx_arch = sprom->bxa2g;
858c2ecf20Sopenharmony_ci		lpphy->rx_pwr_offset = sprom->rxpo2g;
868c2ecf20Sopenharmony_ci		lpphy->rssi_vf = sprom->rssismf2g;
878c2ecf20Sopenharmony_ci		lpphy->rssi_vc = sprom->rssismc2g;
888c2ecf20Sopenharmony_ci		lpphy->rssi_gs = sprom->rssisav2g;
898c2ecf20Sopenharmony_ci		lpphy->txpa[0] = sprom->pa0b0;
908c2ecf20Sopenharmony_ci		lpphy->txpa[1] = sprom->pa0b1;
918c2ecf20Sopenharmony_ci		lpphy->txpa[2] = sprom->pa0b2;
928c2ecf20Sopenharmony_ci		maxpwr = sprom->maxpwr_bg;
938c2ecf20Sopenharmony_ci		lpphy->max_tx_pwr_med_band = maxpwr;
948c2ecf20Sopenharmony_ci		cckpo = sprom->cck2gpo;
958c2ecf20Sopenharmony_ci		if (cckpo) {
968c2ecf20Sopenharmony_ci			ofdmpo = sprom->ofdm2gpo;
978c2ecf20Sopenharmony_ci			for (i = 0; i < 4; i++) {
988c2ecf20Sopenharmony_ci				lpphy->tx_max_rate[i] =
998c2ecf20Sopenharmony_ci					maxpwr - (ofdmpo & 0xF) * 2;
1008c2ecf20Sopenharmony_ci				ofdmpo >>= 4;
1018c2ecf20Sopenharmony_ci			}
1028c2ecf20Sopenharmony_ci			ofdmpo = sprom->ofdm2gpo;
1038c2ecf20Sopenharmony_ci			for (i = 4; i < 15; i++) {
1048c2ecf20Sopenharmony_ci				lpphy->tx_max_rate[i] =
1058c2ecf20Sopenharmony_ci					maxpwr - (ofdmpo & 0xF) * 2;
1068c2ecf20Sopenharmony_ci				ofdmpo >>= 4;
1078c2ecf20Sopenharmony_ci			}
1088c2ecf20Sopenharmony_ci		} else {
1098c2ecf20Sopenharmony_ci			u8 opo = sprom->opo;
1108c2ecf20Sopenharmony_ci			for (i = 0; i < 4; i++)
1118c2ecf20Sopenharmony_ci				lpphy->tx_max_rate[i] = maxpwr;
1128c2ecf20Sopenharmony_ci			for (i = 4; i < 15; i++)
1138c2ecf20Sopenharmony_ci				lpphy->tx_max_rate[i] = maxpwr - opo;
1148c2ecf20Sopenharmony_ci		}
1158c2ecf20Sopenharmony_ci	} else { /* 5GHz */
1168c2ecf20Sopenharmony_ci		lpphy->tx_isolation_low_band = sprom->tri5gl;
1178c2ecf20Sopenharmony_ci		lpphy->tx_isolation_med_band = sprom->tri5g;
1188c2ecf20Sopenharmony_ci		lpphy->tx_isolation_hi_band = sprom->tri5gh;
1198c2ecf20Sopenharmony_ci		lpphy->bx_arch = sprom->bxa5g;
1208c2ecf20Sopenharmony_ci		lpphy->rx_pwr_offset = sprom->rxpo5g;
1218c2ecf20Sopenharmony_ci		lpphy->rssi_vf = sprom->rssismf5g;
1228c2ecf20Sopenharmony_ci		lpphy->rssi_vc = sprom->rssismc5g;
1238c2ecf20Sopenharmony_ci		lpphy->rssi_gs = sprom->rssisav5g;
1248c2ecf20Sopenharmony_ci		lpphy->txpa[0] = sprom->pa1b0;
1258c2ecf20Sopenharmony_ci		lpphy->txpa[1] = sprom->pa1b1;
1268c2ecf20Sopenharmony_ci		lpphy->txpa[2] = sprom->pa1b2;
1278c2ecf20Sopenharmony_ci		lpphy->txpal[0] = sprom->pa1lob0;
1288c2ecf20Sopenharmony_ci		lpphy->txpal[1] = sprom->pa1lob1;
1298c2ecf20Sopenharmony_ci		lpphy->txpal[2] = sprom->pa1lob2;
1308c2ecf20Sopenharmony_ci		lpphy->txpah[0] = sprom->pa1hib0;
1318c2ecf20Sopenharmony_ci		lpphy->txpah[1] = sprom->pa1hib1;
1328c2ecf20Sopenharmony_ci		lpphy->txpah[2] = sprom->pa1hib2;
1338c2ecf20Sopenharmony_ci		maxpwr = sprom->maxpwr_al;
1348c2ecf20Sopenharmony_ci		ofdmpo = sprom->ofdm5glpo;
1358c2ecf20Sopenharmony_ci		lpphy->max_tx_pwr_low_band = maxpwr;
1368c2ecf20Sopenharmony_ci		for (i = 4; i < 12; i++) {
1378c2ecf20Sopenharmony_ci			lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
1388c2ecf20Sopenharmony_ci			ofdmpo >>= 4;
1398c2ecf20Sopenharmony_ci		}
1408c2ecf20Sopenharmony_ci		maxpwr = sprom->maxpwr_a;
1418c2ecf20Sopenharmony_ci		ofdmpo = sprom->ofdm5gpo;
1428c2ecf20Sopenharmony_ci		lpphy->max_tx_pwr_med_band = maxpwr;
1438c2ecf20Sopenharmony_ci		for (i = 4; i < 12; i++) {
1448c2ecf20Sopenharmony_ci			lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
1458c2ecf20Sopenharmony_ci			ofdmpo >>= 4;
1468c2ecf20Sopenharmony_ci		}
1478c2ecf20Sopenharmony_ci		maxpwr = sprom->maxpwr_ah;
1488c2ecf20Sopenharmony_ci		ofdmpo = sprom->ofdm5ghpo;
1498c2ecf20Sopenharmony_ci		lpphy->max_tx_pwr_hi_band = maxpwr;
1508c2ecf20Sopenharmony_ci		for (i = 4; i < 12; i++) {
1518c2ecf20Sopenharmony_ci			lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
1528c2ecf20Sopenharmony_ci			ofdmpo >>= 4;
1538c2ecf20Sopenharmony_ci		}
1548c2ecf20Sopenharmony_ci	}
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
1608c2ecf20Sopenharmony_ci	u16 temp[3];
1618c2ecf20Sopenharmony_ci	u16 isolation;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	B43_WARN_ON(dev->phy.rev >= 2);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
1668c2ecf20Sopenharmony_ci		isolation = lpphy->tx_isolation_med_band;
1678c2ecf20Sopenharmony_ci	else if (freq <= 5320)
1688c2ecf20Sopenharmony_ci		isolation = lpphy->tx_isolation_low_band;
1698c2ecf20Sopenharmony_ci	else if (freq <= 5700)
1708c2ecf20Sopenharmony_ci		isolation = lpphy->tx_isolation_med_band;
1718c2ecf20Sopenharmony_ci	else
1728c2ecf20Sopenharmony_ci		isolation = lpphy->tx_isolation_hi_band;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	temp[0] = ((isolation - 26) / 12) << 12;
1758c2ecf20Sopenharmony_ci	temp[1] = temp[0] + 0x1000;
1768c2ecf20Sopenharmony_ci	temp[2] = temp[0] + 0x2000;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
1798c2ecf20Sopenharmony_ci	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic void lpphy_table_init(struct b43_wldev *dev)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev));
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2)
1878c2ecf20Sopenharmony_ci		lpphy_rev0_1_table_init(dev);
1888c2ecf20Sopenharmony_ci	else
1898c2ecf20Sopenharmony_ci		lpphy_rev2plus_table_init(dev);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	lpphy_init_tx_gain_table(dev);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2)
1948c2ecf20Sopenharmony_ci		lpphy_adjust_gain_table(dev, freq);
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct ssb_bus *bus = dev->dev->sdev->bus;
2008c2ecf20Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
2018c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
2028c2ecf20Sopenharmony_ci	u16 tmp, tmp2;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF);
2058c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0);
2068c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
2078c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
2088c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
2098c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004);
2108c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078);
2118c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
2128c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016);
2138c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004);
2148c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400);
2158c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400);
2168c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
2178c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
2188c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
2198c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
2208c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
2218c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
2228c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
2238c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
2248c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
2258c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
2268c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
2278c2ecf20Sopenharmony_ci			0xFF00, lpphy->rx_pwr_offset);
2288c2ecf20Sopenharmony_ci	if ((sprom->boardflags_lo & B43_BFL_FEM) &&
2298c2ecf20Sopenharmony_ci	   ((b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||
2308c2ecf20Sopenharmony_ci	   (sprom->boardflags_hi & B43_BFH_PAREF))) {
2318c2ecf20Sopenharmony_ci		ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
2328c2ecf20Sopenharmony_ci		ssb_pmu_set_ldo_paref(&bus->chipco, true);
2338c2ecf20Sopenharmony_ci		if (dev->phy.rev == 0) {
2348c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
2358c2ecf20Sopenharmony_ci					0xFFCF, 0x0010);
2368c2ecf20Sopenharmony_ci		}
2378c2ecf20Sopenharmony_ci		b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
2388c2ecf20Sopenharmony_ci	} else {
2398c2ecf20Sopenharmony_ci		ssb_pmu_set_ldo_paref(&bus->chipco, false);
2408c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
2418c2ecf20Sopenharmony_ci				0xFFCF, 0x0020);
2428c2ecf20Sopenharmony_ci		b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci	tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
2458c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
2468c2ecf20Sopenharmony_ci	if (sprom->boardflags_hi & B43_BFH_RSSIINV)
2478c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
2488c2ecf20Sopenharmony_ci	else
2498c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
2508c2ecf20Sopenharmony_ci	b43_lptab_write(dev, B43_LPTAB16(11, 1), 24);
2518c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
2528c2ecf20Sopenharmony_ci			0xFFF9, (lpphy->bx_arch << 1));
2538c2ecf20Sopenharmony_ci	if (dev->phy.rev == 1 &&
2548c2ecf20Sopenharmony_ci	   (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
2558c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
2568c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
2578c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
2588c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
2598c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A);
2608c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400);
2618c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A);
2628c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00);
2638c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A);
2648c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900);
2658c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A);
2668c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00);
2678c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A);
2688c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900);
2698c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
2708c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
2718c2ecf20Sopenharmony_ci	} else if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ ||
2728c2ecf20Sopenharmony_ci		   (dev->dev->board_type == SSB_BOARD_BU4312) ||
2738c2ecf20Sopenharmony_ci		   (dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) {
2748c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
2758c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
2768c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
2778c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500);
2788c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
2798c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800);
2808c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
2818c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
2828c2ecf20Sopenharmony_ci	} else if (dev->phy.rev == 1 ||
2838c2ecf20Sopenharmony_ci		  (sprom->boardflags_lo & B43_BFL_FEM)) {
2848c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
2858c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
2868c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
2878c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00);
2888c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
2898c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100);
2908c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
2918c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300);
2928c2ecf20Sopenharmony_ci	} else {
2938c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
2948c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900);
2958c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
2968c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
2978c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006);
2988c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500);
2998c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
3008c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci	if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
3038c2ecf20Sopenharmony_ci		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
3048c2ecf20Sopenharmony_ci		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
3058c2ecf20Sopenharmony_ci		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
3068c2ecf20Sopenharmony_ci		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
3078c2ecf20Sopenharmony_ci	}
3088c2ecf20Sopenharmony_ci	if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
3098c2ecf20Sopenharmony_ci	    (dev->dev->chip_id == 0x5354) &&
3108c2ecf20Sopenharmony_ci	    (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
3118c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
3128c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
3138c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
3148c2ecf20Sopenharmony_ci		//FIXME the Broadcom driver caches & delays this HF write!
3158c2ecf20Sopenharmony_ci		b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W);
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
3188c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
3198c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040);
3208c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400);
3218c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00);
3228c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007);
3238c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003);
3248c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020);
3258c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
3268c2ecf20Sopenharmony_ci	} else { /* 5GHz */
3278c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF);
3288c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF);
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci	if (dev->phy.rev == 1) {
3318c2ecf20Sopenharmony_ci		tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
3328c2ecf20Sopenharmony_ci		tmp2 = (tmp & 0x03E0) >> 5;
3338c2ecf20Sopenharmony_ci		tmp2 |= tmp2 << 5;
3348c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
3358c2ecf20Sopenharmony_ci		tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
3368c2ecf20Sopenharmony_ci		tmp2 = (tmp & 0x1F00) >> 8;
3378c2ecf20Sopenharmony_ci		tmp2 |= tmp2 << 5;
3388c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
3398c2ecf20Sopenharmony_ci		tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
3408c2ecf20Sopenharmony_ci		tmp2 = tmp & 0x00FF;
3418c2ecf20Sopenharmony_ci		tmp2 |= tmp << 8;
3428c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_4C5, tmp2);
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic void lpphy_save_dig_flt_state(struct b43_wldev *dev)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	static const u16 addr[] = {
3498c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC1),
3508c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC2),
3518c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC3),
3528c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC4),
3538c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC5),
3548c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC6),
3558c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC7),
3568c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC8),
3578c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xCF),
3588c2ecf20Sopenharmony_ci	};
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	static const u16 coefs[] = {
3618c2ecf20Sopenharmony_ci		0xDE5E, 0xE832, 0xE331, 0x4D26,
3628c2ecf20Sopenharmony_ci		0x0026, 0x1420, 0x0020, 0xFE08,
3638c2ecf20Sopenharmony_ci		0x0008,
3648c2ecf20Sopenharmony_ci	};
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
3678c2ecf20Sopenharmony_ci	int i;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(addr); i++) {
3708c2ecf20Sopenharmony_ci		lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]);
3718c2ecf20Sopenharmony_ci		b43_phy_write(dev, addr[i], coefs[i]);
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cistatic void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	static const u16 addr[] = {
3788c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC1),
3798c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC2),
3808c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC3),
3818c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC4),
3828c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC5),
3838c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC6),
3848c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC7),
3858c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xC8),
3868c2ecf20Sopenharmony_ci		B43_PHY_OFDM(0xCF),
3878c2ecf20Sopenharmony_ci	};
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
3908c2ecf20Sopenharmony_ci	int i;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(addr); i++)
3938c2ecf20Sopenharmony_ci		b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_cistatic void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
4018c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0x8800);
4028c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
4038c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0);
4048c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
4058c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
4068c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0);
4078c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0);
4088c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10);
4098c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4);
4108c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200);
4118c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F);
4128c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40);
4138c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_PREAMBLECONFIRMTO, 0xFF00, 0x2);
4148c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
4158c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
4168c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
4178c2ecf20Sopenharmony_ci	if (dev->dev->board_rev >= 0x18) {
4188c2ecf20Sopenharmony_ci		b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
4198c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
4208c2ecf20Sopenharmony_ci	} else {
4218c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
4228c2ecf20Sopenharmony_ci	}
4238c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4);
4248c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);
4258c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48);
4268c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46);
4278c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10);
4288c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9);
4298c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF);
4308c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500);
4318c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
4328c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
4338c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
4348c2ecf20Sopenharmony_ci	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
4358c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
4368c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
4378c2ecf20Sopenharmony_ci	} else {
4388c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00);
4398c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD);
4408c2ecf20Sopenharmony_ci	}
4418c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F);
4428c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
4438c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19);
4448c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0x03FF, 0x3C00);
4458c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFC1F, 0x3E0);
4468c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
4478c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0x00FF, 0x1900);
4488c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
4498c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
4508c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
4538c2ecf20Sopenharmony_ci		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
4548c2ecf20Sopenharmony_ci		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
4588c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40);
4598c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00);
4608c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6);
4618c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00);
4628c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1);
4638c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
4648c2ecf20Sopenharmony_ci	} else /* 5GHz */
4658c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0xB3);
4688c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
4698c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset);
4708c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RESET_CTL, 0x44);
4718c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RESET_CTL, 0x80);
4728c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, 0xA954);
4738c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1,
4748c2ecf20Sopenharmony_ci		      0x2000 | ((u16)lpphy->rssi_gs << 10) |
4758c2ecf20Sopenharmony_ci		      ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
4788c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
4798c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
4808c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
4818c2ecf20Sopenharmony_ci	}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	lpphy_save_dig_flt_state(dev);
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic void lpphy_baseband_init(struct b43_wldev *dev)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	lpphy_table_init(dev);
4898c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2)
4908c2ecf20Sopenharmony_ci		lpphy_baseband_rev2plus_init(dev);
4918c2ecf20Sopenharmony_ci	else
4928c2ecf20Sopenharmony_ci		lpphy_baseband_rev0_1_init(dev);
4938c2ecf20Sopenharmony_ci}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistruct b2062_freqdata {
4968c2ecf20Sopenharmony_ci	u16 freq;
4978c2ecf20Sopenharmony_ci	u8 data[6];
4988c2ecf20Sopenharmony_ci};
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci/* Initialize the 2062 radio. */
5018c2ecf20Sopenharmony_cistatic void lpphy_2062_init(struct b43_wldev *dev)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
5048c2ecf20Sopenharmony_ci	struct ssb_bus *bus = dev->dev->sdev->bus;
5058c2ecf20Sopenharmony_ci	u32 crystalfreq, tmp, ref;
5068c2ecf20Sopenharmony_ci	unsigned int i;
5078c2ecf20Sopenharmony_ci	const struct b2062_freqdata *fd = NULL;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	static const struct b2062_freqdata freqdata_tab[] = {
5108c2ecf20Sopenharmony_ci		{ .freq = 12000, .data[0] =  6, .data[1] =  6, .data[2] =  6,
5118c2ecf20Sopenharmony_ci				 .data[3] =  6, .data[4] = 10, .data[5] =  6, },
5128c2ecf20Sopenharmony_ci		{ .freq = 13000, .data[0] =  4, .data[1] =  4, .data[2] =  4,
5138c2ecf20Sopenharmony_ci				 .data[3] =  4, .data[4] = 11, .data[5] =  7, },
5148c2ecf20Sopenharmony_ci		{ .freq = 14400, .data[0] =  3, .data[1] =  3, .data[2] =  3,
5158c2ecf20Sopenharmony_ci				 .data[3] =  3, .data[4] = 12, .data[5] =  7, },
5168c2ecf20Sopenharmony_ci		{ .freq = 16200, .data[0] =  3, .data[1] =  3, .data[2] =  3,
5178c2ecf20Sopenharmony_ci				 .data[3] =  3, .data[4] = 13, .data[5] =  8, },
5188c2ecf20Sopenharmony_ci		{ .freq = 18000, .data[0] =  2, .data[1] =  2, .data[2] =  2,
5198c2ecf20Sopenharmony_ci				 .data[3] =  2, .data[4] = 14, .data[5] =  8, },
5208c2ecf20Sopenharmony_ci		{ .freq = 19200, .data[0] =  1, .data[1] =  1, .data[2] =  1,
5218c2ecf20Sopenharmony_ci				 .data[3] =  1, .data[4] = 14, .data[5] =  9, },
5228c2ecf20Sopenharmony_ci	};
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	b2062_upload_init_table(dev);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL3, 0);
5278c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL4, 0);
5288c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL5, 0);
5298c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL6, 0);
5308c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40);
5318c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_PDN_CTL0, 0);
5328c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_CALIB_TS, 0x10);
5338c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_CALIB_TS, 0);
5348c2ecf20Sopenharmony_ci	if (dev->phy.rev > 0) {
5358c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_S_BG_CTL1,
5368c2ecf20Sopenharmony_ci			(b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80);
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
5398c2ecf20Sopenharmony_ci		b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1);
5408c2ecf20Sopenharmony_ci	else
5418c2ecf20Sopenharmony_ci		b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	/* Get the crystal freq, in Hz. */
5448c2ecf20Sopenharmony_ci	crystalfreq = bus->chipco.pmu.crystalfreq * 1000;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU));
5478c2ecf20Sopenharmony_ci	B43_WARN_ON(crystalfreq == 0);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (crystalfreq <= 30000000) {
5508c2ecf20Sopenharmony_ci		lpphy->pdiv = 1;
5518c2ecf20Sopenharmony_ci		b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB);
5528c2ecf20Sopenharmony_ci	} else {
5538c2ecf20Sopenharmony_ci		lpphy->pdiv = 2;
5548c2ecf20Sopenharmony_ci		b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4);
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	tmp = (((800000000 * lpphy->pdiv + crystalfreq) /
5588c2ecf20Sopenharmony_ci	      (2 * crystalfreq)) - 8) & 0xFF;
5598c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) /
5628c2ecf20Sopenharmony_ci	      (32000000 * lpphy->pdiv)) - 1) & 0xFF;
5638c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) /
5668c2ecf20Sopenharmony_ci	      (2000000 * lpphy->pdiv)) - 1) & 0xFF;
5678c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv);
5708c2ecf20Sopenharmony_ci	ref &= 0xFFFF;
5718c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) {
5728c2ecf20Sopenharmony_ci		if (ref < freqdata_tab[i].freq) {
5738c2ecf20Sopenharmony_ci			fd = &freqdata_tab[i];
5748c2ecf20Sopenharmony_ci			break;
5758c2ecf20Sopenharmony_ci		}
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci	if (!fd)
5788c2ecf20Sopenharmony_ci		fd = &freqdata_tab[ARRAY_SIZE(freqdata_tab) - 1];
5798c2ecf20Sopenharmony_ci	b43dbg(dev->wl, "b2062: Using crystal tab entry %u kHz.\n",
5808c2ecf20Sopenharmony_ci	       fd->freq); /* FIXME: Keep this printk until the code is fully debugged. */
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL8,
5838c2ecf20Sopenharmony_ci			((u16)(fd->data[1]) << 4) | fd->data[0]);
5848c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL9,
5858c2ecf20Sopenharmony_ci			((u16)(fd->data[3]) << 4) | fd->data[2]);
5868c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]);
5878c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]);
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci/* Initialize the 2063 radio. */
5918c2ecf20Sopenharmony_cistatic void lpphy_2063_init(struct b43_wldev *dev)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	b2063_upload_init_table(dev);
5948c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_LOGEN_SP5, 0);
5958c2ecf20Sopenharmony_ci	b43_radio_set(dev, B2063_COMM8, 0x38);
5968c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_REG_SP1, 0x56);
5978c2ecf20Sopenharmony_ci	b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2);
5988c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PA_SP7, 0);
5998c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
6008c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
6018c2ecf20Sopenharmony_ci	if (dev->phy.rev == 2) {
6028c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_SP3, 0xa0);
6038c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_SP4, 0xa0);
6048c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_SP2, 0x18);
6058c2ecf20Sopenharmony_ci	} else {
6068c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_SP3, 0x20);
6078c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_SP2, 0x20);
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistruct lpphy_stx_table_entry {
6128c2ecf20Sopenharmony_ci	u16 phy_offset;
6138c2ecf20Sopenharmony_ci	u16 phy_shift;
6148c2ecf20Sopenharmony_ci	u16 rf_addr;
6158c2ecf20Sopenharmony_ci	u16 rf_shift;
6168c2ecf20Sopenharmony_ci	u16 mask;
6178c2ecf20Sopenharmony_ci};
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic const struct lpphy_stx_table_entry lpphy_stx_table[] = {
6208c2ecf20Sopenharmony_ci	{ .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, },
6218c2ecf20Sopenharmony_ci	{ .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, },
6228c2ecf20Sopenharmony_ci	{ .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, },
6238c2ecf20Sopenharmony_ci	{ .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, },
6248c2ecf20Sopenharmony_ci	{ .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, },
6258c2ecf20Sopenharmony_ci	{ .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, },
6268c2ecf20Sopenharmony_ci	{ .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, },
6278c2ecf20Sopenharmony_ci	{ .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, },
6288c2ecf20Sopenharmony_ci	{ .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, },
6298c2ecf20Sopenharmony_ci	{ .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, },
6308c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, },
6318c2ecf20Sopenharmony_ci	{ .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, },
6328c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, },
6338c2ecf20Sopenharmony_ci	{ .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, },
6348c2ecf20Sopenharmony_ci	{ .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, },
6358c2ecf20Sopenharmony_ci	{ .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, },
6368c2ecf20Sopenharmony_ci	{ .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, },
6378c2ecf20Sopenharmony_ci	{ .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, },
6388c2ecf20Sopenharmony_ci	{ .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, },
6398c2ecf20Sopenharmony_ci	{ .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, },
6408c2ecf20Sopenharmony_ci	{ .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, },
6418c2ecf20Sopenharmony_ci	{ .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, },
6428c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, },
6438c2ecf20Sopenharmony_ci	{ .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, },
6448c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, },
6458c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, },
6468c2ecf20Sopenharmony_ci	{ .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, },
6478c2ecf20Sopenharmony_ci	{ .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, },
6488c2ecf20Sopenharmony_ci	{ .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, },
6498c2ecf20Sopenharmony_ci};
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic void lpphy_sync_stx(struct b43_wldev *dev)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	const struct lpphy_stx_table_entry *e;
6548c2ecf20Sopenharmony_ci	unsigned int i;
6558c2ecf20Sopenharmony_ci	u16 tmp;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) {
6588c2ecf20Sopenharmony_ci		e = &lpphy_stx_table[i];
6598c2ecf20Sopenharmony_ci		tmp = b43_radio_read(dev, e->rf_addr);
6608c2ecf20Sopenharmony_ci		tmp >>= e->rf_shift;
6618c2ecf20Sopenharmony_ci		tmp <<= e->phy_shift;
6628c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset),
6638c2ecf20Sopenharmony_ci				~(e->mask << e->phy_shift), tmp);
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci}
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_cistatic void lpphy_radio_init(struct b43_wldev *dev)
6688c2ecf20Sopenharmony_ci{
6698c2ecf20Sopenharmony_ci	/* The radio is attached through the 4wire bus. */
6708c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_FOURWIRE_CTL, 0x2);
6718c2ecf20Sopenharmony_ci	udelay(1);
6728c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD);
6738c2ecf20Sopenharmony_ci	udelay(1);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	if (dev->phy.radio_ver == 0x2062) {
6768c2ecf20Sopenharmony_ci		lpphy_2062_init(dev);
6778c2ecf20Sopenharmony_ci	} else {
6788c2ecf20Sopenharmony_ci		lpphy_2063_init(dev);
6798c2ecf20Sopenharmony_ci		lpphy_sync_stx(dev);
6808c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
6818c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
6828c2ecf20Sopenharmony_ci		if (dev->dev->chip_id == 0x4325) {
6838c2ecf20Sopenharmony_ci			// TODO SSB PMU recalibration
6848c2ecf20Sopenharmony_ci		}
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistruct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_cistatic void lpphy_set_rc_cap(struct b43_wldev *dev)
6918c2ecf20Sopenharmony_ci{
6928c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	if (dev->phy.rev == 1) //FIXME check channel 14!
6978c2ecf20Sopenharmony_ci		rc_cap = min_t(u8, rc_cap + 5, 15);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_RXBB_CALIB2,
7008c2ecf20Sopenharmony_ci			max_t(u8, lpphy->rc_cap - 4, 0x80));
7018c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80);
7028c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RXG_CNT16,
7038c2ecf20Sopenharmony_ci			((lpphy->rc_cap & 0x1F) >> 2) | 0x80);
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_cistatic u8 lpphy_get_bb_mult(struct b43_wldev *dev)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_cistatic void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
7128c2ecf20Sopenharmony_ci{
7138c2ecf20Sopenharmony_ci	b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
7148c2ecf20Sopenharmony_ci}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_cistatic void lpphy_set_deaf(struct b43_wldev *dev, bool user)
7178c2ecf20Sopenharmony_ci{
7188c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	if (user)
7218c2ecf20Sopenharmony_ci		lpphy->crs_usr_disable = true;
7228c2ecf20Sopenharmony_ci	else
7238c2ecf20Sopenharmony_ci		lpphy->crs_sys_disable = true;
7248c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
7258c2ecf20Sopenharmony_ci}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_cistatic void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (user)
7328c2ecf20Sopenharmony_ci		lpphy->crs_usr_disable = false;
7338c2ecf20Sopenharmony_ci	else
7348c2ecf20Sopenharmony_ci		lpphy->crs_sys_disable = false;
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) {
7378c2ecf20Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
7388c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
7398c2ecf20Sopenharmony_ci					0xFF1F, 0x60);
7408c2ecf20Sopenharmony_ci		else
7418c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
7428c2ecf20Sopenharmony_ci					0xFF1F, 0x20);
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	u16 trsw = (tx << 1) | rx;
7498c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
7508c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic void lpphy_disable_crs(struct b43_wldev *dev, bool user)
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	lpphy_set_deaf(dev, user);
7568c2ecf20Sopenharmony_ci	lpphy_set_trsw_over(dev, false, true);
7578c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
7588c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
7598c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
7608c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
7618c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
7628c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
7638c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
7648c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
7658c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
7668c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
7678c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
7688c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
7698c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
7708c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
7718c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
7728c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
7738c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
7748c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
7758c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
7768c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
7778c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
7788c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
7798c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic void lpphy_restore_crs(struct b43_wldev *dev, bool user)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	lpphy_clear_deaf(dev, user);
7858c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
7868c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_cistruct lpphy_tx_gains { u16 gm, pga, pad, dac; };
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cistatic void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
7948c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
7958c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
7968c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
7978c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
7988c2ecf20Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
7998c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
8008c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
8018c2ecf20Sopenharmony_ci		}
8028c2ecf20Sopenharmony_ci	} else {
8038c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
8048c2ecf20Sopenharmony_ci	}
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_cistatic void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
8108c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
8118c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
8128c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
8138c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
8148c2ecf20Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
8158c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
8168c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
8178c2ecf20Sopenharmony_ci		}
8188c2ecf20Sopenharmony_ci	} else {
8198c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2)
8268c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
8278c2ecf20Sopenharmony_ci	else {
8288c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
8298c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_cistatic void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
8358c2ecf20Sopenharmony_ci{
8368c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2)
8378c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
8388c2ecf20Sopenharmony_ci	else {
8398c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
8408c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	struct lpphy_tx_gains gains;
8488c2ecf20Sopenharmony_ci	u16 tmp;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
8518c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
8528c2ecf20Sopenharmony_ci		tmp = b43_phy_read(dev,
8538c2ecf20Sopenharmony_ci				   B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
8548c2ecf20Sopenharmony_ci		gains.gm = tmp & 0x0007;
8558c2ecf20Sopenharmony_ci		gains.pga = (tmp & 0x0078) >> 3;
8568c2ecf20Sopenharmony_ci		gains.pad = (tmp & 0x780) >> 7;
8578c2ecf20Sopenharmony_ci	} else {
8588c2ecf20Sopenharmony_ci		tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
8598c2ecf20Sopenharmony_ci		gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
8608c2ecf20Sopenharmony_ci		gains.gm = tmp & 0xFF;
8618c2ecf20Sopenharmony_ci		gains.pga = (tmp >> 8) & 0xFF;
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	return gains;
8658c2ecf20Sopenharmony_ci}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_cistatic void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
8708c2ecf20Sopenharmony_ci	ctl |= dac << 7;
8718c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_cistatic u16 lpphy_get_pa_gain(struct b43_wldev *dev)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
8828c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_cistatic void lpphy_set_tx_gains(struct b43_wldev *dev,
8868c2ecf20Sopenharmony_ci			       struct lpphy_tx_gains gains)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	u16 rf_gain, pa_gain;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
8918c2ecf20Sopenharmony_ci		rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
8928c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
8938c2ecf20Sopenharmony_ci				0xF800, rf_gain);
8948c2ecf20Sopenharmony_ci	} else {
8958c2ecf20Sopenharmony_ci		pa_gain = lpphy_get_pa_gain(dev);
8968c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
8978c2ecf20Sopenharmony_ci			      (gains.pga << 8) | gains.gm);
8988c2ecf20Sopenharmony_ci		/*
8998c2ecf20Sopenharmony_ci		 * SPEC FIXME The spec calls for (pa_gain << 8) here, but that
9008c2ecf20Sopenharmony_ci		 * conflicts with the spec for set_pa_gain! Vendor driver bug?
9018c2ecf20Sopenharmony_ci		 */
9028c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
9038c2ecf20Sopenharmony_ci				0x8000, gains.pad | (pa_gain << 6));
9048c2ecf20Sopenharmony_ci		b43_phy_write(dev, B43_PHY_OFDM(0xFC),
9058c2ecf20Sopenharmony_ci			      (gains.pga << 8) | gains.gm);
9068c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
9078c2ecf20Sopenharmony_ci				0x8000, gains.pad | (pa_gain << 8));
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci	lpphy_set_dac_gain(dev, gains.dac);
9108c2ecf20Sopenharmony_ci	lpphy_enable_tx_gain_override(dev);
9118c2ecf20Sopenharmony_ci}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cistatic void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
9148c2ecf20Sopenharmony_ci{
9158c2ecf20Sopenharmony_ci	u16 trsw = gain & 0x1;
9168c2ecf20Sopenharmony_ci	u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
9178c2ecf20Sopenharmony_ci	u16 ext_lna = (gain & 2) >> 1;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
9208c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
9218c2ecf20Sopenharmony_ci			0xFBFF, ext_lna << 10);
9228c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
9238c2ecf20Sopenharmony_ci			0xF7FF, ext_lna << 11);
9248c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	u16 low_gain = gain & 0xFFFF;
9308c2ecf20Sopenharmony_ci	u16 high_gain = (gain >> 16) & 0xF;
9318c2ecf20Sopenharmony_ci	u16 ext_lna = (gain >> 21) & 0x1;
9328c2ecf20Sopenharmony_ci	u16 trsw = ~(gain >> 20) & 0x1;
9338c2ecf20Sopenharmony_ci	u16 tmp;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
9368c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
9378c2ecf20Sopenharmony_ci			0xFDFF, ext_lna << 9);
9388c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
9398c2ecf20Sopenharmony_ci			0xFBFF, ext_lna << 10);
9408c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
9418c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
9428c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
9438c2ecf20Sopenharmony_ci		tmp = (gain >> 2) & 0x3;
9448c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
9458c2ecf20Sopenharmony_ci				0xE7FF, tmp<<11);
9468c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
9478c2ecf20Sopenharmony_ci	}
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cistatic void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2)
9538c2ecf20Sopenharmony_ci		lpphy_rev0_1_set_rx_gain(dev, gain);
9548c2ecf20Sopenharmony_ci	else
9558c2ecf20Sopenharmony_ci		lpphy_rev2plus_set_rx_gain(dev, gain);
9568c2ecf20Sopenharmony_ci	lpphy_enable_rx_gain_override(dev);
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_cistatic void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
9628c2ecf20Sopenharmony_ci	lpphy_set_rx_gain(dev, gain);
9638c2ecf20Sopenharmony_ci}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_cistatic void lpphy_stop_ddfs(struct b43_wldev *dev)
9668c2ecf20Sopenharmony_ci{
9678c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
9688c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_cistatic void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
9728c2ecf20Sopenharmony_ci			   int incr1, int incr2, int scale_idx)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	lpphy_stop_ddfs(dev);
9758c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
9768c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
9778c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
9788c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
9798c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
9808c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
9818c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
9828c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
9838c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
9848c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
9858c2ecf20Sopenharmony_ci}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_cistatic bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
9888c2ecf20Sopenharmony_ci			   struct lpphy_iq_est *iq_est)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	int i;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
9938c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
9948c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
9958c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
9968c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	for (i = 0; i < 500; i++) {
9998c2ecf20Sopenharmony_ci		if (!(b43_phy_read(dev,
10008c2ecf20Sopenharmony_ci				B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
10018c2ecf20Sopenharmony_ci			break;
10028c2ecf20Sopenharmony_ci		msleep(1);
10038c2ecf20Sopenharmony_ci	}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
10068c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
10078c2ecf20Sopenharmony_ci		return false;
10088c2ecf20Sopenharmony_ci	}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
10118c2ecf20Sopenharmony_ci	iq_est->iq_prod <<= 16;
10128c2ecf20Sopenharmony_ci	iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
10158c2ecf20Sopenharmony_ci	iq_est->i_pwr <<= 16;
10168c2ecf20Sopenharmony_ci	iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
10198c2ecf20Sopenharmony_ci	iq_est->q_pwr <<= 16;
10208c2ecf20Sopenharmony_ci	iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
10238c2ecf20Sopenharmony_ci	return true;
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_cistatic int lpphy_loopback(struct b43_wldev *dev)
10278c2ecf20Sopenharmony_ci{
10288c2ecf20Sopenharmony_ci	struct lpphy_iq_est iq_est;
10298c2ecf20Sopenharmony_ci	int i, index = -1;
10308c2ecf20Sopenharmony_ci	u32 tmp;
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	memset(&iq_est, 0, sizeof(iq_est));
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	lpphy_set_trsw_over(dev, true, true);
10358c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
10368c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
10378c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
10388c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
10398c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
10408c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
10418c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
10428c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
10438c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
10448c2ecf20Sopenharmony_ci	for (i = 0; i < 32; i++) {
10458c2ecf20Sopenharmony_ci		lpphy_set_rx_gain_by_index(dev, i);
10468c2ecf20Sopenharmony_ci		lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
10478c2ecf20Sopenharmony_ci		if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
10488c2ecf20Sopenharmony_ci			continue;
10498c2ecf20Sopenharmony_ci		tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
10508c2ecf20Sopenharmony_ci		if ((tmp > 4000) && (tmp < 10000)) {
10518c2ecf20Sopenharmony_ci			index = i;
10528c2ecf20Sopenharmony_ci			break;
10538c2ecf20Sopenharmony_ci		}
10548c2ecf20Sopenharmony_ci	}
10558c2ecf20Sopenharmony_ci	lpphy_stop_ddfs(dev);
10568c2ecf20Sopenharmony_ci	return index;
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci/* Fixed-point division algorithm using only integer math. */
10608c2ecf20Sopenharmony_cistatic u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	u32 quotient, remainder;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	if (divisor == 0)
10658c2ecf20Sopenharmony_ci		return 0;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	quotient = dividend / divisor;
10688c2ecf20Sopenharmony_ci	remainder = dividend % divisor;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	while (precision > 0) {
10718c2ecf20Sopenharmony_ci		quotient <<= 1;
10728c2ecf20Sopenharmony_ci		if (remainder << 1 >= divisor) {
10738c2ecf20Sopenharmony_ci			quotient++;
10748c2ecf20Sopenharmony_ci			remainder = (remainder << 1) - divisor;
10758c2ecf20Sopenharmony_ci		}
10768c2ecf20Sopenharmony_ci		precision--;
10778c2ecf20Sopenharmony_ci	}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	if (remainder << 1 >= divisor)
10808c2ecf20Sopenharmony_ci		quotient++;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	return quotient;
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci/* Read the TX power control mode from hardware. */
10868c2ecf20Sopenharmony_cistatic void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev)
10878c2ecf20Sopenharmony_ci{
10888c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
10898c2ecf20Sopenharmony_ci	u16 ctl;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	ctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD);
10928c2ecf20Sopenharmony_ci	switch (ctl & B43_LPPHY_TX_PWR_CTL_CMD_MODE) {
10938c2ecf20Sopenharmony_ci	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF:
10948c2ecf20Sopenharmony_ci		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_OFF;
10958c2ecf20Sopenharmony_ci		break;
10968c2ecf20Sopenharmony_ci	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW:
10978c2ecf20Sopenharmony_ci		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_SW;
10988c2ecf20Sopenharmony_ci		break;
10998c2ecf20Sopenharmony_ci	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW:
11008c2ecf20Sopenharmony_ci		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_HW;
11018c2ecf20Sopenharmony_ci		break;
11028c2ecf20Sopenharmony_ci	default:
11038c2ecf20Sopenharmony_ci		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_UNKNOWN;
11048c2ecf20Sopenharmony_ci		B43_WARN_ON(1);
11058c2ecf20Sopenharmony_ci		break;
11068c2ecf20Sopenharmony_ci	}
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci/* Set the TX power control mode in hardware. */
11108c2ecf20Sopenharmony_cistatic void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev)
11118c2ecf20Sopenharmony_ci{
11128c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
11138c2ecf20Sopenharmony_ci	u16 ctl;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	switch (lpphy->txpctl_mode) {
11168c2ecf20Sopenharmony_ci	case B43_LPPHY_TXPCTL_OFF:
11178c2ecf20Sopenharmony_ci		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF;
11188c2ecf20Sopenharmony_ci		break;
11198c2ecf20Sopenharmony_ci	case B43_LPPHY_TXPCTL_HW:
11208c2ecf20Sopenharmony_ci		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW;
11218c2ecf20Sopenharmony_ci		break;
11228c2ecf20Sopenharmony_ci	case B43_LPPHY_TXPCTL_SW:
11238c2ecf20Sopenharmony_ci		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW;
11248c2ecf20Sopenharmony_ci		break;
11258c2ecf20Sopenharmony_ci	default:
11268c2ecf20Sopenharmony_ci		ctl = 0;
11278c2ecf20Sopenharmony_ci		B43_WARN_ON(1);
11288c2ecf20Sopenharmony_ci	}
11298c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
11308c2ecf20Sopenharmony_ci			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, ctl);
11318c2ecf20Sopenharmony_ci}
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_cistatic void lpphy_set_tx_power_control(struct b43_wldev *dev,
11348c2ecf20Sopenharmony_ci				       enum b43_lpphy_txpctl_mode mode)
11358c2ecf20Sopenharmony_ci{
11368c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
11378c2ecf20Sopenharmony_ci	enum b43_lpphy_txpctl_mode oldmode;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
11408c2ecf20Sopenharmony_ci	oldmode = lpphy->txpctl_mode;
11418c2ecf20Sopenharmony_ci	if (oldmode == mode)
11428c2ecf20Sopenharmony_ci		return;
11438c2ecf20Sopenharmony_ci	lpphy->txpctl_mode = mode;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	if (oldmode == B43_LPPHY_TXPCTL_HW) {
11468c2ecf20Sopenharmony_ci		//TODO Update TX Power NPT
11478c2ecf20Sopenharmony_ci		//TODO Clear all TX Power offsets
11488c2ecf20Sopenharmony_ci	} else {
11498c2ecf20Sopenharmony_ci		if (mode == B43_LPPHY_TXPCTL_HW) {
11508c2ecf20Sopenharmony_ci			//TODO Recalculate target TX power
11518c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
11528c2ecf20Sopenharmony_ci					0xFF80, lpphy->tssi_idx);
11538c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
11548c2ecf20Sopenharmony_ci					0x8FFF, ((u16)lpphy->tssi_npt << 16));
11558c2ecf20Sopenharmony_ci			//TODO Set "TSSI Transmit Count" variable to total transmitted frame count
11568c2ecf20Sopenharmony_ci			lpphy_disable_tx_gain_override(dev);
11578c2ecf20Sopenharmony_ci			lpphy->tx_pwr_idx_over = -1;
11588c2ecf20Sopenharmony_ci		}
11598c2ecf20Sopenharmony_ci	}
11608c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
11618c2ecf20Sopenharmony_ci		if (mode == B43_LPPHY_TXPCTL_HW)
11628c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
11638c2ecf20Sopenharmony_ci		else
11648c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
11658c2ecf20Sopenharmony_ci	}
11668c2ecf20Sopenharmony_ci	lpphy_write_tx_pctl_mode_to_hardware(dev);
11678c2ecf20Sopenharmony_ci}
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_cistatic int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
11708c2ecf20Sopenharmony_ci				       unsigned int new_channel);
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_cistatic void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
11738c2ecf20Sopenharmony_ci{
11748c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
11758c2ecf20Sopenharmony_ci	struct lpphy_iq_est iq_est;
11768c2ecf20Sopenharmony_ci	struct lpphy_tx_gains tx_gains;
11778c2ecf20Sopenharmony_ci	static const u32 ideal_pwr_table[21] = {
11788c2ecf20Sopenharmony_ci		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
11798c2ecf20Sopenharmony_ci		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
11808c2ecf20Sopenharmony_ci		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
11818c2ecf20Sopenharmony_ci		0x0004c, 0x0002c, 0x0001a,
11828c2ecf20Sopenharmony_ci	};
11838c2ecf20Sopenharmony_ci	bool old_txg_ovr;
11848c2ecf20Sopenharmony_ci	u8 old_bbmult;
11858c2ecf20Sopenharmony_ci	u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
11868c2ecf20Sopenharmony_ci	    old_rf2_ovr, old_rf2_ovrval, old_phy_ctl;
11878c2ecf20Sopenharmony_ci	enum b43_lpphy_txpctl_mode old_txpctl;
11888c2ecf20Sopenharmony_ci	u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
11898c2ecf20Sopenharmony_ci	int loopback, i, j, inner_sum, err;
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	memset(&iq_est, 0, sizeof(iq_est));
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	err = b43_lpphy_op_switch_channel(dev, 7);
11948c2ecf20Sopenharmony_ci	if (err) {
11958c2ecf20Sopenharmony_ci		b43dbg(dev->wl,
11968c2ecf20Sopenharmony_ci		       "RC calib: Failed to switch to channel 7, error = %d\n",
11978c2ecf20Sopenharmony_ci		       err);
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci	old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
12008c2ecf20Sopenharmony_ci	old_bbmult = lpphy_get_bb_mult(dev);
12018c2ecf20Sopenharmony_ci	if (old_txg_ovr)
12028c2ecf20Sopenharmony_ci		tx_gains = lpphy_get_tx_gains(dev);
12038c2ecf20Sopenharmony_ci	old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
12048c2ecf20Sopenharmony_ci	old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
12058c2ecf20Sopenharmony_ci	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
12068c2ecf20Sopenharmony_ci	old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
12078c2ecf20Sopenharmony_ci	old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
12088c2ecf20Sopenharmony_ci	old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
12098c2ecf20Sopenharmony_ci	old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
12108c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
12118c2ecf20Sopenharmony_ci	old_txpctl = lpphy->txpctl_mode;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
12148c2ecf20Sopenharmony_ci	lpphy_disable_crs(dev, true);
12158c2ecf20Sopenharmony_ci	loopback = lpphy_loopback(dev);
12168c2ecf20Sopenharmony_ci	if (loopback == -1)
12178c2ecf20Sopenharmony_ci		goto finish;
12188c2ecf20Sopenharmony_ci	lpphy_set_rx_gain_by_index(dev, loopback);
12198c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
12208c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
12218c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
12228c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
12238c2ecf20Sopenharmony_ci	for (i = 128; i <= 159; i++) {
12248c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
12258c2ecf20Sopenharmony_ci		inner_sum = 0;
12268c2ecf20Sopenharmony_ci		for (j = 5; j <= 25; j++) {
12278c2ecf20Sopenharmony_ci			lpphy_run_ddfs(dev, 1, 1, j, j, 0);
12288c2ecf20Sopenharmony_ci			if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
12298c2ecf20Sopenharmony_ci				goto finish;
12308c2ecf20Sopenharmony_ci			mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
12318c2ecf20Sopenharmony_ci			if (j == 5)
12328c2ecf20Sopenharmony_ci				tmp = mean_sq_pwr;
12338c2ecf20Sopenharmony_ci			ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
12348c2ecf20Sopenharmony_ci			normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
12358c2ecf20Sopenharmony_ci			mean_sq_pwr = ideal_pwr - normal_pwr;
12368c2ecf20Sopenharmony_ci			mean_sq_pwr *= mean_sq_pwr;
12378c2ecf20Sopenharmony_ci			inner_sum += mean_sq_pwr;
12388c2ecf20Sopenharmony_ci			if ((i == 128) || (inner_sum < mean_sq_pwr_min)) {
12398c2ecf20Sopenharmony_ci				lpphy->rc_cap = i;
12408c2ecf20Sopenharmony_ci				mean_sq_pwr_min = inner_sum;
12418c2ecf20Sopenharmony_ci			}
12428c2ecf20Sopenharmony_ci		}
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci	lpphy_stop_ddfs(dev);
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_cifinish:
12478c2ecf20Sopenharmony_ci	lpphy_restore_crs(dev, true);
12488c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
12498c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
12508c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
12518c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
12528c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
12538c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
12548c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	lpphy_set_bb_mult(dev, old_bbmult);
12578c2ecf20Sopenharmony_ci	if (old_txg_ovr) {
12588c2ecf20Sopenharmony_ci		/*
12598c2ecf20Sopenharmony_ci		 * SPEC FIXME: The specs say "get_tx_gains" here, which is
12608c2ecf20Sopenharmony_ci		 * illogical. According to lwfinger, vendor driver v4.150.10.5
12618c2ecf20Sopenharmony_ci		 * has a Set here, while v4.174.64.19 has a Get - regression in
12628c2ecf20Sopenharmony_ci		 * the vendor driver? This should be tested this once the code
12638c2ecf20Sopenharmony_ci		 * is testable.
12648c2ecf20Sopenharmony_ci		 */
12658c2ecf20Sopenharmony_ci		lpphy_set_tx_gains(dev, tx_gains);
12668c2ecf20Sopenharmony_ci	}
12678c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, old_txpctl);
12688c2ecf20Sopenharmony_ci	if (lpphy->rc_cap)
12698c2ecf20Sopenharmony_ci		lpphy_set_rc_cap(dev);
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_cistatic void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
12738c2ecf20Sopenharmony_ci{
12748c2ecf20Sopenharmony_ci	struct ssb_bus *bus = dev->dev->sdev->bus;
12758c2ecf20Sopenharmony_ci	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
12768c2ecf20Sopenharmony_ci	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
12778c2ecf20Sopenharmony_ci	int i;
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
12808c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
12818c2ecf20Sopenharmony_ci	b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
12828c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
12838c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
12848c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
12858c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
12868c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
12878c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	for (i = 0; i < 10000; i++) {
12908c2ecf20Sopenharmony_ci		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
12918c2ecf20Sopenharmony_ci			break;
12928c2ecf20Sopenharmony_ci		msleep(1);
12938c2ecf20Sopenharmony_ci	}
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
12968c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
13018c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
13028c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
13038c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
13048c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	if (crystal_freq == 24000000) {
13078c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
13088c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
13098c2ecf20Sopenharmony_ci	} else {
13108c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
13118c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
13128c2ecf20Sopenharmony_ci	}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PA_SP7, 0x7D);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	for (i = 0; i < 10000; i++) {
13178c2ecf20Sopenharmony_ci		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
13188c2ecf20Sopenharmony_ci			break;
13198c2ecf20Sopenharmony_ci		msleep(1);
13208c2ecf20Sopenharmony_ci	}
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
13238c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
13268c2ecf20Sopenharmony_ci}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_cistatic void lpphy_calibrate_rc(struct b43_wldev *dev)
13298c2ecf20Sopenharmony_ci{
13308c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
13338c2ecf20Sopenharmony_ci		lpphy_rev2plus_rc_calib(dev);
13348c2ecf20Sopenharmony_ci	} else if (!lpphy->rc_cap) {
13358c2ecf20Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
13368c2ecf20Sopenharmony_ci			lpphy_rev0_1_rc_calib(dev);
13378c2ecf20Sopenharmony_ci	} else {
13388c2ecf20Sopenharmony_ci		lpphy_set_rc_cap(dev);
13398c2ecf20Sopenharmony_ci	}
13408c2ecf20Sopenharmony_ci}
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_cistatic void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
13438c2ecf20Sopenharmony_ci{
13448c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2)
13458c2ecf20Sopenharmony_ci		return; // rev2+ doesn't support antenna diversity
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
13488c2ecf20Sopenharmony_ci		return;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
13538c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_ci	dev->phy.lp->antenna = antenna;
13588c2ecf20Sopenharmony_ci}
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_cistatic void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
13618c2ecf20Sopenharmony_ci{
13628c2ecf20Sopenharmony_ci	u16 tmp[2];
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	tmp[0] = a;
13658c2ecf20Sopenharmony_ci	tmp[1] = b;
13668c2ecf20Sopenharmony_ci	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
13678c2ecf20Sopenharmony_ci}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_cistatic void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
13728c2ecf20Sopenharmony_ci	struct lpphy_tx_gains gains;
13738c2ecf20Sopenharmony_ci	u32 iq_comp, tx_gain, coeff, rf_power;
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	lpphy->tx_pwr_idx_over = index;
13768c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
13778c2ecf20Sopenharmony_ci	if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
13788c2ecf20Sopenharmony_ci		lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
13798c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
13808c2ecf20Sopenharmony_ci		iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
13818c2ecf20Sopenharmony_ci		tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
13828c2ecf20Sopenharmony_ci		gains.pad = (tx_gain >> 16) & 0xFF;
13838c2ecf20Sopenharmony_ci		gains.gm = tx_gain & 0xFF;
13848c2ecf20Sopenharmony_ci		gains.pga = (tx_gain >> 8) & 0xFF;
13858c2ecf20Sopenharmony_ci		gains.dac = (iq_comp >> 28) & 0xFF;
13868c2ecf20Sopenharmony_ci		lpphy_set_tx_gains(dev, gains);
13878c2ecf20Sopenharmony_ci	} else {
13888c2ecf20Sopenharmony_ci		iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
13898c2ecf20Sopenharmony_ci		tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
13908c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
13918c2ecf20Sopenharmony_ci				0xF800, (tx_gain >> 4) & 0x7FFF);
13928c2ecf20Sopenharmony_ci		lpphy_set_dac_gain(dev, tx_gain & 0x7);
13938c2ecf20Sopenharmony_ci		lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
13948c2ecf20Sopenharmony_ci	}
13958c2ecf20Sopenharmony_ci	lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
13968c2ecf20Sopenharmony_ci	lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
13978c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
13988c2ecf20Sopenharmony_ci		coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
13998c2ecf20Sopenharmony_ci	} else {
14008c2ecf20Sopenharmony_ci		coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
14018c2ecf20Sopenharmony_ci	}
14028c2ecf20Sopenharmony_ci	b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
14038c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2) {
14048c2ecf20Sopenharmony_ci		rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
14058c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
14068c2ecf20Sopenharmony_ci				rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
14078c2ecf20Sopenharmony_ci	}
14088c2ecf20Sopenharmony_ci	lpphy_enable_tx_gain_override(dev);
14098c2ecf20Sopenharmony_ci}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cistatic void lpphy_btcoex_override(struct b43_wldev *dev)
14128c2ecf20Sopenharmony_ci{
14138c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_BTCOEX_CTL, 0x3);
14148c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
14158c2ecf20Sopenharmony_ci}
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_cistatic void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
14188c2ecf20Sopenharmony_ci					 bool blocked)
14198c2ecf20Sopenharmony_ci{
14208c2ecf20Sopenharmony_ci	//TODO check MAC control register
14218c2ecf20Sopenharmony_ci	if (blocked) {
14228c2ecf20Sopenharmony_ci		if (dev->phy.rev >= 2) {
14238c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
14248c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
14258c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
14268c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
14278c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
14288c2ecf20Sopenharmony_ci		} else {
14298c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
14308c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
14318c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
14328c2ecf20Sopenharmony_ci			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
14338c2ecf20Sopenharmony_ci		}
14348c2ecf20Sopenharmony_ci	} else {
14358c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
14368c2ecf20Sopenharmony_ci		if (dev->phy.rev >= 2)
14378c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
14388c2ecf20Sopenharmony_ci		else
14398c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
14408c2ecf20Sopenharmony_ci	}
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci/* This was previously called lpphy_japan_filter */
14448c2ecf20Sopenharmony_cistatic void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
14458c2ecf20Sopenharmony_ci{
14468c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
14478c2ecf20Sopenharmony_ci	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
14508c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
14518c2ecf20Sopenharmony_ci		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
14528c2ecf20Sopenharmony_ci			lpphy_set_rc_cap(dev);
14538c2ecf20Sopenharmony_ci	} else {
14548c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
14558c2ecf20Sopenharmony_ci	}
14568c2ecf20Sopenharmony_ci}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_cistatic void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode)
14598c2ecf20Sopenharmony_ci{
14608c2ecf20Sopenharmony_ci	if (mode != TSSI_MUX_EXT) {
14618c2ecf20Sopenharmony_ci		b43_radio_set(dev, B2063_PA_SP1, 0x2);
14628c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000);
14638c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2063_PA_CTL10, 0x51);
14648c2ecf20Sopenharmony_ci		if (mode == TSSI_MUX_POSTPA) {
14658c2ecf20Sopenharmony_ci			b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE);
14668c2ecf20Sopenharmony_ci			b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7);
14678c2ecf20Sopenharmony_ci		} else {
14688c2ecf20Sopenharmony_ci			b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1);
14698c2ecf20Sopenharmony_ci			b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL,
14708c2ecf20Sopenharmony_ci					0xFFC7, 0x20);
14718c2ecf20Sopenharmony_ci		}
14728c2ecf20Sopenharmony_ci	} else {
14738c2ecf20Sopenharmony_ci		B43_WARN_ON(1);
14748c2ecf20Sopenharmony_ci	}
14758c2ecf20Sopenharmony_ci}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_cistatic void lpphy_tx_pctl_init_hw(struct b43_wldev *dev)
14788c2ecf20Sopenharmony_ci{
14798c2ecf20Sopenharmony_ci	u16 tmp;
14808c2ecf20Sopenharmony_ci	int i;
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	//SPEC TODO Call LP PHY Clear TX Power offsets
14838c2ecf20Sopenharmony_ci	for (i = 0; i < 64; i++) {
14848c2ecf20Sopenharmony_ci		if (dev->phy.rev >= 2)
14858c2ecf20Sopenharmony_ci			b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i);
14868c2ecf20Sopenharmony_ci		else
14878c2ecf20Sopenharmony_ci			b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i);
14888c2ecf20Sopenharmony_ci	}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF);
14918c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000);
14928c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F);
14938c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
14948c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF);
14958c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000);
14968c2ecf20Sopenharmony_ci	} else {
14978c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE);
14988c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4);
14998c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10);
15008c2ecf20Sopenharmony_ci		b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1);
15018c2ecf20Sopenharmony_ci		lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA);
15028c2ecf20Sopenharmony_ci	}
15038c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000);
15048c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF);
15058c2ecf20Sopenharmony_ci	b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA);
15068c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
15078c2ecf20Sopenharmony_ci			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
15088c2ecf20Sopenharmony_ci			B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
15098c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF);
15108c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
15118c2ecf20Sopenharmony_ci			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
15128c2ecf20Sopenharmony_ci			B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW);
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
15158c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000);
15168c2ecf20Sopenharmony_ci		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF);
15178c2ecf20Sopenharmony_ci	} else {
15188c2ecf20Sopenharmony_ci		lpphy_set_tx_power_by_index(dev, 0x7F);
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	b43_dummy_transmission(dev, true, true);
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT);
15248c2ecf20Sopenharmony_ci	if (tmp & 0x8000) {
15258c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI,
15268c2ecf20Sopenharmony_ci				0xFFC0, (tmp & 0xFF) - 32);
15278c2ecf20Sopenharmony_ci	}
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF);
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	// (SPEC?) TODO Set "Target TX frequency" variable to 0
15328c2ecf20Sopenharmony_ci	// SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8!
15338c2ecf20Sopenharmony_ci}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_cistatic void lpphy_tx_pctl_init_sw(struct b43_wldev *dev)
15368c2ecf20Sopenharmony_ci{
15378c2ecf20Sopenharmony_ci	struct lpphy_tx_gains gains;
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
15408c2ecf20Sopenharmony_ci		gains.gm = 4;
15418c2ecf20Sopenharmony_ci		gains.pad = 12;
15428c2ecf20Sopenharmony_ci		gains.pga = 12;
15438c2ecf20Sopenharmony_ci		gains.dac = 0;
15448c2ecf20Sopenharmony_ci	} else {
15458c2ecf20Sopenharmony_ci		gains.gm = 7;
15468c2ecf20Sopenharmony_ci		gains.pad = 14;
15478c2ecf20Sopenharmony_ci		gains.pga = 15;
15488c2ecf20Sopenharmony_ci		gains.dac = 0;
15498c2ecf20Sopenharmony_ci	}
15508c2ecf20Sopenharmony_ci	lpphy_set_tx_gains(dev, gains);
15518c2ecf20Sopenharmony_ci	lpphy_set_bb_mult(dev, 150);
15528c2ecf20Sopenharmony_ci}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci/* Initialize TX power control */
15558c2ecf20Sopenharmony_cistatic void lpphy_tx_pctl_init(struct b43_wldev *dev)
15568c2ecf20Sopenharmony_ci{
15578c2ecf20Sopenharmony_ci	if (0/*FIXME HWPCTL capable */) {
15588c2ecf20Sopenharmony_ci		lpphy_tx_pctl_init_hw(dev);
15598c2ecf20Sopenharmony_ci	} else { /* This device is only software TX power control capable. */
15608c2ecf20Sopenharmony_ci		lpphy_tx_pctl_init_sw(dev);
15618c2ecf20Sopenharmony_ci	}
15628c2ecf20Sopenharmony_ci}
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_cistatic void lpphy_pr41573_workaround(struct b43_wldev *dev)
15658c2ecf20Sopenharmony_ci{
15668c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
15678c2ecf20Sopenharmony_ci	u32 *saved_tab;
15688c2ecf20Sopenharmony_ci	const unsigned int saved_tab_size = 256;
15698c2ecf20Sopenharmony_ci	enum b43_lpphy_txpctl_mode txpctl_mode;
15708c2ecf20Sopenharmony_ci	s8 tx_pwr_idx_over;
15718c2ecf20Sopenharmony_ci	u16 tssi_npt, tssi_idx;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL);
15748c2ecf20Sopenharmony_ci	if (!saved_tab) {
15758c2ecf20Sopenharmony_ci		b43err(dev->wl, "PR41573 failed. Out of memory!\n");
15768c2ecf20Sopenharmony_ci		return;
15778c2ecf20Sopenharmony_ci	}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
15808c2ecf20Sopenharmony_ci	txpctl_mode = lpphy->txpctl_mode;
15818c2ecf20Sopenharmony_ci	tx_pwr_idx_over = lpphy->tx_pwr_idx_over;
15828c2ecf20Sopenharmony_ci	tssi_npt = lpphy->tssi_npt;
15838c2ecf20Sopenharmony_ci	tssi_idx = lpphy->tssi_idx;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
15868c2ecf20Sopenharmony_ci		b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140),
15878c2ecf20Sopenharmony_ci				    saved_tab_size, saved_tab);
15888c2ecf20Sopenharmony_ci	} else {
15898c2ecf20Sopenharmony_ci		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
15908c2ecf20Sopenharmony_ci				    saved_tab_size, saved_tab);
15918c2ecf20Sopenharmony_ci	}
15928c2ecf20Sopenharmony_ci	//FIXME PHY reset
15938c2ecf20Sopenharmony_ci	lpphy_table_init(dev); //FIXME is table init needed?
15948c2ecf20Sopenharmony_ci	lpphy_baseband_init(dev);
15958c2ecf20Sopenharmony_ci	lpphy_tx_pctl_init(dev);
15968c2ecf20Sopenharmony_ci	b43_lpphy_op_software_rfkill(dev, false);
15978c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
15988c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
15998c2ecf20Sopenharmony_ci		b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
16008c2ecf20Sopenharmony_ci				     saved_tab_size, saved_tab);
16018c2ecf20Sopenharmony_ci	} else {
16028c2ecf20Sopenharmony_ci		b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
16038c2ecf20Sopenharmony_ci				     saved_tab_size, saved_tab);
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
16068c2ecf20Sopenharmony_ci	lpphy->tssi_npt = tssi_npt;
16078c2ecf20Sopenharmony_ci	lpphy->tssi_idx = tssi_idx;
16088c2ecf20Sopenharmony_ci	lpphy_set_analog_filter(dev, lpphy->channel);
16098c2ecf20Sopenharmony_ci	if (tx_pwr_idx_over != -1)
16108c2ecf20Sopenharmony_ci		lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
16118c2ecf20Sopenharmony_ci	if (lpphy->rc_cap)
16128c2ecf20Sopenharmony_ci		lpphy_set_rc_cap(dev);
16138c2ecf20Sopenharmony_ci	b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
16148c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, txpctl_mode);
16158c2ecf20Sopenharmony_ci	kfree(saved_tab);
16168c2ecf20Sopenharmony_ci}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_cistruct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cistatic const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
16218c2ecf20Sopenharmony_ci	{ .chan = 1, .c1 = -66, .c0 = 15, },
16228c2ecf20Sopenharmony_ci	{ .chan = 2, .c1 = -66, .c0 = 15, },
16238c2ecf20Sopenharmony_ci	{ .chan = 3, .c1 = -66, .c0 = 15, },
16248c2ecf20Sopenharmony_ci	{ .chan = 4, .c1 = -66, .c0 = 15, },
16258c2ecf20Sopenharmony_ci	{ .chan = 5, .c1 = -66, .c0 = 15, },
16268c2ecf20Sopenharmony_ci	{ .chan = 6, .c1 = -66, .c0 = 15, },
16278c2ecf20Sopenharmony_ci	{ .chan = 7, .c1 = -66, .c0 = 14, },
16288c2ecf20Sopenharmony_ci	{ .chan = 8, .c1 = -66, .c0 = 14, },
16298c2ecf20Sopenharmony_ci	{ .chan = 9, .c1 = -66, .c0 = 14, },
16308c2ecf20Sopenharmony_ci	{ .chan = 10, .c1 = -66, .c0 = 14, },
16318c2ecf20Sopenharmony_ci	{ .chan = 11, .c1 = -66, .c0 = 14, },
16328c2ecf20Sopenharmony_ci	{ .chan = 12, .c1 = -66, .c0 = 13, },
16338c2ecf20Sopenharmony_ci	{ .chan = 13, .c1 = -66, .c0 = 13, },
16348c2ecf20Sopenharmony_ci	{ .chan = 14, .c1 = -66, .c0 = 13, },
16358c2ecf20Sopenharmony_ci};
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_cistatic const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
16388c2ecf20Sopenharmony_ci	{ .chan = 1, .c1 = -64, .c0 = 13, },
16398c2ecf20Sopenharmony_ci	{ .chan = 2, .c1 = -64, .c0 = 13, },
16408c2ecf20Sopenharmony_ci	{ .chan = 3, .c1 = -64, .c0 = 13, },
16418c2ecf20Sopenharmony_ci	{ .chan = 4, .c1 = -64, .c0 = 13, },
16428c2ecf20Sopenharmony_ci	{ .chan = 5, .c1 = -64, .c0 = 12, },
16438c2ecf20Sopenharmony_ci	{ .chan = 6, .c1 = -64, .c0 = 12, },
16448c2ecf20Sopenharmony_ci	{ .chan = 7, .c1 = -64, .c0 = 12, },
16458c2ecf20Sopenharmony_ci	{ .chan = 8, .c1 = -64, .c0 = 12, },
16468c2ecf20Sopenharmony_ci	{ .chan = 9, .c1 = -64, .c0 = 12, },
16478c2ecf20Sopenharmony_ci	{ .chan = 10, .c1 = -64, .c0 = 11, },
16488c2ecf20Sopenharmony_ci	{ .chan = 11, .c1 = -64, .c0 = 11, },
16498c2ecf20Sopenharmony_ci	{ .chan = 12, .c1 = -64, .c0 = 11, },
16508c2ecf20Sopenharmony_ci	{ .chan = 13, .c1 = -64, .c0 = 11, },
16518c2ecf20Sopenharmony_ci	{ .chan = 14, .c1 = -64, .c0 = 10, },
16528c2ecf20Sopenharmony_ci	{ .chan = 34, .c1 = -62, .c0 = 24, },
16538c2ecf20Sopenharmony_ci	{ .chan = 38, .c1 = -62, .c0 = 24, },
16548c2ecf20Sopenharmony_ci	{ .chan = 42, .c1 = -62, .c0 = 24, },
16558c2ecf20Sopenharmony_ci	{ .chan = 46, .c1 = -62, .c0 = 23, },
16568c2ecf20Sopenharmony_ci	{ .chan = 36, .c1 = -62, .c0 = 24, },
16578c2ecf20Sopenharmony_ci	{ .chan = 40, .c1 = -62, .c0 = 24, },
16588c2ecf20Sopenharmony_ci	{ .chan = 44, .c1 = -62, .c0 = 23, },
16598c2ecf20Sopenharmony_ci	{ .chan = 48, .c1 = -62, .c0 = 23, },
16608c2ecf20Sopenharmony_ci	{ .chan = 52, .c1 = -62, .c0 = 23, },
16618c2ecf20Sopenharmony_ci	{ .chan = 56, .c1 = -62, .c0 = 22, },
16628c2ecf20Sopenharmony_ci	{ .chan = 60, .c1 = -62, .c0 = 22, },
16638c2ecf20Sopenharmony_ci	{ .chan = 64, .c1 = -62, .c0 = 22, },
16648c2ecf20Sopenharmony_ci	{ .chan = 100, .c1 = -62, .c0 = 16, },
16658c2ecf20Sopenharmony_ci	{ .chan = 104, .c1 = -62, .c0 = 16, },
16668c2ecf20Sopenharmony_ci	{ .chan = 108, .c1 = -62, .c0 = 15, },
16678c2ecf20Sopenharmony_ci	{ .chan = 112, .c1 = -62, .c0 = 14, },
16688c2ecf20Sopenharmony_ci	{ .chan = 116, .c1 = -62, .c0 = 14, },
16698c2ecf20Sopenharmony_ci	{ .chan = 120, .c1 = -62, .c0 = 13, },
16708c2ecf20Sopenharmony_ci	{ .chan = 124, .c1 = -62, .c0 = 12, },
16718c2ecf20Sopenharmony_ci	{ .chan = 128, .c1 = -62, .c0 = 12, },
16728c2ecf20Sopenharmony_ci	{ .chan = 132, .c1 = -62, .c0 = 12, },
16738c2ecf20Sopenharmony_ci	{ .chan = 136, .c1 = -62, .c0 = 11, },
16748c2ecf20Sopenharmony_ci	{ .chan = 140, .c1 = -62, .c0 = 10, },
16758c2ecf20Sopenharmony_ci	{ .chan = 149, .c1 = -61, .c0 = 9, },
16768c2ecf20Sopenharmony_ci	{ .chan = 153, .c1 = -61, .c0 = 9, },
16778c2ecf20Sopenharmony_ci	{ .chan = 157, .c1 = -61, .c0 = 9, },
16788c2ecf20Sopenharmony_ci	{ .chan = 161, .c1 = -61, .c0 = 8, },
16798c2ecf20Sopenharmony_ci	{ .chan = 165, .c1 = -61, .c0 = 8, },
16808c2ecf20Sopenharmony_ci	{ .chan = 184, .c1 = -62, .c0 = 25, },
16818c2ecf20Sopenharmony_ci	{ .chan = 188, .c1 = -62, .c0 = 25, },
16828c2ecf20Sopenharmony_ci	{ .chan = 192, .c1 = -62, .c0 = 25, },
16838c2ecf20Sopenharmony_ci	{ .chan = 196, .c1 = -62, .c0 = 25, },
16848c2ecf20Sopenharmony_ci	{ .chan = 200, .c1 = -62, .c0 = 25, },
16858c2ecf20Sopenharmony_ci	{ .chan = 204, .c1 = -62, .c0 = 25, },
16868c2ecf20Sopenharmony_ci	{ .chan = 208, .c1 = -62, .c0 = 25, },
16878c2ecf20Sopenharmony_ci	{ .chan = 212, .c1 = -62, .c0 = 25, },
16888c2ecf20Sopenharmony_ci	{ .chan = 216, .c1 = -62, .c0 = 26, },
16898c2ecf20Sopenharmony_ci};
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_cistatic const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
16928c2ecf20Sopenharmony_ci	.chan = 0,
16938c2ecf20Sopenharmony_ci	.c1 = -64,
16948c2ecf20Sopenharmony_ci	.c0 = 0,
16958c2ecf20Sopenharmony_ci};
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_cistatic int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
16988c2ecf20Sopenharmony_ci{
16998c2ecf20Sopenharmony_ci	struct lpphy_iq_est iq_est;
17008c2ecf20Sopenharmony_ci	u16 c0, c1;
17018c2ecf20Sopenharmony_ci	int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
17048c2ecf20Sopenharmony_ci	c0 = c1 >> 8;
17058c2ecf20Sopenharmony_ci	c1 |= 0xFF;
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
17088c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
17118c2ecf20Sopenharmony_ci	if (!ret)
17128c2ecf20Sopenharmony_ci		goto out;
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	prod = iq_est.iq_prod;
17158c2ecf20Sopenharmony_ci	ipwr = iq_est.i_pwr;
17168c2ecf20Sopenharmony_ci	qpwr = iq_est.q_pwr;
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	if (ipwr + qpwr < 2) {
17198c2ecf20Sopenharmony_ci		ret = 0;
17208c2ecf20Sopenharmony_ci		goto out;
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	prod_msb = fls(abs(prod));
17248c2ecf20Sopenharmony_ci	q_msb = fls(abs(qpwr));
17258c2ecf20Sopenharmony_ci	tmp1 = prod_msb - 20;
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	if (tmp1 >= 0) {
17288c2ecf20Sopenharmony_ci		tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
17298c2ecf20Sopenharmony_ci			(ipwr >> tmp1);
17308c2ecf20Sopenharmony_ci	} else {
17318c2ecf20Sopenharmony_ci		tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
17328c2ecf20Sopenharmony_ci			(ipwr << -tmp1);
17338c2ecf20Sopenharmony_ci	}
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	tmp2 = q_msb - 11;
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	if (tmp2 >= 0)
17388c2ecf20Sopenharmony_ci		tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
17398c2ecf20Sopenharmony_ci	else
17408c2ecf20Sopenharmony_ci		tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	tmp4 -= tmp3 * tmp3;
17438c2ecf20Sopenharmony_ci	tmp4 = -int_sqrt(tmp4);
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	c0 = tmp3 >> 3;
17468c2ecf20Sopenharmony_ci	c1 = tmp4 >> 4;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ciout:
17498c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
17508c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
17518c2ecf20Sopenharmony_ci	return ret;
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_cistatic void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
17558c2ecf20Sopenharmony_ci			      u16 wait)
17568c2ecf20Sopenharmony_ci{
17578c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
17588c2ecf20Sopenharmony_ci			0xFFC0, samples - 1);
17598c2ecf20Sopenharmony_ci	if (loops != 0xFFFF)
17608c2ecf20Sopenharmony_ci		loops--;
17618c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
17628c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
17638c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
17648c2ecf20Sopenharmony_ci}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci//SPEC FIXME what does a negative freq mean?
17678c2ecf20Sopenharmony_cistatic void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
17688c2ecf20Sopenharmony_ci{
17698c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
17708c2ecf20Sopenharmony_ci	u16 buf[64];
17718c2ecf20Sopenharmony_ci	int i, samples = 0, theta = 0;
17728c2ecf20Sopenharmony_ci	int rotation = (((36 * freq) / 20) << 16) / 100;
17738c2ecf20Sopenharmony_ci	struct cordic_iq sample;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	lpphy->tx_tone_freq = freq;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	if (freq) {
17788c2ecf20Sopenharmony_ci		/* Find i for which abs(freq) integrally divides 20000 * i */
17798c2ecf20Sopenharmony_ci		for (i = 1; samples * abs(freq) != 20000 * i; i++) {
17808c2ecf20Sopenharmony_ci			samples = (20000 * i) / abs(freq);
17818c2ecf20Sopenharmony_ci			if(B43_WARN_ON(samples > 63))
17828c2ecf20Sopenharmony_ci				return;
17838c2ecf20Sopenharmony_ci		}
17848c2ecf20Sopenharmony_ci	} else {
17858c2ecf20Sopenharmony_ci		samples = 2;
17868c2ecf20Sopenharmony_ci	}
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	for (i = 0; i < samples; i++) {
17898c2ecf20Sopenharmony_ci		sample = cordic_calc_iq(CORDIC_FIXED(theta));
17908c2ecf20Sopenharmony_ci		theta += rotation;
17918c2ecf20Sopenharmony_ci		buf[i] = CORDIC_FLOAT((sample.i * max) & 0xFF) << 8;
17928c2ecf20Sopenharmony_ci		buf[i] |= CORDIC_FLOAT((sample.q * max) & 0xFF);
17938c2ecf20Sopenharmony_ci	}
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	lpphy_run_samples(dev, samples, 0xFFFF, 0);
17988c2ecf20Sopenharmony_ci}
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_cistatic void lpphy_stop_tx_tone(struct b43_wldev *dev)
18018c2ecf20Sopenharmony_ci{
18028c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
18038c2ecf20Sopenharmony_ci	int i;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	lpphy->tx_tone_freq = 0;
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
18088c2ecf20Sopenharmony_ci	for (i = 0; i < 31; i++) {
18098c2ecf20Sopenharmony_ci		if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
18108c2ecf20Sopenharmony_ci			break;
18118c2ecf20Sopenharmony_ci		udelay(100);
18128c2ecf20Sopenharmony_ci	}
18138c2ecf20Sopenharmony_ci}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_cistatic void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
18178c2ecf20Sopenharmony_ci{
18188c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
18198c2ecf20Sopenharmony_ci	struct lpphy_tx_gains oldgains;
18208c2ecf20Sopenharmony_ci	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
18238c2ecf20Sopenharmony_ci	old_txpctl = lpphy->txpctl_mode;
18248c2ecf20Sopenharmony_ci	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
18258c2ecf20Sopenharmony_ci	if (old_afe_ovr)
18268c2ecf20Sopenharmony_ci		oldgains = lpphy_get_tx_gains(dev);
18278c2ecf20Sopenharmony_ci	old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
18288c2ecf20Sopenharmony_ci	old_bbmult = lpphy_get_bb_mult(dev);
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	if (old_afe_ovr)
18338c2ecf20Sopenharmony_ci		lpphy_set_tx_gains(dev, oldgains);
18348c2ecf20Sopenharmony_ci	lpphy_set_bb_mult(dev, old_bbmult);
18358c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, old_txpctl);
18368c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
18378c2ecf20Sopenharmony_ci}
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_cistatic int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
18408c2ecf20Sopenharmony_ci			    bool rx, bool pa, struct lpphy_tx_gains *gains)
18418c2ecf20Sopenharmony_ci{
18428c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
18438c2ecf20Sopenharmony_ci	const struct lpphy_rx_iq_comp *iqcomp = NULL;
18448c2ecf20Sopenharmony_ci	struct lpphy_tx_gains nogains, oldgains;
18458c2ecf20Sopenharmony_ci	u16 tmp;
18468c2ecf20Sopenharmony_ci	int i, ret;
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci	memset(&nogains, 0, sizeof(nogains));
18498c2ecf20Sopenharmony_ci	memset(&oldgains, 0, sizeof(oldgains));
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	if (dev->dev->chip_id == 0x5354) {
18528c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
18538c2ecf20Sopenharmony_ci			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
18548c2ecf20Sopenharmony_ci				iqcomp = &lpphy_5354_iq_table[i];
18558c2ecf20Sopenharmony_ci			}
18568c2ecf20Sopenharmony_ci		}
18578c2ecf20Sopenharmony_ci	} else if (dev->phy.rev >= 2) {
18588c2ecf20Sopenharmony_ci		iqcomp = &lpphy_rev2plus_iq_comp;
18598c2ecf20Sopenharmony_ci	} else {
18608c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
18618c2ecf20Sopenharmony_ci			if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
18628c2ecf20Sopenharmony_ci				iqcomp = &lpphy_rev0_1_iq_table[i];
18638c2ecf20Sopenharmony_ci			}
18648c2ecf20Sopenharmony_ci		}
18658c2ecf20Sopenharmony_ci	}
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	if (B43_WARN_ON(!iqcomp))
18688c2ecf20Sopenharmony_ci		return 0;
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
18718c2ecf20Sopenharmony_ci	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
18728c2ecf20Sopenharmony_ci			0x00FF, iqcomp->c0 << 8);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	if (noise) {
18758c2ecf20Sopenharmony_ci		tx = true;
18768c2ecf20Sopenharmony_ci		rx = false;
18778c2ecf20Sopenharmony_ci		pa = false;
18788c2ecf20Sopenharmony_ci	}
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci	lpphy_set_trsw_over(dev, tx, rx);
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
18838c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
18848c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
18858c2ecf20Sopenharmony_ci				0xFFF7, pa << 3);
18868c2ecf20Sopenharmony_ci	} else {
18878c2ecf20Sopenharmony_ci		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
18888c2ecf20Sopenharmony_ci		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
18898c2ecf20Sopenharmony_ci				0xFFDF, pa << 5);
18908c2ecf20Sopenharmony_ci	}
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci	tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci	if (noise)
18958c2ecf20Sopenharmony_ci		lpphy_set_rx_gain(dev, 0x2D5D);
18968c2ecf20Sopenharmony_ci	else {
18978c2ecf20Sopenharmony_ci		if (tmp)
18988c2ecf20Sopenharmony_ci			oldgains = lpphy_get_tx_gains(dev);
18998c2ecf20Sopenharmony_ci		if (!gains)
19008c2ecf20Sopenharmony_ci			gains = &nogains;
19018c2ecf20Sopenharmony_ci		lpphy_set_tx_gains(dev, *gains);
19028c2ecf20Sopenharmony_ci	}
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
19058c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
19068c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
19078c2ecf20Sopenharmony_ci	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
19088c2ecf20Sopenharmony_ci	lpphy_set_deaf(dev, false);
19098c2ecf20Sopenharmony_ci	if (noise)
19108c2ecf20Sopenharmony_ci		ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
19118c2ecf20Sopenharmony_ci	else {
19128c2ecf20Sopenharmony_ci		lpphy_start_tx_tone(dev, 4000, 100);
19138c2ecf20Sopenharmony_ci		ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
19148c2ecf20Sopenharmony_ci		lpphy_stop_tx_tone(dev);
19158c2ecf20Sopenharmony_ci	}
19168c2ecf20Sopenharmony_ci	lpphy_clear_deaf(dev, false);
19178c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
19188c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
19198c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
19208c2ecf20Sopenharmony_ci	if (!noise) {
19218c2ecf20Sopenharmony_ci		if (tmp)
19228c2ecf20Sopenharmony_ci			lpphy_set_tx_gains(dev, oldgains);
19238c2ecf20Sopenharmony_ci		else
19248c2ecf20Sopenharmony_ci			lpphy_disable_tx_gain_override(dev);
19258c2ecf20Sopenharmony_ci	}
19268c2ecf20Sopenharmony_ci	lpphy_disable_rx_gain_override(dev);
19278c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
19288c2ecf20Sopenharmony_ci	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
19298c2ecf20Sopenharmony_ci	return ret;
19308c2ecf20Sopenharmony_ci}
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_cistatic void lpphy_calibration(struct b43_wldev *dev)
19338c2ecf20Sopenharmony_ci{
19348c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
19358c2ecf20Sopenharmony_ci	enum b43_lpphy_txpctl_mode saved_pctl_mode;
19368c2ecf20Sopenharmony_ci	bool full_cal = false;
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci	if (lpphy->full_calib_chan != lpphy->channel) {
19398c2ecf20Sopenharmony_ci		full_cal = true;
19408c2ecf20Sopenharmony_ci		lpphy->full_calib_chan = lpphy->channel;
19418c2ecf20Sopenharmony_ci	}
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	b43_mac_suspend(dev);
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	lpphy_btcoex_override(dev);
19468c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2)
19478c2ecf20Sopenharmony_ci		lpphy_save_dig_flt_state(dev);
19488c2ecf20Sopenharmony_ci	lpphy_read_tx_pctl_mode_from_hardware(dev);
19498c2ecf20Sopenharmony_ci	saved_pctl_mode = lpphy->txpctl_mode;
19508c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
19518c2ecf20Sopenharmony_ci	//TODO Perform transmit power table I/Q LO calibration
19528c2ecf20Sopenharmony_ci	if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
19538c2ecf20Sopenharmony_ci		lpphy_pr41573_workaround(dev);
19548c2ecf20Sopenharmony_ci	if ((dev->phy.rev >= 2) && full_cal) {
19558c2ecf20Sopenharmony_ci		lpphy_papd_cal_txpwr(dev);
19568c2ecf20Sopenharmony_ci	}
19578c2ecf20Sopenharmony_ci	lpphy_set_tx_power_control(dev, saved_pctl_mode);
19588c2ecf20Sopenharmony_ci	if (dev->phy.rev >= 2)
19598c2ecf20Sopenharmony_ci		lpphy_restore_dig_flt_state(dev);
19608c2ecf20Sopenharmony_ci	lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci	b43_mac_enable(dev);
19638c2ecf20Sopenharmony_ci}
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_cistatic void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
19668c2ecf20Sopenharmony_ci				 u16 set)
19678c2ecf20Sopenharmony_ci{
19688c2ecf20Sopenharmony_ci	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
19698c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_PHY_DATA,
19708c2ecf20Sopenharmony_ci		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
19718c2ecf20Sopenharmony_ci}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_cistatic u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
19748c2ecf20Sopenharmony_ci{
19758c2ecf20Sopenharmony_ci	/* Register 1 is a 32-bit register. */
19768c2ecf20Sopenharmony_ci	B43_WARN_ON(reg == 1);
19778c2ecf20Sopenharmony_ci	/* LP-PHY needs a special bit set for read access */
19788c2ecf20Sopenharmony_ci	if (dev->phy.rev < 2) {
19798c2ecf20Sopenharmony_ci		if (reg != 0x4001)
19808c2ecf20Sopenharmony_ci			reg |= 0x100;
19818c2ecf20Sopenharmony_ci	} else
19828c2ecf20Sopenharmony_ci		reg |= 0x200;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
19858c2ecf20Sopenharmony_ci	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
19868c2ecf20Sopenharmony_ci}
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_cistatic void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
19898c2ecf20Sopenharmony_ci{
19908c2ecf20Sopenharmony_ci	/* Register 1 is a 32-bit register. */
19918c2ecf20Sopenharmony_ci	B43_WARN_ON(reg == 1);
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
19948c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
19958c2ecf20Sopenharmony_ci}
19968c2ecf20Sopenharmony_ci
19978c2ecf20Sopenharmony_cistruct b206x_channel {
19988c2ecf20Sopenharmony_ci	u8 channel;
19998c2ecf20Sopenharmony_ci	u16 freq;
20008c2ecf20Sopenharmony_ci	u8 data[12];
20018c2ecf20Sopenharmony_ci};
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_cistatic const struct b206x_channel b2062_chantbl[] = {
20048c2ecf20Sopenharmony_ci	{ .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF,
20058c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20068c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20078c2ecf20Sopenharmony_ci	{ .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF,
20088c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20098c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20108c2ecf20Sopenharmony_ci	{ .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF,
20118c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20128c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20138c2ecf20Sopenharmony_ci	{ .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF,
20148c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20158c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20168c2ecf20Sopenharmony_ci	{ .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF,
20178c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20188c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20198c2ecf20Sopenharmony_ci	{ .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF,
20208c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20218c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20228c2ecf20Sopenharmony_ci	{ .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF,
20238c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20248c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20258c2ecf20Sopenharmony_ci	{ .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF,
20268c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20278c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20288c2ecf20Sopenharmony_ci	{ .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF,
20298c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20308c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20318c2ecf20Sopenharmony_ci	{ .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF,
20328c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20338c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20348c2ecf20Sopenharmony_ci	{ .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF,
20358c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20368c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20378c2ecf20Sopenharmony_ci	{ .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF,
20388c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20398c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20408c2ecf20Sopenharmony_ci	{ .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF,
20418c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20428c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20438c2ecf20Sopenharmony_ci	{ .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF,
20448c2ecf20Sopenharmony_ci	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
20458c2ecf20Sopenharmony_ci	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
20468c2ecf20Sopenharmony_ci	{ .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22,
20478c2ecf20Sopenharmony_ci	  .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
20488c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20498c2ecf20Sopenharmony_ci	{ .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11,
20508c2ecf20Sopenharmony_ci	  .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20518c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20528c2ecf20Sopenharmony_ci	{ .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11,
20538c2ecf20Sopenharmony_ci	  .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20548c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20558c2ecf20Sopenharmony_ci	{ .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00,
20568c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20578c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20588c2ecf20Sopenharmony_ci	{ .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11,
20598c2ecf20Sopenharmony_ci	  .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20608c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20618c2ecf20Sopenharmony_ci	{ .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11,
20628c2ecf20Sopenharmony_ci	  .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
20638c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20648c2ecf20Sopenharmony_ci	{ .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11,
20658c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20668c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20678c2ecf20Sopenharmony_ci	{ .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00,
20688c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20698c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20708c2ecf20Sopenharmony_ci	{ .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00,
20718c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20728c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20738c2ecf20Sopenharmony_ci	{ .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00,
20748c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
20758c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20768c2ecf20Sopenharmony_ci	{ .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00,
20778c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77,
20788c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20798c2ecf20Sopenharmony_ci	{ .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00,
20808c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77,
20818c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
20828c2ecf20Sopenharmony_ci	{ .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00,
20838c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77,
20848c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
20858c2ecf20Sopenharmony_ci	{ .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00,
20868c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
20878c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
20888c2ecf20Sopenharmony_ci	{ .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00,
20898c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
20908c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
20918c2ecf20Sopenharmony_ci	{ .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00,
20928c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
20938c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
20948c2ecf20Sopenharmony_ci	{ .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00,
20958c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77,
20968c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
20978c2ecf20Sopenharmony_ci	{ .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00,
20988c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
20998c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21008c2ecf20Sopenharmony_ci	{ .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00,
21018c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21028c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21038c2ecf20Sopenharmony_ci	{ .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00,
21048c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21058c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21068c2ecf20Sopenharmony_ci	{ .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00,
21078c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21088c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21098c2ecf20Sopenharmony_ci	{ .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00,
21108c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21118c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21128c2ecf20Sopenharmony_ci	{ .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00,
21138c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21148c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21158c2ecf20Sopenharmony_ci	{ .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00,
21168c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21178c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21188c2ecf20Sopenharmony_ci	{ .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00,
21198c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21208c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21218c2ecf20Sopenharmony_ci	{ .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00,
21228c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21238c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21248c2ecf20Sopenharmony_ci	{ .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00,
21258c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21268c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21278c2ecf20Sopenharmony_ci	{ .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00,
21288c2ecf20Sopenharmony_ci	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
21298c2ecf20Sopenharmony_ci	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
21308c2ecf20Sopenharmony_ci	{ .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77,
21318c2ecf20Sopenharmony_ci	  .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77,
21328c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21338c2ecf20Sopenharmony_ci	{ .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77,
21348c2ecf20Sopenharmony_ci	  .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
21358c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21368c2ecf20Sopenharmony_ci	{ .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66,
21378c2ecf20Sopenharmony_ci	  .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
21388c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21398c2ecf20Sopenharmony_ci	{ .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66,
21408c2ecf20Sopenharmony_ci	  .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
21418c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21428c2ecf20Sopenharmony_ci	{ .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55,
21438c2ecf20Sopenharmony_ci	  .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77,
21448c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21458c2ecf20Sopenharmony_ci	{ .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55,
21468c2ecf20Sopenharmony_ci	  .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
21478c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21488c2ecf20Sopenharmony_ci	{ .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44,
21498c2ecf20Sopenharmony_ci	  .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
21508c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
21518c2ecf20Sopenharmony_ci	{ .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44,
21528c2ecf20Sopenharmony_ci	  .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77,
21538c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
21548c2ecf20Sopenharmony_ci	{ .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44,
21558c2ecf20Sopenharmony_ci	  .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77,
21568c2ecf20Sopenharmony_ci	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
21578c2ecf20Sopenharmony_ci};
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_cistatic const struct b206x_channel b2063_chantbl[] = {
21608c2ecf20Sopenharmony_ci	{ .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C,
21618c2ecf20Sopenharmony_ci	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21628c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21638c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21648c2ecf20Sopenharmony_ci	{ .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C,
21658c2ecf20Sopenharmony_ci	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21668c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21678c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21688c2ecf20Sopenharmony_ci	{ .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C,
21698c2ecf20Sopenharmony_ci	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21708c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21718c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21728c2ecf20Sopenharmony_ci	{ .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C,
21738c2ecf20Sopenharmony_ci	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21748c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21758c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21768c2ecf20Sopenharmony_ci	{ .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C,
21778c2ecf20Sopenharmony_ci	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21788c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21798c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21808c2ecf20Sopenharmony_ci	{ .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C,
21818c2ecf20Sopenharmony_ci	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21828c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21838c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21848c2ecf20Sopenharmony_ci	{ .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C,
21858c2ecf20Sopenharmony_ci	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21868c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21878c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21888c2ecf20Sopenharmony_ci	{ .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C,
21898c2ecf20Sopenharmony_ci	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21908c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21918c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21928c2ecf20Sopenharmony_ci	{ .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C,
21938c2ecf20Sopenharmony_ci	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21948c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21958c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
21968c2ecf20Sopenharmony_ci	{ .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C,
21978c2ecf20Sopenharmony_ci	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
21988c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
21998c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
22008c2ecf20Sopenharmony_ci	{ .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C,
22018c2ecf20Sopenharmony_ci	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
22028c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
22038c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
22048c2ecf20Sopenharmony_ci	{ .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C,
22058c2ecf20Sopenharmony_ci	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
22068c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
22078c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
22088c2ecf20Sopenharmony_ci	{ .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C,
22098c2ecf20Sopenharmony_ci	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
22108c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
22118c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
22128c2ecf20Sopenharmony_ci	{ .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C,
22138c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
22148c2ecf20Sopenharmony_ci	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
22158c2ecf20Sopenharmony_ci	  .data[10] = 0x80, .data[11] = 0x70, },
22168c2ecf20Sopenharmony_ci	{ .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C,
22178c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05,
22188c2ecf20Sopenharmony_ci	  .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80,
22198c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22208c2ecf20Sopenharmony_ci	{ .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C,
22218c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05,
22228c2ecf20Sopenharmony_ci	  .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
22238c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22248c2ecf20Sopenharmony_ci	{ .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C,
22258c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
22268c2ecf20Sopenharmony_ci	  .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
22278c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22288c2ecf20Sopenharmony_ci	{ .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C,
22298c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
22308c2ecf20Sopenharmony_ci	  .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
22318c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22328c2ecf20Sopenharmony_ci	{ .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C,
22338c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
22348c2ecf20Sopenharmony_ci	  .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
22358c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22368c2ecf20Sopenharmony_ci	{ .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C,
22378c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04,
22388c2ecf20Sopenharmony_ci	  .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
22398c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22408c2ecf20Sopenharmony_ci	{ .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C,
22418c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
22428c2ecf20Sopenharmony_ci	  .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
22438c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22448c2ecf20Sopenharmony_ci	{ .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C,
22458c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
22468c2ecf20Sopenharmony_ci	  .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60,
22478c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22488c2ecf20Sopenharmony_ci	{ .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C,
22498c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02,
22508c2ecf20Sopenharmony_ci	  .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60,
22518c2ecf20Sopenharmony_ci	  .data[10] = 0x20, .data[11] = 0x00, },
22528c2ecf20Sopenharmony_ci	{ .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C,
22538c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
22548c2ecf20Sopenharmony_ci	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
22558c2ecf20Sopenharmony_ci	  .data[10] = 0x10, .data[11] = 0x00, },
22568c2ecf20Sopenharmony_ci	{ .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C,
22578c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
22588c2ecf20Sopenharmony_ci	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
22598c2ecf20Sopenharmony_ci	  .data[10] = 0x10, .data[11] = 0x00, },
22608c2ecf20Sopenharmony_ci	{ .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C,
22618c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22628c2ecf20Sopenharmony_ci	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
22638c2ecf20Sopenharmony_ci	  .data[10] = 0x10, .data[11] = 0x00, },
22648c2ecf20Sopenharmony_ci	{ .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C,
22658c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22668c2ecf20Sopenharmony_ci	  .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
22678c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22688c2ecf20Sopenharmony_ci	{ .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C,
22698c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22708c2ecf20Sopenharmony_ci	  .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
22718c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22728c2ecf20Sopenharmony_ci	{ .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C,
22738c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22748c2ecf20Sopenharmony_ci	  .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
22758c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22768c2ecf20Sopenharmony_ci	{ .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C,
22778c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22788c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
22798c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22808c2ecf20Sopenharmony_ci	{ .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C,
22818c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22828c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
22838c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22848c2ecf20Sopenharmony_ci	{ .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C,
22858c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22868c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
22878c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22888c2ecf20Sopenharmony_ci	{ .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C,
22898c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22908c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
22918c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22928c2ecf20Sopenharmony_ci	{ .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C,
22938c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22948c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
22958c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
22968c2ecf20Sopenharmony_ci	{ .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C,
22978c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
22988c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
22998c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23008c2ecf20Sopenharmony_ci	{ .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C,
23018c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23028c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23038c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23048c2ecf20Sopenharmony_ci	{ .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C,
23058c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23068c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23078c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23088c2ecf20Sopenharmony_ci	{ .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C,
23098c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23108c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23118c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23128c2ecf20Sopenharmony_ci	{ .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C,
23138c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23148c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23158c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23168c2ecf20Sopenharmony_ci	{ .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C,
23178c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23188c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23198c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23208c2ecf20Sopenharmony_ci	{ .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C,
23218c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23228c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23238c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23248c2ecf20Sopenharmony_ci	{ .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C,
23258c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
23268c2ecf20Sopenharmony_ci	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
23278c2ecf20Sopenharmony_ci	  .data[10] = 0x00, .data[11] = 0x00, },
23288c2ecf20Sopenharmony_ci	{ .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C,
23298c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E,
23308c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0,
23318c2ecf20Sopenharmony_ci	  .data[10] = 0x50, .data[11] = 0x00, },
23328c2ecf20Sopenharmony_ci	{ .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C,
23338c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D,
23348c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
23358c2ecf20Sopenharmony_ci	  .data[10] = 0x50, .data[11] = 0x00, },
23368c2ecf20Sopenharmony_ci	{ .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C,
23378c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
23388c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
23398c2ecf20Sopenharmony_ci	  .data[10] = 0x50, .data[11] = 0x00, },
23408c2ecf20Sopenharmony_ci	{ .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C,
23418c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
23428c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
23438c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23448c2ecf20Sopenharmony_ci	{ .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C,
23458c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B,
23468c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
23478c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23488c2ecf20Sopenharmony_ci	{ .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C,
23498c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A,
23508c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
23518c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23528c2ecf20Sopenharmony_ci	{ .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C,
23538c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09,
23548c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
23558c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23568c2ecf20Sopenharmony_ci	{ .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C,
23578c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08,
23588c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
23598c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23608c2ecf20Sopenharmony_ci	{ .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C,
23618c2ecf20Sopenharmony_ci	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08,
23628c2ecf20Sopenharmony_ci	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
23638c2ecf20Sopenharmony_ci	  .data[10] = 0x40, .data[11] = 0x00, },
23648c2ecf20Sopenharmony_ci};
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_cistatic void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
23678c2ecf20Sopenharmony_ci{
23688c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
23698c2ecf20Sopenharmony_ci	udelay(20);
23708c2ecf20Sopenharmony_ci	if (dev->dev->chip_id == 0x5354) {
23718c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_N_COMM1, 4);
23728c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
23738c2ecf20Sopenharmony_ci	} else {
23748c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0);
23758c2ecf20Sopenharmony_ci	}
23768c2ecf20Sopenharmony_ci	udelay(5);
23778c2ecf20Sopenharmony_ci}
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_cistatic void lpphy_b2062_vco_calib(struct b43_wldev *dev)
23808c2ecf20Sopenharmony_ci{
23818c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
23828c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
23838c2ecf20Sopenharmony_ci	udelay(200);
23848c2ecf20Sopenharmony_ci}
23858c2ecf20Sopenharmony_ci
23868c2ecf20Sopenharmony_cistatic int lpphy_b2062_tune(struct b43_wldev *dev,
23878c2ecf20Sopenharmony_ci			    unsigned int channel)
23888c2ecf20Sopenharmony_ci{
23898c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
23908c2ecf20Sopenharmony_ci	struct ssb_bus *bus = dev->dev->sdev->bus;
23918c2ecf20Sopenharmony_ci	const struct b206x_channel *chandata = NULL;
23928c2ecf20Sopenharmony_ci	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
23938c2ecf20Sopenharmony_ci	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
23948c2ecf20Sopenharmony_ci	int i, err = 0;
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) {
23978c2ecf20Sopenharmony_ci		if (b2062_chantbl[i].channel == channel) {
23988c2ecf20Sopenharmony_ci			chandata = &b2062_chantbl[i];
23998c2ecf20Sopenharmony_ci			break;
24008c2ecf20Sopenharmony_ci		}
24018c2ecf20Sopenharmony_ci	}
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	if (B43_WARN_ON(!chandata))
24048c2ecf20Sopenharmony_ci		return -EINVAL;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04);
24078c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]);
24088c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]);
24098c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]);
24108c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]);
24118c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]);
24128c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]);
24138c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]);
24148c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]);
24158c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]);
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	tmp1 = crystal_freq / 1000;
24188c2ecf20Sopenharmony_ci	tmp2 = lpphy->pdiv * 1000;
24198c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC);
24208c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07);
24218c2ecf20Sopenharmony_ci	lpphy_b2062_reset_pll_bias(dev);
24228c2ecf20Sopenharmony_ci	tmp3 = tmp2 * channel2freq_lp(channel);
24238c2ecf20Sopenharmony_ci	if (channel2freq_lp(channel) < 4000)
24248c2ecf20Sopenharmony_ci		tmp3 *= 2;
24258c2ecf20Sopenharmony_ci	tmp4 = 48 * tmp1;
24268c2ecf20Sopenharmony_ci	tmp6 = tmp3 / tmp4;
24278c2ecf20Sopenharmony_ci	tmp7 = tmp3 % tmp4;
24288c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6);
24298c2ecf20Sopenharmony_ci	tmp5 = tmp7 * 0x100;
24308c2ecf20Sopenharmony_ci	tmp6 = tmp5 / tmp4;
24318c2ecf20Sopenharmony_ci	tmp7 = tmp5 % tmp4;
24328c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6);
24338c2ecf20Sopenharmony_ci	tmp5 = tmp7 * 0x100;
24348c2ecf20Sopenharmony_ci	tmp6 = tmp5 / tmp4;
24358c2ecf20Sopenharmony_ci	tmp7 = tmp5 % tmp4;
24368c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6);
24378c2ecf20Sopenharmony_ci	tmp5 = tmp7 * 0x100;
24388c2ecf20Sopenharmony_ci	tmp6 = tmp5 / tmp4;
24398c2ecf20Sopenharmony_ci	tmp7 = tmp5 % tmp4;
24408c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
24418c2ecf20Sopenharmony_ci	tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
24428c2ecf20Sopenharmony_ci	tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
24438c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
24448c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci	lpphy_b2062_vco_calib(dev);
24478c2ecf20Sopenharmony_ci	if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) {
24488c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC);
24498c2ecf20Sopenharmony_ci		b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0);
24508c2ecf20Sopenharmony_ci		lpphy_b2062_reset_pll_bias(dev);
24518c2ecf20Sopenharmony_ci		lpphy_b2062_vco_calib(dev);
24528c2ecf20Sopenharmony_ci		if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10)
24538c2ecf20Sopenharmony_ci			err = -EIO;
24548c2ecf20Sopenharmony_ci	}
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04);
24578c2ecf20Sopenharmony_ci	return err;
24588c2ecf20Sopenharmony_ci}
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_cistatic void lpphy_b2063_vco_calib(struct b43_wldev *dev)
24618c2ecf20Sopenharmony_ci{
24628c2ecf20Sopenharmony_ci	u16 tmp;
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
24658c2ecf20Sopenharmony_ci	tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
24668c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
24678c2ecf20Sopenharmony_ci	udelay(1);
24688c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
24698c2ecf20Sopenharmony_ci	udelay(1);
24708c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
24718c2ecf20Sopenharmony_ci	udelay(1);
24728c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
24738c2ecf20Sopenharmony_ci	udelay(300);
24748c2ecf20Sopenharmony_ci	b43_radio_set(dev, B2063_PLL_SP1, 0x40);
24758c2ecf20Sopenharmony_ci}
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_cistatic int lpphy_b2063_tune(struct b43_wldev *dev,
24788c2ecf20Sopenharmony_ci			    unsigned int channel)
24798c2ecf20Sopenharmony_ci{
24808c2ecf20Sopenharmony_ci	struct ssb_bus *bus = dev->dev->sdev->bus;
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci	static const struct b206x_channel *chandata = NULL;
24838c2ecf20Sopenharmony_ci	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
24848c2ecf20Sopenharmony_ci	u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count;
24858c2ecf20Sopenharmony_ci	u16 old_comm15, scale;
24868c2ecf20Sopenharmony_ci	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
24878c2ecf20Sopenharmony_ci	int i, div = (crystal_freq <= 26000000 ? 1 : 2);
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) {
24908c2ecf20Sopenharmony_ci		if (b2063_chantbl[i].channel == channel) {
24918c2ecf20Sopenharmony_ci			chandata = &b2063_chantbl[i];
24928c2ecf20Sopenharmony_ci			break;
24938c2ecf20Sopenharmony_ci		}
24948c2ecf20Sopenharmony_ci	}
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	if (B43_WARN_ON(!chandata))
24978c2ecf20Sopenharmony_ci		return -EINVAL;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]);
25008c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]);
25018c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]);
25028c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]);
25038c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]);
25048c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]);
25058c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]);
25068c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]);
25078c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]);
25088c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]);
25098c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]);
25108c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]);
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	old_comm15 = b43_radio_read(dev, B2063_COMM15);
25138c2ecf20Sopenharmony_ci	b43_radio_set(dev, B2063_COMM15, 0x1E);
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */
25168c2ecf20Sopenharmony_ci		vco_freq = chandata->freq << 1;
25178c2ecf20Sopenharmony_ci	else
25188c2ecf20Sopenharmony_ci		vco_freq = chandata->freq << 2;
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	freqref = crystal_freq * 3;
25218c2ecf20Sopenharmony_ci	val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16);
25228c2ecf20Sopenharmony_ci	val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16);
25238c2ecf20Sopenharmony_ci	val3 = lpphy_qdiv_roundup(vco_freq, 3, 16);
25248c2ecf20Sopenharmony_ci	timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1;
25258c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2);
25268c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6,
25278c2ecf20Sopenharmony_ci			  0xFFF8, timeout >> 2);
25288c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
25298c2ecf20Sopenharmony_ci			  0xFF9F,timeout << 5);
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_ci	timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) +
25328c2ecf20Sopenharmony_ci						999999) / 1000000) + 1;
25338c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref);
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	count = lpphy_qdiv_roundup(val3, val2 + 16, 16);
25368c2ecf20Sopenharmony_ci	count *= (timeout + 1) * (timeoutref + 1);
25378c2ecf20Sopenharmony_ci	count--;
25388c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
25398c2ecf20Sopenharmony_ci						0xF0, count >> 8);
25408c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF);
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci	tmp1 = ((val3 * 62500) / freqref) << 4;
25438c2ecf20Sopenharmony_ci	tmp2 = ((val3 * 62500) % freqref) << 4;
25448c2ecf20Sopenharmony_ci	while (tmp2 >= freqref) {
25458c2ecf20Sopenharmony_ci		tmp1++;
25468c2ecf20Sopenharmony_ci		tmp2 -= freqref;
25478c2ecf20Sopenharmony_ci	}
25488c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4);
25498c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4);
25508c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16);
25518c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF);
25528c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF);
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9);
25558c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88);
25568c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28);
25578c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63);
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	tmp3 = ((41 * (val3 - 3000)) /1200) + 27;
25608c2ecf20Sopenharmony_ci	tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16);
25618c2ecf20Sopenharmony_ci
25628c2ecf20Sopenharmony_ci	if ((tmp4 + tmp3 - 1) / tmp3 > 60) {
25638c2ecf20Sopenharmony_ci		scale = 1;
25648c2ecf20Sopenharmony_ci		tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8;
25658c2ecf20Sopenharmony_ci	} else {
25668c2ecf20Sopenharmony_ci		scale = 0;
25678c2ecf20Sopenharmony_ci		tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
25688c2ecf20Sopenharmony_ci	}
25698c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
25708c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci	tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
25738c2ecf20Sopenharmony_ci	tmp6 *= (tmp5 * 8) * (scale + 1);
25748c2ecf20Sopenharmony_ci	if (tmp6 > 150)
25758c2ecf20Sopenharmony_ci		tmp6 = 0;
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
25788c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
25818c2ecf20Sopenharmony_ci	if (crystal_freq > 26000000)
25828c2ecf20Sopenharmony_ci		b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
25838c2ecf20Sopenharmony_ci	else
25848c2ecf20Sopenharmony_ci		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci	if (val1 == 45)
25878c2ecf20Sopenharmony_ci		b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
25888c2ecf20Sopenharmony_ci	else
25898c2ecf20Sopenharmony_ci		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	b43_radio_set(dev, B2063_PLL_SP2, 0x3);
25928c2ecf20Sopenharmony_ci	udelay(1);
25938c2ecf20Sopenharmony_ci	b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
25948c2ecf20Sopenharmony_ci	lpphy_b2063_vco_calib(dev);
25958c2ecf20Sopenharmony_ci	b43_radio_write(dev, B2063_COMM15, old_comm15);
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_ci	return 0;
25988c2ecf20Sopenharmony_ci}
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_cistatic int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
26018c2ecf20Sopenharmony_ci				       unsigned int new_channel)
26028c2ecf20Sopenharmony_ci{
26038c2ecf20Sopenharmony_ci	struct b43_phy_lp *lpphy = dev->phy.lp;
26048c2ecf20Sopenharmony_ci	int err;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	if (dev->phy.radio_ver == 0x2063) {
26078c2ecf20Sopenharmony_ci		err = lpphy_b2063_tune(dev, new_channel);
26088c2ecf20Sopenharmony_ci		if (err)
26098c2ecf20Sopenharmony_ci			return err;
26108c2ecf20Sopenharmony_ci	} else {
26118c2ecf20Sopenharmony_ci		err = lpphy_b2062_tune(dev, new_channel);
26128c2ecf20Sopenharmony_ci		if (err)
26138c2ecf20Sopenharmony_ci			return err;
26148c2ecf20Sopenharmony_ci		lpphy_set_analog_filter(dev, new_channel);
26158c2ecf20Sopenharmony_ci		lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
26168c2ecf20Sopenharmony_ci	}
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci	lpphy->channel = new_channel;
26198c2ecf20Sopenharmony_ci	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci	return 0;
26228c2ecf20Sopenharmony_ci}
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_cistatic int b43_lpphy_op_init(struct b43_wldev *dev)
26258c2ecf20Sopenharmony_ci{
26268c2ecf20Sopenharmony_ci	int err;
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_ci	if (dev->dev->bus_type != B43_BUS_SSB) {
26298c2ecf20Sopenharmony_ci		b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
26308c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
26318c2ecf20Sopenharmony_ci	}
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
26348c2ecf20Sopenharmony_ci	lpphy_baseband_init(dev);
26358c2ecf20Sopenharmony_ci	lpphy_radio_init(dev);
26368c2ecf20Sopenharmony_ci	lpphy_calibrate_rc(dev);
26378c2ecf20Sopenharmony_ci	err = b43_lpphy_op_switch_channel(dev, 7);
26388c2ecf20Sopenharmony_ci	if (err) {
26398c2ecf20Sopenharmony_ci		b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
26408c2ecf20Sopenharmony_ci		       err);
26418c2ecf20Sopenharmony_ci	}
26428c2ecf20Sopenharmony_ci	lpphy_tx_pctl_init(dev);
26438c2ecf20Sopenharmony_ci	lpphy_calibration(dev);
26448c2ecf20Sopenharmony_ci	//TODO ACI init
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci	return 0;
26478c2ecf20Sopenharmony_ci}
26488c2ecf20Sopenharmony_ci
26498c2ecf20Sopenharmony_cistatic void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
26508c2ecf20Sopenharmony_ci{
26518c2ecf20Sopenharmony_ci	//TODO
26528c2ecf20Sopenharmony_ci}
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_cistatic enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
26558c2ecf20Sopenharmony_ci							 bool ignore_tssi)
26568c2ecf20Sopenharmony_ci{
26578c2ecf20Sopenharmony_ci	//TODO
26588c2ecf20Sopenharmony_ci	return B43_TXPWR_RES_DONE;
26598c2ecf20Sopenharmony_ci}
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_cistatic void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
26628c2ecf20Sopenharmony_ci{
26638c2ecf20Sopenharmony_ci       if (on) {
26648c2ecf20Sopenharmony_ci               b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
26658c2ecf20Sopenharmony_ci       } else {
26668c2ecf20Sopenharmony_ci               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
26678c2ecf20Sopenharmony_ci               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
26688c2ecf20Sopenharmony_ci       }
26698c2ecf20Sopenharmony_ci}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_cistatic void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
26728c2ecf20Sopenharmony_ci{
26738c2ecf20Sopenharmony_ci	//TODO
26748c2ecf20Sopenharmony_ci}
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ciconst struct b43_phy_operations b43_phyops_lp = {
26778c2ecf20Sopenharmony_ci	.allocate		= b43_lpphy_op_allocate,
26788c2ecf20Sopenharmony_ci	.free			= b43_lpphy_op_free,
26798c2ecf20Sopenharmony_ci	.prepare_structs	= b43_lpphy_op_prepare_structs,
26808c2ecf20Sopenharmony_ci	.init			= b43_lpphy_op_init,
26818c2ecf20Sopenharmony_ci	.phy_maskset		= b43_lpphy_op_maskset,
26828c2ecf20Sopenharmony_ci	.radio_read		= b43_lpphy_op_radio_read,
26838c2ecf20Sopenharmony_ci	.radio_write		= b43_lpphy_op_radio_write,
26848c2ecf20Sopenharmony_ci	.software_rfkill	= b43_lpphy_op_software_rfkill,
26858c2ecf20Sopenharmony_ci	.switch_analog		= b43_lpphy_op_switch_analog,
26868c2ecf20Sopenharmony_ci	.switch_channel		= b43_lpphy_op_switch_channel,
26878c2ecf20Sopenharmony_ci	.get_default_chan	= b43_lpphy_op_get_default_chan,
26888c2ecf20Sopenharmony_ci	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,
26898c2ecf20Sopenharmony_ci	.recalc_txpower		= b43_lpphy_op_recalc_txpower,
26908c2ecf20Sopenharmony_ci	.adjust_txpower		= b43_lpphy_op_adjust_txpower,
26918c2ecf20Sopenharmony_ci	.pwork_15sec		= b43_lpphy_op_pwork_15sec,
26928c2ecf20Sopenharmony_ci	.pwork_60sec		= lpphy_calibration,
26938c2ecf20Sopenharmony_ci};
2694