Blame view

arch/arm/mach-pxa/tosa-bt.c 2.87 KB
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Bluetooth built-in chip control
   *
   * Copyright (c) 2008 Dmitry Baryshkov
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/gpio.h>
  #include <linux/delay.h>
  #include <linux/rfkill.h>
a09e64fbc   Russell King   [ARM] Move includ...
18
  #include <mach/tosa_bt.h>
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  
  static void tosa_bt_on(struct tosa_bt_data *data)
  {
  	gpio_set_value(data->gpio_reset, 0);
  	gpio_set_value(data->gpio_pwr, 1);
  	gpio_set_value(data->gpio_reset, 1);
  	mdelay(20);
  	gpio_set_value(data->gpio_reset, 0);
  }
  
  static void tosa_bt_off(struct tosa_bt_data *data)
  {
  	gpio_set_value(data->gpio_reset, 1);
  	mdelay(10);
  	gpio_set_value(data->gpio_pwr, 0);
  	gpio_set_value(data->gpio_reset, 0);
  }
19d337dff   Johannes Berg   rfkill: rewrite
36
  static int tosa_bt_set_block(void *data, bool blocked)
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
37
  {
19d337dff   Johannes Berg   rfkill: rewrite
38
39
  	pr_info("BT_RADIO going: %s
  ", blocked ? "off" : "on");
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
40

19d337dff   Johannes Berg   rfkill: rewrite
41
  	if (!blocked) {
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
42
43
44
45
46
47
48
49
  		pr_info("TOSA_BT: going ON
  ");
  		tosa_bt_on(data);
  	} else {
  		pr_info("TOSA_BT: going OFF
  ");
  		tosa_bt_off(data);
  	}
19d337dff   Johannes Berg   rfkill: rewrite
50

16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
51
52
  	return 0;
  }
19d337dff   Johannes Berg   rfkill: rewrite
53
54
55
  static const struct rfkill_ops tosa_bt_rfkill_ops = {
  	.set_block = tosa_bt_set_block,
  };
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  static int tosa_bt_probe(struct platform_device *dev)
  {
  	int rc;
  	struct rfkill *rfk;
  
  	struct tosa_bt_data *data = dev->dev.platform_data;
  
  	rc = gpio_request(data->gpio_reset, "Bluetooth reset");
  	if (rc)
  		goto err_reset;
  	rc = gpio_direction_output(data->gpio_reset, 0);
  	if (rc)
  		goto err_reset_dir;
  	rc = gpio_request(data->gpio_pwr, "Bluetooth power");
  	if (rc)
  		goto err_pwr;
  	rc = gpio_direction_output(data->gpio_pwr, 0);
  	if (rc)
  		goto err_pwr_dir;
19d337dff   Johannes Berg   rfkill: rewrite
75
76
  	rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
  			   &tosa_bt_rfkill_ops, data);
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
77
78
79
80
  	if (!rfk) {
  		rc = -ENOMEM;
  		goto err_rfk_alloc;
  	}
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
81
82
83
84
85
86
87
88
89
  	rc = rfkill_register(rfk);
  	if (rc)
  		goto err_rfkill;
  
  	platform_set_drvdata(dev, rfk);
  
  	return 0;
  
  err_rfkill:
19d337dff   Johannes Berg   rfkill: rewrite
90
  	rfkill_destroy(rfk);
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  err_rfk_alloc:
  	tosa_bt_off(data);
  err_pwr_dir:
  	gpio_free(data->gpio_pwr);
  err_pwr:
  err_reset_dir:
  	gpio_free(data->gpio_reset);
  err_reset:
  	return rc;
  }
  
  static int __devexit tosa_bt_remove(struct platform_device *dev)
  {
  	struct tosa_bt_data *data = dev->dev.platform_data;
  	struct rfkill *rfk = platform_get_drvdata(dev);
  
  	platform_set_drvdata(dev, NULL);
19d337dff   Johannes Berg   rfkill: rewrite
108
  	if (rfk) {
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
109
  		rfkill_unregister(rfk);
19d337dff   Johannes Berg   rfkill: rewrite
110
111
  		rfkill_destroy(rfk);
  	}
16b32fd0a   Dmitry Eremin-Solenikov   [ARM] 5150/1: Tos...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  	rfk = NULL;
  
  	tosa_bt_off(data);
  
  	gpio_free(data->gpio_pwr);
  	gpio_free(data->gpio_reset);
  
  	return 0;
  }
  
  static struct platform_driver tosa_bt_driver = {
  	.probe = tosa_bt_probe,
  	.remove = __devexit_p(tosa_bt_remove),
  
  	.driver = {
  		.name = "tosa-bt",
  		.owner = THIS_MODULE,
  	},
  };
  
  
  static int __init tosa_bt_init(void)
  {
  	return platform_driver_register(&tosa_bt_driver);
  }
  
  static void __exit tosa_bt_exit(void)
  {
  	platform_driver_unregister(&tosa_bt_driver);
  }
  
  module_init(tosa_bt_init);
  module_exit(tosa_bt_exit);