sar.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2. /* Copyright(c) 2018-2021 Realtek Corporation
  3. */
  4. #include "sar.h"
  5. #include "phy.h"
  6. #include "debug.h"
  7. s8 rtw_query_sar(struct rtw_dev *rtwdev, const struct rtw_sar_arg *arg)
  8. {
  9. const struct rtw_hal *hal = &rtwdev->hal;
  10. const struct rtw_sar *sar = &hal->sar;
  11. switch (sar->src) {
  12. default:
  13. rtw_warn(rtwdev, "unknown SAR source: %d\n", sar->src);
  14. fallthrough;
  15. case RTW_SAR_SOURCE_NONE:
  16. return (s8)rtwdev->chip->max_power_index;
  17. case RTW_SAR_SOURCE_COMMON:
  18. return sar->cfg[arg->path][arg->rs].common[arg->sar_band];
  19. }
  20. }
  21. static int rtw_apply_sar(struct rtw_dev *rtwdev, const struct rtw_sar *new)
  22. {
  23. struct rtw_hal *hal = &rtwdev->hal;
  24. struct rtw_sar *sar = &hal->sar;
  25. if (sar->src != RTW_SAR_SOURCE_NONE && new->src != sar->src) {
  26. rtw_warn(rtwdev, "SAR source: %d is in use\n", sar->src);
  27. return -EBUSY;
  28. }
  29. *sar = *new;
  30. rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
  31. return 0;
  32. }
  33. static s8 rtw_sar_to_phy(struct rtw_dev *rtwdev, u8 fct, s32 sar,
  34. const struct rtw_sar_arg *arg)
  35. {
  36. struct rtw_hal *hal = &rtwdev->hal;
  37. u8 txgi = rtwdev->chip->txgi_factor;
  38. u8 max = rtwdev->chip->max_power_index;
  39. s32 tmp;
  40. s8 base;
  41. tmp = fct > txgi ? sar >> (fct - txgi) : sar << (txgi - fct);
  42. base = arg->sar_band == RTW_SAR_BAND_0 ?
  43. hal->tx_pwr_by_rate_base_2g[arg->path][arg->rs] :
  44. hal->tx_pwr_by_rate_base_5g[arg->path][arg->rs];
  45. return (s8)clamp_t(s32, tmp, -max - 1, max) - base;
  46. }
  47. static const struct cfg80211_sar_freq_ranges rtw_common_sar_freq_ranges[] = {
  48. [RTW_SAR_BAND_0] = { .start_freq = 2412, .end_freq = 2484, },
  49. [RTW_SAR_BAND_1] = { .start_freq = 5180, .end_freq = 5320, },
  50. [RTW_SAR_BAND_3] = { .start_freq = 5500, .end_freq = 5720, },
  51. [RTW_SAR_BAND_4] = { .start_freq = 5745, .end_freq = 5825, },
  52. };
  53. static_assert(ARRAY_SIZE(rtw_common_sar_freq_ranges) == RTW_SAR_BAND_NR);
  54. const struct cfg80211_sar_capa rtw_sar_capa = {
  55. .type = NL80211_SAR_TYPE_POWER,
  56. .num_freq_ranges = RTW_SAR_BAND_NR,
  57. .freq_ranges = rtw_common_sar_freq_ranges,
  58. };
  59. int rtw_set_sar_specs(struct rtw_dev *rtwdev,
  60. const struct cfg80211_sar_specs *sar)
  61. {
  62. struct rtw_sar_arg arg = {0};
  63. struct rtw_sar new = {0};
  64. u32 idx, i, j, k;
  65. s32 power;
  66. s8 val;
  67. if (sar->type != NL80211_SAR_TYPE_POWER)
  68. return -EINVAL;
  69. memset(&new, rtwdev->chip->max_power_index, sizeof(new));
  70. new.src = RTW_SAR_SOURCE_COMMON;
  71. for (i = 0; i < sar->num_sub_specs; i++) {
  72. idx = sar->sub_specs[i].freq_range_index;
  73. if (idx >= RTW_SAR_BAND_NR)
  74. return -EINVAL;
  75. power = sar->sub_specs[i].power;
  76. rtw_dbg(rtwdev, RTW_DBG_REGD, "On freq %u to %u, set SAR %d in 1/%lu dBm\n",
  77. rtw_common_sar_freq_ranges[idx].start_freq,
  78. rtw_common_sar_freq_ranges[idx].end_freq,
  79. power, BIT(RTW_COMMON_SAR_FCT));
  80. for (j = 0; j < RTW_RF_PATH_MAX; j++) {
  81. for (k = 0; k < RTW_RATE_SECTION_MAX; k++) {
  82. arg = (struct rtw_sar_arg){
  83. .sar_band = idx,
  84. .path = j,
  85. .rs = k,
  86. };
  87. val = rtw_sar_to_phy(rtwdev, RTW_COMMON_SAR_FCT,
  88. power, &arg);
  89. new.cfg[j][k].common[idx] = val;
  90. }
  91. }
  92. }
  93. return rtw_apply_sar(rtwdev, &new);
  94. }