xref: /OK3568_Linux_fs/kernel/drivers/mfd/ucb1400_core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Core functions for:
4*4882a593Smuzhiyun  *  Philips UCB1400 multifunction chip
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Based on ucb1400_ts.c:
7*4882a593Smuzhiyun  *  Author:	Nicolas Pitre
8*4882a593Smuzhiyun  *  Created:	September 25, 2006
9*4882a593Smuzhiyun  *  Copyright:	MontaVista Software, Inc.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Spliting done by: Marek Vasut <marek.vasut@gmail.com>
12*4882a593Smuzhiyun  * If something doesn't work and it worked before spliting, e-mail me,
13*4882a593Smuzhiyun  * dont bother Nicolas please ;-)
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * This code is heavily based on ucb1x00-*.c copyrighted by Russell King
16*4882a593Smuzhiyun  * covering the UCB1100, UCB1200 and UCB1300..  Support for the UCB1400 has
17*4882a593Smuzhiyun  * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request.
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/sched.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/ucb1400.h>
24*4882a593Smuzhiyun 
ucb1400_adc_read(struct snd_ac97 * ac97,u16 adc_channel,int adcsync)25*4882a593Smuzhiyun unsigned int ucb1400_adc_read(struct snd_ac97 *ac97, u16 adc_channel,
26*4882a593Smuzhiyun 		int adcsync)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	unsigned int val;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (adcsync)
31*4882a593Smuzhiyun 		adc_channel |= UCB_ADC_SYNC_ENA;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
34*4882a593Smuzhiyun 	ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel |
35*4882a593Smuzhiyun 			UCB_ADC_START);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	while (!((val = ucb1400_reg_read(ac97, UCB_ADC_DATA))
38*4882a593Smuzhiyun 				& UCB_ADC_DAT_VALID))
39*4882a593Smuzhiyun 		schedule_timeout_uninterruptible(1);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	return val & UCB_ADC_DAT_MASK;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ucb1400_adc_read);
44*4882a593Smuzhiyun 
ucb1400_core_probe(struct device * dev)45*4882a593Smuzhiyun static int ucb1400_core_probe(struct device *dev)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	int err;
48*4882a593Smuzhiyun 	struct ucb1400 *ucb;
49*4882a593Smuzhiyun 	struct ucb1400_ts ucb_ts;
50*4882a593Smuzhiyun 	struct ucb1400_gpio ucb_gpio;
51*4882a593Smuzhiyun 	struct snd_ac97 *ac97;
52*4882a593Smuzhiyun 	struct ucb1400_pdata *pdata = dev_get_platdata(dev);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	memset(&ucb_ts, 0, sizeof(ucb_ts));
55*4882a593Smuzhiyun 	memset(&ucb_gpio, 0, sizeof(ucb_gpio));
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL);
58*4882a593Smuzhiyun 	if (!ucb) {
59*4882a593Smuzhiyun 		err = -ENOMEM;
60*4882a593Smuzhiyun 		goto err;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	dev_set_drvdata(dev, ucb);
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	ac97 = to_ac97_t(dev);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	ucb_ts.id = ucb1400_reg_read(ac97, UCB_ID);
68*4882a593Smuzhiyun 	if (ucb_ts.id != UCB_ID_1400) {
69*4882a593Smuzhiyun 		err = -ENODEV;
70*4882a593Smuzhiyun 		goto err0;
71*4882a593Smuzhiyun 	}
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* GPIO */
74*4882a593Smuzhiyun 	ucb_gpio.ac97 = ac97;
75*4882a593Smuzhiyun 	if (pdata) {
76*4882a593Smuzhiyun 		ucb_gpio.gpio_setup = pdata->gpio_setup;
77*4882a593Smuzhiyun 		ucb_gpio.gpio_teardown = pdata->gpio_teardown;
78*4882a593Smuzhiyun 		ucb_gpio.gpio_offset = pdata->gpio_offset;
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 	ucb->ucb1400_gpio = platform_device_alloc("ucb1400_gpio", -1);
81*4882a593Smuzhiyun 	if (!ucb->ucb1400_gpio) {
82*4882a593Smuzhiyun 		err = -ENOMEM;
83*4882a593Smuzhiyun 		goto err0;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 	err = platform_device_add_data(ucb->ucb1400_gpio, &ucb_gpio,
86*4882a593Smuzhiyun 					sizeof(ucb_gpio));
87*4882a593Smuzhiyun 	if (err)
88*4882a593Smuzhiyun 		goto err1;
89*4882a593Smuzhiyun 	err = platform_device_add(ucb->ucb1400_gpio);
90*4882a593Smuzhiyun 	if (err)
91*4882a593Smuzhiyun 		goto err1;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	/* TOUCHSCREEN */
94*4882a593Smuzhiyun 	ucb_ts.ac97 = ac97;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	if (pdata != NULL && pdata->irq >= 0)
97*4882a593Smuzhiyun 		ucb_ts.irq = pdata->irq;
98*4882a593Smuzhiyun 	else
99*4882a593Smuzhiyun 		ucb_ts.irq = -1;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	ucb->ucb1400_ts = platform_device_alloc("ucb1400_ts", -1);
102*4882a593Smuzhiyun 	if (!ucb->ucb1400_ts) {
103*4882a593Smuzhiyun 		err = -ENOMEM;
104*4882a593Smuzhiyun 		goto err2;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 	err = platform_device_add_data(ucb->ucb1400_ts, &ucb_ts,
107*4882a593Smuzhiyun 					sizeof(ucb_ts));
108*4882a593Smuzhiyun 	if (err)
109*4882a593Smuzhiyun 		goto err3;
110*4882a593Smuzhiyun 	err = platform_device_add(ucb->ucb1400_ts);
111*4882a593Smuzhiyun 	if (err)
112*4882a593Smuzhiyun 		goto err3;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	return 0;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun err3:
117*4882a593Smuzhiyun 	platform_device_put(ucb->ucb1400_ts);
118*4882a593Smuzhiyun err2:
119*4882a593Smuzhiyun 	platform_device_del(ucb->ucb1400_gpio);
120*4882a593Smuzhiyun err1:
121*4882a593Smuzhiyun 	platform_device_put(ucb->ucb1400_gpio);
122*4882a593Smuzhiyun err0:
123*4882a593Smuzhiyun 	kfree(ucb);
124*4882a593Smuzhiyun err:
125*4882a593Smuzhiyun 	return err;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
ucb1400_core_remove(struct device * dev)128*4882a593Smuzhiyun static int ucb1400_core_remove(struct device *dev)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	struct ucb1400 *ucb = dev_get_drvdata(dev);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	platform_device_unregister(ucb->ucb1400_ts);
133*4882a593Smuzhiyun 	platform_device_unregister(ucb->ucb1400_gpio);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	kfree(ucb);
136*4882a593Smuzhiyun 	return 0;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static struct device_driver ucb1400_core_driver = {
140*4882a593Smuzhiyun 	.name	= "ucb1400_core",
141*4882a593Smuzhiyun 	.bus	= &ac97_bus_type,
142*4882a593Smuzhiyun 	.probe	= ucb1400_core_probe,
143*4882a593Smuzhiyun 	.remove	= ucb1400_core_remove,
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
ucb1400_core_init(void)146*4882a593Smuzhiyun static int __init ucb1400_core_init(void)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	return driver_register(&ucb1400_core_driver);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
ucb1400_core_exit(void)151*4882a593Smuzhiyun static void __exit ucb1400_core_exit(void)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	driver_unregister(&ucb1400_core_driver);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun module_init(ucb1400_core_init);
157*4882a593Smuzhiyun module_exit(ucb1400_core_exit);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun MODULE_DESCRIPTION("Philips UCB1400 driver");
160*4882a593Smuzhiyun MODULE_LICENSE("GPL");
161