phydm_pathdiv.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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. * The full GNU General Public License is included in this distribution in the
  15. * file called LICENSE.
  16. *
  17. * Contact Information:
  18. * wlanfae <wlanfae@realtek.com>
  19. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20. * Hsinchu 300, Taiwan.
  21. *
  22. * Larry Finger <Larry.Finger@lwfinger.net>
  23. *
  24. *****************************************************************************/
  25. /*************************************************************
  26. * include files
  27. ************************************************************/
  28. #include "mp_precomp.h"
  29. #include "phydm_precomp.h"
  30. #ifdef CONFIG_PATH_DIVERSITY
  31. #if RTL8814A_SUPPORT
  32. void phydm_dtp_fix_tx_path(
  33. void *dm_void,
  34. u8 path)
  35. {
  36. struct dm_struct *dm = (struct dm_struct *)dm_void;
  37. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  38. u8 i, num_enable_path = 0;
  39. if (path == dm_path_div->pre_tx_path)
  40. return;
  41. else
  42. dm_path_div->pre_tx_path = path;
  43. odm_set_bb_reg(dm, R_0x93c, BIT(18) | BIT(19), 3);
  44. for (i = 0; i < 4; i++) {
  45. if (path & BIT(i))
  46. num_enable_path++;
  47. }
  48. PHYDM_DBG(dm, DBG_PATH_DIV, " number of turn-on path : (( %d ))\n",
  49. num_enable_path);
  50. if (num_enable_path == 1) {
  51. odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
  52. if (path == BB_PATH_A) { /* @1-1 */
  53. PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( A ))\n");
  54. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  55. } else if (path == BB_PATH_B) { /* @1-2 */
  56. PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( B ))\n");
  57. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
  58. } else if (path == BB_PATH_C) { /* @1-3 */
  59. PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( C ))\n");
  60. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 0);
  61. } else if (path == BB_PATH_D) { /* @1-4 */
  62. PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( D ))\n");
  63. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 0);
  64. }
  65. } else if (num_enable_path == 2) {
  66. odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
  67. odm_set_bb_reg(dm, R_0x940, 0xf0, path);
  68. if (path == (BB_PATH_AB)) { /* @2-1 */
  69. PHYDM_DBG(dm, DBG_PATH_DIV,
  70. " Turn on path (( A B ))\n");
  71. /* set for 1ss */
  72. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  73. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
  74. /* set for 2ss */
  75. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  76. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
  77. } else if (path == BB_PATH_AC) { /* @2-2 */
  78. PHYDM_DBG(dm, DBG_PATH_DIV,
  79. " Turn on path (( A C ))\n");
  80. /* set for 1ss */
  81. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  82. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
  83. /* set for 2ss */
  84. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  85. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
  86. } else if (path == BB_PATH_AD) { /* @2-3 */
  87. PHYDM_DBG(dm, DBG_PATH_DIV,
  88. " Turn on path (( A D ))\n");
  89. /* set for 1ss */
  90. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  91. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
  92. /* set for 2ss */
  93. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  94. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
  95. } else if (path == BB_PATH_BC) { /* @2-4 */
  96. PHYDM_DBG(dm, DBG_PATH_DIV,
  97. " Turn on path (( B C ))\n");
  98. /* set for 1ss */
  99. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
  100. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
  101. /* set for 2ss */
  102. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
  103. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
  104. } else if (path == BB_PATH_BD) { /* @2-5 */
  105. PHYDM_DBG(dm, DBG_PATH_DIV,
  106. " Turn on path (( B D ))\n");
  107. /* set for 1ss */
  108. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
  109. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
  110. /* set for 2ss */
  111. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
  112. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
  113. } else if (path == BB_PATH_CD) { /* @2-6 */
  114. PHYDM_DBG(dm, DBG_PATH_DIV,
  115. " Turn on path (( C D ))\n");
  116. /* set for 1ss */
  117. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 0);
  118. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
  119. /* set for 2ss */
  120. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 0);
  121. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
  122. }
  123. } else if (num_enable_path == 3) {
  124. odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
  125. odm_set_bb_reg(dm, R_0x940, 0xf0, path);
  126. odm_set_bb_reg(dm, R_0x940, 0xf0000, path);
  127. if (path == BB_PATH_ABC) { /* @3-1 */
  128. PHYDM_DBG(dm, DBG_PATH_DIV,
  129. " Turn on path (( A B C))\n");
  130. /* set for 1ss */
  131. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  132. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
  133. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 2);
  134. /* set for 2ss */
  135. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  136. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
  137. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 2);
  138. /* set for 3ss */
  139. odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
  140. odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 1);
  141. odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 2);
  142. } else if (path == BB_PATH_ABD) { /* @3-2 */
  143. PHYDM_DBG(dm, DBG_PATH_DIV,
  144. " Turn on path (( A B D ))\n");
  145. /* set for 1ss */
  146. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  147. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
  148. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
  149. /* set for 2ss */
  150. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  151. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
  152. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
  153. /* set for 3ss */
  154. odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
  155. odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 1);
  156. odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
  157. } else if (path == BB_PATH_ACD) { /* @3-3 */
  158. PHYDM_DBG(dm, DBG_PATH_DIV,
  159. " Turn on path (( A C D ))\n");
  160. /* set for 1ss */
  161. odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
  162. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
  163. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
  164. /* set for 2ss */
  165. odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
  166. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
  167. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
  168. /* set for 3ss */
  169. odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
  170. odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 1);
  171. odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
  172. } else if (path == BB_PATH_BCD) { /* @3-4 */
  173. PHYDM_DBG(dm, DBG_PATH_DIV,
  174. " Turn on path (( B C D))\n");
  175. /* set for 1ss */
  176. odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
  177. odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
  178. odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
  179. /* set for 2ss */
  180. odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
  181. odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
  182. odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
  183. /* set for 3ss */
  184. odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 0);
  185. odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 1);
  186. odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
  187. }
  188. } else if (num_enable_path == 4)
  189. PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path ((A B C D))\n");
  190. }
  191. void phydm_find_default_path(
  192. void *dm_void)
  193. {
  194. struct dm_struct *dm = (struct dm_struct *)dm_void;
  195. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  196. u32 rssi_avg_a = 0, rssi_avg_b = 0, rssi_avg_c = 0, rssi_avg_d = 0, rssi_avg_bcd = 0;
  197. u32 rssi_total_a = 0, rssi_total_b = 0, rssi_total_c = 0, rssi_total_d = 0;
  198. /* @2 Default path Selection By RSSI */
  199. rssi_avg_a = (dm_path_div->path_a_cnt_all > 0) ? (dm_path_div->path_a_sum_all / dm_path_div->path_a_cnt_all) : 0;
  200. rssi_avg_b = (dm_path_div->path_b_cnt_all > 0) ? (dm_path_div->path_b_sum_all / dm_path_div->path_b_cnt_all) : 0;
  201. rssi_avg_c = (dm_path_div->path_c_cnt_all > 0) ? (dm_path_div->path_c_sum_all / dm_path_div->path_c_cnt_all) : 0;
  202. rssi_avg_d = (dm_path_div->path_d_cnt_all > 0) ? (dm_path_div->path_d_sum_all / dm_path_div->path_d_cnt_all) : 0;
  203. dm_path_div->path_a_sum_all = 0;
  204. dm_path_div->path_a_cnt_all = 0;
  205. dm_path_div->path_b_sum_all = 0;
  206. dm_path_div->path_b_cnt_all = 0;
  207. dm_path_div->path_c_sum_all = 0;
  208. dm_path_div->path_c_cnt_all = 0;
  209. dm_path_div->path_d_sum_all = 0;
  210. dm_path_div->path_d_cnt_all = 0;
  211. if (dm_path_div->use_path_a_as_default_ant == 1) {
  212. rssi_avg_bcd = (rssi_avg_b + rssi_avg_c + rssi_avg_d) / 3;
  213. if ((rssi_avg_a + ANT_DECT_RSSI_TH) > rssi_avg_bcd) {
  214. dm_path_div->is_path_a_exist = true;
  215. dm_path_div->default_path = PATH_A;
  216. } else
  217. dm_path_div->is_path_a_exist = false;
  218. } else {
  219. if (rssi_avg_a >= rssi_avg_b && rssi_avg_a >= rssi_avg_c && rssi_avg_a >= rssi_avg_d)
  220. dm_path_div->default_path = PATH_A;
  221. else if ((rssi_avg_b >= rssi_avg_c) && (rssi_avg_b >= rssi_avg_d))
  222. dm_path_div->default_path = PATH_B;
  223. else if (rssi_avg_c >= rssi_avg_d)
  224. dm_path_div->default_path = PATH_C;
  225. else
  226. dm_path_div->default_path = PATH_D;
  227. }
  228. }
  229. void phydm_candidate_dtp_update(
  230. void *dm_void)
  231. {
  232. struct dm_struct *dm = (struct dm_struct *)dm_void;
  233. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  234. dm_path_div->num_candidate = 3;
  235. if (dm_path_div->use_path_a_as_default_ant == 1) {
  236. if (dm_path_div->num_tx_path == 3) {
  237. if (dm_path_div->is_path_a_exist) {
  238. dm_path_div->ant_candidate_1 = BB_PATH_ABC;
  239. dm_path_div->ant_candidate_2 = BB_PATH_ABD;
  240. dm_path_div->ant_candidate_3 = BB_PATH_ACD;
  241. } else { /* use path BCD */
  242. dm_path_div->num_candidate = 1;
  243. phydm_dtp_fix_tx_path(dm, BB_PATH_BCD);
  244. return;
  245. }
  246. } else if (dm_path_div->num_tx_path == 2) {
  247. if (dm_path_div->is_path_a_exist) {
  248. dm_path_div->ant_candidate_1 = BB_PATH_AB;
  249. dm_path_div->ant_candidate_2 = BB_PATH_AC;
  250. dm_path_div->ant_candidate_3 = BB_PATH_AD;
  251. } else {
  252. dm_path_div->ant_candidate_1 = BB_PATH_BC;
  253. dm_path_div->ant_candidate_2 = BB_PATH_BD;
  254. dm_path_div->ant_candidate_3 = BB_PATH_CD;
  255. }
  256. }
  257. } else {
  258. /* @2 3 TX mode */
  259. if (dm_path_div->num_tx_path == 3) { /* @choose 3 ant form 4 */
  260. if (dm_path_div->default_path == PATH_A) { /* @choose 2 ant form 3 */
  261. dm_path_div->ant_candidate_1 = BB_PATH_ABC;
  262. dm_path_div->ant_candidate_2 = BB_PATH_ABD;
  263. dm_path_div->ant_candidate_3 = BB_PATH_ACD;
  264. } else if (dm_path_div->default_path == PATH_B) {
  265. dm_path_div->ant_candidate_1 = BB_PATH_ABC;
  266. dm_path_div->ant_candidate_2 = BB_PATH_ABD;
  267. dm_path_div->ant_candidate_3 = BB_PATH_BCD;
  268. } else if (dm_path_div->default_path == PATH_C) {
  269. dm_path_div->ant_candidate_1 = BB_PATH_ABC;
  270. dm_path_div->ant_candidate_2 = BB_PATH_ACD;
  271. dm_path_div->ant_candidate_3 = BB_PATH_BCD;
  272. } else if (dm_path_div->default_path == PATH_D) {
  273. dm_path_div->ant_candidate_1 = BB_PATH_ABD;
  274. dm_path_div->ant_candidate_2 = BB_PATH_ACD;
  275. dm_path_div->ant_candidate_3 = BB_PATH_BCD;
  276. }
  277. }
  278. /* @2 2 TX mode */
  279. else if (dm_path_div->num_tx_path == 2) { /* @choose 2 ant form 4 */
  280. if (dm_path_div->default_path == PATH_A) { /* @choose 2 ant form 3 */
  281. dm_path_div->ant_candidate_1 = BB_PATH_AB;
  282. dm_path_div->ant_candidate_2 = BB_PATH_AC;
  283. dm_path_div->ant_candidate_3 = BB_PATH_AD;
  284. } else if (dm_path_div->default_path == PATH_B) {
  285. dm_path_div->ant_candidate_1 = BB_PATH_AB;
  286. dm_path_div->ant_candidate_2 = BB_PATH_BC;
  287. dm_path_div->ant_candidate_3 = BB_PATH_BD;
  288. } else if (dm_path_div->default_path == PATH_C) {
  289. dm_path_div->ant_candidate_1 = BB_PATH_AC;
  290. dm_path_div->ant_candidate_2 = BB_PATH_BC;
  291. dm_path_div->ant_candidate_3 = BB_PATH_CD;
  292. } else if (dm_path_div->default_path == PATH_D) {
  293. dm_path_div->ant_candidate_1 = BB_PATH_AD;
  294. dm_path_div->ant_candidate_2 = BB_PATH_BD;
  295. dm_path_div->ant_candidate_3 = BB_PATH_CD;
  296. }
  297. }
  298. }
  299. }
  300. void phydm_dynamic_tx_path(
  301. void *dm_void)
  302. {
  303. struct dm_struct *dm = (struct dm_struct *)dm_void;
  304. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  305. struct sta_info *entry;
  306. u32 i;
  307. u8 num_client = 0;
  308. u8 h2c_parameter[6] = {0};
  309. if (!dm->is_linked) { /* @is_linked==False */
  310. PHYDM_DBG(dm, DBG_PATH_DIV, "DTP_8814 [No Link!!!]\n");
  311. if (dm_path_div->is_become_linked == true) {
  312. PHYDM_DBG(dm, DBG_PATH_DIV,
  313. " [Be disconnected]----->\n");
  314. dm_path_div->is_become_linked = dm->is_linked;
  315. }
  316. return;
  317. } else {
  318. if (dm_path_div->is_become_linked == false) {
  319. PHYDM_DBG(dm, DBG_PATH_DIV, " [Be Linked !!!]----->\n");
  320. dm_path_div->is_become_linked = dm->is_linked;
  321. }
  322. }
  323. /* @2 [period CTRL] */
  324. if (dm_path_div->dtp_period >= 2)
  325. dm_path_div->dtp_period = 0;
  326. else {
  327. #if 0
  328. /* PHYDM_DBG(dm,DBG_PATH_DIV, "Phydm_Dynamic_Tx_Path_8814A() Stay = (( %d ))\n",dm_path_div->dtp_period); */
  329. #endif
  330. dm_path_div->dtp_period++;
  331. return;
  332. }
  333. /* @2 [Fix path] */
  334. if (dm->path_select != PHYDM_AUTO_PATH)
  335. return;
  336. /* @2 [Check Bfer] */
  337. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  338. #if (BEAMFORMING_SUPPORT == 1)
  339. {
  340. enum beamforming_cap beamform_cap = (dm->beamforming_info.beamform_cap);
  341. if (beamform_cap & BEAMFORMER_CAP) { /* @BFmer On && Div On->Div Off */
  342. if (dm_path_div->fix_path_bfer == 0) {
  343. PHYDM_DBG(dm, DBG_PATH_DIV,
  344. "[ PathDiv : OFF ] BFmer ==1\n");
  345. dm_path_div->fix_path_bfer = 1;
  346. }
  347. return;
  348. } else { /* @BFmer Off && Div Off->Div On */
  349. if (dm_path_div->fix_path_bfer == 1) {
  350. PHYDM_DBG(dm, DBG_PATH_DIV,
  351. "[ PathDiv : ON ] BFmer ==0\n");
  352. dm_path_div->fix_path_bfer = 0;
  353. }
  354. }
  355. }
  356. #endif
  357. #endif
  358. if (dm_path_div->use_path_a_as_default_ant == 1) {
  359. phydm_find_default_path(dm);
  360. phydm_candidate_dtp_update(dm);
  361. } else {
  362. if (dm_path_div->phydm_dtp_state == PHYDM_DTP_INIT) {
  363. phydm_find_default_path(dm);
  364. phydm_candidate_dtp_update(dm);
  365. dm_path_div->phydm_dtp_state = PHYDM_DTP_RUNNING_1;
  366. }
  367. else if (dm_path_div->phydm_dtp_state == PHYDM_DTP_RUNNING_1) {
  368. dm_path_div->dtp_check_patha_counter++;
  369. if (dm_path_div->dtp_check_patha_counter >= NUM_RESET_DTP_PERIOD) {
  370. dm_path_div->dtp_check_patha_counter = 0;
  371. dm_path_div->phydm_dtp_state = PHYDM_DTP_INIT;
  372. }
  373. #if 0
  374. /* @2 Search space update */
  375. else {
  376. /* @1. find the worst candidate */
  377. /* @2. repalce the worst candidate */
  378. }
  379. #endif
  380. }
  381. }
  382. /* @2 Dynamic path Selection H2C */
  383. if (dm_path_div->num_candidate == 1)
  384. return;
  385. else {
  386. h2c_parameter[0] = dm_path_div->num_candidate;
  387. h2c_parameter[1] = dm_path_div->num_tx_path;
  388. h2c_parameter[2] = dm_path_div->ant_candidate_1;
  389. h2c_parameter[3] = dm_path_div->ant_candidate_2;
  390. h2c_parameter[4] = dm_path_div->ant_candidate_3;
  391. odm_fill_h2c_cmd(dm, PHYDM_H2C_DYNAMIC_TX_PATH, 6, h2c_parameter);
  392. }
  393. }
  394. void phydm_dynamic_tx_path_init(
  395. void *dm_void)
  396. {
  397. struct dm_struct *dm = (struct dm_struct *)dm_void;
  398. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  399. void *adapter = dm->adapter;
  400. u8 search_space_2[NUM_CHOOSE2_FROM4] = {BB_PATH_AB, BB_PATH_AC, BB_PATH_AD, BB_PATH_BC, BB_PATH_BD, BB_PATH_CD};
  401. u8 search_space_3[NUM_CHOOSE3_FROM4] = {BB_PATH_BCD, BB_PATH_ACD, BB_PATH_ABD, BB_PATH_ABC};
  402. #if ((DM_ODM_SUPPORT_TYPE == ODM_WIN) && USB_SWITCH_SUPPORT)
  403. dm_path_div->is_u3_mode = (*dm->hub_usb_mode == 2) ? 1 : 0;
  404. PHYDM_DBG(dm, DBG_PATH_DIV, "[WIN USB] is_u3_mode = (( %d ))\n",
  405. dm_path_div->is_u3_mode);
  406. #else
  407. dm_path_div->is_u3_mode = 1;
  408. #endif
  409. PHYDM_DBG(dm, DBG_PATH_DIV, "Dynamic TX path Init 8814\n");
  410. memcpy(&dm_path_div->search_space_2[0], &search_space_2[0],
  411. NUM_CHOOSE2_FROM4);
  412. memcpy(&dm_path_div->search_space_3[0], &search_space_3[0],
  413. NUM_CHOOSE3_FROM4);
  414. dm_path_div->use_path_a_as_default_ant = 1;
  415. dm_path_div->phydm_dtp_state = PHYDM_DTP_INIT;
  416. dm->path_select = PHYDM_AUTO_PATH;
  417. dm_path_div->phydm_path_div_type = PHYDM_4R_PATH_DIV;
  418. if (dm_path_div->is_u3_mode) {
  419. dm_path_div->num_tx_path = 3;
  420. phydm_dtp_fix_tx_path(dm, BB_PATH_BCD); /* @3TX Set Init TX path*/
  421. } else {
  422. dm_path_div->num_tx_path = 2;
  423. phydm_dtp_fix_tx_path(dm, BB_PATH_BC); /* @2TX // Set Init TX path*/
  424. }
  425. }
  426. void phydm_process_rssi_for_path_div(
  427. void *dm_void,
  428. void *phy_info_void,
  429. void *pkt_info_void)
  430. {
  431. struct dm_struct *dm = (struct dm_struct *)dm_void;
  432. struct phydm_phyinfo_struct *phy_info = (struct phydm_phyinfo_struct *)phy_info_void;
  433. struct phydm_perpkt_info_struct *pktinfo = (struct phydm_perpkt_info_struct *)pkt_info_void;
  434. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  435. if (!(pktinfo->is_packet_to_self || pktinfo->is_packet_match_bssid))
  436. return;
  437. if (pktinfo->data_rate <= ODM_RATE11M)
  438. return;
  439. if (dm_path_div->phydm_path_div_type == PHYDM_4R_PATH_DIV) {
  440. #if RTL8814A_SUPPORT
  441. if (dm->support_ic_type & ODM_RTL8814A) {
  442. dm_path_div->path_a_sum_all += phy_info->rx_mimo_signal_strength[0];
  443. dm_path_div->path_a_cnt_all++;
  444. dm_path_div->path_b_sum_all += phy_info->rx_mimo_signal_strength[1];
  445. dm_path_div->path_b_cnt_all++;
  446. dm_path_div->path_c_sum_all += phy_info->rx_mimo_signal_strength[2];
  447. dm_path_div->path_c_cnt_all++;
  448. dm_path_div->path_d_sum_all += phy_info->rx_mimo_signal_strength[3];
  449. dm_path_div->path_d_cnt_all++;
  450. }
  451. #endif
  452. } else {
  453. dm_path_div->path_a_sum[pktinfo->station_id] += phy_info->rx_mimo_signal_strength[0];
  454. dm_path_div->path_a_cnt[pktinfo->station_id]++;
  455. dm_path_div->path_b_sum[pktinfo->station_id] += phy_info->rx_mimo_signal_strength[1];
  456. dm_path_div->path_b_cnt[pktinfo->station_id]++;
  457. }
  458. }
  459. #endif /* @#if RTL8814A_SUPPORT */
  460. void phydm_pathdiv_debug(void *dm_void, char input[][16], u32 *_used,
  461. char *output, u32 *_out_len)
  462. {
  463. struct dm_struct *dm = (struct dm_struct *)dm_void;
  464. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  465. u32 used = *_used;
  466. u32 out_len = *_out_len;
  467. u32 dm_value[10] = {0};
  468. u8 i, input_idx = 0;
  469. for (i = 0; i < 5; i++) {
  470. if (input[i + 1]) {
  471. PHYDM_SSCANF(input[i + 1], DCMD_HEX, &dm_value[i]);
  472. input_idx++;
  473. }
  474. }
  475. if (input_idx == 0)
  476. return;
  477. dm->path_select = (dm_value[0] & 0xf);
  478. PDM_SNPF(out_len, used, output + used, out_len - used,
  479. "Path_select = (( 0x%x ))\n", dm->path_select);
  480. /* @2 [Fix path] */
  481. if (dm->path_select != PHYDM_AUTO_PATH) {
  482. PDM_SNPF(out_len, used, output + used, out_len - used,
  483. "Trun on path [%s%s%s%s]\n",
  484. ((dm->path_select) & 0x1) ? "A" : "",
  485. ((dm->path_select) & 0x2) ? "B" : "",
  486. ((dm->path_select) & 0x4) ? "C" : "",
  487. ((dm->path_select) & 0x8) ? "D" : "");
  488. phydm_dtp_fix_tx_path(dm, dm->path_select);
  489. } else
  490. PDM_SNPF(out_len, used, output + used, out_len - used, "%s\n",
  491. "Auto path");
  492. *_used = used;
  493. *_out_len = out_len;
  494. }
  495. void phydm_c2h_dtp_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
  496. {
  497. struct dm_struct *dm = (struct dm_struct *)dm_void;
  498. struct _ODM_PATH_DIVERSITY_ *dm_path_div = &dm->dm_path_div;
  499. u8 macid = cmd_buf[0];
  500. u8 target = cmd_buf[1];
  501. u8 nsc_1 = cmd_buf[2];
  502. u8 nsc_2 = cmd_buf[3];
  503. u8 nsc_3 = cmd_buf[4];
  504. PHYDM_DBG(dm, DBG_PATH_DIV, "Target_candidate = (( %d ))\n", target);
  505. /*@
  506. if( (nsc_1 >= nsc_2) && (nsc_1 >= nsc_3))
  507. {
  508. phydm_dtp_fix_tx_path(dm, dm_path_div->ant_candidate_1);
  509. }
  510. else if( nsc_2 >= nsc_3)
  511. {
  512. phydm_dtp_fix_tx_path(dm, dm_path_div->ant_candidate_2);
  513. }
  514. else
  515. {
  516. phydm_dtp_fix_tx_path(dm, dm_path_div->ant_candidate_3);
  517. }
  518. */
  519. }
  520. void odm_path_diversity(void *dm_void)
  521. {
  522. struct dm_struct *dm = (struct dm_struct *)dm_void;
  523. if (!(dm->support_ability & ODM_BB_PATH_DIV)) {
  524. PHYDM_DBG(dm, DBG_PATH_DIV, "Return: Not Support PathDiv\n");
  525. return;
  526. }
  527. #if RTL8812A_SUPPORT
  528. if (dm->support_ic_type & ODM_RTL8812)
  529. odm_path_diversity_8812a(dm);
  530. #endif
  531. #if RTL8814A_SUPPORT
  532. if (dm->support_ic_type & ODM_RTL8814A)
  533. phydm_dynamic_tx_path(dm);
  534. #endif
  535. }
  536. void phydm_path_diversity_init(void *dm_void)
  537. {
  538. struct dm_struct *dm = (struct dm_struct *)dm_void;
  539. if (*dm->mp_mode)
  540. return;
  541. if (!(dm->support_ability & ODM_BB_PATH_DIV)) {
  542. PHYDM_DBG(dm, DBG_PATH_DIV, "Return: Not Support PathDiv\n");
  543. return;
  544. }
  545. #if RTL8812A_SUPPORT
  546. if (dm->support_ic_type & ODM_RTL8812)
  547. odm_path_diversity_init_8812a(dm);
  548. #endif
  549. #if RTL8814A_SUPPORT
  550. if (dm->support_ic_type & ODM_RTL8814A)
  551. phydm_dynamic_tx_path_init(dm);
  552. #endif
  553. }
  554. #endif /* @#ifdef CONFIG_PATH_DIVERSITY */