rtlwifi: btcoex: 23b 2ant: check PS state before setting tdma duration
authorYan-Hsuan Chuang <yhchuang@realtek.com>
Tue, 4 Apr 2017 16:49:54 +0000 (11:49 -0500)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 13 Apr 2017 14:08:34 +0000 (17:08 +0300)
For time division multiple access, the wifi and bt take turns to
transmit, but we need to let AP know that wifi is under standby mode by
sending null data to "pretend" entering power saving state using lps
rpwm.

But, the fw does not know if it is the actual power saving mode or just a
fake one to cheat to the AP. Hence, before fw setting the tdma duration,
the fw needs the driver to check the power saving state first.

Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Pkshih <pkshih@realtek.com>
Cc: Birming Chiu <birming@realtek.com>
Cc: Shaofu <shaofu@realtek.com>
Cc: Steven Ting <steventing@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h

index 988f276531ddea0d614f6f6749f0f19f19dba73e..dda14bd0ac45a0ade8d04df46e4c41d036a6afa2 100644 (file)
@@ -978,6 +978,33 @@ static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist,
        btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter);
 }
 
+static void btc8723b2ant_set_lps_rpwm(struct btc_coexist *btcoexist,
+                                     u8 lps_val, u8 rpwm_val)
+{
+       u8 lps = lps_val;
+       u8 rpwm = rpwm_val;
+
+       btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps);
+       btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm);
+}
+
+static void btc8723b2ant_lps_rpwm(struct btc_coexist *btcoexist,
+                                 bool force_exec, u8 lps_val, u8 rpwm_val)
+{
+       coex_dm->cur_lps = lps_val;
+       coex_dm->cur_rpwm = rpwm_val;
+
+       if (!force_exec) {
+               if ((coex_dm->pre_lps == coex_dm->cur_lps) &&
+                   (coex_dm->pre_rpwm == coex_dm->cur_rpwm))
+                       return;
+       }
+       btc8723b2ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val);
+
+       coex_dm->pre_lps = coex_dm->cur_lps;
+       coex_dm->pre_rpwm = coex_dm->cur_rpwm;
+}
+
 static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist,
                                         bool force_exec, bool enable)
 {
@@ -1341,9 +1368,74 @@ static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec,
        coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma;
 }
 
+static void btc8723b2ant_ps_tdma_check_for_power_save_state(
+               struct btc_coexist *btcoexist, bool new_ps_state)
+{
+       u8 lps_mode = 0x0;
+
+       btcoexist->btc_get(btcoexist, BTC_GET_U1_LPS_MODE, &lps_mode);
+
+       if (lps_mode) {
+               /* already under LPS state */
+               if (new_ps_state) {
+                       /* keep state under LPS, do nothing. */
+               } else {
+                       /* will leave LPS state, turn off psTdma first */
+                       btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1);
+               }
+       } else {
+               /* NO PS state */
+               if (new_ps_state) {
+                       /* will enter LPS state, turn off psTdma first */
+                       btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1);
+               } else {
+                       /* keep state under NO PS state, do nothing. */
+               }
+       }
+}
+
+static void btc8723b2ant_power_save_state(struct btc_coexist *btcoexist,
+                                         u8 ps_type, u8 lps_val, u8 rpwm_val)
+{
+       bool low_pwr_disable = false;
+
+       switch (ps_type) {
+       case BTC_PS_WIFI_NATIVE:
+               /* recover to original 32k low power setting */
+               low_pwr_disable = false;
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
+                                  &low_pwr_disable);
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
+               coex_sta->force_lps_on = false;
+               break;
+       case BTC_PS_LPS_ON:
+               btc8723b2ant_ps_tdma_check_for_power_save_state(btcoexist,
+                                                               true);
+               btc8723b2ant_lps_rpwm(btcoexist, NORMAL_EXEC, lps_val,
+                                     rpwm_val);
+               /* when coex force to enter LPS, do not enter 32k low power */
+               low_pwr_disable = true;
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
+                                  &low_pwr_disable);
+               /* power save must executed before psTdma */
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL);
+               coex_sta->force_lps_on = true;
+               break;
+       case BTC_PS_LPS_OFF:
+               btc8723b2ant_ps_tdma_check_for_power_save_state(btcoexist,
+                                                               false);
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
+               coex_sta->force_lps_on = false;
+               break;
+       default:
+               break;
+       }
+}
+
 static void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist)
 {
        /* fw all off */
+       btc8723b2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
        btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1);
        btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
        btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
@@ -1359,6 +1451,7 @@ static void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist)
 static void btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist)
 {
        /* force to reset coex mechanism*/
+       btc8723b2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
 
        btc8723b2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1);
        btc8723b2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6);
@@ -1801,6 +1894,8 @@ static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist)
                /* for HID quality & wifi performance balance at 11n mode */
                btc8723b2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 9);
 
+       btc8723b2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
        if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
            (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH))
                btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9);
index 746930d0d24416370bd7355b826563e81d088a7d..5bcaeceada9c31b4535d2e1000e388f15a398f41 100644 (file)
@@ -122,6 +122,11 @@ struct coex_dm_8723b_2ant {
        u8 bt_status;
        u8 wifi_chnl_info[3];
 
+       u8 pre_lps;
+       u8 cur_lps;
+       u8 pre_rpwm;
+       u8 cur_rpwm;
+
        bool need_recover_0x948;
        u16 backup_0x948;
 };
@@ -160,6 +165,7 @@ struct coex_sta_8723b_2ant {
        u32 crc_err_11g;
        u32 crc_err_11n;
        u32 crc_err_11n_agg;
+       bool force_lps_on;
 
        u8 a2dp_bit_pool;
 };