blob: 05c9bb0b4d5562917949752daacd8d54db2274e3 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
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
26static struct rfkill *bt_rfk;
27static const char bt_name[] = "bcm4329";
28
29static 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
41static struct rfkill_ops mahimahi_rfkill_ops = {
42 .set_block = bluetooth_set_power,
43};
44
45static 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
76err_rfkill_reg:
77 rfkill_destroy(bt_rfk);
78err_rfkill_alloc:
79 gpio_free(MAHIMAHI_GPIO_BT_SHUTDOWN_N);
80err_gpio_shutdown:
81 gpio_free(MAHIMAHI_GPIO_BT_RESET_N);
82err_gpio_reset:
83 return rc;
84}
85
86static 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
96static 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
105static 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
113static void __exit mahimahi_rfkill_exit(void)
114{
115 platform_driver_unregister(&mahimahi_rfkill_driver);
116}
117
118module_init(mahimahi_rfkill_init);
119module_exit(mahimahi_rfkill_exit);
120MODULE_DESCRIPTION("mahimahi rfkill");
121MODULE_AUTHOR("Nick Pelly <npelly@google.com>");
122MODULE_LICENSE("GPL");