@@ -1778,6 +1778,32 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
17781778 rtw89_fw_h2c_rf_ntfy_mcc (rtwdev );
17791779}
17801780
1781+ static u32 rtw8852c_bb_cal_txpwr_ref (struct rtw89_dev * rtwdev ,
1782+ enum rtw89_phy_idx phy_idx , s16 ref )
1783+ {
1784+ s8 ofst_int = 0 ;
1785+ u8 base_cw_0db = 0x27 ;
1786+ u16 tssi_16dbm_cw = 0x12c ;
1787+ s16 pwr_s10_3 = 0 ;
1788+ s16 rf_pwr_cw = 0 ;
1789+ u16 bb_pwr_cw = 0 ;
1790+ u32 pwr_cw = 0 ;
1791+ u32 tssi_ofst_cw = 0 ;
1792+
1793+ pwr_s10_3 = (ref << 1 ) + (s16 )(ofst_int ) + (s16 )(base_cw_0db << 3 );
1794+ bb_pwr_cw = FIELD_GET (GENMASK (2 , 0 ), pwr_s10_3 );
1795+ rf_pwr_cw = FIELD_GET (GENMASK (8 , 3 ), pwr_s10_3 );
1796+ rf_pwr_cw = clamp_t (s16 , rf_pwr_cw , 15 , 63 );
1797+ pwr_cw = (rf_pwr_cw << 3 ) | bb_pwr_cw ;
1798+
1799+ tssi_ofst_cw = (u32 )((s16 )tssi_16dbm_cw + (ref << 1 ) - (16 << 3 ));
1800+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR ,
1801+ "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n" ,
1802+ tssi_ofst_cw , rf_pwr_cw , bb_pwr_cw );
1803+
1804+ return (tssi_ofst_cw << 18 ) | (pwr_cw << 9 ) | (ref & GENMASK (8 , 0 ));
1805+ }
1806+
17811807static
17821808void rtw8852c_set_txpwr_ul_tb_offset (struct rtw89_dev * rtwdev ,
17831809 s8 pw_ofst , enum rtw89_mac_idx mac_idx )
@@ -1813,6 +1839,301 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
18131839 }
18141840}
18151841
1842+ static void rtw8852c_set_txpwr_ref (struct rtw89_dev * rtwdev ,
1843+ enum rtw89_phy_idx phy_idx )
1844+ {
1845+ static const u32 addr [RF_PATH_NUM_8852C ] = {0x5800 , 0x7800 };
1846+ const u32 mask = 0x7FFFFFF ;
1847+ const u8 ofst_ofdm = 0x4 ;
1848+ const u8 ofst_cck = 0x8 ;
1849+ s16 ref_ofdm = 0 ;
1850+ s16 ref_cck = 0 ;
1851+ u32 val ;
1852+ u8 i ;
1853+
1854+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR , "[TXPWR] set txpwr reference\n" );
1855+
1856+ rtw89_mac_txpwr_write32_mask (rtwdev , phy_idx , R_AX_PWR_RATE_CTRL ,
1857+ GENMASK (27 , 10 ), 0x0 );
1858+
1859+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR , "[TXPWR] set bb ofdm txpwr ref\n" );
1860+ val = rtw8852c_bb_cal_txpwr_ref (rtwdev , phy_idx , ref_ofdm );
1861+
1862+ for (i = 0 ; i < RF_PATH_NUM_8852C ; i ++ )
1863+ rtw89_phy_write32_idx (rtwdev , addr [i ] + ofst_ofdm , mask , val ,
1864+ phy_idx );
1865+
1866+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR , "[TXPWR] set bb cck txpwr ref\n" );
1867+ val = rtw8852c_bb_cal_txpwr_ref (rtwdev , phy_idx , ref_cck );
1868+
1869+ for (i = 0 ; i < RF_PATH_NUM_8852C ; i ++ )
1870+ rtw89_phy_write32_idx (rtwdev , addr [i ] + ofst_cck , mask , val ,
1871+ phy_idx );
1872+ }
1873+
1874+ static void rtw8852c_set_txpwr_byrate (struct rtw89_dev * rtwdev ,
1875+ enum rtw89_phy_idx phy_idx )
1876+ {
1877+ u8 ch = rtwdev -> hal .current_channel ;
1878+ static const u8 rs [] = {
1879+ RTW89_RS_CCK ,
1880+ RTW89_RS_OFDM ,
1881+ RTW89_RS_MCS ,
1882+ RTW89_RS_HEDCM ,
1883+ };
1884+ s8 tmp ;
1885+ u8 i , j ;
1886+ u32 val , shf , addr = R_AX_PWR_BY_RATE ;
1887+ struct rtw89_rate_desc cur ;
1888+
1889+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR ,
1890+ "[TXPWR] set txpwr byrate with ch=%d\n" , ch );
1891+
1892+ for (cur .nss = 0 ; cur .nss <= RTW89_NSS_2 ; cur .nss ++ ) {
1893+ for (i = 0 ; i < ARRAY_SIZE (rs ); i ++ ) {
1894+ if (cur .nss >= rtw89_rs_nss_max [rs [i ]])
1895+ continue ;
1896+
1897+ val = 0 ;
1898+ cur .rs = rs [i ];
1899+
1900+ for (j = 0 ; j < rtw89_rs_idx_max [rs [i ]]; j ++ ) {
1901+ cur .idx = j ;
1902+ shf = (j % 4 ) * 8 ;
1903+ tmp = rtw89_phy_read_txpwr_byrate (rtwdev , & cur );
1904+ val |= (tmp << shf );
1905+
1906+ if ((j + 1 ) % 4 )
1907+ continue ;
1908+
1909+ rtw89_mac_txpwr_write32 (rtwdev , phy_idx , addr , val );
1910+ val = 0 ;
1911+ addr += 4 ;
1912+ }
1913+ }
1914+ }
1915+ }
1916+
1917+ static void rtw8852c_set_txpwr_offset (struct rtw89_dev * rtwdev ,
1918+ enum rtw89_phy_idx phy_idx )
1919+ {
1920+ struct rtw89_rate_desc desc = {
1921+ .nss = RTW89_NSS_1 ,
1922+ .rs = RTW89_RS_OFFSET ,
1923+ };
1924+ u32 val = 0 ;
1925+ s8 v ;
1926+
1927+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR , "[TXPWR] set txpwr offset\n" );
1928+
1929+ for (desc .idx = 0 ; desc .idx < RTW89_RATE_OFFSET_MAX ; desc .idx ++ ) {
1930+ v = rtw89_phy_read_txpwr_byrate (rtwdev , & desc );
1931+ val |= ((v & 0xf ) << (4 * desc .idx ));
1932+ }
1933+
1934+ rtw89_mac_txpwr_write32_mask (rtwdev , phy_idx , R_AX_PWR_RATE_OFST_CTRL ,
1935+ GENMASK (19 , 0 ), val );
1936+ }
1937+
1938+ static void rtw8852c_bb_set_tx_shape_dfir (struct rtw89_dev * rtwdev ,
1939+ u8 tx_shape_idx ,
1940+ enum rtw89_phy_idx phy_idx )
1941+ {
1942+ #define __DFIR_CFG_MASK 0xffffff
1943+ #define __DFIR_CFG_NR 8
1944+ #define __DECL_DFIR_VAR (_prefix , _name , _val ...) \
1945+ static const u32 _prefix ## _ ## _name[] = {_val}; \
1946+ static_assert(ARRAY_SIZE(_prefix ## _ ## _name) == __DFIR_CFG_NR)
1947+ #define __DECL_DFIR_PARAM (_name , _val ...) __DECL_DFIR_VAR(param, _name, _val)
1948+ #define __DECL_DFIR_ADDR (_name , _val ...) __DECL_DFIR_VAR(addr, _name, _val)
1949+
1950+ __DECL_DFIR_PARAM (flat ,
1951+ 0x003D23FF , 0x0029B354 , 0x000FC1C8 , 0x00FDB053 ,
1952+ 0x00F86F9A , 0x00FAEF92 , 0x00FE5FCC , 0x00FFDFF5 );
1953+ __DECL_DFIR_PARAM (sharp ,
1954+ 0x003D83FF , 0x002C636A , 0x0013F204 , 0x00008090 ,
1955+ 0x00F87FB0 , 0x00F99F83 , 0x00FDBFBA , 0x00003FF5 );
1956+ __DECL_DFIR_PARAM (sharp_14 ,
1957+ 0x003B13FF , 0x001C42DE , 0x00FDB0AD , 0x00F60F6E ,
1958+ 0x00FD8F92 , 0x0002D011 , 0x0001C02C , 0x00FFF00A );
1959+ __DECL_DFIR_ADDR (filter ,
1960+ 0x45BC , 0x45CC , 0x45D0 , 0x45D4 , 0x45D8 , 0x45C0 ,
1961+ 0x45C4 , 0x45C8 );
1962+ u8 ch = rtwdev -> hal .current_channel ;
1963+ const u32 * param ;
1964+ int i ;
1965+
1966+ if (ch > 14 ) {
1967+ rtw89_warn (rtwdev ,
1968+ "set tx shape dfir by unknown ch: %d on 2G\n" , ch );
1969+ return ;
1970+ }
1971+
1972+ if (ch == 14 )
1973+ param = param_sharp_14 ;
1974+ else
1975+ param = tx_shape_idx == 0 ? param_flat : param_sharp ;
1976+
1977+ for (i = 0 ; i < __DFIR_CFG_NR ; i ++ ) {
1978+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR ,
1979+ "set tx shape dfir: 0x%x: 0x%x\n" , addr_filter [i ],
1980+ param [i ]);
1981+ rtw89_phy_write32_idx (rtwdev , addr_filter [i ], __DFIR_CFG_MASK ,
1982+ param [i ], phy_idx );
1983+ }
1984+
1985+ #undef __DECL_DFIR_ADDR
1986+ #undef __DECL_DFIR_PARAM
1987+ #undef __DECL_DFIR_VAR
1988+ #undef __DFIR_CFG_NR
1989+ #undef __DFIR_CFG_MASK
1990+ }
1991+
1992+ static void rtw8852c_set_tx_shape (struct rtw89_dev * rtwdev ,
1993+ enum rtw89_phy_idx phy_idx )
1994+ {
1995+ u8 band = rtwdev -> hal .current_band_type ;
1996+ u8 regd = rtw89_regd_get (rtwdev , band );
1997+ u8 tx_shape_cck = rtw89_8852c_tx_shape [band ][RTW89_RS_CCK ][regd ];
1998+ u8 tx_shape_ofdm = rtw89_8852c_tx_shape [band ][RTW89_RS_OFDM ][regd ];
1999+
2000+ if (band == RTW89_BAND_2G )
2001+ rtw8852c_bb_set_tx_shape_dfir (rtwdev , tx_shape_cck , phy_idx );
2002+
2003+ rtw89_phy_tssi_ctrl_set_bandedge_cfg (rtwdev ,
2004+ (enum rtw89_mac_idx )phy_idx ,
2005+ tx_shape_ofdm );
2006+ }
2007+
2008+ static void rtw8852c_set_txpwr_limit (struct rtw89_dev * rtwdev ,
2009+ enum rtw89_phy_idx phy_idx )
2010+ {
2011+ #define __MAC_TXPWR_LMT_PAGE_SIZE 40
2012+ u8 ch = rtwdev -> hal .current_channel ;
2013+ u8 bw = rtwdev -> hal .current_band_width ;
2014+ struct rtw89_txpwr_limit lmt [NTX_NUM_8852C ];
2015+ u32 addr , val ;
2016+ const s8 * ptr ;
2017+ u8 i , j , k ;
2018+
2019+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR ,
2020+ "[TXPWR] set txpwr limit with ch=%d bw=%d\n" , ch , bw );
2021+
2022+ for (i = 0 ; i < NTX_NUM_8852C ; i ++ ) {
2023+ rtw89_phy_fill_txpwr_limit (rtwdev , & lmt [i ], i );
2024+
2025+ for (j = 0 ; j < __MAC_TXPWR_LMT_PAGE_SIZE ; j += 4 ) {
2026+ addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i ;
2027+ ptr = (s8 * )& lmt [i ] + j ;
2028+ val = 0 ;
2029+
2030+ for (k = 0 ; k < 4 ; k ++ )
2031+ val |= (ptr [k ] << (8 * k ));
2032+
2033+ rtw89_mac_txpwr_write32 (rtwdev , phy_idx , addr , val );
2034+ }
2035+ }
2036+ #undef __MAC_TXPWR_LMT_PAGE_SIZE
2037+ }
2038+
2039+ static void rtw8852c_set_txpwr_limit_ru (struct rtw89_dev * rtwdev ,
2040+ enum rtw89_phy_idx phy_idx )
2041+ {
2042+ #define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
2043+ u8 ch = rtwdev -> hal .current_channel ;
2044+ u8 bw = rtwdev -> hal .current_band_width ;
2045+ struct rtw89_txpwr_limit_ru lmt_ru [NTX_NUM_8852C ];
2046+ u32 addr , val ;
2047+ const s8 * ptr ;
2048+ u8 i , j , k ;
2049+
2050+ rtw89_debug (rtwdev , RTW89_DBG_TXPWR ,
2051+ "[TXPWR] set txpwr limit ru with ch=%d bw=%d\n" , ch , bw );
2052+
2053+ for (i = 0 ; i < NTX_NUM_8852C ; i ++ ) {
2054+ rtw89_phy_fill_txpwr_limit_ru (rtwdev , & lmt_ru [i ], i );
2055+
2056+ for (j = 0 ; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE ; j += 4 ) {
2057+ addr = R_AX_PWR_RU_LMT + j +
2058+ __MAC_TXPWR_LMT_RU_PAGE_SIZE * i ;
2059+ ptr = (s8 * )& lmt_ru [i ] + j ;
2060+ val = 0 ;
2061+
2062+ for (k = 0 ; k < 4 ; k ++ )
2063+ val |= (ptr [k ] << (8 * k ));
2064+
2065+ rtw89_mac_txpwr_write32 (rtwdev , phy_idx , addr , val );
2066+ }
2067+ }
2068+
2069+ #undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
2070+ }
2071+
2072+ static void rtw8852c_set_txpwr (struct rtw89_dev * rtwdev )
2073+ {
2074+ rtw8852c_set_txpwr_byrate (rtwdev , RTW89_PHY_0 );
2075+ rtw8852c_set_txpwr_offset (rtwdev , RTW89_PHY_0 );
2076+ rtw8852c_set_tx_shape (rtwdev , RTW89_PHY_0 );
2077+ rtw8852c_set_txpwr_limit (rtwdev , RTW89_PHY_0 );
2078+ rtw8852c_set_txpwr_limit_ru (rtwdev , RTW89_PHY_0 );
2079+ }
2080+
2081+ static void rtw8852c_set_txpwr_ctrl (struct rtw89_dev * rtwdev )
2082+ {
2083+ rtw8852c_set_txpwr_ref (rtwdev , RTW89_PHY_0 );
2084+ }
2085+
2086+ static void
2087+ rtw8852c_init_tssi_ctrl (struct rtw89_dev * rtwdev , enum rtw89_phy_idx phy_idx )
2088+ {
2089+ static const struct rtw89_reg2_def ctrl_ini [] = {
2090+ {0xD938 , 0x00010100 },
2091+ {0xD93C , 0x0500D500 },
2092+ {0xD940 , 0x00000500 },
2093+ {0xD944 , 0x00000005 },
2094+ {0xD94C , 0x00220000 },
2095+ {0xD950 , 0x00030000 },
2096+ };
2097+ u32 addr ;
2098+ int i ;
2099+
2100+ for (addr = R_AX_TSSI_CTRL_HEAD ; addr <= R_AX_TSSI_CTRL_TAIL ; addr += 4 )
2101+ rtw89_mac_txpwr_write32 (rtwdev , phy_idx , addr , 0 );
2102+
2103+ for (i = 0 ; i < ARRAY_SIZE (ctrl_ini ); i ++ )
2104+ rtw89_mac_txpwr_write32 (rtwdev , phy_idx , ctrl_ini [i ].addr ,
2105+ ctrl_ini [i ].data );
2106+
2107+ rtw89_phy_tssi_ctrl_set_bandedge_cfg (rtwdev ,
2108+ (enum rtw89_mac_idx )phy_idx ,
2109+ RTW89_TSSI_BANDEDGE_FLAT );
2110+ }
2111+
2112+ static int
2113+ rtw8852c_init_txpwr_unit (struct rtw89_dev * rtwdev , enum rtw89_phy_idx phy_idx )
2114+ {
2115+ int ret ;
2116+
2117+ ret = rtw89_mac_txpwr_write32 (rtwdev , phy_idx , R_AX_PWR_UL_CTRL2 , 0x07763333 );
2118+ if (ret )
2119+ return ret ;
2120+
2121+ ret = rtw89_mac_txpwr_write32 (rtwdev , phy_idx , R_AX_PWR_COEXT_CTRL , 0x01ebf000 );
2122+ if (ret )
2123+ return ret ;
2124+
2125+ ret = rtw89_mac_txpwr_write32 (rtwdev , phy_idx , R_AX_PWR_UL_CTRL0 , 0x0002f8ff );
2126+ if (ret )
2127+ return ret ;
2128+
2129+ rtw8852c_set_txpwr_ul_tb_offset (rtwdev , 0 , phy_idx == RTW89_PHY_1 ?
2130+ RTW89_MAC_1 :
2131+ RTW89_MAC_0 );
2132+ rtw8852c_init_tssi_ctrl (rtwdev , phy_idx );
2133+
2134+ return 0 ;
2135+ }
2136+
18162137static void rtw8852c_bb_cfg_rx_path (struct rtw89_dev * rtwdev , u8 rx_path )
18172138{
18182139 struct rtw89_hal * hal = & rtwdev -> hal ;
@@ -2163,6 +2484,9 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
21632484 .rfk_init = rtw8852c_rfk_init ,
21642485 .rfk_channel = rtw8852c_rfk_channel ,
21652486 .power_trim = rtw8852c_power_trim ,
2487+ .set_txpwr = rtw8852c_set_txpwr ,
2488+ .set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl ,
2489+ .init_txpwr_unit = rtw8852c_init_txpwr_unit ,
21662490 .read_rf = rtw89_phy_read_rf_v1 ,
21672491 .write_rf = rtw89_phy_write_rf_v1 ,
21682492 .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset ,
0 commit comments