soc-component.c 13.5 KB
Newer Older
K
Kuninori Morimoto 已提交
1 2 3 4 5 6 7
// SPDX-License-Identifier: GPL-2.0
//
// soc-component.c
//
// Copyright (C) 2019 Renesas Electronics Corp.
// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
//
8
#include <linux/module.h>
K
Kuninori Morimoto 已提交
9 10
#include <sound/soc.h>

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
int snd_soc_component_initialize(struct snd_soc_component *component,
				 const struct snd_soc_component_driver *driver,
				 struct device *dev, const char *name)
{
	INIT_LIST_HEAD(&component->dai_list);
	INIT_LIST_HEAD(&component->dobj_list);
	INIT_LIST_HEAD(&component->card_list);
	mutex_init(&component->io_mutex);

	component->name		= name;
	component->dev		= dev;
	component->driver	= driver;

	return 0;
}

K
Kuninori Morimoto 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
/**
 * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
 * @component: COMPONENT
 * @clk_id: DAI specific clock ID
 * @source: Source for the clock
 * @freq: new clock frequency in Hz
 * @dir: new clock direction - input/output.
 *
 * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
 */
int snd_soc_component_set_sysclk(struct snd_soc_component *component,
				 int clk_id, int source, unsigned int freq,
				 int dir)
{
	if (component->driver->set_sysclk)
		return component->driver->set_sysclk(component, clk_id, source,
						     freq, dir);

	return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);

/*
 * snd_soc_component_set_pll - configure component PLL.
 * @component: COMPONENT
 * @pll_id: DAI specific PLL ID
 * @source: DAI specific source for the PLL
 * @freq_in: PLL input clock frequency in Hz
 * @freq_out: requested PLL output clock frequency in Hz
 *
 * Configures and enables PLL to generate output clock based on input clock.
 */
int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
			      int source, unsigned int freq_in,
			      unsigned int freq_out)
{
	if (component->driver->set_pll)
		return component->driver->set_pll(component, pll_id, source,
						  freq_in, freq_out);

	return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);

71 72 73 74 75 76 77
void snd_soc_component_seq_notifier(struct snd_soc_component *component,
				    enum snd_soc_dapm_type type, int subseq)
{
	if (component->driver->seq_notifier)
		component->driver->seq_notifier(component, type, subseq);
}

78 79 80 81 82 83 84 85 86
int snd_soc_component_stream_event(struct snd_soc_component *component,
				   int event)
{
	if (component->driver->stream_event)
		return component->driver->stream_event(component, event);

	return 0;
}

87 88 89 90 91 92 93 94 95
int snd_soc_component_set_bias_level(struct snd_soc_component *component,
				     enum snd_soc_bias_level level)
{
	if (component->driver->set_bias_level)
		return component->driver->set_bias_level(component, level);

	return 0;
}

96 97 98 99
static int soc_component_pin(struct snd_soc_component *component,
			     const char *pin,
			     int (*pin_func)(struct snd_soc_dapm_context *dapm,
					     const char *pin))
K
Kuninori Morimoto 已提交
100 101 102 103 104 105 106
{
	struct snd_soc_dapm_context *dapm =
		snd_soc_component_get_dapm(component);
	char *full_name;
	int ret;

	if (!component->name_prefix)
107
		return pin_func(dapm, pin);
K
Kuninori Morimoto 已提交
108 109 110 111 112

	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
	if (!full_name)
		return -ENOMEM;

113
	ret = pin_func(dapm, full_name);
K
Kuninori Morimoto 已提交
114 115 116 117
	kfree(full_name);

	return ret;
}
118 119 120 121 122 123

int snd_soc_component_enable_pin(struct snd_soc_component *component,
				 const char *pin)
{
	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
}
K
Kuninori Morimoto 已提交
124 125 126 127 128
EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);

int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
					  const char *pin)
{
129
	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
K
Kuninori Morimoto 已提交
130 131 132 133 134 135
}
EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);

int snd_soc_component_disable_pin(struct snd_soc_component *component,
				  const char *pin)
{
136
	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
K
Kuninori Morimoto 已提交
137 138 139 140 141 142
}
EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);

int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
					   const char *pin)
{
143
	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
K
Kuninori Morimoto 已提交
144 145 146 147 148 149
}
EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);

int snd_soc_component_nc_pin(struct snd_soc_component *component,
			     const char *pin)
{
150
	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
K
Kuninori Morimoto 已提交
151 152 153 154 155 156
}
EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);

