1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // |
3 | // soc-ac97.c -- ALSA SoC Audio Layer AC97 support |
4 | // |
5 | // Copyright 2005 Wolfson Microelectronics PLC. |
6 | // Copyright 2005 Openedhand Ltd. |
7 | // Copyright (C) 2010 Slimlogic Ltd. |
8 | // Copyright (C) 2010 Texas Instruments Inc. |
9 | // |
10 | // Author: Liam Girdwood <lrg@slimlogic.co.uk> |
11 | // with code, comments and ideas from :- |
12 | // Richard Purdie <richard@openedhand.com> |
13 | |
14 | #include <linux/ctype.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/export.h> |
17 | #include <linux/gpio/consumer.h> |
18 | #include <linux/gpio/driver.h> |
19 | #include <linux/init.h> |
20 | #include <linux/of.h> |
21 | #include <linux/pinctrl/consumer.h> |
22 | #include <linux/slab.h> |
23 | #include <sound/ac97_codec.h> |
24 | #include <sound/soc.h> |
25 | |
26 | struct snd_ac97_reset_cfg { |
27 | struct pinctrl *pctl; |
28 | struct pinctrl_state *pstate_reset; |
29 | struct pinctrl_state *pstate_warm_reset; |
30 | struct pinctrl_state *pstate_run; |
31 | struct gpio_desc *reset_gpio; |
32 | struct gpio_desc *sdata_gpio; |
33 | struct gpio_desc *sync_gpio; |
34 | }; |
35 | |
36 | static struct snd_ac97_bus soc_ac97_bus = { |
37 | .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ |
38 | }; |
39 | |
40 | static void soc_ac97_device_release(struct device *dev) |
41 | { |
42 | kfree(to_ac97_t(dev)); |
43 | } |
44 | |
45 | #ifdef CONFIG_GPIOLIB |
46 | struct snd_ac97_gpio_priv { |
47 | struct gpio_chip gpio_chip; |
48 | unsigned int gpios_set; |
49 | struct snd_soc_component *component; |
50 | }; |
51 | |
52 | static inline struct snd_soc_component *gpio_to_component(struct gpio_chip *chip) |
53 | { |
54 | struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(gc: chip); |
55 | |
56 | return gpio_priv->component; |
57 | } |
58 | |
59 | static int snd_soc_ac97_gpio_request(struct gpio_chip *chip, unsigned int offset) |
60 | { |
61 | if (offset >= AC97_NUM_GPIOS) |
62 | return -EINVAL; |
63 | |
64 | return 0; |
65 | } |
66 | |
67 | static int snd_soc_ac97_gpio_direction_in(struct gpio_chip *chip, |
68 | unsigned int offset) |
69 | { |
70 | struct snd_soc_component *component = gpio_to_component(chip); |
71 | |
72 | dev_dbg(component->dev, "set gpio %d to output\n" , offset); |
73 | return snd_soc_component_update_bits(component, AC97_GPIO_CFG, |
74 | mask: 1 << offset, val: 1 << offset); |
75 | } |
76 | |
77 | static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned int offset) |
78 | { |
79 | struct snd_soc_component *component = gpio_to_component(chip); |
80 | int ret; |
81 | |
82 | ret = snd_soc_component_read(component, AC97_GPIO_STATUS); |
83 | |
84 | dev_dbg(component->dev, "get gpio %d : %d\n" , offset, |
85 | ret & (1 << offset)); |
86 | |
87 | return !!(ret & (1 << offset)); |
88 | } |
89 | |
90 | static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned int offset, |
91 | int value) |
92 | { |
93 | struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(gc: chip); |
94 | struct snd_soc_component *component = gpio_to_component(chip); |
95 | |
96 | gpio_priv->gpios_set &= ~(1 << offset); |
97 | gpio_priv->gpios_set |= (!!value) << offset; |
98 | snd_soc_component_write(component, AC97_GPIO_STATUS, |
99 | val: gpio_priv->gpios_set); |
100 | dev_dbg(component->dev, "set gpio %d to %d\n" , offset, !!value); |
101 | } |
102 | |
103 | static int snd_soc_ac97_gpio_direction_out(struct gpio_chip *chip, |
104 | unsigned offset, int value) |
105 | { |
106 | struct snd_soc_component *component = gpio_to_component(chip); |
107 | |
108 | dev_dbg(component->dev, "set gpio %d to output\n" , offset); |
109 | snd_soc_ac97_gpio_set(chip, offset, value); |
110 | return snd_soc_component_update_bits(component, AC97_GPIO_CFG, |
111 | mask: 1 << offset, val: 0); |
112 | } |
113 | |
114 | static const struct gpio_chip snd_soc_ac97_gpio_chip = { |
115 | .label = "snd_soc_ac97" , |
116 | .owner = THIS_MODULE, |
117 | .request = snd_soc_ac97_gpio_request, |
118 | .direction_input = snd_soc_ac97_gpio_direction_in, |
119 | .get = snd_soc_ac97_gpio_get, |
120 | .direction_output = snd_soc_ac97_gpio_direction_out, |
121 | .set = snd_soc_ac97_gpio_set, |
122 | .can_sleep = 1, |
123 | }; |
124 | |
125 | static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97, |
126 | struct snd_soc_component *component) |
127 | { |
128 | struct snd_ac97_gpio_priv *gpio_priv; |
129 | int ret; |
130 | |
131 | gpio_priv = devm_kzalloc(dev: component->dev, size: sizeof(*gpio_priv), GFP_KERNEL); |
132 | if (!gpio_priv) |
133 | return -ENOMEM; |
134 | ac97->gpio_priv = gpio_priv; |
135 | gpio_priv->component = component; |
136 | gpio_priv->gpio_chip = snd_soc_ac97_gpio_chip; |
137 | gpio_priv->gpio_chip.ngpio = AC97_NUM_GPIOS; |
138 | gpio_priv->gpio_chip.parent = component->dev; |
139 | gpio_priv->gpio_chip.base = -1; |
140 | |
141 | ret = gpiochip_add_data(&gpio_priv->gpio_chip, gpio_priv); |
142 | if (ret != 0) |
143 | dev_err(component->dev, "Failed to add GPIOs: %d\n" , ret); |
144 | return ret; |
145 | } |
146 | |
147 | static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97) |
148 | { |
149 | gpiochip_remove(gc: &ac97->gpio_priv->gpio_chip); |
150 | } |
151 | #else |
152 | static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97, |
153 | struct snd_soc_component *component) |
154 | { |
155 | return 0; |
156 | } |
157 | |
158 | static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97) |
159 | { |
160 | } |
161 | #endif |
162 | |
163 | /** |
164 | * snd_soc_alloc_ac97_component() - Allocate new a AC'97 device |
165 | * @component: The COMPONENT for which to create the AC'97 device |
166 | * |
167 | * Allocated a new snd_ac97 device and intializes it, but does not yet register |
168 | * it. The caller is responsible to either call device_add(&ac97->dev) to |
169 | * register the device, or to call put_device(&ac97->dev) to free the device. |
170 | * |
171 | * Returns: A snd_ac97 device or a PTR_ERR in case of an error. |
172 | */ |
173 | struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component) |
174 | { |
175 | struct snd_ac97 *ac97; |
176 | |
177 | ac97 = kzalloc(size: sizeof(struct snd_ac97), GFP_KERNEL); |
178 | if (ac97 == NULL) |
179 | return ERR_PTR(error: -ENOMEM); |
180 | |
181 | ac97->bus = &soc_ac97_bus; |
182 | ac97->num = 0; |
183 | |
184 | ac97->dev.bus = &ac97_bus_type; |
185 | ac97->dev.parent = component->card->dev; |
186 | ac97->dev.release = soc_ac97_device_release; |
187 | |
188 | dev_set_name(dev: &ac97->dev, name: "%d-%d:%s" , |
189 | component->card->snd_card->number, 0, |
190 | component->name); |
191 | |
192 | device_initialize(dev: &ac97->dev); |
193 | |
194 | return ac97; |
195 | } |
196 | EXPORT_SYMBOL(snd_soc_alloc_ac97_component); |
197 | |
198 | /** |
199 | * snd_soc_new_ac97_component - initailise AC97 device |
200 | * @component: audio component |
201 | * @id: The expected device ID |
202 | * @id_mask: Mask that is applied to the device ID before comparing with @id |
203 | * |
204 | * Initialises AC97 component resources for use by ad-hoc devices only. |
205 | * |
206 | * If @id is not 0 this function will reset the device, then read the ID from |
207 | * the device and check if it matches the expected ID. If it doesn't match an |
208 | * error will be returned and device will not be registered. |
209 | * |
210 | * Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success. |
211 | */ |
212 | struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, |
213 | unsigned int id, unsigned int id_mask) |
214 | { |
215 | struct snd_ac97 *ac97; |
216 | int ret; |
217 | |
218 | ac97 = snd_soc_alloc_ac97_component(component); |
219 | if (IS_ERR(ptr: ac97)) |
220 | return ac97; |
221 | |
222 | if (id) { |
223 | ret = snd_ac97_reset(ac97, try_warm: false, id, id_mask); |
224 | if (ret < 0) { |
225 | dev_err(component->dev, "Failed to reset AC97 device: %d\n" , |
226 | ret); |
227 | goto err_put_device; |
228 | } |
229 | } |
230 | |
231 | ret = device_add(dev: &ac97->dev); |
232 | if (ret) |
233 | goto err_put_device; |
234 | |
235 | ret = snd_soc_ac97_init_gpio(ac97, component); |
236 | if (ret) |
237 | goto err_put_device; |
238 | |
239 | return ac97; |
240 | |
241 | err_put_device: |
242 | put_device(dev: &ac97->dev); |
243 | return ERR_PTR(error: ret); |
244 | } |
245 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_component); |
246 | |
247 | /** |
248 | * snd_soc_free_ac97_component - free AC97 component device |
249 | * @ac97: snd_ac97 device to be freed |
250 | * |
251 | * Frees AC97 component device resources. |
252 | */ |
253 | void snd_soc_free_ac97_component(struct snd_ac97 *ac97) |
254 | { |
255 | snd_soc_ac97_free_gpio(ac97); |
256 | device_del(dev: &ac97->dev); |
257 | ac97->bus = NULL; |
258 | put_device(dev: &ac97->dev); |
259 | } |
260 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_component); |
261 | |
262 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; |
263 | |
264 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) |
265 | { |
266 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; |
267 | |
268 | pinctrl_select_state(p: pctl, s: snd_ac97_rst_cfg.pstate_warm_reset); |
269 | |
270 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.sync_gpio, value: 1); |
271 | |
272 | udelay(10); |
273 | |
274 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.sync_gpio, value: 0); |
275 | |
276 | pinctrl_select_state(p: pctl, s: snd_ac97_rst_cfg.pstate_run); |
277 | msleep(msecs: 2); |
278 | } |
279 | |
280 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) |
281 | { |
282 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; |
283 | |
284 | pinctrl_select_state(p: pctl, s: snd_ac97_rst_cfg.pstate_reset); |
285 | |
286 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.sync_gpio, value: 0); |
287 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.sdata_gpio, value: 0); |
288 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.reset_gpio, value: 0); |
289 | |
290 | udelay(10); |
291 | |
292 | gpiod_direction_output_raw(desc: snd_ac97_rst_cfg.reset_gpio, value: 1); |
293 | |
294 | pinctrl_select_state(p: pctl, s: snd_ac97_rst_cfg.pstate_run); |
295 | msleep(msecs: 2); |
296 | } |
297 | |
298 | static int snd_soc_ac97_parse_pinctl(struct device *dev, |
299 | struct snd_ac97_reset_cfg *cfg) |
300 | { |
301 | struct pinctrl *p; |
302 | struct pinctrl_state *state; |
303 | |
304 | p = devm_pinctrl_get(dev); |
305 | if (IS_ERR(ptr: p)) { |
306 | dev_err(dev, "Failed to get pinctrl\n" ); |
307 | return PTR_ERR(ptr: p); |
308 | } |
309 | cfg->pctl = p; |
310 | |
311 | state = pinctrl_lookup_state(p, name: "ac97-reset" ); |
312 | if (IS_ERR(ptr: state)) { |
313 | dev_err(dev, "Can't find pinctrl state ac97-reset\n" ); |
314 | return PTR_ERR(ptr: state); |
315 | } |
316 | cfg->pstate_reset = state; |
317 | |
318 | state = pinctrl_lookup_state(p, name: "ac97-warm-reset" ); |
319 | if (IS_ERR(ptr: state)) { |
320 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n" ); |
321 | return PTR_ERR(ptr: state); |
322 | } |
323 | cfg->pstate_warm_reset = state; |
324 | |
325 | state = pinctrl_lookup_state(p, name: "ac97-running" ); |
326 | if (IS_ERR(ptr: state)) { |
327 | dev_err(dev, "Can't find pinctrl state ac97-running\n" ); |
328 | return PTR_ERR(ptr: state); |
329 | } |
330 | cfg->pstate_run = state; |
331 | |
332 | cfg->sync_gpio = devm_gpiod_get_index(dev, con_id: "ac97" , idx: 0, flags: GPIOD_ASIS); |
333 | if (IS_ERR(ptr: cfg->sync_gpio)) |
334 | return dev_err_probe(dev, err: PTR_ERR(ptr: cfg->sync_gpio), fmt: "Can't find ac97-sync gpio\n" ); |
335 | gpiod_set_consumer_name(desc: cfg->sync_gpio, name: "AC97 link sync" ); |
336 | |
337 | cfg->sdata_gpio = devm_gpiod_get_index(dev, con_id: "ac97" , idx: 1, flags: GPIOD_ASIS); |
338 | if (IS_ERR(ptr: cfg->sdata_gpio)) |
339 | return dev_err_probe(dev, err: PTR_ERR(ptr: cfg->sdata_gpio), fmt: "Can't find ac97-sdata gpio\n" ); |
340 | gpiod_set_consumer_name(desc: cfg->sdata_gpio, name: "AC97 link sdata" ); |
341 | |
342 | cfg->reset_gpio = devm_gpiod_get_index(dev, con_id: "ac97" , idx: 2, flags: GPIOD_ASIS); |
343 | if (IS_ERR(ptr: cfg->reset_gpio)) |
344 | return dev_err_probe(dev, err: PTR_ERR(ptr: cfg->reset_gpio), fmt: "Can't find ac97-reset gpio\n" ); |
345 | gpiod_set_consumer_name(desc: cfg->reset_gpio, name: "AC97 link reset" ); |
346 | |
347 | return 0; |
348 | } |
349 | |
350 | struct snd_ac97_bus_ops *soc_ac97_ops; |
351 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
352 | |
353 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) |
354 | { |
355 | if (ops == soc_ac97_ops) |
356 | return 0; |
357 | |
358 | if (soc_ac97_ops && ops) |
359 | return -EBUSY; |
360 | |
361 | soc_ac97_ops = ops; |
362 | soc_ac97_bus.ops = ops; |
363 | |
364 | return 0; |
365 | } |
366 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); |
367 | |
368 | /** |
369 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions |
370 | * @ops: bus ops |
371 | * @pdev: platform device |
372 | * |
373 | * This function sets the reset and warm_reset properties of ops and parses |
374 | * the device node of pdev to get pinctrl states and gpio numbers to use. |
375 | */ |
376 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, |
377 | struct platform_device *pdev) |
378 | { |
379 | struct device *dev = &pdev->dev; |
380 | struct snd_ac97_reset_cfg cfg; |
381 | int ret; |
382 | |
383 | ret = snd_soc_ac97_parse_pinctl(dev, cfg: &cfg); |
384 | if (ret) |
385 | return ret; |
386 | |
387 | ret = snd_soc_set_ac97_ops(ops); |
388 | if (ret) |
389 | return ret; |
390 | |
391 | ops->warm_reset = snd_soc_ac97_warm_reset; |
392 | ops->reset = snd_soc_ac97_reset; |
393 | |
394 | snd_ac97_rst_cfg = cfg; |
395 | return 0; |
396 | } |
397 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); |
398 | |