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        rfkill_set_led_trigger_name(rfk, "tosa-bt");
  85
  86        rc = rfkill_register(rfk);
  87        if (rc)
  88                goto err_rfkill;
  89
  90        platform_set_drvdata(dev, rfk);
  91
  92        return 0;
  93
  94err_rfkill:
  95        rfkill_destroy(rfk);
  96err_rfk_alloc:
  97        tosa_bt_off(data);
  98err_pwr_dir:
  99        gpio_free(data->gpio_pwr);
 100err_pwr:
 101err_reset_dir:
 102        gpio_free(data->gpio_reset);
 103err_reset:
 104        return rc;
 105}
 106
 107static int __devexit tosa_bt_remove(struct platform_device *dev)
 108{
 109        struct tosa_bt_data *data = dev->dev.platform_data;
 110        struct rfkill *rfk = platform_get_drvdata(dev);
 111
 112        platform_set_drvdata(dev, NULL);
 113
 114        if (rfk) {
 115                rfkill_unregister(rfk);
 116                rfkill_destroy(rfk);
 117        }
 118        rfk = NULL;
 119
 120        tosa_bt_off(data);
 121
 122        gpio_free(data->gpio_pwr);
 123        gpio_free(data->gpio_reset);
 124
 125        return 0;
 126}
 127
 128static struct platform_driver tosa_bt_driver = {
 129        .probe = tosa_bt_probe,
 130        .remove = __devexit_p(tosa_bt_remove),
 131
 132        .driver = {
 133                .name = "tosa-bt",
 134                .owner = THIS_MODULE,
 135        },
 136};
 137
 138
 139static int __init tosa_bt_init(void)
 140{
 141        return platform_driver_register(&tosa_bt_driver);
 142}
 143
 144static void __exit tosa_bt_exit(void)
 145{
 146        platform_driver_unregister(&tosa_bt_driver);
 147}
 148
 149module_init(tosa_bt_init);
 150module_exit(tosa_bt_exit);
 151