xref: /OK3568_Linux_fs/kernel/drivers/headset_observe/rockchip_headset_core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2014 Rockchip Corporation.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/init.h>
17 #include <linux/delay.h>
18 #include <linux/pm.h>
19 #include <linux/i2c.h>
20 #include <linux/spi/spi.h>
21 #include <linux/platform_device.h>
22 #include <linux/errno.h>
23 #include <linux/err.h>
24 #include <linux/debugfs.h>
25 #include "rk_headset.h"
26 #include <linux/of_gpio.h>
27 #include <linux/gpio.h>
28 #include <linux/iio/consumer.h>
29 
30 /* Debug */
31 #if 0
32 #define DBG(x...) printk(x)
33 #else
34 #define DBG(x...) do { } while (0)
35 #endif
36 
37 static struct rk_headset_pdata *pdata_info;
38 
rockchip_headset_probe(struct platform_device * pdev)39 static int rockchip_headset_probe(struct platform_device *pdev)
40 {
41 	struct device_node *node = pdev->dev.of_node;
42 	struct rk_headset_pdata *pdata;
43 	int ret;
44 	enum of_gpio_flags flags;
45 
46 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
47 	if (!pdata) {
48 		printk("%s failed to allocate driver data\n", __func__);
49 		return -ENOMEM;
50 	}
51 	pdata_info = pdata;
52 
53 	/* headset */
54 	ret = of_get_named_gpio_flags(node, "headset_gpio", 0, &flags);
55 	if (ret < 0) {
56 		dev_err(&pdev->dev, "Can not read property headset_gpio\n");
57 		goto err;
58 	} else {
59 		pdata->headset_gpio = ret;
60 		ret = devm_gpio_request(&pdev->dev, pdata->headset_gpio,
61 					"headset_gpio");
62 		if (ret < 0) {
63 			dev_err(&pdev->dev, "headset_gpio request fail\n");
64 			goto err;
65 		}
66 		ret = gpio_direction_input(pdata->headset_gpio);
67 		if (ret < 0) {
68 			dev_err(&pdev->dev,
69 				"headset_gpio set direction fail\n");
70 			goto err;
71 		}
72 		pdata->headset_insert_type = (flags & OF_GPIO_ACTIVE_LOW) ?
73 						     HEADSET_IN_LOW :
74 						     HEADSET_IN_HIGH;
75 	}
76 	/* hook */
77 	ret = of_get_named_gpio_flags(node, "hook_gpio", 0, &pdata->hook_gpio);
78 	if (ret < 0) {
79 		dev_warn(&pdev->dev, "Can not read property hook_gpio\n");
80 		pdata->hook_gpio = 0;
81 		/* adc mode */
82 		pdata->chan = iio_channel_get(&pdev->dev, NULL);
83 		if (IS_ERR(pdata->chan)) {
84 			pdata->chan = NULL;
85 			dev_warn(&pdev->dev, "have not set adc chan\n");
86 		}
87 	} else {
88 		ret = of_property_read_u32(node, "hook_down_type",
89 					   &pdata->hook_down_type);
90 		if (ret < 0) {
91 			dev_warn(&pdev->dev,
92 				 "have not set hook_down_type,set >hook< insert type low level default\n");
93 			pdata->hook_down_type = 0;
94 		}
95 		ret = devm_gpio_request(&pdev->dev, pdata->hook_gpio,
96 					"hook_gpio");
97 		if (ret < 0) {
98 			dev_warn(&pdev->dev,
99 				 "devm_gpio_request hook_gpio request ERROR\n");
100 			goto err;
101 		}
102 		ret = gpio_direction_input(pdata->hook_gpio);
103 		if (ret < 0) {
104 			dev_warn(&pdev->dev,
105 				 "gpio_direction_input hook_gpio set ERROR\n");
106 			goto err;
107 		}
108 	}
109 
110 #ifdef CONFIG_MODEM_MIC_SWITCH
111 	/* mic */
112 	ret = of_get_named_gpio_flags(node, "mic_switch_gpio", 0, &flags);
113 	if (ret < 0) {
114 		DBG("%s() Can not read property mic_switch_gpio\n",
115 		    __func__);
116 	} else {
117 		pdata->headset_gpio = ret;
118 		ret = of_property_read_u32(node, "hp_mic_io_value",
119 					   &pdata->hp_mic_io_value);
120 		if (ret < 0) {
121 			DBG("%s() have not set hp_mic_io_value ,so default set pull down low level\n",
122 			    __func__);
123 			pdata->hp_mic_io_value = 0;
124 		}
125 		ret = of_property_read_u32(node, "main_mic_io_value",
126 					   &pdata->main_mic_io_value);
127 		if (ret < 0) {
128 			DBG("%s() have not set main_mic_io_value ,so default set pull down low level\n",
129 			    __func__);
130 			pdata->main_mic_io_value = 1;
131 		}
132 	}
133 #endif
134 	ret = of_property_read_u32(node, "rockchip,headset_wakeup",
135 				   &pdata->headset_wakeup);
136 	if (ret < 0)
137 		pdata->headset_wakeup = 1;
138 	if (pdata->chan) { /* hook adc mode */
139 		dev_info(&pdev->dev, "headset have hook adc mode\n");
140 		ret = rk_headset_adc_probe(pdev, pdata);
141 		if (ret < 0) {
142 			goto err;
143 		}
144 	} else { /* hook interrupt mode and not hook */
145 		dev_info(&pdev->dev, "headset have %s mode\n",
146 			 pdata->hook_gpio ? "interrupt hook" : "no hook");
147 		ret = rk_headset_probe(pdev, pdata);
148 		if (ret < 0) {
149 			goto err;
150 		}
151 	}
152 	return 0;
153 err:
154 	return ret;
155 }
156 
rockchip_headset_remove(struct platform_device * pdev)157 static int rockchip_headset_remove(struct platform_device *pdev)
158 {
159 	return 0;
160 }
161 
rockchip_headset_suspend(struct platform_device * pdev,pm_message_t state)162 static int rockchip_headset_suspend(struct platform_device *pdev,
163 				    pm_message_t state)
164 {
165 	if (pdata_info->chan != 0) {
166 		return rk_headset_adc_suspend(pdev, state);
167 	}
168 	return 0;
169 }
170 
rockchip_headset_resume(struct platform_device * pdev)171 static int rockchip_headset_resume(struct platform_device *pdev)
172 {
173 	if (pdata_info->chan != 0) {
174 		return rk_headset_adc_resume(pdev);
175 	}
176 	return 0;
177 }
178 
179 static const struct of_device_id rockchip_headset_of_match[] = {
180 	{ .compatible = "rockchip_headset", },
181 	{},
182 };
183 MODULE_DEVICE_TABLE(of, rockchip_headset_of_match);
184 
185 static struct platform_driver rockchip_headset_driver = {
186 	.probe	= rockchip_headset_probe,
187 	.remove = rockchip_headset_remove,
188 	.resume =	rockchip_headset_resume,
189 	.suspend =	rockchip_headset_suspend,
190 	.driver	= {
191 		.name	= "rockchip_headset",
192 		.owner	= THIS_MODULE,
193 		.of_match_table = of_match_ptr(rockchip_headset_of_match),
194 	},
195 };
196 
rockchip_headset_init(void)197 static int __init rockchip_headset_init(void)
198 {
199 	platform_driver_register(&rockchip_headset_driver);
200 	return 0;
201 }
202 
rockchip_headset_exit(void)203 static void __exit rockchip_headset_exit(void)
204 {
205 	platform_driver_unregister(&rockchip_headset_driver);
206 }
207 late_initcall(rockchip_headset_init);
208 module_exit(rockchip_headset_exit);
209 
210 MODULE_DESCRIPTION("Rockchip Headset Core Driver");
211 MODULE_LICENSE("GPL");
212