1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * arizona-spi.c  --  Arizona SPI bus interface
4   *
5   * Copyright 2012 Wolfson Microelectronics plc
6   *
7   * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8   */
9  
10  #include <linux/acpi.h>
11  #include <linux/err.h>
12  #include <linux/gpio/consumer.h>
13  #include <linux/gpio/machine.h>
14  #include <linux/module.h>
15  #include <linux/pm_runtime.h>
16  #include <linux/regmap.h>
17  #include <linux/regulator/consumer.h>
18  #include <linux/slab.h>
19  #include <linux/spi/spi.h>
20  #include <linux/of.h>
21  #include <uapi/linux/input-event-codes.h>
22  
23  #include <linux/mfd/arizona/core.h>
24  
25  #include "arizona.h"
26  
27  #ifdef CONFIG_ACPI
28  static const struct acpi_gpio_params reset_gpios = { 1, 0, false };
29  static const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
30  
31  static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
32  	{ "reset-gpios", &reset_gpios, 1, },
33  	{ "wlf,ldoena-gpios", &ldoena_gpios, 1 },
34  	{ }
35  };
36  
37  /*
38   * The ACPI resources for the device only describe external GPIO-s. They do
39   * not provide mappings for the GPIO-s coming from the Arizona codec itself.
40   */
41  static const struct gpiod_lookup arizona_soc_gpios[] = {
42  	{ "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
43  	{ "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
44  };
45  
arizona_spi_acpi_remove_lookup(void * lookup)46  static void arizona_spi_acpi_remove_lookup(void *lookup)
47  {
48  	gpiod_remove_lookup_table(lookup);
49  }
50  
51  /* For ACPI tables from boards which ship with Windows as factory OS */
arizona_spi_acpi_windows_probe(struct arizona * arizona)52  static int arizona_spi_acpi_windows_probe(struct arizona *arizona)
53  {
54  	struct gpiod_lookup_table *lookup;
55  	acpi_status status;
56  	int ret;
57  
58  	/* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
59  	devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
60  
61  	/* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
62  	lookup = devm_kzalloc(arizona->dev,
63  			      struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
64  			      GFP_KERNEL);
65  	if (!lookup)
66  		return -ENOMEM;
67  
68  	lookup->dev_id = dev_name(arizona->dev);
69  	memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
70  
71  	gpiod_add_lookup_table(lookup);
72  	ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
73  	if (ret)
74  		return ret;
75  
76  	/* Enable 32KHz clock from SoC to codec for jack-detect */
77  	status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
78  	if (ACPI_FAILURE(status))
79  		dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
80  
81  	return 0;
82  }
83  
84  /* For ACPI tables from boards which ship with Android as factory OS */
arizona_spi_acpi_android_probe(struct arizona * arizona)85  static int arizona_spi_acpi_android_probe(struct arizona *arizona)
86  {
87  	int ret;
88  
89  	/*
90  	 * Get the reset GPIO, treating -ENOENT as -EPROBE_DEFER to wait for
91  	 * the x86-android-tablets module to register the board specific GPIO
92  	 * lookup table.
93  	 */
94  	arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset", GPIOD_OUT_LOW);
95  	if (IS_ERR(arizona->pdata.reset)) {
96  		ret = PTR_ERR(arizona->pdata.reset);
97  		if (ret == -ENOENT) {
98  			dev_info_once(arizona->dev,
99  				      "Deferring probe till GPIO lookup is registered\n");
100  			ret = -EPROBE_DEFER;
101  		}
102  		return dev_err_probe(arizona->dev, ret, "getting reset GPIO\n");
103  	}
104  
105  	return 0;
106  }
107  
108  /*
109   * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
110   * Function A Play/Pause:           0 ohm
111   * Function D Voice assistant:    135 ohm
112   * Function B Volume Up           240 ohm
113   * Function C Volume Down         470 ohm
114   * Minimum Mic DC resistance     1000 ohm
115   * Minimum Ear speaker impedance   16 ohm
116   * Note the first max value below must be less then the min. speaker impedance,
117   * to allow CTIA/OMTP detection to work. The other max values are the closest
118   * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
119   */
120  static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
121  	{ .max =  11, .key = KEY_PLAYPAUSE },
122  	{ .max = 186, .key = KEY_VOICECOMMAND },
123  	{ .max = 348, .key = KEY_VOLUMEUP },
124  	{ .max = 752, .key = KEY_VOLUMEDOWN },
125  };
126  
arizona_spi_acpi_probe(struct arizona * arizona)127  static int arizona_spi_acpi_probe(struct arizona *arizona)
128  {
129  	struct acpi_device *adev = ACPI_COMPANION(arizona->dev);
130  	int ret;
131  
132  	if (acpi_dev_hid_uid_match(adev, "10WM5102", NULL))
133  		ret = arizona_spi_acpi_android_probe(arizona);
134  	else
135  		ret = arizona_spi_acpi_windows_probe(arizona);
136  
137  	if (ret)
138  		return ret;
139  
140  	/*
141  	 * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
142  	 * The IRQ line will stay low when a new IRQ event happens between reading
143  	 * the IRQ status flags and acknowledging them. When the IRQ line stays
144  	 * low like this the IRQ will never trigger again when its type is set
145  	 * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
146  	 *
147  	 * Note theoretically it is possible that some boards are not capable
148  	 * of handling active low level interrupts. In that case setting the
149  	 * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
150  	 * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
151  	 * are a bug in the board's DSDT.
152  	 */
153  	arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
154  
155  	/* Wait 200 ms after jack insertion */
156  	arizona->pdata.micd_detect_debounce = 200;
157  
158  	/* Use standard AOSP values for headset-button mappings */
159  	arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
160  	arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
161  
162  	/* Use left headphone speaker for HP vs line-out detection */
163  	arizona->pdata.hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
164  
165  	return 0;
166  }
167  
168  static const struct acpi_device_id arizona_acpi_match[] = {
169  	{
170  		.id = "WM510204",
171  		.driver_data = WM5102,
172  	},
173  	{
174  		.id = "WM510205",
175  		.driver_data = WM5102,
176  	},
177  	{
178  		.id = "10WM5102",
179  		.driver_data = WM5102,
180  	},
181  	{ }
182  };
183  MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
184  #else
arizona_spi_acpi_probe(struct arizona * arizona)185  static int arizona_spi_acpi_probe(struct arizona *arizona)
186  {
187  	return -ENODEV;
188  }
189  #endif
190  
arizona_spi_probe(struct spi_device * spi)191  static int arizona_spi_probe(struct spi_device *spi)
192  {
193  	struct arizona *arizona;
194  	const struct regmap_config *regmap_config = NULL;
195  	unsigned long type = 0;
196  	int ret;
197  
198  	type = (unsigned long)spi_get_device_match_data(spi);
199  	switch (type) {
200  	case WM5102:
201  		if (IS_ENABLED(CONFIG_MFD_WM5102))
202  			regmap_config = &wm5102_spi_regmap;
203  		break;
204  	case WM5110:
205  	case WM8280:
206  		if (IS_ENABLED(CONFIG_MFD_WM5110))
207  			regmap_config = &wm5110_spi_regmap;
208  		break;
209  	case WM1831:
210  	case CS47L24:
211  		if (IS_ENABLED(CONFIG_MFD_CS47L24))
212  			regmap_config = &cs47l24_spi_regmap;
213  		break;
214  	default:
215  		dev_err(&spi->dev, "Unknown device type %ld\n", type);
216  		return -EINVAL;
217  	}
218  
219  	if (!regmap_config) {
220  		dev_err(&spi->dev,
221  			"No kernel support for device type %ld\n", type);
222  		return -EINVAL;
223  	}
224  
225  	arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL);
226  	if (arizona == NULL)
227  		return -ENOMEM;
228  
229  	arizona->regmap = devm_regmap_init_spi(spi, regmap_config);
230  	if (IS_ERR(arizona->regmap)) {
231  		ret = PTR_ERR(arizona->regmap);
232  		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
233  			ret);
234  		return ret;
235  	}
236  
237  	arizona->type = type;
238  	arizona->dev = &spi->dev;
239  	arizona->irq = spi->irq;
240  
241  	if (has_acpi_companion(&spi->dev)) {
242  		ret = arizona_spi_acpi_probe(arizona);
243  		if (ret)
244  			return ret;
245  	}
246  
247  	return arizona_dev_init(arizona);
248  }
249  
arizona_spi_remove(struct spi_device * spi)250  static void arizona_spi_remove(struct spi_device *spi)
251  {
252  	struct arizona *arizona = spi_get_drvdata(spi);
253  
254  	arizona_dev_exit(arizona);
255  }
256  
257  static const struct spi_device_id arizona_spi_ids[] = {
258  	{ "wm5102", WM5102 },
259  	{ "wm5110", WM5110 },
260  	{ "wm8280", WM8280 },
261  	{ "wm1831", WM1831 },
262  	{ "cs47l24", CS47L24 },
263  	{ },
264  };
265  MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
266  
267  #ifdef CONFIG_OF
268  static const struct of_device_id arizona_spi_of_match[] = {
269  	{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
270  	{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
271  	{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
272  	{ .compatible = "wlf,wm1831", .data = (void *)WM1831 },
273  	{ .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
274  	{},
275  };
276  MODULE_DEVICE_TABLE(of, arizona_spi_of_match);
277  #endif
278  
279  static struct spi_driver arizona_spi_driver = {
280  	.driver = {
281  		.name	= "arizona",
282  		.pm	= pm_ptr(&arizona_pm_ops),
283  		.of_match_table	= of_match_ptr(arizona_spi_of_match),
284  		.acpi_match_table = ACPI_PTR(arizona_acpi_match),
285  	},
286  	.probe		= arizona_spi_probe,
287  	.remove		= arizona_spi_remove,
288  	.id_table	= arizona_spi_ids,
289  };
290  
291  module_spi_driver(arizona_spi_driver);
292  
293  MODULE_SOFTDEP("pre: arizona_ldo1");
294  MODULE_DESCRIPTION("Arizona SPI bus interface");
295  MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
296  MODULE_LICENSE("GPL");
297