diff options
Diffstat (limited to 'drivers/bluetooth/btbcm.c')
-rw-r--r-- | drivers/bluetooth/btbcm.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 124ef0a3e1dd..1f498f358f60 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -23,6 +23,8 @@ #define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) +#define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}}) +#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}}) #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) int btbcm_check_bdaddr(struct hci_dev *hdev) @@ -34,6 +36,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { int err = PTR_ERR(skb); + bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err); return err; } @@ -73,6 +76,8 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) !bacmp(&bda->bdaddr, BDADDR_BCM2076B1) || !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) || + !bacmp(&bda->bdaddr, BDADDR_BCM4334B0) || + !bacmp(&bda->bdaddr, BDADDR_BCM4345C5) || !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) || !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) { bt_dev_info(hdev, "BCM: Using default device address (%pMR)", @@ -103,6 +108,52 @@ int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) } EXPORT_SYMBOL_GPL(btbcm_set_bdaddr); +int btbcm_read_pcm_int_params(struct hci_dev *hdev, + struct bcm_set_pcm_int_params *params) +{ + struct sk_buff *skb; + int err = 0; + + skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err); + return err; + } + + if (skb->len != 6 || skb->data[0]) { + bt_dev_err(hdev, "BCM: Read PCM int params length mismatch"); + kfree_skb(skb); + return -EIO; + } + + if (params) + memcpy(params, skb->data + 1, 5); + + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params); + +int btbcm_write_pcm_int_params(struct hci_dev *hdev, + const struct bcm_set_pcm_int_params *params) +{ + struct sk_buff *skb; + int err; + + skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err); + return err; + } + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params); + int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) { const struct hci_command_hdr *cmd; @@ -173,6 +224,7 @@ static int btbcm_reset(struct hci_dev *hdev) skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { int err = PTR_ERR(skb); + bt_dev_err(hdev, "BCM: Reset failed (%d)", err); return err; } @@ -324,6 +376,7 @@ struct bcm_subver_table { static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x4103, "BCM4330B1" }, /* 002.001.003 */ + { 0x410d, "BCM4334B0" }, /* 002.001.013 */ { 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x4204, "BCM2076B1" }, /* 002.002.004 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */ @@ -332,10 +385,12 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x2122, "BCM4343A0" }, /* 001.001.034 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x6119, "BCM4345C0" }, /* 003.001.025 */ + { 0x6606, "BCM4345C5" }, /* 003.006.006 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */ { 0x6106, "BCM4359C0" }, /* 003.001.006 */ + { 0x4106, "BCM4335A0" }, /* 002.001.006 */ { } }; @@ -437,6 +492,12 @@ int btbcm_finalize(struct hci_dev *hdev) set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + /* Some devices ship with the controller default address. + * Allow the bootloader to set a valid address through the + * device tree. + */ + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + return 0; } EXPORT_SYMBOL_GPL(btbcm_finalize); |