| Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2009 Google, Inc. | 
|  | 3 | * Copyright (C) 2009 HTC Corporation. | 
|  | 4 | * | 
|  | 5 | * This software is licensed under the terms of the GNU General Public | 
|  | 6 | * License version 2, as published by the Free Software Foundation, and | 
|  | 7 | * may be copied, distributed, and modified under those terms. | 
|  | 8 | * | 
|  | 9 | * This program is distributed in the hope that it will be useful, | 
|  | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12 | * GNU General Public License for more details. | 
|  | 13 | * | 
|  | 14 | */ | 
|  | 15 |  | 
|  | 16 | #include <linux/delay.h> | 
|  | 17 | #include <linux/device.h> | 
|  | 18 | #include <linux/module.h> | 
|  | 19 | #include <linux/platform_device.h> | 
|  | 20 | #include <linux/rfkill.h> | 
|  | 21 | #include <asm/gpio.h> | 
|  | 22 | #include <asm/mach-types.h> | 
|  | 23 |  | 
|  | 24 | #include "board-mahimahi.h" | 
|  | 25 |  | 
|  | 26 | static struct rfkill *bt_rfk; | 
|  | 27 | static const char bt_name[] = "bcm4329"; | 
|  | 28 |  | 
|  | 29 | static int bluetooth_set_power(void *data, bool blocked) | 
|  | 30 | { | 
|  | 31 | if (!blocked) { | 
|  | 32 | gpio_direction_output(MAHIMAHI_GPIO_BT_RESET_N, 1); | 
|  | 33 | gpio_direction_output(MAHIMAHI_GPIO_BT_SHUTDOWN_N, 1); | 
|  | 34 | } else { | 
|  | 35 | gpio_direction_output(MAHIMAHI_GPIO_BT_SHUTDOWN_N, 0); | 
|  | 36 | gpio_direction_output(MAHIMAHI_GPIO_BT_RESET_N, 0); | 
|  | 37 | } | 
|  | 38 | return 0; | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 | static struct rfkill_ops mahimahi_rfkill_ops = { | 
|  | 42 | .set_block = bluetooth_set_power, | 
|  | 43 | }; | 
|  | 44 |  | 
|  | 45 | static int mahimahi_rfkill_probe(struct platform_device *pdev) | 
|  | 46 | { | 
|  | 47 | int rc = 0; | 
|  | 48 | bool default_state = true;  /* off */ | 
|  | 49 |  | 
|  | 50 | rc = gpio_request(MAHIMAHI_GPIO_BT_RESET_N, "bt_reset"); | 
|  | 51 | if (rc) | 
|  | 52 | goto err_gpio_reset; | 
|  | 53 | rc = gpio_request(MAHIMAHI_GPIO_BT_SHUTDOWN_N, "bt_shutdown"); | 
|  | 54 | if (rc) | 
|  | 55 | goto err_gpio_shutdown; | 
|  | 56 |  | 
|  | 57 | bluetooth_set_power(NULL, default_state); | 
|  | 58 |  | 
|  | 59 | bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, | 
|  | 60 | &mahimahi_rfkill_ops, NULL); | 
|  | 61 | if (!bt_rfk) { | 
|  | 62 | rc = -ENOMEM; | 
|  | 63 | goto err_rfkill_alloc; | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | rfkill_set_states(bt_rfk, default_state, false); | 
|  | 67 |  | 
|  | 68 | /* userspace cannot take exclusive control */ | 
|  | 69 |  | 
|  | 70 | rc = rfkill_register(bt_rfk); | 
|  | 71 | if (rc) | 
|  | 72 | goto err_rfkill_reg; | 
|  | 73 |  | 
|  | 74 | return 0; | 
|  | 75 |  | 
|  | 76 | err_rfkill_reg: | 
|  | 77 | rfkill_destroy(bt_rfk); | 
|  | 78 | err_rfkill_alloc: | 
|  | 79 | gpio_free(MAHIMAHI_GPIO_BT_SHUTDOWN_N); | 
|  | 80 | err_gpio_shutdown: | 
|  | 81 | gpio_free(MAHIMAHI_GPIO_BT_RESET_N); | 
|  | 82 | err_gpio_reset: | 
|  | 83 | return rc; | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | static int mahimahi_rfkill_remove(struct platform_device *dev) | 
|  | 87 | { | 
|  | 88 | rfkill_unregister(bt_rfk); | 
|  | 89 | rfkill_destroy(bt_rfk); | 
|  | 90 | gpio_free(MAHIMAHI_GPIO_BT_SHUTDOWN_N); | 
|  | 91 | gpio_free(MAHIMAHI_GPIO_BT_RESET_N); | 
|  | 92 |  | 
|  | 93 | return 0; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | static struct platform_driver mahimahi_rfkill_driver = { | 
|  | 97 | .probe = mahimahi_rfkill_probe, | 
|  | 98 | .remove = mahimahi_rfkill_remove, | 
|  | 99 | .driver = { | 
|  | 100 | .name = "mahimahi_rfkill", | 
|  | 101 | .owner = THIS_MODULE, | 
|  | 102 | }, | 
|  | 103 | }; | 
|  | 104 |  | 
|  | 105 | static int __init mahimahi_rfkill_init(void) | 
|  | 106 | { | 
|  | 107 | if (!machine_is_mahimahi()) | 
|  | 108 | return 0; | 
|  | 109 |  | 
|  | 110 | return platform_driver_register(&mahimahi_rfkill_driver); | 
|  | 111 | } | 
|  | 112 |  | 
|  | 113 | static void __exit mahimahi_rfkill_exit(void) | 
|  | 114 | { | 
|  | 115 | platform_driver_unregister(&mahimahi_rfkill_driver); | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | module_init(mahimahi_rfkill_init); | 
|  | 119 | module_exit(mahimahi_rfkill_exit); | 
|  | 120 | MODULE_DESCRIPTION("mahimahi rfkill"); | 
|  | 121 | MODULE_AUTHOR("Nick Pelly <npelly@google.com>"); | 
|  | 122 | MODULE_LICENSE("GPL"); |