blob: ad65459da28e0a1f77e38e30c376939f26f55aa8 [file] [log] [blame]
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001/*
2 * soc-core.c -- ALSA SoC Audio Layer
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
Liam Girdwood0664d882006-12-18 14:39:02 +01005 * Copyright 2005 Openedhand Ltd.
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00006 * Copyright (C) 2010 Slimlogic Ltd.
7 * Copyright (C) 2010 Texas Instruments Inc.
Liam Girdwood0664d882006-12-18 14:39:02 +01008 *
Liam Girdwoodd3311242008-10-12 13:17:36 +01009 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
Liam Girdwood0664d882006-12-18 14:39:02 +010010 * with code, comments and ideas from :-
11 * Richard Purdie <richard@openedhand.com>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020012 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
Frank Mandarinodb2a4162006-10-06 18:31:09 +020018 * TODO:
19 * o Add hw rules to enforce rates, etc.
20 * o More testing with other codecs/machines.
21 * o Add more codecs and platforms to ensure good API coverage.
22 * o Support TDM on PCM and I2S
23 */
24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/bitops.h>
Troy Kisky12ef1932008-10-13 17:42:14 -070031#include <linux/debugfs.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020032#include <linux/platform_device.h>
Mark Brownf0e8ed82011-09-20 11:41:54 +010033#include <linux/ctype.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/slab.h>
Stephen Warrenbec4fa02011-12-12 15:55:34 -070035#include <linux/of.h>
Marek Vasut474828a2009-07-22 13:01:03 +020036#include <sound/ac97_codec.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020037#include <sound/core.h>
Mark Brown3028eb82010-12-05 12:22:46 +000038#include <sound/jack.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020039#include <sound/pcm.h>
40#include <sound/pcm_params.h>
41#include <sound/soc.h>
Liam Girdwood01d75842012-04-25 12:12:49 +010042#include <sound/soc-dpcm.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020043#include <sound/initval.h>
44
Mark Browna8b1d342010-11-03 18:05:58 -040045#define CREATE_TRACE_POINTS
46#include <trace/events/asoc.h>
47
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000048#define NAME_SIZE 32
49
Frank Mandarinodb2a4162006-10-06 18:31:09 +020050static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
51
Mark Brown384c89e2008-12-03 17:34:03 +000052#ifdef CONFIG_DEBUG_FS
Mark Brown8a9dab12011-01-10 22:25:21 +000053struct dentry *snd_soc_debugfs_root;
54EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
Mark Brown384c89e2008-12-03 17:34:03 +000055#endif
56
Mark Brownc5af3a22008-11-28 13:29:45 +000057static DEFINE_MUTEX(client_mutex);
Mark Brown91151712008-11-30 23:31:24 +000058static LIST_HEAD(dai_list);
Mark Brown12a48a8c2008-12-03 19:40:30 +000059static LIST_HEAD(platform_list);
Mark Brown0d0cf002008-12-10 14:32:45 +000060static LIST_HEAD(codec_list);
Mark Brownc5af3a22008-11-28 13:29:45 +000061
Frank Mandarinodb2a4162006-10-06 18:31:09 +020062/*
63 * This is a timeout to do a DAPM powerdown after a stream is closed().
64 * It can be used to eliminate pops between different playback streams, e.g.
65 * between two audio tracks.
66 */
67static int pmdown_time = 5000;
68module_param(pmdown_time, int, 0);
69MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
70
Dimitris Papastamos2bc9a812011-02-01 12:24:08 +000071/* returns the minimum number of bytes needed to represent
72 * a particular given value */
73static int min_bytes_needed(unsigned long val)
74{
75 int c = 0;
76 int i;
77
78 for (i = (sizeof val * 8) - 1; i >= 0; --i, ++c)
79 if (val & (1UL << i))
80 break;
81 c = (sizeof val * 8) - c;
82 if (!c || (c % 8))
83 c = (c + 8) / 8;
84 else
85 c /= 8;
86 return c;
87}
88
Dimitris Papastamos13fd1792011-02-02 13:58:58 +000089/* fill buf which is 'len' bytes with a formatted
90 * string of the form 'reg: value\n' */
91static int format_register_str(struct snd_soc_codec *codec,
92 unsigned int reg, char *buf, size_t len)
Mark Brown2624d5f2009-11-03 21:56:13 +000093{
Stephen Warren00b317a2011-04-01 14:50:44 -060094 int wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
95 int regsize = codec->driver->reg_word_size * 2;
Dimitris Papastamos13fd1792011-02-02 13:58:58 +000096 int ret;
97 char tmpbuf[len + 1];
98 char regbuf[regsize + 1];
99
100 /* since tmpbuf is allocated on the stack, warn the callers if they
101 * try to abuse this function */
102 WARN_ON(len > 63);
103
104 /* +2 for ': ' and + 1 for '\n' */
105 if (wordsize + regsize + 2 + 1 != len)
106 return -EINVAL;
107
Mark Brown25032c12011-08-01 13:52:48 +0900108 ret = snd_soc_read(codec, reg);
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000109 if (ret < 0) {
110 memset(regbuf, 'X', regsize);
111 regbuf[regsize] = '\0';
112 } else {
113 snprintf(regbuf, regsize + 1, "%.*x", regsize, ret);
114 }
115
116 /* prepare the buffer */
117 snprintf(tmpbuf, len + 1, "%.*x: %s\n", wordsize, reg, regbuf);
118 /* copy it back to the caller without the '\0' */
119 memcpy(buf, tmpbuf, len);
120
121 return 0;
122}
123
124/* codec register dump */
125static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
126 size_t count, loff_t pos)
127{
128 int i, step = 1;
Dimitris Papastamos2bc9a812011-02-01 12:24:08 +0000129 int wordsize, regsize;
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000130 int len;
131 size_t total = 0;
132 loff_t p = 0;
Dimitris Papastamos2bc9a812011-02-01 12:24:08 +0000133
Stephen Warren00b317a2011-04-01 14:50:44 -0600134 wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
135 regsize = codec->driver->reg_word_size * 2;
Mark Brown2624d5f2009-11-03 21:56:13 +0000136
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000137 len = wordsize + regsize + 2 + 1;
138
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000139 if (!codec->driver->reg_cache_size)
Mark Brown2624d5f2009-11-03 21:56:13 +0000140 return 0;
141
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000142 if (codec->driver->reg_cache_step)
143 step = codec->driver->reg_cache_step;
Mark Brown2624d5f2009-11-03 21:56:13 +0000144
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000145 for (i = 0; i < codec->driver->reg_cache_size; i += step) {
Lars-Peter Clausenb92d1502011-08-27 18:24:14 +0200146 if (!snd_soc_codec_readable_register(codec, i))
Mark Brown2624d5f2009-11-03 21:56:13 +0000147 continue;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000148 if (codec->driver->display_register) {
149 count += codec->driver->display_register(codec, buf + count,
Mark Brown2624d5f2009-11-03 21:56:13 +0000150 PAGE_SIZE - count, i);
Mark Brown5164d742010-07-14 16:14:33 +0100151 } else {
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000152 /* only support larger than PAGE_SIZE bytes debugfs
153 * entries for the default case */
154 if (p >= pos) {
155 if (total + len >= count - 1)
156 break;
157 format_register_str(codec, i, buf + total, len);
158 total += len;
159 }
160 p += len;
Mark Brown5164d742010-07-14 16:14:33 +0100161 }
Mark Brown2624d5f2009-11-03 21:56:13 +0000162 }
163
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000164 total = min(total, count - 1);
Mark Brown2624d5f2009-11-03 21:56:13 +0000165
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000166 return total;
Mark Brown2624d5f2009-11-03 21:56:13 +0000167}
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000168
Mark Brown2624d5f2009-11-03 21:56:13 +0000169static ssize_t codec_reg_show(struct device *dev,
170 struct device_attribute *attr, char *buf)
171{
Mark Brown36ae1a92012-01-06 17:12:45 -0800172 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000173
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000174 return soc_codec_reg_show(rtd->codec, buf, PAGE_SIZE, 0);
Mark Brown2624d5f2009-11-03 21:56:13 +0000175}
176
177static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
178
Mark Browndbe21402010-02-12 11:37:24 +0000179static ssize_t pmdown_time_show(struct device *dev,
180 struct device_attribute *attr, char *buf)
181{
Mark Brown36ae1a92012-01-06 17:12:45 -0800182 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
Mark Browndbe21402010-02-12 11:37:24 +0000183
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000184 return sprintf(buf, "%ld\n", rtd->pmdown_time);
Mark Browndbe21402010-02-12 11:37:24 +0000185}
186
187static ssize_t pmdown_time_set(struct device *dev,
188 struct device_attribute *attr,
189 const char *buf, size_t count)
190{
Mark Brown36ae1a92012-01-06 17:12:45 -0800191 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
Mark Brownc593b522010-10-27 20:11:17 -0700192 int ret;
Mark Browndbe21402010-02-12 11:37:24 +0000193
Mark Brownc593b522010-10-27 20:11:17 -0700194 ret = strict_strtol(buf, 10, &rtd->pmdown_time);
195 if (ret)
196 return ret;
Mark Browndbe21402010-02-12 11:37:24 +0000197
198 return count;
199}
200
201static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set);
202
Mark Brown2624d5f2009-11-03 21:56:13 +0000203#ifdef CONFIG_DEBUG_FS
Mark Brown2624d5f2009-11-03 21:56:13 +0000204static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000205 size_t count, loff_t *ppos)
Mark Brown2624d5f2009-11-03 21:56:13 +0000206{
207 ssize_t ret;
208 struct snd_soc_codec *codec = file->private_data;
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000209 char *buf;
210
211 if (*ppos < 0 || !count)
212 return -EINVAL;
213
214 buf = kmalloc(count, GFP_KERNEL);
Mark Brown2624d5f2009-11-03 21:56:13 +0000215 if (!buf)
216 return -ENOMEM;
Dimitris Papastamos13fd1792011-02-02 13:58:58 +0000217
218 ret = soc_codec_reg_show(codec, buf, count, *ppos);
219 if (ret >= 0) {
220 if (copy_to_user(user_buf, buf, ret)) {
221 kfree(buf);
222 return -EFAULT;
223 }
224 *ppos += ret;
225 }
226
Mark Brown2624d5f2009-11-03 21:56:13 +0000227 kfree(buf);
228 return ret;
229}
230
231static ssize_t codec_reg_write_file(struct file *file,
232 const char __user *user_buf, size_t count, loff_t *ppos)
233{
234 char buf[32];
Stephen Boyd34e268d2011-05-12 16:50:10 -0700235 size_t buf_size;
Mark Brown2624d5f2009-11-03 21:56:13 +0000236 char *start = buf;
237 unsigned long reg, value;
Mark Brown2624d5f2009-11-03 21:56:13 +0000238 struct snd_soc_codec *codec = file->private_data;
239
240 buf_size = min(count, (sizeof(buf)-1));
241 if (copy_from_user(buf, user_buf, buf_size))
242 return -EFAULT;
243 buf[buf_size] = 0;
244
Mark Brown2624d5f2009-11-03 21:56:13 +0000245 while (*start == ' ')
246 start++;
247 reg = simple_strtoul(start, &start, 16);
Mark Brown2624d5f2009-11-03 21:56:13 +0000248 while (*start == ' ')
249 start++;
250 if (strict_strtoul(start, 16, &value))
251 return -EINVAL;
Mark Brown0d51a9c2011-01-06 16:04:57 +0000252
253 /* Userspace has been fiddling around behind the kernel's back */
254 add_taint(TAINT_USER);
255
Dimitris Papastamose4f078d2010-12-07 16:30:38 +0000256 snd_soc_write(codec, reg, value);
Mark Brown2624d5f2009-11-03 21:56:13 +0000257 return buf_size;
258}
259
260static const struct file_operations codec_reg_fops = {
Stephen Boyd234e3402012-04-05 14:25:11 -0700261 .open = simple_open,
Mark Brown2624d5f2009-11-03 21:56:13 +0000262 .read = codec_reg_read_file,
263 .write = codec_reg_write_file,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200264 .llseek = default_llseek,
Mark Brown2624d5f2009-11-03 21:56:13 +0000265};
266
267static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
268{
Jarkko Nikulad6ce4cf2010-11-05 20:35:20 +0200269 struct dentry *debugfs_card_root = codec->card->debugfs_card_root;
270
271 codec->debugfs_codec_root = debugfs_create_dir(codec->name,
272 debugfs_card_root);
Mark Brown2624d5f2009-11-03 21:56:13 +0000273 if (!codec->debugfs_codec_root) {
Liam Girdwood64e60f92012-02-15 15:15:37 +0000274 dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
Mark Brown2624d5f2009-11-03 21:56:13 +0000275 return;
276 }
277
Mark Brownaaee8ef2011-01-26 20:53:50 +0000278 debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root,
279 &codec->cache_sync);
280 debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root,
281 &codec->cache_only);
282
Mark Brown2624d5f2009-11-03 21:56:13 +0000283 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
284 codec->debugfs_codec_root,
285 codec, &codec_reg_fops);
286 if (!codec->debugfs_reg)
Liam Girdwood64e60f92012-02-15 15:15:37 +0000287 dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
Mark Brown2624d5f2009-11-03 21:56:13 +0000288
Lars-Peter Clausen8eecaf62011-04-30 19:45:48 +0200289 snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
Mark Brown2624d5f2009-11-03 21:56:13 +0000290}
291
292static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
293{
294 debugfs_remove_recursive(codec->debugfs_codec_root);
295}
296
Sebastien Guiriec731f1ab2012-02-15 15:25:31 +0000297static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
298{
299 struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
300
301 platform->debugfs_platform_root = debugfs_create_dir(platform->name,
302 debugfs_card_root);
303 if (!platform->debugfs_platform_root) {
304 dev_warn(platform->dev,
305 "Failed to create platform debugfs directory\n");
306 return;
307 }
308
309 snd_soc_dapm_debugfs_init(&platform->dapm,
310 platform->debugfs_platform_root);
311}
312
313static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
314{
315 debugfs_remove_recursive(platform->debugfs_platform_root);
316}
317
Mark Brownc3c5a192010-09-15 18:15:14 +0100318static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
319 size_t count, loff_t *ppos)
320{
321 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
Mark Brown2b194f9d2010-10-13 10:52:16 +0100322 ssize_t len, ret = 0;
Mark Brownc3c5a192010-09-15 18:15:14 +0100323 struct snd_soc_codec *codec;
324
325 if (!buf)
326 return -ENOMEM;
327
Mark Brown2b194f9d2010-10-13 10:52:16 +0100328 list_for_each_entry(codec, &codec_list, list) {
329 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
330 codec->name);
331 if (len >= 0)
332 ret += len;
333 if (ret > PAGE_SIZE) {
334 ret = PAGE_SIZE;
335 break;
336 }
337 }
Mark Brownc3c5a192010-09-15 18:15:14 +0100338
339 if (ret >= 0)
340 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
341
342 kfree(buf);
343
344 return ret;
345}
346
347static const struct file_operations codec_list_fops = {
348 .read = codec_list_read_file,
349 .llseek = default_llseek,/* read accesses f_pos */
350};
351
Mark Brownf3208782010-09-15 18:19:07 +0100352static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
353 size_t count, loff_t *ppos)
354{
355 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
Mark Brown2b194f9d2010-10-13 10:52:16 +0100356 ssize_t len, ret = 0;
Mark Brownf3208782010-09-15 18:19:07 +0100357 struct snd_soc_dai *dai;
358
359 if (!buf)
360 return -ENOMEM;
361
Mark Brown2b194f9d2010-10-13 10:52:16 +0100362 list_for_each_entry(dai, &dai_list, list) {
363 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name);
364 if (len >= 0)
365 ret += len;
366 if (ret > PAGE_SIZE) {
367 ret = PAGE_SIZE;
368 break;
369 }
370 }
Mark Brownf3208782010-09-15 18:19:07 +0100371
Mark Brown2b194f9d2010-10-13 10:52:16 +0100372 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
Mark Brownf3208782010-09-15 18:19:07 +0100373
374 kfree(buf);
375
376 return ret;
377}
378
379static const struct file_operations dai_list_fops = {
380 .read = dai_list_read_file,
381 .llseek = default_llseek,/* read accesses f_pos */
382};
383
Mark Brown19c7ac22010-09-15 18:22:40 +0100384static ssize_t platform_list_read_file(struct file *file,
385 char __user *user_buf,
386 size_t count, loff_t *ppos)
387{
388 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
Mark Brown2b194f9d2010-10-13 10:52:16 +0100389 ssize_t len, ret = 0;
Mark Brown19c7ac22010-09-15 18:22:40 +0100390 struct snd_soc_platform *platform;
391
392 if (!buf)
393 return -ENOMEM;
394
Mark Brown2b194f9d2010-10-13 10:52:16 +0100395 list_for_each_entry(platform, &platform_list, list) {
396 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
397 platform->name);
398 if (len >= 0)
399 ret += len;
400 if (ret > PAGE_SIZE) {
401 ret = PAGE_SIZE;
402 break;
403 }
404 }
Mark Brown19c7ac22010-09-15 18:22:40 +0100405
Mark Brown2b194f9d2010-10-13 10:52:16 +0100406 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
Mark Brown19c7ac22010-09-15 18:22:40 +0100407
408 kfree(buf);
409
410 return ret;
411}
412
413static const struct file_operations platform_list_fops = {
414 .read = platform_list_read_file,
415 .llseek = default_llseek,/* read accesses f_pos */
416};
417
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200418static void soc_init_card_debugfs(struct snd_soc_card *card)
419{
420 card->debugfs_card_root = debugfs_create_dir(card->name,
Mark Brown8a9dab12011-01-10 22:25:21 +0000421 snd_soc_debugfs_root);
Jarkko Nikula3a45b862010-11-05 20:35:21 +0200422 if (!card->debugfs_card_root) {
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200423 dev_warn(card->dev,
Lothar Waßmann7c08be82011-12-09 14:16:29 +0100424 "ASoC: Failed to create card debugfs directory\n");
Jarkko Nikula3a45b862010-11-05 20:35:21 +0200425 return;
426 }
427
428 card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644,
429 card->debugfs_card_root,
430 &card->pop_time);
431 if (!card->debugfs_pop_time)
432 dev_warn(card->dev,
433 "Failed to create pop time debugfs file\n");
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200434}
435
436static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
437{
438 debugfs_remove_recursive(card->debugfs_card_root);
439}
440
Mark Brown2624d5f2009-11-03 21:56:13 +0000441#else
442
443static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
444{
445}
446
447static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
448{
449}
Axel Linb95fccb2010-11-09 17:06:44 +0800450
Sebastien Guiriec731f1ab2012-02-15 15:25:31 +0000451static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
452{
453}
454
455static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
456{
457}
458
Axel Linb95fccb2010-11-09 17:06:44 +0800459static inline void soc_init_card_debugfs(struct snd_soc_card *card)
460{
461}
462
463static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card)
464{
465}
Mark Brown2624d5f2009-11-03 21:56:13 +0000466#endif
467
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100468struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
469 const char *dai_link, int stream)
470{
471 int i;
472
473 for (i = 0; i < card->num_links; i++) {
474 if (card->rtd[i].dai_link->no_pcm &&
475 !strcmp(card->rtd[i].dai_link->name, dai_link))
476 return card->rtd[i].pcm->streams[stream].substream;
477 }
478 dev_dbg(card->dev, "failed to find dai link %s\n", dai_link);
479 return NULL;
480}
481EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
482
483struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
484 const char *dai_link)
485{
486 int i;
487
488 for (i = 0; i < card->num_links; i++) {
489 if (!strcmp(card->rtd[i].dai_link->name, dai_link))
490 return &card->rtd[i];
491 }
492 dev_dbg(card->dev, "failed to find rtd %s\n", dai_link);
493 return NULL;
494}
495EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
496
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200497#ifdef CONFIG_SND_SOC_AC97_BUS
498/* unregister ac97 codec */
499static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
500{
501 if (codec->ac97->dev.bus)
502 device_unregister(&codec->ac97->dev);
503 return 0;
504}
505
506/* stop no dev release warning */
507static void soc_ac97_device_release(struct device *dev){}
508
509/* register ac97 codec to bus */
510static int soc_ac97_dev_register(struct snd_soc_codec *codec)
511{
512 int err;
513
514 codec->ac97->dev.bus = &ac97_bus_type;
Mark Brown4ac5c612009-04-01 19:35:01 +0100515 codec->ac97->dev.parent = codec->card->dev;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200516 codec->ac97->dev.release = soc_ac97_device_release;
517
Kay Sieversbb072bf2008-11-02 03:50:35 +0100518 dev_set_name(&codec->ac97->dev, "%d-%d:%s",
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000519 codec->card->snd_card->number, 0, codec->name);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200520 err = device_register(&codec->ac97->dev);
521 if (err < 0) {
522 snd_printk(KERN_ERR "Can't register ac97 bus\n");
523 codec->ac97->dev.bus = NULL;
524 return err;
525 }
526 return 0;
527}
528#endif
529
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000530#ifdef CONFIG_PM_SLEEP
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200531/* powers down audio subsystem for suspend */
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000532int snd_soc_suspend(struct device *dev)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200533{
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000534 struct snd_soc_card *card = dev_get_drvdata(dev);
Jarkko Nikula2eea3922010-11-25 17:47:38 +0200535 struct snd_soc_codec *codec;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200536 int i;
537
Daniel Macke3509ff2009-06-03 17:44:49 +0200538 /* If the initialization of this soc device failed, there is no codec
539 * associated with it. Just bail out in this case.
540 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000541 if (list_empty(&card->codec_dev_list))
Daniel Macke3509ff2009-06-03 17:44:49 +0200542 return 0;
543
Andy Green6ed25972008-06-13 16:24:05 +0100544 /* Due to the resume being scheduled into a workqueue we could
545 * suspend before that's finished - wait for it to complete.
546 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000547 snd_power_lock(card->snd_card);
548 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
549 snd_power_unlock(card->snd_card);
Andy Green6ed25972008-06-13 16:24:05 +0100550
551 /* we're going to block userspace touching us until resume completes */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000552 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
Andy Green6ed25972008-06-13 16:24:05 +0100553
Mark Browna00f90f2010-12-02 16:24:24 +0000554 /* mute any active DACs */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000555 for (i = 0; i < card->num_rtd; i++) {
556 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
557 struct snd_soc_dai_driver *drv = dai->driver;
Mark Brown3efab7d2010-05-09 13:25:43 +0100558
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000559 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100560 continue;
561
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000562 if (drv->ops->digital_mute && dai->playback_active)
563 drv->ops->digital_mute(dai, 1);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200564 }
565
Liam Girdwood4ccab3e2008-01-10 14:39:01 +0100566 /* suspend all pcms */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000567 for (i = 0; i < card->num_rtd; i++) {
568 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100569 continue;
570
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000571 snd_pcm_suspend_all(card->rtd[i].pcm);
Mark Brown3efab7d2010-05-09 13:25:43 +0100572 }
Liam Girdwood4ccab3e2008-01-10 14:39:01 +0100573
Mark Brown87506542008-11-18 20:50:34 +0000574 if (card->suspend_pre)
Mark Brown70b2ac12011-01-26 14:05:25 +0000575 card->suspend_pre(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200576
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000577 for (i = 0; i < card->num_rtd; i++) {
578 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
579 struct snd_soc_platform *platform = card->rtd[i].platform;
Mark Brown3efab7d2010-05-09 13:25:43 +0100580
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000581 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100582 continue;
583
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000584 if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
585 cpu_dai->driver->suspend(cpu_dai);
586 if (platform->driver->suspend && !platform->suspended) {
587 platform->driver->suspend(cpu_dai);
588 platform->suspended = 1;
Mark Brown1547aba2010-05-07 21:11:40 +0100589 }
590 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200591
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000592 /* close any waiting streams and save state */
593 for (i = 0; i < card->num_rtd; i++) {
Tejun Heo5b84ba22010-12-11 17:51:26 +0100594 flush_delayed_work_sync(&card->rtd[i].delayed_work);
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200595 card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000596 }
Mark Brown3efab7d2010-05-09 13:25:43 +0100597
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000598 for (i = 0; i < card->num_rtd; i++) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000599
600 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100601 continue;
602
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800603 snd_soc_dapm_stream_event(&card->rtd[i],
604 SNDRV_PCM_STREAM_PLAYBACK,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800605 SND_SOC_DAPM_STREAM_SUSPEND);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000606
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800607 snd_soc_dapm_stream_event(&card->rtd[i],
608 SNDRV_PCM_STREAM_CAPTURE,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800609 SND_SOC_DAPM_STREAM_SUSPEND);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000610 }
611
Mark Browne2d32ff2012-08-31 17:38:32 -0700612 /* Recheck all analogue paths too */
613 dapm_mark_io_dirty(&card->dapm);
614 snd_soc_dapm_sync(&card->dapm);
615
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000616 /* suspend all CODECs */
Jarkko Nikula2eea3922010-11-25 17:47:38 +0200617 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000618 /* If there are paths active then the CODEC will be held with
619 * bias _ON and should not be suspended. */
620 if (!codec->suspended && codec->driver->suspend) {
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200621 switch (codec->dapm.bias_level) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000622 case SND_SOC_BIAS_STANDBY:
Mark Brown125a25d2012-01-31 15:49:10 +0000623 /*
624 * If the CODEC is capable of idle
625 * bias off then being in STANDBY
626 * means it's doing something,
627 * otherwise fall through.
628 */
629 if (codec->dapm.idle_bias_off) {
630 dev_dbg(codec->dev,
631 "idle_bias_off CODEC on over suspend\n");
632 break;
633 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000634 case SND_SOC_BIAS_OFF:
Lars-Peter Clausen84b315e2011-12-02 10:18:28 +0100635 codec->driver->suspend(codec);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000636 codec->suspended = 1;
Mark Brown7be4ba22011-07-18 13:17:13 +0900637 codec->cache_sync = 1;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000638 break;
639 default:
640 dev_dbg(codec->dev, "CODEC is on over suspend\n");
641 break;
642 }
643 }
644 }
645
646 for (i = 0; i < card->num_rtd; i++) {
647 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
648
649 if (card->rtd[i].dai_link->ignore_suspend)
650 continue;
651
652 if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
653 cpu_dai->driver->suspend(cpu_dai);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200654 }
655
Mark Brown87506542008-11-18 20:50:34 +0000656 if (card->suspend_post)
Mark Brown70b2ac12011-01-26 14:05:25 +0000657 card->suspend_post(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200658
659 return 0;
660}
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000661EXPORT_SYMBOL_GPL(snd_soc_suspend);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200662
Andy Green6ed25972008-06-13 16:24:05 +0100663/* deferred resume work, so resume can complete before we finished
664 * setting our codec back up, which can be very slow on I2C
665 */
666static void soc_resume_deferred(struct work_struct *work)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200667{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000668 struct snd_soc_card *card =
669 container_of(work, struct snd_soc_card, deferred_resume_work);
Jarkko Nikula2eea3922010-11-25 17:47:38 +0200670 struct snd_soc_codec *codec;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200671 int i;
672
Andy Green6ed25972008-06-13 16:24:05 +0100673 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
674 * so userspace apps are blocked from touching us
675 */
676
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000677 dev_dbg(card->dev, "starting resume work\n");
Andy Green6ed25972008-06-13 16:24:05 +0100678
Mark Brown99497882010-05-07 20:24:05 +0100679 /* Bring us up into D2 so that DAPM starts enabling things */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000680 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
Mark Brown99497882010-05-07 20:24:05 +0100681
Mark Brown87506542008-11-18 20:50:34 +0000682 if (card->resume_pre)
Mark Brown70b2ac12011-01-26 14:05:25 +0000683 card->resume_pre(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200684
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000685 /* resume AC97 DAIs */
686 for (i = 0; i < card->num_rtd; i++) {
687 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100688
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000689 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100690 continue;
691
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000692 if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
693 cpu_dai->driver->resume(cpu_dai);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200694 }
695
Jarkko Nikula2eea3922010-11-25 17:47:38 +0200696 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000697 /* If the CODEC was idle over suspend then it will have been
698 * left with bias OFF or STANDBY and suspended so we must now
699 * resume. Otherwise the suspend was suppressed.
700 */
701 if (codec->driver->resume && codec->suspended) {
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200702 switch (codec->dapm.bias_level) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000703 case SND_SOC_BIAS_STANDBY:
704 case SND_SOC_BIAS_OFF:
705 codec->driver->resume(codec);
706 codec->suspended = 0;
707 break;
708 default:
709 dev_dbg(codec->dev, "CODEC was on over suspend\n");
710 break;
711 }
Mark Brown1547aba2010-05-07 21:11:40 +0100712 }
713 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200714
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000715 for (i = 0; i < card->num_rtd; i++) {
Mark Brown3efab7d2010-05-09 13:25:43 +0100716
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000717 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100718 continue;
719
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800720 snd_soc_dapm_stream_event(&card->rtd[i],
Liam Girdwoodd9b09512012-03-07 16:32:59 +0000721 SNDRV_PCM_STREAM_PLAYBACK,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800722 SND_SOC_DAPM_STREAM_RESUME);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000723
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800724 snd_soc_dapm_stream_event(&card->rtd[i],
Liam Girdwoodd9b09512012-03-07 16:32:59 +0000725 SNDRV_PCM_STREAM_CAPTURE,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800726 SND_SOC_DAPM_STREAM_RESUME);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200727 }
728
Mark Brown3ff3f642008-05-19 12:32:25 +0200729 /* unmute any active DACs */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000730 for (i = 0; i < card->num_rtd; i++) {
731 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
732 struct snd_soc_dai_driver *drv = dai->driver;
Mark Brown3efab7d2010-05-09 13:25:43 +0100733
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000734 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100735 continue;
736
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000737 if (drv->ops->digital_mute && dai->playback_active)
738 drv->ops->digital_mute(dai, 0);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200739 }
740
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000741 for (i = 0; i < card->num_rtd; i++) {
742 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
743 struct snd_soc_platform *platform = card->rtd[i].platform;
Mark Brown3efab7d2010-05-09 13:25:43 +0100744
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000745 if (card->rtd[i].dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100746 continue;
747
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000748 if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
749 cpu_dai->driver->resume(cpu_dai);
750 if (platform->driver->resume && platform->suspended) {
751 platform->driver->resume(cpu_dai);
752 platform->suspended = 0;
753 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200754 }
755
Mark Brown87506542008-11-18 20:50:34 +0000756 if (card->resume_post)
Mark Brown70b2ac12011-01-26 14:05:25 +0000757 card->resume_post(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200758
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000759 dev_dbg(card->dev, "resume work completed\n");
Andy Green6ed25972008-06-13 16:24:05 +0100760
761 /* userspace can access us now we are back as we were before */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000762 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
Mark Browne2d32ff2012-08-31 17:38:32 -0700763
764 /* Recheck all analogue paths too */
765 dapm_mark_io_dirty(&card->dapm);
766 snd_soc_dapm_sync(&card->dapm);
Andy Green6ed25972008-06-13 16:24:05 +0100767}
768
769/* powers up audio subsystem after a suspend */
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000770int snd_soc_resume(struct device *dev)
Andy Green6ed25972008-06-13 16:24:05 +0100771{
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000772 struct snd_soc_card *card = dev_get_drvdata(dev);
Stephen Warren82e14e82011-05-25 14:06:41 -0600773 int i, ac97_control = 0;
Peter Ujfalusib9dd94a2010-02-22 13:27:13 +0200774
Eric Miao5ff1ddf2011-11-23 22:37:00 +0800775 /* If the initialization of this soc device failed, there is no codec
776 * associated with it. Just bail out in this case.
777 */
778 if (list_empty(&card->codec_dev_list))
779 return 0;
780
Mark Brown64ab9ba2009-03-31 11:27:03 +0100781 /* AC97 devices might have other drivers hanging off them so
782 * need to resume immediately. Other drivers don't have that
783 * problem and may take a substantial amount of time to resume
784 * due to I/O costs and anti-pop so handle them out of line.
785 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000786 for (i = 0; i < card->num_rtd; i++) {
787 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
Stephen Warren82e14e82011-05-25 14:06:41 -0600788 ac97_control |= cpu_dai->driver->ac97_control;
789 }
790 if (ac97_control) {
791 dev_dbg(dev, "Resuming AC97 immediately\n");
792 soc_resume_deferred(&card->deferred_resume_work);
793 } else {
794 dev_dbg(dev, "Scheduling resume work\n");
795 if (!schedule_work(&card->deferred_resume_work))
796 dev_err(dev, "resume work item may be lost\n");
Mark Brown64ab9ba2009-03-31 11:27:03 +0100797 }
Andy Green6ed25972008-06-13 16:24:05 +0100798
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200799 return 0;
800}
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000801EXPORT_SYMBOL_GPL(snd_soc_resume);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200802#else
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000803#define snd_soc_suspend NULL
804#define snd_soc_resume NULL
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200805#endif
806
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100807static const struct snd_soc_dai_ops null_dai_ops = {
Barry Song02a06d32009-10-16 18:13:38 +0800808};
809
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000810static int soc_bind_dai_link(struct snd_soc_card *card, int num)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200811{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000812 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
813 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
Mark Brownfe3e78e2009-11-03 22:13:13 +0000814 struct snd_soc_codec *codec;
Mark Brown435c5e22008-12-04 15:32:53 +0000815 struct snd_soc_platform *platform;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000816 struct snd_soc_dai *codec_dai, *cpu_dai;
Mark Brown848dd8b2011-04-27 18:16:32 +0100817 const char *platform_name;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200818
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000819 dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
Mark Brown63084192008-12-02 15:08:03 +0000820
Mark Brownb19e6e72012-03-14 21:18:39 +0000821 /* Find CPU DAI from registered DAIs*/
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000822 list_for_each_entry(cpu_dai, &dai_list, list) {
Stephen Warrenbc926572012-05-25 18:22:11 -0600823 if (dai_link->cpu_of_node &&
824 (cpu_dai->dev->of_node != dai_link->cpu_of_node))
825 continue;
826 if (dai_link->cpu_name &&
827 strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name))
828 continue;
829 if (dai_link->cpu_dai_name &&
830 strcmp(cpu_dai->name, dai_link->cpu_dai_name))
831 continue;
Stephen Warren2610ab72011-12-07 13:58:27 -0700832
833 rtd->cpu_dai = cpu_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000834 }
Mark Brownb19e6e72012-03-14 21:18:39 +0000835
836 if (!rtd->cpu_dai) {
Mark Brownfb099cb2012-08-09 18:44:37 +0100837 dev_err(card->dev, "CPU DAI %s not registered\n",
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000838 dai_link->cpu_dai_name);
Mark Brownb19e6e72012-03-14 21:18:39 +0000839 return -EPROBE_DEFER;
Mark Brownc5af3a22008-11-28 13:29:45 +0000840 }
841
Mark Brownb19e6e72012-03-14 21:18:39 +0000842 /* Find CODEC from registered CODECs */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000843 list_for_each_entry(codec, &codec_list, list) {
Stephen Warren5a504962011-12-21 10:40:59 -0700844 if (dai_link->codec_of_node) {
845 if (codec->dev->of_node != dai_link->codec_of_node)
846 continue;
847 } else {
848 if (strcmp(codec->name, dai_link->codec_name))
849 continue;
850 }
Mark Brown6b05eda2008-12-08 19:26:48 +0000851
Stephen Warren2610ab72011-12-07 13:58:27 -0700852 rtd->codec = codec;
853
854 /*
855 * CODEC found, so find CODEC DAI from registered DAIs from
856 * this CODEC
857 */
858 list_for_each_entry(codec_dai, &dai_list, list) {
859 if (codec->dev == codec_dai->dev &&
860 !strcmp(codec_dai->name,
861 dai_link->codec_dai_name)) {
862
863 rtd->codec_dai = codec_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000864 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000865 }
Mark Brownb19e6e72012-03-14 21:18:39 +0000866
867 if (!rtd->codec_dai) {
Mark Brownfb099cb2012-08-09 18:44:37 +0100868 dev_err(card->dev, "CODEC DAI %s not registered\n",
Stephen Warren2610ab72011-12-07 13:58:27 -0700869 dai_link->codec_dai_name);
Mark Brownb19e6e72012-03-14 21:18:39 +0000870 return -EPROBE_DEFER;
871 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000872 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000873
Mark Brownb19e6e72012-03-14 21:18:39 +0000874 if (!rtd->codec) {
Mark Brownfb099cb2012-08-09 18:44:37 +0100875 dev_err(card->dev, "CODEC %s not registered\n",
Mark Brownb19e6e72012-03-14 21:18:39 +0000876 dai_link->codec_name);
877 return -EPROBE_DEFER;
878 }
Mark Brown848dd8b2011-04-27 18:16:32 +0100879
880 /* if there's no platform we match on the empty platform */
881 platform_name = dai_link->platform_name;
Stephen Warren5a504962011-12-21 10:40:59 -0700882 if (!platform_name && !dai_link->platform_of_node)
Mark Brown848dd8b2011-04-27 18:16:32 +0100883 platform_name = "snd-soc-dummy";
884
Mark Brownb19e6e72012-03-14 21:18:39 +0000885 /* find one from the set of registered platforms */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000886 list_for_each_entry(platform, &platform_list, list) {
Stephen Warren5a504962011-12-21 10:40:59 -0700887 if (dai_link->platform_of_node) {
888 if (platform->dev->of_node !=
889 dai_link->platform_of_node)
890 continue;
891 } else {
892 if (strcmp(platform->name, platform_name))
893 continue;
894 }
Stephen Warren2610ab72011-12-07 13:58:27 -0700895
896 rtd->platform = platform;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000897 }
Mark Brownb19e6e72012-03-14 21:18:39 +0000898 if (!rtd->platform) {
Mark Brownfb099cb2012-08-09 18:44:37 +0100899 dev_err(card->dev, "platform %s not registered\n",
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000900 dai_link->platform_name);
Mark Brownb19e6e72012-03-14 21:18:39 +0000901 return -EPROBE_DEFER;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000902 }
Mark Brownb19e6e72012-03-14 21:18:39 +0000903
904 card->num_rtd++;
905
906 return 0;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000907}
908
Stephen Warrend12cd192012-06-08 12:34:22 -0600909static int soc_remove_platform(struct snd_soc_platform *platform)
910{
911 int ret;
912
913 if (platform->driver->remove) {
914 ret = platform->driver->remove(platform);
915 if (ret < 0)
916 pr_err("asoc: failed to remove %s: %d\n",
917 platform->name, ret);
918 }
919
920 /* Make sure all DAPM widgets are freed */
921 snd_soc_dapm_free(&platform->dapm);
922
923 soc_cleanup_platform_debugfs(platform);
924 platform->probed = 0;
925 list_del(&platform->card_list);
926 module_put(platform->dev->driver->owner);
927
928 return 0;
929}
930
Jarkko Nikula589c3562010-12-06 16:27:07 +0200931static void soc_remove_codec(struct snd_soc_codec *codec)
932{
933 int err;
934
935 if (codec->driver->remove) {
936 err = codec->driver->remove(codec);
937 if (err < 0)
938 dev_err(codec->dev,
939 "asoc: failed to remove %s: %d\n",
940 codec->name, err);
941 }
942
943 /* Make sure all DAPM widgets are freed */
944 snd_soc_dapm_free(&codec->dapm);
945
946 soc_cleanup_codec_debugfs(codec);
947 codec->probed = 0;
948 list_del(&codec->card_list);
949 module_put(codec->dev->driver->owner);
950}
951
Stephen Warren62ae68f2012-06-08 12:34:23 -0600952static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000953{
954 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000955 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
956 int err;
957
958 /* unregister the rtd device */
959 if (rtd->dev_registered) {
Mark Brown36ae1a92012-01-06 17:12:45 -0800960 device_remove_file(rtd->dev, &dev_attr_pmdown_time);
961 device_remove_file(rtd->dev, &dev_attr_codec_reg);
962 device_unregister(rtd->dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000963 rtd->dev_registered = 0;
964 }
965
966 /* remove the CODEC DAI */
Liam Girdwood0168bf02011-06-07 16:08:05 +0100967 if (codec_dai && codec_dai->probed &&
968 codec_dai->driver->remove_order == order) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000969 if (codec_dai->driver->remove) {
970 err = codec_dai->driver->remove(codec_dai);
971 if (err < 0)
Fabio Estevam0837fc62012-02-17 19:40:38 -0200972 pr_err("asoc: failed to remove %s: %d\n",
973 codec_dai->name, err);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000974 }
975 codec_dai->probed = 0;
976 list_del(&codec_dai->card_list);
977 }
978
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000979 /* remove the cpu_dai */
Liam Girdwood0168bf02011-06-07 16:08:05 +0100980 if (cpu_dai && cpu_dai->probed &&
981 cpu_dai->driver->remove_order == order) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000982 if (cpu_dai->driver->remove) {
983 err = cpu_dai->driver->remove(cpu_dai);
984 if (err < 0)
Fabio Estevam0837fc62012-02-17 19:40:38 -0200985 pr_err("asoc: failed to remove %s: %d\n",
986 cpu_dai->name, err);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000987 }
988 cpu_dai->probed = 0;
989 list_del(&cpu_dai->card_list);
Stephen Warrena9db7db2012-06-08 12:34:20 -0600990
Stephen Warren18d75642012-06-08 12:34:21 -0600991 if (!cpu_dai->codec) {
992 snd_soc_dapm_free(&cpu_dai->dapm);
Stephen Warrena9db7db2012-06-08 12:34:20 -0600993 module_put(cpu_dai->dev->driver->owner);
Stephen Warren18d75642012-06-08 12:34:21 -0600994 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000995 }
996}
997
Stephen Warren62ae68f2012-06-08 12:34:23 -0600998static void soc_remove_link_components(struct snd_soc_card *card, int num,
999 int order)
1000{
1001 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1002 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1003 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1004 struct snd_soc_platform *platform = rtd->platform;
1005 struct snd_soc_codec *codec;
1006
1007 /* remove the platform */
1008 if (platform && platform->probed &&
1009 platform->driver->remove_order == order) {
1010 soc_remove_platform(platform);
1011 }
1012
1013 /* remove the CODEC-side CODEC */
1014 if (codec_dai) {
1015 codec = codec_dai->codec;
1016 if (codec && codec->probed &&
1017 codec->driver->remove_order == order)
1018 soc_remove_codec(codec);
1019 }
1020
1021 /* remove any CPU-side CODEC */
1022 if (cpu_dai) {
1023 codec = cpu_dai->codec;
1024 if (codec && codec->probed &&
1025 codec->driver->remove_order == order)
1026 soc_remove_codec(codec);
1027 }
1028}
1029
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001030static void soc_remove_dai_links(struct snd_soc_card *card)
1031{
Liam Girdwood0168bf02011-06-07 16:08:05 +01001032 int dai, order;
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001033
Liam Girdwood0168bf02011-06-07 16:08:05 +01001034 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1035 order++) {
1036 for (dai = 0; dai < card->num_rtd; dai++)
Stephen Warren62ae68f2012-06-08 12:34:23 -06001037 soc_remove_link_dais(card, dai, order);
Liam Girdwood0168bf02011-06-07 16:08:05 +01001038 }
Stephen Warren62ae68f2012-06-08 12:34:23 -06001039
1040 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1041 order++) {
1042 for (dai = 0; dai < card->num_rtd; dai++)
1043 soc_remove_link_components(card, dai, order);
1044 }
1045
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001046 card->num_rtd = 0;
1047}
1048
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001049static void soc_set_name_prefix(struct snd_soc_card *card,
1050 struct snd_soc_codec *codec)
1051{
1052 int i;
1053
Dimitris Papastamosff819b82010-12-02 14:53:03 +00001054 if (card->codec_conf == NULL)
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001055 return;
1056
Dimitris Papastamosff819b82010-12-02 14:53:03 +00001057 for (i = 0; i < card->num_configs; i++) {
1058 struct snd_soc_codec_conf *map = &card->codec_conf[i];
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001059 if (map->dev_name && !strcmp(codec->name, map->dev_name)) {
1060 codec->name_prefix = map->name_prefix;
1061 break;
1062 }
1063 }
1064}
1065
Jarkko Nikula589c3562010-12-06 16:27:07 +02001066static int soc_probe_codec(struct snd_soc_card *card,
1067 struct snd_soc_codec *codec)
1068{
1069 int ret = 0;
Mark Brown89b95ac02011-03-07 16:38:44 +00001070 const struct snd_soc_codec_driver *driver = codec->driver;
Mark Brown888df392012-02-16 19:37:51 -08001071 struct snd_soc_dai *dai;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001072
1073 codec->card = card;
1074 codec->dapm.card = card;
1075 soc_set_name_prefix(card, codec);
1076
Jarkko Nikula70d29332011-01-27 16:24:22 +02001077 if (!try_module_get(codec->dev->driver->owner))
1078 return -ENODEV;
1079
Lars-Peter Clausend5d1e0b2011-04-30 19:45:49 +02001080 soc_init_codec_debugfs(codec);
1081
Lars-Peter Clausen77530152011-05-05 16:59:09 +02001082 if (driver->dapm_widgets)
1083 snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
1084 driver->num_dapm_widgets);
1085
Mark Brown888df392012-02-16 19:37:51 -08001086 /* Create DAPM widgets for each DAI stream */
1087 list_for_each_entry(dai, &dai_list, list) {
1088 if (dai->dev != codec->dev)
1089 continue;
1090
1091 snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
1092 }
1093
Mark Brown33c5f962011-08-22 18:40:30 +01001094 codec->dapm.idle_bias_off = driver->idle_bias_off;
1095
Mark Brown89b95ac02011-03-07 16:38:44 +00001096 if (driver->probe) {
1097 ret = driver->probe(codec);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001098 if (ret < 0) {
1099 dev_err(codec->dev,
1100 "asoc: failed to probe CODEC %s: %d\n",
1101 codec->name, ret);
Jarkko Nikula70d29332011-01-27 16:24:22 +02001102 goto err_probe;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001103 }
1104 }
1105
Mark Brown38cbf952012-06-22 13:04:02 +01001106 /* If the driver didn't set I/O up try regmap */
Mark Brown98d30882012-08-01 20:05:47 +01001107 if (!codec->write && dev_get_regmap(codec->dev, NULL))
Mark Brown38cbf952012-06-22 13:04:02 +01001108 snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
1109
Mark Brownb7af1da2011-04-07 19:18:44 +09001110 if (driver->controls)
Liam Girdwood022658b2012-02-03 17:43:09 +00001111 snd_soc_add_codec_controls(codec, driver->controls,
Mark Brownb7af1da2011-04-07 19:18:44 +09001112 driver->num_controls);
Mark Brown89b95ac02011-03-07 16:38:44 +00001113 if (driver->dapm_routes)
1114 snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
1115 driver->num_dapm_routes);
1116
Jarkko Nikula589c3562010-12-06 16:27:07 +02001117 /* mark codec as probed and add to card codec list */
1118 codec->probed = 1;
1119 list_add(&codec->card_list, &card->codec_dev_list);
Jarkko Nikula7be31be82010-12-14 12:18:32 +02001120 list_add(&codec->dapm.list, &card->dapm_list);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001121
Jarkko Nikula70d29332011-01-27 16:24:22 +02001122 return 0;
1123
1124err_probe:
Lars-Peter Clausend5d1e0b2011-04-30 19:45:49 +02001125 soc_cleanup_codec_debugfs(codec);
Jarkko Nikula70d29332011-01-27 16:24:22 +02001126 module_put(codec->dev->driver->owner);
1127
Jarkko Nikula589c3562010-12-06 16:27:07 +02001128 return ret;
1129}
1130
Liam Girdwood956245e2011-07-01 16:54:08 +01001131static int soc_probe_platform(struct snd_soc_card *card,
1132 struct snd_soc_platform *platform)
1133{
1134 int ret = 0;
1135 const struct snd_soc_platform_driver *driver = platform->driver;
Liam Girdwoodbe09ad92012-03-07 11:47:41 +00001136 struct snd_soc_dai *dai;
Liam Girdwood956245e2011-07-01 16:54:08 +01001137
1138 platform->card = card;
Liam Girdwoodb7950642011-07-04 22:10:52 +01001139 platform->dapm.card = card;
Liam Girdwood956245e2011-07-01 16:54:08 +01001140
1141 if (!try_module_get(platform->dev->driver->owner))
1142 return -ENODEV;
1143
Sebastien Guiriec731f1ab2012-02-15 15:25:31 +00001144 soc_init_platform_debugfs(platform);
1145
Liam Girdwoodcb2cf612011-07-04 22:10:53 +01001146 if (driver->dapm_widgets)
1147 snd_soc_dapm_new_controls(&platform->dapm,
1148 driver->dapm_widgets, driver->num_dapm_widgets);
1149
Liam Girdwoodbe09ad92012-03-07 11:47:41 +00001150 /* Create DAPM widgets for each DAI stream */
1151 list_for_each_entry(dai, &dai_list, list) {
1152 if (dai->dev != platform->dev)
1153 continue;
1154
1155 snd_soc_dapm_new_dai_widgets(&platform->dapm, dai);
1156 }
1157
Stephen Warren3fec6b62012-04-05 12:28:01 -06001158 platform->dapm.idle_bias_off = 1;
1159
Liam Girdwood956245e2011-07-01 16:54:08 +01001160 if (driver->probe) {
1161 ret = driver->probe(platform);
1162 if (ret < 0) {
1163 dev_err(platform->dev,
1164 "asoc: failed to probe platform %s: %d\n",
1165 platform->name, ret);
1166 goto err_probe;
1167 }
1168 }
1169
Liam Girdwoodcb2cf612011-07-04 22:10:53 +01001170 if (driver->controls)
1171 snd_soc_add_platform_controls(platform, driver->controls,
1172 driver->num_controls);
1173 if (driver->dapm_routes)
1174 snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes,
1175 driver->num_dapm_routes);
1176
Liam Girdwood956245e2011-07-01 16:54:08 +01001177 /* mark platform as probed and add to card platform list */
1178 platform->probed = 1;
1179 list_add(&platform->card_list, &card->platform_dev_list);
Liam Girdwoodb7950642011-07-04 22:10:52 +01001180 list_add(&platform->dapm.list, &card->dapm_list);
Liam Girdwood956245e2011-07-01 16:54:08 +01001181
1182 return 0;
1183
1184err_probe:
Liam Girdwood02db1102012-03-02 16:13:44 +00001185 soc_cleanup_platform_debugfs(platform);
Liam Girdwood956245e2011-07-01 16:54:08 +01001186 module_put(platform->dev->driver->owner);
1187
1188 return ret;
1189}
1190
Mark Brown36ae1a92012-01-06 17:12:45 -08001191static void rtd_release(struct device *dev)
1192{
1193 kfree(dev);
1194}
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001195
Jarkko Nikula589c3562010-12-06 16:27:07 +02001196static int soc_post_component_init(struct snd_soc_card *card,
1197 struct snd_soc_codec *codec,
1198 int num, int dailess)
1199{
1200 struct snd_soc_dai_link *dai_link = NULL;
1201 struct snd_soc_aux_dev *aux_dev = NULL;
1202 struct snd_soc_pcm_runtime *rtd;
1203 const char *temp, *name;
1204 int ret = 0;
1205
1206 if (!dailess) {
1207 dai_link = &card->dai_link[num];
1208 rtd = &card->rtd[num];
1209 name = dai_link->name;
1210 } else {
1211 aux_dev = &card->aux_dev[num];
1212 rtd = &card->rtd_aux[num];
1213 name = aux_dev->name;
1214 }
Janusz Krzysztofik0962bb22011-02-02 21:11:41 +01001215 rtd->card = card;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001216
Mark Brown4b1cfcb2011-10-18 00:11:49 +01001217 /* Make sure all DAPM widgets are instantiated */
1218 snd_soc_dapm_new_widgets(&codec->dapm);
1219
Jarkko Nikula589c3562010-12-06 16:27:07 +02001220 /* machine controls, routes and widgets are not prefixed */
1221 temp = codec->name_prefix;
1222 codec->name_prefix = NULL;
1223
1224 /* do machine specific initialization */
1225 if (!dailess && dai_link->init)
1226 ret = dai_link->init(rtd);
1227 else if (dailess && aux_dev->init)
1228 ret = aux_dev->init(&codec->dapm);
1229 if (ret < 0) {
1230 dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret);
1231 return ret;
1232 }
1233 codec->name_prefix = temp;
1234
Jarkko Nikula589c3562010-12-06 16:27:07 +02001235 /* register the rtd device */
1236 rtd->codec = codec;
Mark Brown36ae1a92012-01-06 17:12:45 -08001237
1238 rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
1239 if (!rtd->dev)
1240 return -ENOMEM;
1241 device_initialize(rtd->dev);
1242 rtd->dev->parent = card->dev;
1243 rtd->dev->release = rtd_release;
1244 rtd->dev->init_name = name;
1245 dev_set_drvdata(rtd->dev, rtd);
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +01001246 mutex_init(&rtd->pcm_mutex);
Liam Girdwood01d75842012-04-25 12:12:49 +01001247 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
1248 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
1249 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
1250 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
Mark Brown36ae1a92012-01-06 17:12:45 -08001251 ret = device_add(rtd->dev);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001252 if (ret < 0) {
1253 dev_err(card->dev,
1254 "asoc: failed to register runtime device: %d\n", ret);
1255 return ret;
1256 }
1257 rtd->dev_registered = 1;
1258
1259 /* add DAPM sysfs entries for this codec */
Mark Brown36ae1a92012-01-06 17:12:45 -08001260 ret = snd_soc_dapm_sys_add(rtd->dev);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001261 if (ret < 0)
1262 dev_err(codec->dev,
1263 "asoc: failed to add codec dapm sysfs entries: %d\n",
1264 ret);
1265
1266 /* add codec sysfs entries */
Mark Brown36ae1a92012-01-06 17:12:45 -08001267 ret = device_create_file(rtd->dev, &dev_attr_codec_reg);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001268 if (ret < 0)
1269 dev_err(codec->dev,
1270 "asoc: failed to add codec sysfs files: %d\n", ret);
1271
Liam Girdwoodf86dcef2012-04-25 12:12:50 +01001272#ifdef CONFIG_DEBUG_FS
1273 /* add DPCM sysfs entries */
Liam Girdwoodcd0f8912012-04-30 11:05:30 +01001274 if (!dailess && !dai_link->dynamic)
Liam Girdwoodf86dcef2012-04-25 12:12:50 +01001275 goto out;
1276
1277 ret = soc_dpcm_debugfs_add(rtd);
1278 if (ret < 0)
1279 dev_err(rtd->dev, "asoc: failed to add dpcm sysfs entries: %d\n", ret);
1280
1281out:
1282#endif
Jarkko Nikula589c3562010-12-06 16:27:07 +02001283 return 0;
1284}
1285
Stephen Warren62ae68f2012-06-08 12:34:23 -06001286static int soc_probe_link_components(struct snd_soc_card *card, int num,
1287 int order)
1288{
1289 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1290 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1291 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1292 struct snd_soc_platform *platform = rtd->platform;
1293 int ret;
1294
1295 /* probe the CPU-side component, if it is a CODEC */
1296 if (cpu_dai->codec &&
1297 !cpu_dai->codec->probed &&
1298 cpu_dai->codec->driver->probe_order == order) {
1299 ret = soc_probe_codec(card, cpu_dai->codec);
1300 if (ret < 0)
1301 return ret;
1302 }
1303
1304 /* probe the CODEC-side component */
1305 if (!codec_dai->codec->probed &&
1306 codec_dai->codec->driver->probe_order == order) {
1307 ret = soc_probe_codec(card, codec_dai->codec);
1308 if (ret < 0)
1309 return ret;
1310 }
1311
1312 /* probe the platform */
1313 if (!platform->probed &&
1314 platform->driver->probe_order == order) {
1315 ret = soc_probe_platform(card, platform);
1316 if (ret < 0)
1317 return ret;
1318 }
1319
1320 return 0;
1321}
1322
1323static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001324{
1325 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1326 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1327 struct snd_soc_codec *codec = rtd->codec;
1328 struct snd_soc_platform *platform = rtd->platform;
Mark Brownc74184e2012-04-04 22:12:09 +01001329 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1330 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1331 struct snd_soc_dapm_widget *play_w, *capture_w;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001332 int ret;
1333
Liam Girdwood0168bf02011-06-07 16:08:05 +01001334 dev_dbg(card->dev, "probe %s dai link %d late %d\n",
1335 card->name, num, order);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001336
1337 /* config components */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001338 cpu_dai->platform = platform;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001339 codec_dai->card = card;
1340 cpu_dai->card = card;
1341
1342 /* set default power off timeout */
1343 rtd->pmdown_time = pmdown_time;
1344
1345 /* probe the cpu_dai */
Liam Girdwood0168bf02011-06-07 16:08:05 +01001346 if (!cpu_dai->probed &&
1347 cpu_dai->driver->probe_order == order) {
Stephen Warrena9db7db2012-06-08 12:34:20 -06001348 if (!cpu_dai->codec) {
1349 cpu_dai->dapm.card = card;
1350 if (!try_module_get(cpu_dai->dev->driver->owner))
1351 return -ENODEV;
Liam Girdwood61b61e32011-05-24 13:57:43 +01001352
Stephen Warren18d75642012-06-08 12:34:21 -06001353 list_add(&cpu_dai->dapm.list, &card->dapm_list);
Stephen Warrena9db7db2012-06-08 12:34:20 -06001354 snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
1355 }
Liam Girdwoodbe09ad92012-03-07 11:47:41 +00001356
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001357 if (cpu_dai->driver->probe) {
1358 ret = cpu_dai->driver->probe(cpu_dai);
1359 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001360 pr_err("asoc: failed to probe CPU DAI %s: %d\n",
1361 cpu_dai->name, ret);
Liam Girdwood61b61e32011-05-24 13:57:43 +01001362 module_put(cpu_dai->dev->driver->owner);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001363 return ret;
1364 }
1365 }
1366 cpu_dai->probed = 1;
Wolfram Sang1c8371d2011-07-17 18:00:26 +02001367 /* mark cpu_dai as probed and add to card dai list */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001368 list_add(&cpu_dai->card_list, &card->dai_dev_list);
1369 }
1370
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001371 /* probe the CODEC DAI */
Liam Girdwood0168bf02011-06-07 16:08:05 +01001372 if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001373 if (codec_dai->driver->probe) {
1374 ret = codec_dai->driver->probe(codec_dai);
1375 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001376 pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
1377 codec_dai->name, ret);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001378 return ret;
Mark Brown6b05eda2008-12-08 19:26:48 +00001379 }
1380 }
1381
Wolfram Sang1c8371d2011-07-17 18:00:26 +02001382 /* mark codec_dai as probed and add to card dai list */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001383 codec_dai->probed = 1;
1384 list_add(&codec_dai->card_list, &card->dai_dev_list);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001385 }
1386
Liam Girdwood0168bf02011-06-07 16:08:05 +01001387 /* complete DAI probe during last probe */
1388 if (order != SND_SOC_COMP_ORDER_LAST)
1389 return 0;
1390
Jarkko Nikula589c3562010-12-06 16:27:07 +02001391 ret = soc_post_component_init(card, codec, num, 0);
1392 if (ret)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001393 return ret;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001394
Mark Brown36ae1a92012-01-06 17:12:45 -08001395 ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001396 if (ret < 0)
Fabio Estevam0837fc62012-02-17 19:40:38 -02001397 pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001398
Namarta Kohli1245b702012-08-16 17:10:41 +05301399 if (cpu_dai->driver->compress_dai) {
1400 /*create compress_device"*/
1401 ret = soc_new_compress(rtd, num);
Mark Brownc74184e2012-04-04 22:12:09 +01001402 if (ret < 0) {
Namarta Kohli1245b702012-08-16 17:10:41 +05301403 pr_err("asoc: can't create compress %s\n",
1404 dai_link->stream_name);
Mark Brownc74184e2012-04-04 22:12:09 +01001405 return ret;
1406 }
1407 } else {
Namarta Kohli1245b702012-08-16 17:10:41 +05301408
1409 if (!dai_link->params) {
1410 /* create the pcm */
1411 ret = soc_new_pcm(rtd, num);
1412 if (ret < 0) {
1413 pr_err("asoc: can't create pcm %s :%d\n",
1414 dai_link->stream_name, ret);
Mark Brownc74184e2012-04-04 22:12:09 +01001415 return ret;
1416 }
Namarta Kohli1245b702012-08-16 17:10:41 +05301417 } else {
1418 /* link the DAI widgets */
1419 play_w = codec_dai->playback_widget;
1420 capture_w = cpu_dai->capture_widget;
1421 if (play_w && capture_w) {
1422 ret = snd_soc_dapm_new_pcm(card, dai_link->params,
Mark Brownc74184e2012-04-04 22:12:09 +01001423 capture_w, play_w);
Namarta Kohli1245b702012-08-16 17:10:41 +05301424 if (ret != 0) {
1425 dev_err(card->dev, "Can't link %s to %s: %d\n",
1426 play_w->name, capture_w->name, ret);
1427 return ret;
1428 }
1429 }
1430
1431 play_w = cpu_dai->playback_widget;
1432 capture_w = codec_dai->capture_widget;
1433 if (play_w && capture_w) {
1434 ret = snd_soc_dapm_new_pcm(card, dai_link->params,
1435 capture_w, play_w);
1436 if (ret != 0) {
1437 dev_err(card->dev, "Can't link %s to %s: %d\n",
1438 play_w->name, capture_w->name, ret);
1439 return ret;
1440 }
Mark Brownc74184e2012-04-04 22:12:09 +01001441 }
1442 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001443 }
1444
1445 /* add platform data for AC97 devices */
1446 if (rtd->codec_dai->driver->ac97_control)
1447 snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
1448
1449 return 0;
1450}
1451
1452#ifdef CONFIG_SND_SOC_AC97_BUS
1453static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
1454{
1455 int ret;
1456
1457 /* Only instantiate AC97 if not already done by the adaptor
1458 * for the generic AC97 subsystem.
1459 */
1460 if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) {
Mika Westerberg0562f782010-10-13 11:30:32 +03001461 /*
1462 * It is possible that the AC97 device is already registered to
1463 * the device subsystem. This happens when the device is created
1464 * via snd_ac97_mixer(). Currently only SoC codec that does so
1465 * is the generic AC97 glue but others migh emerge.
1466 *
1467 * In those cases we don't try to register the device again.
1468 */
1469 if (!rtd->codec->ac97_created)
1470 return 0;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001471
1472 ret = soc_ac97_dev_register(rtd->codec);
1473 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001474 pr_err("asoc: AC97 device register failed:%d\n", ret);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001475 return ret;
1476 }
1477
1478 rtd->codec->ac97_registered = 1;
1479 }
1480 return 0;
1481}
1482
1483static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
1484{
1485 if (codec->ac97_registered) {
1486 soc_ac97_dev_unregister(codec);
1487 codec->ac97_registered = 0;
1488 }
1489}
1490#endif
1491
Mark Brownb19e6e72012-03-14 21:18:39 +00001492static int soc_check_aux_dev(struct snd_soc_card *card, int num)
1493{
1494 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
1495 struct snd_soc_codec *codec;
1496
1497 /* find CODEC from registered CODECs*/
1498 list_for_each_entry(codec, &codec_list, list) {
1499 if (!strcmp(codec->name, aux_dev->codec_name))
1500 return 0;
1501 }
1502
Mark Brownfb099cb2012-08-09 18:44:37 +01001503 dev_err(card->dev, "%s not registered\n", aux_dev->codec_name);
1504
Mark Brownb19e6e72012-03-14 21:18:39 +00001505 return -EPROBE_DEFER;
1506}
1507
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001508static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
1509{
1510 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001511 struct snd_soc_codec *codec;
Jarkko Nikula676ad982010-12-03 09:18:22 +02001512 int ret = -ENODEV;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001513
1514 /* find CODEC from registered CODECs*/
1515 list_for_each_entry(codec, &codec_list, list) {
1516 if (!strcmp(codec->name, aux_dev->codec_name)) {
1517 if (codec->probed) {
1518 dev_err(codec->dev,
1519 "asoc: codec already probed");
1520 ret = -EBUSY;
1521 goto out;
1522 }
Jarkko Nikula676ad982010-12-03 09:18:22 +02001523 goto found;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001524 }
1525 }
Jarkko Nikula676ad982010-12-03 09:18:22 +02001526 /* codec not found */
1527 dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
Mark Brownb19e6e72012-03-14 21:18:39 +00001528 return -EPROBE_DEFER;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001529
Jarkko Nikula676ad982010-12-03 09:18:22 +02001530found:
Jarkko Nikula589c3562010-12-06 16:27:07 +02001531 ret = soc_probe_codec(card, codec);
1532 if (ret < 0)
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001533 return ret;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001534
Jarkko Nikula589c3562010-12-06 16:27:07 +02001535 ret = soc_post_component_init(card, codec, num, 1);
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001536
1537out:
1538 return ret;
1539}
1540
1541static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
1542{
1543 struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
1544 struct snd_soc_codec *codec = rtd->codec;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001545
1546 /* unregister the rtd device */
1547 if (rtd->dev_registered) {
Mark Brown36ae1a92012-01-06 17:12:45 -08001548 device_remove_file(rtd->dev, &dev_attr_codec_reg);
1549 device_del(rtd->dev);
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001550 rtd->dev_registered = 0;
1551 }
1552
Jarkko Nikula589c3562010-12-06 16:27:07 +02001553 if (codec && codec->probed)
1554 soc_remove_codec(codec);
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001555}
1556
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001557static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
1558 enum snd_soc_compress_type compress_type)
1559{
1560 int ret;
1561
1562 if (codec->cache_init)
1563 return 0;
1564
1565 /* override the compress_type if necessary */
1566 if (compress_type && codec->compress_type != compress_type)
1567 codec->compress_type = compress_type;
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001568 ret = snd_soc_cache_init(codec);
1569 if (ret < 0) {
1570 dev_err(codec->dev, "Failed to set cache compression type: %d\n",
1571 ret);
1572 return ret;
1573 }
1574 codec->cache_init = 1;
1575 return 0;
1576}
1577
Mark Brownb19e6e72012-03-14 21:18:39 +00001578static int snd_soc_instantiate_card(struct snd_soc_card *card)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001579{
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001580 struct snd_soc_codec *codec;
1581 struct snd_soc_codec_conf *codec_conf;
1582 enum snd_soc_compress_type compress_type;
Mark Brown75d9ac42011-09-27 16:41:01 +01001583 struct snd_soc_dai_link *dai_link;
Mark Brownf04209a2012-04-09 16:29:21 +01001584 int ret, i, order, dai_fmt;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001585
Liam Girdwood01b9d992012-03-07 10:38:25 +00001586 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001587
Mark Brownb19e6e72012-03-14 21:18:39 +00001588 /* bind DAIs */
1589 for (i = 0; i < card->num_links; i++) {
1590 ret = soc_bind_dai_link(card, i);
1591 if (ret != 0)
1592 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001593 }
1594
Mark Brownb19e6e72012-03-14 21:18:39 +00001595 /* check aux_devs too */
1596 for (i = 0; i < card->num_aux_devs; i++) {
1597 ret = soc_check_aux_dev(card, i);
1598 if (ret != 0)
1599 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001600 }
1601
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001602 /* initialize the register cache for each available codec */
1603 list_for_each_entry(codec, &codec_list, list) {
1604 if (codec->cache_init)
1605 continue;
Dimitris Papastamos861f2fa2011-01-11 11:43:51 +00001606 /* by default we don't override the compress_type */
1607 compress_type = 0;
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001608 /* check to see if we need to override the compress_type */
1609 for (i = 0; i < card->num_configs; ++i) {
1610 codec_conf = &card->codec_conf[i];
1611 if (!strcmp(codec->name, codec_conf->dev_name)) {
1612 compress_type = codec_conf->compress_type;
1613 if (compress_type && compress_type
1614 != codec->compress_type)
1615 break;
1616 }
1617 }
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001618 ret = snd_soc_init_codec_cache(codec, compress_type);
Mark Brownb19e6e72012-03-14 21:18:39 +00001619 if (ret < 0)
1620 goto base_error;
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00001621 }
1622
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001623 /* card bind complete so register a sound card */
1624 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
1625 card->owner, 0, &card->snd_card);
1626 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001627 pr_err("asoc: can't create sound card for card %s: %d\n",
1628 card->name, ret);
Mark Brownb19e6e72012-03-14 21:18:39 +00001629 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001630 }
1631 card->snd_card->dev = card->dev;
1632
Mark Browne37a4972011-03-02 18:21:57 +00001633 card->dapm.bias_level = SND_SOC_BIAS_OFF;
1634 card->dapm.dev = card->dev;
1635 card->dapm.card = card;
1636 list_add(&card->dapm.list, &card->dapm_list);
1637
Lars-Peter Clausend5d1e0b2011-04-30 19:45:49 +02001638#ifdef CONFIG_DEBUG_FS
1639 snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root);
1640#endif
1641
Mark Brown88ee1c62011-02-02 10:43:26 +00001642#ifdef CONFIG_PM_SLEEP
Andy Green6ed25972008-06-13 16:24:05 +01001643 /* deferred resume work */
Mark Brown63084192008-12-02 15:08:03 +00001644 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
Randy Dunlap1301a962008-06-17 19:19:34 +01001645#endif
Andy Green6ed25972008-06-13 16:24:05 +01001646
Mark Brown9a841eb2011-04-12 17:51:37 -07001647 if (card->dapm_widgets)
1648 snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,
1649 card->num_dapm_widgets);
1650
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001651 /* initialise the sound card only once */
1652 if (card->probe) {
Mark Browne7361ec2011-01-26 14:17:20 +00001653 ret = card->probe(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001654 if (ret < 0)
1655 goto card_probe_error;
1656 }
1657
Stephen Warren62ae68f2012-06-08 12:34:23 -06001658 /* probe all components used by DAI links on this card */
Liam Girdwood0168bf02011-06-07 16:08:05 +01001659 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1660 order++) {
1661 for (i = 0; i < card->num_links; i++) {
Stephen Warren62ae68f2012-06-08 12:34:23 -06001662 ret = soc_probe_link_components(card, i, order);
Liam Girdwood0168bf02011-06-07 16:08:05 +01001663 if (ret < 0) {
1664 pr_err("asoc: failed to instantiate card %s: %d\n",
Stephen Warren62ae68f2012-06-08 12:34:23 -06001665 card->name, ret);
1666 goto probe_dai_err;
1667 }
1668 }
1669 }
1670
1671 /* probe all DAI links on this card */
1672 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1673 order++) {
1674 for (i = 0; i < card->num_links; i++) {
1675 ret = soc_probe_link_dais(card, i, order);
1676 if (ret < 0) {
1677 pr_err("asoc: failed to instantiate card %s: %d\n",
1678 card->name, ret);
Liam Girdwood0168bf02011-06-07 16:08:05 +01001679 goto probe_dai_err;
1680 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001681 }
1682 }
1683
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001684 for (i = 0; i < card->num_aux_devs; i++) {
1685 ret = soc_probe_aux_dev(card, i);
1686 if (ret < 0) {
1687 pr_err("asoc: failed to add auxiliary devices %s: %d\n",
1688 card->name, ret);
1689 goto probe_aux_dev_err;
1690 }
1691 }
1692
Mark Brown888df392012-02-16 19:37:51 -08001693 snd_soc_dapm_link_dai_widgets(card);
1694
Mark Brownb7af1da2011-04-07 19:18:44 +09001695 if (card->controls)
Liam Girdwood022658b2012-02-03 17:43:09 +00001696 snd_soc_add_card_controls(card, card->controls, card->num_controls);
Mark Brownb7af1da2011-04-07 19:18:44 +09001697
Mark Brownb8ad29d2011-03-02 18:35:51 +00001698 if (card->dapm_routes)
1699 snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
1700 card->num_dapm_routes);
1701
Mark Brownb90d2f92011-10-10 13:38:06 +01001702 snd_soc_dapm_new_widgets(&card->dapm);
1703
Mark Brown75d9ac42011-09-27 16:41:01 +01001704 for (i = 0; i < card->num_links; i++) {
1705 dai_link = &card->dai_link[i];
Mark Brownf04209a2012-04-09 16:29:21 +01001706 dai_fmt = dai_link->dai_fmt;
Mark Brown75d9ac42011-09-27 16:41:01 +01001707
Mark Brownf04209a2012-04-09 16:29:21 +01001708 if (dai_fmt) {
Mark Brown75d9ac42011-09-27 16:41:01 +01001709 ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
Mark Brownf04209a2012-04-09 16:29:21 +01001710 dai_fmt);
Shawn Guo5e4ba562012-03-09 00:59:40 +08001711 if (ret != 0 && ret != -ENOTSUPP)
Mark Brown75d9ac42011-09-27 16:41:01 +01001712 dev_warn(card->rtd[i].codec_dai->dev,
1713 "Failed to set DAI format: %d\n",
1714 ret);
Mark Brownf04209a2012-04-09 16:29:21 +01001715 }
1716
1717 /* If this is a regular CPU link there will be a platform */
Stephen Warrenfe33d4c2012-05-14 14:47:22 -06001718 if (dai_fmt &&
1719 (dai_link->platform_name || dai_link->platform_of_node)) {
Mark Brownf04209a2012-04-09 16:29:21 +01001720 ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
1721 dai_fmt);
1722 if (ret != 0 && ret != -ENOTSUPP)
1723 dev_warn(card->rtd[i].cpu_dai->dev,
1724 "Failed to set DAI format: %d\n",
1725 ret);
1726 } else if (dai_fmt) {
1727 /* Flip the polarity for the "CPU" end */
1728 dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
1729 switch (dai_link->dai_fmt &
1730 SND_SOC_DAIFMT_MASTER_MASK) {
1731 case SND_SOC_DAIFMT_CBM_CFM:
1732 dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
1733 break;
1734 case SND_SOC_DAIFMT_CBM_CFS:
1735 dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
1736 break;
1737 case SND_SOC_DAIFMT_CBS_CFM:
1738 dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
1739 break;
1740 case SND_SOC_DAIFMT_CBS_CFS:
1741 dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
1742 break;
1743 }
Mark Brown75d9ac42011-09-27 16:41:01 +01001744
1745 ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
Mark Brownf04209a2012-04-09 16:29:21 +01001746 dai_fmt);
Shawn Guo5e4ba562012-03-09 00:59:40 +08001747 if (ret != 0 && ret != -ENOTSUPP)
Mark Brown75d9ac42011-09-27 16:41:01 +01001748 dev_warn(card->rtd[i].cpu_dai->dev,
1749 "Failed to set DAI format: %d\n",
1750 ret);
1751 }
1752 }
1753
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001754 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001755 "%s", card->name);
Liam Girdwood22de71b2011-05-12 16:14:04 +01001756 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
1757 "%s", card->long_name ? card->long_name : card->name);
Mark Brownf0e8ed82011-09-20 11:41:54 +01001758 snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),
1759 "%s", card->driver_name ? card->driver_name : card->name);
1760 for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {
1761 switch (card->snd_card->driver[i]) {
1762 case '_':
1763 case '-':
1764 case '\0':
1765 break;
1766 default:
1767 if (!isalnum(card->snd_card->driver[i]))
1768 card->snd_card->driver[i] = '_';
1769 break;
1770 }
1771 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001772
Mark Brown28e9ad92011-03-02 18:36:34 +00001773 if (card->late_probe) {
1774 ret = card->late_probe(card);
1775 if (ret < 0) {
1776 dev_err(card->dev, "%s late_probe() failed: %d\n",
1777 card->name, ret);
1778 goto probe_aux_dev_err;
1779 }
1780 }
1781
Mark Brown2dc00212011-10-08 13:59:44 +01001782 snd_soc_dapm_new_widgets(&card->dapm);
1783
Stephen Warren16332812011-11-23 12:42:04 -07001784 if (card->fully_routed)
Mark Brownb05d8dc2011-11-27 19:38:34 +00001785 list_for_each_entry(codec, &card->codec_dev_list, card_list)
Stephen Warren16332812011-11-23 12:42:04 -07001786 snd_soc_dapm_auto_nc_codec_pins(codec);
1787
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001788 ret = snd_card_register(card->snd_card);
1789 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001790 pr_err("asoc: failed to register soundcard for %s: %d\n",
1791 card->name, ret);
Axel Lin6b3ed782010-12-07 16:12:29 +08001792 goto probe_aux_dev_err;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001793 }
1794
1795#ifdef CONFIG_SND_SOC_AC97_BUS
1796 /* register any AC97 codecs */
1797 for (i = 0; i < card->num_rtd; i++) {
Axel Lin6b3ed782010-12-07 16:12:29 +08001798 ret = soc_register_ac97_dai_link(&card->rtd[i]);
1799 if (ret < 0) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02001800 pr_err("asoc: failed to register AC97 %s: %d\n",
1801 card->name, ret);
Axel Lin6b3ed782010-12-07 16:12:29 +08001802 while (--i >= 0)
Mark Brown7d8316d2010-12-13 17:03:27 +00001803 soc_unregister_ac97_dai_link(card->rtd[i].codec);
Axel Lin6b3ed782010-12-07 16:12:29 +08001804 goto probe_aux_dev_err;
Mark Brownfe3e78e2009-11-03 22:13:13 +00001805 }
Axel Lin6b3ed782010-12-07 16:12:29 +08001806 }
Mark Brownfe3e78e2009-11-03 22:13:13 +00001807#endif
1808
Mark Brown435c5e22008-12-04 15:32:53 +00001809 card->instantiated = 1;
Mark Brown4f4c0072011-10-07 14:29:19 +01001810 snd_soc_dapm_sync(&card->dapm);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001811 mutex_unlock(&card->mutex);
Mark Brownb19e6e72012-03-14 21:18:39 +00001812
1813 return 0;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001814
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001815probe_aux_dev_err:
1816 for (i = 0; i < card->num_aux_devs; i++)
1817 soc_remove_aux_dev(card, i);
1818
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001819probe_dai_err:
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001820 soc_remove_dai_links(card);
Mark Brownfe3e78e2009-11-03 22:13:13 +00001821
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001822card_probe_error:
Mark Brown87506542008-11-18 20:50:34 +00001823 if (card->remove)
Mark Browne7361ec2011-01-26 14:17:20 +00001824 card->remove(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001825
1826 snd_card_free(card->snd_card);
1827
Mark Brownb19e6e72012-03-14 21:18:39 +00001828base_error:
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001829 mutex_unlock(&card->mutex);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001830
Mark Brownb19e6e72012-03-14 21:18:39 +00001831 return ret;
Mark Brown435c5e22008-12-04 15:32:53 +00001832}
1833
1834/* probes a new socdev */
1835static int soc_probe(struct platform_device *pdev)
1836{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001837 struct snd_soc_card *card = platform_get_drvdata(pdev);
Mark Brown435c5e22008-12-04 15:32:53 +00001838
Vinod Koul70a7ca32011-01-14 19:22:48 +05301839 /*
1840 * no card, so machine driver should be registering card
1841 * we should not be here in that case so ret error
1842 */
1843 if (!card)
1844 return -EINVAL;
1845
Mark Brownfe4085e2012-03-02 13:07:41 +00001846 dev_warn(&pdev->dev,
1847 "ASoC machine %s should use snd_soc_register_card()\n",
1848 card->name);
1849
Mark Brown435c5e22008-12-04 15:32:53 +00001850 /* Bodge while we unpick instantiation */
1851 card->dev = &pdev->dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001852
Mark Brown28d528c2012-08-09 18:45:23 +01001853 return snd_soc_register_card(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001854}
1855
Vinod Koulb0e26482011-01-13 22:48:02 +05301856static int soc_cleanup_card_resources(struct snd_soc_card *card)
1857{
Vinod Koulb0e26482011-01-13 22:48:02 +05301858 int i;
1859
1860 /* make sure any delayed work runs */
1861 for (i = 0; i < card->num_rtd; i++) {
1862 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1863 flush_delayed_work_sync(&rtd->delayed_work);
1864 }
1865
1866 /* remove auxiliary devices */
1867 for (i = 0; i < card->num_aux_devs; i++)
1868 soc_remove_aux_dev(card, i);
1869
1870 /* remove and free each DAI */
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001871 soc_remove_dai_links(card);
Vinod Koulb0e26482011-01-13 22:48:02 +05301872
1873 soc_cleanup_card_debugfs(card);
1874
1875 /* remove the card */
1876 if (card->remove)
Mark Browne7361ec2011-01-26 14:17:20 +00001877 card->remove(card);
Vinod Koulb0e26482011-01-13 22:48:02 +05301878
Lars-Peter Clausen0aaae522011-04-30 19:45:47 +02001879 snd_soc_dapm_free(&card->dapm);
1880
Vinod Koulb0e26482011-01-13 22:48:02 +05301881 snd_card_free(card->snd_card);
1882 return 0;
1883
1884}
1885
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001886/* removes a socdev */
1887static int soc_remove(struct platform_device *pdev)
1888{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001889 struct snd_soc_card *card = platform_get_drvdata(pdev);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001890
Mark Brownc5af3a22008-11-28 13:29:45 +00001891 snd_soc_unregister_card(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001892 return 0;
1893}
1894
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001895int snd_soc_poweroff(struct device *dev)
Mark Brown51737472009-06-22 13:16:51 +01001896{
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001897 struct snd_soc_card *card = dev_get_drvdata(dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001898 int i;
Mark Brown51737472009-06-22 13:16:51 +01001899
1900 if (!card->instantiated)
Mark Brown416356f2009-06-30 19:05:15 +01001901 return 0;
Mark Brown51737472009-06-22 13:16:51 +01001902
1903 /* Flush out pmdown_time work - we actually do want to run it
1904 * now, we're shutting down so no imminent restart. */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001905 for (i = 0; i < card->num_rtd; i++) {
1906 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
Tejun Heo5b84ba22010-12-11 17:51:26 +01001907 flush_delayed_work_sync(&rtd->delayed_work);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001908 }
Mark Brown51737472009-06-22 13:16:51 +01001909
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001910 snd_soc_dapm_shutdown(card);
Mark Brown416356f2009-06-30 19:05:15 +01001911
1912 return 0;
Mark Brown51737472009-06-22 13:16:51 +01001913}
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001914EXPORT_SYMBOL_GPL(snd_soc_poweroff);
Mark Brown51737472009-06-22 13:16:51 +01001915
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001916const struct dev_pm_ops snd_soc_pm_ops = {
Viresh Kumarb1dd5892012-02-24 16:25:49 +05301917 .suspend = snd_soc_suspend,
1918 .resume = snd_soc_resume,
1919 .freeze = snd_soc_suspend,
1920 .thaw = snd_soc_resume,
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001921 .poweroff = snd_soc_poweroff,
Viresh Kumarb1dd5892012-02-24 16:25:49 +05301922 .restore = snd_soc_resume,
Mark Brown416356f2009-06-30 19:05:15 +01001923};
Stephen Warrendeb26072011-04-05 19:35:30 -06001924EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
Mark Brown416356f2009-06-30 19:05:15 +01001925
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001926/* ASoC platform driver */
1927static struct platform_driver soc_driver = {
1928 .driver = {
1929 .name = "soc-audio",
Kay Sievers8b45a202008-04-14 13:33:36 +02001930 .owner = THIS_MODULE,
Mark Brown6f8ab4a2011-01-26 14:59:27 +00001931 .pm = &snd_soc_pm_ops,
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001932 },
1933 .probe = soc_probe,
1934 .remove = soc_remove,
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001935};
1936
Mark Brown096e49d2009-07-05 15:12:22 +01001937/**
1938 * snd_soc_codec_volatile_register: Report if a register is volatile.
1939 *
1940 * @codec: CODEC to query.
1941 * @reg: Register to query.
1942 *
1943 * Boolean function indiciating if a CODEC register is volatile.
1944 */
Mark Brown181e0552011-01-24 14:05:25 +00001945int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
1946 unsigned int reg)
Mark Brown096e49d2009-07-05 15:12:22 +01001947{
Dimitris Papastamos1500b7b2011-01-13 12:20:38 +00001948 if (codec->volatile_register)
1949 return codec->volatile_register(codec, reg);
Mark Brown096e49d2009-07-05 15:12:22 +01001950 else
1951 return 0;
1952}
1953EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1954
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001955/**
Dimitris Papastamos239c9702011-03-24 13:45:18 +00001956 * snd_soc_codec_readable_register: Report if a register is readable.
1957 *
1958 * @codec: CODEC to query.
1959 * @reg: Register to query.
1960 *
1961 * Boolean function indicating if a CODEC register is readable.
1962 */
1963int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
1964 unsigned int reg)
1965{
1966 if (codec->readable_register)
1967 return codec->readable_register(codec, reg);
1968 else
Lars-Peter Clausen63fa0a22011-08-27 18:24:12 +02001969 return 1;
Dimitris Papastamos239c9702011-03-24 13:45:18 +00001970}
1971EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register);
1972
1973/**
1974 * snd_soc_codec_writable_register: Report if a register is writable.
1975 *
1976 * @codec: CODEC to query.
1977 * @reg: Register to query.
1978 *
1979 * Boolean function indicating if a CODEC register is writable.
1980 */
1981int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
1982 unsigned int reg)
1983{
1984 if (codec->writable_register)
1985 return codec->writable_register(codec, reg);
1986 else
Lars-Peter Clausen63fa0a22011-08-27 18:24:12 +02001987 return 1;
Dimitris Papastamos239c9702011-03-24 13:45:18 +00001988}
1989EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register);
1990
Liam Girdwoodf1442bc2011-07-04 11:10:15 +01001991int snd_soc_platform_read(struct snd_soc_platform *platform,
1992 unsigned int reg)
1993{
1994 unsigned int ret;
1995
1996 if (!platform->driver->read) {
1997 dev_err(platform->dev, "platform has no read back\n");
1998 return -1;
1999 }
2000
2001 ret = platform->driver->read(platform, reg);
2002 dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
Liam Girdwooda82ce2a2011-07-04 22:10:50 +01002003 trace_snd_soc_preg_read(platform, reg, ret);
Liam Girdwoodf1442bc2011-07-04 11:10:15 +01002004
2005 return ret;
2006}
2007EXPORT_SYMBOL_GPL(snd_soc_platform_read);
2008
2009int snd_soc_platform_write(struct snd_soc_platform *platform,
2010 unsigned int reg, unsigned int val)
2011{
2012 if (!platform->driver->write) {
2013 dev_err(platform->dev, "platform has no write back\n");
2014 return -1;
2015 }
2016
2017 dev_dbg(platform->dev, "write %x = %x\n", reg, val);
Liam Girdwooda82ce2a2011-07-04 22:10:50 +01002018 trace_snd_soc_preg_write(platform, reg, val);
Liam Girdwoodf1442bc2011-07-04 11:10:15 +01002019 return platform->driver->write(platform, reg, val);
2020}
2021EXPORT_SYMBOL_GPL(snd_soc_platform_write);
2022
Dimitris Papastamos239c9702011-03-24 13:45:18 +00002023/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002024 * snd_soc_new_ac97_codec - initailise AC97 device
2025 * @codec: audio codec
2026 * @ops: AC97 bus operations
2027 * @num: AC97 codec number
2028 *
2029 * Initialises AC97 codec resources for use by ad-hoc devices only.
2030 */
2031int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
2032 struct snd_ac97_bus_ops *ops, int num)
2033{
2034 mutex_lock(&codec->mutex);
2035
2036 codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
2037 if (codec->ac97 == NULL) {
2038 mutex_unlock(&codec->mutex);
2039 return -ENOMEM;
2040 }
2041
2042 codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL);
2043 if (codec->ac97->bus == NULL) {
2044 kfree(codec->ac97);
2045 codec->ac97 = NULL;
2046 mutex_unlock(&codec->mutex);
2047 return -ENOMEM;
2048 }
2049
2050 codec->ac97->bus->ops = ops;
2051 codec->ac97->num = num;
Mika Westerberg0562f782010-10-13 11:30:32 +03002052
2053 /*
2054 * Mark the AC97 device to be created by us. This way we ensure that the
2055 * device will be registered with the device subsystem later on.
2056 */
2057 codec->ac97_created = 1;
2058
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002059 mutex_unlock(&codec->mutex);
2060 return 0;
2061}
2062EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
2063
2064/**
2065 * snd_soc_free_ac97_codec - free AC97 codec device
2066 * @codec: audio codec
2067 *
2068 * Frees AC97 codec device resources.
2069 */
2070void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
2071{
2072 mutex_lock(&codec->mutex);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002073#ifdef CONFIG_SND_SOC_AC97_BUS
2074 soc_unregister_ac97_dai_link(codec);
2075#endif
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002076 kfree(codec->ac97->bus);
2077 kfree(codec->ac97);
2078 codec->ac97 = NULL;
Mika Westerberg0562f782010-10-13 11:30:32 +03002079 codec->ac97_created = 0;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002080 mutex_unlock(&codec->mutex);
2081}
2082EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
2083
Mark Brownc3753702010-11-01 15:41:57 -04002084unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
2085{
2086 unsigned int ret;
2087
Mark Brownc3acec22010-12-02 16:15:29 +00002088 ret = codec->read(codec, reg);
Mark Brownc3753702010-11-01 15:41:57 -04002089 dev_dbg(codec->dev, "read %x => %x\n", reg, ret);
Mark Browna8b1d342010-11-03 18:05:58 -04002090 trace_snd_soc_reg_read(codec, reg, ret);
Mark Brownc3753702010-11-01 15:41:57 -04002091
2092 return ret;
2093}
2094EXPORT_SYMBOL_GPL(snd_soc_read);
2095
2096unsigned int snd_soc_write(struct snd_soc_codec *codec,
2097 unsigned int reg, unsigned int val)
2098{
2099 dev_dbg(codec->dev, "write %x = %x\n", reg, val);
Mark Browna8b1d342010-11-03 18:05:58 -04002100 trace_snd_soc_reg_write(codec, reg, val);
Mark Brownc3acec22010-12-02 16:15:29 +00002101 return codec->write(codec, reg, val);
Mark Brownc3753702010-11-01 15:41:57 -04002102}
2103EXPORT_SYMBOL_GPL(snd_soc_write);
2104
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +00002105unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
2106 unsigned int reg, const void *data, size_t len)
2107{
2108 return codec->bulk_write_raw(codec, reg, data, len);
2109}
2110EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
2111
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002112/**
2113 * snd_soc_update_bits - update codec register bits
2114 * @codec: audio codec
2115 * @reg: codec register
2116 * @mask: register mask
2117 * @value: new value
2118 *
2119 * Writes new register value.
2120 *
Timur Tabi180c3292011-01-10 15:58:13 -06002121 * Returns 1 for change, 0 for no change, or negative error code.
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002122 */
2123int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002124 unsigned int mask, unsigned int value)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002125{
Mark Brown8a713da2011-12-03 12:33:55 +00002126 bool change;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002127 unsigned int old, new;
Timur Tabi180c3292011-01-10 15:58:13 -06002128 int ret;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002129
Mark Brown8a713da2011-12-03 12:33:55 +00002130 if (codec->using_regmap) {
2131 ret = regmap_update_bits_check(codec->control_data, reg,
2132 mask, value, &change);
2133 } else {
2134 ret = snd_soc_read(codec, reg);
Timur Tabi180c3292011-01-10 15:58:13 -06002135 if (ret < 0)
2136 return ret;
Mark Brown8a713da2011-12-03 12:33:55 +00002137
2138 old = ret;
2139 new = (old & ~mask) | (value & mask);
2140 change = old != new;
2141 if (change)
2142 ret = snd_soc_write(codec, reg, new);
Timur Tabi180c3292011-01-10 15:58:13 -06002143 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002144
Mark Brown8a713da2011-12-03 12:33:55 +00002145 if (ret < 0)
2146 return ret;
2147
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002148 return change;
2149}
2150EXPORT_SYMBOL_GPL(snd_soc_update_bits);
2151
2152/**
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002153 * snd_soc_update_bits_locked - update codec register bits
2154 * @codec: audio codec
2155 * @reg: codec register
2156 * @mask: register mask
2157 * @value: new value
2158 *
2159 * Writes new register value, and takes the codec mutex.
2160 *
2161 * Returns 1 for change else 0.
2162 */
Mark Browndd1b3d52009-12-04 14:22:03 +00002163int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
2164 unsigned short reg, unsigned int mask,
2165 unsigned int value)
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002166{
2167 int change;
2168
2169 mutex_lock(&codec->mutex);
2170 change = snd_soc_update_bits(codec, reg, mask, value);
2171 mutex_unlock(&codec->mutex);
2172
2173 return change;
2174}
Mark Browndd1b3d52009-12-04 14:22:03 +00002175EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked);
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002176
2177/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002178 * snd_soc_test_bits - test register for change
2179 * @codec: audio codec
2180 * @reg: codec register
2181 * @mask: register mask
2182 * @value: new value
2183 *
2184 * Tests a register with a new value and checks if the new value is
2185 * different from the old value.
2186 *
2187 * Returns 1 for change else 0.
2188 */
2189int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002190 unsigned int mask, unsigned int value)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002191{
2192 int change;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002193 unsigned int old, new;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002194
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002195 old = snd_soc_read(codec, reg);
2196 new = (old & ~mask) | value;
2197 change = old != new;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002198
2199 return change;
2200}
2201EXPORT_SYMBOL_GPL(snd_soc_test_bits);
2202
2203/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002204 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
2205 * @substream: the pcm substream
2206 * @hw: the hardware parameters
2207 *
2208 * Sets the substream runtime hardware parameters.
2209 */
2210int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
2211 const struct snd_pcm_hardware *hw)
2212{
2213 struct snd_pcm_runtime *runtime = substream->runtime;
2214 runtime->hw.info = hw->info;
2215 runtime->hw.formats = hw->formats;
2216 runtime->hw.period_bytes_min = hw->period_bytes_min;
2217 runtime->hw.period_bytes_max = hw->period_bytes_max;
2218 runtime->hw.periods_min = hw->periods_min;
2219 runtime->hw.periods_max = hw->periods_max;
2220 runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
2221 runtime->hw.fifo_size = hw->fifo_size;
2222 return 0;
2223}
2224EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
2225
2226/**
2227 * snd_soc_cnew - create new control
2228 * @_template: control template
2229 * @data: control private data
Mark Brownac11a2b2009-01-01 12:18:17 +00002230 * @long_name: control long name
Mark Brownefb7ac32011-03-08 17:23:24 +00002231 * @prefix: control name prefix
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002232 *
2233 * Create a new mixer control from a template control.
2234 *
2235 * Returns 0 for success, else error.
2236 */
2237struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
Mark Brown30565572012-02-16 17:07:42 -08002238 void *data, const char *long_name,
Mark Brownefb7ac32011-03-08 17:23:24 +00002239 const char *prefix)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002240{
2241 struct snd_kcontrol_new template;
Mark Brownefb7ac32011-03-08 17:23:24 +00002242 struct snd_kcontrol *kcontrol;
2243 char *name = NULL;
2244 int name_len;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002245
2246 memcpy(&template, _template, sizeof(template));
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002247 template.index = 0;
2248
Mark Brownefb7ac32011-03-08 17:23:24 +00002249 if (!long_name)
2250 long_name = template.name;
2251
2252 if (prefix) {
2253 name_len = strlen(long_name) + strlen(prefix) + 2;
Axel Lin57cf9d42011-08-20 11:03:44 +08002254 name = kmalloc(name_len, GFP_KERNEL);
Mark Brownefb7ac32011-03-08 17:23:24 +00002255 if (!name)
2256 return NULL;
2257
2258 snprintf(name, name_len, "%s %s", prefix, long_name);
2259
2260 template.name = name;
2261 } else {
2262 template.name = long_name;
2263 }
2264
2265 kcontrol = snd_ctl_new1(&template, data);
2266
2267 kfree(name);
2268
2269 return kcontrol;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002270}
2271EXPORT_SYMBOL_GPL(snd_soc_cnew);
2272
Liam Girdwood022658b2012-02-03 17:43:09 +00002273static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
2274 const struct snd_kcontrol_new *controls, int num_controls,
2275 const char *prefix, void *data)
2276{
2277 int err, i;
2278
2279 for (i = 0; i < num_controls; i++) {
2280 const struct snd_kcontrol_new *control = &controls[i];
2281 err = snd_ctl_add(card, snd_soc_cnew(control, data,
2282 control->name, prefix));
2283 if (err < 0) {
2284 dev_err(dev, "Failed to add %s: %d\n", control->name, err);
2285 return err;
2286 }
2287 }
2288
2289 return 0;
2290}
2291
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002292/**
Liam Girdwood022658b2012-02-03 17:43:09 +00002293 * snd_soc_add_codec_controls - add an array of controls to a codec.
2294 * Convenience function to add a list of controls. Many codecs were
Ian Molton3e8e1952009-01-09 00:23:21 +00002295 * duplicating this code.
2296 *
2297 * @codec: codec to add controls to
2298 * @controls: array of controls to add
2299 * @num_controls: number of elements in the array
2300 *
2301 * Return 0 for success, else error.
2302 */
Liam Girdwood022658b2012-02-03 17:43:09 +00002303int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
Ian Molton3e8e1952009-01-09 00:23:21 +00002304 const struct snd_kcontrol_new *controls, int num_controls)
2305{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002306 struct snd_card *card = codec->card->snd_card;
Ian Molton3e8e1952009-01-09 00:23:21 +00002307
Liam Girdwood022658b2012-02-03 17:43:09 +00002308 return snd_soc_add_controls(card, codec->dev, controls, num_controls,
2309 codec->name_prefix, codec);
Ian Molton3e8e1952009-01-09 00:23:21 +00002310}
Liam Girdwood022658b2012-02-03 17:43:09 +00002311EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
Ian Molton3e8e1952009-01-09 00:23:21 +00002312
2313/**
Liam Girdwooda491a5c2011-07-04 22:10:51 +01002314 * snd_soc_add_platform_controls - add an array of controls to a platform.
Liam Girdwood022658b2012-02-03 17:43:09 +00002315 * Convenience function to add a list of controls.
Liam Girdwooda491a5c2011-07-04 22:10:51 +01002316 *
2317 * @platform: platform to add controls to
2318 * @controls: array of controls to add
2319 * @num_controls: number of elements in the array
2320 *
2321 * Return 0 for success, else error.
2322 */
2323int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
2324 const struct snd_kcontrol_new *controls, int num_controls)
2325{
2326 struct snd_card *card = platform->card->snd_card;
Liam Girdwooda491a5c2011-07-04 22:10:51 +01002327
Liam Girdwood022658b2012-02-03 17:43:09 +00002328 return snd_soc_add_controls(card, platform->dev, controls, num_controls,
2329 NULL, platform);
Liam Girdwooda491a5c2011-07-04 22:10:51 +01002330}
2331EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
2332
2333/**
Liam Girdwood022658b2012-02-03 17:43:09 +00002334 * snd_soc_add_card_controls - add an array of controls to a SoC card.
2335 * Convenience function to add a list of controls.
2336 *
2337 * @soc_card: SoC card to add controls to
2338 * @controls: array of controls to add
2339 * @num_controls: number of elements in the array
2340 *
2341 * Return 0 for success, else error.
2342 */
2343int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
2344 const struct snd_kcontrol_new *controls, int num_controls)
2345{
2346 struct snd_card *card = soc_card->snd_card;
2347
2348 return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
2349 NULL, soc_card);
2350}
2351EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
2352
2353/**
2354 * snd_soc_add_dai_controls - add an array of controls to a DAI.
2355 * Convienience function to add a list of controls.
2356 *
2357 * @dai: DAI to add controls to
2358 * @controls: array of controls to add
2359 * @num_controls: number of elements in the array
2360 *
2361 * Return 0 for success, else error.
2362 */
2363int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
2364 const struct snd_kcontrol_new *controls, int num_controls)
2365{
2366 struct snd_card *card = dai->card->snd_card;
2367
2368 return snd_soc_add_controls(card, dai->dev, controls, num_controls,
2369 NULL, dai);
2370}
2371EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
2372
2373/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002374 * snd_soc_info_enum_double - enumerated double mixer info callback
2375 * @kcontrol: mixer control
2376 * @uinfo: control element information
2377 *
2378 * Callback to provide information about a double enumerated
2379 * mixer control.
2380 *
2381 * Returns 0 for success.
2382 */
2383int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
2384 struct snd_ctl_elem_info *uinfo)
2385{
2386 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2387
2388 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2389 uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002390 uinfo->value.enumerated.items = e->max;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002391
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002392 if (uinfo->value.enumerated.item > e->max - 1)
2393 uinfo->value.enumerated.item = e->max - 1;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002394 strcpy(uinfo->value.enumerated.name,
2395 e->texts[uinfo->value.enumerated.item]);
2396 return 0;
2397}
2398EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
2399
2400/**
2401 * snd_soc_get_enum_double - enumerated double mixer get callback
2402 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002403 * @ucontrol: control element information
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002404 *
2405 * Callback to get the value of a double enumerated mixer.
2406 *
2407 * Returns 0 for success.
2408 */
2409int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
2410 struct snd_ctl_elem_value *ucontrol)
2411{
2412 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2413 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002414 unsigned int val, bitmask;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002415
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002416 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002417 ;
2418 val = snd_soc_read(codec, e->reg);
Mark Brown3ff3f642008-05-19 12:32:25 +02002419 ucontrol->value.enumerated.item[0]
2420 = (val >> e->shift_l) & (bitmask - 1);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002421 if (e->shift_l != e->shift_r)
2422 ucontrol->value.enumerated.item[1] =
2423 (val >> e->shift_r) & (bitmask - 1);
2424
2425 return 0;
2426}
2427EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
2428
2429/**
2430 * snd_soc_put_enum_double - enumerated double mixer put callback
2431 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002432 * @ucontrol: control element information
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002433 *
2434 * Callback to set the value of a double enumerated mixer.
2435 *
2436 * Returns 0 for success.
2437 */
2438int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
2439 struct snd_ctl_elem_value *ucontrol)
2440{
2441 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2442 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002443 unsigned int val;
2444 unsigned int mask, bitmask;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002445
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002446 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002447 ;
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002448 if (ucontrol->value.enumerated.item[0] > e->max - 1)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002449 return -EINVAL;
2450 val = ucontrol->value.enumerated.item[0] << e->shift_l;
2451 mask = (bitmask - 1) << e->shift_l;
2452 if (e->shift_l != e->shift_r) {
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002453 if (ucontrol->value.enumerated.item[1] > e->max - 1)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002454 return -EINVAL;
2455 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
2456 mask |= (bitmask - 1) << e->shift_r;
2457 }
2458
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002459 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002460}
2461EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
2462
2463/**
Peter Ujfalusi2e72f8e2009-01-05 09:54:57 +02002464 * snd_soc_get_value_enum_double - semi enumerated double mixer get callback
2465 * @kcontrol: mixer control
2466 * @ucontrol: control element information
2467 *
2468 * Callback to get the value of a double semi enumerated mixer.
2469 *
2470 * Semi enumerated mixer: the enumerated items are referred as values. Can be
2471 * used for handling bitfield coded enumeration for example.
2472 *
2473 * Returns 0 for success.
2474 */
2475int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
2476 struct snd_ctl_elem_value *ucontrol)
2477{
2478 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Peter Ujfalusi74155552009-01-08 13:34:29 +02002479 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002480 unsigned int reg_val, val, mux;
Peter Ujfalusi2e72f8e2009-01-05 09:54:57 +02002481
2482 reg_val = snd_soc_read(codec, e->reg);
2483 val = (reg_val >> e->shift_l) & e->mask;
2484 for (mux = 0; mux < e->max; mux++) {
2485 if (val == e->values[mux])
2486 break;
2487 }
2488 ucontrol->value.enumerated.item[0] = mux;
2489 if (e->shift_l != e->shift_r) {
2490 val = (reg_val >> e->shift_r) & e->mask;
2491 for (mux = 0; mux < e->max; mux++) {
2492 if (val == e->values[mux])
2493 break;
2494 }
2495 ucontrol->value.enumerated.item[1] = mux;
2496 }
2497
2498 return 0;
2499}
2500EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double);
2501
2502/**
2503 * snd_soc_put_value_enum_double - semi enumerated double mixer put callback
2504 * @kcontrol: mixer control
2505 * @ucontrol: control element information
2506 *
2507 * Callback to set the value of a double semi enumerated mixer.
2508 *
2509 * Semi enumerated mixer: the enumerated items are referred as values. Can be
2510 * used for handling bitfield coded enumeration for example.
2511 *
2512 * Returns 0 for success.
2513 */
2514int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
2515 struct snd_ctl_elem_value *ucontrol)
2516{
2517 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Peter Ujfalusi74155552009-01-08 13:34:29 +02002518 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002519 unsigned int val;
2520 unsigned int mask;
Peter Ujfalusi2e72f8e2009-01-05 09:54:57 +02002521
2522 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2523 return -EINVAL;
2524 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
2525 mask = e->mask << e->shift_l;
2526 if (e->shift_l != e->shift_r) {
2527 if (ucontrol->value.enumerated.item[1] > e->max - 1)
2528 return -EINVAL;
2529 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
2530 mask |= e->mask << e->shift_r;
2531 }
2532
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002533 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
Peter Ujfalusi2e72f8e2009-01-05 09:54:57 +02002534}
2535EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
2536
2537/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002538 * snd_soc_info_enum_ext - external enumerated single mixer info callback
2539 * @kcontrol: mixer control
2540 * @uinfo: control element information
2541 *
2542 * Callback to provide information about an external enumerated
2543 * single mixer.
2544 *
2545 * Returns 0 for success.
2546 */
2547int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
2548 struct snd_ctl_elem_info *uinfo)
2549{
2550 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2551
2552 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2553 uinfo->count = 1;
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002554 uinfo->value.enumerated.items = e->max;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002555
Jon Smirlf8ba0b72008-07-29 11:42:27 +01002556 if (uinfo->value.enumerated.item > e->max - 1)
2557 uinfo->value.enumerated.item = e->max - 1;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002558 strcpy(uinfo->value.enumerated.name,
2559 e->texts[uinfo->value.enumerated.item]);
2560 return 0;
2561}
2562EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
2563
2564/**
2565 * snd_soc_info_volsw_ext - external single mixer info callback
2566 * @kcontrol: mixer control
2567 * @uinfo: control element information
2568 *
2569 * Callback to provide information about a single external mixer control.
2570 *
2571 * Returns 0 for success.
2572 */
2573int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
2574 struct snd_ctl_elem_info *uinfo)
2575{
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002576 int max = kcontrol->private_value;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002577
Mark Brownfd5dfad2009-04-15 21:37:46 +01002578 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002579 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2580 else
2581 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2582
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002583 uinfo->count = 1;
2584 uinfo->value.integer.min = 0;
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002585 uinfo->value.integer.max = max;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002586 return 0;
2587}
2588EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
2589
2590/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002591 * snd_soc_info_volsw - single mixer info callback
2592 * @kcontrol: mixer control
2593 * @uinfo: control element information
2594 *
Peter Ujfalusie8f5a102011-10-05 10:29:23 +03002595 * Callback to provide information about a single mixer control, or a double
2596 * mixer control that spans 2 registers.
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002597 *
2598 * Returns 0 for success.
2599 */
2600int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
2601 struct snd_ctl_elem_info *uinfo)
2602{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002603 struct soc_mixer_control *mc =
2604 (struct soc_mixer_control *)kcontrol->private_value;
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002605 int platform_max;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002606
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002607 if (!mc->platform_max)
2608 mc->platform_max = mc->max;
2609 platform_max = mc->platform_max;
2610
2611 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002612 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2613 else
2614 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2615
Peter Ujfalusie8f5a102011-10-05 10:29:23 +03002616 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002617 uinfo->value.integer.min = 0;
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002618 uinfo->value.integer.max = platform_max;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002619 return 0;
2620}
2621EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
2622
2623/**
2624 * snd_soc_get_volsw - single mixer get callback
2625 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002626 * @ucontrol: control element information
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002627 *
Peter Ujfalusif7915d92011-10-05 10:29:24 +03002628 * Callback to get the value of a single mixer control, or a double mixer
2629 * control that spans 2 registers.
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002630 *
2631 * Returns 0 for success.
2632 */
2633int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2634 struct snd_ctl_elem_value *ucontrol)
2635{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002636 struct soc_mixer_control *mc =
2637 (struct soc_mixer_control *)kcontrol->private_value;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002638 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002639 unsigned int reg = mc->reg;
Peter Ujfalusif7915d92011-10-05 10:29:24 +03002640 unsigned int reg2 = mc->rreg;
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002641 unsigned int shift = mc->shift;
2642 unsigned int rshift = mc->rshift;
Jon Smirl4eaa9812008-07-29 11:42:26 +01002643 int max = mc->max;
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002644 unsigned int mask = (1 << fls(max)) - 1;
2645 unsigned int invert = mc->invert;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002646
2647 ucontrol->value.integer.value[0] =
2648 (snd_soc_read(codec, reg) >> shift) & mask;
Peter Ujfalusif7915d92011-10-05 10:29:24 +03002649 if (invert)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002650 ucontrol->value.integer.value[0] =
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002651 max - ucontrol->value.integer.value[0];
Peter Ujfalusif7915d92011-10-05 10:29:24 +03002652
2653 if (snd_soc_volsw_is_stereo(mc)) {
2654 if (reg == reg2)
2655 ucontrol->value.integer.value[1] =
2656 (snd_soc_read(codec, reg) >> rshift) & mask;
2657 else
2658 ucontrol->value.integer.value[1] =
2659 (snd_soc_read(codec, reg2) >> shift) & mask;
2660 if (invert)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002661 ucontrol->value.integer.value[1] =
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002662 max - ucontrol->value.integer.value[1];
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002663 }
2664
2665 return 0;
2666}
2667EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2668
2669/**
2670 * snd_soc_put_volsw - single mixer put callback
2671 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002672 * @ucontrol: control element information
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002673 *
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002674 * Callback to set the value of a single mixer control, or a double mixer
2675 * control that spans 2 registers.
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002676 *
2677 * Returns 0 for success.
2678 */
2679int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2680 struct snd_ctl_elem_value *ucontrol)
2681{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002682 struct soc_mixer_control *mc =
2683 (struct soc_mixer_control *)kcontrol->private_value;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002684 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002685 unsigned int reg = mc->reg;
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002686 unsigned int reg2 = mc->rreg;
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002687 unsigned int shift = mc->shift;
2688 unsigned int rshift = mc->rshift;
Jon Smirl4eaa9812008-07-29 11:42:26 +01002689 int max = mc->max;
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002690 unsigned int mask = (1 << fls(max)) - 1;
2691 unsigned int invert = mc->invert;
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002692 int err;
2693 bool type_2r = 0;
2694 unsigned int val2 = 0;
2695 unsigned int val, val_mask;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002696
2697 val = (ucontrol->value.integer.value[0] & mask);
2698 if (invert)
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002699 val = max - val;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002700 val_mask = mask << shift;
2701 val = val << shift;
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002702 if (snd_soc_volsw_is_stereo(mc)) {
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002703 val2 = (ucontrol->value.integer.value[1] & mask);
2704 if (invert)
Philipp Zabela7a4ac82008-01-10 14:37:42 +01002705 val2 = max - val2;
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002706 if (reg == reg2) {
2707 val_mask |= mask << rshift;
2708 val |= val2 << rshift;
2709 } else {
2710 val2 = val2 << shift;
2711 type_2r = 1;
2712 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002713 }
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002714 err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
Mark Brown3ff3f642008-05-19 12:32:25 +02002715 if (err < 0)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002716 return err;
2717
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002718 if (type_2r)
2719 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
2720
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002721 return err;
2722}
Peter Ujfalusi974815b2011-10-05 10:29:25 +03002723EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002724
Mark Browne13ac2e2008-05-28 17:58:05 +01002725/**
Brian Austin1d99f242012-03-30 10:43:55 -05002726 * snd_soc_get_volsw_sx - single mixer get callback
2727 * @kcontrol: mixer control
2728 * @ucontrol: control element information
2729 *
2730 * Callback to get the value of a single mixer control, or a double mixer
2731 * control that spans 2 registers.
2732 *
2733 * Returns 0 for success.
2734 */
2735int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
2736 struct snd_ctl_elem_value *ucontrol)
2737{
2738 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2739 struct soc_mixer_control *mc =
2740 (struct soc_mixer_control *)kcontrol->private_value;
2741
2742 unsigned int reg = mc->reg;
2743 unsigned int reg2 = mc->rreg;
2744 unsigned int shift = mc->shift;
2745 unsigned int rshift = mc->rshift;
2746 int max = mc->max;
2747 int min = mc->min;
2748 int mask = (1 << (fls(min + max) - 1)) - 1;
2749
2750 ucontrol->value.integer.value[0] =
2751 ((snd_soc_read(codec, reg) >> shift) - min) & mask;
2752
2753 if (snd_soc_volsw_is_stereo(mc))
2754 ucontrol->value.integer.value[1] =
2755 ((snd_soc_read(codec, reg2) >> rshift) - min) & mask;
2756
2757 return 0;
2758}
2759EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
2760
2761/**
2762 * snd_soc_put_volsw_sx - double mixer set callback
2763 * @kcontrol: mixer control
2764 * @uinfo: control element information
2765 *
2766 * Callback to set the value of a double mixer control that spans 2 registers.
2767 *
2768 * Returns 0 for success.
2769 */
2770int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
2771 struct snd_ctl_elem_value *ucontrol)
2772{
2773 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2774 struct soc_mixer_control *mc =
2775 (struct soc_mixer_control *)kcontrol->private_value;
2776
2777 unsigned int reg = mc->reg;
2778 unsigned int reg2 = mc->rreg;
2779 unsigned int shift = mc->shift;
2780 unsigned int rshift = mc->rshift;
2781 int max = mc->max;
2782 int min = mc->min;
2783 int mask = (1 << (fls(min + max) - 1)) - 1;
Brian Austin27f1d752012-04-03 11:33:50 -05002784 int err = 0;
Brian Austin1d99f242012-03-30 10:43:55 -05002785 unsigned short val, val_mask, val2 = 0;
2786
2787 val_mask = mask << shift;
2788 val = (ucontrol->value.integer.value[0] + min) & mask;
2789 val = val << shift;
2790
2791 if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
2792 return err;
2793
2794 if (snd_soc_volsw_is_stereo(mc)) {
2795 val_mask = mask << rshift;
2796 val2 = (ucontrol->value.integer.value[1] + min) & mask;
2797 val2 = val2 << rshift;
2798
2799 if (snd_soc_update_bits_locked(codec, reg2, val_mask, val2))
2800 return err;
2801 }
2802 return 0;
2803}
2804EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
2805
2806/**
Mark Browne13ac2e2008-05-28 17:58:05 +01002807 * snd_soc_info_volsw_s8 - signed mixer info callback
2808 * @kcontrol: mixer control
2809 * @uinfo: control element information
2810 *
2811 * Callback to provide information about a signed mixer control.
2812 *
2813 * Returns 0 for success.
2814 */
2815int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
2816 struct snd_ctl_elem_info *uinfo)
2817{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002818 struct soc_mixer_control *mc =
2819 (struct soc_mixer_control *)kcontrol->private_value;
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002820 int platform_max;
Jon Smirl4eaa9812008-07-29 11:42:26 +01002821 int min = mc->min;
Mark Browne13ac2e2008-05-28 17:58:05 +01002822
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002823 if (!mc->platform_max)
2824 mc->platform_max = mc->max;
2825 platform_max = mc->platform_max;
2826
Mark Browne13ac2e2008-05-28 17:58:05 +01002827 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2828 uinfo->count = 2;
2829 uinfo->value.integer.min = 0;
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03002830 uinfo->value.integer.max = platform_max - min;
Mark Browne13ac2e2008-05-28 17:58:05 +01002831 return 0;
2832}
2833EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
2834
2835/**
2836 * snd_soc_get_volsw_s8 - signed mixer get callback
2837 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002838 * @ucontrol: control element information
Mark Browne13ac2e2008-05-28 17:58:05 +01002839 *
2840 * Callback to get the value of a signed mixer control.
2841 *
2842 * Returns 0 for success.
2843 */
2844int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
2845 struct snd_ctl_elem_value *ucontrol)
2846{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002847 struct soc_mixer_control *mc =
2848 (struct soc_mixer_control *)kcontrol->private_value;
Mark Browne13ac2e2008-05-28 17:58:05 +01002849 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002850 unsigned int reg = mc->reg;
Jon Smirl4eaa9812008-07-29 11:42:26 +01002851 int min = mc->min;
Mark Browne13ac2e2008-05-28 17:58:05 +01002852 int val = snd_soc_read(codec, reg);
2853
2854 ucontrol->value.integer.value[0] =
2855 ((signed char)(val & 0xff))-min;
2856 ucontrol->value.integer.value[1] =
2857 ((signed char)((val >> 8) & 0xff))-min;
2858 return 0;
2859}
2860EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8);
2861
2862/**
2863 * snd_soc_put_volsw_sgn - signed mixer put callback
2864 * @kcontrol: mixer control
Mark Brownac11a2b2009-01-01 12:18:17 +00002865 * @ucontrol: control element information
Mark Browne13ac2e2008-05-28 17:58:05 +01002866 *
2867 * Callback to set the value of a signed mixer control.
2868 *
2869 * Returns 0 for success.
2870 */
2871int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2872 struct snd_ctl_elem_value *ucontrol)
2873{
Jon Smirl4eaa9812008-07-29 11:42:26 +01002874 struct soc_mixer_control *mc =
2875 (struct soc_mixer_control *)kcontrol->private_value;
Mark Browne13ac2e2008-05-28 17:58:05 +01002876 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Jon Smirl815ecf8d2008-07-29 10:22:24 -04002877 unsigned int reg = mc->reg;
Jon Smirl4eaa9812008-07-29 11:42:26 +01002878 int min = mc->min;
Daniel Ribeiro46f58222009-06-07 02:49:11 -03002879 unsigned int val;
Mark Browne13ac2e2008-05-28 17:58:05 +01002880
2881 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2882 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
2883
Eero Nurkkala6c508c62009-10-30 13:34:03 +02002884 return snd_soc_update_bits_locked(codec, reg, 0xffff, val);
Mark Browne13ac2e2008-05-28 17:58:05 +01002885}
2886EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2887
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002888/**
Adam Thomson6c9d8cf2012-05-31 15:18:01 +01002889 * snd_soc_info_volsw_range - single mixer info callback with range.
2890 * @kcontrol: mixer control
2891 * @uinfo: control element information
2892 *
2893 * Callback to provide information, within a range, about a single
2894 * mixer control.
2895 *
2896 * returns 0 for success.
2897 */
2898int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
2899 struct snd_ctl_elem_info *uinfo)
2900{
2901 struct soc_mixer_control *mc =
2902 (struct soc_mixer_control *)kcontrol->private_value;
2903 int platform_max;
2904 int min = mc->min;
2905
2906 if (!mc->platform_max)
2907 mc->platform_max = mc->max;
2908 platform_max = mc->platform_max;
2909
2910 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2911 uinfo->count = 1;
2912 uinfo->value.integer.min = 0;
2913 uinfo->value.integer.max = platform_max - min;
2914
2915 return 0;
2916}
2917EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
2918
2919/**
2920 * snd_soc_put_volsw_range - single mixer put value callback with range.
2921 * @kcontrol: mixer control
2922 * @ucontrol: control element information
2923 *
2924 * Callback to set the value, within a range, for a single mixer control.
2925 *
2926 * Returns 0 for success.
2927 */
2928int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
2929 struct snd_ctl_elem_value *ucontrol)
2930{
2931 struct soc_mixer_control *mc =
2932 (struct soc_mixer_control *)kcontrol->private_value;
2933 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2934 unsigned int reg = mc->reg;
2935 unsigned int shift = mc->shift;
2936 int min = mc->min;
2937 int max = mc->max;
2938 unsigned int mask = (1 << fls(max)) - 1;
2939 unsigned int invert = mc->invert;
2940 unsigned int val, val_mask;
2941
2942 val = ((ucontrol->value.integer.value[0] + min) & mask);
2943 if (invert)
2944 val = max - val;
2945 val_mask = mask << shift;
2946 val = val << shift;
2947
2948 return snd_soc_update_bits_locked(codec, reg, val_mask, val);
2949}
2950EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
2951
2952/**
2953 * snd_soc_get_volsw_range - single mixer get callback with range
2954 * @kcontrol: mixer control
2955 * @ucontrol: control element information
2956 *
2957 * Callback to get the value, within a range, of a single mixer control.
2958 *
2959 * Returns 0 for success.
2960 */
2961int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
2962 struct snd_ctl_elem_value *ucontrol)
2963{
2964 struct soc_mixer_control *mc =
2965 (struct soc_mixer_control *)kcontrol->private_value;
2966 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2967 unsigned int reg = mc->reg;
2968 unsigned int shift = mc->shift;
2969 int min = mc->min;
2970 int max = mc->max;
2971 unsigned int mask = (1 << fls(max)) - 1;
2972 unsigned int invert = mc->invert;
2973
2974 ucontrol->value.integer.value[0] =
2975 (snd_soc_read(codec, reg) >> shift) & mask;
2976 if (invert)
2977 ucontrol->value.integer.value[0] =
2978 max - ucontrol->value.integer.value[0];
2979 ucontrol->value.integer.value[0] =
2980 ucontrol->value.integer.value[0] - min;
2981
2982 return 0;
2983}
2984EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
2985
2986/**
Peter Ujfalusi637d3842010-05-07 14:05:49 +03002987 * snd_soc_limit_volume - Set new limit to an existing volume control.
2988 *
2989 * @codec: where to look for the control
2990 * @name: Name of the control
2991 * @max: new maximum limit
2992 *
2993 * Return 0 for success, else error.
2994 */
2995int snd_soc_limit_volume(struct snd_soc_codec *codec,
2996 const char *name, int max)
2997{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002998 struct snd_card *card = codec->card->snd_card;
Peter Ujfalusi637d3842010-05-07 14:05:49 +03002999 struct snd_kcontrol *kctl;
3000 struct soc_mixer_control *mc;
3001 int found = 0;
3002 int ret = -EINVAL;
3003
3004 /* Sanity check for name and max */
3005 if (unlikely(!name || max <= 0))
3006 return -EINVAL;
3007
3008 list_for_each_entry(kctl, &card->controls, list) {
3009 if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) {
3010 found = 1;
3011 break;
3012 }
3013 }
3014 if (found) {
3015 mc = (struct soc_mixer_control *)kctl->private_value;
3016 if (max <= mc->max) {
Peter Ujfalusid11bb4a2010-05-10 14:39:24 +03003017 mc->platform_max = max;
Peter Ujfalusi637d3842010-05-07 14:05:49 +03003018 ret = 0;
3019 }
3020 }
3021 return ret;
3022}
3023EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
3024
Mark Brown71d08512011-10-10 18:31:26 +01003025int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
3026 struct snd_ctl_elem_info *uinfo)
3027{
3028 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3029 struct soc_bytes *params = (void *)kcontrol->private_value;
3030
3031 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
3032 uinfo->count = params->num_regs * codec->val_bytes;
3033
3034 return 0;
3035}
3036EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
3037
3038int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
3039 struct snd_ctl_elem_value *ucontrol)
3040{
3041 struct soc_bytes *params = (void *)kcontrol->private_value;
3042 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3043 int ret;
3044
3045 if (codec->using_regmap)
3046 ret = regmap_raw_read(codec->control_data, params->base,
3047 ucontrol->value.bytes.data,
3048 params->num_regs * codec->val_bytes);
3049 else
3050 ret = -EINVAL;
3051
Mark Brownf831b052012-02-17 16:20:33 -08003052 /* Hide any masked bytes to ensure consistent data reporting */
3053 if (ret == 0 && params->mask) {
3054 switch (codec->val_bytes) {
3055 case 1:
3056 ucontrol->value.bytes.data[0] &= ~params->mask;
3057 break;
3058 case 2:
3059 ((u16 *)(&ucontrol->value.bytes.data))[0]
3060 &= ~params->mask;
3061 break;
3062 case 4:
3063 ((u32 *)(&ucontrol->value.bytes.data))[0]
3064 &= ~params->mask;
3065 break;
3066 default:
3067 return -EINVAL;
3068 }
3069 }
3070
Mark Brown71d08512011-10-10 18:31:26 +01003071 return ret;
3072}
3073EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
3074
3075int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
3076 struct snd_ctl_elem_value *ucontrol)
3077{
3078 struct soc_bytes *params = (void *)kcontrol->private_value;
3079 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Mark Brownf831b052012-02-17 16:20:33 -08003080 int ret, len;
3081 unsigned int val;
3082 void *data;
Mark Brown71d08512011-10-10 18:31:26 +01003083
Mark Brownf831b052012-02-17 16:20:33 -08003084 if (!codec->using_regmap)
3085 return -EINVAL;
3086
3087 data = ucontrol->value.bytes.data;
3088 len = params->num_regs * codec->val_bytes;
3089
3090 /*
3091 * If we've got a mask then we need to preserve the register
3092 * bits. We shouldn't modify the incoming data so take a
3093 * copy.
3094 */
3095 if (params->mask) {
3096 ret = regmap_read(codec->control_data, params->base, &val);
3097 if (ret != 0)
3098 return ret;
3099
3100 val &= params->mask;
3101
3102 data = kmemdup(data, len, GFP_KERNEL);
3103 if (!data)
3104 return -ENOMEM;
3105
3106 switch (codec->val_bytes) {
3107 case 1:
3108 ((u8 *)data)[0] &= ~params->mask;
3109 ((u8 *)data)[0] |= val;
3110 break;
3111 case 2:
3112 ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
3113 ((u16 *)data)[0] |= cpu_to_be16(val);
3114 break;
3115 case 4:
3116 ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
3117 ((u32 *)data)[0] |= cpu_to_be32(val);
3118 break;
3119 default:
3120 return -EINVAL;
3121 }
3122 }
3123
3124 ret = regmap_raw_write(codec->control_data, params->base,
3125 data, len);
3126
3127 if (params->mask)
3128 kfree(data);
Mark Brown71d08512011-10-10 18:31:26 +01003129
3130 return ret;
3131}
3132EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
3133
apatard@mandriva.comb6f4bb32010-05-15 17:30:01 +02003134/**
Kristoffer KARLSSON4183eed22012-04-20 11:32:13 +02003135 * snd_soc_info_xr_sx - signed multi register info callback
3136 * @kcontrol: mreg control
3137 * @uinfo: control element information
3138 *
3139 * Callback to provide information of a control that can
3140 * span multiple codec registers which together
3141 * forms a single signed value in a MSB/LSB manner.
3142 *
3143 * Returns 0 for success.
3144 */
3145int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
3146 struct snd_ctl_elem_info *uinfo)
3147{
3148 struct soc_mreg_control *mc =
3149 (struct soc_mreg_control *)kcontrol->private_value;
3150 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3151 uinfo->count = 1;
3152 uinfo->value.integer.min = mc->min;
3153 uinfo->value.integer.max = mc->max;
3154
3155 return 0;
3156}
3157EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
3158
3159/**
3160 * snd_soc_get_xr_sx - signed multi register get callback
3161 * @kcontrol: mreg control
3162 * @ucontrol: control element information
3163 *
3164 * Callback to get the value of a control that can span
3165 * multiple codec registers which together forms a single
3166 * signed value in a MSB/LSB manner. The control supports
3167 * specifying total no of bits used to allow for bitfields
3168 * across the multiple codec registers.
3169 *
3170 * Returns 0 for success.
3171 */
3172int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
3173 struct snd_ctl_elem_value *ucontrol)
3174{
3175 struct soc_mreg_control *mc =
3176 (struct soc_mreg_control *)kcontrol->private_value;
3177 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3178 unsigned int regbase = mc->regbase;
3179 unsigned int regcount = mc->regcount;
3180 unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
3181 unsigned int regwmask = (1<<regwshift)-1;
3182 unsigned int invert = mc->invert;
3183 unsigned long mask = (1UL<<mc->nbits)-1;
3184 long min = mc->min;
3185 long max = mc->max;
3186 long val = 0;
3187 unsigned long regval;
3188 unsigned int i;
3189
3190 for (i = 0; i < regcount; i++) {
3191 regval = snd_soc_read(codec, regbase+i) & regwmask;
3192 val |= regval << (regwshift*(regcount-i-1));
3193 }
3194 val &= mask;
3195 if (min < 0 && val > max)
3196 val |= ~mask;
3197 if (invert)
3198 val = max - val;
3199 ucontrol->value.integer.value[0] = val;
3200
3201 return 0;
3202}
3203EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
3204
3205/**
3206 * snd_soc_put_xr_sx - signed multi register get callback
3207 * @kcontrol: mreg control
3208 * @ucontrol: control element information
3209 *
3210 * Callback to set the value of a control that can span
3211 * multiple codec registers which together forms a single
3212 * signed value in a MSB/LSB manner. The control supports
3213 * specifying total no of bits used to allow for bitfields
3214 * across the multiple codec registers.
3215 *
3216 * Returns 0 for success.
3217 */
3218int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
3219 struct snd_ctl_elem_value *ucontrol)
3220{
3221 struct soc_mreg_control *mc =
3222 (struct soc_mreg_control *)kcontrol->private_value;
3223 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3224 unsigned int regbase = mc->regbase;
3225 unsigned int regcount = mc->regcount;
3226 unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
3227 unsigned int regwmask = (1<<regwshift)-1;
3228 unsigned int invert = mc->invert;
3229 unsigned long mask = (1UL<<mc->nbits)-1;
Kristoffer KARLSSON4183eed22012-04-20 11:32:13 +02003230 long max = mc->max;
3231 long val = ucontrol->value.integer.value[0];
3232 unsigned int i, regval, regmask;
3233 int err;
3234
3235 if (invert)
3236 val = max - val;
3237 val &= mask;
3238 for (i = 0; i < regcount; i++) {
3239 regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
3240 regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
3241 err = snd_soc_update_bits_locked(codec, regbase+i,
3242 regmask, regval);
3243 if (err < 0)
3244 return err;
3245 }
3246
3247 return 0;
3248}
3249EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
3250
3251/**
Kristoffer KARLSSONdd7b10b2012-04-20 11:32:44 +02003252 * snd_soc_get_strobe - strobe get callback
3253 * @kcontrol: mixer control
3254 * @ucontrol: control element information
3255 *
3256 * Callback get the value of a strobe mixer control.
3257 *
3258 * Returns 0 for success.
3259 */
3260int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
3261 struct snd_ctl_elem_value *ucontrol)
3262{
3263 struct soc_mixer_control *mc =
3264 (struct soc_mixer_control *)kcontrol->private_value;
3265 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3266 unsigned int reg = mc->reg;
3267 unsigned int shift = mc->shift;
3268 unsigned int mask = 1 << shift;
3269 unsigned int invert = mc->invert != 0;
3270 unsigned int val = snd_soc_read(codec, reg) & mask;
3271
3272 if (shift != 0 && val != 0)
3273 val = val >> shift;
3274 ucontrol->value.enumerated.item[0] = val ^ invert;
3275
3276 return 0;
3277}
3278EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
3279
3280/**
3281 * snd_soc_put_strobe - strobe put callback
3282 * @kcontrol: mixer control
3283 * @ucontrol: control element information
3284 *
3285 * Callback strobe a register bit to high then low (or the inverse)
3286 * in one pass of a single mixer enum control.
3287 *
3288 * Returns 1 for success.
3289 */
3290int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
3291 struct snd_ctl_elem_value *ucontrol)
3292{
3293 struct soc_mixer_control *mc =
3294 (struct soc_mixer_control *)kcontrol->private_value;
3295 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3296 unsigned int reg = mc->reg;
3297 unsigned int shift = mc->shift;
3298 unsigned int mask = 1 << shift;
3299 unsigned int invert = mc->invert != 0;
3300 unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
3301 unsigned int val1 = (strobe ^ invert) ? mask : 0;
3302 unsigned int val2 = (strobe ^ invert) ? 0 : mask;
3303 int err;
3304
3305 err = snd_soc_update_bits_locked(codec, reg, mask, val1);
3306 if (err < 0)
3307 return err;
3308
3309 err = snd_soc_update_bits_locked(codec, reg, mask, val2);
3310 return err;
3311}
3312EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
3313
3314/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003315 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
3316 * @dai: DAI
3317 * @clk_id: DAI specific clock ID
3318 * @freq: new clock frequency in Hz
3319 * @dir: new clock direction - input/output.
3320 *
3321 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
3322 */
3323int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
3324 unsigned int freq, int dir)
3325{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003326 if (dai->driver && dai->driver->ops->set_sysclk)
3327 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
Mark Brownec4ee522011-03-07 20:58:11 +00003328 else if (dai->codec && dai->codec->driver->set_sysclk)
Mark Brownda1c6ea2011-08-24 20:09:01 +01003329 return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0,
Mark Brownec4ee522011-03-07 20:58:11 +00003330 freq, dir);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003331 else
3332 return -EINVAL;
3333}
3334EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
3335
3336/**
Mark Brownec4ee522011-03-07 20:58:11 +00003337 * snd_soc_codec_set_sysclk - configure CODEC system or master clock.
3338 * @codec: CODEC
3339 * @clk_id: DAI specific clock ID
Mark Brownda1c6ea2011-08-24 20:09:01 +01003340 * @source: Source for the clock
Mark Brownec4ee522011-03-07 20:58:11 +00003341 * @freq: new clock frequency in Hz
3342 * @dir: new clock direction - input/output.
3343 *
3344 * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
3345 */
3346int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
Mark Brownda1c6ea2011-08-24 20:09:01 +01003347 int source, unsigned int freq, int dir)
Mark Brownec4ee522011-03-07 20:58:11 +00003348{
3349 if (codec->driver->set_sysclk)
Mark Brownda1c6ea2011-08-24 20:09:01 +01003350 return codec->driver->set_sysclk(codec, clk_id, source,
3351 freq, dir);
Mark Brownec4ee522011-03-07 20:58:11 +00003352 else
3353 return -EINVAL;
3354}
3355EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk);
3356
3357/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003358 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
3359 * @dai: DAI
Mark Brownac11a2b2009-01-01 12:18:17 +00003360 * @div_id: DAI specific clock divider ID
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003361 * @div: new clock divisor.
3362 *
3363 * Configures the clock dividers. This is used to derive the best DAI bit and
3364 * frame clocks from the system or master clock. It's best to set the DAI bit
3365 * and frame clocks as low as possible to save system power.
3366 */
3367int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
3368 int div_id, int div)
3369{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003370 if (dai->driver && dai->driver->ops->set_clkdiv)
3371 return dai->driver->ops->set_clkdiv(dai, div_id, div);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003372 else
3373 return -EINVAL;
3374}
3375EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
3376
3377/**
3378 * snd_soc_dai_set_pll - configure DAI PLL.
3379 * @dai: DAI
3380 * @pll_id: DAI specific PLL ID
Mark Brown85488032009-09-05 18:52:16 +01003381 * @source: DAI specific source for the PLL
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003382 * @freq_in: PLL input clock frequency in Hz
3383 * @freq_out: requested PLL output clock frequency in Hz
3384 *
3385 * Configures and enables PLL to generate output clock based on input clock.
3386 */
Mark Brown85488032009-09-05 18:52:16 +01003387int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
3388 unsigned int freq_in, unsigned int freq_out)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003389{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003390 if (dai->driver && dai->driver->ops->set_pll)
3391 return dai->driver->ops->set_pll(dai, pll_id, source,
Mark Brown85488032009-09-05 18:52:16 +01003392 freq_in, freq_out);
Mark Brownec4ee522011-03-07 20:58:11 +00003393 else if (dai->codec && dai->codec->driver->set_pll)
3394 return dai->codec->driver->set_pll(dai->codec, pll_id, source,
3395 freq_in, freq_out);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003396 else
3397 return -EINVAL;
3398}
3399EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
3400
Mark Brownec4ee522011-03-07 20:58:11 +00003401/*
3402 * snd_soc_codec_set_pll - configure codec PLL.
3403 * @codec: CODEC
3404 * @pll_id: DAI specific PLL ID
3405 * @source: DAI specific source for the PLL
3406 * @freq_in: PLL input clock frequency in Hz
3407 * @freq_out: requested PLL output clock frequency in Hz
3408 *
3409 * Configures and enables PLL to generate output clock based on input clock.
3410 */
3411int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
3412 unsigned int freq_in, unsigned int freq_out)
3413{
3414 if (codec->driver->set_pll)
3415 return codec->driver->set_pll(codec, pll_id, source,
3416 freq_in, freq_out);
3417 else
3418 return -EINVAL;
3419}
3420EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
3421
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003422/**
3423 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
3424 * @dai: DAI
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003425 * @fmt: SND_SOC_DAIFMT_ format value.
3426 *
3427 * Configures the DAI hardware format and clocking.
3428 */
3429int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
3430{
Shawn Guo5e4ba562012-03-09 00:59:40 +08003431 if (dai->driver == NULL)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003432 return -EINVAL;
Shawn Guo5e4ba562012-03-09 00:59:40 +08003433 if (dai->driver->ops->set_fmt == NULL)
3434 return -ENOTSUPP;
3435 return dai->driver->ops->set_fmt(dai, fmt);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003436}
3437EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
3438
3439/**
3440 * snd_soc_dai_set_tdm_slot - configure DAI TDM.
3441 * @dai: DAI
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03003442 * @tx_mask: bitmask representing active TX slots.
3443 * @rx_mask: bitmask representing active RX slots.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003444 * @slots: Number of slots in use.
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03003445 * @slot_width: Width in bits for each slot.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003446 *
3447 * Configures a DAI for TDM operation. Both mask and slots are codec and DAI
3448 * specific.
3449 */
3450int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03003451 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003452{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003453 if (dai->driver && dai->driver->ops->set_tdm_slot)
3454 return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03003455 slots, slot_width);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003456 else
3457 return -EINVAL;
3458}
3459EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
3460
3461/**
Barry Song472df3c2009-09-12 01:16:29 +08003462 * snd_soc_dai_set_channel_map - configure DAI audio channel map
3463 * @dai: DAI
3464 * @tx_num: how many TX channels
3465 * @tx_slot: pointer to an array which imply the TX slot number channel
3466 * 0~num-1 uses
3467 * @rx_num: how many RX channels
3468 * @rx_slot: pointer to an array which imply the RX slot number channel
3469 * 0~num-1 uses
3470 *
3471 * configure the relationship between channel number and TDM slot number.
3472 */
3473int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
3474 unsigned int tx_num, unsigned int *tx_slot,
3475 unsigned int rx_num, unsigned int *rx_slot)
3476{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003477 if (dai->driver && dai->driver->ops->set_channel_map)
3478 return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
Barry Song472df3c2009-09-12 01:16:29 +08003479 rx_num, rx_slot);
3480 else
3481 return -EINVAL;
3482}
3483EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
3484
3485/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003486 * snd_soc_dai_set_tristate - configure DAI system or master clock.
3487 * @dai: DAI
3488 * @tristate: tristate enable
3489 *
3490 * Tristates the DAI so that others can use it.
3491 */
3492int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
3493{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003494 if (dai->driver && dai->driver->ops->set_tristate)
3495 return dai->driver->ops->set_tristate(dai, tristate);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003496 else
3497 return -EINVAL;
3498}
3499EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
3500
3501/**
3502 * snd_soc_dai_digital_mute - configure DAI system or master clock.
3503 * @dai: DAI
3504 * @mute: mute enable
3505 *
3506 * Mutes the DAI DAC.
3507 */
3508int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
3509{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003510 if (dai->driver && dai->driver->ops->digital_mute)
3511 return dai->driver->ops->digital_mute(dai, mute);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003512 else
Mark Brown04570c62012-04-13 19:16:03 +01003513 return -ENOTSUPP;
Liam Girdwood8c6529d2008-07-08 13:19:13 +01003514}
3515EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
3516
Mark Brownc5af3a22008-11-28 13:29:45 +00003517/**
3518 * snd_soc_register_card - Register a card with the ASoC core
3519 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003520 * @card: Card to register
Mark Brownc5af3a22008-11-28 13:29:45 +00003521 *
Mark Brownc5af3a22008-11-28 13:29:45 +00003522 */
Vinod Koul70a7ca32011-01-14 19:22:48 +05303523int snd_soc_register_card(struct snd_soc_card *card)
Mark Brownc5af3a22008-11-28 13:29:45 +00003524{
Mark Brownb19e6e72012-03-14 21:18:39 +00003525 int i, ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003526
Mark Brownc5af3a22008-11-28 13:29:45 +00003527 if (!card->name || !card->dev)
3528 return -EINVAL;
3529
Stephen Warren5a504962011-12-21 10:40:59 -07003530 for (i = 0; i < card->num_links; i++) {
3531 struct snd_soc_dai_link *link = &card->dai_link[i];
3532
3533 /*
3534 * Codec must be specified by 1 of name or OF node,
3535 * not both or neither.
3536 */
3537 if (!!link->codec_name == !!link->codec_of_node) {
3538 dev_err(card->dev,
Liam Girdwood3b09bb82012-01-09 12:09:29 +00003539 "Neither/both codec name/of_node are set for %s\n",
3540 link->name);
Stephen Warren5a504962011-12-21 10:40:59 -07003541 return -EINVAL;
3542 }
Stephen Warrenbc926572012-05-25 18:22:11 -06003543 /* Codec DAI name must be specified */
3544 if (!link->codec_dai_name) {
3545 dev_err(card->dev, "codec_dai_name not set for %s\n",
3546 link->name);
3547 return -EINVAL;
3548 }
Stephen Warren5a504962011-12-21 10:40:59 -07003549
3550 /*
3551 * Platform may be specified by either name or OF node, but
3552 * can be left unspecified, and a dummy platform will be used.
3553 */
3554 if (link->platform_name && link->platform_of_node) {
3555 dev_err(card->dev,
Liam Girdwood3b09bb82012-01-09 12:09:29 +00003556 "Both platform name/of_node are set for %s\n", link->name);
Stephen Warren5a504962011-12-21 10:40:59 -07003557 return -EINVAL;
3558 }
3559
3560 /*
Stephen Warrenbc926572012-05-25 18:22:11 -06003561 * CPU device may be specified by either name or OF node, but
3562 * can be left unspecified, and will be matched based on DAI
3563 * name alone..
Stephen Warren5a504962011-12-21 10:40:59 -07003564 */
Stephen Warrenbc926572012-05-25 18:22:11 -06003565 if (link->cpu_name && link->cpu_of_node) {
Stephen Warren5a504962011-12-21 10:40:59 -07003566 dev_err(card->dev,
Stephen Warrenbc926572012-05-25 18:22:11 -06003567 "Neither/both cpu name/of_node are set for %s\n",
3568 link->name);
3569 return -EINVAL;
3570 }
3571 /*
3572 * At least one of CPU DAI name or CPU device name/node must be
3573 * specified
3574 */
3575 if (!link->cpu_dai_name &&
3576 !(link->cpu_name || link->cpu_of_node)) {
3577 dev_err(card->dev,
3578 "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
Liam Girdwood3b09bb82012-01-09 12:09:29 +00003579 link->name);
Stephen Warren5a504962011-12-21 10:40:59 -07003580 return -EINVAL;
3581 }
3582 }
3583
Mark Browned77cc12011-05-03 18:25:34 +01003584 dev_set_drvdata(card->dev, card);
3585
Stephen Warren111c6412011-01-28 14:26:35 -07003586 snd_soc_initialize_card_lists(card);
3587
Vinod Koul150dd2f2011-01-13 22:48:32 +05303588 soc_init_card_debugfs(card);
3589
Mark Brown181a6892012-03-14 20:18:49 +00003590 card->rtd = devm_kzalloc(card->dev,
3591 sizeof(struct snd_soc_pcm_runtime) *
3592 (card->num_links + card->num_aux_devs),
3593 GFP_KERNEL);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003594 if (card->rtd == NULL)
3595 return -ENOMEM;
Liam Girdwooda7dbb602012-04-17 18:00:11 +01003596 card->num_rtd = 0;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02003597 card->rtd_aux = &card->rtd[card->num_links];
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003598
3599 for (i = 0; i < card->num_links; i++)
3600 card->rtd[i].dai_link = &card->dai_link[i];
3601
Mark Brownc5af3a22008-11-28 13:29:45 +00003602 INIT_LIST_HEAD(&card->list);
Mark Browndb432b42011-10-03 21:06:40 +01003603 INIT_LIST_HEAD(&card->dapm_dirty);
Mark Brownc5af3a22008-11-28 13:29:45 +00003604 card->instantiated = 0;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003605 mutex_init(&card->mutex);
Liam Girdwooda73fb2d2012-03-07 10:38:26 +00003606 mutex_init(&card->dapm_mutex);
Mark Brownc5af3a22008-11-28 13:29:45 +00003607
Mark Brownb19e6e72012-03-14 21:18:39 +00003608 ret = snd_soc_instantiate_card(card);
3609 if (ret != 0)
3610 soc_cleanup_card_debugfs(card);
Mark Brownc5af3a22008-11-28 13:29:45 +00003611
Mark Brownb19e6e72012-03-14 21:18:39 +00003612 return ret;
Mark Brownc5af3a22008-11-28 13:29:45 +00003613}
Vinod Koul70a7ca32011-01-14 19:22:48 +05303614EXPORT_SYMBOL_GPL(snd_soc_register_card);
Mark Brownc5af3a22008-11-28 13:29:45 +00003615
3616/**
3617 * snd_soc_unregister_card - Unregister a card with the ASoC core
3618 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003619 * @card: Card to unregister
Mark Brownc5af3a22008-11-28 13:29:45 +00003620 *
Mark Brownc5af3a22008-11-28 13:29:45 +00003621 */
Vinod Koul70a7ca32011-01-14 19:22:48 +05303622int snd_soc_unregister_card(struct snd_soc_card *card)
Mark Brownc5af3a22008-11-28 13:29:45 +00003623{
Vinod Koulb0e26482011-01-13 22:48:02 +05303624 if (card->instantiated)
3625 soc_cleanup_card_resources(card);
Mark Brownc5af3a22008-11-28 13:29:45 +00003626 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
3627
3628 return 0;
3629}
Vinod Koul70a7ca32011-01-14 19:22:48 +05303630EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
Mark Brownc5af3a22008-11-28 13:29:45 +00003631
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003632/*
3633 * Simplify DAI link configuration by removing ".-1" from device names
3634 * and sanitizing names.
3635 */
Dimitris Papastamos0b9a2142010-12-06 15:49:20 +00003636static char *fmt_single_name(struct device *dev, int *id)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003637{
3638 char *found, name[NAME_SIZE];
3639 int id1, id2;
3640
3641 if (dev_name(dev) == NULL)
3642 return NULL;
3643
Dimitris Papastamos58818a72010-12-06 15:42:17 +00003644 strlcpy(name, dev_name(dev), NAME_SIZE);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003645
3646 /* are we a "%s.%d" name (platform and SPI components) */
3647 found = strstr(name, dev->driver->name);
3648 if (found) {
3649 /* get ID */
3650 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) {
3651
3652 /* discard ID from name if ID == -1 */
3653 if (*id == -1)
3654 found[strlen(dev->driver->name)] = '\0';
3655 }
3656
3657 } else {
3658 /* I2C component devices are named "bus-addr" */
3659 if (sscanf(name, "%x-%x", &id1, &id2) == 2) {
3660 char tmp[NAME_SIZE];
3661
3662 /* create unique ID number from I2C addr and bus */
Jarkko Nikula05899442010-10-19 11:10:45 +03003663 *id = ((id1 & 0xffff) << 16) + id2;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003664
3665 /* sanitize component name for DAI link creation */
3666 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name);
Dimitris Papastamos58818a72010-12-06 15:42:17 +00003667 strlcpy(name, tmp, NAME_SIZE);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003668 } else
3669 *id = 0;
3670 }
3671
3672 return kstrdup(name, GFP_KERNEL);
3673}
3674
3675/*
3676 * Simplify DAI link naming for single devices with multiple DAIs by removing
3677 * any ".-1" and using the DAI name (instead of device name).
3678 */
3679static inline char *fmt_multiple_name(struct device *dev,
3680 struct snd_soc_dai_driver *dai_drv)
3681{
3682 if (dai_drv->name == NULL) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02003683 pr_err("asoc: error - multiple DAI %s registered with no name\n",
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003684 dev_name(dev));
3685 return NULL;
3686 }
3687
3688 return kstrdup(dai_drv->name, GFP_KERNEL);
3689}
3690
Mark Brown91151712008-11-30 23:31:24 +00003691/**
3692 * snd_soc_register_dai - Register a DAI with the ASoC core
3693 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003694 * @dai: DAI to register
Mark Brown91151712008-11-30 23:31:24 +00003695 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003696int snd_soc_register_dai(struct device *dev,
3697 struct snd_soc_dai_driver *dai_drv)
Mark Brown91151712008-11-30 23:31:24 +00003698{
Mark Brown054880f2012-04-09 17:29:19 +01003699 struct snd_soc_codec *codec;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003700 struct snd_soc_dai *dai;
Mark Brown91151712008-11-30 23:31:24 +00003701
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003702 dev_dbg(dev, "dai register %s\n", dev_name(dev));
Mark Brown91151712008-11-30 23:31:24 +00003703
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003704 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
3705 if (dai == NULL)
Lu Guanquna7393622011-04-20 16:00:51 +08003706 return -ENOMEM;
Eric Miao6335d052009-03-03 09:41:00 +08003707
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003708 /* create DAI component name */
3709 dai->name = fmt_single_name(dev, &dai->id);
3710 if (dai->name == NULL) {
3711 kfree(dai);
3712 return -ENOMEM;
3713 }
3714
3715 dai->dev = dev;
3716 dai->driver = dai_drv;
Liam Girdwoodbe09ad92012-03-07 11:47:41 +00003717 dai->dapm.dev = dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003718 if (!dai->driver->ops)
3719 dai->driver->ops = &null_dai_ops;
Mark Brown91151712008-11-30 23:31:24 +00003720
3721 mutex_lock(&client_mutex);
Mark Brown054880f2012-04-09 17:29:19 +01003722
3723 list_for_each_entry(codec, &codec_list, list) {
3724 if (codec->dev == dev) {
3725 dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
3726 dai->name, codec->name);
3727 dai->codec = codec;
3728 break;
3729 }
3730 }
3731
Peter Ujfalusi5f800082012-08-07 10:24:13 +03003732 if (!dai->codec)
3733 dai->dapm.idle_bias_off = 1;
3734
Mark Brown91151712008-11-30 23:31:24 +00003735 list_add(&dai->list, &dai_list);
Mark Brown054880f2012-04-09 17:29:19 +01003736
Mark Brown91151712008-11-30 23:31:24 +00003737 mutex_unlock(&client_mutex);
3738
3739 pr_debug("Registered DAI '%s'\n", dai->name);
3740
3741 return 0;
3742}
3743EXPORT_SYMBOL_GPL(snd_soc_register_dai);
3744
3745/**
3746 * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
3747 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003748 * @dai: DAI to unregister
Mark Brown91151712008-11-30 23:31:24 +00003749 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003750void snd_soc_unregister_dai(struct device *dev)
Mark Brown91151712008-11-30 23:31:24 +00003751{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003752 struct snd_soc_dai *dai;
3753
3754 list_for_each_entry(dai, &dai_list, list) {
3755 if (dev == dai->dev)
3756 goto found;
3757 }
3758 return;
3759
3760found:
Mark Brown91151712008-11-30 23:31:24 +00003761 mutex_lock(&client_mutex);
3762 list_del(&dai->list);
3763 mutex_unlock(&client_mutex);
3764
3765 pr_debug("Unregistered DAI '%s'\n", dai->name);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003766 kfree(dai->name);
3767 kfree(dai);
Mark Brown91151712008-11-30 23:31:24 +00003768}
3769EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
3770
3771/**
3772 * snd_soc_register_dais - Register multiple DAIs with the ASoC core
3773 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003774 * @dai: Array of DAIs to register
3775 * @count: Number of DAIs
Mark Brown91151712008-11-30 23:31:24 +00003776 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003777int snd_soc_register_dais(struct device *dev,
3778 struct snd_soc_dai_driver *dai_drv, size_t count)
Mark Brown91151712008-11-30 23:31:24 +00003779{
Mark Brown054880f2012-04-09 17:29:19 +01003780 struct snd_soc_codec *codec;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003781 struct snd_soc_dai *dai;
3782 int i, ret = 0;
3783
Liam Girdwood720ffa42010-08-18 00:30:30 +01003784 dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
Mark Brown91151712008-11-30 23:31:24 +00003785
3786 for (i = 0; i < count; i++) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003787
3788 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
Axel Linc46e0072010-11-03 15:04:45 +08003789 if (dai == NULL) {
3790 ret = -ENOMEM;
3791 goto err;
3792 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003793
3794 /* create DAI component name */
3795 dai->name = fmt_multiple_name(dev, &dai_drv[i]);
3796 if (dai->name == NULL) {
3797 kfree(dai);
3798 ret = -EINVAL;
Mark Brown91151712008-11-30 23:31:24 +00003799 goto err;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003800 }
3801
3802 dai->dev = dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003803 dai->driver = &dai_drv[i];
Mark Brown0f9141c2010-10-12 15:43:21 +01003804 if (dai->driver->id)
3805 dai->id = dai->driver->id;
3806 else
3807 dai->id = i;
Liam Girdwoodbe09ad92012-03-07 11:47:41 +00003808 dai->dapm.dev = dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003809 if (!dai->driver->ops)
3810 dai->driver->ops = &null_dai_ops;
3811
3812 mutex_lock(&client_mutex);
Mark Brown054880f2012-04-09 17:29:19 +01003813
3814 list_for_each_entry(codec, &codec_list, list) {
3815 if (codec->dev == dev) {
3816 dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
3817 dai->name, codec->name);
3818 dai->codec = codec;
3819 break;
3820 }
3821 }
3822
Peter Ujfalusi5f800082012-08-07 10:24:13 +03003823 if (!dai->codec)
3824 dai->dapm.idle_bias_off = 1;
3825
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003826 list_add(&dai->list, &dai_list);
Mark Brown054880f2012-04-09 17:29:19 +01003827
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003828 mutex_unlock(&client_mutex);
3829
3830 pr_debug("Registered DAI '%s'\n", dai->name);
Mark Brown91151712008-11-30 23:31:24 +00003831 }
3832
3833 return 0;
3834
3835err:
3836 for (i--; i >= 0; i--)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003837 snd_soc_unregister_dai(dev);
Mark Brown91151712008-11-30 23:31:24 +00003838
3839 return ret;
3840}
3841EXPORT_SYMBOL_GPL(snd_soc_register_dais);
3842
3843/**
3844 * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
3845 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003846 * @dai: Array of DAIs to unregister
3847 * @count: Number of DAIs
Mark Brown91151712008-11-30 23:31:24 +00003848 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003849void snd_soc_unregister_dais(struct device *dev, size_t count)
Mark Brown91151712008-11-30 23:31:24 +00003850{
3851 int i;
3852
3853 for (i = 0; i < count; i++)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003854 snd_soc_unregister_dai(dev);
Mark Brown91151712008-11-30 23:31:24 +00003855}
3856EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
3857
Mark Brown12a48a8c2008-12-03 19:40:30 +00003858/**
3859 * snd_soc_register_platform - Register a platform with the ASoC core
3860 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003861 * @platform: platform to register
Mark Brown12a48a8c2008-12-03 19:40:30 +00003862 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003863int snd_soc_register_platform(struct device *dev,
3864 struct snd_soc_platform_driver *platform_drv)
Mark Brown12a48a8c2008-12-03 19:40:30 +00003865{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003866 struct snd_soc_platform *platform;
Mark Brown12a48a8c2008-12-03 19:40:30 +00003867
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003868 dev_dbg(dev, "platform register %s\n", dev_name(dev));
3869
3870 platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
3871 if (platform == NULL)
Lu Guanquna7393622011-04-20 16:00:51 +08003872 return -ENOMEM;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003873
3874 /* create platform component name */
3875 platform->name = fmt_single_name(dev, &platform->id);
3876 if (platform->name == NULL) {
3877 kfree(platform);
3878 return -ENOMEM;
3879 }
3880
3881 platform->dev = dev;
3882 platform->driver = platform_drv;
Liam Girdwoodb7950642011-07-04 22:10:52 +01003883 platform->dapm.dev = dev;
3884 platform->dapm.platform = platform;
Liam Girdwood64a648c2011-07-25 11:15:15 +01003885 platform->dapm.stream_event = platform_drv->stream_event;
Liam Girdwoodcc22d372012-03-06 18:16:18 +00003886 mutex_init(&platform->mutex);
Mark Brown12a48a8c2008-12-03 19:40:30 +00003887
3888 mutex_lock(&client_mutex);
3889 list_add(&platform->list, &platform_list);
3890 mutex_unlock(&client_mutex);
3891
3892 pr_debug("Registered platform '%s'\n", platform->name);
3893
3894 return 0;
3895}
3896EXPORT_SYMBOL_GPL(snd_soc_register_platform);
3897
3898/**
3899 * snd_soc_unregister_platform - Unregister a platform from the ASoC core
3900 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003901 * @platform: platform to unregister
Mark Brown12a48a8c2008-12-03 19:40:30 +00003902 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003903void snd_soc_unregister_platform(struct device *dev)
Mark Brown12a48a8c2008-12-03 19:40:30 +00003904{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003905 struct snd_soc_platform *platform;
3906
3907 list_for_each_entry(platform, &platform_list, list) {
3908 if (dev == platform->dev)
3909 goto found;
3910 }
3911 return;
3912
3913found:
Mark Brown12a48a8c2008-12-03 19:40:30 +00003914 mutex_lock(&client_mutex);
3915 list_del(&platform->list);
3916 mutex_unlock(&client_mutex);
3917
3918 pr_debug("Unregistered platform '%s'\n", platform->name);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003919 kfree(platform->name);
3920 kfree(platform);
Mark Brown12a48a8c2008-12-03 19:40:30 +00003921}
3922EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
3923
Mark Brown151ab222009-05-09 16:22:58 +01003924static u64 codec_format_map[] = {
3925 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
3926 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
3927 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
3928 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
3929 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
3930 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
3931 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
3932 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
3933 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
3934 SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
3935 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
3936 SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
3937 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
3938 SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
3939 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
3940 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
3941};
3942
3943/* Fix up the DAI formats for endianness: codecs don't actually see
3944 * the endianness of the data but we're using the CPU format
3945 * definitions which do need to include endianness so we ensure that
3946 * codec DAIs always have both big and little endian variants set.
3947 */
3948static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
3949{
3950 int i;
3951
3952 for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
3953 if (stream->formats & codec_format_map[i])
3954 stream->formats |= codec_format_map[i];
3955}
3956
Mark Brown0d0cf002008-12-10 14:32:45 +00003957/**
3958 * snd_soc_register_codec - Register a codec with the ASoC core
3959 *
Mark Brownac11a2b2009-01-01 12:18:17 +00003960 * @codec: codec to register
Mark Brown0d0cf002008-12-10 14:32:45 +00003961 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003962int snd_soc_register_codec(struct device *dev,
Mark Brown001ae4c2010-12-02 16:21:08 +00003963 const struct snd_soc_codec_driver *codec_drv,
3964 struct snd_soc_dai_driver *dai_drv,
3965 int num_dai)
Mark Brown0d0cf002008-12-10 14:32:45 +00003966{
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00003967 size_t reg_size;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003968 struct snd_soc_codec *codec;
3969 int ret, i;
Mark Brown151ab222009-05-09 16:22:58 +01003970
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003971 dev_dbg(dev, "codec register %s\n", dev_name(dev));
Mark Brown0d0cf002008-12-10 14:32:45 +00003972
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003973 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
3974 if (codec == NULL)
3975 return -ENOMEM;
Mark Brown0d0cf002008-12-10 14:32:45 +00003976
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00003977 /* create CODEC component name */
3978 codec->name = fmt_single_name(dev, &codec->id);
3979 if (codec->name == NULL) {
3980 kfree(codec);
3981 return -ENOMEM;
Mark Brown151ab222009-05-09 16:22:58 +01003982 }
3983
Dimitris Papastamos23bbce32010-12-02 14:53:01 +00003984 if (codec_drv->compress_type)
3985 codec->compress_type = codec_drv->compress_type;
3986 else
3987 codec->compress_type = SND_SOC_FLAT_COMPRESSION;
3988
Mark Brownc3acec22010-12-02 16:15:29 +00003989 codec->write = codec_drv->write;
3990 codec->read = codec_drv->read;
Dimitris Papastamos1500b7b2011-01-13 12:20:38 +00003991 codec->volatile_register = codec_drv->volatile_register;
3992 codec->readable_register = codec_drv->readable_register;
Dimitris Papastamos80204542011-03-24 13:45:17 +00003993 codec->writable_register = codec_drv->writable_register;
Mark Brown5124e692012-02-08 13:20:50 +00003994 codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
Liam Girdwoodce6120c2010-11-05 15:53:46 +02003995 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
3996 codec->dapm.dev = dev;
3997 codec->dapm.codec = codec;
Mark Brown474b62d2011-01-18 16:14:44 +00003998 codec->dapm.seq_notifier = codec_drv->seq_notifier;
Liam Girdwood64a648c2011-07-25 11:15:15 +01003999 codec->dapm.stream_event = codec_drv->stream_event;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004000 codec->dev = dev;
4001 codec->driver = codec_drv;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004002 codec->num_dai = num_dai;
4003 mutex_init(&codec->mutex);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004004
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00004005 /* allocate CODEC register cache */
4006 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00004007 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00004008 codec->reg_size = reg_size;
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00004009 /* it is necessary to make a copy of the default register cache
4010 * because in the case of using a compression type that requires
4011 * the default register cache to be marked as __devinitconst the
4012 * kernel might have freed the array by the time we initialize
4013 * the cache.
4014 */
Dimitris Papastamos2aa86322011-01-10 10:10:56 +00004015 if (codec_drv->reg_cache_default) {
4016 codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
4017 reg_size, GFP_KERNEL);
4018 if (!codec->reg_def_copy) {
4019 ret = -ENOMEM;
4020 goto fail;
4021 }
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00004022 }
4023 }
4024
Dimitris Papastamos1500b7b2011-01-13 12:20:38 +00004025 if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
4026 if (!codec->volatile_register)
4027 codec->volatile_register = snd_soc_default_volatile_register;
4028 if (!codec->readable_register)
4029 codec->readable_register = snd_soc_default_readable_register;
Dimitris Papastamos80204542011-03-24 13:45:17 +00004030 if (!codec->writable_register)
4031 codec->writable_register = snd_soc_default_writable_register;
Dimitris Papastamos1500b7b2011-01-13 12:20:38 +00004032 }
4033
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004034 for (i = 0; i < num_dai; i++) {
4035 fixup_codec_formats(&dai_drv[i].playback);
4036 fixup_codec_formats(&dai_drv[i].capture);
4037 }
4038
Mark Brown054880f2012-04-09 17:29:19 +01004039 mutex_lock(&client_mutex);
4040 list_add(&codec->list, &codec_list);
4041 mutex_unlock(&client_mutex);
4042
Mark Brown26b01cc2010-08-18 20:20:55 +01004043 /* register any DAIs */
4044 if (num_dai) {
4045 ret = snd_soc_register_dais(dev, dai_drv, num_dai);
4046 if (ret < 0)
Mark Brown054880f2012-04-09 17:29:19 +01004047 dev_err(codec->dev, "Failed to regster DAIs: %d\n",
4048 ret);
Mark Brown26b01cc2010-08-18 20:20:55 +01004049 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004050
Mark Brown0d0cf002008-12-10 14:32:45 +00004051 pr_debug("Registered codec '%s'\n", codec->name);
Mark Brown0d0cf002008-12-10 14:32:45 +00004052 return 0;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004053
Dimitris Papastamosfdf0f542010-12-02 16:11:06 +00004054fail:
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00004055 kfree(codec->reg_def_copy);
4056 codec->reg_def_copy = NULL;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004057 kfree(codec->name);
4058 kfree(codec);
4059 return ret;
Mark Brown0d0cf002008-12-10 14:32:45 +00004060}
4061EXPORT_SYMBOL_GPL(snd_soc_register_codec);
4062
4063/**
4064 * snd_soc_unregister_codec - Unregister a codec from the ASoC core
4065 *
Mark Brownac11a2b2009-01-01 12:18:17 +00004066 * @codec: codec to unregister
Mark Brown0d0cf002008-12-10 14:32:45 +00004067 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004068void snd_soc_unregister_codec(struct device *dev)
Mark Brown0d0cf002008-12-10 14:32:45 +00004069{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004070 struct snd_soc_codec *codec;
4071 int i;
4072
4073 list_for_each_entry(codec, &codec_list, list) {
4074 if (dev == codec->dev)
4075 goto found;
4076 }
4077 return;
4078
4079found:
Mark Brown26b01cc2010-08-18 20:20:55 +01004080 if (codec->num_dai)
4081 for (i = 0; i < codec->num_dai; i++)
4082 snd_soc_unregister_dai(dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004083
Mark Brown0d0cf002008-12-10 14:32:45 +00004084 mutex_lock(&client_mutex);
4085 list_del(&codec->list);
4086 mutex_unlock(&client_mutex);
4087
4088 pr_debug("Unregistered codec '%s'\n", codec->name);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004089
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00004090 snd_soc_cache_exit(codec);
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00004091 kfree(codec->reg_def_copy);
Dimitris Papastamos1aafcd42010-10-21 13:19:45 +01004092 kfree(codec->name);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00004093 kfree(codec);
Mark Brown0d0cf002008-12-10 14:32:45 +00004094}
4095EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
4096
Stephen Warrenbec4fa02011-12-12 15:55:34 -07004097/* Retrieve a card's name from device tree */
4098int snd_soc_of_parse_card_name(struct snd_soc_card *card,
4099 const char *propname)
4100{
4101 struct device_node *np = card->dev->of_node;
4102 int ret;
4103
4104 ret = of_property_read_string_index(np, propname, 0, &card->name);
4105 /*
4106 * EINVAL means the property does not exist. This is fine providing
4107 * card->name was previously set, which is checked later in
4108 * snd_soc_register_card.
4109 */
4110 if (ret < 0 && ret != -EINVAL) {
4111 dev_err(card->dev,
4112 "Property '%s' could not be read: %d\n",
4113 propname, ret);
4114 return ret;
4115 }
4116
4117 return 0;
4118}
4119EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
4120
Stephen Warrena4a54dd2011-12-12 15:55:35 -07004121int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
4122 const char *propname)
4123{
4124 struct device_node *np = card->dev->of_node;
4125 int num_routes;
4126 struct snd_soc_dapm_route *routes;
4127 int i, ret;
4128
4129 num_routes = of_property_count_strings(np, propname);
Richard Zhaoc34ce322012-04-24 15:24:43 +08004130 if (num_routes < 0 || num_routes & 1) {
Stephen Warrena4a54dd2011-12-12 15:55:35 -07004131 dev_err(card->dev,
Richard Zhaoc34ce322012-04-24 15:24:43 +08004132 "Property '%s' does not exist or its length is not even\n",
4133 propname);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07004134 return -EINVAL;
4135 }
4136 num_routes /= 2;
4137 if (!num_routes) {
4138 dev_err(card->dev,
4139 "Property '%s's length is zero\n",
4140 propname);
4141 return -EINVAL;
4142 }
4143
4144 routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes),
4145 GFP_KERNEL);
4146 if (!routes) {
4147 dev_err(card->dev,
4148 "Could not allocate DAPM route table\n");
4149 return -EINVAL;
4150 }
4151
4152 for (i = 0; i < num_routes; i++) {
4153 ret = of_property_read_string_index(np, propname,
4154 2 * i, &routes[i].sink);
4155 if (ret) {
4156 dev_err(card->dev,
4157 "Property '%s' index %d could not be read: %d\n",
4158 propname, 2 * i, ret);
Matthias Kaehlckeb761c0c2012-07-11 17:36:34 +02004159 kfree(routes);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07004160 return -EINVAL;
4161 }
4162 ret = of_property_read_string_index(np, propname,
4163 (2 * i) + 1, &routes[i].source);
4164 if (ret) {
4165 dev_err(card->dev,
4166 "Property '%s' index %d could not be read: %d\n",
4167 propname, (2 * i) + 1, ret);
Matthias Kaehlckeb761c0c2012-07-11 17:36:34 +02004168 kfree(routes);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07004169 return -EINVAL;
4170 }
4171 }
4172
4173 card->num_dapm_routes = num_routes;
4174 card->dapm_routes = routes;
4175
4176 return 0;
4177}
4178EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
4179
Takashi Iwaic9b3a402008-12-10 07:47:22 +01004180static int __init snd_soc_init(void)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004181{
Mark Brown384c89e2008-12-03 17:34:03 +00004182#ifdef CONFIG_DEBUG_FS
Mark Brown8a9dab12011-01-10 22:25:21 +00004183 snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
4184 if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
Fabio Estevam0837fc62012-02-17 19:40:38 -02004185 pr_warn("ASoC: Failed to create debugfs directory\n");
Mark Brown8a9dab12011-01-10 22:25:21 +00004186 snd_soc_debugfs_root = NULL;
Mark Brown384c89e2008-12-03 17:34:03 +00004187 }
Mark Brownc3c5a192010-09-15 18:15:14 +01004188
Mark Brown8a9dab12011-01-10 22:25:21 +00004189 if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL,
Mark Brownc3c5a192010-09-15 18:15:14 +01004190 &codec_list_fops))
4191 pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
4192
Mark Brown8a9dab12011-01-10 22:25:21 +00004193 if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL,
Mark Brownf3208782010-09-15 18:19:07 +01004194 &dai_list_fops))
4195 pr_warn("ASoC: Failed to create DAI list debugfs file\n");
Mark Brown19c7ac22010-09-15 18:22:40 +01004196
Mark Brown8a9dab12011-01-10 22:25:21 +00004197 if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL,
Mark Brown19c7ac22010-09-15 18:22:40 +01004198 &platform_list_fops))
4199 pr_warn("ASoC: Failed to create platform list debugfs file\n");
Mark Brown384c89e2008-12-03 17:34:03 +00004200#endif
4201
Mark Brownfb257892011-04-28 10:57:54 +01004202 snd_soc_util_init();
4203
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004204 return platform_driver_register(&soc_driver);
4205}
Mark Brown4abe8e12010-10-12 17:41:03 +01004206module_init(snd_soc_init);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004207
Mark Brown7d8c16a2008-11-30 22:11:24 +00004208static void __exit snd_soc_exit(void)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004209{
Mark Brownfb257892011-04-28 10:57:54 +01004210 snd_soc_util_exit();
4211
Mark Brown384c89e2008-12-03 17:34:03 +00004212#ifdef CONFIG_DEBUG_FS
Mark Brown8a9dab12011-01-10 22:25:21 +00004213 debugfs_remove_recursive(snd_soc_debugfs_root);
Mark Brown384c89e2008-12-03 17:34:03 +00004214#endif
Mark Brown3ff3f642008-05-19 12:32:25 +02004215 platform_driver_unregister(&soc_driver);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004216}
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004217module_exit(snd_soc_exit);
4218
4219/* Module information */
Liam Girdwoodd3311242008-10-12 13:17:36 +01004220MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
Frank Mandarinodb2a4162006-10-06 18:31:09 +02004221MODULE_DESCRIPTION("ALSA SoC Core");
4222MODULE_LICENSE("GPL");
Kay Sievers8b45a202008-04-14 13:33:36 +02004223MODULE_ALIAS("platform:soc-audio");