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 | ||
19d337df | 38 | static int tosa_bt_set_block(void *data, bool blocked) |
16b32fd0 | 39 | { |
19d337df | 40 | pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on"); |
16b32fd0 | 41 | |
19d337df | 42 | if (!blocked) { |
16b32fd0 DB |
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 | } | |
19d337df | 49 | |
16b32fd0 DB |
50 | return 0; |
51 | } | |
52 | ||
19d337df JB |
53 | static const struct rfkill_ops tosa_bt_rfkill_ops = { |
54 | .set_block = tosa_bt_set_block, | |
55 | }; | |
56 | ||
16b32fd0 DB |
57 | static 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 | ||
19d337df JB |
77 | rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH, |
78 | &tosa_bt_rfkill_ops, data); | |
16b32fd0 DB |
79 | if (!rfk) { |
80 | rc = -ENOMEM; | |
81 | goto err_rfk_alloc; | |
82 | } | |
83 | ||
16b32fd0 DB |
84 | rc = rfkill_register(rfk); |
85 | if (rc) | |
86 | goto err_rfkill; | |
87 | ||
88 | platform_set_drvdata(dev, rfk); | |
89 | ||
90 | return 0; | |
91 | ||
92 | err_rfkill: | |
19d337df | 93 | rfkill_destroy(rfk); |
16b32fd0 DB |
94 | err_rfk_alloc: |
95 | tosa_bt_off(data); | |
96 | err_pwr_dir: | |
97 | gpio_free(data->gpio_pwr); | |
98 | err_pwr: | |
99 | err_reset_dir: | |
100 | gpio_free(data->gpio_reset); | |
101 | err_reset: | |
102 | return rc; | |
103 | } | |
104 | ||
351a102d | 105 | static int tosa_bt_remove(struct platform_device *dev) |
16b32fd0 DB |
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 | ||
19d337df | 112 | if (rfk) { |
16b32fd0 | 113 | rfkill_unregister(rfk); |
19d337df JB |
114 | rfkill_destroy(rfk); |
115 | } | |
16b32fd0 DB |
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 | ||
126 | static struct platform_driver tosa_bt_driver = { | |
127 | .probe = tosa_bt_probe, | |
351a102d | 128 | .remove = tosa_bt_remove, |
16b32fd0 DB |
129 | |
130 | .driver = { | |
131 | .name = "tosa-bt", | |
132 | .owner = THIS_MODULE, | |
133 | }, | |
134 | }; | |
135 | ||
136 | ||
137 | static int __init tosa_bt_init(void) | |
138 | { | |
139 | return platform_driver_register(&tosa_bt_driver); | |
140 | } | |
141 | ||
142 | static void __exit tosa_bt_exit(void) | |
143 | { | |
144 | platform_driver_unregister(&tosa_bt_driver); | |
145 | } | |
146 | ||
147 | module_init(tosa_bt_init); | |
148 | module_exit(tosa_bt_exit); |