Skip to content

Commit e036afb

Browse files
satijavVudentz
authored andcommitted
Bluetooth: btintel: Add support to configure TX power
BRDS - Bluetooth Regulatory Domain Specific absorption rate Bluetooth has regulatory limitations which prohibit or allow usage of certain bands or channels as well as limiting Tx power. The Tx power values can be configured in ACPI table. This patch reads from ACPI entry configures the controller accordingly. Signed-off-by: Kiran K <[email protected]> Signed-off-by: Vijay Satija <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 6ac4233 commit e036afb

File tree

2 files changed

+356
-0
lines changed

2 files changed

+356
-0
lines changed

drivers/bluetooth/btintel.c

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ enum {
3535
DSM_SET_RESET_METHOD = 3,
3636
};
3737

38+
#define BTINTEL_BT_DOMAIN 0x12
39+
#define BTINTEL_SAR_LEGACY 0
40+
#define BTINTEL_SAR_INC_PWR 1
41+
#define BTINTEL_SAR_INC_PWR_SUPPORTED 0
42+
3843
#define CMD_WRITE_BOOT_PARAMS 0xfc0e
3944
struct cmd_write_boot_params {
4045
__le32 boot_addr;
@@ -2806,6 +2811,331 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
28062811
return 0;
28072812
}
28082813

