]>
Commit | Line | Data |
---|---|---|
16b32fd0 DB |
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 | ||
a09e64fb | 19 | #include <mach/tosa_bt.h> |
16b32fd0 DB |
20 | |
21 | static 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 | ||
30 | static 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 | ||
38 | static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) | |
39 | { | |
40 | pr_info("BT_RADIO going: %s\n", | |
41 | state == RFKILL_STATE_ON ? "on" : "off"); | |
42 | ||
43 | if (state == RFKILL_STATE_ON) { | |
44 | pr_info("TOSA_BT: going ON\n"); | |
45 | tosa_bt_on(data); | |
46 | } else { | |
47 | pr_info("TOSA_BT: going OFF\n"); | |
48 | tosa_bt_off(data); | |
49 | } | |
50 | return 0; | |
51 | } | |
52 | ||
53 | static int tosa_bt_probe(struct platform_device *dev) | |
54 | { | |
55 | int rc; | |
56 | struct rfkill *rfk; | |
57 | ||
58 | struct tosa_bt_data *data = dev->dev.platform_data; | |
59 | ||
60 | rc = gpio_request(data->gpio_reset, "Bluetooth reset"); | |
61 | if (rc) | |
62 | goto err_reset; | |
63 | rc = gpio_direction_output(data->gpio_reset, 0); | |
64 | if (rc) | |
65 | goto err_reset_dir; | |
66 | rc = gpio_request(data->gpio_pwr, "Bluetooth power"); | |
67 | if (rc) | |
68 | goto err_pwr; | |
69 | rc = gpio_direction_output(data->gpio_pwr, 0); | |
70 | if (rc) | |
71 | goto err_pwr_dir; | |
72 | ||
73 | rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH); | |
74 | if (!rfk) { | |
75 | rc = -ENOMEM; | |
76 | goto err_rfk_alloc; | |
77 | } | |
78 | ||
79 | rfk->name = "tosa-bt"; | |
80 | rfk->toggle_radio = tosa_bt_toggle_radio; | |
81 | rfk->data = data; | |
82 | #ifdef CONFIG_RFKILL_LEDS | |
83 | rfk->led_trigger.name = "tosa-bt"; | |
84 | #endif | |
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 | ||
94 | err_rfkill: | |
95 | if (rfk) | |
96 | rfkill_free(rfk); | |
97 | rfk = NULL; | |
98 | err_rfk_alloc: | |
99 | tosa_bt_off(data); | |
100 | err_pwr_dir: | |
101 | gpio_free(data->gpio_pwr); | |
102 | err_pwr: | |
103 | err_reset_dir: | |
104 | gpio_free(data->gpio_reset); | |
105 | err_reset: | |
106 | return rc; | |
107 | } | |
108 | ||
109 | static int __devexit tosa_bt_remove(struct platform_device *dev) | |
110 | { | |
111 | struct tosa_bt_data *data = dev->dev.platform_data; | |
112 | struct rfkill *rfk = platform_get_drvdata(dev); | |
113 | ||
114 | platform_set_drvdata(dev, NULL); | |
115 | ||
116 | if (rfk) | |
117 | rfkill_unregister(rfk); | |
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 | ||
128 | static 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 | ||
139 | static int __init tosa_bt_init(void) | |
140 | { | |
141 | return platform_driver_register(&tosa_bt_driver); | |
142 | } | |
143 | ||
144 | static void __exit tosa_bt_exit(void) | |
145 | { | |
146 | platform_driver_unregister(&tosa_bt_driver); | |
147 | } | |
148 | ||
149 | module_init(tosa_bt_init); | |
150 | module_exit(tosa_bt_exit); |