int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
				      const char *pin)
{
157
	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
K
Kuninori Morimoto 已提交
158 159 160 161 162 163
}
EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);

int snd_soc_component_get_pin_status(struct snd_soc_component *component,
				     const char *pin)
{
164
	return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
K
Kuninori Morimoto 已提交
165 166 167 168 169 170
}
EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);

int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
				       const char *pin)
{
171
	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
K
Kuninori Morimoto 已提交
172 173 174 175 176 177 178
}
EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);

int snd_soc_component_force_enable_pin_unlocked(
	struct snd_soc_component *component,
	const char *pin)
{
179
	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
K
Kuninori Morimoto 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
}
EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);

/**
 * snd_soc_component_set_jack - configure component jack.
 * @component: COMPONENTs
 * @jack: structure to use for the jack
 * @data: can be used if codec driver need extra data for configuring jack
 *
 * Configures and enables jack detection function.
 */
int snd_soc_component_set_jack(struct snd_soc_component *component,
			       struct snd_soc_jack *jack, void *data)
{
	if (component->driver->set_jack)
		return component->driver->set_jack(component, jack, data);

	return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

int snd_soc_component_module_get(struct snd_soc_component *component,
				 int upon_open)
{
	if (component->driver->module_get_upon_open == !!upon_open &&
	    !try_module_get(component->dev->driver->owner))
		return -ENODEV;

	return 0;
}

void snd_soc_component_module_put(struct snd_soc_component *component,
				  int upon_open)
{
	if (component->driver->module_get_upon_open == !!upon_open)
		module_put(component->dev->driver->owner);
}
217 218 219 220

int snd_soc_component_open(struct snd_soc_component *component,
			   struct snd_pcm_substream *substream)
{
221 222
	if (component->driver->open)
		return component->driver->open(component, substream);
223 224
	return 0;
}
225 226 227 228

int snd_soc_component_close(struct snd_soc_component *component,
			    struct snd_pcm_substream *substream)
{
229 230
	if (component->driver->close)
		return component->driver->close(component, substream);
231 232
	return 0;
}
233 234 235 236

int snd_soc_component_prepare(struct snd_soc_component *component,
			      struct snd_pcm_substream *substream)
{
237 238
	if (component->driver->prepare)
		return component->driver->prepare(component, substream);
239 240
	return 0;
}
241 242 243 244 245

int snd_soc_component_hw_params(struct snd_soc_component *component,
				struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params)
{
246 247 248
	if (component->driver->hw_params)
		return component->driver->hw_params(component,
						    substream, params);
249 250
	return 0;
}
251 252 253 254

int snd_soc_component_hw_free(struct snd_soc_component *component,
			       struct snd_pcm_substream *substream)
{
255 256
	if (component->driver->hw_free)
		return component->driver->hw_free(component, substream);
257 258
	return 0;
}
259 260 261 262 263

int snd_soc_component_trigger(struct snd_soc_component *component,
			      struct snd_pcm_substream *substream,
			      int cmd)
{
264 265
	if (component->driver->trigger)
		return component->driver->trigger(component, substream, cmd);
266 267
	return 0;
}
268 269 270 271 272 273 274

void snd_soc_component_suspend(struct snd_soc_component *component)
{
	if (component->driver->suspend)
		component->driver->suspend(component);
	component->suspended = 1;
}
275 276 277 278 279 280 281

void snd_soc_component_resume(struct snd_soc_component *component)
{
	if (component->driver->resume)
		component->driver->resume(component);
	component->suspended = 0;
}
282 283 284 285 286

int snd_soc_component_is_suspended(struct snd_soc_component *component)
{
	return component->suspended;
}
287 288 289 290 291 292 293 294

int snd_soc_component_probe(struct snd_soc_component *component)
{
	if (component->driver->probe)
		return component->driver->probe(component);

	return 0;
}
295 296 297 298 299 300

void snd_soc_component_remove(struct snd_soc_component *component)
{
	if (component->driver->remove)
		component->driver->remove(component);
}
301 302 303 304 305 306 307 308 309

int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
				      struct device_node *ep)
{
	if (component->driver->of_xlate_dai_id)
		return component->driver->of_xlate_dai_id(component, ep);

	return -ENOTSUPP;
}
310 311 312 313 314 315 316 317 318 319

