summaryrefslogtreecommitdiff
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e97d036cde70..3970224b3b09 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2083,6 +2083,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
BT_INFO("%s: Found device firmware: %s", hdev->name, fwname);
+ /* Save the DDC file name for later use to apply once the firmware
+ * downloading is done.
+ */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
+ le16_to_cpu(params->dev_revid));
+
kfree_skb(skb);
if (fw->size < 644) {
@@ -2244,6 +2250,43 @@ done:
clear_bit(BTUSB_BOOTLOADER, &data->flags);
+ /* Once the device is running in operational mode, it needs to apply
+ * the device configuration (DDC) parameters.
+ *
+ * The device can work without DDC parameters, so even if it fails
+ * to load the file, no need to fail the setup.
+ */
+ err = request_firmware_direct(&fw, fwname, &hdev->dev);
+ if (err < 0)
+ return 0;
+
+ BT_INFO("%s: Found Intel DDC parameters: %s", hdev->name, fwname);
+
+ fw_ptr = fw->data;
+
+ /* DDC file contains one or more DDC structure which has
+ * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
+ */
+ while (fw->size > fw_ptr - fw->data) {
+ u8 cmd_plen = fw_ptr[0] + sizeof(u8);
+
+ skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: Failed to send Intel_Write_DDC (%ld)",
+ hdev->name, PTR_ERR(skb));
+ release_firmware(fw);
+ return PTR_ERR(skb);
+ }
+
+ fw_ptr += cmd_plen;
+ kfree_skb(skb);
+ }
+
+ release_firmware(fw);
+
+ BT_INFO("%s: Applying Intel DDC parameters completed", hdev->name);
+
return 0;
}