PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm/mach-pxa/tosa-bt.c

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