xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_acs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 
16 /* ************************************************************
17  * include files
18  * ************************************************************ */
19 #include "mp_precomp.h"
20 #include "phydm_precomp.h"
21 
22 
23 u8
odm_get_auto_channel_select_result(void * p_dm_void,u8 band)24 odm_get_auto_channel_select_result(
25 	void			*p_dm_void,
26 	u8			band
27 )
28 {
29 	struct PHY_DM_STRUCT		*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
30 	struct _ACS_					*p_acs = &p_dm->dm_acs;
31 
32 	PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
33 
34 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
35 	if (band == ODM_BAND_2_4G) {
36 		PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_2g=%d\n", p_acs->clean_channel_2g));
37 		return (u8)p_acs->clean_channel_2g;
38 	} else {
39 		PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_5g=%d\n", p_acs->clean_channel_5g));
40 		return (u8)p_acs->clean_channel_5g;
41 	}
42 #else
43 	return (u8)p_acs->clean_channel_2g;
44 #endif
45 
46 }
47 
48 void
odm_auto_channel_select_init(void * p_dm_void)49 odm_auto_channel_select_init(
50 	void			*p_dm_void
51 )
52 {
53 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
54 	struct PHY_DM_STRUCT					*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
55 	struct _ACS_						*p_acs = &p_dm->dm_acs;
56 	u8						i;
57 
58 	if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR))
59 		return;
60 
61 	if (p_acs->is_force_acs_result)
62 		return;
63 
64 	PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
65 
66 	p_acs->clean_channel_2g = 1;
67 	p_acs->clean_channel_5g = 36;
68 
69 	for (i = 0; i < ODM_MAX_CHANNEL_2G; ++i) {
70 		p_acs->channel_info_2g[0][i] = 0;
71 		p_acs->channel_info_2g[1][i] = 0;
72 	}
73 
74 	if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
75 		for (i = 0; i < ODM_MAX_CHANNEL_5G; ++i) {
76 			p_acs->channel_info_5g[0][i] = 0;
77 			p_acs->channel_info_5g[1][i] = 0;
78 		}
79 	}
80 #endif
81 }
82 
83 void
odm_auto_channel_select_reset(void * p_dm_void)84 odm_auto_channel_select_reset(
85 	void			*p_dm_void
86 )
87 {
88 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
89 	struct PHY_DM_STRUCT					*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
90 	struct _ACS_						*p_acs = &p_dm->dm_acs;
91 	struct _CCX_INFO		*ccx_info = &p_dm->dm_ccx_info;
92 
93 	if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR))
94 		return;
95 
96 	if (p_acs->is_force_acs_result)
97 		return;
98 
99 	PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
100 
101 	ccx_info->nhm_period = 0x1388;	/*20ms*/
102 	phydm_nhm_setting(p_dm, SET_NHM_SETTING);
103 	phydm_nhm_trigger(p_dm);
104 #endif
105 }
106 
107 void
odm_auto_channel_select(void * p_dm_void,u8 channel)108 odm_auto_channel_select(
109 	void			*p_dm_void,
110 	u8			channel
111 )
112 {
113 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
114 	struct PHY_DM_STRUCT					*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
115 	struct _ACS_						*p_acs = &p_dm->dm_acs;
116 	struct _CCX_INFO		*ccx_info = &p_dm->dm_ccx_info;
117 	u8						channel_idx = 0, search_idx = 0;
118 	u8						noisy_nhm_th = 0x52;
119 	u8						i, noisy_nhm_th_index, low_pwr_cnt = 0;
120 	u16						max_score = 0;
121 
122 	PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
123 
124 	if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR)) {
125 		PHYDM_DBG(p_dm, DBG_DIG, ("Return: Not support\n"));
126 		return;
127 	}
128 
129 	if (p_acs->is_force_acs_result) {
130 		PHYDM_DBG(p_dm, DBG_DIG, ("Force clean CH{2G,5G}={%d,%d}\n",
131 			p_acs->clean_channel_2g, p_acs->clean_channel_5g));
132 		return;
133 	}
134 
135 	PHYDM_DBG(p_dm, ODM_COMP_API, ("CH=%d\n", channel));
136 
137 	phydm_get_nhm_result(p_dm);
138 	noisy_nhm_th_index = (noisy_nhm_th - ccx_info->nhm_th[0]) << 2;
139 
140 	for (i = 0; i <= 11; i++) {
141 		if (i <= noisy_nhm_th_index)
142 			low_pwr_cnt += ccx_info->nhm_result[i];
143 	}
144 
145 	ccx_info->nhm_period = 0x2710;
146 	phydm_nhm_setting(p_dm, SET_NHM_SETTING);
147 
148 	if (channel >= 1 && channel <= 14) {
149 		channel_idx = channel - 1;
150 		p_acs->channel_info_2g[1][channel_idx]++;
151 
152 		if (p_acs->channel_info_2g[1][channel_idx] >= 2)
153 			p_acs->channel_info_2g[0][channel_idx] = (p_acs->channel_info_2g[0][channel_idx] >> 1) +
154 				(p_acs->channel_info_2g[0][channel_idx] >> 2) + (low_pwr_cnt >> 2);
155 		else
156 			p_acs->channel_info_2g[0][channel_idx] = low_pwr_cnt;
157 
158 		PHYDM_DBG(p_dm, ODM_COMP_API, ("low_pwr_cnt = %d\n", low_pwr_cnt));
159 		PHYDM_DBG(p_dm, ODM_COMP_API, ("CH_Info[0][%d]=%d, CH_Info[1][%d]=%d\n", channel_idx, p_acs->channel_info_2g[0][channel_idx], channel_idx, p_acs->channel_info_2g[1][channel_idx]));
160 
161 		for (search_idx = 0; search_idx < ODM_MAX_CHANNEL_2G; search_idx++) {
162 			if (p_acs->channel_info_2g[1][search_idx] != 0 && p_acs->channel_info_2g[0][search_idx] >= max_score) {
163 				max_score = p_acs->channel_info_2g[0][search_idx];
164 				p_acs->clean_channel_2g = search_idx + 1;
165 			}
166 		}
167 		PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_2g=%d, max_score=%d\n",
168 				p_acs->clean_channel_2g, max_score));
169 
170 	} else if (channel >= 36) {
171 		/* Need to do */
172 		p_acs->clean_channel_5g = channel;
173 	}
174 #endif
175 }
176 
177 boolean
phydm_acs_check(void * p_dm_void)178 phydm_acs_check(
179 	void	*p_dm_void
180 )
181 {
182 #if (DM_ODM_SUPPORT_TYPE == ODM_AP)
183 	struct PHY_DM_STRUCT	*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
184 	struct rtl8192cd_priv		*priv = p_dm->priv;
185 
186 	if ((priv->auto_channel != 0) && (priv->auto_channel != 2)) /* if struct _ACS_ running, do not do FA/CCA counter read */
187 		return true;
188 	else
189 		return false;
190 #else
191 	return false;
192 #endif
193 }
194 
195 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
196 
197 void
phydm_auto_channel_select_setting_ap(void * p_dm_void,u32 setting,u32 acs_step)198 phydm_auto_channel_select_setting_ap(
199 	void   *p_dm_void,
200 	u32  setting,             /* 0: STORE_DEFAULT_NHM_SETTING; 1: RESTORE_DEFAULT_NHM_SETTING, 2: ACS_NHM_SETTING */
201 	u32  acs_step
202 )
203 {
204 	struct PHY_DM_STRUCT           *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
205 	struct rtl8192cd_priv       *priv           = p_dm->priv;
206 	struct _ACS_                    *p_acs         = &p_dm->dm_acs;
207 
208 	PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
209 
210 	/* 3 Store Default setting */
211 	if (setting == STORE_DEFAULT_NHM_SETTING) {
212 		PHYDM_DBG(p_dm, ODM_COMP_API, ("STORE_DEFAULT_NHM_SETTING\n"));
213 
214 		if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {  /* store reg0x990, reg0x994, reg0x998, reg0x99c, Reg0x9a0 */
215 			p_acs->reg0x990 = odm_read_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC);                /* reg0x990 */
216 			p_acs->reg0x994 = odm_read_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC);           /* reg0x994 */
217 			p_acs->reg0x998 = odm_read_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC);       /* reg0x998 */
218 			p_acs->reg0x99c = odm_read_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC);       /* Reg0x99c */
219 			p_acs->reg0x9a0 = odm_read_1byte(p_dm, ODM_REG_NHM_TH8_11AC);                   /* Reg0x9a0, u8 */
220 		} else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
221 			p_acs->reg0x890 = odm_read_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11N);             /* reg0x890 */
222 			p_acs->reg0x894 = odm_read_4byte(p_dm, ODM_REG_CCX_PERIOD_11N);                  /* reg0x894 */
223 			p_acs->reg0x898 = odm_read_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N);         /* reg0x898 */
224 			p_acs->reg0x89c = odm_read_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N);         /* Reg0x89c */
225 			p_acs->reg0xe28 = odm_read_1byte(p_dm, ODM_REG_NHM_TH8_11N);                     /* Reg0xe28, u8 */
226 		}
227 	}
228 
229 	/* 3 Restore Default setting */
230 	else if (setting == RESTORE_DEFAULT_NHM_SETTING) {
231 		PHYDM_DBG(p_dm, ODM_COMP_API, ("RESTORE_DEFAULT_NHM_SETTING\n"));
232 
233 		if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {  /* store reg0x990, reg0x994, reg0x998, reg0x99c, Reg0x9a0 */
234 			odm_write_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC,          p_acs->reg0x990);
235 			odm_write_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC,     p_acs->reg0x994);
236 			odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, p_acs->reg0x998);
237 			odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, p_acs->reg0x99c);
238 			odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11AC,             p_acs->reg0x9a0);
239 		} else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
240 			odm_write_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11N,     p_acs->reg0x890);
241 			odm_write_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC,          p_acs->reg0x894);
242 			odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, p_acs->reg0x898);
243 			odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, p_acs->reg0x89c);
244 			odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11N,             p_acs->reg0xe28);
245 		}
246 	}
247 
248 	/* 3 struct _ACS_ setting */
249 	else if (setting == ACS_NHM_SETTING) {
250 		PHYDM_DBG(p_dm, ODM_COMP_API, ("ACS_NHM_SETTING\n"));
251 		u16  period;
252 		period = 0x61a8;
253 		p_acs->acs_step = acs_step;
254 
255 		if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
256 			/* 4 Set NHM period, 0x990[31:16]=0x61a8, Time duration for NHM unit: 4us, 0x61a8=100ms */
257 			odm_write_2byte(p_dm, ODM_REG_CCX_PERIOD_11AC + 2, period);
258 			/* 4 Set NHM ignore_cca=1, ignore_txon=1, ccx_en=0 */
259 			odm_set_bb_reg(p_dm, ODM_REG_NHM_TH9_TH10_11AC, BIT(8) | BIT(9) | BIT(10), 3);
260 
261 			if (p_acs->acs_step == 0) {
262 				/* 4 Set IGI */
263 				odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
264 				if (get_rf_mimo_mode(priv) != RF_1T1R)
265 					odm_set_bb_reg(p_dm, 0xe50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
266 
267 				/* 4 Set struct _ACS_ NHM threshold */
268 				odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, 0x82786e64);
269 				odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, 0xffffff8c);
270 				odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11AC, 0xff);
271 				odm_write_2byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC + 2, 0xffff);
272 
273 			} else if (p_acs->acs_step == 1) {
274 				/* 4 Set IGI */
275 				odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
276 				if (get_rf_mimo_mode(priv) != RF_1T1R)
277 					odm_set_bb_reg(p_dm, 0xe50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
278 
279 				/* 4 Set struct _ACS_ NHM threshold */
280 				odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, 0x5a50463c);
281 				odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, 0xffffff64);
282 
283 			}
284 
285 		} else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
286 			/* 4 Set NHM period, 0x894[31:16]=0x61a8, Time duration for NHM unit: 4us, 0x61a8=100ms */
287 			odm_write_2byte(p_dm, ODM_REG_CCX_PERIOD_11AC + 2, period);
288 			/* 4 Set NHM ignore_cca=1, ignore_txon=1, ccx_en=0 */
289 			odm_set_bb_reg(p_dm, ODM_REG_NHM_TH9_TH10_11N, BIT(8) | BIT(9) | BIT(10), 3);
290 
291 			if (p_acs->acs_step == 0) {
292 				/* 4 Set IGI */
293 				odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
294 				if (get_rf_mimo_mode(priv) != RF_1T1R)
295 					odm_set_bb_reg(p_dm, 0xc58, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
296 
297 				/* 4 Set struct _ACS_ NHM threshold */
298 				odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, 0x82786e64);
299 				odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffff8c);
300 				odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11N, 0xff);
301 				odm_write_2byte(p_dm, ODM_REG_NHM_TH9_TH10_11N + 2, 0xffff);
302 
303 			} else if (p_acs->acs_step == 1) {
304 				/* 4 Set IGI */
305 				odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
306 				if (get_rf_mimo_mode(priv) != RF_1T1R)
307 					odm_set_bb_reg(p_dm, 0xc58, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
308 
309 				/* 4 Set struct _ACS_ NHM threshold */
310 				odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, 0x5a50463c);
311 				odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffff64);
312 
313 			}
314 		}
315 	}
316 
317 }
318 
319 void
phydm_get_nhm_statistics_ap(void * p_dm_void,u32 idx,u32 acs_step)320 phydm_get_nhm_statistics_ap(
321 	void       *p_dm_void,
322 	u32      idx,                /* @ 2G, Real channel number = idx+1 */
323 	u32      acs_step
324 )
325 {
326 	struct PHY_DM_STRUCT	*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
327 	struct rtl8192cd_priv     *priv    = p_dm->priv;
328 	struct _ACS_                  *p_acs    = &p_dm->dm_acs;
329 	u32                value32 = 0;
330 	u8                i;
331 
332 	p_acs->acs_step = acs_step;
333 
334 	if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
335 		/* 4 Check if NHM result is ready */
336 		for (i = 0; i < 20; i++) {
337 
338 			ODM_delay_ms(1);
339 			if (odm_get_bb_reg(p_dm, REG_FPGA0_PSD_REPORT, BIT(17)))
340 				break;
341 		}
342 
343 		/* 4 Get NHM Statistics */
344 		if (p_acs->acs_step == 1) {
345 
346 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11N);
347 
348 			p_acs->nhm_cnt[idx][9] = (value32 & MASKBYTE1) >> 8;
349 			p_acs->nhm_cnt[idx][8] = (value32 & MASKBYTE0);
350 
351 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11N);   /* ODM_REG_NHM_CNT3_TO_CNT0_11N */
352 
353 			p_acs->nhm_cnt[idx][7] = (value32 & MASKBYTE3) >> 24;
354 			p_acs->nhm_cnt[idx][6] = (value32 & MASKBYTE2) >> 16;
355 			p_acs->nhm_cnt[idx][5] = (value32 & MASKBYTE1) >> 8;
356 
357 		} else if (p_acs->acs_step == 2) {
358 
359 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11N);  /* ODM_REG_NHM_CNT3_TO_CNT0_11N */
360 
361 			p_acs->nhm_cnt[idx][4] = odm_read_1byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11N);
362 			p_acs->nhm_cnt[idx][3] = (value32 & MASKBYTE3) >> 24;
363 			p_acs->nhm_cnt[idx][2] = (value32 & MASKBYTE2) >> 16;
364 			p_acs->nhm_cnt[idx][1] = (value32 & MASKBYTE1) >> 8;
365 			p_acs->nhm_cnt[idx][0] = (value32 & MASKBYTE0);
366 		}
367 	} else if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
368 		/* 4 Check if NHM result is ready */
369 		for (i = 0; i < 20; i++) {
370 
371 			ODM_delay_ms(1);
372 			if (odm_get_bb_reg(p_dm, ODM_REG_NHM_DUR_READY_11AC, BIT(16)))
373 				break;
374 		}
375 
376 		if (p_acs->acs_step == 1) {
377 
378 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11AC);
379 
380 			p_acs->nhm_cnt[idx][9] = (value32 & MASKBYTE1) >> 8;
381 			p_acs->nhm_cnt[idx][8] = (value32 & MASKBYTE0);
382 
383 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11AC);    /* ODM_REG_NHM_CNT3_TO_CNT0_11AC */
384 
385 			p_acs->nhm_cnt[idx][7] = (value32 & MASKBYTE3) >> 24;
386 			p_acs->nhm_cnt[idx][6] = (value32 & MASKBYTE2) >> 16;
387 			p_acs->nhm_cnt[idx][5] = (value32 & MASKBYTE1) >> 8;
388 
389 		} else if (p_acs->acs_step == 2) {
390 
391 			value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11AC);     /* ODM_REG_NHM_CNT3_TO_CNT0_11AC */
392 
393 			p_acs->nhm_cnt[idx][4] = odm_read_1byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11AC);
394 			p_acs->nhm_cnt[idx][3] = (value32 & MASKBYTE3) >> 24;
395 			p_acs->nhm_cnt[idx][2] = (value32 & MASKBYTE2) >> 16;
396 			p_acs->nhm_cnt[idx][1] = (value32 & MASKBYTE1) >> 8;
397 			p_acs->nhm_cnt[idx][0] = (value32 & MASKBYTE0);
398 		}
399 	}
400 
401 }
402 
403 
404 /* #define ACS_DEBUG_INFO */ /* acs debug default off */
405 #if 0
406 int phydm_AutoChannelSelectAP(
407 	void   *p_dm_void,
408 	u32  ACS_Type,                      /*  0: RXCount_Type, 1:NHM_Type */
409 	u32  available_chnl_num        /*  amount of all channels */
410 )
411 {
412 	struct PHY_DM_STRUCT               *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
413 	struct _ACS_                    *p_acs    = &p_dm->dm_acs;
414 	struct rtl8192cd_priv			*priv    = p_dm->priv;
415 
416 	static u32           score2G[MAX_2G_CHANNEL_NUM], score5G[MAX_5G_CHANNEL_NUM];
417 	u32                  score[MAX_BSS_NUM], use_nhm = 0;
418 	u32                  minScore = 0xffffffff;
419 	u32                  tmpScore, tmpIdx = 0;
420 	u32                  traffic_check = 0;
421 	u32                  fa_count_weighting = 1;
422 	int                     i, j, idx = 0, idx_2G_end = -1, idx_5G_begin = -1, minChan = 0;
423 	struct bss_desc *pBss = NULL;
424 
425 #ifdef _DEBUG_RTL8192CD_
426 	char tmpbuf[400];
427 	int len = 0;
428 #endif
429 
430 	memset(score2G, '\0', sizeof(score2G));
431 	memset(score5G, '\0', sizeof(score5G));
432 
433 	for (i = 0; i < priv->available_chnl_num; i++) {
434 		if (priv->available_chnl[i] <= 14)
435 			idx_2G_end = i;
436 		else
437 			break;
438 	}
439 
440 	for (i = 0; i < priv->available_chnl_num; i++) {
441 		if (priv->available_chnl[i] > 14) {
442 			idx_5G_begin = i;
443 			break;
444 		}
445 	}
446 
447 	/*  DELETE */
448 #ifndef CONFIG_RTL_NEW_AUTOCH
449 	for (i = 0; i < priv->site_survey->count; i++) {
450 		pBss = &priv->site_survey->bss[i];
451 		for (idx = 0; idx < priv->available_chnl_num; idx++) {
452 			if (pBss->channel == priv->available_chnl[idx]) {
453 				if (pBss->channel <= 14)
454 					setChannelScore(idx, score2G, 0, MAX_2G_CHANNEL_NUM - 1);
455 				else
456 					score5G[idx - idx_5G_begin] += 5;
457 				break;
458 			}
459 		}
460 	}
461 #endif
462 
463 	if (idx_2G_end >= 0)
464 		for (i = 0; i <= idx_2G_end; i++)
465 			score[i] = score2G[i];
466 	if (idx_5G_begin >= 0)
467 		for (i = idx_5G_begin; i < priv->available_chnl_num; i++)
468 			score[i] = score5G[i - idx_5G_begin];
469 
470 #ifdef CONFIG_RTL_NEW_AUTOCH
471 	{
472 		u32 y, ch_begin = 0, ch_end = priv->available_chnl_num;
473 
474 		u32 do_ap_check = 1, ap_ratio = 0;
475 
476 		if (idx_2G_end >= 0)
477 			ch_end = idx_2G_end + 1;
478 		if (idx_5G_begin >= 0)
479 			ch_begin = idx_5G_begin;
480 
481 #ifdef ACS_DEBUG_INFO/* for debug */
482 		printk("\n");
483 		for (y = ch_begin; y < ch_end; y++)
484 			printk("1. init: chnl[%d] 20M_rx[%d] 40M_rx[%d] fa_cnt[%d] score[%d]\n",
485 			       priv->available_chnl[y],
486 			       priv->chnl_ss_mac_rx_count[y],
487 			       priv->chnl_ss_mac_rx_count_40M[y],
488 			       priv->chnl_ss_fa_count[y],
489 			       score[y]);
490 		printk("\n");
491 #endif
492 
493 #if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE)
494 		if (p_dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8192E) && priv->pmib->dot11RFEntry.acs_type) {
495 			u32 tmp_score[MAX_BSS_NUM];
496 			memcpy(tmp_score, score, sizeof(score));
497 			if (find_clean_channel(priv, ch_begin, ch_end, tmp_score)) {
498 				/* memcpy(score, tmp_score, sizeof(score)); */
499 #ifdef _DEBUG_RTL8192CD_
500 				printk("!! Found clean channel, select minimum FA channel\n");
501 #endif
502 				goto USE_CLN_CH;
503 			}
504 #ifdef _DEBUG_RTL8192CD_
505 			printk("!! Not found clean channel, use NHM algorithm\n");
506 #endif
507 			use_nhm = 1;
508 USE_CLN_CH:
509 			for (y = ch_begin; y < ch_end; y++) {
510 				for (i = 0; i <= 9; i++) {
511 					u32 val32 = priv->nhm_cnt[y][i];
512 					for (j = 0; j < i; j++)
513 						val32 *= 3;
514 					score[y] += val32;
515 				}
516 
517 #ifdef _DEBUG_RTL8192CD_
518 				printk("nhm_cnt_%d: H<-[ %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d]->L, score: %d\n",
519 				       y + 1, priv->nhm_cnt[y][9], priv->nhm_cnt[y][8], priv->nhm_cnt[y][7],
520 				       priv->nhm_cnt[y][6], priv->nhm_cnt[y][5], priv->nhm_cnt[y][4],
521 				       priv->nhm_cnt[y][3], priv->nhm_cnt[y][2], priv->nhm_cnt[y][1],
522 				       priv->nhm_cnt[y][0], score[y]);
523 #endif
524 			}
525 
526 			if (!use_nhm)
527 				memcpy(score, tmp_score, sizeof(score));
528 
529 			goto choose_ch;
530 		}
531 #endif
532 
533 		/*  For each channel, weighting behind channels with MAC RX counter */
534 		/* For each channel, weighting the channel with FA counter */
535 
536 		for (y = ch_begin; y < ch_end; y++) {
537 			score[y] += 8 * priv->chnl_ss_mac_rx_count[y];
538 			if (priv->chnl_ss_mac_rx_count[y] > 30)
539 				do_ap_check = 0;
540 			if (priv->chnl_ss_mac_rx_count[y] > MAC_RX_COUNT_THRESHOLD)
541 				traffic_check = 1;
542 
543 #ifdef RTK_5G_SUPPORT
544 			if (*p_dm->p_band_type == ODM_BAND_2_4G)
545 #endif
546 			{
547 				if ((int)(y - 4) >= (int)ch_begin)
548 					score[y - 4] += 2 * priv->chnl_ss_mac_rx_count[y];
549 				if ((int)(y - 3) >= (int)ch_begin)
550 					score[y - 3] += 8 * priv->chnl_ss_mac_rx_count[y];
551 				if ((int)(y - 2) >= (int)ch_begin)
552 					score[y - 2] += 8 * priv->chnl_ss_mac_rx_count[y];
553 				if ((int)(y - 1) >= (int)ch_begin)
554 					score[y - 1] += 10 * priv->chnl_ss_mac_rx_count[y];
555 				if ((int)(y + 1) < (int)ch_end)
556 					score[y + 1] += 10 * priv->chnl_ss_mac_rx_count[y];
557 				if ((int)(y + 2) < (int)ch_end)
558 					score[y + 2] += 8 * priv->chnl_ss_mac_rx_count[y];
559 				if ((int)(y + 3) < (int)ch_end)
560 					score[y + 3] += 8 * priv->chnl_ss_mac_rx_count[y];
561 				if ((int)(y + 4) < (int)ch_end)
562 					score[y + 4] += 2 * priv->chnl_ss_mac_rx_count[y];
563 			}
564 
565 			/* this is for CH_LOAD caculation */
566 			if (priv->chnl_ss_cca_count[y] > priv->chnl_ss_fa_count[y])
567 				priv->chnl_ss_cca_count[y] -= priv->chnl_ss_fa_count[y];
568 			else
569 				priv->chnl_ss_cca_count[y] = 0;
570 		}
571 
572 #ifdef ACS_DEBUG_INFO/* for debug */
573 		printk("\n");
574 		for (y = ch_begin; y < ch_end; y++)
575 			printk("2. after 20M check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
576 		printk("\n");
577 #endif
578 
579 		for (y = ch_begin; y < ch_end; y++) {
580 			if (priv->chnl_ss_mac_rx_count_40M[y]) {
581 				score[y] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
582 				if (priv->chnl_ss_mac_rx_count_40M[y] > 30)
583 					do_ap_check = 0;
584 				if (priv->chnl_ss_mac_rx_count_40M[y] > MAC_RX_COUNT_THRESHOLD)
585 					traffic_check = 1;
586 
587 #ifdef RTK_5G_SUPPORT
588 				if (*p_dm->p_band_type == ODM_BAND_2_4G)
589 #endif
590 				{
591 					if ((int)(y - 6) >= (int)ch_begin)
592 						score[y - 6] += 1 * priv->chnl_ss_mac_rx_count_40M[y];
593 					if ((int)(y - 5) >= (int)ch_begin)
594 						score[y - 5] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
595 					if ((int)(y - 4) >= (int)ch_begin)
596 						score[y - 4] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
597 					if ((int)(y - 3) >= (int)ch_begin)
598 						score[y - 3] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
599 					if ((int)(y - 2) >= (int)ch_begin)
600 						score[y - 2] += (5 * priv->chnl_ss_mac_rx_count_40M[y]) / 2;
601 					if ((int)(y - 1) >= (int)ch_begin)
602 						score[y - 1] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
603 					if ((int)(y + 1) < (int)ch_end)
604 						score[y + 1] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
605 					if ((int)(y + 2) < (int)ch_end)
606 						score[y + 2] += (5 * priv->chnl_ss_mac_rx_count_40M[y]) / 2;
607 					if ((int)(y + 3) < (int)ch_end)
608 						score[y + 3] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
609 					if ((int)(y + 4) < (int)ch_end)
610 						score[y + 4] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
611 					if ((int)(y + 5) < (int)ch_end)
612 						score[y + 5] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
613 					if ((int)(y + 6) < (int)ch_end)
614 						score[y + 6] += 1 * priv->chnl_ss_mac_rx_count_40M[y];
615 				}
616 			}
617 		}
618 
619 #ifdef ACS_DEBUG_INFO/* for debug */
620 		printk("\n");
621 		for (y = ch_begin; y < ch_end; y++)
622 			printk("3. after 40M check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
623 		printk("\n");
624 		printk("4. do_ap_check=%d traffic_check=%d\n", do_ap_check, traffic_check);
625 		printk("\n");
626 #endif
627 
628 		if (traffic_check == 0)
629 			fa_count_weighting = 5;
630 		else
631 			fa_count_weighting = 1;
632 
633 		for (y = ch_begin; y < ch_end; y++)
634 			score[y] += fa_count_weighting * priv->chnl_ss_fa_count[y];
635 
636 #ifdef ACS_DEBUG_INFO/* for debug */
637 		printk("\n");
638 		for (y = ch_begin; y < ch_end; y++)
639 			printk("5. after fa check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
640 		printk("\n");
641 #endif
642 
643 		if (do_ap_check) {
644 			for (i = 0; i < priv->site_survey->count; i++) {
645 				pBss = &priv->site_survey->bss[i];
646 				for (y = ch_begin; y < ch_end; y++) {
647 					if (pBss->channel == priv->available_chnl[y]) {
648 						if (pBss->channel <= 14) {
649 #ifdef ACS_DEBUG_INFO/* for debug */
650 							printk("\n");
651 							printk("chnl[%d] has ap rssi=%d bw[0x%02x]\n",
652 							       pBss->channel, pBss->rssi, pBss->t_stamp[1]);
653 							printk("\n");
654 #endif
655 							if (pBss->rssi > 60)
656 								ap_ratio = 4;
657 							else if (pBss->rssi > 35)
658 								ap_ratio = 2;
659 							else
660 								ap_ratio = 1;
661 
662 							if ((pBss->t_stamp[1] & 0x6) == 0) {
663 								score[y] += 50 * ap_ratio;
664 								if ((int)(y - 4) >= (int)ch_begin)
665 									score[y - 4] += 10 * ap_ratio;
666 								if ((int)(y - 3) >= (int)ch_begin)
667 									score[y - 3] += 20 * ap_ratio;
668 								if ((int)(y - 2) >= (int)ch_begin)
669 									score[y - 2] += 30 * ap_ratio;
670 								if ((int)(y - 1) >= (int)ch_begin)
671 									score[y - 1] += 40 * ap_ratio;
672 								if ((int)(y + 1) < (int)ch_end)
673 									score[y + 1] += 40 * ap_ratio;
674 								if ((int)(y + 2) < (int)ch_end)
675 									score[y + 2] += 30 * ap_ratio;
676 								if ((int)(y + 3) < (int)ch_end)
677 									score[y + 3] += 20 * ap_ratio;
678 								if ((int)(y + 4) < (int)ch_end)
679 									score[y + 4] += 10 * ap_ratio;
680 							} else if ((pBss->t_stamp[1] & 0x4) == 0) {
681 								score[y] += 50 * ap_ratio;
682 								if ((int)(y - 3) >= (int)ch_begin)
683 									score[y - 3] += 20 * ap_ratio;
684 								if ((int)(y - 2) >= (int)ch_begin)
685 									score[y - 2] += 30 * ap_ratio;
686 								if ((int)(y - 1) >= (int)ch_begin)
687 									score[y - 1] += 40 * ap_ratio;
688 								if ((int)(y + 1) < (int)ch_end)
689 									score[y + 1] += 50 * ap_ratio;
690 								if ((int)(y + 2) < (int)ch_end)
691 									score[y + 2] += 50 * ap_ratio;
692 								if ((int)(y + 3) < (int)ch_end)
693 									score[y + 3] += 50 * ap_ratio;
694 								if ((int)(y + 4) < (int)ch_end)
695 									score[y + 4] += 50 * ap_ratio;
696 								if ((int)(y + 5) < (int)ch_end)
697 									score[y + 5] += 40 * ap_ratio;
698 								if ((int)(y + 6) < (int)ch_end)
699 									score[y + 6] += 30 * ap_ratio;
700 								if ((int)(y + 7) < (int)ch_end)
701 									score[y + 7] += 20 * ap_ratio;
702 							} else {
703 								score[y] += 50 * ap_ratio;
704 								if ((int)(y - 7) >= (int)ch_begin)
705 									score[y - 7] += 20 * ap_ratio;
706 								if ((int)(y - 6) >= (int)ch_begin)
707 									score[y - 6] += 30 * ap_ratio;
708 								if ((int)(y - 5) >= (int)ch_begin)
709 									score[y - 5] += 40 * ap_ratio;
710 								if ((int)(y - 4) >= (int)ch_begin)
711 									score[y - 4] += 50 * ap_ratio;
712 								if ((int)(y - 3) >= (int)ch_begin)
713 									score[y - 3] += 50 * ap_ratio;
714 								if ((int)(y - 2) >= (int)ch_begin)
715 									score[y - 2] += 50 * ap_ratio;
716 								if ((int)(y - 1) >= (int)ch_begin)
717 									score[y - 1] += 50 * ap_ratio;
718 								if ((int)(y + 1) < (int)ch_end)
719 									score[y + 1] += 40 * ap_ratio;
720 								if ((int)(y + 2) < (int)ch_end)
721 									score[y + 2] += 30 * ap_ratio;
722 								if ((int)(y + 3) < (int)ch_end)
723 									score[y + 3] += 20 * ap_ratio;
724 							}
725 						} else {
726 							if ((pBss->t_stamp[1] & 0x6) == 0)
727 								score[y] += 500;
728 							else if ((pBss->t_stamp[1] & 0x4) == 0) {
729 								score[y] += 500;
730 								if ((int)(y + 1) < (int)ch_end)
731 									score[y + 1] += 500;
732 							} else {
733 								score[y] += 500;
734 								if ((int)(y - 1) >= (int)ch_begin)
735 									score[y - 1] += 500;
736 							}
737 						}
738 						break;
739 					}
740 				}
741 			}
742 		}
743 
744 #ifdef ACS_DEBUG_INFO/* for debug */
745 		printk("\n");
746 		for (y = ch_begin; y < ch_end; y++)
747 			printk("6. after ap check: chnl[%d]:%d\n", priv->available_chnl[y], score[y]);
748 		printk("\n");
749 #endif
750 
751 #ifdef SS_CH_LOAD_PROC
752 
753 		/*  caculate noise level -- suggested by wilson */
754 		for (y = ch_begin; y < ch_end; y++)  {
755 			int fa_lv = 0, cca_lv = 0;
756 			if (priv->chnl_ss_fa_count[y] > 1000)
757 				fa_lv = 100;
758 			else if (priv->chnl_ss_fa_count[y] > 500)
759 				fa_lv = 34 * (priv->chnl_ss_fa_count[y] - 500) / 500 + 66;
760 			else if (priv->chnl_ss_fa_count[y] > 200)
761 				fa_lv = 33 * (priv->chnl_ss_fa_count[y] - 200) / 300 + 33;
762 			else if (priv->chnl_ss_fa_count[y] > 100)
763 				fa_lv = 18 * (priv->chnl_ss_fa_count[y] - 100) / 100 + 15;
764 			else
765 				fa_lv = 15 * priv->chnl_ss_fa_count[y] / 100;
766 			if (priv->chnl_ss_cca_count[y] > 400)
767 				cca_lv = 100;
768 			else if (priv->chnl_ss_cca_count[y] > 200)
769 				cca_lv = 34 * (priv->chnl_ss_cca_count[y] - 200) / 200 + 66;
770 			else if (priv->chnl_ss_cca_count[y] > 80)
771 				cca_lv = 33 * (priv->chnl_ss_cca_count[y] - 80) / 120 + 33;
772 			else if (priv->chnl_ss_cca_count[y] > 40)
773 				cca_lv = 18 * (priv->chnl_ss_cca_count[y] - 40) / 40 + 15;
774 			else
775 				cca_lv = 15 * priv->chnl_ss_cca_count[y] / 40;
776 
777 			priv->chnl_ss_load[y] = (((fa_lv > cca_lv) ? fa_lv : cca_lv) * 75 + ((score[y] > 100) ? 100 : score[y]) * 25) / 100;
778 
779 			DEBUG_INFO("ch:%d f=%d (%d), c=%d (%d), fl=%d, cl=%d, sc=%d, cu=%d\n",
780 				   priv->available_chnl[y],
781 				   priv->chnl_ss_fa_count[y], fa_thd,
782 				   priv->chnl_ss_cca_count[y], cca_thd,
783 				   fa_lv,
784 				   cca_lv,
785 				   score[y],
786 				   priv->chnl_ss_load[y]);
787 
788 		}
789 #endif
790 	}
791 #endif
792 
793 choose_ch:
794 
795 #ifdef DFS
796 	/*  heavy weighted DFS channel */
797 	if (idx_5G_begin >= 0) {
798 		for (i = idx_5G_begin; i < priv->available_chnl_num; i++) {
799 			if (!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(priv->available_chnl[i])
800 			    && (score[i] != 0xffffffff))
801 				score[i] += 1600;
802 		}
803 	}
804 #endif
805 
806 
807 	/* prevent Auto channel selecting wrong channel in 40M mode----------------- */
808 	if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)
809 	    && priv->pshare->is_40m_bw) {
810 #if 0
811 		if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 1) {
812 			/* Upper Primary channel, cannot select the two lowest channels */
813 			if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) {
814 				score[0] = 0xffffffff;
815 				score[1] = 0xffffffff;
816 				score[2] = 0xffffffff;
817 				score[3] = 0xffffffff;
818 				score[4] = 0xffffffff;
819 
820 				score[13] = 0xffffffff;
821 				score[12] = 0xffffffff;
822 				score[11] = 0xffffffff;
823 			}
824 
825 			/*			if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { */
826 			/*				score[idx_5G_begin] = 0xffffffff; */
827 			/*				score[idx_5G_begin + 1] = 0xffffffff; */
828 			/*			} */
829 		} else if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 2) {
830 			/* Lower Primary channel, cannot select the two highest channels */
831 			if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) {
832 				score[0] = 0xffffffff;
833 				score[1] = 0xffffffff;
834 				score[2] = 0xffffffff;
835 
836 				score[13] = 0xffffffff;
837 				score[12] = 0xffffffff;
838 				score[11] = 0xffffffff;
839 				score[10] = 0xffffffff;
840 				score[9] = 0xffffffff;
841 			}
842 
843 			/*			if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { */
844 			/*				score[priv->available_chnl_num - 2] = 0xffffffff; */
845 			/*				score[priv->available_chnl_num - 1] = 0xffffffff; */
846 			/*			} */
847 		}
848 #endif
849 		for (i = 0; i <= idx_2G_end; ++i)
850 			if (priv->available_chnl[i] == 14)
851 				score[i] = 0xffffffff;		/*  mask chan14 */
852 
853 #ifdef RTK_5G_SUPPORT
854 		if (idx_5G_begin >= 0) {
855 			for (i = idx_5G_begin; i < priv->available_chnl_num; i++) {
856 				int ch = priv->available_chnl[i];
857 				if (priv->available_chnl[i] > 144)
858 					--ch;
859 				if ((ch % 4) || ch == 140 || ch == 164)	/* mask ch 140, ch 165, ch 184... */
860 					score[i] = 0xffffffff;
861 			}
862 		}
863 #endif
864 
865 
866 	}
867 
868 	if (priv->pmib->dot11RFEntry.disable_ch1213) {
869 		for (i = 0; i <= idx_2G_end; ++i) {
870 			int ch = priv->available_chnl[i];
871 			if ((ch == 12) || (ch == 13))
872 				score[i] = 0xffffffff;
873 		}
874 	}
875 
876 	if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_GLOBAL) ||
877 	     (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_WORLD_WIDE)) &&
878 	    (idx_2G_end >= 11) && (idx_2G_end < 14)) {
879 		score[13] = 0xffffffff;	/*  mask chan14 */
880 		score[12] = 0xffffffff; /*  mask chan13 */
881 		score[11] = 0xffffffff; /*  mask chan12 */
882 	}
883 
884 	/* ------------------------------------------------------------------ */
885 
886 #ifdef _DEBUG_RTL8192CD_
887 	for (i = 0; i < priv->available_chnl_num; i++)
888 		len += sprintf(tmpbuf + len, "ch%d:%u ", priv->available_chnl[i], score[i]);
889 	strcat(tmpbuf, "\n");
890 	panic_printk("%s", tmpbuf);
891 
892 #endif
893 
894 	if ((*p_dm->p_band_type == ODM_BAND_5G)
895 	    && (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80)) {
896 		for (i = 0; i < priv->available_chnl_num; i++) {
897 			if (is80MChannel(priv->available_chnl, priv->available_chnl_num, priv->available_chnl[i])) {
898 				tmpScore = 0;
899 				for (j = 0; j < 4; j++) {
900 					if ((tmpScore != 0xffffffff) && (score[i + j] != 0xffffffff))
901 						tmpScore += score[i + j];
902 					else
903 						tmpScore = 0xffffffff;
904 				}
905 				tmpScore = tmpScore / 4;
906 				if (minScore > tmpScore) {
907 					minScore = tmpScore;
908 
909 					tmpScore = 0xffffffff;
910 					for (j = 0; j < 4; j++) {
911 						if (score[i + j] < tmpScore) {
912 							tmpScore = score[i + j];
913 							tmpIdx = i + j;
914 						}
915 					}
916 
917 					idx = tmpIdx;
918 				}
919 				i += 3;
920 			}
921 		}
922 		if (minScore == 0xffffffff) {
923 			/*  there is no 80M channels */
924 			priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
925 			for (i = 0; i < priv->available_chnl_num; i++) {
926 				if (score[i] < minScore) {
927 					minScore = score[i];
928 					idx = i;
929 				}
930 			}
931 		}
932 	} else if ((*p_dm->p_band_type == ODM_BAND_5G)
933 		&& (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40)) {
934 		for (i = 0; i < priv->available_chnl_num; i++) {
935 			if (is40MChannel(priv->available_chnl, priv->available_chnl_num, priv->available_chnl[i])) {
936 				tmpScore = 0;
937 				for (j = 0; j < 2; j++) {
938 					if ((tmpScore != 0xffffffff) && (score[i + j] != 0xffffffff))
939 						tmpScore += score[i + j];
940 					else
941 						tmpScore = 0xffffffff;
942 				}
943 				tmpScore = tmpScore / 2;
944 				if (minScore > tmpScore) {
945 					minScore = tmpScore;
946 
947 					tmpScore = 0xffffffff;
948 					for (j = 0; j < 2; j++) {
949 						if (score[i + j] < tmpScore) {
950 							tmpScore = score[i + j];
951 							tmpIdx = i + j;
952 						}
953 					}
954 
955 					idx = tmpIdx;
956 				}
957 				i += 1;
958 			}
959 		}
960 		if (minScore == 0xffffffff) {
961 			/*  there is no 40M channels */
962 			priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
963 			for (i = 0; i < priv->available_chnl_num; i++) {
964 				if (score[i] < minScore) {
965 					minScore = score[i];
966 					idx = i;
967 				}
968 			}
969 		}
970 	} else if ((*p_dm->p_band_type == ODM_BAND_2_4G)
971 		&& (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40)
972 		   && (priv->available_chnl_num >= 8)) {
973 		u32 groupScore[14];
974 
975 		memset(groupScore, 0xff, sizeof(groupScore));
976 		for (i = 0; i < priv->available_chnl_num - 4; i++) {
977 			if (score[i] != 0xffffffff && score[i + 4] != 0xffffffff) {
978 				groupScore[i] = score[i] + score[i + 4];
979 				DEBUG_INFO("groupScore, ch %d,%d: %d\n", i + 1, i + 5, groupScore[i]);
980 				if (groupScore[i] < minScore) {
981 #ifdef AUTOCH_SS_SPEEDUP
982 					if (priv->pmib->miscEntry.autoch_1611_enable) {
983 						if (priv->available_chnl[i] == 1 || priv->available_chnl[i] == 6 || priv->available_chnl[i] == 11) {
984 							minScore = groupScore[i];
985 							idx = i;
986 						}
987 					} else
988 #endif
989 					{
990 						minScore = groupScore[i];
991 						idx = i;
992 					}
993 				}
994 			}
995 		}
996 
997 		if (score[idx] < score[idx + 4]) {
998 			GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
999 			priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_ABOVE;
1000 		} else {
1001 			idx = idx + 4;
1002 			GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1003 			priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_BELOW;
1004 		}
1005 	} else {
1006 		for (i = 0; i < priv->available_chnl_num; i++) {
1007 			if (score[i] < minScore) {
1008 #ifdef AUTOCH_SS_SPEEDUP
1009 				if (priv->pmib->miscEntry.autoch_1611_enable) {
1010 					if (priv->available_chnl[i] == 1 || priv->available_chnl[i] == 6 || priv->available_chnl[i] == 11) {
1011 						minScore = score[i];
1012 						idx = i;
1013 					}
1014 				} else
1015 #endif
1016 				{
1017 					minScore = score[i];
1018 					idx = i;
1019 				}
1020 			}
1021 		}
1022 	}
1023 
1024 	if (IS_A_CUT_8881A(priv) &&
1025 	    (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80)) {
1026 		if ((priv->available_chnl[idx] == 36) ||
1027 		    (priv->available_chnl[idx] == 52) ||
1028 		    (priv->available_chnl[idx] == 100) ||
1029 		    (priv->available_chnl[idx] == 116) ||
1030 		    (priv->available_chnl[idx] == 132) ||
1031 		    (priv->available_chnl[idx] == 149) ||
1032 		    (priv->available_chnl[idx] == 165))
1033 			idx++;
1034 		else if ((priv->available_chnl[idx] == 48) ||
1035 			 (priv->available_chnl[idx] == 64) ||
1036 			 (priv->available_chnl[idx] == 112) ||
1037 			 (priv->available_chnl[idx] == 128) ||
1038 			 (priv->available_chnl[idx] == 144) ||
1039 			 (priv->available_chnl[idx] == 161) ||
1040 			 (priv->available_chnl[idx] == 177))
1041 			idx--;
1042 	}
1043 
1044 	minChan = priv->available_chnl[idx];
1045 
1046 	/*  skip channel 14 if don't support ofdm */
1047 	if ((priv->pmib->dot11RFEntry.disable_ch14_ofdm) &&
1048 	    (minChan == 14)) {
1049 		score[idx] = 0xffffffff;
1050 
1051 		minScore = 0xffffffff;
1052 		for (i = 0; i < priv->available_chnl_num; i++) {
1053 			if (score[i] < minScore) {
1054 				minScore = score[i];
1055 				idx = i;
1056 			}
1057 		}
1058 		minChan = priv->available_chnl[idx];
1059 	}
1060 
1061 #if 0
1062 	/* Check if selected channel available for 80M/40M BW or NOT ? */
1063 	if (*p_dm->p_band_type == ODM_BAND_5G) {
1064 		if (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80) {
1065 			if (!is80MChannel(priv->available_chnl, priv->available_chnl_num, minChan)) {
1066 
1067 				/* priv->pmib->dot11n_config_entry.dot11nUse40M = CHANNEL_WIDTH_40; */
1068 				priv->pshare->is_40m_bw = CHANNEL_WIDTH_40;
1069 			}
1070 		}
1071 
1072 		if (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40) {
1073 			if (!is40MChannel(priv->available_chnl, priv->available_chnl_num, minChan)) {
1074 
1075 				/* priv->pmib->dot11n_config_entry.dot11nUse40M = CHANNEL_WIDTH_20; */
1076 				priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
1077 			}
1078 		}
1079 	}
1080 #endif
1081 
1082 #ifdef CONFIG_RTL_NEW_AUTOCH
1083 	RTL_W32(RXERR_RPT, RXERR_RPT_RST);
1084 #endif
1085 
1086 	/*  auto adjust contro-sideband */
1087 	if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)
1088 	    && (priv->pshare->is_40m_bw == 1 || priv->pshare->is_40m_bw == 2)) {
1089 
1090 #ifdef RTK_5G_SUPPORT
1091 		if (*p_dm->p_band_type == ODM_BAND_5G) {
1092 			if ((minChan > 144) ? ((minChan - 1) % 8) : (minChan % 8)) {
1093 				GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1094 				priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_ABOVE;
1095 			} else {
1096 				GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1097 				priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_BELOW;
1098 			}
1099 
1100 		} else
1101 #endif
1102 		{
1103 #if 0
1104 #ifdef CONFIG_RTL_NEW_AUTOCH
1105 			unsigned int ch_max;
1106 
1107 			if (priv->available_chnl[idx_2G_end] >= 13)
1108 				ch_max = 13;
1109 			else
1110 				ch_max = priv->available_chnl[idx_2G_end];
1111 
1112 			if ((minChan >= 5) && (minChan <= (ch_max - 5))) {
1113 				if (score[minChan + 4] > score[minChan - 4]) { /*  what if some channels were cancelled? */
1114 					GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1115 					priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_BELOW;
1116 				} else {
1117 					GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1118 					priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_ABOVE;
1119 				}
1120 			} else
1121 #endif
1122 			{
1123 				if (minChan < 5) {
1124 					GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1125 					priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_ABOVE;
1126 				} else if (minChan > 7) {
1127 					GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1128 					priv->pshare->offset_2nd_chan	= HT_2NDCH_OFFSET_BELOW;
1129 				}
1130 			}
1131 #endif
1132 		}
1133 	}
1134 	/* ----------------------- */
1135 
1136 #if defined(__ECOS) && defined(CONFIG_SDIO_HCI)
1137 	panic_printk("Auto channel choose ch:%d\n", minChan);
1138 #else
1139 #ifdef _DEBUG_RTL8192CD_
1140 	panic_printk("Auto channel choose ch:%d\n", minChan);
1141 #endif
1142 #endif
1143 #ifdef ACS_DEBUG_INFO/* for debug */
1144 	printk("7. minChan:%d 2nd_offset:%d\n", minChan, priv->pshare->offset_2nd_chan);
1145 #endif
1146 
1147 	return minChan;
1148 }
1149 #endif
1150 
1151 #endif
1152