xref: /openbmc/linux/sound/soc/soc-component.c (revision 2b77dcc5)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // soc-component.c
4 //
5 // Copyright (C) 2019 Renesas Electronics Corp.
6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 //
8 #include <linux/module.h>
9 #include <sound/soc.h>
10 
11 /**
12  * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
13  * @component: COMPONENT
14  * @clk_id: DAI specific clock ID
15  * @source: Source for the clock
16  * @freq: new clock frequency in Hz
17  * @dir: new clock direction - input/output.
18  *
19  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
20  */
21 int snd_soc_component_set_sysclk(struct snd_soc_component *component,
22 				 int clk_id, int source, unsigned int freq,
23 				 int dir)
24 {
25 	if (component->driver->set_sysclk)
26 		return component->driver->set_sysclk(component, clk_id, source,
27 						     freq, dir);
28 
29 	return -ENOTSUPP;
30 }
31 EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
32 
33 /*
34  * snd_soc_component_set_pll - configure component PLL.
35  * @component: COMPONENT
36  * @pll_id: DAI specific PLL ID
37  * @source: DAI specific source for the PLL
38  * @freq_in: PLL input clock frequency in Hz
39  * @freq_out: requested PLL output clock frequency in Hz
40  *
41  * Configures and enables PLL to generate output clock based on input clock.
42  */
43 int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
44 			      int source, unsigned int freq_in,
45 			      unsigned int freq_out)
46 {
47 	if (component->driver->set_pll)
48 		return component->driver->set_pll(component, pll_id, source,
49 						  freq_in, freq_out);
50 
51 	return -EINVAL;
52 }
53 EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
54 
55 void snd_soc_component_seq_notifier(struct snd_soc_component *component,
56 				    enum snd_soc_dapm_type type, int subseq)
57 {
58 	if (component->driver->seq_notifier)
59 		component->driver->seq_notifier(component, type, subseq);
60 }
61 
62 int snd_soc_component_stream_event(struct snd_soc_component *component,
63 				   int event)
64 {
65 	if (component->driver->stream_event)
66 		return component->driver->stream_event(component, event);
67 
68 	return 0;
69 }
70 
71 int snd_soc_component_set_bias_level(struct snd_soc_component *component,
72 				     enum snd_soc_bias_level level)
73 {
74 	if (component->driver->set_bias_level)
75 		return component->driver->set_bias_level(component, level);
76 
77 	return 0;
78 }
79 
80 int snd_soc_component_enable_pin(struct snd_soc_component *component,
81 				 const char *pin)
82 {
83 	struct snd_soc_dapm_context *dapm =
84 		snd_soc_component_get_dapm(component);
85 	char *full_name;
86 	int ret;
87 
88 	if (!component->name_prefix)
89 		return snd_soc_dapm_enable_pin(dapm, pin);
90 
91 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
92 	if (!full_name)
93 		return -ENOMEM;
94 
95 	ret = snd_soc_dapm_enable_pin(dapm, full_name);
96 	kfree(full_name);
97 
98 	return ret;
99 }
100 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
101 
102 int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
103 					  const char *pin)
104 {
105 	struct snd_soc_dapm_context *dapm =
106 		snd_soc_component_get_dapm(component);
107 	char *full_name;
108 	int ret;
109 
110 	if (!component->name_prefix)
111 		return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
112 
113 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
114 	if (!full_name)
115 		return -ENOMEM;
116 
117 	ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name);
118 	kfree(full_name);
119 
120 	return ret;
121 }
122 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
123 
124 int snd_soc_component_disable_pin(struct snd_soc_component *component,
125 				  const char *pin)
126 {
127 	struct snd_soc_dapm_context *dapm =
128 		snd_soc_component_get_dapm(component);
129 	char *full_name;
130 	int ret;
131 
132 	if (!component->name_prefix)
133 		return snd_soc_dapm_disable_pin(dapm, pin);
134 
135 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
136 	if (!full_name)
137 		return -ENOMEM;
138 
139 	ret = snd_soc_dapm_disable_pin(dapm, full_name);
140 	kfree(full_name);
141 
142 	return ret;
143 }
144 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
145 
146 int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
147 					   const char *pin)
148 {
149 	struct snd_soc_dapm_context *dapm =
150 		snd_soc_component_get_dapm(component);
151 	char *full_name;
152 	int ret;
153 
154 	if (!component->name_prefix)
155 		return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
156 
157 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
158 	if (!full_name)
159 		return -ENOMEM;
160 
161 	ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name);
162 	kfree(full_name);
163 
164 	return ret;
165 }
166 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
167 
168 int snd_soc_component_nc_pin(struct snd_soc_component *component,
169 			     const char *pin)
170 {
171 	struct snd_soc_dapm_context *dapm =
172 		snd_soc_component_get_dapm(component);
173 	char *full_name;
174 	int ret;
175 
176 	if (!component->name_prefix)
177 		return snd_soc_dapm_nc_pin(dapm, pin);
178 
179 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
180 	if (!full_name)
181 		return -ENOMEM;
182 
183 	ret = snd_soc_dapm_nc_pin(dapm, full_name);
184 	kfree(full_name);
185 
186 	return ret;
187 }
188 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
189 
190 int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
191 				      const char *pin)
192 {
193 	struct snd_soc_dapm_context *dapm =
194 		snd_soc_component_get_dapm(component);
195 	char *full_name;
196 	int ret;
197 
198 	if (!component->name_prefix)
199 		return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
200 
201 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
202 	if (!full_name)
203 		return -ENOMEM;
204 
205 	ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name);
206 	kfree(full_name);
207 
208 	return ret;
209 }
210 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
211 
212 int snd_soc_component_get_pin_status(struct snd_soc_component *component,
213 				     const char *pin)
214 {
215 	struct snd_soc_dapm_context *dapm =
216 		snd_soc_component_get_dapm(component);
217 	char *full_name;
218 	int ret;
219 
220 	if (!component->name_prefix)
221 		return snd_soc_dapm_get_pin_status(dapm, pin);
222 
223 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
224 	if (!full_name)
225 		return -ENOMEM;
226 
227 	ret = snd_soc_dapm_get_pin_status(dapm, full_name);
228 	kfree(full_name);
229 
230 	return ret;
231 }
232 EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
233 
234 int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
235 				       const char *pin)
236 {
237 	struct snd_soc_dapm_context *dapm =
238 		snd_soc_component_get_dapm(component);
239 	char *full_name;
240 	int ret;
241 
242 	if (!component->name_prefix)
243 		return snd_soc_dapm_force_enable_pin(dapm, pin);
244 
245 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
246 	if (!full_name)
247 		return -ENOMEM;
248 
249 	ret = snd_soc_dapm_force_enable_pin(dapm, full_name);
250 	kfree(full_name);
251 
252 	return ret;
253 }
254 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
255 
256 int snd_soc_component_force_enable_pin_unlocked(
257 	struct snd_soc_component *component,
258 	const char *pin)
259 {
260 	struct snd_soc_dapm_context *dapm =
261 		snd_soc_component_get_dapm(component);
262 	char *full_name;
263 	int ret;
264 
265 	if (!component->name_prefix)
266 		return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
267 
268 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
269 	if (!full_name)
270 		return -ENOMEM;
271 
272 	ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name);
273 	kfree(full_name);
274 
275 	return ret;
276 }
277 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
278 
279 /**
280  * snd_soc_component_set_jack - configure component jack.
281  * @component: COMPONENTs
282  * @jack: structure to use for the jack
283  * @data: can be used if codec driver need extra data for configuring jack
284  *
285  * Configures and enables jack detection function.
286  */
287 int snd_soc_component_set_jack(struct snd_soc_component *component,
288 			       struct snd_soc_jack *jack, void *data)
289 {
290 	if (component->driver->set_jack)
291 		return component->driver->set_jack(component, jack, data);
292 
293 	return -ENOTSUPP;
294 }
295 EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
296 
297 int snd_soc_component_module_get(struct snd_soc_component *component,
298 				 int upon_open)
299 {
300 	if (component->driver->module_get_upon_open == !!upon_open &&
301 	    !try_module_get(component->dev->driver->owner))
302 		return -ENODEV;
303 
304 	return 0;
305 }
306 
307 void snd_soc_component_module_put(struct snd_soc_component *component,
308 				  int upon_open)
309 {
310 	if (component->driver->module_get_upon_open == !!upon_open)
311 		module_put(component->dev->driver->owner);
312 }
313 
314 int snd_soc_component_open(struct snd_soc_component *component,
315 			   struct snd_pcm_substream *substream)
316 {
317 	if (component->driver->ops &&
318 	    component->driver->ops->open)
319 		return component->driver->ops->open(substream);
320 
321 	return 0;
322 }
323 
324 int snd_soc_component_close(struct snd_soc_component *component,
325 			    struct snd_pcm_substream *substream)
326 {
327 	if (component->driver->ops &&
328 	    component->driver->ops->close)
329 		return component->driver->ops->close(substream);
330 
331 	return 0;
332 }
333 
334 int snd_soc_component_prepare(struct snd_soc_component *component,
335 			      struct snd_pcm_substream *substream)
336 {
337 	if (component->driver->ops &&
338 	    component->driver->ops->prepare)
339 		return component->driver->ops->prepare(substream);
340 
341 	return 0;
342 }
343 
344 int snd_soc_component_hw_params(struct snd_soc_component *component,
345 				struct snd_pcm_substream *substream,
346 				struct snd_pcm_hw_params *params)
347 {
348 	if (component->driver->ops &&
349 	    component->driver->ops->hw_params)
350 		return component->driver->ops->hw_params(substream, params);
351 
352 	return 0;
353 }
354 
355 int snd_soc_component_hw_free(struct snd_soc_component *component,
356 			       struct snd_pcm_substream *substream)
357 {
358 	if (component->driver->ops &&
359 	    component->driver->ops->hw_free)
360 		return component->driver->ops->hw_free(substream);
361 
362 	return 0;
363 }
364 
365 int snd_soc_component_trigger(struct snd_soc_component *component,
366 			      struct snd_pcm_substream *substream,
367 			      int cmd)
368 {
369 	if (component->driver->ops &&
370 	    component->driver->ops->trigger)
371 		return component->driver->ops->trigger(substream, cmd);
372 
373 	return 0;
374 }
375 
376 void snd_soc_component_suspend(struct snd_soc_component *component)
377 {
378 	if (component->driver->suspend)
379 		component->driver->suspend(component);
380 	component->suspended = 1;
381 }
382 
383 void snd_soc_component_resume(struct snd_soc_component *component)
384 {
385 	if (component->driver->resume)
386 		component->driver->resume(component);
387 	component->suspended = 0;
388 }
389 
390 int snd_soc_component_is_suspended(struct snd_soc_component *component)
391 {
392 	return component->suspended;
393 }
394 
395 int snd_soc_component_probe(struct snd_soc_component *component)
396 {
397 	if (component->driver->probe)
398 		return component->driver->probe(component);
399 
400 	return 0;
401 }
402 
403 void snd_soc_component_remove(struct snd_soc_component *component)
404 {
405 	if (component->driver->remove)
406 		component->driver->remove(component);
407 }
408 
409 int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
410 				      struct device_node *ep)
411 {
412 	if (component->driver->of_xlate_dai_id)
413 		return component->driver->of_xlate_dai_id(component, ep);
414 
415 	return -ENOTSUPP;
416 }
417 
418 int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
419 					struct of_phandle_args *args,
420 					const char **dai_name)
421 {
422 	if (component->driver->of_xlate_dai_name)
423 		return component->driver->of_xlate_dai_name(component,
424 						     args, dai_name);
425 	return -ENOTSUPP;
426 }
427 
428 int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
429 {
430 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
431 	struct snd_soc_component *component;
432 	struct snd_soc_rtdcom_list *rtdcom;
433 
434 	for_each_rtdcom(rtd, rtdcom) {
435 		component = rtdcom->component;
436 
437 		/* FIXME: use 1st pointer */
438 		if (component->driver->ops &&
439 		    component->driver->ops->pointer)
440 			return component->driver->ops->pointer(substream);
441 	}
442 
443 	return 0;
444 }
445 
446 int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
447 				unsigned int cmd, void *arg)
448 {
449 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
450 	struct snd_soc_component *component;
451 	struct snd_soc_rtdcom_list *rtdcom;
452 
453 	for_each_rtdcom(rtd, rtdcom) {
454 		component = rtdcom->component;
455 
456 		/* FIXME: use 1st ioctl */
457 		if (component->driver->ops &&
458 		    component->driver->ops->ioctl)
459 			return component->driver->ops->ioctl(substream,
460 							     cmd, arg);
461 	}
462 
463 	return snd_pcm_lib_ioctl(substream, cmd, arg);
464 }
465 
466 int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
467 				    int channel, unsigned long pos,
468 				    void __user *buf, unsigned long bytes)
469 {
470 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
471 	struct snd_soc_rtdcom_list *rtdcom;
472 	struct snd_soc_component *component;
473 
474 	for_each_rtdcom(rtd, rtdcom) {
475 		component = rtdcom->component;
476 
477 		/* FIXME. it returns 1st copy now */
478 		if (component->driver->ops &&
479 		    component->driver->ops->copy_user)
480 			return component->driver->ops->copy_user(
481 				substream, channel, pos, buf, bytes);
482 	}
483 
484 	return -EINVAL;
485 }
486 
487 struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
488 					unsigned long offset)
489 {
490 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
491 	struct snd_soc_rtdcom_list *rtdcom;
492 	struct snd_soc_component *component;
493 	struct page *page;
494 
495 	for_each_rtdcom(rtd, rtdcom) {
496 		component = rtdcom->component;
497 
498 		/* FIXME. it returns 1st page now */
499 		if (component->driver->ops &&
500 		    component->driver->ops->page) {
501 			page = component->driver->ops->page(substream, offset);
502 			if (page)
503 				return page;
504 		}
505 	}
506 
507 	return NULL;
508 }
509 
510 int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
511 			       struct vm_area_struct *vma)
512 {
513 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
514 	struct snd_soc_rtdcom_list *rtdcom;
515 	struct snd_soc_component *component;
516 
517 	for_each_rtdcom(rtd, rtdcom) {
518 		component = rtdcom->component;
519 
520 		/* FIXME. it returns 1st mmap now */
521 		if (component->driver->ops &&
522 		    component->driver->ops->mmap)
523 			return component->driver->ops->mmap(substream, vma);
524 	}
525 
526 	return -EINVAL;
527 }
528 
529 int snd_soc_pcm_component_new(struct snd_pcm *pcm)
530 {
531 	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
532 	struct snd_soc_rtdcom_list *rtdcom;
533 	struct snd_soc_component *component;
534 	int ret;
535 
536 	for_each_rtdcom(rtd, rtdcom) {
537 		component = rtdcom->component;
538 
539 		if (component->driver->pcm_new) {
540 			ret = component->driver->pcm_new(rtd);
541 			if (ret < 0)
542 				return ret;
543 		}
544 	}
545 
546 	return 0;
547 }
548 
549 void snd_soc_pcm_component_free(struct snd_pcm *pcm)
550 {
551 	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
552 	struct snd_soc_rtdcom_list *rtdcom;
553 	struct snd_soc_component *component;
554 
555 	for_each_rtdcom(rtd, rtdcom) {
556 		component = rtdcom->component;
557 
558 		if (component->driver->pcm_free)
559 			component->driver->pcm_free(pcm);
560 	}
561 }
562