linux/arch/arm/mach-pxa/tosa-bt.c
<<
>>
Prefs
   1/*
   2 * Bluetooth built-in chip control
   3 *
   4 * Copyright (c) 2008 Dmitry Baryshkov
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/platform_device.h>
  15#include <linux/gpio.h>
  16#include <linux/delay.h>
  17#include <linux/rfkill.h>
  18
  19#include <mach/tosa_bt.h>
  20
  21static void tosa_bt_on(struct tosa_bt_data *data)
  22{
  23        gpio_set_value(data->gpio_reset, 0);
  24        gpio_set_value(data->gpio_pwr, 1);
  25        gpio_set_value(data->gpio_reset, 1);
  26        mdelay(20);
  27        gpio_set_value(data->gpio_reset, 0);
  28}
  29
  30static void tosa_bt_off(struct tosa_bt_data *data)
  31{
  32        gpio_set_value(data->gpio_reset, 1);
  33        mdelay(10);
  34        gpio_set_value(data->gpio_pwr, 0);
  35        gpio_set_value(data->gpio_reset, 0);
  36}
  37
  38static int tosa_bt_set_block(void *data, bool blocked)
  39{
  40        pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
  41
  42        if (!blocked) {
  43                pr_info("TOSA_BT: going ON\n");
  44                tosa_bt_on(data);
  45        } else {
  46                pr_info("TOSA_BT: going OFF\n");
  47                tosa_bt_off(data);
  48        }
  49
  50        return 0;
  51}
  52
  53static const struct rfkill_ops tosa_bt_rfkill_ops = {
  54        .set_block = tosa_bt_set_block,
  55};
  56
  57static int tosa_bt_probe(struct platform_device *dev)
  58{
  59        int rc;
  60        struct rfkill *rfk;
  61
  62        struct tosa_bt_data *data = dev->dev.platform_data;
  63
  64        rc = gpio_request(data->gpio_reset, "Bluetooth reset");
  65        if (rc)
  66                goto err_reset;
  67        rc = gpio_direction_output(data->gpio_reset, 0);
  68        if (rc)
  69                goto err_reset_dir;
  70        rc = gpio_request(data->gpio_pwr, "Bluetooth power");
  71        if (rc)
  72                goto err_pwr;
  73        rc = gpio_direction_output(data->gpio_pwr, 0);
  74        if (rc)
  75                goto err_pwr_dir;
  76
  77        rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
  78                           &tosa_bt_rfkill_ops, data);
  79        if (!rfk) {
  80                rc = -ENOMEM;
  81                goto err_rfk_alloc;
  82        }
  83
  84        rc = rfkill_register(rfk);
  85        if (rc)
  86                goto err_rfkill;
  87
  88        platform_set_drvdata(dev, rfk);
  89
  90        return 0;
  91
  92err_rfkill:
  93        rfkill_destroy(rfk);
  94err_rfk_alloc:
  95        tosa_bt_off(data);
  96err_pwr_dir:
  97        gpio_free(data->gpio_pwr);
  98err_pwr:
  99err_reset_dir:
 100        gpio_free(data->gpio_reset);
 101err_reset:
 102        return rc;
 103}
 104
 105static int __devexit tosa_bt_remove(struct platform_device *dev)
 106{
 107        struct tosa_bt_data *data = dev->dev.platform_data;
 108        struct rfkill *rfk = platform_get_drvdata(dev);
 109
 110        platform_set_drvdata(dev, NULL);
 111
 112        if (rfk) {
 113                rfkill_unregister(rfk);
 114                rfkill_destroy(rfk);
 115        }
 116        rfk = NULL;
 117
 118        tosa_bt_off(data);
 119
 120        gpio_free(data->gpio_pwr);
 121        gpio_free(data->gpio_reset);
 122
 123        return 0;
 124}
 125
 126static struct platform_driver tosa_bt_driver = {
 127        .probe = tosa_bt_probe,
 128        .remove = __devexit_p(tosa_bt_remove),
 129
 130        .driver = {
 131                .name = "tosa-bt",
 132                .owner = THIS_MODULE,
 133        },
 134};
 135
 136
 137static int __init tosa_bt_init(void)
 138{
 139        return platform_driver_register(&tosa_bt_driver);
 140}
 141
 142static void __exit tosa_bt_exit(void)
 143{
 144        platform_driver_unregister(&tosa_bt_driver);
 145}
 146
 147module_init(tosa_bt_init);
 148module_exit(tosa_bt_exit);
 149