int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
					struct of_phandle_args *args,
					const char **dai_name)
{
	if (component->driver->of_xlate_dai_name)
		return component->driver->of_xlate_dai_name(component,
						     args, dai_name);
	return -ENOTSUPP;
}
320

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
void snd_soc_component_setup_regmap(struct snd_soc_component *component)
{
	int val_bytes = regmap_get_val_bytes(component->regmap);

	/* Errors are legitimate for non-integer byte multiples */
	if (val_bytes > 0)
		component->val_bytes = val_bytes;
}

#ifdef CONFIG_REGMAP

/**
 * snd_soc_component_init_regmap() - Initialize regmap instance for the
 *                                   component
 * @component: The component for which to initialize the regmap instance
 * @regmap: The regmap instance that should be used by the component
 *
 * This function allows deferred assignment of the regmap instance that is
 * associated with the component. Only use this if the regmap instance is not
 * yet ready when the component is registered. The function must also be called
 * before the first IO attempt of the component.
 */
void snd_soc_component_init_regmap(struct snd_soc_component *component,
				   struct regmap *regmap)
{
	component->regmap = regmap;
	snd_soc_component_setup_regmap(component);
}
EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);

/**
 * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
 *                                   component
 * @component: The component for which to de-initialize the regmap instance
 *
 * Calls regmap_exit() on the regmap instance associated to the component and
 * removes the regmap instance from the component.
 *
 * This function should only be used if snd_soc_component_init_regmap() was used
 * to initialize the regmap instance.
 */
void snd_soc_component_exit_regmap(struct snd_soc_component *component)
{
	regmap_exit(component->regmap);
	component->regmap = NULL;
}
EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);

#endif

371 372 373 374
int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
375
	int i;
376

377
	/* FIXME: use 1st pointer */
378
	for_each_rtd_components(rtd, i, component)
379 380
		if (component->driver->pointer)
			return component->driver->pointer(component, substream);
381 382 383

	return 0;
}
384 385 386 387 388 389

int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
				unsigned int cmd, void *arg)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
390
	int i;
391

392
	/* FIXME: use 1st ioctl */
393
	for_each_rtd_components(rtd, i, component)
394 395 396
		if (component->driver->ioctl)
			return component->driver->ioctl(component, substream,
							cmd, arg);
397 398 399

	return snd_pcm_lib_ioctl(substream, cmd, arg);
}
400

401 402 403 404
int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
405
	int i, ret;
406

407
	for_each_rtd_components(rtd, i, component) {
408
		if (component->driver->sync_stop) {
409 410 411 412 413 414 415 416 417 418
			ret = component->driver->sync_stop(component,
							   substream);
			if (ret < 0)
				return ret;
		}
	}

	return 0;
}

419 420 421 422 423 424
int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
				    int channel, unsigned long pos,
				    void __user *buf, unsigned long bytes)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
425
	int i;
426

427
	/* FIXME. it returns 1st copy now */
428
	for_each_rtd_components(rtd, i, component)
429 430 431
		if (component->driver->copy_user)
			return component->driver->copy_user(
				component, substream, channel, pos, buf, bytes);
432 433 434

	return -EINVAL;
}
435 436 437 438 439 440 441

struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
					unsigned long offset)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
	struct page *page;
442
	int i;
443

444
	/* FIXME. it returns 1st page now */
445
	for_each_rtd_components(rtd, i, component) {
446 447 448 449 450 451
		if (component->driver->page) {
			page = component->driver->page(component,
						       substream, offset);
			if (page)
				return page;
		}
452 453 454 455
	}

	return NULL;
}
456 457 458 459 460 461

int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
			       struct vm_area_struct *vma)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component;
462
	int i;
463

464
	/* FIXME. it returns 1st mmap now */
465
	for_each_rtd_components(rtd, i, component)
466 467 468
		if (component->driver->mmap)
			return component->driver->mmap(component,
						       substream, vma);
469 470 471

	return -EINVAL;
}
472

473
int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
474 475 476
{
	struct snd_soc_component *component;
	int ret;
477
	int i;
478

479
	for_each_rtd_components(rtd, i, component) {
480 481 482 483 484
		if (component->driver->pcm_construct) {
			ret = component->driver->pcm_construct(component, rtd);
			if (ret < 0)
				return ret;
		}
485 486 487 488
	}

	return 0;
}
489

490
void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
491 492
{
	struct snd_soc_component *component;
493
	int i;
494

495 496 497
	if (!rtd->pcm)
		return;

498
	for_each_rtd_components(rtd, i, component)
499
		if (component->driver->pcm_destruct)
500
			component->driver->pcm_destruct(component, rtd->pcm);
501
}