@@ -92,13 +92,65 @@ static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
9292 return 0 ;
9393}
9494
95+ static
96+ s32 rtw89_sar_cfg_acpi_get_min (const struct rtw89_sar_entry_from_acpi * ent ,
97+ enum rtw89_rf_path path ,
98+ enum rtw89_acpi_sar_subband subband_low ,
99+ enum rtw89_acpi_sar_subband subband_high )
100+ {
101+ return min (ent -> v [subband_low ][path ], ent -> v [subband_high ][path ]);
102+ }
103+
104+ static int rtw89_query_sar_config_acpi (struct rtw89_dev * rtwdev ,
105+ const struct rtw89_sar_parm * sar_parm ,
106+ s32 * cfg )
107+ {
108+ const struct rtw89_sar_cfg_acpi * rtwsar = & rtwdev -> sar .cfg_acpi ;
109+ const struct rtw89_sar_table_from_acpi * tbl = rtwsar -> tables ;
110+ enum rtw89_acpi_sar_subband subband_l , subband_h ;
111+ const struct rtw89_sar_entry_from_acpi * ent ;
112+ u32 center_freq = sar_parm -> center_freq ;
113+ const struct rtw89_6ghz_span * span ;
114+ enum rtw89_regulation_type regd ;
115+ enum rtw89_band band ;
116+ s32 cfg_a , cfg_b ;
117+
118+ span = rtw89_get_6ghz_span (rtwdev , center_freq );
119+
120+ if (span && RTW89_ACPI_SAR_SPAN_VALID (span )) {
121+ subband_l = span -> acpi_sar_subband_low ;
122+ subband_h = span -> acpi_sar_subband_high ;
123+ } else {
124+ subband_l = rtw89_acpi_sar_get_subband (rtwdev , center_freq );
125+ subband_h = subband_l ;
126+ }
127+
128+ band = rtw89_acpi_sar_subband_to_band (rtwdev , subband_l );
129+ regd = rtw89_regd_get (rtwdev , band );
130+ ent = & tbl -> entries [regd ];
131+
132+ cfg_a = rtw89_sar_cfg_acpi_get_min (ent , RF_PATH_A , subband_l , subband_h );
133+ cfg_b = rtw89_sar_cfg_acpi_get_min (ent , RF_PATH_B , subband_l , subband_h );
134+ * cfg = min (cfg_a , cfg_b );
135+
136+ if (sar_parm -> ntx == RTW89_2TX )
137+ * cfg -= rtwsar -> downgrade_2tx ;
138+
139+ return 0 ;
140+ }
141+
95142static const
96143struct rtw89_sar_handler rtw89_sar_handlers [RTW89_SAR_SOURCE_NR ] = {
97144 [RTW89_SAR_SOURCE_COMMON ] = {
98145 .descr_sar_source = "RTW89_SAR_SOURCE_COMMON" ,
99146 .txpwr_factor_sar = 2 ,
100147 .query_sar_config = rtw89_query_sar_config_common ,
101148 },
149+ [RTW89_SAR_SOURCE_ACPI ] = {
150+ .descr_sar_source = "RTW89_SAR_SOURCE_ACPI" ,
151+ .txpwr_factor_sar = TXPWR_FACTOR_OF_RTW89_ACPI_SAR ,
152+ .query_sar_config = rtw89_query_sar_config_acpi ,
153+ },
102154};
103155
104156#define rtw89_sar_set_src (_dev , _src , _cfg_name , _cfg_data ) \
@@ -288,16 +340,7 @@ int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
288340static int rtw89_apply_sar_common (struct rtw89_dev * rtwdev ,
289341 const struct rtw89_sar_cfg_common * sar )
290342{
291- enum rtw89_sar_sources src ;
292-
293- lockdep_assert_wiphy (rtwdev -> hw -> wiphy );
294-
295- src = rtwdev -> sar .src ;
296- if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON ) {
297- rtw89_warn (rtwdev , "SAR source: %d is in use" , src );
298- return - EBUSY ;
299- }
300-
343+ /* let common SAR have the highest priority; always apply it */
301344 rtw89_sar_set_src (rtwdev , RTW89_SAR_SOURCE_COMMON , cfg_common , sar );
302345 rtw89_core_set_chip_txpwr (rtwdev );
303346 rtw89_tas_reset (rtwdev , false);
@@ -365,6 +408,78 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
365408 return rtw89_apply_sar_common (rtwdev , & sar_common );
366409}
367410
411+ static void rtw89_apply_sar_acpi (struct rtw89_dev * rtwdev ,
412+ const struct rtw89_sar_cfg_acpi * sar )
413+ {
414+ const struct rtw89_sar_table_from_acpi * tbl ;
415+ const struct rtw89_sar_entry_from_acpi * ent ;
416+ enum rtw89_sar_sources src ;
417+ unsigned int i , j , k ;
418+
419+ src = rtwdev -> sar .src ;
420+ if (src != RTW89_SAR_SOURCE_NONE ) {
421+ rtw89_warn (rtwdev , "SAR source: %d is in use" , src );
422+ return ;
423+ }
424+
425+ rtw89_debug (rtwdev , RTW89_DBG_SAR ,
426+ "SAR-ACPI downgrade 2TX: %u (unit: 1/%lu dBm)\n" ,
427+ sar -> downgrade_2tx , BIT (TXPWR_FACTOR_OF_RTW89_ACPI_SAR ));
428+
429+ for (i = 0 ; i < sar -> valid_num ; i ++ ) {
430+ tbl = & sar -> tables [i ];
431+
432+ for (j = 0 ; j < RTW89_REGD_NUM ; j ++ ) {
433+ ent = & tbl -> entries [j ];
434+
435+ rtw89_debug (rtwdev , RTW89_DBG_SAR ,
436+ "SAR-ACPI-[%u] REGD-%s (unit: 1/%lu dBm)\n" ,
437+ i , rtw89_regd_get_string (j ),
438+ BIT (TXPWR_FACTOR_OF_RTW89_ACPI_SAR ));
439+
440+ for (k = 0 ; k < NUM_OF_RTW89_ACPI_SAR_SUBBAND ; k ++ )
441+ rtw89_debug (rtwdev , RTW89_DBG_SAR ,
442+ "On subband %u, { %d, %d }\n" , k ,
443+ ent -> v [k ][RF_PATH_A ], ent -> v [k ][RF_PATH_B ]);
444+ }
445+ }
446+
447+ rtw89_sar_set_src (rtwdev , RTW89_SAR_SOURCE_ACPI , cfg_acpi , sar );
448+
449+ /* SAR via ACPI is only configured in the early initial phase, so
450+ * it does not seem necessary to reset txpwr related things here.
451+ */
452+ }
453+
454+ static void rtw89_set_sar_from_acpi (struct rtw89_dev * rtwdev )
455+ {
456+ struct rtw89_sar_cfg_acpi * cfg ;
457+ int ret ;
458+
459+ lockdep_assert_wiphy (rtwdev -> hw -> wiphy );
460+
461+ cfg = kzalloc (sizeof (* cfg ), GFP_KERNEL );
462+ if (!cfg )
463+ return ;
464+
465+ ret = rtw89_acpi_evaluate_sar (rtwdev , cfg );
466+ if (ret ) {
467+ rtw89_debug (rtwdev , RTW89_DBG_SAR ,
468+ "evaluating ACPI SAR returns %d\n" , ret );
469+ goto out ;
470+ }
471+
472+ if (unlikely (!cfg -> valid_num )) {
473+ rtw89_debug (rtwdev , RTW89_DBG_SAR , "no valid SAR table from ACPI\n" );
474+ goto out ;
475+ }
476+
477+ rtw89_apply_sar_acpi (rtwdev , cfg );
478+
479+ out :
480+ kfree (cfg );
481+ }
482+
368483static bool rtw89_tas_query_sar_config (struct rtw89_dev * rtwdev , s32 * cfg )
369484{
370485 const struct rtw89_chan * chan = rtw89_chan_get (rtwdev , RTW89_CHANCTX_0 );
@@ -524,7 +639,7 @@ static void rtw89_tas_rolling_average(struct rtw89_dev *rtwdev)
524639 rtw89_tas_state_update (rtwdev , state );
525640}
526641
527- void rtw89_tas_init (struct rtw89_dev * rtwdev )
642+ static void rtw89_tas_init (struct rtw89_dev * rtwdev )
528643{
529644 const struct rtw89_chip_info * chip = rtwdev -> chip ;
530645 struct rtw89_tas_info * tas = & rtwdev -> tas ;
@@ -671,3 +786,9 @@ void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev,
671786 }
672787}
673788EXPORT_SYMBOL (rtw89_tas_chanctx_cb );
789+
790+ void rtw89_sar_init (struct rtw89_dev * rtwdev )
791+ {
792+ rtw89_set_sar_from_acpi (rtwdev );
793+ rtw89_tas_init (rtwdev );
794+ }
0 commit comments