int hci_uart_tx_wakeup(struct hci_uart *hu) { struct tty_struct *tty = hu->tty; struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); return 0; } BT_DBG(""); restart: clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); #if !defined(CONFIG_MT5931_MT6622) /*added by Barry,for broadcom 4325*/ #ifdef CONFIG_BT_AUTOSLEEP #ifdef CONFIG_RFKILL_RK extern int rfkill_rk_sleep_bt(bool bSleep); rfkill_rk_sleep_bt(false); #else //extern void bcm4325_sleep(unsigned long bSleep); //bcm4325_sleep(0); #endif #endif #endif while ((skb = hci_uart_dequeue(hu))) { int len; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); len = tty->ops->write(tty, skb->data, skb->len); hdev->stat.byte_tx += len; skb_pull(skb, len); if (skb->len) { hu->tx_skb = skb; break; } hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type); kfree_skb(skb); } if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) goto restart; clear_bit(HCI_UART_SENDING, &hu->tx_state); #if defined(CONFIG_MT5931_MT6622) /* Host can enter sleep after 5s no UART data */ wake_lock_timeout(&bt_wake_lock, WAKE_LOCK_TIMEOUT); #endif return 0; }
static int rfkill_rk_set_power(void *data, bool blocked) { struct rfkill_rk_data *rfkill = data; struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio; struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio; DBG("Enter %s\n", __func__); DBG("Set blocked:%d\n", blocked); if (false == blocked) { rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup if (gpio_is_valid(poweron->io)) { gpio_direction_output(poweron->io, poweron->enable); msleep(20); } if (gpio_is_valid(reset->io)) { gpio_direction_output(reset->io, reset->enable); msleep(20); gpio_direction_output(reset->io, !reset->enable); msleep(20); } LOG("bt turn on power\n"); } else { #if WIFI_BT_POWER_TOGGLE if (!rk29sdk_wifi_power_state) { #endif if (gpio_is_valid(poweron->io)) { gpio_direction_output(poweron->io, !poweron->enable); msleep(20); } LOG("bt shut off power\n"); #if WIFI_BT_POWER_TOGGLE }else { LOG("bt shouldn't shut off power, wifi is using it!\n"); } #endif if (gpio_is_valid(reset->io)) { gpio_direction_output(reset->io, reset->enable);/* bt reset active*/ msleep(20); } } #if WIFI_BT_POWER_TOGGLE rk29sdk_bt_power_state = !blocked; #endif return 0; }
static int rfkill_rk_pm_prepare(struct device *dev) { struct rfkill_rk_data *rfkill = g_rfkill; struct rfkill_rk_gpio* rts; struct rfkill_rk_irq* wake_host_irq; DBG("Enter %s\n",__FUNCTION__); if (!rfkill) return 0; rts = &rfkill->pdata->rts_gpio; wake_host_irq = &rfkill->pdata->wake_host_irq; //To prevent uart to receive bt data when suspended if (gpio_is_valid(rts->io)) { DBG("Disable UART_RTS\n"); if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); } gpio_direction_output(rts->io, !rts->enable); } #ifdef CONFIG_BT_AUTOSLEEP // BT进入睡眠状态,不接收主控数据 rfkill_rk_sleep_bt(BT_SLEEP); #endif /* 至此,蓝牙不再送数据到UART,也不再接收主控的UART数据 * 接着调用enable_irq使能 bt_wake_host irq,当远端设备有数据 * 到来时,将通过该IRQ唤醒主控 */ // enable bt wakeup host if (gpio_is_valid(wake_host_irq->gpio.io)) { DBG("enable irq for bt wakeup host\n"); enable_irq(wake_host_irq->irq); } #ifdef CONFIG_RFKILL_RESET rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); rfkill_rk_set_power(rfkill, BT_BLOCKED); #endif return 0; }
static int bluesleep_write_proc_btwrite(struct file *file, const char *buffer, unsigned long count, void *data) { char b; if (count < 1) return -EINVAL; if (copy_from_user(&b, buffer, 1)) return -EFAULT; DBG("btwrite %c\n", b); /* HCI_DEV_WRITE */ if (b != '0') { rfkill_rk_sleep_bt(BT_WAKEUP); } return count; }
static int rfkill_rk_set_power(void *data, bool blocked) { struct rfkill_rk_data *rfkill = data; struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio; struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio; struct rfkill_rk_gpio* rts = &rfkill->pdata->rts_gpio; DBG("Enter %s\n", __func__); DBG("Set blocked:%d\n", blocked); if (false == blocked) { rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup #if 0//defined(CONFIG_AP6210) if (gpio_is_valid(rts->io)) { if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); } DBG("ENABLE UART_RTS\n"); gpio_direction_output(rts->io, rts->enable); msleep(20); } #endif if (gpio_is_valid(poweron->io)) { gpio_direction_output(poweron->io, poweron->enable); msleep(20); } if (gpio_is_valid(reset->io)) { gpio_direction_output(reset->io, reset->enable); msleep(20); gpio_direction_output(reset->io, !reset->enable); msleep(20); } #if defined(CONFIG_AP6210) if (gpio_is_valid(rts->io)) { if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); } DBG("ENABLE UART_RTS\n"); gpio_direction_output(rts->io, rts->enable); msleep(100); DBG("DISABLE UART_RTS\n"); gpio_direction_output(rts->io, !rts->enable); if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fmux); } } #endif #if 0//defined(CONFIG_AP6210) if (gpio_is_valid(rts->io)) { DBG("DISABLE UART_RTS\n"); gpio_direction_output(rts->io, !rts->enable); if (rts->iomux.name) { rk_mux_api_set(rts->iomux.name, rts->iomux.fmux); } } #endif LOG("bt turn on power\n"); } else { #if WIFI_BT_POWER_TOGGLE if (!rk29sdk_wifi_power_state) { #endif if (gpio_is_valid(poweron->io)) { gpio_direction_output(poweron->io, !poweron->enable); msleep(20); } LOG("bt shut off power\n"); #if WIFI_BT_POWER_TOGGLE }else { LOG("bt shouldn't shut off power, wifi is using it!\n"); } #endif if (gpio_is_valid(reset->io)) { gpio_direction_output(reset->io, reset->enable);/* bt reset active*/ msleep(20); } } #if WIFI_BT_POWER_TOGGLE rk29sdk_bt_power_state = !blocked; #endif return 0; }