hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/******************************************************************************
 *
 * Copyright(c) 2019 Realtek Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 *****************************************************************************/
#define _PHL_EXT_TX_PWR_LMT_C_
#include "phl_headers.h"
 
/**
 * The function to update current TX power limit value to HW register
 * @phl: see struct phl_info_t
 *
 */
enum rtw_phl_status
rtw_phl_set_power_limit(void *phl)
{
   struct    phl_info_t *phl_info = (struct phl_info_t *)phl;
   enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
   u8 hw_band = 0;
 
   for (hw_band = 0; hw_band < HW_BAND_MAX; hw_band++) {
       if (rtw_hal_set_power_limit(phl_info->hal, hw_band) == RTW_HAL_STATUS_SUCCESS)
           phl_status = RTW_PHL_STATUS_SUCCESS;
   }
   return phl_status;
}
 
/**
 * The function to get TX power limit value with specific parameters
 * @phl: see struct phl_info_t
 * @hw_band: 0x0: band0, 0x1: band1
 * @rate: data rate
 * @bandwidth: banddwidth
 * @beamforming: 0: TX w/o BF, 1: TX w/ BF
 * @tx_num: tx number, 0: 1TX, 1: 2TX
 * @channel: center channel
 *
 */
s8 rtw_phl_get_power_limit(void *phl, u8 hw_band,
   u16 rate, u8 bandwidth, u8 beamforming, u8 tx_num, u8 channel)
{
   struct    phl_info_t *phl_info = (struct phl_info_t *)phl;
 
   return rtw_hal_get_power_limit(phl_info->hal, hw_band, rate,
       bandwidth, beamforming, tx_num, channel);
}
 
/**
 * The function to update user defined extended tx power limit to halrf
 * @phl: see struct phl_info_t
 * @hw_band: 0x0: band0, 0x1: band1
 * @ext_pwr_lmt_info: table of extended tx power limit value
 *
 * Note,
 * This function will enable extended tx power limit mechanism.
 * After enabled this mechanism, halrf will use
 * min(original tx power limit, extended tx power limit) to be
 * final tx power limit value.
 *
 */
void
rtw_phl_enable_ext_pwr_lmt(void *phl, u8 hw_band,
       struct rtw_phl_ext_pwr_lmt_info *ext_pwr_lmt_info)
{
   struct phl_info_t *phl_info = (struct phl_info_t *)phl;
 
   rtw_hal_enable_ext_pwr_lmt(phl_info->hal, hw_band, ext_pwr_lmt_info);
}
 
void
rtw_phl_set_ext_pwr_lmt_en(void *phl, bool enable)
{
   struct phl_info_t *phl_info = (struct phl_info_t *)phl;
   u8 hw_band = 0;
 
   for (hw_band = 0; hw_band < HW_BAND_MAX; hw_band++) {
       rtw_hal_set_ext_pwr_lmt_en(phl_info->hal, hw_band, enable);
   }
}
 
static void
_phl_cmd_updt_epl_done(
   void *drv_priv, u8 *cmd, u32 cmd_len,
   enum rtw_phl_status status)
{
   if (cmd) {
       _os_kmem_free(drv_priv, cmd, cmd_len);
       cmd = NULL;
       PHL_INFO("%s...\n", __func__);
   }
}
 
 
static enum rtw_phl_status
_phl_updt_ext_txpwr_lmt(
   void *phl, struct rtw_phl_cmd_epl_para *param)
{
   struct phl_info_t *phl_info = (struct phl_info_t *)phl;
   u8 hw_band = 0;
   bool cur_state = rtw_hal_get_ext_pwr_lmt_en(phl_info->hal, hw_band);
   bool tgt_state = (param->en ? true : false);
 
   if (param->upt_info) {
       for (hw_band = 0; hw_band < HW_BAND_MAX; hw_band++) {
           rtw_phl_enable_ext_pwr_lmt(phl, hw_band, &param->info);
       }
   }
   /* Only update state and reload when state changed OR table updated */
   if (tgt_state != cur_state || param->upt_info) {
       rtw_phl_set_ext_pwr_lmt_en(phl, tgt_state);
       if (param->pwrlmt_rld)
           rtw_phl_set_power_limit(phl);
   }
 
   return RTW_PHL_STATUS_SUCCESS;
}
 
enum rtw_phl_status
phl_cmd_updt_ext_txpwr_lmt(
   void *phl, u8 *param)
{
   struct rtw_phl_cmd_epl_para *cmd_para = (struct rtw_phl_cmd_epl_para *)param;
 
   return _phl_updt_ext_txpwr_lmt(phl, cmd_para);
}
 
enum rtw_phl_status
rtw_phl_cmd_updt_ext_txpwr_lmt(void *phl,
   struct rtw_phl_cmd_epl_para *param,
   enum phl_cmd_type cmd_type,
   u32 cmd_timeout)
{
   struct phl_info_t *phl_info = (struct phl_info_t *)phl;
   enum rtw_phl_status sts = RTW_PHL_STATUS_FAILURE;
   struct rtw_phl_cmd_epl_para *cmd_param = NULL;
   u32 cmd_param_len = 0;
 
#ifdef CONFIG_CMD_DISP
   if (cmd_type == PHL_CMD_DIRECTLY)
       return _phl_updt_ext_txpwr_lmt(phl, param);
 
   cmd_param_len = sizeof(struct rtw_phl_cmd_epl_para);
   cmd_param = _os_kmem_alloc(phl_to_drvpriv(phl_info), cmd_param_len);
   if (cmd_param == NULL) {
       PHL_ERR("%s: alloc cmd_param failed!\n", __func__);
       goto end;
   } else {
       _os_mem_cpy(phl_to_drvpriv(phl_info), cmd_param,
           param, cmd_param_len);
   }
 
   sts = phl_cmd_enqueue(phl,
           HW_BAND_0,
           MSG_EVT_UPDT_EXT_TXPWR_LMT,
           (u8 *)cmd_param, 0,
           _phl_cmd_updt_epl_done,
           cmd_type, cmd_timeout);
 
   if (is_cmd_failure(sts)) {
       /* Send cmd success, but wait cmd fail*/
       sts = RTW_PHL_STATUS_FAILURE;
   } else if (sts != RTW_PHL_STATUS_SUCCESS) {
       /* Send cmd fail */
       _os_kmem_free(phl_to_drvpriv(phl_info), cmd_param, cmd_param_len);
       sts = RTW_PHL_STATUS_FAILURE;
   }
end:
   return sts;
#else
   PHL_ERR("%s : CONFIG_CMD_DISP need to be enabled for MSG_EVT_UPDT_EXT_TXPWR_LMT !! \n", __func__);
 
   return sts;
#endif
}