2814+
#ifdef CONFIG_ACPI
2815+
static acpi_status btintel_evaluate_acpi_method(struct hci_dev *hdev,
2816+
acpi_string method,
2817+
union acpi_object **ptr,
2818+
u8 pkg_size)
2819+
{
2820+
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
2821+
union acpi_object *p;
2822+
acpi_status status;
2823+
acpi_handle handle;
2824+
2825+
handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
2826+
if (!handle) {
2827+
bt_dev_dbg(hdev, "ACPI-BT: No ACPI support for Bluetooth device");
2828+
return AE_NOT_EXIST;
2829+
}
2830+
2831+
status = acpi_evaluate_object(handle, method, NULL, &buffer);
2832+
2833+
if (ACPI_FAILURE(status)) {
2834+
bt_dev_dbg(hdev, "ACPI-BT: ACPI Failure: %s method: %s",
2835+
acpi_format_exception(status), method);
2836+
return status;
2837+
}
2838+
2839+
p = buffer.pointer;
2840+
2841+
if (p->type != ACPI_TYPE_PACKAGE || p->package.count < pkg_size) {
2842+
bt_dev_warn(hdev, "ACPI-BT: Invalid object type: %d or package count: %d",
2843+
p->type, p->package.count);
2844+
kfree(buffer.pointer);
2845+
return AE_ERROR;
2846+
}
2847+
2848+
*ptr = buffer.pointer;
2849+
return 0;
2850+
}
2851+
2852+
static union acpi_object *btintel_acpi_get_bt_pkg(union acpi_object *buffer)
2853+
{
2854+
union acpi_object *domain, *bt_pkg;
2855+
int i;
2856+
2857+
for (i = 1; i < buffer->package.count; i++) {
2858+
bt_pkg = &buffer->package.elements[i];
2859+
domain = &bt_pkg->package.elements[0];
2860+
if (domain->type == ACPI_TYPE_INTEGER &&
2861+
domain->integer.value == BTINTEL_BT_DOMAIN)
2862+
return bt_pkg;
2863+
}
2864+
return ERR_PTR(-ENOENT);
2865+
}
2866+
2867+
static int btintel_send_sar_ddc(struct hci_dev *hdev, struct btintel_cp_ddc_write *data, u8 len)
2868+
{
2869+
struct sk_buff *skb;
2870+
2871+
skb = __hci_cmd_sync(hdev, 0xfc8b, len, data, HCI_CMD_TIMEOUT);
2872+
if (IS_ERR(skb)) {
2873+
bt_dev_warn(hdev, "Failed to send sar ddc id:0x%4.4x (%ld)",
2874+
le16_to_cpu(data->id), PTR_ERR(skb));
2875+
return PTR_ERR(skb);
2876+
}
2877+
kfree_skb(skb);
2878+
return 0;
2879+
}
2880+
2881+
static int btintel_send_edr(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2882+
int id, struct btintel_sar_inc_pwr *sar)
2883+
{
2884+
cmd->len = 5;
2885+
cmd->id = cpu_to_le16(id);
2886+
cmd->data[0] = sar->br >> 3;
2887+
cmd->data[1] = sar->edr2 >> 3;
2888+
cmd->data[2] = sar->edr3 >> 3;
2889+
return btintel_send_sar_ddc(hdev, cmd, 6);
2890+
}
2891+
2892+
static int btintel_send_le(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2893+
int id, struct btintel_sar_inc_pwr *sar)
2894+
{
2895+
cmd->len = 3;
2896+
cmd->id = cpu_to_le16(id);
2897+
cmd->data[0] = min3(sar->le, sar->le_lr, sar->le_2mhz) >> 3;
2898+
return btintel_send_sar_ddc(hdev, cmd, 4);
2899+
}
2900+
2901+
static int btintel_send_br(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2902+
int id, struct btintel_sar_inc_pwr *sar)
2903+
{
2904+
cmd->len = 3;
2905+
cmd->id = cpu_to_le16(id);
2906+
cmd->data[0] = sar->br >> 3;
2907+
return btintel_send_sar_ddc(hdev, cmd, 4);
2908+
}
2909+
2910+
static int btintel_send_br_mutual(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2911+
int id, struct btintel_sar_inc_pwr *sar)
2912+
{
2913+
cmd->len = 3;
2914+
cmd->id = cpu_to_le16(id);
2915+
cmd->data[0] = sar->br;
2916+
return btintel_send_sar_ddc(hdev, cmd, 4);
2917+
}
2918+
2919+
static int btintel_send_edr2(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2920+
int id, struct btintel_sar_inc_pwr *sar)
2921+
{
2922+
cmd->len = 3;
2923+
cmd->id = cpu_to_le16(id);
2924+
cmd->data[0] = sar->edr2;
2925+
return btintel_send_sar_ddc(hdev, cmd, 4);
2926+
}
2927+
2928+
static int btintel_send_edr3(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
2929+
int id, struct btintel_sar_inc_pwr *sar)
2930+
{
2931+
cmd->len = 3;
2932+
cmd->id = cpu_to_le16(id);
2933+
cmd->data[0] = sar->edr3;
2934+
return btintel_send_sar_ddc(hdev, cmd, 4);
2935+
}
2936+
2937+
static int btintel_set_legacy_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar)
2938+
{
2939+
struct btintel_cp_ddc_write *cmd;
2940+
u8 buffer[64];
2941+
int ret;
2942+
2943+
cmd = (void *)buffer;
2944+
ret = btintel_send_br(hdev, cmd, 0x0131, sar);
2945+
if (ret)
2946+
return ret;
2947+
2948+
ret = btintel_send_br(hdev, cmd, 0x0132, sar);
2949+
if (ret)
2950+
return ret;
2951+
2952+
ret = btintel_send_le(hdev, cmd, 0x0133, sar);
2953+
if (ret)
2954+
return ret;
2955+
2956+
ret = btintel_send_edr(hdev, cmd, 0x0137, sar);
2957+
if (ret)
2958+
return ret;
2959+
2960+
ret = btintel_send_edr(hdev, cmd, 0x0138, sar);
2961+
if (ret)
2962+
return ret;
2963+
2964+
ret = btintel_send_edr(hdev, cmd, 0x013b, sar);
2965+
if (ret)
2966+
return ret;
2967+
2968+
ret = btintel_send_edr(hdev, cmd, 0x013c, sar);
2969+
2970+
return ret;
2971+
}
2972+
2973+
static int btintel_set_mutual_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar)
2974+
{
2975+
struct btintel_cp_ddc_write *cmd;
2976+
struct sk_buff *skb;
2977+
u8 buffer[64];
2978+
bool enable;
2979+
int ret;
2980+
2981+
cmd = (void *)buffer;
2982+
2983+
cmd->len = 3;
2984+
cmd->id = cpu_to_le16(0x019e);
2985+
2986+
if (sar->revision == BTINTEL_SAR_INC_PWR &&
2987+
sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED)
2988+
cmd->data[0] = 0x01;
2989+
else
2990+
cmd->data[0] = 0x00;
2991+
2992+
ret = btintel_send_sar_ddc(hdev, cmd, 4);
2993+
if (ret)
2994+
return ret;
2995+
2996+
if (sar->revision == BTINTEL_SAR_INC_PWR &&
2997+
sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED) {
2998+
cmd->len = 3;
2999+
cmd->id = cpu_to_le16(0x019f);
3000+
cmd->data[0] = sar->sar_2400_chain_a;
3001+
3002+
ret = btintel_send_sar_ddc(hdev, cmd, 4);
3003+
if (ret)
3004+
return ret;
3005+
}
3006+
3007+
ret = btintel_send_br_mutual(hdev, cmd, 0x01a0, sar);
3008+
if (ret)
3009+
return ret;
3010+
3011+
ret = btintel_send_edr2(hdev, cmd, 0x01a1, sar);
3012+
if (ret)
3013+
return ret;
3014+
3015+
ret = btintel_send_edr3(hdev, cmd, 0x01a2, sar);
3016+
if (ret)
3017+
return ret;
3018+
3019+
ret = btintel_send_le(hdev, cmd, 0x01a3, sar);
3020+
if (ret)
3021+
return ret;
3022+
3023+
enable = true;
3024+
skb = __hci_cmd_sync(hdev, 0xfe25, 1, &enable, HCI_CMD_TIMEOUT);
3025+
if (IS_ERR(skb)) {
3026+
bt_dev_warn(hdev, "Failed to send Intel SAR Enable (%ld)", PTR_ERR(skb));
3027+
return PTR_ERR(skb);
3028+
}
3029+
3030+
kfree_skb(skb);
3031+
return 0;
3032+
}
3033+
3034+
static int btintel_sar_send_to_device(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar,
3035+
struct intel_version_tlv *ver)
3036+
{
3037+
u16 cnvi, cnvr;
3038+
int ret;
3039+
3040+
cnvi = ver->cnvi_top & 0xfff;
3041+
cnvr = ver->cnvr_top & 0xfff;
3042+
3043+
if (cnvi < BTINTEL_CNVI_BLAZARI && cnvr < BTINTEL_CNVR_FMP2) {
3044+
bt_dev_info(hdev, "Applying legacy Bluetooth SAR");
3045+
ret = btintel_set_legacy_sar(hdev, sar);
3046+
} else if (cnvi == BTINTEL_CNVI_GAP || cnvr == BTINTEL_CNVR_FMP2) {
3047+
bt_dev_info(hdev, "Applying mutual Bluetooth SAR");
3048+
ret = btintel_set_mutual_sar(hdev, sar);
3049+
} else {
3050+
ret = -EOPNOTSUPP;
3051+
}
3052+
3053+
return ret;
3054+
}
3055+
3056+
static int btintel_acpi_set_sar(struct hci_dev *hdev, struct intel_version_tlv *ver)
3057+
{
3058+
union acpi_object *bt_pkg, *buffer = NULL;
3059+
struct btintel_sar_inc_pwr sar;
3060+
acpi_status status;
3061+
u8 revision;
3062+
int ret;
3063+
3064+
status = btintel_evaluate_acpi_method(hdev, "BRDS", &buffer, 2);
3065+
if (ACPI_FAILURE(status))
3066+
return -ENOENT;
3067+
3068+
bt_pkg = btintel_acpi_get_bt_pkg(buffer);
3069+
3070+
if (IS_ERR(bt_pkg)) {
3071+
ret = PTR_ERR(bt_pkg);
3072+
goto error;
3073+
}
3074+
3075+
if (!bt_pkg->package.count) {
3076+
ret = -EINVAL;
3077+
goto error;
3078+
}
3079+
3080+
revision = buffer->package.elements[0].integer.value;
3081+
3082+
if (revision > BTINTEL_SAR_INC_PWR) {
3083+
bt_dev_dbg(hdev, "BT_SAR: revision: 0x%2.2x not supported", revision);
3084+
ret = -EOPNOTSUPP;
3085+
goto error;
3086+
}
3087+
3088+
memset(&sar, 0, sizeof(sar));
3089+
3090+
if (revision == BTINTEL_SAR_LEGACY && bt_pkg->package.count == 8) {
3091+
sar.revision = revision;
3092+
sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value;
3093+
sar.br = bt_pkg->package.elements[2].integer.value;
3094+
sar.edr2 = bt_pkg->package.elements[3].integer.value;
3095+
sar.edr3 = bt_pkg->package.elements[4].integer.value;
3096+
sar.le = bt_pkg->package.elements[5].integer.value;
3097+
sar.le_2mhz = bt_pkg->package.elements[6].integer.value;
3098+
sar.le_lr = bt_pkg->package.elements[7].integer.value;
3099+
3100+
} else if (revision == BTINTEL_SAR_INC_PWR && bt_pkg->package.count == 10) {
3101+
sar.revision = revision;
3102+
sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value;
3103+
sar.inc_power_mode = bt_pkg->package.elements[2].integer.value;
3104+
sar.sar_2400_chain_a = bt_pkg->package.elements[3].integer.value;
3105+
sar.br = bt_pkg->package.elements[4].integer.value;
3106+
sar.edr2 = bt_pkg->package.elements[5].integer.value;
3107+
sar.edr3 = bt_pkg->package.elements[6].integer.value;
3108+
sar.le = bt_pkg->package.elements[7].integer.value;
3109+
sar.le_2mhz = bt_pkg->package.elements[8].integer.value;
3110+
sar.le_lr = bt_pkg->package.elements[9].integer.value;
3111+
} else {
3112+
ret = -EINVAL;
3113+
goto error;
3114+
}
3115+
3116+
/* Apply only if it is enabled in BIOS */
3117+
if (sar.bt_sar_bios != 1) {
3118+
bt_dev_dbg(hdev, "Bluetooth SAR is not enabled");
3119+
ret = -EOPNOTSUPP;
3120+
goto error;
3121+
}
3122+
3123+
ret = btintel_sar_send_to_device(hdev, &sar, ver);
3124+
error:
3125+
kfree(buffer);
3126+
return ret;
3127+
}
3128+
#endif /* CONFIG_ACPI */
3129+
3130+
static int btintel_set_specific_absorption_rate(struct hci_dev *hdev,
3131+
struct intel_version_tlv *ver)
3132+
{
3133+
#ifdef CONFIG_ACPI
3134+
return btintel_acpi_set_sar(hdev, ver);
3135+
#endif
3136+
return 0;
3137+
}
3138+
28093139
int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
28103140
struct intel_version_tlv *ver)
28113141
{
@@ -2883,6 +3213,9 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
28833213

28843214
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
28853215

3216+
/* Send sar values to controller */
3217+
btintel_set_specific_absorption_rate(hdev, ver);
3218+
28863219
/* Set PPAG feature */
28873220
btintel_set_ppag(hdev, ver);
28883221

drivers/bluetooth/btintel.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ struct intel_tlv {
5858
#define BTINTEL_CNVI_BLAZARU 0x930
5959
#define BTINTEL_CNVI_SCP 0xA00
6060

61+
/* CNVR */
62+
#define BTINTEL_CNVR_FMP2 0x910
63+
6164
#define BTINTEL_IMG_BOOTLOADER 0x01 /* Bootloader image */
6265
#define BTINTEL_IMG_IML 0x02 /* Intermediate image */
6366
#define BTINTEL_IMG_OP 0x03 /* Operational image */
@@ -165,6 +168,26 @@ struct hci_ppag_enable_cmd {
165168
#define INTEL_TLV_DEBUG_EXCEPTION 0x02
166169
#define INTEL_TLV_TEST_EXCEPTION 0xDE
167170

171+
struct btintel_cp_ddc_write {
172+
u8 len;
173+
__le16 id;
174+
u8 data[];
175+
} __packed;
176+
177+
/* Bluetooth SAR feature (BRDS), Revision 1 */
178+
struct btintel_sar_inc_pwr {
179+
u8 revision;
180+
u32 bt_sar_bios; /* Mode of SAR control to be used, 1:enabled in bios */
181+
u32 inc_power_mode; /* Increased power mode */
182+
u8 sar_2400_chain_a; /* Sar power restriction LB */
183+
u8 br;
184+
u8 edr2;
185+
u8 edr3;
186+
u8 le;
187+
u8 le_2mhz;
188+
u8 le_lr;
189+
};
190+
168191
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
169192
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
170193
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)

0 commit comments

Comments
 (0)