| OLD | NEW |
| 1 /* | 1 /* |
| 2 * soc-core.c -- ALSA SoC Audio Layer | 2 * soc-core.c -- ALSA SoC Audio Layer |
| 3 * | 3 * |
| 4 * Copyright 2005 Wolfson Microelectronics PLC. | 4 * Copyright 2005 Wolfson Microelectronics PLC. |
| 5 * Copyright 2005 Openedhand Ltd. | 5 * Copyright 2005 Openedhand Ltd. |
| 6 * Copyright (C) 2010 Slimlogic Ltd. | 6 * Copyright (C) 2010 Slimlogic Ltd. |
| 7 * Copyright (C) 2010 Texas Instruments Inc. | 7 * Copyright (C) 2010 Texas Instruments Inc. |
| 8 * | 8 * |
| 9 * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 9 * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 10 * with code, comments and ideas from :- | 10 * with code, comments and ideas from :- |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include <linux/moduleparam.h> | 26 #include <linux/moduleparam.h> |
| 27 #include <linux/init.h> | 27 #include <linux/init.h> |
| 28 #include <linux/delay.h> | 28 #include <linux/delay.h> |
| 29 #include <linux/pm.h> | 29 #include <linux/pm.h> |
| 30 #include <linux/bitops.h> | 30 #include <linux/bitops.h> |
| 31 #include <linux/debugfs.h> | 31 #include <linux/debugfs.h> |
| 32 #include <linux/platform_device.h> | 32 #include <linux/platform_device.h> |
| 33 #include <linux/slab.h> | 33 #include <linux/slab.h> |
| 34 #include <sound/ac97_codec.h> | 34 #include <sound/ac97_codec.h> |
| 35 #include <sound/core.h> | 35 #include <sound/core.h> |
| 36 #include <sound/jack.h> |
| 36 #include <sound/pcm.h> | 37 #include <sound/pcm.h> |
| 37 #include <sound/pcm_params.h> | 38 #include <sound/pcm_params.h> |
| 38 #include <sound/soc.h> | 39 #include <sound/soc.h> |
| 39 #include <sound/soc-dapm.h> | |
| 40 #include <sound/initval.h> | 40 #include <sound/initval.h> |
| 41 | 41 |
| 42 #define CREATE_TRACE_POINTS |
| 43 #include <trace/events/asoc.h> |
| 44 |
| 42 #define NAME_SIZE 32 | 45 #define NAME_SIZE 32 |
| 43 | 46 |
| 44 static DEFINE_MUTEX(pcm_mutex); | 47 static DEFINE_MUTEX(pcm_mutex); |
| 45 static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 48 static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
| 46 | 49 |
| 47 #ifdef CONFIG_DEBUG_FS | 50 #ifdef CONFIG_DEBUG_FS |
| 48 struct dentry *asoc_debugfs_root; | 51 struct dentry *snd_soc_debugfs_root; |
| 49 EXPORT_SYMBOL_GPL(asoc_debugfs_root); | 52 EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); |
| 50 #endif | 53 #endif |
| 51 | 54 |
| 52 static DEFINE_MUTEX(client_mutex); | 55 static DEFINE_MUTEX(client_mutex); |
| 53 static LIST_HEAD(card_list); | 56 static LIST_HEAD(card_list); |
| 54 static LIST_HEAD(dai_list); | 57 static LIST_HEAD(dai_list); |
| 55 static LIST_HEAD(platform_list); | 58 static LIST_HEAD(platform_list); |
| 56 static LIST_HEAD(codec_list); | 59 static LIST_HEAD(codec_list); |
| 57 | 60 |
| 58 static int snd_soc_register_card(struct snd_soc_card *card); | |
| 59 static int snd_soc_unregister_card(struct snd_soc_card *card); | |
| 60 static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); | 61 static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); |
| 61 | 62 |
| 62 /* | 63 /* |
| 63 * This is a timeout to do a DAPM powerdown after a stream is closed(). | 64 * 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 * It can be used to eliminate pops between different playback streams, e.g. |
| 65 * between two audio tracks. | 66 * between two audio tracks. |
| 66 */ | 67 */ |
| 67 static int pmdown_time = 5000; | 68 static int pmdown_time = 5000; |
| 68 module_param(pmdown_time, int, 0); | 69 module_param(pmdown_time, int, 0); |
| 69 MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 70 MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
| 70 | 71 |
| 71 /* | 72 /* returns the minimum number of bytes needed to represent |
| 72 * This function forces any delayed work to be queued and run. | 73 * a particular given value */ |
| 73 */ | 74 static int min_bytes_needed(unsigned long val) |
| 74 static int run_delayed_work(struct delayed_work *dwork) | |
| 75 { | 75 { |
| 76 int c = 0; |
| 77 int i; |
| 78 |
| 79 for (i = (sizeof val * 8) - 1; i >= 0; --i, ++c) |
| 80 if (val & (1UL << i)) |
| 81 break; |
| 82 c = (sizeof val * 8) - c; |
| 83 if (!c || (c % 8)) |
| 84 c = (c + 8) / 8; |
| 85 else |
| 86 c /= 8; |
| 87 return c; |
| 88 } |
| 89 |
| 90 /* fill buf which is 'len' bytes with a formatted |
| 91 * string of the form 'reg: value\n' */ |
| 92 static int format_register_str(struct snd_soc_codec *codec, |
| 93 unsigned int reg, char *buf, size_t len) |
| 94 { |
| 95 int wordsize = codec->driver->reg_word_size * 2; |
| 96 int regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; |
| 76 int ret; | 97 int ret; |
| 98 char tmpbuf[len + 1]; |
| 99 char regbuf[regsize + 1]; |
| 77 | 100 |
| 78 » /* cancel any work waiting to be queued. */ | 101 » /* since tmpbuf is allocated on the stack, warn the callers if they |
| 79 » ret = cancel_delayed_work(dwork); | 102 » * try to abuse this function */ |
| 103 » WARN_ON(len > 63); |
| 80 | 104 |
| 81 » /* if there was any work waiting then we run it now and | 105 » /* +2 for ': ' and + 1 for '\n' */ |
| 82 » * wait for it's completion */ | 106 » if (wordsize + regsize + 2 + 1 != len) |
| 83 » if (ret) { | 107 » » return -EINVAL; |
| 84 » » schedule_delayed_work(dwork, 0); | 108 |
| 85 » » flush_scheduled_work(); | 109 » ret = snd_soc_read(codec , reg); |
| 110 » if (ret < 0) { |
| 111 » » memset(regbuf, 'X', regsize); |
| 112 » » regbuf[regsize] = '\0'; |
| 113 » } else { |
| 114 » » snprintf(regbuf, regsize + 1, "%.*x", regsize, ret); |
| 86 } | 115 } |
| 87 » return ret; | 116 |
| 117 » /* prepare the buffer */ |
| 118 » snprintf(tmpbuf, len + 1, "%.*x: %s\n", wordsize, reg, regbuf); |
| 119 » /* copy it back to the caller without the '\0' */ |
| 120 » memcpy(buf, tmpbuf, len); |
| 121 |
| 122 » return 0; |
| 88 } | 123 } |
| 89 | 124 |
| 90 /* codec register dump */ | 125 /* codec register dump */ |
| 91 static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | 126 static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf, |
| 127 » » » » size_t count, loff_t pos) |
| 92 { | 128 { |
| 93 » int ret, i, step = 1, count = 0; | 129 » int i, step = 1; |
| 130 » int wordsize, regsize; |
| 131 » int len; |
| 132 » size_t total = 0; |
| 133 » loff_t p = 0; |
| 134 |
| 135 » wordsize = codec->driver->reg_word_size * 2; |
| 136 » regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; |
| 137 |
| 138 » len = wordsize + regsize + 2 + 1; |
| 94 | 139 |
| 95 if (!codec->driver->reg_cache_size) | 140 if (!codec->driver->reg_cache_size) |
| 96 return 0; | 141 return 0; |
| 97 | 142 |
| 98 if (codec->driver->reg_cache_step) | 143 if (codec->driver->reg_cache_step) |
| 99 step = codec->driver->reg_cache_step; | 144 step = codec->driver->reg_cache_step; |
| 100 | 145 |
| 101 count += sprintf(buf, "%s registers\n", codec->name); | |
| 102 for (i = 0; i < codec->driver->reg_cache_size; i += step) { | 146 for (i = 0; i < codec->driver->reg_cache_size; i += step) { |
| 103 » » if (codec->driver->readable_register && !codec->driver->readable
_register(i)) | 147 » » if (codec->readable_register && !codec->readable_register(codec,
i)) |
| 104 continue; | 148 continue; |
| 105 | |
| 106 count += sprintf(buf + count, "%2x: ", i); | |
| 107 if (count >= PAGE_SIZE - 1) | |
| 108 break; | |
| 109 | |
| 110 if (codec->driver->display_register) { | 149 if (codec->driver->display_register) { |
| 111 count += codec->driver->display_register(codec, buf + co
unt, | 150 count += codec->driver->display_register(codec, buf + co
unt, |
| 112 PAGE_SIZE - count, i); | 151 PAGE_SIZE - count, i); |
| 113 } else { | 152 } else { |
| 114 » » » /* If the read fails it's almost certainly due to | 153 » » » /* only support larger than PAGE_SIZE bytes debugfs |
| 115 » » » * the register being volatile and the device being | 154 » » » * entries for the default case */ |
| 116 » » » * powered off. | 155 » » » if (p >= pos) { |
| 117 » » » */ | 156 » » » » if (total + len >= count - 1) |
| 118 » » » ret = codec->driver->read(codec, i); | 157 » » » » » break; |
| 119 » » » if (ret >= 0) | 158 » » » » format_register_str(codec, i, buf + total, len); |
| 120 » » » » count += snprintf(buf + count, | 159 » » » » total += len; |
| 121 » » » » » » PAGE_SIZE - count, | 160 » » » } |
| 122 » » » » » » "%4x", ret); | 161 » » » p += len; |
| 123 » » » else | |
| 124 » » » » count += snprintf(buf + count, | |
| 125 » » » » » » PAGE_SIZE - count, | |
| 126 » » » » » » "<no data: %d>", ret); | |
| 127 } | 162 } |
| 128 | |
| 129 if (count >= PAGE_SIZE - 1) | |
| 130 break; | |
| 131 | |
| 132 count += snprintf(buf + count, PAGE_SIZE - count, "\n"); | |
| 133 if (count >= PAGE_SIZE - 1) | |
| 134 break; | |
| 135 } | 163 } |
| 136 | 164 |
| 137 » /* Truncate count; min() would cause a warning */ | 165 » total = min(total, count - 1); |
| 138 » if (count >= PAGE_SIZE) | |
| 139 » » count = PAGE_SIZE - 1; | |
| 140 | 166 |
| 141 » return count; | 167 » return total; |
| 142 } | 168 } |
| 169 |
| 143 static ssize_t codec_reg_show(struct device *dev, | 170 static ssize_t codec_reg_show(struct device *dev, |
| 144 struct device_attribute *attr, char *buf) | 171 struct device_attribute *attr, char *buf) |
| 145 { | 172 { |
| 146 struct snd_soc_pcm_runtime *rtd = | 173 struct snd_soc_pcm_runtime *rtd = |
| 147 container_of(dev, struct snd_soc_pcm_runtime, dev); | 174 container_of(dev, struct snd_soc_pcm_runtime, dev); |
| 148 | 175 |
| 149 » return soc_codec_reg_show(rtd->codec, buf); | 176 » return soc_codec_reg_show(rtd->codec, buf, PAGE_SIZE, 0); |
| 150 } | 177 } |
| 151 | 178 |
| 152 static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 179 static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
| 153 | 180 |
| 154 static ssize_t pmdown_time_show(struct device *dev, | 181 static ssize_t pmdown_time_show(struct device *dev, |
| 155 struct device_attribute *attr, char *buf) | 182 struct device_attribute *attr, char *buf) |
| 156 { | 183 { |
| 157 struct snd_soc_pcm_runtime *rtd = | 184 struct snd_soc_pcm_runtime *rtd = |
| 158 container_of(dev, struct snd_soc_pcm_runtime, dev); | 185 container_of(dev, struct snd_soc_pcm_runtime, dev); |
| 159 | 186 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 178 static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); | 205 static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); |
| 179 | 206 |
| 180 #ifdef CONFIG_DEBUG_FS | 207 #ifdef CONFIG_DEBUG_FS |
| 181 static int codec_reg_open_file(struct inode *inode, struct file *file) | 208 static int codec_reg_open_file(struct inode *inode, struct file *file) |
| 182 { | 209 { |
| 183 file->private_data = inode->i_private; | 210 file->private_data = inode->i_private; |
| 184 return 0; | 211 return 0; |
| 185 } | 212 } |
| 186 | 213 |
| 187 static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | 214 static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, |
| 188 » » » size_t count, loff_t *ppos) | 215 » » » » size_t count, loff_t *ppos) |
| 189 { | 216 { |
| 190 ssize_t ret; | 217 ssize_t ret; |
| 191 struct snd_soc_codec *codec = file->private_data; | 218 struct snd_soc_codec *codec = file->private_data; |
| 192 » char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 219 » char *buf; |
| 220 |
| 221 » if (*ppos < 0 || !count) |
| 222 » » return -EINVAL; |
| 223 |
| 224 » buf = kmalloc(count, GFP_KERNEL); |
| 193 if (!buf) | 225 if (!buf) |
| 194 return -ENOMEM; | 226 return -ENOMEM; |
| 195 » ret = soc_codec_reg_show(codec, buf); | 227 |
| 196 » if (ret >= 0) | 228 » ret = soc_codec_reg_show(codec, buf, count, *ppos); |
| 197 » » ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | 229 » if (ret >= 0) { |
| 230 » » if (copy_to_user(user_buf, buf, ret)) { |
| 231 » » » kfree(buf); |
| 232 » » » return -EFAULT; |
| 233 » » } |
| 234 » » *ppos += ret; |
| 235 » } |
| 236 |
| 198 kfree(buf); | 237 kfree(buf); |
| 199 return ret; | 238 return ret; |
| 200 } | 239 } |
| 201 | 240 |
| 202 static ssize_t codec_reg_write_file(struct file *file, | 241 static ssize_t codec_reg_write_file(struct file *file, |
| 203 const char __user *user_buf, size_t count, loff_t *ppos) | 242 const char __user *user_buf, size_t count, loff_t *ppos) |
| 204 { | 243 { |
| 205 char buf[32]; | 244 char buf[32]; |
| 206 int buf_size; | 245 int buf_size; |
| 207 char *start = buf; | 246 char *start = buf; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 219 | 258 |
| 220 while (*start == ' ') | 259 while (*start == ' ') |
| 221 start++; | 260 start++; |
| 222 reg = simple_strtoul(start, &start, 16); | 261 reg = simple_strtoul(start, &start, 16); |
| 223 if ((reg >= codec->driver->reg_cache_size) || (reg % step)) | 262 if ((reg >= codec->driver->reg_cache_size) || (reg % step)) |
| 224 return -EINVAL; | 263 return -EINVAL; |
| 225 while (*start == ' ') | 264 while (*start == ' ') |
| 226 start++; | 265 start++; |
| 227 if (strict_strtoul(start, 16, &value)) | 266 if (strict_strtoul(start, 16, &value)) |
| 228 return -EINVAL; | 267 return -EINVAL; |
| 229 » codec->driver->write(codec, reg, value); | 268 |
| 269 » /* Userspace has been fiddling around behind the kernel's back */ |
| 270 » add_taint(TAINT_USER); |
| 271 |
| 272 » snd_soc_write(codec, reg, value); |
| 230 return buf_size; | 273 return buf_size; |
| 231 } | 274 } |
| 232 | 275 |
| 233 static const struct file_operations codec_reg_fops = { | 276 static const struct file_operations codec_reg_fops = { |
| 234 .open = codec_reg_open_file, | 277 .open = codec_reg_open_file, |
| 235 .read = codec_reg_read_file, | 278 .read = codec_reg_read_file, |
| 236 .write = codec_reg_write_file, | 279 .write = codec_reg_write_file, |
| 237 .llseek = default_llseek, | 280 .llseek = default_llseek, |
| 238 }; | 281 }; |
| 239 | 282 |
| 240 static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 283 static void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
| 241 { | 284 { |
| 242 » codec->debugfs_codec_root = debugfs_create_dir(codec->name , | 285 » struct dentry *debugfs_card_root = codec->card->debugfs_card_root; |
| 243 » » » » » » asoc_debugfs_root); | 286 |
| 287 » codec->debugfs_codec_root = debugfs_create_dir(codec->name, |
| 288 » » » » » » debugfs_card_root); |
| 244 if (!codec->debugfs_codec_root) { | 289 if (!codec->debugfs_codec_root) { |
| 245 printk(KERN_WARNING | 290 printk(KERN_WARNING |
| 246 "ASoC: Failed to create codec debugfs directory\n"); | 291 "ASoC: Failed to create codec debugfs directory\n"); |
| 247 return; | 292 return; |
| 248 } | 293 } |
| 249 | 294 |
| 295 debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root, |
| 296 &codec->cache_sync); |
| 297 debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root, |
| 298 &codec->cache_only); |
| 299 |
| 250 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 300 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
| 251 codec->debugfs_codec_root, | 301 codec->debugfs_codec_root, |
| 252 codec, &codec_reg_fops); | 302 codec, &codec_reg_fops); |
| 253 if (!codec->debugfs_reg) | 303 if (!codec->debugfs_reg) |
| 254 printk(KERN_WARNING | 304 printk(KERN_WARNING |
| 255 "ASoC: Failed to create codec register debugfs file\n"); | 305 "ASoC: Failed to create codec register debugfs file\n"); |
| 256 | 306 |
| 257 » codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, | 307 » codec->dapm.debugfs_dapm = debugfs_create_dir("dapm", |
| 258 » » » » » » codec->debugfs_codec_root, | |
| 259 » » » » » » &codec->pop_time); | |
| 260 » if (!codec->debugfs_pop_time) | |
| 261 » » printk(KERN_WARNING | |
| 262 » » "Failed to create pop time debugfs file\n"); | |
| 263 | |
| 264 » codec->debugfs_dapm = debugfs_create_dir("dapm", | |
| 265 codec->debugfs_codec_root); | 308 codec->debugfs_codec_root); |
| 266 » if (!codec->debugfs_dapm) | 309 » if (!codec->dapm.debugfs_dapm) |
| 267 printk(KERN_WARNING | 310 printk(KERN_WARNING |
| 268 "Failed to create DAPM debugfs directory\n"); | 311 "Failed to create DAPM debugfs directory\n"); |
| 269 | 312 |
| 270 » snd_soc_dapm_debugfs_init(codec); | 313 » snd_soc_dapm_debugfs_init(&codec->dapm); |
| 271 } | 314 } |
| 272 | 315 |
| 273 static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 316 static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) |
| 274 { | 317 { |
| 275 debugfs_remove_recursive(codec->debugfs_codec_root); | 318 debugfs_remove_recursive(codec->debugfs_codec_root); |
| 276 } | 319 } |
| 277 | 320 |
| 278 static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, | 321 static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, |
| 279 size_t count, loff_t *ppos) | 322 size_t count, loff_t *ppos) |
| 280 { | 323 { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 kfree(buf); | 411 kfree(buf); |
| 369 | 412 |
| 370 return ret; | 413 return ret; |
| 371 } | 414 } |
| 372 | 415 |
| 373 static const struct file_operations platform_list_fops = { | 416 static const struct file_operations platform_list_fops = { |
| 374 .read = platform_list_read_file, | 417 .read = platform_list_read_file, |
| 375 .llseek = default_llseek,/* read accesses f_pos */ | 418 .llseek = default_llseek,/* read accesses f_pos */ |
| 376 }; | 419 }; |
| 377 | 420 |
| 421 static void soc_init_card_debugfs(struct snd_soc_card *card) |
| 422 { |
| 423 card->debugfs_card_root = debugfs_create_dir(card->name, |
| 424 snd_soc_debugfs_root); |
| 425 if (!card->debugfs_card_root) { |
| 426 dev_warn(card->dev, |
| 427 "ASoC: Failed to create codec debugfs directory\n"); |
| 428 return; |
| 429 } |
| 430 |
| 431 card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, |
| 432 card->debugfs_card_root, |
| 433 &card->pop_time); |
| 434 if (!card->debugfs_pop_time) |
| 435 dev_warn(card->dev, |
| 436 "Failed to create pop time debugfs file\n"); |
| 437 } |
| 438 |
| 439 static void soc_cleanup_card_debugfs(struct snd_soc_card *card) |
| 440 { |
| 441 debugfs_remove_recursive(card->debugfs_card_root); |
| 442 } |
| 443 |
| 378 #else | 444 #else |
| 379 | 445 |
| 380 static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 446 static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
| 381 { | 447 { |
| 382 } | 448 } |
| 383 | 449 |
| 384 static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 450 static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) |
| 385 { | 451 { |
| 386 } | 452 } |
| 453 |
| 454 static inline void soc_init_card_debugfs(struct snd_soc_card *card) |
| 455 { |
| 456 } |
| 457 |
| 458 static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card) |
| 459 { |
| 460 } |
| 387 #endif | 461 #endif |
| 388 | 462 |
| 389 #ifdef CONFIG_SND_SOC_AC97_BUS | 463 #ifdef CONFIG_SND_SOC_AC97_BUS |
| 390 /* unregister ac97 codec */ | 464 /* unregister ac97 codec */ |
| 391 static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) | 465 static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) |
| 392 { | 466 { |
| 393 if (codec->ac97->dev.bus) | 467 if (codec->ac97->dev.bus) |
| 394 device_unregister(&codec->ac97->dev); | 468 device_unregister(&codec->ac97->dev); |
| 395 return 0; | 469 return 0; |
| 396 } | 470 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 } | 565 } |
| 492 | 566 |
| 493 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { | 567 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { |
| 494 ret = rtd->dai_link->ops->startup(substream); | 568 ret = rtd->dai_link->ops->startup(substream); |
| 495 if (ret < 0) { | 569 if (ret < 0) { |
| 496 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_li
nk->name); | 570 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_li
nk->name); |
| 497 goto machine_err; | 571 goto machine_err; |
| 498 } | 572 } |
| 499 } | 573 } |
| 500 | 574 |
| 501 » /* Check that the codec and cpu DAI's are compatible */ | 575 » /* Check that the codec and cpu DAIs are compatible */ |
| 502 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 576 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 503 runtime->hw.rate_min = | 577 runtime->hw.rate_min = |
| 504 max(codec_dai_drv->playback.rate_min, | 578 max(codec_dai_drv->playback.rate_min, |
| 505 cpu_dai_drv->playback.rate_min); | 579 cpu_dai_drv->playback.rate_min); |
| 506 runtime->hw.rate_max = | 580 runtime->hw.rate_max = |
| 507 min(codec_dai_drv->playback.rate_max, | 581 min(codec_dai_drv->playback.rate_max, |
| 508 cpu_dai_drv->playback.rate_max); | 582 cpu_dai_drv->playback.rate_max); |
| 509 runtime->hw.channels_min = | 583 runtime->hw.channels_min = |
| 510 max(codec_dai_drv->playback.channels_min, | 584 max(codec_dai_drv->playback.channels_min, |
| 511 cpu_dai_drv->playback.channels_min); | 585 cpu_dai_drv->playback.channels_min); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 | 914 |
| 841 codec_err: | 915 codec_err: |
| 842 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 916 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
| 843 rtd->dai_link->ops->hw_free(substream); | 917 rtd->dai_link->ops->hw_free(substream); |
| 844 | 918 |
| 845 mutex_unlock(&pcm_mutex); | 919 mutex_unlock(&pcm_mutex); |
| 846 return ret; | 920 return ret; |
| 847 } | 921 } |
| 848 | 922 |
| 849 /* | 923 /* |
| 850 * Free's resources allocated by hw_params, can be called multiple times | 924 * Frees resources allocated by hw_params, can be called multiple times |
| 851 */ | 925 */ |
| 852 static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | 926 static int soc_pcm_hw_free(struct snd_pcm_substream *substream) |
| 853 { | 927 { |
| 854 struct snd_soc_pcm_runtime *rtd = substream->private_data; | 928 struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 855 struct snd_soc_platform *platform = rtd->platform; | 929 struct snd_soc_platform *platform = rtd->platform; |
| 856 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 930 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
| 857 struct snd_soc_dai *codec_dai = rtd->codec_dai; | 931 struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 858 struct snd_soc_codec *codec = rtd->codec; | 932 struct snd_soc_codec *codec = rtd->codec; |
| 859 | 933 |
| 860 mutex_lock(&pcm_mutex); | 934 mutex_lock(&pcm_mutex); |
| 861 | 935 |
| 862 /* apply codec digital mute */ | 936 /* apply codec digital mute */ |
| 863 if (!codec->active) | 937 if (!codec->active) |
| 864 snd_soc_dai_digital_mute(codec_dai, 1); | 938 snd_soc_dai_digital_mute(codec_dai, 1); |
| 865 | 939 |
| 866 /* free any machine hw params */ | 940 /* free any machine hw params */ |
| 867 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 941 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
| 868 rtd->dai_link->ops->hw_free(substream); | 942 rtd->dai_link->ops->hw_free(substream); |
| 869 | 943 |
| 870 /* free any DMA resources */ | 944 /* free any DMA resources */ |
| 871 if (platform->driver->ops->hw_free) | 945 if (platform->driver->ops->hw_free) |
| 872 platform->driver->ops->hw_free(substream); | 946 platform->driver->ops->hw_free(substream); |
| 873 | 947 |
| 874 » /* now free hw params for the DAI's */ | 948 » /* now free hw params for the DAIs */ |
| 875 if (codec_dai->driver->ops->hw_free) | 949 if (codec_dai->driver->ops->hw_free) |
| 876 codec_dai->driver->ops->hw_free(substream, codec_dai); | 950 codec_dai->driver->ops->hw_free(substream, codec_dai); |
| 877 | 951 |
| 878 if (cpu_dai->driver->ops->hw_free) | 952 if (cpu_dai->driver->ops->hw_free) |
| 879 cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 953 cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
| 880 | 954 |
| 881 mutex_unlock(&pcm_mutex); | 955 mutex_unlock(&pcm_mutex); |
| 882 return 0; | 956 return 0; |
| 883 } | 957 } |
| 884 | 958 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 static struct snd_pcm_ops soc_pcm_ops = { | 1020 static struct snd_pcm_ops soc_pcm_ops = { |
| 947 .open = soc_pcm_open, | 1021 .open = soc_pcm_open, |
| 948 .close = soc_codec_close, | 1022 .close = soc_codec_close, |
| 949 .hw_params = soc_pcm_hw_params, | 1023 .hw_params = soc_pcm_hw_params, |
| 950 .hw_free = soc_pcm_hw_free, | 1024 .hw_free = soc_pcm_hw_free, |
| 951 .prepare = soc_pcm_prepare, | 1025 .prepare = soc_pcm_prepare, |
| 952 .trigger = soc_pcm_trigger, | 1026 .trigger = soc_pcm_trigger, |
| 953 .pointer = soc_pcm_pointer, | 1027 .pointer = soc_pcm_pointer, |
| 954 }; | 1028 }; |
| 955 | 1029 |
| 956 #ifdef CONFIG_PM | 1030 #ifdef CONFIG_PM_SLEEP |
| 957 /* powers down audio subsystem for suspend */ | 1031 /* powers down audio subsystem for suspend */ |
| 958 static int soc_suspend(struct device *dev) | 1032 int snd_soc_suspend(struct device *dev) |
| 959 { | 1033 { |
| 960 » struct platform_device *pdev = to_platform_device(dev); | 1034 » struct snd_soc_card *card = dev_get_drvdata(dev); |
| 961 » struct snd_soc_card *card = platform_get_drvdata(pdev); | 1035 » struct snd_soc_codec *codec; |
| 962 int i; | 1036 int i; |
| 963 | 1037 |
| 964 /* If the initialization of this soc device failed, there is no codec | 1038 /* If the initialization of this soc device failed, there is no codec |
| 965 * associated with it. Just bail out in this case. | 1039 * associated with it. Just bail out in this case. |
| 966 */ | 1040 */ |
| 967 if (list_empty(&card->codec_dev_list)) | 1041 if (list_empty(&card->codec_dev_list)) |
| 968 return 0; | 1042 return 0; |
| 969 | 1043 |
| 970 /* Due to the resume being scheduled into a workqueue we could | 1044 /* Due to the resume being scheduled into a workqueue we could |
| 971 * suspend before that's finished - wait for it to complete. | 1045 * suspend before that's finished - wait for it to complete. |
| 972 */ | 1046 */ |
| 973 snd_power_lock(card->snd_card); | 1047 snd_power_lock(card->snd_card); |
| 974 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); | 1048 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); |
| 975 snd_power_unlock(card->snd_card); | 1049 snd_power_unlock(card->snd_card); |
| 976 | 1050 |
| 977 /* we're going to block userspace touching us until resume completes */ | 1051 /* we're going to block userspace touching us until resume completes */ |
| 978 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); | 1052 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); |
| 979 | 1053 |
| 980 » /* mute any active DAC's */ | 1054 » /* mute any active DACs */ |
| 981 for (i = 0; i < card->num_rtd; i++) { | 1055 for (i = 0; i < card->num_rtd; i++) { |
| 982 struct snd_soc_dai *dai = card->rtd[i].codec_dai; | 1056 struct snd_soc_dai *dai = card->rtd[i].codec_dai; |
| 983 struct snd_soc_dai_driver *drv = dai->driver; | 1057 struct snd_soc_dai_driver *drv = dai->driver; |
| 984 | 1058 |
| 985 if (card->rtd[i].dai_link->ignore_suspend) | 1059 if (card->rtd[i].dai_link->ignore_suspend) |
| 986 continue; | 1060 continue; |
| 987 | 1061 |
| 988 if (drv->ops->digital_mute && dai->playback_active) | 1062 if (drv->ops->digital_mute && dai->playback_active) |
| 989 drv->ops->digital_mute(dai, 1); | 1063 drv->ops->digital_mute(dai, 1); |
| 990 } | 1064 } |
| 991 | 1065 |
| 992 /* suspend all pcms */ | 1066 /* suspend all pcms */ |
| 993 for (i = 0; i < card->num_rtd; i++) { | 1067 for (i = 0; i < card->num_rtd; i++) { |
| 994 if (card->rtd[i].dai_link->ignore_suspend) | 1068 if (card->rtd[i].dai_link->ignore_suspend) |
| 995 continue; | 1069 continue; |
| 996 | 1070 |
| 997 snd_pcm_suspend_all(card->rtd[i].pcm); | 1071 snd_pcm_suspend_all(card->rtd[i].pcm); |
| 998 } | 1072 } |
| 999 | 1073 |
| 1000 if (card->suspend_pre) | 1074 if (card->suspend_pre) |
| 1001 » » card->suspend_pre(pdev, PMSG_SUSPEND); | 1075 » » card->suspend_pre(card); |
| 1002 | 1076 |
| 1003 for (i = 0; i < card->num_rtd; i++) { | 1077 for (i = 0; i < card->num_rtd; i++) { |
| 1004 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1078 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
| 1005 struct snd_soc_platform *platform = card->rtd[i].platform; | 1079 struct snd_soc_platform *platform = card->rtd[i].platform; |
| 1006 | 1080 |
| 1007 if (card->rtd[i].dai_link->ignore_suspend) | 1081 if (card->rtd[i].dai_link->ignore_suspend) |
| 1008 continue; | 1082 continue; |
| 1009 | 1083 |
| 1010 if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) | 1084 if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) |
| 1011 cpu_dai->driver->suspend(cpu_dai); | 1085 cpu_dai->driver->suspend(cpu_dai); |
| 1012 if (platform->driver->suspend && !platform->suspended) { | 1086 if (platform->driver->suspend && !platform->suspended) { |
| 1013 platform->driver->suspend(cpu_dai); | 1087 platform->driver->suspend(cpu_dai); |
| 1014 platform->suspended = 1; | 1088 platform->suspended = 1; |
| 1015 } | 1089 } |
| 1016 } | 1090 } |
| 1017 | 1091 |
| 1018 /* close any waiting streams and save state */ | 1092 /* close any waiting streams and save state */ |
| 1019 for (i = 0; i < card->num_rtd; i++) { | 1093 for (i = 0; i < card->num_rtd; i++) { |
| 1020 » » run_delayed_work(&card->rtd[i].delayed_work); | 1094 » » flush_delayed_work_sync(&card->rtd[i].delayed_work); |
| 1021 » » card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bia
s_level; | 1095 » » card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec
->dapm.bias_level; |
| 1022 } | 1096 } |
| 1023 | 1097 |
| 1024 for (i = 0; i < card->num_rtd; i++) { | 1098 for (i = 0; i < card->num_rtd; i++) { |
| 1025 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driv
er; | 1099 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driv
er; |
| 1026 | 1100 |
| 1027 if (card->rtd[i].dai_link->ignore_suspend) | 1101 if (card->rtd[i].dai_link->ignore_suspend) |
| 1028 continue; | 1102 continue; |
| 1029 | 1103 |
| 1030 if (driver->playback.stream_name != NULL) | 1104 if (driver->playback.stream_name != NULL) |
| 1031 snd_soc_dapm_stream_event(&card->rtd[i], driver->playbac
k.stream_name, | 1105 snd_soc_dapm_stream_event(&card->rtd[i], driver->playbac
k.stream_name, |
| 1032 SND_SOC_DAPM_STREAM_SUSPEND); | 1106 SND_SOC_DAPM_STREAM_SUSPEND); |
| 1033 | 1107 |
| 1034 if (driver->capture.stream_name != NULL) | 1108 if (driver->capture.stream_name != NULL) |
| 1035 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture
.stream_name, | 1109 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture
.stream_name, |
| 1036 SND_SOC_DAPM_STREAM_SUSPEND); | 1110 SND_SOC_DAPM_STREAM_SUSPEND); |
| 1037 } | 1111 } |
| 1038 | 1112 |
| 1039 /* suspend all CODECs */ | 1113 /* suspend all CODECs */ |
| 1040 » for (i = 0; i < card->num_rtd; i++) { | 1114 » list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
| 1041 » » struct snd_soc_codec *codec = card->rtd[i].codec; | |
| 1042 /* If there are paths active then the CODEC will be held with | 1115 /* If there are paths active then the CODEC will be held with |
| 1043 * bias _ON and should not be suspended. */ | 1116 * bias _ON and should not be suspended. */ |
| 1044 if (!codec->suspended && codec->driver->suspend) { | 1117 if (!codec->suspended && codec->driver->suspend) { |
| 1045 » » » switch (codec->bias_level) { | 1118 » » » switch (codec->dapm.bias_level) { |
| 1046 case SND_SOC_BIAS_STANDBY: | 1119 case SND_SOC_BIAS_STANDBY: |
| 1047 case SND_SOC_BIAS_OFF: | 1120 case SND_SOC_BIAS_OFF: |
| 1048 codec->driver->suspend(codec, PMSG_SUSPEND); | 1121 codec->driver->suspend(codec, PMSG_SUSPEND); |
| 1049 codec->suspended = 1; | 1122 codec->suspended = 1; |
| 1050 break; | 1123 break; |
| 1051 default: | 1124 default: |
| 1052 dev_dbg(codec->dev, "CODEC is on over suspend\n"
); | 1125 dev_dbg(codec->dev, "CODEC is on over suspend\n"
); |
| 1053 break; | 1126 break; |
| 1054 } | 1127 } |
| 1055 } | 1128 } |
| 1056 } | 1129 } |
| 1057 | 1130 |
| 1058 for (i = 0; i < card->num_rtd; i++) { | 1131 for (i = 0; i < card->num_rtd; i++) { |
| 1059 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1132 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
| 1060 | 1133 |
| 1061 if (card->rtd[i].dai_link->ignore_suspend) | 1134 if (card->rtd[i].dai_link->ignore_suspend) |
| 1062 continue; | 1135 continue; |
| 1063 | 1136 |
| 1064 if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) | 1137 if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) |
| 1065 cpu_dai->driver->suspend(cpu_dai); | 1138 cpu_dai->driver->suspend(cpu_dai); |
| 1066 } | 1139 } |
| 1067 | 1140 |
| 1068 if (card->suspend_post) | 1141 if (card->suspend_post) |
| 1069 » » card->suspend_post(pdev, PMSG_SUSPEND); | 1142 » » card->suspend_post(card); |
| 1070 | 1143 |
| 1071 return 0; | 1144 return 0; |
| 1072 } | 1145 } |
| 1146 EXPORT_SYMBOL_GPL(snd_soc_suspend); |
| 1073 | 1147 |
| 1074 /* deferred resume work, so resume can complete before we finished | 1148 /* deferred resume work, so resume can complete before we finished |
| 1075 * setting our codec back up, which can be very slow on I2C | 1149 * setting our codec back up, which can be very slow on I2C |
| 1076 */ | 1150 */ |
| 1077 static void soc_resume_deferred(struct work_struct *work) | 1151 static void soc_resume_deferred(struct work_struct *work) |
| 1078 { | 1152 { |
| 1079 struct snd_soc_card *card = | 1153 struct snd_soc_card *card = |
| 1080 container_of(work, struct snd_soc_card, deferred_resume_
work); | 1154 container_of(work, struct snd_soc_card, deferred_resume_
work); |
| 1081 » struct platform_device *pdev = to_platform_device(card->dev); | 1155 » struct snd_soc_codec *codec; |
| 1082 int i; | 1156 int i; |
| 1083 | 1157 |
| 1084 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 1158 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
| 1085 * so userspace apps are blocked from touching us | 1159 * so userspace apps are blocked from touching us |
| 1086 */ | 1160 */ |
| 1087 | 1161 |
| 1088 dev_dbg(card->dev, "starting resume work\n"); | 1162 dev_dbg(card->dev, "starting resume work\n"); |
| 1089 | 1163 |
| 1090 /* Bring us up into D2 so that DAPM starts enabling things */ | 1164 /* Bring us up into D2 so that DAPM starts enabling things */ |
| 1091 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); | 1165 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); |
| 1092 | 1166 |
| 1093 if (card->resume_pre) | 1167 if (card->resume_pre) |
| 1094 » » card->resume_pre(pdev); | 1168 » » card->resume_pre(card); |
| 1095 | 1169 |
| 1096 /* resume AC97 DAIs */ | 1170 /* resume AC97 DAIs */ |
| 1097 for (i = 0; i < card->num_rtd; i++) { | 1171 for (i = 0; i < card->num_rtd; i++) { |
| 1098 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1172 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
| 1099 | 1173 |
| 1100 if (card->rtd[i].dai_link->ignore_suspend) | 1174 if (card->rtd[i].dai_link->ignore_suspend) |
| 1101 continue; | 1175 continue; |
| 1102 | 1176 |
| 1103 if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) | 1177 if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) |
| 1104 cpu_dai->driver->resume(cpu_dai); | 1178 cpu_dai->driver->resume(cpu_dai); |
| 1105 } | 1179 } |
| 1106 | 1180 |
| 1107 » for (i = 0; i < card->num_rtd; i++) { | 1181 » list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
| 1108 » » struct snd_soc_codec *codec = card->rtd[i].codec; | |
| 1109 /* If the CODEC was idle over suspend then it will have been | 1182 /* If the CODEC was idle over suspend then it will have been |
| 1110 * left with bias OFF or STANDBY and suspended so we must now | 1183 * left with bias OFF or STANDBY and suspended so we must now |
| 1111 * resume. Otherwise the suspend was suppressed. | 1184 * resume. Otherwise the suspend was suppressed. |
| 1112 */ | 1185 */ |
| 1113 if (codec->driver->resume && codec->suspended) { | 1186 if (codec->driver->resume && codec->suspended) { |
| 1114 » » » switch (codec->bias_level) { | 1187 » » » switch (codec->dapm.bias_level) { |
| 1115 case SND_SOC_BIAS_STANDBY: | 1188 case SND_SOC_BIAS_STANDBY: |
| 1116 case SND_SOC_BIAS_OFF: | 1189 case SND_SOC_BIAS_OFF: |
| 1117 codec->driver->resume(codec); | 1190 codec->driver->resume(codec); |
| 1118 codec->suspended = 0; | 1191 codec->suspended = 0; |
| 1119 break; | 1192 break; |
| 1120 default: | 1193 default: |
| 1121 dev_dbg(codec->dev, "CODEC was on over suspend\n
"); | 1194 dev_dbg(codec->dev, "CODEC was on over suspend\n
"); |
| 1122 break; | 1195 break; |
| 1123 } | 1196 } |
| 1124 } | 1197 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 | 1233 |
| 1161 if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) | 1234 if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) |
| 1162 cpu_dai->driver->resume(cpu_dai); | 1235 cpu_dai->driver->resume(cpu_dai); |
| 1163 if (platform->driver->resume && platform->suspended) { | 1236 if (platform->driver->resume && platform->suspended) { |
| 1164 platform->driver->resume(cpu_dai); | 1237 platform->driver->resume(cpu_dai); |
| 1165 platform->suspended = 0; | 1238 platform->suspended = 0; |
| 1166 } | 1239 } |
| 1167 } | 1240 } |
| 1168 | 1241 |
| 1169 if (card->resume_post) | 1242 if (card->resume_post) |
| 1170 » » card->resume_post(pdev); | 1243 » » card->resume_post(card); |
| 1171 | 1244 |
| 1172 dev_dbg(card->dev, "resume work completed\n"); | 1245 dev_dbg(card->dev, "resume work completed\n"); |
| 1173 | 1246 |
| 1174 /* userspace can access us now we are back as we were before */ | 1247 /* userspace can access us now we are back as we were before */ |
| 1175 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); | 1248 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
| 1176 } | 1249 } |
| 1177 | 1250 |
| 1178 /* powers up audio subsystem after a suspend */ | 1251 /* powers up audio subsystem after a suspend */ |
| 1179 static int soc_resume(struct device *dev) | 1252 int snd_soc_resume(struct device *dev) |
| 1180 { | 1253 { |
| 1181 » struct platform_device *pdev = to_platform_device(dev); | 1254 » struct snd_soc_card *card = dev_get_drvdata(dev); |
| 1182 » struct snd_soc_card *card = platform_get_drvdata(pdev); | |
| 1183 int i; | 1255 int i; |
| 1184 | 1256 |
| 1185 /* AC97 devices might have other drivers hanging off them so | 1257 /* AC97 devices might have other drivers hanging off them so |
| 1186 * need to resume immediately. Other drivers don't have that | 1258 * need to resume immediately. Other drivers don't have that |
| 1187 * problem and may take a substantial amount of time to resume | 1259 * problem and may take a substantial amount of time to resume |
| 1188 * due to I/O costs and anti-pop so handle them out of line. | 1260 * due to I/O costs and anti-pop so handle them out of line. |
| 1189 */ | 1261 */ |
| 1190 for (i = 0; i < card->num_rtd; i++) { | 1262 for (i = 0; i < card->num_rtd; i++) { |
| 1191 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1263 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
| 1192 if (cpu_dai->driver->ac97_control) { | 1264 if (cpu_dai->driver->ac97_control) { |
| 1193 dev_dbg(dev, "Resuming AC97 immediately\n"); | 1265 dev_dbg(dev, "Resuming AC97 immediately\n"); |
| 1194 soc_resume_deferred(&card->deferred_resume_work); | 1266 soc_resume_deferred(&card->deferred_resume_work); |
| 1195 } else { | 1267 } else { |
| 1196 dev_dbg(dev, "Scheduling resume work\n"); | 1268 dev_dbg(dev, "Scheduling resume work\n"); |
| 1197 if (!schedule_work(&card->deferred_resume_work)) | 1269 if (!schedule_work(&card->deferred_resume_work)) |
| 1198 dev_err(dev, "resume work item may be lost\n"); | 1270 dev_err(dev, "resume work item may be lost\n"); |
| 1199 } | 1271 } |
| 1200 } | 1272 } |
| 1201 | 1273 |
| 1202 return 0; | 1274 return 0; |
| 1203 } | 1275 } |
| 1276 EXPORT_SYMBOL_GPL(snd_soc_resume); |
| 1204 #else | 1277 #else |
| 1205 #define soc_suspend» NULL | 1278 #define snd_soc_suspend NULL |
| 1206 #define soc_resume» NULL | 1279 #define snd_soc_resume NULL |
| 1207 #endif | 1280 #endif |
| 1208 | 1281 |
| 1209 static struct snd_soc_dai_ops null_dai_ops = { | 1282 static struct snd_soc_dai_ops null_dai_ops = { |
| 1210 }; | 1283 }; |
| 1211 | 1284 |
| 1212 static int soc_bind_dai_link(struct snd_soc_card *card, int num) | 1285 static int soc_bind_dai_link(struct snd_soc_card *card, int num) |
| 1213 { | 1286 { |
| 1214 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1287 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
| 1215 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1288 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
| 1216 struct snd_soc_codec *codec; | 1289 struct snd_soc_codec *codec; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1243 /* do we already have the CODEC for this link ? */ | 1316 /* do we already have the CODEC for this link ? */ |
| 1244 if (rtd->codec) { | 1317 if (rtd->codec) { |
| 1245 goto find_platform; | 1318 goto find_platform; |
| 1246 } | 1319 } |
| 1247 | 1320 |
| 1248 /* no, then find CODEC from registered CODECs*/ | 1321 /* no, then find CODEC from registered CODECs*/ |
| 1249 list_for_each_entry(codec, &codec_list, list) { | 1322 list_for_each_entry(codec, &codec_list, list) { |
| 1250 if (!strcmp(codec->name, dai_link->codec_name)) { | 1323 if (!strcmp(codec->name, dai_link->codec_name)) { |
| 1251 rtd->codec = codec; | 1324 rtd->codec = codec; |
| 1252 | 1325 |
| 1253 if (!try_module_get(codec->dev->driver->owner)) | |
| 1254 return -ENODEV; | |
| 1255 | |
| 1256 /* CODEC found, so find CODEC DAI from registered DAIs f
rom this CODEC*/ | 1326 /* CODEC found, so find CODEC DAI from registered DAIs f
rom this CODEC*/ |
| 1257 list_for_each_entry(codec_dai, &dai_list, list) { | 1327 list_for_each_entry(codec_dai, &dai_list, list) { |
| 1258 if (codec->dev == codec_dai->dev && | 1328 if (codec->dev == codec_dai->dev && |
| 1259 !strcmp(codec_dai->name, dai_lin
k->codec_dai_name)) { | 1329 !strcmp(codec_dai->name, dai_lin
k->codec_dai_name)) { |
| 1260 rtd->codec_dai = codec_dai; | 1330 rtd->codec_dai = codec_dai; |
| 1261 goto find_platform; | 1331 goto find_platform; |
| 1262 } | 1332 } |
| 1263 } | 1333 } |
| 1264 dev_dbg(card->dev, "CODEC DAI %s not registered\n", | 1334 dev_dbg(card->dev, "CODEC DAI %s not registered\n", |
| 1265 dai_link->codec_dai_name); | 1335 dai_link->codec_dai_name); |
| 1266 | 1336 |
| 1267 goto find_platform; | 1337 goto find_platform; |
| 1268 } | 1338 } |
| 1269 } | 1339 } |
| 1270 dev_dbg(card->dev, "CODEC %s not registered\n", | 1340 dev_dbg(card->dev, "CODEC %s not registered\n", |
| 1271 dai_link->codec_name); | 1341 dai_link->codec_name); |
| 1272 | 1342 |
| 1273 find_platform: | 1343 find_platform: |
| 1274 /* do we already have the CODEC DAI for this link ? */ | 1344 /* do we already have the CODEC DAI for this link ? */ |
| 1275 if (rtd->platform) { | 1345 if (rtd->platform) { |
| 1276 goto out; | 1346 goto out; |
| 1277 } | 1347 } |
| 1278 /* no, then find CPU DAI from registered DAIs*/ | 1348 /* no, then find CPU DAI from registered DAIs*/ |
| 1279 list_for_each_entry(platform, &platform_list, list) { | 1349 list_for_each_entry(platform, &platform_list, list) { |
| 1280 if (!strcmp(platform->name, dai_link->platform_name)) { | 1350 if (!strcmp(platform->name, dai_link->platform_name)) { |
| 1281 | |
| 1282 if (!try_module_get(platform->dev->driver->owner)) | |
| 1283 return -ENODEV; | |
| 1284 | |
| 1285 rtd->platform = platform; | 1351 rtd->platform = platform; |
| 1286 goto out; | 1352 goto out; |
| 1287 } | 1353 } |
| 1288 } | 1354 } |
| 1289 | 1355 |
| 1290 dev_dbg(card->dev, "platform %s not registered\n", | 1356 dev_dbg(card->dev, "platform %s not registered\n", |
| 1291 dai_link->platform_name); | 1357 dai_link->platform_name); |
| 1292 return 0; | 1358 return 0; |
| 1293 | 1359 |
| 1294 out: | 1360 out: |
| 1295 /* mark rtd as complete if we found all 4 of our client devices */ | 1361 /* mark rtd as complete if we found all 4 of our client devices */ |
| 1296 if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) { | 1362 if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) { |
| 1297 rtd->complete = 1; | 1363 rtd->complete = 1; |
| 1298 card->num_rtd++; | 1364 card->num_rtd++; |
| 1299 } | 1365 } |
| 1300 return 1; | 1366 return 1; |
| 1301 } | 1367 } |
| 1302 | 1368 |
| 1369 static void soc_remove_codec(struct snd_soc_codec *codec) |
| 1370 { |
| 1371 int err; |
| 1372 |
| 1373 if (codec->driver->remove) { |
| 1374 err = codec->driver->remove(codec); |
| 1375 if (err < 0) |
| 1376 dev_err(codec->dev, |
| 1377 "asoc: failed to remove %s: %d\n", |
| 1378 codec->name, err); |
| 1379 } |
| 1380 |
| 1381 /* Make sure all DAPM widgets are freed */ |
| 1382 snd_soc_dapm_free(&codec->dapm); |
| 1383 |
| 1384 soc_cleanup_codec_debugfs(codec); |
| 1385 codec->probed = 0; |
| 1386 list_del(&codec->card_list); |
| 1387 module_put(codec->dev->driver->owner); |
| 1388 } |
| 1389 |
| 1303 static void soc_remove_dai_link(struct snd_soc_card *card, int num) | 1390 static void soc_remove_dai_link(struct snd_soc_card *card, int num) |
| 1304 { | 1391 { |
| 1305 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1392 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
| 1306 struct snd_soc_codec *codec = rtd->codec; | 1393 struct snd_soc_codec *codec = rtd->codec; |
| 1307 struct snd_soc_platform *platform = rtd->platform; | 1394 struct snd_soc_platform *platform = rtd->platform; |
| 1308 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1395 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
| 1309 int err; | 1396 int err; |
| 1310 | 1397 |
| 1311 /* unregister the rtd device */ | 1398 /* unregister the rtd device */ |
| 1312 if (rtd->dev_registered) { | 1399 if (rtd->dev_registered) { |
| 1313 device_remove_file(&rtd->dev, &dev_attr_pmdown_time); | 1400 device_remove_file(&rtd->dev, &dev_attr_pmdown_time); |
| 1401 device_remove_file(&rtd->dev, &dev_attr_codec_reg); |
| 1314 device_unregister(&rtd->dev); | 1402 device_unregister(&rtd->dev); |
| 1315 rtd->dev_registered = 0; | 1403 rtd->dev_registered = 0; |
| 1316 } | 1404 } |
| 1317 | 1405 |
| 1318 /* remove the CODEC DAI */ | 1406 /* remove the CODEC DAI */ |
| 1319 if (codec_dai && codec_dai->probed) { | 1407 if (codec_dai && codec_dai->probed) { |
| 1320 if (codec_dai->driver->remove) { | 1408 if (codec_dai->driver->remove) { |
| 1321 err = codec_dai->driver->remove(codec_dai); | 1409 err = codec_dai->driver->remove(codec_dai); |
| 1322 if (err < 0) | 1410 if (err < 0) |
| 1323 printk(KERN_ERR "asoc: failed to remove %s\n", c
odec_dai->name); | 1411 printk(KERN_ERR "asoc: failed to remove %s\n", c
odec_dai->name); |
| 1324 } | 1412 } |
| 1325 codec_dai->probed = 0; | 1413 codec_dai->probed = 0; |
| 1326 list_del(&codec_dai->card_list); | 1414 list_del(&codec_dai->card_list); |
| 1327 } | 1415 } |
| 1328 | 1416 |
| 1329 /* remove the platform */ | 1417 /* remove the platform */ |
| 1330 if (platform && platform->probed) { | 1418 if (platform && platform->probed) { |
| 1331 if (platform->driver->remove) { | 1419 if (platform->driver->remove) { |
| 1332 err = platform->driver->remove(platform); | 1420 err = platform->driver->remove(platform); |
| 1333 if (err < 0) | 1421 if (err < 0) |
| 1334 printk(KERN_ERR "asoc: failed to remove %s\n", p
latform->name); | 1422 printk(KERN_ERR "asoc: failed to remove %s\n", p
latform->name); |
| 1335 } | 1423 } |
| 1336 platform->probed = 0; | 1424 platform->probed = 0; |
| 1337 list_del(&platform->card_list); | 1425 list_del(&platform->card_list); |
| 1338 module_put(platform->dev->driver->owner); | 1426 module_put(platform->dev->driver->owner); |
| 1339 } | 1427 } |
| 1340 | 1428 |
| 1341 /* remove the CODEC */ | 1429 /* remove the CODEC */ |
| 1342 » if (codec && codec->probed) { | 1430 » if (codec && codec->probed) |
| 1343 » » if (codec->driver->remove) { | 1431 » » soc_remove_codec(codec); |
| 1344 » » » err = codec->driver->remove(codec); | |
| 1345 » » » if (err < 0) | |
| 1346 » » » » printk(KERN_ERR "asoc: failed to remove %s\n", c
odec->name); | |
| 1347 » » } | |
| 1348 | |
| 1349 » » /* Make sure all DAPM widgets are freed */ | |
| 1350 » » snd_soc_dapm_free(codec); | |
| 1351 | |
| 1352 » » soc_cleanup_codec_debugfs(codec); | |
| 1353 » » device_remove_file(&rtd->dev, &dev_attr_codec_reg); | |
| 1354 » » codec->probed = 0; | |
| 1355 » » list_del(&codec->card_list); | |
| 1356 » » module_put(codec->dev->driver->owner); | |
| 1357 » } | |
| 1358 | 1432 |
| 1359 /* remove the cpu_dai */ | 1433 /* remove the cpu_dai */ |
| 1360 if (cpu_dai && cpu_dai->probed) { | 1434 if (cpu_dai && cpu_dai->probed) { |
| 1361 if (cpu_dai->driver->remove) { | 1435 if (cpu_dai->driver->remove) { |
| 1362 err = cpu_dai->driver->remove(cpu_dai); | 1436 err = cpu_dai->driver->remove(cpu_dai); |
| 1363 if (err < 0) | 1437 if (err < 0) |
| 1364 printk(KERN_ERR "asoc: failed to remove %s\n", c
pu_dai->name); | 1438 printk(KERN_ERR "asoc: failed to remove %s\n", c
pu_dai->name); |
| 1365 } | 1439 } |
| 1366 cpu_dai->probed = 0; | 1440 cpu_dai->probed = 0; |
| 1367 list_del(&cpu_dai->card_list); | 1441 list_del(&cpu_dai->card_list); |
| 1368 module_put(cpu_dai->dev->driver->owner); | 1442 module_put(cpu_dai->dev->driver->owner); |
| 1369 } | 1443 } |
| 1370 } | 1444 } |
| 1371 | 1445 |
| 1446 static void soc_set_name_prefix(struct snd_soc_card *card, |
| 1447 struct snd_soc_codec *codec) |
| 1448 { |
| 1449 int i; |
| 1450 |
| 1451 if (card->codec_conf == NULL) |
| 1452 return; |
| 1453 |
| 1454 for (i = 0; i < card->num_configs; i++) { |
| 1455 struct snd_soc_codec_conf *map = &card->codec_conf[i]; |
| 1456 if (map->dev_name && !strcmp(codec->name, map->dev_name)) { |
| 1457 codec->name_prefix = map->name_prefix; |
| 1458 break; |
| 1459 } |
| 1460 } |
| 1461 } |
| 1462 |
| 1463 static int soc_probe_codec(struct snd_soc_card *card, |
| 1464 struct snd_soc_codec *codec) |
| 1465 { |
| 1466 int ret = 0; |
| 1467 |
| 1468 codec->card = card; |
| 1469 codec->dapm.card = card; |
| 1470 soc_set_name_prefix(card, codec); |
| 1471 |
| 1472 if (!try_module_get(codec->dev->driver->owner)) |
| 1473 return -ENODEV; |
| 1474 |
| 1475 if (codec->driver->probe) { |
| 1476 ret = codec->driver->probe(codec); |
| 1477 if (ret < 0) { |
| 1478 dev_err(codec->dev, |
| 1479 "asoc: failed to probe CODEC %s: %d\n", |
| 1480 codec->name, ret); |
| 1481 goto err_probe; |
| 1482 } |
| 1483 } |
| 1484 |
| 1485 soc_init_codec_debugfs(codec); |
| 1486 |
| 1487 /* mark codec as probed and add to card codec list */ |
| 1488 codec->probed = 1; |
| 1489 list_add(&codec->card_list, &card->codec_dev_list); |
| 1490 list_add(&codec->dapm.list, &card->dapm_list); |
| 1491 |
| 1492 return 0; |
| 1493 |
| 1494 err_probe: |
| 1495 module_put(codec->dev->driver->owner); |
| 1496 |
| 1497 return ret; |
| 1498 } |
| 1499 |
| 1372 static void rtd_release(struct device *dev) {} | 1500 static void rtd_release(struct device *dev) {} |
| 1373 | 1501 |
| 1502 static int soc_post_component_init(struct snd_soc_card *card, |
| 1503 struct snd_soc_codec *codec, |
| 1504 int num, int dailess) |
| 1505 { |
| 1506 struct snd_soc_dai_link *dai_link = NULL; |
| 1507 struct snd_soc_aux_dev *aux_dev = NULL; |
| 1508 struct snd_soc_pcm_runtime *rtd; |
| 1509 const char *temp, *name; |
| 1510 int ret = 0; |
| 1511 |
| 1512 if (!dailess) { |
| 1513 dai_link = &card->dai_link[num]; |
| 1514 rtd = &card->rtd[num]; |
| 1515 name = dai_link->name; |
| 1516 } else { |
| 1517 aux_dev = &card->aux_dev[num]; |
| 1518 rtd = &card->rtd_aux[num]; |
| 1519 name = aux_dev->name; |
| 1520 } |
| 1521 rtd->card = card; |
| 1522 |
| 1523 /* machine controls, routes and widgets are not prefixed */ |
| 1524 temp = codec->name_prefix; |
| 1525 codec->name_prefix = NULL; |
| 1526 |
| 1527 /* do machine specific initialization */ |
| 1528 if (!dailess && dai_link->init) |
| 1529 ret = dai_link->init(rtd); |
| 1530 else if (dailess && aux_dev->init) |
| 1531 ret = aux_dev->init(&codec->dapm); |
| 1532 if (ret < 0) { |
| 1533 dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret); |
| 1534 return ret; |
| 1535 } |
| 1536 codec->name_prefix = temp; |
| 1537 |
| 1538 /* Make sure all DAPM widgets are instantiated */ |
| 1539 snd_soc_dapm_new_widgets(&codec->dapm); |
| 1540 |
| 1541 /* register the rtd device */ |
| 1542 rtd->codec = codec; |
| 1543 rtd->dev.parent = card->dev; |
| 1544 rtd->dev.release = rtd_release; |
| 1545 rtd->dev.init_name = name; |
| 1546 ret = device_register(&rtd->dev); |
| 1547 if (ret < 0) { |
| 1548 dev_err(card->dev, |
| 1549 "asoc: failed to register runtime device: %d\n", ret); |
| 1550 return ret; |
| 1551 } |
| 1552 rtd->dev_registered = 1; |
| 1553 |
| 1554 /* add DAPM sysfs entries for this codec */ |
| 1555 ret = snd_soc_dapm_sys_add(&rtd->dev); |
| 1556 if (ret < 0) |
| 1557 dev_err(codec->dev, |
| 1558 "asoc: failed to add codec dapm sysfs entries: %d\n", |
| 1559 ret); |
| 1560 |
| 1561 /* add codec sysfs entries */ |
| 1562 ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); |
| 1563 if (ret < 0) |
| 1564 dev_err(codec->dev, |
| 1565 "asoc: failed to add codec sysfs files: %d\n", ret); |
| 1566 |
| 1567 return 0; |
| 1568 } |
| 1569 |
| 1374 static int soc_probe_dai_link(struct snd_soc_card *card, int num) | 1570 static int soc_probe_dai_link(struct snd_soc_card *card, int num) |
| 1375 { | 1571 { |
| 1376 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1572 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
| 1377 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1573 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
| 1378 struct snd_soc_codec *codec = rtd->codec; | 1574 struct snd_soc_codec *codec = rtd->codec; |
| 1379 struct snd_soc_platform *platform = rtd->platform; | 1575 struct snd_soc_platform *platform = rtd->platform; |
| 1380 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1576 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
| 1381 int ret; | 1577 int ret; |
| 1382 | 1578 |
| 1383 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); | 1579 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); |
| 1384 | 1580 |
| 1385 /* config components */ | 1581 /* config components */ |
| 1386 codec_dai->codec = codec; | 1582 codec_dai->codec = codec; |
| 1387 codec->card = card; | |
| 1388 cpu_dai->platform = platform; | 1583 cpu_dai->platform = platform; |
| 1389 rtd->card = card; | |
| 1390 rtd->dev.parent = card->dev; | |
| 1391 codec_dai->card = card; | 1584 codec_dai->card = card; |
| 1392 cpu_dai->card = card; | 1585 cpu_dai->card = card; |
| 1393 | 1586 |
| 1394 /* set default power off timeout */ | 1587 /* set default power off timeout */ |
| 1395 rtd->pmdown_time = pmdown_time; | 1588 rtd->pmdown_time = pmdown_time; |
| 1396 | 1589 |
| 1397 /* probe the cpu_dai */ | 1590 /* probe the cpu_dai */ |
| 1398 if (!cpu_dai->probed) { | 1591 if (!cpu_dai->probed) { |
| 1399 if (cpu_dai->driver->probe) { | 1592 if (cpu_dai->driver->probe) { |
| 1400 ret = cpu_dai->driver->probe(cpu_dai); | 1593 ret = cpu_dai->driver->probe(cpu_dai); |
| 1401 if (ret < 0) { | 1594 if (ret < 0) { |
| 1402 printk(KERN_ERR "asoc: failed to probe CPU DAI %
s\n", | 1595 printk(KERN_ERR "asoc: failed to probe CPU DAI %
s\n", |
| 1403 cpu_dai->name); | 1596 cpu_dai->name); |
| 1404 return ret; | 1597 return ret; |
| 1405 } | 1598 } |
| 1406 } | 1599 } |
| 1407 cpu_dai->probed = 1; | 1600 cpu_dai->probed = 1; |
| 1408 /* mark cpu_dai as probed and add to card cpu_dai list */ | 1601 /* mark cpu_dai as probed and add to card cpu_dai list */ |
| 1409 list_add(&cpu_dai->card_list, &card->dai_dev_list); | 1602 list_add(&cpu_dai->card_list, &card->dai_dev_list); |
| 1410 } | 1603 } |
| 1411 | 1604 |
| 1412 /* probe the CODEC */ | 1605 /* probe the CODEC */ |
| 1413 if (!codec->probed) { | 1606 if (!codec->probed) { |
| 1414 » » if (codec->driver->probe) { | 1607 » » ret = soc_probe_codec(card, codec); |
| 1415 » » » ret = codec->driver->probe(codec); | 1608 » » if (ret < 0) |
| 1416 » » » if (ret < 0) { | 1609 » » » return ret; |
| 1417 » » » » printk(KERN_ERR "asoc: failed to probe CODEC %s\
n", | |
| 1418 » » » » » » codec->name); | |
| 1419 » » » » return ret; | |
| 1420 » » » } | |
| 1421 » » } | |
| 1422 | |
| 1423 » » soc_init_codec_debugfs(codec); | |
| 1424 | |
| 1425 » » /* mark codec as probed and add to card codec list */ | |
| 1426 » » codec->probed = 1; | |
| 1427 » » list_add(&codec->card_list, &card->codec_dev_list); | |
| 1428 } | 1610 } |
| 1429 | 1611 |
| 1430 /* probe the platform */ | 1612 /* probe the platform */ |
| 1431 if (!platform->probed) { | 1613 if (!platform->probed) { |
| 1614 if (!try_module_get(platform->dev->driver->owner)) |
| 1615 return -ENODEV; |
| 1616 |
| 1432 if (platform->driver->probe) { | 1617 if (platform->driver->probe) { |
| 1433 ret = platform->driver->probe(platform); | 1618 ret = platform->driver->probe(platform); |
| 1434 if (ret < 0) { | 1619 if (ret < 0) { |
| 1435 printk(KERN_ERR "asoc: failed to probe platform
%s\n", | 1620 printk(KERN_ERR "asoc: failed to probe platform
%s\n", |
| 1436 platform->name); | 1621 platform->name); |
| 1622 module_put(platform->dev->driver->owner); |
| 1437 return ret; | 1623 return ret; |
| 1438 } | 1624 } |
| 1439 } | 1625 } |
| 1440 /* mark platform as probed and add to card platform list */ | 1626 /* mark platform as probed and add to card platform list */ |
| 1441 platform->probed = 1; | 1627 platform->probed = 1; |
| 1442 list_add(&platform->card_list, &card->platform_dev_list); | 1628 list_add(&platform->card_list, &card->platform_dev_list); |
| 1443 } | 1629 } |
| 1444 | 1630 |
| 1445 /* probe the CODEC DAI */ | 1631 /* probe the CODEC DAI */ |
| 1446 if (!codec_dai->probed) { | 1632 if (!codec_dai->probed) { |
| 1447 if (codec_dai->driver->probe) { | 1633 if (codec_dai->driver->probe) { |
| 1448 ret = codec_dai->driver->probe(codec_dai); | 1634 ret = codec_dai->driver->probe(codec_dai); |
| 1449 if (ret < 0) { | 1635 if (ret < 0) { |
| 1450 printk(KERN_ERR "asoc: failed to probe CODEC DAI
%s\n", | 1636 printk(KERN_ERR "asoc: failed to probe CODEC DAI
%s\n", |
| 1451 codec_dai->name); | 1637 codec_dai->name); |
| 1452 return ret; | 1638 return ret; |
| 1453 } | 1639 } |
| 1454 } | 1640 } |
| 1455 | 1641 |
| 1456 /* mark cpu_dai as probed and add to card cpu_dai list */ | 1642 /* mark cpu_dai as probed and add to card cpu_dai list */ |
| 1457 codec_dai->probed = 1; | 1643 codec_dai->probed = 1; |
| 1458 list_add(&codec_dai->card_list, &card->dai_dev_list); | 1644 list_add(&codec_dai->card_list, &card->dai_dev_list); |
| 1459 } | 1645 } |
| 1460 | 1646 |
| 1461 /* DAPM dai link stream work */ | 1647 /* DAPM dai link stream work */ |
| 1462 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | 1648 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); |
| 1463 | 1649 |
| 1464 » /* now that all clients have probed, initialise the DAI link */ | 1650 » ret = soc_post_component_init(card, codec, num, 0); |
| 1465 » if (dai_link->init) { | 1651 » if (ret) |
| 1466 » » ret = dai_link->init(rtd); | 1652 » » return ret; |
| 1467 » » if (ret < 0) { | |
| 1468 » » » printk(KERN_ERR "asoc: failed to init %s\n", dai_link->s
tream_name); | |
| 1469 » » » return ret; | |
| 1470 » » } | |
| 1471 » } | |
| 1472 | 1653 |
| 1473 /* Make sure all DAPM widgets are instantiated */ | |
| 1474 snd_soc_dapm_new_widgets(codec); | |
| 1475 snd_soc_dapm_sync(codec); | |
| 1476 | |
| 1477 /* register the rtd device */ | |
| 1478 rtd->dev.release = rtd_release; | |
| 1479 rtd->dev.init_name = dai_link->name; | |
| 1480 ret = device_register(&rtd->dev); | |
| 1481 if (ret < 0) { | |
| 1482 printk(KERN_ERR "asoc: failed to register DAI runtime device %d\
n", ret); | |
| 1483 return ret; | |
| 1484 } | |
| 1485 | |
| 1486 rtd->dev_registered = 1; | |
| 1487 ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); | 1654 ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); |
| 1488 if (ret < 0) | 1655 if (ret < 0) |
| 1489 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | 1656 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); |
| 1490 | 1657 |
| 1491 /* add DAPM sysfs entries for this codec */ | |
| 1492 ret = snd_soc_dapm_sys_add(&rtd->dev); | |
| 1493 if (ret < 0) | |
| 1494 printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entrie
s\n"); | |
| 1495 | |
| 1496 /* add codec sysfs entries */ | |
| 1497 ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | |
| 1498 if (ret < 0) | |
| 1499 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | |
| 1500 | |
| 1501 /* create the pcm */ | 1658 /* create the pcm */ |
| 1502 ret = soc_new_pcm(rtd, num); | 1659 ret = soc_new_pcm(rtd, num); |
| 1503 if (ret < 0) { | 1660 if (ret < 0) { |
| 1504 printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_
name); | 1661 printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_
name); |
| 1505 return ret; | 1662 return ret; |
| 1506 } | 1663 } |
| 1507 | 1664 |
| 1508 /* add platform data for AC97 devices */ | 1665 /* add platform data for AC97 devices */ |
| 1509 if (rtd->codec_dai->driver->ac97_control) | 1666 if (rtd->codec_dai->driver->ac97_control) |
| 1510 snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); | 1667 snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 | 1702 |
| 1546 static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) | 1703 static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) |
| 1547 { | 1704 { |
| 1548 if (codec->ac97_registered) { | 1705 if (codec->ac97_registered) { |
| 1549 soc_ac97_dev_unregister(codec); | 1706 soc_ac97_dev_unregister(codec); |
| 1550 codec->ac97_registered = 0; | 1707 codec->ac97_registered = 0; |
| 1551 } | 1708 } |
| 1552 } | 1709 } |
| 1553 #endif | 1710 #endif |
| 1554 | 1711 |
| 1712 static int soc_probe_aux_dev(struct snd_soc_card *card, int num) |
| 1713 { |
| 1714 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
| 1715 struct snd_soc_codec *codec; |
| 1716 int ret = -ENODEV; |
| 1717 |
| 1718 /* find CODEC from registered CODECs*/ |
| 1719 list_for_each_entry(codec, &codec_list, list) { |
| 1720 if (!strcmp(codec->name, aux_dev->codec_name)) { |
| 1721 if (codec->probed) { |
| 1722 dev_err(codec->dev, |
| 1723 "asoc: codec already probed"); |
| 1724 ret = -EBUSY; |
| 1725 goto out; |
| 1726 } |
| 1727 goto found; |
| 1728 } |
| 1729 } |
| 1730 /* codec not found */ |
| 1731 dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name); |
| 1732 goto out; |
| 1733 |
| 1734 found: |
| 1735 ret = soc_probe_codec(card, codec); |
| 1736 if (ret < 0) |
| 1737 return ret; |
| 1738 |
| 1739 ret = soc_post_component_init(card, codec, num, 1); |
| 1740 |
| 1741 out: |
| 1742 return ret; |
| 1743 } |
| 1744 |
| 1745 static void soc_remove_aux_dev(struct snd_soc_card *card, int num) |
| 1746 { |
| 1747 struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
| 1748 struct snd_soc_codec *codec = rtd->codec; |
| 1749 |
| 1750 /* unregister the rtd device */ |
| 1751 if (rtd->dev_registered) { |
| 1752 device_remove_file(&rtd->dev, &dev_attr_codec_reg); |
| 1753 device_unregister(&rtd->dev); |
| 1754 rtd->dev_registered = 0; |
| 1755 } |
| 1756 |
| 1757 if (codec && codec->probed) |
| 1758 soc_remove_codec(codec); |
| 1759 } |
| 1760 |
| 1761 static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, |
| 1762 enum snd_soc_compress_type compress_type) |
| 1763 { |
| 1764 int ret; |
| 1765 |
| 1766 if (codec->cache_init) |
| 1767 return 0; |
| 1768 |
| 1769 /* override the compress_type if necessary */ |
| 1770 if (compress_type && codec->compress_type != compress_type) |
| 1771 codec->compress_type = compress_type; |
| 1772 ret = snd_soc_cache_init(codec); |
| 1773 if (ret < 0) { |
| 1774 dev_err(codec->dev, "Failed to set cache compression type: %d\n"
, |
| 1775 ret); |
| 1776 return ret; |
| 1777 } |
| 1778 codec->cache_init = 1; |
| 1779 return 0; |
| 1780 } |
| 1781 |
| 1555 static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1782 static void snd_soc_instantiate_card(struct snd_soc_card *card) |
| 1556 { | 1783 { |
| 1557 » struct platform_device *pdev = to_platform_device(card->dev); | 1784 » struct snd_soc_codec *codec; |
| 1785 » struct snd_soc_codec_conf *codec_conf; |
| 1786 » enum snd_soc_compress_type compress_type; |
| 1558 int ret, i; | 1787 int ret, i; |
| 1559 | 1788 |
| 1560 mutex_lock(&card->mutex); | 1789 mutex_lock(&card->mutex); |
| 1561 | 1790 |
| 1562 if (card->instantiated) { | 1791 if (card->instantiated) { |
| 1563 mutex_unlock(&card->mutex); | 1792 mutex_unlock(&card->mutex); |
| 1564 return; | 1793 return; |
| 1565 } | 1794 } |
| 1566 | 1795 |
| 1567 /* bind DAIs */ | 1796 /* bind DAIs */ |
| 1568 for (i = 0; i < card->num_links; i++) | 1797 for (i = 0; i < card->num_links; i++) |
| 1569 soc_bind_dai_link(card, i); | 1798 soc_bind_dai_link(card, i); |
| 1570 | 1799 |
| 1571 /* bind completed ? */ | 1800 /* bind completed ? */ |
| 1572 if (card->num_rtd != card->num_links) { | 1801 if (card->num_rtd != card->num_links) { |
| 1573 mutex_unlock(&card->mutex); | 1802 mutex_unlock(&card->mutex); |
| 1574 return; | 1803 return; |
| 1575 } | 1804 } |
| 1576 | 1805 |
| 1806 /* initialize the register cache for each available codec */ |
| 1807 list_for_each_entry(codec, &codec_list, list) { |
| 1808 if (codec->cache_init) |
| 1809 continue; |
| 1810 /* by default we don't override the compress_type */ |
| 1811 compress_type = 0; |
| 1812 /* check to see if we need to override the compress_type */ |
| 1813 for (i = 0; i < card->num_configs; ++i) { |
| 1814 codec_conf = &card->codec_conf[i]; |
| 1815 if (!strcmp(codec->name, codec_conf->dev_name)) { |
| 1816 compress_type = codec_conf->compress_type; |
| 1817 if (compress_type && compress_type |
| 1818 != codec->compress_type) |
| 1819 break; |
| 1820 } |
| 1821 } |
| 1822 ret = snd_soc_init_codec_cache(codec, compress_type); |
| 1823 if (ret < 0) { |
| 1824 mutex_unlock(&card->mutex); |
| 1825 return; |
| 1826 } |
| 1827 } |
| 1828 |
| 1577 /* card bind complete so register a sound card */ | 1829 /* card bind complete so register a sound card */ |
| 1578 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1830 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
| 1579 card->owner, 0, &card->snd_card); | 1831 card->owner, 0, &card->snd_card); |
| 1580 if (ret < 0) { | 1832 if (ret < 0) { |
| 1581 printk(KERN_ERR "asoc: can't create sound card for card %s\n", | 1833 printk(KERN_ERR "asoc: can't create sound card for card %s\n", |
| 1582 card->name); | 1834 card->name); |
| 1583 mutex_unlock(&card->mutex); | 1835 mutex_unlock(&card->mutex); |
| 1584 return; | 1836 return; |
| 1585 } | 1837 } |
| 1586 card->snd_card->dev = card->dev; | 1838 card->snd_card->dev = card->dev; |
| 1587 | 1839 |
| 1588 #ifdef CONFIG_PM | 1840 #ifdef CONFIG_PM_SLEEP |
| 1589 /* deferred resume work */ | 1841 /* deferred resume work */ |
| 1590 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | 1842 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); |
| 1591 #endif | 1843 #endif |
| 1592 | 1844 |
| 1593 /* initialise the sound card only once */ | 1845 /* initialise the sound card only once */ |
| 1594 if (card->probe) { | 1846 if (card->probe) { |
| 1595 » » ret = card->probe(pdev); | 1847 » » ret = card->probe(card); |
| 1596 if (ret < 0) | 1848 if (ret < 0) |
| 1597 goto card_probe_error; | 1849 goto card_probe_error; |
| 1598 } | 1850 } |
| 1599 | 1851 |
| 1600 for (i = 0; i < card->num_links; i++) { | 1852 for (i = 0; i < card->num_links; i++) { |
| 1601 ret = soc_probe_dai_link(card, i); | 1853 ret = soc_probe_dai_link(card, i); |
| 1602 if (ret < 0) { | 1854 if (ret < 0) { |
| 1603 pr_err("asoc: failed to instantiate card %s: %d\n", | 1855 pr_err("asoc: failed to instantiate card %s: %d\n", |
| 1604 card->name, ret); | 1856 card->name, ret); |
| 1605 goto probe_dai_err; | 1857 goto probe_dai_err; |
| 1606 } | 1858 } |
| 1607 } | 1859 } |
| 1608 | 1860 |
| 1861 for (i = 0; i < card->num_aux_devs; i++) { |
| 1862 ret = soc_probe_aux_dev(card, i); |
| 1863 if (ret < 0) { |
| 1864 pr_err("asoc: failed to add auxiliary devices %s: %d\n", |
| 1865 card->name, ret); |
| 1866 goto probe_aux_dev_err; |
| 1867 } |
| 1868 } |
| 1869 |
| 1609 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1870 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
| 1610 "%s", card->name); | 1871 "%s", card->name); |
| 1611 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | 1872 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
| 1612 "%s", card->name); | 1873 "%s", card->name); |
| 1613 | 1874 |
| 1614 ret = snd_card_register(card->snd_card); | 1875 ret = snd_card_register(card->snd_card); |
| 1615 if (ret < 0) { | 1876 if (ret < 0) { |
| 1616 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", c
ard->name); | 1877 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", c
ard->name); |
| 1617 » » goto probe_dai_err; | 1878 » » goto probe_aux_dev_err; |
| 1618 } | 1879 } |
| 1619 | 1880 |
| 1620 #ifdef CONFIG_SND_SOC_AC97_BUS | 1881 #ifdef CONFIG_SND_SOC_AC97_BUS |
| 1621 /* register any AC97 codecs */ | 1882 /* register any AC97 codecs */ |
| 1622 for (i = 0; i < card->num_rtd; i++) { | 1883 for (i = 0; i < card->num_rtd; i++) { |
| 1623 ret = soc_register_ac97_dai_link(&card->rtd[i]); | 1884 ret = soc_register_ac97_dai_link(&card->rtd[i]); |
| 1624 if (ret < 0) { | 1885 if (ret < 0) { |
| 1625 printk(KERN_ERR "asoc: failed to register AC97 %s\n", ca
rd->name); | 1886 printk(KERN_ERR "asoc: failed to register AC97 %s\n", ca
rd->name); |
| 1626 while (--i >= 0) | 1887 while (--i >= 0) |
| 1627 » » » » soc_unregister_ac97_dai_link(&card->rtd[i]); | 1888 » » » » soc_unregister_ac97_dai_link(card->rtd[i].codec)
; |
| 1628 » » » goto probe_dai_err; | 1889 » » » goto probe_aux_dev_err; |
| 1629 } | 1890 } |
| 1630 } | 1891 } |
| 1631 #endif | 1892 #endif |
| 1632 | 1893 |
| 1633 card->instantiated = 1; | 1894 card->instantiated = 1; |
| 1634 mutex_unlock(&card->mutex); | 1895 mutex_unlock(&card->mutex); |
| 1635 return; | 1896 return; |
| 1636 | 1897 |
| 1898 probe_aux_dev_err: |
| 1899 for (i = 0; i < card->num_aux_devs; i++) |
| 1900 soc_remove_aux_dev(card, i); |
| 1901 |
| 1637 probe_dai_err: | 1902 probe_dai_err: |
| 1638 for (i = 0; i < card->num_links; i++) | 1903 for (i = 0; i < card->num_links; i++) |
| 1639 soc_remove_dai_link(card, i); | 1904 soc_remove_dai_link(card, i); |
| 1640 | 1905 |
| 1641 card_probe_error: | 1906 card_probe_error: |
| 1642 if (card->remove) | 1907 if (card->remove) |
| 1643 » » card->remove(pdev); | 1908 » » card->remove(card); |
| 1644 | 1909 |
| 1645 snd_card_free(card->snd_card); | 1910 snd_card_free(card->snd_card); |
| 1646 | 1911 |
| 1647 mutex_unlock(&card->mutex); | 1912 mutex_unlock(&card->mutex); |
| 1648 } | 1913 } |
| 1649 | 1914 |
| 1650 /* | 1915 /* |
| 1651 * Attempt to initialise any uninitialised cards. Must be called with | 1916 * Attempt to initialise any uninitialised cards. Must be called with |
| 1652 * client_mutex. | 1917 * client_mutex. |
| 1653 */ | 1918 */ |
| 1654 static void snd_soc_instantiate_cards(void) | 1919 static void snd_soc_instantiate_cards(void) |
| 1655 { | 1920 { |
| 1656 struct snd_soc_card *card; | 1921 struct snd_soc_card *card; |
| 1657 list_for_each_entry(card, &card_list, list) | 1922 list_for_each_entry(card, &card_list, list) |
| 1658 snd_soc_instantiate_card(card); | 1923 snd_soc_instantiate_card(card); |
| 1659 } | 1924 } |
| 1660 | 1925 |
| 1661 /* probes a new socdev */ | 1926 /* probes a new socdev */ |
| 1662 static int soc_probe(struct platform_device *pdev) | 1927 static int soc_probe(struct platform_device *pdev) |
| 1663 { | 1928 { |
| 1664 struct snd_soc_card *card = platform_get_drvdata(pdev); | 1929 struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 1665 int ret = 0; | 1930 int ret = 0; |
| 1666 | 1931 |
| 1932 /* |
| 1933 * no card, so machine driver should be registering card |
| 1934 * we should not be here in that case so ret error |
| 1935 */ |
| 1936 if (!card) |
| 1937 return -EINVAL; |
| 1938 |
| 1667 /* Bodge while we unpick instantiation */ | 1939 /* Bodge while we unpick instantiation */ |
| 1668 card->dev = &pdev->dev; | 1940 card->dev = &pdev->dev; |
| 1669 INIT_LIST_HEAD(&card->dai_dev_list); | |
| 1670 INIT_LIST_HEAD(&card->codec_dev_list); | |
| 1671 INIT_LIST_HEAD(&card->platform_dev_list); | |
| 1672 | 1941 |
| 1673 ret = snd_soc_register_card(card); | 1942 ret = snd_soc_register_card(card); |
| 1674 if (ret != 0) { | 1943 if (ret != 0) { |
| 1675 dev_err(&pdev->dev, "Failed to register card\n"); | 1944 dev_err(&pdev->dev, "Failed to register card\n"); |
| 1676 return ret; | 1945 return ret; |
| 1677 } | 1946 } |
| 1678 | 1947 |
| 1679 return 0; | 1948 return 0; |
| 1680 } | 1949 } |
| 1681 | 1950 |
| 1951 static int soc_cleanup_card_resources(struct snd_soc_card *card) |
| 1952 { |
| 1953 int i; |
| 1954 |
| 1955 /* make sure any delayed work runs */ |
| 1956 for (i = 0; i < card->num_rtd; i++) { |
| 1957 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
| 1958 flush_delayed_work_sync(&rtd->delayed_work); |
| 1959 } |
| 1960 |
| 1961 /* remove auxiliary devices */ |
| 1962 for (i = 0; i < card->num_aux_devs; i++) |
| 1963 soc_remove_aux_dev(card, i); |
| 1964 |
| 1965 /* remove and free each DAI */ |
| 1966 for (i = 0; i < card->num_rtd; i++) |
| 1967 soc_remove_dai_link(card, i); |
| 1968 |
| 1969 soc_cleanup_card_debugfs(card); |
| 1970 |
| 1971 /* remove the card */ |
| 1972 if (card->remove) |
| 1973 card->remove(card); |
| 1974 |
| 1975 kfree(card->rtd); |
| 1976 snd_card_free(card->snd_card); |
| 1977 return 0; |
| 1978 |
| 1979 } |
| 1980 |
| 1682 /* removes a socdev */ | 1981 /* removes a socdev */ |
| 1683 static int soc_remove(struct platform_device *pdev) | 1982 static int soc_remove(struct platform_device *pdev) |
| 1684 { | 1983 { |
| 1685 struct snd_soc_card *card = platform_get_drvdata(pdev); | 1984 struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 1686 int i; | |
| 1687 | 1985 |
| 1688 if (card->instantiated) { | |
| 1689 | |
| 1690 /* make sure any delayed work runs */ | |
| 1691 for (i = 0; i < card->num_rtd; i++) { | |
| 1692 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | |
| 1693 run_delayed_work(&rtd->delayed_work); | |
| 1694 } | |
| 1695 | |
| 1696 /* remove and free each DAI */ | |
| 1697 for (i = 0; i < card->num_rtd; i++) | |
| 1698 soc_remove_dai_link(card, i); | |
| 1699 | |
| 1700 /* remove the card */ | |
| 1701 if (card->remove) | |
| 1702 card->remove(pdev); | |
| 1703 | |
| 1704 kfree(card->rtd); | |
| 1705 snd_card_free(card->snd_card); | |
| 1706 } | |
| 1707 snd_soc_unregister_card(card); | 1986 snd_soc_unregister_card(card); |
| 1708 return 0; | 1987 return 0; |
| 1709 } | 1988 } |
| 1710 | 1989 |
| 1711 static int soc_poweroff(struct device *dev) | 1990 int snd_soc_poweroff(struct device *dev) |
| 1712 { | 1991 { |
| 1713 » struct platform_device *pdev = to_platform_device(dev); | 1992 » struct snd_soc_card *card = dev_get_drvdata(dev); |
| 1714 » struct snd_soc_card *card = platform_get_drvdata(pdev); | |
| 1715 int i; | 1993 int i; |
| 1716 | 1994 |
| 1717 if (!card->instantiated) | 1995 if (!card->instantiated) |
| 1718 return 0; | 1996 return 0; |
| 1719 | 1997 |
| 1720 /* Flush out pmdown_time work - we actually do want to run it | 1998 /* Flush out pmdown_time work - we actually do want to run it |
| 1721 * now, we're shutting down so no imminent restart. */ | 1999 * now, we're shutting down so no imminent restart. */ |
| 1722 for (i = 0; i < card->num_rtd; i++) { | 2000 for (i = 0; i < card->num_rtd; i++) { |
| 1723 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | 2001 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
| 1724 » » run_delayed_work(&rtd->delayed_work); | 2002 » » flush_delayed_work_sync(&rtd->delayed_work); |
| 1725 } | 2003 } |
| 1726 | 2004 |
| 1727 snd_soc_dapm_shutdown(card); | 2005 snd_soc_dapm_shutdown(card); |
| 1728 | 2006 |
| 1729 return 0; | 2007 return 0; |
| 1730 } | 2008 } |
| 2009 EXPORT_SYMBOL_GPL(snd_soc_poweroff); |
| 1731 | 2010 |
| 1732 static const struct dev_pm_ops soc_pm_ops = { | 2011 const struct dev_pm_ops snd_soc_pm_ops = { |
| 1733 » .suspend = soc_suspend, | 2012 » .suspend = snd_soc_suspend, |
| 1734 » .resume = soc_resume, | 2013 » .resume = snd_soc_resume, |
| 1735 » .poweroff = soc_poweroff, | 2014 » .poweroff = snd_soc_poweroff, |
| 1736 }; | 2015 }; |
| 1737 | 2016 |
| 1738 /* ASoC platform driver */ | 2017 /* ASoC platform driver */ |
| 1739 static struct platform_driver soc_driver = { | 2018 static struct platform_driver soc_driver = { |
| 1740 .driver = { | 2019 .driver = { |
| 1741 .name = "soc-audio", | 2020 .name = "soc-audio", |
| 1742 .owner = THIS_MODULE, | 2021 .owner = THIS_MODULE, |
| 1743 » » .pm» » = &soc_pm_ops, | 2022 » » .pm» » = &snd_soc_pm_ops, |
| 1744 }, | 2023 }, |
| 1745 .probe = soc_probe, | 2024 .probe = soc_probe, |
| 1746 .remove = soc_remove, | 2025 .remove = soc_remove, |
| 1747 }; | 2026 }; |
| 1748 | 2027 |
| 1749 /* create a new pcm */ | 2028 /* create a new pcm */ |
| 1750 static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | 2029 static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
| 1751 { | 2030 { |
| 1752 struct snd_soc_codec *codec = rtd->codec; | 2031 struct snd_soc_codec *codec = rtd->codec; |
| 1753 struct snd_soc_platform *platform = rtd->platform; | 2032 struct snd_soc_platform *platform = rtd->platform; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1803 } | 2082 } |
| 1804 | 2083 |
| 1805 /** | 2084 /** |
| 1806 * snd_soc_codec_volatile_register: Report if a register is volatile. | 2085 * snd_soc_codec_volatile_register: Report if a register is volatile. |
| 1807 * | 2086 * |
| 1808 * @codec: CODEC to query. | 2087 * @codec: CODEC to query. |
| 1809 * @reg: Register to query. | 2088 * @reg: Register to query. |
| 1810 * | 2089 * |
| 1811 * Boolean function indiciating if a CODEC register is volatile. | 2090 * Boolean function indiciating if a CODEC register is volatile. |
| 1812 */ | 2091 */ |
| 1813 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) | 2092 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, |
| 2093 » » » » unsigned int reg) |
| 1814 { | 2094 { |
| 1815 » if (codec->driver->volatile_register) | 2095 » if (codec->volatile_register) |
| 1816 » » return codec->driver->volatile_register(reg); | 2096 » » return codec->volatile_register(codec, reg); |
| 1817 else | 2097 else |
| 1818 return 0; | 2098 return 0; |
| 1819 } | 2099 } |
| 1820 EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); | 2100 EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); |
| 1821 | 2101 |
| 1822 /** | 2102 /** |
| 1823 * snd_soc_new_ac97_codec - initailise AC97 device | 2103 * snd_soc_new_ac97_codec - initailise AC97 device |
| 1824 * @codec: audio codec | 2104 * @codec: audio codec |
| 1825 * @ops: AC97 bus operations | 2105 * @ops: AC97 bus operations |
| 1826 * @num: AC97 codec number | 2106 * @num: AC97 codec number |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1873 soc_unregister_ac97_dai_link(codec); | 2153 soc_unregister_ac97_dai_link(codec); |
| 1874 #endif | 2154 #endif |
| 1875 kfree(codec->ac97->bus); | 2155 kfree(codec->ac97->bus); |
| 1876 kfree(codec->ac97); | 2156 kfree(codec->ac97); |
| 1877 codec->ac97 = NULL; | 2157 codec->ac97 = NULL; |
| 1878 codec->ac97_created = 0; | 2158 codec->ac97_created = 0; |
| 1879 mutex_unlock(&codec->mutex); | 2159 mutex_unlock(&codec->mutex); |
| 1880 } | 2160 } |
| 1881 EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | 2161 EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); |
| 1882 | 2162 |
| 2163 unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) |
| 2164 { |
| 2165 unsigned int ret; |
| 2166 |
| 2167 ret = codec->read(codec, reg); |
| 2168 dev_dbg(codec->dev, "read %x => %x\n", reg, ret); |
| 2169 trace_snd_soc_reg_read(codec, reg, ret); |
| 2170 |
| 2171 return ret; |
| 2172 } |
| 2173 EXPORT_SYMBOL_GPL(snd_soc_read); |
| 2174 |
| 2175 unsigned int snd_soc_write(struct snd_soc_codec *codec, |
| 2176 unsigned int reg, unsigned int val) |
| 2177 { |
| 2178 dev_dbg(codec->dev, "write %x = %x\n", reg, val); |
| 2179 trace_snd_soc_reg_write(codec, reg, val); |
| 2180 return codec->write(codec, reg, val); |
| 2181 } |
| 2182 EXPORT_SYMBOL_GPL(snd_soc_write); |
| 2183 |
| 1883 /** | 2184 /** |
| 1884 * snd_soc_update_bits - update codec register bits | 2185 * snd_soc_update_bits - update codec register bits |
| 1885 * @codec: audio codec | 2186 * @codec: audio codec |
| 1886 * @reg: codec register | 2187 * @reg: codec register |
| 1887 * @mask: register mask | 2188 * @mask: register mask |
| 1888 * @value: new value | 2189 * @value: new value |
| 1889 * | 2190 * |
| 1890 * Writes new register value. | 2191 * Writes new register value. |
| 1891 * | 2192 * |
| 1892 * Returns 1 for change else 0. | 2193 * Returns 1 for change, 0 for no change, or negative error code. |
| 1893 */ | 2194 */ |
| 1894 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, | 2195 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, |
| 1895 unsigned int mask, unsigned int value) | 2196 unsigned int mask, unsigned int value) |
| 1896 { | 2197 { |
| 1897 int change; | 2198 int change; |
| 1898 unsigned int old, new; | 2199 unsigned int old, new; |
| 2200 int ret; |
| 1899 | 2201 |
| 1900 » old = snd_soc_read(codec, reg); | 2202 » ret = snd_soc_read(codec, reg); |
| 2203 » if (ret < 0) |
| 2204 » » return ret; |
| 2205 |
| 2206 » old = ret; |
| 1901 new = (old & ~mask) | value; | 2207 new = (old & ~mask) | value; |
| 1902 change = old != new; | 2208 change = old != new; |
| 1903 » if (change) | 2209 » if (change) { |
| 1904 » » snd_soc_write(codec, reg, new); | 2210 » » ret = snd_soc_write(codec, reg, new); |
| 2211 » » if (ret < 0) |
| 2212 » » » return ret; |
| 2213 » } |
| 1905 | 2214 |
| 1906 return change; | 2215 return change; |
| 1907 } | 2216 } |
| 1908 EXPORT_SYMBOL_GPL(snd_soc_update_bits); | 2217 EXPORT_SYMBOL_GPL(snd_soc_update_bits); |
| 1909 | 2218 |
| 1910 /** | 2219 /** |
| 1911 * snd_soc_update_bits_locked - update codec register bits | 2220 * snd_soc_update_bits_locked - update codec register bits |
| 1912 * @codec: audio codec | 2221 * @codec: audio codec |
| 1913 * @reg: codec register | 2222 * @reg: codec register |
| 1914 * @mask: register mask | 2223 * @mask: register mask |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 * @codec: codec to add controls to | 2322 * @codec: codec to add controls to |
| 2014 * @controls: array of controls to add | 2323 * @controls: array of controls to add |
| 2015 * @num_controls: number of elements in the array | 2324 * @num_controls: number of elements in the array |
| 2016 * | 2325 * |
| 2017 * Return 0 for success, else error. | 2326 * Return 0 for success, else error. |
| 2018 */ | 2327 */ |
| 2019 int snd_soc_add_controls(struct snd_soc_codec *codec, | 2328 int snd_soc_add_controls(struct snd_soc_codec *codec, |
| 2020 const struct snd_kcontrol_new *controls, int num_controls) | 2329 const struct snd_kcontrol_new *controls, int num_controls) |
| 2021 { | 2330 { |
| 2022 struct snd_card *card = codec->card->snd_card; | 2331 struct snd_card *card = codec->card->snd_card; |
| 2332 char prefixed_name[44], *name; |
| 2023 int err, i; | 2333 int err, i; |
| 2024 | 2334 |
| 2025 for (i = 0; i < num_controls; i++) { | 2335 for (i = 0; i < num_controls; i++) { |
| 2026 const struct snd_kcontrol_new *control = &controls[i]; | 2336 const struct snd_kcontrol_new *control = &controls[i]; |
| 2027 » » err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); | 2337 » » if (codec->name_prefix) { |
| 2338 » » » snprintf(prefixed_name, sizeof(prefixed_name), "%s %s", |
| 2339 » » » » codec->name_prefix, control->name); |
| 2340 » » » name = prefixed_name; |
| 2341 » » } else { |
| 2342 » » » name = control->name; |
| 2343 » » } |
| 2344 » » err = snd_ctl_add(card, snd_soc_cnew(control, codec, name)); |
| 2028 if (err < 0) { | 2345 if (err < 0) { |
| 2029 dev_err(codec->dev, "%s: Failed to add %s: %d\n", | 2346 dev_err(codec->dev, "%s: Failed to add %s: %d\n", |
| 2030 » » » » codec->name, control->name, err); | 2347 » » » » codec->name, name, err); |
| 2031 return err; | 2348 return err; |
| 2032 } | 2349 } |
| 2033 } | 2350 } |
| 2034 | 2351 |
| 2035 return 0; | 2352 return 0; |
| 2036 } | 2353 } |
| 2037 EXPORT_SYMBOL_GPL(snd_soc_add_controls); | 2354 EXPORT_SYMBOL_GPL(snd_soc_add_controls); |
| 2038 | 2355 |
| 2039 /** | 2356 /** |
| 2040 * snd_soc_info_enum_double - enumerated double mixer info callback | 2357 * snd_soc_info_enum_double - enumerated double mixer info callback |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2846 else | 3163 else |
| 2847 return -EINVAL; | 3164 return -EINVAL; |
| 2848 } | 3165 } |
| 2849 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 3166 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
| 2850 | 3167 |
| 2851 /** | 3168 /** |
| 2852 * snd_soc_register_card - Register a card with the ASoC core | 3169 * snd_soc_register_card - Register a card with the ASoC core |
| 2853 * | 3170 * |
| 2854 * @card: Card to register | 3171 * @card: Card to register |
| 2855 * | 3172 * |
| 2856 * Note that currently this is an internal only function: it will be | |
| 2857 * exposed to machine drivers after further backporting of ASoC v2 | |
| 2858 * registration APIs. | |
| 2859 */ | 3173 */ |
| 2860 static int snd_soc_register_card(struct snd_soc_card *card) | 3174 int snd_soc_register_card(struct snd_soc_card *card) |
| 2861 { | 3175 { |
| 2862 int i; | 3176 int i; |
| 2863 | 3177 |
| 2864 if (!card->name || !card->dev) | 3178 if (!card->name || !card->dev) |
| 2865 return -EINVAL; | 3179 return -EINVAL; |
| 2866 | 3180 |
| 2867 » card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links
, | 3181 » snd_soc_initialize_card_lists(card); |
| 2868 » » » GFP_KERNEL); | 3182 |
| 3183 » soc_init_card_debugfs(card); |
| 3184 |
| 3185 » card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * |
| 3186 » » » (card->num_links + card->num_aux_devs), |
| 3187 » » » GFP_KERNEL); |
| 2869 if (card->rtd == NULL) | 3188 if (card->rtd == NULL) |
| 2870 return -ENOMEM; | 3189 return -ENOMEM; |
| 3190 card->rtd_aux = &card->rtd[card->num_links]; |
| 2871 | 3191 |
| 2872 for (i = 0; i < card->num_links; i++) | 3192 for (i = 0; i < card->num_links; i++) |
| 2873 card->rtd[i].dai_link = &card->dai_link[i]; | 3193 card->rtd[i].dai_link = &card->dai_link[i]; |
| 2874 | 3194 |
| 2875 INIT_LIST_HEAD(&card->list); | 3195 INIT_LIST_HEAD(&card->list); |
| 2876 card->instantiated = 0; | 3196 card->instantiated = 0; |
| 2877 mutex_init(&card->mutex); | 3197 mutex_init(&card->mutex); |
| 2878 | 3198 |
| 2879 mutex_lock(&client_mutex); | 3199 mutex_lock(&client_mutex); |
| 2880 list_add(&card->list, &card_list); | 3200 list_add(&card->list, &card_list); |
| 2881 snd_soc_instantiate_cards(); | 3201 snd_soc_instantiate_cards(); |
| 2882 mutex_unlock(&client_mutex); | 3202 mutex_unlock(&client_mutex); |
| 2883 | 3203 |
| 2884 dev_dbg(card->dev, "Registered card '%s'\n", card->name); | 3204 dev_dbg(card->dev, "Registered card '%s'\n", card->name); |
| 2885 | 3205 |
| 2886 return 0; | 3206 return 0; |
| 2887 } | 3207 } |
| 3208 EXPORT_SYMBOL_GPL(snd_soc_register_card); |
| 2888 | 3209 |
| 2889 /** | 3210 /** |
| 2890 * snd_soc_unregister_card - Unregister a card with the ASoC core | 3211 * snd_soc_unregister_card - Unregister a card with the ASoC core |
| 2891 * | 3212 * |
| 2892 * @card: Card to unregister | 3213 * @card: Card to unregister |
| 2893 * | 3214 * |
| 2894 * Note that currently this is an internal only function: it will be | |
| 2895 * exposed to machine drivers after further backporting of ASoC v2 | |
| 2896 * registration APIs. | |
| 2897 */ | 3215 */ |
| 2898 static int snd_soc_unregister_card(struct snd_soc_card *card) | 3216 int snd_soc_unregister_card(struct snd_soc_card *card) |
| 2899 { | 3217 { |
| 3218 if (card->instantiated) |
| 3219 soc_cleanup_card_resources(card); |
| 2900 mutex_lock(&client_mutex); | 3220 mutex_lock(&client_mutex); |
| 2901 list_del(&card->list); | 3221 list_del(&card->list); |
| 2902 mutex_unlock(&client_mutex); | 3222 mutex_unlock(&client_mutex); |
| 2903 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); | 3223 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); |
| 2904 | 3224 |
| 2905 return 0; | 3225 return 0; |
| 2906 } | 3226 } |
| 3227 EXPORT_SYMBOL_GPL(snd_soc_unregister_card); |
| 2907 | 3228 |
| 2908 /* | 3229 /* |
| 2909 * Simplify DAI link configuration by removing ".-1" from device names | 3230 * Simplify DAI link configuration by removing ".-1" from device names |
| 2910 * and sanitizing names. | 3231 * and sanitizing names. |
| 2911 */ | 3232 */ |
| 2912 static inline char *fmt_single_name(struct device *dev, int *id) | 3233 static char *fmt_single_name(struct device *dev, int *id) |
| 2913 { | 3234 { |
| 2914 char *found, name[NAME_SIZE]; | 3235 char *found, name[NAME_SIZE]; |
| 2915 int id1, id2; | 3236 int id1, id2; |
| 2916 | 3237 |
| 2917 if (dev_name(dev) == NULL) | 3238 if (dev_name(dev) == NULL) |
| 2918 return NULL; | 3239 return NULL; |
| 2919 | 3240 |
| 2920 » strncpy(name, dev_name(dev), NAME_SIZE); | 3241 » strlcpy(name, dev_name(dev), NAME_SIZE); |
| 2921 | 3242 |
| 2922 /* are we a "%s.%d" name (platform and SPI components) */ | 3243 /* are we a "%s.%d" name (platform and SPI components) */ |
| 2923 found = strstr(name, dev->driver->name); | 3244 found = strstr(name, dev->driver->name); |
| 2924 if (found) { | 3245 if (found) { |
| 2925 /* get ID */ | 3246 /* get ID */ |
| 2926 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) { | 3247 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) { |
| 2927 | 3248 |
| 2928 /* discard ID from name if ID == -1 */ | 3249 /* discard ID from name if ID == -1 */ |
| 2929 if (*id == -1) | 3250 if (*id == -1) |
| 2930 found[strlen(dev->driver->name)] = '\0'; | 3251 found[strlen(dev->driver->name)] = '\0'; |
| 2931 } | 3252 } |
| 2932 | 3253 |
| 2933 } else { | 3254 } else { |
| 2934 /* I2C component devices are named "bus-addr" */ | 3255 /* I2C component devices are named "bus-addr" */ |
| 2935 if (sscanf(name, "%x-%x", &id1, &id2) == 2) { | 3256 if (sscanf(name, "%x-%x", &id1, &id2) == 2) { |
| 2936 char tmp[NAME_SIZE]; | 3257 char tmp[NAME_SIZE]; |
| 2937 | 3258 |
| 2938 /* create unique ID number from I2C addr and bus */ | 3259 /* create unique ID number from I2C addr and bus */ |
| 2939 *id = ((id1 & 0xffff) << 16) + id2; | 3260 *id = ((id1 & 0xffff) << 16) + id2; |
| 2940 | 3261 |
| 2941 /* sanitize component name for DAI link creation */ | 3262 /* sanitize component name for DAI link creation */ |
| 2942 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, nam
e); | 3263 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, nam
e); |
| 2943 » » » strncpy(name, tmp, NAME_SIZE); | 3264 » » » strlcpy(name, tmp, NAME_SIZE); |
| 2944 } else | 3265 } else |
| 2945 *id = 0; | 3266 *id = 0; |
| 2946 } | 3267 } |
| 2947 | 3268 |
| 2948 return kstrdup(name, GFP_KERNEL); | 3269 return kstrdup(name, GFP_KERNEL); |
| 2949 } | 3270 } |
| 2950 | 3271 |
| 2951 /* | 3272 /* |
| 2952 * Simplify DAI link naming for single devices with multiple DAIs by removing | 3273 * Simplify DAI link naming for single devices with multiple DAIs by removing |
| 2953 * any ".-1" and using the DAI name (instead of device name). | 3274 * any ".-1" and using the DAI name (instead of device name). |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3198 if (stream->formats & codec_format_map[i]) | 3519 if (stream->formats & codec_format_map[i]) |
| 3199 stream->formats |= codec_format_map[i]; | 3520 stream->formats |= codec_format_map[i]; |
| 3200 } | 3521 } |
| 3201 | 3522 |
| 3202 /** | 3523 /** |
| 3203 * snd_soc_register_codec - Register a codec with the ASoC core | 3524 * snd_soc_register_codec - Register a codec with the ASoC core |
| 3204 * | 3525 * |
| 3205 * @codec: codec to register | 3526 * @codec: codec to register |
| 3206 */ | 3527 */ |
| 3207 int snd_soc_register_codec(struct device *dev, | 3528 int snd_soc_register_codec(struct device *dev, |
| 3208 » » struct snd_soc_codec_driver *codec_drv, | 3529 » » » const struct snd_soc_codec_driver *codec_drv, |
| 3209 » » struct snd_soc_dai_driver *dai_drv, int num_dai) | 3530 » » » struct snd_soc_dai_driver *dai_drv, |
| 3531 » » » int num_dai) |
| 3210 { | 3532 { |
| 3533 size_t reg_size; |
| 3211 struct snd_soc_codec *codec; | 3534 struct snd_soc_codec *codec; |
| 3212 int ret, i; | 3535 int ret, i; |
| 3213 | 3536 |
| 3214 dev_dbg(dev, "codec register %s\n", dev_name(dev)); | 3537 dev_dbg(dev, "codec register %s\n", dev_name(dev)); |
| 3215 | 3538 |
| 3216 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 3539 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
| 3217 if (codec == NULL) | 3540 if (codec == NULL) |
| 3218 return -ENOMEM; | 3541 return -ENOMEM; |
| 3219 | 3542 |
| 3220 /* create CODEC component name */ | 3543 /* create CODEC component name */ |
| 3221 codec->name = fmt_single_name(dev, &codec->id); | 3544 codec->name = fmt_single_name(dev, &codec->id); |
| 3222 if (codec->name == NULL) { | 3545 if (codec->name == NULL) { |
| 3223 kfree(codec); | 3546 kfree(codec); |
| 3224 return -ENOMEM; | 3547 return -ENOMEM; |
| 3225 } | 3548 } |
| 3226 | 3549 |
| 3550 if (codec_drv->compress_type) |
| 3551 codec->compress_type = codec_drv->compress_type; |
| 3552 else |
| 3553 codec->compress_type = SND_SOC_FLAT_COMPRESSION; |
| 3554 |
| 3555 codec->write = codec_drv->write; |
| 3556 codec->read = codec_drv->read; |
| 3557 codec->volatile_register = codec_drv->volatile_register; |
| 3558 codec->readable_register = codec_drv->readable_register; |
| 3559 codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
| 3560 codec->dapm.dev = dev; |
| 3561 codec->dapm.codec = codec; |
| 3562 codec->dapm.seq_notifier = codec_drv->seq_notifier; |
| 3563 codec->dev = dev; |
| 3564 codec->driver = codec_drv; |
| 3565 codec->num_dai = num_dai; |
| 3566 mutex_init(&codec->mutex); |
| 3567 |
| 3227 /* allocate CODEC register cache */ | 3568 /* allocate CODEC register cache */ |
| 3228 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { | 3569 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { |
| 3229 | 3570 » » reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; |
| 3230 » » if (codec_drv->reg_cache_default) | 3571 » » codec->reg_size = reg_size; |
| 3231 » » » codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | 3572 » » /* it is necessary to make a copy of the default register cache |
| 3232 » » » » codec_drv->reg_cache_size * codec_drv->reg_word_
size, GFP_KERNEL); | 3573 » » * because in the case of using a compression type that requires |
| 3233 » » else | 3574 » » * the default register cache to be marked as __devinitconst the |
| 3234 » » » codec->reg_cache = kzalloc(codec_drv->reg_cache_size * | 3575 » » * kernel might have freed the array by the time we initialize |
| 3235 » » » » codec_drv->reg_word_size, GFP_KERNEL); | 3576 » » * the cache. |
| 3236 | 3577 » » */ |
| 3237 » » if (codec->reg_cache == NULL) { | 3578 » » if (codec_drv->reg_cache_default) { |
| 3238 » » » kfree(codec->name); | 3579 » » » codec->reg_def_copy = kmemdup(codec_drv->reg_cache_defau
lt, |
| 3239 » » » kfree(codec); | 3580 » » » » » » reg_size, GFP_KERNEL); |
| 3240 » » » return -ENOMEM; | 3581 » » » if (!codec->reg_def_copy) { |
| 3582 » » » » ret = -ENOMEM; |
| 3583 » » » » goto fail; |
| 3584 » » » } |
| 3241 } | 3585 } |
| 3242 } | 3586 } |
| 3243 | 3587 |
| 3244 » codec->dev = dev; | 3588 » if (codec_drv->reg_access_size && codec_drv->reg_access_default) { |
| 3245 » codec->driver = codec_drv; | 3589 » » if (!codec->volatile_register) |
| 3246 » codec->bias_level = SND_SOC_BIAS_OFF; | 3590 » » » codec->volatile_register = snd_soc_default_volatile_regi
ster; |
| 3247 » codec->num_dai = num_dai; | 3591 » » if (!codec->readable_register) |
| 3248 » mutex_init(&codec->mutex); | 3592 » » » codec->readable_register = snd_soc_default_readable_regi
ster; |
| 3249 » INIT_LIST_HEAD(&codec->dapm_widgets); | 3593 » } |
| 3250 » INIT_LIST_HEAD(&codec->dapm_paths); | |
| 3251 | 3594 |
| 3252 for (i = 0; i < num_dai; i++) { | 3595 for (i = 0; i < num_dai; i++) { |
| 3253 fixup_codec_formats(&dai_drv[i].playback); | 3596 fixup_codec_formats(&dai_drv[i].playback); |
| 3254 fixup_codec_formats(&dai_drv[i].capture); | 3597 fixup_codec_formats(&dai_drv[i].capture); |
| 3255 } | 3598 } |
| 3256 | 3599 |
| 3257 /* register any DAIs */ | 3600 /* register any DAIs */ |
| 3258 if (num_dai) { | 3601 if (num_dai) { |
| 3259 ret = snd_soc_register_dais(dev, dai_drv, num_dai); | 3602 ret = snd_soc_register_dais(dev, dai_drv, num_dai); |
| 3260 if (ret < 0) | 3603 if (ret < 0) |
| 3261 » » » goto error; | 3604 » » » goto fail; |
| 3262 } | 3605 } |
| 3263 | 3606 |
| 3264 mutex_lock(&client_mutex); | 3607 mutex_lock(&client_mutex); |
| 3265 list_add(&codec->list, &codec_list); | 3608 list_add(&codec->list, &codec_list); |
| 3266 snd_soc_instantiate_cards(); | 3609 snd_soc_instantiate_cards(); |
| 3267 mutex_unlock(&client_mutex); | 3610 mutex_unlock(&client_mutex); |
| 3268 | 3611 |
| 3269 pr_debug("Registered codec '%s'\n", codec->name); | 3612 pr_debug("Registered codec '%s'\n", codec->name); |
| 3270 return 0; | 3613 return 0; |
| 3271 | 3614 |
| 3272 error: | 3615 fail: |
| 3273 » if (codec->reg_cache) | 3616 » kfree(codec->reg_def_copy); |
| 3274 » » kfree(codec->reg_cache); | 3617 » codec->reg_def_copy = NULL; |
| 3275 kfree(codec->name); | 3618 kfree(codec->name); |
| 3276 kfree(codec); | 3619 kfree(codec); |
| 3277 return ret; | 3620 return ret; |
| 3278 } | 3621 } |
| 3279 EXPORT_SYMBOL_GPL(snd_soc_register_codec); | 3622 EXPORT_SYMBOL_GPL(snd_soc_register_codec); |
| 3280 | 3623 |
| 3281 /** | 3624 /** |
| 3282 * snd_soc_unregister_codec - Unregister a codec from the ASoC core | 3625 * snd_soc_unregister_codec - Unregister a codec from the ASoC core |
| 3283 * | 3626 * |
| 3284 * @codec: codec to unregister | 3627 * @codec: codec to unregister |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3298 if (codec->num_dai) | 3641 if (codec->num_dai) |
| 3299 for (i = 0; i < codec->num_dai; i++) | 3642 for (i = 0; i < codec->num_dai; i++) |
| 3300 snd_soc_unregister_dai(dev); | 3643 snd_soc_unregister_dai(dev); |
| 3301 | 3644 |
| 3302 mutex_lock(&client_mutex); | 3645 mutex_lock(&client_mutex); |
| 3303 list_del(&codec->list); | 3646 list_del(&codec->list); |
| 3304 mutex_unlock(&client_mutex); | 3647 mutex_unlock(&client_mutex); |
| 3305 | 3648 |
| 3306 pr_debug("Unregistered codec '%s'\n", codec->name); | 3649 pr_debug("Unregistered codec '%s'\n", codec->name); |
| 3307 | 3650 |
| 3308 » if (codec->reg_cache) | 3651 » snd_soc_cache_exit(codec); |
| 3309 » » kfree(codec->reg_cache); | 3652 » kfree(codec->reg_def_copy); |
| 3310 kfree(codec->name); | 3653 kfree(codec->name); |
| 3311 kfree(codec); | 3654 kfree(codec); |
| 3312 } | 3655 } |
| 3313 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 3656 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
| 3314 | 3657 |
| 3315 static int __init snd_soc_init(void) | 3658 static int __init snd_soc_init(void) |
| 3316 { | 3659 { |
| 3317 #ifdef CONFIG_DEBUG_FS | 3660 #ifdef CONFIG_DEBUG_FS |
| 3318 » asoc_debugfs_root = debugfs_create_dir("asoc", NULL); | 3661 » snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); |
| 3319 » if (IS_ERR(asoc_debugfs_root) || !asoc_debugfs_root) { | 3662 » if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) { |
| 3320 printk(KERN_WARNING | 3663 printk(KERN_WARNING |
| 3321 "ASoC: Failed to create debugfs directory\n"); | 3664 "ASoC: Failed to create debugfs directory\n"); |
| 3322 » » asoc_debugfs_root = NULL; | 3665 » » snd_soc_debugfs_root = NULL; |
| 3323 } | 3666 } |
| 3324 | 3667 |
| 3325 » if (!debugfs_create_file("codecs", 0444, asoc_debugfs_root, NULL, | 3668 » if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL, |
| 3326 &codec_list_fops)) | 3669 &codec_list_fops)) |
| 3327 pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); | 3670 pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); |
| 3328 | 3671 |
| 3329 » if (!debugfs_create_file("dais", 0444, asoc_debugfs_root, NULL, | 3672 » if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, |
| 3330 &dai_list_fops)) | 3673 &dai_list_fops)) |
| 3331 pr_warn("ASoC: Failed to create DAI list debugfs file\n"); | 3674 pr_warn("ASoC: Failed to create DAI list debugfs file\n"); |
| 3332 | 3675 |
| 3333 » if (!debugfs_create_file("platforms", 0444, asoc_debugfs_root, NULL, | 3676 » if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL, |
| 3334 &platform_list_fops)) | 3677 &platform_list_fops)) |
| 3335 pr_warn("ASoC: Failed to create platform list debugfs file\n"); | 3678 pr_warn("ASoC: Failed to create platform list debugfs file\n"); |
| 3336 #endif | 3679 #endif |
| 3337 | 3680 |
| 3338 return platform_driver_register(&soc_driver); | 3681 return platform_driver_register(&soc_driver); |
| 3339 } | 3682 } |
| 3340 module_init(snd_soc_init); | 3683 module_init(snd_soc_init); |
| 3341 | 3684 |
| 3342 static void __exit snd_soc_exit(void) | 3685 static void __exit snd_soc_exit(void) |
| 3343 { | 3686 { |
| 3344 #ifdef CONFIG_DEBUG_FS | 3687 #ifdef CONFIG_DEBUG_FS |
| 3345 » debugfs_remove_recursive(asoc_debugfs_root); | 3688 » debugfs_remove_recursive(snd_soc_debugfs_root); |
| 3346 #endif | 3689 #endif |
| 3347 platform_driver_unregister(&soc_driver); | 3690 platform_driver_unregister(&soc_driver); |
| 3348 } | 3691 } |
| 3349 module_exit(snd_soc_exit); | 3692 module_exit(snd_soc_exit); |
| 3350 | 3693 |
| 3351 /* Module information */ | 3694 /* Module information */ |
| 3352 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); | 3695 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); |
| 3353 MODULE_DESCRIPTION("ALSA SoC Core"); | 3696 MODULE_DESCRIPTION("ALSA SoC Core"); |
| 3354 MODULE_LICENSE("GPL"); | 3697 MODULE_LICENSE("GPL"); |
| 3355 MODULE_ALIAS("platform:soc-audio"); | 3698 MODULE_ALIAS("platform:soc-audio"); |
| OLD | NEW |