Skip to content

Commit

Permalink
Bluetooth: mt7921s: Support wake on bluetooth
Browse files Browse the repository at this point in the history
Enable wake on bluetooth on mt7921s that can be supported since the
firmware with version 20211129211059 was added, and the patch would
not cause any harm even when the old firmware is applied.

The patch was tested by setting up an HID or HOGP profile to connect a
Bluetooth keyboard and mouse, then putting the system to suspend, then
trying to wake up the system by moving the Bluetooth keyboard or mouse,
and then checking if the system can wake up and be brought back to
the normal state.

Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Mark Chen <mark-yw.chen@mediatek.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Mark Chen authored and Marcel Holtmann committed Jan 10, 2022
1 parent 4b68587 commit ce64b3e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
8 changes: 8 additions & 0 deletions drivers/bluetooth/btmtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ struct btmtk_tci_sleep {
u8 time_compensation;
} __packed;

struct btmtk_wakeon {
u8 mode;
u8 gpo;
u8 active_high;
__le16 enable_delay;
__le16 wakeup_delay;
} __packed;

struct btmtk_hci_wmt_params {
u8 op;
u8 flag;
Expand Down
33 changes: 32 additions & 1 deletion drivers/bluetooth/btmtksdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,32 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}

static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
bool may_wakeup = device_may_wakeup(bdev->dev);
const struct btmtk_wakeon bt_awake = {
.mode = 0x1,
.gpo = 0,
.active_high = 0x1,
.enable_delay = cpu_to_le16(0xc80),
.wakeup_delay = cpu_to_le16(0x20),
};

if (may_wakeup && bdev->data->chipid == 0x7921) {
struct sk_buff *skb;

skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake),
&bt_awake, HCI_CMD_TIMEOUT);
if (IS_ERR(skb))
may_wakeup = false;

kfree_skb(skb);
}

return may_wakeup;
}

static int btmtksdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
Expand Down Expand Up @@ -997,6 +1023,7 @@ static int btmtksdio_probe(struct sdio_func *func,
hdev->setup = btmtksdio_setup;
hdev->shutdown = btmtksdio_shutdown;
hdev->send = btmtksdio_send_frame;
hdev->wakeup = btmtksdio_sdio_wakeup;
hdev->set_bdaddr = btmtk_set_bdaddr;

SET_HCIDEV_DEV(hdev, &func->dev);
Expand Down Expand Up @@ -1032,7 +1059,11 @@ static int btmtksdio_probe(struct sdio_func *func,
*/
pm_runtime_put_noidle(bdev->dev);

return 0;
err = device_init_wakeup(bdev->dev, true);
if (err)
bt_dev_err(hdev, "failed to initialize device wakeup");

return err;
}

static void btmtksdio_remove(struct sdio_func *func)
Expand Down

0 comments on commit ce64b3e

Please sign in to comment.