diff options
Diffstat (limited to 'sound')
382 files changed, 15924 insertions, 6716 deletions
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 7487eb76e034..3edf736319fe 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c | |||
@@ -150,6 +150,8 @@ static int soundbus_device_resume(struct device * dev) | |||
150 | 150 | ||
151 | #endif /* CONFIG_PM */ | 151 | #endif /* CONFIG_PM */ |
152 | 152 | ||
153 | /* soundbus_dev_attrs is declared in sysfs.c */ | ||
154 | ATTRIBUTE_GROUPS(soundbus_dev); | ||
153 | static struct bus_type soundbus_bus_type = { | 155 | static struct bus_type soundbus_bus_type = { |
154 | .name = "aoa-soundbus", | 156 | .name = "aoa-soundbus", |
155 | .probe = soundbus_probe, | 157 | .probe = soundbus_probe, |
@@ -160,7 +162,7 @@ static struct bus_type soundbus_bus_type = { | |||
160 | .suspend = soundbus_device_suspend, | 162 | .suspend = soundbus_device_suspend, |
161 | .resume = soundbus_device_resume, | 163 | .resume = soundbus_device_resume, |
162 | #endif | 164 | #endif |
163 | .dev_attrs = soundbus_dev_attrs, | 165 | .dev_groups = soundbus_dev_groups, |
164 | }; | 166 | }; |
165 | 167 | ||
166 | int soundbus_add_one(struct soundbus_dev *dev) | 168 | int soundbus_add_one(struct soundbus_dev *dev) |
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index adecbf36f4f6..21e756cf2824 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h | |||
@@ -199,6 +199,6 @@ struct soundbus_driver { | |||
199 | extern int soundbus_register_driver(struct soundbus_driver *drv); | 199 | extern int soundbus_register_driver(struct soundbus_driver *drv); |
200 | extern void soundbus_unregister_driver(struct soundbus_driver *drv); | 200 | extern void soundbus_unregister_driver(struct soundbus_driver *drv); |
201 | 201 | ||
202 | extern struct device_attribute soundbus_dev_attrs[]; | 202 | extern struct attribute *soundbus_dev_attrs[]; |
203 | 203 | ||
204 | #endif /* __SOUNDBUS_H */ | 204 | #endif /* __SOUNDBUS_H */ |
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c index e0980b5c2cd8..5b2d51d99768 100644 --- a/sound/aoa/soundbus/sysfs.c +++ b/sound/aoa/soundbus/sysfs.c | |||
@@ -30,13 +30,16 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
30 | 30 | ||
31 | return length; | 31 | return length; |
32 | } | 32 | } |
33 | static DEVICE_ATTR_RO(modalias); | ||
33 | 34 | ||
34 | soundbus_config_of_attr (name, "%s\n"); | 35 | soundbus_config_of_attr (name, "%s\n"); |
36 | static DEVICE_ATTR_RO(name); | ||
35 | soundbus_config_of_attr (type, "%s\n"); | 37 | soundbus_config_of_attr (type, "%s\n"); |
38 | static DEVICE_ATTR_RO(type); | ||
36 | 39 | ||
37 | struct device_attribute soundbus_dev_attrs[] = { | 40 | struct attribute *soundbus_dev_attrs[] = { |
38 | __ATTR_RO(name), | 41 | &dev_attr_name.attr, |
39 | __ATTR_RO(type), | 42 | &dev_attr_type.attr, |
40 | __ATTR_RO(modalias), | 43 | &dev_attr_modalias.attr, |
41 | __ATTR_NULL | 44 | NULL, |
42 | }; | 45 | }; |
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index cf4cedf2b420..6dad042630d8 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -916,7 +916,6 @@ static struct ac97c_platform_data *atmel_ac97c_probe_dt(struct device *dev) | |||
916 | { | 916 | { |
917 | struct ac97c_platform_data *pdata; | 917 | struct ac97c_platform_data *pdata; |
918 | struct device_node *node = dev->of_node; | 918 | struct device_node *node = dev->of_node; |
919 | const struct of_device_id *match; | ||
920 | 919 | ||
921 | if (!node) { | 920 | if (!node) { |
922 | dev_err(dev, "Device does not have associated DT data\n"); | 921 | dev_err(dev, "Device does not have associated DT data\n"); |
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 313f22e9d929..6c96feeaf01e 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -6,6 +6,12 @@ config SND_PCM | |||
6 | tristate | 6 | tristate |
7 | select SND_TIMER | 7 | select SND_TIMER |
8 | 8 | ||
9 | config SND_PCM_ELD | ||
10 | bool | ||
11 | |||
12 | config SND_PCM_IEC958 | ||
13 | bool | ||
14 | |||
9 | config SND_DMAENGINE_PCM | 15 | config SND_DMAENGINE_PCM |
10 | tristate | 16 | tristate |
11 | 17 | ||
@@ -176,9 +182,18 @@ config SND_SUPPORT_OLD_API | |||
176 | Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3 | 182 | Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3 |
177 | or older). | 183 | or older). |
178 | 184 | ||
185 | config SND_PROC_FS | ||
186 | bool "Sound Proc FS Support" if EXPERT | ||
187 | depends on PROC_FS | ||
188 | default y | ||
189 | help | ||
190 | Say 'N' to disable Sound proc FS, which may reduce code size about | ||
191 | 9KB on x86_64 platform. | ||
192 | If unsure say Y. | ||
193 | |||
179 | config SND_VERBOSE_PROCFS | 194 | config SND_VERBOSE_PROCFS |
180 | bool "Verbose procfs contents" | 195 | bool "Verbose procfs contents" |
181 | depends on PROC_FS | 196 | depends on SND_PROC_FS |
182 | default y | 197 | default y |
183 | help | 198 | help |
184 | Say Y here to include code for verbose procfs contents (provides | 199 | Say Y here to include code for verbose procfs contents (provides |
@@ -221,9 +236,6 @@ config SND_PCM_XRUN_DEBUG | |||
221 | config SND_VMASTER | 236 | config SND_VMASTER |
222 | bool | 237 | bool |
223 | 238 | ||
224 | config SND_KCTL_JACK | ||
225 | bool | ||
226 | |||
227 | config SND_DMA_SGBUF | 239 | config SND_DMA_SGBUF |
228 | def_bool y | 240 | def_bool y |
229 | depends on X86 | 241 | depends on X86 |
diff --git a/sound/core/Makefile b/sound/core/Makefile index 4daf2f58261c..3354f91e003a 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile | |||
@@ -3,16 +3,21 @@ | |||
3 | # Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-y := sound.o init.o memory.o info.o control.o misc.o device.o | 6 | snd-y := sound.o init.o memory.o control.o misc.o device.o |
7 | ifneq ($(CONFIG_SND_PROC_FS),) | ||
8 | snd-y += info.o | ||
9 | snd-$(CONFIG_SND_OSSEMUL) += info_oss.o | ||
10 | endif | ||
7 | snd-$(CONFIG_ISA_DMA_API) += isadma.o | 11 | snd-$(CONFIG_ISA_DMA_API) += isadma.o |
8 | snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o | 12 | snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o |
9 | snd-$(CONFIG_SND_VMASTER) += vmaster.o | 13 | snd-$(CONFIG_SND_VMASTER) += vmaster.o |
10 | snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o | 14 | snd-$(CONFIG_SND_JACK) += ctljack.o jack.o |
11 | snd-$(CONFIG_SND_JACK) += jack.o | ||
12 | 15 | ||
13 | snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ | 16 | snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ |
14 | pcm_memory.o memalloc.o | 17 | pcm_memory.o memalloc.o |
15 | snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o | 18 | snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o |
19 | snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o | ||
20 | snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o | ||
16 | 21 | ||
17 | # for trace-points | 22 | # for trace-points |
18 | CFLAGS_pcm_lib.o := -I$(src) | 23 | CFLAGS_pcm_lib.o := -I$(src) |
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c index e4b38fbe51da..84a3cd683068 100644 --- a/sound/core/ctljack.c +++ b/sound/core/ctljack.c | |||
@@ -31,19 +31,52 @@ static struct snd_kcontrol_new jack_detect_kctl = { | |||
31 | .get = jack_detect_kctl_get, | 31 | .get = jack_detect_kctl_get, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static int get_available_index(struct snd_card *card, const char *name) | ||
35 | { | ||
36 | struct snd_ctl_elem_id sid; | ||
37 | |||
38 | memset(&sid, 0, sizeof(sid)); | ||
39 | |||
40 | sid.index = 0; | ||
41 | sid.iface = SNDRV_CTL_ELEM_IFACE_CARD; | ||
42 | strlcpy(sid.name, name, sizeof(sid.name)); | ||
43 | |||
44 | while (snd_ctl_find_id(card, &sid)) { | ||
45 | sid.index++; | ||
46 | /* reset numid; otherwise snd_ctl_find_id() hits this again */ | ||
47 | sid.numid = 0; | ||
48 | } | ||
49 | |||
50 | return sid.index; | ||
51 | } | ||
52 | |||
53 | static void jack_kctl_name_gen(char *name, const char *src_name, int size) | ||
54 | { | ||
55 | size_t count = strlen(src_name); | ||
56 | bool need_cat = true; | ||
57 | |||
58 | /* remove redundant " Jack" from src_name */ | ||
59 | if (count >= 5) | ||
60 | need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false; | ||
61 | |||
62 | snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name); | ||
63 | |||
64 | } | ||
65 | |||
34 | struct snd_kcontrol * | 66 | struct snd_kcontrol * |
35 | snd_kctl_jack_new(const char *name, int idx, void *private_data) | 67 | snd_kctl_jack_new(const char *name, struct snd_card *card) |
36 | { | 68 | { |
37 | struct snd_kcontrol *kctl; | 69 | struct snd_kcontrol *kctl; |
38 | kctl = snd_ctl_new1(&jack_detect_kctl, private_data); | 70 | |
71 | kctl = snd_ctl_new1(&jack_detect_kctl, NULL); | ||
39 | if (!kctl) | 72 | if (!kctl) |
40 | return NULL; | 73 | return NULL; |
41 | snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name); | 74 | |
42 | kctl->id.index = idx; | 75 | jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name)); |
76 | kctl->id.index = get_available_index(card, kctl->id.name); | ||
43 | kctl->private_value = 0; | 77 | kctl->private_value = 0; |
44 | return kctl; | 78 | return kctl; |
45 | } | 79 | } |
46 | EXPORT_SYMBOL_GPL(snd_kctl_jack_new); | ||
47 | 80 | ||
48 | void snd_kctl_jack_report(struct snd_card *card, | 81 | void snd_kctl_jack_report(struct snd_card *card, |
49 | struct snd_kcontrol *kctl, bool status) | 82 | struct snd_kcontrol *kctl, bool status) |
@@ -53,4 +86,3 @@ void snd_kctl_jack_report(struct snd_card *card, | |||
53 | kctl->private_value = status; | 86 | kctl->private_value = status; |
54 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); | 87 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); |
55 | } | 88 | } |
56 | EXPORT_SYMBOL_GPL(snd_kctl_jack_report); | ||
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 886be7da989d..f845ecf7e172 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c | |||
@@ -121,16 +121,9 @@ static struct snd_timer *mytimer; | |||
121 | static int __init snd_hrtimer_init(void) | 121 | static int __init snd_hrtimer_init(void) |
122 | { | 122 | { |
123 | struct snd_timer *timer; | 123 | struct snd_timer *timer; |
124 | struct timespec tp; | ||
125 | int err; | 124 | int err; |
126 | 125 | ||
127 | hrtimer_get_res(CLOCK_MONOTONIC, &tp); | 126 | resolution = hrtimer_resolution; |
128 | if (tp.tv_sec > 0 || !tp.tv_nsec) { | ||
129 | pr_err("snd-hrtimer: Invalid resolution %u.%09u", | ||
130 | (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | resolution = tp.tv_nsec; | ||
134 | 127 | ||
135 | /* Create a new timer and set up the fields */ | 128 | /* Create a new timer and set up the fields */ |
136 | err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER, | 129 | err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER, |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 51692c8a39ea..36d2416f90d9 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -484,7 +484,7 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) | |||
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
486 | 486 | ||
487 | #ifdef CONFIG_PROC_FS | 487 | #ifdef CONFIG_SND_PROC_FS |
488 | /* | 488 | /* |
489 | * Info interface | 489 | * Info interface |
490 | */ | 490 | */ |
@@ -521,10 +521,10 @@ static void __exit snd_hwdep_proc_done(void) | |||
521 | { | 521 | { |
522 | snd_info_free_entry(snd_hwdep_proc_entry); | 522 | snd_info_free_entry(snd_hwdep_proc_entry); |
523 | } | 523 | } |
524 | #else /* !CONFIG_PROC_FS */ | 524 | #else /* !CONFIG_SND_PROC_FS */ |
525 | #define snd_hwdep_proc_init() | 525 | #define snd_hwdep_proc_init() |
526 | #define snd_hwdep_proc_done() | 526 | #define snd_hwdep_proc_done() |
527 | #endif /* CONFIG_PROC_FS */ | 527 | #endif /* CONFIG_SND_PROC_FS */ |
528 | 528 | ||
529 | 529 | ||
530 | /* | 530 | /* |
diff --git a/sound/core/info.c b/sound/core/info.c index 9f404e965ea2..895362a696c9 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -33,12 +33,6 @@ | |||
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <stdarg.h> | 34 | #include <stdarg.h> |
35 | 35 | ||
36 | /* | ||
37 | * | ||
38 | */ | ||
39 | |||
40 | #ifdef CONFIG_PROC_FS | ||
41 | |||
42 | int snd_info_check_reserved_words(const char *str) | 36 | int snd_info_check_reserved_words(const char *str) |
43 | { | 37 | { |
44 | static char *reserved[] = | 38 | static char *reserved[] = |
@@ -78,81 +72,51 @@ struct snd_info_private_data { | |||
78 | }; | 72 | }; |
79 | 73 | ||
80 | static int snd_info_version_init(void); | 74 | static int snd_info_version_init(void); |
81 | static int snd_info_version_done(void); | ||
82 | static void snd_info_disconnect(struct snd_info_entry *entry); | 75 | static void snd_info_disconnect(struct snd_info_entry *entry); |
83 | 76 | ||
77 | /* | ||
84 | 78 | ||
85 | /* resize the proc r/w buffer */ | 79 | */ |
86 | static int resize_info_buffer(struct snd_info_buffer *buffer, | ||
87 | unsigned int nsize) | ||
88 | { | ||
89 | char *nbuf; | ||
90 | 80 | ||
91 | nsize = PAGE_ALIGN(nsize); | 81 | static struct snd_info_entry *snd_proc_root; |
92 | nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL | __GFP_ZERO); | 82 | struct snd_info_entry *snd_seq_root; |
93 | if (! nbuf) | 83 | EXPORT_SYMBOL(snd_seq_root); |
94 | return -ENOMEM; | ||
95 | 84 | ||
96 | buffer->buffer = nbuf; | 85 | #ifdef CONFIG_SND_OSSEMUL |
97 | buffer->len = nsize; | 86 | struct snd_info_entry *snd_oss_root; |
98 | return 0; | 87 | #endif |
99 | } | ||
100 | 88 | ||
101 | /** | 89 | static int alloc_info_private(struct snd_info_entry *entry, |
102 | * snd_iprintf - printf on the procfs buffer | 90 | struct snd_info_private_data **ret) |
103 | * @buffer: the procfs buffer | ||
104 | * @fmt: the printf format | ||
105 | * | ||
106 | * Outputs the string on the procfs buffer just like printf(). | ||
107 | * | ||
108 | * Return: The size of output string, or a negative error code. | ||
109 | */ | ||
110 | int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...) | ||
111 | { | 91 | { |
112 | va_list args; | 92 | struct snd_info_private_data *data; |
113 | int len, res; | ||
114 | int err = 0; | ||
115 | 93 | ||
116 | might_sleep(); | 94 | if (!entry || !entry->p) |
117 | if (buffer->stop || buffer->error) | 95 | return -ENODEV; |
118 | return 0; | 96 | if (!try_module_get(entry->module)) |
119 | len = buffer->len - buffer->size; | 97 | return -EFAULT; |
120 | va_start(args, fmt); | 98 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
121 | for (;;) { | 99 | if (!data) { |
122 | va_list ap; | 100 | module_put(entry->module); |
123 | va_copy(ap, args); | 101 | return -ENOMEM; |
124 | res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap); | ||
125 | va_end(ap); | ||
126 | if (res < len) | ||
127 | break; | ||
128 | err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); | ||
129 | if (err < 0) | ||
130 | break; | ||
131 | len = buffer->len - buffer->size; | ||
132 | } | 102 | } |
133 | va_end(args); | 103 | data->entry = entry; |
134 | 104 | *ret = data; | |
135 | if (err < 0) | 105 | return 0; |
136 | return err; | ||
137 | buffer->curr += res; | ||
138 | buffer->size += res; | ||
139 | return res; | ||
140 | } | 106 | } |
141 | 107 | ||
142 | EXPORT_SYMBOL(snd_iprintf); | 108 | static bool valid_pos(loff_t pos, size_t count) |
109 | { | ||
110 | if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) | ||
111 | return false; | ||
112 | if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) | ||
113 | return false; | ||
114 | return true; | ||
115 | } | ||
143 | 116 | ||
144 | /* | 117 | /* |
145 | 118 | * file ops for binary proc files | |
146 | */ | 119 | */ |
147 | |||
148 | static struct proc_dir_entry *snd_proc_root; | ||
149 | struct snd_info_entry *snd_seq_root; | ||
150 | EXPORT_SYMBOL(snd_seq_root); | ||
151 | |||
152 | #ifdef CONFIG_SND_OSSEMUL | ||
153 | struct snd_info_entry *snd_oss_root; | ||
154 | #endif | ||
155 | |||
156 | static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) | 120 | static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) |
157 | { | 121 | { |
158 | struct snd_info_private_data *data; | 122 | struct snd_info_private_data *data; |
@@ -162,17 +126,14 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) | |||
162 | data = file->private_data; | 126 | data = file->private_data; |
163 | entry = data->entry; | 127 | entry = data->entry; |
164 | mutex_lock(&entry->access); | 128 | mutex_lock(&entry->access); |
165 | if (entry->content == SNDRV_INFO_CONTENT_DATA && | 129 | if (entry->c.ops->llseek) { |
166 | entry->c.ops->llseek) { | ||
167 | offset = entry->c.ops->llseek(entry, | 130 | offset = entry->c.ops->llseek(entry, |
168 | data->file_private_data, | 131 | data->file_private_data, |
169 | file, offset, orig); | 132 | file, offset, orig); |
170 | goto out; | 133 | goto out; |
171 | } | 134 | } |
172 | if (entry->content == SNDRV_INFO_CONTENT_DATA) | 135 | |
173 | size = entry->size; | 136 | size = entry->size; |
174 | else | ||
175 | size = 0; | ||
176 | switch (orig) { | 137 | switch (orig) { |
177 | case SEEK_SET: | 138 | case SEEK_SET: |
178 | break; | 139 | break; |
@@ -201,45 +162,20 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) | |||
201 | static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, | 162 | static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, |
202 | size_t count, loff_t * offset) | 163 | size_t count, loff_t * offset) |
203 | { | 164 | { |
204 | struct snd_info_private_data *data; | 165 | struct snd_info_private_data *data = file->private_data; |
205 | struct snd_info_entry *entry; | 166 | struct snd_info_entry *entry = data->entry; |
206 | struct snd_info_buffer *buf; | 167 | size_t size; |
207 | size_t size = 0; | ||
208 | loff_t pos; | 168 | loff_t pos; |
209 | 169 | ||
210 | data = file->private_data; | ||
211 | if (snd_BUG_ON(!data)) | ||
212 | return -ENXIO; | ||
213 | pos = *offset; | 170 | pos = *offset; |
214 | if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) | 171 | if (!valid_pos(pos, count)) |
215 | return -EIO; | ||
216 | if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) | ||
217 | return -EIO; | 172 | return -EIO; |
218 | entry = data->entry; | 173 | if (pos >= entry->size) |
219 | switch (entry->content) { | 174 | return 0; |
220 | case SNDRV_INFO_CONTENT_TEXT: | 175 | size = entry->size - pos; |
221 | buf = data->rbuffer; | 176 | size = min(count, size); |
222 | if (buf == NULL) | 177 | size = entry->c.ops->read(entry, data->file_private_data, |
223 | return -EIO; | 178 | file, buffer, size, pos); |
224 | if (pos >= buf->size) | ||
225 | return 0; | ||
226 | size = buf->size - pos; | ||
227 | size = min(count, size); | ||
228 | if (copy_to_user(buffer, buf->buffer + pos, size)) | ||
229 | return -EFAULT; | ||
230 | break; | ||
231 | case SNDRV_INFO_CONTENT_DATA: | ||
232 | if (pos >= entry->size) | ||
233 | return 0; | ||
234 | if (entry->c.ops->read) { | ||
235 | size = entry->size - pos; | ||
236 | size = min(count, size); | ||
237 | size = entry->c.ops->read(entry, | ||
238 | data->file_private_data, | ||
239 | file, buffer, size, pos); | ||
240 | } | ||
241 | break; | ||
242 | } | ||
243 | if ((ssize_t) size > 0) | 179 | if ((ssize_t) size > 0) |
244 | *offset = pos + size; | 180 | *offset = pos + size; |
245 | return size; | 181 | return size; |
@@ -248,347 +184,319 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, | |||
248 | static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer, | 184 | static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer, |
249 | size_t count, loff_t * offset) | 185 | size_t count, loff_t * offset) |
250 | { | 186 | { |
251 | struct snd_info_private_data *data; | 187 | struct snd_info_private_data *data = file->private_data; |
252 | struct snd_info_entry *entry; | 188 | struct snd_info_entry *entry = data->entry; |
253 | struct snd_info_buffer *buf; | ||
254 | ssize_t size = 0; | 189 | ssize_t size = 0; |
255 | loff_t pos; | 190 | loff_t pos; |
256 | 191 | ||
257 | data = file->private_data; | ||
258 | if (snd_BUG_ON(!data)) | ||
259 | return -ENXIO; | ||
260 | entry = data->entry; | ||
261 | pos = *offset; | 192 | pos = *offset; |
262 | if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) | 193 | if (!valid_pos(pos, count)) |
263 | return -EIO; | ||
264 | if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) | ||
265 | return -EIO; | 194 | return -EIO; |
266 | switch (entry->content) { | 195 | if (count > 0) { |
267 | case SNDRV_INFO_CONTENT_TEXT: | 196 | size_t maxsize = entry->size - pos; |
268 | buf = data->wbuffer; | 197 | count = min(count, maxsize); |
269 | if (buf == NULL) | 198 | size = entry->c.ops->write(entry, data->file_private_data, |
270 | return -EIO; | 199 | file, buffer, count, pos); |
271 | mutex_lock(&entry->access); | ||
272 | if (pos + count >= buf->len) { | ||
273 | if (resize_info_buffer(buf, pos + count)) { | ||
274 | mutex_unlock(&entry->access); | ||
275 | return -ENOMEM; | ||
276 | } | ||
277 | } | ||
278 | if (copy_from_user(buf->buffer + pos, buffer, count)) { | ||
279 | mutex_unlock(&entry->access); | ||
280 | return -EFAULT; | ||
281 | } | ||
282 | buf->size = pos + count; | ||
283 | mutex_unlock(&entry->access); | ||
284 | size = count; | ||
285 | break; | ||
286 | case SNDRV_INFO_CONTENT_DATA: | ||
287 | if (entry->c.ops->write && count > 0) { | ||
288 | size_t maxsize = entry->size - pos; | ||
289 | count = min(count, maxsize); | ||
290 | size = entry->c.ops->write(entry, | ||
291 | data->file_private_data, | ||
292 | file, buffer, count, pos); | ||
293 | } | ||
294 | break; | ||
295 | } | 200 | } |
296 | if ((ssize_t) size > 0) | 201 | if (size > 0) |
297 | *offset = pos + size; | 202 | *offset = pos + size; |
298 | return size; | 203 | return size; |
299 | } | 204 | } |
300 | 205 | ||
301 | static int snd_info_entry_open(struct inode *inode, struct file *file) | 206 | static unsigned int snd_info_entry_poll(struct file *file, poll_table *wait) |
302 | { | 207 | { |
208 | struct snd_info_private_data *data = file->private_data; | ||
209 | struct snd_info_entry *entry = data->entry; | ||
210 | unsigned int mask = 0; | ||
211 | |||
212 | if (entry->c.ops->poll) | ||
213 | return entry->c.ops->poll(entry, | ||
214 | data->file_private_data, | ||
215 | file, wait); | ||
216 | if (entry->c.ops->read) | ||
217 | mask |= POLLIN | POLLRDNORM; | ||
218 | if (entry->c.ops->write) | ||
219 | mask |= POLLOUT | POLLWRNORM; | ||
220 | return mask; | ||
221 | } | ||
222 | |||
223 | static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, | ||
224 | unsigned long arg) | ||
225 | { | ||
226 | struct snd_info_private_data *data = file->private_data; | ||
227 | struct snd_info_entry *entry = data->entry; | ||
228 | |||
229 | if (!entry->c.ops->ioctl) | ||
230 | return -ENOTTY; | ||
231 | return entry->c.ops->ioctl(entry, data->file_private_data, | ||
232 | file, cmd, arg); | ||
233 | } | ||
234 | |||
235 | static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) | ||
236 | { | ||
237 | struct inode *inode = file_inode(file); | ||
238 | struct snd_info_private_data *data; | ||
303 | struct snd_info_entry *entry; | 239 | struct snd_info_entry *entry; |
240 | |||
241 | data = file->private_data; | ||
242 | if (data == NULL) | ||
243 | return 0; | ||
244 | entry = data->entry; | ||
245 | if (!entry->c.ops->mmap) | ||
246 | return -ENXIO; | ||
247 | return entry->c.ops->mmap(entry, data->file_private_data, | ||
248 | inode, file, vma); | ||
249 | } | ||
250 | |||
251 | static int snd_info_entry_open(struct inode *inode, struct file *file) | ||
252 | { | ||
253 | struct snd_info_entry *entry = PDE_DATA(inode); | ||
304 | struct snd_info_private_data *data; | 254 | struct snd_info_private_data *data; |
305 | struct snd_info_buffer *buffer; | ||
306 | int mode, err; | 255 | int mode, err; |
307 | 256 | ||
308 | mutex_lock(&info_mutex); | 257 | mutex_lock(&info_mutex); |
309 | entry = PDE_DATA(inode); | 258 | err = alloc_info_private(entry, &data); |
310 | if (entry == NULL || ! entry->p) { | 259 | if (err < 0) |
311 | mutex_unlock(&info_mutex); | 260 | goto unlock; |
312 | return -ENODEV; | 261 | |
313 | } | ||
314 | if (!try_module_get(entry->module)) { | ||
315 | err = -EFAULT; | ||
316 | goto __error1; | ||
317 | } | ||
318 | mode = file->f_flags & O_ACCMODE; | 262 | mode = file->f_flags & O_ACCMODE; |
319 | if (mode == O_RDONLY || mode == O_RDWR) { | 263 | if (((mode == O_RDONLY || mode == O_RDWR) && !entry->c.ops->read) || |
320 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && | 264 | ((mode == O_WRONLY || mode == O_RDWR) && !entry->c.ops->write)) { |
321 | entry->c.ops->read == NULL)) { | 265 | err = -ENODEV; |
322 | err = -ENODEV; | 266 | goto error; |
323 | goto __error; | ||
324 | } | ||
325 | } | 267 | } |
326 | if (mode == O_WRONLY || mode == O_RDWR) { | 268 | |
327 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && | 269 | if (entry->c.ops->open) { |
328 | entry->c.ops->write == NULL)) { | 270 | err = entry->c.ops->open(entry, mode, &data->file_private_data); |
329 | err = -ENODEV; | 271 | if (err < 0) |
330 | goto __error; | 272 | goto error; |
331 | } | ||
332 | } | ||
333 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
334 | if (data == NULL) { | ||
335 | err = -ENOMEM; | ||
336 | goto __error; | ||
337 | } | ||
338 | data->entry = entry; | ||
339 | switch (entry->content) { | ||
340 | case SNDRV_INFO_CONTENT_TEXT: | ||
341 | if (mode == O_RDONLY || mode == O_RDWR) { | ||
342 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | ||
343 | if (buffer == NULL) | ||
344 | goto __nomem; | ||
345 | data->rbuffer = buffer; | ||
346 | buffer->len = PAGE_SIZE; | ||
347 | buffer->buffer = kzalloc(buffer->len, GFP_KERNEL); | ||
348 | if (buffer->buffer == NULL) | ||
349 | goto __nomem; | ||
350 | } | ||
351 | if (mode == O_WRONLY || mode == O_RDWR) { | ||
352 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | ||
353 | if (buffer == NULL) | ||
354 | goto __nomem; | ||
355 | data->wbuffer = buffer; | ||
356 | buffer->len = PAGE_SIZE; | ||
357 | buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); | ||
358 | if (buffer->buffer == NULL) | ||
359 | goto __nomem; | ||
360 | } | ||
361 | break; | ||
362 | case SNDRV_INFO_CONTENT_DATA: /* data */ | ||
363 | if (entry->c.ops->open) { | ||
364 | if ((err = entry->c.ops->open(entry, mode, | ||
365 | &data->file_private_data)) < 0) { | ||
366 | kfree(data); | ||
367 | goto __error; | ||
368 | } | ||
369 | } | ||
370 | break; | ||
371 | } | 273 | } |
274 | |||
372 | file->private_data = data; | 275 | file->private_data = data; |
373 | mutex_unlock(&info_mutex); | 276 | mutex_unlock(&info_mutex); |
374 | if (entry->content == SNDRV_INFO_CONTENT_TEXT && | ||
375 | (mode == O_RDONLY || mode == O_RDWR)) { | ||
376 | if (entry->c.text.read) { | ||
377 | mutex_lock(&entry->access); | ||
378 | entry->c.text.read(entry, data->rbuffer); | ||
379 | mutex_unlock(&entry->access); | ||
380 | } | ||
381 | } | ||
382 | return 0; | 277 | return 0; |
383 | 278 | ||
384 | __nomem: | 279 | error: |
385 | if (data->rbuffer) { | ||
386 | kfree(data->rbuffer->buffer); | ||
387 | kfree(data->rbuffer); | ||
388 | } | ||
389 | if (data->wbuffer) { | ||
390 | kfree(data->wbuffer->buffer); | ||
391 | kfree(data->wbuffer); | ||
392 | } | ||
393 | kfree(data); | 280 | kfree(data); |
394 | err = -ENOMEM; | ||
395 | __error: | ||
396 | module_put(entry->module); | 281 | module_put(entry->module); |
397 | __error1: | 282 | unlock: |
398 | mutex_unlock(&info_mutex); | 283 | mutex_unlock(&info_mutex); |
399 | return err; | 284 | return err; |
400 | } | 285 | } |
401 | 286 | ||
402 | static int snd_info_entry_release(struct inode *inode, struct file *file) | 287 | static int snd_info_entry_release(struct inode *inode, struct file *file) |
403 | { | 288 | { |
404 | struct snd_info_entry *entry; | 289 | struct snd_info_private_data *data = file->private_data; |
405 | struct snd_info_private_data *data; | 290 | struct snd_info_entry *entry = data->entry; |
406 | int mode; | ||
407 | 291 | ||
408 | mode = file->f_flags & O_ACCMODE; | 292 | if (entry->c.ops->release) |
409 | data = file->private_data; | 293 | entry->c.ops->release(entry, file->f_flags & O_ACCMODE, |
410 | entry = data->entry; | 294 | data->file_private_data); |
411 | switch (entry->content) { | ||
412 | case SNDRV_INFO_CONTENT_TEXT: | ||
413 | if (data->rbuffer) { | ||
414 | kfree(data->rbuffer->buffer); | ||
415 | kfree(data->rbuffer); | ||
416 | } | ||
417 | if (data->wbuffer) { | ||
418 | if (entry->c.text.write) { | ||
419 | entry->c.text.write(entry, data->wbuffer); | ||
420 | if (data->wbuffer->error) { | ||
421 | if (entry->card) | ||
422 | dev_warn(entry->card->dev, "info: data write error to %s (%i)\n", | ||
423 | entry->name, | ||
424 | data->wbuffer->error); | ||
425 | else | ||
426 | pr_warn("ALSA: info: data write error to %s (%i)\n", | ||
427 | entry->name, | ||
428 | data->wbuffer->error); | ||
429 | } | ||
430 | } | ||
431 | kfree(data->wbuffer->buffer); | ||
432 | kfree(data->wbuffer); | ||
433 | } | ||
434 | break; | ||
435 | case SNDRV_INFO_CONTENT_DATA: | ||
436 | if (entry->c.ops->release) | ||
437 | entry->c.ops->release(entry, mode, | ||
438 | data->file_private_data); | ||
439 | break; | ||
440 | } | ||
441 | module_put(entry->module); | 295 | module_put(entry->module); |
442 | kfree(data); | 296 | kfree(data); |
443 | return 0; | 297 | return 0; |
444 | } | 298 | } |
445 | 299 | ||
446 | static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait) | 300 | static const struct file_operations snd_info_entry_operations = |
447 | { | 301 | { |
448 | struct snd_info_private_data *data; | 302 | .owner = THIS_MODULE, |
449 | struct snd_info_entry *entry; | 303 | .llseek = snd_info_entry_llseek, |
450 | unsigned int mask; | 304 | .read = snd_info_entry_read, |
305 | .write = snd_info_entry_write, | ||
306 | .poll = snd_info_entry_poll, | ||
307 | .unlocked_ioctl = snd_info_entry_ioctl, | ||
308 | .mmap = snd_info_entry_mmap, | ||
309 | .open = snd_info_entry_open, | ||
310 | .release = snd_info_entry_release, | ||
311 | }; | ||
451 | 312 | ||
452 | data = file->private_data; | 313 | /* |
453 | if (data == NULL) | 314 | * file ops for text proc files |
454 | return 0; | 315 | */ |
455 | entry = data->entry; | 316 | static ssize_t snd_info_text_entry_write(struct file *file, |
456 | mask = 0; | 317 | const char __user *buffer, |
457 | switch (entry->content) { | 318 | size_t count, loff_t *offset) |
458 | case SNDRV_INFO_CONTENT_DATA: | 319 | { |
459 | if (entry->c.ops->poll) | 320 | struct seq_file *m = file->private_data; |
460 | return entry->c.ops->poll(entry, | 321 | struct snd_info_private_data *data = m->private; |
461 | data->file_private_data, | 322 | struct snd_info_entry *entry = data->entry; |
462 | file, wait); | 323 | struct snd_info_buffer *buf; |
463 | if (entry->c.ops->read) | 324 | loff_t pos; |
464 | mask |= POLLIN | POLLRDNORM; | 325 | size_t next; |
465 | if (entry->c.ops->write) | 326 | int err = 0; |
466 | mask |= POLLOUT | POLLWRNORM; | 327 | |
467 | break; | 328 | pos = *offset; |
329 | if (!valid_pos(pos, count)) | ||
330 | return -EIO; | ||
331 | next = pos + count; | ||
332 | mutex_lock(&entry->access); | ||
333 | buf = data->wbuffer; | ||
334 | if (!buf) { | ||
335 | data->wbuffer = buf = kzalloc(sizeof(*buf), GFP_KERNEL); | ||
336 | if (!buf) { | ||
337 | err = -ENOMEM; | ||
338 | goto error; | ||
339 | } | ||
468 | } | 340 | } |
469 | return mask; | 341 | if (next > buf->len) { |
342 | char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), | ||
343 | GFP_KERNEL | __GFP_ZERO); | ||
344 | if (!nbuf) { | ||
345 | err = -ENOMEM; | ||
346 | goto error; | ||
347 | } | ||
348 | buf->buffer = nbuf; | ||
349 | buf->len = PAGE_ALIGN(next); | ||
350 | } | ||
351 | if (copy_from_user(buf->buffer + pos, buffer, count)) { | ||
352 | err = -EFAULT; | ||
353 | goto error; | ||
354 | } | ||
355 | buf->size = next; | ||
356 | error: | ||
357 | mutex_unlock(&entry->access); | ||
358 | if (err < 0) | ||
359 | return err; | ||
360 | *offset = next; | ||
361 | return count; | ||
470 | } | 362 | } |
471 | 363 | ||
472 | static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, | 364 | static int snd_info_seq_show(struct seq_file *seq, void *p) |
473 | unsigned long arg) | ||
474 | { | 365 | { |
475 | struct snd_info_private_data *data; | 366 | struct snd_info_private_data *data = seq->private; |
476 | struct snd_info_entry *entry; | 367 | struct snd_info_entry *entry = data->entry; |
477 | 368 | ||
478 | data = file->private_data; | 369 | if (entry->c.text.read) { |
479 | if (data == NULL) | 370 | data->rbuffer->buffer = (char *)seq; /* XXX hack! */ |
480 | return 0; | 371 | entry->c.text.read(entry, data->rbuffer); |
481 | entry = data->entry; | ||
482 | switch (entry->content) { | ||
483 | case SNDRV_INFO_CONTENT_DATA: | ||
484 | if (entry->c.ops->ioctl) | ||
485 | return entry->c.ops->ioctl(entry, | ||
486 | data->file_private_data, | ||
487 | file, cmd, arg); | ||
488 | break; | ||
489 | } | 372 | } |
490 | return -ENOTTY; | 373 | return 0; |
491 | } | 374 | } |
492 | 375 | ||
493 | static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) | 376 | static int snd_info_text_entry_open(struct inode *inode, struct file *file) |
494 | { | 377 | { |
495 | struct inode *inode = file_inode(file); | 378 | struct snd_info_entry *entry = PDE_DATA(inode); |
496 | struct snd_info_private_data *data; | 379 | struct snd_info_private_data *data; |
497 | struct snd_info_entry *entry; | 380 | int err; |
498 | 381 | ||
499 | data = file->private_data; | 382 | mutex_lock(&info_mutex); |
500 | if (data == NULL) | 383 | err = alloc_info_private(entry, &data); |
501 | return 0; | 384 | if (err < 0) |
502 | entry = data->entry; | 385 | goto unlock; |
503 | switch (entry->content) { | 386 | |
504 | case SNDRV_INFO_CONTENT_DATA: | 387 | data->rbuffer = kzalloc(sizeof(*data->rbuffer), GFP_KERNEL); |
505 | if (entry->c.ops->mmap) | 388 | if (!data->rbuffer) { |
506 | return entry->c.ops->mmap(entry, | 389 | err = -ENOMEM; |
507 | data->file_private_data, | 390 | goto error; |
508 | inode, file, vma); | ||
509 | break; | ||
510 | } | 391 | } |
511 | return -ENXIO; | 392 | if (entry->size) |
393 | err = single_open_size(file, snd_info_seq_show, data, | ||
394 | entry->size); | ||
395 | else | ||
396 | err = single_open(file, snd_info_seq_show, data); | ||
397 | if (err < 0) | ||
398 | goto error; | ||
399 | mutex_unlock(&info_mutex); | ||
400 | return 0; | ||
401 | |||
402 | error: | ||
403 | kfree(data->rbuffer); | ||
404 | kfree(data); | ||
405 | module_put(entry->module); | ||
406 | unlock: | ||
407 | mutex_unlock(&info_mutex); | ||
408 | return err; | ||
512 | } | 409 | } |
513 | 410 | ||
514 | static const struct file_operations snd_info_entry_operations = | 411 | static int snd_info_text_entry_release(struct inode *inode, struct file *file) |
412 | { | ||
413 | struct seq_file *m = file->private_data; | ||
414 | struct snd_info_private_data *data = m->private; | ||
415 | struct snd_info_entry *entry = data->entry; | ||
416 | |||
417 | if (data->wbuffer && entry->c.text.write) | ||
418 | entry->c.text.write(entry, data->wbuffer); | ||
419 | |||
420 | single_release(inode, file); | ||
421 | kfree(data->rbuffer); | ||
422 | if (data->wbuffer) { | ||
423 | kfree(data->wbuffer->buffer); | ||
424 | kfree(data->wbuffer); | ||
425 | } | ||
426 | |||
427 | module_put(entry->module); | ||
428 | kfree(data); | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static const struct file_operations snd_info_text_entry_ops = | ||
515 | { | 433 | { |
516 | .owner = THIS_MODULE, | 434 | .owner = THIS_MODULE, |
517 | .llseek = snd_info_entry_llseek, | 435 | .open = snd_info_text_entry_open, |
518 | .read = snd_info_entry_read, | 436 | .release = snd_info_text_entry_release, |
519 | .write = snd_info_entry_write, | 437 | .write = snd_info_text_entry_write, |
520 | .poll = snd_info_entry_poll, | 438 | .llseek = seq_lseek, |
521 | .unlocked_ioctl = snd_info_entry_ioctl, | 439 | .read = seq_read, |
522 | .mmap = snd_info_entry_mmap, | ||
523 | .open = snd_info_entry_open, | ||
524 | .release = snd_info_entry_release, | ||
525 | }; | 440 | }; |
526 | 441 | ||
527 | int __init snd_info_init(void) | 442 | static struct snd_info_entry *create_subdir(struct module *mod, |
443 | const char *name) | ||
528 | { | 444 | { |
529 | struct proc_dir_entry *p; | 445 | struct snd_info_entry *entry; |
530 | 446 | ||
531 | p = proc_mkdir("asound", NULL); | 447 | entry = snd_info_create_module_entry(mod, name, NULL); |
532 | if (p == NULL) | 448 | if (!entry) |
449 | return NULL; | ||
450 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
451 | if (snd_info_register(entry) < 0) { | ||
452 | snd_info_free_entry(entry); | ||
453 | return NULL; | ||
454 | } | ||
455 | return entry; | ||
456 | } | ||
457 | |||
458 | static struct snd_info_entry * | ||
459 | snd_info_create_entry(const char *name, struct snd_info_entry *parent); | ||
460 | |||
461 | int __init snd_info_init(void) | ||
462 | { | ||
463 | snd_proc_root = snd_info_create_entry("asound", NULL); | ||
464 | if (!snd_proc_root) | ||
533 | return -ENOMEM; | 465 | return -ENOMEM; |
534 | snd_proc_root = p; | 466 | snd_proc_root->mode = S_IFDIR | S_IRUGO | S_IXUGO; |
467 | snd_proc_root->p = proc_mkdir("asound", NULL); | ||
468 | if (!snd_proc_root->p) | ||
469 | goto error; | ||
535 | #ifdef CONFIG_SND_OSSEMUL | 470 | #ifdef CONFIG_SND_OSSEMUL |
536 | { | 471 | snd_oss_root = create_subdir(THIS_MODULE, "oss"); |
537 | struct snd_info_entry *entry; | 472 | if (!snd_oss_root) |
538 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL) | 473 | goto error; |
539 | return -ENOMEM; | ||
540 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
541 | if (snd_info_register(entry) < 0) { | ||
542 | snd_info_free_entry(entry); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | snd_oss_root = entry; | ||
546 | } | ||
547 | #endif | 474 | #endif |
548 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) | 475 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
549 | { | 476 | snd_seq_root = create_subdir(THIS_MODULE, "seq"); |
550 | struct snd_info_entry *entry; | 477 | if (!snd_seq_root) |
551 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL) | 478 | goto error; |
552 | return -ENOMEM; | ||
553 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
554 | if (snd_info_register(entry) < 0) { | ||
555 | snd_info_free_entry(entry); | ||
556 | return -ENOMEM; | ||
557 | } | ||
558 | snd_seq_root = entry; | ||
559 | } | ||
560 | #endif | 479 | #endif |
561 | snd_info_version_init(); | 480 | if (snd_info_version_init() < 0 || |
562 | snd_minor_info_init(); | 481 | snd_minor_info_init() < 0 || |
563 | snd_minor_info_oss_init(); | 482 | snd_minor_info_oss_init() < 0 || |
564 | snd_card_info_init(); | 483 | snd_card_info_init() < 0 || |
484 | snd_info_minor_register() < 0) | ||
485 | goto error; | ||
565 | return 0; | 486 | return 0; |
487 | |||
488 | error: | ||
489 | snd_info_free_entry(snd_proc_root); | ||
490 | return -ENOMEM; | ||
566 | } | 491 | } |
567 | 492 | ||
568 | int __exit snd_info_done(void) | 493 | int __exit snd_info_done(void) |
569 | { | 494 | { |
570 | snd_card_info_done(); | 495 | snd_info_free_entry(snd_proc_root); |
571 | snd_minor_info_oss_done(); | ||
572 | snd_minor_info_done(); | ||
573 | snd_info_version_done(); | ||
574 | if (snd_proc_root) { | ||
575 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) | ||
576 | snd_info_free_entry(snd_seq_root); | ||
577 | #endif | ||
578 | #ifdef CONFIG_SND_OSSEMUL | ||
579 | snd_info_free_entry(snd_oss_root); | ||
580 | #endif | ||
581 | proc_remove(snd_proc_root); | ||
582 | } | ||
583 | return 0; | 496 | return 0; |
584 | } | 497 | } |
585 | 498 | ||
586 | /* | 499 | /* |
587 | |||
588 | */ | ||
589 | |||
590 | |||
591 | /* | ||
592 | * create a card proc file | 500 | * create a card proc file |
593 | * called from init.c | 501 | * called from init.c |
594 | */ | 502 | */ |
@@ -601,33 +509,58 @@ int snd_info_card_create(struct snd_card *card) | |||
601 | return -ENXIO; | 509 | return -ENXIO; |
602 | 510 | ||
603 | sprintf(str, "card%i", card->number); | 511 | sprintf(str, "card%i", card->number); |
604 | if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL) | 512 | entry = create_subdir(card->module, str); |
605 | return -ENOMEM; | 513 | if (!entry) |
606 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
607 | if (snd_info_register(entry) < 0) { | ||
608 | snd_info_free_entry(entry); | ||
609 | return -ENOMEM; | 514 | return -ENOMEM; |
610 | } | ||
611 | card->proc_root = entry; | 515 | card->proc_root = entry; |
612 | return 0; | 516 | return 0; |
613 | } | 517 | } |
614 | 518 | ||
519 | /* register all pending info entries */ | ||
520 | static int snd_info_register_recursive(struct snd_info_entry *entry) | ||
521 | { | ||
522 | struct snd_info_entry *p; | ||
523 | int err; | ||
524 | |||
525 | if (!entry->p) { | ||
526 | err = snd_info_register(entry); | ||
527 | if (err < 0) | ||
528 | return err; | ||
529 | } | ||
530 | |||
531 | list_for_each_entry(p, &entry->children, list) { | ||
532 | err = snd_info_register_recursive(p); | ||
533 | if (err < 0) | ||
534 | return err; | ||
535 | } | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
615 | /* | 540 | /* |
616 | * register the card proc file | 541 | * register the card proc file |
617 | * called from init.c | 542 | * called from init.c |
543 | * can be called multiple times for reinitialization | ||
618 | */ | 544 | */ |
619 | int snd_info_card_register(struct snd_card *card) | 545 | int snd_info_card_register(struct snd_card *card) |
620 | { | 546 | { |
621 | struct proc_dir_entry *p; | 547 | struct proc_dir_entry *p; |
548 | int err; | ||
622 | 549 | ||
623 | if (snd_BUG_ON(!card)) | 550 | if (snd_BUG_ON(!card)) |
624 | return -ENXIO; | 551 | return -ENXIO; |
625 | 552 | ||
553 | err = snd_info_register_recursive(card->proc_root); | ||
554 | if (err < 0) | ||
555 | return err; | ||
556 | |||
626 | if (!strcmp(card->id, card->proc_root->name)) | 557 | if (!strcmp(card->id, card->proc_root->name)) |
627 | return 0; | 558 | return 0; |
628 | 559 | ||
629 | p = proc_symlink(card->id, snd_proc_root, card->proc_root->name); | 560 | if (card->proc_root_link) |
630 | if (p == NULL) | 561 | return 0; |
562 | p = proc_symlink(card->id, snd_proc_root->p, card->proc_root->name); | ||
563 | if (!p) | ||
631 | return -ENOMEM; | 564 | return -ENOMEM; |
632 | card->proc_root_link = p; | 565 | card->proc_root_link = p; |
633 | return 0; | 566 | return 0; |
@@ -645,7 +578,7 @@ void snd_info_card_id_change(struct snd_card *card) | |||
645 | } | 578 | } |
646 | if (strcmp(card->id, card->proc_root->name)) | 579 | if (strcmp(card->id, card->proc_root->name)) |
647 | card->proc_root_link = proc_symlink(card->id, | 580 | card->proc_root_link = proc_symlink(card->id, |
648 | snd_proc_root, | 581 | snd_proc_root->p, |
649 | card->proc_root->name); | 582 | card->proc_root->name); |
650 | mutex_unlock(&info_mutex); | 583 | mutex_unlock(&info_mutex); |
651 | } | 584 | } |
@@ -753,9 +686,10 @@ const char *snd_info_get_str(char *dest, const char *src, int len) | |||
753 | 686 | ||
754 | EXPORT_SYMBOL(snd_info_get_str); | 687 | EXPORT_SYMBOL(snd_info_get_str); |
755 | 688 | ||
756 | /** | 689 | /* |
757 | * snd_info_create_entry - create an info entry | 690 | * snd_info_create_entry - create an info entry |
758 | * @name: the proc file name | 691 | * @name: the proc file name |
692 | * @parent: the parent directory | ||
759 | * | 693 | * |
760 | * Creates an info entry with the given file name and initializes as | 694 | * Creates an info entry with the given file name and initializes as |
761 | * the default state. | 695 | * the default state. |
@@ -765,7 +699,8 @@ EXPORT_SYMBOL(snd_info_get_str); | |||
765 | * | 699 | * |
766 | * Return: The pointer of the new instance, or %NULL on failure. | 700 | * Return: The pointer of the new instance, or %NULL on failure. |
767 | */ | 701 | */ |
768 | static struct snd_info_entry *snd_info_create_entry(const char *name) | 702 | static struct snd_info_entry * |
703 | snd_info_create_entry(const char *name, struct snd_info_entry *parent) | ||
769 | { | 704 | { |
770 | struct snd_info_entry *entry; | 705 | struct snd_info_entry *entry; |
771 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 706 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
@@ -781,6 +716,9 @@ static struct snd_info_entry *snd_info_create_entry(const char *name) | |||
781 | mutex_init(&entry->access); | 716 | mutex_init(&entry->access); |
782 | INIT_LIST_HEAD(&entry->children); | 717 | INIT_LIST_HEAD(&entry->children); |
783 | INIT_LIST_HEAD(&entry->list); | 718 | INIT_LIST_HEAD(&entry->list); |
719 | entry->parent = parent; | ||
720 | if (parent) | ||
721 | list_add_tail(&entry->list, &parent->children); | ||
784 | return entry; | 722 | return entry; |
785 | } | 723 | } |
786 | 724 | ||
@@ -798,11 +736,9 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module, | |||
798 | const char *name, | 736 | const char *name, |
799 | struct snd_info_entry *parent) | 737 | struct snd_info_entry *parent) |
800 | { | 738 | { |
801 | struct snd_info_entry *entry = snd_info_create_entry(name); | 739 | struct snd_info_entry *entry = snd_info_create_entry(name, parent); |
802 | if (entry) { | 740 | if (entry) |
803 | entry->module = module; | 741 | entry->module = module; |
804 | entry->parent = parent; | ||
805 | } | ||
806 | return entry; | 742 | return entry; |
807 | } | 743 | } |
808 | 744 | ||
@@ -822,11 +758,10 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, | |||
822 | const char *name, | 758 | const char *name, |
823 | struct snd_info_entry * parent) | 759 | struct snd_info_entry * parent) |
824 | { | 760 | { |
825 | struct snd_info_entry *entry = snd_info_create_entry(name); | 761 | struct snd_info_entry *entry = snd_info_create_entry(name, parent); |
826 | if (entry) { | 762 | if (entry) { |
827 | entry->module = card->module; | 763 | entry->module = card->module; |
828 | entry->card = card; | 764 | entry->card = card; |
829 | entry->parent = parent; | ||
830 | } | 765 | } |
831 | return entry; | 766 | return entry; |
832 | } | 767 | } |
@@ -835,95 +770,39 @@ EXPORT_SYMBOL(snd_info_create_card_entry); | |||
835 | 770 | ||
836 | static void snd_info_disconnect(struct snd_info_entry *entry) | 771 | static void snd_info_disconnect(struct snd_info_entry *entry) |
837 | { | 772 | { |
838 | struct list_head *p, *n; | 773 | struct snd_info_entry *p; |
839 | struct proc_dir_entry *root; | ||
840 | |||
841 | list_for_each_safe(p, n, &entry->children) { | ||
842 | snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); | ||
843 | } | ||
844 | 774 | ||
845 | if (! entry->p) | 775 | if (!entry->p) |
846 | return; | 776 | return; |
847 | list_del_init(&entry->list); | 777 | list_for_each_entry(p, &entry->children, list) |
848 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; | 778 | snd_info_disconnect(p); |
849 | snd_BUG_ON(!root); | ||
850 | proc_remove(entry->p); | 779 | proc_remove(entry->p); |
851 | entry->p = NULL; | 780 | entry->p = NULL; |
852 | } | 781 | } |
853 | 782 | ||
854 | static int snd_info_dev_free_entry(struct snd_device *device) | ||
855 | { | ||
856 | struct snd_info_entry *entry = device->device_data; | ||
857 | snd_info_free_entry(entry); | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | static int snd_info_dev_register_entry(struct snd_device *device) | ||
862 | { | ||
863 | struct snd_info_entry *entry = device->device_data; | ||
864 | return snd_info_register(entry); | ||
865 | } | ||
866 | |||
867 | /** | ||
868 | * snd_card_proc_new - create an info entry for the given card | ||
869 | * @card: the card instance | ||
870 | * @name: the file name | ||
871 | * @entryp: the pointer to store the new info entry | ||
872 | * | ||
873 | * Creates a new info entry and assigns it to the given card. | ||
874 | * Unlike snd_info_create_card_entry(), this function registers the | ||
875 | * info entry as an ALSA device component, so that it can be | ||
876 | * unregistered/released without explicit call. | ||
877 | * Also, you don't have to register this entry via snd_info_register(), | ||
878 | * since this will be registered by snd_card_register() automatically. | ||
879 | * | ||
880 | * The parent is assumed as card->proc_root. | ||
881 | * | ||
882 | * For releasing this entry, use snd_device_free() instead of | ||
883 | * snd_info_free_entry(). | ||
884 | * | ||
885 | * Return: Zero if successful, or a negative error code on failure. | ||
886 | */ | ||
887 | int snd_card_proc_new(struct snd_card *card, const char *name, | ||
888 | struct snd_info_entry **entryp) | ||
889 | { | ||
890 | static struct snd_device_ops ops = { | ||
891 | .dev_free = snd_info_dev_free_entry, | ||
892 | .dev_register = snd_info_dev_register_entry, | ||
893 | /* disconnect is done via snd_info_card_disconnect() */ | ||
894 | }; | ||
895 | struct snd_info_entry *entry; | ||
896 | int err; | ||
897 | |||
898 | entry = snd_info_create_card_entry(card, name, card->proc_root); | ||
899 | if (! entry) | ||
900 | return -ENOMEM; | ||
901 | if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) { | ||
902 | snd_info_free_entry(entry); | ||
903 | return err; | ||
904 | } | ||
905 | if (entryp) | ||
906 | *entryp = entry; | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | EXPORT_SYMBOL(snd_card_proc_new); | ||
911 | |||
912 | /** | 783 | /** |
913 | * snd_info_free_entry - release the info entry | 784 | * snd_info_free_entry - release the info entry |
914 | * @entry: the info entry | 785 | * @entry: the info entry |
915 | * | 786 | * |
916 | * Releases the info entry. Don't call this after registered. | 787 | * Releases the info entry. |
917 | */ | 788 | */ |
918 | void snd_info_free_entry(struct snd_info_entry * entry) | 789 | void snd_info_free_entry(struct snd_info_entry * entry) |
919 | { | 790 | { |
920 | if (entry == NULL) | 791 | struct snd_info_entry *p, *n; |
792 | |||
793 | if (!entry) | ||
921 | return; | 794 | return; |
922 | if (entry->p) { | 795 | if (entry->p) { |
923 | mutex_lock(&info_mutex); | 796 | mutex_lock(&info_mutex); |
924 | snd_info_disconnect(entry); | 797 | snd_info_disconnect(entry); |
925 | mutex_unlock(&info_mutex); | 798 | mutex_unlock(&info_mutex); |
926 | } | 799 | } |
800 | |||
801 | /* free all children at first */ | ||
802 | list_for_each_entry_safe(p, n, &entry->children, list) | ||
803 | snd_info_free_entry(p); | ||
804 | |||
805 | list_del(&entry->list); | ||
927 | kfree(entry->name); | 806 | kfree(entry->name); |
928 | if (entry->private_free) | 807 | if (entry->private_free) |
929 | entry->private_free(entry); | 808 | entry->private_free(entry); |
@@ -946,7 +825,7 @@ int snd_info_register(struct snd_info_entry * entry) | |||
946 | 825 | ||
947 | if (snd_BUG_ON(!entry)) | 826 | if (snd_BUG_ON(!entry)) |
948 | return -ENXIO; | 827 | return -ENXIO; |
949 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; | 828 | root = entry->parent == NULL ? snd_proc_root->p : entry->parent->p; |
950 | mutex_lock(&info_mutex); | 829 | mutex_lock(&info_mutex); |
951 | if (S_ISDIR(entry->mode)) { | 830 | if (S_ISDIR(entry->mode)) { |
952 | p = proc_mkdir_mode(entry->name, entry->mode, root); | 831 | p = proc_mkdir_mode(entry->name, entry->mode, root); |
@@ -955,8 +834,13 @@ int snd_info_register(struct snd_info_entry * entry) | |||
955 | return -ENOMEM; | 834 | return -ENOMEM; |
956 | } | 835 | } |
957 | } else { | 836 | } else { |
837 | const struct file_operations *ops; | ||
838 | if (entry->content == SNDRV_INFO_CONTENT_DATA) | ||
839 | ops = &snd_info_entry_operations; | ||
840 | else | ||
841 | ops = &snd_info_text_entry_ops; | ||
958 | p = proc_create_data(entry->name, entry->mode, root, | 842 | p = proc_create_data(entry->name, entry->mode, root, |
959 | &snd_info_entry_operations, entry); | 843 | ops, entry); |
960 | if (!p) { | 844 | if (!p) { |
961 | mutex_unlock(&info_mutex); | 845 | mutex_unlock(&info_mutex); |
962 | return -ENOMEM; | 846 | return -ENOMEM; |
@@ -964,8 +848,6 @@ int snd_info_register(struct snd_info_entry * entry) | |||
964 | proc_set_size(p, entry->size); | 848 | proc_set_size(p, entry->size); |
965 | } | 849 | } |
966 | entry->p = p; | 850 | entry->p = p; |
967 | if (entry->parent) | ||
968 | list_add_tail(&entry->list, &entry->parent->children); | ||
969 | mutex_unlock(&info_mutex); | 851 | mutex_unlock(&info_mutex); |
970 | return 0; | 852 | return 0; |
971 | } | 853 | } |
@@ -976,8 +858,6 @@ EXPORT_SYMBOL(snd_info_register); | |||
976 | 858 | ||
977 | */ | 859 | */ |
978 | 860 | ||
979 | static struct snd_info_entry *snd_info_version_entry; | ||
980 | |||
981 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 861 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
982 | { | 862 | { |
983 | snd_iprintf(buffer, | 863 | snd_iprintf(buffer, |
@@ -993,18 +873,5 @@ static int __init snd_info_version_init(void) | |||
993 | if (entry == NULL) | 873 | if (entry == NULL) |
994 | return -ENOMEM; | 874 | return -ENOMEM; |
995 | entry->c.text.read = snd_info_version_read; | 875 | entry->c.text.read = snd_info_version_read; |
996 | if (snd_info_register(entry) < 0) { | 876 | return snd_info_register(entry); /* freed in error path */ |
997 | snd_info_free_entry(entry); | ||
998 | return -ENOMEM; | ||
999 | } | ||
1000 | snd_info_version_entry = entry; | ||
1001 | return 0; | ||
1002 | } | 877 | } |
1003 | |||
1004 | static int __exit snd_info_version_done(void) | ||
1005 | { | ||
1006 | snd_info_free_entry(snd_info_version_entry); | ||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index 83c29dbff9c0..1478c8dfd473 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
@@ -29,15 +29,12 @@ | |||
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | 31 | ||
32 | #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) | ||
33 | |||
34 | /* | 32 | /* |
35 | * OSS compatible part | 33 | * OSS compatible part |
36 | */ | 34 | */ |
37 | 35 | ||
38 | static DEFINE_MUTEX(strings); | 36 | static DEFINE_MUTEX(strings); |
39 | static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; | 37 | static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; |
40 | static struct snd_info_entry *snd_sndstat_proc_entry; | ||
41 | 38 | ||
42 | int snd_oss_info_register(int dev, int num, char *string) | 39 | int snd_oss_info_register(int dev, int num, char *string) |
43 | { | 40 | { |
@@ -112,27 +109,15 @@ static void snd_sndstat_proc_read(struct snd_info_entry *entry, | |||
112 | snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); | 109 | snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); |
113 | } | 110 | } |
114 | 111 | ||
115 | int snd_info_minor_register(void) | 112 | int __init snd_info_minor_register(void) |
116 | { | 113 | { |
117 | struct snd_info_entry *entry; | 114 | struct snd_info_entry *entry; |
118 | 115 | ||
119 | memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); | 116 | memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); |
120 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { | 117 | entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", |
121 | entry->c.text.read = snd_sndstat_proc_read; | 118 | snd_oss_root); |
122 | if (snd_info_register(entry) < 0) { | 119 | if (!entry) |
123 | snd_info_free_entry(entry); | 120 | return -ENOMEM; |
124 | entry = NULL; | 121 | entry->c.text.read = snd_sndstat_proc_read; |
125 | } | 122 | return snd_info_register(entry); /* freed in error path */ |
126 | } | ||
127 | snd_sndstat_proc_entry = entry; | ||
128 | return 0; | ||
129 | } | 123 | } |
130 | |||
131 | int snd_info_minor_unregister(void) | ||
132 | { | ||
133 | snd_info_free_entry(snd_sndstat_proc_entry); | ||
134 | snd_sndstat_proc_entry = NULL; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | #endif /* CONFIG_SND_OSSEMUL */ | ||
diff --git a/sound/core/init.c b/sound/core/init.c index 04734e047bfe..20f37fb3800e 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -100,35 +100,28 @@ int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); | |||
100 | EXPORT_SYMBOL(snd_mixer_oss_notify_callback); | 100 | EXPORT_SYMBOL(snd_mixer_oss_notify_callback); |
101 | #endif | 101 | #endif |
102 | 102 | ||
103 | #ifdef CONFIG_PROC_FS | 103 | #ifdef CONFIG_SND_PROC_FS |
104 | static void snd_card_id_read(struct snd_info_entry *entry, | 104 | static void snd_card_id_read(struct snd_info_entry *entry, |
105 | struct snd_info_buffer *buffer) | 105 | struct snd_info_buffer *buffer) |
106 | { | 106 | { |
107 | snd_iprintf(buffer, "%s\n", entry->card->id); | 107 | snd_iprintf(buffer, "%s\n", entry->card->id); |
108 | } | 108 | } |
109 | 109 | ||
110 | static inline int init_info_for_card(struct snd_card *card) | 110 | static int init_info_for_card(struct snd_card *card) |
111 | { | 111 | { |
112 | int err; | ||
113 | struct snd_info_entry *entry; | 112 | struct snd_info_entry *entry; |
114 | 113 | ||
115 | if ((err = snd_info_card_register(card)) < 0) { | 114 | entry = snd_info_create_card_entry(card, "id", card->proc_root); |
116 | dev_dbg(card->dev, "unable to create card info\n"); | 115 | if (!entry) { |
117 | return err; | ||
118 | } | ||
119 | if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) { | ||
120 | dev_dbg(card->dev, "unable to create card entry\n"); | 116 | dev_dbg(card->dev, "unable to create card entry\n"); |
121 | return err; | 117 | return -ENOMEM; |
122 | } | 118 | } |
123 | entry->c.text.read = snd_card_id_read; | 119 | entry->c.text.read = snd_card_id_read; |
124 | if (snd_info_register(entry) < 0) { | ||
125 | snd_info_free_entry(entry); | ||
126 | entry = NULL; | ||
127 | } | ||
128 | card->proc_id = entry; | 120 | card->proc_id = entry; |
129 | return 0; | 121 | |
122 | return snd_info_card_register(card); | ||
130 | } | 123 | } |
131 | #else /* !CONFIG_PROC_FS */ | 124 | #else /* !CONFIG_SND_PROC_FS */ |
132 | #define init_info_for_card(card) | 125 | #define init_info_for_card(card) |
133 | #endif | 126 | #endif |
134 | 127 | ||
@@ -756,7 +749,7 @@ int snd_card_register(struct snd_card *card) | |||
756 | if (snd_cards[card->number]) { | 749 | if (snd_cards[card->number]) { |
757 | /* already registered */ | 750 | /* already registered */ |
758 | mutex_unlock(&snd_card_mutex); | 751 | mutex_unlock(&snd_card_mutex); |
759 | return 0; | 752 | return snd_info_card_register(card); /* register pending info */ |
760 | } | 753 | } |
761 | if (*card->id) { | 754 | if (*card->id) { |
762 | /* make a unique id name from the given string */ | 755 | /* make a unique id name from the given string */ |
@@ -782,9 +775,7 @@ int snd_card_register(struct snd_card *card) | |||
782 | 775 | ||
783 | EXPORT_SYMBOL(snd_card_register); | 776 | EXPORT_SYMBOL(snd_card_register); |
784 | 777 | ||
785 | #ifdef CONFIG_PROC_FS | 778 | #ifdef CONFIG_SND_PROC_FS |
786 | static struct snd_info_entry *snd_card_info_entry; | ||
787 | |||
788 | static void snd_card_info_read(struct snd_info_entry *entry, | 779 | static void snd_card_info_read(struct snd_info_entry *entry, |
789 | struct snd_info_buffer *buffer) | 780 | struct snd_info_buffer *buffer) |
790 | { | 781 | { |
@@ -810,7 +801,6 @@ static void snd_card_info_read(struct snd_info_entry *entry, | |||
810 | } | 801 | } |
811 | 802 | ||
812 | #ifdef CONFIG_SND_OSSEMUL | 803 | #ifdef CONFIG_SND_OSSEMUL |
813 | |||
814 | void snd_card_info_read_oss(struct snd_info_buffer *buffer) | 804 | void snd_card_info_read_oss(struct snd_info_buffer *buffer) |
815 | { | 805 | { |
816 | int idx, count; | 806 | int idx, count; |
@@ -832,7 +822,6 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer) | |||
832 | #endif | 822 | #endif |
833 | 823 | ||
834 | #ifdef MODULE | 824 | #ifdef MODULE |
835 | static struct snd_info_entry *snd_card_module_info_entry; | ||
836 | static void snd_card_module_info_read(struct snd_info_entry *entry, | 825 | static void snd_card_module_info_read(struct snd_info_entry *entry, |
837 | struct snd_info_buffer *buffer) | 826 | struct snd_info_buffer *buffer) |
838 | { | 827 | { |
@@ -857,36 +846,21 @@ int __init snd_card_info_init(void) | |||
857 | if (! entry) | 846 | if (! entry) |
858 | return -ENOMEM; | 847 | return -ENOMEM; |
859 | entry->c.text.read = snd_card_info_read; | 848 | entry->c.text.read = snd_card_info_read; |
860 | if (snd_info_register(entry) < 0) { | 849 | if (snd_info_register(entry) < 0) |
861 | snd_info_free_entry(entry); | 850 | return -ENOMEM; /* freed in error path */ |
862 | return -ENOMEM; | ||
863 | } | ||
864 | snd_card_info_entry = entry; | ||
865 | 851 | ||
866 | #ifdef MODULE | 852 | #ifdef MODULE |
867 | entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); | 853 | entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); |
868 | if (entry) { | 854 | if (!entry) |
869 | entry->c.text.read = snd_card_module_info_read; | 855 | return -ENOMEM; |
870 | if (snd_info_register(entry) < 0) | 856 | entry->c.text.read = snd_card_module_info_read; |
871 | snd_info_free_entry(entry); | 857 | if (snd_info_register(entry) < 0) |
872 | else | 858 | return -ENOMEM; /* freed in error path */ |
873 | snd_card_module_info_entry = entry; | ||
874 | } | ||
875 | #endif | 859 | #endif |
876 | 860 | ||
877 | return 0; | 861 | return 0; |
878 | } | 862 | } |
879 | 863 | #endif /* CONFIG_SND_PROC_FS */ | |
880 | int __exit snd_card_info_done(void) | ||
881 | { | ||
882 | snd_info_free_entry(snd_card_info_entry); | ||
883 | #ifdef MODULE | ||
884 | snd_info_free_entry(snd_card_module_info_entry); | ||
885 | #endif | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | #endif /* CONFIG_PROC_FS */ | ||
890 | 864 | ||
891 | /** | 865 | /** |
892 | * snd_component_add - add a component string | 866 | * snd_component_add - add a component string |
diff --git a/sound/core/jack.c b/sound/core/jack.c index 8658578eb584..7237acbdcbbc 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -24,6 +24,13 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <sound/jack.h> | 25 | #include <sound/jack.h> |
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include <sound/control.h> | ||
28 | |||
29 | struct snd_jack_kctl { | ||
30 | struct snd_kcontrol *kctl; | ||
31 | struct list_head list; /* list of controls belong to the same jack */ | ||
32 | unsigned int mask_bits; /* only masked status bits are reported via kctl */ | ||
33 | }; | ||
27 | 34 | ||
28 | static int jack_switch_types[SND_JACK_SWITCH_TYPES] = { | 35 | static int jack_switch_types[SND_JACK_SWITCH_TYPES] = { |
29 | SW_HEADPHONE_INSERT, | 36 | SW_HEADPHONE_INSERT, |
@@ -54,7 +61,13 @@ static int snd_jack_dev_disconnect(struct snd_device *device) | |||
54 | static int snd_jack_dev_free(struct snd_device *device) | 61 | static int snd_jack_dev_free(struct snd_device *device) |
55 | { | 62 | { |
56 | struct snd_jack *jack = device->device_data; | 63 | struct snd_jack *jack = device->device_data; |
64 | struct snd_card *card = device->card; | ||
65 | struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl; | ||
57 | 66 | ||
67 | list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) { | ||
68 | list_del_init(&jack_kctl->list); | ||
69 | snd_ctl_remove(card, jack_kctl->kctl); | ||
70 | } | ||
58 | if (jack->private_free) | 71 | if (jack->private_free) |
59 | jack->private_free(jack); | 72 | jack->private_free(jack); |
60 | 73 | ||
@@ -74,6 +87,10 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
74 | 87 | ||
75 | snprintf(jack->name, sizeof(jack->name), "%s %s", | 88 | snprintf(jack->name, sizeof(jack->name), "%s %s", |
76 | card->shortname, jack->id); | 89 | card->shortname, jack->id); |
90 | |||
91 | if (!jack->input_dev) | ||
92 | return 0; | ||
93 | |||
77 | jack->input_dev->name = jack->name; | 94 | jack->input_dev->name = jack->name; |
78 | 95 | ||
79 | /* Default to the sound card device. */ | 96 | /* Default to the sound card device. */ |
@@ -100,6 +117,77 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
100 | return err; | 117 | return err; |
101 | } | 118 | } |
102 | 119 | ||
120 | static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl) | ||
121 | { | ||
122 | struct snd_jack_kctl *jack_kctl; | ||
123 | |||
124 | jack_kctl = kctl->private_data; | ||
125 | if (jack_kctl) { | ||
126 | list_del(&jack_kctl->list); | ||
127 | kfree(jack_kctl); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl) | ||
132 | { | ||
133 | list_add_tail(&jack_kctl->list, &jack->kctl_list); | ||
134 | } | ||
135 | |||
136 | static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask) | ||
137 | { | ||
138 | struct snd_kcontrol *kctl; | ||
139 | struct snd_jack_kctl *jack_kctl; | ||
140 | int err; | ||
141 | |||
142 | kctl = snd_kctl_jack_new(name, card); | ||
143 | if (!kctl) | ||
144 | return NULL; | ||
145 | |||
146 | err = snd_ctl_add(card, kctl); | ||
147 | if (err < 0) | ||
148 | return NULL; | ||
149 | |||
150 | jack_kctl = kzalloc(sizeof(*jack_kctl), GFP_KERNEL); | ||
151 | |||
152 | if (!jack_kctl) | ||
153 | goto error; | ||
154 | |||
155 | jack_kctl->kctl = kctl; | ||
156 | jack_kctl->mask_bits = mask; | ||
157 | |||
158 | kctl->private_data = jack_kctl; | ||
159 | kctl->private_free = snd_jack_kctl_private_free; | ||
160 | |||
161 | return jack_kctl; | ||
162 | error: | ||
163 | snd_ctl_free_one(kctl); | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * snd_jack_add_new_kctl - Create a new snd_jack_kctl and add it to jack | ||
169 | * @jack: the jack instance which the kctl will attaching to | ||
170 | * @name: the name for the snd_kcontrol object | ||
171 | * @mask: a bitmask of enum snd_jack_type values that can be detected | ||
172 | * by this snd_jack_kctl object. | ||
173 | * | ||
174 | * Creates a new snd_kcontrol object and adds it to the jack kctl_list. | ||
175 | * | ||
176 | * Return: Zero if successful, or a negative error code on failure. | ||
177 | */ | ||
178 | int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask) | ||
179 | { | ||
180 | struct snd_jack_kctl *jack_kctl; | ||
181 | |||
182 | jack_kctl = snd_jack_kctl_new(jack->card, name, mask); | ||
183 | if (!jack_kctl) | ||
184 | return -ENOMEM; | ||
185 | |||
186 | snd_jack_kctl_add(jack, jack_kctl); | ||
187 | return 0; | ||
188 | } | ||
189 | EXPORT_SYMBOL(snd_jack_add_new_kctl); | ||
190 | |||
103 | /** | 191 | /** |
104 | * snd_jack_new - Create a new jack | 192 | * snd_jack_new - Create a new jack |
105 | * @card: the card instance | 193 | * @card: the card instance |
@@ -107,6 +195,8 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
107 | * @type: a bitmask of enum snd_jack_type values that can be detected by | 195 | * @type: a bitmask of enum snd_jack_type values that can be detected by |
108 | * this jack | 196 | * this jack |
109 | * @jjack: Used to provide the allocated jack object to the caller. | 197 | * @jjack: Used to provide the allocated jack object to the caller. |
198 | * @initial_kctl: if true, create a kcontrol and add it to the jack list. | ||
199 | * @phantom_jack: Don't create a input device for phantom jacks. | ||
110 | * | 200 | * |
111 | * Creates a new jack object. | 201 | * Creates a new jack object. |
112 | * | 202 | * |
@@ -114,9 +204,10 @@ static int snd_jack_dev_register(struct snd_device *device) | |||
114 | * On success @jjack will be initialised. | 204 | * On success @jjack will be initialised. |
115 | */ | 205 | */ |
116 | int snd_jack_new(struct snd_card *card, const char *id, int type, | 206 | int snd_jack_new(struct snd_card *card, const char *id, int type, |
117 | struct snd_jack **jjack) | 207 | struct snd_jack **jjack, bool initial_kctl, bool phantom_jack) |
118 | { | 208 | { |
119 | struct snd_jack *jack; | 209 | struct snd_jack *jack; |
210 | struct snd_jack_kctl *jack_kctl = NULL; | ||
120 | int err; | 211 | int err; |
121 | int i; | 212 | int i; |
122 | static struct snd_device_ops ops = { | 213 | static struct snd_device_ops ops = { |
@@ -125,31 +216,47 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
125 | .dev_disconnect = snd_jack_dev_disconnect, | 216 | .dev_disconnect = snd_jack_dev_disconnect, |
126 | }; | 217 | }; |
127 | 218 | ||
219 | if (initial_kctl) { | ||
220 | jack_kctl = snd_jack_kctl_new(card, id, type); | ||
221 | if (!jack_kctl) | ||
222 | return -ENOMEM; | ||
223 | } | ||
224 | |||
128 | jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL); | 225 | jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL); |
129 | if (jack == NULL) | 226 | if (jack == NULL) |
130 | return -ENOMEM; | 227 | return -ENOMEM; |
131 | 228 | ||
132 | jack->id = kstrdup(id, GFP_KERNEL); | 229 | jack->id = kstrdup(id, GFP_KERNEL); |
133 | 230 | ||
134 | jack->input_dev = input_allocate_device(); | 231 | /* don't creat input device for phantom jack */ |
135 | if (jack->input_dev == NULL) { | 232 | if (!phantom_jack) { |
136 | err = -ENOMEM; | 233 | jack->input_dev = input_allocate_device(); |
137 | goto fail_input; | 234 | if (jack->input_dev == NULL) { |
138 | } | 235 | err = -ENOMEM; |
236 | goto fail_input; | ||
237 | } | ||
139 | 238 | ||
140 | jack->input_dev->phys = "ALSA"; | 239 | jack->input_dev->phys = "ALSA"; |
141 | 240 | ||
142 | jack->type = type; | 241 | jack->type = type; |
143 | 242 | ||
144 | for (i = 0; i < SND_JACK_SWITCH_TYPES; i++) | 243 | for (i = 0; i < SND_JACK_SWITCH_TYPES; i++) |
145 | if (type & (1 << i)) | 244 | if (type & (1 << i)) |
146 | input_set_capability(jack->input_dev, EV_SW, | 245 | input_set_capability(jack->input_dev, EV_SW, |
147 | jack_switch_types[i]); | 246 | jack_switch_types[i]); |
247 | |||
248 | } | ||
148 | 249 | ||
149 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); | 250 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); |
150 | if (err < 0) | 251 | if (err < 0) |
151 | goto fail_input; | 252 | goto fail_input; |
152 | 253 | ||
254 | jack->card = card; | ||
255 | INIT_LIST_HEAD(&jack->kctl_list); | ||
256 | |||
257 | if (initial_kctl) | ||
258 | snd_jack_kctl_add(jack, jack_kctl); | ||
259 | |||
153 | *jjack = jack; | 260 | *jjack = jack; |
154 | 261 | ||
155 | return 0; | 262 | return 0; |
@@ -175,6 +282,8 @@ EXPORT_SYMBOL(snd_jack_new); | |||
175 | void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) | 282 | void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) |
176 | { | 283 | { |
177 | WARN_ON(jack->registered); | 284 | WARN_ON(jack->registered); |
285 | if (!jack->input_dev) | ||
286 | return; | ||
178 | 287 | ||
179 | jack->input_dev->dev.parent = parent; | 288 | jack->input_dev->dev.parent = parent; |
180 | } | 289 | } |
@@ -230,11 +339,19 @@ EXPORT_SYMBOL(snd_jack_set_key); | |||
230 | */ | 339 | */ |
231 | void snd_jack_report(struct snd_jack *jack, int status) | 340 | void snd_jack_report(struct snd_jack *jack, int status) |
232 | { | 341 | { |
342 | struct snd_jack_kctl *jack_kctl; | ||
233 | int i; | 343 | int i; |
234 | 344 | ||
235 | if (!jack) | 345 | if (!jack) |
236 | return; | 346 | return; |
237 | 347 | ||
348 | list_for_each_entry(jack_kctl, &jack->kctl_list, list) | ||
349 | snd_kctl_jack_report(jack->card, jack_kctl->kctl, | ||
350 | status & jack_kctl->mask_bits); | ||
351 | |||
352 | if (!jack->input_dev) | ||
353 | return; | ||
354 | |||
238 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { | 355 | for (i = 0; i < ARRAY_SIZE(jack->key); i++) { |
239 | int testbit = SND_JACK_BTN_0 >> i; | 356 | int testbit = SND_JACK_BTN_0 >> i; |
240 | 357 | ||
@@ -252,9 +369,6 @@ void snd_jack_report(struct snd_jack *jack, int status) | |||
252 | } | 369 | } |
253 | 370 | ||
254 | input_sync(jack->input_dev); | 371 | input_sync(jack->input_dev); |
372 | |||
255 | } | 373 | } |
256 | EXPORT_SYMBOL(snd_jack_report); | 374 | EXPORT_SYMBOL(snd_jack_report); |
257 | |||
258 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
259 | MODULE_DESCRIPTION("Jack detection support for ALSA"); | ||
260 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 082509eb805d..f05cb6a8cbe0 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -124,7 +124,7 @@ static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size) | |||
124 | dmab->addr = 0; | 124 | dmab->addr = 0; |
125 | 125 | ||
126 | if (dev->of_node) | 126 | if (dev->of_node) |
127 | pool = of_get_named_gen_pool(dev->of_node, "iram", 0); | 127 | pool = of_gen_pool_get(dev->of_node, "iram", 0); |
128 | 128 | ||
129 | if (!pool) | 129 | if (!pool) |
130 | return; | 130 | return; |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 056f8e274851..a99f7200ff3f 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1111,7 +1111,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix | |||
1111 | return 0; | 1111 | return 0; |
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | #ifdef CONFIG_PROC_FS | 1114 | #ifdef CONFIG_SND_PROC_FS |
1115 | /* | 1115 | /* |
1116 | */ | 1116 | */ |
1117 | #define MIXER_VOL(name) [SOUND_MIXER_##name] = #name | 1117 | #define MIXER_VOL(name) [SOUND_MIXER_##name] = #name |
@@ -1255,10 +1255,10 @@ static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer) | |||
1255 | snd_info_free_entry(mixer->proc_entry); | 1255 | snd_info_free_entry(mixer->proc_entry); |
1256 | mixer->proc_entry = NULL; | 1256 | mixer->proc_entry = NULL; |
1257 | } | 1257 | } |
1258 | #else /* !CONFIG_PROC_FS */ | 1258 | #else /* !CONFIG_SND_PROC_FS */ |
1259 | #define snd_mixer_oss_proc_init(mix) | 1259 | #define snd_mixer_oss_proc_init(mix) |
1260 | #define snd_mixer_oss_proc_done(mix) | 1260 | #define snd_mixer_oss_proc_done(mix) |
1261 | #endif /* CONFIG_PROC_FS */ | 1261 | #endif /* CONFIG_SND_PROC_FS */ |
1262 | 1262 | ||
1263 | static void snd_mixer_oss_build(struct snd_mixer_oss *mixer) | 1263 | static void snd_mixer_oss_build(struct snd_mixer_oss *mixer) |
1264 | { | 1264 | { |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index b25bcf5b8644..02bd96954dc4 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -1027,7 +1027,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) | |||
1027 | static ssize_t show_pcm_class(struct device *dev, | 1027 | static ssize_t show_pcm_class(struct device *dev, |
1028 | struct device_attribute *attr, char *buf) | 1028 | struct device_attribute *attr, char *buf) |
1029 | { | 1029 | { |
1030 | struct snd_pcm *pcm; | 1030 | struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev); |
1031 | struct snd_pcm *pcm = pstr->pcm; | ||
1031 | const char *str; | 1032 | const char *str; |
1032 | static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = { | 1033 | static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = { |
1033 | [SNDRV_PCM_CLASS_GENERIC] = "generic", | 1034 | [SNDRV_PCM_CLASS_GENERIC] = "generic", |
@@ -1036,8 +1037,7 @@ static ssize_t show_pcm_class(struct device *dev, | |||
1036 | [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", | 1037 | [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", |
1037 | }; | 1038 | }; |
1038 | 1039 | ||
1039 | if (! (pcm = dev_get_drvdata(dev)) || | 1040 | if (pcm->dev_class > SNDRV_PCM_CLASS_LAST) |
1040 | pcm->dev_class > SNDRV_PCM_CLASS_LAST) | ||
1041 | str = "none"; | 1041 | str = "none"; |
1042 | else | 1042 | else |
1043 | str = strs[pcm->dev_class]; | 1043 | str = strs[pcm->dev_class]; |
@@ -1181,7 +1181,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) | |||
1181 | } | 1181 | } |
1182 | EXPORT_SYMBOL(snd_pcm_notify); | 1182 | EXPORT_SYMBOL(snd_pcm_notify); |
1183 | 1183 | ||
1184 | #ifdef CONFIG_PROC_FS | 1184 | #ifdef CONFIG_SND_PROC_FS |
1185 | /* | 1185 | /* |
1186 | * Info interface | 1186 | * Info interface |
1187 | */ | 1187 | */ |
@@ -1227,10 +1227,10 @@ static void snd_pcm_proc_done(void) | |||
1227 | snd_info_free_entry(snd_pcm_proc_entry); | 1227 | snd_info_free_entry(snd_pcm_proc_entry); |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | #else /* !CONFIG_PROC_FS */ | 1230 | #else /* !CONFIG_SND_PROC_FS */ |
1231 | #define snd_pcm_proc_init() | 1231 | #define snd_pcm_proc_init() |
1232 | #define snd_pcm_proc_done() | 1232 | #define snd_pcm_proc_done() |
1233 | #endif /* CONFIG_PROC_FS */ | 1233 | #endif /* CONFIG_SND_PROC_FS */ |
1234 | 1234 | ||
1235 | 1235 | ||
1236 | /* | 1236 | /* |
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c new file mode 100644 index 000000000000..e70379fb63d0 --- /dev/null +++ b/sound/core/pcm_drm_eld.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * PCM DRM helpers | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <linux/export.h> | ||
9 | #include <drm/drm_edid.h> | ||
10 | #include <sound/pcm.h> | ||
11 | #include <sound/pcm_drm_eld.h> | ||
12 | |||
13 | static const unsigned int eld_rates[] = { | ||
14 | 32000, | ||
15 | 44100, | ||
16 | 48000, | ||
17 | 88200, | ||
18 | 96000, | ||
19 | 176400, | ||
20 | 192000, | ||
21 | }; | ||
22 | |||
23 | static unsigned int sad_max_channels(const u8 *sad) | ||
24 | { | ||
25 | return 1 + (sad[0] & 7); | ||
26 | } | ||
27 | |||
28 | static int eld_limit_rates(struct snd_pcm_hw_params *params, | ||
29 | struct snd_pcm_hw_rule *rule) | ||
30 | { | ||
31 | struct snd_interval *r = hw_param_interval(params, rule->var); | ||
32 | struct snd_interval *c; | ||
33 | unsigned int rate_mask = 7, i; | ||
34 | const u8 *sad, *eld = rule->private; | ||
35 | |||
36 | sad = drm_eld_sad(eld); | ||
37 | if (sad) { | ||
38 | c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
39 | |||
40 | for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) { | ||
41 | unsigned max_channels = sad_max_channels(sad); | ||
42 | |||
43 | /* | ||
44 | * Exclude SADs which do not include the | ||
45 | * requested number of channels. | ||
46 | */ | ||
47 | if (c->min <= max_channels) | ||
48 | rate_mask |= sad[1]; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates, | ||
53 | rate_mask); | ||
54 | } | ||
55 | |||
56 | static int eld_limit_channels(struct snd_pcm_hw_params *params, | ||
57 | struct snd_pcm_hw_rule *rule) | ||
58 | { | ||
59 | struct snd_interval *c = hw_param_interval(params, rule->var); | ||
60 | struct snd_interval *r; | ||
61 | struct snd_interval t = { .min = 1, .max = 2, .integer = 1, }; | ||
62 | unsigned int i; | ||
63 | const u8 *sad, *eld = rule->private; | ||
64 | |||
65 | sad = drm_eld_sad(eld); | ||
66 | if (sad) { | ||
67 | unsigned int rate_mask = 0; | ||
68 | |||
69 | /* Convert the rate interval to a mask */ | ||
70 | r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
71 | for (i = 0; i < ARRAY_SIZE(eld_rates); i++) | ||
72 | if (r->min <= eld_rates[i] && r->max >= eld_rates[i]) | ||
73 | rate_mask |= BIT(i); | ||
74 | |||
75 | for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) | ||
76 | if (rate_mask & sad[1]) | ||
77 | t.max = max(t.max, sad_max_channels(sad)); | ||
78 | } | ||
79 | |||
80 | return snd_interval_refine(c, &t); | ||
81 | } | ||
82 | |||
83 | int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld) | ||
84 | { | ||
85 | int ret; | ||
86 | |||
87 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
88 | eld_limit_rates, eld, | ||
89 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
90 | if (ret < 0) | ||
91 | return ret; | ||
92 | |||
93 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
94 | eld_limit_channels, eld, | ||
95 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld); | ||
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c new file mode 100644 index 000000000000..36b2d7aca1bd --- /dev/null +++ b/sound/core/pcm_iec958.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * PCM DRM helpers | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <linux/export.h> | ||
9 | #include <linux/types.h> | ||
10 | #include <sound/asoundef.h> | ||
11 | #include <sound/pcm.h> | ||
12 | #include <sound/pcm_iec958.h> | ||
13 | |||
14 | /** | ||
15 | * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status | ||
16 | * @runtime: pcm runtime structure with ->rate filled in | ||
17 | * @cs: channel status buffer, at least four bytes | ||
18 | * @len: length of channel status buffer | ||
19 | * | ||
20 | * Create the consumer format channel status data in @cs of maximum size | ||
21 | * @len corresponding to the parameters of the PCM runtime @runtime. | ||
22 | * | ||
23 | * Drivers may wish to tweak the contents of the buffer after creation. | ||
24 | * | ||
25 | * Returns: length of buffer, or negative error code if something failed. | ||
26 | */ | ||
27 | int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, | ||
28 | size_t len) | ||
29 | { | ||
30 | unsigned int fs, ws; | ||
31 | |||
32 | if (len < 4) | ||
33 | return -EINVAL; | ||
34 | |||
35 | switch (runtime->rate) { | ||
36 | case 32000: | ||
37 | fs = IEC958_AES3_CON_FS_32000; | ||
38 | break; | ||
39 | case 44100: | ||
40 | fs = IEC958_AES3_CON_FS_44100; | ||
41 | break; | ||
42 | case 48000: | ||
43 | fs = IEC958_AES3_CON_FS_48000; | ||
44 | break; | ||
45 | case 88200: | ||
46 | fs = IEC958_AES3_CON_FS_88200; | ||
47 | break; | ||
48 | case 96000: | ||
49 | fs = IEC958_AES3_CON_FS_96000; | ||
50 | break; | ||
51 | case 176400: | ||
52 | fs = IEC958_AES3_CON_FS_176400; | ||
53 | break; | ||
54 | case 192000: | ||
55 | fs = IEC958_AES3_CON_FS_192000; | ||
56 | break; | ||
57 | default: | ||
58 | return -EINVAL; | ||
59 | } | ||
60 | |||
61 | if (len > 4) { | ||
62 | switch (snd_pcm_format_width(runtime->format)) { | ||
63 | case 16: | ||
64 | ws = IEC958_AES4_CON_WORDLEN_20_16; | ||
65 | break; | ||
66 | case 18: | ||
67 | ws = IEC958_AES4_CON_WORDLEN_22_18; | ||
68 | break; | ||
69 | case 20: | ||
70 | ws = IEC958_AES4_CON_WORDLEN_20_16 | | ||
71 | IEC958_AES4_CON_MAX_WORDLEN_24; | ||
72 | break; | ||
73 | case 24: | ||
74 | ws = IEC958_AES4_CON_WORDLEN_24_20 | | ||
75 | IEC958_AES4_CON_MAX_WORDLEN_24; | ||
76 | break; | ||
77 | |||
78 | default: | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | memset(cs, 0, len); | ||
84 | |||
85 | cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; | ||
86 | cs[1] = IEC958_AES1_CON_GENERAL; | ||
87 | cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; | ||
88 | cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs; | ||
89 | |||
90 | if (len > 4) | ||
91 | cs[4] = ws; | ||
92 | |||
93 | return len; | ||
94 | } | ||
95 | EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); | ||
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ac6b33f3779c..7d45645f10ba 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -339,7 +339,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
339 | if (delta > new_hw_ptr) { | 339 | if (delta > new_hw_ptr) { |
340 | /* check for double acknowledged interrupts */ | 340 | /* check for double acknowledged interrupts */ |
341 | hdelta = curr_jiffies - runtime->hw_ptr_jiffies; | 341 | hdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
342 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { | 342 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2 + 1) { |
343 | hw_base += runtime->buffer_size; | 343 | hw_base += runtime->buffer_size; |
344 | if (hw_base >= runtime->boundary) { | 344 | if (hw_base >= runtime->boundary) { |
345 | hw_base = 0; | 345 | hw_base = 0; |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 941f64a853eb..b65fa5a1943b 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -6,7 +6,8 @@ | |||
6 | snd-seq-device-objs := seq_device.o | 6 | snd-seq-device-objs := seq_device.o |
7 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | 7 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ |
8 | seq_fifo.o seq_prioq.o seq_timer.o \ | 8 | seq_fifo.o seq_prioq.o seq_timer.o \ |
9 | seq_system.o seq_ports.o seq_info.o | 9 | seq_system.o seq_ports.o |
10 | snd-seq-$(CONFIG_SND_PROC_FS) += seq_info.o | ||
10 | snd-seq-midi-objs := seq_midi.o | 11 | snd-seq-midi-objs := seq_midi.o |
11 | snd-seq-midi-emul-objs := seq_midi_emul.o | 12 | snd-seq-midi-emul-objs := seq_midi_emul.o |
12 | snd-seq-midi-event-objs := seq_midi_event.o | 13 | snd-seq-midi-event-objs := seq_midi_event.o |
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 72873a46afeb..7354b8bed860 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c | |||
@@ -45,7 +45,7 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC); | |||
45 | */ | 45 | */ |
46 | static int register_device(void); | 46 | static int register_device(void); |
47 | static void unregister_device(void); | 47 | static void unregister_device(void); |
48 | #ifdef CONFIG_PROC_FS | 48 | #ifdef CONFIG_SND_PROC_FS |
49 | static int register_proc(void); | 49 | static int register_proc(void); |
50 | static void unregister_proc(void); | 50 | static void unregister_proc(void); |
51 | #else | 51 | #else |
@@ -261,7 +261,7 @@ unregister_device(void) | |||
261 | * /proc interface | 261 | * /proc interface |
262 | */ | 262 | */ |
263 | 263 | ||
264 | #ifdef CONFIG_PROC_FS | 264 | #ifdef CONFIG_SND_PROC_FS |
265 | 265 | ||
266 | static struct snd_info_entry *info_entry; | 266 | static struct snd_info_entry *info_entry; |
267 | 267 | ||
@@ -303,4 +303,4 @@ unregister_proc(void) | |||
303 | snd_info_free_entry(info_entry); | 303 | snd_info_free_entry(info_entry); |
304 | info_entry = NULL; | 304 | info_entry = NULL; |
305 | } | 305 | } |
306 | #endif /* CONFIG_PROC_FS */ | 306 | #endif /* CONFIG_SND_PROC_FS */ |
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 2de3feff70d0..b1221b29728e 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c | |||
@@ -479,8 +479,7 @@ snd_seq_oss_reset(struct seq_oss_devinfo *dp) | |||
479 | snd_seq_oss_timer_stop(dp->timer); | 479 | snd_seq_oss_timer_stop(dp->timer); |
480 | } | 480 | } |
481 | 481 | ||
482 | 482 | #ifdef CONFIG_SND_PROC_FS | |
483 | #ifdef CONFIG_PROC_FS | ||
484 | /* | 483 | /* |
485 | * misc. functions for proc interface | 484 | * misc. functions for proc interface |
486 | */ | 485 | */ |
@@ -531,4 +530,4 @@ snd_seq_oss_system_info_read(struct snd_info_buffer *buf) | |||
531 | snd_seq_oss_readq_info_read(dp->readq, buf); | 530 | snd_seq_oss_readq_info_read(dp->readq, buf); |
532 | } | 531 | } |
533 | } | 532 | } |
534 | #endif /* CONFIG_PROC_FS */ | 533 | #endif /* CONFIG_SND_PROC_FS */ |
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 96e8395ae586..aaff9ee32695 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c | |||
@@ -665,7 +665,7 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info | |||
665 | } | 665 | } |
666 | 666 | ||
667 | 667 | ||
668 | #ifdef CONFIG_PROC_FS | 668 | #ifdef CONFIG_SND_PROC_FS |
669 | /* | 669 | /* |
670 | * proc interface | 670 | * proc interface |
671 | */ | 671 | */ |
@@ -705,4 +705,4 @@ snd_seq_oss_midi_info_read(struct snd_info_buffer *buf) | |||
705 | snd_use_lock_free(&mdev->use_lock); | 705 | snd_use_lock_free(&mdev->use_lock); |
706 | } | 706 | } |
707 | } | 707 | } |
708 | #endif /* CONFIG_PROC_FS */ | 708 | #endif /* CONFIG_SND_PROC_FS */ |
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index c080c73cea04..ccd893566f1d 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c | |||
@@ -222,7 +222,7 @@ snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int | |||
222 | } | 222 | } |
223 | 223 | ||
224 | 224 | ||
225 | #ifdef CONFIG_PROC_FS | 225 | #ifdef CONFIG_SND_PROC_FS |
226 | /* | 226 | /* |
227 | * proc interface | 227 | * proc interface |
228 | */ | 228 | */ |
@@ -233,4 +233,4 @@ snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf | |||
233 | (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"), | 233 | (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"), |
234 | q->qlen, q->input_time); | 234 | q->qlen, q->input_time); |
235 | } | 235 | } |
236 | #endif /* CONFIG_PROC_FS */ | 236 | #endif /* CONFIG_SND_PROC_FS */ |
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 48e4fe1b68ab..0f3b38184fe5 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c | |||
@@ -630,7 +630,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in | |||
630 | } | 630 | } |
631 | 631 | ||
632 | 632 | ||
633 | #ifdef CONFIG_PROC_FS | 633 | #ifdef CONFIG_SND_PROC_FS |
634 | /* | 634 | /* |
635 | * proc interface | 635 | * proc interface |
636 | */ | 636 | */ |
@@ -658,4 +658,4 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf) | |||
658 | snd_use_lock_free(&rec->use_lock); | 658 | snd_use_lock_free(&rec->use_lock); |
659 | } | 659 | } |
660 | } | 660 | } |
661 | #endif /* CONFIG_PROC_FS */ | 661 | #endif /* CONFIG_SND_PROC_FS */ |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index edbdab85fc02..b64f20deba90 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -2447,7 +2447,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); | |||
2447 | 2447 | ||
2448 | /*---------------------------------------------------------------------------*/ | 2448 | /*---------------------------------------------------------------------------*/ |
2449 | 2449 | ||
2450 | #ifdef CONFIG_PROC_FS | 2450 | #ifdef CONFIG_SND_PROC_FS |
2451 | /* | 2451 | /* |
2452 | * /proc interface | 2452 | * /proc interface |
2453 | */ | 2453 | */ |
@@ -2549,7 +2549,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, | |||
2549 | snd_seq_client_unlock(client); | 2549 | snd_seq_client_unlock(client); |
2550 | } | 2550 | } |
2551 | } | 2551 | } |
2552 | #endif /* CONFIG_PROC_FS */ | 2552 | #endif /* CONFIG_SND_PROC_FS */ |
2553 | 2553 | ||
2554 | /*---------------------------------------------------------------------------*/ | 2554 | /*---------------------------------------------------------------------------*/ |
2555 | 2555 | ||
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index d99f99d61983..c4acf17e9f5e 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c | |||
@@ -72,7 +72,7 @@ static struct bus_type snd_seq_bus_type = { | |||
72 | /* | 72 | /* |
73 | * proc interface -- just for compatibility | 73 | * proc interface -- just for compatibility |
74 | */ | 74 | */ |
75 | #ifdef CONFIG_PROC_FS | 75 | #ifdef CONFIG_SND_PROC_FS |
76 | static struct snd_info_entry *info_entry; | 76 | static struct snd_info_entry *info_entry; |
77 | 77 | ||
78 | static int print_dev_info(struct device *dev, void *data) | 78 | static int print_dev_info(struct device *dev, void *data) |
@@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(snd_seq_driver_unregister); | |||
272 | 272 | ||
273 | static int __init seq_dev_proc_init(void) | 273 | static int __init seq_dev_proc_init(void) |
274 | { | 274 | { |
275 | #ifdef CONFIG_PROC_FS | 275 | #ifdef CONFIG_SND_PROC_FS |
276 | info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", | 276 | info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", |
277 | snd_seq_root); | 277 | snd_seq_root); |
278 | if (info_entry == NULL) | 278 | if (info_entry == NULL) |
@@ -305,7 +305,7 @@ static void __exit alsa_seq_device_exit(void) | |||
305 | #ifdef CONFIG_MODULES | 305 | #ifdef CONFIG_MODULES |
306 | cancel_work_sync(&autoload_work); | 306 | cancel_work_sync(&autoload_work); |
307 | #endif | 307 | #endif |
308 | #ifdef CONFIG_PROC_FS | 308 | #ifdef CONFIG_SND_PROC_FS |
309 | snd_info_free_entry(info_entry); | 309 | snd_info_free_entry(info_entry); |
310 | #endif | 310 | #endif |
311 | bus_unregister(&snd_seq_bus_type); | 311 | bus_unregister(&snd_seq_bus_type); |
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index acf7769419f0..97015447b9b3 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "seq_clientmgr.h" | 27 | #include "seq_clientmgr.h" |
28 | #include "seq_timer.h" | 28 | #include "seq_timer.h" |
29 | 29 | ||
30 | #ifdef CONFIG_PROC_FS | ||
31 | static struct snd_info_entry *queues_entry; | 30 | static struct snd_info_entry *queues_entry; |
32 | static struct snd_info_entry *clients_entry; | 31 | static struct snd_info_entry *clients_entry; |
33 | static struct snd_info_entry *timer_entry; | 32 | static struct snd_info_entry *timer_entry; |
@@ -51,6 +50,13 @@ create_info_entry(char *name, void (*read)(struct snd_info_entry *, | |||
51 | return entry; | 50 | return entry; |
52 | } | 51 | } |
53 | 52 | ||
53 | static void free_info_entries(void) | ||
54 | { | ||
55 | snd_info_free_entry(queues_entry); | ||
56 | snd_info_free_entry(clients_entry); | ||
57 | snd_info_free_entry(timer_entry); | ||
58 | } | ||
59 | |||
54 | /* create all our /proc entries */ | 60 | /* create all our /proc entries */ |
55 | int __init snd_seq_info_init(void) | 61 | int __init snd_seq_info_init(void) |
56 | { | 62 | { |
@@ -59,14 +65,17 @@ int __init snd_seq_info_init(void) | |||
59 | clients_entry = create_info_entry("clients", | 65 | clients_entry = create_info_entry("clients", |
60 | snd_seq_info_clients_read); | 66 | snd_seq_info_clients_read); |
61 | timer_entry = create_info_entry("timer", snd_seq_info_timer_read); | 67 | timer_entry = create_info_entry("timer", snd_seq_info_timer_read); |
68 | if (!queues_entry || !clients_entry || !timer_entry) | ||
69 | goto error; | ||
62 | return 0; | 70 | return 0; |
71 | |||
72 | error: | ||
73 | free_info_entries(); | ||
74 | return -ENOMEM; | ||
63 | } | 75 | } |
64 | 76 | ||
65 | int __exit snd_seq_info_done(void) | 77 | int __exit snd_seq_info_done(void) |
66 | { | 78 | { |
67 | snd_info_free_entry(queues_entry); | 79 | free_info_entries(); |
68 | snd_info_free_entry(clients_entry); | ||
69 | snd_info_free_entry(timer_entry); | ||
70 | return 0; | 80 | return 0; |
71 | } | 81 | } |
72 | #endif | ||
diff --git a/sound/core/seq/seq_info.h b/sound/core/seq/seq_info.h index 4892a7f35c08..f8549f81a645 100644 --- a/sound/core/seq/seq_info.h +++ b/sound/core/seq/seq_info.h | |||
@@ -29,7 +29,7 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, struct snd_info_buffe | |||
29 | void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); | 29 | void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); |
30 | 30 | ||
31 | 31 | ||
32 | #ifdef CONFIG_PROC_FS | 32 | #ifdef CONFIG_SND_PROC_FS |
33 | int snd_seq_info_init( void ); | 33 | int snd_seq_info_init( void ); |
34 | int snd_seq_info_done( void ); | 34 | int snd_seq_info_done( void ); |
35 | #else | 35 | #else |
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index a0cda38205b9..7dfd0f429410 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c | |||
@@ -753,7 +753,7 @@ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) | |||
753 | 753 | ||
754 | /*----------------------------------------------------------------*/ | 754 | /*----------------------------------------------------------------*/ |
755 | 755 | ||
756 | #ifdef CONFIG_PROC_FS | 756 | #ifdef CONFIG_SND_PROC_FS |
757 | /* exported to seq_info.c */ | 757 | /* exported to seq_info.c */ |
758 | void snd_seq_info_queues_read(struct snd_info_entry *entry, | 758 | void snd_seq_info_queues_read(struct snd_info_entry *entry, |
759 | struct snd_info_buffer *buffer) | 759 | struct snd_info_buffer *buffer) |
@@ -787,5 +787,5 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, | |||
787 | queuefree(q); | 787 | queuefree(q); |
788 | } | 788 | } |
789 | } | 789 | } |
790 | #endif /* CONFIG_PROC_FS */ | 790 | #endif /* CONFIG_SND_PROC_FS */ |
791 | 791 | ||
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 186f1611103c..82b220c769c1 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -422,7 +422,7 @@ snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | 424 | ||
425 | #ifdef CONFIG_PROC_FS | 425 | #ifdef CONFIG_SND_PROC_FS |
426 | /* exported to seq_info.c */ | 426 | /* exported to seq_info.c */ |
427 | void snd_seq_info_timer_read(struct snd_info_entry *entry, | 427 | void snd_seq_info_timer_read(struct snd_info_entry *entry, |
428 | struct snd_info_buffer *buffer) | 428 | struct snd_info_buffer *buffer) |
@@ -449,5 +449,5 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, | |||
449 | queuefree(q); | 449 | queuefree(q); |
450 | } | 450 | } |
451 | } | 451 | } |
452 | #endif /* CONFIG_PROC_FS */ | 452 | #endif /* CONFIG_SND_PROC_FS */ |
453 | 453 | ||
diff --git a/sound/core/sound.c b/sound/core/sound.c index 5fc93d00572a..175f9e4e01c8 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -330,13 +330,10 @@ int snd_unregister_device(struct device *dev) | |||
330 | } | 330 | } |
331 | EXPORT_SYMBOL(snd_unregister_device); | 331 | EXPORT_SYMBOL(snd_unregister_device); |
332 | 332 | ||
333 | #ifdef CONFIG_PROC_FS | 333 | #ifdef CONFIG_SND_PROC_FS |
334 | /* | 334 | /* |
335 | * INFO PART | 335 | * INFO PART |
336 | */ | 336 | */ |
337 | |||
338 | static struct snd_info_entry *snd_minor_info_entry; | ||
339 | |||
340 | static const char *snd_device_type_name(int type) | 337 | static const char *snd_device_type_name(int type) |
341 | { | 338 | { |
342 | switch (type) { | 339 | switch (type) { |
@@ -389,23 +386,12 @@ int __init snd_minor_info_init(void) | |||
389 | struct snd_info_entry *entry; | 386 | struct snd_info_entry *entry; |
390 | 387 | ||
391 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); | 388 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); |
392 | if (entry) { | 389 | if (!entry) |
393 | entry->c.text.read = snd_minor_info_read; | 390 | return -ENOMEM; |
394 | if (snd_info_register(entry) < 0) { | 391 | entry->c.text.read = snd_minor_info_read; |
395 | snd_info_free_entry(entry); | 392 | return snd_info_register(entry); /* freed in error path */ |
396 | entry = NULL; | ||
397 | } | ||
398 | } | ||
399 | snd_minor_info_entry = entry; | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | int __exit snd_minor_info_done(void) | ||
404 | { | ||
405 | snd_info_free_entry(snd_minor_info_entry); | ||
406 | return 0; | ||
407 | } | 393 | } |
408 | #endif /* CONFIG_PROC_FS */ | 394 | #endif /* CONFIG_SND_PROC_FS */ |
409 | 395 | ||
410 | /* | 396 | /* |
411 | * INIT PART | 397 | * INIT PART |
@@ -423,7 +409,6 @@ static int __init alsa_sound_init(void) | |||
423 | unregister_chrdev(major, "alsa"); | 409 | unregister_chrdev(major, "alsa"); |
424 | return -ENOMEM; | 410 | return -ENOMEM; |
425 | } | 411 | } |
426 | snd_info_minor_register(); | ||
427 | #ifndef MODULE | 412 | #ifndef MODULE |
428 | pr_info("Advanced Linux Sound Architecture Driver Initialized.\n"); | 413 | pr_info("Advanced Linux Sound Architecture Driver Initialized.\n"); |
429 | #endif | 414 | #endif |
@@ -432,7 +417,6 @@ static int __init alsa_sound_init(void) | |||
432 | 417 | ||
433 | static void __exit alsa_sound_exit(void) | 418 | static void __exit alsa_sound_exit(void) |
434 | { | 419 | { |
435 | snd_info_minor_unregister(); | ||
436 | snd_info_done(); | 420 | snd_info_done(); |
437 | unregister_chrdev(major, "alsa"); | 421 | unregister_chrdev(major, "alsa"); |
438 | } | 422 | } |
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 573a65eb2b79..0ca9d72b2273 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
@@ -19,12 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifdef CONFIG_SND_OSSEMUL | ||
23 | |||
24 | #if !IS_ENABLED(CONFIG_SOUND) | ||
25 | #error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel." | ||
26 | #endif | ||
27 | |||
28 | #include <linux/init.h> | 22 | #include <linux/init.h> |
29 | #include <linux/export.h> | 23 | #include <linux/export.h> |
30 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -213,10 +207,7 @@ EXPORT_SYMBOL(snd_unregister_oss_device); | |||
213 | * INFO PART | 207 | * INFO PART |
214 | */ | 208 | */ |
215 | 209 | ||
216 | #ifdef CONFIG_PROC_FS | 210 | #ifdef CONFIG_SND_PROC_FS |
217 | |||
218 | static struct snd_info_entry *snd_minor_info_oss_entry; | ||
219 | |||
220 | static const char *snd_oss_device_type_name(int type) | 211 | static const char *snd_oss_device_type_name(int type) |
221 | { | 212 | { |
222 | switch (type) { | 213 | switch (type) { |
@@ -263,22 +254,9 @@ int __init snd_minor_info_oss_init(void) | |||
263 | struct snd_info_entry *entry; | 254 | struct snd_info_entry *entry; |
264 | 255 | ||
265 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); | 256 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); |
266 | if (entry) { | 257 | if (!entry) |
267 | entry->c.text.read = snd_minor_info_oss_read; | 258 | return -ENOMEM; |
268 | if (snd_info_register(entry) < 0) { | 259 | entry->c.text.read = snd_minor_info_oss_read; |
269 | snd_info_free_entry(entry); | 260 | return snd_info_register(entry); /* freed in error path */ |
270 | entry = NULL; | ||
271 | } | ||
272 | } | ||
273 | snd_minor_info_oss_entry = entry; | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int __exit snd_minor_info_oss_done(void) | ||
278 | { | ||
279 | snd_info_free_entry(snd_minor_info_oss_entry); | ||
280 | return 0; | ||
281 | } | 261 | } |
282 | #endif /* CONFIG_PROC_FS */ | 262 | #endif /* CONFIG_SND_PROC_FS */ |
283 | |||
284 | #endif /* CONFIG_SND_OSSEMUL */ | ||
diff --git a/sound/core/timer.c b/sound/core/timer.c index a9a1a047c521..31f40f03e5b7 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1034,7 +1034,7 @@ static int snd_timer_register_system(void) | |||
1034 | return snd_timer_global_register(timer); | 1034 | return snd_timer_global_register(timer); |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | #ifdef CONFIG_PROC_FS | 1037 | #ifdef CONFIG_SND_PROC_FS |
1038 | /* | 1038 | /* |
1039 | * Info interface | 1039 | * Info interface |
1040 | */ | 1040 | */ |
@@ -1104,7 +1104,7 @@ static void __exit snd_timer_proc_done(void) | |||
1104 | { | 1104 | { |
1105 | snd_info_free_entry(snd_timer_proc_entry); | 1105 | snd_info_free_entry(snd_timer_proc_entry); |
1106 | } | 1106 | } |
1107 | #else /* !CONFIG_PROC_FS */ | 1107 | #else /* !CONFIG_SND_PROC_FS */ |
1108 | #define snd_timer_proc_init() | 1108 | #define snd_timer_proc_init() |
1109 | #define snd_timer_proc_done() | 1109 | #define snd_timer_proc_done() |
1110 | #endif | 1110 | #endif |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 7f9126efc1e5..54f348a4fb78 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -1053,8 +1053,6 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) | |||
1053 | return 0; | 1053 | return 0; |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | #ifdef CONFIG_PROC_FS | ||
1057 | |||
1058 | static void print_dpcm_info(struct snd_info_buffer *buffer, | 1056 | static void print_dpcm_info(struct snd_info_buffer *buffer, |
1059 | struct loopback_pcm *dpcm, | 1057 | struct loopback_pcm *dpcm, |
1060 | const char *id) | 1058 | const char *id) |
@@ -1128,12 +1126,6 @@ static int loopback_proc_new(struct loopback *loopback, int cidx) | |||
1128 | return 0; | 1126 | return 0; |
1129 | } | 1127 | } |
1130 | 1128 | ||
1131 | #else /* !CONFIG_PROC_FS */ | ||
1132 | |||
1133 | #define loopback_proc_new(loopback, cidx) do { } while (0) | ||
1134 | |||
1135 | #endif | ||
1136 | |||
1137 | static int loopback_probe(struct platform_device *devptr) | 1129 | static int loopback_probe(struct platform_device *devptr) |
1138 | { | 1130 | { |
1139 | struct snd_card *card; | 1131 | struct snd_card *card; |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index d11baaf0f0b4..016e451ed506 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -156,13 +156,13 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) | |||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | struct dummy_model model_emu10k1 = { | 159 | static struct dummy_model model_emu10k1 = { |
160 | .name = "emu10k1", | 160 | .name = "emu10k1", |
161 | .playback_constraints = emu10k1_playback_constraints, | 161 | .playback_constraints = emu10k1_playback_constraints, |
162 | .buffer_bytes_max = 128 * 1024, | 162 | .buffer_bytes_max = 128 * 1024, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | struct dummy_model model_rme9652 = { | 165 | static struct dummy_model model_rme9652 = { |
166 | .name = "rme9652", | 166 | .name = "rme9652", |
167 | .buffer_bytes_max = 26 * 64 * 1024, | 167 | .buffer_bytes_max = 26 * 64 * 1024, |
168 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | 168 | .formats = SNDRV_PCM_FMTBIT_S32_LE, |
@@ -172,7 +172,7 @@ struct dummy_model model_rme9652 = { | |||
172 | .periods_max = 2, | 172 | .periods_max = 2, |
173 | }; | 173 | }; |
174 | 174 | ||
175 | struct dummy_model model_ice1712 = { | 175 | static struct dummy_model model_ice1712 = { |
176 | .name = "ice1712", | 176 | .name = "ice1712", |
177 | .buffer_bytes_max = 256 * 1024, | 177 | .buffer_bytes_max = 256 * 1024, |
178 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | 178 | .formats = SNDRV_PCM_FMTBIT_S32_LE, |
@@ -182,7 +182,7 @@ struct dummy_model model_ice1712 = { | |||
182 | .periods_max = 1024, | 182 | .periods_max = 1024, |
183 | }; | 183 | }; |
184 | 184 | ||
185 | struct dummy_model model_uda1341 = { | 185 | static struct dummy_model model_uda1341 = { |
186 | .name = "uda1341", | 186 | .name = "uda1341", |
187 | .buffer_bytes_max = 16380, | 187 | .buffer_bytes_max = 16380, |
188 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 188 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
@@ -192,7 +192,7 @@ struct dummy_model model_uda1341 = { | |||
192 | .periods_max = 255, | 192 | .periods_max = 255, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | struct dummy_model model_ac97 = { | 195 | static struct dummy_model model_ac97 = { |
196 | .name = "ac97", | 196 | .name = "ac97", |
197 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 197 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
198 | .channels_min = 2, | 198 | .channels_min = 2, |
@@ -202,7 +202,7 @@ struct dummy_model model_ac97 = { | |||
202 | .rate_max = 48000, | 202 | .rate_max = 48000, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | struct dummy_model model_ca0106 = { | 205 | static struct dummy_model model_ca0106 = { |
206 | .name = "ca0106", | 206 | .name = "ca0106", |
207 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 207 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
208 | .buffer_bytes_max = ((65536-64)*8), | 208 | .buffer_bytes_max = ((65536-64)*8), |
@@ -216,7 +216,7 @@ struct dummy_model model_ca0106 = { | |||
216 | .rate_max = 192000, | 216 | .rate_max = 192000, |
217 | }; | 217 | }; |
218 | 218 | ||
219 | struct dummy_model *dummy_models[] = { | 219 | static struct dummy_model *dummy_models[] = { |
220 | &model_emu10k1, | 220 | &model_emu10k1, |
221 | &model_rme9652, | 221 | &model_rme9652, |
222 | &model_ice1712, | 222 | &model_ice1712, |
@@ -914,7 +914,7 @@ static int snd_card_dummy_new_mixer(struct snd_dummy *dummy) | |||
914 | return 0; | 914 | return 0; |
915 | } | 915 | } |
916 | 916 | ||
917 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS) | 917 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_PROC_FS) |
918 | /* | 918 | /* |
919 | * proc interface | 919 | * proc interface |
920 | */ | 920 | */ |
@@ -1042,7 +1042,7 @@ static void dummy_proc_init(struct snd_dummy *chip) | |||
1042 | } | 1042 | } |
1043 | #else | 1043 | #else |
1044 | #define dummy_proc_init(x) | 1044 | #define dummy_proc_init(x) |
1045 | #endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */ | 1045 | #endif /* CONFIG_SND_DEBUG && CONFIG_SND_PROC_FS */ |
1046 | 1046 | ||
1047 | static int snd_dummy_probe(struct platform_device *devptr) | 1047 | static int snd_dummy_probe(struct platform_device *devptr) |
1048 | { | 1048 | { |
diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile index b94009b0b19f..c8eaa433d71a 100644 --- a/sound/drivers/opl4/Makefile +++ b/sound/drivers/opl4/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o | 6 | snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o |
7 | snd-opl4-lib-$(CONFIG_SND_PROC_FS) += opl4_proc.o | ||
7 | snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o | 8 | snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o |
8 | 9 | ||
9 | obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o | 10 | obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o |
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 3b0ee42a5343..89c7aa04b3bc 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c | |||
@@ -176,9 +176,7 @@ static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device) | |||
176 | 176 | ||
177 | static void snd_opl4_free(struct snd_opl4 *opl4) | 177 | static void snd_opl4_free(struct snd_opl4 *opl4) |
178 | { | 178 | { |
179 | #ifdef CONFIG_PROC_FS | ||
180 | snd_opl4_free_proc(opl4); | 179 | snd_opl4_free_proc(opl4); |
181 | #endif | ||
182 | release_and_free_resource(opl4->res_fm_port); | 180 | release_and_free_resource(opl4->res_fm_port); |
183 | release_and_free_resource(opl4->res_pcm_port); | 181 | release_and_free_resource(opl4->res_pcm_port); |
184 | kfree(opl4); | 182 | kfree(opl4); |
@@ -249,9 +247,7 @@ int snd_opl4_create(struct snd_card *card, | |||
249 | snd_opl4_enable_opl4(opl4); | 247 | snd_opl4_enable_opl4(opl4); |
250 | 248 | ||
251 | snd_opl4_create_mixer(opl4); | 249 | snd_opl4_create_mixer(opl4); |
252 | #ifdef CONFIG_PROC_FS | ||
253 | snd_opl4_create_proc(opl4); | 250 | snd_opl4_create_proc(opl4); |
254 | #endif | ||
255 | 251 | ||
256 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | 252 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) |
257 | opl4->seq_client = -1; | 253 | opl4->seq_client = -1; |
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h index 470e5a758a02..9a41bdebce6b 100644 --- a/sound/drivers/opl4/opl4_local.h +++ b/sound/drivers/opl4/opl4_local.h | |||
@@ -178,7 +178,7 @@ struct snd_opl4 { | |||
178 | spinlock_t reg_lock; | 178 | spinlock_t reg_lock; |
179 | struct snd_card *card; | 179 | struct snd_card *card; |
180 | 180 | ||
181 | #ifdef CONFIG_PROC_FS | 181 | #ifdef CONFIG_SND_PROC_FS |
182 | struct snd_info_entry *proc_entry; | 182 | struct snd_info_entry *proc_entry; |
183 | int memory_access; | 183 | int memory_access; |
184 | #endif | 184 | #endif |
@@ -207,10 +207,13 @@ void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, i | |||
207 | /* opl4_mixer.c */ | 207 | /* opl4_mixer.c */ |
208 | int snd_opl4_create_mixer(struct snd_opl4 *opl4); | 208 | int snd_opl4_create_mixer(struct snd_opl4 *opl4); |
209 | 209 | ||
210 | #ifdef CONFIG_PROC_FS | 210 | #ifdef CONFIG_SND_PROC_FS |
211 | /* opl4_proc.c */ | 211 | /* opl4_proc.c */ |
212 | int snd_opl4_create_proc(struct snd_opl4 *opl4); | 212 | int snd_opl4_create_proc(struct snd_opl4 *opl4); |
213 | void snd_opl4_free_proc(struct snd_opl4 *opl4); | 213 | void snd_opl4_free_proc(struct snd_opl4 *opl4); |
214 | #else | ||
215 | static inline int snd_opl4_create_proc(struct snd_opl4 *opl4) { return 0; } | ||
216 | static inline void snd_opl4_free_proc(struct snd_opl4 *opl4) {} | ||
214 | #endif | 217 | #endif |
215 | 218 | ||
216 | /* opl4_seq.c */ | 219 | /* opl4_seq.c */ |
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index 9b824bfc919d..cd2c07fa2ef4 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <sound/info.h> | 23 | #include <sound/info.h> |
24 | 24 | ||
25 | #ifdef CONFIG_PROC_FS | ||
26 | |||
27 | static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, | 25 | static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, |
28 | unsigned short mode, void **file_private_data) | 26 | unsigned short mode, void **file_private_data) |
29 | { | 27 | { |
@@ -129,5 +127,3 @@ void snd_opl4_free_proc(struct snd_opl4 *opl4) | |||
129 | { | 127 | { |
130 | snd_info_free_entry(opl4->proc_entry); | 128 | snd_info_free_entry(opl4->proc_entry); |
131 | } | 129 | } |
132 | |||
133 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index d9647bd84d0f..27e25bb78c97 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -42,16 +42,13 @@ struct snd_pcsp pcsp_chip; | |||
42 | static int snd_pcsp_create(struct snd_card *card) | 42 | static int snd_pcsp_create(struct snd_card *card) |
43 | { | 43 | { |
44 | static struct snd_device_ops ops = { }; | 44 | static struct snd_device_ops ops = { }; |
45 | struct timespec tp; | 45 | unsigned int resolution = hrtimer_resolution; |
46 | int err; | 46 | int err, div, min_div, order; |
47 | int div, min_div, order; | ||
48 | |||
49 | hrtimer_get_res(CLOCK_MONOTONIC, &tp); | ||
50 | 47 | ||
51 | if (!nopcm) { | 48 | if (!nopcm) { |
52 | if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { | 49 | if (resolution > PCSP_MAX_PERIOD_NS) { |
53 | printk(KERN_ERR "PCSP: Timer resolution is not sufficient " | 50 | printk(KERN_ERR "PCSP: Timer resolution is not sufficient " |
54 | "(%linS)\n", tp.tv_nsec); | 51 | "(%unS)\n", resolution); |
55 | printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " | 52 | printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " |
56 | "enabled.\n"); | 53 | "enabled.\n"); |
57 | printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); | 54 | printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); |
@@ -59,13 +56,13 @@ static int snd_pcsp_create(struct snd_card *card) | |||
59 | } | 56 | } |
60 | } | 57 | } |
61 | 58 | ||
62 | if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) | 59 | if (loops_per_jiffy >= PCSP_MIN_LPJ && resolution <= PCSP_MIN_PERIOD_NS) |
63 | min_div = MIN_DIV; | 60 | min_div = MIN_DIV; |
64 | else | 61 | else |
65 | min_div = MAX_DIV; | 62 | min_div = MAX_DIV; |
66 | #if PCSP_DEBUG | 63 | #if PCSP_DEBUG |
67 | printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n", | 64 | printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%u\n", |
68 | loops_per_jiffy, min_div, tp.tv_nsec); | 65 | loops_per_jiffy, min_div, resolution); |
69 | #endif | 66 | #endif |
70 | 67 | ||
71 | div = MAX_DIV / min_div; | 68 | div = MAX_DIV / min_div; |
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index ecec547782b2..8850b7de1d38 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -95,6 +95,7 @@ config SND_BEBOB | |||
95 | * Tascam IF-FW/DM | 95 | * Tascam IF-FW/DM |
96 | * Behringer XENIX UFX 1204/1604 | 96 | * Behringer XENIX UFX 1204/1604 |
97 | * Behringer Digital Mixer X32 series (X-UF Card) | 97 | * Behringer Digital Mixer X32 series (X-UF Card) |
98 | * Behringer FCA610/1616 | ||
98 | * Apogee Rosetta 200/400 (X-FireWire card) | 99 | * Apogee Rosetta 200/400 (X-FireWire card) |
99 | * Apogee DA/AD/DD-16X (X-FireWire card) | 100 | * Apogee DA/AD/DD-16X (X-FireWire card) |
100 | * Apogee Ensemble | 101 | * Apogee Ensemble |
@@ -114,6 +115,7 @@ config SND_BEBOB | |||
114 | * M-Audio FireWire410/AudioPhile/Solo | 115 | * M-Audio FireWire410/AudioPhile/Solo |
115 | * M-Audio Ozonic/NRV10/ProfireLightBridge | 116 | * M-Audio Ozonic/NRV10/ProfireLightBridge |
116 | * M-Audio FireWire 1814/ProjectMix IO | 117 | * M-Audio FireWire 1814/ProjectMix IO |
118 | * Digidesign Mbox 2 Pro | ||
117 | 119 | ||
118 | To compile this driver as a module, choose M here: the module | 120 | To compile this driver as a module, choose M here: the module |
119 | will be called snd-bebob. | 121 | will be called snd-bebob. |
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index e061355f535f..7bb988fa6b6d 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c | |||
@@ -40,24 +40,28 @@ | |||
40 | #define TAG_CIP 1 | 40 | #define TAG_CIP 1 |
41 | 41 | ||
42 | /* common isochronous packet header parameters */ | 42 | /* common isochronous packet header parameters */ |
43 | #define CIP_EOH (1u << 31) | 43 | #define CIP_EOH_SHIFT 31 |
44 | #define CIP_EOH (1u << CIP_EOH_SHIFT) | ||
44 | #define CIP_EOH_MASK 0x80000000 | 45 | #define CIP_EOH_MASK 0x80000000 |
45 | #define CIP_FMT_AM (0x10 << 24) | 46 | #define CIP_SID_SHIFT 24 |
47 | #define CIP_SID_MASK 0x3f000000 | ||
48 | #define CIP_DBS_MASK 0x00ff0000 | ||
49 | #define CIP_DBS_SHIFT 16 | ||
50 | #define CIP_DBC_MASK 0x000000ff | ||
51 | #define CIP_FMT_SHIFT 24 | ||
46 | #define CIP_FMT_MASK 0x3f000000 | 52 | #define CIP_FMT_MASK 0x3f000000 |
53 | #define CIP_FDF_MASK 0x00ff0000 | ||
54 | #define CIP_FDF_SHIFT 16 | ||
47 | #define CIP_SYT_MASK 0x0000ffff | 55 | #define CIP_SYT_MASK 0x0000ffff |
48 | #define CIP_SYT_NO_INFO 0xffff | 56 | #define CIP_SYT_NO_INFO 0xffff |
49 | #define CIP_FDF_MASK 0x00ff0000 | ||
50 | #define CIP_FDF_SFC_SHIFT 16 | ||
51 | 57 | ||
52 | /* | 58 | /* |
53 | * Audio and Music transfer protocol specific parameters | 59 | * Audio and Music transfer protocol specific parameters |
54 | * only "Clock-based rate control mode" is supported | 60 | * only "Clock-based rate control mode" is supported |
55 | */ | 61 | */ |
56 | #define AMDTP_FDF_AM824 (0 << (CIP_FDF_SFC_SHIFT + 3)) | 62 | #define CIP_FMT_AM (0x10 << CIP_FMT_SHIFT) |
63 | #define AMDTP_FDF_AM824 (0 << (CIP_FDF_SHIFT + 3)) | ||
57 | #define AMDTP_FDF_NO_DATA 0xff | 64 | #define AMDTP_FDF_NO_DATA 0xff |
58 | #define AMDTP_DBS_MASK 0x00ff0000 | ||
59 | #define AMDTP_DBS_SHIFT 16 | ||
60 | #define AMDTP_DBC_MASK 0x000000ff | ||
61 | 65 | ||
62 | /* TODO: make these configurable */ | 66 | /* TODO: make these configurable */ |
63 | #define INTERRUPT_INTERVAL 16 | 67 | #define INTERRUPT_INTERVAL 16 |
@@ -251,19 +255,24 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters); | |||
251 | */ | 255 | */ |
252 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) | 256 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) |
253 | { | 257 | { |
254 | return 8 + s->syt_interval * s->data_block_quadlets * 4; | 258 | unsigned int multiplier = 1; |
259 | |||
260 | if (s->flags & CIP_JUMBO_PAYLOAD) | ||
261 | multiplier = 5; | ||
262 | |||
263 | return 8 + s->syt_interval * s->data_block_quadlets * 4 * multiplier; | ||
255 | } | 264 | } |
256 | EXPORT_SYMBOL(amdtp_stream_get_max_payload); | 265 | EXPORT_SYMBOL(amdtp_stream_get_max_payload); |
257 | 266 | ||
258 | static void amdtp_write_s16(struct amdtp_stream *s, | 267 | static void write_pcm_s16(struct amdtp_stream *s, |
259 | struct snd_pcm_substream *pcm, | 268 | struct snd_pcm_substream *pcm, |
260 | __be32 *buffer, unsigned int frames); | 269 | __be32 *buffer, unsigned int frames); |
261 | static void amdtp_write_s32(struct amdtp_stream *s, | 270 | static void write_pcm_s32(struct amdtp_stream *s, |
262 | struct snd_pcm_substream *pcm, | 271 | struct snd_pcm_substream *pcm, |
263 | __be32 *buffer, unsigned int frames); | 272 | __be32 *buffer, unsigned int frames); |
264 | static void amdtp_read_s32(struct amdtp_stream *s, | 273 | static void read_pcm_s32(struct amdtp_stream *s, |
265 | struct snd_pcm_substream *pcm, | 274 | struct snd_pcm_substream *pcm, |
266 | __be32 *buffer, unsigned int frames); | 275 | __be32 *buffer, unsigned int frames); |
267 | 276 | ||
268 | /** | 277 | /** |
269 | * amdtp_stream_set_pcm_format - set the PCM format | 278 | * amdtp_stream_set_pcm_format - set the PCM format |
@@ -286,16 +295,16 @@ void amdtp_stream_set_pcm_format(struct amdtp_stream *s, | |||
286 | /* fall through */ | 295 | /* fall through */ |
287 | case SNDRV_PCM_FORMAT_S16: | 296 | case SNDRV_PCM_FORMAT_S16: |
288 | if (s->direction == AMDTP_OUT_STREAM) { | 297 | if (s->direction == AMDTP_OUT_STREAM) { |
289 | s->transfer_samples = amdtp_write_s16; | 298 | s->transfer_samples = write_pcm_s16; |
290 | break; | 299 | break; |
291 | } | 300 | } |
292 | WARN_ON(1); | 301 | WARN_ON(1); |
293 | /* fall through */ | 302 | /* fall through */ |
294 | case SNDRV_PCM_FORMAT_S32: | 303 | case SNDRV_PCM_FORMAT_S32: |
295 | if (s->direction == AMDTP_OUT_STREAM) | 304 | if (s->direction == AMDTP_OUT_STREAM) |
296 | s->transfer_samples = amdtp_write_s32; | 305 | s->transfer_samples = write_pcm_s32; |
297 | else | 306 | else |
298 | s->transfer_samples = amdtp_read_s32; | 307 | s->transfer_samples = read_pcm_s32; |
299 | break; | 308 | break; |
300 | } | 309 | } |
301 | } | 310 | } |
@@ -316,17 +325,25 @@ void amdtp_stream_pcm_prepare(struct amdtp_stream *s) | |||
316 | } | 325 | } |
317 | EXPORT_SYMBOL(amdtp_stream_pcm_prepare); | 326 | EXPORT_SYMBOL(amdtp_stream_pcm_prepare); |
318 | 327 | ||
319 | static unsigned int calculate_data_blocks(struct amdtp_stream *s) | 328 | static unsigned int calculate_data_blocks(struct amdtp_stream *s, |
329 | unsigned int syt) | ||
320 | { | 330 | { |
321 | unsigned int phase, data_blocks; | 331 | unsigned int phase, data_blocks; |
322 | 332 | ||
323 | if (s->flags & CIP_BLOCKING) | 333 | /* Blocking mode. */ |
324 | data_blocks = s->syt_interval; | 334 | if (s->flags & CIP_BLOCKING) { |
325 | else if (!cip_sfc_is_base_44100(s->sfc)) { | 335 | /* This module generate empty packet for 'no data'. */ |
326 | /* Sample_rate / 8000 is an integer, and precomputed. */ | 336 | if (syt == CIP_SYT_NO_INFO) |
327 | data_blocks = s->data_block_state; | 337 | data_blocks = 0; |
338 | else | ||
339 | data_blocks = s->syt_interval; | ||
340 | /* Non-blocking mode. */ | ||
328 | } else { | 341 | } else { |
329 | phase = s->data_block_state; | 342 | if (!cip_sfc_is_base_44100(s->sfc)) { |
343 | /* Sample_rate / 8000 is an integer, and precomputed. */ | ||
344 | data_blocks = s->data_block_state; | ||
345 | } else { | ||
346 | phase = s->data_block_state; | ||
330 | 347 | ||
331 | /* | 348 | /* |
332 | * This calculates the number of data blocks per packet so that | 349 | * This calculates the number of data blocks per packet so that |
@@ -336,16 +353,17 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s) | |||
336 | * as possible in the sequence (to prevent underruns of the | 353 | * as possible in the sequence (to prevent underruns of the |
337 | * device's buffer). | 354 | * device's buffer). |
338 | */ | 355 | */ |
339 | if (s->sfc == CIP_SFC_44100) | 356 | if (s->sfc == CIP_SFC_44100) |
340 | /* 6 6 5 6 5 6 5 ... */ | 357 | /* 6 6 5 6 5 6 5 ... */ |
341 | data_blocks = 5 + ((phase & 1) ^ | 358 | data_blocks = 5 + ((phase & 1) ^ |
342 | (phase == 0 || phase >= 40)); | 359 | (phase == 0 || phase >= 40)); |
343 | else | 360 | else |
344 | /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ | 361 | /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ |
345 | data_blocks = 11 * (s->sfc >> 1) + (phase == 0); | 362 | data_blocks = 11 * (s->sfc >> 1) + (phase == 0); |
346 | if (++phase >= (80 >> (s->sfc >> 1))) | 363 | if (++phase >= (80 >> (s->sfc >> 1))) |
347 | phase = 0; | 364 | phase = 0; |
348 | s->data_block_state = phase; | 365 | s->data_block_state = phase; |
366 | } | ||
349 | } | 367 | } |
350 | 368 | ||
351 | return data_blocks; | 369 | return data_blocks; |
@@ -394,9 +412,9 @@ static unsigned int calculate_syt(struct amdtp_stream *s, | |||
394 | } | 412 | } |
395 | } | 413 | } |
396 | 414 | ||
397 | static void amdtp_write_s32(struct amdtp_stream *s, | 415 | static void write_pcm_s32(struct amdtp_stream *s, |
398 | struct snd_pcm_substream *pcm, | 416 | struct snd_pcm_substream *pcm, |
399 | __be32 *buffer, unsigned int frames) | 417 | __be32 *buffer, unsigned int frames) |
400 | { | 418 | { |
401 | struct snd_pcm_runtime *runtime = pcm->runtime; | 419 | struct snd_pcm_runtime *runtime = pcm->runtime; |
402 | unsigned int channels, remaining_frames, i, c; | 420 | unsigned int channels, remaining_frames, i, c; |
@@ -419,9 +437,9 @@ static void amdtp_write_s32(struct amdtp_stream *s, | |||
419 | } | 437 | } |
420 | } | 438 | } |
421 | 439 | ||
422 | static void amdtp_write_s16(struct amdtp_stream *s, | 440 | static void write_pcm_s16(struct amdtp_stream *s, |
423 | struct snd_pcm_substream *pcm, | 441 | struct snd_pcm_substream *pcm, |
424 | __be32 *buffer, unsigned int frames) | 442 | __be32 *buffer, unsigned int frames) |
425 | { | 443 | { |
426 | struct snd_pcm_runtime *runtime = pcm->runtime; | 444 | struct snd_pcm_runtime *runtime = pcm->runtime; |
427 | unsigned int channels, remaining_frames, i, c; | 445 | unsigned int channels, remaining_frames, i, c; |
@@ -444,9 +462,9 @@ static void amdtp_write_s16(struct amdtp_stream *s, | |||
444 | } | 462 | } |
445 | } | 463 | } |
446 | 464 | ||
447 | static void amdtp_read_s32(struct amdtp_stream *s, | 465 | static void read_pcm_s32(struct amdtp_stream *s, |
448 | struct snd_pcm_substream *pcm, | 466 | struct snd_pcm_substream *pcm, |
449 | __be32 *buffer, unsigned int frames) | 467 | __be32 *buffer, unsigned int frames) |
450 | { | 468 | { |
451 | struct snd_pcm_runtime *runtime = pcm->runtime; | 469 | struct snd_pcm_runtime *runtime = pcm->runtime; |
452 | unsigned int channels, remaining_frames, i, c; | 470 | unsigned int channels, remaining_frames, i, c; |
@@ -468,8 +486,8 @@ static void amdtp_read_s32(struct amdtp_stream *s, | |||
468 | } | 486 | } |
469 | } | 487 | } |
470 | 488 | ||
471 | static void amdtp_fill_pcm_silence(struct amdtp_stream *s, | 489 | static void write_pcm_silence(struct amdtp_stream *s, |
472 | __be32 *buffer, unsigned int frames) | 490 | __be32 *buffer, unsigned int frames) |
473 | { | 491 | { |
474 | unsigned int i, c; | 492 | unsigned int i, c; |
475 | 493 | ||
@@ -510,8 +528,8 @@ static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port) | |||
510 | s->midi_fifo_used[port] += amdtp_rate_table[s->sfc]; | 528 | s->midi_fifo_used[port] += amdtp_rate_table[s->sfc]; |
511 | } | 529 | } |
512 | 530 | ||
513 | static void amdtp_fill_midi(struct amdtp_stream *s, | 531 | static void write_midi_messages(struct amdtp_stream *s, |
514 | __be32 *buffer, unsigned int frames) | 532 | __be32 *buffer, unsigned int frames) |
515 | { | 533 | { |
516 | unsigned int f, port; | 534 | unsigned int f, port; |
517 | u8 *b; | 535 | u8 *b; |
@@ -537,8 +555,8 @@ static void amdtp_fill_midi(struct amdtp_stream *s, | |||
537 | } | 555 | } |
538 | } | 556 | } |
539 | 557 | ||
540 | static void amdtp_pull_midi(struct amdtp_stream *s, | 558 | static void read_midi_messages(struct amdtp_stream *s, |
541 | __be32 *buffer, unsigned int frames) | 559 | __be32 *buffer, unsigned int frames) |
542 | { | 560 | { |
543 | unsigned int f, port; | 561 | unsigned int f, port; |
544 | int len; | 562 | int len; |
@@ -633,57 +651,48 @@ static inline int queue_in_packet(struct amdtp_stream *s) | |||
633 | amdtp_stream_get_max_payload(s), false); | 651 | amdtp_stream_get_max_payload(s), false); |
634 | } | 652 | } |
635 | 653 | ||
636 | static void handle_out_packet(struct amdtp_stream *s, unsigned int syt) | 654 | static int handle_out_packet(struct amdtp_stream *s, unsigned int data_blocks, |
655 | unsigned int syt) | ||
637 | { | 656 | { |
638 | __be32 *buffer; | 657 | __be32 *buffer; |
639 | unsigned int data_blocks, payload_length; | 658 | unsigned int payload_length; |
640 | struct snd_pcm_substream *pcm; | 659 | struct snd_pcm_substream *pcm; |
641 | 660 | ||
642 | if (s->packet_index < 0) | ||
643 | return; | ||
644 | |||
645 | /* this module generate empty packet for 'no data' */ | ||
646 | if (!(s->flags & CIP_BLOCKING) || (syt != CIP_SYT_NO_INFO)) | ||
647 | data_blocks = calculate_data_blocks(s); | ||
648 | else | ||
649 | data_blocks = 0; | ||
650 | |||
651 | buffer = s->buffer.packets[s->packet_index].buffer; | 661 | buffer = s->buffer.packets[s->packet_index].buffer; |
652 | buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | | 662 | buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | |
653 | (s->data_block_quadlets << AMDTP_DBS_SHIFT) | | 663 | (s->data_block_quadlets << CIP_DBS_SHIFT) | |
654 | s->data_block_counter); | 664 | s->data_block_counter); |
655 | buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | | 665 | buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | |
656 | (s->sfc << CIP_FDF_SFC_SHIFT) | syt); | 666 | (s->sfc << CIP_FDF_SHIFT) | syt); |
657 | buffer += 2; | 667 | buffer += 2; |
658 | 668 | ||
659 | pcm = ACCESS_ONCE(s->pcm); | 669 | pcm = ACCESS_ONCE(s->pcm); |
660 | if (pcm) | 670 | if (pcm) |
661 | s->transfer_samples(s, pcm, buffer, data_blocks); | 671 | s->transfer_samples(s, pcm, buffer, data_blocks); |
662 | else | 672 | else |
663 | amdtp_fill_pcm_silence(s, buffer, data_blocks); | 673 | write_pcm_silence(s, buffer, data_blocks); |
664 | if (s->midi_ports) | 674 | if (s->midi_ports) |
665 | amdtp_fill_midi(s, buffer, data_blocks); | 675 | write_midi_messages(s, buffer, data_blocks); |
666 | 676 | ||
667 | s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; | 677 | s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; |
668 | 678 | ||
669 | payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; | 679 | payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; |
670 | if (queue_out_packet(s, payload_length, false) < 0) { | 680 | if (queue_out_packet(s, payload_length, false) < 0) |
671 | s->packet_index = -1; | 681 | return -EIO; |
672 | amdtp_stream_pcm_abort(s); | ||
673 | return; | ||
674 | } | ||
675 | 682 | ||
676 | if (pcm) | 683 | if (pcm) |
677 | update_pcm_pointers(s, pcm, data_blocks); | 684 | update_pcm_pointers(s, pcm, data_blocks); |
685 | |||
686 | /* No need to return the number of handled data blocks. */ | ||
687 | return 0; | ||
678 | } | 688 | } |
679 | 689 | ||
680 | static void handle_in_packet(struct amdtp_stream *s, | 690 | static int handle_in_packet(struct amdtp_stream *s, |
681 | unsigned int payload_quadlets, | 691 | unsigned int payload_quadlets, __be32 *buffer, |
682 | __be32 *buffer) | 692 | unsigned int *data_blocks) |
683 | { | 693 | { |
684 | u32 cip_header[2]; | 694 | u32 cip_header[2]; |
685 | unsigned int data_blocks, data_block_quadlets, data_block_counter, | 695 | unsigned int data_block_quadlets, data_block_counter, dbc_interval; |
686 | dbc_interval; | ||
687 | struct snd_pcm_substream *pcm = NULL; | 696 | struct snd_pcm_substream *pcm = NULL; |
688 | bool lost; | 697 | bool lost; |
689 | 698 | ||
@@ -700,33 +709,34 @@ static void handle_in_packet(struct amdtp_stream *s, | |||
700 | dev_info_ratelimited(&s->unit->device, | 709 | dev_info_ratelimited(&s->unit->device, |
701 | "Invalid CIP header for AMDTP: %08X:%08X\n", | 710 | "Invalid CIP header for AMDTP: %08X:%08X\n", |
702 | cip_header[0], cip_header[1]); | 711 | cip_header[0], cip_header[1]); |
712 | *data_blocks = 0; | ||
703 | goto end; | 713 | goto end; |
704 | } | 714 | } |
705 | 715 | ||
706 | /* Calculate data blocks */ | 716 | /* Calculate data blocks */ |
707 | if (payload_quadlets < 3 || | 717 | if (payload_quadlets < 3 || |
708 | ((cip_header[1] & CIP_FDF_MASK) == | 718 | ((cip_header[1] & CIP_FDF_MASK) == |
709 | (AMDTP_FDF_NO_DATA << CIP_FDF_SFC_SHIFT))) { | 719 | (AMDTP_FDF_NO_DATA << CIP_FDF_SHIFT))) { |
710 | data_blocks = 0; | 720 | *data_blocks = 0; |
711 | } else { | 721 | } else { |
712 | data_block_quadlets = | 722 | data_block_quadlets = |
713 | (cip_header[0] & AMDTP_DBS_MASK) >> AMDTP_DBS_SHIFT; | 723 | (cip_header[0] & CIP_DBS_MASK) >> CIP_DBS_SHIFT; |
714 | /* avoid division by zero */ | 724 | /* avoid division by zero */ |
715 | if (data_block_quadlets == 0) { | 725 | if (data_block_quadlets == 0) { |
716 | dev_info_ratelimited(&s->unit->device, | 726 | dev_err(&s->unit->device, |
717 | "Detect invalid value in dbs field: %08X\n", | 727 | "Detect invalid value in dbs field: %08X\n", |
718 | cip_header[0]); | 728 | cip_header[0]); |
719 | goto err; | 729 | return -EPROTO; |
720 | } | 730 | } |
721 | if (s->flags & CIP_WRONG_DBS) | 731 | if (s->flags & CIP_WRONG_DBS) |
722 | data_block_quadlets = s->data_block_quadlets; | 732 | data_block_quadlets = s->data_block_quadlets; |
723 | 733 | ||
724 | data_blocks = (payload_quadlets - 2) / data_block_quadlets; | 734 | *data_blocks = (payload_quadlets - 2) / data_block_quadlets; |
725 | } | 735 | } |
726 | 736 | ||
727 | /* Check data block counter continuity */ | 737 | /* Check data block counter continuity */ |
728 | data_block_counter = cip_header[0] & AMDTP_DBC_MASK; | 738 | data_block_counter = cip_header[0] & CIP_DBC_MASK; |
729 | if (data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && | 739 | if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && |
730 | s->data_block_counter != UINT_MAX) | 740 | s->data_block_counter != UINT_MAX) |
731 | data_block_counter = s->data_block_counter; | 741 | data_block_counter = s->data_block_counter; |
732 | 742 | ||
@@ -736,49 +746,46 @@ static void handle_in_packet(struct amdtp_stream *s, | |||
736 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | 746 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { |
737 | lost = data_block_counter != s->data_block_counter; | 747 | lost = data_block_counter != s->data_block_counter; |
738 | } else { | 748 | } else { |
739 | if ((data_blocks > 0) && (s->tx_dbc_interval > 0)) | 749 | if ((*data_blocks > 0) && (s->tx_dbc_interval > 0)) |
740 | dbc_interval = s->tx_dbc_interval; | 750 | dbc_interval = s->tx_dbc_interval; |
741 | else | 751 | else |
742 | dbc_interval = data_blocks; | 752 | dbc_interval = *data_blocks; |
743 | 753 | ||
744 | lost = data_block_counter != | 754 | lost = data_block_counter != |
745 | ((s->data_block_counter + dbc_interval) & 0xff); | 755 | ((s->data_block_counter + dbc_interval) & 0xff); |
746 | } | 756 | } |
747 | 757 | ||
748 | if (lost) { | 758 | if (lost) { |
749 | dev_info(&s->unit->device, | 759 | dev_err(&s->unit->device, |
750 | "Detect discontinuity of CIP: %02X %02X\n", | 760 | "Detect discontinuity of CIP: %02X %02X\n", |
751 | s->data_block_counter, data_block_counter); | 761 | s->data_block_counter, data_block_counter); |
752 | goto err; | 762 | return -EIO; |
753 | } | 763 | } |
754 | 764 | ||
755 | if (data_blocks > 0) { | 765 | if (*data_blocks > 0) { |
756 | buffer += 2; | 766 | buffer += 2; |
757 | 767 | ||
758 | pcm = ACCESS_ONCE(s->pcm); | 768 | pcm = ACCESS_ONCE(s->pcm); |
759 | if (pcm) | 769 | if (pcm) |
760 | s->transfer_samples(s, pcm, buffer, data_blocks); | 770 | s->transfer_samples(s, pcm, buffer, *data_blocks); |
761 | 771 | ||
762 | if (s->midi_ports) | 772 | if (s->midi_ports) |
763 | amdtp_pull_midi(s, buffer, data_blocks); | 773 | read_midi_messages(s, buffer, *data_blocks); |
764 | } | 774 | } |
765 | 775 | ||
766 | if (s->flags & CIP_DBC_IS_END_EVENT) | 776 | if (s->flags & CIP_DBC_IS_END_EVENT) |
767 | s->data_block_counter = data_block_counter; | 777 | s->data_block_counter = data_block_counter; |
768 | else | 778 | else |
769 | s->data_block_counter = | 779 | s->data_block_counter = |
770 | (data_block_counter + data_blocks) & 0xff; | 780 | (data_block_counter + *data_blocks) & 0xff; |
771 | end: | 781 | end: |
772 | if (queue_in_packet(s) < 0) | 782 | if (queue_in_packet(s) < 0) |
773 | goto err; | 783 | return -EIO; |
774 | 784 | ||
775 | if (pcm) | 785 | if (pcm) |
776 | update_pcm_pointers(s, pcm, data_blocks); | 786 | update_pcm_pointers(s, pcm, *data_blocks); |
777 | 787 | ||
778 | return; | 788 | return 0; |
779 | err: | ||
780 | s->packet_index = -1; | ||
781 | amdtp_stream_pcm_abort(s); | ||
782 | } | 789 | } |
783 | 790 | ||
784 | static void out_stream_callback(struct fw_iso_context *context, u32 cycle, | 791 | static void out_stream_callback(struct fw_iso_context *context, u32 cycle, |
@@ -787,6 +794,10 @@ static void out_stream_callback(struct fw_iso_context *context, u32 cycle, | |||
787 | { | 794 | { |
788 | struct amdtp_stream *s = private_data; | 795 | struct amdtp_stream *s = private_data; |
789 | unsigned int i, syt, packets = header_length / 4; | 796 | unsigned int i, syt, packets = header_length / 4; |
797 | unsigned int data_blocks; | ||
798 | |||
799 | if (s->packet_index < 0) | ||
800 | return; | ||
790 | 801 | ||
791 | /* | 802 | /* |
792 | * Compute the cycle of the last queued packet. | 803 | * Compute the cycle of the last queued packet. |
@@ -797,8 +808,15 @@ static void out_stream_callback(struct fw_iso_context *context, u32 cycle, | |||
797 | 808 | ||
798 | for (i = 0; i < packets; ++i) { | 809 | for (i = 0; i < packets; ++i) { |
799 | syt = calculate_syt(s, ++cycle); | 810 | syt = calculate_syt(s, ++cycle); |
800 | handle_out_packet(s, syt); | 811 | data_blocks = calculate_data_blocks(s, syt); |
812 | |||
813 | if (handle_out_packet(s, data_blocks, syt) < 0) { | ||
814 | s->packet_index = -1; | ||
815 | amdtp_stream_pcm_abort(s); | ||
816 | return; | ||
817 | } | ||
801 | } | 818 | } |
819 | |||
802 | fw_iso_context_queue_flush(s->context); | 820 | fw_iso_context_queue_flush(s->context); |
803 | } | 821 | } |
804 | 822 | ||
@@ -807,32 +825,55 @@ static void in_stream_callback(struct fw_iso_context *context, u32 cycle, | |||
807 | void *private_data) | 825 | void *private_data) |
808 | { | 826 | { |
809 | struct amdtp_stream *s = private_data; | 827 | struct amdtp_stream *s = private_data; |
810 | unsigned int p, syt, packets, payload_quadlets; | 828 | unsigned int p, syt, packets; |
829 | unsigned int payload_quadlets, max_payload_quadlets; | ||
830 | unsigned int data_blocks; | ||
811 | __be32 *buffer, *headers = header; | 831 | __be32 *buffer, *headers = header; |
812 | 832 | ||
833 | if (s->packet_index < 0) | ||
834 | return; | ||
835 | |||
813 | /* The number of packets in buffer */ | 836 | /* The number of packets in buffer */ |
814 | packets = header_length / IN_PACKET_HEADER_SIZE; | 837 | packets = header_length / IN_PACKET_HEADER_SIZE; |
815 | 838 | ||
839 | /* For buffer-over-run prevention. */ | ||
840 | max_payload_quadlets = amdtp_stream_get_max_payload(s) / 4; | ||
841 | |||
816 | for (p = 0; p < packets; p++) { | 842 | for (p = 0; p < packets; p++) { |
817 | if (s->packet_index < 0) | 843 | buffer = s->buffer.packets[s->packet_index].buffer; |
844 | |||
845 | /* The number of quadlets in this packet */ | ||
846 | payload_quadlets = | ||
847 | (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4; | ||
848 | if (payload_quadlets > max_payload_quadlets) { | ||
849 | dev_err(&s->unit->device, | ||
850 | "Detect jumbo payload: %02x %02x\n", | ||
851 | payload_quadlets, max_payload_quadlets); | ||
852 | s->packet_index = -1; | ||
818 | break; | 853 | break; |
854 | } | ||
819 | 855 | ||
820 | buffer = s->buffer.packets[s->packet_index].buffer; | 856 | if (handle_in_packet(s, payload_quadlets, buffer, |
857 | &data_blocks) < 0) { | ||
858 | s->packet_index = -1; | ||
859 | break; | ||
860 | } | ||
821 | 861 | ||
822 | /* Process sync slave stream */ | 862 | /* Process sync slave stream */ |
823 | if (s->sync_slave && s->sync_slave->callbacked) { | 863 | if (s->sync_slave && s->sync_slave->callbacked) { |
824 | syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; | 864 | syt = be32_to_cpu(buffer[1]) & CIP_SYT_MASK; |
825 | handle_out_packet(s->sync_slave, syt); | 865 | if (handle_out_packet(s->sync_slave, |
866 | data_blocks, syt) < 0) { | ||
867 | s->packet_index = -1; | ||
868 | break; | ||
869 | } | ||
826 | } | 870 | } |
827 | |||
828 | /* The number of quadlets in this packet */ | ||
829 | payload_quadlets = | ||
830 | (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4; | ||
831 | handle_in_packet(s, payload_quadlets, buffer); | ||
832 | } | 871 | } |
833 | 872 | ||
834 | /* Queueing error or detecting discontinuity */ | 873 | /* Queueing error or detecting discontinuity */ |
835 | if (s->packet_index < 0) { | 874 | if (s->packet_index < 0) { |
875 | amdtp_stream_pcm_abort(s); | ||
876 | |||
836 | /* Abort sync slave. */ | 877 | /* Abort sync slave. */ |
837 | if (s->sync_slave) { | 878 | if (s->sync_slave) { |
838 | s->sync_slave->packet_index = -1; | 879 | s->sync_slave->packet_index = -1; |
@@ -872,7 +913,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, | |||
872 | 913 | ||
873 | if (s->direction == AMDTP_IN_STREAM) | 914 | if (s->direction == AMDTP_IN_STREAM) |
874 | context->callback.sc = in_stream_callback; | 915 | context->callback.sc = in_stream_callback; |
875 | else if ((s->flags & CIP_BLOCKING) && (s->flags & CIP_SYNC_TO_DEVICE)) | 916 | else if (s->flags & CIP_SYNC_TO_DEVICE) |
876 | context->callback.sc = slave_stream_callback; | 917 | context->callback.sc = slave_stream_callback; |
877 | else | 918 | else |
878 | context->callback.sc = out_stream_callback; | 919 | context->callback.sc = out_stream_callback; |
@@ -1013,8 +1054,10 @@ EXPORT_SYMBOL(amdtp_stream_pcm_pointer); | |||
1013 | */ | 1054 | */ |
1014 | void amdtp_stream_update(struct amdtp_stream *s) | 1055 | void amdtp_stream_update(struct amdtp_stream *s) |
1015 | { | 1056 | { |
1057 | /* Precomputing. */ | ||
1016 | ACCESS_ONCE(s->source_node_id_field) = | 1058 | ACCESS_ONCE(s->source_node_id_field) = |
1017 | (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; | 1059 | (fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) & |
1060 | CIP_SID_MASK; | ||
1018 | } | 1061 | } |
1019 | EXPORT_SYMBOL(amdtp_stream_update); | 1062 | EXPORT_SYMBOL(amdtp_stream_update); |
1020 | 1063 | ||
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h index 8a03a91e728b..26b909329e54 100644 --- a/sound/firewire/amdtp.h +++ b/sound/firewire/amdtp.h | |||
@@ -29,6 +29,9 @@ | |||
29 | * packet is not continuous from an initial value. | 29 | * packet is not continuous from an initial value. |
30 | * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty | 30 | * @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty |
31 | * packet is wrong but the others are correct. | 31 | * packet is wrong but the others are correct. |
32 | * @CIP_JUMBO_PAYLOAD: Only for in-stream. The number of data blocks in an | ||
33 | * packet is larger than IEC 61883-6 defines. Current implementation | ||
34 | * allows 5 times as large as IEC 61883-6 defines. | ||
32 | */ | 35 | */ |
33 | enum cip_flags { | 36 | enum cip_flags { |
34 | CIP_NONBLOCKING = 0x00, | 37 | CIP_NONBLOCKING = 0x00, |
@@ -40,6 +43,7 @@ enum cip_flags { | |||
40 | CIP_SKIP_DBC_ZERO_CHECK = 0x20, | 43 | CIP_SKIP_DBC_ZERO_CHECK = 0x20, |
41 | CIP_SKIP_INIT_DBC_CHECK = 0x40, | 44 | CIP_SKIP_INIT_DBC_CHECK = 0x40, |
42 | CIP_EMPTY_HAS_WRONG_DBC = 0x80, | 45 | CIP_EMPTY_HAS_WRONG_DBC = 0x80, |
46 | CIP_JUMBO_PAYLOAD = 0x100, | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /** | 49 | /** |
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 611b7dae7ee5..27a04ac8ffee 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -33,6 +33,7 @@ static DEFINE_MUTEX(devices_mutex); | |||
33 | static DECLARE_BITMAP(devices_used, SNDRV_CARDS); | 33 | static DECLARE_BITMAP(devices_used, SNDRV_CARDS); |
34 | 34 | ||
35 | /* Offsets from information register. */ | 35 | /* Offsets from information register. */ |
36 | #define INFO_OFFSET_BEBOB_VERSION 0x08 | ||
36 | #define INFO_OFFSET_GUID 0x10 | 37 | #define INFO_OFFSET_GUID 0x10 |
37 | #define INFO_OFFSET_HW_MODEL_ID 0x18 | 38 | #define INFO_OFFSET_HW_MODEL_ID 0x18 |
38 | #define INFO_OFFSET_HW_MODEL_REVISION 0x1c | 39 | #define INFO_OFFSET_HW_MODEL_REVISION 0x1c |
@@ -57,6 +58,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); | |||
57 | #define VEN_FOCUSRITE 0x0000130e | 58 | #define VEN_FOCUSRITE 0x0000130e |
58 | #define VEN_MAUDIO1 0x00000d6c | 59 | #define VEN_MAUDIO1 0x00000d6c |
59 | #define VEN_MAUDIO2 0x000007f5 | 60 | #define VEN_MAUDIO2 0x000007f5 |
61 | #define VEN_DIGIDESIGN 0x00a07e | ||
60 | 62 | ||
61 | #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 | 63 | #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 |
62 | #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 | 64 | #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 |
@@ -72,6 +74,7 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) | |||
72 | u32 hw_id; | 74 | u32 hw_id; |
73 | u32 data[2] = {0}; | 75 | u32 data[2] = {0}; |
74 | u32 revision; | 76 | u32 revision; |
77 | u32 version; | ||
75 | int err; | 78 | int err; |
76 | 79 | ||
77 | /* get vendor name from root directory */ | 80 | /* get vendor name from root directory */ |
@@ -104,6 +107,12 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) | |||
104 | if (err < 0) | 107 | if (err < 0) |
105 | goto end; | 108 | goto end; |
106 | 109 | ||
110 | err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_BEBOB_VERSION, | ||
111 | &version); | ||
112 | if (err < 0) | ||
113 | goto end; | ||
114 | bebob->version = version; | ||
115 | |||
107 | strcpy(bebob->card->driver, "BeBoB"); | 116 | strcpy(bebob->card->driver, "BeBoB"); |
108 | strcpy(bebob->card->shortname, model); | 117 | strcpy(bebob->card->shortname, model); |
109 | strcpy(bebob->card->mixername, model); | 118 | strcpy(bebob->card->mixername, model); |
@@ -364,6 +373,10 @@ static const struct ieee1394_device_id bebob_id_table[] = { | |||
364 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), | 373 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), |
365 | /* Behringer, Digital Mixer X32 series (X-UF Card) */ | 374 | /* Behringer, Digital Mixer X32 series (X-UF Card) */ |
366 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), | 375 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), |
376 | /* Behringer, F-Control Audio 1616 */ | ||
377 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x001616, &spec_normal), | ||
378 | /* Behringer, F-Control Audio 610 */ | ||
379 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x000610, &spec_normal), | ||
367 | /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ | 380 | /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ |
368 | /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ | 381 | /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ |
369 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), | 382 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), |
@@ -433,11 +446,11 @@ static const struct ieee1394_device_id bebob_id_table[] = { | |||
433 | /* M-Audio ProjectMix */ | 446 | /* M-Audio ProjectMix */ |
434 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, | 447 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, |
435 | &maudio_special_spec), | 448 | &maudio_special_spec), |
449 | /* Digidesign Mbox 2 Pro */ | ||
450 | SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), | ||
436 | /* IDs are unknown but able to be supported */ | 451 | /* IDs are unknown but able to be supported */ |
437 | /* Apogee, Mini-ME Firewire */ | 452 | /* Apogee, Mini-ME Firewire */ |
438 | /* Apogee, Mini-DAC Firewire */ | 453 | /* Apogee, Mini-DAC Firewire */ |
439 | /* Behringer, F-Control Audio 1616 */ | ||
440 | /* Behringer, F-Control Audio 610 */ | ||
441 | /* Cakawalk, Sonar Power Studio 66 */ | 454 | /* Cakawalk, Sonar Power Studio 66 */ |
442 | /* CME, UF400e */ | 455 | /* CME, UF400e */ |
443 | /* ESI, Quotafire XL */ | 456 | /* ESI, Quotafire XL */ |
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index dfbcd233178c..d23caca7f369 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h | |||
@@ -49,10 +49,15 @@ struct snd_bebob_stream_formation { | |||
49 | extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; | 49 | extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; |
50 | 50 | ||
51 | /* device specific operations */ | 51 | /* device specific operations */ |
52 | #define SND_BEBOB_CLOCK_INTERNAL "Internal" | 52 | enum snd_bebob_clock_type { |
53 | SND_BEBOB_CLOCK_TYPE_INTERNAL = 0, | ||
54 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, | ||
55 | SND_BEBOB_CLOCK_TYPE_SYT, | ||
56 | }; | ||
53 | struct snd_bebob_clock_spec { | 57 | struct snd_bebob_clock_spec { |
54 | unsigned int num; | 58 | unsigned int num; |
55 | const char *const *labels; | 59 | const char *const *labels; |
60 | enum snd_bebob_clock_type *types; | ||
56 | int (*get)(struct snd_bebob *bebob, unsigned int *id); | 61 | int (*get)(struct snd_bebob *bebob, unsigned int *id); |
57 | }; | 62 | }; |
58 | struct snd_bebob_rate_spec { | 63 | struct snd_bebob_rate_spec { |
@@ -92,8 +97,7 @@ struct snd_bebob { | |||
92 | struct amdtp_stream rx_stream; | 97 | struct amdtp_stream rx_stream; |
93 | struct cmp_connection out_conn; | 98 | struct cmp_connection out_conn; |
94 | struct cmp_connection in_conn; | 99 | struct cmp_connection in_conn; |
95 | atomic_t capture_substreams; | 100 | atomic_t substreams_counter; |
96 | atomic_t playback_substreams; | ||
97 | 101 | ||
98 | struct snd_bebob_stream_formation | 102 | struct snd_bebob_stream_formation |
99 | tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; | 103 | tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; |
@@ -110,6 +114,9 @@ struct snd_bebob { | |||
110 | /* for M-Audio special devices */ | 114 | /* for M-Audio special devices */ |
111 | void *maudio_special_quirk; | 115 | void *maudio_special_quirk; |
112 | bool deferred_registration; | 116 | bool deferred_registration; |
117 | |||
118 | /* For BeBoB version quirk. */ | ||
119 | unsigned int version; | ||
113 | }; | 120 | }; |
114 | 121 | ||
115 | static inline int | 122 | static inline int |
@@ -159,7 +166,8 @@ enum avc_bridgeco_plug_type { | |||
159 | AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, | 166 | AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, |
160 | AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, | 167 | AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, |
161 | AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, | 168 | AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, |
162 | AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05 | 169 | AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05, |
170 | AVC_BRIDGECO_PLUG_TYPE_ADDITION = 0x06 | ||
163 | }; | 171 | }; |
164 | static inline void | 172 | static inline void |
165 | avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], | 173 | avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], |
@@ -205,8 +213,8 @@ int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, | |||
205 | /* for AMDTP streaming */ | 213 | /* for AMDTP streaming */ |
206 | int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate); | 214 | int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate); |
207 | int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate); | 215 | int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate); |
208 | int snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, | 216 | int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, |
209 | bool *internal); | 217 | enum snd_bebob_clock_type *src); |
210 | int snd_bebob_stream_discover(struct snd_bebob *bebob); | 218 | int snd_bebob_stream_discover(struct snd_bebob *bebob); |
211 | int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); | 219 | int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); |
212 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); | 220 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); |
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c index fc67c1b7cb5b..a1a39494ea6c 100644 --- a/sound/firewire/bebob/bebob_focusrite.c +++ b/sound/firewire/bebob/bebob_focusrite.c | |||
@@ -103,11 +103,17 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) | |||
103 | &data, sizeof(__be32), 0); | 103 | &data, sizeof(__be32), 0); |
104 | } | 104 | } |
105 | 105 | ||
106 | static const char *const saffirepro_10_clk_src_labels[] = { | 106 | static enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { |
107 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" | 107 | SND_BEBOB_CLOCK_TYPE_INTERNAL, |
108 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ | ||
109 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ | ||
108 | }; | 110 | }; |
109 | static const char *const saffirepro_26_clk_src_labels[] = { | 111 | static enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { |
110 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" | 112 | SND_BEBOB_CLOCK_TYPE_INTERNAL, |
113 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ | ||
114 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT1 */ | ||
115 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT2 */ | ||
116 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ | ||
111 | }; | 117 | }; |
112 | /* Value maps between registers and labels for SaffirePro 10/26. */ | 118 | /* Value maps between registers and labels for SaffirePro 10/26. */ |
113 | static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { | 119 | static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { |
@@ -178,7 +184,7 @@ saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | |||
178 | goto end; | 184 | goto end; |
179 | 185 | ||
180 | /* depending on hardware, use a different mapping */ | 186 | /* depending on hardware, use a different mapping */ |
181 | if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) | 187 | if (bebob->spec->clock->types == saffirepro_10_clk_src_types) |
182 | map = saffirepro_clk_maps[0]; | 188 | map = saffirepro_clk_maps[0]; |
183 | else | 189 | else |
184 | map = saffirepro_clk_maps[1]; | 190 | map = saffirepro_clk_maps[1]; |
@@ -195,8 +201,9 @@ end: | |||
195 | } | 201 | } |
196 | 202 | ||
197 | struct snd_bebob_spec saffire_le_spec; | 203 | struct snd_bebob_spec saffire_le_spec; |
198 | static const char *const saffire_both_clk_src_labels[] = { | 204 | static enum snd_bebob_clock_type saffire_both_clk_src_types[] = { |
199 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" | 205 | SND_BEBOB_CLOCK_TYPE_INTERNAL, |
206 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, | ||
200 | }; | 207 | }; |
201 | static int | 208 | static int |
202 | saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | 209 | saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) |
@@ -259,8 +266,8 @@ static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { | |||
259 | }; | 266 | }; |
260 | /* Saffire Pro 26 I/O */ | 267 | /* Saffire Pro 26 I/O */ |
261 | static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { | 268 | static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { |
262 | .num = ARRAY_SIZE(saffirepro_26_clk_src_labels), | 269 | .num = ARRAY_SIZE(saffirepro_26_clk_src_types), |
263 | .labels = saffirepro_26_clk_src_labels, | 270 | .types = saffirepro_26_clk_src_types, |
264 | .get = &saffirepro_both_clk_src_get, | 271 | .get = &saffirepro_both_clk_src_get, |
265 | }; | 272 | }; |
266 | struct snd_bebob_spec saffirepro_26_spec = { | 273 | struct snd_bebob_spec saffirepro_26_spec = { |
@@ -270,8 +277,8 @@ struct snd_bebob_spec saffirepro_26_spec = { | |||
270 | }; | 277 | }; |
271 | /* Saffire Pro 10 I/O */ | 278 | /* Saffire Pro 10 I/O */ |
272 | static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { | 279 | static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { |
273 | .num = ARRAY_SIZE(saffirepro_10_clk_src_labels), | 280 | .num = ARRAY_SIZE(saffirepro_10_clk_src_types), |
274 | .labels = saffirepro_10_clk_src_labels, | 281 | .types = saffirepro_10_clk_src_types, |
275 | .get = &saffirepro_both_clk_src_get, | 282 | .get = &saffirepro_both_clk_src_get, |
276 | }; | 283 | }; |
277 | struct snd_bebob_spec saffirepro_10_spec = { | 284 | struct snd_bebob_spec saffirepro_10_spec = { |
@@ -285,8 +292,8 @@ static struct snd_bebob_rate_spec saffire_both_rate_spec = { | |||
285 | .set = &snd_bebob_stream_set_rate, | 292 | .set = &snd_bebob_stream_set_rate, |
286 | }; | 293 | }; |
287 | static struct snd_bebob_clock_spec saffire_both_clk_spec = { | 294 | static struct snd_bebob_clock_spec saffire_both_clk_spec = { |
288 | .num = ARRAY_SIZE(saffire_both_clk_src_labels), | 295 | .num = ARRAY_SIZE(saffire_both_clk_src_types), |
289 | .labels = saffire_both_clk_src_labels, | 296 | .types = saffire_both_clk_src_types, |
290 | .get = &saffire_both_clk_src_get, | 297 | .get = &saffire_both_clk_src_get, |
291 | }; | 298 | }; |
292 | /* Saffire LE */ | 299 | /* Saffire LE */ |
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 9ee25a63f684..057495d54ab0 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -340,9 +340,12 @@ end: | |||
340 | } | 340 | } |
341 | 341 | ||
342 | /* Clock source control for special firmware */ | 342 | /* Clock source control for special firmware */ |
343 | static const char *const special_clk_labels[] = { | 343 | static enum snd_bebob_clock_type special_clk_types[] = { |
344 | SND_BEBOB_CLOCK_INTERNAL " with Digital Mute", "Digital", | 344 | SND_BEBOB_CLOCK_TYPE_INTERNAL, /* With digital mute */ |
345 | "Word Clock", SND_BEBOB_CLOCK_INTERNAL}; | 345 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* SPDIF/ADAT */ |
346 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ | ||
347 | SND_BEBOB_CLOCK_TYPE_INTERNAL, | ||
348 | }; | ||
346 | static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) | 349 | static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) |
347 | { | 350 | { |
348 | struct special_params *params = bebob->maudio_special_quirk; | 351 | struct special_params *params = bebob->maudio_special_quirk; |
@@ -352,7 +355,13 @@ static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) | |||
352 | static int special_clk_ctl_info(struct snd_kcontrol *kctl, | 355 | static int special_clk_ctl_info(struct snd_kcontrol *kctl, |
353 | struct snd_ctl_elem_info *einf) | 356 | struct snd_ctl_elem_info *einf) |
354 | { | 357 | { |
355 | return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_labels), | 358 | static const char *const special_clk_labels[] = { |
359 | "Internal with Digital Mute", | ||
360 | "Digital", | ||
361 | "Word Clock", | ||
362 | "Internal" | ||
363 | }; | ||
364 | return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_types), | ||
356 | special_clk_labels); | 365 | special_clk_labels); |
357 | } | 366 | } |
358 | static int special_clk_ctl_get(struct snd_kcontrol *kctl, | 367 | static int special_clk_ctl_get(struct snd_kcontrol *kctl, |
@@ -371,7 +380,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
371 | int err, id; | 380 | int err, id; |
372 | 381 | ||
373 | id = uval->value.enumerated.item[0]; | 382 | id = uval->value.enumerated.item[0]; |
374 | if (id >= ARRAY_SIZE(special_clk_labels)) | 383 | if (id >= ARRAY_SIZE(special_clk_types)) |
375 | return -EINVAL; | 384 | return -EINVAL; |
376 | 385 | ||
377 | mutex_lock(&bebob->mutex); | 386 | mutex_lock(&bebob->mutex); |
@@ -708,8 +717,8 @@ static struct snd_bebob_rate_spec special_rate_spec = { | |||
708 | .set = &special_set_rate, | 717 | .set = &special_set_rate, |
709 | }; | 718 | }; |
710 | static struct snd_bebob_clock_spec special_clk_spec = { | 719 | static struct snd_bebob_clock_spec special_clk_spec = { |
711 | .num = ARRAY_SIZE(special_clk_labels), | 720 | .num = ARRAY_SIZE(special_clk_types), |
712 | .labels = special_clk_labels, | 721 | .types = special_clk_types, |
713 | .get = &special_clk_get, | 722 | .get = &special_clk_get, |
714 | }; | 723 | }; |
715 | static struct snd_bebob_meter_spec special_meter_spec = { | 724 | static struct snd_bebob_meter_spec special_meter_spec = { |
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index 63343d578df3..5681143925cd 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c | |||
@@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) | |||
17 | if (err < 0) | 17 | if (err < 0) |
18 | goto end; | 18 | goto end; |
19 | 19 | ||
20 | atomic_inc(&bebob->capture_substreams); | 20 | atomic_inc(&bebob->substreams_counter); |
21 | err = snd_bebob_stream_start_duplex(bebob, 0); | 21 | err = snd_bebob_stream_start_duplex(bebob, 0); |
22 | if (err < 0) | 22 | if (err < 0) |
23 | snd_bebob_stream_lock_release(bebob); | 23 | snd_bebob_stream_lock_release(bebob); |
@@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) | |||
34 | if (err < 0) | 34 | if (err < 0) |
35 | goto end; | 35 | goto end; |
36 | 36 | ||
37 | atomic_inc(&bebob->playback_substreams); | 37 | atomic_inc(&bebob->substreams_counter); |
38 | err = snd_bebob_stream_start_duplex(bebob, 0); | 38 | err = snd_bebob_stream_start_duplex(bebob, 0); |
39 | if (err < 0) | 39 | if (err < 0) |
40 | snd_bebob_stream_lock_release(bebob); | 40 | snd_bebob_stream_lock_release(bebob); |
@@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) | |||
46 | { | 46 | { |
47 | struct snd_bebob *bebob = substream->rmidi->private_data; | 47 | struct snd_bebob *bebob = substream->rmidi->private_data; |
48 | 48 | ||
49 | atomic_dec(&bebob->capture_substreams); | 49 | atomic_dec(&bebob->substreams_counter); |
50 | snd_bebob_stream_stop_duplex(bebob); | 50 | snd_bebob_stream_stop_duplex(bebob); |
51 | 51 | ||
52 | snd_bebob_stream_lock_release(bebob); | 52 | snd_bebob_stream_lock_release(bebob); |
@@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) | |||
57 | { | 57 | { |
58 | struct snd_bebob *bebob = substream->rmidi->private_data; | 58 | struct snd_bebob *bebob = substream->rmidi->private_data; |
59 | 59 | ||
60 | atomic_dec(&bebob->playback_substreams); | 60 | atomic_dec(&bebob->substreams_counter); |
61 | snd_bebob_stream_stop_duplex(bebob); | 61 | snd_bebob_stream_stop_duplex(bebob); |
62 | 62 | ||
63 | snd_bebob_stream_lock_release(bebob); | 63 | snd_bebob_stream_lock_release(bebob); |
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 4a55561ed4ec..7a2c1f53bc44 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c | |||
@@ -157,7 +157,7 @@ pcm_open(struct snd_pcm_substream *substream) | |||
157 | struct snd_bebob *bebob = substream->private_data; | 157 | struct snd_bebob *bebob = substream->private_data; |
158 | struct snd_bebob_rate_spec *spec = bebob->spec->rate; | 158 | struct snd_bebob_rate_spec *spec = bebob->spec->rate; |
159 | unsigned int sampling_rate; | 159 | unsigned int sampling_rate; |
160 | bool internal; | 160 | enum snd_bebob_clock_type src; |
161 | int err; | 161 | int err; |
162 | 162 | ||
163 | err = snd_bebob_stream_lock_try(bebob); | 163 | err = snd_bebob_stream_lock_try(bebob); |
@@ -168,7 +168,7 @@ pcm_open(struct snd_pcm_substream *substream) | |||
168 | if (err < 0) | 168 | if (err < 0) |
169 | goto err_locked; | 169 | goto err_locked; |
170 | 170 | ||
171 | err = snd_bebob_stream_check_internal_clock(bebob, &internal); | 171 | err = snd_bebob_stream_get_clock_src(bebob, &src); |
172 | if (err < 0) | 172 | if (err < 0) |
173 | goto err_locked; | 173 | goto err_locked; |
174 | 174 | ||
@@ -176,7 +176,7 @@ pcm_open(struct snd_pcm_substream *substream) | |||
176 | * When source of clock is internal or any PCM stream are running, | 176 | * When source of clock is internal or any PCM stream are running, |
177 | * the available sampling rate is limited at current sampling rate. | 177 | * the available sampling rate is limited at current sampling rate. |
178 | */ | 178 | */ |
179 | if (!internal || | 179 | if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || |
180 | amdtp_stream_pcm_running(&bebob->tx_stream) || | 180 | amdtp_stream_pcm_running(&bebob->tx_stream) || |
181 | amdtp_stream_pcm_running(&bebob->rx_stream)) { | 181 | amdtp_stream_pcm_running(&bebob->rx_stream)) { |
182 | err = spec->get(bebob, &sampling_rate); | 182 | err = spec->get(bebob, &sampling_rate); |
@@ -213,7 +213,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
213 | struct snd_bebob *bebob = substream->private_data; | 213 | struct snd_bebob *bebob = substream->private_data; |
214 | 214 | ||
215 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | 215 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) |
216 | atomic_inc(&bebob->capture_substreams); | 216 | atomic_inc(&bebob->substreams_counter); |
217 | amdtp_stream_set_pcm_format(&bebob->tx_stream, | 217 | amdtp_stream_set_pcm_format(&bebob->tx_stream, |
218 | params_format(hw_params)); | 218 | params_format(hw_params)); |
219 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | 219 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, |
@@ -226,7 +226,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
226 | struct snd_bebob *bebob = substream->private_data; | 226 | struct snd_bebob *bebob = substream->private_data; |
227 | 227 | ||
228 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) | 228 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) |
229 | atomic_inc(&bebob->playback_substreams); | 229 | atomic_inc(&bebob->substreams_counter); |
230 | amdtp_stream_set_pcm_format(&bebob->rx_stream, | 230 | amdtp_stream_set_pcm_format(&bebob->rx_stream, |
231 | params_format(hw_params)); | 231 | params_format(hw_params)); |
232 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | 232 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, |
@@ -239,7 +239,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream) | |||
239 | struct snd_bebob *bebob = substream->private_data; | 239 | struct snd_bebob *bebob = substream->private_data; |
240 | 240 | ||
241 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | 241 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) |
242 | atomic_dec(&bebob->capture_substreams); | 242 | atomic_dec(&bebob->substreams_counter); |
243 | 243 | ||
244 | snd_bebob_stream_stop_duplex(bebob); | 244 | snd_bebob_stream_stop_duplex(bebob); |
245 | 245 | ||
@@ -251,7 +251,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream) | |||
251 | struct snd_bebob *bebob = substream->private_data; | 251 | struct snd_bebob *bebob = substream->private_data; |
252 | 252 | ||
253 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) | 253 | if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) |
254 | atomic_dec(&bebob->playback_substreams); | 254 | atomic_dec(&bebob->substreams_counter); |
255 | 255 | ||
256 | snd_bebob_stream_stop_duplex(bebob); | 256 | snd_bebob_stream_stop_duplex(bebob); |
257 | 257 | ||
diff --git a/sound/firewire/bebob/bebob_proc.c b/sound/firewire/bebob/bebob_proc.c index 335da64506e0..301cc6a93945 100644 --- a/sound/firewire/bebob/bebob_proc.c +++ b/sound/firewire/bebob/bebob_proc.c | |||
@@ -132,25 +132,27 @@ static void | |||
132 | proc_read_clock(struct snd_info_entry *entry, | 132 | proc_read_clock(struct snd_info_entry *entry, |
133 | struct snd_info_buffer *buffer) | 133 | struct snd_info_buffer *buffer) |
134 | { | 134 | { |
135 | static const char *const clk_labels[] = { | ||
136 | "Internal", | ||
137 | "External", | ||
138 | "SYT-Match", | ||
139 | }; | ||
135 | struct snd_bebob *bebob = entry->private_data; | 140 | struct snd_bebob *bebob = entry->private_data; |
136 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; | 141 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; |
137 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | 142 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; |
138 | unsigned int rate, id; | 143 | enum snd_bebob_clock_type src; |
139 | bool internal; | 144 | unsigned int rate; |
140 | 145 | ||
141 | if (rate_spec->get(bebob, &rate) >= 0) | 146 | if (rate_spec->get(bebob, &rate) >= 0) |
142 | snd_iprintf(buffer, "Sampling rate: %d\n", rate); | 147 | snd_iprintf(buffer, "Sampling rate: %d\n", rate); |
143 | 148 | ||
144 | if (clk_spec) { | 149 | if (snd_bebob_stream_get_clock_src(bebob, &src) >= 0) { |
145 | if (clk_spec->get(bebob, &id) >= 0) | 150 | if (clk_spec) |
146 | snd_iprintf(buffer, "Clock Source: %s\n", | 151 | snd_iprintf(buffer, "Clock Source: %s\n", |
147 | clk_spec->labels[id]); | 152 | clk_labels[src]); |
148 | } else { | 153 | else |
149 | if (snd_bebob_stream_check_internal_clock(bebob, | ||
150 | &internal) >= 0) | ||
151 | snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", | 154 | snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", |
152 | (internal) ? "Internal" : "External", | 155 | clk_labels[src], bebob->sync_input_plug); |
153 | bebob->sync_input_plug); | ||
154 | } | 156 | } |
155 | } | 157 | } |
156 | 158 | ||
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 98e4fc8121a1..5be5242e1ed8 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #include "./bebob.h" | 9 | #include "./bebob.h" |
10 | 10 | ||
11 | #define CALLBACK_TIMEOUT 1000 | 11 | #define CALLBACK_TIMEOUT 2000 |
12 | #define FW_ISO_RESOURCE_DELAY 1000 | 12 | #define FW_ISO_RESOURCE_DELAY 1000 |
13 | 13 | ||
14 | /* | 14 | /* |
@@ -116,16 +116,15 @@ end: | |||
116 | return err; | 116 | return err; |
117 | } | 117 | } |
118 | 118 | ||
119 | int | 119 | int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, |
120 | snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | 120 | enum snd_bebob_clock_type *src) |
121 | { | 121 | { |
122 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | 122 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; |
123 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; | 123 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; |
124 | unsigned int id; | 124 | unsigned int id; |
125 | enum avc_bridgeco_plug_type type; | ||
125 | int err = 0; | 126 | int err = 0; |
126 | 127 | ||
127 | *internal = false; | ||
128 | |||
129 | /* 1.The device has its own operation to switch source of clock */ | 128 | /* 1.The device has its own operation to switch source of clock */ |
130 | if (clk_spec) { | 129 | if (clk_spec) { |
131 | err = clk_spec->get(bebob, &id); | 130 | err = clk_spec->get(bebob, &id); |
@@ -143,10 +142,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | |||
143 | goto end; | 142 | goto end; |
144 | } | 143 | } |
145 | 144 | ||
146 | if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, | 145 | *src = clk_spec->types[id]; |
147 | strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) | ||
148 | *internal = true; | ||
149 | |||
150 | goto end; | 146 | goto end; |
151 | } | 147 | } |
152 | 148 | ||
@@ -155,7 +151,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | |||
155 | * to use internal clock always | 151 | * to use internal clock always |
156 | */ | 152 | */ |
157 | if (bebob->sync_input_plug < 0) { | 153 | if (bebob->sync_input_plug < 0) { |
158 | *internal = true; | 154 | *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; |
159 | goto end; | 155 | goto end; |
160 | } | 156 | } |
161 | 157 | ||
@@ -178,18 +174,79 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | |||
178 | * Here check the first field. This field is used for direction. | 174 | * Here check the first field. This field is used for direction. |
179 | */ | 175 | */ |
180 | if (input[0] == 0xff) { | 176 | if (input[0] == 0xff) { |
181 | *internal = true; | 177 | *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; |
182 | goto end; | 178 | goto end; |
183 | } | 179 | } |
184 | 180 | ||
185 | /* | 181 | /* The source from any output plugs is for one purpose only. */ |
186 | * If source of clock is internal CSR, Music Sub Unit Sync Input is | 182 | if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) { |
187 | * a destination of Music Sub Unit Sync Output. | 183 | /* |
188 | */ | 184 | * In BeBoB architecture, the source from music subunit may |
189 | *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) && | 185 | * bypass from oPCR[0]. This means that this source gives |
190 | (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) && | 186 | * synchronization to IEEE 1394 cycle start packet. |
191 | (input[2] == 0x0c) && | 187 | */ |
192 | (input[3] == 0x00)); | 188 | if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && |
189 | input[2] == 0x0c) { | ||
190 | *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; | ||
191 | goto end; | ||
192 | } | ||
193 | /* The source from any input units is for several purposes. */ | ||
194 | } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) { | ||
195 | if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) { | ||
196 | if (input[3] == 0x00) { | ||
197 | /* | ||
198 | * This source comes from iPCR[0]. This means | ||
199 | * that presentation timestamp calculated by | ||
200 | * SYT series of the received packets. In | ||
201 | * short, this driver is the master of | ||
202 | * synchronization. | ||
203 | */ | ||
204 | *src = SND_BEBOB_CLOCK_TYPE_SYT; | ||
205 | goto end; | ||
206 | } else { | ||
207 | /* | ||
208 | * This source comes from iPCR[1-29]. This | ||
209 | * means that the synchronization stream is not | ||
210 | * the Audio/MIDI compound stream. | ||
211 | */ | ||
212 | *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; | ||
213 | goto end; | ||
214 | } | ||
215 | } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { | ||
216 | /* Check type of this plug. */ | ||
217 | avc_bridgeco_fill_unit_addr(addr, | ||
218 | AVC_BRIDGECO_PLUG_DIR_IN, | ||
219 | AVC_BRIDGECO_PLUG_UNIT_EXT, | ||
220 | input[3]); | ||
221 | err = avc_bridgeco_get_plug_type(bebob->unit, addr, | ||
222 | &type); | ||
223 | if (err < 0) | ||
224 | goto end; | ||
225 | |||
226 | if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) { | ||
227 | /* | ||
228 | * SPDIF/ADAT or sometimes (not always) word | ||
229 | * clock. | ||
230 | */ | ||
231 | *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; | ||
232 | goto end; | ||
233 | } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { | ||
234 | /* Often word clock. */ | ||
235 | *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; | ||
236 | goto end; | ||
237 | } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { | ||
238 | /* | ||
239 | * Not standard. | ||
240 | * Mostly, additional internal clock. | ||
241 | */ | ||
242 | *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; | ||
243 | goto end; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /* Not supported. */ | ||
249 | err = -EIO; | ||
193 | end: | 250 | end: |
194 | return err; | 251 | return err; |
195 | } | 252 | } |
@@ -417,8 +474,24 @@ destroy_both_connections(struct snd_bebob *bebob) | |||
417 | static int | 474 | static int |
418 | get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) | 475 | get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) |
419 | { | 476 | { |
420 | /* currently this module doesn't support SYT-Match mode */ | 477 | enum snd_bebob_clock_type src; |
421 | *sync_mode = CIP_SYNC_TO_DEVICE; | 478 | int err; |
479 | |||
480 | err = snd_bebob_stream_get_clock_src(bebob, &src); | ||
481 | if (err < 0) | ||
482 | return err; | ||
483 | |||
484 | switch (src) { | ||
485 | case SND_BEBOB_CLOCK_TYPE_INTERNAL: | ||
486 | case SND_BEBOB_CLOCK_TYPE_EXTERNAL: | ||
487 | *sync_mode = CIP_SYNC_TO_DEVICE; | ||
488 | break; | ||
489 | default: | ||
490 | case SND_BEBOB_CLOCK_TYPE_SYT: | ||
491 | *sync_mode = 0; | ||
492 | break; | ||
493 | } | ||
494 | |||
422 | return 0; | 495 | return 0; |
423 | } | 496 | } |
424 | 497 | ||
@@ -467,6 +540,17 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) | |||
467 | /* See comments in next function */ | 540 | /* See comments in next function */ |
468 | init_completion(&bebob->bus_reset); | 541 | init_completion(&bebob->bus_reset); |
469 | bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; | 542 | bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; |
543 | |||
544 | /* | ||
545 | * BeBoB v3 transfers packets with these qurks: | ||
546 | * - In the beginning of streaming, the value of dbc is incremented | ||
547 | * even if no data blocks are transferred. | ||
548 | * - The value of dbc is reset suddenly. | ||
549 | */ | ||
550 | if (bebob->version > 2) | ||
551 | bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | | ||
552 | CIP_SKIP_DBC_ZERO_CHECK; | ||
553 | |||
470 | /* | 554 | /* |
471 | * At high sampling rate, M-Audio special firmware transmits empty | 555 | * At high sampling rate, M-Audio special firmware transmits empty |
472 | * packet with the value of dbc incremented by 8 but the others are | 556 | * packet with the value of dbc incremented by 8 but the others are |
@@ -490,7 +574,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
490 | { | 574 | { |
491 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; | 575 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; |
492 | struct amdtp_stream *master, *slave; | 576 | struct amdtp_stream *master, *slave; |
493 | atomic_t *slave_substreams; | ||
494 | enum cip_flags sync_mode; | 577 | enum cip_flags sync_mode; |
495 | unsigned int curr_rate; | 578 | unsigned int curr_rate; |
496 | bool updated = false; | 579 | bool updated = false; |
@@ -515,8 +598,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
515 | mutex_lock(&bebob->mutex); | 598 | mutex_lock(&bebob->mutex); |
516 | 599 | ||
517 | /* Need no substreams */ | 600 | /* Need no substreams */ |
518 | if (atomic_read(&bebob->playback_substreams) == 0 && | 601 | if (atomic_read(&bebob->substreams_counter) == 0) |
519 | atomic_read(&bebob->capture_substreams) == 0) | ||
520 | goto end; | 602 | goto end; |
521 | 603 | ||
522 | err = get_sync_mode(bebob, &sync_mode); | 604 | err = get_sync_mode(bebob, &sync_mode); |
@@ -525,11 +607,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
525 | if (sync_mode == CIP_SYNC_TO_DEVICE) { | 607 | if (sync_mode == CIP_SYNC_TO_DEVICE) { |
526 | master = &bebob->tx_stream; | 608 | master = &bebob->tx_stream; |
527 | slave = &bebob->rx_stream; | 609 | slave = &bebob->rx_stream; |
528 | slave_substreams = &bebob->playback_substreams; | ||
529 | } else { | 610 | } else { |
530 | master = &bebob->rx_stream; | 611 | master = &bebob->rx_stream; |
531 | slave = &bebob->tx_stream; | 612 | slave = &bebob->tx_stream; |
532 | slave_substreams = &bebob->capture_substreams; | ||
533 | } | 613 | } |
534 | 614 | ||
535 | /* | 615 | /* |
@@ -630,7 +710,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
630 | } | 710 | } |
631 | 711 | ||
632 | /* start slave if needed */ | 712 | /* start slave if needed */ |
633 | if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { | 713 | if (!amdtp_stream_running(slave)) { |
634 | err = start_stream(bebob, slave, rate); | 714 | err = start_stream(bebob, slave, rate); |
635 | if (err < 0) { | 715 | if (err < 0) { |
636 | dev_err(&bebob->unit->device, | 716 | dev_err(&bebob->unit->device, |
@@ -656,31 +736,25 @@ end: | |||
656 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) | 736 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) |
657 | { | 737 | { |
658 | struct amdtp_stream *master, *slave; | 738 | struct amdtp_stream *master, *slave; |
659 | atomic_t *master_substreams, *slave_substreams; | ||
660 | 739 | ||
661 | if (bebob->master == &bebob->rx_stream) { | 740 | if (bebob->master == &bebob->rx_stream) { |
662 | slave = &bebob->tx_stream; | 741 | slave = &bebob->tx_stream; |
663 | master = &bebob->rx_stream; | 742 | master = &bebob->rx_stream; |
664 | slave_substreams = &bebob->capture_substreams; | ||
665 | master_substreams = &bebob->playback_substreams; | ||
666 | } else { | 743 | } else { |
667 | slave = &bebob->rx_stream; | 744 | slave = &bebob->rx_stream; |
668 | master = &bebob->tx_stream; | 745 | master = &bebob->tx_stream; |
669 | slave_substreams = &bebob->playback_substreams; | ||
670 | master_substreams = &bebob->capture_substreams; | ||
671 | } | 746 | } |
672 | 747 | ||
673 | mutex_lock(&bebob->mutex); | 748 | mutex_lock(&bebob->mutex); |
674 | 749 | ||
675 | if (atomic_read(slave_substreams) == 0) { | 750 | if (atomic_read(&bebob->substreams_counter) == 0) { |
751 | amdtp_stream_pcm_abort(master); | ||
752 | amdtp_stream_stop(master); | ||
753 | |||
676 | amdtp_stream_pcm_abort(slave); | 754 | amdtp_stream_pcm_abort(slave); |
677 | amdtp_stream_stop(slave); | 755 | amdtp_stream_stop(slave); |
678 | 756 | ||
679 | if (atomic_read(master_substreams) == 0) { | 757 | break_both_connections(bebob); |
680 | amdtp_stream_pcm_abort(master); | ||
681 | amdtp_stream_stop(master); | ||
682 | break_both_connections(bebob); | ||
683 | } | ||
684 | } | 758 | } |
685 | 759 | ||
686 | mutex_unlock(&bebob->mutex); | 760 | mutex_unlock(&bebob->mutex); |
diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c index ad635004d699..9242e33d2cf1 100644 --- a/sound/firewire/bebob/bebob_terratec.c +++ b/sound/firewire/bebob/bebob_terratec.c | |||
@@ -8,8 +8,10 @@ | |||
8 | 8 | ||
9 | #include "./bebob.h" | 9 | #include "./bebob.h" |
10 | 10 | ||
11 | static const char *const phase88_rack_clk_src_labels[] = { | 11 | static enum snd_bebob_clock_type phase88_rack_clk_src_types[] = { |
12 | SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock" | 12 | SND_BEBOB_CLOCK_TYPE_INTERNAL, |
13 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ | ||
14 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ | ||
13 | }; | 15 | }; |
14 | static int | 16 | static int |
15 | phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | 17 | phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id) |
@@ -34,13 +36,23 @@ end: | |||
34 | return err; | 36 | return err; |
35 | } | 37 | } |
36 | 38 | ||
37 | static const char *const phase24_series_clk_src_labels[] = { | 39 | static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { |
38 | SND_BEBOB_CLOCK_INTERNAL, "Digital In" | 40 | SND_BEBOB_CLOCK_TYPE_INTERNAL, |
41 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ | ||
39 | }; | 42 | }; |
40 | static int | 43 | static int |
41 | phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | 44 | phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) |
42 | { | 45 | { |
43 | return avc_audio_get_selector(bebob->unit, 0, 4, id); | 46 | int err; |
47 | |||
48 | err = avc_audio_get_selector(bebob->unit, 0, 4, id); | ||
49 | if (err < 0) | ||
50 | return err; | ||
51 | |||
52 | if (*id >= ARRAY_SIZE(phase24_series_clk_src_types)) | ||
53 | return -EIO; | ||
54 | |||
55 | return 0; | ||
44 | } | 56 | } |
45 | 57 | ||
46 | static struct snd_bebob_rate_spec phase_series_rate_spec = { | 58 | static struct snd_bebob_rate_spec phase_series_rate_spec = { |
@@ -50,8 +62,8 @@ static struct snd_bebob_rate_spec phase_series_rate_spec = { | |||
50 | 62 | ||
51 | /* PHASE 88 Rack FW */ | 63 | /* PHASE 88 Rack FW */ |
52 | static struct snd_bebob_clock_spec phase88_rack_clk = { | 64 | static struct snd_bebob_clock_spec phase88_rack_clk = { |
53 | .num = ARRAY_SIZE(phase88_rack_clk_src_labels), | 65 | .num = ARRAY_SIZE(phase88_rack_clk_src_types), |
54 | .labels = phase88_rack_clk_src_labels, | 66 | .types = phase88_rack_clk_src_types, |
55 | .get = &phase88_rack_clk_src_get, | 67 | .get = &phase88_rack_clk_src_get, |
56 | }; | 68 | }; |
57 | struct snd_bebob_spec phase88_rack_spec = { | 69 | struct snd_bebob_spec phase88_rack_spec = { |
@@ -62,8 +74,8 @@ struct snd_bebob_spec phase88_rack_spec = { | |||
62 | 74 | ||
63 | /* 'PHASE 24 FW' and 'PHASE X24 FW' */ | 75 | /* 'PHASE 24 FW' and 'PHASE X24 FW' */ |
64 | static struct snd_bebob_clock_spec phase24_series_clk = { | 76 | static struct snd_bebob_clock_spec phase24_series_clk = { |
65 | .num = ARRAY_SIZE(phase24_series_clk_src_labels), | 77 | .num = ARRAY_SIZE(phase24_series_clk_src_types), |
66 | .labels = phase24_series_clk_src_labels, | 78 | .types = phase24_series_clk_src_types, |
67 | .get = &phase24_series_clk_src_get, | 79 | .get = &phase24_series_clk_src_get, |
68 | }; | 80 | }; |
69 | struct snd_bebob_spec phase24_series_spec = { | 81 | struct snd_bebob_spec phase24_series_spec = { |
diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c index ef1fe3823a9c..58101702410b 100644 --- a/sound/firewire/bebob/bebob_yamaha.c +++ b/sound/firewire/bebob/bebob_yamaha.c | |||
@@ -28,15 +28,27 @@ | |||
28 | * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. | 28 | * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | static const char *const clk_src_labels[] = {SND_BEBOB_CLOCK_INTERNAL, "SPDIF"}; | 31 | static enum snd_bebob_clock_type clk_src_types[] = { |
32 | SND_BEBOB_CLOCK_TYPE_INTERNAL, | ||
33 | SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ | ||
34 | }; | ||
32 | static int | 35 | static int |
33 | clk_src_get(struct snd_bebob *bebob, unsigned int *id) | 36 | clk_src_get(struct snd_bebob *bebob, unsigned int *id) |
34 | { | 37 | { |
35 | return avc_audio_get_selector(bebob->unit, 0, 4, id); | 38 | int err; |
39 | |||
40 | err = avc_audio_get_selector(bebob->unit, 0, 4, id); | ||
41 | if (err < 0) | ||
42 | return err; | ||
43 | |||
44 | if (*id >= ARRAY_SIZE(clk_src_types)) | ||
45 | return -EIO; | ||
46 | |||
47 | return 0; | ||
36 | } | 48 | } |
37 | static struct snd_bebob_clock_spec clock_spec = { | 49 | static struct snd_bebob_clock_spec clock_spec = { |
38 | .num = ARRAY_SIZE(clk_src_labels), | 50 | .num = ARRAY_SIZE(clk_src_types), |
39 | .labels = clk_src_labels, | 51 | .types = clk_src_types, |
40 | .get = &clk_src_get, | 52 | .get = &clk_src_get, |
41 | }; | 53 | }; |
42 | static struct snd_bebob_rate_spec rate_spec = { | 54 | static struct snd_bebob_rate_spec rate_spec = { |
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index e6757cd85724..873d40fc4509 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -232,9 +232,15 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw, | |||
232 | goto end; | 232 | goto end; |
233 | } | 233 | } |
234 | 234 | ||
235 | /* OXFW starts to transmit packets with non-zero dbc. */ | 235 | /* |
236 | * OXFW starts to transmit packets with non-zero dbc. | ||
237 | * OXFW postpone transferring packets till handling any asynchronous | ||
238 | * packets. As a result, next isochronous packet includes more data | ||
239 | * blocks than IEC 61883-6 defines. | ||
240 | */ | ||
236 | if (stream == &oxfw->tx_stream) | 241 | if (stream == &oxfw->tx_stream) |
237 | oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; | 242 | oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK | |
243 | CIP_JUMBO_PAYLOAD; | ||
238 | end: | 244 | end: |
239 | return err; | 245 | return err; |
240 | } | 246 | } |
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 001c6588a5ff..3129546398d0 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig | |||
@@ -1,3 +1,29 @@ | |||
1 | config SND_HDA_CORE | 1 | config SND_HDA_CORE |
2 | tristate | 2 | tristate |
3 | select REGMAP | 3 | select REGMAP |
4 | |||
5 | config SND_HDA_DSP_LOADER | ||
6 | bool | ||
7 | |||
8 | config SND_HDA_I915 | ||
9 | bool | ||
10 | default y | ||
11 | depends on DRM_I915 | ||
12 | depends on SND_HDA_CORE | ||
13 | |||
14 | config SND_HDA_EXT_CORE | ||
15 | tristate | ||
16 | select SND_HDA_CORE | ||
17 | |||
18 | config SND_HDA_PREALLOC_SIZE | ||
19 | int "Pre-allocated buffer size for HD-audio driver" | ||
20 | range 0 32768 | ||
21 | default 64 | ||
22 | help | ||
23 | Specifies the default pre-allocated buffer-size in kB for the | ||
24 | HD-audio driver. A larger buffer (e.g. 2048) is preferred | ||
25 | for systems using PulseAudio. The default 64 is chosen just | ||
26 | for compatibility reasons. | ||
27 | |||
28 | Note that the pre-allocation size can be changed dynamically | ||
29 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. | ||
diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 7a359f5b7e25..7e999c995cdc 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile | |||
@@ -1,7 +1,13 @@ | |||
1 | snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ | 1 | snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ |
2 | hdac_regmap.o array.o | 2 | hdac_regmap.o hdac_controller.o hdac_stream.o array.o |
3 | 3 | ||
4 | snd-hda-core-objs += trace.o | 4 | snd-hda-core-objs += trace.o |
5 | CFLAGS_trace.o := -I$(src) | 5 | CFLAGS_trace.o := -I$(src) |
6 | 6 | ||
7 | # for sync with i915 gfx driver | ||
8 | snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o | ||
9 | |||
7 | obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o | 10 | obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o |
11 | |||
12 | #extended hda | ||
13 | obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ | ||
diff --git a/sound/hda/ext/Makefile b/sound/hda/ext/Makefile new file mode 100644 index 000000000000..9b6f641c7777 --- /dev/null +++ b/sound/hda/ext/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | snd-hda-ext-core-objs := hdac_ext_bus.o hdac_ext_controller.o hdac_ext_stream.o | ||
2 | |||
3 | obj-$(CONFIG_SND_HDA_EXT_CORE) += snd-hda-ext-core.o | ||
diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c new file mode 100644 index 000000000000..0aa5d9eb6c3f --- /dev/null +++ b/sound/hda/ext/hdac_ext_bus.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * hdac-ext-bus.c - HD-audio extended core bus functions. | ||
3 | * | ||
4 | * Copyright (C) 2014-2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/hdaudio_ext.h> | ||
23 | |||
24 | MODULE_DESCRIPTION("HDA extended core"); | ||
25 | MODULE_LICENSE("GPL v2"); | ||
26 | |||
27 | static void hdac_ext_writel(u32 value, u32 __iomem *addr) | ||
28 | { | ||
29 | writel(value, addr); | ||
30 | } | ||
31 | |||
32 | static u32 hdac_ext_readl(u32 __iomem *addr) | ||
33 | { | ||
34 | return readl(addr); | ||
35 | } | ||
36 | |||
37 | static void hdac_ext_writew(u16 value, u16 __iomem *addr) | ||
38 | { | ||
39 | writew(value, addr); | ||
40 | } | ||
41 | |||
42 | static u16 hdac_ext_readw(u16 __iomem *addr) | ||
43 | { | ||
44 | return readw(addr); | ||
45 | } | ||
46 | |||
47 | static void hdac_ext_writeb(u8 value, u8 __iomem *addr) | ||
48 | { | ||
49 | writeb(value, addr); | ||
50 | } | ||
51 | |||
52 | static u8 hdac_ext_readb(u8 __iomem *addr) | ||
53 | { | ||
54 | return readb(addr); | ||
55 | } | ||
56 | |||
57 | static int hdac_ext_dma_alloc_pages(struct hdac_bus *bus, int type, | ||
58 | size_t size, struct snd_dma_buffer *buf) | ||
59 | { | ||
60 | return snd_dma_alloc_pages(type, bus->dev, size, buf); | ||
61 | } | ||
62 | |||
63 | static void hdac_ext_dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | ||
64 | { | ||
65 | snd_dma_free_pages(buf); | ||
66 | } | ||
67 | |||
68 | static const struct hdac_io_ops hdac_ext_default_io = { | ||
69 | .reg_writel = hdac_ext_writel, | ||
70 | .reg_readl = hdac_ext_readl, | ||
71 | .reg_writew = hdac_ext_writew, | ||
72 | .reg_readw = hdac_ext_readw, | ||
73 | .reg_writeb = hdac_ext_writeb, | ||
74 | .reg_readb = hdac_ext_readb, | ||
75 | .dma_alloc_pages = hdac_ext_dma_alloc_pages, | ||
76 | .dma_free_pages = hdac_ext_dma_free_pages, | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * snd_hdac_ext_bus_init - initialize a HD-audio extended bus | ||
81 | * @ebus: the pointer to extended bus object | ||
82 | * @dev: device pointer | ||
83 | * @ops: bus verb operators | ||
84 | * @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use | ||
85 | * default ops | ||
86 | * | ||
87 | * Returns 0 if successful, or a negative error code. | ||
88 | */ | ||
89 | int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, | ||
90 | const struct hdac_bus_ops *ops, | ||
91 | const struct hdac_io_ops *io_ops) | ||
92 | { | ||
93 | int ret; | ||
94 | static int idx; | ||
95 | |||
96 | /* check if io ops are provided, if not load the defaults */ | ||
97 | if (io_ops == NULL) | ||
98 | io_ops = &hdac_ext_default_io; | ||
99 | |||
100 | ret = snd_hdac_bus_init(&ebus->bus, dev, ops, io_ops); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | |||
104 | INIT_LIST_HEAD(&ebus->hlink_list); | ||
105 | ebus->idx = idx++; | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init); | ||
110 | |||
111 | /** | ||
112 | * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus | ||
113 | * @ebus: the pointer to extended bus object | ||
114 | */ | ||
115 | void snd_hdac_ext_bus_exit(struct hdac_ext_bus *ebus) | ||
116 | { | ||
117 | snd_hdac_bus_exit(&ebus->bus); | ||
118 | WARN_ON(!list_empty(&ebus->hlink_list)); | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); | ||
121 | |||
122 | static void default_release(struct device *dev) | ||
123 | { | ||
124 | snd_hdac_ext_bus_device_exit(container_of(dev, struct hdac_device, dev)); | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * snd_hdac_ext_device_init - initialize the HDA extended codec base device | ||
129 | * @ebus: hdac extended bus to attach to | ||
130 | * @addr: codec address | ||
131 | * | ||
132 | * Returns zero for success or a negative error code. | ||
133 | */ | ||
134 | int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) | ||
135 | { | ||
136 | struct hdac_device *hdev = NULL; | ||
137 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
138 | char name[15]; | ||
139 | int ret; | ||
140 | |||
141 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); | ||
142 | if (!hdev) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); | ||
146 | |||
147 | ret = snd_hdac_device_init(hdev, bus, name, addr); | ||
148 | if (ret < 0) { | ||
149 | dev_err(bus->dev, "device init failed for hdac device\n"); | ||
150 | return ret; | ||
151 | } | ||
152 | hdev->type = HDA_DEV_ASOC; | ||
153 | hdev->dev.release = default_release; | ||
154 | |||
155 | ret = snd_hdac_device_register(hdev); | ||
156 | if (ret) { | ||
157 | dev_err(bus->dev, "failed to register hdac device\n"); | ||
158 | snd_hdac_ext_bus_device_exit(hdev); | ||
159 | return ret; | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); | ||
164 | |||
165 | /** | ||
166 | * snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device | ||
167 | * @hdev: hdac device to clean up | ||
168 | */ | ||
169 | void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) | ||
170 | { | ||
171 | snd_hdac_device_exit(hdev); | ||
172 | kfree(hdev); | ||
173 | } | ||
174 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); | ||
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c new file mode 100644 index 000000000000..b2da19b60f4e --- /dev/null +++ b/sound/hda/ext/hdac_ext_controller.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * hdac-ext-controller.c - HD-audio extended controller functions. | ||
3 | * | ||
4 | * Copyright (C) 2014-2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/hda_register.h> | ||
23 | #include <sound/hdaudio_ext.h> | ||
24 | |||
25 | /* | ||
26 | * maximum HDAC capablities we should parse to avoid endless looping: | ||
27 | * currently we have 4 extended caps, so this is future proof for now. | ||
28 | * extend when this limit is seen meeting in real HW | ||
29 | */ | ||
30 | #define HDAC_MAX_CAPS 10 | ||
31 | |||
32 | /** | ||
33 | * snd_hdac_ext_bus_parse_capabilities - parse capablity structure | ||
34 | * @ebus: the pointer to extended bus object | ||
35 | * | ||
36 | * Returns 0 if successful, or a negative error code. | ||
37 | */ | ||
38 | int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *ebus) | ||
39 | { | ||
40 | unsigned int cur_cap; | ||
41 | unsigned int offset; | ||
42 | struct hdac_bus *bus = &ebus->bus; | ||
43 | unsigned int counter = 0; | ||
44 | |||
45 | offset = snd_hdac_chip_readl(bus, LLCH); | ||
46 | |||
47 | if (offset < 0) | ||
48 | return -EIO; | ||
49 | |||
50 | /* Lets walk the linked capabilities list */ | ||
51 | do { | ||
52 | cur_cap = _snd_hdac_chip_read(l, bus, offset); | ||
53 | |||
54 | if (cur_cap < 0) | ||
55 | return -EIO; | ||
56 | |||
57 | dev_dbg(bus->dev, "Capability version: 0x%x\n", | ||
58 | ((cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF)); | ||
59 | |||
60 | dev_dbg(bus->dev, "HDA capability ID: 0x%x\n", | ||
61 | (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF); | ||
62 | |||
63 | switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) { | ||
64 | case AZX_ML_CAP_ID: | ||
65 | dev_dbg(bus->dev, "Found ML capability\n"); | ||
66 | ebus->mlcap = bus->remap_addr + offset; | ||
67 | break; | ||
68 | |||
69 | case AZX_GTS_CAP_ID: | ||
70 | dev_dbg(bus->dev, "Found GTS capability offset=%x\n", offset); | ||
71 | ebus->gtscap = bus->remap_addr + offset; | ||
72 | break; | ||
73 | |||
74 | case AZX_PP_CAP_ID: | ||
75 | /* PP capability found, the Audio DSP is present */ | ||
76 | dev_dbg(bus->dev, "Found PP capability offset=%x\n", offset); | ||
77 | ebus->ppcap = bus->remap_addr + offset; | ||
78 | break; | ||
79 | |||
80 | case AZX_SPB_CAP_ID: | ||
81 | /* SPIB capability found, handler function */ | ||
82 | dev_dbg(bus->dev, "Found SPB capability\n"); | ||
83 | ebus->spbcap = bus->remap_addr + offset; | ||
84 | break; | ||
85 | |||
86 | default: | ||
87 | dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | counter++; | ||
92 | |||
93 | if (counter > HDAC_MAX_CAPS) { | ||
94 | dev_err(bus->dev, "We exceeded HDAC Ext capablities!!!\n"); | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | /* read the offset of next capabiity */ | ||
99 | offset = cur_cap & AZX_CAP_HDR_NXT_PTR_MASK; | ||
100 | |||
101 | } while (offset); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_parse_capabilities); | ||
106 | |||
107 | /* | ||
108 | * processing pipe helpers - these helpers are useful for dealing with HDA | ||
109 | * new capability of processing pipelines | ||
110 | */ | ||
111 | |||
112 | /** | ||
113 | * snd_hdac_ext_bus_ppcap_enable - enable/disable processing pipe capability | ||
114 | * @ebus: HD-audio extended core bus | ||
115 | * @enable: flag to turn on/off the capability | ||
116 | */ | ||
117 | void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *ebus, bool enable) | ||
118 | { | ||
119 | struct hdac_bus *bus = &ebus->bus; | ||
120 | |||
121 | if (!ebus->ppcap) { | ||
122 | dev_err(bus->dev, "Address of PP capability is NULL"); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | if (enable) | ||
127 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_GPROCEN); | ||
128 | else | ||
129 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_GPROCEN, 0); | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); | ||
132 | |||
133 | /** | ||
134 | * snd_hdac_ext_bus_ppcap_int_enable - ppcap interrupt enable/disable | ||
135 | * @ebus: HD-audio extended core bus | ||
136 | * @enable: flag to enable/disable interrupt | ||
137 | */ | ||
138 | void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *ebus, bool enable) | ||
139 | { | ||
140 | struct hdac_bus *bus = &ebus->bus; | ||
141 | |||
142 | if (!ebus->ppcap) { | ||
143 | dev_err(bus->dev, "Address of PP capability is NULL\n"); | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | if (enable) | ||
148 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_PIE); | ||
149 | else | ||
150 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_PIE, 0); | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); | ||
153 | |||
154 | /* | ||
155 | * Multilink helpers - these helpers are useful for dealing with HDA | ||
156 | * new multilink capability | ||
157 | */ | ||
158 | |||
159 | /** | ||
160 | * snd_hdac_ext_bus_get_ml_capabilities - get multilink capability | ||
161 | * @ebus: HD-audio extended core bus | ||
162 | * | ||
163 | * This will parse all links and read the mlink capabilities and add them | ||
164 | * in hlink_list of extended hdac bus | ||
165 | * Note: this will be freed on bus exit by driver | ||
166 | */ | ||
167 | int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) | ||
168 | { | ||
169 | int idx; | ||
170 | u32 link_count; | ||
171 | struct hdac_ext_link *hlink; | ||
172 | struct hdac_bus *bus = &ebus->bus; | ||
173 | |||
174 | link_count = readl(ebus->mlcap + AZX_REG_ML_MLCD) + 1; | ||
175 | |||
176 | dev_dbg(bus->dev, "In %s Link count: %d\n", __func__, link_count); | ||
177 | |||
178 | for (idx = 0; idx < link_count; idx++) { | ||
179 | hlink = kzalloc(sizeof(*hlink), GFP_KERNEL); | ||
180 | if (!hlink) | ||
181 | return -ENOMEM; | ||
182 | hlink->index = idx; | ||
183 | hlink->bus = bus; | ||
184 | hlink->ml_addr = ebus->mlcap + AZX_ML_BASE + | ||
185 | (AZX_ML_INTERVAL * idx); | ||
186 | hlink->lcaps = snd_hdac_chip_readl(bus, ML_LCAP); | ||
187 | hlink->lsdiid = snd_hdac_chip_readw(bus, ML_LSDIID); | ||
188 | |||
189 | list_add_tail(&hlink->list, &ebus->hlink_list); | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities); | ||
195 | |||
196 | /** | ||
197 | * snd_hdac_link_free_all- free hdac extended link objects | ||
198 | * | ||
199 | * @ebus: HD-audio ext core bus | ||
200 | */ | ||
201 | |||
202 | void snd_hdac_link_free_all(struct hdac_ext_bus *ebus) | ||
203 | { | ||
204 | struct hdac_ext_link *l; | ||
205 | |||
206 | while (!list_empty(&ebus->hlink_list)) { | ||
207 | l = list_first_entry(&ebus->hlink_list, struct hdac_ext_link, list); | ||
208 | list_del(&l->list); | ||
209 | kfree(l); | ||
210 | } | ||
211 | } | ||
212 | EXPORT_SYMBOL_GPL(snd_hdac_link_free_all); | ||
213 | |||
214 | /** | ||
215 | * snd_hdac_ext_bus_get_link_index - get link based on codec name | ||
216 | * @ebus: HD-audio extended core bus | ||
217 | * @codec_name: codec name | ||
218 | */ | ||
219 | struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus, | ||
220 | const char *codec_name) | ||
221 | { | ||
222 | int i; | ||
223 | struct hdac_ext_link *hlink = NULL; | ||
224 | int bus_idx, addr; | ||
225 | |||
226 | if (sscanf(codec_name, "ehdaudio%dD%d", &bus_idx, &addr) != 2) | ||
227 | return NULL; | ||
228 | if (ebus->idx != bus_idx) | ||
229 | return NULL; | ||
230 | |||
231 | list_for_each_entry(hlink, &ebus->hlink_list, list) { | ||
232 | for (i = 0; i < HDA_MAX_CODECS; i++) { | ||
233 | if (hlink->lsdiid & (0x1 << addr)) | ||
234 | return hlink; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | return NULL; | ||
239 | } | ||
240 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_link); | ||
241 | |||
242 | static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) | ||
243 | { | ||
244 | int timeout; | ||
245 | u32 val; | ||
246 | int mask = (1 << AZX_MLCTL_CPA); | ||
247 | |||
248 | udelay(3); | ||
249 | timeout = 50; | ||
250 | |||
251 | do { | ||
252 | val = snd_hdac_chip_readl(link->bus, ML_LCTL); | ||
253 | if (enable) { | ||
254 | if (((val & mask) >> AZX_MLCTL_CPA)) | ||
255 | return 0; | ||
256 | } else { | ||
257 | if (!((val & mask) >> AZX_MLCTL_CPA)) | ||
258 | return 0; | ||
259 | } | ||
260 | udelay(3); | ||
261 | } while (--timeout); | ||
262 | |||
263 | return -EIO; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * snd_hdac_ext_bus_link_power_up -power up hda link | ||
268 | * @link: HD-audio extended link | ||
269 | */ | ||
270 | int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) | ||
271 | { | ||
272 | snd_hdac_chip_updatel(link->bus, ML_LCTL, 0, AZX_MLCTL_SPA); | ||
273 | |||
274 | return check_hdac_link_power_active(link, true); | ||
275 | } | ||
276 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up); | ||
277 | |||
278 | /** | ||
279 | * snd_hdac_ext_bus_link_power_down -power down hda link | ||
280 | * @link: HD-audio extended link | ||
281 | */ | ||
282 | int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link) | ||
283 | { | ||
284 | snd_hdac_chip_updatel(link->bus, ML_LCTL, AZX_MLCTL_SPA, 0); | ||
285 | |||
286 | return check_hdac_link_power_active(link, false); | ||
287 | } | ||
288 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down); | ||
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c new file mode 100644 index 000000000000..f8ffbdbb450d --- /dev/null +++ b/sound/hda/ext/hdac_ext_stream.c | |||
@@ -0,0 +1,452 @@ | |||
1 | /* | ||
2 | * hdac-ext-stream.c - HD-audio extended stream operations. | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/hda_register.h> | ||
24 | #include <sound/hdaudio_ext.h> | ||
25 | |||
26 | /** | ||
27 | * snd_hdac_ext_stream_init - initialize each stream (aka device) | ||
28 | * @ebus: HD-audio ext core bus | ||
29 | * @stream: HD-audio ext core stream object to initialize | ||
30 | * @idx: stream index number | ||
31 | * @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE) | ||
32 | * @tag: the tag id to assign | ||
33 | * | ||
34 | * initialize the stream, if ppcap is enabled then init those and then | ||
35 | * invoke hdac stream initialization routine | ||
36 | */ | ||
37 | void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus, | ||
38 | struct hdac_ext_stream *stream, | ||
39 | int idx, int direction, int tag) | ||
40 | { | ||
41 | struct hdac_bus *bus = &ebus->bus; | ||
42 | |||
43 | if (ebus->ppcap) { | ||
44 | stream->pphc_addr = ebus->ppcap + AZX_PPHC_BASE + | ||
45 | AZX_PPHC_INTERVAL * idx; | ||
46 | |||
47 | stream->pplc_addr = ebus->ppcap + AZX_PPLC_BASE + | ||
48 | AZX_PPLC_MULTI * ebus->num_streams + | ||
49 | AZX_PPLC_INTERVAL * idx; | ||
50 | } | ||
51 | |||
52 | stream->decoupled = false; | ||
53 | snd_hdac_stream_init(bus, &stream->hstream, idx, direction, tag); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init); | ||
56 | |||
57 | /** | ||
58 | * snd_hdac_ext_stream_init_all - create and initialize the stream objects | ||
59 | * for an extended hda bus | ||
60 | * @ebus: HD-audio ext core bus | ||
61 | * @start_idx: start index for streams | ||
62 | * @num_stream: number of streams to initialize | ||
63 | * @dir: direction of streams | ||
64 | */ | ||
65 | int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, | ||
66 | int num_stream, int dir) | ||
67 | { | ||
68 | int stream_tag = 0; | ||
69 | int i, tag, idx = start_idx; | ||
70 | |||
71 | for (i = 0; i < num_stream; i++) { | ||
72 | struct hdac_ext_stream *stream = | ||
73 | kzalloc(sizeof(*stream), GFP_KERNEL); | ||
74 | if (!stream) | ||
75 | return -ENOMEM; | ||
76 | tag = ++stream_tag; | ||
77 | snd_hdac_ext_stream_init(ebus, stream, idx, dir, tag); | ||
78 | idx++; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | |||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all); | ||
85 | |||
86 | /** | ||
87 | * snd_hdac_stream_free_all - free hdac extended stream objects | ||
88 | * | ||
89 | * @ebus: HD-audio ext core bus | ||
90 | */ | ||
91 | void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus) | ||
92 | { | ||
93 | struct hdac_stream *s; | ||
94 | struct hdac_ext_stream *stream; | ||
95 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
96 | |||
97 | while (!list_empty(&bus->stream_list)) { | ||
98 | s = list_first_entry(&bus->stream_list, struct hdac_stream, list); | ||
99 | stream = stream_to_hdac_ext_stream(s); | ||
100 | list_del(&s->list); | ||
101 | kfree(stream); | ||
102 | } | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); | ||
105 | |||
106 | /** | ||
107 | * snd_hdac_ext_stream_decouple - decouple the hdac stream | ||
108 | * @ebus: HD-audio ext core bus | ||
109 | * @stream: HD-audio ext core stream object to initialize | ||
110 | * @decouple: flag to decouple | ||
111 | */ | ||
112 | void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, | ||
113 | struct hdac_ext_stream *stream, bool decouple) | ||
114 | { | ||
115 | struct hdac_stream *hstream = &stream->hstream; | ||
116 | struct hdac_bus *bus = &ebus->bus; | ||
117 | |||
118 | spin_lock_irq(&bus->reg_lock); | ||
119 | if (decouple) | ||
120 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, | ||
121 | AZX_PPCTL_PROCEN(hstream->index)); | ||
122 | else | ||
123 | snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, | ||
124 | AZX_PPCTL_PROCEN(hstream->index), 0); | ||
125 | stream->decoupled = decouple; | ||
126 | spin_unlock_irq(&bus->reg_lock); | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); | ||
129 | |||
130 | /** | ||
131 | * snd_hdac_ext_linkstream_start - start a stream | ||
132 | * @stream: HD-audio ext core stream to start | ||
133 | */ | ||
134 | void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *stream) | ||
135 | { | ||
136 | snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, 0, AZX_PPLCCTL_RUN); | ||
137 | } | ||
138 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_start); | ||
139 | |||
140 | /** | ||
141 | * snd_hdac_ext_link_stream_clear - stop a stream DMA | ||
142 | * @stream: HD-audio ext core stream to stop | ||
143 | */ | ||
144 | void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *stream) | ||
145 | { | ||
146 | snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, AZX_PPLCCTL_RUN, 0); | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_clear); | ||
149 | |||
150 | /** | ||
151 | * snd_hdac_ext_link_stream_reset - reset a stream | ||
152 | * @stream: HD-audio ext core stream to reset | ||
153 | */ | ||
154 | void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *stream) | ||
155 | { | ||
156 | unsigned char val; | ||
157 | int timeout; | ||
158 | |||
159 | snd_hdac_ext_link_stream_clear(stream); | ||
160 | |||
161 | snd_hdac_updatel(stream->pplc_addr, AZX_REG_PPLCCTL, 0, AZX_PPLCCTL_STRST); | ||
162 | udelay(3); | ||
163 | timeout = 50; | ||
164 | do { | ||
165 | val = readl(stream->pplc_addr + AZX_REG_PPLCCTL) & | ||
166 | AZX_PPLCCTL_STRST; | ||
167 | if (val) | ||
168 | break; | ||
169 | udelay(3); | ||
170 | } while (--timeout); | ||
171 | val &= ~AZX_PPLCCTL_STRST; | ||
172 | writel(val, stream->pplc_addr + AZX_REG_PPLCCTL); | ||
173 | udelay(3); | ||
174 | |||
175 | timeout = 50; | ||
176 | /* waiting for hardware to report that the stream is out of reset */ | ||
177 | do { | ||
178 | val = readl(stream->pplc_addr + AZX_REG_PPLCCTL) & AZX_PPLCCTL_STRST; | ||
179 | if (!val) | ||
180 | break; | ||
181 | udelay(3); | ||
182 | } while (--timeout); | ||
183 | |||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_reset); | ||
186 | |||
187 | /** | ||
188 | * snd_hdac_ext_link_stream_setup - set up the SD for streaming | ||
189 | * @stream: HD-audio ext core stream to set up | ||
190 | * @fmt: stream format | ||
191 | */ | ||
192 | int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *stream, int fmt) | ||
193 | { | ||
194 | struct hdac_stream *hstream = &stream->hstream; | ||
195 | unsigned int val; | ||
196 | |||
197 | /* make sure the run bit is zero for SD */ | ||
198 | snd_hdac_ext_link_stream_clear(stream); | ||
199 | /* program the stream_tag */ | ||
200 | val = readl(stream->pplc_addr + AZX_REG_PPLCCTL); | ||
201 | val = (val & ~AZX_PPLCCTL_STRM_MASK) | | ||
202 | (hstream->stream_tag << AZX_PPLCCTL_STRM_SHIFT); | ||
203 | writel(val, stream->pplc_addr + AZX_REG_PPLCCTL); | ||
204 | |||
205 | /* program the stream format */ | ||
206 | writew(fmt, stream->pplc_addr + AZX_REG_PPLCFMT); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_stream_setup); | ||
211 | |||
212 | /** | ||
213 | * snd_hdac_ext_link_set_stream_id - maps stream id to link output | ||
214 | * @link: HD-audio ext link to set up | ||
215 | * @stream: stream id | ||
216 | */ | ||
217 | void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link, | ||
218 | int stream) | ||
219 | { | ||
220 | snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, (1 << stream), 0); | ||
221 | } | ||
222 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_set_stream_id); | ||
223 | |||
224 | /** | ||
225 | * snd_hdac_ext_link_clear_stream_id - maps stream id to link output | ||
226 | * @link: HD-audio ext link to set up | ||
227 | * @stream: stream id | ||
228 | */ | ||
229 | void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, | ||
230 | int stream) | ||
231 | { | ||
232 | snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, 0, (1 << stream)); | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id); | ||
235 | |||
236 | static struct hdac_ext_stream * | ||
237 | hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, | ||
238 | struct snd_pcm_substream *substream) | ||
239 | { | ||
240 | struct hdac_ext_stream *res = NULL; | ||
241 | struct hdac_stream *stream = NULL; | ||
242 | struct hdac_bus *hbus = &ebus->bus; | ||
243 | |||
244 | if (!ebus->ppcap) { | ||
245 | dev_err(hbus->dev, "stream type not supported\n"); | ||
246 | return NULL; | ||
247 | } | ||
248 | |||
249 | list_for_each_entry(stream, &hbus->stream_list, list) { | ||
250 | struct hdac_ext_stream *hstream = container_of(stream, | ||
251 | struct hdac_ext_stream, | ||
252 | hstream); | ||
253 | if (stream->direction != substream->stream) | ||
254 | continue; | ||
255 | |||
256 | /* check if decoupled stream and not in use is available */ | ||
257 | if (hstream->decoupled && !hstream->link_locked) { | ||
258 | res = hstream; | ||
259 | break; | ||
260 | } | ||
261 | |||
262 | if (!hstream->link_locked) { | ||
263 | snd_hdac_ext_stream_decouple(ebus, hstream, true); | ||
264 | res = hstream; | ||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | if (res) { | ||
269 | spin_lock_irq(&hbus->reg_lock); | ||
270 | res->link_locked = 1; | ||
271 | res->link_substream = substream; | ||
272 | spin_unlock_irq(&hbus->reg_lock); | ||
273 | } | ||
274 | return res; | ||
275 | } | ||
276 | |||
277 | static struct hdac_ext_stream * | ||
278 | hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, | ||
279 | struct snd_pcm_substream *substream) | ||
280 | { | ||
281 | struct hdac_ext_stream *res = NULL; | ||
282 | struct hdac_stream *stream = NULL; | ||
283 | struct hdac_bus *hbus = &ebus->bus; | ||
284 | int key; | ||
285 | |||
286 | if (!ebus->ppcap) { | ||
287 | dev_err(hbus->dev, "stream type not supported\n"); | ||
288 | return NULL; | ||
289 | } | ||
290 | |||
291 | /* make a non-zero unique key for the substream */ | ||
292 | key = (substream->pcm->device << 16) | (substream->number << 2) | | ||
293 | (substream->stream + 1); | ||
294 | |||
295 | list_for_each_entry(stream, &hbus->stream_list, list) { | ||
296 | struct hdac_ext_stream *hstream = container_of(stream, | ||
297 | struct hdac_ext_stream, | ||
298 | hstream); | ||
299 | if (stream->direction != substream->stream) | ||
300 | continue; | ||
301 | |||
302 | if (stream->opened) { | ||
303 | if (!hstream->decoupled) | ||
304 | snd_hdac_ext_stream_decouple(ebus, hstream, true); | ||
305 | res = hstream; | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | if (res) { | ||
310 | spin_lock_irq(&hbus->reg_lock); | ||
311 | res->hstream.opened = 1; | ||
312 | res->hstream.running = 0; | ||
313 | res->hstream.assigned_key = key; | ||
314 | res->hstream.substream = substream; | ||
315 | spin_unlock_irq(&hbus->reg_lock); | ||
316 | } | ||
317 | |||
318 | return res; | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * snd_hdac_ext_stream_assign - assign a stream for the PCM | ||
323 | * @ebus: HD-audio ext core bus | ||
324 | * @substream: PCM substream to assign | ||
325 | * @type: type of stream (coupled, host or link stream) | ||
326 | * | ||
327 | * This assigns the stream based on the type (coupled/host/link), for the | ||
328 | * given PCM substream, assigns it and returns the stream object | ||
329 | * | ||
330 | * coupled: Looks for an unused stream | ||
331 | * host: Looks for an unused decoupled host stream | ||
332 | * link: Looks for an unused decoupled link stream | ||
333 | * | ||
334 | * If no stream is free, returns NULL. The function tries to keep using | ||
335 | * the same stream object when it's used beforehand. when a stream is | ||
336 | * decoupled, it becomes a host stream and link stream. | ||
337 | */ | ||
338 | struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *ebus, | ||
339 | struct snd_pcm_substream *substream, | ||
340 | int type) | ||
341 | { | ||
342 | struct hdac_ext_stream *hstream = NULL; | ||
343 | struct hdac_stream *stream = NULL; | ||
344 | struct hdac_bus *hbus = &ebus->bus; | ||
345 | |||
346 | switch (type) { | ||
347 | case HDAC_EXT_STREAM_TYPE_COUPLED: | ||
348 | stream = snd_hdac_stream_assign(hbus, substream); | ||
349 | if (stream) | ||
350 | hstream = container_of(stream, | ||
351 | struct hdac_ext_stream, hstream); | ||
352 | return hstream; | ||
353 | |||
354 | case HDAC_EXT_STREAM_TYPE_HOST: | ||
355 | return hdac_ext_host_stream_assign(ebus, substream); | ||
356 | |||
357 | case HDAC_EXT_STREAM_TYPE_LINK: | ||
358 | return hdac_ext_link_stream_assign(ebus, substream); | ||
359 | |||
360 | default: | ||
361 | return NULL; | ||
362 | } | ||
363 | } | ||
364 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_assign); | ||
365 | |||
366 | /** | ||
367 | * snd_hdac_ext_stream_release - release the assigned stream | ||
368 | * @stream: HD-audio ext core stream to release | ||
369 | * @type: type of stream (coupled, host or link stream) | ||
370 | * | ||
371 | * Release the stream that has been assigned by snd_hdac_ext_stream_assign(). | ||
372 | */ | ||
373 | void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) | ||
374 | { | ||
375 | struct hdac_bus *bus = stream->hstream.bus; | ||
376 | struct hdac_ext_bus *ebus = hbus_to_ebus(bus); | ||
377 | |||
378 | switch (type) { | ||
379 | case HDAC_EXT_STREAM_TYPE_COUPLED: | ||
380 | snd_hdac_stream_release(&stream->hstream); | ||
381 | break; | ||
382 | |||
383 | case HDAC_EXT_STREAM_TYPE_HOST: | ||
384 | if (stream->decoupled) { | ||
385 | snd_hdac_ext_stream_decouple(ebus, stream, false); | ||
386 | snd_hdac_stream_release(&stream->hstream); | ||
387 | } | ||
388 | break; | ||
389 | |||
390 | case HDAC_EXT_STREAM_TYPE_LINK: | ||
391 | if (stream->decoupled) | ||
392 | snd_hdac_ext_stream_decouple(ebus, stream, false); | ||
393 | spin_lock_irq(&bus->reg_lock); | ||
394 | stream->link_locked = 0; | ||
395 | stream->link_substream = NULL; | ||
396 | spin_unlock_irq(&bus->reg_lock); | ||
397 | break; | ||
398 | |||
399 | default: | ||
400 | dev_dbg(bus->dev, "Invalid type %d\n", type); | ||
401 | } | ||
402 | |||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release); | ||
405 | |||
406 | /** | ||
407 | * snd_hdac_ext_stream_spbcap_enable - enable SPIB for a stream | ||
408 | * @ebus: HD-audio ext core bus | ||
409 | * @enable: flag to enable/disable SPIB | ||
410 | * @index: stream index for which SPIB need to be enabled | ||
411 | */ | ||
412 | void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, | ||
413 | bool enable, int index) | ||
414 | { | ||
415 | u32 mask = 0; | ||
416 | u32 register_mask = 0; | ||
417 | struct hdac_bus *bus = &ebus->bus; | ||
418 | |||
419 | if (!ebus->spbcap) { | ||
420 | dev_err(bus->dev, "Address of SPB capability is NULL"); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | mask |= (1 << index); | ||
425 | |||
426 | register_mask = snd_hdac_chip_readl(bus, SPB_SPBFCCTL); | ||
427 | |||
428 | mask |= register_mask; | ||
429 | |||
430 | if (enable) | ||
431 | snd_hdac_updatel(ebus->spbcap, AZX_REG_SPB_SPBFCCTL, 0, mask); | ||
432 | else | ||
433 | snd_hdac_updatel(ebus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0); | ||
434 | } | ||
435 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable); | ||
436 | |||
437 | /** | ||
438 | * snd_hdac_ext_stop_streams - stop all stream if running | ||
439 | * @ebus: HD-audio ext core bus | ||
440 | */ | ||
441 | void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus) | ||
442 | { | ||
443 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
444 | struct hdac_stream *stream; | ||
445 | |||
446 | if (bus->chip_init) { | ||
447 | list_for_each_entry(stream, &bus->stream_list, list) | ||
448 | snd_hdac_stream_stop(stream); | ||
449 | snd_hdac_bus_stop_chip(bus); | ||
450 | } | ||
451 | } | ||
452 | EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams); | ||
diff --git a/sound/hda/hda_bus_type.c b/sound/hda/hda_bus_type.c index 519914a12e8a..89c2711baaaf 100644 --- a/sound/hda/hda_bus_type.c +++ b/sound/hda/hda_bus_type.c | |||
@@ -10,6 +10,40 @@ | |||
10 | MODULE_DESCRIPTION("HD-audio bus"); | 10 | MODULE_DESCRIPTION("HD-audio bus"); |
11 | MODULE_LICENSE("GPL"); | 11 | MODULE_LICENSE("GPL"); |
12 | 12 | ||
13 | /** | ||
14 | * hdac_get_device_id - gets the hdac device id entry | ||
15 | * @hdev: HD-audio core device | ||
16 | * @drv: HD-audio codec driver | ||
17 | * | ||
18 | * Compares the hdac device vendor_id and revision_id to the hdac_device | ||
19 | * driver id_table and returns the matching device id entry. | ||
20 | */ | ||
21 | const struct hda_device_id * | ||
22 | hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv) | ||
23 | { | ||
24 | if (drv->id_table) { | ||
25 | const struct hda_device_id *id = drv->id_table; | ||
26 | |||
27 | while (id->vendor_id) { | ||
28 | if (hdev->vendor_id == id->vendor_id && | ||
29 | (!id->rev_id || id->rev_id == hdev->revision_id)) | ||
30 | return id; | ||
31 | id++; | ||
32 | } | ||
33 | } | ||
34 | |||
35 | return NULL; | ||
36 | } | ||
37 | EXPORT_SYMBOL_GPL(hdac_get_device_id); | ||
38 | |||
39 | static int hdac_codec_match(struct hdac_device *dev, struct hdac_driver *drv) | ||
40 | { | ||
41 | if (hdac_get_device_id(dev, drv)) | ||
42 | return 1; | ||
43 | else | ||
44 | return 0; | ||
45 | } | ||
46 | |||
13 | static int hda_bus_match(struct device *dev, struct device_driver *drv) | 47 | static int hda_bus_match(struct device *dev, struct device_driver *drv) |
14 | { | 48 | { |
15 | struct hdac_device *hdev = dev_to_hdac_dev(dev); | 49 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
@@ -17,8 +51,15 @@ static int hda_bus_match(struct device *dev, struct device_driver *drv) | |||
17 | 51 | ||
18 | if (hdev->type != hdrv->type) | 52 | if (hdev->type != hdrv->type) |
19 | return 0; | 53 | return 0; |
54 | |||
55 | /* | ||
56 | * if driver provided a match function use that otherwise we will | ||
57 | * use hdac_codec_match function | ||
58 | */ | ||
20 | if (hdrv->match) | 59 | if (hdrv->match) |
21 | return hdrv->match(hdev, hdrv); | 60 | return hdrv->match(hdev, hdrv); |
61 | else | ||
62 | return hdac_codec_match(hdev, hdrv); | ||
22 | return 1; | 63 | return 1; |
23 | } | 64 | } |
24 | 65 | ||
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 8e262da74f6a..27c447e4fe5c 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c | |||
@@ -11,21 +11,36 @@ | |||
11 | 11 | ||
12 | static void process_unsol_events(struct work_struct *work); | 12 | static void process_unsol_events(struct work_struct *work); |
13 | 13 | ||
14 | static const struct hdac_bus_ops default_ops = { | ||
15 | .command = snd_hdac_bus_send_cmd, | ||
16 | .get_response = snd_hdac_bus_get_response, | ||
17 | }; | ||
18 | |||
14 | /** | 19 | /** |
15 | * snd_hdac_bus_init - initialize a HD-audio bas bus | 20 | * snd_hdac_bus_init - initialize a HD-audio bas bus |
16 | * @bus: the pointer to bus object | 21 | * @bus: the pointer to bus object |
22 | * @ops: bus verb operators | ||
23 | * @io_ops: lowlevel I/O operators | ||
17 | * | 24 | * |
18 | * Returns 0 if successful, or a negative error code. | 25 | * Returns 0 if successful, or a negative error code. |
19 | */ | 26 | */ |
20 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | 27 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
21 | const struct hdac_bus_ops *ops) | 28 | const struct hdac_bus_ops *ops, |
29 | const struct hdac_io_ops *io_ops) | ||
22 | { | 30 | { |
23 | memset(bus, 0, sizeof(*bus)); | 31 | memset(bus, 0, sizeof(*bus)); |
24 | bus->dev = dev; | 32 | bus->dev = dev; |
25 | bus->ops = ops; | 33 | if (ops) |
34 | bus->ops = ops; | ||
35 | else | ||
36 | bus->ops = &default_ops; | ||
37 | bus->io_ops = io_ops; | ||
38 | INIT_LIST_HEAD(&bus->stream_list); | ||
26 | INIT_LIST_HEAD(&bus->codec_list); | 39 | INIT_LIST_HEAD(&bus->codec_list); |
27 | INIT_WORK(&bus->unsol_work, process_unsol_events); | 40 | INIT_WORK(&bus->unsol_work, process_unsol_events); |
41 | spin_lock_init(&bus->reg_lock); | ||
28 | mutex_init(&bus->cmd_mutex); | 42 | mutex_init(&bus->cmd_mutex); |
43 | bus->irq = -1; | ||
29 | return 0; | 44 | return 0; |
30 | } | 45 | } |
31 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init); | 46 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init); |
@@ -36,6 +51,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init); | |||
36 | */ | 51 | */ |
37 | void snd_hdac_bus_exit(struct hdac_bus *bus) | 52 | void snd_hdac_bus_exit(struct hdac_bus *bus) |
38 | { | 53 | { |
54 | WARN_ON(!list_empty(&bus->stream_list)); | ||
39 | WARN_ON(!list_empty(&bus->codec_list)); | 55 | WARN_ON(!list_empty(&bus->codec_list)); |
40 | cancel_work_sync(&bus->unsol_work); | 56 | cancel_work_sync(&bus->unsol_work); |
41 | } | 57 | } |
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c new file mode 100644 index 000000000000..b5a17cb510a0 --- /dev/null +++ b/sound/hda/hdac_controller.c | |||
@@ -0,0 +1,507 @@ | |||
1 | /* | ||
2 | * HD-audio controller helpers | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/export.h> | ||
8 | #include <sound/core.h> | ||
9 | #include <sound/hdaudio.h> | ||
10 | #include <sound/hda_register.h> | ||
11 | |||
12 | /* clear CORB read pointer properly */ | ||
13 | static void azx_clear_corbrp(struct hdac_bus *bus) | ||
14 | { | ||
15 | int timeout; | ||
16 | |||
17 | for (timeout = 1000; timeout > 0; timeout--) { | ||
18 | if (snd_hdac_chip_readw(bus, CORBRP) & AZX_CORBRP_RST) | ||
19 | break; | ||
20 | udelay(1); | ||
21 | } | ||
22 | if (timeout <= 0) | ||
23 | dev_err(bus->dev, "CORB reset timeout#1, CORBRP = %d\n", | ||
24 | snd_hdac_chip_readw(bus, CORBRP)); | ||
25 | |||
26 | snd_hdac_chip_writew(bus, CORBRP, 0); | ||
27 | for (timeout = 1000; timeout > 0; timeout--) { | ||
28 | if (snd_hdac_chip_readw(bus, CORBRP) == 0) | ||
29 | break; | ||
30 | udelay(1); | ||
31 | } | ||
32 | if (timeout <= 0) | ||
33 | dev_err(bus->dev, "CORB reset timeout#2, CORBRP = %d\n", | ||
34 | snd_hdac_chip_readw(bus, CORBRP)); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * snd_hdac_bus_init_cmd_io - set up CORB/RIRB buffers | ||
39 | * @bus: HD-audio core bus | ||
40 | */ | ||
41 | void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) | ||
42 | { | ||
43 | spin_lock_irq(&bus->reg_lock); | ||
44 | /* CORB set up */ | ||
45 | bus->corb.addr = bus->rb.addr; | ||
46 | bus->corb.buf = (__le32 *)bus->rb.area; | ||
47 | snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr); | ||
48 | snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr)); | ||
49 | |||
50 | /* set the corb size to 256 entries (ULI requires explicitly) */ | ||
51 | snd_hdac_chip_writeb(bus, CORBSIZE, 0x02); | ||
52 | /* set the corb write pointer to 0 */ | ||
53 | snd_hdac_chip_writew(bus, CORBWP, 0); | ||
54 | |||
55 | /* reset the corb hw read pointer */ | ||
56 | snd_hdac_chip_writew(bus, CORBRP, AZX_CORBRP_RST); | ||
57 | if (!bus->corbrp_self_clear) | ||
58 | azx_clear_corbrp(bus); | ||
59 | |||
60 | /* enable corb dma */ | ||
61 | snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN); | ||
62 | |||
63 | /* RIRB set up */ | ||
64 | bus->rirb.addr = bus->rb.addr + 2048; | ||
65 | bus->rirb.buf = (__le32 *)(bus->rb.area + 2048); | ||
66 | bus->rirb.wp = bus->rirb.rp = 0; | ||
67 | memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds)); | ||
68 | snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr); | ||
69 | snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr)); | ||
70 | |||
71 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | ||
72 | snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02); | ||
73 | /* reset the rirb hw write pointer */ | ||
74 | snd_hdac_chip_writew(bus, RIRBWP, AZX_RIRBWP_RST); | ||
75 | /* set N=1, get RIRB response interrupt for new entry */ | ||
76 | snd_hdac_chip_writew(bus, RINTCNT, 1); | ||
77 | /* enable rirb dma and response irq */ | ||
78 | snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); | ||
79 | spin_unlock_irq(&bus->reg_lock); | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io); | ||
82 | |||
83 | /** | ||
84 | * snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers | ||
85 | * @bus: HD-audio core bus | ||
86 | */ | ||
87 | void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus) | ||
88 | { | ||
89 | spin_lock_irq(&bus->reg_lock); | ||
90 | /* disable ringbuffer DMAs */ | ||
91 | snd_hdac_chip_writeb(bus, RIRBCTL, 0); | ||
92 | snd_hdac_chip_writeb(bus, CORBCTL, 0); | ||
93 | /* disable unsolicited responses */ | ||
94 | snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0); | ||
95 | spin_unlock_irq(&bus->reg_lock); | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io); | ||
98 | |||
99 | static unsigned int azx_command_addr(u32 cmd) | ||
100 | { | ||
101 | unsigned int addr = cmd >> 28; | ||
102 | |||
103 | if (snd_BUG_ON(addr >= HDA_MAX_CODECS)) | ||
104 | addr = 0; | ||
105 | return addr; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * snd_hdac_bus_send_cmd - send a command verb via CORB | ||
110 | * @bus: HD-audio core bus | ||
111 | * @val: encoded verb value to send | ||
112 | * | ||
113 | * Returns zero for success or a negative error code. | ||
114 | */ | ||
115 | int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val) | ||
116 | { | ||
117 | unsigned int addr = azx_command_addr(val); | ||
118 | unsigned int wp, rp; | ||
119 | |||
120 | spin_lock_irq(&bus->reg_lock); | ||
121 | |||
122 | bus->last_cmd[azx_command_addr(val)] = val; | ||
123 | |||
124 | /* add command to corb */ | ||
125 | wp = snd_hdac_chip_readw(bus, CORBWP); | ||
126 | if (wp == 0xffff) { | ||
127 | /* something wrong, controller likely turned to D3 */ | ||
128 | spin_unlock_irq(&bus->reg_lock); | ||
129 | return -EIO; | ||
130 | } | ||
131 | wp++; | ||
132 | wp %= AZX_MAX_CORB_ENTRIES; | ||
133 | |||
134 | rp = snd_hdac_chip_readw(bus, CORBRP); | ||
135 | if (wp == rp) { | ||
136 | /* oops, it's full */ | ||
137 | spin_unlock_irq(&bus->reg_lock); | ||
138 | return -EAGAIN; | ||
139 | } | ||
140 | |||
141 | bus->rirb.cmds[addr]++; | ||
142 | bus->corb.buf[wp] = cpu_to_le32(val); | ||
143 | snd_hdac_chip_writew(bus, CORBWP, wp); | ||
144 | |||
145 | spin_unlock_irq(&bus->reg_lock); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd); | ||
150 | |||
151 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) | ||
152 | |||
153 | /** | ||
154 | * snd_hdac_bus_update_rirb - retrieve RIRB entries | ||
155 | * @bus: HD-audio core bus | ||
156 | * | ||
157 | * Usually called from interrupt handler. | ||
158 | */ | ||
159 | void snd_hdac_bus_update_rirb(struct hdac_bus *bus) | ||
160 | { | ||
161 | unsigned int rp, wp; | ||
162 | unsigned int addr; | ||
163 | u32 res, res_ex; | ||
164 | |||
165 | wp = snd_hdac_chip_readw(bus, RIRBWP); | ||
166 | if (wp == 0xffff) { | ||
167 | /* something wrong, controller likely turned to D3 */ | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | if (wp == bus->rirb.wp) | ||
172 | return; | ||
173 | bus->rirb.wp = wp; | ||
174 | |||
175 | while (bus->rirb.rp != wp) { | ||
176 | bus->rirb.rp++; | ||
177 | bus->rirb.rp %= AZX_MAX_RIRB_ENTRIES; | ||
178 | |||
179 | rp = bus->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | ||
180 | res_ex = le32_to_cpu(bus->rirb.buf[rp + 1]); | ||
181 | res = le32_to_cpu(bus->rirb.buf[rp]); | ||
182 | addr = res_ex & 0xf; | ||
183 | if (addr >= HDA_MAX_CODECS) { | ||
184 | dev_err(bus->dev, | ||
185 | "spurious response %#x:%#x, rp = %d, wp = %d", | ||
186 | res, res_ex, bus->rirb.rp, wp); | ||
187 | snd_BUG(); | ||
188 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) | ||
189 | snd_hdac_bus_queue_event(bus, res, res_ex); | ||
190 | else if (bus->rirb.cmds[addr]) { | ||
191 | bus->rirb.res[addr] = res; | ||
192 | bus->rirb.cmds[addr]--; | ||
193 | } else { | ||
194 | dev_err_ratelimited(bus->dev, | ||
195 | "spurious response %#x:%#x, last cmd=%#08x\n", | ||
196 | res, res_ex, bus->last_cmd[addr]); | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(snd_hdac_bus_update_rirb); | ||
201 | |||
202 | /** | ||
203 | * snd_hdac_bus_get_response - receive a response via RIRB | ||
204 | * @bus: HD-audio core bus | ||
205 | * @addr: codec address | ||
206 | * @res: pointer to store the value, NULL when not needed | ||
207 | * | ||
208 | * Returns zero if a value is read, or a negative error code. | ||
209 | */ | ||
210 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, | ||
211 | unsigned int *res) | ||
212 | { | ||
213 | unsigned long timeout; | ||
214 | unsigned long loopcounter; | ||
215 | |||
216 | timeout = jiffies + msecs_to_jiffies(1000); | ||
217 | |||
218 | for (loopcounter = 0;; loopcounter++) { | ||
219 | spin_lock_irq(&bus->reg_lock); | ||
220 | if (!bus->rirb.cmds[addr]) { | ||
221 | if (res) | ||
222 | *res = bus->rirb.res[addr]; /* the last value */ | ||
223 | spin_unlock_irq(&bus->reg_lock); | ||
224 | return 0; | ||
225 | } | ||
226 | spin_unlock_irq(&bus->reg_lock); | ||
227 | if (time_after(jiffies, timeout)) | ||
228 | break; | ||
229 | if (loopcounter > 3000) | ||
230 | msleep(2); /* temporary workaround */ | ||
231 | else { | ||
232 | udelay(10); | ||
233 | cond_resched(); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | return -EIO; | ||
238 | } | ||
239 | EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response); | ||
240 | |||
241 | /* | ||
242 | * Lowlevel interface | ||
243 | */ | ||
244 | |||
245 | /** | ||
246 | * snd_hdac_bus_enter_link_reset - enter link reset | ||
247 | * @bus: HD-audio core bus | ||
248 | * | ||
249 | * Enter to the link reset state. | ||
250 | */ | ||
251 | void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus) | ||
252 | { | ||
253 | unsigned long timeout; | ||
254 | |||
255 | /* reset controller */ | ||
256 | snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, 0); | ||
257 | |||
258 | timeout = jiffies + msecs_to_jiffies(100); | ||
259 | while ((snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET) && | ||
260 | time_before(jiffies, timeout)) | ||
261 | usleep_range(500, 1000); | ||
262 | } | ||
263 | EXPORT_SYMBOL_GPL(snd_hdac_bus_enter_link_reset); | ||
264 | |||
265 | /** | ||
266 | * snd_hdac_bus_exit_link_reset - exit link reset | ||
267 | * @bus: HD-audio core bus | ||
268 | * | ||
269 | * Exit from the link reset state. | ||
270 | */ | ||
271 | void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus) | ||
272 | { | ||
273 | unsigned long timeout; | ||
274 | |||
275 | snd_hdac_chip_updateb(bus, GCTL, 0, AZX_GCTL_RESET); | ||
276 | |||
277 | timeout = jiffies + msecs_to_jiffies(100); | ||
278 | while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout)) | ||
279 | usleep_range(500, 1000); | ||
280 | } | ||
281 | EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset); | ||
282 | |||
283 | /* reset codec link */ | ||
284 | static int azx_reset(struct hdac_bus *bus, bool full_reset) | ||
285 | { | ||
286 | if (!full_reset) | ||
287 | goto skip_reset; | ||
288 | |||
289 | /* clear STATESTS */ | ||
290 | snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); | ||
291 | |||
292 | /* reset controller */ | ||
293 | snd_hdac_bus_enter_link_reset(bus); | ||
294 | |||
295 | /* delay for >= 100us for codec PLL to settle per spec | ||
296 | * Rev 0.9 section 5.5.1 | ||
297 | */ | ||
298 | usleep_range(500, 1000); | ||
299 | |||
300 | /* Bring controller out of reset */ | ||
301 | snd_hdac_bus_exit_link_reset(bus); | ||
302 | |||
303 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | ||
304 | usleep_range(1000, 1200); | ||
305 | |||
306 | skip_reset: | ||
307 | /* check to see if controller is ready */ | ||
308 | if (!snd_hdac_chip_readb(bus, GCTL)) { | ||
309 | dev_dbg(bus->dev, "azx_reset: controller not ready!\n"); | ||
310 | return -EBUSY; | ||
311 | } | ||
312 | |||
313 | /* Accept unsolicited responses */ | ||
314 | snd_hdac_chip_updatel(bus, GCTL, 0, AZX_GCTL_UNSOL); | ||
315 | |||
316 | /* detect codecs */ | ||
317 | if (!bus->codec_mask) { | ||
318 | bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); | ||
319 | dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /* enable interrupts */ | ||
326 | static void azx_int_enable(struct hdac_bus *bus) | ||
327 | { | ||
328 | /* enable controller CIE and GIE */ | ||
329 | snd_hdac_chip_updatel(bus, INTCTL, 0, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); | ||
330 | } | ||
331 | |||
332 | /* disable interrupts */ | ||
333 | static void azx_int_disable(struct hdac_bus *bus) | ||
334 | { | ||
335 | struct hdac_stream *azx_dev; | ||
336 | |||
337 | /* disable interrupts in stream descriptor */ | ||
338 | list_for_each_entry(azx_dev, &bus->stream_list, list) | ||
339 | snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); | ||
340 | |||
341 | /* disable SIE for all streams */ | ||
342 | snd_hdac_chip_writeb(bus, INTCTL, 0); | ||
343 | |||
344 | /* disable controller CIE and GIE */ | ||
345 | snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN, 0); | ||
346 | } | ||
347 | |||
348 | /* clear interrupts */ | ||
349 | static void azx_int_clear(struct hdac_bus *bus) | ||
350 | { | ||
351 | struct hdac_stream *azx_dev; | ||
352 | |||
353 | /* clear stream status */ | ||
354 | list_for_each_entry(azx_dev, &bus->stream_list, list) | ||
355 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); | ||
356 | |||
357 | /* clear STATESTS */ | ||
358 | snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); | ||
359 | |||
360 | /* clear rirb status */ | ||
361 | snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); | ||
362 | |||
363 | /* clear int status */ | ||
364 | snd_hdac_chip_writel(bus, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * snd_hdac_bus_init_chip - reset and start the controller registers | ||
369 | * @bus: HD-audio core bus | ||
370 | * @full_reset: Do full reset | ||
371 | */ | ||
372 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset) | ||
373 | { | ||
374 | if (bus->chip_init) | ||
375 | return false; | ||
376 | |||
377 | /* reset controller */ | ||
378 | azx_reset(bus, full_reset); | ||
379 | |||
380 | /* initialize interrupts */ | ||
381 | azx_int_clear(bus); | ||
382 | azx_int_enable(bus); | ||
383 | |||
384 | /* initialize the codec command I/O */ | ||
385 | snd_hdac_bus_init_cmd_io(bus); | ||
386 | |||
387 | /* program the position buffer */ | ||
388 | if (bus->use_posbuf && bus->posbuf.addr) { | ||
389 | snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); | ||
390 | snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr)); | ||
391 | } | ||
392 | |||
393 | bus->chip_init = true; | ||
394 | return true; | ||
395 | } | ||
396 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip); | ||
397 | |||
398 | /** | ||
399 | * snd_hdac_bus_stop_chip - disable the whole IRQ and I/Os | ||
400 | * @bus: HD-audio core bus | ||
401 | */ | ||
402 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus) | ||
403 | { | ||
404 | if (!bus->chip_init) | ||
405 | return; | ||
406 | |||
407 | /* disable interrupts */ | ||
408 | azx_int_disable(bus); | ||
409 | azx_int_clear(bus); | ||
410 | |||
411 | /* disable CORB/RIRB */ | ||
412 | snd_hdac_bus_stop_cmd_io(bus); | ||
413 | |||
414 | /* disable position buffer */ | ||
415 | if (bus->posbuf.addr) { | ||
416 | snd_hdac_chip_writel(bus, DPLBASE, 0); | ||
417 | snd_hdac_chip_writel(bus, DPUBASE, 0); | ||
418 | } | ||
419 | |||
420 | bus->chip_init = false; | ||
421 | } | ||
422 | EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip); | ||
423 | |||
424 | /** | ||
425 | * snd_hdac_bus_handle_stream_irq - interrupt handler for streams | ||
426 | * @bus: HD-audio core bus | ||
427 | * @status: INTSTS register value | ||
428 | * @ask: callback to be called for woken streams | ||
429 | */ | ||
430 | void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, | ||
431 | void (*ack)(struct hdac_bus *, | ||
432 | struct hdac_stream *)) | ||
433 | { | ||
434 | struct hdac_stream *azx_dev; | ||
435 | u8 sd_status; | ||
436 | |||
437 | list_for_each_entry(azx_dev, &bus->stream_list, list) { | ||
438 | if (status & azx_dev->sd_int_sta_mask) { | ||
439 | sd_status = snd_hdac_stream_readb(azx_dev, SD_STS); | ||
440 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); | ||
441 | if (!azx_dev->substream || !azx_dev->running || | ||
442 | !(sd_status & SD_INT_COMPLETE)) | ||
443 | continue; | ||
444 | if (ack) | ||
445 | ack(bus, azx_dev); | ||
446 | } | ||
447 | } | ||
448 | } | ||
449 | EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq); | ||
450 | |||
451 | /** | ||
452 | * snd_hdac_bus_alloc_stream_pages - allocate BDL and other buffers | ||
453 | * @bus: HD-audio core bus | ||
454 | * | ||
455 | * Call this after assigning the all streams. | ||
456 | * Returns zero for success, or a negative error code. | ||
457 | */ | ||
458 | int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) | ||
459 | { | ||
460 | struct hdac_stream *s; | ||
461 | int num_streams = 0; | ||
462 | int err; | ||
463 | |||
464 | list_for_each_entry(s, &bus->stream_list, list) { | ||
465 | /* allocate memory for the BDL for each stream */ | ||
466 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | ||
467 | BDL_SIZE, &s->bdl); | ||
468 | num_streams++; | ||
469 | if (err < 0) | ||
470 | return -ENOMEM; | ||
471 | } | ||
472 | |||
473 | if (WARN_ON(!num_streams)) | ||
474 | return -EINVAL; | ||
475 | /* allocate memory for the position buffer */ | ||
476 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | ||
477 | num_streams * 8, &bus->posbuf); | ||
478 | if (err < 0) | ||
479 | return -ENOMEM; | ||
480 | list_for_each_entry(s, &bus->stream_list, list) | ||
481 | s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); | ||
482 | |||
483 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ | ||
484 | return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | ||
485 | PAGE_SIZE, &bus->rb); | ||
486 | } | ||
487 | EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); | ||
488 | |||
489 | /** | ||
490 | * snd_hdac_bus_free_stream_pages - release BDL and other buffers | ||
491 | * @bus: HD-audio core bus | ||
492 | */ | ||
493 | void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) | ||
494 | { | ||
495 | struct hdac_stream *s; | ||
496 | |||
497 | list_for_each_entry(s, &bus->stream_list, list) { | ||
498 | if (s->bdl.area) | ||
499 | bus->io_ops->dma_free_pages(bus, &s->bdl); | ||
500 | } | ||
501 | |||
502 | if (bus->rb.area) | ||
503 | bus->io_ops->dma_free_pages(bus, &bus->rb); | ||
504 | if (bus->posbuf.area) | ||
505 | bus->io_ops->dma_free_pages(bus, &bus->posbuf); | ||
506 | } | ||
507 | EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); | ||
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index f75bf5622687..cdee7103f649 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/pm_runtime.h> | 10 | #include <linux/pm_runtime.h> |
11 | #include <sound/hdaudio.h> | 11 | #include <sound/hdaudio.h> |
12 | #include <sound/hda_regmap.h> | 12 | #include <sound/hda_regmap.h> |
13 | #include <sound/pcm.h> | ||
13 | #include "local.h" | 14 | #include "local.h" |
14 | 15 | ||
15 | static void setup_fg_nodes(struct hdac_device *codec); | 16 | static void setup_fg_nodes(struct hdac_device *codec); |
@@ -551,6 +552,21 @@ void snd_hdac_power_down_pm(struct hdac_device *codec) | |||
551 | EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); | 552 | EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); |
552 | #endif | 553 | #endif |
553 | 554 | ||
555 | /* | ||
556 | * Enable/disable the link power for a codec. | ||
557 | */ | ||
558 | int snd_hdac_link_power(struct hdac_device *codec, bool enable) | ||
559 | { | ||
560 | if (!codec->link_power_control) | ||
561 | return 0; | ||
562 | |||
563 | if (codec->bus->ops->link_power) | ||
564 | return codec->bus->ops->link_power(codec->bus, enable); | ||
565 | else | ||
566 | return -EINVAL; | ||
567 | } | ||
568 | EXPORT_SYMBOL_GPL(snd_hdac_link_power); | ||
569 | |||
554 | /* codec vendor labels */ | 570 | /* codec vendor labels */ |
555 | struct hda_vendor_id { | 571 | struct hda_vendor_id { |
556 | unsigned int id; | 572 | unsigned int id; |
@@ -597,3 +613,302 @@ static int get_codec_vendor_name(struct hdac_device *codec) | |||
597 | codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); | 613 | codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); |
598 | return codec->vendor_name ? 0 : -ENOMEM; | 614 | return codec->vendor_name ? 0 : -ENOMEM; |
599 | } | 615 | } |
616 | |||
617 | /* | ||
618 | * stream formats | ||
619 | */ | ||
620 | struct hda_rate_tbl { | ||
621 | unsigned int hz; | ||
622 | unsigned int alsa_bits; | ||
623 | unsigned int hda_fmt; | ||
624 | }; | ||
625 | |||
626 | /* rate = base * mult / div */ | ||
627 | #define HDA_RATE(base, mult, div) \ | ||
628 | (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ | ||
629 | (((div) - 1) << AC_FMT_DIV_SHIFT)) | ||
630 | |||
631 | static struct hda_rate_tbl rate_bits[] = { | ||
632 | /* rate in Hz, ALSA rate bitmask, HDA format value */ | ||
633 | |||
634 | /* autodetected value used in snd_hda_query_supported_pcm */ | ||
635 | { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, | ||
636 | { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, | ||
637 | { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, | ||
638 | { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, | ||
639 | { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, | ||
640 | { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, | ||
641 | { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, | ||
642 | { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, | ||
643 | { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, | ||
644 | { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, | ||
645 | { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, | ||
646 | #define AC_PAR_PCM_RATE_BITS 11 | ||
647 | /* up to bits 10, 384kHZ isn't supported properly */ | ||
648 | |||
649 | /* not autodetected value */ | ||
650 | { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, | ||
651 | |||
652 | { 0 } /* terminator */ | ||
653 | }; | ||
654 | |||
655 | /** | ||
656 | * snd_hdac_calc_stream_format - calculate the format bitset | ||
657 | * @rate: the sample rate | ||
658 | * @channels: the number of channels | ||
659 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) | ||
660 | * @maxbps: the max. bps | ||
661 | * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant) | ||
662 | * | ||
663 | * Calculate the format bitset from the given rate, channels and th PCM format. | ||
664 | * | ||
665 | * Return zero if invalid. | ||
666 | */ | ||
667 | unsigned int snd_hdac_calc_stream_format(unsigned int rate, | ||
668 | unsigned int channels, | ||
669 | unsigned int format, | ||
670 | unsigned int maxbps, | ||
671 | unsigned short spdif_ctls) | ||
672 | { | ||
673 | int i; | ||
674 | unsigned int val = 0; | ||
675 | |||
676 | for (i = 0; rate_bits[i].hz; i++) | ||
677 | if (rate_bits[i].hz == rate) { | ||
678 | val = rate_bits[i].hda_fmt; | ||
679 | break; | ||
680 | } | ||
681 | if (!rate_bits[i].hz) | ||
682 | return 0; | ||
683 | |||
684 | if (channels == 0 || channels > 8) | ||
685 | return 0; | ||
686 | val |= channels - 1; | ||
687 | |||
688 | switch (snd_pcm_format_width(format)) { | ||
689 | case 8: | ||
690 | val |= AC_FMT_BITS_8; | ||
691 | break; | ||
692 | case 16: | ||
693 | val |= AC_FMT_BITS_16; | ||
694 | break; | ||
695 | case 20: | ||
696 | case 24: | ||
697 | case 32: | ||
698 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) | ||
699 | val |= AC_FMT_BITS_32; | ||
700 | else if (maxbps >= 24) | ||
701 | val |= AC_FMT_BITS_24; | ||
702 | else | ||
703 | val |= AC_FMT_BITS_20; | ||
704 | break; | ||
705 | default: | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | if (spdif_ctls & AC_DIG1_NONAUDIO) | ||
710 | val |= AC_FMT_TYPE_NON_PCM; | ||
711 | |||
712 | return val; | ||
713 | } | ||
714 | EXPORT_SYMBOL_GPL(snd_hdac_calc_stream_format); | ||
715 | |||
716 | static unsigned int query_pcm_param(struct hdac_device *codec, hda_nid_t nid) | ||
717 | { | ||
718 | unsigned int val = 0; | ||
719 | |||
720 | if (nid != codec->afg && | ||
721 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) | ||
722 | val = snd_hdac_read_parm(codec, nid, AC_PAR_PCM); | ||
723 | if (!val || val == -1) | ||
724 | val = snd_hdac_read_parm(codec, codec->afg, AC_PAR_PCM); | ||
725 | if (!val || val == -1) | ||
726 | return 0; | ||
727 | return val; | ||
728 | } | ||
729 | |||
730 | static unsigned int query_stream_param(struct hdac_device *codec, hda_nid_t nid) | ||
731 | { | ||
732 | unsigned int streams = snd_hdac_read_parm(codec, nid, AC_PAR_STREAM); | ||
733 | |||
734 | if (!streams || streams == -1) | ||
735 | streams = snd_hdac_read_parm(codec, codec->afg, AC_PAR_STREAM); | ||
736 | if (!streams || streams == -1) | ||
737 | return 0; | ||
738 | return streams; | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * snd_hdac_query_supported_pcm - query the supported PCM rates and formats | ||
743 | * @codec: the codec object | ||
744 | * @nid: NID to query | ||
745 | * @ratesp: the pointer to store the detected rate bitflags | ||
746 | * @formatsp: the pointer to store the detected formats | ||
747 | * @bpsp: the pointer to store the detected format widths | ||
748 | * | ||
749 | * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp | ||
750 | * or @bsps argument is ignored. | ||
751 | * | ||
752 | * Returns 0 if successful, otherwise a negative error code. | ||
753 | */ | ||
754 | int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, | ||
755 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | ||
756 | { | ||
757 | unsigned int i, val, wcaps; | ||
758 | |||
759 | wcaps = get_wcaps(codec, nid); | ||
760 | val = query_pcm_param(codec, nid); | ||
761 | |||
762 | if (ratesp) { | ||
763 | u32 rates = 0; | ||
764 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { | ||
765 | if (val & (1 << i)) | ||
766 | rates |= rate_bits[i].alsa_bits; | ||
767 | } | ||
768 | if (rates == 0) { | ||
769 | dev_err(&codec->dev, | ||
770 | "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n", | ||
771 | nid, val, | ||
772 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); | ||
773 | return -EIO; | ||
774 | } | ||
775 | *ratesp = rates; | ||
776 | } | ||
777 | |||
778 | if (formatsp || bpsp) { | ||
779 | u64 formats = 0; | ||
780 | unsigned int streams, bps; | ||
781 | |||
782 | streams = query_stream_param(codec, nid); | ||
783 | if (!streams) | ||
784 | return -EIO; | ||
785 | |||
786 | bps = 0; | ||
787 | if (streams & AC_SUPFMT_PCM) { | ||
788 | if (val & AC_SUPPCM_BITS_8) { | ||
789 | formats |= SNDRV_PCM_FMTBIT_U8; | ||
790 | bps = 8; | ||
791 | } | ||
792 | if (val & AC_SUPPCM_BITS_16) { | ||
793 | formats |= SNDRV_PCM_FMTBIT_S16_LE; | ||
794 | bps = 16; | ||
795 | } | ||
796 | if (wcaps & AC_WCAP_DIGITAL) { | ||
797 | if (val & AC_SUPPCM_BITS_32) | ||
798 | formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; | ||
799 | if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) | ||
800 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | ||
801 | if (val & AC_SUPPCM_BITS_24) | ||
802 | bps = 24; | ||
803 | else if (val & AC_SUPPCM_BITS_20) | ||
804 | bps = 20; | ||
805 | } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| | ||
806 | AC_SUPPCM_BITS_32)) { | ||
807 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | ||
808 | if (val & AC_SUPPCM_BITS_32) | ||
809 | bps = 32; | ||
810 | else if (val & AC_SUPPCM_BITS_24) | ||
811 | bps = 24; | ||
812 | else if (val & AC_SUPPCM_BITS_20) | ||
813 | bps = 20; | ||
814 | } | ||
815 | } | ||
816 | #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */ | ||
817 | if (streams & AC_SUPFMT_FLOAT32) { | ||
818 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; | ||
819 | if (!bps) | ||
820 | bps = 32; | ||
821 | } | ||
822 | #endif | ||
823 | if (streams == AC_SUPFMT_AC3) { | ||
824 | /* should be exclusive */ | ||
825 | /* temporary hack: we have still no proper support | ||
826 | * for the direct AC3 stream... | ||
827 | */ | ||
828 | formats |= SNDRV_PCM_FMTBIT_U8; | ||
829 | bps = 8; | ||
830 | } | ||
831 | if (formats == 0) { | ||
832 | dev_err(&codec->dev, | ||
833 | "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n", | ||
834 | nid, val, | ||
835 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, | ||
836 | streams); | ||
837 | return -EIO; | ||
838 | } | ||
839 | if (formatsp) | ||
840 | *formatsp = formats; | ||
841 | if (bpsp) | ||
842 | *bpsp = bps; | ||
843 | } | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | EXPORT_SYMBOL_GPL(snd_hdac_query_supported_pcm); | ||
848 | |||
849 | /** | ||
850 | * snd_hdac_is_supported_format - Check the validity of the format | ||
851 | * @codec: the codec object | ||
852 | * @nid: NID to check | ||
853 | * @format: the HD-audio format value to check | ||
854 | * | ||
855 | * Check whether the given node supports the format value. | ||
856 | * | ||
857 | * Returns true if supported, false if not. | ||
858 | */ | ||
859 | bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid, | ||
860 | unsigned int format) | ||
861 | { | ||
862 | int i; | ||
863 | unsigned int val = 0, rate, stream; | ||
864 | |||
865 | val = query_pcm_param(codec, nid); | ||
866 | if (!val) | ||
867 | return false; | ||
868 | |||
869 | rate = format & 0xff00; | ||
870 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) | ||
871 | if (rate_bits[i].hda_fmt == rate) { | ||
872 | if (val & (1 << i)) | ||
873 | break; | ||
874 | return false; | ||
875 | } | ||
876 | if (i >= AC_PAR_PCM_RATE_BITS) | ||
877 | return false; | ||
878 | |||
879 | stream = query_stream_param(codec, nid); | ||
880 | if (!stream) | ||
881 | return false; | ||
882 | |||
883 | if (stream & AC_SUPFMT_PCM) { | ||
884 | switch (format & 0xf0) { | ||
885 | case 0x00: | ||
886 | if (!(val & AC_SUPPCM_BITS_8)) | ||
887 | return false; | ||
888 | break; | ||
889 | case 0x10: | ||
890 | if (!(val & AC_SUPPCM_BITS_16)) | ||
891 | return false; | ||
892 | break; | ||
893 | case 0x20: | ||
894 | if (!(val & AC_SUPPCM_BITS_20)) | ||
895 | return false; | ||
896 | break; | ||
897 | case 0x30: | ||
898 | if (!(val & AC_SUPPCM_BITS_24)) | ||
899 | return false; | ||
900 | break; | ||
901 | case 0x40: | ||
902 | if (!(val & AC_SUPPCM_BITS_32)) | ||
903 | return false; | ||
904 | break; | ||
905 | default: | ||
906 | return false; | ||
907 | } | ||
908 | } else { | ||
909 | /* FIXME: check for float32 and AC3? */ | ||
910 | } | ||
911 | |||
912 | return true; | ||
913 | } | ||
914 | EXPORT_SYMBOL_GPL(snd_hdac_is_supported_format); | ||
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c new file mode 100644 index 000000000000..442500e06b7c --- /dev/null +++ b/sound/hda/hdac_i915.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * hdac_i915.c - routines for sync between HD-A core and i915 display driver | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the Free | ||
6 | * Software Foundation; either version 2 of the License, or (at your option) | ||
7 | * any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/component.h> | ||
19 | #include <drm/i915_component.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/hdaudio.h> | ||
22 | #include <sound/hda_i915.h> | ||
23 | |||
24 | static struct i915_audio_component *hdac_acomp; | ||
25 | |||
26 | int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) | ||
27 | { | ||
28 | struct i915_audio_component *acomp = bus->audio_component; | ||
29 | |||
30 | if (!acomp || !acomp->ops) | ||
31 | return -ENODEV; | ||
32 | |||
33 | if (!acomp->ops->codec_wake_override) { | ||
34 | dev_warn(bus->dev, | ||
35 | "Invalid codec wake callback\n"); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | dev_dbg(bus->dev, "%s codec wakeup\n", | ||
40 | enable ? "enable" : "disable"); | ||
41 | |||
42 | acomp->ops->codec_wake_override(acomp->dev, enable); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); | ||
47 | |||
48 | int snd_hdac_display_power(struct hdac_bus *bus, bool enable) | ||
49 | { | ||
50 | struct i915_audio_component *acomp = bus->audio_component; | ||
51 | |||
52 | if (!acomp || !acomp->ops) | ||
53 | return -ENODEV; | ||
54 | |||
55 | dev_dbg(bus->dev, "display power %s\n", | ||
56 | enable ? "enable" : "disable"); | ||
57 | |||
58 | if (enable) { | ||
59 | if (!bus->i915_power_refcount++) | ||
60 | acomp->ops->get_power(acomp->dev); | ||
61 | } else { | ||
62 | WARN_ON(!bus->i915_power_refcount); | ||
63 | if (!--bus->i915_power_refcount) | ||
64 | acomp->ops->put_power(acomp->dev); | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(snd_hdac_display_power); | ||
70 | |||
71 | int snd_hdac_get_display_clk(struct hdac_bus *bus) | ||
72 | { | ||
73 | struct i915_audio_component *acomp = bus->audio_component; | ||
74 | |||
75 | if (!acomp || !acomp->ops) | ||
76 | return -ENODEV; | ||
77 | |||
78 | return acomp->ops->get_cdclk_freq(acomp->dev); | ||
79 | } | ||
80 | EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk); | ||
81 | |||
82 | static int hdac_component_master_bind(struct device *dev) | ||
83 | { | ||
84 | struct i915_audio_component *acomp = hdac_acomp; | ||
85 | int ret; | ||
86 | |||
87 | ret = component_bind_all(dev, acomp); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
91 | if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && | ||
92 | acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { | ||
93 | ret = -EINVAL; | ||
94 | goto out_unbind; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Atm, we don't support dynamic unbinding initiated by the child | ||
99 | * component, so pin its containing module until we unbind. | ||
100 | */ | ||
101 | if (!try_module_get(acomp->ops->owner)) { | ||
102 | ret = -ENODEV; | ||
103 | goto out_unbind; | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | |||
108 | out_unbind: | ||
109 | component_unbind_all(dev, acomp); | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static void hdac_component_master_unbind(struct device *dev) | ||
115 | { | ||
116 | struct i915_audio_component *acomp = hdac_acomp; | ||
117 | |||
118 | module_put(acomp->ops->owner); | ||
119 | component_unbind_all(dev, acomp); | ||
120 | WARN_ON(acomp->ops || acomp->dev); | ||
121 | } | ||
122 | |||
123 | static const struct component_master_ops hdac_component_master_ops = { | ||
124 | .bind = hdac_component_master_bind, | ||
125 | .unbind = hdac_component_master_unbind, | ||
126 | }; | ||
127 | |||
128 | static int hdac_component_master_match(struct device *dev, void *data) | ||
129 | { | ||
130 | /* i915 is the only supported component */ | ||
131 | return !strcmp(dev->driver->name, "i915"); | ||
132 | } | ||
133 | |||
134 | int snd_hdac_i915_init(struct hdac_bus *bus) | ||
135 | { | ||
136 | struct component_match *match = NULL; | ||
137 | struct device *dev = bus->dev; | ||
138 | struct i915_audio_component *acomp; | ||
139 | int ret; | ||
140 | |||
141 | acomp = kzalloc(sizeof(*acomp), GFP_KERNEL); | ||
142 | if (!acomp) | ||
143 | return -ENOMEM; | ||
144 | bus->audio_component = acomp; | ||
145 | hdac_acomp = acomp; | ||
146 | |||
147 | component_match_add(dev, &match, hdac_component_master_match, bus); | ||
148 | ret = component_master_add_with_match(dev, &hdac_component_master_ops, | ||
149 | match); | ||
150 | if (ret < 0) | ||
151 | goto out_err; | ||
152 | |||
153 | /* | ||
154 | * Atm, we don't support deferring the component binding, so make sure | ||
155 | * i915 is loaded and that the binding successfully completes. | ||
156 | */ | ||
157 | request_module("i915"); | ||
158 | |||
159 | if (!acomp->ops) { | ||
160 | ret = -ENODEV; | ||
161 | goto out_master_del; | ||
162 | } | ||
163 | dev_dbg(dev, "bound to i915 component master\n"); | ||
164 | |||
165 | return 0; | ||
166 | out_master_del: | ||
167 | component_master_del(dev, &hdac_component_master_ops); | ||
168 | out_err: | ||
169 | kfree(acomp); | ||
170 | bus->audio_component = NULL; | ||
171 | dev_err(dev, "failed to add i915 component master (%d)\n", ret); | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(snd_hdac_i915_init); | ||
176 | |||
177 | int snd_hdac_i915_exit(struct hdac_bus *bus) | ||
178 | { | ||
179 | struct device *dev = bus->dev; | ||
180 | struct i915_audio_component *acomp = bus->audio_component; | ||
181 | |||
182 | if (!acomp) | ||
183 | return 0; | ||
184 | |||
185 | WARN_ON(bus->i915_power_refcount); | ||
186 | if (bus->i915_power_refcount > 0 && acomp->ops) | ||
187 | acomp->ops->put_power(acomp->dev); | ||
188 | |||
189 | component_master_del(dev, &hdac_component_master_ops); | ||
190 | |||
191 | kfree(acomp); | ||
192 | bus->audio_component = NULL; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | EXPORT_SYMBOL_GPL(snd_hdac_i915_exit); | ||
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c index 7371e0c3926f..1eabcdf69457 100644 --- a/sound/hda/hdac_regmap.c +++ b/sound/hda/hdac_regmap.c | |||
@@ -246,6 +246,9 @@ static int hda_reg_read(void *context, unsigned int reg, unsigned int *val) | |||
246 | return hda_reg_read_stereo_amp(codec, reg, val); | 246 | return hda_reg_read_stereo_amp(codec, reg, val); |
247 | if (verb == AC_VERB_GET_PROC_COEF) | 247 | if (verb == AC_VERB_GET_PROC_COEF) |
248 | return hda_reg_read_coef(codec, reg, val); | 248 | return hda_reg_read_coef(codec, reg, val); |
249 | if ((verb & 0x700) == AC_VERB_SET_AMP_GAIN_MUTE) | ||
250 | reg &= ~AC_AMP_FAKE_MUTE; | ||
251 | |||
249 | err = snd_hdac_exec_verb(codec, reg, 0, val); | 252 | err = snd_hdac_exec_verb(codec, reg, 0, val); |
250 | if (err < 0) | 253 | if (err < 0) |
251 | return err; | 254 | return err; |
@@ -265,6 +268,9 @@ static int hda_reg_write(void *context, unsigned int reg, unsigned int val) | |||
265 | unsigned int verb; | 268 | unsigned int verb; |
266 | int i, bytes, err; | 269 | int i, bytes, err; |
267 | 270 | ||
271 | if (codec->caps_overwriting) | ||
272 | return 0; | ||
273 | |||
268 | reg &= ~0x00080000U; /* drop GET bit */ | 274 | reg &= ~0x00080000U; /* drop GET bit */ |
269 | reg |= (codec->addr << 28); | 275 | reg |= (codec->addr << 28); |
270 | verb = get_verb(reg); | 276 | verb = get_verb(reg); |
@@ -280,6 +286,8 @@ static int hda_reg_write(void *context, unsigned int reg, unsigned int val) | |||
280 | 286 | ||
281 | switch (verb & 0xf00) { | 287 | switch (verb & 0xf00) { |
282 | case AC_VERB_SET_AMP_GAIN_MUTE: | 288 | case AC_VERB_SET_AMP_GAIN_MUTE: |
289 | if ((reg & AC_AMP_FAKE_MUTE) && (val & AC_AMP_MUTE)) | ||
290 | val = 0; | ||
283 | verb = AC_VERB_SET_AMP_GAIN_MUTE; | 291 | verb = AC_VERB_SET_AMP_GAIN_MUTE; |
284 | if (reg & AC_AMP_GET_LEFT) | 292 | if (reg & AC_AMP_GET_LEFT) |
285 | verb |= AC_AMP_SET_LEFT >> 8; | 293 | verb |= AC_AMP_SET_LEFT >> 8; |
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c new file mode 100644 index 000000000000..4c15d0accc9e --- /dev/null +++ b/sound/hda/hdac_stream.c | |||
@@ -0,0 +1,697 @@ | |||
1 | /* | ||
2 | * HD-audio stream operations | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/export.h> | ||
8 | #include <linux/clocksource.h> | ||
9 | #include <sound/core.h> | ||
10 | #include <sound/pcm.h> | ||
11 | #include <sound/hdaudio.h> | ||
12 | #include <sound/hda_register.h> | ||
13 | #include "trace.h" | ||
14 | |||
15 | /** | ||
16 | * snd_hdac_stream_init - initialize each stream (aka device) | ||
17 | * @bus: HD-audio core bus | ||
18 | * @azx_dev: HD-audio core stream object to initialize | ||
19 | * @idx: stream index number | ||
20 | * @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE) | ||
21 | * @tag: the tag id to assign | ||
22 | * | ||
23 | * Assign the starting bdl address to each stream (device) and initialize. | ||
24 | */ | ||
25 | void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, | ||
26 | int idx, int direction, int tag) | ||
27 | { | ||
28 | azx_dev->bus = bus; | ||
29 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | ||
30 | azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80); | ||
31 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | ||
32 | azx_dev->sd_int_sta_mask = 1 << idx; | ||
33 | azx_dev->index = idx; | ||
34 | azx_dev->direction = direction; | ||
35 | azx_dev->stream_tag = tag; | ||
36 | snd_hdac_dsp_lock_init(azx_dev); | ||
37 | list_add_tail(&azx_dev->list, &bus->stream_list); | ||
38 | } | ||
39 | EXPORT_SYMBOL_GPL(snd_hdac_stream_init); | ||
40 | |||
41 | /** | ||
42 | * snd_hdac_stream_start - start a stream | ||
43 | * @azx_dev: HD-audio core stream to start | ||
44 | * @fresh_start: false = wallclock timestamp relative to period wallclock | ||
45 | * | ||
46 | * Start a stream, set start_wallclk and set the running flag. | ||
47 | */ | ||
48 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) | ||
49 | { | ||
50 | struct hdac_bus *bus = azx_dev->bus; | ||
51 | |||
52 | trace_snd_hdac_stream_start(bus, azx_dev); | ||
53 | |||
54 | azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK); | ||
55 | if (!fresh_start) | ||
56 | azx_dev->start_wallclk -= azx_dev->period_wallclk; | ||
57 | |||
58 | /* enable SIE */ | ||
59 | snd_hdac_chip_updatel(bus, INTCTL, 0, 1 << azx_dev->index); | ||
60 | /* set DMA start and interrupt mask */ | ||
61 | snd_hdac_stream_updateb(azx_dev, SD_CTL, | ||
62 | 0, SD_CTL_DMA_START | SD_INT_MASK); | ||
63 | azx_dev->running = true; | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(snd_hdac_stream_start); | ||
66 | |||
67 | /** | ||
68 | * snd_hdac_stream_clear - stop a stream DMA | ||
69 | * @azx_dev: HD-audio core stream to stop | ||
70 | */ | ||
71 | void snd_hdac_stream_clear(struct hdac_stream *azx_dev) | ||
72 | { | ||
73 | snd_hdac_stream_updateb(azx_dev, SD_CTL, | ||
74 | SD_CTL_DMA_START | SD_INT_MASK, 0); | ||
75 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | ||
76 | azx_dev->running = false; | ||
77 | } | ||
78 | EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); | ||
79 | |||
80 | /** | ||
81 | * snd_hdac_stream_stop - stop a stream | ||
82 | * @azx_dev: HD-audio core stream to stop | ||
83 | * | ||
84 | * Stop a stream DMA and disable stream interrupt | ||
85 | */ | ||
86 | void snd_hdac_stream_stop(struct hdac_stream *azx_dev) | ||
87 | { | ||
88 | trace_snd_hdac_stream_stop(azx_dev->bus, azx_dev); | ||
89 | |||
90 | snd_hdac_stream_clear(azx_dev); | ||
91 | /* disable SIE */ | ||
92 | snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0); | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(snd_hdac_stream_stop); | ||
95 | |||
96 | /** | ||
97 | * snd_hdac_stream_reset - reset a stream | ||
98 | * @azx_dev: HD-audio core stream to reset | ||
99 | */ | ||
100 | void snd_hdac_stream_reset(struct hdac_stream *azx_dev) | ||
101 | { | ||
102 | unsigned char val; | ||
103 | int timeout; | ||
104 | |||
105 | snd_hdac_stream_clear(azx_dev); | ||
106 | |||
107 | snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); | ||
108 | udelay(3); | ||
109 | timeout = 300; | ||
110 | do { | ||
111 | val = snd_hdac_stream_readb(azx_dev, SD_CTL) & | ||
112 | SD_CTL_STREAM_RESET; | ||
113 | if (val) | ||
114 | break; | ||
115 | } while (--timeout); | ||
116 | val &= ~SD_CTL_STREAM_RESET; | ||
117 | snd_hdac_stream_writeb(azx_dev, SD_CTL, val); | ||
118 | udelay(3); | ||
119 | |||
120 | timeout = 300; | ||
121 | /* waiting for hardware to report that the stream is out of reset */ | ||
122 | do { | ||
123 | val = snd_hdac_stream_readb(azx_dev, SD_CTL) & | ||
124 | SD_CTL_STREAM_RESET; | ||
125 | if (!val) | ||
126 | break; | ||
127 | } while (--timeout); | ||
128 | |||
129 | /* reset first position - may not be synced with hw at this time */ | ||
130 | if (azx_dev->posbuf) | ||
131 | *azx_dev->posbuf = 0; | ||
132 | } | ||
133 | EXPORT_SYMBOL_GPL(snd_hdac_stream_reset); | ||
134 | |||
135 | /** | ||
136 | * snd_hdac_stream_setup - set up the SD for streaming | ||
137 | * @azx_dev: HD-audio core stream to set up | ||
138 | */ | ||
139 | int snd_hdac_stream_setup(struct hdac_stream *azx_dev) | ||
140 | { | ||
141 | struct hdac_bus *bus = azx_dev->bus; | ||
142 | struct snd_pcm_runtime *runtime; | ||
143 | unsigned int val; | ||
144 | |||
145 | if (azx_dev->substream) | ||
146 | runtime = azx_dev->substream->runtime; | ||
147 | else | ||
148 | runtime = NULL; | ||
149 | /* make sure the run bit is zero for SD */ | ||
150 | snd_hdac_stream_clear(azx_dev); | ||
151 | /* program the stream_tag */ | ||
152 | val = snd_hdac_stream_readl(azx_dev, SD_CTL); | ||
153 | val = (val & ~SD_CTL_STREAM_TAG_MASK) | | ||
154 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); | ||
155 | if (!bus->snoop) | ||
156 | val |= SD_CTL_TRAFFIC_PRIO; | ||
157 | snd_hdac_stream_writel(azx_dev, SD_CTL, val); | ||
158 | |||
159 | /* program the length of samples in cyclic buffer */ | ||
160 | snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize); | ||
161 | |||
162 | /* program the stream format */ | ||
163 | /* this value needs to be the same as the one programmed */ | ||
164 | snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val); | ||
165 | |||
166 | /* program the stream LVI (last valid index) of the BDL */ | ||
167 | snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1); | ||
168 | |||
169 | /* program the BDL address */ | ||
170 | /* lower BDL address */ | ||
171 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); | ||
172 | /* upper BDL address */ | ||
173 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, | ||
174 | upper_32_bits(azx_dev->bdl.addr)); | ||
175 | |||
176 | /* enable the position buffer */ | ||
177 | if (bus->use_posbuf && bus->posbuf.addr) { | ||
178 | if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE)) | ||
179 | snd_hdac_chip_writel(bus, DPLBASE, | ||
180 | (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE); | ||
181 | } | ||
182 | |||
183 | /* set the interrupt enable bits in the descriptor control register */ | ||
184 | snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); | ||
185 | |||
186 | if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) | ||
187 | azx_dev->fifo_size = | ||
188 | snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; | ||
189 | else | ||
190 | azx_dev->fifo_size = 0; | ||
191 | |||
192 | /* when LPIB delay correction gives a small negative value, | ||
193 | * we ignore it; currently set the threshold statically to | ||
194 | * 64 frames | ||
195 | */ | ||
196 | if (runtime && runtime->period_size > 64) | ||
197 | azx_dev->delay_negative_threshold = | ||
198 | -frames_to_bytes(runtime, 64); | ||
199 | else | ||
200 | azx_dev->delay_negative_threshold = 0; | ||
201 | |||
202 | /* wallclk has 24Mhz clock source */ | ||
203 | if (runtime) | ||
204 | azx_dev->period_wallclk = (((runtime->period_size * 24000) / | ||
205 | runtime->rate) * 1000); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(snd_hdac_stream_setup); | ||
210 | |||
211 | /** | ||
212 | * snd_hdac_stream_cleanup - cleanup a stream | ||
213 | * @azx_dev: HD-audio core stream to clean up | ||
214 | */ | ||
215 | void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev) | ||
216 | { | ||
217 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
218 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
219 | snd_hdac_stream_writel(azx_dev, SD_CTL, 0); | ||
220 | azx_dev->bufsize = 0; | ||
221 | azx_dev->period_bytes = 0; | ||
222 | azx_dev->format_val = 0; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(snd_hdac_stream_cleanup); | ||
225 | |||
226 | /** | ||
227 | * snd_hdac_stream_assign - assign a stream for the PCM | ||
228 | * @bus: HD-audio core bus | ||
229 | * @substream: PCM substream to assign | ||
230 | * | ||
231 | * Look for an unused stream for the given PCM substream, assign it | ||
232 | * and return the stream object. If no stream is free, returns NULL. | ||
233 | * The function tries to keep using the same stream object when it's used | ||
234 | * beforehand. Also, when bus->reverse_assign flag is set, the last free | ||
235 | * or matching entry is returned. This is needed for some strange codecs. | ||
236 | */ | ||
237 | struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, | ||
238 | struct snd_pcm_substream *substream) | ||
239 | { | ||
240 | struct hdac_stream *azx_dev; | ||
241 | struct hdac_stream *res = NULL; | ||
242 | |||
243 | /* make a non-zero unique key for the substream */ | ||
244 | int key = (substream->pcm->device << 16) | (substream->number << 2) | | ||
245 | (substream->stream + 1); | ||
246 | |||
247 | list_for_each_entry(azx_dev, &bus->stream_list, list) { | ||
248 | if (azx_dev->direction != substream->stream) | ||
249 | continue; | ||
250 | if (azx_dev->opened) | ||
251 | continue; | ||
252 | if (azx_dev->assigned_key == key) { | ||
253 | res = azx_dev; | ||
254 | break; | ||
255 | } | ||
256 | if (!res || bus->reverse_assign) | ||
257 | res = azx_dev; | ||
258 | } | ||
259 | if (res) { | ||
260 | spin_lock_irq(&bus->reg_lock); | ||
261 | res->opened = 1; | ||
262 | res->running = 0; | ||
263 | res->assigned_key = key; | ||
264 | res->substream = substream; | ||
265 | spin_unlock_irq(&bus->reg_lock); | ||
266 | } | ||
267 | return res; | ||
268 | } | ||
269 | EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); | ||
270 | |||
271 | /** | ||
272 | * snd_hdac_stream_release - release the assigned stream | ||
273 | * @azx_dev: HD-audio core stream to release | ||
274 | * | ||
275 | * Release the stream that has been assigned by snd_hdac_stream_assign(). | ||
276 | */ | ||
277 | void snd_hdac_stream_release(struct hdac_stream *azx_dev) | ||
278 | { | ||
279 | struct hdac_bus *bus = azx_dev->bus; | ||
280 | |||
281 | spin_lock_irq(&bus->reg_lock); | ||
282 | azx_dev->opened = 0; | ||
283 | azx_dev->running = 0; | ||
284 | azx_dev->substream = NULL; | ||
285 | spin_unlock_irq(&bus->reg_lock); | ||
286 | } | ||
287 | EXPORT_SYMBOL_GPL(snd_hdac_stream_release); | ||
288 | |||
289 | /* | ||
290 | * set up a BDL entry | ||
291 | */ | ||
292 | static int setup_bdle(struct hdac_bus *bus, | ||
293 | struct snd_dma_buffer *dmab, | ||
294 | struct hdac_stream *azx_dev, __le32 **bdlp, | ||
295 | int ofs, int size, int with_ioc) | ||
296 | { | ||
297 | __le32 *bdl = *bdlp; | ||
298 | |||
299 | while (size > 0) { | ||
300 | dma_addr_t addr; | ||
301 | int chunk; | ||
302 | |||
303 | if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) | ||
304 | return -EINVAL; | ||
305 | |||
306 | addr = snd_sgbuf_get_addr(dmab, ofs); | ||
307 | /* program the address field of the BDL entry */ | ||
308 | bdl[0] = cpu_to_le32((u32)addr); | ||
309 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | ||
310 | /* program the size field of the BDL entry */ | ||
311 | chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); | ||
312 | /* one BDLE cannot cross 4K boundary on CTHDA chips */ | ||
313 | if (bus->align_bdle_4k) { | ||
314 | u32 remain = 0x1000 - (ofs & 0xfff); | ||
315 | |||
316 | if (chunk > remain) | ||
317 | chunk = remain; | ||
318 | } | ||
319 | bdl[2] = cpu_to_le32(chunk); | ||
320 | /* program the IOC to enable interrupt | ||
321 | * only when the whole fragment is processed | ||
322 | */ | ||
323 | size -= chunk; | ||
324 | bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); | ||
325 | bdl += 4; | ||
326 | azx_dev->frags++; | ||
327 | ofs += chunk; | ||
328 | } | ||
329 | *bdlp = bdl; | ||
330 | return ofs; | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * snd_hdac_stream_setup_periods - set up BDL entries | ||
335 | * @azx_dev: HD-audio core stream to set up | ||
336 | * | ||
337 | * Set up the buffer descriptor table of the given stream based on the | ||
338 | * period and buffer sizes of the assigned PCM substream. | ||
339 | */ | ||
340 | int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev) | ||
341 | { | ||
342 | struct hdac_bus *bus = azx_dev->bus; | ||
343 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
344 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
345 | __le32 *bdl; | ||
346 | int i, ofs, periods, period_bytes; | ||
347 | int pos_adj, pos_align; | ||
348 | |||
349 | /* reset BDL address */ | ||
350 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
351 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
352 | |||
353 | period_bytes = azx_dev->period_bytes; | ||
354 | periods = azx_dev->bufsize / period_bytes; | ||
355 | |||
356 | /* program the initial BDL entries */ | ||
357 | bdl = (__le32 *)azx_dev->bdl.area; | ||
358 | ofs = 0; | ||
359 | azx_dev->frags = 0; | ||
360 | |||
361 | pos_adj = bus->bdl_pos_adj; | ||
362 | if (!azx_dev->no_period_wakeup && pos_adj > 0) { | ||
363 | pos_align = pos_adj; | ||
364 | pos_adj = (pos_adj * runtime->rate + 47999) / 48000; | ||
365 | if (!pos_adj) | ||
366 | pos_adj = pos_align; | ||
367 | else | ||
368 | pos_adj = ((pos_adj + pos_align - 1) / pos_align) * | ||
369 | pos_align; | ||
370 | pos_adj = frames_to_bytes(runtime, pos_adj); | ||
371 | if (pos_adj >= period_bytes) { | ||
372 | dev_warn(bus->dev, "Too big adjustment %d\n", | ||
373 | pos_adj); | ||
374 | pos_adj = 0; | ||
375 | } else { | ||
376 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
377 | azx_dev, | ||
378 | &bdl, ofs, pos_adj, true); | ||
379 | if (ofs < 0) | ||
380 | goto error; | ||
381 | } | ||
382 | } else | ||
383 | pos_adj = 0; | ||
384 | |||
385 | for (i = 0; i < periods; i++) { | ||
386 | if (i == periods - 1 && pos_adj) | ||
387 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
388 | azx_dev, &bdl, ofs, | ||
389 | period_bytes - pos_adj, 0); | ||
390 | else | ||
391 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
392 | azx_dev, &bdl, ofs, | ||
393 | period_bytes, | ||
394 | !azx_dev->no_period_wakeup); | ||
395 | if (ofs < 0) | ||
396 | goto error; | ||
397 | } | ||
398 | return 0; | ||
399 | |||
400 | error: | ||
401 | dev_err(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n", | ||
402 | azx_dev->bufsize, period_bytes); | ||
403 | return -EINVAL; | ||
404 | } | ||
405 | EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods); | ||
406 | |||
407 | /* snd_hdac_stream_set_params - set stream parameters | ||
408 | * @azx_dev: HD-audio core stream for which parameters are to be set | ||
409 | * @format_val: format value parameter | ||
410 | * | ||
411 | * Setup the HD-audio core stream parameters from substream of the stream | ||
412 | * and passed format value | ||
413 | */ | ||
414 | int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, | ||
415 | unsigned int format_val) | ||
416 | { | ||
417 | |||
418 | unsigned int bufsize, period_bytes; | ||
419 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
420 | struct snd_pcm_runtime *runtime; | ||
421 | int err; | ||
422 | |||
423 | if (!substream) | ||
424 | return -EINVAL; | ||
425 | runtime = substream->runtime; | ||
426 | bufsize = snd_pcm_lib_buffer_bytes(substream); | ||
427 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
428 | |||
429 | if (bufsize != azx_dev->bufsize || | ||
430 | period_bytes != azx_dev->period_bytes || | ||
431 | format_val != azx_dev->format_val || | ||
432 | runtime->no_period_wakeup != azx_dev->no_period_wakeup) { | ||
433 | azx_dev->bufsize = bufsize; | ||
434 | azx_dev->period_bytes = period_bytes; | ||
435 | azx_dev->format_val = format_val; | ||
436 | azx_dev->no_period_wakeup = runtime->no_period_wakeup; | ||
437 | err = snd_hdac_stream_setup_periods(azx_dev); | ||
438 | if (err < 0) | ||
439 | return err; | ||
440 | } | ||
441 | return 0; | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(snd_hdac_stream_set_params); | ||
444 | |||
445 | static cycle_t azx_cc_read(const struct cyclecounter *cc) | ||
446 | { | ||
447 | struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc); | ||
448 | |||
449 | return snd_hdac_chip_readl(azx_dev->bus, WALLCLK); | ||
450 | } | ||
451 | |||
452 | static void azx_timecounter_init(struct hdac_stream *azx_dev, | ||
453 | bool force, cycle_t last) | ||
454 | { | ||
455 | struct timecounter *tc = &azx_dev->tc; | ||
456 | struct cyclecounter *cc = &azx_dev->cc; | ||
457 | u64 nsec; | ||
458 | |||
459 | cc->read = azx_cc_read; | ||
460 | cc->mask = CLOCKSOURCE_MASK(32); | ||
461 | |||
462 | /* | ||
463 | * Converting from 24 MHz to ns means applying a 125/3 factor. | ||
464 | * To avoid any saturation issues in intermediate operations, | ||
465 | * the 125 factor is applied first. The division is applied | ||
466 | * last after reading the timecounter value. | ||
467 | * Applying the 1/3 factor as part of the multiplication | ||
468 | * requires at least 20 bits for a decent precision, however | ||
469 | * overflows occur after about 4 hours or less, not a option. | ||
470 | */ | ||
471 | |||
472 | cc->mult = 125; /* saturation after 195 years */ | ||
473 | cc->shift = 0; | ||
474 | |||
475 | nsec = 0; /* audio time is elapsed time since trigger */ | ||
476 | timecounter_init(tc, cc, nsec); | ||
477 | if (force) { | ||
478 | /* | ||
479 | * force timecounter to use predefined value, | ||
480 | * used for synchronized starts | ||
481 | */ | ||
482 | tc->cycle_last = last; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * snd_hdac_stream_timecounter_init - initialize time counter | ||
488 | * @azx_dev: HD-audio core stream (master stream) | ||
489 | * @streams: bit flags of streams to set up | ||
490 | * | ||
491 | * Initializes the time counter of streams marked by the bit flags (each | ||
492 | * bit corresponds to the stream index). | ||
493 | * The trigger timestamp of PCM substream assigned to the given stream is | ||
494 | * updated accordingly, too. | ||
495 | */ | ||
496 | void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, | ||
497 | unsigned int streams) | ||
498 | { | ||
499 | struct hdac_bus *bus = azx_dev->bus; | ||
500 | struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; | ||
501 | struct hdac_stream *s; | ||
502 | bool inited = false; | ||
503 | cycle_t cycle_last = 0; | ||
504 | int i = 0; | ||
505 | |||
506 | list_for_each_entry(s, &bus->stream_list, list) { | ||
507 | if (streams & (1 << i)) { | ||
508 | azx_timecounter_init(s, inited, cycle_last); | ||
509 | if (!inited) { | ||
510 | inited = true; | ||
511 | cycle_last = s->tc.cycle_last; | ||
512 | } | ||
513 | } | ||
514 | i++; | ||
515 | } | ||
516 | |||
517 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); | ||
518 | runtime->trigger_tstamp_latched = true; | ||
519 | } | ||
520 | EXPORT_SYMBOL_GPL(snd_hdac_stream_timecounter_init); | ||
521 | |||
522 | /** | ||
523 | * snd_hdac_stream_sync_trigger - turn on/off stream sync register | ||
524 | * @azx_dev: HD-audio core stream (master stream) | ||
525 | * @streams: bit flags of streams to sync | ||
526 | */ | ||
527 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, | ||
528 | unsigned int streams, unsigned int reg) | ||
529 | { | ||
530 | struct hdac_bus *bus = azx_dev->bus; | ||
531 | unsigned int val; | ||
532 | |||
533 | if (!reg) | ||
534 | reg = AZX_REG_SSYNC; | ||
535 | val = _snd_hdac_chip_read(l, bus, reg); | ||
536 | if (set) | ||
537 | val |= streams; | ||
538 | else | ||
539 | val &= ~streams; | ||
540 | _snd_hdac_chip_write(l, bus, reg, val); | ||
541 | } | ||
542 | EXPORT_SYMBOL_GPL(snd_hdac_stream_sync_trigger); | ||
543 | |||
544 | /** | ||
545 | * snd_hdac_stream_sync - sync with start/strop trigger operation | ||
546 | * @azx_dev: HD-audio core stream (master stream) | ||
547 | * @start: true = start, false = stop | ||
548 | * @streams: bit flags of streams to sync | ||
549 | * | ||
550 | * For @start = true, wait until all FIFOs get ready. | ||
551 | * For @start = false, wait until all RUN bits are cleared. | ||
552 | */ | ||
553 | void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, | ||
554 | unsigned int streams) | ||
555 | { | ||
556 | struct hdac_bus *bus = azx_dev->bus; | ||
557 | int i, nwait, timeout; | ||
558 | struct hdac_stream *s; | ||
559 | |||
560 | for (timeout = 5000; timeout; timeout--) { | ||
561 | nwait = 0; | ||
562 | i = 0; | ||
563 | list_for_each_entry(s, &bus->stream_list, list) { | ||
564 | if (streams & (1 << i)) { | ||
565 | if (start) { | ||
566 | /* check FIFO gets ready */ | ||
567 | if (!(snd_hdac_stream_readb(s, SD_STS) & | ||
568 | SD_STS_FIFO_READY)) | ||
569 | nwait++; | ||
570 | } else { | ||
571 | /* check RUN bit is cleared */ | ||
572 | if (snd_hdac_stream_readb(s, SD_CTL) & | ||
573 | SD_CTL_DMA_START) | ||
574 | nwait++; | ||
575 | } | ||
576 | } | ||
577 | i++; | ||
578 | } | ||
579 | if (!nwait) | ||
580 | break; | ||
581 | cpu_relax(); | ||
582 | } | ||
583 | } | ||
584 | EXPORT_SYMBOL_GPL(snd_hdac_stream_sync); | ||
585 | |||
586 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
587 | /** | ||
588 | * snd_hdac_dsp_prepare - prepare for DSP loading | ||
589 | * @azx_dev: HD-audio core stream used for DSP loading | ||
590 | * @format: HD-audio stream format | ||
591 | * @byte_size: data chunk byte size | ||
592 | * @bufp: allocated buffer | ||
593 | * | ||
594 | * Allocate the buffer for the given size and set up the given stream for | ||
595 | * DSP loading. Returns the stream tag (>= 0), or a negative error code. | ||
596 | */ | ||
597 | int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, | ||
598 | unsigned int byte_size, struct snd_dma_buffer *bufp) | ||
599 | { | ||
600 | struct hdac_bus *bus = azx_dev->bus; | ||
601 | u32 *bdl; | ||
602 | int err; | ||
603 | |||
604 | snd_hdac_dsp_lock(azx_dev); | ||
605 | spin_lock_irq(&bus->reg_lock); | ||
606 | if (azx_dev->running || azx_dev->locked) { | ||
607 | spin_unlock_irq(&bus->reg_lock); | ||
608 | err = -EBUSY; | ||
609 | goto unlock; | ||
610 | } | ||
611 | azx_dev->locked = true; | ||
612 | spin_unlock_irq(&bus->reg_lock); | ||
613 | |||
614 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, | ||
615 | byte_size, bufp); | ||
616 | if (err < 0) | ||
617 | goto err_alloc; | ||
618 | |||
619 | azx_dev->substream = NULL; | ||
620 | azx_dev->bufsize = byte_size; | ||
621 | azx_dev->period_bytes = byte_size; | ||
622 | azx_dev->format_val = format; | ||
623 | |||
624 | snd_hdac_stream_reset(azx_dev); | ||
625 | |||
626 | /* reset BDL address */ | ||
627 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
628 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
629 | |||
630 | azx_dev->frags = 0; | ||
631 | bdl = (u32 *)azx_dev->bdl.area; | ||
632 | err = setup_bdle(bus, bufp, azx_dev, &bdl, 0, byte_size, 0); | ||
633 | if (err < 0) | ||
634 | goto error; | ||
635 | |||
636 | snd_hdac_stream_setup(azx_dev); | ||
637 | snd_hdac_dsp_unlock(azx_dev); | ||
638 | return azx_dev->stream_tag; | ||
639 | |||
640 | error: | ||
641 | bus->io_ops->dma_free_pages(bus, bufp); | ||
642 | err_alloc: | ||
643 | spin_lock_irq(&bus->reg_lock); | ||
644 | azx_dev->locked = false; | ||
645 | spin_unlock_irq(&bus->reg_lock); | ||
646 | unlock: | ||
647 | snd_hdac_dsp_unlock(azx_dev); | ||
648 | return err; | ||
649 | } | ||
650 | EXPORT_SYMBOL_GPL(snd_hdac_dsp_prepare); | ||
651 | |||
652 | /** | ||
653 | * snd_hdac_dsp_trigger - start / stop DSP loading | ||
654 | * @azx_dev: HD-audio core stream used for DSP loading | ||
655 | * @start: trigger start or stop | ||
656 | */ | ||
657 | void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start) | ||
658 | { | ||
659 | if (start) | ||
660 | snd_hdac_stream_start(azx_dev, true); | ||
661 | else | ||
662 | snd_hdac_stream_stop(azx_dev); | ||
663 | } | ||
664 | EXPORT_SYMBOL_GPL(snd_hdac_dsp_trigger); | ||
665 | |||
666 | /** | ||
667 | * snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal | ||
668 | * @azx_dev: HD-audio core stream used for DSP loading | ||
669 | * @dmab: buffer used by DSP loading | ||
670 | */ | ||
671 | void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, | ||
672 | struct snd_dma_buffer *dmab) | ||
673 | { | ||
674 | struct hdac_bus *bus = azx_dev->bus; | ||
675 | |||
676 | if (!dmab->area || !azx_dev->locked) | ||
677 | return; | ||
678 | |||
679 | snd_hdac_dsp_lock(azx_dev); | ||
680 | /* reset BDL address */ | ||
681 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
682 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
683 | snd_hdac_stream_writel(azx_dev, SD_CTL, 0); | ||
684 | azx_dev->bufsize = 0; | ||
685 | azx_dev->period_bytes = 0; | ||
686 | azx_dev->format_val = 0; | ||
687 | |||
688 | bus->io_ops->dma_free_pages(bus, dmab); | ||
689 | dmab->area = NULL; | ||
690 | |||
691 | spin_lock_irq(&bus->reg_lock); | ||
692 | azx_dev->locked = false; | ||
693 | spin_unlock_irq(&bus->reg_lock); | ||
694 | snd_hdac_dsp_unlock(azx_dev); | ||
695 | } | ||
696 | EXPORT_SYMBOL_GPL(snd_hdac_dsp_cleanup); | ||
697 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | ||
diff --git a/sound/hda/trace.h b/sound/hda/trace.h index 33a7eb5573d4..e27e2c0b7b17 100644 --- a/sound/hda/trace.h +++ b/sound/hda/trace.h | |||
@@ -50,6 +50,33 @@ TRACE_EVENT(hda_unsol_event, | |||
50 | ), | 50 | ), |
51 | TP_printk("%s", __get_str(msg)) | 51 | TP_printk("%s", __get_str(msg)) |
52 | ); | 52 | ); |
53 | |||
54 | DECLARE_EVENT_CLASS(hdac_stream, | ||
55 | TP_PROTO(struct hdac_bus *bus, struct hdac_stream *azx_dev), | ||
56 | |||
57 | TP_ARGS(bus, azx_dev), | ||
58 | |||
59 | TP_STRUCT__entry( | ||
60 | __field(unsigned char, stream_tag) | ||
61 | ), | ||
62 | |||
63 | TP_fast_assign( | ||
64 | __entry->stream_tag = (azx_dev)->stream_tag; | ||
65 | ), | ||
66 | |||
67 | TP_printk("stream_tag: %d", __entry->stream_tag) | ||
68 | ); | ||
69 | |||
70 | DEFINE_EVENT(hdac_stream, snd_hdac_stream_start, | ||
71 | TP_PROTO(struct hdac_bus *bus, struct hdac_stream *azx_dev), | ||
72 | TP_ARGS(bus, azx_dev) | ||
73 | ); | ||
74 | |||
75 | DEFINE_EVENT(hdac_stream, snd_hdac_stream_stop, | ||
76 | TP_PROTO(struct hdac_bus *bus, struct hdac_stream *azx_dev), | ||
77 | TP_ARGS(bus, azx_dev) | ||
78 | ); | ||
79 | |||
53 | #endif /* __HDAC_TRACE_H */ | 80 | #endif /* __HDAC_TRACE_H */ |
54 | 81 | ||
55 | /* This part must be outside protection */ | 82 | /* This part must be outside protection */ |
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index c65731088aa2..bf377dc192aa 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -859,7 +859,6 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | |||
859 | return 0; | 859 | return 0; |
860 | } | 860 | } |
861 | 861 | ||
862 | #ifdef CONFIG_PROC_FS | ||
863 | static void proc_regs_read(struct snd_info_entry *entry, | 862 | static void proc_regs_read(struct snd_info_entry *entry, |
864 | struct snd_info_buffer *buffer) | 863 | struct snd_info_buffer *buffer) |
865 | { | 864 | { |
@@ -884,9 +883,6 @@ static int proc_init(struct snd_akm4xxx *ak) | |||
884 | snd_info_set_text_ops(entry, ak, proc_regs_read); | 883 | snd_info_set_text_ops(entry, ak, proc_regs_read); |
885 | return 0; | 884 | return 0; |
886 | } | 885 | } |
887 | #else /* !CONFIG_PROC_FS */ | ||
888 | static int proc_init(struct snd_akm4xxx *ak) { return 0; } | ||
889 | #endif | ||
890 | 886 | ||
891 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | 887 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) |
892 | { | 888 | { |
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index 0dd43414016e..3b5d9a7a63eb 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c | |||
@@ -109,7 +109,7 @@ static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
109 | unsigned long flags; | 109 | unsigned long flags; |
110 | int addr = kcontrol->private_value & 0xff; | 110 | int addr = kcontrol->private_value & 0xff; |
111 | int change; | 111 | int change; |
112 | unsigned char val1, val2, oval1, oval2, tmp; | 112 | unsigned char val1, val2, oval1, oval2; |
113 | 113 | ||
114 | val1 = ucontrol->value.integer.value[0] & 127; | 114 | val1 = ucontrol->value.integer.value[0] & 127; |
115 | val2 = ucontrol->value.integer.value[1] & 127; | 115 | val2 = ucontrol->value.integer.value[1] & 127; |
@@ -120,11 +120,8 @@ static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
120 | gus->gf1.ics_regs[addr][0] = val1; | 120 | gus->gf1.ics_regs[addr][0] = val1; |
121 | gus->gf1.ics_regs[addr][1] = val2; | 121 | gus->gf1.ics_regs[addr][1] = val2; |
122 | if (gus->ics_flag && gus->ics_flipped && | 122 | if (gus->ics_flag && gus->ics_flipped && |
123 | (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV)) { | 123 | (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV)) |
124 | tmp = val1; | 124 | swap(val1, val2); |
125 | val1 = val2; | ||
126 | val2 = tmp; | ||
127 | } | ||
128 | addr <<= 3; | 125 | addr <<= 3; |
129 | outb(addr | 0, GUSP(gus, MIXCNTRLPORT)); | 126 | outb(addr | 0, GUSP(gus, MIXCNTRLPORT)); |
130 | outb(1, GUSP(gus, MIXDATAPORT)); | 127 | outb(1, GUSP(gus, MIXDATAPORT)); |
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig index d2f615ab177a..2153d31fb663 100644 --- a/sound/mips/Kconfig +++ b/sound/mips/Kconfig | |||
@@ -12,12 +12,14 @@ if SND_MIPS | |||
12 | config SND_SGI_O2 | 12 | config SND_SGI_O2 |
13 | tristate "SGI O2 Audio" | 13 | tristate "SGI O2 Audio" |
14 | depends on SGI_IP32 | 14 | depends on SGI_IP32 |
15 | select SND_PCM | ||
15 | help | 16 | help |
16 | Sound support for the SGI O2 Workstation. | 17 | Sound support for the SGI O2 Workstation. |
17 | 18 | ||
18 | config SND_SGI_HAL2 | 19 | config SND_SGI_HAL2 |
19 | tristate "SGI HAL2 Audio" | 20 | tristate "SGI HAL2 Audio" |
20 | depends on SGI_HAS_HAL2 | 21 | depends on SGI_HAS_HAL2 |
22 | select SND_PCM | ||
21 | help | 23 | help |
22 | Sound support for the SGI Indy and Indigo2 Workstation. | 24 | Sound support for the SGI Indy and Indigo2 Workstation. |
23 | 25 | ||
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index ec1ee07df59d..10c8de1f8d29 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -2860,6 +2860,7 @@ static struct { | |||
2860 | {NULL} | 2860 | {NULL} |
2861 | }; | 2861 | }; |
2862 | 2862 | ||
2863 | #ifdef MODULE | ||
2863 | static struct isapnp_device_id id_table[] = { | 2864 | static struct isapnp_device_id id_table[] = { |
2864 | { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), | 2865 | { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), |
2865 | ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 }, | 2866 | ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 }, |
@@ -2877,6 +2878,7 @@ static struct isapnp_device_id id_table[] = { | |||
2877 | }; | 2878 | }; |
2878 | 2879 | ||
2879 | MODULE_DEVICE_TABLE(isapnp, id_table); | 2880 | MODULE_DEVICE_TABLE(isapnp, id_table); |
2881 | #endif | ||
2880 | 2882 | ||
2881 | static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev) | 2883 | static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev) |
2882 | { | 2884 | { |
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c index a8ceef8d1a8d..a8bb4a06ba6f 100644 --- a/sound/oss/msnd_pinnacle.c +++ b/sound/oss/msnd_pinnacle.c | |||
@@ -1288,8 +1288,7 @@ static int __init calibrate_adc(WORD srate) | |||
1288 | & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); | 1288 | & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); |
1289 | if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && | 1289 | if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && |
1290 | chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { | 1290 | chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { |
1291 | __set_current_state(TASK_INTERRUPTIBLE); | 1291 | schedule_timeout_interruptible(HZ / 3); |
1292 | schedule_timeout(HZ / 3); | ||
1293 | return 0; | 1292 | return 0; |
1294 | } | 1293 | } |
1295 | printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); | 1294 | printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); |
diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c index 048439a16000..dc91072f4d82 100644 --- a/sound/oss/sb_audio.c +++ b/sound/oss/sb_audio.c | |||
@@ -102,12 +102,8 @@ void sb_audio_close(int dev) | |||
102 | if(devc->duplex | 102 | if(devc->duplex |
103 | && !devc->fullduplex | 103 | && !devc->fullduplex |
104 | && (devc->opened & OPEN_READ) && (devc->opened & OPEN_WRITE)) | 104 | && (devc->opened & OPEN_READ) && (devc->opened & OPEN_WRITE)) |
105 | { | 105 | swap(audio_devs[dev]->dmap_out, audio_devs[dev]->dmap_in); |
106 | struct dma_buffparms *dmap_temp; | 106 | |
107 | dmap_temp = audio_devs[dev]->dmap_out; | ||
108 | audio_devs[dev]->dmap_out = audio_devs[dev]->dmap_in; | ||
109 | audio_devs[dev]->dmap_in = dmap_temp; | ||
110 | } | ||
111 | audio_devs[dev]->dmap_out->dma = devc->dma8; | 107 | audio_devs[dev]->dmap_out->dma = devc->dma8; |
112 | audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ? | 108 | audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ? |
113 | devc->dma16 : devc->dma8; | 109 | devc->dma16 : devc->dma8; |
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile index 41fa322f0971..526175333710 100644 --- a/sound/pci/ac97/Makefile +++ b/sound/pci/ac97/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ac97-codec-y := ac97_codec.o ac97_pcm.o | 6 | snd-ac97-codec-y := ac97_codec.o ac97_pcm.o |
7 | snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o | 7 | snd-ac97-codec-$(CONFIG_SND_PROC_FS) += ac97_proc.o |
8 | 8 | ||
9 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o | 10 | obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o |
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index c276a5e3f7ac..941a5062cc20 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h | |||
@@ -28,7 +28,7 @@ int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, | |||
28 | unsigned short mask, unsigned short value); | 28 | unsigned short mask, unsigned short value); |
29 | 29 | ||
30 | /* ac97_proc.c */ | 30 | /* ac97_proc.c */ |
31 | #ifdef CONFIG_PROC_FS | 31 | #ifdef CONFIG_SND_PROC_FS |
32 | void snd_ac97_bus_proc_init(struct snd_ac97_bus * ac97); | 32 | void snd_ac97_bus_proc_init(struct snd_ac97_bus * ac97); |
33 | void snd_ac97_bus_proc_done(struct snd_ac97_bus * ac97); | 33 | void snd_ac97_bus_proc_done(struct snd_ac97_bus * ac97); |
34 | void snd_ac97_proc_init(struct snd_ac97 * ac97); | 34 | void snd_ac97_proc_init(struct snd_ac97 * ac97); |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 66ddd981d1d5..1fc6d8bc09e5 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -898,8 +898,8 @@ snd_ad1889_create(struct snd_card *card, | |||
898 | return err; | 898 | return err; |
899 | 899 | ||
900 | /* check PCI availability (32bit DMA) */ | 900 | /* check PCI availability (32bit DMA) */ |
901 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || | 901 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || |
902 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 902 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
903 | dev_err(card->dev, "error setting 32-bit DMA mask.\n"); | 903 | dev_err(card->dev, "error setting 32-bit DMA mask.\n"); |
904 | pci_disable_device(pci); | 904 | pci_disable_device(pci); |
905 | return -ENXIO; | 905 | return -ENXIO; |
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index 3bf0dc53360a..2fb1fbba3e5e 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c | |||
@@ -35,11 +35,7 @@ MODULE_DESCRIPTION("Universal routines for AK4531 codec"); | |||
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | */ | 36 | */ |
37 | 37 | ||
38 | #ifdef CONFIG_PROC_FS | ||
39 | static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531); | 38 | static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531); |
40 | #else | ||
41 | #define snd_ak4531_proc_init(card,ak) | ||
42 | #endif | ||
43 | 39 | ||
44 | /* | 40 | /* |
45 | * | 41 | * |
@@ -466,7 +462,6 @@ void snd_ak4531_resume(struct snd_ak4531 *ak4531) | |||
466 | } | 462 | } |
467 | #endif | 463 | #endif |
468 | 464 | ||
469 | #ifdef CONFIG_PROC_FS | ||
470 | /* | 465 | /* |
471 | * /proc interface | 466 | * /proc interface |
472 | */ | 467 | */ |
@@ -491,4 +486,3 @@ snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531) | |||
491 | if (! snd_card_proc_new(card, "ak4531", &entry)) | 486 | if (! snd_card_proc_new(card, "ak4531", &entry)) |
492 | snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read); | 487 | snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read); |
493 | } | 488 | } |
494 | #endif | ||
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index c8d499575c01..36470af7eda7 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2105,8 +2105,8 @@ static int snd_ali_create(struct snd_card *card, | |||
2105 | if (err < 0) | 2105 | if (err < 0) |
2106 | return err; | 2106 | return err; |
2107 | /* check, if we can restrict PCI DMA transfers to 31 bits */ | 2107 | /* check, if we can restrict PCI DMA transfers to 31 bits */ |
2108 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(31)) < 0 || | 2108 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(31)) < 0 || |
2109 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(31)) < 0) { | 2109 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(31)) < 0) { |
2110 | dev_err(card->dev, | 2110 | dev_err(card->dev, |
2111 | "architecture does not support 31bit PCI busmaster DMA\n"); | 2111 | "architecture does not support 31bit PCI busmaster DMA\n"); |
2112 | pci_disable_device(pci); | 2112 | pci_disable_device(pci); |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 57e034f208dc..add3176398d3 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -658,8 +658,8 @@ static int snd_als300_create(struct snd_card *card, | |||
658 | if ((err = pci_enable_device(pci)) < 0) | 658 | if ((err = pci_enable_device(pci)) < 0) |
659 | return err; | 659 | return err; |
660 | 660 | ||
661 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || | 661 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || |
662 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { | 662 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { |
663 | dev_err(card->dev, "error setting 28bit DMA mask\n"); | 663 | dev_err(card->dev, "error setting 28bit DMA mask\n"); |
664 | pci_disable_device(pci); | 664 | pci_disable_device(pci); |
665 | return -ENXIO; | 665 | return -ENXIO; |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index a3dea464134d..ff39a0c7277b 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -871,8 +871,8 @@ static int snd_card_als4000_probe(struct pci_dev *pci, | |||
871 | return err; | 871 | return err; |
872 | } | 872 | } |
873 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 873 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
874 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || | 874 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || |
875 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { | 875 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { |
876 | dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n"); | 876 | dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n"); |
877 | pci_disable_device(pci); | 877 | pci_disable_device(pci); |
878 | return -ENXIO; | 878 | return -ENXIO; |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 6610bd096fc9..d17937b92331 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
33 | #include <linux/stringify.h> | 33 | #include <linux/stringify.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/vmalloc.h> | ||
35 | 36 | ||
36 | #ifdef MODULE_FIRMWARE | 37 | #ifdef MODULE_FIRMWARE |
37 | MODULE_FIRMWARE("asihpi/dsp5000.bin"); | 38 | MODULE_FIRMWARE("asihpi/dsp5000.bin"); |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 42a20c806b39..1028fc8bdff5 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1530,7 +1530,6 @@ static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |||
1530 | #endif /* CONFIG_PM_SLEEP */ | 1530 | #endif /* CONFIG_PM_SLEEP */ |
1531 | 1531 | ||
1532 | 1532 | ||
1533 | #ifdef CONFIG_PROC_FS | ||
1534 | /* | 1533 | /* |
1535 | * proc interface for register dump | 1534 | * proc interface for register dump |
1536 | */ | 1535 | */ |
@@ -1552,9 +1551,6 @@ static void snd_atiixp_proc_init(struct atiixp *chip) | |||
1552 | if (! snd_card_proc_new(chip->card, "atiixp", &entry)) | 1551 | if (! snd_card_proc_new(chip->card, "atiixp", &entry)) |
1553 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); | 1552 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); |
1554 | } | 1553 | } |
1555 | #else /* !CONFIG_PROC_FS */ | ||
1556 | #define snd_atiixp_proc_init(chip) | ||
1557 | #endif | ||
1558 | 1554 | ||
1559 | 1555 | ||
1560 | /* | 1556 | /* |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0a38e08164ab..27ed678a46df 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1156,7 +1156,6 @@ static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |||
1156 | #define SND_ATIIXP_PM_OPS NULL | 1156 | #define SND_ATIIXP_PM_OPS NULL |
1157 | #endif /* CONFIG_PM_SLEEP */ | 1157 | #endif /* CONFIG_PM_SLEEP */ |
1158 | 1158 | ||
1159 | #ifdef CONFIG_PROC_FS | ||
1160 | /* | 1159 | /* |
1161 | * proc interface for register dump | 1160 | * proc interface for register dump |
1162 | */ | 1161 | */ |
@@ -1178,9 +1177,6 @@ static void snd_atiixp_proc_init(struct atiixp_modem *chip) | |||
1178 | if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) | 1177 | if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) |
1179 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); | 1178 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); |
1180 | } | 1179 | } |
1181 | #else | ||
1182 | #define snd_atiixp_proc_init(chip) | ||
1183 | #endif | ||
1184 | 1180 | ||
1185 | 1181 | ||
1186 | /* | 1182 | /* |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 996369134ea8..32092184bbf2 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -150,8 +150,8 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
150 | // check PCI availability (DMA). | 150 | // check PCI availability (DMA). |
151 | if ((err = pci_enable_device(pci)) < 0) | 151 | if ((err = pci_enable_device(pci)) < 0) |
152 | return err; | 152 | return err; |
153 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || | 153 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || |
154 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 154 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
155 | dev_err(card->dev, "error to set DMA mask\n"); | 155 | dev_err(card->dev, "error to set DMA mask\n"); |
156 | pci_disable_device(pci); | 156 | pci_disable_device(pci); |
157 | return -ENXIO; | 157 | return -ENXIO; |
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 8d2fee7b33bd..167714303070 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c | |||
@@ -258,8 +258,8 @@ static int snd_aw2_create(struct snd_card *card, | |||
258 | pci_set_master(pci); | 258 | pci_set_master(pci); |
259 | 259 | ||
260 | /* check PCI availability (32bit DMA) */ | 260 | /* check PCI availability (32bit DMA) */ |
261 | if ((pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) || | 261 | if ((dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) || |
262 | (pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0)) { | 262 | (dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0)) { |
263 | dev_err(card->dev, "Impossible to set 32bit mask DMA\n"); | 263 | dev_err(card->dev, "Impossible to set 32bit mask DMA\n"); |
264 | pci_disable_device(pci); | 264 | pci_disable_device(pci); |
265 | return -ENXIO; | 265 | return -ENXIO; |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 33b2a0af1b59..07a4acc99541 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2420,8 +2420,8 @@ snd_azf3328_create(struct snd_card *card, | |||
2420 | chip->irq = -1; | 2420 | chip->irq = -1; |
2421 | 2421 | ||
2422 | /* check if we can restrict PCI DMA transfers to 24 bits */ | 2422 | /* check if we can restrict PCI DMA transfers to 24 bits */ |
2423 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || | 2423 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || |
2424 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { | 2424 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { |
2425 | dev_err(card->dev, | 2425 | dev_err(card->dev, |
2426 | "architecture does not support 24bit PCI busmaster DMA\n" | 2426 | "architecture does not support 24bit PCI busmaster DMA\n" |
2427 | ); | 2427 | ); |
diff --git a/sound/pci/ca0106/Makefile b/sound/pci/ca0106/Makefile index dcbae7b31546..c1455fc5588c 100644 --- a/sound/pci/ca0106/Makefile +++ b/sound/pci/ca0106/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | snd-ca0106-objs := ca0106_main.o ca0106_proc.o ca0106_mixer.o ca_midi.o | 1 | snd-ca0106-objs := ca0106_main.o ca0106_mixer.o ca_midi.o |
2 | snd-ca0106-$(CONFIG_SND_PROC_FS) += ca0106_proc.o | ||
2 | 3 | ||
3 | obj-$(CONFIG_SND_CA0106) += snd-ca0106.o | 4 | obj-$(CONFIG_SND_CA0106) += snd-ca0106.o |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index dd75b7536fa2..d3cd95633ee2 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1676,8 +1676,8 @@ static int snd_ca0106_create(int dev, struct snd_card *card, | |||
1676 | err = pci_enable_device(pci); | 1676 | err = pci_enable_device(pci); |
1677 | if (err < 0) | 1677 | if (err < 0) |
1678 | return err; | 1678 | return err; |
1679 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || | 1679 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || |
1680 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 1680 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
1681 | dev_err(card->dev, "error to set 32bit mask DMA\n"); | 1681 | dev_err(card->dev, "error to set 32bit mask DMA\n"); |
1682 | pci_disable_device(pci); | 1682 | pci_disable_device(pci); |
1683 | return -ENXIO; | 1683 | return -ENXIO; |
@@ -1885,7 +1885,7 @@ static int snd_ca0106_probe(struct pci_dev *pci, | |||
1885 | goto error; | 1885 | goto error; |
1886 | dev_dbg(card->dev, " done.\n"); | 1886 | dev_dbg(card->dev, " done.\n"); |
1887 | 1887 | ||
1888 | #ifdef CONFIG_PROC_FS | 1888 | #ifdef CONFIG_SND_PROC_FS |
1889 | snd_ca0106_proc_init(chip); | 1889 | snd_ca0106_proc_init(chip); |
1890 | #endif | 1890 | #endif |
1891 | 1891 | ||
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 2c5c28adbefd..9b2b8b38122f 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c | |||
@@ -75,8 +75,6 @@ | |||
75 | #include "ca0106.h" | 75 | #include "ca0106.h" |
76 | 76 | ||
77 | 77 | ||
78 | #ifdef CONFIG_PROC_FS | ||
79 | |||
80 | struct snd_ca0106_category_str { | 78 | struct snd_ca0106_category_str { |
81 | int val; | 79 | int val; |
82 | const char *name; | 80 | const char *name; |
@@ -453,5 +451,3 @@ int snd_ca0106_proc_init(struct snd_ca0106 *emu) | |||
453 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); | 451 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); |
454 | return 0; | 452 | return 0; |
455 | } | 453 | } |
456 | |||
457 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 6cf464d9043d..24cdcba06d27 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -2772,7 +2772,6 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) | |||
2772 | * proc interface | 2772 | * proc interface |
2773 | */ | 2773 | */ |
2774 | 2774 | ||
2775 | #ifdef CONFIG_PROC_FS | ||
2776 | static void snd_cmipci_proc_read(struct snd_info_entry *entry, | 2775 | static void snd_cmipci_proc_read(struct snd_info_entry *entry, |
2777 | struct snd_info_buffer *buffer) | 2776 | struct snd_info_buffer *buffer) |
2778 | { | 2777 | { |
@@ -2798,10 +2797,6 @@ static void snd_cmipci_proc_init(struct cmipci *cm) | |||
2798 | if (! snd_card_proc_new(cm->card, "cmipci", &entry)) | 2797 | if (! snd_card_proc_new(cm->card, "cmipci", &entry)) |
2799 | snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); | 2798 | snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); |
2800 | } | 2799 | } |
2801 | #else /* !CONFIG_PROC_FS */ | ||
2802 | static inline void snd_cmipci_proc_init(struct cmipci *cm) {} | ||
2803 | #endif | ||
2804 | |||
2805 | 2800 | ||
2806 | static const struct pci_device_id snd_cmipci_ids[] = { | 2801 | static const struct pci_device_id snd_cmipci_ids[] = { |
2807 | {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, | 2802 | {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 8d74004b1ed2..2a9f4a345171 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2816,7 +2816,7 @@ int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; } | |||
2816 | static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } | 2816 | static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } |
2817 | #endif /* CONFIG_GAMEPORT */ | 2817 | #endif /* CONFIG_GAMEPORT */ |
2818 | 2818 | ||
2819 | #ifdef CONFIG_PROC_FS | 2819 | #ifdef CONFIG_SND_PROC_FS |
2820 | /* | 2820 | /* |
2821 | * proc interface | 2821 | * proc interface |
2822 | */ | 2822 | */ |
@@ -2865,7 +2865,7 @@ static int snd_cs46xx_proc_done(struct snd_cs46xx *chip) | |||
2865 | #endif | 2865 | #endif |
2866 | return 0; | 2866 | return 0; |
2867 | } | 2867 | } |
2868 | #else /* !CONFIG_PROC_FS */ | 2868 | #else /* !CONFIG_SND_PROC_FS */ |
2869 | #define snd_cs46xx_proc_init(card, chip) | 2869 | #define snd_cs46xx_proc_init(card, chip) |
2870 | #define snd_cs46xx_proc_done(chip) | 2870 | #define snd_cs46xx_proc_done(chip) |
2871 | #endif | 2871 | #endif |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index 86f14620f817..bdf4114167ea 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -95,7 +95,7 @@ int cs46xx_dsp_resume(struct snd_cs46xx * chip); | |||
95 | #endif | 95 | #endif |
96 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, | 96 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, |
97 | int symbol_type); | 97 | int symbol_type); |
98 | #ifdef CONFIG_PROC_FS | 98 | #ifdef CONFIG_SND_PROC_FS |
99 | int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip); | 99 | int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip); |
100 | int cs46xx_dsp_proc_done (struct snd_cs46xx *chip); | 100 | int cs46xx_dsp_proc_done (struct snd_cs46xx *chip); |
101 | #else | 101 | #else |
@@ -118,7 +118,7 @@ int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip); | |||
118 | int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data); | 118 | int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data); |
119 | struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, | 119 | struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, |
120 | u32 * scb_data, u32 dest); | 120 | u32 * scb_data, u32 dest); |
121 | #ifdef CONFIG_PROC_FS | 121 | #ifdef CONFIG_SND_PROC_FS |
122 | void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb); | 122 | void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb); |
123 | void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, | 123 | void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, |
124 | struct dsp_scb_descriptor * scb); | 124 | struct dsp_scb_descriptor * scb); |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 5c99efb004c0..d2951ed4bf71 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -476,7 +476,7 @@ cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symb | |||
476 | } | 476 | } |
477 | 477 | ||
478 | 478 | ||
479 | #ifdef CONFIG_PROC_FS | 479 | #ifdef CONFIG_SND_PROC_FS |
480 | static struct dsp_symbol_entry * | 480 | static struct dsp_symbol_entry * |
481 | cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type) | 481 | cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type) |
482 | { | 482 | { |
@@ -929,7 +929,7 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) | |||
929 | 929 | ||
930 | return 0; | 930 | return 0; |
931 | } | 931 | } |
932 | #endif /* CONFIG_PROC_FS */ | 932 | #endif /* CONFIG_SND_PROC_FS */ |
933 | 933 | ||
934 | static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, | 934 | static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, |
935 | u32 dest, int size) | 935 | u32 dest, int size) |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 2c90c0bded69..7488e1b7a770 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -67,7 +67,7 @@ static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * s | |||
67 | 67 | ||
68 | } | 68 | } |
69 | 69 | ||
70 | #ifdef CONFIG_PROC_FS | 70 | #ifdef CONFIG_SND_PROC_FS |
71 | static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, | 71 | static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, |
72 | struct snd_info_buffer *buffer) | 72 | struct snd_info_buffer *buffer) |
73 | { | 73 | { |
@@ -228,7 +228,7 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * | |||
228 | } | 228 | } |
229 | 229 | ||
230 | 230 | ||
231 | #ifdef CONFIG_PROC_FS | 231 | #ifdef CONFIG_SND_PROC_FS |
232 | void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) | 232 | void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) |
233 | { | 233 | { |
234 | if (scb->proc_info) { | 234 | if (scb->proc_info) { |
@@ -285,7 +285,7 @@ out: | |||
285 | scb->proc_info = entry; | 285 | scb->proc_info = entry; |
286 | } | 286 | } |
287 | } | 287 | } |
288 | #endif /* CONFIG_PROC_FS */ | 288 | #endif /* CONFIG_SND_PROC_FS */ |
289 | 289 | ||
290 | static struct dsp_scb_descriptor * | 290 | static struct dsp_scb_descriptor * |
291 | _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest, | 291 | _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest, |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 963b912550d4..de409cda50aa 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -289,8 +289,8 @@ static int snd_cs5535audio_create(struct snd_card *card, | |||
289 | if ((err = pci_enable_device(pci)) < 0) | 289 | if ((err = pci_enable_device(pci)) < 0) |
290 | return err; | 290 | return err; |
291 | 291 | ||
292 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || | 292 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || |
293 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 293 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
294 | dev_warn(card->dev, "unable to get 32bit dma\n"); | 294 | dev_warn(card->dev, "unable to get 32bit dma\n"); |
295 | err = -ENXIO; | 295 | err = -ENXIO; |
296 | goto pcifail; | 296 | goto pcifail; |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 1cac55fd1139..9667cbfb0ca2 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -1910,8 +1910,8 @@ static int hw_card_start(struct hw *hw) | |||
1910 | return err; | 1910 | return err; |
1911 | 1911 | ||
1912 | /* Set DMA transfer mask */ | 1912 | /* Set DMA transfer mask */ |
1913 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || | 1913 | if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 || |
1914 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { | 1914 | dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) { |
1915 | dev_err(hw->card->dev, | 1915 | dev_err(hw->card->dev, |
1916 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", | 1916 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
1917 | CT_XFI_DMA_MASK); | 1917 | CT_XFI_DMA_MASK); |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 955ad871e9a8..9dc2950e1ab7 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -2035,8 +2035,8 @@ static int hw_card_start(struct hw *hw) | |||
2035 | return err; | 2035 | return err; |
2036 | 2036 | ||
2037 | /* Set DMA transfer mask */ | 2037 | /* Set DMA transfer mask */ |
2038 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || | 2038 | if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 || |
2039 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { | 2039 | dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) { |
2040 | dev_err(hw->card->dev, | 2040 | dev_err(hw->card->dev, |
2041 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", | 2041 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
2042 | CT_XFI_DMA_MASK); | 2042 | CT_XFI_DMA_MASK); |
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile index fc5591e7777e..29b44ca27010 100644 --- a/sound/pci/emu10k1/Makefile +++ b/sound/pci/emu10k1/Makefile | |||
@@ -5,7 +5,8 @@ | |||
5 | 5 | ||
6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ | 6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ |
7 | irq.o memory.o voice.o emumpu401.o emupcm.o io.o \ | 7 | irq.o memory.o voice.o emumpu401.o emupcm.o io.o \ |
8 | emuproc.o emumixer.o emufx.o timer.o p16v.o | 8 | emumixer.o emufx.o timer.o p16v.o |
9 | snd-emu10k1-$(CONFIG_SND_PROC_FS) += emuproc.o | ||
9 | snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o | 10 | snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o |
10 | snd-emu10k1x-objs := emu10k1x.o | 11 | snd-emu10k1x-objs := emu10k1x.o |
11 | 12 | ||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 37d0220a094c..db7a2e5e4a14 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -183,8 +183,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, | |||
183 | } | 183 | } |
184 | #endif | 184 | #endif |
185 | 185 | ||
186 | strcpy(card->driver, emu->card_capabilities->driver); | 186 | strlcpy(card->driver, emu->card_capabilities->driver, |
187 | strcpy(card->shortname, emu->card_capabilities->name); | 187 | sizeof(card->driver)); |
188 | strlcpy(card->shortname, emu->card_capabilities->name, | ||
189 | sizeof(card->shortname)); | ||
188 | snprintf(card->longname, sizeof(card->longname), | 190 | snprintf(card->longname, sizeof(card->longname), |
189 | "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", | 191 | "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", |
190 | card->shortname, emu->revision, emu->serial, emu->port, emu->irq); | 192 | card->shortname, emu->revision, emu->serial, emu->port, emu->irq); |
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 874cd76c7b7f..d2c7ea3a7610 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c | |||
@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp) | |||
415 | snd_emu10k1_ptr_write(hw, Z2, ch, 0); | 415 | snd_emu10k1_ptr_write(hw, Z2, ch, 0); |
416 | 416 | ||
417 | /* invalidate maps */ | 417 | /* invalidate maps */ |
418 | temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK; | 418 | temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); |
419 | snd_emu10k1_ptr_write(hw, MAPA, ch, temp); | 419 | snd_emu10k1_ptr_write(hw, MAPA, ch, temp); |
420 | snd_emu10k1_ptr_write(hw, MAPB, ch, temp); | 420 | snd_emu10k1_ptr_write(hw, MAPB, ch, temp); |
421 | #if 0 | 421 | #if 0 |
@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp) | |||
436 | snd_emu10k1_ptr_write(hw, CDF, ch, sample); | 436 | snd_emu10k1_ptr_write(hw, CDF, ch, sample); |
437 | 437 | ||
438 | /* invalidate maps */ | 438 | /* invalidate maps */ |
439 | temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK; | 439 | temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); |
440 | snd_emu10k1_ptr_write(hw, MAPA, ch, temp); | 440 | snd_emu10k1_ptr_write(hw, MAPA, ch, temp); |
441 | snd_emu10k1_ptr_write(hw, MAPB, ch, temp); | 441 | snd_emu10k1_ptr_write(hw, MAPB, ch, temp); |
442 | 442 | ||
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 54079f5d5673..28e2f8b42f5e 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
282 | snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ | 282 | snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ |
283 | snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ | 283 | snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ |
284 | 284 | ||
285 | silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK; | 285 | silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); |
286 | for (ch = 0; ch < NUM_G; ch++) { | 286 | for (ch = 0; ch < NUM_G; ch++) { |
287 | snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); | 287 | snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); |
288 | snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); | 288 | snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); |
@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
348 | outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); | 348 | outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); |
349 | } | 349 | } |
350 | 350 | ||
351 | if (emu->address_mode == 0) { | ||
352 | /* use 16M in 4G */ | ||
353 | outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG); | ||
354 | } | ||
355 | |||
351 | return 0; | 356 | return 0; |
352 | } | 357 | } |
353 | 358 | ||
@@ -1446,7 +1451,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1446 | * | 1451 | * |
1447 | */ | 1452 | */ |
1448 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, | 1453 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, |
1449 | .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", | 1454 | .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", |
1450 | .id = "Audigy2", | 1455 | .id = "Audigy2", |
1451 | .emu10k2_chip = 1, | 1456 | .emu10k2_chip = 1, |
1452 | .ca0108_chip = 1, | 1457 | .ca0108_chip = 1, |
@@ -1596,7 +1601,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1596 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | 1601 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ |
1597 | .ac97_chip = 1} , | 1602 | .ac97_chip = 1} , |
1598 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 1603 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
1599 | .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", | 1604 | .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", |
1600 | .id = "Audigy2", | 1605 | .id = "Audigy2", |
1601 | .emu10k2_chip = 1, | 1606 | .emu10k2_chip = 1, |
1602 | .ca0102_chip = 1, | 1607 | .ca0102_chip = 1, |
@@ -1902,10 +1907,12 @@ int snd_emu10k1_create(struct snd_card *card, | |||
1902 | 1907 | ||
1903 | is_audigy = emu->audigy = c->emu10k2_chip; | 1908 | is_audigy = emu->audigy = c->emu10k2_chip; |
1904 | 1909 | ||
1910 | /* set addressing mode */ | ||
1911 | emu->address_mode = is_audigy ? 0 : 1; | ||
1905 | /* set the DMA transfer mask */ | 1912 | /* set the DMA transfer mask */ |
1906 | emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; | 1913 | emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; |
1907 | if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || | 1914 | if (dma_set_mask(&pci->dev, emu->dma_mask) < 0 || |
1908 | pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { | 1915 | dma_set_coherent_mask(&pci->dev, emu->dma_mask) < 0) { |
1909 | dev_err(card->dev, | 1916 | dev_err(card->dev, |
1910 | "architecture does not support PCI busmaster DMA with mask 0x%lx\n", | 1917 | "architecture does not support PCI busmaster DMA with mask 0x%lx\n", |
1911 | emu->dma_mask); | 1918 | emu->dma_mask); |
@@ -1928,7 +1935,7 @@ int snd_emu10k1_create(struct snd_card *card, | |||
1928 | 1935 | ||
1929 | emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; | 1936 | emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; |
1930 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 1937 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), |
1931 | 32 * 1024, &emu->ptb_pages) < 0) { | 1938 | (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) { |
1932 | err = -ENOMEM; | 1939 | err = -ENOMEM; |
1933 | goto error; | 1940 | goto error; |
1934 | } | 1941 | } |
@@ -2027,8 +2034,8 @@ int snd_emu10k1_create(struct snd_card *card, | |||
2027 | 2034 | ||
2028 | /* Clear silent pages and set up pointers */ | 2035 | /* Clear silent pages and set up pointers */ |
2029 | memset(emu->silent_page.area, 0, PAGE_SIZE); | 2036 | memset(emu->silent_page.area, 0, PAGE_SIZE); |
2030 | silent_page = emu->silent_page.addr << 1; | 2037 | silent_page = emu->silent_page.addr << emu->address_mode; |
2031 | for (idx = 0; idx < MAXPAGES; idx++) | 2038 | for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) |
2032 | ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); | 2039 | ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); |
2033 | 2040 | ||
2034 | /* set up voice indices */ | 2041 | /* set up voice indices */ |
@@ -2056,7 +2063,7 @@ int snd_emu10k1_create(struct snd_card *card, | |||
2056 | if (err < 0) | 2063 | if (err < 0) |
2057 | goto error; | 2064 | goto error; |
2058 | 2065 | ||
2059 | #ifdef CONFIG_PROC_FS | 2066 | #ifdef CONFIG_SND_PROC_FS |
2060 | snd_emu10k1_proc_init(emu); | 2067 | snd_emu10k1_proc_init(emu); |
2061 | #endif | 2068 | #endif |
2062 | 2069 | ||
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 0dc07385af0e..14a305bd8a98 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -380,7 +380,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, | |||
380 | snd_emu10k1_ptr_write(emu, Z1, voice, 0); | 380 | snd_emu10k1_ptr_write(emu, Z1, voice, 0); |
381 | snd_emu10k1_ptr_write(emu, Z2, voice, 0); | 381 | snd_emu10k1_ptr_write(emu, Z2, voice, 0); |
382 | /* invalidate maps */ | 382 | /* invalidate maps */ |
383 | silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; | 383 | silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); |
384 | snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); | 384 | snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); |
385 | snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); | 385 | snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); |
386 | /* modulation envelope */ | 386 | /* modulation envelope */ |
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 53745f4c2bf5..cf05229b569b 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <sound/emu10k1.h> | 34 | #include <sound/emu10k1.h> |
35 | #include "p16v.h" | 35 | #include "p16v.h" |
36 | 36 | ||
37 | #ifdef CONFIG_PROC_FS | ||
38 | static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu, | 37 | static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu, |
39 | struct snd_info_buffer *buffer, | 38 | struct snd_info_buffer *buffer, |
40 | char *title, | 39 | char *title, |
@@ -656,4 +655,3 @@ int snd_emu10k1_proc_init(struct snd_emu10k1 *emu) | |||
656 | } | 655 | } |
657 | return 0; | 656 | return 0; |
658 | } | 657 | } |
659 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index c68e6dd2fa67..4f1f69be1865 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -34,10 +34,11 @@ | |||
34 | * aligned pages in others | 34 | * aligned pages in others |
35 | */ | 35 | */ |
36 | #define __set_ptb_entry(emu,page,addr) \ | 36 | #define __set_ptb_entry(emu,page,addr) \ |
37 | (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page))) | 37 | (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page))) |
38 | 38 | ||
39 | #define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) | 39 | #define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) |
40 | #define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) | 40 | #define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) |
41 | #define MAX_ALIGN_PAGES1 (MAXPAGES1 / UNIT_PAGES) | ||
41 | /* get aligned page from offset address */ | 42 | /* get aligned page from offset address */ |
42 | #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) | 43 | #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) |
43 | /* get offset address from aligned page */ | 44 | /* get offset address from aligned page */ |
@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis | |||
124 | } | 125 | } |
125 | page = blk->mapped_page + blk->pages; | 126 | page = blk->mapped_page + blk->pages; |
126 | } | 127 | } |
127 | size = MAX_ALIGN_PAGES - page; | 128 | size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page; |
128 | if (size >= max_size) { | 129 | if (size >= max_size) { |
129 | *nextp = pos; | 130 | *nextp = pos; |
130 | return page; | 131 | return page; |
@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) | |||
181 | q = get_emu10k1_memblk(p, mapped_link); | 182 | q = get_emu10k1_memblk(p, mapped_link); |
182 | end_page = q->mapped_page; | 183 | end_page = q->mapped_page; |
183 | } else | 184 | } else |
184 | end_page = MAX_ALIGN_PAGES; | 185 | end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0); |
185 | 186 | ||
186 | /* remove links */ | 187 | /* remove links */ |
187 | list_del(&blk->mapped_link); | 188 | list_del(&blk->mapped_link); |
@@ -307,7 +308,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst | |||
307 | if (snd_BUG_ON(!emu)) | 308 | if (snd_BUG_ON(!emu)) |
308 | return NULL; | 309 | return NULL; |
309 | if (snd_BUG_ON(runtime->dma_bytes <= 0 || | 310 | if (snd_BUG_ON(runtime->dma_bytes <= 0 || |
310 | runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) | 311 | runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE)) |
311 | return NULL; | 312 | return NULL; |
312 | hdr = emu->memhdr; | 313 | hdr = emu->memhdr; |
313 | if (snd_BUG_ON(!hdr)) | 314 | if (snd_BUG_ON(!hdr)) |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index e1858d9d23d8..8963d7688fb0 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1580,8 +1580,8 @@ static int snd_es1938_create(struct snd_card *card, | |||
1580 | if ((err = pci_enable_device(pci)) < 0) | 1580 | if ((err = pci_enable_device(pci)) < 0) |
1581 | return err; | 1581 | return err; |
1582 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 1582 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
1583 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || | 1583 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || |
1584 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { | 1584 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { |
1585 | dev_err(card->dev, | 1585 | dev_err(card->dev, |
1586 | "architecture does not support 24bit PCI busmaster DMA\n"); | 1586 | "architecture does not support 24bit PCI busmaster DMA\n"); |
1587 | pci_disable_device(pci); | 1587 | pci_disable_device(pci); |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 059f3846d7b8..e0d9363dc7fd 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2689,8 +2689,8 @@ static int snd_es1968_create(struct snd_card *card, | |||
2689 | if ((err = pci_enable_device(pci)) < 0) | 2689 | if ((err = pci_enable_device(pci)) < 0) |
2690 | return err; | 2690 | return err; |
2691 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2691 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2692 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || | 2692 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || |
2693 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { | 2693 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { |
2694 | dev_err(card->dev, | 2694 | dev_err(card->dev, |
2695 | "architecture does not support 28bit PCI busmaster DMA\n"); | 2695 | "architecture does not support 28bit PCI busmaster DMA\n"); |
2696 | pci_disable_device(pci); | 2696 | pci_disable_device(pci); |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index a5ed1c181784..e94cfd5c69f7 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -4,7 +4,7 @@ config SND_HDA | |||
4 | tristate | 4 | tristate |
5 | select SND_PCM | 5 | select SND_PCM |
6 | select SND_VMASTER | 6 | select SND_VMASTER |
7 | select SND_KCTL_JACK | 7 | select SND_JACK if INPUT=y || INPUT=SND |
8 | select SND_HDA_CORE | 8 | select SND_HDA_CORE |
9 | 9 | ||
10 | config SND_HDA_INTEL | 10 | config SND_HDA_INTEL |
@@ -38,22 +38,6 @@ config SND_HDA_TEGRA | |||
38 | 38 | ||
39 | if SND_HDA | 39 | if SND_HDA |
40 | 40 | ||
41 | config SND_HDA_DSP_LOADER | ||
42 | bool | ||
43 | |||
44 | config SND_HDA_PREALLOC_SIZE | ||
45 | int "Pre-allocated buffer size for HD-audio driver" | ||
46 | range 0 32768 | ||
47 | default 64 | ||
48 | help | ||
49 | Specifies the default pre-allocated buffer-size in kB for the | ||
50 | HD-audio driver. A larger buffer (e.g. 2048) is preferred | ||
51 | for systems using PulseAudio. The default 64 is chosen just | ||
52 | for compatibility reasons. | ||
53 | |||
54 | Note that the pre-allocation size can be changed dynamically | ||
55 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. | ||
56 | |||
57 | config SND_HDA_HWDEP | 41 | config SND_HDA_HWDEP |
58 | bool "Build hwdep interface for HD-audio driver" | 42 | bool "Build hwdep interface for HD-audio driver" |
59 | select SND_HWDEP | 43 | select SND_HWDEP |
@@ -87,14 +71,6 @@ config SND_HDA_INPUT_BEEP_MODE | |||
87 | Set 1 to always enable the digital beep interface for HD-audio by | 71 | Set 1 to always enable the digital beep interface for HD-audio by |
88 | default. | 72 | default. |
89 | 73 | ||
90 | config SND_HDA_INPUT_JACK | ||
91 | bool "Support jack plugging notification via input layer" | ||
92 | depends on INPUT=y || INPUT=SND | ||
93 | select SND_JACK | ||
94 | help | ||
95 | Say Y here to enable the jack plugging notification via | ||
96 | input layer. | ||
97 | |||
98 | config SND_HDA_PATCH_LOADER | 74 | config SND_HDA_PATCH_LOADER |
99 | bool "Support initialization patch loading for HD-audio" | 75 | bool "Support initialization patch loading for HD-audio" |
100 | select FW_LOADER | 76 | select FW_LOADER |
@@ -156,11 +132,6 @@ config SND_HDA_CODEC_HDMI | |||
156 | comment "Set to Y if you want auto-loading the codec driver" | 132 | comment "Set to Y if you want auto-loading the codec driver" |
157 | depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m | 133 | depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m |
158 | 134 | ||
159 | config SND_HDA_I915 | ||
160 | bool | ||
161 | default y | ||
162 | depends on DRM_I915 | ||
163 | |||
164 | config SND_HDA_CODEC_CIRRUS | 135 | config SND_HDA_CODEC_CIRRUS |
165 | tristate "Build Cirrus Logic codec support" | 136 | tristate "Build Cirrus Logic codec support" |
166 | select SND_HDA_GENERIC | 137 | select SND_HDA_GENERIC |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index af78fb33a4fd..6d83c6e0396a 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,16 +1,16 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-controller-objs := hda_controller.o | ||
3 | snd-hda-tegra-objs := hda_tegra.o | 2 | snd-hda-tegra-objs := hda_tegra.o |
4 | # for haswell power well | ||
5 | snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o | ||
6 | 3 | ||
7 | snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o | 4 | snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o |
8 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-y += hda_controller.o |
6 | snd-hda-codec-$(CONFIG_SND_PROC_FS) += hda_proc.o | ||
7 | |||
9 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 8 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
10 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 9 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
11 | 10 | ||
12 | # for trace-points | 11 | # for trace-points |
13 | CFLAGS_hda_controller.o := -I$(src) | 12 | CFLAGS_hda_controller.o := -I$(src) |
13 | CFLAGS_hda_intel.o := -I$(src) | ||
14 | 14 | ||
15 | snd-hda-codec-generic-objs := hda_generic.o | 15 | snd-hda-codec-generic-objs := hda_generic.o |
16 | snd-hda-codec-realtek-objs := patch_realtek.o | 16 | snd-hda-codec-realtek-objs := patch_realtek.o |
@@ -27,7 +27,6 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o | |||
27 | 27 | ||
28 | # common driver | 28 | # common driver |
29 | obj-$(CONFIG_SND_HDA) := snd-hda-codec.o | 29 | obj-$(CONFIG_SND_HDA) := snd-hda-codec.o |
30 | obj-$(CONFIG_SND_HDA) += snd-hda-controller.o | ||
31 | 30 | ||
32 | # codec drivers | 31 | # codec drivers |
33 | obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o | 32 | obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o |
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 3364dc0fdeab..c397e7da0eac 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Beep Input Interface for HD-audio codec | 2 | * Digital Beep Input Interface for HD-audio codec |
3 | * | 3 | * |
4 | * Author: Matthew Ranostay <mranostay@embeddedalley.com> | 4 | * Author: Matt Ranostay <mranostay@gmail.com> |
5 | * Copyright (c) 2008 Embedded Alley Solutions Inc | 5 | * Copyright (c) 2008 Embedded Alley Solutions Inc |
6 | * | 6 | * |
7 | * This driver is free software; you can redistribute it and/or modify | 7 | * This driver is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 46524ff7e79e..1052ad380e97 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Digital Beep Input Interface for HD-audio codec | 2 | * Digital Beep Input Interface for HD-audio codec |
3 | * | 3 | * |
4 | * Author: Matthew Ranostay <mranostay@embeddedalley.com> | 4 | * Author: Matt Ranostay <mranostay@gmail.com> |
5 | * Copyright (c) 2008 Embedded Alley Solutions Inc | 5 | * Copyright (c) 2008 Embedded Alley Solutions Inc |
6 | * | 6 | * |
7 | * This driver is free software; you can redistribute it and/or modify | 7 | * This driver is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 00aa31c5f08e..d5ac25cc7fee 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c | |||
@@ -27,15 +27,7 @@ static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv) | |||
27 | u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id; | 27 | u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id; |
28 | 28 | ||
29 | for (preset = driver->preset; preset->id; preset++) { | 29 | for (preset = driver->preset; preset->id; preset++) { |
30 | u32 mask = preset->mask; | 30 | if (preset->id == id && |
31 | |||
32 | if (preset->afg && preset->afg != codec->core.afg) | ||
33 | continue; | ||
34 | if (preset->mfg && preset->mfg != codec->core.mfg) | ||
35 | continue; | ||
36 | if (!mask) | ||
37 | mask = ~0; | ||
38 | if (preset->id == (id & mask) && | ||
39 | (!preset->rev || preset->rev == codec->core.revision_id)) { | 31 | (!preset->rev || preset->rev == codec->core.revision_id)) { |
40 | codec->preset = preset; | 32 | codec->preset = preset; |
41 | return 1; | 33 | return 1; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 873ed1bce12b..5de3c5d8c2c0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -146,11 +146,11 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd, | |||
146 | bus->no_response_fallback = 0; | 146 | bus->no_response_fallback = 0; |
147 | mutex_unlock(&bus->core.cmd_mutex); | 147 | mutex_unlock(&bus->core.cmd_mutex); |
148 | snd_hda_power_down_pm(codec); | 148 | snd_hda_power_down_pm(codec); |
149 | if (!codec_in_pm(codec) && res && err < 0 && bus->rirb_error) { | 149 | if (!codec_in_pm(codec) && res && err == -EAGAIN) { |
150 | if (bus->response_reset) { | 150 | if (bus->response_reset) { |
151 | codec_dbg(codec, | 151 | codec_dbg(codec, |
152 | "resetting BUS due to fatal communication error\n"); | 152 | "resetting BUS due to fatal communication error\n"); |
153 | bus->ops.bus_reset(bus); | 153 | snd_hda_bus_reset(bus); |
154 | } | 154 | } |
155 | goto again; | 155 | goto again; |
156 | } | 156 | } |
@@ -436,8 +436,8 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid) | |||
436 | get_wcaps_type(wcaps) != AC_WID_PIN) | 436 | get_wcaps_type(wcaps) != AC_WID_PIN) |
437 | return 0; | 437 | return 0; |
438 | 438 | ||
439 | parm = snd_hda_param_read(codec, nid, AC_PAR_DEVLIST_LEN); | 439 | parm = snd_hdac_read_parm_uncached(&codec->core, nid, AC_PAR_DEVLIST_LEN); |
440 | if (parm == -1 && codec->bus->rirb_error) | 440 | if (parm == -1) |
441 | parm = 0; | 441 | parm = 0; |
442 | return parm & AC_DEV_LIST_LEN_MASK; | 442 | return parm & AC_DEV_LIST_LEN_MASK; |
443 | } | 443 | } |
@@ -467,10 +467,9 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | |||
467 | 467 | ||
468 | devices = 0; | 468 | devices = 0; |
469 | while (devices < dev_len) { | 469 | while (devices < dev_len) { |
470 | parm = snd_hda_codec_read(codec, nid, 0, | 470 | if (snd_hdac_read(&codec->core, nid, |
471 | AC_VERB_GET_DEVICE_LIST, devices); | 471 | AC_VERB_GET_DEVICE_LIST, devices, &parm)) |
472 | if (parm == -1 && codec->bus->rirb_error) | 472 | break; /* error */ |
473 | break; | ||
474 | 473 | ||
475 | for (i = 0; i < 8; i++) { | 474 | for (i = 0; i < 8; i++) { |
476 | dev_list[devices] = (u8)parm; | 475 | dev_list[devices] = (u8)parm; |
@@ -484,96 +483,6 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | |||
484 | } | 483 | } |
485 | 484 | ||
486 | /* | 485 | /* |
487 | * destructor | ||
488 | */ | ||
489 | static void snd_hda_bus_free(struct hda_bus *bus) | ||
490 | { | ||
491 | if (!bus) | ||
492 | return; | ||
493 | if (bus->ops.private_free) | ||
494 | bus->ops.private_free(bus); | ||
495 | snd_hdac_bus_exit(&bus->core); | ||
496 | kfree(bus); | ||
497 | } | ||
498 | |||
499 | static int snd_hda_bus_dev_free(struct snd_device *device) | ||
500 | { | ||
501 | snd_hda_bus_free(device->device_data); | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int snd_hda_bus_dev_disconnect(struct snd_device *device) | ||
506 | { | ||
507 | struct hda_bus *bus = device->device_data; | ||
508 | bus->shutdown = 1; | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | /* hdac_bus_ops translations */ | ||
513 | static int _hda_bus_command(struct hdac_bus *_bus, unsigned int cmd) | ||
514 | { | ||
515 | struct hda_bus *bus = container_of(_bus, struct hda_bus, core); | ||
516 | return bus->ops.command(bus, cmd); | ||
517 | } | ||
518 | |||
519 | static int _hda_bus_get_response(struct hdac_bus *_bus, unsigned int addr, | ||
520 | unsigned int *res) | ||
521 | { | ||
522 | struct hda_bus *bus = container_of(_bus, struct hda_bus, core); | ||
523 | *res = bus->ops.get_response(bus, addr); | ||
524 | return bus->rirb_error ? -EIO : 0; | ||
525 | } | ||
526 | |||
527 | static const struct hdac_bus_ops bus_ops = { | ||
528 | .command = _hda_bus_command, | ||
529 | .get_response = _hda_bus_get_response, | ||
530 | }; | ||
531 | |||
532 | /** | ||
533 | * snd_hda_bus_new - create a HDA bus | ||
534 | * @card: the card entry | ||
535 | * @busp: the pointer to store the created bus instance | ||
536 | * | ||
537 | * Returns 0 if successful, or a negative error code. | ||
538 | */ | ||
539 | int snd_hda_bus_new(struct snd_card *card, | ||
540 | struct hda_bus **busp) | ||
541 | { | ||
542 | struct hda_bus *bus; | ||
543 | int err; | ||
544 | static struct snd_device_ops dev_ops = { | ||
545 | .dev_disconnect = snd_hda_bus_dev_disconnect, | ||
546 | .dev_free = snd_hda_bus_dev_free, | ||
547 | }; | ||
548 | |||
549 | if (busp) | ||
550 | *busp = NULL; | ||
551 | |||
552 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | ||
553 | if (!bus) | ||
554 | return -ENOMEM; | ||
555 | |||
556 | err = snd_hdac_bus_init(&bus->core, card->dev, &bus_ops); | ||
557 | if (err < 0) { | ||
558 | kfree(bus); | ||
559 | return err; | ||
560 | } | ||
561 | |||
562 | bus->card = card; | ||
563 | mutex_init(&bus->prepare_mutex); | ||
564 | |||
565 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); | ||
566 | if (err < 0) { | ||
567 | snd_hda_bus_free(bus); | ||
568 | return err; | ||
569 | } | ||
570 | if (busp) | ||
571 | *busp = bus; | ||
572 | return 0; | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(snd_hda_bus_new); | ||
575 | |||
576 | /* | ||
577 | * read widget caps for each widget and store in cache | 486 | * read widget caps for each widget and store in cache |
578 | */ | 487 | */ |
579 | static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | 488 | static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) |
@@ -873,14 +782,15 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, | |||
873 | struct hda_pcm *pcm; | 782 | struct hda_pcm *pcm; |
874 | va_list args; | 783 | va_list args; |
875 | 784 | ||
876 | va_start(args, fmt); | ||
877 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 785 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
878 | if (!pcm) | 786 | if (!pcm) |
879 | return NULL; | 787 | return NULL; |
880 | 788 | ||
881 | pcm->codec = codec; | 789 | pcm->codec = codec; |
882 | kref_init(&pcm->kref); | 790 | kref_init(&pcm->kref); |
791 | va_start(args, fmt); | ||
883 | pcm->name = kvasprintf(GFP_KERNEL, fmt, args); | 792 | pcm->name = kvasprintf(GFP_KERNEL, fmt, args); |
793 | va_end(args); | ||
884 | if (!pcm->name) { | 794 | if (!pcm->name) { |
885 | kfree(pcm); | 795 | kfree(pcm); |
886 | return NULL; | 796 | return NULL; |
@@ -949,6 +859,7 @@ void snd_hda_codec_register(struct hda_codec *codec) | |||
949 | return; | 859 | return; |
950 | if (device_is_registered(hda_codec_dev(codec))) { | 860 | if (device_is_registered(hda_codec_dev(codec))) { |
951 | snd_hda_register_beep_device(codec); | 861 | snd_hda_register_beep_device(codec); |
862 | snd_hdac_link_power(&codec->core, true); | ||
952 | pm_runtime_enable(hda_codec_dev(codec)); | 863 | pm_runtime_enable(hda_codec_dev(codec)); |
953 | /* it was powered up in snd_hda_codec_new(), now all done */ | 864 | /* it was powered up in snd_hda_codec_new(), now all done */ |
954 | snd_hda_power_down(codec); | 865 | snd_hda_power_down(codec); |
@@ -976,6 +887,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) | |||
976 | 887 | ||
977 | codec->in_freeing = 1; | 888 | codec->in_freeing = 1; |
978 | snd_hdac_device_unregister(&codec->core); | 889 | snd_hdac_device_unregister(&codec->core); |
890 | snd_hdac_link_power(&codec->core, false); | ||
979 | put_device(hda_codec_dev(codec)); | 891 | put_device(hda_codec_dev(codec)); |
980 | return 0; | 892 | return 0; |
981 | } | 893 | } |
@@ -1375,6 +1287,31 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
1375 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); | 1287 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); |
1376 | 1288 | ||
1377 | /** | 1289 | /** |
1290 | * snd_hda_codec_amp_update - update the AMP mono value | ||
1291 | * @codec: HD-audio codec | ||
1292 | * @nid: NID to read the AMP value | ||
1293 | * @ch: channel to update (0 or 1) | ||
1294 | * @dir: #HDA_INPUT or #HDA_OUTPUT | ||
1295 | * @idx: the index value (only for input direction) | ||
1296 | * @mask: bit mask to set | ||
1297 | * @val: the bits value to set | ||
1298 | * | ||
1299 | * Update the AMP values for the given channel, direction and index. | ||
1300 | */ | ||
1301 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, | ||
1302 | int ch, int dir, int idx, int mask, int val) | ||
1303 | { | ||
1304 | unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); | ||
1305 | |||
1306 | /* enable fake mute if no h/w mute but min=mute */ | ||
1307 | if ((query_amp_caps(codec, nid, dir) & | ||
1308 | (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE) | ||
1309 | cmd |= AC_AMP_FAKE_MUTE; | ||
1310 | return snd_hdac_regmap_update_raw(&codec->core, cmd, mask, val); | ||
1311 | } | ||
1312 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update); | ||
1313 | |||
1314 | /** | ||
1378 | * snd_hda_codec_amp_stereo - update the AMP stereo values | 1315 | * snd_hda_codec_amp_stereo - update the AMP stereo values |
1379 | * @codec: HD-audio codec | 1316 | * @codec: HD-audio codec |
1380 | * @nid: NID to read the AMP value | 1317 | * @nid: NID to read the AMP value |
@@ -2082,6 +2019,16 @@ static struct snd_kcontrol_new vmaster_mute_mode = { | |||
2082 | .put = vmaster_mute_mode_put, | 2019 | .put = vmaster_mute_mode_put, |
2083 | }; | 2020 | }; |
2084 | 2021 | ||
2022 | /* meta hook to call each driver's vmaster hook */ | ||
2023 | static void vmaster_hook(void *private_data, int enabled) | ||
2024 | { | ||
2025 | struct hda_vmaster_mute_hook *hook = private_data; | ||
2026 | |||
2027 | if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER) | ||
2028 | enabled = hook->mute_mode; | ||
2029 | hook->hook(hook->codec, enabled); | ||
2030 | } | ||
2031 | |||
2085 | /** | 2032 | /** |
2086 | * snd_hda_add_vmaster_hook - Add a vmaster hook for mute-LED | 2033 | * snd_hda_add_vmaster_hook - Add a vmaster hook for mute-LED |
2087 | * @codec: the HDA codec | 2034 | * @codec: the HDA codec |
@@ -2100,9 +2047,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec, | |||
2100 | 2047 | ||
2101 | if (!hook->hook || !hook->sw_kctl) | 2048 | if (!hook->hook || !hook->sw_kctl) |
2102 | return 0; | 2049 | return 0; |
2103 | snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); | ||
2104 | hook->codec = codec; | 2050 | hook->codec = codec; |
2105 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | 2051 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; |
2052 | snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook); | ||
2106 | if (!expose_enum_ctl) | 2053 | if (!expose_enum_ctl) |
2107 | return 0; | 2054 | return 0; |
2108 | kctl = snd_ctl_new1(&vmaster_mute_mode, hook); | 2055 | kctl = snd_ctl_new1(&vmaster_mute_mode, hook); |
@@ -2128,14 +2075,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) | |||
2128 | */ | 2075 | */ |
2129 | if (hook->codec->bus->shutdown) | 2076 | if (hook->codec->bus->shutdown) |
2130 | return; | 2077 | return; |
2131 | switch (hook->mute_mode) { | 2078 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); |
2132 | case HDA_VMUTE_FOLLOW_MASTER: | ||
2133 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); | ||
2134 | break; | ||
2135 | default: | ||
2136 | hook->hook(hook->codec, hook->mute_mode); | ||
2137 | break; | ||
2138 | } | ||
2139 | } | 2079 | } |
2140 | EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook); | 2080 | EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook); |
2141 | 2081 | ||
@@ -3194,6 +3134,7 @@ static int hda_codec_runtime_suspend(struct device *dev) | |||
3194 | if (codec_has_clkstop(codec) && codec_has_epss(codec) && | 3134 | if (codec_has_clkstop(codec) && codec_has_epss(codec) && |
3195 | (state & AC_PWRST_CLK_STOP_OK)) | 3135 | (state & AC_PWRST_CLK_STOP_OK)) |
3196 | snd_hdac_codec_link_down(&codec->core); | 3136 | snd_hdac_codec_link_down(&codec->core); |
3137 | snd_hdac_link_power(&codec->core, false); | ||
3197 | return 0; | 3138 | return 0; |
3198 | } | 3139 | } |
3199 | 3140 | ||
@@ -3201,6 +3142,7 @@ static int hda_codec_runtime_resume(struct device *dev) | |||
3201 | { | 3142 | { |
3202 | struct hda_codec *codec = dev_to_hda_codec(dev); | 3143 | struct hda_codec *codec = dev_to_hda_codec(dev); |
3203 | 3144 | ||
3145 | snd_hdac_link_power(&codec->core, true); | ||
3204 | snd_hdac_codec_link_up(&codec->core); | 3146 | snd_hdac_codec_link_up(&codec->core); |
3205 | hda_call_codec_resume(codec); | 3147 | hda_call_codec_resume(codec); |
3206 | pm_runtime_mark_last_busy(dev); | 3148 | pm_runtime_mark_last_busy(dev); |
@@ -3284,311 +3226,6 @@ int snd_hda_codec_build_controls(struct hda_codec *codec) | |||
3284 | } | 3226 | } |
3285 | 3227 | ||
3286 | /* | 3228 | /* |
3287 | * stream formats | ||
3288 | */ | ||
3289 | struct hda_rate_tbl { | ||
3290 | unsigned int hz; | ||
3291 | unsigned int alsa_bits; | ||
3292 | unsigned int hda_fmt; | ||
3293 | }; | ||
3294 | |||
3295 | /* rate = base * mult / div */ | ||
3296 | #define HDA_RATE(base, mult, div) \ | ||
3297 | (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ | ||
3298 | (((div) - 1) << AC_FMT_DIV_SHIFT)) | ||
3299 | |||
3300 | static struct hda_rate_tbl rate_bits[] = { | ||
3301 | /* rate in Hz, ALSA rate bitmask, HDA format value */ | ||
3302 | |||
3303 | /* autodetected value used in snd_hda_query_supported_pcm */ | ||
3304 | { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, | ||
3305 | { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, | ||
3306 | { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, | ||
3307 | { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, | ||
3308 | { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, | ||
3309 | { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, | ||
3310 | { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, | ||
3311 | { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, | ||
3312 | { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, | ||
3313 | { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, | ||
3314 | { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, | ||
3315 | #define AC_PAR_PCM_RATE_BITS 11 | ||
3316 | /* up to bits 10, 384kHZ isn't supported properly */ | ||
3317 | |||
3318 | /* not autodetected value */ | ||
3319 | { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, | ||
3320 | |||
3321 | { 0 } /* terminator */ | ||
3322 | }; | ||
3323 | |||
3324 | /** | ||
3325 | * snd_hda_calc_stream_format - calculate format bitset | ||
3326 | * @codec: HD-audio codec | ||
3327 | * @rate: the sample rate | ||
3328 | * @channels: the number of channels | ||
3329 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) | ||
3330 | * @maxbps: the max. bps | ||
3331 | * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant) | ||
3332 | * | ||
3333 | * Calculate the format bitset from the given rate, channels and th PCM format. | ||
3334 | * | ||
3335 | * Return zero if invalid. | ||
3336 | */ | ||
3337 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, | ||
3338 | unsigned int rate, | ||
3339 | unsigned int channels, | ||
3340 | unsigned int format, | ||
3341 | unsigned int maxbps, | ||
3342 | unsigned short spdif_ctls) | ||
3343 | { | ||
3344 | int i; | ||
3345 | unsigned int val = 0; | ||
3346 | |||
3347 | for (i = 0; rate_bits[i].hz; i++) | ||
3348 | if (rate_bits[i].hz == rate) { | ||
3349 | val = rate_bits[i].hda_fmt; | ||
3350 | break; | ||
3351 | } | ||
3352 | if (!rate_bits[i].hz) { | ||
3353 | codec_dbg(codec, "invalid rate %d\n", rate); | ||
3354 | return 0; | ||
3355 | } | ||
3356 | |||
3357 | if (channels == 0 || channels > 8) { | ||
3358 | codec_dbg(codec, "invalid channels %d\n", channels); | ||
3359 | return 0; | ||
3360 | } | ||
3361 | val |= channels - 1; | ||
3362 | |||
3363 | switch (snd_pcm_format_width(format)) { | ||
3364 | case 8: | ||
3365 | val |= AC_FMT_BITS_8; | ||
3366 | break; | ||
3367 | case 16: | ||
3368 | val |= AC_FMT_BITS_16; | ||
3369 | break; | ||
3370 | case 20: | ||
3371 | case 24: | ||
3372 | case 32: | ||
3373 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) | ||
3374 | val |= AC_FMT_BITS_32; | ||
3375 | else if (maxbps >= 24) | ||
3376 | val |= AC_FMT_BITS_24; | ||
3377 | else | ||
3378 | val |= AC_FMT_BITS_20; | ||
3379 | break; | ||
3380 | default: | ||
3381 | codec_dbg(codec, "invalid format width %d\n", | ||
3382 | snd_pcm_format_width(format)); | ||
3383 | return 0; | ||
3384 | } | ||
3385 | |||
3386 | if (spdif_ctls & AC_DIG1_NONAUDIO) | ||
3387 | val |= AC_FMT_TYPE_NON_PCM; | ||
3388 | |||
3389 | return val; | ||
3390 | } | ||
3391 | EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); | ||
3392 | |||
3393 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) | ||
3394 | { | ||
3395 | unsigned int val = 0; | ||
3396 | if (nid != codec->core.afg && | ||
3397 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) | ||
3398 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | ||
3399 | if (!val || val == -1) | ||
3400 | val = snd_hda_param_read(codec, codec->core.afg, AC_PAR_PCM); | ||
3401 | if (!val || val == -1) | ||
3402 | return 0; | ||
3403 | return val; | ||
3404 | } | ||
3405 | |||
3406 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) | ||
3407 | { | ||
3408 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | ||
3409 | if (!streams || streams == -1) | ||
3410 | streams = snd_hda_param_read(codec, codec->core.afg, AC_PAR_STREAM); | ||
3411 | if (!streams || streams == -1) | ||
3412 | return 0; | ||
3413 | return streams; | ||
3414 | } | ||
3415 | |||
3416 | /** | ||
3417 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | ||
3418 | * @codec: the HDA codec | ||
3419 | * @nid: NID to query | ||
3420 | * @ratesp: the pointer to store the detected rate bitflags | ||
3421 | * @formatsp: the pointer to store the detected formats | ||
3422 | * @bpsp: the pointer to store the detected format widths | ||
3423 | * | ||
3424 | * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp | ||
3425 | * or @bsps argument is ignored. | ||
3426 | * | ||
3427 | * Returns 0 if successful, otherwise a negative error code. | ||
3428 | */ | ||
3429 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | ||
3430 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | ||
3431 | { | ||
3432 | unsigned int i, val, wcaps; | ||
3433 | |||
3434 | wcaps = get_wcaps(codec, nid); | ||
3435 | val = query_pcm_param(codec, nid); | ||
3436 | |||
3437 | if (ratesp) { | ||
3438 | u32 rates = 0; | ||
3439 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { | ||
3440 | if (val & (1 << i)) | ||
3441 | rates |= rate_bits[i].alsa_bits; | ||
3442 | } | ||
3443 | if (rates == 0) { | ||
3444 | codec_err(codec, | ||
3445 | "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n", | ||
3446 | nid, val, | ||
3447 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); | ||
3448 | return -EIO; | ||
3449 | } | ||
3450 | *ratesp = rates; | ||
3451 | } | ||
3452 | |||
3453 | if (formatsp || bpsp) { | ||
3454 | u64 formats = 0; | ||
3455 | unsigned int streams, bps; | ||
3456 | |||
3457 | streams = query_stream_param(codec, nid); | ||
3458 | if (!streams) | ||
3459 | return -EIO; | ||
3460 | |||
3461 | bps = 0; | ||
3462 | if (streams & AC_SUPFMT_PCM) { | ||
3463 | if (val & AC_SUPPCM_BITS_8) { | ||
3464 | formats |= SNDRV_PCM_FMTBIT_U8; | ||
3465 | bps = 8; | ||
3466 | } | ||
3467 | if (val & AC_SUPPCM_BITS_16) { | ||
3468 | formats |= SNDRV_PCM_FMTBIT_S16_LE; | ||
3469 | bps = 16; | ||
3470 | } | ||
3471 | if (wcaps & AC_WCAP_DIGITAL) { | ||
3472 | if (val & AC_SUPPCM_BITS_32) | ||
3473 | formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; | ||
3474 | if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) | ||
3475 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | ||
3476 | if (val & AC_SUPPCM_BITS_24) | ||
3477 | bps = 24; | ||
3478 | else if (val & AC_SUPPCM_BITS_20) | ||
3479 | bps = 20; | ||
3480 | } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| | ||
3481 | AC_SUPPCM_BITS_32)) { | ||
3482 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | ||
3483 | if (val & AC_SUPPCM_BITS_32) | ||
3484 | bps = 32; | ||
3485 | else if (val & AC_SUPPCM_BITS_24) | ||
3486 | bps = 24; | ||
3487 | else if (val & AC_SUPPCM_BITS_20) | ||
3488 | bps = 20; | ||
3489 | } | ||
3490 | } | ||
3491 | #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */ | ||
3492 | if (streams & AC_SUPFMT_FLOAT32) { | ||
3493 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; | ||
3494 | if (!bps) | ||
3495 | bps = 32; | ||
3496 | } | ||
3497 | #endif | ||
3498 | if (streams == AC_SUPFMT_AC3) { | ||
3499 | /* should be exclusive */ | ||
3500 | /* temporary hack: we have still no proper support | ||
3501 | * for the direct AC3 stream... | ||
3502 | */ | ||
3503 | formats |= SNDRV_PCM_FMTBIT_U8; | ||
3504 | bps = 8; | ||
3505 | } | ||
3506 | if (formats == 0) { | ||
3507 | codec_err(codec, | ||
3508 | "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n", | ||
3509 | nid, val, | ||
3510 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, | ||
3511 | streams); | ||
3512 | return -EIO; | ||
3513 | } | ||
3514 | if (formatsp) | ||
3515 | *formatsp = formats; | ||
3516 | if (bpsp) | ||
3517 | *bpsp = bps; | ||
3518 | } | ||
3519 | |||
3520 | return 0; | ||
3521 | } | ||
3522 | EXPORT_SYMBOL_GPL(snd_hda_query_supported_pcm); | ||
3523 | |||
3524 | /** | ||
3525 | * snd_hda_is_supported_format - Check the validity of the format | ||
3526 | * @codec: HD-audio codec | ||
3527 | * @nid: NID to check | ||
3528 | * @format: the HD-audio format value to check | ||
3529 | * | ||
3530 | * Check whether the given node supports the format value. | ||
3531 | * | ||
3532 | * Returns 1 if supported, 0 if not. | ||
3533 | */ | ||
3534 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | ||
3535 | unsigned int format) | ||
3536 | { | ||
3537 | int i; | ||
3538 | unsigned int val = 0, rate, stream; | ||
3539 | |||
3540 | val = query_pcm_param(codec, nid); | ||
3541 | if (!val) | ||
3542 | return 0; | ||
3543 | |||
3544 | rate = format & 0xff00; | ||
3545 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) | ||
3546 | if (rate_bits[i].hda_fmt == rate) { | ||
3547 | if (val & (1 << i)) | ||
3548 | break; | ||
3549 | return 0; | ||
3550 | } | ||
3551 | if (i >= AC_PAR_PCM_RATE_BITS) | ||
3552 | return 0; | ||
3553 | |||
3554 | stream = query_stream_param(codec, nid); | ||
3555 | if (!stream) | ||
3556 | return 0; | ||
3557 | |||
3558 | if (stream & AC_SUPFMT_PCM) { | ||
3559 | switch (format & 0xf0) { | ||
3560 | case 0x00: | ||
3561 | if (!(val & AC_SUPPCM_BITS_8)) | ||
3562 | return 0; | ||
3563 | break; | ||
3564 | case 0x10: | ||
3565 | if (!(val & AC_SUPPCM_BITS_16)) | ||
3566 | return 0; | ||
3567 | break; | ||
3568 | case 0x20: | ||
3569 | if (!(val & AC_SUPPCM_BITS_20)) | ||
3570 | return 0; | ||
3571 | break; | ||
3572 | case 0x30: | ||
3573 | if (!(val & AC_SUPPCM_BITS_24)) | ||
3574 | return 0; | ||
3575 | break; | ||
3576 | case 0x40: | ||
3577 | if (!(val & AC_SUPPCM_BITS_32)) | ||
3578 | return 0; | ||
3579 | break; | ||
3580 | default: | ||
3581 | return 0; | ||
3582 | } | ||
3583 | } else { | ||
3584 | /* FIXME: check for float32 and AC3? */ | ||
3585 | } | ||
3586 | |||
3587 | return 1; | ||
3588 | } | ||
3589 | EXPORT_SYMBOL_GPL(snd_hda_is_supported_format); | ||
3590 | |||
3591 | /* | ||
3592 | * PCM stuff | 3229 | * PCM stuff |
3593 | */ | 3230 | */ |
3594 | static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo, | 3231 | static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo, |
@@ -3800,9 +3437,6 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
3800 | struct hda_pcm *cpcm; | 3437 | struct hda_pcm *cpcm; |
3801 | int dev, err; | 3438 | int dev, err; |
3802 | 3439 | ||
3803 | if (snd_BUG_ON(!bus->ops.attach_pcm)) | ||
3804 | return -EINVAL; | ||
3805 | |||
3806 | err = snd_hda_codec_parse_pcms(codec); | 3440 | err = snd_hda_codec_parse_pcms(codec); |
3807 | if (err < 0) { | 3441 | if (err < 0) { |
3808 | snd_hda_codec_reset(codec); | 3442 | snd_hda_codec_reset(codec); |
@@ -3820,7 +3454,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
3820 | if (dev < 0) | 3454 | if (dev < 0) |
3821 | continue; /* no fatal error */ | 3455 | continue; /* no fatal error */ |
3822 | cpcm->device = dev; | 3456 | cpcm->device = dev; |
3823 | err = bus->ops.attach_pcm(bus, codec, cpcm); | 3457 | err = snd_hda_attach_pcm_stream(bus, codec, cpcm); |
3824 | if (err < 0) { | 3458 | if (err < 0) { |
3825 | codec_err(codec, | 3459 | codec_err(codec, |
3826 | "cannot attach PCM stream %d for codec #%d\n", | 3460 | "cannot attach PCM stream %d for codec #%d\n", |
@@ -3887,6 +3521,9 @@ static void codec_set_power_save(struct hda_codec *codec, int delay) | |||
3887 | { | 3521 | { |
3888 | struct device *dev = hda_codec_dev(codec); | 3522 | struct device *dev = hda_codec_dev(codec); |
3889 | 3523 | ||
3524 | if (delay == 0 && codec->auto_runtime_pm) | ||
3525 | delay = 3000; | ||
3526 | |||
3890 | if (delay > 0) { | 3527 | if (delay > 0) { |
3891 | pm_runtime_set_autosuspend_delay(dev, delay); | 3528 | pm_runtime_set_autosuspend_delay(dev, delay); |
3892 | pm_runtime_use_autosuspend(dev); | 3529 | pm_runtime_use_autosuspend(dev); |
@@ -4490,10 +4127,10 @@ int snd_hda_add_imux_item(struct hda_codec *codec, | |||
4490 | EXPORT_SYMBOL_GPL(snd_hda_add_imux_item); | 4127 | EXPORT_SYMBOL_GPL(snd_hda_add_imux_item); |
4491 | 4128 | ||
4492 | /** | 4129 | /** |
4493 | * snd_hda_bus_reset - Reset the bus | 4130 | * snd_hda_bus_reset_codecs - Reset the bus |
4494 | * @bus: HD-audio bus | 4131 | * @bus: HD-audio bus |
4495 | */ | 4132 | */ |
4496 | void snd_hda_bus_reset(struct hda_bus *bus) | 4133 | void snd_hda_bus_reset_codecs(struct hda_bus *bus) |
4497 | { | 4134 | { |
4498 | struct hda_codec *codec; | 4135 | struct hda_codec *codec; |
4499 | 4136 | ||
@@ -4508,7 +4145,6 @@ void snd_hda_bus_reset(struct hda_bus *bus) | |||
4508 | #endif | 4145 | #endif |
4509 | } | 4146 | } |
4510 | } | 4147 | } |
4511 | EXPORT_SYMBOL_GPL(snd_hda_bus_reset); | ||
4512 | 4148 | ||
4513 | /** | 4149 | /** |
4514 | * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer | 4150 | * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 9075ac28dc4b..12837abbbbe5 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -40,32 +40,6 @@ struct hda_codec; | |||
40 | struct hda_pcm; | 40 | struct hda_pcm; |
41 | struct hda_pcm_stream; | 41 | struct hda_pcm_stream; |
42 | 42 | ||
43 | /* bus operators */ | ||
44 | struct hda_bus_ops { | ||
45 | /* send a single command */ | ||
46 | int (*command)(struct hda_bus *bus, unsigned int cmd); | ||
47 | /* get a response from the last command */ | ||
48 | unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr); | ||
49 | /* free the private data */ | ||
50 | void (*private_free)(struct hda_bus *); | ||
51 | /* attach a PCM stream */ | ||
52 | int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, | ||
53 | struct hda_pcm *pcm); | ||
54 | /* reset bus for retry verb */ | ||
55 | void (*bus_reset)(struct hda_bus *bus); | ||
56 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
57 | /* prepare DSP transfer */ | ||
58 | int (*load_dsp_prepare)(struct hda_bus *bus, unsigned int format, | ||
59 | unsigned int byte_size, | ||
60 | struct snd_dma_buffer *bufp); | ||
61 | /* start/stop DSP transfer */ | ||
62 | void (*load_dsp_trigger)(struct hda_bus *bus, bool start); | ||
63 | /* clean up DSP transfer */ | ||
64 | void (*load_dsp_cleanup)(struct hda_bus *bus, | ||
65 | struct snd_dma_buffer *dmab); | ||
66 | #endif | ||
67 | }; | ||
68 | |||
69 | /* | 43 | /* |
70 | * codec bus | 44 | * codec bus |
71 | * | 45 | * |
@@ -77,10 +51,8 @@ struct hda_bus { | |||
77 | 51 | ||
78 | struct snd_card *card; | 52 | struct snd_card *card; |
79 | 53 | ||
80 | void *private_data; | ||
81 | struct pci_dev *pci; | 54 | struct pci_dev *pci; |
82 | const char *modelname; | 55 | const char *modelname; |
83 | struct hda_bus_ops ops; | ||
84 | 56 | ||
85 | struct mutex prepare_mutex; | 57 | struct mutex prepare_mutex; |
86 | 58 | ||
@@ -92,7 +64,6 @@ struct hda_bus { | |||
92 | unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ | 64 | unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ |
93 | /* status for codec/controller */ | 65 | /* status for codec/controller */ |
94 | unsigned int shutdown :1; /* being unloaded */ | 66 | unsigned int shutdown :1; /* being unloaded */ |
95 | unsigned int rirb_error:1; /* error in codec communication */ | ||
96 | unsigned int response_reset:1; /* controller was reset */ | 67 | unsigned int response_reset:1; /* controller was reset */ |
97 | unsigned int in_reset:1; /* during reset operation */ | 68 | unsigned int in_reset:1; /* during reset operation */ |
98 | unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ | 69 | unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ |
@@ -100,6 +71,9 @@ struct hda_bus { | |||
100 | int primary_dig_out_type; /* primary digital out PCM type */ | 71 | int primary_dig_out_type; /* primary digital out PCM type */ |
101 | }; | 72 | }; |
102 | 73 | ||
74 | /* from hdac_bus to hda_bus */ | ||
75 | #define to_hda_bus(bus) container_of(bus, struct hda_bus, core) | ||
76 | |||
103 | /* | 77 | /* |
104 | * codec preset | 78 | * codec preset |
105 | * | 79 | * |
@@ -108,11 +82,7 @@ struct hda_bus { | |||
108 | */ | 82 | */ |
109 | struct hda_codec_preset { | 83 | struct hda_codec_preset { |
110 | unsigned int id; | 84 | unsigned int id; |
111 | unsigned int mask; | ||
112 | unsigned int subs; | ||
113 | unsigned int subs_mask; | ||
114 | unsigned int rev; | 85 | unsigned int rev; |
115 | hda_nid_t afg, mfg; | ||
116 | const char *name; | 86 | const char *name; |
117 | int (*patch)(struct hda_codec *codec); | 87 | int (*patch)(struct hda_codec *codec); |
118 | }; | 88 | }; |
@@ -281,6 +251,7 @@ struct hda_codec { | |||
281 | unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */ | 251 | unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */ |
282 | unsigned int dump_coef:1; /* dump processing coefs in codec proc file */ | 252 | unsigned int dump_coef:1; /* dump processing coefs in codec proc file */ |
283 | unsigned int power_save_node:1; /* advanced PM for each widget */ | 253 | unsigned int power_save_node:1; /* advanced PM for each widget */ |
254 | unsigned int auto_runtime_pm:1; /* enable automatic codec runtime pm */ | ||
284 | #ifdef CONFIG_PM | 255 | #ifdef CONFIG_PM |
285 | unsigned long power_on_acct; | 256 | unsigned long power_on_acct; |
286 | unsigned long power_off_acct; | 257 | unsigned long power_off_acct; |
@@ -300,10 +271,8 @@ struct hda_codec { | |||
300 | unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */ | 271 | unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */ |
301 | struct delayed_work jackpoll_work; | 272 | struct delayed_work jackpoll_work; |
302 | 273 | ||
303 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
304 | /* jack detection */ | 274 | /* jack detection */ |
305 | struct snd_array jacks; | 275 | struct snd_array jacks; |
306 | #endif | ||
307 | 276 | ||
308 | int depop_delay; /* depop delay in ms, -1 for default delay time */ | 277 | int depop_delay; /* depop delay in ms, -1 for default delay time */ |
309 | 278 | ||
@@ -328,7 +297,10 @@ struct hda_codec { | |||
328 | /* | 297 | /* |
329 | * constructors | 298 | * constructors |
330 | */ | 299 | */ |
331 | int snd_hda_bus_new(struct snd_card *card, struct hda_bus **busp); | 300 | int snd_hda_bus_new(struct snd_card *card, |
301 | const struct hdac_bus_ops *ops, | ||
302 | const struct hdac_io_ops *io_ops, | ||
303 | struct hda_bus **busp); | ||
332 | int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, | 304 | int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, |
333 | unsigned int codec_addr, struct hda_codec **codecp); | 305 | unsigned int codec_addr, struct hda_codec **codecp); |
334 | int snd_hda_codec_configure(struct hda_codec *codec); | 306 | int snd_hda_codec_configure(struct hda_codec *codec); |
@@ -367,8 +339,6 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | |||
367 | hda_nid_t nid, int recursive); | 339 | hda_nid_t nid, int recursive); |
368 | int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, | 340 | int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, |
369 | u8 *dev_list, int max_devices); | 341 | u8 *dev_list, int max_devices); |
370 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | ||
371 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); | ||
372 | 342 | ||
373 | struct hda_verb { | 343 | struct hda_verb { |
374 | hda_nid_t nid; | 344 | hda_nid_t nid; |
@@ -460,17 +430,17 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
460 | int do_now); | 430 | int do_now); |
461 | #define snd_hda_codec_cleanup_stream(codec, nid) \ | 431 | #define snd_hda_codec_cleanup_stream(codec, nid) \ |
462 | __snd_hda_codec_cleanup_stream(codec, nid, 0) | 432 | __snd_hda_codec_cleanup_stream(codec, nid, 0) |
463 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, | 433 | |
464 | unsigned int rate, | 434 | #define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, bpsp) \ |
465 | unsigned int channels, | 435 | snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, bpsp) |
466 | unsigned int format, | 436 | #define snd_hda_is_supported_format(codec, nid, fmt) \ |
467 | unsigned int maxbps, | 437 | snd_hdac_is_supported_format(&(codec)->core, nid, fmt) |
468 | unsigned short spdif_ctls); | ||
469 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | ||
470 | unsigned int format); | ||
471 | 438 | ||
472 | extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[]; | 439 | extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[]; |
473 | 440 | ||
441 | int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, | ||
442 | struct hda_pcm *cpcm); | ||
443 | |||
474 | /* | 444 | /* |
475 | * Misc | 445 | * Misc |
476 | */ | 446 | */ |
@@ -481,6 +451,7 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | |||
481 | int snd_hda_lock_devices(struct hda_bus *bus); | 451 | int snd_hda_lock_devices(struct hda_bus *bus); |
482 | void snd_hda_unlock_devices(struct hda_bus *bus); | 452 | void snd_hda_unlock_devices(struct hda_bus *bus); |
483 | void snd_hda_bus_reset(struct hda_bus *bus); | 453 | void snd_hda_bus_reset(struct hda_bus *bus); |
454 | void snd_hda_bus_reset_codecs(struct hda_bus *bus); | ||
484 | 455 | ||
485 | /* | 456 | /* |
486 | * power management | 457 | * power management |
@@ -526,24 +497,12 @@ int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf); | |||
526 | #endif | 497 | #endif |
527 | 498 | ||
528 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 499 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
529 | static inline int | 500 | int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, |
530 | snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, | 501 | unsigned int size, |
531 | unsigned int size, | 502 | struct snd_dma_buffer *bufp); |
532 | struct snd_dma_buffer *bufp) | 503 | void snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start); |
533 | { | 504 | void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, |
534 | return codec->bus->ops.load_dsp_prepare(codec->bus, format, size, bufp); | 505 | struct snd_dma_buffer *dmab); |
535 | } | ||
536 | static inline void | ||
537 | snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) | ||
538 | { | ||
539 | return codec->bus->ops.load_dsp_trigger(codec->bus, start); | ||
540 | } | ||
541 | static inline void | ||
542 | snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, | ||
543 | struct snd_dma_buffer *dmab) | ||
544 | { | ||
545 | return codec->bus->ops.load_dsp_cleanup(codec->bus, dmab); | ||
546 | } | ||
547 | #else | 506 | #else |
548 | static inline int | 507 | static inline int |
549 | snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, | 508 | snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 26ce990592a0..944455997fdc 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -32,229 +32,29 @@ | |||
32 | #include "hda_controller.h" | 32 | #include "hda_controller.h" |
33 | 33 | ||
34 | #define CREATE_TRACE_POINTS | 34 | #define CREATE_TRACE_POINTS |
35 | #include "hda_intel_trace.h" | 35 | #include "hda_controller_trace.h" |
36 | 36 | ||
37 | /* DSP lock helpers */ | 37 | /* DSP lock helpers */ |
38 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 38 | #define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev)) |
39 | #define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) | 39 | #define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev)) |
40 | #define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) | 40 | #define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev)) |
41 | #define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) | ||
42 | #define dsp_is_locked(dev) ((dev)->locked) | ||
43 | #else | ||
44 | #define dsp_lock_init(dev) do {} while (0) | ||
45 | #define dsp_lock(dev) do {} while (0) | ||
46 | #define dsp_unlock(dev) do {} while (0) | ||
47 | #define dsp_is_locked(dev) 0 | ||
48 | #endif | ||
49 | |||
50 | /* | ||
51 | * AZX stream operations. | ||
52 | */ | ||
53 | |||
54 | /* start a stream */ | ||
55 | static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | ||
56 | { | ||
57 | /* | ||
58 | * Before stream start, initialize parameter | ||
59 | */ | ||
60 | azx_dev->insufficient = 1; | ||
61 | |||
62 | /* enable SIE */ | ||
63 | azx_writel(chip, INTCTL, | ||
64 | azx_readl(chip, INTCTL) | (1 << azx_dev->index)); | ||
65 | /* set DMA start and interrupt mask */ | ||
66 | azx_sd_writeb(chip, azx_dev, SD_CTL, | ||
67 | azx_sd_readb(chip, azx_dev, SD_CTL) | | ||
68 | SD_CTL_DMA_START | SD_INT_MASK); | ||
69 | } | ||
70 | |||
71 | /* stop DMA */ | ||
72 | static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) | ||
73 | { | ||
74 | azx_sd_writeb(chip, azx_dev, SD_CTL, | ||
75 | azx_sd_readb(chip, azx_dev, SD_CTL) & | ||
76 | ~(SD_CTL_DMA_START | SD_INT_MASK)); | ||
77 | azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | ||
78 | } | ||
79 | |||
80 | /* stop a stream */ | ||
81 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | ||
82 | { | ||
83 | azx_stream_clear(chip, azx_dev); | ||
84 | /* disable SIE */ | ||
85 | azx_writel(chip, INTCTL, | ||
86 | azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); | ||
87 | } | ||
88 | EXPORT_SYMBOL_GPL(azx_stream_stop); | ||
89 | |||
90 | /* reset stream */ | ||
91 | static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) | ||
92 | { | ||
93 | unsigned char val; | ||
94 | int timeout; | ||
95 | |||
96 | azx_stream_clear(chip, azx_dev); | ||
97 | |||
98 | azx_sd_writeb(chip, azx_dev, SD_CTL, | ||
99 | azx_sd_readb(chip, azx_dev, SD_CTL) | | ||
100 | SD_CTL_STREAM_RESET); | ||
101 | udelay(3); | ||
102 | timeout = 300; | ||
103 | while (!((val = azx_sd_readb(chip, azx_dev, SD_CTL)) & | ||
104 | SD_CTL_STREAM_RESET) && --timeout) | ||
105 | ; | ||
106 | val &= ~SD_CTL_STREAM_RESET; | ||
107 | azx_sd_writeb(chip, azx_dev, SD_CTL, val); | ||
108 | udelay(3); | ||
109 | |||
110 | timeout = 300; | ||
111 | /* waiting for hardware to report that the stream is out of reset */ | ||
112 | while (((val = azx_sd_readb(chip, azx_dev, SD_CTL)) & | ||
113 | SD_CTL_STREAM_RESET) && --timeout) | ||
114 | ; | ||
115 | |||
116 | /* reset first position - may not be synced with hw at this time */ | ||
117 | *azx_dev->posbuf = 0; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * set up the SD for streaming | ||
122 | */ | ||
123 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | ||
124 | { | ||
125 | unsigned int val; | ||
126 | /* make sure the run bit is zero for SD */ | ||
127 | azx_stream_clear(chip, azx_dev); | ||
128 | /* program the stream_tag */ | ||
129 | val = azx_sd_readl(chip, azx_dev, SD_CTL); | ||
130 | val = (val & ~SD_CTL_STREAM_TAG_MASK) | | ||
131 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); | ||
132 | if (!azx_snoop(chip)) | ||
133 | val |= SD_CTL_TRAFFIC_PRIO; | ||
134 | azx_sd_writel(chip, azx_dev, SD_CTL, val); | ||
135 | |||
136 | /* program the length of samples in cyclic buffer */ | ||
137 | azx_sd_writel(chip, azx_dev, SD_CBL, azx_dev->bufsize); | ||
138 | |||
139 | /* program the stream format */ | ||
140 | /* this value needs to be the same as the one programmed */ | ||
141 | azx_sd_writew(chip, azx_dev, SD_FORMAT, azx_dev->format_val); | ||
142 | |||
143 | /* program the stream LVI (last valid index) of the BDL */ | ||
144 | azx_sd_writew(chip, azx_dev, SD_LVI, azx_dev->frags - 1); | ||
145 | |||
146 | /* program the BDL address */ | ||
147 | /* lower BDL address */ | ||
148 | azx_sd_writel(chip, azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); | ||
149 | /* upper BDL address */ | ||
150 | azx_sd_writel(chip, azx_dev, SD_BDLPU, | ||
151 | upper_32_bits(azx_dev->bdl.addr)); | ||
152 | |||
153 | /* enable the position buffer */ | ||
154 | if (chip->get_position[0] != azx_get_pos_lpib || | ||
155 | chip->get_position[1] != azx_get_pos_lpib) { | ||
156 | if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE)) | ||
157 | azx_writel(chip, DPLBASE, | ||
158 | (u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE); | ||
159 | } | ||
160 | |||
161 | /* set the interrupt enable bits in the descriptor control register */ | ||
162 | azx_sd_writel(chip, azx_dev, SD_CTL, | ||
163 | azx_sd_readl(chip, azx_dev, SD_CTL) | SD_INT_MASK); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | 41 | ||
168 | /* assign a stream for the PCM */ | 42 | /* assign a stream for the PCM */ |
169 | static inline struct azx_dev * | 43 | static inline struct azx_dev * |
170 | azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) | 44 | azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) |
171 | { | 45 | { |
172 | int dev, i, nums; | 46 | struct hdac_stream *s; |
173 | struct azx_dev *res = NULL; | 47 | |
174 | /* make a non-zero unique key for the substream */ | 48 | s = snd_hdac_stream_assign(azx_bus(chip), substream); |
175 | int key = (substream->pcm->device << 16) | (substream->number << 2) | | 49 | if (!s) |
176 | (substream->stream + 1); | 50 | return NULL; |
177 | 51 | return stream_to_azx_dev(s); | |
178 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
179 | dev = chip->playback_index_offset; | ||
180 | nums = chip->playback_streams; | ||
181 | } else { | ||
182 | dev = chip->capture_index_offset; | ||
183 | nums = chip->capture_streams; | ||
184 | } | ||
185 | for (i = 0; i < nums; i++, dev++) { | ||
186 | struct azx_dev *azx_dev = &chip->azx_dev[dev]; | ||
187 | dsp_lock(azx_dev); | ||
188 | if (!azx_dev->opened && !dsp_is_locked(azx_dev)) { | ||
189 | if (azx_dev->assigned_key == key) { | ||
190 | azx_dev->opened = 1; | ||
191 | azx_dev->assigned_key = key; | ||
192 | dsp_unlock(azx_dev); | ||
193 | return azx_dev; | ||
194 | } | ||
195 | if (!res || | ||
196 | (chip->driver_caps & AZX_DCAPS_REVERSE_ASSIGN)) | ||
197 | res = azx_dev; | ||
198 | } | ||
199 | dsp_unlock(azx_dev); | ||
200 | } | ||
201 | if (res) { | ||
202 | dsp_lock(res); | ||
203 | res->opened = 1; | ||
204 | res->assigned_key = key; | ||
205 | dsp_unlock(res); | ||
206 | } | ||
207 | return res; | ||
208 | } | 52 | } |
209 | 53 | ||
210 | /* release the assigned stream */ | 54 | /* release the assigned stream */ |
211 | static inline void azx_release_device(struct azx_dev *azx_dev) | 55 | static inline void azx_release_device(struct azx_dev *azx_dev) |
212 | { | 56 | { |
213 | azx_dev->opened = 0; | 57 | snd_hdac_stream_release(azx_stream(azx_dev)); |
214 | } | ||
215 | |||
216 | static cycle_t azx_cc_read(const struct cyclecounter *cc) | ||
217 | { | ||
218 | struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc); | ||
219 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
220 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
221 | struct azx *chip = apcm->chip; | ||
222 | |||
223 | return azx_readl(chip, WALLCLK); | ||
224 | } | ||
225 | |||
226 | static void azx_timecounter_init(struct snd_pcm_substream *substream, | ||
227 | bool force, cycle_t last) | ||
228 | { | ||
229 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
230 | struct timecounter *tc = &azx_dev->azx_tc; | ||
231 | struct cyclecounter *cc = &azx_dev->azx_cc; | ||
232 | u64 nsec; | ||
233 | |||
234 | cc->read = azx_cc_read; | ||
235 | cc->mask = CLOCKSOURCE_MASK(32); | ||
236 | |||
237 | /* | ||
238 | * Converting from 24 MHz to ns means applying a 125/3 factor. | ||
239 | * To avoid any saturation issues in intermediate operations, | ||
240 | * the 125 factor is applied first. The division is applied | ||
241 | * last after reading the timecounter value. | ||
242 | * Applying the 1/3 factor as part of the multiplication | ||
243 | * requires at least 20 bits for a decent precision, however | ||
244 | * overflows occur after about 4 hours or less, not a option. | ||
245 | */ | ||
246 | |||
247 | cc->mult = 125; /* saturation after 195 years */ | ||
248 | cc->shift = 0; | ||
249 | |||
250 | nsec = 0; /* audio time is elapsed time since trigger */ | ||
251 | timecounter_init(tc, cc, nsec); | ||
252 | if (force) | ||
253 | /* | ||
254 | * force timecounter to use predefined value, | ||
255 | * used for synchronized starts | ||
256 | */ | ||
257 | tc->cycle_last = last; | ||
258 | } | 58 | } |
259 | 59 | ||
260 | static inline struct hda_pcm_stream * | 60 | static inline struct hda_pcm_stream * |
@@ -285,119 +85,6 @@ static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, | |||
285 | } | 85 | } |
286 | 86 | ||
287 | /* | 87 | /* |
288 | * set up a BDL entry | ||
289 | */ | ||
290 | static int setup_bdle(struct azx *chip, | ||
291 | struct snd_dma_buffer *dmab, | ||
292 | struct azx_dev *azx_dev, u32 **bdlp, | ||
293 | int ofs, int size, int with_ioc) | ||
294 | { | ||
295 | u32 *bdl = *bdlp; | ||
296 | |||
297 | while (size > 0) { | ||
298 | dma_addr_t addr; | ||
299 | int chunk; | ||
300 | |||
301 | if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) | ||
302 | return -EINVAL; | ||
303 | |||
304 | addr = snd_sgbuf_get_addr(dmab, ofs); | ||
305 | /* program the address field of the BDL entry */ | ||
306 | bdl[0] = cpu_to_le32((u32)addr); | ||
307 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | ||
308 | /* program the size field of the BDL entry */ | ||
309 | chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); | ||
310 | /* one BDLE cannot cross 4K boundary on CTHDA chips */ | ||
311 | if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { | ||
312 | u32 remain = 0x1000 - (ofs & 0xfff); | ||
313 | if (chunk > remain) | ||
314 | chunk = remain; | ||
315 | } | ||
316 | bdl[2] = cpu_to_le32(chunk); | ||
317 | /* program the IOC to enable interrupt | ||
318 | * only when the whole fragment is processed | ||
319 | */ | ||
320 | size -= chunk; | ||
321 | bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); | ||
322 | bdl += 4; | ||
323 | azx_dev->frags++; | ||
324 | ofs += chunk; | ||
325 | } | ||
326 | *bdlp = bdl; | ||
327 | return ofs; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * set up BDL entries | ||
332 | */ | ||
333 | static int azx_setup_periods(struct azx *chip, | ||
334 | struct snd_pcm_substream *substream, | ||
335 | struct azx_dev *azx_dev) | ||
336 | { | ||
337 | u32 *bdl; | ||
338 | int i, ofs, periods, period_bytes; | ||
339 | int pos_adj = 0; | ||
340 | |||
341 | /* reset BDL address */ | ||
342 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | ||
343 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
344 | |||
345 | period_bytes = azx_dev->period_bytes; | ||
346 | periods = azx_dev->bufsize / period_bytes; | ||
347 | |||
348 | /* program the initial BDL entries */ | ||
349 | bdl = (u32 *)azx_dev->bdl.area; | ||
350 | ofs = 0; | ||
351 | azx_dev->frags = 0; | ||
352 | |||
353 | if (chip->bdl_pos_adj) | ||
354 | pos_adj = chip->bdl_pos_adj[chip->dev_index]; | ||
355 | if (!azx_dev->no_period_wakeup && pos_adj > 0) { | ||
356 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
357 | int pos_align = pos_adj; | ||
358 | pos_adj = (pos_adj * runtime->rate + 47999) / 48000; | ||
359 | if (!pos_adj) | ||
360 | pos_adj = pos_align; | ||
361 | else | ||
362 | pos_adj = ((pos_adj + pos_align - 1) / pos_align) * | ||
363 | pos_align; | ||
364 | pos_adj = frames_to_bytes(runtime, pos_adj); | ||
365 | if (pos_adj >= period_bytes) { | ||
366 | dev_warn(chip->card->dev,"Too big adjustment %d\n", | ||
367 | pos_adj); | ||
368 | pos_adj = 0; | ||
369 | } else { | ||
370 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), | ||
371 | azx_dev, | ||
372 | &bdl, ofs, pos_adj, true); | ||
373 | if (ofs < 0) | ||
374 | goto error; | ||
375 | } | ||
376 | } else | ||
377 | pos_adj = 0; | ||
378 | |||
379 | for (i = 0; i < periods; i++) { | ||
380 | if (i == periods - 1 && pos_adj) | ||
381 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), | ||
382 | azx_dev, &bdl, ofs, | ||
383 | period_bytes - pos_adj, 0); | ||
384 | else | ||
385 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), | ||
386 | azx_dev, &bdl, ofs, | ||
387 | period_bytes, | ||
388 | !azx_dev->no_period_wakeup); | ||
389 | if (ofs < 0) | ||
390 | goto error; | ||
391 | } | ||
392 | return 0; | ||
393 | |||
394 | error: | ||
395 | dev_err(chip->card->dev, "Too many BDL entries: buffer=%d, period=%d\n", | ||
396 | azx_dev->bufsize, period_bytes); | ||
397 | return -EINVAL; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * PCM ops | 88 | * PCM ops |
402 | */ | 89 | */ |
403 | 90 | ||
@@ -407,13 +94,9 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
407 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); | 94 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
408 | struct azx *chip = apcm->chip; | 95 | struct azx *chip = apcm->chip; |
409 | struct azx_dev *azx_dev = get_azx_dev(substream); | 96 | struct azx_dev *azx_dev = get_azx_dev(substream); |
410 | unsigned long flags; | ||
411 | 97 | ||
98 | trace_azx_pcm_close(chip, azx_dev); | ||
412 | mutex_lock(&chip->open_mutex); | 99 | mutex_lock(&chip->open_mutex); |
413 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
414 | azx_dev->substream = NULL; | ||
415 | azx_dev->running = 0; | ||
416 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
417 | azx_release_device(azx_dev); | 100 | azx_release_device(azx_dev); |
418 | if (hinfo->ops.close) | 101 | if (hinfo->ops.close) |
419 | hinfo->ops.close(hinfo, apcm->codec, substream); | 102 | hinfo->ops.close(hinfo, apcm->codec, substream); |
@@ -428,18 +111,23 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
428 | { | 111 | { |
429 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 112 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
430 | struct azx *chip = apcm->chip; | 113 | struct azx *chip = apcm->chip; |
114 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
431 | int ret; | 115 | int ret; |
432 | 116 | ||
433 | dsp_lock(get_azx_dev(substream)); | 117 | trace_azx_pcm_hw_params(chip, azx_dev); |
434 | if (dsp_is_locked(get_azx_dev(substream))) { | 118 | dsp_lock(azx_dev); |
119 | if (dsp_is_locked(azx_dev)) { | ||
435 | ret = -EBUSY; | 120 | ret = -EBUSY; |
436 | goto unlock; | 121 | goto unlock; |
437 | } | 122 | } |
438 | 123 | ||
124 | azx_dev->core.bufsize = 0; | ||
125 | azx_dev->core.period_bytes = 0; | ||
126 | azx_dev->core.format_val = 0; | ||
439 | ret = chip->ops->substream_alloc_pages(chip, substream, | 127 | ret = chip->ops->substream_alloc_pages(chip, substream, |
440 | params_buffer_bytes(hw_params)); | 128 | params_buffer_bytes(hw_params)); |
441 | unlock: | 129 | unlock: |
442 | dsp_unlock(get_azx_dev(substream)); | 130 | dsp_unlock(azx_dev); |
443 | return ret; | 131 | return ret; |
444 | } | 132 | } |
445 | 133 | ||
@@ -453,19 +141,13 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
453 | 141 | ||
454 | /* reset BDL address */ | 142 | /* reset BDL address */ |
455 | dsp_lock(azx_dev); | 143 | dsp_lock(azx_dev); |
456 | if (!dsp_is_locked(azx_dev)) { | 144 | if (!dsp_is_locked(azx_dev)) |
457 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | 145 | snd_hdac_stream_cleanup(azx_stream(azx_dev)); |
458 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
459 | azx_sd_writel(chip, azx_dev, SD_CTL, 0); | ||
460 | azx_dev->bufsize = 0; | ||
461 | azx_dev->period_bytes = 0; | ||
462 | azx_dev->format_val = 0; | ||
463 | } | ||
464 | 146 | ||
465 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); | 147 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
466 | 148 | ||
467 | err = chip->ops->substream_free_pages(chip, substream); | 149 | err = chip->ops->substream_free_pages(chip, substream); |
468 | azx_dev->prepared = 0; | 150 | azx_stream(azx_dev)->prepared = 0; |
469 | dsp_unlock(azx_dev); | 151 | dsp_unlock(azx_dev); |
470 | return err; | 152 | return err; |
471 | } | 153 | } |
@@ -477,21 +159,21 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
477 | struct azx_dev *azx_dev = get_azx_dev(substream); | 159 | struct azx_dev *azx_dev = get_azx_dev(substream); |
478 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); | 160 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
479 | struct snd_pcm_runtime *runtime = substream->runtime; | 161 | struct snd_pcm_runtime *runtime = substream->runtime; |
480 | unsigned int bufsize, period_bytes, format_val, stream_tag; | 162 | unsigned int format_val, stream_tag; |
481 | int err; | 163 | int err; |
482 | struct hda_spdif_out *spdif = | 164 | struct hda_spdif_out *spdif = |
483 | snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); | 165 | snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); |
484 | unsigned short ctls = spdif ? spdif->ctls : 0; | 166 | unsigned short ctls = spdif ? spdif->ctls : 0; |
485 | 167 | ||
168 | trace_azx_pcm_prepare(chip, azx_dev); | ||
486 | dsp_lock(azx_dev); | 169 | dsp_lock(azx_dev); |
487 | if (dsp_is_locked(azx_dev)) { | 170 | if (dsp_is_locked(azx_dev)) { |
488 | err = -EBUSY; | 171 | err = -EBUSY; |
489 | goto unlock; | 172 | goto unlock; |
490 | } | 173 | } |
491 | 174 | ||
492 | azx_stream_reset(chip, azx_dev); | 175 | snd_hdac_stream_reset(azx_stream(azx_dev)); |
493 | format_val = snd_hda_calc_stream_format(apcm->codec, | 176 | format_val = snd_hdac_calc_stream_format(runtime->rate, |
494 | runtime->rate, | ||
495 | runtime->channels, | 177 | runtime->channels, |
496 | runtime->format, | 178 | runtime->format, |
497 | hinfo->maxbps, | 179 | hinfo->maxbps, |
@@ -504,55 +186,23 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
504 | goto unlock; | 186 | goto unlock; |
505 | } | 187 | } |
506 | 188 | ||
507 | bufsize = snd_pcm_lib_buffer_bytes(substream); | 189 | err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val); |
508 | period_bytes = snd_pcm_lib_period_bytes(substream); | 190 | if (err < 0) |
509 | 191 | goto unlock; | |
510 | dev_dbg(chip->card->dev, "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", | ||
511 | bufsize, format_val); | ||
512 | |||
513 | if (bufsize != azx_dev->bufsize || | ||
514 | period_bytes != azx_dev->period_bytes || | ||
515 | format_val != azx_dev->format_val || | ||
516 | runtime->no_period_wakeup != azx_dev->no_period_wakeup) { | ||
517 | azx_dev->bufsize = bufsize; | ||
518 | azx_dev->period_bytes = period_bytes; | ||
519 | azx_dev->format_val = format_val; | ||
520 | azx_dev->no_period_wakeup = runtime->no_period_wakeup; | ||
521 | err = azx_setup_periods(chip, substream, azx_dev); | ||
522 | if (err < 0) | ||
523 | goto unlock; | ||
524 | } | ||
525 | 192 | ||
526 | /* when LPIB delay correction gives a small negative value, | 193 | snd_hdac_stream_setup(azx_stream(azx_dev)); |
527 | * we ignore it; currently set the threshold statically to | ||
528 | * 64 frames | ||
529 | */ | ||
530 | if (runtime->period_size > 64) | ||
531 | azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64); | ||
532 | else | ||
533 | azx_dev->delay_negative_threshold = 0; | ||
534 | |||
535 | /* wallclk has 24Mhz clock source */ | ||
536 | azx_dev->period_wallclk = (((runtime->period_size * 24000) / | ||
537 | runtime->rate) * 1000); | ||
538 | azx_setup_controller(chip, azx_dev); | ||
539 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
540 | azx_dev->fifo_size = | ||
541 | azx_sd_readw(chip, azx_dev, SD_FIFOSIZE) + 1; | ||
542 | else | ||
543 | azx_dev->fifo_size = 0; | ||
544 | 194 | ||
545 | stream_tag = azx_dev->stream_tag; | 195 | stream_tag = azx_dev->core.stream_tag; |
546 | /* CA-IBG chips need the playback stream starting from 1 */ | 196 | /* CA-IBG chips need the playback stream starting from 1 */ |
547 | if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && | 197 | if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && |
548 | stream_tag > chip->capture_streams) | 198 | stream_tag > chip->capture_streams) |
549 | stream_tag -= chip->capture_streams; | 199 | stream_tag -= chip->capture_streams; |
550 | err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, | 200 | err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, |
551 | azx_dev->format_val, substream); | 201 | azx_dev->core.format_val, substream); |
552 | 202 | ||
553 | unlock: | 203 | unlock: |
554 | if (!err) | 204 | if (!err) |
555 | azx_dev->prepared = 1; | 205 | azx_stream(azx_dev)->prepared = 1; |
556 | dsp_unlock(azx_dev); | 206 | dsp_unlock(azx_dev); |
557 | return err; | 207 | return err; |
558 | } | 208 | } |
@@ -561,28 +211,36 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
561 | { | 211 | { |
562 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 212 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
563 | struct azx *chip = apcm->chip; | 213 | struct azx *chip = apcm->chip; |
214 | struct hdac_bus *bus = azx_bus(chip); | ||
564 | struct azx_dev *azx_dev; | 215 | struct azx_dev *azx_dev; |
565 | struct snd_pcm_substream *s; | 216 | struct snd_pcm_substream *s; |
566 | int rstart = 0, start, nsync = 0, sbits = 0; | 217 | struct hdac_stream *hstr; |
567 | int nwait, timeout; | 218 | bool start; |
219 | int sbits = 0; | ||
220 | int sync_reg; | ||
568 | 221 | ||
569 | azx_dev = get_azx_dev(substream); | 222 | azx_dev = get_azx_dev(substream); |
570 | trace_azx_pcm_trigger(chip, azx_dev, cmd); | 223 | trace_azx_pcm_trigger(chip, azx_dev, cmd); |
571 | 224 | ||
572 | if (dsp_is_locked(azx_dev) || !azx_dev->prepared) | 225 | hstr = azx_stream(azx_dev); |
226 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) | ||
227 | sync_reg = AZX_REG_OLD_SSYNC; | ||
228 | else | ||
229 | sync_reg = AZX_REG_SSYNC; | ||
230 | |||
231 | if (dsp_is_locked(azx_dev) || !hstr->prepared) | ||
573 | return -EPIPE; | 232 | return -EPIPE; |
574 | 233 | ||
575 | switch (cmd) { | 234 | switch (cmd) { |
576 | case SNDRV_PCM_TRIGGER_START: | 235 | case SNDRV_PCM_TRIGGER_START: |
577 | rstart = 1; | ||
578 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 236 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
579 | case SNDRV_PCM_TRIGGER_RESUME: | 237 | case SNDRV_PCM_TRIGGER_RESUME: |
580 | start = 1; | 238 | start = true; |
581 | break; | 239 | break; |
582 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 240 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
583 | case SNDRV_PCM_TRIGGER_SUSPEND: | 241 | case SNDRV_PCM_TRIGGER_SUSPEND: |
584 | case SNDRV_PCM_TRIGGER_STOP: | 242 | case SNDRV_PCM_TRIGGER_STOP: |
585 | start = 0; | 243 | start = false; |
586 | break; | 244 | break; |
587 | default: | 245 | default: |
588 | return -EINVAL; | 246 | return -EINVAL; |
@@ -592,115 +250,55 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
592 | if (s->pcm->card != substream->pcm->card) | 250 | if (s->pcm->card != substream->pcm->card) |
593 | continue; | 251 | continue; |
594 | azx_dev = get_azx_dev(s); | 252 | azx_dev = get_azx_dev(s); |
595 | sbits |= 1 << azx_dev->index; | 253 | sbits |= 1 << azx_dev->core.index; |
596 | nsync++; | ||
597 | snd_pcm_trigger_done(s, substream); | 254 | snd_pcm_trigger_done(s, substream); |
598 | } | 255 | } |
599 | 256 | ||
600 | spin_lock(&chip->reg_lock); | 257 | spin_lock(&bus->reg_lock); |
601 | 258 | ||
602 | /* first, set SYNC bits of corresponding streams */ | 259 | /* first, set SYNC bits of corresponding streams */ |
603 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) | 260 | snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg); |
604 | azx_writel(chip, OLD_SSYNC, | ||
605 | azx_readl(chip, OLD_SSYNC) | sbits); | ||
606 | else | ||
607 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); | ||
608 | 261 | ||
609 | snd_pcm_group_for_each_entry(s, substream) { | 262 | snd_pcm_group_for_each_entry(s, substream) { |
610 | if (s->pcm->card != substream->pcm->card) | 263 | if (s->pcm->card != substream->pcm->card) |
611 | continue; | 264 | continue; |
612 | azx_dev = get_azx_dev(s); | 265 | azx_dev = get_azx_dev(s); |
613 | if (start) { | 266 | if (start) { |
614 | azx_dev->start_wallclk = azx_readl(chip, WALLCLK); | 267 | azx_dev->insufficient = 1; |
615 | if (!rstart) | 268 | snd_hdac_stream_start(azx_stream(azx_dev), true); |
616 | azx_dev->start_wallclk -= | ||
617 | azx_dev->period_wallclk; | ||
618 | azx_stream_start(chip, azx_dev); | ||
619 | } else { | 269 | } else { |
620 | azx_stream_stop(chip, azx_dev); | 270 | snd_hdac_stream_stop(azx_stream(azx_dev)); |
621 | } | ||
622 | azx_dev->running = start; | ||
623 | } | ||
624 | spin_unlock(&chip->reg_lock); | ||
625 | if (start) { | ||
626 | /* wait until all FIFOs get ready */ | ||
627 | for (timeout = 5000; timeout; timeout--) { | ||
628 | nwait = 0; | ||
629 | snd_pcm_group_for_each_entry(s, substream) { | ||
630 | if (s->pcm->card != substream->pcm->card) | ||
631 | continue; | ||
632 | azx_dev = get_azx_dev(s); | ||
633 | if (!(azx_sd_readb(chip, azx_dev, SD_STS) & | ||
634 | SD_STS_FIFO_READY)) | ||
635 | nwait++; | ||
636 | } | ||
637 | if (!nwait) | ||
638 | break; | ||
639 | cpu_relax(); | ||
640 | } | ||
641 | } else { | ||
642 | /* wait until all RUN bits are cleared */ | ||
643 | for (timeout = 5000; timeout; timeout--) { | ||
644 | nwait = 0; | ||
645 | snd_pcm_group_for_each_entry(s, substream) { | ||
646 | if (s->pcm->card != substream->pcm->card) | ||
647 | continue; | ||
648 | azx_dev = get_azx_dev(s); | ||
649 | if (azx_sd_readb(chip, azx_dev, SD_CTL) & | ||
650 | SD_CTL_DMA_START) | ||
651 | nwait++; | ||
652 | } | ||
653 | if (!nwait) | ||
654 | break; | ||
655 | cpu_relax(); | ||
656 | } | 271 | } |
657 | } | 272 | } |
658 | spin_lock(&chip->reg_lock); | 273 | spin_unlock(&bus->reg_lock); |
274 | |||
275 | snd_hdac_stream_sync(hstr, start, sbits); | ||
276 | |||
277 | spin_lock(&bus->reg_lock); | ||
659 | /* reset SYNC bits */ | 278 | /* reset SYNC bits */ |
660 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) | 279 | snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg); |
661 | azx_writel(chip, OLD_SSYNC, | 280 | if (start) |
662 | azx_readl(chip, OLD_SSYNC) & ~sbits); | 281 | snd_hdac_stream_timecounter_init(hstr, sbits); |
663 | else | 282 | spin_unlock(&bus->reg_lock); |
664 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); | ||
665 | if (start) { | ||
666 | azx_timecounter_init(substream, 0, 0); | ||
667 | snd_pcm_gettime(substream->runtime, &substream->runtime->trigger_tstamp); | ||
668 | substream->runtime->trigger_tstamp_latched = true; | ||
669 | |||
670 | if (nsync > 1) { | ||
671 | cycle_t cycle_last; | ||
672 | |||
673 | /* same start cycle for master and group */ | ||
674 | azx_dev = get_azx_dev(substream); | ||
675 | cycle_last = azx_dev->azx_tc.cycle_last; | ||
676 | |||
677 | snd_pcm_group_for_each_entry(s, substream) { | ||
678 | if (s->pcm->card != substream->pcm->card) | ||
679 | continue; | ||
680 | azx_timecounter_init(s, 1, cycle_last); | ||
681 | } | ||
682 | } | ||
683 | } | ||
684 | spin_unlock(&chip->reg_lock); | ||
685 | return 0; | 283 | return 0; |
686 | } | 284 | } |
687 | 285 | ||
688 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) | 286 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) |
689 | { | 287 | { |
690 | return azx_sd_readl(chip, azx_dev, SD_LPIB); | 288 | return snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev)); |
691 | } | 289 | } |
692 | EXPORT_SYMBOL_GPL(azx_get_pos_lpib); | 290 | EXPORT_SYMBOL_GPL(azx_get_pos_lpib); |
693 | 291 | ||
694 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) | 292 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) |
695 | { | 293 | { |
696 | return le32_to_cpu(*azx_dev->posbuf); | 294 | return snd_hdac_stream_get_pos_posbuf(azx_stream(azx_dev)); |
697 | } | 295 | } |
698 | EXPORT_SYMBOL_GPL(azx_get_pos_posbuf); | 296 | EXPORT_SYMBOL_GPL(azx_get_pos_posbuf); |
699 | 297 | ||
700 | unsigned int azx_get_position(struct azx *chip, | 298 | unsigned int azx_get_position(struct azx *chip, |
701 | struct azx_dev *azx_dev) | 299 | struct azx_dev *azx_dev) |
702 | { | 300 | { |
703 | struct snd_pcm_substream *substream = azx_dev->substream; | 301 | struct snd_pcm_substream *substream = azx_dev->core.substream; |
704 | unsigned int pos; | 302 | unsigned int pos; |
705 | int stream = substream->stream; | 303 | int stream = substream->stream; |
706 | int delay = 0; | 304 | int delay = 0; |
@@ -710,7 +308,7 @@ unsigned int azx_get_position(struct azx *chip, | |||
710 | else /* use the position buffer as default */ | 308 | else /* use the position buffer as default */ |
711 | pos = azx_get_pos_posbuf(chip, azx_dev); | 309 | pos = azx_get_pos_posbuf(chip, azx_dev); |
712 | 310 | ||
713 | if (pos >= azx_dev->bufsize) | 311 | if (pos >= azx_dev->core.bufsize) |
714 | pos = 0; | 312 | pos = 0; |
715 | 313 | ||
716 | if (substream->runtime) { | 314 | if (substream->runtime) { |
@@ -752,7 +350,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, | |||
752 | 350 | ||
753 | snd_pcm_gettime(substream->runtime, system_ts); | 351 | snd_pcm_gettime(substream->runtime, system_ts); |
754 | 352 | ||
755 | nsec = timecounter_read(&azx_dev->azx_tc); | 353 | nsec = timecounter_read(&azx_dev->core.tc); |
756 | nsec = div_u64(nsec, 3); /* can be optimized */ | 354 | nsec = div_u64(nsec, 3); /* can be optimized */ |
757 | if (audio_tstamp_config->report_delay) | 355 | if (audio_tstamp_config->report_delay) |
758 | nsec = azx_adjust_codec_delay(substream, nsec); | 356 | nsec = azx_adjust_codec_delay(substream, nsec); |
@@ -802,17 +400,18 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
802 | struct azx *chip = apcm->chip; | 400 | struct azx *chip = apcm->chip; |
803 | struct azx_dev *azx_dev; | 401 | struct azx_dev *azx_dev; |
804 | struct snd_pcm_runtime *runtime = substream->runtime; | 402 | struct snd_pcm_runtime *runtime = substream->runtime; |
805 | unsigned long flags; | ||
806 | int err; | 403 | int err; |
807 | int buff_step; | 404 | int buff_step; |
808 | 405 | ||
809 | snd_hda_codec_pcm_get(apcm->info); | 406 | snd_hda_codec_pcm_get(apcm->info); |
810 | mutex_lock(&chip->open_mutex); | 407 | mutex_lock(&chip->open_mutex); |
811 | azx_dev = azx_assign_device(chip, substream); | 408 | azx_dev = azx_assign_device(chip, substream); |
409 | trace_azx_pcm_open(chip, azx_dev); | ||
812 | if (azx_dev == NULL) { | 410 | if (azx_dev == NULL) { |
813 | err = -EBUSY; | 411 | err = -EBUSY; |
814 | goto unlock; | 412 | goto unlock; |
815 | } | 413 | } |
414 | runtime->private_data = azx_dev; | ||
816 | runtime->hw = azx_pcm_hw; | 415 | runtime->hw = azx_pcm_hw; |
817 | runtime->hw.channels_min = hinfo->channels_min; | 416 | runtime->hw.channels_min = hinfo->channels_min; |
818 | runtime->hw.channels_max = hinfo->channels_max; | 417 | runtime->hw.channels_max = hinfo->channels_max; |
@@ -874,12 +473,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
874 | runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; | 473 | runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; |
875 | } | 474 | } |
876 | 475 | ||
877 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
878 | azx_dev->substream = substream; | ||
879 | azx_dev->running = 0; | ||
880 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
881 | |||
882 | runtime->private_data = azx_dev; | ||
883 | snd_pcm_set_sync(substream); | 476 | snd_pcm_set_sync(substream); |
884 | mutex_unlock(&chip->open_mutex); | 477 | mutex_unlock(&chip->open_mutex); |
885 | return 0; | 478 | return 0; |
@@ -928,10 +521,11 @@ static void azx_pcm_free(struct snd_pcm *pcm) | |||
928 | 521 | ||
929 | #define MAX_PREALLOC_SIZE (32 * 1024 * 1024) | 522 | #define MAX_PREALLOC_SIZE (32 * 1024 * 1024) |
930 | 523 | ||
931 | static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | 524 | int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, |
932 | struct hda_pcm *cpcm) | 525 | struct hda_pcm *cpcm) |
933 | { | 526 | { |
934 | struct azx *chip = bus->private_data; | 527 | struct hdac_bus *bus = &_bus->core; |
528 | struct azx *chip = bus_to_azx(bus); | ||
935 | struct snd_pcm *pcm; | 529 | struct snd_pcm *pcm; |
936 | struct azx_pcm *apcm; | 530 | struct azx_pcm *apcm; |
937 | int pcm_dev = cpcm->device; | 531 | int pcm_dev = cpcm->device; |
@@ -979,89 +573,6 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
979 | return 0; | 573 | return 0; |
980 | } | 574 | } |
981 | 575 | ||
982 | /* | ||
983 | * CORB / RIRB interface | ||
984 | */ | ||
985 | static int azx_alloc_cmd_io(struct azx *chip) | ||
986 | { | ||
987 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ | ||
988 | return chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, | ||
989 | PAGE_SIZE, &chip->rb); | ||
990 | } | ||
991 | |||
992 | static void azx_init_cmd_io(struct azx *chip) | ||
993 | { | ||
994 | int timeout; | ||
995 | |||
996 | spin_lock_irq(&chip->reg_lock); | ||
997 | /* CORB set up */ | ||
998 | chip->corb.addr = chip->rb.addr; | ||
999 | chip->corb.buf = (u32 *)chip->rb.area; | ||
1000 | azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); | ||
1001 | azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr)); | ||
1002 | |||
1003 | /* set the corb size to 256 entries (ULI requires explicitly) */ | ||
1004 | azx_writeb(chip, CORBSIZE, 0x02); | ||
1005 | /* set the corb write pointer to 0 */ | ||
1006 | azx_writew(chip, CORBWP, 0); | ||
1007 | |||
1008 | /* reset the corb hw read pointer */ | ||
1009 | azx_writew(chip, CORBRP, AZX_CORBRP_RST); | ||
1010 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { | ||
1011 | for (timeout = 1000; timeout > 0; timeout--) { | ||
1012 | if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST) | ||
1013 | break; | ||
1014 | udelay(1); | ||
1015 | } | ||
1016 | if (timeout <= 0) | ||
1017 | dev_err(chip->card->dev, "CORB reset timeout#1, CORBRP = %d\n", | ||
1018 | azx_readw(chip, CORBRP)); | ||
1019 | |||
1020 | azx_writew(chip, CORBRP, 0); | ||
1021 | for (timeout = 1000; timeout > 0; timeout--) { | ||
1022 | if (azx_readw(chip, CORBRP) == 0) | ||
1023 | break; | ||
1024 | udelay(1); | ||
1025 | } | ||
1026 | if (timeout <= 0) | ||
1027 | dev_err(chip->card->dev, "CORB reset timeout#2, CORBRP = %d\n", | ||
1028 | azx_readw(chip, CORBRP)); | ||
1029 | } | ||
1030 | |||
1031 | /* enable corb dma */ | ||
1032 | azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN); | ||
1033 | |||
1034 | /* RIRB set up */ | ||
1035 | chip->rirb.addr = chip->rb.addr + 2048; | ||
1036 | chip->rirb.buf = (u32 *)(chip->rb.area + 2048); | ||
1037 | chip->rirb.wp = chip->rirb.rp = 0; | ||
1038 | memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); | ||
1039 | azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); | ||
1040 | azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); | ||
1041 | |||
1042 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | ||
1043 | azx_writeb(chip, RIRBSIZE, 0x02); | ||
1044 | /* reset the rirb hw write pointer */ | ||
1045 | azx_writew(chip, RIRBWP, AZX_RIRBWP_RST); | ||
1046 | /* set N=1, get RIRB response interrupt for new entry */ | ||
1047 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | ||
1048 | azx_writew(chip, RINTCNT, 0xc0); | ||
1049 | else | ||
1050 | azx_writew(chip, RINTCNT, 1); | ||
1051 | /* enable rirb dma and response irq */ | ||
1052 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); | ||
1053 | spin_unlock_irq(&chip->reg_lock); | ||
1054 | } | ||
1055 | |||
1056 | static void azx_free_cmd_io(struct azx *chip) | ||
1057 | { | ||
1058 | spin_lock_irq(&chip->reg_lock); | ||
1059 | /* disable ringbuffer DMAs */ | ||
1060 | azx_writeb(chip, RIRBCTL, 0); | ||
1061 | azx_writeb(chip, CORBCTL, 0); | ||
1062 | spin_unlock_irq(&chip->reg_lock); | ||
1063 | } | ||
1064 | |||
1065 | static unsigned int azx_command_addr(u32 cmd) | 576 | static unsigned int azx_command_addr(u32 cmd) |
1066 | { | 577 | { |
1067 | unsigned int addr = cmd >> 28; | 578 | unsigned int addr = cmd >> 28; |
@@ -1074,92 +585,12 @@ static unsigned int azx_command_addr(u32 cmd) | |||
1074 | return addr; | 585 | return addr; |
1075 | } | 586 | } |
1076 | 587 | ||
1077 | /* send a command */ | ||
1078 | static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | ||
1079 | { | ||
1080 | struct azx *chip = bus->private_data; | ||
1081 | unsigned int addr = azx_command_addr(val); | ||
1082 | unsigned int wp, rp; | ||
1083 | |||
1084 | spin_lock_irq(&chip->reg_lock); | ||
1085 | |||
1086 | /* add command to corb */ | ||
1087 | wp = azx_readw(chip, CORBWP); | ||
1088 | if (wp == 0xffff) { | ||
1089 | /* something wrong, controller likely turned to D3 */ | ||
1090 | spin_unlock_irq(&chip->reg_lock); | ||
1091 | return -EIO; | ||
1092 | } | ||
1093 | wp++; | ||
1094 | wp %= AZX_MAX_CORB_ENTRIES; | ||
1095 | |||
1096 | rp = azx_readw(chip, CORBRP); | ||
1097 | if (wp == rp) { | ||
1098 | /* oops, it's full */ | ||
1099 | spin_unlock_irq(&chip->reg_lock); | ||
1100 | return -EAGAIN; | ||
1101 | } | ||
1102 | |||
1103 | chip->rirb.cmds[addr]++; | ||
1104 | chip->corb.buf[wp] = cpu_to_le32(val); | ||
1105 | azx_writew(chip, CORBWP, wp); | ||
1106 | |||
1107 | spin_unlock_irq(&chip->reg_lock); | ||
1108 | |||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1112 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) | ||
1113 | |||
1114 | /* retrieve RIRB entry - called from interrupt handler */ | ||
1115 | static void azx_update_rirb(struct azx *chip) | ||
1116 | { | ||
1117 | unsigned int rp, wp; | ||
1118 | unsigned int addr; | ||
1119 | u32 res, res_ex; | ||
1120 | |||
1121 | wp = azx_readw(chip, RIRBWP); | ||
1122 | if (wp == 0xffff) { | ||
1123 | /* something wrong, controller likely turned to D3 */ | ||
1124 | return; | ||
1125 | } | ||
1126 | |||
1127 | if (wp == chip->rirb.wp) | ||
1128 | return; | ||
1129 | chip->rirb.wp = wp; | ||
1130 | |||
1131 | while (chip->rirb.rp != wp) { | ||
1132 | chip->rirb.rp++; | ||
1133 | chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES; | ||
1134 | |||
1135 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | ||
1136 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); | ||
1137 | res = le32_to_cpu(chip->rirb.buf[rp]); | ||
1138 | addr = res_ex & 0xf; | ||
1139 | if ((addr >= AZX_MAX_CODECS) || !(chip->codec_mask & (1 << addr))) { | ||
1140 | dev_err(chip->card->dev, "spurious response %#x:%#x, rp = %d, wp = %d", | ||
1141 | res, res_ex, | ||
1142 | chip->rirb.rp, wp); | ||
1143 | snd_BUG(); | ||
1144 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) | ||
1145 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); | ||
1146 | else if (chip->rirb.cmds[addr]) { | ||
1147 | chip->rirb.res[addr] = res; | ||
1148 | smp_wmb(); | ||
1149 | chip->rirb.cmds[addr]--; | ||
1150 | } else if (printk_ratelimit()) { | ||
1151 | dev_err(chip->card->dev, "spurious response %#x:%#x, last cmd=%#08x\n", | ||
1152 | res, res_ex, | ||
1153 | chip->last_cmd[addr]); | ||
1154 | } | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | /* receive a response */ | 588 | /* receive a response */ |
1159 | static unsigned int azx_rirb_get_response(struct hda_bus *bus, | 589 | static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, |
1160 | unsigned int addr) | 590 | unsigned int *res) |
1161 | { | 591 | { |
1162 | struct azx *chip = bus->private_data; | 592 | struct azx *chip = bus_to_azx(bus); |
593 | struct hda_bus *hbus = &chip->bus; | ||
1163 | unsigned long timeout; | 594 | unsigned long timeout; |
1164 | unsigned long loopcounter; | 595 | unsigned long loopcounter; |
1165 | int do_poll = 0; | 596 | int do_poll = 0; |
@@ -1168,22 +599,21 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1168 | timeout = jiffies + msecs_to_jiffies(1000); | 599 | timeout = jiffies + msecs_to_jiffies(1000); |
1169 | 600 | ||
1170 | for (loopcounter = 0;; loopcounter++) { | 601 | for (loopcounter = 0;; loopcounter++) { |
1171 | if (chip->polling_mode || do_poll) { | 602 | spin_lock_irq(&bus->reg_lock); |
1172 | spin_lock_irq(&chip->reg_lock); | 603 | if (chip->polling_mode || do_poll) |
1173 | azx_update_rirb(chip); | 604 | snd_hdac_bus_update_rirb(bus); |
1174 | spin_unlock_irq(&chip->reg_lock); | 605 | if (!bus->rirb.cmds[addr]) { |
1175 | } | ||
1176 | if (!chip->rirb.cmds[addr]) { | ||
1177 | smp_rmb(); | ||
1178 | bus->rirb_error = 0; | ||
1179 | |||
1180 | if (!do_poll) | 606 | if (!do_poll) |
1181 | chip->poll_count = 0; | 607 | chip->poll_count = 0; |
1182 | return chip->rirb.res[addr]; /* the last value */ | 608 | if (res) |
609 | *res = bus->rirb.res[addr]; /* the last value */ | ||
610 | spin_unlock_irq(&bus->reg_lock); | ||
611 | return 0; | ||
1183 | } | 612 | } |
613 | spin_unlock_irq(&bus->reg_lock); | ||
1184 | if (time_after(jiffies, timeout)) | 614 | if (time_after(jiffies, timeout)) |
1185 | break; | 615 | break; |
1186 | if (bus->needs_damn_long_delay || loopcounter > 3000) | 616 | if (hbus->needs_damn_long_delay || loopcounter > 3000) |
1187 | msleep(2); /* temporary workaround */ | 617 | msleep(2); /* temporary workaround */ |
1188 | else { | 618 | else { |
1189 | udelay(10); | 619 | udelay(10); |
@@ -1191,13 +621,13 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1191 | } | 621 | } |
1192 | } | 622 | } |
1193 | 623 | ||
1194 | if (bus->no_response_fallback) | 624 | if (hbus->no_response_fallback) |
1195 | return -1; | 625 | return -EIO; |
1196 | 626 | ||
1197 | if (!chip->polling_mode && chip->poll_count < 2) { | 627 | if (!chip->polling_mode && chip->poll_count < 2) { |
1198 | dev_dbg(chip->card->dev, | 628 | dev_dbg(chip->card->dev, |
1199 | "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", | 629 | "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", |
1200 | chip->last_cmd[addr]); | 630 | bus->last_cmd[addr]); |
1201 | do_poll = 1; | 631 | do_poll = 1; |
1202 | chip->poll_count++; | 632 | chip->poll_count++; |
1203 | goto again; | 633 | goto again; |
@@ -1207,7 +637,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1207 | if (!chip->polling_mode) { | 637 | if (!chip->polling_mode) { |
1208 | dev_warn(chip->card->dev, | 638 | dev_warn(chip->card->dev, |
1209 | "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", | 639 | "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", |
1210 | chip->last_cmd[addr]); | 640 | bus->last_cmd[addr]); |
1211 | chip->polling_mode = 1; | 641 | chip->polling_mode = 1; |
1212 | goto again; | 642 | goto again; |
1213 | } | 643 | } |
@@ -1215,12 +645,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1215 | if (chip->msi) { | 645 | if (chip->msi) { |
1216 | dev_warn(chip->card->dev, | 646 | dev_warn(chip->card->dev, |
1217 | "No response from codec, disabling MSI: last cmd=0x%08x\n", | 647 | "No response from codec, disabling MSI: last cmd=0x%08x\n", |
1218 | chip->last_cmd[addr]); | 648 | bus->last_cmd[addr]); |
1219 | if (chip->ops->disable_msi_reset_irq(chip) && | 649 | if (chip->ops->disable_msi_reset_irq && |
1220 | chip->ops->disable_msi_reset_irq(chip) < 0) { | 650 | chip->ops->disable_msi_reset_irq(chip) < 0) |
1221 | bus->rirb_error = 1; | 651 | return -EIO; |
1222 | return -1; | ||
1223 | } | ||
1224 | goto again; | 652 | goto again; |
1225 | } | 653 | } |
1226 | 654 | ||
@@ -1229,28 +657,24 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1229 | * phase, this is likely an access to a non-existing codec | 657 | * phase, this is likely an access to a non-existing codec |
1230 | * slot. Better to return an error and reset the system. | 658 | * slot. Better to return an error and reset the system. |
1231 | */ | 659 | */ |
1232 | return -1; | 660 | return -EIO; |
1233 | } | 661 | } |
1234 | 662 | ||
1235 | /* a fatal communication error; need either to reset or to fallback | 663 | /* a fatal communication error; need either to reset or to fallback |
1236 | * to the single_cmd mode | 664 | * to the single_cmd mode |
1237 | */ | 665 | */ |
1238 | bus->rirb_error = 1; | 666 | if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { |
1239 | if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { | 667 | hbus->response_reset = 1; |
1240 | bus->response_reset = 1; | 668 | return -EAGAIN; /* give a chance to retry */ |
1241 | return -1; /* give a chance to retry */ | ||
1242 | } | 669 | } |
1243 | 670 | ||
1244 | dev_err(chip->card->dev, | 671 | dev_err(chip->card->dev, |
1245 | "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", | 672 | "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", |
1246 | chip->last_cmd[addr]); | 673 | bus->last_cmd[addr]); |
1247 | chip->single_cmd = 1; | 674 | chip->single_cmd = 1; |
1248 | bus->response_reset = 0; | 675 | hbus->response_reset = 0; |
1249 | /* release CORB/RIRB */ | 676 | snd_hdac_bus_stop_cmd_io(bus); |
1250 | azx_free_cmd_io(chip); | 677 | return -EIO; |
1251 | /* disable unsolicited responses */ | ||
1252 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL); | ||
1253 | return -1; | ||
1254 | } | 678 | } |
1255 | 679 | ||
1256 | /* | 680 | /* |
@@ -1272,7 +696,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) | |||
1272 | /* check IRV busy bit */ | 696 | /* check IRV busy bit */ |
1273 | if (azx_readw(chip, IRS) & AZX_IRS_VALID) { | 697 | if (azx_readw(chip, IRS) & AZX_IRS_VALID) { |
1274 | /* reuse rirb.res as the response return value */ | 698 | /* reuse rirb.res as the response return value */ |
1275 | chip->rirb.res[addr] = azx_readl(chip, IR); | 699 | azx_bus(chip)->rirb.res[addr] = azx_readl(chip, IR); |
1276 | return 0; | 700 | return 0; |
1277 | } | 701 | } |
1278 | udelay(1); | 702 | udelay(1); |
@@ -1280,18 +704,18 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) | |||
1280 | if (printk_ratelimit()) | 704 | if (printk_ratelimit()) |
1281 | dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n", | 705 | dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n", |
1282 | azx_readw(chip, IRS)); | 706 | azx_readw(chip, IRS)); |
1283 | chip->rirb.res[addr] = -1; | 707 | azx_bus(chip)->rirb.res[addr] = -1; |
1284 | return -EIO; | 708 | return -EIO; |
1285 | } | 709 | } |
1286 | 710 | ||
1287 | /* send a command */ | 711 | /* send a command */ |
1288 | static int azx_single_send_cmd(struct hda_bus *bus, u32 val) | 712 | static int azx_single_send_cmd(struct hdac_bus *bus, u32 val) |
1289 | { | 713 | { |
1290 | struct azx *chip = bus->private_data; | 714 | struct azx *chip = bus_to_azx(bus); |
1291 | unsigned int addr = azx_command_addr(val); | 715 | unsigned int addr = azx_command_addr(val); |
1292 | int timeout = 50; | 716 | int timeout = 50; |
1293 | 717 | ||
1294 | bus->rirb_error = 0; | 718 | bus->last_cmd[azx_command_addr(val)] = val; |
1295 | while (timeout--) { | 719 | while (timeout--) { |
1296 | /* check ICB busy bit */ | 720 | /* check ICB busy bit */ |
1297 | if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { | 721 | if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { |
@@ -1313,11 +737,12 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) | |||
1313 | } | 737 | } |
1314 | 738 | ||
1315 | /* receive a response */ | 739 | /* receive a response */ |
1316 | static unsigned int azx_single_get_response(struct hda_bus *bus, | 740 | static int azx_single_get_response(struct hdac_bus *bus, unsigned int addr, |
1317 | unsigned int addr) | 741 | unsigned int *res) |
1318 | { | 742 | { |
1319 | struct azx *chip = bus->private_data; | 743 | if (res) |
1320 | return chip->rirb.res[addr]; | 744 | *res = bus->rirb.res[addr]; |
745 | return 0; | ||
1321 | } | 746 | } |
1322 | 747 | ||
1323 | /* | 748 | /* |
@@ -1328,32 +753,48 @@ static unsigned int azx_single_get_response(struct hda_bus *bus, | |||
1328 | */ | 753 | */ |
1329 | 754 | ||
1330 | /* send a command */ | 755 | /* send a command */ |
1331 | static int azx_send_cmd(struct hda_bus *bus, unsigned int val) | 756 | static int azx_send_cmd(struct hdac_bus *bus, unsigned int val) |
1332 | { | 757 | { |
1333 | struct azx *chip = bus->private_data; | 758 | struct azx *chip = bus_to_azx(bus); |
1334 | 759 | ||
1335 | if (chip->disabled) | 760 | if (chip->disabled) |
1336 | return 0; | 761 | return 0; |
1337 | chip->last_cmd[azx_command_addr(val)] = val; | ||
1338 | if (chip->single_cmd) | 762 | if (chip->single_cmd) |
1339 | return azx_single_send_cmd(bus, val); | 763 | return azx_single_send_cmd(bus, val); |
1340 | else | 764 | else |
1341 | return azx_corb_send_cmd(bus, val); | 765 | return snd_hdac_bus_send_cmd(bus, val); |
1342 | } | 766 | } |
1343 | 767 | ||
1344 | /* get a response */ | 768 | /* get a response */ |
1345 | static unsigned int azx_get_response(struct hda_bus *bus, | 769 | static int azx_get_response(struct hdac_bus *bus, unsigned int addr, |
1346 | unsigned int addr) | 770 | unsigned int *res) |
1347 | { | 771 | { |
1348 | struct azx *chip = bus->private_data; | 772 | struct azx *chip = bus_to_azx(bus); |
773 | |||
1349 | if (chip->disabled) | 774 | if (chip->disabled) |
1350 | return 0; | 775 | return 0; |
1351 | if (chip->single_cmd) | 776 | if (chip->single_cmd) |
1352 | return azx_single_get_response(bus, addr); | 777 | return azx_single_get_response(bus, addr, res); |
778 | else | ||
779 | return azx_rirb_get_response(bus, addr, res); | ||
780 | } | ||
781 | |||
782 | static int azx_link_power(struct hdac_bus *bus, bool enable) | ||
783 | { | ||
784 | struct azx *chip = bus_to_azx(bus); | ||
785 | |||
786 | if (chip->ops->link_power) | ||
787 | return chip->ops->link_power(chip, enable); | ||
1353 | else | 788 | else |
1354 | return azx_rirb_get_response(bus, addr); | 789 | return -EINVAL; |
1355 | } | 790 | } |
1356 | 791 | ||
792 | static const struct hdac_bus_ops bus_core_ops = { | ||
793 | .command = azx_send_cmd, | ||
794 | .get_response = azx_get_response, | ||
795 | .link_power = azx_link_power, | ||
796 | }; | ||
797 | |||
1357 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 798 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
1358 | /* | 799 | /* |
1359 | * DSP loading code (e.g. for CA0132) | 800 | * DSP loading code (e.g. for CA0132) |
@@ -1363,339 +804,132 @@ static unsigned int azx_get_response(struct hda_bus *bus, | |||
1363 | static struct azx_dev * | 804 | static struct azx_dev * |
1364 | azx_get_dsp_loader_dev(struct azx *chip) | 805 | azx_get_dsp_loader_dev(struct azx *chip) |
1365 | { | 806 | { |
1366 | return &chip->azx_dev[chip->playback_index_offset]; | 807 | struct hdac_bus *bus = azx_bus(chip); |
808 | struct hdac_stream *s; | ||
809 | |||
810 | list_for_each_entry(s, &bus->stream_list, list) | ||
811 | if (s->index == chip->playback_index_offset) | ||
812 | return stream_to_azx_dev(s); | ||
813 | |||
814 | return NULL; | ||
1367 | } | 815 | } |
1368 | 816 | ||
1369 | static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | 817 | int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, |
1370 | unsigned int byte_size, | 818 | unsigned int byte_size, |
1371 | struct snd_dma_buffer *bufp) | 819 | struct snd_dma_buffer *bufp) |
1372 | { | 820 | { |
1373 | u32 *bdl; | 821 | struct hdac_bus *bus = &codec->bus->core; |
1374 | struct azx *chip = bus->private_data; | 822 | struct azx *chip = bus_to_azx(bus); |
1375 | struct azx_dev *azx_dev; | 823 | struct azx_dev *azx_dev; |
824 | struct hdac_stream *hstr; | ||
825 | bool saved = false; | ||
1376 | int err; | 826 | int err; |
1377 | 827 | ||
1378 | azx_dev = azx_get_dsp_loader_dev(chip); | 828 | azx_dev = azx_get_dsp_loader_dev(chip); |
1379 | 829 | hstr = azx_stream(azx_dev); | |
1380 | dsp_lock(azx_dev); | 830 | spin_lock_irq(&bus->reg_lock); |
1381 | spin_lock_irq(&chip->reg_lock); | 831 | if (hstr->opened) { |
1382 | if (azx_dev->running || azx_dev->locked) { | 832 | chip->saved_azx_dev = *azx_dev; |
1383 | spin_unlock_irq(&chip->reg_lock); | 833 | saved = true; |
1384 | err = -EBUSY; | ||
1385 | goto unlock; | ||
1386 | } | 834 | } |
1387 | azx_dev->prepared = 0; | 835 | spin_unlock_irq(&bus->reg_lock); |
1388 | chip->saved_azx_dev = *azx_dev; | ||
1389 | azx_dev->locked = 1; | ||
1390 | spin_unlock_irq(&chip->reg_lock); | ||
1391 | |||
1392 | err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV_SG, | ||
1393 | byte_size, bufp); | ||
1394 | if (err < 0) | ||
1395 | goto err_alloc; | ||
1396 | 836 | ||
1397 | azx_dev->bufsize = byte_size; | 837 | err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp); |
1398 | azx_dev->period_bytes = byte_size; | 838 | if (err < 0) { |
1399 | azx_dev->format_val = format; | 839 | spin_lock_irq(&bus->reg_lock); |
1400 | 840 | if (saved) | |
1401 | azx_stream_reset(chip, azx_dev); | 841 | *azx_dev = chip->saved_azx_dev; |
1402 | 842 | spin_unlock_irq(&bus->reg_lock); | |
1403 | /* reset BDL address */ | 843 | return err; |
1404 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | 844 | } |
1405 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1406 | |||
1407 | azx_dev->frags = 0; | ||
1408 | bdl = (u32 *)azx_dev->bdl.area; | ||
1409 | err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); | ||
1410 | if (err < 0) | ||
1411 | goto error; | ||
1412 | |||
1413 | azx_setup_controller(chip, azx_dev); | ||
1414 | dsp_unlock(azx_dev); | ||
1415 | return azx_dev->stream_tag; | ||
1416 | 845 | ||
1417 | error: | 846 | hstr->prepared = 0; |
1418 | chip->ops->dma_free_pages(chip, bufp); | ||
1419 | err_alloc: | ||
1420 | spin_lock_irq(&chip->reg_lock); | ||
1421 | if (azx_dev->opened) | ||
1422 | *azx_dev = chip->saved_azx_dev; | ||
1423 | azx_dev->locked = 0; | ||
1424 | spin_unlock_irq(&chip->reg_lock); | ||
1425 | unlock: | ||
1426 | dsp_unlock(azx_dev); | ||
1427 | return err; | 847 | return err; |
1428 | } | 848 | } |
849 | EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_prepare); | ||
1429 | 850 | ||
1430 | static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) | 851 | void snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) |
1431 | { | 852 | { |
1432 | struct azx *chip = bus->private_data; | 853 | struct hdac_bus *bus = &codec->bus->core; |
854 | struct azx *chip = bus_to_azx(bus); | ||
1433 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | 855 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); |
1434 | 856 | ||
1435 | if (start) | 857 | snd_hdac_dsp_trigger(azx_stream(azx_dev), start); |
1436 | azx_stream_start(chip, azx_dev); | ||
1437 | else | ||
1438 | azx_stream_stop(chip, azx_dev); | ||
1439 | azx_dev->running = start; | ||
1440 | } | 858 | } |
859 | EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_trigger); | ||
1441 | 860 | ||
1442 | static void azx_load_dsp_cleanup(struct hda_bus *bus, | 861 | void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, |
1443 | struct snd_dma_buffer *dmab) | 862 | struct snd_dma_buffer *dmab) |
1444 | { | 863 | { |
1445 | struct azx *chip = bus->private_data; | 864 | struct hdac_bus *bus = &codec->bus->core; |
865 | struct azx *chip = bus_to_azx(bus); | ||
1446 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | 866 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); |
867 | struct hdac_stream *hstr = azx_stream(azx_dev); | ||
1447 | 868 | ||
1448 | if (!dmab->area || !azx_dev->locked) | 869 | if (!dmab->area || !hstr->locked) |
1449 | return; | 870 | return; |
1450 | 871 | ||
1451 | dsp_lock(azx_dev); | 872 | snd_hdac_dsp_cleanup(hstr, dmab); |
1452 | /* reset BDL address */ | 873 | spin_lock_irq(&bus->reg_lock); |
1453 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | 874 | if (hstr->opened) |
1454 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1455 | azx_sd_writel(chip, azx_dev, SD_CTL, 0); | ||
1456 | azx_dev->bufsize = 0; | ||
1457 | azx_dev->period_bytes = 0; | ||
1458 | azx_dev->format_val = 0; | ||
1459 | |||
1460 | chip->ops->dma_free_pages(chip, dmab); | ||
1461 | dmab->area = NULL; | ||
1462 | |||
1463 | spin_lock_irq(&chip->reg_lock); | ||
1464 | if (azx_dev->opened) | ||
1465 | *azx_dev = chip->saved_azx_dev; | 875 | *azx_dev = chip->saved_azx_dev; |
1466 | azx_dev->locked = 0; | 876 | hstr->locked = false; |
1467 | spin_unlock_irq(&chip->reg_lock); | 877 | spin_unlock_irq(&bus->reg_lock); |
1468 | dsp_unlock(azx_dev); | ||
1469 | } | 878 | } |
879 | EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_cleanup); | ||
1470 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | 880 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ |
1471 | 881 | ||
1472 | int azx_alloc_stream_pages(struct azx *chip) | ||
1473 | { | ||
1474 | int i, err; | ||
1475 | |||
1476 | for (i = 0; i < chip->num_streams; i++) { | ||
1477 | dsp_lock_init(&chip->azx_dev[i]); | ||
1478 | /* allocate memory for the BDL for each stream */ | ||
1479 | err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, | ||
1480 | BDL_SIZE, | ||
1481 | &chip->azx_dev[i].bdl); | ||
1482 | if (err < 0) | ||
1483 | return -ENOMEM; | ||
1484 | } | ||
1485 | /* allocate memory for the position buffer */ | ||
1486 | err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV, | ||
1487 | chip->num_streams * 8, &chip->posbuf); | ||
1488 | if (err < 0) | ||
1489 | return -ENOMEM; | ||
1490 | |||
1491 | /* allocate CORB/RIRB */ | ||
1492 | err = azx_alloc_cmd_io(chip); | ||
1493 | if (err < 0) | ||
1494 | return err; | ||
1495 | return 0; | ||
1496 | } | ||
1497 | EXPORT_SYMBOL_GPL(azx_alloc_stream_pages); | ||
1498 | |||
1499 | void azx_free_stream_pages(struct azx *chip) | ||
1500 | { | ||
1501 | int i; | ||
1502 | if (chip->azx_dev) { | ||
1503 | for (i = 0; i < chip->num_streams; i++) | ||
1504 | if (chip->azx_dev[i].bdl.area) | ||
1505 | chip->ops->dma_free_pages( | ||
1506 | chip, &chip->azx_dev[i].bdl); | ||
1507 | } | ||
1508 | if (chip->rb.area) | ||
1509 | chip->ops->dma_free_pages(chip, &chip->rb); | ||
1510 | if (chip->posbuf.area) | ||
1511 | chip->ops->dma_free_pages(chip, &chip->posbuf); | ||
1512 | } | ||
1513 | EXPORT_SYMBOL_GPL(azx_free_stream_pages); | ||
1514 | |||
1515 | /* | 882 | /* |
1516 | * Lowlevel interface | 883 | * reset and start the controller registers |
1517 | */ | 884 | */ |
1518 | 885 | void azx_init_chip(struct azx *chip, bool full_reset) | |
1519 | /* enter link reset */ | ||
1520 | void azx_enter_link_reset(struct azx *chip) | ||
1521 | { | ||
1522 | unsigned long timeout; | ||
1523 | |||
1524 | /* reset controller */ | ||
1525 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET); | ||
1526 | |||
1527 | timeout = jiffies + msecs_to_jiffies(100); | ||
1528 | while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) && | ||
1529 | time_before(jiffies, timeout)) | ||
1530 | usleep_range(500, 1000); | ||
1531 | } | ||
1532 | EXPORT_SYMBOL_GPL(azx_enter_link_reset); | ||
1533 | |||
1534 | /* exit link reset */ | ||
1535 | static void azx_exit_link_reset(struct azx *chip) | ||
1536 | { | ||
1537 | unsigned long timeout; | ||
1538 | |||
1539 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET); | ||
1540 | |||
1541 | timeout = jiffies + msecs_to_jiffies(100); | ||
1542 | while (!azx_readb(chip, GCTL) && | ||
1543 | time_before(jiffies, timeout)) | ||
1544 | usleep_range(500, 1000); | ||
1545 | } | ||
1546 | |||
1547 | /* reset codec link */ | ||
1548 | static int azx_reset(struct azx *chip, bool full_reset) | ||
1549 | { | ||
1550 | if (!full_reset) | ||
1551 | goto __skip; | ||
1552 | |||
1553 | /* clear STATESTS */ | ||
1554 | azx_writew(chip, STATESTS, STATESTS_INT_MASK); | ||
1555 | |||
1556 | /* reset controller */ | ||
1557 | azx_enter_link_reset(chip); | ||
1558 | |||
1559 | /* delay for >= 100us for codec PLL to settle per spec | ||
1560 | * Rev 0.9 section 5.5.1 | ||
1561 | */ | ||
1562 | usleep_range(500, 1000); | ||
1563 | |||
1564 | /* Bring controller out of reset */ | ||
1565 | azx_exit_link_reset(chip); | ||
1566 | |||
1567 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | ||
1568 | usleep_range(1000, 1200); | ||
1569 | |||
1570 | __skip: | ||
1571 | /* check to see if controller is ready */ | ||
1572 | if (!azx_readb(chip, GCTL)) { | ||
1573 | dev_dbg(chip->card->dev, "azx_reset: controller not ready!\n"); | ||
1574 | return -EBUSY; | ||
1575 | } | ||
1576 | |||
1577 | /* Accept unsolicited responses */ | ||
1578 | if (!chip->single_cmd) | ||
1579 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | | ||
1580 | AZX_GCTL_UNSOL); | ||
1581 | |||
1582 | /* detect codecs */ | ||
1583 | if (!chip->codec_mask) { | ||
1584 | chip->codec_mask = azx_readw(chip, STATESTS); | ||
1585 | dev_dbg(chip->card->dev, "codec_mask = 0x%x\n", | ||
1586 | chip->codec_mask); | ||
1587 | } | ||
1588 | |||
1589 | return 0; | ||
1590 | } | ||
1591 | |||
1592 | /* enable interrupts */ | ||
1593 | static void azx_int_enable(struct azx *chip) | ||
1594 | { | ||
1595 | /* enable controller CIE and GIE */ | ||
1596 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | | ||
1597 | AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); | ||
1598 | } | ||
1599 | |||
1600 | /* disable interrupts */ | ||
1601 | static void azx_int_disable(struct azx *chip) | ||
1602 | { | ||
1603 | int i; | ||
1604 | |||
1605 | /* disable interrupts in stream descriptor */ | ||
1606 | for (i = 0; i < chip->num_streams; i++) { | ||
1607 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | ||
1608 | azx_sd_writeb(chip, azx_dev, SD_CTL, | ||
1609 | azx_sd_readb(chip, azx_dev, SD_CTL) & | ||
1610 | ~SD_INT_MASK); | ||
1611 | } | ||
1612 | |||
1613 | /* disable SIE for all streams */ | ||
1614 | azx_writeb(chip, INTCTL, 0); | ||
1615 | |||
1616 | /* disable controller CIE and GIE */ | ||
1617 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & | ||
1618 | ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN)); | ||
1619 | } | ||
1620 | |||
1621 | /* clear interrupts */ | ||
1622 | static void azx_int_clear(struct azx *chip) | ||
1623 | { | 886 | { |
1624 | int i; | 887 | if (snd_hdac_bus_init_chip(azx_bus(chip), full_reset)) { |
1625 | 888 | /* correct RINTCNT for CXT */ | |
1626 | /* clear stream status */ | 889 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) |
1627 | for (i = 0; i < chip->num_streams; i++) { | 890 | azx_writew(chip, RINTCNT, 0xc0); |
1628 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | ||
1629 | azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); | ||
1630 | } | 891 | } |
1631 | |||
1632 | /* clear STATESTS */ | ||
1633 | azx_writew(chip, STATESTS, STATESTS_INT_MASK); | ||
1634 | |||
1635 | /* clear rirb status */ | ||
1636 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | ||
1637 | |||
1638 | /* clear int status */ | ||
1639 | azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); | ||
1640 | } | 892 | } |
893 | EXPORT_SYMBOL_GPL(azx_init_chip); | ||
1641 | 894 | ||
1642 | /* | 895 | void azx_stop_all_streams(struct azx *chip) |
1643 | * reset and start the controller registers | ||
1644 | */ | ||
1645 | void azx_init_chip(struct azx *chip, bool full_reset) | ||
1646 | { | 896 | { |
1647 | if (chip->initialized) | 897 | struct hdac_bus *bus = azx_bus(chip); |
1648 | return; | 898 | struct hdac_stream *s; |
1649 | |||
1650 | /* reset controller */ | ||
1651 | azx_reset(chip, full_reset); | ||
1652 | |||
1653 | /* initialize interrupts */ | ||
1654 | azx_int_clear(chip); | ||
1655 | azx_int_enable(chip); | ||
1656 | |||
1657 | /* initialize the codec command I/O */ | ||
1658 | if (!chip->single_cmd) | ||
1659 | azx_init_cmd_io(chip); | ||
1660 | |||
1661 | /* program the position buffer */ | ||
1662 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | ||
1663 | azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr)); | ||
1664 | 899 | ||
1665 | chip->initialized = 1; | 900 | list_for_each_entry(s, &bus->stream_list, list) |
901 | snd_hdac_stream_stop(s); | ||
1666 | } | 902 | } |
1667 | EXPORT_SYMBOL_GPL(azx_init_chip); | 903 | EXPORT_SYMBOL_GPL(azx_stop_all_streams); |
1668 | 904 | ||
1669 | void azx_stop_chip(struct azx *chip) | 905 | void azx_stop_chip(struct azx *chip) |
1670 | { | 906 | { |
1671 | if (!chip->initialized) | 907 | snd_hdac_bus_stop_chip(azx_bus(chip)); |
1672 | return; | ||
1673 | |||
1674 | /* disable interrupts */ | ||
1675 | azx_int_disable(chip); | ||
1676 | azx_int_clear(chip); | ||
1677 | |||
1678 | /* disable CORB/RIRB */ | ||
1679 | azx_free_cmd_io(chip); | ||
1680 | |||
1681 | /* disable position buffer */ | ||
1682 | azx_writel(chip, DPLBASE, 0); | ||
1683 | azx_writel(chip, DPUBASE, 0); | ||
1684 | |||
1685 | chip->initialized = 0; | ||
1686 | } | 908 | } |
1687 | EXPORT_SYMBOL_GPL(azx_stop_chip); | 909 | EXPORT_SYMBOL_GPL(azx_stop_chip); |
1688 | 910 | ||
1689 | /* | 911 | /* |
1690 | * interrupt handler | 912 | * interrupt handler |
1691 | */ | 913 | */ |
914 | static void stream_update(struct hdac_bus *bus, struct hdac_stream *s) | ||
915 | { | ||
916 | struct azx *chip = bus_to_azx(bus); | ||
917 | struct azx_dev *azx_dev = stream_to_azx_dev(s); | ||
918 | |||
919 | /* check whether this IRQ is really acceptable */ | ||
920 | if (!chip->ops->position_check || | ||
921 | chip->ops->position_check(chip, azx_dev)) { | ||
922 | spin_unlock(&bus->reg_lock); | ||
923 | snd_pcm_period_elapsed(azx_stream(azx_dev)->substream); | ||
924 | spin_lock(&bus->reg_lock); | ||
925 | } | ||
926 | } | ||
927 | |||
1692 | irqreturn_t azx_interrupt(int irq, void *dev_id) | 928 | irqreturn_t azx_interrupt(int irq, void *dev_id) |
1693 | { | 929 | { |
1694 | struct azx *chip = dev_id; | 930 | struct azx *chip = dev_id; |
1695 | struct azx_dev *azx_dev; | 931 | struct hdac_bus *bus = azx_bus(chip); |
1696 | u32 status; | 932 | u32 status; |
1697 | u8 sd_status; | ||
1698 | int i; | ||
1699 | 933 | ||
1700 | #ifdef CONFIG_PM | 934 | #ifdef CONFIG_PM |
1701 | if (azx_has_pm_runtime(chip)) | 935 | if (azx_has_pm_runtime(chip)) |
@@ -1703,36 +937,20 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
1703 | return IRQ_NONE; | 937 | return IRQ_NONE; |
1704 | #endif | 938 | #endif |
1705 | 939 | ||
1706 | spin_lock(&chip->reg_lock); | 940 | spin_lock(&bus->reg_lock); |
1707 | 941 | ||
1708 | if (chip->disabled) { | 942 | if (chip->disabled) { |
1709 | spin_unlock(&chip->reg_lock); | 943 | spin_unlock(&bus->reg_lock); |
1710 | return IRQ_NONE; | 944 | return IRQ_NONE; |
1711 | } | 945 | } |
1712 | 946 | ||
1713 | status = azx_readl(chip, INTSTS); | 947 | status = azx_readl(chip, INTSTS); |
1714 | if (status == 0 || status == 0xffffffff) { | 948 | if (status == 0 || status == 0xffffffff) { |
1715 | spin_unlock(&chip->reg_lock); | 949 | spin_unlock(&bus->reg_lock); |
1716 | return IRQ_NONE; | 950 | return IRQ_NONE; |
1717 | } | 951 | } |
1718 | 952 | ||
1719 | for (i = 0; i < chip->num_streams; i++) { | 953 | snd_hdac_bus_handle_stream_irq(bus, status, stream_update); |
1720 | azx_dev = &chip->azx_dev[i]; | ||
1721 | if (status & azx_dev->sd_int_sta_mask) { | ||
1722 | sd_status = azx_sd_readb(chip, azx_dev, SD_STS); | ||
1723 | azx_sd_writeb(chip, azx_dev, SD_STS, SD_INT_MASK); | ||
1724 | if (!azx_dev->substream || !azx_dev->running || | ||
1725 | !(sd_status & SD_INT_COMPLETE)) | ||
1726 | continue; | ||
1727 | /* check whether this IRQ is really acceptable */ | ||
1728 | if (!chip->ops->position_check || | ||
1729 | chip->ops->position_check(chip, azx_dev)) { | ||
1730 | spin_unlock(&chip->reg_lock); | ||
1731 | snd_pcm_period_elapsed(azx_dev->substream); | ||
1732 | spin_lock(&chip->reg_lock); | ||
1733 | } | ||
1734 | } | ||
1735 | } | ||
1736 | 954 | ||
1737 | /* clear rirb int */ | 955 | /* clear rirb int */ |
1738 | status = azx_readb(chip, RIRBSTS); | 956 | status = azx_readb(chip, RIRBSTS); |
@@ -1740,12 +958,12 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
1740 | if (status & RIRB_INT_RESPONSE) { | 958 | if (status & RIRB_INT_RESPONSE) { |
1741 | if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) | 959 | if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) |
1742 | udelay(80); | 960 | udelay(80); |
1743 | azx_update_rirb(chip); | 961 | snd_hdac_bus_update_rirb(bus); |
1744 | } | 962 | } |
1745 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 963 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
1746 | } | 964 | } |
1747 | 965 | ||
1748 | spin_unlock(&chip->reg_lock); | 966 | spin_unlock(&bus->reg_lock); |
1749 | 967 | ||
1750 | return IRQ_HANDLED; | 968 | return IRQ_HANDLED; |
1751 | } | 969 | } |
@@ -1762,29 +980,31 @@ static int probe_codec(struct azx *chip, int addr) | |||
1762 | { | 980 | { |
1763 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | | 981 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | |
1764 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | 982 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; |
1765 | unsigned int res; | 983 | struct hdac_bus *bus = azx_bus(chip); |
984 | int err; | ||
985 | unsigned int res = -1; | ||
1766 | 986 | ||
1767 | mutex_lock(&chip->bus->core.cmd_mutex); | 987 | mutex_lock(&bus->cmd_mutex); |
1768 | chip->probing = 1; | 988 | chip->probing = 1; |
1769 | azx_send_cmd(chip->bus, cmd); | 989 | azx_send_cmd(bus, cmd); |
1770 | res = azx_get_response(chip->bus, addr); | 990 | err = azx_get_response(bus, addr, &res); |
1771 | chip->probing = 0; | 991 | chip->probing = 0; |
1772 | mutex_unlock(&chip->bus->core.cmd_mutex); | 992 | mutex_unlock(&bus->cmd_mutex); |
1773 | if (res == -1) | 993 | if (err < 0 || res == -1) |
1774 | return -EIO; | 994 | return -EIO; |
1775 | dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr); | 995 | dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr); |
1776 | return 0; | 996 | return 0; |
1777 | } | 997 | } |
1778 | 998 | ||
1779 | static void azx_bus_reset(struct hda_bus *bus) | 999 | void snd_hda_bus_reset(struct hda_bus *bus) |
1780 | { | 1000 | { |
1781 | struct azx *chip = bus->private_data; | 1001 | struct azx *chip = bus_to_azx(&bus->core); |
1782 | 1002 | ||
1783 | bus->in_reset = 1; | 1003 | bus->in_reset = 1; |
1784 | azx_stop_chip(chip); | 1004 | azx_stop_chip(chip); |
1785 | azx_init_chip(chip, true); | 1005 | azx_init_chip(chip, true); |
1786 | if (chip->initialized) | 1006 | if (bus->core.chip_init) |
1787 | snd_hda_bus_reset(chip->bus); | 1007 | snd_hda_bus_reset_codecs(bus); |
1788 | bus->in_reset = 0; | 1008 | bus->in_reset = 0; |
1789 | } | 1009 | } |
1790 | 1010 | ||
@@ -1809,33 +1029,30 @@ static int get_jackpoll_interval(struct azx *chip) | |||
1809 | return j; | 1029 | return j; |
1810 | } | 1030 | } |
1811 | 1031 | ||
1812 | static struct hda_bus_ops bus_ops = { | ||
1813 | .command = azx_send_cmd, | ||
1814 | .get_response = azx_get_response, | ||
1815 | .attach_pcm = azx_attach_pcm_stream, | ||
1816 | .bus_reset = azx_bus_reset, | ||
1817 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1818 | .load_dsp_prepare = azx_load_dsp_prepare, | ||
1819 | .load_dsp_trigger = azx_load_dsp_trigger, | ||
1820 | .load_dsp_cleanup = azx_load_dsp_cleanup, | ||
1821 | #endif | ||
1822 | }; | ||
1823 | |||
1824 | /* HD-audio bus initialization */ | 1032 | /* HD-audio bus initialization */ |
1825 | int azx_bus_create(struct azx *chip, const char *model) | 1033 | int azx_bus_init(struct azx *chip, const char *model, |
1034 | const struct hdac_io_ops *io_ops) | ||
1826 | { | 1035 | { |
1827 | struct hda_bus *bus; | 1036 | struct hda_bus *bus = &chip->bus; |
1828 | int err; | 1037 | int err; |
1829 | 1038 | ||
1830 | err = snd_hda_bus_new(chip->card, &bus); | 1039 | err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, |
1040 | io_ops); | ||
1831 | if (err < 0) | 1041 | if (err < 0) |
1832 | return err; | 1042 | return err; |
1833 | 1043 | ||
1834 | chip->bus = bus; | 1044 | bus->card = chip->card; |
1835 | bus->private_data = chip; | 1045 | mutex_init(&bus->prepare_mutex); |
1836 | bus->pci = chip->pci; | 1046 | bus->pci = chip->pci; |
1837 | bus->modelname = model; | 1047 | bus->modelname = model; |
1838 | bus->ops = bus_ops; | 1048 | bus->core.snoop = azx_snoop(chip); |
1049 | if (chip->get_position[0] != azx_get_pos_lpib || | ||
1050 | chip->get_position[1] != azx_get_pos_lpib) | ||
1051 | bus->core.use_posbuf = true; | ||
1052 | if (chip->bdl_pos_adj) | ||
1053 | bus->core.bdl_pos_adj = chip->bdl_pos_adj[chip->dev_index]; | ||
1054 | if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR) | ||
1055 | bus->core.corbrp_self_clear = true; | ||
1839 | 1056 | ||
1840 | if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { | 1057 | if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { |
1841 | dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); | 1058 | dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); |
@@ -1854,12 +1071,12 @@ int azx_bus_create(struct azx *chip, const char *model) | |||
1854 | 1071 | ||
1855 | return 0; | 1072 | return 0; |
1856 | } | 1073 | } |
1857 | EXPORT_SYMBOL_GPL(azx_bus_create); | 1074 | EXPORT_SYMBOL_GPL(azx_bus_init); |
1858 | 1075 | ||
1859 | /* Probe codecs */ | 1076 | /* Probe codecs */ |
1860 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots) | 1077 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots) |
1861 | { | 1078 | { |
1862 | struct hda_bus *bus = chip->bus; | 1079 | struct hdac_bus *bus = azx_bus(chip); |
1863 | int c, codecs, err; | 1080 | int c, codecs, err; |
1864 | 1081 | ||
1865 | codecs = 0; | 1082 | codecs = 0; |
@@ -1868,14 +1085,14 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) | |||
1868 | 1085 | ||
1869 | /* First try to probe all given codec slots */ | 1086 | /* First try to probe all given codec slots */ |
1870 | for (c = 0; c < max_slots; c++) { | 1087 | for (c = 0; c < max_slots; c++) { |
1871 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { | 1088 | if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1872 | if (probe_codec(chip, c) < 0) { | 1089 | if (probe_codec(chip, c) < 0) { |
1873 | /* Some BIOSen give you wrong codec addresses | 1090 | /* Some BIOSen give you wrong codec addresses |
1874 | * that don't exist | 1091 | * that don't exist |
1875 | */ | 1092 | */ |
1876 | dev_warn(chip->card->dev, | 1093 | dev_warn(chip->card->dev, |
1877 | "Codec #%d probe error; disabling it...\n", c); | 1094 | "Codec #%d probe error; disabling it...\n", c); |
1878 | chip->codec_mask &= ~(1 << c); | 1095 | bus->codec_mask &= ~(1 << c); |
1879 | /* More badly, accessing to a non-existing | 1096 | /* More badly, accessing to a non-existing |
1880 | * codec often screws up the controller chip, | 1097 | * codec often screws up the controller chip, |
1881 | * and disturbs the further communications. | 1098 | * and disturbs the further communications. |
@@ -1891,9 +1108,9 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) | |||
1891 | 1108 | ||
1892 | /* Then create codec instances */ | 1109 | /* Then create codec instances */ |
1893 | for (c = 0; c < max_slots; c++) { | 1110 | for (c = 0; c < max_slots; c++) { |
1894 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { | 1111 | if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1895 | struct hda_codec *codec; | 1112 | struct hda_codec *codec; |
1896 | err = snd_hda_codec_new(bus, bus->card, c, &codec); | 1113 | err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); |
1897 | if (err < 0) | 1114 | if (err < 0) |
1898 | continue; | 1115 | continue; |
1899 | codec->jackpoll_interval = get_jackpoll_interval(chip); | 1116 | codec->jackpoll_interval = get_jackpoll_interval(chip); |
@@ -1913,40 +1130,39 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs); | |||
1913 | int azx_codec_configure(struct azx *chip) | 1130 | int azx_codec_configure(struct azx *chip) |
1914 | { | 1131 | { |
1915 | struct hda_codec *codec; | 1132 | struct hda_codec *codec; |
1916 | list_for_each_codec(codec, chip->bus) { | 1133 | list_for_each_codec(codec, &chip->bus) { |
1917 | snd_hda_codec_configure(codec); | 1134 | snd_hda_codec_configure(codec); |
1918 | } | 1135 | } |
1919 | return 0; | 1136 | return 0; |
1920 | } | 1137 | } |
1921 | EXPORT_SYMBOL_GPL(azx_codec_configure); | 1138 | EXPORT_SYMBOL_GPL(azx_codec_configure); |
1922 | 1139 | ||
1923 | 1140 | static int stream_direction(struct azx *chip, unsigned char index) | |
1924 | static bool is_input_stream(struct azx *chip, unsigned char index) | ||
1925 | { | 1141 | { |
1926 | return (index >= chip->capture_index_offset && | 1142 | if (index >= chip->capture_index_offset && |
1927 | index < chip->capture_index_offset + chip->capture_streams); | 1143 | index < chip->capture_index_offset + chip->capture_streams) |
1144 | return SNDRV_PCM_STREAM_CAPTURE; | ||
1145 | return SNDRV_PCM_STREAM_PLAYBACK; | ||
1928 | } | 1146 | } |
1929 | 1147 | ||
1930 | /* initialize SD streams */ | 1148 | /* initialize SD streams */ |
1931 | int azx_init_stream(struct azx *chip) | 1149 | int azx_init_streams(struct azx *chip) |
1932 | { | 1150 | { |
1933 | int i; | 1151 | int i; |
1934 | int in_stream_tag = 0; | 1152 | int stream_tags[2] = { 0, 0 }; |
1935 | int out_stream_tag = 0; | ||
1936 | 1153 | ||
1937 | /* initialize each stream (aka device) | 1154 | /* initialize each stream (aka device) |
1938 | * assign the starting bdl address to each stream (device) | 1155 | * assign the starting bdl address to each stream (device) |
1939 | * and initialize | 1156 | * and initialize |
1940 | */ | 1157 | */ |
1941 | for (i = 0; i < chip->num_streams; i++) { | 1158 | for (i = 0; i < chip->num_streams; i++) { |
1942 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | 1159 | struct azx_dev *azx_dev = kzalloc(sizeof(*azx_dev), GFP_KERNEL); |
1943 | azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); | 1160 | int dir, tag; |
1944 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1161 | |
1945 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1162 | if (!azx_dev) |
1946 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1163 | return -ENOMEM; |
1947 | azx_dev->sd_int_sta_mask = 1 << i; | ||
1948 | azx_dev->index = i; | ||
1949 | 1164 | ||
1165 | dir = stream_direction(chip, i); | ||
1950 | /* stream tag must be unique throughout | 1166 | /* stream tag must be unique throughout |
1951 | * the stream direction group, | 1167 | * the stream direction group, |
1952 | * valid values 1...15 | 1168 | * valid values 1...15 |
@@ -1954,17 +1170,26 @@ int azx_init_stream(struct azx *chip) | |||
1954 | * AZX_DCAPS_SEPARATE_STREAM_TAG is used | 1170 | * AZX_DCAPS_SEPARATE_STREAM_TAG is used |
1955 | */ | 1171 | */ |
1956 | if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) | 1172 | if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) |
1957 | azx_dev->stream_tag = | 1173 | tag = ++stream_tags[dir]; |
1958 | is_input_stream(chip, i) ? | ||
1959 | ++in_stream_tag : | ||
1960 | ++out_stream_tag; | ||
1961 | else | 1174 | else |
1962 | azx_dev->stream_tag = i + 1; | 1175 | tag = i + 1; |
1176 | snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev), | ||
1177 | i, dir, tag); | ||
1963 | } | 1178 | } |
1964 | 1179 | ||
1965 | return 0; | 1180 | return 0; |
1966 | } | 1181 | } |
1967 | EXPORT_SYMBOL_GPL(azx_init_stream); | 1182 | EXPORT_SYMBOL_GPL(azx_init_streams); |
1968 | 1183 | ||
1969 | MODULE_LICENSE("GPL"); | 1184 | void azx_free_streams(struct azx *chip) |
1970 | MODULE_DESCRIPTION("Common HDA driver functions"); | 1185 | { |
1186 | struct hdac_bus *bus = azx_bus(chip); | ||
1187 | struct hdac_stream *s; | ||
1188 | |||
1189 | while (!list_empty(&bus->stream_list)) { | ||
1190 | s = list_first_entry(&bus->stream_list, struct hdac_stream, list); | ||
1191 | list_del(&s->list); | ||
1192 | kfree(stream_to_azx_dev(s)); | ||
1193 | } | ||
1194 | } | ||
1195 | EXPORT_SYMBOL_GPL(azx_free_streams); | ||
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 0efdb094d21c..314105cd5061 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -21,135 +21,10 @@ | |||
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include "hda_codec.h" | 23 | #include "hda_codec.h" |
24 | #include <sound/hda_register.h> | ||
24 | 25 | ||
25 | /* | 26 | #define AZX_MAX_CODECS HDA_MAX_CODECS |
26 | * registers | ||
27 | */ | ||
28 | #define AZX_REG_GCAP 0x00 | ||
29 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ | ||
30 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | ||
31 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | ||
32 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ | ||
33 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ | ||
34 | #define AZX_REG_VMIN 0x02 | ||
35 | #define AZX_REG_VMAJ 0x03 | ||
36 | #define AZX_REG_OUTPAY 0x04 | ||
37 | #define AZX_REG_INPAY 0x06 | ||
38 | #define AZX_REG_GCTL 0x08 | ||
39 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ | ||
40 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ | ||
41 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | ||
42 | #define AZX_REG_WAKEEN 0x0c | ||
43 | #define AZX_REG_STATESTS 0x0e | ||
44 | #define AZX_REG_GSTS 0x10 | ||
45 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ | ||
46 | #define AZX_REG_INTCTL 0x20 | ||
47 | #define AZX_REG_INTSTS 0x24 | ||
48 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ | ||
49 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | ||
50 | #define AZX_REG_SSYNC 0x38 | ||
51 | #define AZX_REG_CORBLBASE 0x40 | ||
52 | #define AZX_REG_CORBUBASE 0x44 | ||
53 | #define AZX_REG_CORBWP 0x48 | ||
54 | #define AZX_REG_CORBRP 0x4a | ||
55 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ | ||
56 | #define AZX_REG_CORBCTL 0x4c | ||
57 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ | ||
58 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | ||
59 | #define AZX_REG_CORBSTS 0x4d | ||
60 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ | ||
61 | #define AZX_REG_CORBSIZE 0x4e | ||
62 | |||
63 | #define AZX_REG_RIRBLBASE 0x50 | ||
64 | #define AZX_REG_RIRBUBASE 0x54 | ||
65 | #define AZX_REG_RIRBWP 0x58 | ||
66 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ | ||
67 | #define AZX_REG_RINTCNT 0x5a | ||
68 | #define AZX_REG_RIRBCTL 0x5c | ||
69 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | ||
70 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | ||
71 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | ||
72 | #define AZX_REG_RIRBSTS 0x5d | ||
73 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ | ||
74 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | ||
75 | #define AZX_REG_RIRBSIZE 0x5e | ||
76 | |||
77 | #define AZX_REG_IC 0x60 | ||
78 | #define AZX_REG_IR 0x64 | ||
79 | #define AZX_REG_IRS 0x68 | ||
80 | #define AZX_IRS_VALID (1<<1) | ||
81 | #define AZX_IRS_BUSY (1<<0) | ||
82 | |||
83 | #define AZX_REG_DPLBASE 0x70 | ||
84 | #define AZX_REG_DPUBASE 0x74 | ||
85 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | ||
86 | |||
87 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | ||
88 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | ||
89 | |||
90 | /* stream register offsets from stream base */ | ||
91 | #define AZX_REG_SD_CTL 0x00 | ||
92 | #define AZX_REG_SD_STS 0x03 | ||
93 | #define AZX_REG_SD_LPIB 0x04 | ||
94 | #define AZX_REG_SD_CBL 0x08 | ||
95 | #define AZX_REG_SD_LVI 0x0c | ||
96 | #define AZX_REG_SD_FIFOW 0x0e | ||
97 | #define AZX_REG_SD_FIFOSIZE 0x10 | ||
98 | #define AZX_REG_SD_FORMAT 0x12 | ||
99 | #define AZX_REG_SD_BDLPL 0x18 | ||
100 | #define AZX_REG_SD_BDLPU 0x1c | ||
101 | |||
102 | /* PCI space */ | ||
103 | #define AZX_PCIREG_TCSEL 0x44 | ||
104 | |||
105 | /* | ||
106 | * other constants | ||
107 | */ | ||
108 | |||
109 | /* max number of fragments - we may use more if allocating more pages for BDL */ | ||
110 | #define BDL_SIZE 4096 | ||
111 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | ||
112 | #define AZX_MAX_FRAG 32 | ||
113 | /* max buffer size - no h/w limit, you can increase as you like */ | ||
114 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | ||
115 | |||
116 | /* RIRB int mask: overrun[2], response[0] */ | ||
117 | #define RIRB_INT_RESPONSE 0x01 | ||
118 | #define RIRB_INT_OVERRUN 0x04 | ||
119 | #define RIRB_INT_MASK 0x05 | ||
120 | |||
121 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | ||
122 | #define AZX_MAX_CODECS 8 | ||
123 | #define AZX_DEFAULT_CODECS 4 | 27 | #define AZX_DEFAULT_CODECS 4 |
124 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) | ||
125 | |||
126 | /* SD_CTL bits */ | ||
127 | #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ | ||
128 | #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ | ||
129 | #define SD_CTL_STRIPE (3 << 16) /* stripe control */ | ||
130 | #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ | ||
131 | #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ | ||
132 | #define SD_CTL_STREAM_TAG_MASK (0xf << 20) | ||
133 | #define SD_CTL_STREAM_TAG_SHIFT 20 | ||
134 | |||
135 | /* SD_CTL and SD_STS */ | ||
136 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ | ||
137 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | ||
138 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ | ||
139 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ | ||
140 | SD_INT_COMPLETE) | ||
141 | |||
142 | /* SD_STS */ | ||
143 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | ||
144 | |||
145 | /* INTCTL and INTSTS */ | ||
146 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ | ||
147 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | ||
148 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | ||
149 | |||
150 | /* below are so far hardcoded - should read registers in future */ | ||
151 | #define AZX_MAX_CORB_ENTRIES 256 | ||
152 | #define AZX_MAX_RIRB_ENTRIES 256 | ||
153 | 28 | ||
154 | /* driver quirks (capabilities) */ | 29 | /* driver quirks (capabilities) */ |
155 | /* bits 0-7 are used for indicating driver type */ | 30 | /* bits 0-7 are used for indicating driver type */ |
@@ -183,40 +58,10 @@ enum { | |||
183 | AZX_SNOOP_TYPE_NVIDIA, | 58 | AZX_SNOOP_TYPE_NVIDIA, |
184 | }; | 59 | }; |
185 | 60 | ||
186 | /* HD Audio class code */ | ||
187 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | ||
188 | |||
189 | struct azx_dev { | 61 | struct azx_dev { |
190 | struct snd_dma_buffer bdl; /* BDL buffer */ | 62 | struct hdac_stream core; |
191 | u32 *posbuf; /* position buffer pointer */ | 63 | |
192 | |||
193 | unsigned int bufsize; /* size of the play buffer in bytes */ | ||
194 | unsigned int period_bytes; /* size of the period in bytes */ | ||
195 | unsigned int frags; /* number for period in the play buffer */ | ||
196 | unsigned int fifo_size; /* FIFO size */ | ||
197 | unsigned long start_wallclk; /* start + minimum wallclk */ | ||
198 | unsigned long period_wallclk; /* wallclk for period */ | ||
199 | |||
200 | void __iomem *sd_addr; /* stream descriptor pointer */ | ||
201 | |||
202 | u32 sd_int_sta_mask; /* stream int status mask */ | ||
203 | |||
204 | /* pcm support */ | ||
205 | struct snd_pcm_substream *substream; /* assigned substream, | ||
206 | * set in PCM open | ||
207 | */ | ||
208 | unsigned int format_val; /* format value to be set in the | ||
209 | * controller and the codec | ||
210 | */ | ||
211 | unsigned char stream_tag; /* assigned stream */ | ||
212 | unsigned char index; /* stream index */ | ||
213 | int assigned_key; /* last device# key assigned to */ | ||
214 | |||
215 | unsigned int opened:1; | ||
216 | unsigned int running:1; | ||
217 | unsigned int irq_pending:1; | 64 | unsigned int irq_pending:1; |
218 | unsigned int prepared:1; | ||
219 | unsigned int locked:1; | ||
220 | /* | 65 | /* |
221 | * For VIA: | 66 | * For VIA: |
222 | * A flag to ensure DMA position is 0 | 67 | * A flag to ensure DMA position is 0 |
@@ -224,50 +69,17 @@ struct azx_dev { | |||
224 | */ | 69 | */ |
225 | unsigned int insufficient:1; | 70 | unsigned int insufficient:1; |
226 | unsigned int wc_marked:1; | 71 | unsigned int wc_marked:1; |
227 | unsigned int no_period_wakeup:1; | ||
228 | |||
229 | struct timecounter azx_tc; | ||
230 | struct cyclecounter azx_cc; | ||
231 | |||
232 | int delay_negative_threshold; | ||
233 | |||
234 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
235 | /* Allows dsp load to have sole access to the playback stream. */ | ||
236 | struct mutex dsp_mutex; | ||
237 | #endif | ||
238 | }; | 72 | }; |
239 | 73 | ||
240 | /* CORB/RIRB */ | 74 | #define azx_stream(dev) (&(dev)->core) |
241 | struct azx_rb { | 75 | #define stream_to_azx_dev(s) container_of(s, struct azx_dev, core) |
242 | u32 *buf; /* CORB/RIRB buffer | ||
243 | * Each CORB entry is 4byte, RIRB is 8byte | ||
244 | */ | ||
245 | dma_addr_t addr; /* physical address of CORB/RIRB buffer */ | ||
246 | /* for RIRB */ | ||
247 | unsigned short rp, wp; /* read/write pointers */ | ||
248 | int cmds[AZX_MAX_CODECS]; /* number of pending requests */ | ||
249 | u32 res[AZX_MAX_CODECS]; /* last read value */ | ||
250 | }; | ||
251 | 76 | ||
252 | struct azx; | 77 | struct azx; |
253 | 78 | ||
254 | /* Functions to read/write to hda registers. */ | 79 | /* Functions to read/write to hda registers. */ |
255 | struct hda_controller_ops { | 80 | struct hda_controller_ops { |
256 | /* Register Access */ | ||
257 | void (*reg_writel)(u32 value, u32 __iomem *addr); | ||
258 | u32 (*reg_readl)(u32 __iomem *addr); | ||
259 | void (*reg_writew)(u16 value, u16 __iomem *addr); | ||
260 | u16 (*reg_readw)(u16 __iomem *addr); | ||
261 | void (*reg_writeb)(u8 value, u8 __iomem *addr); | ||
262 | u8 (*reg_readb)(u8 __iomem *addr); | ||
263 | /* Disable msi if supported, PCI only */ | 81 | /* Disable msi if supported, PCI only */ |
264 | int (*disable_msi_reset_irq)(struct azx *); | 82 | int (*disable_msi_reset_irq)(struct azx *); |
265 | /* Allocation ops */ | ||
266 | int (*dma_alloc_pages)(struct azx *chip, | ||
267 | int type, | ||
268 | size_t size, | ||
269 | struct snd_dma_buffer *buf); | ||
270 | void (*dma_free_pages)(struct azx *chip, struct snd_dma_buffer *buf); | ||
271 | int (*substream_alloc_pages)(struct azx *chip, | 83 | int (*substream_alloc_pages)(struct azx *chip, |
272 | struct snd_pcm_substream *substream, | 84 | struct snd_pcm_substream *substream, |
273 | size_t size); | 85 | size_t size); |
@@ -277,6 +89,8 @@ struct hda_controller_ops { | |||
277 | struct vm_area_struct *area); | 89 | struct vm_area_struct *area); |
278 | /* Check if current position is acceptable */ | 90 | /* Check if current position is acceptable */ |
279 | int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); | 91 | int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); |
92 | /* enable/disable the link power */ | ||
93 | int (*link_power)(struct azx *chip, bool enable); | ||
280 | }; | 94 | }; |
281 | 95 | ||
282 | struct azx_pcm { | 96 | struct azx_pcm { |
@@ -291,6 +105,8 @@ typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *); | |||
291 | typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); | 105 | typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); |
292 | 106 | ||
293 | struct azx { | 107 | struct azx { |
108 | struct hda_bus bus; | ||
109 | |||
294 | struct snd_card *card; | 110 | struct snd_card *card; |
295 | struct pci_dev *pci; | 111 | struct pci_dev *pci; |
296 | int dev_index; | 112 | int dev_index; |
@@ -312,35 +128,16 @@ struct azx { | |||
312 | azx_get_pos_callback_t get_position[2]; | 128 | azx_get_pos_callback_t get_position[2]; |
313 | azx_get_delay_callback_t get_delay[2]; | 129 | azx_get_delay_callback_t get_delay[2]; |
314 | 130 | ||
315 | /* pci resources */ | ||
316 | unsigned long addr; | ||
317 | void __iomem *remap_addr; | ||
318 | int irq; | ||
319 | |||
320 | /* locks */ | 131 | /* locks */ |
321 | spinlock_t reg_lock; | ||
322 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ | 132 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ |
323 | 133 | ||
324 | /* streams (x num_streams) */ | ||
325 | struct azx_dev *azx_dev; | ||
326 | |||
327 | /* PCM */ | 134 | /* PCM */ |
328 | struct list_head pcm_list; /* azx_pcm list */ | 135 | struct list_head pcm_list; /* azx_pcm list */ |
329 | 136 | ||
330 | /* HD codec */ | 137 | /* HD codec */ |
331 | unsigned short codec_mask; | ||
332 | int codec_probe_mask; /* copied from probe_mask option */ | 138 | int codec_probe_mask; /* copied from probe_mask option */ |
333 | struct hda_bus *bus; | ||
334 | unsigned int beep_mode; | 139 | unsigned int beep_mode; |
335 | 140 | ||
336 | /* CORB/RIRB */ | ||
337 | struct azx_rb corb; | ||
338 | struct azx_rb rirb; | ||
339 | |||
340 | /* CORB/RIRB and position buffers */ | ||
341 | struct snd_dma_buffer rb; | ||
342 | struct snd_dma_buffer posbuf; | ||
343 | |||
344 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 141 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
345 | const struct firmware *fw; | 142 | const struct firmware *fw; |
346 | #endif | 143 | #endif |
@@ -349,7 +146,6 @@ struct azx { | |||
349 | const int *bdl_pos_adj; | 146 | const int *bdl_pos_adj; |
350 | int poll_count; | 147 | int poll_count; |
351 | unsigned int running:1; | 148 | unsigned int running:1; |
352 | unsigned int initialized:1; | ||
353 | unsigned int single_cmd:1; | 149 | unsigned int single_cmd:1; |
354 | unsigned int polling_mode:1; | 150 | unsigned int polling_mode:1; |
355 | unsigned int msi:1; | 151 | unsigned int msi:1; |
@@ -359,14 +155,14 @@ struct azx { | |||
359 | unsigned int region_requested:1; | 155 | unsigned int region_requested:1; |
360 | unsigned int disabled:1; /* disabled by VGA-switcher */ | 156 | unsigned int disabled:1; /* disabled by VGA-switcher */ |
361 | 157 | ||
362 | /* for debugging */ | ||
363 | unsigned int last_cmd[AZX_MAX_CODECS]; | ||
364 | |||
365 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 158 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
366 | struct azx_dev saved_azx_dev; | 159 | struct azx_dev saved_azx_dev; |
367 | #endif | 160 | #endif |
368 | }; | 161 | }; |
369 | 162 | ||
163 | #define azx_bus(chip) (&(chip)->bus.core) | ||
164 | #define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core) | ||
165 | |||
370 | #ifdef CONFIG_X86 | 166 | #ifdef CONFIG_X86 |
371 | #define azx_snoop(chip) ((chip)->snoop) | 167 | #define azx_snoop(chip) ((chip)->snoop) |
372 | #else | 168 | #else |
@@ -378,30 +174,17 @@ struct azx { | |||
378 | */ | 174 | */ |
379 | 175 | ||
380 | #define azx_writel(chip, reg, value) \ | 176 | #define azx_writel(chip, reg, value) \ |
381 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)) | 177 | snd_hdac_chip_writel(azx_bus(chip), reg, value) |
382 | #define azx_readl(chip, reg) \ | 178 | #define azx_readl(chip, reg) \ |
383 | ((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)) | 179 | snd_hdac_chip_readl(azx_bus(chip), reg) |
384 | #define azx_writew(chip, reg, value) \ | 180 | #define azx_writew(chip, reg, value) \ |
385 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)) | 181 | snd_hdac_chip_writew(azx_bus(chip), reg, value) |
386 | #define azx_readw(chip, reg) \ | 182 | #define azx_readw(chip, reg) \ |
387 | ((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)) | 183 | snd_hdac_chip_readw(azx_bus(chip), reg) |
388 | #define azx_writeb(chip, reg, value) \ | 184 | #define azx_writeb(chip, reg, value) \ |
389 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)) | 185 | snd_hdac_chip_writeb(azx_bus(chip), reg, value) |
390 | #define azx_readb(chip, reg) \ | 186 | #define azx_readb(chip, reg) \ |
391 | ((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg)) | 187 | snd_hdac_chip_readb(azx_bus(chip), reg) |
392 | |||
393 | #define azx_sd_writel(chip, dev, reg, value) \ | ||
394 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg)) | ||
395 | #define azx_sd_readl(chip, dev, reg) \ | ||
396 | ((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg)) | ||
397 | #define azx_sd_writew(chip, dev, reg, value) \ | ||
398 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg)) | ||
399 | #define azx_sd_readw(chip, dev, reg) \ | ||
400 | ((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg)) | ||
401 | #define azx_sd_writeb(chip, dev, reg, value) \ | ||
402 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg)) | ||
403 | #define azx_sd_readb(chip, dev, reg) \ | ||
404 | ((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg)) | ||
405 | 188 | ||
406 | #define azx_has_pm_runtime(chip) \ | 189 | #define azx_has_pm_runtime(chip) \ |
407 | ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME) | 190 | ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME) |
@@ -416,22 +199,27 @@ unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev); | |||
416 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); | 199 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); |
417 | 200 | ||
418 | /* Stream control. */ | 201 | /* Stream control. */ |
419 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); | 202 | void azx_stop_all_streams(struct azx *chip); |
420 | 203 | ||
421 | /* Allocation functions. */ | 204 | /* Allocation functions. */ |
422 | int azx_alloc_stream_pages(struct azx *chip); | 205 | #define azx_alloc_stream_pages(chip) \ |
423 | void azx_free_stream_pages(struct azx *chip); | 206 | snd_hdac_bus_alloc_stream_pages(azx_bus(chip)) |
207 | #define azx_free_stream_pages(chip) \ | ||
208 | snd_hdac_bus_free_stream_pages(azx_bus(chip)) | ||
424 | 209 | ||
425 | /* Low level azx interface */ | 210 | /* Low level azx interface */ |
426 | void azx_init_chip(struct azx *chip, bool full_reset); | 211 | void azx_init_chip(struct azx *chip, bool full_reset); |
427 | void azx_stop_chip(struct azx *chip); | 212 | void azx_stop_chip(struct azx *chip); |
428 | void azx_enter_link_reset(struct azx *chip); | 213 | #define azx_enter_link_reset(chip) \ |
214 | snd_hdac_bus_enter_link_reset(azx_bus(chip)) | ||
429 | irqreturn_t azx_interrupt(int irq, void *dev_id); | 215 | irqreturn_t azx_interrupt(int irq, void *dev_id); |
430 | 216 | ||
431 | /* Codec interface */ | 217 | /* Codec interface */ |
432 | int azx_bus_create(struct azx *chip, const char *model); | 218 | int azx_bus_init(struct azx *chip, const char *model, |
219 | const struct hdac_io_ops *io_ops); | ||
433 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots); | 220 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots); |
434 | int azx_codec_configure(struct azx *chip); | 221 | int azx_codec_configure(struct azx *chip); |
435 | int azx_init_stream(struct azx *chip); | 222 | int azx_init_streams(struct azx *chip); |
223 | void azx_free_streams(struct azx *chip); | ||
436 | 224 | ||
437 | #endif /* __SOUND_HDA_CONTROLLER_H */ | 225 | #endif /* __SOUND_HDA_CONTROLLER_H */ |
diff --git a/sound/pci/hda/hda_controller_trace.h b/sound/pci/hda/hda_controller_trace.h new file mode 100644 index 000000000000..3e18d99bfb70 --- /dev/null +++ b/sound/pci/hda/hda_controller_trace.h | |||
@@ -0,0 +1,98 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM hda_controller | ||
3 | #define TRACE_INCLUDE_FILE hda_controller_trace | ||
4 | |||
5 | #if !defined(_TRACE_HDA_CONTROLLER_H) || defined(TRACE_HEADER_MULTI_READ) | ||
6 | #define _TRACE_HDA_CONTROLLER_H | ||
7 | |||
8 | #include <linux/tracepoint.h> | ||
9 | |||
10 | struct azx; | ||
11 | struct azx_dev; | ||
12 | |||
13 | TRACE_EVENT(azx_pcm_trigger, | ||
14 | |||
15 | TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd), | ||
16 | |||
17 | TP_ARGS(chip, dev, cmd), | ||
18 | |||
19 | TP_STRUCT__entry( | ||
20 | __field( int, card ) | ||
21 | __field( int, idx ) | ||
22 | __field( int, cmd ) | ||
23 | ), | ||
24 | |||
25 | TP_fast_assign( | ||
26 | __entry->card = (chip)->card->number; | ||
27 | __entry->idx = (dev)->core.index; | ||
28 | __entry->cmd = cmd; | ||
29 | ), | ||
30 | |||
31 | TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd) | ||
32 | ); | ||
33 | |||
34 | TRACE_EVENT(azx_get_position, | ||
35 | |||
36 | TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay), | ||
37 | |||
38 | TP_ARGS(chip, dev, pos, delay), | ||
39 | |||
40 | TP_STRUCT__entry( | ||
41 | __field( int, card ) | ||
42 | __field( int, idx ) | ||
43 | __field( unsigned int, pos ) | ||
44 | __field( unsigned int, delay ) | ||
45 | ), | ||
46 | |||
47 | TP_fast_assign( | ||
48 | __entry->card = (chip)->card->number; | ||
49 | __entry->idx = (dev)->core.index; | ||
50 | __entry->pos = pos; | ||
51 | __entry->delay = delay; | ||
52 | ), | ||
53 | |||
54 | TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay) | ||
55 | ); | ||
56 | |||
57 | DECLARE_EVENT_CLASS(azx_pcm, | ||
58 | TP_PROTO(struct azx *chip, struct azx_dev *azx_dev), | ||
59 | |||
60 | TP_ARGS(chip, azx_dev), | ||
61 | |||
62 | TP_STRUCT__entry( | ||
63 | __field( unsigned char, stream_tag ) | ||
64 | ), | ||
65 | |||
66 | TP_fast_assign( | ||
67 | __entry->stream_tag = (azx_dev)->core.stream_tag; | ||
68 | ), | ||
69 | |||
70 | TP_printk("stream_tag: %d", __entry->stream_tag) | ||
71 | ); | ||
72 | |||
73 | DEFINE_EVENT(azx_pcm, azx_pcm_open, | ||
74 | TP_PROTO(struct azx *chip, struct azx_dev *azx_dev), | ||
75 | TP_ARGS(chip, azx_dev) | ||
76 | ); | ||
77 | |||
78 | DEFINE_EVENT(azx_pcm, azx_pcm_close, | ||
79 | TP_PROTO(struct azx *chip, struct azx_dev *azx_dev), | ||
80 | TP_ARGS(chip, azx_dev) | ||
81 | ); | ||
82 | |||
83 | DEFINE_EVENT(azx_pcm, azx_pcm_hw_params, | ||
84 | TP_PROTO(struct azx *chip, struct azx_dev *azx_dev), | ||
85 | TP_ARGS(chip, azx_dev) | ||
86 | ); | ||
87 | |||
88 | DEFINE_EVENT(azx_pcm, azx_pcm_prepare, | ||
89 | TP_PROTO(struct azx *chip, struct azx_dev *azx_dev), | ||
90 | TP_ARGS(chip, azx_dev) | ||
91 | ); | ||
92 | |||
93 | #endif /* _TRACE_HDA_CONTROLLER_H */ | ||
94 | |||
95 | /* This part must be outside protection */ | ||
96 | #undef TRACE_INCLUDE_PATH | ||
97 | #define TRACE_INCLUDE_PATH . | ||
98 | #include <trace/define_trace.h> | ||
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 0e6d7534f491..c746cd9a4450 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -448,7 +448,7 @@ void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e) | |||
448 | hdmi_show_short_audio_desc(codec, e->sad + i); | 448 | hdmi_show_short_audio_desc(codec, e->sad + i); |
449 | } | 449 | } |
450 | 450 | ||
451 | #ifdef CONFIG_PROC_FS | 451 | #ifdef CONFIG_SND_PROC_FS |
452 | 452 | ||
453 | static void hdmi_print_sad_info(int i, struct cea_sad *a, | 453 | static void hdmi_print_sad_info(int i, struct cea_sad *a, |
454 | struct snd_info_buffer *buffer) | 454 | struct snd_info_buffer *buffer) |
@@ -586,7 +586,7 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld, | |||
586 | } | 586 | } |
587 | } | 587 | } |
588 | } | 588 | } |
589 | #endif /* CONFIG_PROC_FS */ | 589 | #endif /* CONFIG_SND_PROC_FS */ |
590 | 590 | ||
591 | /* update PCM info based on ELD */ | 591 | /* update PCM info based on ELD */ |
592 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, | 592 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 3d2597b7037b..b077bb644434 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -844,8 +844,16 @@ static hda_nid_t path_power_update(struct hda_codec *codec, | |||
844 | snd_hda_codec_write(codec, nid, 0, | 844 | snd_hda_codec_write(codec, nid, 0, |
845 | AC_VERB_SET_POWER_STATE, state); | 845 | AC_VERB_SET_POWER_STATE, state); |
846 | changed = nid; | 846 | changed = nid; |
847 | /* all known codecs seem to be capable to handl | ||
848 | * widgets state even in D3, so far. | ||
849 | * if any new codecs need to restore the widget | ||
850 | * states after D0 transition, call the function | ||
851 | * below. | ||
852 | */ | ||
853 | #if 0 /* disabled */ | ||
847 | if (state == AC_PWRST_D0) | 854 | if (state == AC_PWRST_D0) |
848 | snd_hdac_regmap_sync_node(&codec->core, nid); | 855 | snd_hdac_regmap_sync_node(&codec->core, nid); |
856 | #endif | ||
849 | } | 857 | } |
850 | } | 858 | } |
851 | return changed; | 859 | return changed; |
@@ -3259,7 +3267,8 @@ static int create_input_ctls(struct hda_codec *codec) | |||
3259 | val = PIN_IN; | 3267 | val = PIN_IN; |
3260 | if (cfg->inputs[i].type == AUTO_PIN_MIC) | 3268 | if (cfg->inputs[i].type == AUTO_PIN_MIC) |
3261 | val |= snd_hda_get_default_vref(codec, pin); | 3269 | val |= snd_hda_get_default_vref(codec, pin); |
3262 | if (pin != spec->hp_mic_pin) | 3270 | if (pin != spec->hp_mic_pin && |
3271 | !snd_hda_codec_get_pin_target(codec, pin)) | ||
3263 | set_pin_target(codec, pin, val, false); | 3272 | set_pin_target(codec, pin, val, false); |
3264 | 3273 | ||
3265 | if (mixer) { | 3274 | if (mixer) { |
@@ -4917,9 +4926,12 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
4917 | dig_only: | 4926 | dig_only: |
4918 | parse_digital(codec); | 4927 | parse_digital(codec); |
4919 | 4928 | ||
4920 | if (spec->power_down_unused || codec->power_save_node) | 4929 | if (spec->power_down_unused || codec->power_save_node) { |
4921 | if (!codec->power_filter) | 4930 | if (!codec->power_filter) |
4922 | codec->power_filter = snd_hda_gen_path_power_filter; | 4931 | codec->power_filter = snd_hda_gen_path_power_filter; |
4932 | if (!codec->patch_ops.stream_pm) | ||
4933 | codec->patch_ops.stream_pm = snd_hda_gen_stream_pm; | ||
4934 | } | ||
4923 | 4935 | ||
4924 | if (!spec->no_analog && spec->beep_nid) { | 4936 | if (!spec->no_analog && spec->beep_nid) { |
4925 | err = snd_hda_attach_beep_device(codec, spec->beep_nid); | 4937 | err = snd_hda_attach_beep_device(codec, spec->beep_nid); |
@@ -5163,7 +5175,7 @@ static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
5163 | int err = 0; | 5175 | int err = 0; |
5164 | 5176 | ||
5165 | mutex_lock(&spec->pcm_mutex); | 5177 | mutex_lock(&spec->pcm_mutex); |
5166 | if (!spec->indep_hp_enabled) | 5178 | if (spec->indep_hp && !spec->indep_hp_enabled) |
5167 | err = -EBUSY; | 5179 | err = -EBUSY; |
5168 | else | 5180 | else |
5169 | spec->active_streams |= 1 << STREAM_INDEP_HP; | 5181 | spec->active_streams |= 1 << STREAM_INDEP_HP; |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c deleted file mode 100644 index 3052a2b095f7..000000000000 --- a/sound/pci/hda/hda_i915.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * hda_i915.c - routines for Haswell HDA controller power well support | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the Free | ||
6 | * Software Foundation; either version 2 of the License, or (at your option) | ||
7 | * any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software Foundation, | ||
16 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/component.h> | ||
23 | #include <drm/i915_component.h> | ||
24 | #include <sound/core.h> | ||
25 | #include "hda_controller.h" | ||
26 | #include "hda_intel.h" | ||
27 | |||
28 | /* Intel HSW/BDW display HDA controller Extended Mode registers. | ||
29 | * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display | ||
30 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N | ||
31 | * The values will be lost when the display power well is disabled. | ||
32 | */ | ||
33 | #define AZX_REG_EM4 0x100c | ||
34 | #define AZX_REG_EM5 0x1010 | ||
35 | |||
36 | int hda_display_power(struct hda_intel *hda, bool enable) | ||
37 | { | ||
38 | struct i915_audio_component *acomp = &hda->audio_component; | ||
39 | |||
40 | if (!acomp->ops) | ||
41 | return -ENODEV; | ||
42 | |||
43 | dev_dbg(&hda->chip.pci->dev, "display power %s\n", | ||
44 | enable ? "enable" : "disable"); | ||
45 | if (enable) | ||
46 | acomp->ops->get_power(acomp->dev); | ||
47 | else | ||
48 | acomp->ops->put_power(acomp->dev); | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void haswell_set_bclk(struct hda_intel *hda) | ||
54 | { | ||
55 | int cdclk_freq; | ||
56 | unsigned int bclk_m, bclk_n; | ||
57 | struct i915_audio_component *acomp = &hda->audio_component; | ||
58 | struct pci_dev *pci = hda->chip.pci; | ||
59 | |||
60 | /* Only Haswell/Broadwell need set BCLK */ | ||
61 | if (pci->device != 0x0a0c && pci->device != 0x0c0c | ||
62 | && pci->device != 0x0d0c && pci->device != 0x160c) | ||
63 | return; | ||
64 | |||
65 | if (!acomp->ops) | ||
66 | return; | ||
67 | |||
68 | cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev); | ||
69 | switch (cdclk_freq) { | ||
70 | case 337500: | ||
71 | bclk_m = 16; | ||
72 | bclk_n = 225; | ||
73 | break; | ||
74 | |||
75 | case 450000: | ||
76 | default: /* default CDCLK 450MHz */ | ||
77 | bclk_m = 4; | ||
78 | bclk_n = 75; | ||
79 | break; | ||
80 | |||
81 | case 540000: | ||
82 | bclk_m = 4; | ||
83 | bclk_n = 90; | ||
84 | break; | ||
85 | |||
86 | case 675000: | ||
87 | bclk_m = 8; | ||
88 | bclk_n = 225; | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | azx_writew(&hda->chip, EM4, bclk_m); | ||
93 | azx_writew(&hda->chip, EM5, bclk_n); | ||
94 | } | ||
95 | |||
96 | static int hda_component_master_bind(struct device *dev) | ||
97 | { | ||
98 | struct snd_card *card = dev_get_drvdata(dev); | ||
99 | struct azx *chip = card->private_data; | ||
100 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
101 | struct i915_audio_component *acomp = &hda->audio_component; | ||
102 | int ret; | ||
103 | |||
104 | ret = component_bind_all(dev, acomp); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | |||
108 | if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && | ||
109 | acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { | ||
110 | ret = -EINVAL; | ||
111 | goto out_unbind; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Atm, we don't support dynamic unbinding initiated by the child | ||
116 | * component, so pin its containing module until we unbind. | ||
117 | */ | ||
118 | if (!try_module_get(acomp->ops->owner)) { | ||
119 | ret = -ENODEV; | ||
120 | goto out_unbind; | ||
121 | } | ||
122 | |||
123 | return 0; | ||
124 | |||
125 | out_unbind: | ||
126 | component_unbind_all(dev, acomp); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static void hda_component_master_unbind(struct device *dev) | ||
132 | { | ||
133 | struct snd_card *card = dev_get_drvdata(dev); | ||
134 | struct azx *chip = card->private_data; | ||
135 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
136 | struct i915_audio_component *acomp = &hda->audio_component; | ||
137 | |||
138 | module_put(acomp->ops->owner); | ||
139 | component_unbind_all(dev, acomp); | ||
140 | WARN_ON(acomp->ops || acomp->dev); | ||
141 | } | ||
142 | |||
143 | static const struct component_master_ops hda_component_master_ops = { | ||
144 | .bind = hda_component_master_bind, | ||
145 | .unbind = hda_component_master_unbind, | ||
146 | }; | ||
147 | |||
148 | static int hda_component_master_match(struct device *dev, void *data) | ||
149 | { | ||
150 | /* i915 is the only supported component */ | ||
151 | return !strcmp(dev->driver->name, "i915"); | ||
152 | } | ||
153 | |||
154 | int hda_i915_init(struct hda_intel *hda) | ||
155 | { | ||
156 | struct component_match *match = NULL; | ||
157 | struct device *dev = &hda->chip.pci->dev; | ||
158 | struct i915_audio_component *acomp = &hda->audio_component; | ||
159 | int ret; | ||
160 | |||
161 | component_match_add(dev, &match, hda_component_master_match, hda); | ||
162 | ret = component_master_add_with_match(dev, &hda_component_master_ops, | ||
163 | match); | ||
164 | if (ret < 0) | ||
165 | goto out_err; | ||
166 | |||
167 | /* | ||
168 | * Atm, we don't support deferring the component binding, so make sure | ||
169 | * i915 is loaded and that the binding successfully completes. | ||
170 | */ | ||
171 | request_module("i915"); | ||
172 | |||
173 | if (!acomp->ops) { | ||
174 | ret = -ENODEV; | ||
175 | goto out_master_del; | ||
176 | } | ||
177 | |||
178 | dev_dbg(dev, "bound to i915 component master\n"); | ||
179 | |||
180 | return 0; | ||
181 | out_master_del: | ||
182 | component_master_del(dev, &hda_component_master_ops); | ||
183 | out_err: | ||
184 | dev_err(dev, "failed to add i915 component master (%d)\n", ret); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | int hda_i915_exit(struct hda_intel *hda) | ||
190 | { | ||
191 | struct device *dev = &hda->chip.pci->dev; | ||
192 | |||
193 | component_master_del(dev, &hda_component_master_ops); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 34040d26c94f..745535d1840a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #endif | 57 | #endif |
58 | #include <sound/core.h> | 58 | #include <sound/core.h> |
59 | #include <sound/initval.h> | 59 | #include <sound/initval.h> |
60 | #include <sound/hdaudio.h> | ||
61 | #include <sound/hda_i915.h> | ||
60 | #include <linux/vgaarb.h> | 62 | #include <linux/vgaarb.h> |
61 | #include <linux/vga_switcheroo.h> | 63 | #include <linux/vga_switcheroo.h> |
62 | #include <linux/firmware.h> | 64 | #include <linux/firmware.h> |
@@ -64,6 +66,9 @@ | |||
64 | #include "hda_controller.h" | 66 | #include "hda_controller.h" |
65 | #include "hda_intel.h" | 67 | #include "hda_intel.h" |
66 | 68 | ||
69 | #define CREATE_TRACE_POINTS | ||
70 | #include "hda_intel_trace.h" | ||
71 | |||
67 | /* position fix mode */ | 72 | /* position fix mode */ |
68 | enum { | 73 | enum { |
69 | POS_FIX_AUTO, | 74 | POS_FIX_AUTO, |
@@ -166,7 +171,7 @@ MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " | |||
166 | 171 | ||
167 | #ifdef CONFIG_PM | 172 | #ifdef CONFIG_PM |
168 | static int param_set_xint(const char *val, const struct kernel_param *kp); | 173 | static int param_set_xint(const char *val, const struct kernel_param *kp); |
169 | static struct kernel_param_ops param_ops_xint = { | 174 | static const struct kernel_param_ops param_ops_xint = { |
170 | .set = param_set_xint, | 175 | .set = param_set_xint, |
171 | .get = param_get_int, | 176 | .get = param_get_int, |
172 | }; | 177 | }; |
@@ -340,6 +345,11 @@ enum { | |||
340 | #define use_vga_switcheroo(chip) 0 | 345 | #define use_vga_switcheroo(chip) 0 |
341 | #endif | 346 | #endif |
342 | 347 | ||
348 | #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ | ||
349 | ((pci)->device == 0x0c0c) || \ | ||
350 | ((pci)->device == 0x0d0c) || \ | ||
351 | ((pci)->device == 0x160c)) | ||
352 | |||
343 | static char *driver_short_names[] = { | 353 | static char *driver_short_names[] = { |
344 | [AZX_DRIVER_ICH] = "HDA Intel", | 354 | [AZX_DRIVER_ICH] = "HDA Intel", |
345 | [AZX_DRIVER_PCH] = "HDA Intel PCH", | 355 | [AZX_DRIVER_PCH] = "HDA Intel PCH", |
@@ -491,11 +501,22 @@ static void azx_init_pci(struct azx *chip) | |||
491 | } | 501 | } |
492 | } | 502 | } |
493 | 503 | ||
504 | static void hda_intel_init_chip(struct azx *chip, bool full_reset) | ||
505 | { | ||
506 | struct hdac_bus *bus = azx_bus(chip); | ||
507 | |||
508 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | ||
509 | snd_hdac_set_codec_wakeup(bus, true); | ||
510 | azx_init_chip(chip, full_reset); | ||
511 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | ||
512 | snd_hdac_set_codec_wakeup(bus, false); | ||
513 | } | ||
514 | |||
494 | /* calculate runtime delay from LPIB */ | 515 | /* calculate runtime delay from LPIB */ |
495 | static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, | 516 | static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, |
496 | unsigned int pos) | 517 | unsigned int pos) |
497 | { | 518 | { |
498 | struct snd_pcm_substream *substream = azx_dev->substream; | 519 | struct snd_pcm_substream *substream = azx_dev->core.substream; |
499 | int stream = substream->stream; | 520 | int stream = substream->stream; |
500 | unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev); | 521 | unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev); |
501 | int delay; | 522 | int delay; |
@@ -505,16 +526,16 @@ static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, | |||
505 | else | 526 | else |
506 | delay = lpib_pos - pos; | 527 | delay = lpib_pos - pos; |
507 | if (delay < 0) { | 528 | if (delay < 0) { |
508 | if (delay >= azx_dev->delay_negative_threshold) | 529 | if (delay >= azx_dev->core.delay_negative_threshold) |
509 | delay = 0; | 530 | delay = 0; |
510 | else | 531 | else |
511 | delay += azx_dev->bufsize; | 532 | delay += azx_dev->core.bufsize; |
512 | } | 533 | } |
513 | 534 | ||
514 | if (delay >= azx_dev->period_bytes) { | 535 | if (delay >= azx_dev->core.period_bytes) { |
515 | dev_info(chip->card->dev, | 536 | dev_info(chip->card->dev, |
516 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | 537 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", |
517 | delay, azx_dev->period_bytes); | 538 | delay, azx_dev->core.period_bytes); |
518 | delay = 0; | 539 | delay = 0; |
519 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | 540 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; |
520 | chip->get_delay[stream] = NULL; | 541 | chip->get_delay[stream] = NULL; |
@@ -543,6 +564,14 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
543 | return 0; | 564 | return 0; |
544 | } | 565 | } |
545 | 566 | ||
567 | /* Enable/disable i915 display power for the link */ | ||
568 | static int azx_intel_link_power(struct azx *chip, bool enable) | ||
569 | { | ||
570 | struct hdac_bus *bus = azx_bus(chip); | ||
571 | |||
572 | return snd_hdac_display_power(bus, enable); | ||
573 | } | ||
574 | |||
546 | /* | 575 | /* |
547 | * Check whether the current DMA position is acceptable for updating | 576 | * Check whether the current DMA position is acceptable for updating |
548 | * periods. Returns non-zero if it's OK. | 577 | * periods. Returns non-zero if it's OK. |
@@ -554,13 +583,13 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
554 | */ | 583 | */ |
555 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | 584 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) |
556 | { | 585 | { |
557 | struct snd_pcm_substream *substream = azx_dev->substream; | 586 | struct snd_pcm_substream *substream = azx_dev->core.substream; |
558 | int stream = substream->stream; | 587 | int stream = substream->stream; |
559 | u32 wallclk; | 588 | u32 wallclk; |
560 | unsigned int pos; | 589 | unsigned int pos; |
561 | 590 | ||
562 | wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; | 591 | wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk; |
563 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) | 592 | if (wallclk < (azx_dev->core.period_wallclk * 2) / 3) |
564 | return -1; /* bogus (too early) interrupt */ | 593 | return -1; /* bogus (too early) interrupt */ |
565 | 594 | ||
566 | if (chip->get_position[stream]) | 595 | if (chip->get_position[stream]) |
@@ -571,6 +600,9 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
571 | dev_info(chip->card->dev, | 600 | dev_info(chip->card->dev, |
572 | "Invalid position buffer, using LPIB read method instead.\n"); | 601 | "Invalid position buffer, using LPIB read method instead.\n"); |
573 | chip->get_position[stream] = azx_get_pos_lpib; | 602 | chip->get_position[stream] = azx_get_pos_lpib; |
603 | if (chip->get_position[0] == azx_get_pos_lpib && | ||
604 | chip->get_position[1] == azx_get_pos_lpib) | ||
605 | azx_bus(chip)->use_posbuf = false; | ||
574 | pos = azx_get_pos_lpib(chip, azx_dev); | 606 | pos = azx_get_pos_lpib(chip, azx_dev); |
575 | chip->get_delay[stream] = NULL; | 607 | chip->get_delay[stream] = NULL; |
576 | } else { | 608 | } else { |
@@ -580,17 +612,17 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
580 | } | 612 | } |
581 | } | 613 | } |
582 | 614 | ||
583 | if (pos >= azx_dev->bufsize) | 615 | if (pos >= azx_dev->core.bufsize) |
584 | pos = 0; | 616 | pos = 0; |
585 | 617 | ||
586 | if (WARN_ONCE(!azx_dev->period_bytes, | 618 | if (WARN_ONCE(!azx_dev->core.period_bytes, |
587 | "hda-intel: zero azx_dev->period_bytes")) | 619 | "hda-intel: zero azx_dev->period_bytes")) |
588 | return -1; /* this shouldn't happen! */ | 620 | return -1; /* this shouldn't happen! */ |
589 | if (wallclk < (azx_dev->period_wallclk * 5) / 4 && | 621 | if (wallclk < (azx_dev->core.period_wallclk * 5) / 4 && |
590 | pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) | 622 | pos % azx_dev->core.period_bytes > azx_dev->core.period_bytes / 2) |
591 | /* NG - it's below the first next period boundary */ | 623 | /* NG - it's below the first next period boundary */ |
592 | return chip->bdl_pos_adj[chip->dev_index] ? 0 : -1; | 624 | return chip->bdl_pos_adj[chip->dev_index] ? 0 : -1; |
593 | azx_dev->start_wallclk += wallclk; | 625 | azx_dev->core.start_wallclk += wallclk; |
594 | return 1; /* OK, it's fine */ | 626 | return 1; /* OK, it's fine */ |
595 | } | 627 | } |
596 | 628 | ||
@@ -601,7 +633,9 @@ static void azx_irq_pending_work(struct work_struct *work) | |||
601 | { | 633 | { |
602 | struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work); | 634 | struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work); |
603 | struct azx *chip = &hda->chip; | 635 | struct azx *chip = &hda->chip; |
604 | int i, pending, ok; | 636 | struct hdac_bus *bus = azx_bus(chip); |
637 | struct hdac_stream *s; | ||
638 | int pending, ok; | ||
605 | 639 | ||
606 | if (!hda->irq_pending_warned) { | 640 | if (!hda->irq_pending_warned) { |
607 | dev_info(chip->card->dev, | 641 | dev_info(chip->card->dev, |
@@ -612,25 +646,25 @@ static void azx_irq_pending_work(struct work_struct *work) | |||
612 | 646 | ||
613 | for (;;) { | 647 | for (;;) { |
614 | pending = 0; | 648 | pending = 0; |
615 | spin_lock_irq(&chip->reg_lock); | 649 | spin_lock_irq(&bus->reg_lock); |
616 | for (i = 0; i < chip->num_streams; i++) { | 650 | list_for_each_entry(s, &bus->stream_list, list) { |
617 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | 651 | struct azx_dev *azx_dev = stream_to_azx_dev(s); |
618 | if (!azx_dev->irq_pending || | 652 | if (!azx_dev->irq_pending || |
619 | !azx_dev->substream || | 653 | !s->substream || |
620 | !azx_dev->running) | 654 | !s->running) |
621 | continue; | 655 | continue; |
622 | ok = azx_position_ok(chip, azx_dev); | 656 | ok = azx_position_ok(chip, azx_dev); |
623 | if (ok > 0) { | 657 | if (ok > 0) { |
624 | azx_dev->irq_pending = 0; | 658 | azx_dev->irq_pending = 0; |
625 | spin_unlock(&chip->reg_lock); | 659 | spin_unlock(&bus->reg_lock); |
626 | snd_pcm_period_elapsed(azx_dev->substream); | 660 | snd_pcm_period_elapsed(s->substream); |
627 | spin_lock(&chip->reg_lock); | 661 | spin_lock(&bus->reg_lock); |
628 | } else if (ok < 0) { | 662 | } else if (ok < 0) { |
629 | pending = 0; /* too early */ | 663 | pending = 0; /* too early */ |
630 | } else | 664 | } else |
631 | pending++; | 665 | pending++; |
632 | } | 666 | } |
633 | spin_unlock_irq(&chip->reg_lock); | 667 | spin_unlock_irq(&bus->reg_lock); |
634 | if (!pending) | 668 | if (!pending) |
635 | return; | 669 | return; |
636 | msleep(1); | 670 | msleep(1); |
@@ -640,16 +674,21 @@ static void azx_irq_pending_work(struct work_struct *work) | |||
640 | /* clear irq_pending flags and assure no on-going workq */ | 674 | /* clear irq_pending flags and assure no on-going workq */ |
641 | static void azx_clear_irq_pending(struct azx *chip) | 675 | static void azx_clear_irq_pending(struct azx *chip) |
642 | { | 676 | { |
643 | int i; | 677 | struct hdac_bus *bus = azx_bus(chip); |
678 | struct hdac_stream *s; | ||
644 | 679 | ||
645 | spin_lock_irq(&chip->reg_lock); | 680 | spin_lock_irq(&bus->reg_lock); |
646 | for (i = 0; i < chip->num_streams; i++) | 681 | list_for_each_entry(s, &bus->stream_list, list) { |
647 | chip->azx_dev[i].irq_pending = 0; | 682 | struct azx_dev *azx_dev = stream_to_azx_dev(s); |
648 | spin_unlock_irq(&chip->reg_lock); | 683 | azx_dev->irq_pending = 0; |
684 | } | ||
685 | spin_unlock_irq(&bus->reg_lock); | ||
649 | } | 686 | } |
650 | 687 | ||
651 | static int azx_acquire_irq(struct azx *chip, int do_disconnect) | 688 | static int azx_acquire_irq(struct azx *chip, int do_disconnect) |
652 | { | 689 | { |
690 | struct hdac_bus *bus = azx_bus(chip); | ||
691 | |||
653 | if (request_irq(chip->pci->irq, azx_interrupt, | 692 | if (request_irq(chip->pci->irq, azx_interrupt, |
654 | chip->msi ? 0 : IRQF_SHARED, | 693 | chip->msi ? 0 : IRQF_SHARED, |
655 | KBUILD_MODNAME, chip)) { | 694 | KBUILD_MODNAME, chip)) { |
@@ -660,7 +699,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
660 | snd_card_disconnect(chip->card); | 699 | snd_card_disconnect(chip->card); |
661 | return -1; | 700 | return -1; |
662 | } | 701 | } |
663 | chip->irq = chip->pci->irq; | 702 | bus->irq = chip->pci->irq; |
664 | pci_intx(chip->pci, !chip->msi); | 703 | pci_intx(chip->pci, !chip->msi); |
665 | return 0; | 704 | return 0; |
666 | } | 705 | } |
@@ -673,8 +712,8 @@ static unsigned int azx_via_get_position(struct azx *chip, | |||
673 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | 712 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; |
674 | unsigned int fifo_size; | 713 | unsigned int fifo_size; |
675 | 714 | ||
676 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | 715 | link_pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev)); |
677 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 716 | if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
678 | /* Playback, no problem using link position */ | 717 | /* Playback, no problem using link position */ |
679 | return link_pos; | 718 | return link_pos; |
680 | } | 719 | } |
@@ -683,13 +722,14 @@ static unsigned int azx_via_get_position(struct azx *chip, | |||
683 | /* For new chipset, | 722 | /* For new chipset, |
684 | * use mod to get the DMA position just like old chipset | 723 | * use mod to get the DMA position just like old chipset |
685 | */ | 724 | */ |
686 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | 725 | mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf); |
687 | mod_dma_pos %= azx_dev->period_bytes; | 726 | mod_dma_pos %= azx_dev->core.period_bytes; |
688 | 727 | ||
689 | /* azx_dev->fifo_size can't get FIFO size of in stream. | 728 | /* azx_dev->fifo_size can't get FIFO size of in stream. |
690 | * Get from base address + offset. | 729 | * Get from base address + offset. |
691 | */ | 730 | */ |
692 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | 731 | fifo_size = readw(azx_bus(chip)->remap_addr + |
732 | VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
693 | 733 | ||
694 | if (azx_dev->insufficient) { | 734 | if (azx_dev->insufficient) { |
695 | /* Link position never gather than FIFO size */ | 735 | /* Link position never gather than FIFO size */ |
@@ -700,20 +740,20 @@ static unsigned int azx_via_get_position(struct azx *chip, | |||
700 | } | 740 | } |
701 | 741 | ||
702 | if (link_pos <= fifo_size) | 742 | if (link_pos <= fifo_size) |
703 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | 743 | mini_pos = azx_dev->core.bufsize + link_pos - fifo_size; |
704 | else | 744 | else |
705 | mini_pos = link_pos - fifo_size; | 745 | mini_pos = link_pos - fifo_size; |
706 | 746 | ||
707 | /* Find nearest previous boudary */ | 747 | /* Find nearest previous boudary */ |
708 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | 748 | mod_mini_pos = mini_pos % azx_dev->core.period_bytes; |
709 | mod_link_pos = link_pos % azx_dev->period_bytes; | 749 | mod_link_pos = link_pos % azx_dev->core.period_bytes; |
710 | if (mod_link_pos >= fifo_size) | 750 | if (mod_link_pos >= fifo_size) |
711 | bound_pos = link_pos - mod_link_pos; | 751 | bound_pos = link_pos - mod_link_pos; |
712 | else if (mod_dma_pos >= mod_mini_pos) | 752 | else if (mod_dma_pos >= mod_mini_pos) |
713 | bound_pos = mini_pos - mod_mini_pos; | 753 | bound_pos = mini_pos - mod_mini_pos; |
714 | else { | 754 | else { |
715 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | 755 | bound_pos = mini_pos - mod_mini_pos + azx_dev->core.period_bytes; |
716 | if (bound_pos >= azx_dev->bufsize) | 756 | if (bound_pos >= azx_dev->core.bufsize) |
717 | bound_pos = 0; | 757 | bound_pos = 0; |
718 | } | 758 | } |
719 | 759 | ||
@@ -755,9 +795,9 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
755 | mutex_lock(&card_list_lock); | 795 | mutex_lock(&card_list_lock); |
756 | list_for_each_entry(hda, &card_list, list) { | 796 | list_for_each_entry(hda, &card_list, list) { |
757 | chip = &hda->chip; | 797 | chip = &hda->chip; |
758 | if (!chip->bus || chip->disabled) | 798 | if (!hda->probe_continued || chip->disabled) |
759 | continue; | 799 | continue; |
760 | snd_hda_set_power_save(chip->bus, power_save * 1000); | 800 | snd_hda_set_power_save(&chip->bus, power_save * 1000); |
761 | } | 801 | } |
762 | mutex_unlock(&card_list_lock); | 802 | mutex_unlock(&card_list_lock); |
763 | return 0; | 803 | return 0; |
@@ -767,6 +807,50 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
767 | #define azx_del_card_list(chip) /* NOP */ | 807 | #define azx_del_card_list(chip) /* NOP */ |
768 | #endif /* CONFIG_PM */ | 808 | #endif /* CONFIG_PM */ |
769 | 809 | ||
810 | /* Intel HSW/BDW display HDA controller is in GPU. Both its power and link BCLK | ||
811 | * depends on GPU. Two Extended Mode registers EM4 (M value) and EM5 (N Value) | ||
812 | * are used to convert CDClk (Core Display Clock) to 24MHz BCLK: | ||
813 | * BCLK = CDCLK * M / N | ||
814 | * The values will be lost when the display power well is disabled and need to | ||
815 | * be restored to avoid abnormal playback speed. | ||
816 | */ | ||
817 | static void haswell_set_bclk(struct hda_intel *hda) | ||
818 | { | ||
819 | struct azx *chip = &hda->chip; | ||
820 | int cdclk_freq; | ||
821 | unsigned int bclk_m, bclk_n; | ||
822 | |||
823 | if (!hda->need_i915_power) | ||
824 | return; | ||
825 | |||
826 | cdclk_freq = snd_hdac_get_display_clk(azx_bus(chip)); | ||
827 | switch (cdclk_freq) { | ||
828 | case 337500: | ||
829 | bclk_m = 16; | ||
830 | bclk_n = 225; | ||
831 | break; | ||
832 | |||
833 | case 450000: | ||
834 | default: /* default CDCLK 450MHz */ | ||
835 | bclk_m = 4; | ||
836 | bclk_n = 75; | ||
837 | break; | ||
838 | |||
839 | case 540000: | ||
840 | bclk_m = 4; | ||
841 | bclk_n = 90; | ||
842 | break; | ||
843 | |||
844 | case 675000: | ||
845 | bclk_m = 8; | ||
846 | bclk_n = 225; | ||
847 | break; | ||
848 | } | ||
849 | |||
850 | azx_writew(chip, HSW_EM4, bclk_m); | ||
851 | azx_writew(chip, HSW_EM5, bclk_n); | ||
852 | } | ||
853 | |||
770 | #if defined(CONFIG_PM_SLEEP) || defined(SUPPORT_VGA_SWITCHEROO) | 854 | #if defined(CONFIG_PM_SLEEP) || defined(SUPPORT_VGA_SWITCHEROO) |
771 | /* | 855 | /* |
772 | * power management | 856 | * power management |
@@ -776,6 +860,7 @@ static int azx_suspend(struct device *dev) | |||
776 | struct snd_card *card = dev_get_drvdata(dev); | 860 | struct snd_card *card = dev_get_drvdata(dev); |
777 | struct azx *chip; | 861 | struct azx *chip; |
778 | struct hda_intel *hda; | 862 | struct hda_intel *hda; |
863 | struct hdac_bus *bus; | ||
779 | 864 | ||
780 | if (!card) | 865 | if (!card) |
781 | return 0; | 866 | return 0; |
@@ -785,19 +870,23 @@ static int azx_suspend(struct device *dev) | |||
785 | if (chip->disabled || hda->init_failed) | 870 | if (chip->disabled || hda->init_failed) |
786 | return 0; | 871 | return 0; |
787 | 872 | ||
873 | bus = azx_bus(chip); | ||
788 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 874 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
789 | azx_clear_irq_pending(chip); | 875 | azx_clear_irq_pending(chip); |
790 | azx_stop_chip(chip); | 876 | azx_stop_chip(chip); |
791 | azx_enter_link_reset(chip); | 877 | azx_enter_link_reset(chip); |
792 | if (chip->irq >= 0) { | 878 | if (bus->irq >= 0) { |
793 | free_irq(chip->irq, chip); | 879 | free_irq(bus->irq, chip); |
794 | chip->irq = -1; | 880 | bus->irq = -1; |
795 | } | 881 | } |
796 | 882 | ||
797 | if (chip->msi) | 883 | if (chip->msi) |
798 | pci_disable_msi(chip->pci); | 884 | pci_disable_msi(chip->pci); |
799 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 885 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
800 | hda_display_power(hda, false); | 886 | && hda->need_i915_power) |
887 | snd_hdac_display_power(bus, false); | ||
888 | |||
889 | trace_azx_suspend(chip); | ||
801 | return 0; | 890 | return 0; |
802 | } | 891 | } |
803 | 892 | ||
@@ -816,8 +905,9 @@ static int azx_resume(struct device *dev) | |||
816 | if (chip->disabled || hda->init_failed) | 905 | if (chip->disabled || hda->init_failed) |
817 | return 0; | 906 | return 0; |
818 | 907 | ||
819 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 908 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
820 | hda_display_power(hda, true); | 909 | && hda->need_i915_power) { |
910 | snd_hdac_display_power(azx_bus(chip), true); | ||
821 | haswell_set_bclk(hda); | 911 | haswell_set_bclk(hda); |
822 | } | 912 | } |
823 | if (chip->msi) | 913 | if (chip->msi) |
@@ -827,9 +917,11 @@ static int azx_resume(struct device *dev) | |||
827 | return -EIO; | 917 | return -EIO; |
828 | azx_init_pci(chip); | 918 | azx_init_pci(chip); |
829 | 919 | ||
830 | azx_init_chip(chip, true); | 920 | hda_intel_init_chip(chip, true); |
831 | 921 | ||
832 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 922 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
923 | |||
924 | trace_azx_resume(chip); | ||
833 | return 0; | 925 | return 0; |
834 | } | 926 | } |
835 | #endif /* CONFIG_PM_SLEEP || SUPPORT_VGA_SWITCHEROO */ | 927 | #endif /* CONFIG_PM_SLEEP || SUPPORT_VGA_SWITCHEROO */ |
@@ -859,9 +951,11 @@ static int azx_runtime_suspend(struct device *dev) | |||
859 | azx_stop_chip(chip); | 951 | azx_stop_chip(chip); |
860 | azx_enter_link_reset(chip); | 952 | azx_enter_link_reset(chip); |
861 | azx_clear_irq_pending(chip); | 953 | azx_clear_irq_pending(chip); |
862 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 954 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
863 | hda_display_power(hda, false); | 955 | && hda->need_i915_power) |
956 | snd_hdac_display_power(azx_bus(chip), false); | ||
864 | 957 | ||
958 | trace_azx_runtime_suspend(chip); | ||
865 | return 0; | 959 | return 0; |
866 | } | 960 | } |
867 | 961 | ||
@@ -870,7 +964,7 @@ static int azx_runtime_resume(struct device *dev) | |||
870 | struct snd_card *card = dev_get_drvdata(dev); | 964 | struct snd_card *card = dev_get_drvdata(dev); |
871 | struct azx *chip; | 965 | struct azx *chip; |
872 | struct hda_intel *hda; | 966 | struct hda_intel *hda; |
873 | struct hda_bus *bus; | 967 | struct hdac_bus *bus; |
874 | struct hda_codec *codec; | 968 | struct hda_codec *codec; |
875 | int status; | 969 | int status; |
876 | 970 | ||
@@ -885,20 +979,24 @@ static int azx_runtime_resume(struct device *dev) | |||
885 | if (!azx_has_pm_runtime(chip)) | 979 | if (!azx_has_pm_runtime(chip)) |
886 | return 0; | 980 | return 0; |
887 | 981 | ||
888 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 982 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
889 | hda_display_power(hda, true); | 983 | && hda->need_i915_power) { |
984 | bus = azx_bus(chip); | ||
985 | snd_hdac_display_power(bus, true); | ||
890 | haswell_set_bclk(hda); | 986 | haswell_set_bclk(hda); |
987 | /* toggle codec wakeup bit for STATESTS read */ | ||
988 | snd_hdac_set_codec_wakeup(bus, true); | ||
989 | snd_hdac_set_codec_wakeup(bus, false); | ||
891 | } | 990 | } |
892 | 991 | ||
893 | /* Read STATESTS before controller reset */ | 992 | /* Read STATESTS before controller reset */ |
894 | status = azx_readw(chip, STATESTS); | 993 | status = azx_readw(chip, STATESTS); |
895 | 994 | ||
896 | azx_init_pci(chip); | 995 | azx_init_pci(chip); |
897 | azx_init_chip(chip, true); | 996 | hda_intel_init_chip(chip, true); |
898 | 997 | ||
899 | bus = chip->bus; | 998 | if (status) { |
900 | if (status && bus) { | 999 | list_for_each_codec(codec, &chip->bus) |
901 | list_for_each_codec(codec, bus) | ||
902 | if (status & (1 << codec->addr)) | 1000 | if (status & (1 << codec->addr)) |
903 | schedule_delayed_work(&codec->jackpoll_work, | 1001 | schedule_delayed_work(&codec->jackpoll_work, |
904 | codec->jackpoll_interval); | 1002 | codec->jackpoll_interval); |
@@ -908,6 +1006,7 @@ static int azx_runtime_resume(struct device *dev) | |||
908 | azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & | 1006 | azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & |
909 | ~STATESTS_INT_MASK); | 1007 | ~STATESTS_INT_MASK); |
910 | 1008 | ||
1009 | trace_azx_runtime_resume(chip); | ||
911 | return 0; | 1010 | return 0; |
912 | } | 1011 | } |
913 | 1012 | ||
@@ -926,7 +1025,7 @@ static int azx_runtime_idle(struct device *dev) | |||
926 | return 0; | 1025 | return 0; |
927 | 1026 | ||
928 | if (!power_save_controller || !azx_has_pm_runtime(chip) || | 1027 | if (!power_save_controller || !azx_has_pm_runtime(chip) || |
929 | chip->bus->core.codec_powered) | 1028 | azx_bus(chip)->codec_powered) |
930 | return -EBUSY; | 1029 | return -EBUSY; |
931 | 1030 | ||
932 | return 0; | 1031 | return 0; |
@@ -964,7 +1063,7 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
964 | if (chip->disabled == disabled) | 1063 | if (chip->disabled == disabled) |
965 | return; | 1064 | return; |
966 | 1065 | ||
967 | if (!chip->bus) { | 1066 | if (!hda->probe_continued) { |
968 | chip->disabled = disabled; | 1067 | chip->disabled = disabled; |
969 | if (!disabled) { | 1068 | if (!disabled) { |
970 | dev_info(chip->card->dev, | 1069 | dev_info(chip->card->dev, |
@@ -985,11 +1084,11 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
985 | * put ourselves there */ | 1084 | * put ourselves there */ |
986 | pci->current_state = PCI_D3cold; | 1085 | pci->current_state = PCI_D3cold; |
987 | chip->disabled = true; | 1086 | chip->disabled = true; |
988 | if (snd_hda_lock_devices(chip->bus)) | 1087 | if (snd_hda_lock_devices(&chip->bus)) |
989 | dev_warn(chip->card->dev, | 1088 | dev_warn(chip->card->dev, |
990 | "Cannot lock devices!\n"); | 1089 | "Cannot lock devices!\n"); |
991 | } else { | 1090 | } else { |
992 | snd_hda_unlock_devices(chip->bus); | 1091 | snd_hda_unlock_devices(&chip->bus); |
993 | pm_runtime_get_noresume(card->dev); | 1092 | pm_runtime_get_noresume(card->dev); |
994 | chip->disabled = false; | 1093 | chip->disabled = false; |
995 | azx_resume(card->dev); | 1094 | azx_resume(card->dev); |
@@ -1006,11 +1105,11 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
1006 | wait_for_completion(&hda->probe_wait); | 1105 | wait_for_completion(&hda->probe_wait); |
1007 | if (hda->init_failed) | 1106 | if (hda->init_failed) |
1008 | return false; | 1107 | return false; |
1009 | if (chip->disabled || !chip->bus) | 1108 | if (chip->disabled || !hda->probe_continued) |
1010 | return true; | 1109 | return true; |
1011 | if (snd_hda_lock_devices(chip->bus)) | 1110 | if (snd_hda_lock_devices(&chip->bus)) |
1012 | return false; | 1111 | return false; |
1013 | snd_hda_unlock_devices(chip->bus); | 1112 | snd_hda_unlock_devices(&chip->bus); |
1014 | return true; | 1113 | return true; |
1015 | } | 1114 | } |
1016 | 1115 | ||
@@ -1043,7 +1142,7 @@ static int register_vga_switcheroo(struct azx *chip) | |||
1043 | */ | 1142 | */ |
1044 | err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, | 1143 | err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, |
1045 | VGA_SWITCHEROO_DIS, | 1144 | VGA_SWITCHEROO_DIS, |
1046 | chip->bus != NULL); | 1145 | hda->probe_continued); |
1047 | if (err < 0) | 1146 | if (err < 0) |
1048 | return err; | 1147 | return err; |
1049 | hda->vga_switcheroo_registered = 1; | 1148 | hda->vga_switcheroo_registered = 1; |
@@ -1066,7 +1165,7 @@ static int azx_free(struct azx *chip) | |||
1066 | { | 1165 | { |
1067 | struct pci_dev *pci = chip->pci; | 1166 | struct pci_dev *pci = chip->pci; |
1068 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 1167 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
1069 | int i; | 1168 | struct hdac_bus *bus = azx_bus(chip); |
1070 | 1169 | ||
1071 | if (azx_has_pm_runtime(chip) && chip->running) | 1170 | if (azx_has_pm_runtime(chip) && chip->running) |
1072 | pm_runtime_get_noresume(&pci->dev); | 1171 | pm_runtime_get_noresume(&pci->dev); |
@@ -1077,42 +1176,54 @@ static int azx_free(struct azx *chip) | |||
1077 | complete_all(&hda->probe_wait); | 1176 | complete_all(&hda->probe_wait); |
1078 | 1177 | ||
1079 | if (use_vga_switcheroo(hda)) { | 1178 | if (use_vga_switcheroo(hda)) { |
1080 | if (chip->disabled && chip->bus) | 1179 | if (chip->disabled && hda->probe_continued) |
1081 | snd_hda_unlock_devices(chip->bus); | 1180 | snd_hda_unlock_devices(&chip->bus); |
1082 | if (hda->vga_switcheroo_registered) | 1181 | if (hda->vga_switcheroo_registered) |
1083 | vga_switcheroo_unregister_client(chip->pci); | 1182 | vga_switcheroo_unregister_client(chip->pci); |
1084 | } | 1183 | } |
1085 | 1184 | ||
1086 | if (chip->initialized) { | 1185 | if (bus->chip_init) { |
1087 | azx_clear_irq_pending(chip); | 1186 | azx_clear_irq_pending(chip); |
1088 | for (i = 0; i < chip->num_streams; i++) | 1187 | azx_stop_all_streams(chip); |
1089 | azx_stream_stop(chip, &chip->azx_dev[i]); | ||
1090 | azx_stop_chip(chip); | 1188 | azx_stop_chip(chip); |
1091 | } | 1189 | } |
1092 | 1190 | ||
1093 | if (chip->irq >= 0) | 1191 | if (bus->irq >= 0) |
1094 | free_irq(chip->irq, (void*)chip); | 1192 | free_irq(bus->irq, (void*)chip); |
1095 | if (chip->msi) | 1193 | if (chip->msi) |
1096 | pci_disable_msi(chip->pci); | 1194 | pci_disable_msi(chip->pci); |
1097 | iounmap(chip->remap_addr); | 1195 | iounmap(bus->remap_addr); |
1098 | 1196 | ||
1099 | azx_free_stream_pages(chip); | 1197 | azx_free_stream_pages(chip); |
1198 | azx_free_streams(chip); | ||
1199 | snd_hdac_bus_exit(bus); | ||
1200 | |||
1100 | if (chip->region_requested) | 1201 | if (chip->region_requested) |
1101 | pci_release_regions(chip->pci); | 1202 | pci_release_regions(chip->pci); |
1203 | |||
1102 | pci_disable_device(chip->pci); | 1204 | pci_disable_device(chip->pci); |
1103 | kfree(chip->azx_dev); | ||
1104 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 1205 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
1105 | release_firmware(chip->fw); | 1206 | release_firmware(chip->fw); |
1106 | #endif | 1207 | #endif |
1208 | |||
1107 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1209 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1108 | hda_display_power(hda, false); | 1210 | if (hda->need_i915_power) |
1109 | hda_i915_exit(hda); | 1211 | snd_hdac_display_power(bus, false); |
1212 | snd_hdac_i915_exit(bus); | ||
1110 | } | 1213 | } |
1111 | kfree(hda); | 1214 | kfree(hda); |
1112 | 1215 | ||
1113 | return 0; | 1216 | return 0; |
1114 | } | 1217 | } |
1115 | 1218 | ||
1219 | static int azx_dev_disconnect(struct snd_device *device) | ||
1220 | { | ||
1221 | struct azx *chip = device->device_data; | ||
1222 | |||
1223 | chip->bus.shutdown = 1; | ||
1224 | return 0; | ||
1225 | } | ||
1226 | |||
1116 | static int azx_dev_free(struct snd_device *device) | 1227 | static int azx_dev_free(struct snd_device *device) |
1117 | { | 1228 | { |
1118 | return azx_free(device->device_data); | 1229 | return azx_free(device->device_data); |
@@ -1279,9 +1390,9 @@ static void check_probe_mask(struct azx *chip, int dev) | |||
1279 | /* check forced option */ | 1390 | /* check forced option */ |
1280 | if (chip->codec_probe_mask != -1 && | 1391 | if (chip->codec_probe_mask != -1 && |
1281 | (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { | 1392 | (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { |
1282 | chip->codec_mask = chip->codec_probe_mask & 0xff; | 1393 | azx_bus(chip)->codec_mask = chip->codec_probe_mask & 0xff; |
1283 | dev_info(chip->card->dev, "codec_mask forced to 0x%x\n", | 1394 | dev_info(chip->card->dev, "codec_mask forced to 0x%x\n", |
1284 | chip->codec_mask); | 1395 | (int)azx_bus(chip)->codec_mask); |
1285 | } | 1396 | } |
1286 | } | 1397 | } |
1287 | 1398 | ||
@@ -1368,12 +1479,15 @@ static void azx_probe_work(struct work_struct *work) | |||
1368 | /* | 1479 | /* |
1369 | * constructor | 1480 | * constructor |
1370 | */ | 1481 | */ |
1482 | static const struct hdac_io_ops pci_hda_io_ops; | ||
1483 | static const struct hda_controller_ops pci_hda_ops; | ||
1484 | |||
1371 | static int azx_create(struct snd_card *card, struct pci_dev *pci, | 1485 | static int azx_create(struct snd_card *card, struct pci_dev *pci, |
1372 | int dev, unsigned int driver_caps, | 1486 | int dev, unsigned int driver_caps, |
1373 | const struct hda_controller_ops *hda_ops, | ||
1374 | struct azx **rchip) | 1487 | struct azx **rchip) |
1375 | { | 1488 | { |
1376 | static struct snd_device_ops ops = { | 1489 | static struct snd_device_ops ops = { |
1490 | .dev_disconnect = azx_dev_disconnect, | ||
1377 | .dev_free = azx_dev_free, | 1491 | .dev_free = azx_dev_free, |
1378 | }; | 1492 | }; |
1379 | struct hda_intel *hda; | 1493 | struct hda_intel *hda; |
@@ -1393,12 +1507,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1393 | } | 1507 | } |
1394 | 1508 | ||
1395 | chip = &hda->chip; | 1509 | chip = &hda->chip; |
1396 | spin_lock_init(&chip->reg_lock); | ||
1397 | mutex_init(&chip->open_mutex); | 1510 | mutex_init(&chip->open_mutex); |
1398 | chip->card = card; | 1511 | chip->card = card; |
1399 | chip->pci = pci; | 1512 | chip->pci = pci; |
1400 | chip->ops = hda_ops; | 1513 | chip->ops = &pci_hda_ops; |
1401 | chip->irq = -1; | ||
1402 | chip->driver_caps = driver_caps; | 1514 | chip->driver_caps = driver_caps; |
1403 | chip->driver_type = driver_caps & 0xff; | 1515 | chip->driver_type = driver_caps & 0xff; |
1404 | check_msi(chip); | 1516 | check_msi(chip); |
@@ -1430,6 +1542,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1430 | } | 1542 | } |
1431 | chip->bdl_pos_adj = bdl_pos_adj; | 1543 | chip->bdl_pos_adj = bdl_pos_adj; |
1432 | 1544 | ||
1545 | err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); | ||
1546 | if (err < 0) { | ||
1547 | kfree(hda); | ||
1548 | pci_disable_device(pci); | ||
1549 | return err; | ||
1550 | } | ||
1551 | |||
1433 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 1552 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
1434 | if (err < 0) { | 1553 | if (err < 0) { |
1435 | dev_err(card->dev, "Error creating device [card]!\n"); | 1554 | dev_err(card->dev, "Error creating device [card]!\n"); |
@@ -1450,6 +1569,7 @@ static int azx_first_init(struct azx *chip) | |||
1450 | int dev = chip->dev_index; | 1569 | int dev = chip->dev_index; |
1451 | struct pci_dev *pci = chip->pci; | 1570 | struct pci_dev *pci = chip->pci; |
1452 | struct snd_card *card = chip->card; | 1571 | struct snd_card *card = chip->card; |
1572 | struct hdac_bus *bus = azx_bus(chip); | ||
1453 | int err; | 1573 | int err; |
1454 | unsigned short gcap; | 1574 | unsigned short gcap; |
1455 | unsigned int dma_bits = 64; | 1575 | unsigned int dma_bits = 64; |
@@ -1469,9 +1589,9 @@ static int azx_first_init(struct azx *chip) | |||
1469 | return err; | 1589 | return err; |
1470 | chip->region_requested = 1; | 1590 | chip->region_requested = 1; |
1471 | 1591 | ||
1472 | chip->addr = pci_resource_start(pci, 0); | 1592 | bus->addr = pci_resource_start(pci, 0); |
1473 | chip->remap_addr = pci_ioremap_bar(pci, 0); | 1593 | bus->remap_addr = pci_ioremap_bar(pci, 0); |
1474 | if (chip->remap_addr == NULL) { | 1594 | if (bus->remap_addr == NULL) { |
1475 | dev_err(card->dev, "ioremap error\n"); | 1595 | dev_err(card->dev, "ioremap error\n"); |
1476 | return -ENXIO; | 1596 | return -ENXIO; |
1477 | } | 1597 | } |
@@ -1489,7 +1609,7 @@ static int azx_first_init(struct azx *chip) | |||
1489 | return -EBUSY; | 1609 | return -EBUSY; |
1490 | 1610 | ||
1491 | pci_set_master(pci); | 1611 | pci_set_master(pci); |
1492 | synchronize_irq(chip->irq); | 1612 | synchronize_irq(bus->irq); |
1493 | 1613 | ||
1494 | gcap = azx_readw(chip, GCAP); | 1614 | gcap = azx_readw(chip, GCAP); |
1495 | dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); | 1615 | dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); |
@@ -1531,11 +1651,11 @@ static int azx_first_init(struct azx *chip) | |||
1531 | /* allow 64bit DMA address if supported by H/W */ | 1651 | /* allow 64bit DMA address if supported by H/W */ |
1532 | if (!(gcap & AZX_GCAP_64OK)) | 1652 | if (!(gcap & AZX_GCAP_64OK)) |
1533 | dma_bits = 32; | 1653 | dma_bits = 32; |
1534 | if (!pci_set_dma_mask(pci, DMA_BIT_MASK(dma_bits))) { | 1654 | if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { |
1535 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(dma_bits)); | 1655 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); |
1536 | } else { | 1656 | } else { |
1537 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); | 1657 | dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); |
1538 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)); | 1658 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); |
1539 | } | 1659 | } |
1540 | 1660 | ||
1541 | /* read number of streams from GCAP register instead of using | 1661 | /* read number of streams from GCAP register instead of using |
@@ -1566,17 +1686,15 @@ static int azx_first_init(struct azx *chip) | |||
1566 | chip->capture_index_offset = 0; | 1686 | chip->capture_index_offset = 0; |
1567 | chip->playback_index_offset = chip->capture_streams; | 1687 | chip->playback_index_offset = chip->capture_streams; |
1568 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 1688 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
1569 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), | ||
1570 | GFP_KERNEL); | ||
1571 | if (!chip->azx_dev) | ||
1572 | return -ENOMEM; | ||
1573 | 1689 | ||
1574 | err = azx_alloc_stream_pages(chip); | 1690 | /* initialize streams */ |
1691 | err = azx_init_streams(chip); | ||
1575 | if (err < 0) | 1692 | if (err < 0) |
1576 | return err; | 1693 | return err; |
1577 | 1694 | ||
1578 | /* initialize streams */ | 1695 | err = azx_alloc_stream_pages(chip); |
1579 | azx_init_stream(chip); | 1696 | if (err < 0) |
1697 | return err; | ||
1580 | 1698 | ||
1581 | /* initialize chip */ | 1699 | /* initialize chip */ |
1582 | azx_init_pci(chip); | 1700 | azx_init_pci(chip); |
@@ -1588,10 +1706,10 @@ static int azx_first_init(struct azx *chip) | |||
1588 | haswell_set_bclk(hda); | 1706 | haswell_set_bclk(hda); |
1589 | } | 1707 | } |
1590 | 1708 | ||
1591 | azx_init_chip(chip, (probe_only[dev] & 2) == 0); | 1709 | hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0); |
1592 | 1710 | ||
1593 | /* codec detection */ | 1711 | /* codec detection */ |
1594 | if (!chip->codec_mask) { | 1712 | if (!azx_bus(chip)->codec_mask) { |
1595 | dev_err(card->dev, "no codecs found!\n"); | 1713 | dev_err(card->dev, "no codecs found!\n"); |
1596 | return -ENODEV; | 1714 | return -ENODEV; |
1597 | } | 1715 | } |
@@ -1601,7 +1719,7 @@ static int azx_first_init(struct azx *chip) | |||
1601 | sizeof(card->shortname)); | 1719 | sizeof(card->shortname)); |
1602 | snprintf(card->longname, sizeof(card->longname), | 1720 | snprintf(card->longname, sizeof(card->longname), |
1603 | "%s at 0x%lx irq %i", | 1721 | "%s at 0x%lx irq %i", |
1604 | card->shortname, chip->addr, chip->irq); | 1722 | card->shortname, bus->addr, bus->irq); |
1605 | 1723 | ||
1606 | return 0; | 1724 | return 0; |
1607 | } | 1725 | } |
@@ -1670,10 +1788,11 @@ static u8 pci_azx_readb(u8 __iomem *addr) | |||
1670 | 1788 | ||
1671 | static int disable_msi_reset_irq(struct azx *chip) | 1789 | static int disable_msi_reset_irq(struct azx *chip) |
1672 | { | 1790 | { |
1791 | struct hdac_bus *bus = azx_bus(chip); | ||
1673 | int err; | 1792 | int err; |
1674 | 1793 | ||
1675 | free_irq(chip->irq, chip); | 1794 | free_irq(bus->irq, chip); |
1676 | chip->irq = -1; | 1795 | bus->irq = -1; |
1677 | pci_disable_msi(chip->pci); | 1796 | pci_disable_msi(chip->pci); |
1678 | chip->msi = 0; | 1797 | chip->msi = 0; |
1679 | err = azx_acquire_irq(chip, 1); | 1798 | err = azx_acquire_irq(chip, 1); |
@@ -1684,15 +1803,16 @@ static int disable_msi_reset_irq(struct azx *chip) | |||
1684 | } | 1803 | } |
1685 | 1804 | ||
1686 | /* DMA page allocation helpers. */ | 1805 | /* DMA page allocation helpers. */ |
1687 | static int dma_alloc_pages(struct azx *chip, | 1806 | static int dma_alloc_pages(struct hdac_bus *bus, |
1688 | int type, | 1807 | int type, |
1689 | size_t size, | 1808 | size_t size, |
1690 | struct snd_dma_buffer *buf) | 1809 | struct snd_dma_buffer *buf) |
1691 | { | 1810 | { |
1811 | struct azx *chip = bus_to_azx(bus); | ||
1692 | int err; | 1812 | int err; |
1693 | 1813 | ||
1694 | err = snd_dma_alloc_pages(type, | 1814 | err = snd_dma_alloc_pages(type, |
1695 | chip->card->dev, | 1815 | bus->dev, |
1696 | size, buf); | 1816 | size, buf); |
1697 | if (err < 0) | 1817 | if (err < 0) |
1698 | return err; | 1818 | return err; |
@@ -1700,8 +1820,10 @@ static int dma_alloc_pages(struct azx *chip, | |||
1700 | return 0; | 1820 | return 0; |
1701 | } | 1821 | } |
1702 | 1822 | ||
1703 | static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf) | 1823 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) |
1704 | { | 1824 | { |
1825 | struct azx *chip = bus_to_azx(bus); | ||
1826 | |||
1705 | mark_pages_wc(chip, buf, false); | 1827 | mark_pages_wc(chip, buf, false); |
1706 | snd_dma_free_pages(buf); | 1828 | snd_dma_free_pages(buf); |
1707 | } | 1829 | } |
@@ -1714,9 +1836,6 @@ static int substream_alloc_pages(struct azx *chip, | |||
1714 | int ret; | 1836 | int ret; |
1715 | 1837 | ||
1716 | mark_runtime_wc(chip, azx_dev, substream, false); | 1838 | mark_runtime_wc(chip, azx_dev, substream, false); |
1717 | azx_dev->bufsize = 0; | ||
1718 | azx_dev->period_bytes = 0; | ||
1719 | azx_dev->format_val = 0; | ||
1720 | ret = snd_pcm_lib_malloc_pages(substream, size); | 1839 | ret = snd_pcm_lib_malloc_pages(substream, size); |
1721 | if (ret < 0) | 1840 | if (ret < 0) |
1722 | return ret; | 1841 | return ret; |
@@ -1743,20 +1862,24 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, | |||
1743 | #endif | 1862 | #endif |
1744 | } | 1863 | } |
1745 | 1864 | ||
1746 | static const struct hda_controller_ops pci_hda_ops = { | 1865 | static const struct hdac_io_ops pci_hda_io_ops = { |
1747 | .reg_writel = pci_azx_writel, | 1866 | .reg_writel = pci_azx_writel, |
1748 | .reg_readl = pci_azx_readl, | 1867 | .reg_readl = pci_azx_readl, |
1749 | .reg_writew = pci_azx_writew, | 1868 | .reg_writew = pci_azx_writew, |
1750 | .reg_readw = pci_azx_readw, | 1869 | .reg_readw = pci_azx_readw, |
1751 | .reg_writeb = pci_azx_writeb, | 1870 | .reg_writeb = pci_azx_writeb, |
1752 | .reg_readb = pci_azx_readb, | 1871 | .reg_readb = pci_azx_readb, |
1753 | .disable_msi_reset_irq = disable_msi_reset_irq, | ||
1754 | .dma_alloc_pages = dma_alloc_pages, | 1872 | .dma_alloc_pages = dma_alloc_pages, |
1755 | .dma_free_pages = dma_free_pages, | 1873 | .dma_free_pages = dma_free_pages, |
1874 | }; | ||
1875 | |||
1876 | static const struct hda_controller_ops pci_hda_ops = { | ||
1877 | .disable_msi_reset_irq = disable_msi_reset_irq, | ||
1756 | .substream_alloc_pages = substream_alloc_pages, | 1878 | .substream_alloc_pages = substream_alloc_pages, |
1757 | .substream_free_pages = substream_free_pages, | 1879 | .substream_free_pages = substream_free_pages, |
1758 | .pcm_mmap_prepare = pcm_mmap_prepare, | 1880 | .pcm_mmap_prepare = pcm_mmap_prepare, |
1759 | .position_check = azx_position_check, | 1881 | .position_check = azx_position_check, |
1882 | .link_power = azx_intel_link_power, | ||
1760 | }; | 1883 | }; |
1761 | 1884 | ||
1762 | static int azx_probe(struct pci_dev *pci, | 1885 | static int azx_probe(struct pci_dev *pci, |
@@ -1783,8 +1906,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1783 | return err; | 1906 | return err; |
1784 | } | 1907 | } |
1785 | 1908 | ||
1786 | err = azx_create(card, pci, dev, pci_id->driver_data, | 1909 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); |
1787 | &pci_hda_ops, &chip); | ||
1788 | if (err < 0) | 1910 | if (err < 0) |
1789 | goto out_free; | 1911 | goto out_free; |
1790 | card->private_data = chip; | 1912 | card->private_data = chip; |
@@ -1846,25 +1968,45 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { | |||
1846 | static int azx_probe_continue(struct azx *chip) | 1968 | static int azx_probe_continue(struct azx *chip) |
1847 | { | 1969 | { |
1848 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 1970 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
1971 | struct hdac_bus *bus = azx_bus(chip); | ||
1849 | struct pci_dev *pci = chip->pci; | 1972 | struct pci_dev *pci = chip->pci; |
1850 | int dev = chip->dev_index; | 1973 | int dev = chip->dev_index; |
1851 | int err; | 1974 | int err; |
1852 | 1975 | ||
1853 | /* Request power well for Haswell HDA controller and codec */ | 1976 | hda->probe_continued = 1; |
1977 | |||
1978 | /* Request display power well for the HDA controller or codec. For | ||
1979 | * Haswell/Broadwell, both the display HDA controller and codec need | ||
1980 | * this power. For other platforms, like Baytrail/Braswell, only the | ||
1981 | * display codec needs the power and it can be released after probe. | ||
1982 | */ | ||
1854 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1983 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1855 | #ifdef CONFIG_SND_HDA_I915 | 1984 | /* HSW/BDW controllers need this power */ |
1856 | err = hda_i915_init(hda); | 1985 | if (CONTROLLER_IN_GPU(pci)) |
1857 | if (err < 0) | 1986 | hda->need_i915_power = 1; |
1858 | goto out_free; | 1987 | |
1859 | err = hda_display_power(hda, true); | 1988 | err = snd_hdac_i915_init(bus); |
1989 | if (err < 0) { | ||
1990 | /* if the controller is bound only with HDMI/DP | ||
1991 | * (for HSW and BDW), we need to abort the probe; | ||
1992 | * for other chips, still continue probing as other | ||
1993 | * codecs can be on the same link. | ||
1994 | */ | ||
1995 | if (CONTROLLER_IN_GPU(pci)) | ||
1996 | goto out_free; | ||
1997 | else | ||
1998 | goto skip_i915; | ||
1999 | } | ||
2000 | |||
2001 | err = snd_hdac_display_power(bus, true); | ||
1860 | if (err < 0) { | 2002 | if (err < 0) { |
1861 | dev_err(chip->card->dev, | 2003 | dev_err(chip->card->dev, |
1862 | "Cannot turn on display power on i915\n"); | 2004 | "Cannot turn on display power on i915\n"); |
1863 | goto out_free; | 2005 | goto i915_power_fail; |
1864 | } | 2006 | } |
1865 | #endif | ||
1866 | } | 2007 | } |
1867 | 2008 | ||
2009 | skip_i915: | ||
1868 | err = azx_first_init(chip); | 2010 | err = azx_first_init(chip); |
1869 | if (err < 0) | 2011 | if (err < 0) |
1870 | goto out_free; | 2012 | goto out_free; |
@@ -1874,17 +2016,13 @@ static int azx_probe_continue(struct azx *chip) | |||
1874 | #endif | 2016 | #endif |
1875 | 2017 | ||
1876 | /* create codec instances */ | 2018 | /* create codec instances */ |
1877 | err = azx_bus_create(chip, model[dev]); | ||
1878 | if (err < 0) | ||
1879 | goto out_free; | ||
1880 | |||
1881 | err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]); | 2019 | err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]); |
1882 | if (err < 0) | 2020 | if (err < 0) |
1883 | goto out_free; | 2021 | goto out_free; |
1884 | 2022 | ||
1885 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 2023 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
1886 | if (chip->fw) { | 2024 | if (chip->fw) { |
1887 | err = snd_hda_load_patch(chip->bus, chip->fw->size, | 2025 | err = snd_hda_load_patch(&chip->bus, chip->fw->size, |
1888 | chip->fw->data); | 2026 | chip->fw->data); |
1889 | if (err < 0) | 2027 | if (err < 0) |
1890 | goto out_free; | 2028 | goto out_free; |
@@ -1906,11 +2044,16 @@ static int azx_probe_continue(struct azx *chip) | |||
1906 | 2044 | ||
1907 | chip->running = 1; | 2045 | chip->running = 1; |
1908 | azx_add_card_list(chip); | 2046 | azx_add_card_list(chip); |
1909 | snd_hda_set_power_save(chip->bus, power_save * 1000); | 2047 | snd_hda_set_power_save(&chip->bus, power_save * 1000); |
1910 | if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) | 2048 | if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) |
1911 | pm_runtime_put_noidle(&pci->dev); | 2049 | pm_runtime_put_noidle(&pci->dev); |
1912 | 2050 | ||
1913 | out_free: | 2051 | out_free: |
2052 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL | ||
2053 | && !hda->need_i915_power) | ||
2054 | snd_hdac_display_power(bus, false); | ||
2055 | |||
2056 | i915_power_fail: | ||
1914 | if (err < 0) | 2057 | if (err < 0) |
1915 | hda->init_failed = 1; | 2058 | hda->init_failed = 1; |
1916 | complete_all(&hda->probe_wait); | 2059 | complete_all(&hda->probe_wait); |
@@ -2037,6 +2180,8 @@ static const struct pci_device_id azx_ids[] = { | |||
2037 | { PCI_DEVICE(0x1022, 0x780d), | 2180 | { PCI_DEVICE(0x1022, 0x780d), |
2038 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, | 2181 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, |
2039 | /* ATI HDMI */ | 2182 | /* ATI HDMI */ |
2183 | { PCI_DEVICE(0x1002, 0x1308), | ||
2184 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | ||
2040 | { PCI_DEVICE(0x1002, 0x793b), | 2185 | { PCI_DEVICE(0x1002, 0x793b), |
2041 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, | 2186 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
2042 | { PCI_DEVICE(0x1002, 0x7919), | 2187 | { PCI_DEVICE(0x1002, 0x7919), |
@@ -2045,6 +2190,8 @@ static const struct pci_device_id azx_ids[] = { | |||
2045 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, | 2190 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
2046 | { PCI_DEVICE(0x1002, 0x970f), | 2191 | { PCI_DEVICE(0x1002, 0x970f), |
2047 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, | 2192 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
2193 | { PCI_DEVICE(0x1002, 0x9840), | ||
2194 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | ||
2048 | { PCI_DEVICE(0x1002, 0xaa00), | 2195 | { PCI_DEVICE(0x1002, 0xaa00), |
2049 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, | 2196 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
2050 | { PCI_DEVICE(0x1002, 0xaa08), | 2197 | { PCI_DEVICE(0x1002, 0xaa08), |
@@ -2089,6 +2236,8 @@ static const struct pci_device_id azx_ids[] = { | |||
2089 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | 2236 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
2090 | { PCI_DEVICE(0x1002, 0xaab0), | 2237 | { PCI_DEVICE(0x1002, 0xaab0), |
2091 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | 2238 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
2239 | { PCI_DEVICE(0x1002, 0xaac8), | ||
2240 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | ||
2092 | /* VIA VT8251/VT8237A */ | 2241 | /* VIA VT8251/VT8237A */ |
2093 | { PCI_DEVICE(0x1106, 0x3288), | 2242 | { PCI_DEVICE(0x1106, 0x3288), |
2094 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, | 2243 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, |
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h index d5231f7216a7..354f0bbed833 100644 --- a/sound/pci/hda/hda_intel.h +++ b/sound/pci/hda/hda_intel.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #ifndef __SOUND_HDA_INTEL_H | 16 | #ifndef __SOUND_HDA_INTEL_H |
17 | #define __SOUND_HDA_INTEL_H | 17 | #define __SOUND_HDA_INTEL_H |
18 | 18 | ||
19 | #include <drm/i915_component.h> | ||
20 | #include "hda_controller.h" | 19 | #include "hda_controller.h" |
21 | 20 | ||
22 | struct hda_intel { | 21 | struct hda_intel { |
@@ -34,6 +33,7 @@ struct hda_intel { | |||
34 | 33 | ||
35 | /* extra flags */ | 34 | /* extra flags */ |
36 | unsigned int irq_pending_warned:1; | 35 | unsigned int irq_pending_warned:1; |
36 | unsigned int probe_continued:1; | ||
37 | 37 | ||
38 | /* VGA-switcheroo setup */ | 38 | /* VGA-switcheroo setup */ |
39 | unsigned int use_vga_switcheroo:1; | 39 | unsigned int use_vga_switcheroo:1; |
@@ -43,29 +43,7 @@ struct hda_intel { | |||
43 | /* secondary power domain for hdmi audio under vga device */ | 43 | /* secondary power domain for hdmi audio under vga device */ |
44 | struct dev_pm_domain hdmi_pm_domain; | 44 | struct dev_pm_domain hdmi_pm_domain; |
45 | 45 | ||
46 | /* i915 component interface */ | 46 | bool need_i915_power:1; /* the hda controller needs i915 power */ |
47 | struct i915_audio_component audio_component; | ||
48 | }; | 47 | }; |
49 | 48 | ||
50 | #ifdef CONFIG_SND_HDA_I915 | ||
51 | int hda_display_power(struct hda_intel *hda, bool enable); | ||
52 | void haswell_set_bclk(struct hda_intel *hda); | ||
53 | int hda_i915_init(struct hda_intel *hda); | ||
54 | int hda_i915_exit(struct hda_intel *hda); | ||
55 | #else | ||
56 | static inline int hda_display_power(struct hda_intel *hda, bool enable) | ||
57 | { | ||
58 | return 0; | ||
59 | } | ||
60 | static inline void haswell_set_bclk(struct hda_intel *hda) { return; } | ||
61 | static inline int hda_i915_init(struct hda_intel *hda) | ||
62 | { | ||
63 | return -ENODEV; | ||
64 | } | ||
65 | static inline int hda_i915_exit(struct hda_intel *hda) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | #endif | 49 | #endif |
diff --git a/sound/pci/hda/hda_intel_trace.h b/sound/pci/hda/hda_intel_trace.h index 7b5e4c2cf9d5..0922d8b1b17d 100644 --- a/sound/pci/hda/hda_intel_trace.h +++ b/sound/pci/hda/hda_intel_trace.h | |||
@@ -7,52 +7,43 @@ | |||
7 | 7 | ||
8 | #include <linux/tracepoint.h> | 8 | #include <linux/tracepoint.h> |
9 | 9 | ||
10 | struct azx; | 10 | DECLARE_EVENT_CLASS(hda_pm, |
11 | struct azx_dev; | 11 | TP_PROTO(struct azx *chip), |
12 | 12 | ||
13 | TRACE_EVENT(azx_pcm_trigger, | 13 | TP_ARGS(chip), |
14 | |||
15 | TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd), | ||
16 | |||
17 | TP_ARGS(chip, dev, cmd), | ||
18 | 14 | ||
19 | TP_STRUCT__entry( | 15 | TP_STRUCT__entry( |
20 | __field( int, card ) | 16 | __field(int, dev_index) |
21 | __field( int, idx ) | ||
22 | __field( int, cmd ) | ||
23 | ), | 17 | ), |
24 | 18 | ||
25 | TP_fast_assign( | 19 | TP_fast_assign( |
26 | __entry->card = (chip)->card->number; | 20 | __entry->dev_index = (chip)->dev_index; |
27 | __entry->idx = (dev)->index; | ||
28 | __entry->cmd = cmd; | ||
29 | ), | 21 | ), |
30 | 22 | ||
31 | TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd) | 23 | TP_printk("card index: %d", __entry->dev_index) |
32 | ); | 24 | ); |
33 | 25 | ||
34 | TRACE_EVENT(azx_get_position, | 26 | DEFINE_EVENT(hda_pm, azx_suspend, |
35 | 27 | TP_PROTO(struct azx *chip), | |
36 | TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay), | 28 | TP_ARGS(chip) |
37 | 29 | ); | |
38 | TP_ARGS(chip, dev, pos, delay), | ||
39 | 30 | ||
40 | TP_STRUCT__entry( | 31 | DEFINE_EVENT(hda_pm, azx_resume, |
41 | __field( int, card ) | 32 | TP_PROTO(struct azx *chip), |
42 | __field( int, idx ) | 33 | TP_ARGS(chip) |
43 | __field( unsigned int, pos ) | 34 | ); |
44 | __field( unsigned int, delay ) | ||
45 | ), | ||
46 | 35 | ||
47 | TP_fast_assign( | 36 | #ifdef CONFIG_PM |
48 | __entry->card = (chip)->card->number; | 37 | DEFINE_EVENT(hda_pm, azx_runtime_suspend, |
49 | __entry->idx = (dev)->index; | 38 | TP_PROTO(struct azx *chip), |
50 | __entry->pos = pos; | 39 | TP_ARGS(chip) |
51 | __entry->delay = delay; | 40 | ); |
52 | ), | ||
53 | 41 | ||
54 | TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay) | 42 | DEFINE_EVENT(hda_pm, azx_runtime_resume, |
43 | TP_PROTO(struct azx *chip), | ||
44 | TP_ARGS(chip) | ||
55 | ); | 45 | ); |
46 | #endif | ||
56 | 47 | ||
57 | #endif /* _TRACE_HDA_INTEL_H */ | 48 | #endif /* _TRACE_HDA_INTEL_H */ |
58 | 49 | ||
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index d7cfe7b8c32b..366efbf87d41 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -132,11 +132,11 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) | |||
132 | 132 | ||
133 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | 133 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { |
134 | struct hda_jack_callback *cb, *next; | 134 | struct hda_jack_callback *cb, *next; |
135 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 135 | |
136 | /* free jack instances manually when clearing/reconfiguring */ | 136 | /* free jack instances manually when clearing/reconfiguring */ |
137 | if (!codec->bus->shutdown && jack->jack) | 137 | if (!codec->bus->shutdown && jack->jack) |
138 | snd_device_free(codec->card, jack->jack); | 138 | snd_device_free(codec->card, jack->jack); |
139 | #endif | 139 | |
140 | for (cb = jack->callback; cb; cb = next) { | 140 | for (cb = jack->callback; cb; cb = next) { |
141 | next = cb->next; | 141 | next = cb->next; |
142 | kfree(cb); | 142 | kfree(cb); |
@@ -337,20 +337,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec) | |||
337 | jack = codec->jacktbl.list; | 337 | jack = codec->jacktbl.list; |
338 | for (i = 0; i < codec->jacktbl.used; i++, jack++) | 338 | for (i = 0; i < codec->jacktbl.used; i++, jack++) |
339 | if (jack->nid) { | 339 | if (jack->nid) { |
340 | if (!jack->kctl || jack->block_report) | 340 | if (!jack->jack || jack->block_report) |
341 | continue; | 341 | continue; |
342 | state = get_jack_plug_state(jack->pin_sense); | 342 | state = get_jack_plug_state(jack->pin_sense); |
343 | snd_kctl_jack_report(codec->card, jack->kctl, state); | 343 | snd_jack_report(jack->jack, |
344 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 344 | state ? jack->type : 0); |
345 | if (jack->jack) | ||
346 | snd_jack_report(jack->jack, | ||
347 | state ? jack->type : 0); | ||
348 | #endif | ||
349 | } | 345 | } |
350 | } | 346 | } |
351 | EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync); | 347 | EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync); |
352 | 348 | ||
353 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
354 | /* guess the jack type from the pin-config */ | 349 | /* guess the jack type from the pin-config */ |
355 | static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) | 350 | static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) |
356 | { | 351 | { |
@@ -377,54 +372,42 @@ static void hda_free_jack_priv(struct snd_jack *jack) | |||
377 | jacks->nid = 0; | 372 | jacks->nid = 0; |
378 | jacks->jack = NULL; | 373 | jacks->jack = NULL; |
379 | } | 374 | } |
380 | #endif | ||
381 | 375 | ||
382 | /** | 376 | /** |
383 | * snd_hda_jack_add_kctl - Add a kctl for the given pin | 377 | * snd_hda_jack_add_kctl - Add a kctl for the given pin |
384 | * @codec: the HDA codec | 378 | * @codec: the HDA codec |
385 | * @nid: pin NID to assign | 379 | * @nid: pin NID to assign |
386 | * @name: string name for the jack | 380 | * @name: string name for the jack |
387 | * @idx: index number for the jack | ||
388 | * @phantom_jack: flag to deal as a phantom jack | 381 | * @phantom_jack: flag to deal as a phantom jack |
389 | * | 382 | * |
390 | * This assigns a jack-detection kctl to the given pin. The kcontrol | 383 | * This assigns a jack-detection kctl to the given pin. The kcontrol |
391 | * will have the given name and index. | 384 | * will have the given name and index. |
392 | */ | 385 | */ |
393 | static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 386 | static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
394 | const char *name, int idx, bool phantom_jack) | 387 | const char *name, bool phantom_jack) |
395 | { | 388 | { |
396 | struct hda_jack_tbl *jack; | 389 | struct hda_jack_tbl *jack; |
397 | struct snd_kcontrol *kctl; | 390 | int err, state, type; |
398 | int err, state; | ||
399 | 391 | ||
400 | jack = snd_hda_jack_tbl_new(codec, nid); | 392 | jack = snd_hda_jack_tbl_new(codec, nid); |
401 | if (!jack) | 393 | if (!jack) |
402 | return 0; | 394 | return 0; |
403 | if (jack->kctl) | 395 | if (jack->jack) |
404 | return 0; /* already created */ | 396 | return 0; /* already created */ |
405 | kctl = snd_kctl_jack_new(name, idx, codec); | 397 | |
406 | if (!kctl) | 398 | type = get_input_jack_type(codec, nid); |
407 | return -ENOMEM; | 399 | err = snd_jack_new(codec->card, name, type, |
408 | err = snd_hda_ctl_add(codec, nid, kctl); | 400 | &jack->jack, true, phantom_jack); |
409 | if (err < 0) | 401 | if (err < 0) |
410 | return err; | 402 | return err; |
411 | jack->kctl = kctl; | ||
412 | jack->phantom_jack = !!phantom_jack; | ||
413 | 403 | ||
404 | jack->phantom_jack = !!phantom_jack; | ||
405 | jack->type = type; | ||
406 | jack->jack->private_data = jack; | ||
407 | jack->jack->private_free = hda_free_jack_priv; | ||
414 | state = snd_hda_jack_detect(codec, nid); | 408 | state = snd_hda_jack_detect(codec, nid); |
415 | snd_kctl_jack_report(codec->card, kctl, state); | 409 | snd_jack_report(jack->jack, state ? jack->type : 0); |
416 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 410 | |
417 | if (!phantom_jack) { | ||
418 | jack->type = get_input_jack_type(codec, nid); | ||
419 | err = snd_jack_new(codec->card, name, jack->type, | ||
420 | &jack->jack); | ||
421 | if (err < 0) | ||
422 | return err; | ||
423 | jack->jack->private_data = jack; | ||
424 | jack->jack->private_free = hda_free_jack_priv; | ||
425 | snd_jack_report(jack->jack, state ? jack->type : 0); | ||
426 | } | ||
427 | #endif | ||
428 | return 0; | 411 | return 0; |
429 | } | 412 | } |
430 | 413 | ||
@@ -433,44 +416,23 @@ static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
433 | * @codec: the HDA codec | 416 | * @codec: the HDA codec |
434 | * @nid: pin NID | 417 | * @nid: pin NID |
435 | * @name: the name string for the jack ctl | 418 | * @name: the name string for the jack ctl |
436 | * @idx: the ctl index for the jack ctl | ||
437 | * | 419 | * |
438 | * This is a simple helper calling __snd_hda_jack_add_kctl(). | 420 | * This is a simple helper calling __snd_hda_jack_add_kctl(). |
439 | */ | 421 | */ |
440 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 422 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
441 | const char *name, int idx) | 423 | const char *name) |
442 | { | 424 | { |
443 | return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); | 425 | return __snd_hda_jack_add_kctl(codec, nid, name, false); |
444 | } | 426 | } |
445 | EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl); | 427 | EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl); |
446 | 428 | ||
447 | /* get the unique index number for the given kctl name */ | ||
448 | static int get_unique_index(struct hda_codec *codec, const char *name, int idx) | ||
449 | { | ||
450 | struct hda_jack_tbl *jack; | ||
451 | int i, len = strlen(name); | ||
452 | again: | ||
453 | jack = codec->jacktbl.list; | ||
454 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||
455 | /* jack->kctl.id contains "XXX Jack" name string with index */ | ||
456 | if (jack->kctl && | ||
457 | !strncmp(name, jack->kctl->id.name, len) && | ||
458 | !strcmp(" Jack", jack->kctl->id.name + len) && | ||
459 | jack->kctl->id.index == idx) { | ||
460 | idx++; | ||
461 | goto again; | ||
462 | } | ||
463 | } | ||
464 | return idx; | ||
465 | } | ||
466 | |||
467 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | 429 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, |
468 | const struct auto_pin_cfg *cfg, | 430 | const struct auto_pin_cfg *cfg, |
469 | const char *base_name) | 431 | const char *base_name) |
470 | { | 432 | { |
471 | unsigned int def_conf, conn; | 433 | unsigned int def_conf, conn; |
472 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | 434 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
473 | int idx, err; | 435 | int err; |
474 | bool phantom_jack; | 436 | bool phantom_jack; |
475 | 437 | ||
476 | if (!nid) | 438 | if (!nid) |
@@ -482,16 +444,14 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
482 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | 444 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || |
483 | !is_jack_detectable(codec, nid); | 445 | !is_jack_detectable(codec, nid); |
484 | 446 | ||
485 | if (base_name) { | 447 | if (base_name) |
486 | strlcpy(name, base_name, sizeof(name)); | 448 | strlcpy(name, base_name, sizeof(name)); |
487 | idx = 0; | 449 | else |
488 | } else | 450 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL); |
489 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); | ||
490 | if (phantom_jack) | 451 | if (phantom_jack) |
491 | /* Example final name: "Internal Mic Phantom Jack" */ | 452 | /* Example final name: "Internal Mic Phantom Jack" */ |
492 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | 453 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); |
493 | idx = get_unique_index(codec, name, idx); | 454 | err = __snd_hda_jack_add_kctl(codec, nid, name, phantom_jack); |
494 | err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); | ||
495 | if (err < 0) | 455 | if (err < 0) |
496 | return err; | 456 | return err; |
497 | 457 | ||
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index b279e327a23b..387d30984dfe 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -39,11 +39,8 @@ struct hda_jack_tbl { | |||
39 | unsigned int block_report:1; /* in a transitional state - do not report to userspace */ | 39 | unsigned int block_report:1; /* in a transitional state - do not report to userspace */ |
40 | hda_nid_t gating_jack; /* valid when gating jack plugged */ | 40 | hda_nid_t gating_jack; /* valid when gating jack plugged */ |
41 | hda_nid_t gated_jack; /* gated is dependent on this jack */ | 41 | hda_nid_t gated_jack; /* gated is dependent on this jack */ |
42 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ | ||
43 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
44 | int type; | 42 | int type; |
45 | struct snd_jack *jack; | 43 | struct snd_jack *jack; |
46 | #endif | ||
47 | }; | 44 | }; |
48 | 45 | ||
49 | struct hda_jack_tbl * | 46 | struct hda_jack_tbl * |
@@ -85,7 +82,7 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | |||
85 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); | 82 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); |
86 | 83 | ||
87 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 84 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
88 | const char *name, int idx); | 85 | const char *name); |
89 | int snd_hda_jack_add_kctls(struct hda_codec *codec, | 86 | int snd_hda_jack_add_kctls(struct hda_codec *codec, |
90 | const struct auto_pin_cfg *cfg); | 87 | const struct auto_pin_cfg *cfg); |
91 | 88 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3b567f42296b..4a21c2199e02 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -129,8 +129,8 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | |||
129 | /* lowlevel accessor with caching; use carefully */ | 129 | /* lowlevel accessor with caching; use carefully */ |
130 | #define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \ | 130 | #define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \ |
131 | snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx) | 131 | snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx) |
132 | #define snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val) \ | 132 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, |
133 | snd_hdac_regmap_update_amp(&(codec)->core, nid, ch, dir, idx, mask, val) | 133 | int ch, int dir, int idx, int mask, int val); |
134 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 134 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, |
135 | int dir, int idx, int mask, int val); | 135 | int dir, int idx, int mask, int val); |
136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, | 136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, |
@@ -330,7 +330,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | |||
330 | /* | 330 | /* |
331 | * generic proc interface | 331 | * generic proc interface |
332 | */ | 332 | */ |
333 | #ifdef CONFIG_PROC_FS | 333 | #ifdef CONFIG_SND_PROC_FS |
334 | int snd_hda_codec_proc_new(struct hda_codec *codec); | 334 | int snd_hda_codec_proc_new(struct hda_codec *codec); |
335 | #else | 335 | #else |
336 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | 336 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } |
@@ -777,7 +777,7 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, | |||
777 | unsigned char *buf, int *eld_size, | 777 | unsigned char *buf, int *eld_size, |
778 | bool rev3_or_later); | 778 | bool rev3_or_later); |
779 | 779 | ||
780 | #ifdef CONFIG_PROC_FS | 780 | #ifdef CONFIG_SND_PROC_FS |
781 | void snd_hdmi_print_eld_info(struct hdmi_eld *eld, | 781 | void snd_hdmi_print_eld_info(struct hdmi_eld *eld, |
782 | struct snd_info_buffer *buffer); | 782 | struct snd_info_buffer *buffer); |
783 | void snd_hdmi_write_eld_info(struct hdmi_eld *eld, | 783 | void snd_hdmi_write_eld_info(struct hdmi_eld *eld, |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 2e4fd5c56d3b..477742cb70a2 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -87,13 +87,13 @@ MODULE_PARM_DESC(power_save, | |||
87 | /* | 87 | /* |
88 | * DMA page allocation ops. | 88 | * DMA page allocation ops. |
89 | */ | 89 | */ |
90 | static int dma_alloc_pages(struct azx *chip, int type, size_t size, | 90 | static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size, |
91 | struct snd_dma_buffer *buf) | 91 | struct snd_dma_buffer *buf) |
92 | { | 92 | { |
93 | return snd_dma_alloc_pages(type, chip->card->dev, size, buf); | 93 | return snd_dma_alloc_pages(type, bus->dev, size, buf); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf) | 96 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) |
97 | { | 97 | { |
98 | snd_dma_free_pages(buf); | 98 | snd_dma_free_pages(buf); |
99 | } | 99 | } |
@@ -102,11 +102,6 @@ static int substream_alloc_pages(struct azx *chip, | |||
102 | struct snd_pcm_substream *substream, | 102 | struct snd_pcm_substream *substream, |
103 | size_t size) | 103 | size_t size) |
104 | { | 104 | { |
105 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
106 | |||
107 | azx_dev->bufsize = 0; | ||
108 | azx_dev->period_bytes = 0; | ||
109 | azx_dev->format_val = 0; | ||
110 | return snd_pcm_lib_malloc_pages(substream, size); | 105 | return snd_pcm_lib_malloc_pages(substream, size); |
111 | } | 106 | } |
112 | 107 | ||
@@ -173,7 +168,7 @@ static u8 hda_tegra_readb(u8 *addr) | |||
173 | return (v >> shift) & 0xff; | 168 | return (v >> shift) & 0xff; |
174 | } | 169 | } |
175 | 170 | ||
176 | static const struct hda_controller_ops hda_tegra_ops = { | 171 | static const struct hdac_io_ops hda_tegra_io_ops = { |
177 | .reg_writel = hda_tegra_writel, | 172 | .reg_writel = hda_tegra_writel, |
178 | .reg_readl = hda_tegra_readl, | 173 | .reg_readl = hda_tegra_readl, |
179 | .reg_writew = hda_tegra_writew, | 174 | .reg_writew = hda_tegra_writew, |
@@ -182,6 +177,9 @@ static const struct hda_controller_ops hda_tegra_ops = { | |||
182 | .reg_readb = hda_tegra_readb, | 177 | .reg_readb = hda_tegra_readb, |
183 | .dma_alloc_pages = dma_alloc_pages, | 178 | .dma_alloc_pages = dma_alloc_pages, |
184 | .dma_free_pages = dma_free_pages, | 179 | .dma_free_pages = dma_free_pages, |
180 | }; | ||
181 | |||
182 | static const struct hda_controller_ops hda_tegra_ops = { | ||
185 | .substream_alloc_pages = substream_alloc_pages, | 183 | .substream_alloc_pages = substream_alloc_pages, |
186 | .substream_free_pages = substream_free_pages, | 184 | .substream_free_pages = substream_free_pages, |
187 | }; | 185 | }; |
@@ -282,21 +280,29 @@ static const struct dev_pm_ops hda_tegra_pm = { | |||
282 | SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume) | 280 | SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume) |
283 | }; | 281 | }; |
284 | 282 | ||
283 | static int hda_tegra_dev_disconnect(struct snd_device *device) | ||
284 | { | ||
285 | struct azx *chip = device->device_data; | ||
286 | |||
287 | chip->bus.shutdown = 1; | ||
288 | return 0; | ||
289 | } | ||
290 | |||
285 | /* | 291 | /* |
286 | * destructor | 292 | * destructor |
287 | */ | 293 | */ |
288 | static int hda_tegra_dev_free(struct snd_device *device) | 294 | static int hda_tegra_dev_free(struct snd_device *device) |
289 | { | 295 | { |
290 | int i; | ||
291 | struct azx *chip = device->device_data; | 296 | struct azx *chip = device->device_data; |
292 | 297 | ||
293 | if (chip->initialized) { | 298 | if (azx_bus(chip)->chip_init) { |
294 | for (i = 0; i < chip->num_streams; i++) | 299 | azx_stop_all_streams(chip); |
295 | azx_stream_stop(chip, &chip->azx_dev[i]); | ||
296 | azx_stop_chip(chip); | 300 | azx_stop_chip(chip); |
297 | } | 301 | } |
298 | 302 | ||
299 | azx_free_stream_pages(chip); | 303 | azx_free_stream_pages(chip); |
304 | azx_free_streams(chip); | ||
305 | snd_hdac_bus_exit(azx_bus(chip)); | ||
300 | 306 | ||
301 | return 0; | 307 | return 0; |
302 | } | 308 | } |
@@ -304,31 +310,40 @@ static int hda_tegra_dev_free(struct snd_device *device) | |||
304 | static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) | 310 | static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) |
305 | { | 311 | { |
306 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | 312 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); |
313 | struct hdac_bus *bus = azx_bus(chip); | ||
307 | struct device *dev = hda->dev; | 314 | struct device *dev = hda->dev; |
308 | struct resource *res; | 315 | struct resource *res; |
309 | int err; | 316 | int err; |
310 | 317 | ||
311 | hda->hda_clk = devm_clk_get(dev, "hda"); | 318 | hda->hda_clk = devm_clk_get(dev, "hda"); |
312 | if (IS_ERR(hda->hda_clk)) | 319 | if (IS_ERR(hda->hda_clk)) { |
320 | dev_err(dev, "failed to get hda clock\n"); | ||
313 | return PTR_ERR(hda->hda_clk); | 321 | return PTR_ERR(hda->hda_clk); |
322 | } | ||
314 | hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x"); | 323 | hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x"); |
315 | if (IS_ERR(hda->hda2codec_2x_clk)) | 324 | if (IS_ERR(hda->hda2codec_2x_clk)) { |
325 | dev_err(dev, "failed to get hda2codec_2x clock\n"); | ||
316 | return PTR_ERR(hda->hda2codec_2x_clk); | 326 | return PTR_ERR(hda->hda2codec_2x_clk); |
327 | } | ||
317 | hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi"); | 328 | hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi"); |
318 | if (IS_ERR(hda->hda2hdmi_clk)) | 329 | if (IS_ERR(hda->hda2hdmi_clk)) { |
330 | dev_err(dev, "failed to get hda2hdmi clock\n"); | ||
319 | return PTR_ERR(hda->hda2hdmi_clk); | 331 | return PTR_ERR(hda->hda2hdmi_clk); |
332 | } | ||
320 | 333 | ||
321 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
322 | hda->regs = devm_ioremap_resource(dev, res); | 335 | hda->regs = devm_ioremap_resource(dev, res); |
323 | if (IS_ERR(hda->regs)) | 336 | if (IS_ERR(hda->regs)) |
324 | return PTR_ERR(hda->regs); | 337 | return PTR_ERR(hda->regs); |
325 | 338 | ||
326 | chip->remap_addr = hda->regs + HDA_BAR0; | 339 | bus->remap_addr = hda->regs + HDA_BAR0; |
327 | chip->addr = res->start + HDA_BAR0; | 340 | bus->addr = res->start + HDA_BAR0; |
328 | 341 | ||
329 | err = hda_tegra_enable_clocks(hda); | 342 | err = hda_tegra_enable_clocks(hda); |
330 | if (err) | 343 | if (err) { |
344 | dev_err(dev, "failed to get enable clocks\n"); | ||
331 | return err; | 345 | return err; |
346 | } | ||
332 | 347 | ||
333 | hda_tegra_init(hda); | 348 | hda_tegra_init(hda); |
334 | 349 | ||
@@ -337,6 +352,7 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) | |||
337 | 352 | ||
338 | static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | 353 | static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) |
339 | { | 354 | { |
355 | struct hdac_bus *bus = azx_bus(chip); | ||
340 | struct snd_card *card = chip->card; | 356 | struct snd_card *card = chip->card; |
341 | int err; | 357 | int err; |
342 | unsigned short gcap; | 358 | unsigned short gcap; |
@@ -354,9 +370,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | |||
354 | irq_id); | 370 | irq_id); |
355 | return err; | 371 | return err; |
356 | } | 372 | } |
357 | chip->irq = irq_id; | 373 | bus->irq = irq_id; |
358 | 374 | ||
359 | synchronize_irq(chip->irq); | 375 | synchronize_irq(bus->irq); |
360 | 376 | ||
361 | gcap = azx_readw(chip, GCAP); | 377 | gcap = azx_readw(chip, GCAP); |
362 | dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); | 378 | dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); |
@@ -374,23 +390,26 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | |||
374 | chip->capture_index_offset = 0; | 390 | chip->capture_index_offset = 0; |
375 | chip->playback_index_offset = chip->capture_streams; | 391 | chip->playback_index_offset = chip->capture_streams; |
376 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 392 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
377 | chip->azx_dev = devm_kcalloc(card->dev, chip->num_streams, | ||
378 | sizeof(*chip->azx_dev), GFP_KERNEL); | ||
379 | if (!chip->azx_dev) | ||
380 | return -ENOMEM; | ||
381 | 393 | ||
382 | err = azx_alloc_stream_pages(chip); | 394 | /* initialize streams */ |
383 | if (err < 0) | 395 | err = azx_init_streams(chip); |
396 | if (err < 0) { | ||
397 | dev_err(card->dev, "failed to initialize streams: %d\n", err); | ||
384 | return err; | 398 | return err; |
399 | } | ||
385 | 400 | ||
386 | /* initialize streams */ | 401 | err = azx_alloc_stream_pages(chip); |
387 | azx_init_stream(chip); | 402 | if (err < 0) { |
403 | dev_err(card->dev, "failed to allocate stream pages: %d\n", | ||
404 | err); | ||
405 | return err; | ||
406 | } | ||
388 | 407 | ||
389 | /* initialize chip */ | 408 | /* initialize chip */ |
390 | azx_init_chip(chip, 1); | 409 | azx_init_chip(chip, 1); |
391 | 410 | ||
392 | /* codec detection */ | 411 | /* codec detection */ |
393 | if (!chip->codec_mask) { | 412 | if (!bus->codec_mask) { |
394 | dev_err(card->dev, "no codecs found!\n"); | 413 | dev_err(card->dev, "no codecs found!\n"); |
395 | return -ENODEV; | 414 | return -ENODEV; |
396 | } | 415 | } |
@@ -399,7 +418,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | |||
399 | strcpy(card->shortname, "tegra-hda"); | 418 | strcpy(card->shortname, "tegra-hda"); |
400 | snprintf(card->longname, sizeof(card->longname), | 419 | snprintf(card->longname, sizeof(card->longname), |
401 | "%s at 0x%lx irq %i", | 420 | "%s at 0x%lx irq %i", |
402 | card->shortname, chip->addr, chip->irq); | 421 | card->shortname, bus->addr, bus->irq); |
403 | 422 | ||
404 | return 0; | 423 | return 0; |
405 | } | 424 | } |
@@ -409,10 +428,10 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) | |||
409 | */ | 428 | */ |
410 | static int hda_tegra_create(struct snd_card *card, | 429 | static int hda_tegra_create(struct snd_card *card, |
411 | unsigned int driver_caps, | 430 | unsigned int driver_caps, |
412 | const struct hda_controller_ops *hda_ops, | ||
413 | struct hda_tegra *hda) | 431 | struct hda_tegra *hda) |
414 | { | 432 | { |
415 | static struct snd_device_ops ops = { | 433 | static struct snd_device_ops ops = { |
434 | .dev_disconnect = hda_tegra_dev_disconnect, | ||
416 | .dev_free = hda_tegra_dev_free, | 435 | .dev_free = hda_tegra_dev_free, |
417 | }; | 436 | }; |
418 | struct azx *chip; | 437 | struct azx *chip; |
@@ -420,11 +439,9 @@ static int hda_tegra_create(struct snd_card *card, | |||
420 | 439 | ||
421 | chip = &hda->chip; | 440 | chip = &hda->chip; |
422 | 441 | ||
423 | spin_lock_init(&chip->reg_lock); | ||
424 | mutex_init(&chip->open_mutex); | 442 | mutex_init(&chip->open_mutex); |
425 | chip->card = card; | 443 | chip->card = card; |
426 | chip->ops = hda_ops; | 444 | chip->ops = &hda_tegra_ops; |
427 | chip->irq = -1; | ||
428 | chip->driver_caps = driver_caps; | 445 | chip->driver_caps = driver_caps; |
429 | chip->driver_type = driver_caps & 0xff; | 446 | chip->driver_type = driver_caps & 0xff; |
430 | chip->dev_index = 0; | 447 | chip->dev_index = 0; |
@@ -435,6 +452,10 @@ static int hda_tegra_create(struct snd_card *card, | |||
435 | chip->single_cmd = false; | 452 | chip->single_cmd = false; |
436 | chip->snoop = true; | 453 | chip->snoop = true; |
437 | 454 | ||
455 | err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); | ||
456 | if (err < 0) | ||
457 | return err; | ||
458 | |||
438 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 459 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
439 | if (err < 0) { | 460 | if (err < 0) { |
440 | dev_err(card->dev, "Error creating device\n"); | 461 | dev_err(card->dev, "Error creating device\n"); |
@@ -452,11 +473,12 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match); | |||
452 | 473 | ||
453 | static int hda_tegra_probe(struct platform_device *pdev) | 474 | static int hda_tegra_probe(struct platform_device *pdev) |
454 | { | 475 | { |
476 | const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY | | ||
477 | AZX_DCAPS_CORBRP_SELF_CLEAR; | ||
455 | struct snd_card *card; | 478 | struct snd_card *card; |
456 | struct azx *chip; | 479 | struct azx *chip; |
457 | struct hda_tegra *hda; | 480 | struct hda_tegra *hda; |
458 | int err; | 481 | int err; |
459 | const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY; | ||
460 | 482 | ||
461 | hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL); | 483 | hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL); |
462 | if (!hda) | 484 | if (!hda) |
@@ -471,7 +493,7 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
471 | return err; | 493 | return err; |
472 | } | 494 | } |
473 | 495 | ||
474 | err = hda_tegra_create(card, driver_flags, &hda_tegra_ops, hda); | 496 | err = hda_tegra_create(card, driver_flags, hda); |
475 | if (err < 0) | 497 | if (err < 0) |
476 | goto out_free; | 498 | goto out_free; |
477 | card->private_data = chip; | 499 | card->private_data = chip; |
@@ -483,10 +505,6 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
483 | goto out_free; | 505 | goto out_free; |
484 | 506 | ||
485 | /* create codec instances */ | 507 | /* create codec instances */ |
486 | err = azx_bus_create(chip, NULL); | ||
487 | if (err < 0) | ||
488 | goto out_free; | ||
489 | |||
490 | err = azx_probe_codecs(chip, 0); | 508 | err = azx_probe_codecs(chip, 0); |
491 | if (err < 0) | 509 | if (err < 0) |
492 | goto out_free; | 510 | goto out_free; |
@@ -500,7 +518,7 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
500 | goto out_free; | 518 | goto out_free; |
501 | 519 | ||
502 | chip->running = 1; | 520 | chip->running = 1; |
503 | snd_hda_set_power_save(chip->bus, power_save * 1000); | 521 | snd_hda_set_power_save(&chip->bus, power_save * 1000); |
504 | 522 | ||
505 | return 0; | 523 | return 0; |
506 | 524 | ||
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 231f89029779..c033a4ee6547 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -205,8 +205,6 @@ static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp) | |||
205 | if (err < 0) | 205 | if (err < 0) |
206 | return err; | 206 | return err; |
207 | 207 | ||
208 | codec->patch_ops = ad198x_auto_patch_ops; | ||
209 | |||
210 | return 0; | 208 | return 0; |
211 | } | 209 | } |
212 | 210 | ||
@@ -223,6 +221,7 @@ static int alloc_ad_spec(struct hda_codec *codec) | |||
223 | return -ENOMEM; | 221 | return -ENOMEM; |
224 | codec->spec = spec; | 222 | codec->spec = spec; |
225 | snd_hda_gen_spec_init(&spec->gen); | 223 | snd_hda_gen_spec_init(&spec->gen); |
224 | codec->patch_ops = ad198x_auto_patch_ops; | ||
226 | return 0; | 225 | return 0; |
227 | } | 226 | } |
228 | 227 | ||
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index 447302695195..484bbf4134cd 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c | |||
@@ -63,6 +63,7 @@ static int patch_ca0110(struct hda_codec *codec) | |||
63 | return -ENOMEM; | 63 | return -ENOMEM; |
64 | snd_hda_gen_spec_init(spec); | 64 | snd_hda_gen_spec_init(spec); |
65 | codec->spec = spec; | 65 | codec->spec = spec; |
66 | codec->patch_ops = ca0110_patch_ops; | ||
66 | 67 | ||
67 | spec->multi_cap_vol = 1; | 68 | spec->multi_cap_vol = 1; |
68 | codec->bus->needs_damn_long_delay = 1; | 69 | codec->bus->needs_damn_long_delay = 1; |
@@ -71,8 +72,6 @@ static int patch_ca0110(struct hda_codec *codec) | |||
71 | if (err < 0) | 72 | if (err < 0) |
72 | goto error; | 73 | goto error; |
73 | 74 | ||
74 | codec->patch_ops = ca0110_patch_ops; | ||
75 | |||
76 | return 0; | 75 | return 0; |
77 | 76 | ||
78 | error: | 77 | error: |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4a4e7b282e4f..0f039abe9673 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #define FLOAT_TWO 0x40000000 | 43 | #define FLOAT_TWO 0x40000000 |
44 | #define FLOAT_MINUS_5 0xc0a00000 | 44 | #define FLOAT_MINUS_5 0xc0a00000 |
45 | 45 | ||
46 | #define UNSOL_TAG_HP 0x10 | ||
47 | #define UNSOL_TAG_AMIC1 0x12 | ||
48 | #define UNSOL_TAG_DSP 0x16 | 46 | #define UNSOL_TAG_DSP 0x16 |
49 | 47 | ||
50 | #define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18) | 48 | #define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18) |
@@ -703,8 +701,8 @@ struct ca0132_spec { | |||
703 | unsigned int num_mixers; | 701 | unsigned int num_mixers; |
704 | const struct hda_verb *base_init_verbs; | 702 | const struct hda_verb *base_init_verbs; |
705 | const struct hda_verb *base_exit_verbs; | 703 | const struct hda_verb *base_exit_verbs; |
706 | const struct hda_verb *init_verbs[5]; | 704 | const struct hda_verb *chip_init_verbs; |
707 | unsigned int num_init_verbs; /* exclude base init verbs */ | 705 | struct hda_verb *spec_init_verbs; |
708 | struct auto_pin_cfg autocfg; | 706 | struct auto_pin_cfg autocfg; |
709 | 707 | ||
710 | /* Nodes configurations */ | 708 | /* Nodes configurations */ |
@@ -719,6 +717,8 @@ struct ca0132_spec { | |||
719 | unsigned int num_inputs; | 717 | unsigned int num_inputs; |
720 | hda_nid_t shared_mic_nid; | 718 | hda_nid_t shared_mic_nid; |
721 | hda_nid_t shared_out_nid; | 719 | hda_nid_t shared_out_nid; |
720 | hda_nid_t unsol_tag_hp; | ||
721 | hda_nid_t unsol_tag_amic1; | ||
722 | 722 | ||
723 | /* chip access */ | 723 | /* chip access */ |
724 | struct mutex chipio_mutex; /* chip access mutex */ | 724 | struct mutex chipio_mutex; /* chip access mutex */ |
@@ -748,6 +748,7 @@ struct ca0132_spec { | |||
748 | 748 | ||
749 | struct hda_codec *codec; | 749 | struct hda_codec *codec; |
750 | struct delayed_work unsol_hp_work; | 750 | struct delayed_work unsol_hp_work; |
751 | int quirk; | ||
751 | 752 | ||
752 | #ifdef ENABLE_TUNING_CONTROLS | 753 | #ifdef ENABLE_TUNING_CONTROLS |
753 | long cur_ctl_vals[TUNING_CTLS_COUNT]; | 754 | long cur_ctl_vals[TUNING_CTLS_COUNT]; |
@@ -755,6 +756,19 @@ struct ca0132_spec { | |||
755 | }; | 756 | }; |
756 | 757 | ||
757 | /* | 758 | /* |
759 | * CA0132 quirks table | ||
760 | */ | ||
761 | enum { | ||
762 | QUIRK_NONE, | ||
763 | QUIRK_ALIENWARE, | ||
764 | }; | ||
765 | |||
766 | static const struct snd_pci_quirk ca0132_quirks[] = { | ||
767 | SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE), | ||
768 | {} | ||
769 | }; | ||
770 | |||
771 | /* | ||
758 | * CA0132 codec access | 772 | * CA0132 codec access |
759 | */ | 773 | */ |
760 | static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid, | 774 | static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid, |
@@ -2052,11 +2066,8 @@ static int dma_convert_to_hda_format(struct hda_codec *codec, | |||
2052 | { | 2066 | { |
2053 | unsigned int format_val; | 2067 | unsigned int format_val; |
2054 | 2068 | ||
2055 | format_val = snd_hda_calc_stream_format(codec, | 2069 | format_val = snd_hdac_calc_stream_format(sample_rate, |
2056 | sample_rate, | 2070 | channels, SNDRV_PCM_FORMAT_S32_LE, 32, 0); |
2057 | channels, | ||
2058 | SNDRV_PCM_FORMAT_S32_LE, | ||
2059 | 32, 0); | ||
2060 | 2071 | ||
2061 | if (hda_format) | 2072 | if (hda_format) |
2062 | *hda_format = (unsigned short)format_val; | 2073 | *hda_format = (unsigned short)format_val; |
@@ -3227,7 +3238,7 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) | |||
3227 | struct hda_jack_tbl *jack; | 3238 | struct hda_jack_tbl *jack; |
3228 | 3239 | ||
3229 | ca0132_select_out(spec->codec); | 3240 | ca0132_select_out(spec->codec); |
3230 | jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP); | 3241 | jack = snd_hda_jack_tbl_get(spec->codec, spec->unsol_tag_hp); |
3231 | if (jack) { | 3242 | if (jack) { |
3232 | jack->block_report = 0; | 3243 | jack->block_report = 0; |
3233 | snd_hda_jack_report_sync(spec->codec); | 3244 | snd_hda_jack_report_sync(spec->codec); |
@@ -4417,8 +4428,9 @@ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) | |||
4417 | 4428 | ||
4418 | static void ca0132_init_unsol(struct hda_codec *codec) | 4429 | static void ca0132_init_unsol(struct hda_codec *codec) |
4419 | { | 4430 | { |
4420 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback); | 4431 | struct ca0132_spec *spec = codec->spec; |
4421 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1, | 4432 | snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_hp, hp_callback); |
4433 | snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_amic1, | ||
4422 | amic_callback); | 4434 | amic_callback); |
4423 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, | 4435 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, |
4424 | ca0132_process_dsp_response); | 4436 | ca0132_process_dsp_response); |
@@ -4479,17 +4491,6 @@ static struct hda_verb ca0132_init_verbs0[] = { | |||
4479 | {} | 4491 | {} |
4480 | }; | 4492 | }; |
4481 | 4493 | ||
4482 | static struct hda_verb ca0132_init_verbs1[] = { | ||
4483 | {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_HP}, | ||
4484 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_AMIC1}, | ||
4485 | /* config EAPD */ | ||
4486 | {0x0b, 0x78D, 0x00}, | ||
4487 | /*{0x0b, AC_VERB_SET_EAPD_BTLENABLE, 0x02},*/ | ||
4488 | /*{0x10, 0x78D, 0x02},*/ | ||
4489 | /*{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x02},*/ | ||
4490 | {} | ||
4491 | }; | ||
4492 | |||
4493 | static void ca0132_init_chip(struct hda_codec *codec) | 4494 | static void ca0132_init_chip(struct hda_codec *codec) |
4494 | { | 4495 | { |
4495 | struct ca0132_spec *spec = codec->spec; | 4496 | struct ca0132_spec *spec = codec->spec; |
@@ -4569,8 +4570,8 @@ static int ca0132_init(struct hda_codec *codec) | |||
4569 | 4570 | ||
4570 | init_input(codec, cfg->dig_in_pin, spec->dig_in); | 4571 | init_input(codec, cfg->dig_in_pin, spec->dig_in); |
4571 | 4572 | ||
4572 | for (i = 0; i < spec->num_init_verbs; i++) | 4573 | snd_hda_sequence_write(codec, spec->chip_init_verbs); |
4573 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 4574 | snd_hda_sequence_write(codec, spec->spec_init_verbs); |
4574 | 4575 | ||
4575 | ca0132_select_out(codec); | 4576 | ca0132_select_out(codec); |
4576 | ca0132_select_mic(codec); | 4577 | ca0132_select_mic(codec); |
@@ -4591,6 +4592,7 @@ static void ca0132_free(struct hda_codec *codec) | |||
4591 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | 4592 | snd_hda_sequence_write(codec, spec->base_exit_verbs); |
4592 | ca0132_exit_chip(codec); | 4593 | ca0132_exit_chip(codec); |
4593 | snd_hda_power_down(codec); | 4594 | snd_hda_power_down(codec); |
4595 | kfree(spec->spec_init_verbs); | ||
4594 | kfree(codec->spec); | 4596 | kfree(codec->spec); |
4595 | } | 4597 | } |
4596 | 4598 | ||
@@ -4617,18 +4619,25 @@ static void ca0132_config(struct hda_codec *codec) | |||
4617 | 4619 | ||
4618 | spec->num_outputs = 2; | 4620 | spec->num_outputs = 2; |
4619 | spec->out_pins[0] = 0x0b; /* speaker out */ | 4621 | spec->out_pins[0] = 0x0b; /* speaker out */ |
4620 | spec->out_pins[1] = 0x10; /* headphone out */ | 4622 | if (spec->quirk == QUIRK_ALIENWARE) { |
4623 | codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); | ||
4624 | spec->out_pins[1] = 0x0f; | ||
4625 | } else{ | ||
4626 | spec->out_pins[1] = 0x10; /* headphone out */ | ||
4627 | } | ||
4621 | spec->shared_out_nid = 0x2; | 4628 | spec->shared_out_nid = 0x2; |
4629 | spec->unsol_tag_hp = spec->out_pins[1]; | ||
4622 | 4630 | ||
4623 | spec->num_inputs = 3; | ||
4624 | spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ | 4631 | spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ |
4625 | spec->adcs[1] = 0x8; /* analog mic2 */ | 4632 | spec->adcs[1] = 0x8; /* analog mic2 */ |
4626 | spec->adcs[2] = 0xa; /* what u hear */ | 4633 | spec->adcs[2] = 0xa; /* what u hear */ |
4627 | spec->shared_mic_nid = 0x7; | ||
4628 | 4634 | ||
4635 | spec->num_inputs = 3; | ||
4629 | spec->input_pins[0] = 0x12; | 4636 | spec->input_pins[0] = 0x12; |
4630 | spec->input_pins[1] = 0x11; | 4637 | spec->input_pins[1] = 0x11; |
4631 | spec->input_pins[2] = 0x13; | 4638 | spec->input_pins[2] = 0x13; |
4639 | spec->shared_mic_nid = 0x7; | ||
4640 | spec->unsol_tag_amic1 = spec->input_pins[0]; | ||
4632 | 4641 | ||
4633 | /* SPDIF I/O */ | 4642 | /* SPDIF I/O */ |
4634 | spec->dig_out = 0x05; | 4643 | spec->dig_out = 0x05; |
@@ -4641,10 +4650,56 @@ static void ca0132_config(struct hda_codec *codec) | |||
4641 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; | 4650 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; |
4642 | } | 4651 | } |
4643 | 4652 | ||
4653 | static int ca0132_prepare_verbs(struct hda_codec *codec) | ||
4654 | { | ||
4655 | /* Verbs + terminator (an empty element) */ | ||
4656 | #define NUM_SPEC_VERBS 4 | ||
4657 | struct ca0132_spec *spec = codec->spec; | ||
4658 | |||
4659 | spec->chip_init_verbs = ca0132_init_verbs0; | ||
4660 | spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL); | ||
4661 | if (!spec->spec_init_verbs) | ||
4662 | return -ENOMEM; | ||
4663 | |||
4664 | /* HP jack autodetection */ | ||
4665 | spec->spec_init_verbs[0].nid = spec->unsol_tag_hp; | ||
4666 | spec->spec_init_verbs[0].param = AC_VERB_SET_UNSOLICITED_ENABLE; | ||
4667 | spec->spec_init_verbs[0].verb = AC_USRSP_EN | spec->unsol_tag_hp; | ||
4668 | |||
4669 | /* MIC1 jack autodetection */ | ||
4670 | spec->spec_init_verbs[1].nid = spec->unsol_tag_amic1; | ||
4671 | spec->spec_init_verbs[1].param = AC_VERB_SET_UNSOLICITED_ENABLE; | ||
4672 | spec->spec_init_verbs[1].verb = AC_USRSP_EN | spec->unsol_tag_amic1; | ||
4673 | |||
4674 | /* config EAPD */ | ||
4675 | spec->spec_init_verbs[2].nid = 0x0b; | ||
4676 | spec->spec_init_verbs[2].param = 0x78D; | ||
4677 | spec->spec_init_verbs[2].verb = 0x00; | ||
4678 | |||
4679 | /* Previously commented configuration */ | ||
4680 | /* | ||
4681 | spec->spec_init_verbs[3].nid = 0x0b; | ||
4682 | spec->spec_init_verbs[3].param = AC_VERB_SET_EAPD_BTLENABLE; | ||
4683 | spec->spec_init_verbs[3].verb = 0x02; | ||
4684 | |||
4685 | spec->spec_init_verbs[4].nid = 0x10; | ||
4686 | spec->spec_init_verbs[4].param = 0x78D; | ||
4687 | spec->spec_init_verbs[4].verb = 0x02; | ||
4688 | |||
4689 | spec->spec_init_verbs[5].nid = 0x10; | ||
4690 | spec->spec_init_verbs[5].param = AC_VERB_SET_EAPD_BTLENABLE; | ||
4691 | spec->spec_init_verbs[5].verb = 0x02; | ||
4692 | */ | ||
4693 | |||
4694 | /* Terminator: spec->spec_init_verbs[NUM_SPEC_VERBS-1] */ | ||
4695 | return 0; | ||
4696 | } | ||
4697 | |||
4644 | static int patch_ca0132(struct hda_codec *codec) | 4698 | static int patch_ca0132(struct hda_codec *codec) |
4645 | { | 4699 | { |
4646 | struct ca0132_spec *spec; | 4700 | struct ca0132_spec *spec; |
4647 | int err; | 4701 | int err; |
4702 | const struct snd_pci_quirk *quirk; | ||
4648 | 4703 | ||
4649 | codec_dbg(codec, "patch_ca0132\n"); | 4704 | codec_dbg(codec, "patch_ca0132\n"); |
4650 | 4705 | ||
@@ -4654,15 +4709,23 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4654 | codec->spec = spec; | 4709 | codec->spec = spec; |
4655 | spec->codec = codec; | 4710 | spec->codec = codec; |
4656 | 4711 | ||
4712 | codec->patch_ops = ca0132_patch_ops; | ||
4713 | codec->pcm_format_first = 1; | ||
4714 | codec->no_sticky_stream = 1; | ||
4715 | |||
4716 | /* Detect codec quirk */ | ||
4717 | quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks); | ||
4718 | if (quirk) | ||
4719 | spec->quirk = quirk->value; | ||
4720 | else | ||
4721 | spec->quirk = QUIRK_NONE; | ||
4722 | |||
4657 | spec->dsp_state = DSP_DOWNLOAD_INIT; | 4723 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
4658 | spec->num_mixers = 1; | 4724 | spec->num_mixers = 1; |
4659 | spec->mixers[0] = ca0132_mixer; | 4725 | spec->mixers[0] = ca0132_mixer; |
4660 | 4726 | ||
4661 | spec->base_init_verbs = ca0132_base_init_verbs; | 4727 | spec->base_init_verbs = ca0132_base_init_verbs; |
4662 | spec->base_exit_verbs = ca0132_base_exit_verbs; | 4728 | spec->base_exit_verbs = ca0132_base_exit_verbs; |
4663 | spec->init_verbs[0] = ca0132_init_verbs0; | ||
4664 | spec->init_verbs[1] = ca0132_init_verbs1; | ||
4665 | spec->num_init_verbs = 2; | ||
4666 | 4729 | ||
4667 | INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed); | 4730 | INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed); |
4668 | 4731 | ||
@@ -4670,13 +4733,13 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4670 | 4733 | ||
4671 | ca0132_config(codec); | 4734 | ca0132_config(codec); |
4672 | 4735 | ||
4673 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | 4736 | err = ca0132_prepare_verbs(codec); |
4674 | if (err < 0) | 4737 | if (err < 0) |
4675 | return err; | 4738 | return err; |
4676 | 4739 | ||
4677 | codec->patch_ops = ca0132_patch_ops; | 4740 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); |
4678 | codec->pcm_format_first = 1; | 4741 | if (err < 0) |
4679 | codec->no_sticky_stream = 1; | 4742 | return err; |
4680 | 4743 | ||
4681 | return 0; | 4744 | return 0; |
4682 | } | 4745 | } |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 50e9dd675579..25ccf781fbe7 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -584,6 +584,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
584 | if (!spec) | 584 | if (!spec) |
585 | return -ENOMEM; | 585 | return -ENOMEM; |
586 | 586 | ||
587 | codec->patch_ops = cs_patch_ops; | ||
587 | spec->gen.automute_hook = cs_automute; | 588 | spec->gen.automute_hook = cs_automute; |
588 | codec->single_adc_amp = 1; | 589 | codec->single_adc_amp = 1; |
589 | 590 | ||
@@ -595,8 +596,6 @@ static int patch_cs420x(struct hda_codec *codec) | |||
595 | if (err < 0) | 596 | if (err < 0) |
596 | goto error; | 597 | goto error; |
597 | 598 | ||
598 | codec->patch_ops = cs_patch_ops; | ||
599 | |||
600 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 599 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
601 | 600 | ||
602 | return 0; | 601 | return 0; |
@@ -738,6 +737,7 @@ static int patch_cs4208(struct hda_codec *codec) | |||
738 | if (!spec) | 737 | if (!spec) |
739 | return -ENOMEM; | 738 | return -ENOMEM; |
740 | 739 | ||
740 | codec->patch_ops = cs_patch_ops; | ||
741 | spec->gen.automute_hook = cs_automute; | 741 | spec->gen.automute_hook = cs_automute; |
742 | /* exclude NID 0x10 (HP) from output volumes due to different steps */ | 742 | /* exclude NID 0x10 (HP) from output volumes due to different steps */ |
743 | spec->gen.out_vol_mask = 1ULL << 0x10; | 743 | spec->gen.out_vol_mask = 1ULL << 0x10; |
@@ -756,8 +756,6 @@ static int patch_cs4208(struct hda_codec *codec) | |||
756 | if (err < 0) | 756 | if (err < 0) |
757 | goto error; | 757 | goto error; |
758 | 758 | ||
759 | codec->patch_ops = cs_patch_ops; | ||
760 | |||
761 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 759 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
762 | 760 | ||
763 | return 0; | 761 | return 0; |
@@ -1150,6 +1148,7 @@ static int patch_cs4210(struct hda_codec *codec) | |||
1150 | if (!spec) | 1148 | if (!spec) |
1151 | return -ENOMEM; | 1149 | return -ENOMEM; |
1152 | 1150 | ||
1151 | codec->patch_ops = cs421x_patch_ops; | ||
1153 | spec->gen.automute_hook = cs_automute; | 1152 | spec->gen.automute_hook = cs_automute; |
1154 | 1153 | ||
1155 | snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl, | 1154 | snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl, |
@@ -1167,8 +1166,6 @@ static int patch_cs4210(struct hda_codec *codec) | |||
1167 | if (err < 0) | 1166 | if (err < 0) |
1168 | goto error; | 1167 | goto error; |
1169 | 1168 | ||
1170 | codec->patch_ops = cs421x_patch_ops; | ||
1171 | |||
1172 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 1169 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
1173 | 1170 | ||
1174 | return 0; | 1171 | return 0; |
@@ -1187,11 +1184,12 @@ static int patch_cs4213(struct hda_codec *codec) | |||
1187 | if (!spec) | 1184 | if (!spec) |
1188 | return -ENOMEM; | 1185 | return -ENOMEM; |
1189 | 1186 | ||
1187 | codec->patch_ops = cs421x_patch_ops; | ||
1188 | |||
1190 | err = cs421x_parse_auto_config(codec); | 1189 | err = cs421x_parse_auto_config(codec); |
1191 | if (err < 0) | 1190 | if (err < 0) |
1192 | goto error; | 1191 | goto error; |
1193 | 1192 | ||
1194 | codec->patch_ops = cs421x_patch_ops; | ||
1195 | return 0; | 1193 | return 0; |
1196 | 1194 | ||
1197 | error: | 1195 | error: |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 617d9012e78a..f5ed078710f8 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -57,6 +57,7 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
57 | return -ENOMEM; | 57 | return -ENOMEM; |
58 | 58 | ||
59 | codec->spec = spec; | 59 | codec->spec = spec; |
60 | codec->patch_ops = cmi_auto_patch_ops; | ||
60 | cfg = &spec->gen.autocfg; | 61 | cfg = &spec->gen.autocfg; |
61 | snd_hda_gen_spec_init(&spec->gen); | 62 | snd_hda_gen_spec_init(&spec->gen); |
62 | 63 | ||
@@ -67,7 +68,6 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
67 | if (err < 0) | 68 | if (err < 0) |
68 | goto error; | 69 | goto error; |
69 | 70 | ||
70 | codec->patch_ops = cmi_auto_patch_ops; | ||
71 | return 0; | 71 | return 0; |
72 | 72 | ||
73 | error: | 73 | error: |
@@ -86,6 +86,7 @@ static int patch_cmi8888(struct hda_codec *codec) | |||
86 | return -ENOMEM; | 86 | return -ENOMEM; |
87 | 87 | ||
88 | codec->spec = spec; | 88 | codec->spec = spec; |
89 | codec->patch_ops = cmi_auto_patch_ops; | ||
89 | cfg = &spec->gen.autocfg; | 90 | cfg = &spec->gen.autocfg; |
90 | snd_hda_gen_spec_init(&spec->gen); | 91 | snd_hda_gen_spec_init(&spec->gen); |
91 | 92 | ||
@@ -112,7 +113,6 @@ static int patch_cmi8888(struct hda_codec *codec) | |||
112 | } | 113 | } |
113 | } | 114 | } |
114 | 115 | ||
115 | codec->patch_ops = cmi_auto_patch_ops; | ||
116 | return 0; | 116 | return 0; |
117 | 117 | ||
118 | error: | 118 | error: |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index f8f0dfbef149..f788a91b544a 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -850,6 +850,7 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
850 | return -ENOMEM; | 850 | return -ENOMEM; |
851 | snd_hda_gen_spec_init(&spec->gen); | 851 | snd_hda_gen_spec_init(&spec->gen); |
852 | codec->spec = spec; | 852 | codec->spec = spec; |
853 | codec->patch_ops = cx_auto_patch_ops; | ||
853 | 854 | ||
854 | cx_auto_parse_beep(codec); | 855 | cx_auto_parse_beep(codec); |
855 | cx_auto_parse_eapd(codec); | 856 | cx_auto_parse_eapd(codec); |
@@ -908,8 +909,6 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
908 | if (err < 0) | 909 | if (err < 0) |
909 | goto error; | 910 | goto error; |
910 | 911 | ||
911 | codec->patch_ops = cx_auto_patch_ops; | ||
912 | |||
913 | /* Some laptops with Conexant chips show stalls in S3 resume, | 912 | /* Some laptops with Conexant chips show stalls in S3 resume, |
914 | * which falls into the single-cmd mode. | 913 | * which falls into the single-cmd mode. |
915 | * Better to make reset, then. | 914 | * Better to make reset, then. |
@@ -968,6 +967,14 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
968 | .patch = patch_conexant_auto }, | 967 | .patch = patch_conexant_auto }, |
969 | { .id = 0x14f150b9, .name = "CX20665", | 968 | { .id = 0x14f150b9, .name = "CX20665", |
970 | .patch = patch_conexant_auto }, | 969 | .patch = patch_conexant_auto }, |
970 | { .id = 0x14f150f1, .name = "CX20721", | ||
971 | .patch = patch_conexant_auto }, | ||
972 | { .id = 0x14f150f2, .name = "CX20722", | ||
973 | .patch = patch_conexant_auto }, | ||
974 | { .id = 0x14f150f3, .name = "CX20723", | ||
975 | .patch = patch_conexant_auto }, | ||
976 | { .id = 0x14f150f4, .name = "CX20724", | ||
977 | .patch = patch_conexant_auto }, | ||
971 | { .id = 0x14f1510f, .name = "CX20751/2", | 978 | { .id = 0x14f1510f, .name = "CX20751/2", |
972 | .patch = patch_conexant_auto }, | 979 | .patch = patch_conexant_auto }, |
973 | { .id = 0x14f15110, .name = "CX20751/2", | 980 | { .id = 0x14f15110, .name = "CX20751/2", |
@@ -1002,6 +1009,10 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab"); | |||
1002 | MODULE_ALIAS("snd-hda-codec-id:14f150ac"); | 1009 | MODULE_ALIAS("snd-hda-codec-id:14f150ac"); |
1003 | MODULE_ALIAS("snd-hda-codec-id:14f150b8"); | 1010 | MODULE_ALIAS("snd-hda-codec-id:14f150b8"); |
1004 | MODULE_ALIAS("snd-hda-codec-id:14f150b9"); | 1011 | MODULE_ALIAS("snd-hda-codec-id:14f150b9"); |
1012 | MODULE_ALIAS("snd-hda-codec-id:14f150f1"); | ||
1013 | MODULE_ALIAS("snd-hda-codec-id:14f150f2"); | ||
1014 | MODULE_ALIAS("snd-hda-codec-id:14f150f3"); | ||
1015 | MODULE_ALIAS("snd-hda-codec-id:14f150f4"); | ||
1005 | MODULE_ALIAS("snd-hda-codec-id:14f1510f"); | 1016 | MODULE_ALIAS("snd-hda-codec-id:14f1510f"); |
1006 | MODULE_ALIAS("snd-hda-codec-id:14f15110"); | 1017 | MODULE_ALIAS("snd-hda-codec-id:14f15110"); |
1007 | MODULE_ALIAS("snd-hda-codec-id:14f15111"); | 1018 | MODULE_ALIAS("snd-hda-codec-id:14f15111"); |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5f44f60a6389..95158914cc6c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -86,7 +86,7 @@ struct hdmi_spec_per_pin { | |||
86 | bool non_pcm; | 86 | bool non_pcm; |
87 | bool chmap_set; /* channel-map override by ALSA API? */ | 87 | bool chmap_set; /* channel-map override by ALSA API? */ |
88 | unsigned char chmap[8]; /* ALSA API channel-map */ | 88 | unsigned char chmap[8]; /* ALSA API channel-map */ |
89 | #ifdef CONFIG_PROC_FS | 89 | #ifdef CONFIG_SND_PROC_FS |
90 | struct snd_info_entry *proc_entry; | 90 | struct snd_info_entry *proc_entry; |
91 | #endif | 91 | #endif |
92 | }; | 92 | }; |
@@ -548,7 +548,7 @@ static void hdmi_set_channel_count(struct hda_codec *codec, | |||
548 | * ELD proc files | 548 | * ELD proc files |
549 | */ | 549 | */ |
550 | 550 | ||
551 | #ifdef CONFIG_PROC_FS | 551 | #ifdef CONFIG_SND_PROC_FS |
552 | static void print_eld_info(struct snd_info_entry *entry, | 552 | static void print_eld_info(struct snd_info_entry *entry, |
553 | struct snd_info_buffer *buffer) | 553 | struct snd_info_buffer *buffer) |
554 | { | 554 | { |
@@ -591,8 +591,8 @@ static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index) | |||
591 | 591 | ||
592 | static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) | 592 | static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) |
593 | { | 593 | { |
594 | if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) { | 594 | if (!per_pin->codec->bus->shutdown) { |
595 | snd_device_free(per_pin->codec->card, per_pin->proc_entry); | 595 | snd_info_free_entry(per_pin->proc_entry); |
596 | per_pin->proc_entry = NULL; | 596 | per_pin->proc_entry = NULL; |
597 | } | 597 | } |
598 | } | 598 | } |
@@ -2049,9 +2049,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
2049 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2049 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2050 | struct hda_pcm *info; | 2050 | struct hda_pcm *info; |
2051 | struct hda_pcm_stream *pstr; | 2051 | struct hda_pcm_stream *pstr; |
2052 | struct hdmi_spec_per_pin *per_pin; | ||
2053 | 2052 | ||
2054 | per_pin = get_pin(spec, pin_idx); | ||
2055 | info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx); | 2053 | info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx); |
2056 | if (!info) | 2054 | if (!info) |
2057 | return -ENOMEM; | 2055 | return -ENOMEM; |
@@ -2081,7 +2079,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | |||
2081 | strncat(hdmi_str, " Phantom", | 2079 | strncat(hdmi_str, " Phantom", |
2082 | sizeof(hdmi_str) - strlen(hdmi_str) - 1); | 2080 | sizeof(hdmi_str) - strlen(hdmi_str) - 1); |
2083 | 2081 | ||
2084 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); | 2082 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str); |
2085 | } | 2083 | } |
2086 | 2084 | ||
2087 | static int generic_hdmi_build_controls(struct hda_codec *codec) | 2085 | static int generic_hdmi_build_controls(struct hda_codec *codec) |
@@ -2335,6 +2333,15 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2335 | intel_haswell_fixup_enable_dp12(codec); | 2333 | intel_haswell_fixup_enable_dp12(codec); |
2336 | } | 2334 | } |
2337 | 2335 | ||
2336 | /* For Valleyview/Cherryview, only the display codec is in the display | ||
2337 | * power well and can use link_power ops to request/release the power. | ||
2338 | * For Haswell/Broadwell, the controller is also in the power well and | ||
2339 | * can cover the codec power request, and so need not set this flag. | ||
2340 | * For previous platforms, there is no such power well feature. | ||
2341 | */ | ||
2342 | if (is_valleyview_plus(codec) || is_skylake(codec)) | ||
2343 | codec->core.link_power_control = 1; | ||
2344 | |||
2338 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | 2345 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
2339 | codec->depop_delay = 0; | 2346 | codec->depop_delay = 0; |
2340 | 2347 | ||
@@ -2349,6 +2356,10 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2349 | codec->dp_mst = true; | 2356 | codec->dp_mst = true; |
2350 | } | 2357 | } |
2351 | 2358 | ||
2359 | /* Enable runtime pm for HDMI audio codec of HSW/BDW/SKL/BYT/BSW */ | ||
2360 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | ||
2361 | codec->auto_runtime_pm = 1; | ||
2362 | |||
2352 | generic_hdmi_init_per_pins(codec); | 2363 | generic_hdmi_init_per_pins(codec); |
2353 | 2364 | ||
2354 | init_channel_allocations(); | 2365 | init_channel_allocations(); |
@@ -2923,6 +2934,171 @@ static int patch_nvhdmi(struct hda_codec *codec) | |||
2923 | } | 2934 | } |
2924 | 2935 | ||
2925 | /* | 2936 | /* |
2937 | * The HDA codec on NVIDIA Tegra contains two scratch registers that are | ||
2938 | * accessed using vendor-defined verbs. These registers can be used for | ||
2939 | * interoperability between the HDA and HDMI drivers. | ||
2940 | */ | ||
2941 | |||
2942 | /* Audio Function Group node */ | ||
2943 | #define NVIDIA_AFG_NID 0x01 | ||
2944 | |||
2945 | /* | ||
2946 | * The SCRATCH0 register is used to notify the HDMI codec of changes in audio | ||
2947 | * format. On Tegra, bit 31 is used as a trigger that causes an interrupt to | ||
2948 | * be raised in the HDMI codec. The remainder of the bits is arbitrary. This | ||
2949 | * implementation stores the HDA format (see AC_FMT_*) in bits [15:0] and an | ||
2950 | * additional bit (at position 30) to signal the validity of the format. | ||
2951 | * | ||
2952 | * | 31 | 30 | 29 16 | 15 0 | | ||
2953 | * +---------+-------+--------+--------+ | ||
2954 | * | TRIGGER | VALID | UNUSED | FORMAT | | ||
2955 | * +-----------------------------------| | ||
2956 | * | ||
2957 | * Note that for the trigger bit to take effect it needs to change value | ||
2958 | * (i.e. it needs to be toggled). | ||
2959 | */ | ||
2960 | #define NVIDIA_GET_SCRATCH0 0xfa6 | ||
2961 | #define NVIDIA_SET_SCRATCH0_BYTE0 0xfa7 | ||
2962 | #define NVIDIA_SET_SCRATCH0_BYTE1 0xfa8 | ||
2963 | #define NVIDIA_SET_SCRATCH0_BYTE2 0xfa9 | ||
2964 | #define NVIDIA_SET_SCRATCH0_BYTE3 0xfaa | ||
2965 | #define NVIDIA_SCRATCH_TRIGGER (1 << 7) | ||
2966 | #define NVIDIA_SCRATCH_VALID (1 << 6) | ||
2967 | |||
2968 | #define NVIDIA_GET_SCRATCH1 0xfab | ||
2969 | #define NVIDIA_SET_SCRATCH1_BYTE0 0xfac | ||
2970 | #define NVIDIA_SET_SCRATCH1_BYTE1 0xfad | ||
2971 | #define NVIDIA_SET_SCRATCH1_BYTE2 0xfae | ||
2972 | #define NVIDIA_SET_SCRATCH1_BYTE3 0xfaf | ||
2973 | |||
2974 | /* | ||
2975 | * The format parameter is the HDA audio format (see AC_FMT_*). If set to 0, | ||
2976 | * the format is invalidated so that the HDMI codec can be disabled. | ||
2977 | */ | ||
2978 | static void tegra_hdmi_set_format(struct hda_codec *codec, unsigned int format) | ||
2979 | { | ||
2980 | unsigned int value; | ||
2981 | |||
2982 | /* bits [31:30] contain the trigger and valid bits */ | ||
2983 | value = snd_hda_codec_read(codec, NVIDIA_AFG_NID, 0, | ||
2984 | NVIDIA_GET_SCRATCH0, 0); | ||
2985 | value = (value >> 24) & 0xff; | ||
2986 | |||
2987 | /* bits [15:0] are used to store the HDA format */ | ||
2988 | snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0, | ||
2989 | NVIDIA_SET_SCRATCH0_BYTE0, | ||
2990 | (format >> 0) & 0xff); | ||
2991 | snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0, | ||
2992 | NVIDIA_SET_SCRATCH0_BYTE1, | ||
2993 | (format >> 8) & 0xff); | ||
2994 | |||
2995 | /* bits [16:24] are unused */ | ||
2996 | snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0, | ||
2997 | NVIDIA_SET_SCRATCH0_BYTE2, 0); | ||
2998 | |||
2999 | /* | ||
3000 | * Bit 30 signals that the data is valid and hence that HDMI audio can | ||
3001 | * be enabled. | ||
3002 | */ | ||
3003 | if (format == 0) | ||
3004 | value &= ~NVIDIA_SCRATCH_VALID; | ||
3005 | else | ||
3006 | value |= NVIDIA_SCRATCH_VALID; | ||
3007 | |||
3008 | /* | ||
3009 | * Whenever the trigger bit is toggled, an interrupt is raised in the | ||
3010 | * HDMI codec. The HDMI driver will use that as trigger to update its | ||
3011 | * configuration. | ||
3012 | */ | ||
3013 | value ^= NVIDIA_SCRATCH_TRIGGER; | ||
3014 | |||
3015 | snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0, | ||
3016 | NVIDIA_SET_SCRATCH0_BYTE3, value); | ||
3017 | } | ||
3018 | |||
3019 | static int tegra_hdmi_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3020 | struct hda_codec *codec, | ||
3021 | unsigned int stream_tag, | ||
3022 | unsigned int format, | ||
3023 | struct snd_pcm_substream *substream) | ||
3024 | { | ||
3025 | int err; | ||
3026 | |||
3027 | err = generic_hdmi_playback_pcm_prepare(hinfo, codec, stream_tag, | ||
3028 | format, substream); | ||
3029 | if (err < 0) | ||
3030 | return err; | ||
3031 | |||
3032 | /* notify the HDMI codec of the format change */ | ||
3033 | tegra_hdmi_set_format(codec, format); | ||
3034 | |||
3035 | return 0; | ||
3036 | } | ||
3037 | |||
3038 | static int tegra_hdmi_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3039 | struct hda_codec *codec, | ||
3040 | struct snd_pcm_substream *substream) | ||
3041 | { | ||
3042 | /* invalidate the format in the HDMI codec */ | ||
3043 | tegra_hdmi_set_format(codec, 0); | ||
3044 | |||
3045 | return generic_hdmi_playback_pcm_cleanup(hinfo, codec, substream); | ||
3046 | } | ||
3047 | |||
3048 | static struct hda_pcm *hda_find_pcm_by_type(struct hda_codec *codec, int type) | ||
3049 | { | ||
3050 | struct hdmi_spec *spec = codec->spec; | ||
3051 | unsigned int i; | ||
3052 | |||
3053 | for (i = 0; i < spec->num_pins; i++) { | ||
3054 | struct hda_pcm *pcm = get_pcm_rec(spec, i); | ||
3055 | |||
3056 | if (pcm->pcm_type == type) | ||
3057 | return pcm; | ||
3058 | } | ||
3059 | |||
3060 | return NULL; | ||
3061 | } | ||
3062 | |||
3063 | static int tegra_hdmi_build_pcms(struct hda_codec *codec) | ||
3064 | { | ||
3065 | struct hda_pcm_stream *stream; | ||
3066 | struct hda_pcm *pcm; | ||
3067 | int err; | ||
3068 | |||
3069 | err = generic_hdmi_build_pcms(codec); | ||
3070 | if (err < 0) | ||
3071 | return err; | ||
3072 | |||
3073 | pcm = hda_find_pcm_by_type(codec, HDA_PCM_TYPE_HDMI); | ||
3074 | if (!pcm) | ||
3075 | return -ENODEV; | ||
3076 | |||
3077 | /* | ||
3078 | * Override ->prepare() and ->cleanup() operations to notify the HDMI | ||
3079 | * codec about format changes. | ||
3080 | */ | ||
3081 | stream = &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
3082 | stream->ops.prepare = tegra_hdmi_pcm_prepare; | ||
3083 | stream->ops.cleanup = tegra_hdmi_pcm_cleanup; | ||
3084 | |||
3085 | return 0; | ||
3086 | } | ||
3087 | |||
3088 | static int patch_tegra_hdmi(struct hda_codec *codec) | ||
3089 | { | ||
3090 | int err; | ||
3091 | |||
3092 | err = patch_generic_hdmi(codec); | ||
3093 | if (err) | ||
3094 | return err; | ||
3095 | |||
3096 | codec->patch_ops.build_pcms = tegra_hdmi_build_pcms; | ||
3097 | |||
3098 | return 0; | ||
3099 | } | ||
3100 | |||
3101 | /* | ||
2926 | * ATI/AMD-specific implementations | 3102 | * ATI/AMD-specific implementations |
2927 | */ | 3103 | */ |
2928 | 3104 | ||
@@ -3321,7 +3497,10 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3321 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, | 3497 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, |
3322 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, | 3498 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, |
3323 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, | 3499 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, |
3324 | { .id = 0x10de0028, .name = "Tegra12x HDMI", .patch = patch_nvhdmi }, | 3500 | { .id = 0x10de0020, .name = "Tegra30 HDMI", .patch = patch_tegra_hdmi }, |
3501 | { .id = 0x10de0022, .name = "Tegra114 HDMI", .patch = patch_tegra_hdmi }, | ||
3502 | { .id = 0x10de0028, .name = "Tegra124 HDMI", .patch = patch_tegra_hdmi }, | ||
3503 | { .id = 0x10de0029, .name = "Tegra210 HDMI/DP", .patch = patch_tegra_hdmi }, | ||
3325 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, | 3504 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, |
3326 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, | 3505 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, |
3327 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, | 3506 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, |
@@ -3348,6 +3527,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3348 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, | 3527 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, |
3349 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, | 3528 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, |
3350 | { .id = 0x80862809, .name = "Skylake HDMI", .patch = patch_generic_hdmi }, | 3529 | { .id = 0x80862809, .name = "Skylake HDMI", .patch = patch_generic_hdmi }, |
3530 | { .id = 0x8086280a, .name = "Broxton HDMI", .patch = patch_generic_hdmi }, | ||
3351 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | 3531 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
3352 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, | 3532 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, |
3353 | { .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, | 3533 | { .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, |
@@ -3412,6 +3592,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862806"); | |||
3412 | MODULE_ALIAS("snd-hda-codec-id:80862807"); | 3592 | MODULE_ALIAS("snd-hda-codec-id:80862807"); |
3413 | MODULE_ALIAS("snd-hda-codec-id:80862808"); | 3593 | MODULE_ALIAS("snd-hda-codec-id:80862808"); |
3414 | MODULE_ALIAS("snd-hda-codec-id:80862809"); | 3594 | MODULE_ALIAS("snd-hda-codec-id:80862809"); |
3595 | MODULE_ALIAS("snd-hda-codec-id:8086280a"); | ||
3415 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | 3596 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
3416 | MODULE_ALIAS("snd-hda-codec-id:80862882"); | 3597 | MODULE_ALIAS("snd-hda-codec-id:80862882"); |
3417 | MODULE_ALIAS("snd-hda-codec-id:80862883"); | 3598 | MODULE_ALIAS("snd-hda-codec-id:80862883"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 06199e4e930f..d35cf506a7db 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -883,6 +883,8 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = { | |||
883 | { 0x10ec0668, 0x1028, 0, "ALC3661" }, | 883 | { 0x10ec0668, 0x1028, 0, "ALC3661" }, |
884 | { 0x10ec0275, 0x1028, 0, "ALC3260" }, | 884 | { 0x10ec0275, 0x1028, 0, "ALC3260" }, |
885 | { 0x10ec0899, 0x1028, 0, "ALC3861" }, | 885 | { 0x10ec0899, 0x1028, 0, "ALC3861" }, |
886 | { 0x10ec0298, 0x1028, 0, "ALC3266" }, | ||
887 | { 0x10ec0256, 0x1028, 0, "ALC3246" }, | ||
886 | { 0x10ec0670, 0x1025, 0, "ALC669X" }, | 888 | { 0x10ec0670, 0x1025, 0, "ALC669X" }, |
887 | { 0x10ec0676, 0x1025, 0, "ALC679X" }, | 889 | { 0x10ec0676, 0x1025, 0, "ALC679X" }, |
888 | { 0x10ec0282, 0x1043, 0, "ALC3229" }, | 890 | { 0x10ec0282, 0x1043, 0, "ALC3229" }, |
@@ -1001,6 +1003,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) | |||
1001 | codec->single_adc_amp = 1; | 1003 | codec->single_adc_amp = 1; |
1002 | /* FIXME: do we need this for all Realtek codec models? */ | 1004 | /* FIXME: do we need this for all Realtek codec models? */ |
1003 | codec->spdif_status_reset = 1; | 1005 | codec->spdif_status_reset = 1; |
1006 | codec->patch_ops = alc_patch_ops; | ||
1004 | 1007 | ||
1005 | err = alc_codec_rename_from_preset(codec); | 1008 | err = alc_codec_rename_from_preset(codec); |
1006 | if (err < 0) { | 1009 | if (err < 0) { |
@@ -1445,6 +1448,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
1445 | spec->gen.need_dac_fix = 1; | 1448 | spec->gen.need_dac_fix = 1; |
1446 | spec->gen.beep_nid = 0x01; | 1449 | spec->gen.beep_nid = 0x01; |
1447 | 1450 | ||
1451 | codec->patch_ops.unsol_event = alc880_unsol_event; | ||
1452 | |||
1448 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, | 1453 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, |
1449 | alc880_fixups); | 1454 | alc880_fixups); |
1450 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1455 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -1457,10 +1462,6 @@ static int patch_alc880(struct hda_codec *codec) | |||
1457 | if (!spec->gen.no_analog) | 1462 | if (!spec->gen.no_analog) |
1458 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 1463 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
1459 | 1464 | ||
1460 | codec->patch_ops = alc_patch_ops; | ||
1461 | codec->patch_ops.unsol_event = alc880_unsol_event; | ||
1462 | |||
1463 | |||
1464 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 1465 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
1465 | 1466 | ||
1466 | return 0; | 1467 | return 0; |
@@ -1697,6 +1698,8 @@ static int patch_alc260(struct hda_codec *codec) | |||
1697 | spec->gen.prefer_hp_amp = 1; | 1698 | spec->gen.prefer_hp_amp = 1; |
1698 | spec->gen.beep_nid = 0x01; | 1699 | spec->gen.beep_nid = 0x01; |
1699 | 1700 | ||
1701 | spec->shutup = alc_eapd_shutup; | ||
1702 | |||
1700 | snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, | 1703 | snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, |
1701 | alc260_fixups); | 1704 | alc260_fixups); |
1702 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1705 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -1709,9 +1712,6 @@ static int patch_alc260(struct hda_codec *codec) | |||
1709 | if (!spec->gen.no_analog) | 1712 | if (!spec->gen.no_analog) |
1710 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 1713 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
1711 | 1714 | ||
1712 | codec->patch_ops = alc_patch_ops; | ||
1713 | spec->shutup = alc_eapd_shutup; | ||
1714 | |||
1715 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 1715 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
1716 | 1716 | ||
1717 | return 0; | 1717 | return 0; |
@@ -2166,6 +2166,7 @@ static const struct hda_fixup alc882_fixups[] = { | |||
2166 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 2166 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
2167 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD), | 2167 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD), |
2168 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), | 2168 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), |
2169 | SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), | ||
2169 | SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD), | 2170 | SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD), |
2170 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), | 2171 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), |
2171 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD), | 2172 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD), |
@@ -2296,8 +2297,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
2296 | if (!spec->gen.no_analog && spec->gen.beep_nid) | 2297 | if (!spec->gen.no_analog && spec->gen.beep_nid) |
2297 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 2298 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
2298 | 2299 | ||
2299 | codec->patch_ops = alc_patch_ops; | ||
2300 | |||
2301 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 2300 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
2302 | 2301 | ||
2303 | return 0; | 2302 | return 0; |
@@ -2433,6 +2432,8 @@ static int patch_alc262(struct hda_codec *codec) | |||
2433 | spec = codec->spec; | 2432 | spec = codec->spec; |
2434 | spec->gen.shared_mic_vref_pin = 0x18; | 2433 | spec->gen.shared_mic_vref_pin = 0x18; |
2435 | 2434 | ||
2435 | spec->shutup = alc_eapd_shutup; | ||
2436 | |||
2436 | #if 0 | 2437 | #if 0 |
2437 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is | 2438 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is |
2438 | * under-run | 2439 | * under-run |
@@ -2458,9 +2459,6 @@ static int patch_alc262(struct hda_codec *codec) | |||
2458 | if (!spec->gen.no_analog && spec->gen.beep_nid) | 2459 | if (!spec->gen.no_analog && spec->gen.beep_nid) |
2459 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 2460 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
2460 | 2461 | ||
2461 | codec->patch_ops = alc_patch_ops; | ||
2462 | spec->shutup = alc_eapd_shutup; | ||
2463 | |||
2464 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 2462 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
2465 | 2463 | ||
2466 | return 0; | 2464 | return 0; |
@@ -2564,6 +2562,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
2564 | spec = codec->spec; | 2562 | spec = codec->spec; |
2565 | spec->gen.beep_nid = 0x01; | 2563 | spec->gen.beep_nid = 0x01; |
2566 | 2564 | ||
2565 | spec->shutup = alc_eapd_shutup; | ||
2566 | |||
2567 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); | 2567 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); |
2568 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 2568 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
2569 | 2569 | ||
@@ -2585,9 +2585,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
2585 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 2585 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
2586 | } | 2586 | } |
2587 | 2587 | ||
2588 | codec->patch_ops = alc_patch_ops; | ||
2589 | spec->shutup = alc_eapd_shutup; | ||
2590 | |||
2591 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 2588 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
2592 | 2589 | ||
2593 | return 0; | 2590 | return 0; |
@@ -3583,6 +3580,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3583 | break; | 3580 | break; |
3584 | case 0x10ec0286: | 3581 | case 0x10ec0286: |
3585 | case 0x10ec0288: | 3582 | case 0x10ec0288: |
3583 | case 0x10ec0298: | ||
3586 | alc_process_coef_fw(codec, coef0288); | 3584 | alc_process_coef_fw(codec, coef0288); |
3587 | break; | 3585 | break; |
3588 | case 0x10ec0292: | 3586 | case 0x10ec0292: |
@@ -3657,6 +3655,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3657 | break; | 3655 | break; |
3658 | case 0x10ec0286: | 3656 | case 0x10ec0286: |
3659 | case 0x10ec0288: | 3657 | case 0x10ec0288: |
3658 | case 0x10ec0298: | ||
3660 | alc_update_coef_idx(codec, 0x4f, 0x000c, 0); | 3659 | alc_update_coef_idx(codec, 0x4f, 0x000c, 0); |
3661 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3660 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3662 | alc_process_coef_fw(codec, coef0288); | 3661 | alc_process_coef_fw(codec, coef0288); |
@@ -3673,6 +3672,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3673 | alc_process_coef_fw(codec, coef0293); | 3672 | alc_process_coef_fw(codec, coef0293); |
3674 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3673 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3675 | break; | 3674 | break; |
3675 | case 0x10ec0662: | ||
3676 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
3677 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | ||
3678 | break; | ||
3676 | case 0x10ec0668: | 3679 | case 0x10ec0668: |
3677 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3680 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3678 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3681 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
@@ -3736,9 +3739,9 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3736 | break; | 3739 | break; |
3737 | case 0x10ec0286: | 3740 | case 0x10ec0286: |
3738 | case 0x10ec0288: | 3741 | case 0x10ec0288: |
3742 | case 0x10ec0298: | ||
3739 | alc_process_coef_fw(codec, coef0288); | 3743 | alc_process_coef_fw(codec, coef0288); |
3740 | break; | 3744 | break; |
3741 | break; | ||
3742 | case 0x10ec0292: | 3745 | case 0x10ec0292: |
3743 | alc_process_coef_fw(codec, coef0292); | 3746 | alc_process_coef_fw(codec, coef0292); |
3744 | break; | 3747 | break; |
@@ -3801,6 +3804,9 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
3801 | case 0x10ec0283: | 3804 | case 0x10ec0283: |
3802 | alc_process_coef_fw(codec, coef0233); | 3805 | alc_process_coef_fw(codec, coef0233); |
3803 | break; | 3806 | break; |
3807 | case 0x10ec0298: | ||
3808 | alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);/* Headset output enable */ | ||
3809 | /* ALC298 jack type setting is the same with ALC286/ALC288 */ | ||
3804 | case 0x10ec0286: | 3810 | case 0x10ec0286: |
3805 | case 0x10ec0288: | 3811 | case 0x10ec0288: |
3806 | alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400); | 3812 | alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400); |
@@ -3869,6 +3875,9 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) | |||
3869 | case 0x10ec0283: | 3875 | case 0x10ec0283: |
3870 | alc_process_coef_fw(codec, coef0233); | 3876 | alc_process_coef_fw(codec, coef0233); |
3871 | break; | 3877 | break; |
3878 | case 0x10ec0298: | ||
3879 | alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */ | ||
3880 | /* ALC298 jack type setting is the same with ALC286/ALC288 */ | ||
3872 | case 0x10ec0286: | 3881 | case 0x10ec0286: |
3873 | case 0x10ec0288: | 3882 | case 0x10ec0288: |
3874 | alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400); | 3883 | alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400); |
@@ -3931,6 +3940,9 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
3931 | val = alc_read_coef_idx(codec, 0x46); | 3940 | val = alc_read_coef_idx(codec, 0x46); |
3932 | is_ctia = (val & 0x0070) == 0x0070; | 3941 | is_ctia = (val & 0x0070) == 0x0070; |
3933 | break; | 3942 | break; |
3943 | case 0x10ec0298: | ||
3944 | alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020); /* Headset output enable */ | ||
3945 | /* ALC298 check jack type is the same with ALC286/ALC288 */ | ||
3934 | case 0x10ec0286: | 3946 | case 0x10ec0286: |
3935 | case 0x10ec0288: | 3947 | case 0x10ec0288: |
3936 | alc_process_coef_fw(codec, coef0288); | 3948 | alc_process_coef_fw(codec, coef0288); |
@@ -4012,7 +4024,7 @@ static void alc_update_headset_mode(struct hda_codec *codec) | |||
4012 | if (new_headset_mode != ALC_HEADSET_MODE_MIC) { | 4024 | if (new_headset_mode != ALC_HEADSET_MODE_MIC) { |
4013 | snd_hda_set_pin_ctl_cache(codec, hp_pin, | 4025 | snd_hda_set_pin_ctl_cache(codec, hp_pin, |
4014 | AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 4026 | AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); |
4015 | if (spec->headphone_mic_pin) | 4027 | if (spec->headphone_mic_pin && spec->headphone_mic_pin != hp_pin) |
4016 | snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin, | 4028 | snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin, |
4017 | PIN_VREFHIZ); | 4029 | PIN_VREFHIZ); |
4018 | } | 4030 | } |
@@ -4190,11 +4202,18 @@ static void alc_shutup_dell_xps13(struct hda_codec *codec) | |||
4190 | static void alc_fixup_dell_xps13(struct hda_codec *codec, | 4202 | static void alc_fixup_dell_xps13(struct hda_codec *codec, |
4191 | const struct hda_fixup *fix, int action) | 4203 | const struct hda_fixup *fix, int action) |
4192 | { | 4204 | { |
4193 | if (action == HDA_FIXUP_ACT_PROBE) { | 4205 | struct alc_spec *spec = codec->spec; |
4194 | struct alc_spec *spec = codec->spec; | 4206 | struct hda_input_mux *imux = &spec->gen.input_mux; |
4195 | struct hda_input_mux *imux = &spec->gen.input_mux; | 4207 | int i; |
4196 | int i; | ||
4197 | 4208 | ||
4209 | switch (action) { | ||
4210 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
4211 | /* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise | ||
4212 | * it causes a click noise at start up | ||
4213 | */ | ||
4214 | snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ); | ||
4215 | break; | ||
4216 | case HDA_FIXUP_ACT_PROBE: | ||
4198 | spec->shutup = alc_shutup_dell_xps13; | 4217 | spec->shutup = alc_shutup_dell_xps13; |
4199 | 4218 | ||
4200 | /* Make the internal mic the default input source. */ | 4219 | /* Make the internal mic the default input source. */ |
@@ -4204,9 +4223,27 @@ static void alc_fixup_dell_xps13(struct hda_codec *codec, | |||
4204 | break; | 4223 | break; |
4205 | } | 4224 | } |
4206 | } | 4225 | } |
4226 | break; | ||
4207 | } | 4227 | } |
4208 | } | 4228 | } |
4209 | 4229 | ||
4230 | static void alc_fixup_headset_mode_alc662(struct hda_codec *codec, | ||
4231 | const struct hda_fixup *fix, int action) | ||
4232 | { | ||
4233 | struct alc_spec *spec = codec->spec; | ||
4234 | |||
4235 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
4236 | spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; | ||
4237 | spec->gen.hp_mic = 1; /* Mic-in is same pin as headphone */ | ||
4238 | |||
4239 | /* Disable boost for mic-in permanently. (This code is only called | ||
4240 | from quirks that guarantee that the headphone is at NID 0x1b.) */ | ||
4241 | snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000); | ||
4242 | snd_hda_override_wcaps(codec, 0x1b, get_wcaps(codec, 0x1b) & ~AC_WCAP_IN_AMP); | ||
4243 | } else | ||
4244 | alc_fixup_headset_mode(codec, fix, action); | ||
4245 | } | ||
4246 | |||
4210 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, | 4247 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, |
4211 | const struct hda_fixup *fix, int action) | 4248 | const struct hda_fixup *fix, int action) |
4212 | { | 4249 | { |
@@ -4404,6 +4441,55 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec, | |||
4404 | } | 4441 | } |
4405 | } | 4442 | } |
4406 | 4443 | ||
4444 | /* Hook to update amp GPIO4 for automute */ | ||
4445 | static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec, | ||
4446 | struct hda_jack_callback *jack) | ||
4447 | { | ||
4448 | struct alc_spec *spec = codec->spec; | ||
4449 | |||
4450 | snd_hda_gen_hp_automute(codec, jack); | ||
4451 | /* mute_led_polarity is set to 0, so we pass inverted value here */ | ||
4452 | alc_update_gpio_led(codec, 0x10, !spec->gen.hp_jack_present); | ||
4453 | } | ||
4454 | |||
4455 | /* Manage GPIOs for HP EliteBook Folio 9480m. | ||
4456 | * | ||
4457 | * GPIO4 is the headphone amplifier power control | ||
4458 | * GPIO3 is the audio output mute indicator LED | ||
4459 | */ | ||
4460 | |||
4461 | static void alc280_fixup_hp_9480m(struct hda_codec *codec, | ||
4462 | const struct hda_fixup *fix, | ||
4463 | int action) | ||
4464 | { | ||
4465 | struct alc_spec *spec = codec->spec; | ||
4466 | static const struct hda_verb gpio_init[] = { | ||
4467 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, | ||
4468 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, | ||
4469 | {} | ||
4470 | }; | ||
4471 | |||
4472 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
4473 | /* Set the hooks to turn the headphone amp on/off | ||
4474 | * as needed | ||
4475 | */ | ||
4476 | spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; | ||
4477 | spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook; | ||
4478 | |||
4479 | /* The GPIOs are currently off */ | ||
4480 | spec->gpio_led = 0; | ||
4481 | |||
4482 | /* GPIO3 is connected to the output mute LED, | ||
4483 | * high is on, low is off | ||
4484 | */ | ||
4485 | spec->mute_led_polarity = 0; | ||
4486 | spec->gpio_mute_led_mask = 0x08; | ||
4487 | |||
4488 | /* Initialize GPIO configuration */ | ||
4489 | snd_hda_add_verbs(codec, gpio_init); | ||
4490 | } | ||
4491 | } | ||
4492 | |||
4407 | /* for hda_fixup_thinkpad_acpi() */ | 4493 | /* for hda_fixup_thinkpad_acpi() */ |
4408 | #include "thinkpad_helper.c" | 4494 | #include "thinkpad_helper.c" |
4409 | 4495 | ||
@@ -4427,6 +4513,7 @@ enum { | |||
4427 | ALC269_FIXUP_LIFEBOOK, | 4513 | ALC269_FIXUP_LIFEBOOK, |
4428 | ALC269_FIXUP_LIFEBOOK_EXTMIC, | 4514 | ALC269_FIXUP_LIFEBOOK_EXTMIC, |
4429 | ALC269_FIXUP_LIFEBOOK_HP_PIN, | 4515 | ALC269_FIXUP_LIFEBOOK_HP_PIN, |
4516 | ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT, | ||
4430 | ALC269_FIXUP_AMIC, | 4517 | ALC269_FIXUP_AMIC, |
4431 | ALC269_FIXUP_DMIC, | 4518 | ALC269_FIXUP_DMIC, |
4432 | ALC269VB_FIXUP_AMIC, | 4519 | ALC269VB_FIXUP_AMIC, |
@@ -4447,6 +4534,7 @@ enum { | |||
4447 | ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | 4534 | ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, |
4448 | ALC269_FIXUP_HEADSET_MODE, | 4535 | ALC269_FIXUP_HEADSET_MODE, |
4449 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, | 4536 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4537 | ALC269_FIXUP_ASPIRE_HEADSET_MIC, | ||
4450 | ALC269_FIXUP_ASUS_X101_FUNC, | 4538 | ALC269_FIXUP_ASUS_X101_FUNC, |
4451 | ALC269_FIXUP_ASUS_X101_VERB, | 4539 | ALC269_FIXUP_ASUS_X101_VERB, |
4452 | ALC269_FIXUP_ASUS_X101, | 4540 | ALC269_FIXUP_ASUS_X101, |
@@ -4474,6 +4562,7 @@ enum { | |||
4474 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, | 4562 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4475 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | 4563 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, |
4476 | ALC292_FIXUP_TPT440_DOCK, | 4564 | ALC292_FIXUP_TPT440_DOCK, |
4565 | ALC292_FIXUP_TPT440_DOCK2, | ||
4477 | ALC283_FIXUP_BXBT2807_MIC, | 4566 | ALC283_FIXUP_BXBT2807_MIC, |
4478 | ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, | 4567 | ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, |
4479 | ALC282_FIXUP_ASPIRE_V5_PINS, | 4568 | ALC282_FIXUP_ASPIRE_V5_PINS, |
@@ -4481,9 +4570,15 @@ enum { | |||
4481 | ALC286_FIXUP_HP_GPIO_LED, | 4570 | ALC286_FIXUP_HP_GPIO_LED, |
4482 | ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, | 4571 | ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, |
4483 | ALC280_FIXUP_HP_DOCK_PINS, | 4572 | ALC280_FIXUP_HP_DOCK_PINS, |
4573 | ALC280_FIXUP_HP_9480M, | ||
4484 | ALC288_FIXUP_DELL_HEADSET_MODE, | 4574 | ALC288_FIXUP_DELL_HEADSET_MODE, |
4485 | ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, | 4575 | ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, |
4486 | ALC288_FIXUP_DELL_XPS_13_GPIO6, | 4576 | ALC288_FIXUP_DELL_XPS_13_GPIO6, |
4577 | ALC288_FIXUP_DELL_XPS_13, | ||
4578 | ALC288_FIXUP_DISABLE_AAMIX, | ||
4579 | ALC292_FIXUP_DELL_E7X, | ||
4580 | ALC292_FIXUP_DISABLE_AAMIX, | ||
4581 | ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
4487 | }; | 4582 | }; |
4488 | 4583 | ||
4489 | static const struct hda_fixup alc269_fixups[] = { | 4584 | static const struct hda_fixup alc269_fixups[] = { |
@@ -4590,6 +4685,10 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4590 | { } | 4685 | { } |
4591 | }, | 4686 | }, |
4592 | }, | 4687 | }, |
4688 | [ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT] = { | ||
4689 | .type = HDA_FIXUP_FUNC, | ||
4690 | .v.func = alc269_fixup_pincfg_no_hp_to_lineout, | ||
4691 | }, | ||
4593 | [ALC269_FIXUP_AMIC] = { | 4692 | [ALC269_FIXUP_AMIC] = { |
4594 | .type = HDA_FIXUP_PINS, | 4693 | .type = HDA_FIXUP_PINS, |
4595 | .v.pins = (const struct hda_pintbl[]) { | 4694 | .v.pins = (const struct hda_pintbl[]) { |
@@ -4718,6 +4817,15 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4718 | .type = HDA_FIXUP_FUNC, | 4817 | .type = HDA_FIXUP_FUNC, |
4719 | .v.func = alc_fixup_headset_mode_no_hp_mic, | 4818 | .v.func = alc_fixup_headset_mode_no_hp_mic, |
4720 | }, | 4819 | }, |
4820 | [ALC269_FIXUP_ASPIRE_HEADSET_MIC] = { | ||
4821 | .type = HDA_FIXUP_PINS, | ||
4822 | .v.pins = (const struct hda_pintbl[]) { | ||
4823 | { 0x19, 0x01a1913c }, /* headset mic w/o jack detect */ | ||
4824 | { } | ||
4825 | }, | ||
4826 | .chained = true, | ||
4827 | .chain_id = ALC269_FIXUP_HEADSET_MODE, | ||
4828 | }, | ||
4721 | [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = { | 4829 | [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = { |
4722 | .type = HDA_FIXUP_PINS, | 4830 | .type = HDA_FIXUP_PINS, |
4723 | .v.pins = (const struct hda_pintbl[]) { | 4831 | .v.pins = (const struct hda_pintbl[]) { |
@@ -4920,6 +5028,12 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4920 | .chain_id = ALC269_FIXUP_HEADSET_MODE | 5028 | .chain_id = ALC269_FIXUP_HEADSET_MODE |
4921 | }, | 5029 | }, |
4922 | [ALC292_FIXUP_TPT440_DOCK] = { | 5030 | [ALC292_FIXUP_TPT440_DOCK] = { |
5031 | .type = HDA_FIXUP_FUNC, | ||
5032 | .v.func = alc269_fixup_pincfg_no_hp_to_lineout, | ||
5033 | .chained = true, | ||
5034 | .chain_id = ALC292_FIXUP_TPT440_DOCK2 | ||
5035 | }, | ||
5036 | [ALC292_FIXUP_TPT440_DOCK2] = { | ||
4923 | .type = HDA_FIXUP_PINS, | 5037 | .type = HDA_FIXUP_PINS, |
4924 | .v.pins = (const struct hda_pintbl[]) { | 5038 | .v.pins = (const struct hda_pintbl[]) { |
4925 | { 0x16, 0x21211010 }, /* dock headphone */ | 5039 | { 0x16, 0x21211010 }, /* dock headphone */ |
@@ -4979,6 +5093,10 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4979 | .chained = true, | 5093 | .chained = true, |
4980 | .chain_id = ALC280_FIXUP_HP_GPIO4 | 5094 | .chain_id = ALC280_FIXUP_HP_GPIO4 |
4981 | }, | 5095 | }, |
5096 | [ALC280_FIXUP_HP_9480M] = { | ||
5097 | .type = HDA_FIXUP_FUNC, | ||
5098 | .v.func = alc280_fixup_hp_9480m, | ||
5099 | }, | ||
4982 | [ALC288_FIXUP_DELL_HEADSET_MODE] = { | 5100 | [ALC288_FIXUP_DELL_HEADSET_MODE] = { |
4983 | .type = HDA_FIXUP_FUNC, | 5101 | .type = HDA_FIXUP_FUNC, |
4984 | .v.func = alc_fixup_headset_mode_dell_alc288, | 5102 | .v.func = alc_fixup_headset_mode_dell_alc288, |
@@ -5006,6 +5124,40 @@ static const struct hda_fixup alc269_fixups[] = { | |||
5006 | .chained = true, | 5124 | .chained = true, |
5007 | .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE | 5125 | .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE |
5008 | }, | 5126 | }, |
5127 | [ALC288_FIXUP_DISABLE_AAMIX] = { | ||
5128 | .type = HDA_FIXUP_FUNC, | ||
5129 | .v.func = alc_fixup_disable_aamix, | ||
5130 | .chained = true, | ||
5131 | .chain_id = ALC288_FIXUP_DELL_XPS_13_GPIO6 | ||
5132 | }, | ||
5133 | [ALC288_FIXUP_DELL_XPS_13] = { | ||
5134 | .type = HDA_FIXUP_FUNC, | ||
5135 | .v.func = alc_fixup_dell_xps13, | ||
5136 | .chained = true, | ||
5137 | .chain_id = ALC288_FIXUP_DISABLE_AAMIX | ||
5138 | }, | ||
5139 | [ALC292_FIXUP_DISABLE_AAMIX] = { | ||
5140 | .type = HDA_FIXUP_FUNC, | ||
5141 | .v.func = alc_fixup_disable_aamix, | ||
5142 | .chained = true, | ||
5143 | .chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE | ||
5144 | }, | ||
5145 | [ALC292_FIXUP_DELL_E7X] = { | ||
5146 | .type = HDA_FIXUP_FUNC, | ||
5147 | .v.func = alc_fixup_dell_xps13, | ||
5148 | .chained = true, | ||
5149 | .chain_id = ALC292_FIXUP_DISABLE_AAMIX | ||
5150 | }, | ||
5151 | [ALC298_FIXUP_DELL1_MIC_NO_PRESENCE] = { | ||
5152 | .type = HDA_FIXUP_PINS, | ||
5153 | .v.pins = (const struct hda_pintbl[]) { | ||
5154 | { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
5155 | { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ | ||
5156 | { } | ||
5157 | }, | ||
5158 | .chained = true, | ||
5159 | .chain_id = ALC269_FIXUP_HEADSET_MODE | ||
5160 | }, | ||
5009 | }; | 5161 | }; |
5010 | 5162 | ||
5011 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 5163 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -5013,20 +5165,26 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5013 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | 5165 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), |
5014 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | 5166 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), |
5015 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), | 5167 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), |
5168 | SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC), | ||
5169 | SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), | ||
5016 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), | 5170 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), |
5017 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), | 5171 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), |
5018 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | 5172 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), |
5019 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), | 5173 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), |
5020 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 5174 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
5175 | SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X), | ||
5176 | SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X), | ||
5021 | SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER), | 5177 | SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER), |
5022 | SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 5178 | SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
5023 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 5179 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
5024 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 5180 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
5025 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 5181 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
5026 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 5182 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
5183 | SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X), | ||
5027 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), | 5184 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), |
5028 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5185 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
5029 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5186 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
5187 | SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13), | ||
5030 | SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 5188 | SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
5031 | SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5189 | SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
5032 | SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5190 | SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
@@ -5057,6 +5215,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5057 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 5215 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5058 | SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 5216 | SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5059 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 5217 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5218 | SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M), | ||
5060 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 5219 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5061 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 5220 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5062 | /* ALC290 */ | 5221 | /* ALC290 */ |
@@ -5110,7 +5269,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5110 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 5269 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
5111 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), | 5270 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), |
5112 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), | 5271 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), |
5272 | SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT), | ||
5113 | SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), | 5273 | SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), |
5274 | SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN), | ||
5114 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), | 5275 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), |
5115 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), | 5276 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), |
5116 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), | 5277 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), |
@@ -5140,6 +5301,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5140 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5301 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5141 | SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK), | 5302 | SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK), |
5142 | SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK), | 5303 | SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK), |
5304 | SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK), | ||
5143 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5305 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5144 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 5306 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
5145 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 5307 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
@@ -5211,6 +5373,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
5211 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, | 5373 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, |
5212 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, | 5374 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, |
5213 | {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"}, | 5375 | {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"}, |
5376 | {.id = ALC269_FIXUP_HEADSET_MODE, .name = "headset-mode"}, | ||
5377 | {.id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, .name = "headset-mode-no-hp-mic"}, | ||
5214 | {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, | 5378 | {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, |
5215 | {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"}, | 5379 | {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"}, |
5216 | {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"}, | 5380 | {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"}, |
@@ -5269,6 +5433,13 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
5269 | {0x1d, 0x40700001}, \ | 5433 | {0x1d, 0x40700001}, \ |
5270 | {0x1e, 0x411111f0} | 5434 | {0x1e, 0x411111f0} |
5271 | 5435 | ||
5436 | #define ALC298_STANDARD_PINS \ | ||
5437 | {0x18, 0x411111f0}, \ | ||
5438 | {0x19, 0x411111f0}, \ | ||
5439 | {0x1a, 0x411111f0}, \ | ||
5440 | {0x1e, 0x411111f0}, \ | ||
5441 | {0x1f, 0x411111f0} | ||
5442 | |||
5272 | static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | 5443 | static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { |
5273 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, | 5444 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, |
5274 | ALC255_STANDARD_PINS, | 5445 | ALC255_STANDARD_PINS, |
@@ -5337,6 +5508,20 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5337 | {0x17, 0x40000000}, | 5508 | {0x17, 0x40000000}, |
5338 | {0x1d, 0x40700001}, | 5509 | {0x1d, 0x40700001}, |
5339 | {0x21, 0x02211050}), | 5510 | {0x21, 0x02211050}), |
5511 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5512 | ALC255_STANDARD_PINS, | ||
5513 | {0x12, 0x90a60180}, | ||
5514 | {0x14, 0x90170130}, | ||
5515 | {0x17, 0x40000000}, | ||
5516 | {0x1d, 0x40700001}, | ||
5517 | {0x21, 0x02211040}), | ||
5518 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5519 | ALC255_STANDARD_PINS, | ||
5520 | {0x12, 0x90a60160}, | ||
5521 | {0x14, 0x90170120}, | ||
5522 | {0x17, 0x40000000}, | ||
5523 | {0x1d, 0x40700001}, | ||
5524 | {0x21, 0x02211030}), | ||
5340 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 5525 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
5341 | ALC256_STANDARD_PINS, | 5526 | ALC256_STANDARD_PINS, |
5342 | {0x13, 0x40000000}), | 5527 | {0x13, 0x40000000}), |
@@ -5534,6 +5719,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5534 | {0x16, 0x411111f0}, | 5719 | {0x16, 0x411111f0}, |
5535 | {0x18, 0x411111f0}, | 5720 | {0x18, 0x411111f0}, |
5536 | {0x19, 0x411111f0}), | 5721 | {0x19, 0x411111f0}), |
5722 | SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5723 | ALC298_STANDARD_PINS, | ||
5724 | {0x12, 0x90a60130}, | ||
5725 | {0x13, 0x40000000}, | ||
5726 | {0x14, 0x411111f0}, | ||
5727 | {0x17, 0x90170140}, | ||
5728 | {0x1d, 0x4068a36d}, | ||
5729 | {0x21, 0x03211020}), | ||
5537 | {} | 5730 | {} |
5538 | }; | 5731 | }; |
5539 | 5732 | ||
@@ -5592,6 +5785,12 @@ static int patch_alc269(struct hda_codec *codec) | |||
5592 | spec->gen.shared_mic_vref_pin = 0x18; | 5785 | spec->gen.shared_mic_vref_pin = 0x18; |
5593 | codec->power_save_node = 1; | 5786 | codec->power_save_node = 1; |
5594 | 5787 | ||
5788 | #ifdef CONFIG_PM | ||
5789 | codec->patch_ops.suspend = alc269_suspend; | ||
5790 | codec->patch_ops.resume = alc269_resume; | ||
5791 | #endif | ||
5792 | spec->shutup = alc269_shutup; | ||
5793 | |||
5595 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 5794 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
5596 | alc269_fixup_tbl, alc269_fixups); | 5795 | alc269_fixup_tbl, alc269_fixups); |
5597 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); | 5796 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); |
@@ -5688,15 +5887,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
5688 | if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) | 5887 | if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) |
5689 | set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); | 5888 | set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); |
5690 | 5889 | ||
5691 | codec->patch_ops = alc_patch_ops; | ||
5692 | codec->patch_ops.stream_pm = snd_hda_gen_stream_pm; | ||
5693 | #ifdef CONFIG_PM | ||
5694 | codec->patch_ops.suspend = alc269_suspend; | ||
5695 | codec->patch_ops.resume = alc269_resume; | ||
5696 | #endif | ||
5697 | if (!spec->shutup) | ||
5698 | spec->shutup = alc269_shutup; | ||
5699 | |||
5700 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 5890 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
5701 | 5891 | ||
5702 | return 0; | 5892 | return 0; |
@@ -5812,6 +6002,10 @@ static int patch_alc861(struct hda_codec *codec) | |||
5812 | spec = codec->spec; | 6002 | spec = codec->spec; |
5813 | spec->gen.beep_nid = 0x23; | 6003 | spec->gen.beep_nid = 0x23; |
5814 | 6004 | ||
6005 | #ifdef CONFIG_PM | ||
6006 | spec->power_hook = alc_power_eapd; | ||
6007 | #endif | ||
6008 | |||
5815 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); | 6009 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); |
5816 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 6010 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
5817 | 6011 | ||
@@ -5823,11 +6017,6 @@ static int patch_alc861(struct hda_codec *codec) | |||
5823 | if (!spec->gen.no_analog) | 6017 | if (!spec->gen.no_analog) |
5824 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | 6018 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); |
5825 | 6019 | ||
5826 | codec->patch_ops = alc_patch_ops; | ||
5827 | #ifdef CONFIG_PM | ||
5828 | spec->power_hook = alc_power_eapd; | ||
5829 | #endif | ||
5830 | |||
5831 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 6020 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
5832 | 6021 | ||
5833 | return 0; | 6022 | return 0; |
@@ -5904,6 +6093,8 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5904 | spec = codec->spec; | 6093 | spec = codec->spec; |
5905 | spec->gen.beep_nid = 0x23; | 6094 | spec->gen.beep_nid = 0x23; |
5906 | 6095 | ||
6096 | spec->shutup = alc_eapd_shutup; | ||
6097 | |||
5907 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); | 6098 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); |
5908 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 6099 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
5909 | 6100 | ||
@@ -5915,10 +6106,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5915 | if (!spec->gen.no_analog) | 6106 | if (!spec->gen.no_analog) |
5916 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 6107 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
5917 | 6108 | ||
5918 | codec->patch_ops = alc_patch_ops; | ||
5919 | |||
5920 | spec->shutup = alc_eapd_shutup; | ||
5921 | |||
5922 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 6109 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
5923 | 6110 | ||
5924 | return 0; | 6111 | return 0; |
@@ -6071,7 +6258,9 @@ enum { | |||
6071 | ALC662_FIXUP_NO_JACK_DETECT, | 6258 | ALC662_FIXUP_NO_JACK_DETECT, |
6072 | ALC662_FIXUP_ZOTAC_Z68, | 6259 | ALC662_FIXUP_ZOTAC_Z68, |
6073 | ALC662_FIXUP_INV_DMIC, | 6260 | ALC662_FIXUP_INV_DMIC, |
6261 | ALC662_FIXUP_DELL_MIC_NO_PRESENCE, | ||
6074 | ALC668_FIXUP_DELL_MIC_NO_PRESENCE, | 6262 | ALC668_FIXUP_DELL_MIC_NO_PRESENCE, |
6263 | ALC662_FIXUP_HEADSET_MODE, | ||
6075 | ALC668_FIXUP_HEADSET_MODE, | 6264 | ALC668_FIXUP_HEADSET_MODE, |
6076 | ALC662_FIXUP_BASS_MODE4_CHMAP, | 6265 | ALC662_FIXUP_BASS_MODE4_CHMAP, |
6077 | ALC662_FIXUP_BASS_16, | 6266 | ALC662_FIXUP_BASS_16, |
@@ -6264,6 +6453,20 @@ static const struct hda_fixup alc662_fixups[] = { | |||
6264 | .chained = true, | 6453 | .chained = true, |
6265 | .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE | 6454 | .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE |
6266 | }, | 6455 | }, |
6456 | [ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = { | ||
6457 | .type = HDA_FIXUP_PINS, | ||
6458 | .v.pins = (const struct hda_pintbl[]) { | ||
6459 | { 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */ | ||
6460 | /* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */ | ||
6461 | { } | ||
6462 | }, | ||
6463 | .chained = true, | ||
6464 | .chain_id = ALC662_FIXUP_HEADSET_MODE | ||
6465 | }, | ||
6466 | [ALC662_FIXUP_HEADSET_MODE] = { | ||
6467 | .type = HDA_FIXUP_FUNC, | ||
6468 | .v.func = alc_fixup_headset_mode_alc662, | ||
6469 | }, | ||
6267 | [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = { | 6470 | [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = { |
6268 | .type = HDA_FIXUP_PINS, | 6471 | .type = HDA_FIXUP_PINS, |
6269 | .v.pins = (const struct hda_pintbl[]) { | 6472 | .v.pins = (const struct hda_pintbl[]) { |
@@ -6415,6 +6618,18 @@ static const struct hda_model_fixup alc662_fixup_models[] = { | |||
6415 | }; | 6618 | }; |
6416 | 6619 | ||
6417 | static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { | 6620 | static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { |
6621 | SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE, | ||
6622 | {0x12, 0x4004c000}, | ||
6623 | {0x14, 0x01014010}, | ||
6624 | {0x15, 0x411111f0}, | ||
6625 | {0x16, 0x411111f0}, | ||
6626 | {0x18, 0x01a19020}, | ||
6627 | {0x19, 0x411111f0}, | ||
6628 | {0x1a, 0x0181302f}, | ||
6629 | {0x1b, 0x0221401f}, | ||
6630 | {0x1c, 0x411111f0}, | ||
6631 | {0x1d, 0x4054c601}, | ||
6632 | {0x1e, 0x411111f0}), | ||
6418 | SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, | 6633 | SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, |
6419 | {0x12, 0x99a30130}, | 6634 | {0x12, 0x99a30130}, |
6420 | {0x14, 0x90170110}, | 6635 | {0x14, 0x90170110}, |
@@ -6491,6 +6706,8 @@ static int patch_alc662(struct hda_codec *codec) | |||
6491 | 6706 | ||
6492 | spec = codec->spec; | 6707 | spec = codec->spec; |
6493 | 6708 | ||
6709 | spec->shutup = alc_eapd_shutup; | ||
6710 | |||
6494 | /* handle multiple HPs as is */ | 6711 | /* handle multiple HPs as is */ |
6495 | spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; | 6712 | spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; |
6496 | 6713 | ||
@@ -6542,9 +6759,6 @@ static int patch_alc662(struct hda_codec *codec) | |||
6542 | } | 6759 | } |
6543 | } | 6760 | } |
6544 | 6761 | ||
6545 | codec->patch_ops = alc_patch_ops; | ||
6546 | spec->shutup = alc_eapd_shutup; | ||
6547 | |||
6548 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 6762 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
6549 | 6763 | ||
6550 | return 0; | 6764 | return 0; |
@@ -6581,8 +6795,6 @@ static int patch_alc680(struct hda_codec *codec) | |||
6581 | return err; | 6795 | return err; |
6582 | } | 6796 | } |
6583 | 6797 | ||
6584 | codec->patch_ops = alc_patch_ops; | ||
6585 | |||
6586 | return 0; | 6798 | return 0; |
6587 | } | 6799 | } |
6588 | 6800 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 43c99ce4a520..dcc7fe91244c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -100,6 +100,7 @@ enum { | |||
100 | STAC_HP_ENVY_BASS, | 100 | STAC_HP_ENVY_BASS, |
101 | STAC_HP_BNB13_EQ, | 101 | STAC_HP_BNB13_EQ, |
102 | STAC_HP_ENVY_TS_BASS, | 102 | STAC_HP_ENVY_TS_BASS, |
103 | STAC_HP_ENVY_TS_DAC_BIND, | ||
103 | STAC_92HD83XXX_GPIO10_EAPD, | 104 | STAC_92HD83XXX_GPIO10_EAPD, |
104 | STAC_92HD83XXX_MODELS | 105 | STAC_92HD83XXX_MODELS |
105 | }; | 106 | }; |
@@ -2171,6 +2172,22 @@ static void stac92hd83xxx_fixup_gpio10_eapd(struct hda_codec *codec, | |||
2171 | spec->eapd_switch = 0; | 2172 | spec->eapd_switch = 0; |
2172 | } | 2173 | } |
2173 | 2174 | ||
2175 | static void hp_envy_ts_fixup_dac_bind(struct hda_codec *codec, | ||
2176 | const struct hda_fixup *fix, | ||
2177 | int action) | ||
2178 | { | ||
2179 | struct sigmatel_spec *spec = codec->spec; | ||
2180 | static hda_nid_t preferred_pairs[] = { | ||
2181 | 0xd, 0x13, | ||
2182 | 0 | ||
2183 | }; | ||
2184 | |||
2185 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
2186 | return; | ||
2187 | |||
2188 | spec->gen.preferred_dacs = preferred_pairs; | ||
2189 | } | ||
2190 | |||
2174 | static const struct hda_verb hp_bnb13_eq_verbs[] = { | 2191 | static const struct hda_verb hp_bnb13_eq_verbs[] = { |
2175 | /* 44.1KHz base */ | 2192 | /* 44.1KHz base */ |
2176 | { 0x22, 0x7A6, 0x3E }, | 2193 | { 0x22, 0x7A6, 0x3E }, |
@@ -2686,6 +2703,12 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = { | |||
2686 | {} | 2703 | {} |
2687 | }, | 2704 | }, |
2688 | }, | 2705 | }, |
2706 | [STAC_HP_ENVY_TS_DAC_BIND] = { | ||
2707 | .type = HDA_FIXUP_FUNC, | ||
2708 | .v.func = hp_envy_ts_fixup_dac_bind, | ||
2709 | .chained = true, | ||
2710 | .chain_id = STAC_HP_ENVY_TS_BASS, | ||
2711 | }, | ||
2689 | [STAC_92HD83XXX_GPIO10_EAPD] = { | 2712 | [STAC_92HD83XXX_GPIO10_EAPD] = { |
2690 | .type = HDA_FIXUP_FUNC, | 2713 | .type = HDA_FIXUP_FUNC, |
2691 | .v.func = stac92hd83xxx_fixup_gpio10_eapd, | 2714 | .v.func = stac92hd83xxx_fixup_gpio10_eapd, |
@@ -2764,6 +2787,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2764 | "HP bNB13", STAC_HP_BNB13_EQ), | 2787 | "HP bNB13", STAC_HP_BNB13_EQ), |
2765 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, | 2788 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, |
2766 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), | 2789 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), |
2790 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1967, | ||
2791 | "HP ENVY TS", STAC_HP_ENVY_TS_DAC_BIND), | ||
2767 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, | 2792 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, |
2768 | "HP bNB13", STAC_HP_BNB13_EQ), | 2793 | "HP bNB13", STAC_HP_BNB13_EQ), |
2769 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, | 2794 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, |
@@ -4337,7 +4362,7 @@ static void stac_shutup(struct hda_codec *codec) | |||
4337 | 4362 | ||
4338 | #define stac_free snd_hda_gen_free | 4363 | #define stac_free snd_hda_gen_free |
4339 | 4364 | ||
4340 | #ifdef CONFIG_PROC_FS | 4365 | #ifdef CONFIG_SND_PROC_FS |
4341 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, | 4366 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, |
4342 | struct hda_codec *codec, hda_nid_t nid) | 4367 | struct hda_codec *codec, hda_nid_t nid) |
4343 | { | 4368 | { |
@@ -4403,7 +4428,6 @@ static const struct hda_codec_ops stac_patch_ops = { | |||
4403 | #ifdef CONFIG_PM | 4428 | #ifdef CONFIG_PM |
4404 | .suspend = stac_suspend, | 4429 | .suspend = stac_suspend, |
4405 | #endif | 4430 | #endif |
4406 | .stream_pm = snd_hda_gen_stream_pm, | ||
4407 | .reboot_notify = stac_shutup, | 4431 | .reboot_notify = stac_shutup, |
4408 | }; | 4432 | }; |
4409 | 4433 | ||
@@ -4418,6 +4442,7 @@ static int alloc_stac_spec(struct hda_codec *codec) | |||
4418 | codec->spec = spec; | 4442 | codec->spec = spec; |
4419 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ | 4443 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ |
4420 | spec->gen.dac_min_mute = true; | 4444 | spec->gen.dac_min_mute = true; |
4445 | codec->patch_ops = stac_patch_ops; | ||
4421 | return 0; | 4446 | return 0; |
4422 | } | 4447 | } |
4423 | 4448 | ||
@@ -4434,7 +4459,6 @@ static int patch_stac9200(struct hda_codec *codec) | |||
4434 | spec->linear_tone_beep = 1; | 4459 | spec->linear_tone_beep = 1; |
4435 | spec->gen.own_eapd_ctl = 1; | 4460 | spec->gen.own_eapd_ctl = 1; |
4436 | 4461 | ||
4437 | codec->patch_ops = stac_patch_ops; | ||
4438 | codec->power_filter = snd_hda_codec_eapd_power_filter; | 4462 | codec->power_filter = snd_hda_codec_eapd_power_filter; |
4439 | 4463 | ||
4440 | snd_hda_add_verbs(codec, stac9200_eapd_init); | 4464 | snd_hda_add_verbs(codec, stac9200_eapd_init); |
@@ -4467,8 +4491,6 @@ static int patch_stac925x(struct hda_codec *codec) | |||
4467 | spec->linear_tone_beep = 1; | 4491 | spec->linear_tone_beep = 1; |
4468 | spec->gen.own_eapd_ctl = 1; | 4492 | spec->gen.own_eapd_ctl = 1; |
4469 | 4493 | ||
4470 | codec->patch_ops = stac_patch_ops; | ||
4471 | |||
4472 | snd_hda_add_verbs(codec, stac925x_core_init); | 4494 | snd_hda_add_verbs(codec, stac925x_core_init); |
4473 | 4495 | ||
4474 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, | 4496 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, |
@@ -4538,8 +4560,6 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
4538 | spec->gen.own_eapd_ctl = 1; | 4560 | spec->gen.own_eapd_ctl = 1; |
4539 | spec->gen.power_down_unused = 1; | 4561 | spec->gen.power_down_unused = 1; |
4540 | 4562 | ||
4541 | codec->patch_ops = stac_patch_ops; | ||
4542 | |||
4543 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, | 4563 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, |
4544 | stac92hd73xx_fixups); | 4564 | stac92hd73xx_fixups); |
4545 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4565 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -4615,8 +4635,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4615 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 4635 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
4616 | spec->default_polarity = -1; /* no default cfg */ | 4636 | spec->default_polarity = -1; /* no default cfg */ |
4617 | 4637 | ||
4618 | codec->patch_ops = stac_patch_ops; | ||
4619 | |||
4620 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); | 4638 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); |
4621 | 4639 | ||
4622 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, | 4640 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, |
@@ -4665,8 +4683,6 @@ static int patch_stac92hd95(struct hda_codec *codec) | |||
4665 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); | 4683 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); |
4666 | spec->default_polarity = 0; | 4684 | spec->default_polarity = 0; |
4667 | 4685 | ||
4668 | codec->patch_ops = stac_patch_ops; | ||
4669 | |||
4670 | snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl, | 4686 | snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl, |
4671 | stac92hd95_fixups); | 4687 | stac92hd95_fixups); |
4672 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4688 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -4697,15 +4713,14 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4697 | return err; | 4713 | return err; |
4698 | 4714 | ||
4699 | spec = codec->spec; | 4715 | spec = codec->spec; |
4700 | codec->power_save_node = 1; | 4716 | /* disabled power_save_node since it causes noises on a Dell machine */ |
4717 | /* codec->power_save_node = 1; */ | ||
4701 | spec->linear_tone_beep = 0; | 4718 | spec->linear_tone_beep = 0; |
4702 | spec->gen.own_eapd_ctl = 1; | 4719 | spec->gen.own_eapd_ctl = 1; |
4703 | spec->gen.power_down_unused = 1; | 4720 | spec->gen.power_down_unused = 1; |
4704 | spec->gen.mixer_nid = 0x17; | 4721 | spec->gen.mixer_nid = 0x17; |
4705 | spec->have_spdif_mux = 1; | 4722 | spec->have_spdif_mux = 1; |
4706 | 4723 | ||
4707 | codec->patch_ops = stac_patch_ops; | ||
4708 | |||
4709 | /* GPIO0 = EAPD */ | 4724 | /* GPIO0 = EAPD */ |
4710 | spec->gpio_mask = 0x01; | 4725 | spec->gpio_mask = 0x01; |
4711 | spec->gpio_dir = 0x01; | 4726 | spec->gpio_dir = 0x01; |
@@ -4784,8 +4799,6 @@ static int patch_stac922x(struct hda_codec *codec) | |||
4784 | spec->linear_tone_beep = 1; | 4799 | spec->linear_tone_beep = 1; |
4785 | spec->gen.own_eapd_ctl = 1; | 4800 | spec->gen.own_eapd_ctl = 1; |
4786 | 4801 | ||
4787 | codec->patch_ops = stac_patch_ops; | ||
4788 | |||
4789 | snd_hda_add_verbs(codec, stac922x_core_init); | 4802 | snd_hda_add_verbs(codec, stac922x_core_init); |
4790 | 4803 | ||
4791 | /* Fix Mux capture level; max to 2 */ | 4804 | /* Fix Mux capture level; max to 2 */ |
@@ -4841,8 +4854,6 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4841 | spec->aloopback_shift = 0; | 4854 | spec->aloopback_shift = 0; |
4842 | spec->eapd_switch = 1; | 4855 | spec->eapd_switch = 1; |
4843 | 4856 | ||
4844 | codec->patch_ops = stac_patch_ops; | ||
4845 | |||
4846 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, | 4857 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, |
4847 | stac927x_fixups); | 4858 | stac927x_fixups); |
4848 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4859 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -4904,8 +4915,6 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4904 | /* Turn on/off EAPD per HP plugging */ | 4915 | /* Turn on/off EAPD per HP plugging */ |
4905 | spec->eapd_switch = 1; | 4916 | spec->eapd_switch = 1; |
4906 | 4917 | ||
4907 | codec->patch_ops = stac_patch_ops; | ||
4908 | |||
4909 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, | 4918 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, |
4910 | stac9205_fixups); | 4919 | stac9205_fixups); |
4911 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4920 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -4977,8 +4986,6 @@ static int patch_stac9872(struct hda_codec *codec) | |||
4977 | spec->linear_tone_beep = 1; | 4986 | spec->linear_tone_beep = 1; |
4978 | spec->gen.own_eapd_ctl = 1; | 4987 | spec->gen.own_eapd_ctl = 1; |
4979 | 4988 | ||
4980 | codec->patch_ops = stac_patch_ops; | ||
4981 | |||
4982 | snd_hda_add_verbs(codec, stac9872_core_init); | 4989 | snd_hda_add_verbs(codec, stac9872_core_init); |
4983 | 4990 | ||
4984 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, | 4991 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 31a95cca015d..da5366405eda 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -117,6 +117,8 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, | |||
117 | struct snd_pcm_substream *substream, | 117 | struct snd_pcm_substream *substream, |
118 | int action); | 118 | int action); |
119 | 119 | ||
120 | static const struct hda_codec_ops via_patch_ops; /* defined below */ | ||
121 | |||
120 | static struct via_spec *via_new_spec(struct hda_codec *codec) | 122 | static struct via_spec *via_new_spec(struct hda_codec *codec) |
121 | { | 123 | { |
122 | struct via_spec *spec; | 124 | struct via_spec *spec; |
@@ -137,6 +139,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec) | |||
137 | spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO; | 139 | spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO; |
138 | codec->power_save_node = 1; | 140 | codec->power_save_node = 1; |
139 | spec->gen.power_down_unused = 1; | 141 | spec->gen.power_down_unused = 1; |
142 | codec->patch_ops = via_patch_ops; | ||
140 | return spec; | 143 | return spec; |
141 | } | 144 | } |
142 | 145 | ||
@@ -238,7 +241,9 @@ static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol, | |||
238 | struct snd_ctl_elem_value *ucontrol) | 241 | struct snd_ctl_elem_value *ucontrol) |
239 | { | 242 | { |
240 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 243 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
241 | ucontrol->value.enumerated.item[0] = codec->power_save_node; | 244 | struct via_spec *spec = codec->spec; |
245 | |||
246 | ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused; | ||
242 | return 0; | 247 | return 0; |
243 | } | 248 | } |
244 | 249 | ||
@@ -249,9 +254,9 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, | |||
249 | struct via_spec *spec = codec->spec; | 254 | struct via_spec *spec = codec->spec; |
250 | bool val = !!ucontrol->value.enumerated.item[0]; | 255 | bool val = !!ucontrol->value.enumerated.item[0]; |
251 | 256 | ||
252 | if (val == codec->power_save_node) | 257 | if (val == spec->gen.power_down_unused) |
253 | return 0; | 258 | return 0; |
254 | codec->power_save_node = val; | 259 | /* codec->power_save_node = val; */ /* widget PM seems yet broken */ |
255 | spec->gen.power_down_unused = val; | 260 | spec->gen.power_down_unused = val; |
256 | analog_low_current_mode(codec); | 261 | analog_low_current_mode(codec); |
257 | return 1; | 262 | return 1; |
@@ -449,6 +454,15 @@ static int via_suspend(struct hda_codec *codec) | |||
449 | 454 | ||
450 | return 0; | 455 | return 0; |
451 | } | 456 | } |
457 | |||
458 | static int via_resume(struct hda_codec *codec) | ||
459 | { | ||
460 | /* some delay here to make jack detection working (bko#98921) */ | ||
461 | msleep(10); | ||
462 | codec->patch_ops.init(codec); | ||
463 | regcache_sync(codec->core.regmap); | ||
464 | return 0; | ||
465 | } | ||
452 | #endif | 466 | #endif |
453 | 467 | ||
454 | #ifdef CONFIG_PM | 468 | #ifdef CONFIG_PM |
@@ -472,9 +486,9 @@ static const struct hda_codec_ops via_patch_ops = { | |||
472 | .init = via_init, | 486 | .init = via_init, |
473 | .free = via_free, | 487 | .free = via_free, |
474 | .unsol_event = snd_hda_jack_unsol_event, | 488 | .unsol_event = snd_hda_jack_unsol_event, |
475 | .stream_pm = snd_hda_gen_stream_pm, | ||
476 | #ifdef CONFIG_PM | 489 | #ifdef CONFIG_PM |
477 | .suspend = via_suspend, | 490 | .suspend = via_suspend, |
491 | .resume = via_resume, | ||
478 | .check_power_status = via_check_power_status, | 492 | .check_power_status = via_check_power_status, |
479 | #endif | 493 | #endif |
480 | }; | 494 | }; |
@@ -651,6 +665,9 @@ static int patch_vt1708(struct hda_codec *codec) | |||
651 | if (spec == NULL) | 665 | if (spec == NULL) |
652 | return -ENOMEM; | 666 | return -ENOMEM; |
653 | 667 | ||
668 | /* override some patch_ops */ | ||
669 | codec->patch_ops.build_controls = vt1708_build_controls; | ||
670 | codec->patch_ops.build_pcms = vt1708_build_pcms; | ||
654 | spec->gen.mixer_nid = 0x17; | 671 | spec->gen.mixer_nid = 0x17; |
655 | 672 | ||
656 | /* set jackpoll_interval while parsing the codec */ | 673 | /* set jackpoll_interval while parsing the codec */ |
@@ -679,10 +696,6 @@ static int patch_vt1708(struct hda_codec *codec) | |||
679 | 696 | ||
680 | spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; | 697 | spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; |
681 | 698 | ||
682 | codec->patch_ops = via_patch_ops; | ||
683 | codec->patch_ops.build_controls = vt1708_build_controls; | ||
684 | codec->patch_ops.build_pcms = vt1708_build_pcms; | ||
685 | |||
686 | /* clear jackpoll_interval again; it's set dynamically */ | 699 | /* clear jackpoll_interval again; it's set dynamically */ |
687 | codec->jackpoll_interval = 0; | 700 | codec->jackpoll_interval = 0; |
688 | 701 | ||
@@ -707,8 +720,6 @@ static int patch_vt1709(struct hda_codec *codec) | |||
707 | return err; | 720 | return err; |
708 | } | 721 | } |
709 | 722 | ||
710 | codec->patch_ops = via_patch_ops; | ||
711 | |||
712 | return 0; | 723 | return 0; |
713 | } | 724 | } |
714 | 725 | ||
@@ -735,7 +746,6 @@ static int patch_vt1708B(struct hda_codec *codec) | |||
735 | return err; | 746 | return err; |
736 | } | 747 | } |
737 | 748 | ||
738 | codec->patch_ops = via_patch_ops; | ||
739 | return 0; | 749 | return 0; |
740 | } | 750 | } |
741 | 751 | ||
@@ -800,7 +810,6 @@ static int patch_vt1708S(struct hda_codec *codec) | |||
800 | 810 | ||
801 | spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; | 811 | spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; |
802 | 812 | ||
803 | codec->patch_ops = via_patch_ops; | ||
804 | return 0; | 813 | return 0; |
805 | } | 814 | } |
806 | 815 | ||
@@ -842,7 +851,6 @@ static int patch_vt1702(struct hda_codec *codec) | |||
842 | 851 | ||
843 | spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; | 852 | spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; |
844 | 853 | ||
845 | codec->patch_ops = via_patch_ops; | ||
846 | return 0; | 854 | return 0; |
847 | } | 855 | } |
848 | 856 | ||
@@ -915,7 +923,6 @@ static int patch_vt1718S(struct hda_codec *codec) | |||
915 | 923 | ||
916 | spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; | 924 | spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; |
917 | 925 | ||
918 | codec->patch_ops = via_patch_ops; | ||
919 | return 0; | 926 | return 0; |
920 | } | 927 | } |
921 | 928 | ||
@@ -1015,7 +1022,6 @@ static int patch_vt1716S(struct hda_codec *codec) | |||
1015 | spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer; | 1022 | spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer; |
1016 | spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; | 1023 | spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; |
1017 | 1024 | ||
1018 | codec->patch_ops = via_patch_ops; | ||
1019 | return 0; | 1025 | return 0; |
1020 | } | 1026 | } |
1021 | 1027 | ||
@@ -1123,7 +1129,6 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
1123 | else | 1129 | else |
1124 | spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; | 1130 | spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; |
1125 | 1131 | ||
1126 | codec->patch_ops = via_patch_ops; | ||
1127 | return 0; | 1132 | return 0; |
1128 | } | 1133 | } |
1129 | 1134 | ||
@@ -1162,7 +1167,6 @@ static int patch_vt1812(struct hda_codec *codec) | |||
1162 | 1167 | ||
1163 | spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; | 1168 | spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; |
1164 | 1169 | ||
1165 | codec->patch_ops = via_patch_ops; | ||
1166 | return 0; | 1170 | return 0; |
1167 | } | 1171 | } |
1168 | 1172 | ||
@@ -1200,7 +1204,6 @@ static int patch_vt3476(struct hda_codec *codec) | |||
1200 | 1204 | ||
1201 | spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs; | 1205 | spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs; |
1202 | 1206 | ||
1203 | codec->patch_ops = via_patch_ops; | ||
1204 | return 0; | 1207 | return 0; |
1205 | } | 1208 | } |
1206 | 1209 | ||
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index f7b1523e8a82..8ae3bb7975d1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2530,8 +2530,8 @@ static int snd_ice1712_create(struct snd_card *card, | |||
2530 | if (err < 0) | 2530 | if (err < 0) |
2531 | return err; | 2531 | return err; |
2532 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2532 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2533 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || | 2533 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || |
2534 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { | 2534 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { |
2535 | dev_err(card->dev, | 2535 | dev_err(card->dev, |
2536 | "architecture does not support 28bit PCI busmaster DMA\n"); | 2536 | "architecture does not support 28bit PCI busmaster DMA\n"); |
2537 | pci_disable_device(pci); | 2537 | pci_disable_device(pci); |
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 6f55e02e5c84..7c387b04067e 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c | |||
@@ -203,7 +203,6 @@ static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", | |||
203 | #define AK4620_DEEMVOL_REG 0x03 | 203 | #define AK4620_DEEMVOL_REG 0x03 |
204 | #define AK4620_SMUTE (1<<7) | 204 | #define AK4620_SMUTE (1<<7) |
205 | 205 | ||
206 | #ifdef CONFIG_PROC_FS | ||
207 | /* | 206 | /* |
208 | * Conversion from int value to its binary form. Used for debugging. | 207 | * Conversion from int value to its binary form. Used for debugging. |
209 | * The output buffer must be allocated prior to calling the function. | 208 | * The output buffer must be allocated prior to calling the function. |
@@ -228,7 +227,6 @@ static char *get_binary(char *buffer, int value) | |||
228 | buffer[pos] = '\0'; | 227 | buffer[pos] = '\0'; |
229 | return buffer; | 228 | return buffer; |
230 | } | 229 | } |
231 | #endif /* CONFIG_PROC_FS */ | ||
232 | 230 | ||
233 | /* | 231 | /* |
234 | * Initial setup of the conversion array GPIO <-> rate | 232 | * Initial setup of the conversion array GPIO <-> rate |
@@ -486,7 +484,7 @@ static void set_cpld(struct snd_ice1712 *ice, unsigned int val) | |||
486 | reg_write(ice, GPIO_CPLD_CSN, val); | 484 | reg_write(ice, GPIO_CPLD_CSN, val); |
487 | spec->cpld = val; | 485 | spec->cpld = val; |
488 | } | 486 | } |
489 | #ifdef CONFIG_PROC_FS | 487 | |
490 | static void proc_regs_read(struct snd_info_entry *entry, | 488 | static void proc_regs_read(struct snd_info_entry *entry, |
491 | struct snd_info_buffer *buffer) | 489 | struct snd_info_buffer *buffer) |
492 | { | 490 | { |
@@ -507,9 +505,6 @@ static void proc_init(struct snd_ice1712 *ice) | |||
507 | if (!snd_card_proc_new(ice->card, "quartet", &entry)) | 505 | if (!snd_card_proc_new(ice->card, "quartet", &entry)) |
508 | snd_info_set_text_ops(entry, ice, proc_regs_read); | 506 | snd_info_set_text_ops(entry, ice, proc_regs_read); |
509 | } | 507 | } |
510 | #else /* !CONFIG_PROC_FS */ | ||
511 | static void proc_init(struct snd_ice1712 *ice) {} | ||
512 | #endif | ||
513 | 508 | ||
514 | static int qtet_mute_get(struct snd_kcontrol *kcontrol, | 509 | static int qtet_mute_get(struct snd_kcontrol *kcontrol, |
515 | struct snd_ctl_elem_value *ucontrol) | 510 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b120925223ae..42bcbac801a3 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2900,7 +2900,6 @@ static int intel8x0_in_clock_list(struct intel8x0 *chip) | |||
2900 | return 1; | 2900 | return 1; |
2901 | } | 2901 | } |
2902 | 2902 | ||
2903 | #ifdef CONFIG_PROC_FS | ||
2904 | static void snd_intel8x0_proc_read(struct snd_info_entry * entry, | 2903 | static void snd_intel8x0_proc_read(struct snd_info_entry * entry, |
2905 | struct snd_info_buffer *buffer) | 2904 | struct snd_info_buffer *buffer) |
2906 | { | 2905 | { |
@@ -2942,9 +2941,6 @@ static void snd_intel8x0_proc_init(struct intel8x0 *chip) | |||
2942 | if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) | 2941 | if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) |
2943 | snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read); | 2942 | snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read); |
2944 | } | 2943 | } |
2945 | #else | ||
2946 | #define snd_intel8x0_proc_init(x) | ||
2947 | #endif | ||
2948 | 2944 | ||
2949 | static int snd_intel8x0_dev_free(struct snd_device *device) | 2945 | static int snd_intel8x0_dev_free(struct snd_device *device) |
2950 | { | 2946 | { |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 7577f31cd504..1bc98c867133 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1065,7 +1065,6 @@ static SIMPLE_DEV_PM_OPS(intel8x0m_pm, intel8x0m_suspend, intel8x0m_resume); | |||
1065 | #define INTEL8X0M_PM_OPS NULL | 1065 | #define INTEL8X0M_PM_OPS NULL |
1066 | #endif /* CONFIG_PM_SLEEP */ | 1066 | #endif /* CONFIG_PM_SLEEP */ |
1067 | 1067 | ||
1068 | #ifdef CONFIG_PROC_FS | ||
1069 | static void snd_intel8x0m_proc_read(struct snd_info_entry * entry, | 1068 | static void snd_intel8x0m_proc_read(struct snd_info_entry * entry, |
1070 | struct snd_info_buffer *buffer) | 1069 | struct snd_info_buffer *buffer) |
1071 | { | 1070 | { |
@@ -1093,10 +1092,6 @@ static void snd_intel8x0m_proc_init(struct intel8x0m *chip) | |||
1093 | if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) | 1092 | if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) |
1094 | snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read); | 1093 | snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read); |
1095 | } | 1094 | } |
1096 | #else /* !CONFIG_PROC_FS */ | ||
1097 | #define snd_intel8x0m_proc_init(chip) | ||
1098 | #endif /* CONFIG_PROC_FS */ | ||
1099 | |||
1100 | 1095 | ||
1101 | static int snd_intel8x0m_dev_free(struct snd_device *device) | 1096 | static int snd_intel8x0m_dev_free(struct snd_device *device) |
1102 | { | 1097 | { |
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 601315a1f58f..cba89beb2b38 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c | |||
@@ -57,13 +57,13 @@ static const char card_name[] = "LX6464ES"; | |||
57 | #define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056 | 57 | #define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056 |
58 | 58 | ||
59 | static const struct pci_device_id snd_lx6464es_ids[] = { | 59 | static const struct pci_device_id snd_lx6464es_ids[] = { |
60 | { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES), | 60 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
61 | .subvendor = PCI_VENDOR_ID_DIGIGRAM, | 61 | PCI_VENDOR_ID_DIGIGRAM, |
62 | .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM | 62 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM), |
63 | }, /* LX6464ES */ | 63 | }, /* LX6464ES */ |
64 | { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES), | 64 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES, |
65 | .subvendor = PCI_VENDOR_ID_DIGIGRAM, | 65 | PCI_VENDOR_ID_DIGIGRAM, |
66 | .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM | 66 | PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM), |
67 | }, /* LX6464ES-CAE */ | 67 | }, /* LX6464ES-CAE */ |
68 | { 0, }, | 68 | { 0, }, |
69 | }; | 69 | }; |
@@ -412,9 +412,9 @@ static int lx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
412 | err = snd_pcm_lib_free_pages(substream); | 412 | err = snd_pcm_lib_free_pages(substream); |
413 | 413 | ||
414 | if (is_capture) | 414 | if (is_capture) |
415 | chip->capture_stream.stream = 0; | 415 | chip->capture_stream.stream = NULL; |
416 | else | 416 | else |
417 | chip->playback_stream.stream = 0; | 417 | chip->playback_stream.stream = NULL; |
418 | 418 | ||
419 | exit: | 419 | exit: |
420 | mutex_unlock(&chip->setup_mutex); | 420 | mutex_unlock(&chip->setup_mutex); |
@@ -981,7 +981,7 @@ static int snd_lx6464es_create(struct snd_card *card, | |||
981 | pci_set_master(pci); | 981 | pci_set_master(pci); |
982 | 982 | ||
983 | /* check if we can restrict PCI DMA transfers to 32 bits */ | 983 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
984 | err = pci_set_dma_mask(pci, DMA_BIT_MASK(32)); | 984 | err = dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); |
985 | if (err < 0) { | 985 | if (err < 0) { |
986 | dev_err(card->dev, | 986 | dev_err(card->dev, |
987 | "architecture does not support 32bit PCI busmaster DMA\n"); | 987 | "architecture does not support 32bit PCI busmaster DMA\n"); |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 9be660993bd0..72e89cedc52d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2537,8 +2537,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2537 | return -EIO; | 2537 | return -EIO; |
2538 | 2538 | ||
2539 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2539 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2540 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || | 2540 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || |
2541 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { | 2541 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { |
2542 | dev_err(card->dev, | 2542 | dev_err(card->dev, |
2543 | "architecture does not support 28bit PCI busmaster DMA\n"); | 2543 | "architecture does not support 28bit PCI busmaster DMA\n"); |
2544 | pci_disable_device(pci); | 2544 | pci_disable_device(pci); |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index c3a9f39f8d61..bc81b9f75ed0 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1269,7 +1269,7 @@ static int snd_mixart_probe(struct pci_dev *pci, | |||
1269 | pci_set_master(pci); | 1269 | pci_set_master(pci); |
1270 | 1270 | ||
1271 | /* check if we can restrict PCI DMA transfers to 32 bits */ | 1271 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
1272 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 1272 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
1273 | dev_err(&pci->dev, | 1273 | dev_err(&pci->dev, |
1274 | "architecture does not support 32bit PCI busmaster DMA\n"); | 1274 | "architecture does not support 32bit PCI busmaster DMA\n"); |
1275 | pci_disable_device(pci); | 1275 | pci_disable_device(pci); |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index ffff3b25fd73..b4ef5804212d 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -196,7 +196,6 @@ static void oxygen_gpio_changed(struct work_struct *work) | |||
196 | chip->model.gpio_changed(chip); | 196 | chip->model.gpio_changed(chip); |
197 | } | 197 | } |
198 | 198 | ||
199 | #ifdef CONFIG_PROC_FS | ||
200 | static void oxygen_proc_read(struct snd_info_entry *entry, | 199 | static void oxygen_proc_read(struct snd_info_entry *entry, |
201 | struct snd_info_buffer *buffer) | 200 | struct snd_info_buffer *buffer) |
202 | { | 201 | { |
@@ -250,9 +249,6 @@ static void oxygen_proc_init(struct oxygen *chip) | |||
250 | if (!snd_card_proc_new(chip->card, "oxygen", &entry)) | 249 | if (!snd_card_proc_new(chip->card, "oxygen", &entry)) |
251 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); | 250 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); |
252 | } | 251 | } |
253 | #else | ||
254 | #define oxygen_proc_init(chip) | ||
255 | #endif | ||
256 | 252 | ||
257 | static const struct pci_device_id * | 253 | static const struct pci_device_id * |
258 | oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) | 254 | oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 6ce68604c25e..90ac479f389f 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -286,7 +286,7 @@ static void xonar_ds_init(struct oxygen *chip) | |||
286 | xonar_enable_output(chip); | 286 | xonar_enable_output(chip); |
287 | 287 | ||
288 | snd_jack_new(chip->card, "Headphone", | 288 | snd_jack_new(chip->card, "Headphone", |
289 | SND_JACK_HEADPHONE, &data->hp_jack); | 289 | SND_JACK_HEADPHONE, &data->hp_jack, false, false); |
290 | xonar_ds_handle_hp_jack(chip); | 290 | xonar_ds_handle_hp_jack(chip); |
291 | 291 | ||
292 | snd_component_add(chip->card, "WM8776"); | 292 | snd_component_add(chip->card, "WM8776"); |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index c6092e48ceb6..9293235281dc 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1537,7 +1537,7 @@ static int pcxhr_probe(struct pci_dev *pci, | |||
1537 | pci_set_master(pci); | 1537 | pci_set_master(pci); |
1538 | 1538 | ||
1539 | /* check if we can restrict PCI DMA transfers to 32 bits */ | 1539 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
1540 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 1540 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { |
1541 | dev_err(&pci->dev, | 1541 | dev_err(&pci->dev, |
1542 | "architecture does not support 32bit PCI busmaster DMA\n"); | 1542 | "architecture does not support 32bit PCI busmaster DMA\n"); |
1543 | pci_disable_device(pci); | 1543 | pci_disable_device(pci); |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index efe669b80256..f3860b850210 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -383,9 +383,9 @@ static void __sis_map_silence(struct sis7019 *sis) | |||
383 | { | 383 | { |
384 | /* Helper function: must hold sis->voice_lock on entry */ | 384 | /* Helper function: must hold sis->voice_lock on entry */ |
385 | if (!sis->silence_users) | 385 | if (!sis->silence_users) |
386 | sis->silence_dma_addr = pci_map_single(sis->pci, | 386 | sis->silence_dma_addr = dma_map_single(&sis->pci->dev, |
387 | sis->suspend_state[0], | 387 | sis->suspend_state[0], |
388 | 4096, PCI_DMA_TODEVICE); | 388 | 4096, DMA_TO_DEVICE); |
389 | sis->silence_users++; | 389 | sis->silence_users++; |
390 | } | 390 | } |
391 | 391 | ||
@@ -394,8 +394,8 @@ static void __sis_unmap_silence(struct sis7019 *sis) | |||
394 | /* Helper function: must hold sis->voice_lock on entry */ | 394 | /* Helper function: must hold sis->voice_lock on entry */ |
395 | sis->silence_users--; | 395 | sis->silence_users--; |
396 | if (!sis->silence_users) | 396 | if (!sis->silence_users) |
397 | pci_unmap_single(sis->pci, sis->silence_dma_addr, 4096, | 397 | dma_unmap_single(&sis->pci->dev, sis->silence_dma_addr, 4096, |
398 | PCI_DMA_TODEVICE); | 398 | DMA_TO_DEVICE); |
399 | } | 399 | } |
400 | 400 | ||
401 | static void sis_free_voice(struct sis7019 *sis, struct voice *voice) | 401 | static void sis_free_voice(struct sis7019 *sis, struct voice *voice) |
@@ -1325,7 +1325,7 @@ static int sis_chip_create(struct snd_card *card, | |||
1325 | if (rc) | 1325 | if (rc) |
1326 | goto error_out; | 1326 | goto error_out; |
1327 | 1327 | ||
1328 | rc = pci_set_dma_mask(pci, DMA_BIT_MASK(30)); | 1328 | rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30)); |
1329 | if (rc < 0) { | 1329 | if (rc < 0) { |
1330 | dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA"); | 1330 | dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA"); |
1331 | goto error_out_enabled; | 1331 | goto error_out_enabled; |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 0f40624a4275..1b6fad7d4d56 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1259,8 +1259,8 @@ static int snd_sonicvibes_create(struct snd_card *card, | |||
1259 | if ((err = pci_enable_device(pci)) < 0) | 1259 | if ((err = pci_enable_device(pci)) < 0) |
1260 | return err; | 1260 | return err; |
1261 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 1261 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
1262 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || | 1262 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || |
1263 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { | 1263 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { |
1264 | dev_err(card->dev, | 1264 | dev_err(card->dev, |
1265 | "architecture does not support 24bit PCI busmaster DMA\n"); | 1265 | "architecture does not support 24bit PCI busmaster DMA\n"); |
1266 | pci_disable_device(pci); | 1266 | pci_disable_device(pci); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index b72be035f785..599d2b7eb5b8 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3551,8 +3551,8 @@ int snd_trident_create(struct snd_card *card, | |||
3551 | if ((err = pci_enable_device(pci)) < 0) | 3551 | if ((err = pci_enable_device(pci)) < 0) |
3552 | return err; | 3552 | return err; |
3553 | /* check, if we can restrict PCI DMA transfers to 30 bits */ | 3553 | /* check, if we can restrict PCI DMA transfers to 30 bits */ |
3554 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0 || | 3554 | if (dma_set_mask(&pci->dev, DMA_BIT_MASK(30)) < 0 || |
3555 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(30)) < 0) { | 3555 | dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(30)) < 0) { |
3556 | dev_err(card->dev, | 3556 | dev_err(card->dev, |
3557 | "architecture does not support 30bit PCI busmaster DMA\n"); | 3557 | "architecture does not support 30bit PCI busmaster DMA\n"); |
3558 | pci_disable_device(pci); | 3558 | pci_disable_device(pci); |
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 0d1c27e911b8..6120a067494a 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c | |||
@@ -31,10 +31,15 @@ | |||
31 | */ | 31 | */ |
32 | static struct pmac_keywest *keywest_ctx; | 32 | static struct pmac_keywest *keywest_ctx; |
33 | 33 | ||
34 | static bool keywest_probed; | ||
34 | 35 | ||
35 | static int keywest_probe(struct i2c_client *client, | 36 | static int keywest_probe(struct i2c_client *client, |
36 | const struct i2c_device_id *id) | 37 | const struct i2c_device_id *id) |
37 | { | 38 | { |
39 | keywest_probed = true; | ||
40 | /* If instantiated via i2c-powermac, we still need to set the client */ | ||
41 | if (!keywest_ctx->client) | ||
42 | keywest_ctx->client = client; | ||
38 | i2c_set_clientdata(client, keywest_ctx); | 43 | i2c_set_clientdata(client, keywest_ctx); |
39 | return 0; | 44 | return 0; |
40 | } | 45 | } |
@@ -52,7 +57,7 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) | |||
52 | return -EINVAL; | 57 | return -EINVAL; |
53 | 58 | ||
54 | if (strncmp(adapter->name, "mac-io", 6)) | 59 | if (strncmp(adapter->name, "mac-io", 6)) |
55 | return 0; /* ignored */ | 60 | return -EINVAL; /* ignored */ |
56 | 61 | ||
57 | memset(&info, 0, sizeof(struct i2c_board_info)); | 62 | memset(&info, 0, sizeof(struct i2c_board_info)); |
58 | strlcpy(info.type, "keywest", I2C_NAME_SIZE); | 63 | strlcpy(info.type, "keywest", I2C_NAME_SIZE); |
@@ -92,7 +97,8 @@ static int keywest_remove(struct i2c_client *client) | |||
92 | 97 | ||
93 | 98 | ||
94 | static const struct i2c_device_id keywest_i2c_id[] = { | 99 | static const struct i2c_device_id keywest_i2c_id[] = { |
95 | { "keywest", 0 }, | 100 | { "MAC,tas3004", 0 }, /* instantiated by i2c-powermac */ |
101 | { "keywest", 0 }, /* instantiated by us if needed */ | ||
96 | { } | 102 | { } |
97 | }; | 103 | }; |
98 | 104 | ||
@@ -100,7 +106,6 @@ static struct i2c_driver keywest_driver = { | |||
100 | .driver = { | 106 | .driver = { |
101 | .name = "PMac Keywest Audio", | 107 | .name = "PMac Keywest Audio", |
102 | }, | 108 | }, |
103 | .attach_adapter = keywest_attach_adapter, | ||
104 | .probe = keywest_probe, | 109 | .probe = keywest_probe, |
105 | .remove = keywest_remove, | 110 | .remove = keywest_remove, |
106 | .id_table = keywest_i2c_id, | 111 | .id_table = keywest_i2c_id, |
@@ -132,16 +137,37 @@ int snd_pmac_tumbler_post_init(void) | |||
132 | /* exported */ | 137 | /* exported */ |
133 | int snd_pmac_keywest_init(struct pmac_keywest *i2c) | 138 | int snd_pmac_keywest_init(struct pmac_keywest *i2c) |
134 | { | 139 | { |
135 | int err; | 140 | struct i2c_adapter *adap; |
141 | int err, i = 0; | ||
136 | 142 | ||
137 | if (keywest_ctx) | 143 | if (keywest_ctx) |
138 | return -EBUSY; | 144 | return -EBUSY; |
139 | 145 | ||
146 | adap = i2c_get_adapter(0); | ||
147 | if (!adap) | ||
148 | return -EPROBE_DEFER; | ||
149 | |||
140 | keywest_ctx = i2c; | 150 | keywest_ctx = i2c; |
141 | 151 | ||
142 | if ((err = i2c_add_driver(&keywest_driver))) { | 152 | if ((err = i2c_add_driver(&keywest_driver))) { |
143 | snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); | 153 | snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); |
154 | i2c_put_adapter(adap); | ||
144 | return err; | 155 | return err; |
145 | } | 156 | } |
146 | return 0; | 157 | |
158 | /* There was already a device from i2c-powermac. Great, let's return */ | ||
159 | if (keywest_probed) | ||
160 | return 0; | ||
161 | |||
162 | /* We assume Macs have consecutive I2C bus numbers starting at 0 */ | ||
163 | while (adap) { | ||
164 | /* Scan for devices to be bound to */ | ||
165 | err = keywest_attach_adapter(adap); | ||
166 | if (!err) | ||
167 | return 0; | ||
168 | i2c_put_adapter(adap); | ||
169 | adap = i2c_get_adapter(++i); | ||
170 | } | ||
171 | |||
172 | return -ENODEV; | ||
147 | } | 173 | } |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index cc1b71875b26..2ae9619443d1 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -58,6 +58,7 @@ source "sound/soc/tegra/Kconfig" | |||
58 | source "sound/soc/txx9/Kconfig" | 58 | source "sound/soc/txx9/Kconfig" |
59 | source "sound/soc/ux500/Kconfig" | 59 | source "sound/soc/ux500/Kconfig" |
60 | source "sound/soc/xtensa/Kconfig" | 60 | source "sound/soc/xtensa/Kconfig" |
61 | source "sound/soc/zte/Kconfig" | ||
61 | 62 | ||
62 | # Supported codecs | 63 | # Supported codecs |
63 | source "sound/soc/codecs/Kconfig" | 64 | source "sound/soc/codecs/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index e5526338aeda..e189903fabf4 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o |
3 | snd-soc-core-objs += soc-topology.o | ||
3 | 4 | ||
4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | 5 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) |
5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 6 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
@@ -39,3 +40,4 @@ obj-$(CONFIG_SND_SOC) += tegra/ | |||
39 | obj-$(CONFIG_SND_SOC) += txx9/ | 40 | obj-$(CONFIG_SND_SOC) += txx9/ |
40 | obj-$(CONFIG_SND_SOC) += ux500/ | 41 | obj-$(CONFIG_SND_SOC) += ux500/ |
41 | obj-$(CONFIG_SND_SOC) += xtensa/ | 42 | obj-$(CONFIG_SND_SOC) += xtensa/ |
43 | obj-$(CONFIG_SND_SOC) += zte/ | ||
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e7d08806f3e9..1489cd461aec 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -6,29 +6,35 @@ config SND_ATMEL_SOC | |||
6 | the ATMEL SSC interface. You will also need | 6 | the ATMEL SSC interface. You will also need |
7 | to select the audio interfaces to support below. | 7 | to select the audio interfaces to support below. |
8 | 8 | ||
9 | if SND_ATMEL_SOC | ||
10 | |||
9 | config SND_ATMEL_SOC_PDC | 11 | config SND_ATMEL_SOC_PDC |
10 | tristate | 12 | tristate |
11 | depends on SND_ATMEL_SOC | 13 | default m if SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=m |
14 | default y if SND_ATMEL_SOC_SSC_PDC=y || (SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=y) | ||
15 | |||
16 | config SND_ATMEL_SOC_SSC_PDC | ||
17 | tristate | ||
12 | 18 | ||
13 | config SND_ATMEL_SOC_DMA | 19 | config SND_ATMEL_SOC_DMA |
14 | tristate | 20 | tristate |
15 | depends on SND_ATMEL_SOC | ||
16 | select SND_SOC_GENERIC_DMAENGINE_PCM | 21 | select SND_SOC_GENERIC_DMAENGINE_PCM |
22 | default m if SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=m | ||
23 | default y if SND_ATMEL_SOC_SSC_DMA=y || (SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=y) | ||
24 | |||
25 | config SND_ATMEL_SOC_SSC_DMA | ||
26 | tristate | ||
17 | 27 | ||
18 | config SND_ATMEL_SOC_SSC | 28 | config SND_ATMEL_SOC_SSC |
19 | tristate | 29 | tristate |
20 | depends on SND_ATMEL_SOC | 30 | default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y |
21 | help | 31 | default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m |
22 | Say Y or M if you want to add support for codecs the | ||
23 | ATMEL SSC interface. You will also needs to select the individual | ||
24 | machine drivers to support below. | ||
25 | 32 | ||
26 | config SND_AT91_SOC_SAM9G20_WM8731 | 33 | config SND_AT91_SOC_SAM9G20_WM8731 |
27 | tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" | 34 | tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" |
28 | depends on ARCH_AT91 || COMPILE_TEST | 35 | depends on ARCH_AT91 || COMPILE_TEST |
29 | depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI | 36 | depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI |
30 | select SND_ATMEL_SOC_PDC | 37 | select SND_ATMEL_SOC_SSC_PDC |
31 | select SND_ATMEL_SOC_SSC | ||
32 | select SND_SOC_WM8731 | 38 | select SND_SOC_WM8731 |
33 | help | 39 | help |
34 | Say Y if you want to add support for SoC audio on WM8731-based | 40 | Say Y if you want to add support for SoC audio on WM8731-based |
@@ -37,9 +43,8 @@ config SND_AT91_SOC_SAM9G20_WM8731 | |||
37 | config SND_ATMEL_SOC_WM8904 | 43 | config SND_ATMEL_SOC_WM8904 |
38 | tristate "Atmel ASoC driver for boards using WM8904 codec" | 44 | tristate "Atmel ASoC driver for boards using WM8904 codec" |
39 | depends on ARCH_AT91 || COMPILE_TEST | 45 | depends on ARCH_AT91 || COMPILE_TEST |
40 | depends on ATMEL_SSC && SND_ATMEL_SOC && I2C | 46 | depends on ATMEL_SSC && I2C |
41 | select SND_ATMEL_SOC_SSC | 47 | select SND_ATMEL_SOC_SSC_DMA |
42 | select SND_ATMEL_SOC_DMA | ||
43 | select SND_SOC_WM8904 | 48 | select SND_SOC_WM8904 |
44 | help | 49 | help |
45 | Say Y if you want to add support for Atmel ASoC driver for boards using | 50 | Say Y if you want to add support for Atmel ASoC driver for boards using |
@@ -48,10 +53,10 @@ config SND_ATMEL_SOC_WM8904 | |||
48 | config SND_AT91_SOC_SAM9X5_WM8731 | 53 | config SND_AT91_SOC_SAM9X5_WM8731 |
49 | tristate "SoC Audio support for WM8731-based at91sam9x5 board" | 54 | tristate "SoC Audio support for WM8731-based at91sam9x5 board" |
50 | depends on ARCH_AT91 || COMPILE_TEST | 55 | depends on ARCH_AT91 || COMPILE_TEST |
51 | depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI | 56 | depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI |
52 | select SND_ATMEL_SOC_SSC | 57 | select SND_ATMEL_SOC_SSC_DMA |
53 | select SND_ATMEL_SOC_DMA | ||
54 | select SND_SOC_WM8731 | 58 | select SND_SOC_WM8731 |
55 | help | 59 | help |
56 | Say Y if you want to add support for audio SoC on an | 60 | Say Y if you want to add support for audio SoC on an |
57 | at91sam9x5 based board that is using WM8731 codec. | 61 | at91sam9x5 based board that is using WM8731 codec. |
62 | endif | ||
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index b6625c8c411b..dd57a9eac171 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c | |||
@@ -124,8 +124,7 @@ static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = { | |||
124 | 124 | ||
125 | int atmel_pcm_dma_platform_register(struct device *dev) | 125 | int atmel_pcm_dma_platform_register(struct device *dev) |
126 | { | 126 | { |
127 | return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, | 127 | return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, 0); |
128 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
129 | } | 128 | } |
130 | EXPORT_SYMBOL(atmel_pcm_dma_platform_register); | 129 | EXPORT_SYMBOL(atmel_pcm_dma_platform_register); |
131 | 130 | ||
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 8de836165cf2..d7469cdd90dc 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -95,8 +95,9 @@ static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { | |||
95 | 95 | ||
96 | static const struct snd_soc_dapm_route intercon[] = { | 96 | static const struct snd_soc_dapm_route intercon[] = { |
97 | 97 | ||
98 | /* speaker connected to LHPOUT */ | 98 | /* speaker connected to LHPOUT/RHPOUT */ |
99 | {"Ext Spk", NULL, "LHPOUT"}, | 99 | {"Ext Spk", NULL, "LHPOUT"}, |
100 | {"Ext Spk", NULL, "RHPOUT"}, | ||
100 | 101 | ||
101 | /* mic is connected to Mic Jack, with WM8731 Mic Bias */ | 102 | /* mic is connected to Mic Jack, with WM8731 Mic Bias */ |
102 | {"MICIN", NULL, "Mic Bias"}, | 103 | {"MICIN", NULL, "Mic Bias"}, |
@@ -108,9 +109,7 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
108 | */ | 109 | */ |
109 | static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) | 110 | static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) |
110 | { | 111 | { |
111 | struct snd_soc_codec *codec = rtd->codec; | ||
112 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 112 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
113 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
114 | int ret; | 113 | int ret; |
115 | 114 | ||
116 | printk(KERN_DEBUG | 115 | printk(KERN_DEBUG |
@@ -124,10 +123,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) | |||
124 | return ret; | 123 | return ret; |
125 | } | 124 | } |
126 | 125 | ||
127 | /* not connected */ | ||
128 | snd_soc_dapm_nc_pin(dapm, "RLINEIN"); | ||
129 | snd_soc_dapm_nc_pin(dapm, "LLINEIN"); | ||
130 | |||
131 | #ifndef ENABLE_MIC_INPUT | 126 | #ifndef ENABLE_MIC_INPUT |
132 | snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); | 127 | snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); |
133 | #endif | 128 | #endif |
@@ -158,6 +153,7 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { | |||
158 | .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), | 153 | .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), |
159 | .dapm_routes = intercon, | 154 | .dapm_routes = intercon, |
160 | .num_dapm_routes = ARRAY_SIZE(intercon), | 155 | .num_dapm_routes = ARRAY_SIZE(intercon), |
156 | .fully_routed = true, | ||
161 | }; | 157 | }; |
162 | 158 | ||
163 | static int at91sam9g20ek_audio_probe(struct platform_device *pdev) | 159 | static int at91sam9g20ek_audio_probe(struct platform_device *pdev) |
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index c75995f2779c..58c3164802b8 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "../codecs/wm8731.h" | 21 | #include "../codecs/wm8731.h" |
22 | #include "psc.h" | 22 | #include "psc.h" |
23 | 23 | ||
24 | static struct platform_device_id db1200_pids[] = { | 24 | static const struct platform_device_id db1200_pids[] = { |
25 | { | 25 | { |
26 | .name = "db1200-ac97", | 26 | .name = "db1200-ac97", |
27 | .driver_data = 0, | 27 | .driver_data = 0, |
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 5f664471d99e..67a73330db5e 100644 --- a/sound/soc/cirrus/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
@@ -60,7 +60,6 @@ int devm_ep93xx_pcm_platform_register(struct device *dev) | |||
60 | { | 60 | { |
61 | return devm_snd_dmaengine_pcm_register(dev, | 61 | return devm_snd_dmaengine_pcm_register(dev, |
62 | &ep93xx_dmaengine_pcm_config, | 62 | &ep93xx_dmaengine_pcm_config, |
63 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
64 | SND_DMAENGINE_PCM_FLAG_NO_DT | | 63 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
65 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 64 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
66 | } | 65 | } |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index a0f265327fdf..38b3dad9d48a 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -1140,7 +1140,7 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec, | |||
1140 | break; | 1140 | break; |
1141 | 1141 | ||
1142 | case SND_SOC_BIAS_STANDBY: | 1142 | case SND_SOC_BIAS_STANDBY: |
1143 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1143 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1144 | /* Enable Audio PLL & Audio section */ | 1144 | /* Enable Audio PLL & Audio section */ |
1145 | data = AUDIO_PLL | AUDIO_SECTION_ON; | 1145 | data = AUDIO_PLL | AUDIO_SECTION_ON; |
1146 | pm860x_reg_write(pm860x->i2c, REG_MISC2, data); | 1146 | pm860x_reg_write(pm860x->i2c, REG_MISC2, data); |
@@ -1156,7 +1156,6 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec, | |||
1156 | pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0); | 1156 | pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0); |
1157 | break; | 1157 | break; |
1158 | } | 1158 | } |
1159 | codec->dapm.bias_level = level; | ||
1160 | return 0; | 1159 | return 0; |
1161 | } | 1160 | } |
1162 | 1161 | ||
@@ -1187,16 +1186,16 @@ static struct snd_soc_dai_driver pm860x_dai[] = { | |||
1187 | .channels_min = 2, | 1186 | .channels_min = 2, |
1188 | .channels_max = 2, | 1187 | .channels_max = 2, |
1189 | .rates = PM860X_RATES, | 1188 | .rates = PM860X_RATES, |
1190 | .formats = SNDRV_PCM_FORMAT_S16_LE | \ | 1189 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ |
1191 | SNDRV_PCM_FORMAT_S18_3LE, | 1190 | SNDRV_PCM_FMTBIT_S18_3LE, |
1192 | }, | 1191 | }, |
1193 | .capture = { | 1192 | .capture = { |
1194 | .stream_name = "PCM Capture", | 1193 | .stream_name = "PCM Capture", |
1195 | .channels_min = 2, | 1194 | .channels_min = 2, |
1196 | .channels_max = 2, | 1195 | .channels_max = 2, |
1197 | .rates = PM860X_RATES, | 1196 | .rates = PM860X_RATES, |
1198 | .formats = SNDRV_PCM_FORMAT_S16_LE | \ | 1197 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ |
1199 | SNDRV_PCM_FORMAT_S18_3LE, | 1198 | SNDRV_PCM_FMTBIT_S18_3LE, |
1200 | }, | 1199 | }, |
1201 | .ops = &pm860x_pcm_dai_ops, | 1200 | .ops = &pm860x_pcm_dai_ops, |
1202 | }, { | 1201 | }, { |
@@ -1208,16 +1207,16 @@ static struct snd_soc_dai_driver pm860x_dai[] = { | |||
1208 | .channels_min = 2, | 1207 | .channels_min = 2, |
1209 | .channels_max = 2, | 1208 | .channels_max = 2, |
1210 | .rates = SNDRV_PCM_RATE_8000_48000, | 1209 | .rates = SNDRV_PCM_RATE_8000_48000, |
1211 | .formats = SNDRV_PCM_FORMAT_S16_LE | \ | 1210 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ |
1212 | SNDRV_PCM_FORMAT_S18_3LE, | 1211 | SNDRV_PCM_FMTBIT_S18_3LE, |
1213 | }, | 1212 | }, |
1214 | .capture = { | 1213 | .capture = { |
1215 | .stream_name = "I2S Capture", | 1214 | .stream_name = "I2S Capture", |
1216 | .channels_min = 2, | 1215 | .channels_min = 2, |
1217 | .channels_max = 2, | 1216 | .channels_max = 2, |
1218 | .rates = SNDRV_PCM_RATE_8000_48000, | 1217 | .rates = SNDRV_PCM_RATE_8000_48000, |
1219 | .formats = SNDRV_PCM_FORMAT_S16_LE | \ | 1218 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ |
1220 | SNDRV_PCM_FORMAT_S18_3LE, | 1219 | SNDRV_PCM_FMTBIT_S18_3LE, |
1221 | }, | 1220 | }, |
1222 | .ops = &pm860x_i2s_dai_ops, | 1221 | .ops = &pm860x_i2s_dai_ops, |
1223 | }, | 1222 | }, |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 061c46587628..efaafce8ba38 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -16,7 +16,7 @@ config SND_SOC_ALL_CODECS | |||
16 | select SND_SOC_88PM860X if MFD_88PM860X | 16 | select SND_SOC_88PM860X if MFD_88PM860X |
17 | select SND_SOC_L3 | 17 | select SND_SOC_L3 |
18 | select SND_SOC_AB8500_CODEC if ABX500_CORE | 18 | select SND_SOC_AB8500_CODEC if ABX500_CORE |
19 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS | 19 | select SND_SOC_AC97_CODEC |
20 | select SND_SOC_AD1836 if SPI_MASTER | 20 | select SND_SOC_AD1836 if SPI_MASTER |
21 | select SND_SOC_AD193X_SPI if SPI_MASTER | 21 | select SND_SOC_AD193X_SPI if SPI_MASTER |
22 | select SND_SOC_AD193X_I2C if I2C | 22 | select SND_SOC_AD193X_I2C if I2C |
@@ -54,7 +54,7 @@ config SND_SOC_ALL_CODECS | |||
54 | select SND_SOC_CS4271_SPI if SPI_MASTER | 54 | select SND_SOC_CS4271_SPI if SPI_MASTER |
55 | select SND_SOC_CS42XX8_I2C if I2C | 55 | select SND_SOC_CS42XX8_I2C if I2C |
56 | select SND_SOC_CX20442 if TTY | 56 | select SND_SOC_CX20442 if TTY |
57 | select SND_SOC_DA7210 if I2C | 57 | select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI |
58 | select SND_SOC_DA7213 if I2C | 58 | select SND_SOC_DA7213 if I2C |
59 | select SND_SOC_DA732X if I2C | 59 | select SND_SOC_DA732X if I2C |
60 | select SND_SOC_DA9055 if I2C | 60 | select SND_SOC_DA9055 if I2C |
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS | |||
104 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 104 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
105 | select SND_SOC_TAS2552 if I2C | 105 | select SND_SOC_TAS2552 if I2C |
106 | select SND_SOC_TAS5086 if I2C | 106 | select SND_SOC_TAS5086 if I2C |
107 | select SND_SOC_TAS571X if I2C | ||
107 | select SND_SOC_TFA9879 if I2C | 108 | select SND_SOC_TFA9879 if I2C |
108 | select SND_SOC_TLV320AIC23_I2C if I2C | 109 | select SND_SOC_TLV320AIC23_I2C if I2C |
109 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER | 110 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER |
@@ -211,8 +212,9 @@ config SND_SOC_AB8500_CODEC | |||
211 | tristate | 212 | tristate |
212 | 213 | ||
213 | config SND_SOC_AC97_CODEC | 214 | config SND_SOC_AC97_CODEC |
214 | tristate | 215 | tristate "Build generic ASoC AC97 CODEC driver" |
215 | select SND_AC97_CODEC | 216 | select SND_AC97_CODEC |
217 | select SND_SOC_AC97_BUS | ||
216 | 218 | ||
217 | config SND_SOC_AD1836 | 219 | config SND_SOC_AD1836 |
218 | tristate | 220 | tristate |
@@ -507,6 +509,11 @@ config SND_SOC_RL6231 | |||
507 | default m if SND_SOC_RT5670=m | 509 | default m if SND_SOC_RT5670=m |
508 | default m if SND_SOC_RT5677=m | 510 | default m if SND_SOC_RT5677=m |
509 | 511 | ||
512 | config SND_SOC_RL6347A | ||
513 | tristate | ||
514 | default y if SND_SOC_RT286=y | ||
515 | default m if SND_SOC_RT286=m | ||
516 | |||
510 | config SND_SOC_RT286 | 517 | config SND_SOC_RT286 |
511 | tristate | 518 | tristate |
512 | depends on I2C | 519 | depends on I2C |
@@ -611,6 +618,10 @@ config SND_SOC_TAS5086 | |||
611 | tristate "Texas Instruments TAS5086 speaker amplifier" | 618 | tristate "Texas Instruments TAS5086 speaker amplifier" |
612 | depends on I2C | 619 | depends on I2C |
613 | 620 | ||
621 | config SND_SOC_TAS571X | ||
622 | tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers" | ||
623 | depends on I2C | ||
624 | |||
614 | config SND_SOC_TFA9879 | 625 | config SND_SOC_TFA9879 |
615 | tristate "NXP Semiconductors TFA9879 amplifier" | 626 | tristate "NXP Semiconductors TFA9879 amplifier" |
616 | depends on I2C | 627 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index abe2d7edf65c..cf160d972cb3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -77,6 +77,7 @@ snd-soc-pcm512x-objs := pcm512x.o | |||
77 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o | 77 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o |
78 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o | 78 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o |
79 | snd-soc-rl6231-objs := rl6231.o | 79 | snd-soc-rl6231-objs := rl6231.o |
80 | snd-soc-rl6347a-objs := rl6347a.o | ||
80 | snd-soc-rt286-objs := rt286.o | 81 | snd-soc-rt286-objs := rt286.o |
81 | snd-soc-rt5631-objs := rt5631.o | 82 | snd-soc-rt5631-objs := rt5631.o |
82 | snd-soc-rt5640-objs := rt5640.o | 83 | snd-soc-rt5640-objs := rt5640.o |
@@ -106,6 +107,7 @@ snd-soc-sta350-objs := sta350.o | |||
106 | snd-soc-sta529-objs := sta529.o | 107 | snd-soc-sta529-objs := sta529.o |
107 | snd-soc-stac9766-objs := stac9766.o | 108 | snd-soc-stac9766-objs := stac9766.o |
108 | snd-soc-tas5086-objs := tas5086.o | 109 | snd-soc-tas5086-objs := tas5086.o |
110 | snd-soc-tas571x-objs := tas571x.o | ||
109 | snd-soc-tfa9879-objs := tfa9879.o | 111 | snd-soc-tfa9879-objs := tfa9879.o |
110 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 112 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
111 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o | 113 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o |
@@ -262,6 +264,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o | |||
262 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o | 264 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o |
263 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | 265 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o |
264 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o | 266 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o |
267 | obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o | ||
265 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o | 268 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o |
266 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 269 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
267 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 270 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
@@ -288,6 +291,7 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | |||
288 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 291 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
289 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o | 292 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o |
290 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 293 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
294 | obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o | ||
291 | obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o | 295 | obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o |
292 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 296 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
293 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o | 297 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 88ca9cb0ce79..c7d243db010a 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -1209,6 +1209,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1209 | struct snd_ctl_elem_value *ucontrol) | 1209 | struct snd_ctl_elem_value *ucontrol) |
1210 | { | 1210 | { |
1211 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1211 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1212 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1212 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | 1213 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); |
1213 | struct device *dev = codec->dev; | 1214 | struct device *dev = codec->dev; |
1214 | bool apply_fir, apply_iir; | 1215 | bool apply_fir, apply_iir; |
@@ -1234,15 +1235,14 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1234 | apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; | 1235 | apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; |
1235 | apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; | 1236 | apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; |
1236 | 1237 | ||
1237 | status = snd_soc_dapm_force_enable_pin(&codec->dapm, | 1238 | status = snd_soc_dapm_force_enable_pin(dapm, "ANC Configure Input"); |
1238 | "ANC Configure Input"); | ||
1239 | if (status < 0) { | 1239 | if (status < 0) { |
1240 | dev_err(dev, | 1240 | dev_err(dev, |
1241 | "%s: ERROR: Failed to enable power (status = %d)!\n", | 1241 | "%s: ERROR: Failed to enable power (status = %d)!\n", |
1242 | __func__, status); | 1242 | __func__, status); |
1243 | goto cleanup; | 1243 | goto cleanup; |
1244 | } | 1244 | } |
1245 | snd_soc_dapm_sync(&codec->dapm); | 1245 | snd_soc_dapm_sync(dapm); |
1246 | 1246 | ||
1247 | anc_configure(codec, apply_fir, apply_iir); | 1247 | anc_configure(codec, apply_fir, apply_iir); |
1248 | 1248 | ||
@@ -1259,8 +1259,8 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1259 | drvdata->anc_status = ANC_IIR_CONFIGURED; | 1259 | drvdata->anc_status = ANC_IIR_CONFIGURED; |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | 1262 | status = snd_soc_dapm_disable_pin(dapm, "ANC Configure Input"); |
1263 | snd_soc_dapm_sync(&codec->dapm); | 1263 | snd_soc_dapm_sync(dapm); |
1264 | 1264 | ||
1265 | cleanup: | 1265 | cleanup: |
1266 | mutex_unlock(&drvdata->ctrl_lock); | 1266 | mutex_unlock(&drvdata->ctrl_lock); |
@@ -1947,6 +1947,7 @@ static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec) | |||
1947 | static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, | 1947 | static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, |
1948 | struct amic_settings *amics) | 1948 | struct amic_settings *amics) |
1949 | { | 1949 | { |
1950 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1950 | u8 value8; | 1951 | u8 value8; |
1951 | unsigned int value; | 1952 | unsigned int value; |
1952 | int status; | 1953 | int status; |
@@ -1973,15 +1974,15 @@ static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, | |||
1973 | dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__, | 1974 | dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__, |
1974 | amic_micbias_str(amics->mic1a_micbias)); | 1975 | amic_micbias_str(amics->mic1a_micbias)); |
1975 | route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias]; | 1976 | route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias]; |
1976 | status = snd_soc_dapm_add_routes(&codec->dapm, route, 1); | 1977 | status = snd_soc_dapm_add_routes(dapm, route, 1); |
1977 | dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__, | 1978 | dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__, |
1978 | amic_micbias_str(amics->mic1b_micbias)); | 1979 | amic_micbias_str(amics->mic1b_micbias)); |
1979 | route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias]; | 1980 | route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias]; |
1980 | status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | 1981 | status |= snd_soc_dapm_add_routes(dapm, route, 1); |
1981 | dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__, | 1982 | dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__, |
1982 | amic_micbias_str(amics->mic2_micbias)); | 1983 | amic_micbias_str(amics->mic2_micbias)); |
1983 | route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias]; | 1984 | route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias]; |
1984 | status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | 1985 | status |= snd_soc_dapm_add_routes(dapm, route, 1); |
1985 | if (status < 0) { | 1986 | if (status < 0) { |
1986 | dev_err(codec->dev, | 1987 | dev_err(codec->dev, |
1987 | "%s: Failed to add AMic-regulator DAPM-routes (%d).\n", | 1988 | "%s: Failed to add AMic-regulator DAPM-routes (%d).\n", |
@@ -2461,6 +2462,7 @@ static void ab8500_codec_of_probe(struct device *dev, struct device_node *np, | |||
2461 | 2462 | ||
2462 | static int ab8500_codec_probe(struct snd_soc_codec *codec) | 2463 | static int ab8500_codec_probe(struct snd_soc_codec *codec) |
2463 | { | 2464 | { |
2465 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2464 | struct device *dev = codec->dev; | 2466 | struct device *dev = codec->dev; |
2465 | struct device_node *np = dev->of_node; | 2467 | struct device_node *np = dev->of_node; |
2466 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); | 2468 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); |
@@ -2541,7 +2543,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2541 | &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value; | 2543 | &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value; |
2542 | drvdata->sid_fir_values = (long *)fc->value; | 2544 | drvdata->sid_fir_values = (long *)fc->value; |
2543 | 2545 | ||
2544 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | 2546 | snd_soc_dapm_disable_pin(dapm, "ANC Configure Input"); |
2545 | 2547 | ||
2546 | mutex_init(&drvdata->ctrl_lock); | 2548 | mutex_init(&drvdata->ctrl_lock); |
2547 | 2549 | ||
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index d0ac723eee32..5b3224c63943 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -44,10 +44,6 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
44 | return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); | 44 | return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); |
45 | } | 45 | } |
46 | 46 | ||
47 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
48 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ | ||
49 | SNDRV_PCM_RATE_48000) | ||
50 | |||
51 | static const struct snd_soc_dai_ops ac97_dai_ops = { | 47 | static const struct snd_soc_dai_ops ac97_dai_ops = { |
52 | .prepare = ac97_prepare, | 48 | .prepare = ac97_prepare, |
53 | }; | 49 | }; |
@@ -58,13 +54,13 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
58 | .stream_name = "AC97 Playback", | 54 | .stream_name = "AC97 Playback", |
59 | .channels_min = 1, | 55 | .channels_min = 1, |
60 | .channels_max = 2, | 56 | .channels_max = 2, |
61 | .rates = STD_AC97_RATES, | 57 | .rates = SNDRV_PCM_RATE_KNOT, |
62 | .formats = SND_SOC_STD_AC97_FMTS,}, | 58 | .formats = SND_SOC_STD_AC97_FMTS,}, |
63 | .capture = { | 59 | .capture = { |
64 | .stream_name = "AC97 Capture", | 60 | .stream_name = "AC97 Capture", |
65 | .channels_min = 1, | 61 | .channels_min = 1, |
66 | .channels_max = 2, | 62 | .channels_max = 2, |
67 | .rates = STD_AC97_RATES, | 63 | .rates = SNDRV_PCM_RATE_KNOT, |
68 | .formats = SND_SOC_STD_AC97_FMTS,}, | 64 | .formats = SND_SOC_STD_AC97_FMTS,}, |
69 | .ops = &ac97_dai_ops, | 65 | .ops = &ac97_dai_ops, |
70 | }; | 66 | }; |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 685998dd086e..95f0bec26a1b 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -251,7 +251,7 @@ static int ad1836_resume(struct snd_soc_codec *codec) | |||
251 | static int ad1836_probe(struct snd_soc_codec *codec) | 251 | static int ad1836_probe(struct snd_soc_codec *codec) |
252 | { | 252 | { |
253 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | 253 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); |
254 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 254 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
255 | int num_dacs, num_adcs; | 255 | int num_dacs, num_adcs; |
256 | int ret = 0; | 256 | int ret = 0; |
257 | int i; | 257 | int i; |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 783dcb57043a..a43160254929 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -1444,7 +1444,6 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec, | |||
1444 | ADAU1373_PWDN_CTRL3_PWR_EN, 0); | 1444 | ADAU1373_PWDN_CTRL3_PWR_EN, 0); |
1445 | break; | 1445 | break; |
1446 | } | 1446 | } |
1447 | codec->dapm.bias_level = level; | ||
1448 | return 0; | 1447 | return 0; |
1449 | } | 1448 | } |
1450 | 1449 | ||
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d4e219b6b98f..ff7f846e3b76 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_gpio.h> | 17 | #include <linux/of_gpio.h> |
18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
19 | #include <linux/regulator/consumer.h> | ||
19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -101,6 +102,10 @@ | |||
101 | 102 | ||
102 | #define ADAU1701_FIRMWARE "adau1701.bin" | 103 | #define ADAU1701_FIRMWARE "adau1701.bin" |
103 | 104 | ||
105 | static const char * const supply_names[] = { | ||
106 | "dvdd", "avdd" | ||
107 | }; | ||
108 | |||
104 | struct adau1701 { | 109 | struct adau1701 { |
105 | int gpio_nreset; | 110 | int gpio_nreset; |
106 | int gpio_pll_mode[2]; | 111 | int gpio_pll_mode[2]; |
@@ -112,6 +117,7 @@ struct adau1701 { | |||
112 | u8 pin_config[12]; | 117 | u8 pin_config[12]; |
113 | 118 | ||
114 | struct sigmadsp *sigmadsp; | 119 | struct sigmadsp *sigmadsp; |
120 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
115 | }; | 121 | }; |
116 | 122 | ||
117 | static const struct snd_kcontrol_new adau1701_controls[] = { | 123 | static const struct snd_kcontrol_new adau1701_controls[] = { |
@@ -565,7 +571,6 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec, | |||
565 | break; | 571 | break; |
566 | } | 572 | } |
567 | 573 | ||
568 | codec->dapm.bias_level = level; | ||
569 | return 0; | 574 | return 0; |
570 | } | 575 | } |
571 | 576 | ||
@@ -669,6 +674,13 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
669 | if (ret) | 674 | if (ret) |
670 | return ret; | 675 | return ret; |
671 | 676 | ||
677 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
678 | adau1701->supplies); | ||
679 | if (ret < 0) { | ||
680 | dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
672 | /* | 684 | /* |
673 | * Let the pll_clkdiv variable default to something that won't happen | 685 | * Let the pll_clkdiv variable default to something that won't happen |
674 | * at runtime. That way, we can postpone the firmware download from | 686 | * at runtime. That way, we can postpone the firmware download from |
@@ -680,7 +692,7 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
680 | /* initalize with pre-configured pll mode settings */ | 692 | /* initalize with pre-configured pll mode settings */ |
681 | ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); | 693 | ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); |
682 | if (ret < 0) | 694 | if (ret < 0) |
683 | return ret; | 695 | goto exit_regulators_disable; |
684 | 696 | ||
685 | /* set up pin config */ | 697 | /* set up pin config */ |
686 | val = 0; | 698 | val = 0; |
@@ -696,10 +708,60 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
696 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); | 708 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); |
697 | 709 | ||
698 | return 0; | 710 | return 0; |
711 | |||
712 | exit_regulators_disable: | ||
713 | |||
714 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
715 | return ret; | ||
699 | } | 716 | } |
700 | 717 | ||
718 | static int adau1701_remove(struct snd_soc_codec *codec) | ||
719 | { | ||
720 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
721 | |||
722 | if (gpio_is_valid(adau1701->gpio_nreset)) | ||
723 | gpio_set_value_cansleep(adau1701->gpio_nreset, 0); | ||
724 | |||
725 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | #ifdef CONFIG_PM | ||
731 | static int adau1701_suspend(struct snd_soc_codec *codec) | ||
732 | { | ||
733 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
734 | |||
735 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), | ||
736 | adau1701->supplies); | ||
737 | |||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static int adau1701_resume(struct snd_soc_codec *codec) | ||
742 | { | ||
743 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
744 | int ret; | ||
745 | |||
746 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
747 | adau1701->supplies); | ||
748 | if (ret < 0) { | ||
749 | dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); | ||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | return adau1701_reset(codec, adau1701->pll_clkdiv, 0); | ||
754 | } | ||
755 | #else | ||
756 | #define adau1701_resume NULL | ||
757 | #define adau1701_suspend NULL | ||
758 | #endif /* CONFIG_PM */ | ||
759 | |||
701 | static struct snd_soc_codec_driver adau1701_codec_drv = { | 760 | static struct snd_soc_codec_driver adau1701_codec_drv = { |
702 | .probe = adau1701_probe, | 761 | .probe = adau1701_probe, |
762 | .remove = adau1701_remove, | ||
763 | .resume = adau1701_resume, | ||
764 | .suspend = adau1701_suspend, | ||
703 | .set_bias_level = adau1701_set_bias_level, | 765 | .set_bias_level = adau1701_set_bias_level, |
704 | .idle_bias_off = true, | 766 | .idle_bias_off = true, |
705 | 767 | ||
@@ -730,32 +792,58 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
730 | struct device *dev = &client->dev; | 792 | struct device *dev = &client->dev; |
731 | int gpio_nreset = -EINVAL; | 793 | int gpio_nreset = -EINVAL; |
732 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; | 794 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; |
733 | int ret; | 795 | int ret, i; |
734 | 796 | ||
735 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); | 797 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); |
736 | if (!adau1701) | 798 | if (!adau1701) |
737 | return -ENOMEM; | 799 | return -ENOMEM; |
738 | 800 | ||
801 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
802 | adau1701->supplies[i].supply = supply_names[i]; | ||
803 | |||
804 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(adau1701->supplies), | ||
805 | adau1701->supplies); | ||
806 | if (ret < 0) { | ||
807 | dev_err(dev, "Failed to get regulators: %d\n", ret); | ||
808 | return ret; | ||
809 | } | ||
810 | |||
811 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
812 | adau1701->supplies); | ||
813 | if (ret < 0) { | ||
814 | dev_err(dev, "Failed to enable regulators: %d\n", ret); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
739 | adau1701->client = client; | 818 | adau1701->client = client; |
740 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | 819 | adau1701->regmap = devm_regmap_init(dev, NULL, client, |
741 | &adau1701_regmap); | 820 | &adau1701_regmap); |
742 | if (IS_ERR(adau1701->regmap)) | 821 | if (IS_ERR(adau1701->regmap)) { |
743 | return PTR_ERR(adau1701->regmap); | 822 | ret = PTR_ERR(adau1701->regmap); |
823 | goto exit_regulators_disable; | ||
824 | } | ||
825 | |||
744 | 826 | ||
745 | if (dev->of_node) { | 827 | if (dev->of_node) { |
746 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); | 828 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); |
747 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) | 829 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) { |
748 | return gpio_nreset; | 830 | ret = gpio_nreset; |
831 | goto exit_regulators_disable; | ||
832 | } | ||
749 | 833 | ||
750 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, | 834 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, |
751 | "adi,pll-mode-gpios", 0); | 835 | "adi,pll-mode-gpios", 0); |
752 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) | 836 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) { |
753 | return gpio_pll_mode[0]; | 837 | ret = gpio_pll_mode[0]; |
838 | goto exit_regulators_disable; | ||
839 | } | ||
754 | 840 | ||
755 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, | 841 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, |
756 | "adi,pll-mode-gpios", 1); | 842 | "adi,pll-mode-gpios", 1); |
757 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) | 843 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) { |
758 | return gpio_pll_mode[1]; | 844 | ret = gpio_pll_mode[1]; |
845 | goto exit_regulators_disable; | ||
846 | } | ||
759 | 847 | ||
760 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", | 848 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", |
761 | &adau1701->pll_clkdiv); | 849 | &adau1701->pll_clkdiv); |
@@ -769,7 +857,7 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
769 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, | 857 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, |
770 | "ADAU1701 Reset"); | 858 | "ADAU1701 Reset"); |
771 | if (ret < 0) | 859 | if (ret < 0) |
772 | return ret; | 860 | goto exit_regulators_disable; |
773 | } | 861 | } |
774 | 862 | ||
775 | if (gpio_is_valid(gpio_pll_mode[0]) && | 863 | if (gpio_is_valid(gpio_pll_mode[0]) && |
@@ -778,13 +866,13 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
778 | GPIOF_OUT_INIT_LOW, | 866 | GPIOF_OUT_INIT_LOW, |
779 | "ADAU1701 PLL mode 0"); | 867 | "ADAU1701 PLL mode 0"); |
780 | if (ret < 0) | 868 | if (ret < 0) |
781 | return ret; | 869 | goto exit_regulators_disable; |
782 | 870 | ||
783 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], | 871 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], |
784 | GPIOF_OUT_INIT_LOW, | 872 | GPIOF_OUT_INIT_LOW, |
785 | "ADAU1701 PLL mode 1"); | 873 | "ADAU1701 PLL mode 1"); |
786 | if (ret < 0) | 874 | if (ret < 0) |
787 | return ret; | 875 | goto exit_regulators_disable; |
788 | } | 876 | } |
789 | 877 | ||
790 | adau1701->gpio_nreset = gpio_nreset; | 878 | adau1701->gpio_nreset = gpio_nreset; |
@@ -795,11 +883,17 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
795 | 883 | ||
796 | adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, | 884 | adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, |
797 | &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); | 885 | &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); |
798 | if (IS_ERR(adau1701->sigmadsp)) | 886 | if (IS_ERR(adau1701->sigmadsp)) { |
799 | return PTR_ERR(adau1701->sigmadsp); | 887 | ret = PTR_ERR(adau1701->sigmadsp); |
888 | goto exit_regulators_disable; | ||
889 | } | ||
800 | 890 | ||
801 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 891 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
802 | &adau1701_dai, 1); | 892 | &adau1701_dai, 1); |
893 | |||
894 | exit_regulators_disable: | ||
895 | |||
896 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
803 | return ret; | 897 | return ret; |
804 | } | 898 | } |
805 | 899 | ||
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index a1baeee160f4..2f12477e539e 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -466,7 +466,6 @@ static int adau1761_set_bias_level(struct snd_soc_codec *codec, | |||
466 | break; | 466 | break; |
467 | 467 | ||
468 | } | 468 | } |
469 | codec->dapm.bias_level = level; | ||
470 | return 0; | 469 | return 0; |
471 | } | 470 | } |
472 | 471 | ||
@@ -483,6 +482,7 @@ static enum adau1761_output_mode adau1761_get_lineout_mode( | |||
483 | 482 | ||
484 | static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) | 483 | static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) |
485 | { | 484 | { |
485 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
486 | struct adau1761_platform_data *pdata = codec->dev->platform_data; | 486 | struct adau1761_platform_data *pdata = codec->dev->platform_data; |
487 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 487 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
488 | enum adau1761_digmic_jackdet_pin_mode mode; | 488 | enum adau1761_digmic_jackdet_pin_mode mode; |
@@ -515,21 +515,18 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) | |||
515 | if (ret) | 515 | if (ret) |
516 | return ret; | 516 | return ret; |
517 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */ | 517 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */ |
518 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 518 | ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, |
519 | adau1761_no_dmic_routes, | ||
520 | ARRAY_SIZE(adau1761_no_dmic_routes)); | 519 | ARRAY_SIZE(adau1761_no_dmic_routes)); |
521 | if (ret) | 520 | if (ret) |
522 | return ret; | 521 | return ret; |
523 | break; | 522 | break; |
524 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: | 523 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: |
525 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 524 | ret = snd_soc_dapm_new_controls(dapm, adau1761_dmic_widgets, |
526 | adau1761_dmic_widgets, | ||
527 | ARRAY_SIZE(adau1761_dmic_widgets)); | 525 | ARRAY_SIZE(adau1761_dmic_widgets)); |
528 | if (ret) | 526 | if (ret) |
529 | return ret; | 527 | return ret; |
530 | 528 | ||
531 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 529 | ret = snd_soc_dapm_add_routes(dapm, adau1761_dmic_routes, |
532 | adau1761_dmic_routes, | ||
533 | ARRAY_SIZE(adau1761_dmic_routes)); | 530 | ARRAY_SIZE(adau1761_dmic_routes)); |
534 | if (ret) | 531 | if (ret) |
535 | return ret; | 532 | return ret; |
@@ -547,6 +544,7 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) | |||
547 | 544 | ||
548 | static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) | 545 | static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) |
549 | { | 546 | { |
547 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
550 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 548 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
551 | struct adau1761_platform_data *pdata = codec->dev->platform_data; | 549 | struct adau1761_platform_data *pdata = codec->dev->platform_data; |
552 | enum adau1761_output_mode mode; | 550 | enum adau1761_output_mode mode; |
@@ -577,12 +575,12 @@ static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) | |||
577 | } | 575 | } |
578 | 576 | ||
579 | if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) { | 577 | if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) { |
580 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 578 | ret = snd_soc_dapm_new_controls(dapm, |
581 | adau1761_capless_dapm_widgets, | 579 | adau1761_capless_dapm_widgets, |
582 | ARRAY_SIZE(adau1761_capless_dapm_widgets)); | 580 | ARRAY_SIZE(adau1761_capless_dapm_widgets)); |
583 | if (ret) | 581 | if (ret) |
584 | return ret; | 582 | return ret; |
585 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 583 | ret = snd_soc_dapm_add_routes(dapm, |
586 | adau1761_capless_dapm_routes, | 584 | adau1761_capless_dapm_routes, |
587 | ARRAY_SIZE(adau1761_capless_dapm_routes)); | 585 | ARRAY_SIZE(adau1761_capless_dapm_routes)); |
588 | } else { | 586 | } else { |
@@ -590,12 +588,12 @@ static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) | |||
590 | ARRAY_SIZE(adau1761_mono_controls)); | 588 | ARRAY_SIZE(adau1761_mono_controls)); |
591 | if (ret) | 589 | if (ret) |
592 | return ret; | 590 | return ret; |
593 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 591 | ret = snd_soc_dapm_new_controls(dapm, |
594 | adau1761_mono_dapm_widgets, | 592 | adau1761_mono_dapm_widgets, |
595 | ARRAY_SIZE(adau1761_mono_dapm_widgets)); | 593 | ARRAY_SIZE(adau1761_mono_dapm_widgets)); |
596 | if (ret) | 594 | if (ret) |
597 | return ret; | 595 | return ret; |
598 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 596 | ret = snd_soc_dapm_add_routes(dapm, |
599 | adau1761_mono_dapm_routes, | 597 | adau1761_mono_dapm_routes, |
600 | ARRAY_SIZE(adau1761_mono_dapm_routes)); | 598 | ARRAY_SIZE(adau1761_mono_dapm_routes)); |
601 | } | 599 | } |
@@ -640,6 +638,7 @@ static bool adau1761_readable_register(struct device *dev, unsigned int reg) | |||
640 | 638 | ||
641 | static int adau1761_codec_probe(struct snd_soc_codec *codec) | 639 | static int adau1761_codec_probe(struct snd_soc_codec *codec) |
642 | { | 640 | { |
641 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
643 | struct adau1761_platform_data *pdata = codec->dev->platform_data; | 642 | struct adau1761_platform_data *pdata = codec->dev->platform_data; |
644 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 643 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
645 | int ret; | 644 | int ret; |
@@ -692,14 +691,12 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) | |||
692 | return ret; | 691 | return ret; |
693 | 692 | ||
694 | if (adau->type == ADAU1761) { | 693 | if (adau->type == ADAU1761) { |
695 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 694 | ret = snd_soc_dapm_new_controls(dapm, adau1761_dapm_widgets, |
696 | adau1761_dapm_widgets, | ||
697 | ARRAY_SIZE(adau1761_dapm_widgets)); | 695 | ARRAY_SIZE(adau1761_dapm_widgets)); |
698 | if (ret) | 696 | if (ret) |
699 | return ret; | 697 | return ret; |
700 | 698 | ||
701 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 699 | ret = snd_soc_dapm_add_routes(dapm, adau1761_dapm_routes, |
702 | adau1761_dapm_routes, | ||
703 | ARRAY_SIZE(adau1761_dapm_routes)); | 700 | ARRAY_SIZE(adau1761_dapm_routes)); |
704 | if (ret) | 701 | if (ret) |
705 | return ret; | 702 | return ret; |
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index 35581f43fa6d..fde9068550a6 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c | |||
@@ -339,7 +339,6 @@ static int adau1781_set_bias_level(struct snd_soc_codec *codec, | |||
339 | break; | 339 | break; |
340 | } | 340 | } |
341 | 341 | ||
342 | codec->dapm.bias_level = level; | ||
343 | return 0; | 342 | return 0; |
344 | } | 343 | } |
345 | 344 | ||
@@ -383,6 +382,7 @@ static int adau1781_set_input_mode(struct adau *adau, unsigned int reg, | |||
383 | 382 | ||
384 | static int adau1781_codec_probe(struct snd_soc_codec *codec) | 383 | static int adau1781_codec_probe(struct snd_soc_codec *codec) |
385 | { | 384 | { |
385 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
386 | struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev); | 386 | struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev); |
387 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 387 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
388 | int ret; | 388 | int ret; |
@@ -403,19 +403,17 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) | |||
403 | } | 403 | } |
404 | 404 | ||
405 | if (pdata && pdata->use_dmic) { | 405 | if (pdata && pdata->use_dmic) { |
406 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 406 | ret = snd_soc_dapm_new_controls(dapm, |
407 | adau1781_dmic_dapm_widgets, | 407 | adau1781_dmic_dapm_widgets, |
408 | ARRAY_SIZE(adau1781_dmic_dapm_widgets)); | 408 | ARRAY_SIZE(adau1781_dmic_dapm_widgets)); |
409 | if (ret) | 409 | if (ret) |
410 | return ret; | 410 | return ret; |
411 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 411 | ret = snd_soc_dapm_add_routes(dapm, adau1781_dmic_dapm_routes, |
412 | adau1781_dmic_dapm_routes, | ||
413 | ARRAY_SIZE(adau1781_dmic_dapm_routes)); | 412 | ARRAY_SIZE(adau1781_dmic_dapm_routes)); |
414 | if (ret) | 413 | if (ret) |
415 | return ret; | 414 | return ret; |
416 | } else { | 415 | } else { |
417 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 416 | ret = snd_soc_dapm_add_routes(dapm, adau1781_adc_dapm_routes, |
418 | adau1781_adc_dapm_routes, | ||
419 | ARRAY_SIZE(adau1781_adc_dapm_routes)); | 417 | ARRAY_SIZE(adau1781_adc_dapm_routes)); |
420 | if (ret) | 418 | if (ret) |
421 | return ret; | 419 | return ret; |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index fa2e690e51c8..fcf05b254ecd 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -155,6 +155,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
155 | struct snd_ctl_elem_value *ucontrol) | 155 | struct snd_ctl_elem_value *ucontrol) |
156 | { | 156 | { |
157 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 157 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
158 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
158 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 159 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
159 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 160 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
160 | struct snd_soc_dapm_update update; | 161 | struct snd_soc_dapm_update update; |
@@ -188,7 +189,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
188 | update.reg = reg; | 189 | update.reg = reg; |
189 | update.val = val; | 190 | update.val = val; |
190 | 191 | ||
191 | snd_soc_dapm_mux_update_power(&codec->dapm, kcontrol, | 192 | snd_soc_dapm_mux_update_power(dapm, kcontrol, |
192 | ucontrol->value.enumerated.item[0], e, &update); | 193 | ucontrol->value.enumerated.item[0], e, &update); |
193 | } | 194 | } |
194 | 195 | ||
@@ -444,8 +445,8 @@ static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, | |||
444 | static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, | 445 | static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, |
445 | int clk_id, unsigned int freq, int dir) | 446 | int clk_id, unsigned int freq, int dir) |
446 | { | 447 | { |
448 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec); | ||
447 | struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); | 449 | struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); |
448 | struct snd_soc_dapm_context *dapm = &dai->codec->dapm; | ||
449 | 450 | ||
450 | switch (clk_id) { | 451 | switch (clk_id) { |
451 | case ADAU17X1_CLK_SRC_MCLK: | 452 | case ADAU17X1_CLK_SRC_MCLK: |
@@ -804,6 +805,7 @@ EXPORT_SYMBOL_GPL(adau17x1_setup_firmware); | |||
804 | 805 | ||
805 | int adau17x1_add_widgets(struct snd_soc_codec *codec) | 806 | int adau17x1_add_widgets(struct snd_soc_codec *codec) |
806 | { | 807 | { |
808 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
807 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 809 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
808 | int ret; | 810 | int ret; |
809 | 811 | ||
@@ -811,14 +813,13 @@ int adau17x1_add_widgets(struct snd_soc_codec *codec) | |||
811 | ARRAY_SIZE(adau17x1_controls)); | 813 | ARRAY_SIZE(adau17x1_controls)); |
812 | if (ret) | 814 | if (ret) |
813 | return ret; | 815 | return ret; |
814 | ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets, | 816 | ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets, |
815 | ARRAY_SIZE(adau17x1_dapm_widgets)); | 817 | ARRAY_SIZE(adau17x1_dapm_widgets)); |
816 | if (ret) | 818 | if (ret) |
817 | return ret; | 819 | return ret; |
818 | 820 | ||
819 | if (adau17x1_has_dsp(adau)) { | 821 | if (adau17x1_has_dsp(adau)) { |
820 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 822 | ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets, |
821 | adau17x1_dsp_dapm_widgets, | ||
822 | ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); | 823 | ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); |
823 | if (ret) | 824 | if (ret) |
824 | return ret; | 825 | return ret; |
@@ -840,21 +841,20 @@ EXPORT_SYMBOL_GPL(adau17x1_add_widgets); | |||
840 | 841 | ||
841 | int adau17x1_add_routes(struct snd_soc_codec *codec) | 842 | int adau17x1_add_routes(struct snd_soc_codec *codec) |
842 | { | 843 | { |
844 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
843 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 845 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
844 | int ret; | 846 | int ret; |
845 | 847 | ||
846 | ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes, | 848 | ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes, |
847 | ARRAY_SIZE(adau17x1_dapm_routes)); | 849 | ARRAY_SIZE(adau17x1_dapm_routes)); |
848 | if (ret) | 850 | if (ret) |
849 | return ret; | 851 | return ret; |
850 | 852 | ||
851 | if (adau17x1_has_dsp(adau)) { | 853 | if (adau17x1_has_dsp(adau)) { |
852 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 854 | ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes, |
853 | adau17x1_dsp_dapm_routes, | ||
854 | ARRAY_SIZE(adau17x1_dsp_dapm_routes)); | 855 | ARRAY_SIZE(adau17x1_dsp_dapm_routes)); |
855 | } else { | 856 | } else { |
856 | ret = snd_soc_dapm_add_routes(&codec->dapm, | 857 | ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, |
857 | adau17x1_no_dsp_dapm_routes, | ||
858 | ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); | 858 | ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); |
859 | } | 859 | } |
860 | return ret; | 860 | return ret; |
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index 7ad8e156e2df..9bdd15f408c1 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c | |||
@@ -202,7 +202,7 @@ static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { | |||
202 | ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) | 202 | ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) |
203 | 203 | ||
204 | #define ADAU1977_DC_SUB_SWITCH(x) \ | 204 | #define ADAU1977_DC_SUB_SWITCH(x) \ |
205 | SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \ | 205 | SOC_SINGLE("ADC" #x " DC Subtraction Capture Switch", \ |
206 | ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) | 206 | ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) |
207 | 207 | ||
208 | static const struct snd_kcontrol_new adau1977_snd_controls[] = { | 208 | static const struct snd_kcontrol_new adau1977_snd_controls[] = { |
@@ -485,7 +485,7 @@ static int adau1977_set_bias_level(struct snd_soc_codec *codec, | |||
485 | case SND_SOC_BIAS_PREPARE: | 485 | case SND_SOC_BIAS_PREPARE: |
486 | break; | 486 | break; |
487 | case SND_SOC_BIAS_STANDBY: | 487 | case SND_SOC_BIAS_STANDBY: |
488 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 488 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
489 | ret = adau1977_power_enable(adau1977); | 489 | ret = adau1977_power_enable(adau1977); |
490 | break; | 490 | break; |
491 | case SND_SOC_BIAS_OFF: | 491 | case SND_SOC_BIAS_OFF: |
@@ -493,12 +493,7 @@ static int adau1977_set_bias_level(struct snd_soc_codec *codec, | |||
493 | break; | 493 | break; |
494 | } | 494 | } |
495 | 495 | ||
496 | if (ret) | 496 | return ret; |
497 | return ret; | ||
498 | |||
499 | codec->dapm.bias_level = level; | ||
500 | |||
501 | return 0; | ||
502 | } | 497 | } |
503 | 498 | ||
504 | static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | 499 | static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
@@ -853,12 +848,13 @@ static int adau1977_set_sysclk(struct snd_soc_codec *codec, | |||
853 | 848 | ||
854 | static int adau1977_codec_probe(struct snd_soc_codec *codec) | 849 | static int adau1977_codec_probe(struct snd_soc_codec *codec) |
855 | { | 850 | { |
851 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
856 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); | 852 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); |
857 | int ret; | 853 | int ret; |
858 | 854 | ||
859 | switch (adau1977->type) { | 855 | switch (adau1977->type) { |
860 | case ADAU1977: | 856 | case ADAU1977: |
861 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 857 | ret = snd_soc_dapm_new_controls(dapm, |
862 | adau1977_micbias_dapm_widgets, | 858 | adau1977_micbias_dapm_widgets, |
863 | ARRAY_SIZE(adau1977_micbias_dapm_widgets)); | 859 | ARRAY_SIZE(adau1977_micbias_dapm_widgets)); |
864 | if (ret < 0) | 860 | if (ret < 0) |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 4373ada95648..36d842570745 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -539,7 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
539 | unsigned int freq, int dir) | 539 | unsigned int freq, int dir) |
540 | { | 540 | { |
541 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 541 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
542 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 542 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
543 | 543 | ||
544 | if (dir == SND_SOC_CLOCK_IN) { | 544 | if (dir == SND_SOC_CLOCK_IN) { |
545 | switch (clk_id) { | 545 | switch (clk_id) { |
@@ -622,6 +622,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
622 | static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, | 622 | static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, |
623 | int source, unsigned int freq_in, unsigned int freq_out) | 623 | int source, unsigned int freq_in, unsigned int freq_out) |
624 | { | 624 | { |
625 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
625 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 626 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
626 | unsigned int pll_ctrl1 = 0; | 627 | unsigned int pll_ctrl1 = 0; |
627 | unsigned int pll_ctrl2 = 0; | 628 | unsigned int pll_ctrl2 = 0; |
@@ -687,7 +688,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, | |||
687 | 688 | ||
688 | adav80x->pll_src = source; | 689 | adav80x->pll_src = source; |
689 | 690 | ||
690 | snd_soc_dapm_sync(&codec->dapm); | 691 | snd_soc_dapm_sync(dapm); |
691 | } | 692 | } |
692 | 693 | ||
693 | return 0; | 694 | return 0; |
@@ -714,7 +715,6 @@ static int adav80x_set_bias_level(struct snd_soc_codec *codec, | |||
714 | break; | 715 | break; |
715 | } | 716 | } |
716 | 717 | ||
717 | codec->dapm.bias_level = level; | ||
718 | return 0; | 718 | return 0; |
719 | } | 719 | } |
720 | 720 | ||
@@ -801,11 +801,12 @@ static struct snd_soc_dai_driver adav80x_dais[] = { | |||
801 | 801 | ||
802 | static int adav80x_probe(struct snd_soc_codec *codec) | 802 | static int adav80x_probe(struct snd_soc_codec *codec) |
803 | { | 803 | { |
804 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
804 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 805 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
805 | 806 | ||
806 | /* Force PLLs on for SYSCLK output */ | 807 | /* Force PLLs on for SYSCLK output */ |
807 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | 808 | snd_soc_dapm_force_enable_pin(dapm, "PLL1"); |
808 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | 809 | snd_soc_dapm_force_enable_pin(dapm, "PLL2"); |
809 | 810 | ||
810 | /* Power down S/PDIF receiver, since it is currently not supported */ | 811 | /* Power down S/PDIF receiver, since it is currently not supported */ |
811 | regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20); | 812 | regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20); |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 9130d916f2f4..8670861e5bec 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -341,7 +341,6 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec, | |||
341 | snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0); | 341 | snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0); |
342 | break; | 342 | break; |
343 | } | 343 | } |
344 | codec->dapm.bias_level = level; | ||
345 | return 0; | 344 | return 0; |
346 | } | 345 | } |
347 | 346 | ||
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 81b54a270bd8..2d0ff4595ea0 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -412,7 +412,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, | |||
412 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); | 412 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); |
413 | break; | 413 | break; |
414 | case SND_SOC_BIAS_STANDBY: | 414 | case SND_SOC_BIAS_STANDBY: |
415 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 415 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
416 | if (pdata && gpio_is_valid(pdata->gpio_power)) | 416 | if (pdata && gpio_is_valid(pdata->gpio_power)) |
417 | gpio_set_value(pdata->gpio_power, 1); | 417 | gpio_set_value(pdata->gpio_power, 1); |
418 | mdelay(1); | 418 | mdelay(1); |
@@ -439,7 +439,6 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, | |||
439 | regcache_mark_dirty(ak4641->regmap); | 439 | regcache_mark_dirty(ak4641->regmap); |
440 | break; | 440 | break; |
441 | } | 441 | } |
442 | codec->dapm.bias_level = level; | ||
443 | return 0; | 442 | return 0; |
444 | } | 443 | } |
445 | 444 | ||
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 13585e88f597..7c0f6552c229 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -482,7 +482,6 @@ static int ak4642_set_bias_level(struct snd_soc_codec *codec, | |||
482 | snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM); | 482 | snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM); |
483 | break; | 483 | break; |
484 | } | 484 | } |
485 | codec->dapm.bias_level = level; | ||
486 | 485 | ||
487 | return 0; | 486 | return 0; |
488 | } | 487 | } |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 2a58b1dccd2f..0e59063aeb6f 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -577,7 +577,6 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec, | |||
577 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); | 577 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); |
578 | break; | 578 | break; |
579 | } | 579 | } |
580 | codec->dapm.bias_level = level; | ||
581 | return 0; | 580 | return 0; |
582 | } | 581 | } |
583 | 582 | ||
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 0e357996864b..0fc24e0d518c 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -826,7 +826,6 @@ static int alc5623_set_bias_level(struct snd_soc_codec *codec, | |||
826 | snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0); | 826 | snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0); |
827 | break; | 827 | break; |
828 | } | 828 | } |
829 | codec->dapm.bias_level = level; | ||
830 | return 0; | 829 | return 0; |
831 | } | 830 | } |
832 | 831 | ||
@@ -894,7 +893,7 @@ static int alc5623_resume(struct snd_soc_codec *codec) | |||
894 | static int alc5623_probe(struct snd_soc_codec *codec) | 893 | static int alc5623_probe(struct snd_soc_codec *codec) |
895 | { | 894 | { |
896 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | 895 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); |
897 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 896 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
898 | 897 | ||
899 | alc5623_reset(codec); | 898 | alc5623_reset(codec); |
900 | 899 | ||
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index db3283abbe18..607a63b9705f 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -1000,7 +1000,6 @@ static int alc5632_set_bias_level(struct snd_soc_codec *codec, | |||
1000 | ALC5632_PWR_MANAG_ADD1_MASK, 0); | 1000 | ALC5632_PWR_MANAG_ADD1_MASK, 0); |
1001 | break; | 1001 | break; |
1002 | } | 1002 | } |
1003 | codec->dapm.bias_level = level; | ||
1004 | return 0; | 1003 | return 0; |
1005 | } | 1004 | } |
1006 | 1005 | ||
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index eff4b4d512b7..802e05eae3e9 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -208,11 +208,12 @@ static const struct snd_soc_dapm_widget arizona_spkr = | |||
208 | 208 | ||
209 | int arizona_init_spk(struct snd_soc_codec *codec) | 209 | int arizona_init_spk(struct snd_soc_codec *codec) |
210 | { | 210 | { |
211 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
211 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 212 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
212 | struct arizona *arizona = priv->arizona; | 213 | struct arizona *arizona = priv->arizona; |
213 | int ret; | 214 | int ret; |
214 | 215 | ||
215 | ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1); | 216 | ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1); |
216 | if (ret != 0) | 217 | if (ret != 0) |
217 | return ret; | 218 | return ret; |
218 | 219 | ||
@@ -220,8 +221,7 @@ int arizona_init_spk(struct snd_soc_codec *codec) | |||
220 | case WM8997: | 221 | case WM8997: |
221 | break; | 222 | break; |
222 | default: | 223 | default: |
223 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 224 | ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1); |
224 | &arizona_spkr, 1); | ||
225 | if (ret != 0) | 225 | if (ret != 0) |
226 | return ret; | 226 | return ret; |
227 | break; | 227 | break; |
@@ -258,13 +258,14 @@ static const struct snd_soc_dapm_route arizona_mono_routes[] = { | |||
258 | 258 | ||
259 | int arizona_init_mono(struct snd_soc_codec *codec) | 259 | int arizona_init_mono(struct snd_soc_codec *codec) |
260 | { | 260 | { |
261 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
261 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 262 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
262 | struct arizona *arizona = priv->arizona; | 263 | struct arizona *arizona = priv->arizona; |
263 | int i; | 264 | int i; |
264 | 265 | ||
265 | for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) { | 266 | for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) { |
266 | if (arizona->pdata.out_mono[i]) | 267 | if (arizona->pdata.out_mono[i]) |
267 | snd_soc_dapm_add_routes(&codec->dapm, | 268 | snd_soc_dapm_add_routes(dapm, |
268 | &arizona_mono_routes[i], 1); | 269 | &arizona_mono_routes[i], 1); |
269 | } | 270 | } |
270 | 271 | ||
@@ -274,6 +275,7 @@ EXPORT_SYMBOL_GPL(arizona_init_mono); | |||
274 | 275 | ||
275 | int arizona_init_gpio(struct snd_soc_codec *codec) | 276 | int arizona_init_gpio(struct snd_soc_codec *codec) |
276 | { | 277 | { |
278 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
277 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 279 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
278 | struct arizona *arizona = priv->arizona; | 280 | struct arizona *arizona = priv->arizona; |
279 | int i; | 281 | int i; |
@@ -281,23 +283,21 @@ int arizona_init_gpio(struct snd_soc_codec *codec) | |||
281 | switch (arizona->type) { | 283 | switch (arizona->type) { |
282 | case WM5110: | 284 | case WM5110: |
283 | case WM8280: | 285 | case WM8280: |
284 | snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity"); | 286 | snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity"); |
285 | break; | 287 | break; |
286 | default: | 288 | default: |
287 | break; | 289 | break; |
288 | } | 290 | } |
289 | 291 | ||
290 | snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity"); | 292 | snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity"); |
291 | 293 | ||
292 | for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { | 294 | for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { |
293 | switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) { | 295 | switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) { |
294 | case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT: | 296 | case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT: |
295 | snd_soc_dapm_enable_pin(&codec->dapm, | 297 | snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity"); |
296 | "DRC1 Signal Activity"); | ||
297 | break; | 298 | break; |
298 | case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT: | 299 | case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT: |
299 | snd_soc_dapm_enable_pin(&codec->dapm, | 300 | snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity"); |
300 | "DRC2 Signal Activity"); | ||
301 | break; | 301 | break; |
302 | default: | 302 | default: |
303 | break; | 303 | break; |
@@ -851,6 +851,134 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
851 | } | 851 | } |
852 | EXPORT_SYMBOL_GPL(arizona_hp_ev); | 852 | EXPORT_SYMBOL_GPL(arizona_hp_ev); |
853 | 853 | ||
854 | static int arizona_dvfs_enable(struct snd_soc_codec *codec) | ||
855 | { | ||
856 | const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
857 | struct arizona *arizona = priv->arizona; | ||
858 | int ret; | ||
859 | |||
860 | ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000); | ||
861 | if (ret) { | ||
862 | dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret); | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | ret = regmap_update_bits(arizona->regmap, | ||
867 | ARIZONA_DYNAMIC_FREQUENCY_SCALING_1, | ||
868 | ARIZONA_SUBSYS_MAX_FREQ, | ||
869 | ARIZONA_SUBSYS_MAX_FREQ); | ||
870 | if (ret) { | ||
871 | dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret); | ||
872 | regulator_set_voltage(arizona->dcvdd, 1200000, 1800000); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static int arizona_dvfs_disable(struct snd_soc_codec *codec) | ||
880 | { | ||
881 | const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
882 | struct arizona *arizona = priv->arizona; | ||
883 | int ret; | ||
884 | |||
885 | ret = regmap_update_bits(arizona->regmap, | ||
886 | ARIZONA_DYNAMIC_FREQUENCY_SCALING_1, | ||
887 | ARIZONA_SUBSYS_MAX_FREQ, 0); | ||
888 | if (ret) { | ||
889 | dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret); | ||
890 | return ret; | ||
891 | } | ||
892 | |||
893 | ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000); | ||
894 | if (ret) { | ||
895 | dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret); | ||
896 | return ret; | ||
897 | } | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags) | ||
903 | { | ||
904 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
905 | int ret = 0; | ||
906 | |||
907 | mutex_lock(&priv->dvfs_lock); | ||
908 | |||
909 | if (!priv->dvfs_cached && !priv->dvfs_reqs) { | ||
910 | ret = arizona_dvfs_enable(codec); | ||
911 | if (ret) | ||
912 | goto err; | ||
913 | } | ||
914 | |||
915 | priv->dvfs_reqs |= flags; | ||
916 | err: | ||
917 | mutex_unlock(&priv->dvfs_lock); | ||
918 | return ret; | ||
919 | } | ||
920 | EXPORT_SYMBOL_GPL(arizona_dvfs_up); | ||
921 | |||
922 | int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags) | ||
923 | { | ||
924 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
925 | unsigned int old_reqs; | ||
926 | int ret = 0; | ||
927 | |||
928 | mutex_lock(&priv->dvfs_lock); | ||
929 | |||
930 | old_reqs = priv->dvfs_reqs; | ||
931 | priv->dvfs_reqs &= ~flags; | ||
932 | |||
933 | if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs) | ||
934 | ret = arizona_dvfs_disable(codec); | ||
935 | |||
936 | mutex_unlock(&priv->dvfs_lock); | ||
937 | return ret; | ||
938 | } | ||
939 | EXPORT_SYMBOL_GPL(arizona_dvfs_down); | ||
940 | |||
941 | int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w, | ||
942 | struct snd_kcontrol *kcontrol, int event) | ||
943 | { | ||
944 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
945 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
946 | int ret = 0; | ||
947 | |||
948 | mutex_lock(&priv->dvfs_lock); | ||
949 | |||
950 | switch (event) { | ||
951 | case SND_SOC_DAPM_POST_PMU: | ||
952 | if (priv->dvfs_reqs) | ||
953 | ret = arizona_dvfs_enable(codec); | ||
954 | |||
955 | priv->dvfs_cached = false; | ||
956 | break; | ||
957 | case SND_SOC_DAPM_PRE_PMD: | ||
958 | /* We must ensure DVFS is disabled before the codec goes into | ||
959 | * suspend so that we are never in an illegal state of DVFS | ||
960 | * enabled without enough DCVDD | ||
961 | */ | ||
962 | priv->dvfs_cached = true; | ||
963 | |||
964 | if (priv->dvfs_reqs) | ||
965 | ret = arizona_dvfs_disable(codec); | ||
966 | break; | ||
967 | default: | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | mutex_unlock(&priv->dvfs_lock); | ||
972 | return ret; | ||
973 | } | ||
974 | EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev); | ||
975 | |||
976 | void arizona_init_dvfs(struct arizona_priv *priv) | ||
977 | { | ||
978 | mutex_init(&priv->dvfs_lock); | ||
979 | } | ||
980 | EXPORT_SYMBOL_GPL(arizona_init_dvfs); | ||
981 | |||
854 | static unsigned int arizona_sysclk_48k_rates[] = { | 982 | static unsigned int arizona_sysclk_48k_rates[] = { |
855 | 6144000, | 983 | 6144000, |
856 | 12288000, | 984 | 12288000, |
@@ -1266,7 +1394,7 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1266 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 1394 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
1267 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | 1395 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; |
1268 | int base = dai->driver->base; | 1396 | int base = dai->driver->base; |
1269 | int i, sr_val; | 1397 | int i, sr_val, ret; |
1270 | 1398 | ||
1271 | /* | 1399 | /* |
1272 | * We will need to be more flexible than this in future, | 1400 | * We will need to be more flexible than this in future, |
@@ -1282,6 +1410,23 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1282 | } | 1410 | } |
1283 | sr_val = i; | 1411 | sr_val = i; |
1284 | 1412 | ||
1413 | switch (priv->arizona->type) { | ||
1414 | case WM5102: | ||
1415 | case WM8997: | ||
1416 | if (arizona_sr_vals[sr_val] >= 88200) | ||
1417 | ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ); | ||
1418 | else | ||
1419 | ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ); | ||
1420 | |||
1421 | if (ret) { | ||
1422 | arizona_aif_err(dai, "Failed to change DVFS %d\n", ret); | ||
1423 | return ret; | ||
1424 | } | ||
1425 | break; | ||
1426 | default: | ||
1427 | break; | ||
1428 | } | ||
1429 | |||
1285 | switch (dai_priv->clk) { | 1430 | switch (dai_priv->clk) { |
1286 | case ARIZONA_CLK_SYSCLK: | 1431 | case ARIZONA_CLK_SYSCLK: |
1287 | switch (priv->arizona->type) { | 1432 | switch (priv->arizona->type) { |
@@ -1474,6 +1619,7 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1474 | int clk_id, unsigned int freq, int dir) | 1619 | int clk_id, unsigned int freq, int dir) |
1475 | { | 1620 | { |
1476 | struct snd_soc_codec *codec = dai->codec; | 1621 | struct snd_soc_codec *codec = dai->codec; |
1622 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1477 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 1623 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
1478 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | 1624 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; |
1479 | struct snd_soc_dapm_route routes[2]; | 1625 | struct snd_soc_dapm_route routes[2]; |
@@ -1504,15 +1650,15 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1504 | 1650 | ||
1505 | routes[0].source = arizona_dai_clk_str(dai_priv->clk); | 1651 | routes[0].source = arizona_dai_clk_str(dai_priv->clk); |
1506 | routes[1].source = arizona_dai_clk_str(dai_priv->clk); | 1652 | routes[1].source = arizona_dai_clk_str(dai_priv->clk); |
1507 | snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | 1653 | snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes)); |
1508 | 1654 | ||
1509 | routes[0].source = arizona_dai_clk_str(clk_id); | 1655 | routes[0].source = arizona_dai_clk_str(clk_id); |
1510 | routes[1].source = arizona_dai_clk_str(clk_id); | 1656 | routes[1].source = arizona_dai_clk_str(clk_id); |
1511 | snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | 1657 | snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); |
1512 | 1658 | ||
1513 | dai_priv->clk = clk_id; | 1659 | dai_priv->clk = clk_id; |
1514 | 1660 | ||
1515 | return snd_soc_dapm_sync(&codec->dapm); | 1661 | return snd_soc_dapm_sync(dapm); |
1516 | } | 1662 | } |
1517 | 1663 | ||
1518 | static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate) | 1664 | static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate) |
@@ -2140,6 +2286,33 @@ int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff) | |||
2140 | } | 2286 | } |
2141 | EXPORT_SYMBOL_GPL(arizona_set_output_mode); | 2287 | EXPORT_SYMBOL_GPL(arizona_set_output_mode); |
2142 | 2288 | ||
2289 | static const struct soc_enum arizona_adsp2_rate_enum[] = { | ||
2290 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, | ||
2291 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
2292 | ARIZONA_RATE_ENUM_SIZE, | ||
2293 | arizona_rate_text, arizona_rate_val), | ||
2294 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1, | ||
2295 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
2296 | ARIZONA_RATE_ENUM_SIZE, | ||
2297 | arizona_rate_text, arizona_rate_val), | ||
2298 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, | ||
2299 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
2300 | ARIZONA_RATE_ENUM_SIZE, | ||
2301 | arizona_rate_text, arizona_rate_val), | ||
2302 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1, | ||
2303 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
2304 | ARIZONA_RATE_ENUM_SIZE, | ||
2305 | arizona_rate_text, arizona_rate_val), | ||
2306 | }; | ||
2307 | |||
2308 | const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = { | ||
2309 | SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]), | ||
2310 | SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]), | ||
2311 | SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]), | ||
2312 | SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]), | ||
2313 | }; | ||
2314 | EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls); | ||
2315 | |||
2143 | MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); | 2316 | MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); |
2144 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2317 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
2145 | MODULE_LICENSE("GPL"); | 2318 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 11ff899b0272..43deb0462309 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -60,6 +60,9 @@ | |||
60 | #define ARIZONA_MAX_DAI 6 | 60 | #define ARIZONA_MAX_DAI 6 |
61 | #define ARIZONA_MAX_ADSP 4 | 61 | #define ARIZONA_MAX_ADSP 4 |
62 | 62 | ||
63 | #define ARIZONA_DVFS_SR1_RQ 0x001 | ||
64 | #define ARIZONA_DVFS_ADSP1_RQ 0x100 | ||
65 | |||
63 | struct arizona; | 66 | struct arizona; |
64 | struct wm_adsp; | 67 | struct wm_adsp; |
65 | 68 | ||
@@ -84,6 +87,10 @@ struct arizona_priv { | |||
84 | 87 | ||
85 | unsigned int spk_ena:2; | 88 | unsigned int spk_ena:2; |
86 | unsigned int spk_ena_pending:1; | 89 | unsigned int spk_ena_pending:1; |
90 | |||
91 | unsigned int dvfs_reqs; | ||
92 | struct mutex dvfs_lock; | ||
93 | bool dvfs_cached; | ||
87 | }; | 94 | }; |
88 | 95 | ||
89 | #define ARIZONA_NUM_MIXER_INPUTS 103 | 96 | #define ARIZONA_NUM_MIXER_INPUTS 103 |
@@ -107,8 +114,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
107 | arizona_mixer_tlv) | 114 | arizona_mixer_tlv) |
108 | 115 | ||
109 | #define ARIZONA_MUX_ENUM_DECL(name, reg) \ | 116 | #define ARIZONA_MUX_ENUM_DECL(name, reg) \ |
110 | SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ | 117 | SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \ |
111 | arizona_mixer_texts, arizona_mixer_values) | 118 | name, reg, 0, 0xff, arizona_mixer_texts, arizona_mixer_values) |
112 | 119 | ||
113 | #define ARIZONA_MUX_CTL_DECL(name) \ | 120 | #define ARIZONA_MUX_CTL_DECL(name) \ |
114 | const struct snd_kcontrol_new name##_mux = \ | 121 | const struct snd_kcontrol_new name##_mux = \ |
@@ -210,6 +217,8 @@ extern const struct soc_enum arizona_ng_hold; | |||
210 | extern const struct soc_enum arizona_in_hpf_cut_enum; | 217 | extern const struct soc_enum arizona_in_hpf_cut_enum; |
211 | extern const struct soc_enum arizona_in_dmic_osr[]; | 218 | extern const struct soc_enum arizona_in_dmic_osr[]; |
212 | 219 | ||
220 | extern const struct snd_kcontrol_new arizona_adsp2_rate_controls[]; | ||
221 | |||
213 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | 222 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, |
214 | struct snd_kcontrol *kcontrol, | 223 | struct snd_kcontrol *kcontrol, |
215 | int event); | 224 | int event); |
@@ -245,6 +254,12 @@ struct arizona_fll { | |||
245 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; | 254 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; |
246 | }; | 255 | }; |
247 | 256 | ||
257 | extern int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags); | ||
258 | extern int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags); | ||
259 | extern int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w, | ||
260 | struct snd_kcontrol *kcontrol, int event); | ||
261 | extern void arizona_init_dvfs(struct arizona_priv *priv); | ||
262 | |||
248 | extern int arizona_init_fll(struct arizona *arizona, int id, int base, | 263 | extern int arizona_init_fll(struct arizona *arizona, int id, int base, |
249 | int lock_irq, int ok_irq, struct arizona_fll *fll); | 264 | int lock_irq, int ok_irq, struct arizona_fll *fll); |
250 | extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | 265 | extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source, |
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c index e7238b8904bc..b084ad113e96 100644 --- a/sound/soc/codecs/bt-sco.c +++ b/sound/soc/codecs/bt-sco.c | |||
@@ -63,7 +63,7 @@ static int bt_sco_remove(struct platform_device *pdev) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | static struct platform_device_id bt_sco_driver_ids[] = { | 66 | static const struct platform_device_id bt_sco_driver_ids[] = { |
67 | { | 67 | { |
68 | .name = "dfbmcs320", | 68 | .name = "dfbmcs320", |
69 | }, | 69 | }, |
@@ -74,9 +74,18 @@ static struct platform_device_id bt_sco_driver_ids[] = { | |||
74 | }; | 74 | }; |
75 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); | 75 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); |
76 | 76 | ||
77 | #if defined(CONFIG_OF) | ||
78 | static const struct of_device_id bt_sco_codec_of_match[] = { | ||
79 | { .compatible = "delta,dfbmcs320", }, | ||
80 | {}, | ||
81 | }; | ||
82 | MODULE_DEVICE_TABLE(of, bt_sco_codec_of_match); | ||
83 | #endif | ||
84 | |||
77 | static struct platform_driver bt_sco_driver = { | 85 | static struct platform_driver bt_sco_driver = { |
78 | .driver = { | 86 | .driver = { |
79 | .name = "bt-sco", | 87 | .name = "bt-sco", |
88 | .of_match_table = of_match_ptr(bt_sco_codec_of_match), | ||
80 | }, | 89 | }, |
81 | .probe = bt_sco_probe, | 90 | .probe = bt_sco_probe, |
82 | .remove = bt_sco_remove, | 91 | .remove = bt_sco_remove, |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index d6dedd4eab29..1c895a53001d 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -92,7 +92,6 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec, | |||
92 | DAVINCI_VC_REG12_POWER_ALL_OFF); | 92 | DAVINCI_VC_REG12_POWER_ALL_OFF); |
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | codec->dapm.bias_level = level; | ||
96 | 95 | ||
97 | return 0; | 96 | return 0; |
98 | } | 97 | } |
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 60598b230341..8f40025b7e7c 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index cac48ddf3ba6..d7ec4756e45b 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -503,7 +503,6 @@ static int cs4265_set_bias_level(struct snd_soc_codec *codec, | |||
503 | CS4265_PWRCTL_PDN); | 503 | CS4265_PWRCTL_PDN); |
504 | break; | 504 | break; |
505 | } | 505 | } |
506 | codec->dapm.bias_level = level; | ||
507 | return 0; | 506 | return 0; |
508 | } | 507 | } |
509 | 508 | ||
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 1589e7a881d8..4de52c9957ac 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -897,7 +897,7 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec, | |||
897 | CS42L52_PWRCTL1_PDN_CODEC, 0); | 897 | CS42L52_PWRCTL1_PDN_CODEC, 0); |
898 | break; | 898 | break; |
899 | case SND_SOC_BIAS_STANDBY: | 899 | case SND_SOC_BIAS_STANDBY: |
900 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 900 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
901 | regcache_cache_only(cs42l52->regmap, false); | 901 | regcache_cache_only(cs42l52->regmap, false); |
902 | regcache_sync(cs42l52->regmap); | 902 | regcache_sync(cs42l52->regmap); |
903 | } | 903 | } |
@@ -908,7 +908,6 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec, | |||
908 | regcache_cache_only(cs42l52->regmap, true); | 908 | regcache_cache_only(cs42l52->regmap, true); |
909 | break; | 909 | break; |
910 | } | 910 | } |
911 | codec->dapm.bias_level = level; | ||
912 | 911 | ||
913 | return 0; | 912 | return 0; |
914 | } | 913 | } |
@@ -956,7 +955,7 @@ static void cs42l52_beep_work(struct work_struct *work) | |||
956 | struct cs42l52_private *cs42l52 = | 955 | struct cs42l52_private *cs42l52 = |
957 | container_of(work, struct cs42l52_private, beep_work); | 956 | container_of(work, struct cs42l52_private, beep_work); |
958 | struct snd_soc_codec *codec = cs42l52->codec; | 957 | struct snd_soc_codec *codec = cs42l52->codec; |
959 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 958 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
960 | int i; | 959 | int i; |
961 | int val = 0; | 960 | int val = 0; |
962 | int best = 0; | 961 | int best = 0; |
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index cbc654fe48c7..1e11ba45a79f 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -953,7 +953,7 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec, | |||
953 | CS42L56_PDN_ALL_MASK, 0); | 953 | CS42L56_PDN_ALL_MASK, 0); |
954 | break; | 954 | break; |
955 | case SND_SOC_BIAS_STANDBY: | 955 | case SND_SOC_BIAS_STANDBY: |
956 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 956 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
957 | regcache_cache_only(cs42l56->regmap, false); | 957 | regcache_cache_only(cs42l56->regmap, false); |
958 | regcache_sync(cs42l56->regmap); | 958 | regcache_sync(cs42l56->regmap); |
959 | ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies), | 959 | ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies), |
@@ -978,7 +978,6 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec, | |||
978 | cs42l56->supplies); | 978 | cs42l56->supplies); |
979 | break; | 979 | break; |
980 | } | 980 | } |
981 | codec->dapm.bias_level = level; | ||
982 | 981 | ||
983 | return 0; | 982 | return 0; |
984 | } | 983 | } |
@@ -1026,7 +1025,7 @@ static void cs42l56_beep_work(struct work_struct *work) | |||
1026 | struct cs42l56_private *cs42l56 = | 1025 | struct cs42l56_private *cs42l56 = |
1027 | container_of(work, struct cs42l56_private, beep_work); | 1026 | container_of(work, struct cs42l56_private, beep_work); |
1028 | struct snd_soc_codec *codec = cs42l56->codec; | 1027 | struct snd_soc_codec *codec = cs42l56->codec; |
1029 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1028 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1030 | int i; | 1029 | int i; |
1031 | int val = 0; | 1030 | int val = 0; |
1032 | int best = 0; | 1031 | int best = 0; |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 8ecedba79606..b7853b9d3a60 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -1208,7 +1208,7 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec, | |||
1208 | break; | 1208 | break; |
1209 | 1209 | ||
1210 | case SND_SOC_BIAS_STANDBY: | 1210 | case SND_SOC_BIAS_STANDBY: |
1211 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1211 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1212 | regcache_cache_only(cs42l73->regmap, false); | 1212 | regcache_cache_only(cs42l73->regmap, false); |
1213 | regcache_sync(cs42l73->regmap); | 1213 | regcache_sync(cs42l73->regmap); |
1214 | } | 1214 | } |
@@ -1228,7 +1228,6 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec, | |||
1228 | snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1); | 1228 | snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1); |
1229 | break; | 1229 | break; |
1230 | } | 1230 | } |
1231 | codec->dapm.bias_level = level; | ||
1232 | return 0; | 1231 | return 0; |
1233 | } | 1232 | } |
1234 | 1233 | ||
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 670ebfe12903..e1d46862e81f 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); | |||
380 | static int cs42xx8_codec_probe(struct snd_soc_codec *codec) | 380 | static int cs42xx8_codec_probe(struct snd_soc_codec *codec) |
381 | { | 381 | { |
382 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | 382 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); |
383 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 383 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
384 | 384 | ||
385 | switch (cs42xx8->drvdata->num_adcs) { | 385 | switch (cs42xx8->drvdata->num_adcs) { |
386 | case 3: | 386 | case 3: |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 0f334bc1b63c..d6f4abbbf8a7 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -333,7 +333,7 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec, | |||
333 | 333 | ||
334 | switch (level) { | 334 | switch (level) { |
335 | case SND_SOC_BIAS_PREPARE: | 335 | case SND_SOC_BIAS_PREPARE: |
336 | if (codec->dapm.bias_level != SND_SOC_BIAS_STANDBY) | 336 | if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_STANDBY) |
337 | break; | 337 | break; |
338 | if (IS_ERR(cx20442->por)) | 338 | if (IS_ERR(cx20442->por)) |
339 | err = PTR_ERR(cx20442->por); | 339 | err = PTR_ERR(cx20442->por); |
@@ -341,7 +341,7 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec, | |||
341 | err = regulator_enable(cx20442->por); | 341 | err = regulator_enable(cx20442->por); |
342 | break; | 342 | break; |
343 | case SND_SOC_BIAS_STANDBY: | 343 | case SND_SOC_BIAS_STANDBY: |
344 | if (codec->dapm.bias_level != SND_SOC_BIAS_PREPARE) | 344 | if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_PREPARE) |
345 | break; | 345 | break; |
346 | if (IS_ERR(cx20442->por)) | 346 | if (IS_ERR(cx20442->por)) |
347 | err = PTR_ERR(cx20442->por); | 347 | err = PTR_ERR(cx20442->por); |
@@ -351,8 +351,6 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec, | |||
351 | default: | 351 | default: |
352 | break; | 352 | break; |
353 | } | 353 | } |
354 | if (!err) | ||
355 | codec->dapm.bias_level = level; | ||
356 | 354 | ||
357 | return err; | 355 | return err; |
358 | } | 356 | } |
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 9ec577f0edb4..238e48a3a4fe 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -1374,7 +1374,7 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, | |||
1374 | case SND_SOC_BIAS_PREPARE: | 1374 | case SND_SOC_BIAS_PREPARE: |
1375 | break; | 1375 | break; |
1376 | case SND_SOC_BIAS_STANDBY: | 1376 | case SND_SOC_BIAS_STANDBY: |
1377 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1377 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1378 | /* Enable VMID reference & master bias */ | 1378 | /* Enable VMID reference & master bias */ |
1379 | snd_soc_update_bits(codec, DA7213_REFERENCES, | 1379 | snd_soc_update_bits(codec, DA7213_REFERENCES, |
1380 | DA7213_VMID_EN | DA7213_BIAS_EN, | 1380 | DA7213_VMID_EN | DA7213_BIAS_EN, |
@@ -1387,7 +1387,6 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, | |||
1387 | DA7213_VMID_EN | DA7213_BIAS_EN, 0); | 1387 | DA7213_VMID_EN | DA7213_BIAS_EN, 0); |
1388 | break; | 1388 | break; |
1389 | } | 1389 | } |
1390 | codec->dapm.bias_level = level; | ||
1391 | return 0; | 1390 | return 0; |
1392 | } | 1391 | } |
1393 | 1392 | ||
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 911c26c705fc..207523686bd5 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -1432,7 +1432,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, | |||
1432 | case SND_SOC_BIAS_PREPARE: | 1432 | case SND_SOC_BIAS_PREPARE: |
1433 | break; | 1433 | break; |
1434 | case SND_SOC_BIAS_STANDBY: | 1434 | case SND_SOC_BIAS_STANDBY: |
1435 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1435 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1436 | /* Init Codec */ | 1436 | /* Init Codec */ |
1437 | snd_soc_write(codec, DA732X_REG_REF1, | 1437 | snd_soc_write(codec, DA732X_REG_REF1, |
1438 | DA732X_VMID_FASTCHG); | 1438 | DA732X_VMID_FASTCHG); |
@@ -1502,8 +1502,6 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, | |||
1502 | break; | 1502 | break; |
1503 | } | 1503 | } |
1504 | 1504 | ||
1505 | codec->dapm.bias_level = level; | ||
1506 | |||
1507 | return 0; | 1505 | return 0; |
1508 | } | 1506 | } |
1509 | 1507 | ||
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index ad19cc56702b..66bb446473b8 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -1364,7 +1364,7 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, | |||
1364 | case SND_SOC_BIAS_PREPARE: | 1364 | case SND_SOC_BIAS_PREPARE: |
1365 | break; | 1365 | break; |
1366 | case SND_SOC_BIAS_STANDBY: | 1366 | case SND_SOC_BIAS_STANDBY: |
1367 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1367 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1368 | /* Enable VMID reference & master bias */ | 1368 | /* Enable VMID reference & master bias */ |
1369 | snd_soc_update_bits(codec, DA9055_REFERENCES, | 1369 | snd_soc_update_bits(codec, DA9055_REFERENCES, |
1370 | DA9055_VMID_EN | DA9055_BIAS_EN, | 1370 | DA9055_VMID_EN | DA9055_BIAS_EN, |
@@ -1377,7 +1377,6 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, | |||
1377 | DA9055_VMID_EN | DA9055_BIAS_EN, 0); | 1377 | DA9055_VMID_EN | DA9055_BIAS_EN, 0); |
1378 | break; | 1378 | break; |
1379 | } | 1379 | } |
1380 | codec->dapm.bias_level = level; | ||
1381 | return 0; | 1380 | return 0; |
1382 | } | 1381 | } |
1383 | 1382 | ||
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index c5f35a07e8e4..6a091016e0fc 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c | |||
@@ -536,7 +536,7 @@ static int es8328_set_bias_level(struct snd_soc_codec *codec, | |||
536 | break; | 536 | break; |
537 | 537 | ||
538 | case SND_SOC_BIAS_STANDBY: | 538 | case SND_SOC_BIAS_STANDBY: |
539 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 539 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
540 | snd_soc_update_bits(codec, ES8328_CONTROL1, | 540 | snd_soc_update_bits(codec, ES8328_CONTROL1, |
541 | ES8328_CONTROL1_VMIDSEL_MASK | | 541 | ES8328_CONTROL1_VMIDSEL_MASK | |
542 | ES8328_CONTROL1_ENREF, | 542 | ES8328_CONTROL1_ENREF, |
@@ -566,7 +566,6 @@ static int es8328_set_bias_level(struct snd_soc_codec *codec, | |||
566 | 0); | 566 | 0); |
567 | break; | 567 | break; |
568 | } | 568 | } |
569 | codec->dapm.bias_level = level; | ||
570 | return 0; | 569 | return 0; |
571 | } | 570 | } |
572 | 571 | ||
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 3a89ce66d51d..ebd90283c960 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -909,8 +909,6 @@ static int isabelle_set_bias_level(struct snd_soc_codec *codec, | |||
909 | break; | 909 | break; |
910 | } | 910 | } |
911 | 911 | ||
912 | codec->dapm.bias_level = level; | ||
913 | |||
914 | return 0; | 912 | return 0; |
915 | } | 913 | } |
916 | 914 | ||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 933f4476d76c..9363fdbca9cd 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -258,7 +258,7 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
258 | break; | 258 | break; |
259 | case SND_SOC_BIAS_STANDBY: | 259 | case SND_SOC_BIAS_STANDBY: |
260 | /* The only way to clear the suspend flag is to reset the codec */ | 260 | /* The only way to clear the suspend flag is to reset the codec */ |
261 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 261 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
262 | jz4740_codec_wakeup(regmap); | 262 | jz4740_codec_wakeup(regmap); |
263 | 263 | ||
264 | mask = JZ4740_CODEC_1_VREF_DISABLE | | 264 | mask = JZ4740_CODEC_1_VREF_DISABLE | |
@@ -281,8 +281,6 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
281 | break; | 281 | break; |
282 | } | 282 | } |
283 | 283 | ||
284 | codec->dapm.bias_level = level; | ||
285 | |||
286 | return 0; | 284 | return 0; |
287 | } | 285 | } |
288 | 286 | ||
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index a924bb9d7886..99ffc49aa779 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -23,11 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include <sound/tlv.h> | 24 | #include <sound/tlv.h> |
25 | 25 | ||
26 | struct lm4857 { | ||
27 | struct regmap *regmap; | ||
28 | uint8_t mode; | ||
29 | }; | ||
30 | |||
31 | static const struct reg_default lm4857_default_regs[] = { | 26 | static const struct reg_default lm4857_default_regs[] = { |
32 | { 0x0, 0x00 }, | 27 | { 0x0, 0x00 }, |
33 | { 0x1, 0x00 }, | 28 | { 0x1, 0x00 }, |
@@ -46,66 +41,33 @@ static const struct reg_default lm4857_default_regs[] = { | |||
46 | #define LM4857_WAKEUP 5 | 41 | #define LM4857_WAKEUP 5 |
47 | #define LM4857_EPGAIN 4 | 42 | #define LM4857_EPGAIN 4 |
48 | 43 | ||
49 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | 44 | static const unsigned int lm4857_mode_values[] = { |
50 | struct snd_ctl_elem_value *ucontrol) | 45 | 0, |
51 | { | 46 | 6, |
52 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 47 | 7, |
53 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | 48 | 8, |
54 | 49 | 9, | |
55 | ucontrol->value.integer.value[0] = lm4857->mode; | 50 | }; |
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | ||
61 | struct snd_ctl_elem_value *ucontrol) | ||
62 | { | ||
63 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
64 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
65 | uint8_t value = ucontrol->value.integer.value[0]; | ||
66 | |||
67 | lm4857->mode = value; | ||
68 | |||
69 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | ||
70 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6); | ||
71 | |||
72 | return 1; | ||
73 | } | ||
74 | |||
75 | static int lm4857_set_bias_level(struct snd_soc_codec *codec, | ||
76 | enum snd_soc_bias_level level) | ||
77 | { | ||
78 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
79 | |||
80 | switch (level) { | ||
81 | case SND_SOC_BIAS_ON: | ||
82 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, | ||
83 | lm4857->mode + 6); | ||
84 | break; | ||
85 | case SND_SOC_BIAS_STANDBY: | ||
86 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0); | ||
87 | break; | ||
88 | default: | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | codec->dapm.bias_level = level; | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | 51 | ||
97 | static const char *lm4857_mode[] = { | 52 | static const char * const lm4857_mode_texts[] = { |
53 | "Off", | ||
98 | "Earpiece", | 54 | "Earpiece", |
99 | "Loudspeaker", | 55 | "Loudspeaker", |
100 | "Loudspeaker + Headphone", | 56 | "Loudspeaker + Headphone", |
101 | "Headphone", | 57 | "Headphone", |
102 | }; | 58 | }; |
103 | 59 | ||
104 | static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); | 60 | static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(lm4857_mode_enum, |
61 | LM4857_CTRL, 0, 0xf, lm4857_mode_texts, lm4857_mode_values); | ||
62 | |||
63 | static const struct snd_kcontrol_new lm4857_mode_ctrl = | ||
64 | SOC_DAPM_ENUM("Mode", lm4857_mode_enum); | ||
105 | 65 | ||
106 | static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { | 66 | static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { |
107 | SND_SOC_DAPM_INPUT("IN"), | 67 | SND_SOC_DAPM_INPUT("IN"), |
108 | 68 | ||
69 | SND_SOC_DAPM_DEMUX("Mode", SND_SOC_NOPM, 0, 0, &lm4857_mode_ctrl), | ||
70 | |||
109 | SND_SOC_DAPM_OUTPUT("LS"), | 71 | SND_SOC_DAPM_OUTPUT("LS"), |
110 | SND_SOC_DAPM_OUTPUT("HP"), | 72 | SND_SOC_DAPM_OUTPUT("HP"), |
111 | SND_SOC_DAPM_OUTPUT("EP"), | 73 | SND_SOC_DAPM_OUTPUT("EP"), |
@@ -127,24 +89,18 @@ static const struct snd_kcontrol_new lm4857_controls[] = { | |||
127 | LM4857_WAKEUP, 1, 0), | 89 | LM4857_WAKEUP, 1, 0), |
128 | SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL, | 90 | SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL, |
129 | LM4857_EPGAIN, 1, 0), | 91 | LM4857_EPGAIN, 1, 0), |
130 | |||
131 | SOC_ENUM_EXT("Mode", lm4857_mode_enum, | ||
132 | lm4857_get_mode, lm4857_set_mode), | ||
133 | }; | 92 | }; |
134 | 93 | ||
135 | /* There is a demux between the input signal and the output signals. | ||
136 | * Currently there is no easy way to model it in ASoC and since it does not make | ||
137 | * much of a difference in practice simply connect the input direclty to the | ||
138 | * outputs. */ | ||
139 | static const struct snd_soc_dapm_route lm4857_routes[] = { | 94 | static const struct snd_soc_dapm_route lm4857_routes[] = { |
140 | {"LS", NULL, "IN"}, | 95 | { "Mode", NULL, "IN" }, |
141 | {"HP", NULL, "IN"}, | 96 | { "LS", "Loudspeaker", "Mode" }, |
142 | {"EP", NULL, "IN"}, | 97 | { "LS", "Loudspeaker + Headphone", "Mode" }, |
98 | { "HP", "Headphone", "Mode" }, | ||
99 | { "HP", "Loudspeaker + Headphone", "Mode" }, | ||
100 | { "EP", "Earpiece", "Mode" }, | ||
143 | }; | 101 | }; |
144 | 102 | ||
145 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { | 103 | static struct snd_soc_component_driver lm4857_component_driver = { |
146 | .set_bias_level = lm4857_set_bias_level, | ||
147 | |||
148 | .controls = lm4857_controls, | 104 | .controls = lm4857_controls, |
149 | .num_controls = ARRAY_SIZE(lm4857_controls), | 105 | .num_controls = ARRAY_SIZE(lm4857_controls), |
150 | .dapm_widgets = lm4857_dapm_widgets, | 106 | .dapm_widgets = lm4857_dapm_widgets, |
@@ -167,25 +123,14 @@ static const struct regmap_config lm4857_regmap_config = { | |||
167 | static int lm4857_i2c_probe(struct i2c_client *i2c, | 123 | static int lm4857_i2c_probe(struct i2c_client *i2c, |
168 | const struct i2c_device_id *id) | 124 | const struct i2c_device_id *id) |
169 | { | 125 | { |
170 | struct lm4857 *lm4857; | 126 | struct regmap *regmap; |
171 | |||
172 | lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); | ||
173 | if (!lm4857) | ||
174 | return -ENOMEM; | ||
175 | |||
176 | i2c_set_clientdata(i2c, lm4857); | ||
177 | |||
178 | lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config); | ||
179 | if (IS_ERR(lm4857->regmap)) | ||
180 | return PTR_ERR(lm4857->regmap); | ||
181 | 127 | ||
182 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); | 128 | regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config); |
183 | } | 129 | if (IS_ERR(regmap)) |
130 | return PTR_ERR(regmap); | ||
184 | 131 | ||
185 | static int lm4857_i2c_remove(struct i2c_client *i2c) | 132 | return devm_snd_soc_register_component(&i2c->dev, |
186 | { | 133 | &lm4857_component_driver, NULL, 0); |
187 | snd_soc_unregister_codec(&i2c->dev); | ||
188 | return 0; | ||
189 | } | 134 | } |
190 | 135 | ||
191 | static const struct i2c_device_id lm4857_i2c_id[] = { | 136 | static const struct i2c_device_id lm4857_i2c_id[] = { |
@@ -200,7 +145,6 @@ static struct i2c_driver lm4857_i2c_driver = { | |||
200 | .owner = THIS_MODULE, | 145 | .owner = THIS_MODULE, |
201 | }, | 146 | }, |
202 | .probe = lm4857_i2c_probe, | 147 | .probe = lm4857_i2c_probe, |
203 | .remove = lm4857_i2c_remove, | ||
204 | .id_table = lm4857_i2c_id, | 148 | .id_table = lm4857_i2c_id, |
205 | }; | 149 | }; |
206 | 150 | ||
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index c4dfde9bdf1c..6600aa0a33dc 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -1271,7 +1271,7 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec, | |||
1271 | break; | 1271 | break; |
1272 | 1272 | ||
1273 | case SND_SOC_BIAS_STANDBY: | 1273 | case SND_SOC_BIAS_STANDBY: |
1274 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 1274 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
1275 | regcache_sync(lm49453->regmap); | 1275 | regcache_sync(lm49453->regmap); |
1276 | 1276 | ||
1277 | snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG, | 1277 | snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG, |
@@ -1284,8 +1284,6 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec, | |||
1284 | break; | 1284 | break; |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | codec->dapm.bias_level = level; | ||
1288 | |||
1289 | return 0; | 1287 | return 0; |
1290 | } | 1288 | } |
1291 | 1289 | ||
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 805b3f8cd39d..d0f45348bfbb 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -1571,7 +1571,7 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec, | |||
1571 | break; | 1571 | break; |
1572 | 1572 | ||
1573 | case SND_SOC_BIAS_STANDBY: | 1573 | case SND_SOC_BIAS_STANDBY: |
1574 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 1574 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
1575 | regcache_sync(max98088->regmap); | 1575 | regcache_sync(max98088->regmap); |
1576 | 1576 | ||
1577 | snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, | 1577 | snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, |
@@ -1584,7 +1584,6 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec, | |||
1584 | regcache_mark_dirty(max98088->regmap); | 1584 | regcache_mark_dirty(max98088->regmap); |
1585 | break; | 1585 | break; |
1586 | } | 1586 | } |
1587 | codec->dapm.bias_level = level; | ||
1588 | return 0; | 1587 | return 0; |
1589 | } | 1588 | } |
1590 | 1589 | ||
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 3e33ef2acf3c..78268f0514e9 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "max98090.h" | 27 | #include "max98090.h" |
28 | 28 | ||
29 | /* Allows for sparsely populated register maps */ | 29 | /* Allows for sparsely populated register maps */ |
30 | static struct reg_default max98090_reg[] = { | 30 | static const struct reg_default max98090_reg[] = { |
31 | { 0x00, 0x00 }, /* 00 Software Reset */ | 31 | { 0x00, 0x00 }, /* 00 Software Reset */ |
32 | { 0x03, 0x04 }, /* 03 Interrupt Masks */ | 32 | { 0x03, 0x04 }, /* 03 Interrupt Masks */ |
33 | { 0x04, 0x00 }, /* 04 System Clock Quick */ | 33 | { 0x04, 0x00 }, /* 04 System Clock Quick */ |
@@ -1500,7 +1500,7 @@ static const struct snd_soc_dapm_route max98091_dapm_routes[] = { | |||
1500 | static int max98090_add_widgets(struct snd_soc_codec *codec) | 1500 | static int max98090_add_widgets(struct snd_soc_codec *codec) |
1501 | { | 1501 | { |
1502 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 1502 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
1503 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1503 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1504 | 1504 | ||
1505 | snd_soc_add_codec_controls(codec, max98090_snd_controls, | 1505 | snd_soc_add_codec_controls(codec, max98090_snd_controls, |
1506 | ARRAY_SIZE(max98090_snd_controls)); | 1506 | ARRAY_SIZE(max98090_snd_controls)); |
@@ -1798,16 +1798,17 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1798 | * away from ON. Disable the clock in that case, otherwise | 1798 | * away from ON. Disable the clock in that case, otherwise |
1799 | * enable it. | 1799 | * enable it. |
1800 | */ | 1800 | */ |
1801 | if (!IS_ERR(max98090->mclk)) { | 1801 | if (IS_ERR(max98090->mclk)) |
1802 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 1802 | break; |
1803 | clk_disable_unprepare(max98090->mclk); | 1803 | |
1804 | else | 1804 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) |
1805 | clk_prepare_enable(max98090->mclk); | 1805 | clk_disable_unprepare(max98090->mclk); |
1806 | } | 1806 | else |
1807 | clk_prepare_enable(max98090->mclk); | ||
1807 | break; | 1808 | break; |
1808 | 1809 | ||
1809 | case SND_SOC_BIAS_STANDBY: | 1810 | case SND_SOC_BIAS_STANDBY: |
1810 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1811 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1811 | ret = regcache_sync(max98090->regmap); | 1812 | ret = regcache_sync(max98090->regmap); |
1812 | if (ret != 0) { | 1813 | if (ret != 0) { |
1813 | dev_err(codec->dev, | 1814 | dev_err(codec->dev, |
@@ -1824,7 +1825,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1824 | regcache_mark_dirty(max98090->regmap); | 1825 | regcache_mark_dirty(max98090->regmap); |
1825 | break; | 1826 | break; |
1826 | } | 1827 | } |
1827 | codec->dapm.bias_level = level; | ||
1828 | return 0; | 1828 | return 0; |
1829 | } | 1829 | } |
1830 | 1830 | ||
@@ -2187,7 +2187,6 @@ static void max98090_jack_work(struct work_struct *work) | |||
2187 | struct max98090_priv, | 2187 | struct max98090_priv, |
2188 | jack_work.work); | 2188 | jack_work.work); |
2189 | struct snd_soc_codec *codec = max98090->codec; | 2189 | struct snd_soc_codec *codec = max98090->codec; |
2190 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2191 | int status = 0; | 2190 | int status = 0; |
2192 | int reg; | 2191 | int reg; |
2193 | 2192 | ||
@@ -2266,8 +2265,6 @@ static void max98090_jack_work(struct work_struct *work) | |||
2266 | 2265 | ||
2267 | snd_soc_jack_report(max98090->jack, status, | 2266 | snd_soc_jack_report(max98090->jack, status, |
2268 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2267 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
2269 | |||
2270 | snd_soc_dapm_sync(dapm); | ||
2271 | } | 2268 | } |
2272 | 2269 | ||
2273 | static irqreturn_t max98090_interrupt(int irq, void *data) | 2270 | static irqreturn_t max98090_interrupt(int irq, void *data) |
@@ -2422,6 +2419,8 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2422 | struct max98090_cdata *cdata; | 2419 | struct max98090_cdata *cdata; |
2423 | enum max98090_type devtype; | 2420 | enum max98090_type devtype; |
2424 | int ret = 0; | 2421 | int ret = 0; |
2422 | int err; | ||
2423 | unsigned int micbias; | ||
2425 | 2424 | ||
2426 | dev_dbg(codec->dev, "max98090_probe\n"); | 2425 | dev_dbg(codec->dev, "max98090_probe\n"); |
2427 | 2426 | ||
@@ -2506,8 +2505,17 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2506 | snd_soc_write(codec, M98090_REG_BIAS_CONTROL, | 2505 | snd_soc_write(codec, M98090_REG_BIAS_CONTROL, |
2507 | M98090_VCM_MODE_MASK); | 2506 | M98090_VCM_MODE_MASK); |
2508 | 2507 | ||
2508 | err = device_property_read_u32(codec->dev, "maxim,micbias", &micbias); | ||
2509 | if (err) { | ||
2510 | micbias = M98090_MBVSEL_2V8; | ||
2511 | dev_info(codec->dev, "use default 2.8v micbias\n"); | ||
2512 | } else if (micbias < M98090_MBVSEL_2V2 || micbias > M98090_MBVSEL_2V8) { | ||
2513 | dev_err(codec->dev, "micbias out of range 0x%x\n", micbias); | ||
2514 | micbias = M98090_MBVSEL_2V8; | ||
2515 | } | ||
2516 | |||
2509 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, | 2517 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, |
2510 | M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); | 2518 | M98090_MBVSEL_MASK, micbias); |
2511 | 2519 | ||
2512 | max98090_add_widgets(codec); | 2520 | max98090_add_widgets(codec); |
2513 | 2521 | ||
@@ -2696,7 +2704,7 @@ static const struct of_device_id max98090_of_match[] = { | |||
2696 | MODULE_DEVICE_TABLE(of, max98090_of_match); | 2704 | MODULE_DEVICE_TABLE(of, max98090_of_match); |
2697 | 2705 | ||
2698 | #ifdef CONFIG_ACPI | 2706 | #ifdef CONFIG_ACPI |
2699 | static struct acpi_device_id max98090_acpi_match[] = { | 2707 | static const struct acpi_device_id max98090_acpi_match[] = { |
2700 | { "193C9890", MAX98090 }, | 2708 | { "193C9890", MAX98090 }, |
2701 | { } | 2709 | { } |
2702 | }; | 2710 | }; |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 8fba0c3db798..9a46d3dcf703 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -1650,16 +1650,17 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec, | |||
1650 | * away from ON. Disable the clock in that case, otherwise | 1650 | * away from ON. Disable the clock in that case, otherwise |
1651 | * enable it. | 1651 | * enable it. |
1652 | */ | 1652 | */ |
1653 | if (!IS_ERR(max98095->mclk)) { | 1653 | if (IS_ERR(max98095->mclk)) |
1654 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 1654 | break; |
1655 | clk_disable_unprepare(max98095->mclk); | 1655 | |
1656 | else | 1656 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) |
1657 | clk_prepare_enable(max98095->mclk); | 1657 | clk_disable_unprepare(max98095->mclk); |
1658 | } | 1658 | else |
1659 | clk_prepare_enable(max98095->mclk); | ||
1659 | break; | 1660 | break; |
1660 | 1661 | ||
1661 | case SND_SOC_BIAS_STANDBY: | 1662 | case SND_SOC_BIAS_STANDBY: |
1662 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1663 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1663 | ret = regcache_sync(max98095->regmap); | 1664 | ret = regcache_sync(max98095->regmap); |
1664 | 1665 | ||
1665 | if (ret != 0) { | 1666 | if (ret != 0) { |
@@ -1678,7 +1679,6 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec, | |||
1678 | regcache_mark_dirty(max98095->regmap); | 1679 | regcache_mark_dirty(max98095->regmap); |
1679 | break; | 1680 | break; |
1680 | } | 1681 | } |
1681 | codec->dapm.bias_level = level; | ||
1682 | return 0; | 1682 | return 0; |
1683 | } | 1683 | } |
1684 | 1684 | ||
@@ -2198,7 +2198,7 @@ static int max98095_suspend(struct snd_soc_codec *codec) | |||
2198 | if (max98095->headphone_jack || max98095->mic_jack) | 2198 | if (max98095->headphone_jack || max98095->mic_jack) |
2199 | max98095_jack_detect_disable(codec); | 2199 | max98095_jack_detect_disable(codec); |
2200 | 2200 | ||
2201 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2201 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
2202 | 2202 | ||
2203 | return 0; | 2203 | return 0; |
2204 | } | 2204 | } |
@@ -2208,7 +2208,7 @@ static int max98095_resume(struct snd_soc_codec *codec) | |||
2208 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | 2208 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
2209 | struct i2c_client *client = to_i2c_client(codec->dev); | 2209 | struct i2c_client *client = to_i2c_client(codec->dev); |
2210 | 2210 | ||
2211 | max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2211 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2212 | 2212 | ||
2213 | if (max98095->headphone_jack || max98095->mic_jack) { | 2213 | if (max98095->headphone_jack || max98095->mic_jack) { |
2214 | max98095_jack_detect_enable(codec); | 2214 | max98095_jack_detect_enable(codec); |
@@ -2301,8 +2301,8 @@ static int max98095_probe(struct snd_soc_codec *codec) | |||
2301 | /* register an audio interrupt */ | 2301 | /* register an audio interrupt */ |
2302 | ret = request_threaded_irq(client->irq, NULL, | 2302 | ret = request_threaded_irq(client->irq, NULL, |
2303 | max98095_report_jack, | 2303 | max98095_report_jack, |
2304 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 2304 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | |
2305 | "max98095", codec); | 2305 | IRQF_ONESHOT, "max98095", codec); |
2306 | if (ret) { | 2306 | if (ret) { |
2307 | dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); | 2307 | dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); |
2308 | goto err_access; | 2308 | goto err_access; |
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index bf3e933ee895..3a2fda08a893 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c | |||
@@ -60,13 +60,12 @@ static int max98357a_codec_probe(struct snd_soc_codec *codec) | |||
60 | { | 60 | { |
61 | struct gpio_desc *sdmode; | 61 | struct gpio_desc *sdmode; |
62 | 62 | ||
63 | sdmode = devm_gpiod_get(codec->dev, "sdmode"); | 63 | sdmode = devm_gpiod_get(codec->dev, "sdmode", GPIOD_OUT_LOW); |
64 | if (IS_ERR(sdmode)) { | 64 | if (IS_ERR(sdmode)) { |
65 | dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", | 65 | dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", |
66 | __func__, PTR_ERR(sdmode)); | 66 | __func__, PTR_ERR(sdmode)); |
67 | return PTR_ERR(sdmode); | 67 | return PTR_ERR(sdmode); |
68 | } | 68 | } |
69 | gpiod_direction_output(sdmode, 0); | ||
70 | snd_soc_codec_set_drvdata(codec, sdmode); | 69 | snd_soc_codec_set_drvdata(codec, sdmode); |
71 | 70 | ||
72 | return 0; | 71 | return 0; |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 10f8e47ce2c2..481d58f1cb3f 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -252,7 +252,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec, | |||
252 | case SND_SOC_BIAS_PREPARE: | 252 | case SND_SOC_BIAS_PREPARE: |
253 | break; | 253 | break; |
254 | case SND_SOC_BIAS_STANDBY: | 254 | case SND_SOC_BIAS_STANDBY: |
255 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 255 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
256 | ret = regcache_sync(max9850->regmap); | 256 | ret = regcache_sync(max9850->regmap); |
257 | if (ret) { | 257 | if (ret) { |
258 | dev_err(codec->dev, | 258 | dev_err(codec->dev, |
@@ -264,7 +264,6 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec, | |||
264 | case SND_SOC_BIAS_OFF: | 264 | case SND_SOC_BIAS_OFF: |
265 | break; | 265 | break; |
266 | } | 266 | } |
267 | codec->dapm.bias_level = level; | ||
268 | return 0; | 267 | return 0; |
269 | } | 268 | } |
270 | 269 | ||
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index 9b5a17de4690..aad664225dc3 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c | |||
@@ -346,7 +346,7 @@ static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai, | |||
346 | } | 346 | } |
347 | 347 | ||
348 | regmap_update_bits(max98925->regmap, MAX98925_FORMAT, | 348 | regmap_update_bits(max98925->regmap, MAX98925_FORMAT, |
349 | M98925_DAI_BCI_MASK, invert); | 349 | M98925_DAI_BCI_MASK | M98925_DAI_WCI_MASK, invert); |
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 2ffb9a0570dc..3d44fc50e4d0 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -623,14 +623,14 @@ static int mc13783_probe(struct snd_soc_codec *codec) | |||
623 | AUDIO_SSI_SEL, 0); | 623 | AUDIO_SSI_SEL, 0); |
624 | else | 624 | else |
625 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC, | 625 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC, |
626 | 0, AUDIO_SSI_SEL); | 626 | AUDIO_SSI_SEL, AUDIO_SSI_SEL); |
627 | 627 | ||
628 | if (priv->dac_ssi_port == MC13783_SSI1_PORT) | 628 | if (priv->dac_ssi_port == MC13783_SSI1_PORT) |
629 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, | 629 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, |
630 | AUDIO_SSI_SEL, 0); | 630 | AUDIO_SSI_SEL, 0); |
631 | else | 631 | else |
632 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, | 632 | mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, |
633 | 0, AUDIO_SSI_SEL); | 633 | AUDIO_SSI_SEL, AUDIO_SSI_SEL); |
634 | 634 | ||
635 | return 0; | 635 | return 0; |
636 | } | 636 | } |
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 711f55039522..b74118e019fb 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -341,6 +341,7 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream, | |||
341 | struct snd_soc_codec *codec = dai->codec; | 341 | struct snd_soc_codec *codec = dai->codec; |
342 | struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); | 342 | struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); |
343 | int i = get_coeff(priv->mclk, params_rate(hw_params)); | 343 | int i = get_coeff(priv->mclk, params_rate(hw_params)); |
344 | int srate; | ||
344 | 345 | ||
345 | if (i < 0) | 346 | if (i < 0) |
346 | return i; | 347 | return i; |
@@ -370,53 +371,16 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream, | |||
370 | BIT(0) | BIT(1), 0); | 371 | BIT(0) | BIT(1), 0); |
371 | } | 372 | } |
372 | 373 | ||
373 | switch (params_rate(hw_params)) { | 374 | srate = get_srate(params_rate(hw_params)); |
374 | case 16000: | 375 | if (srate < 0) |
375 | snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, | 376 | return srate; |
376 | get_srate(params_rate(hw_params))); | 377 | |
377 | snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, | 378 | snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, srate); |
378 | coeff_div[i].pllnl); | 379 | snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, coeff_div[i].pllnl); |
379 | snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, | 380 | snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, coeff_div[i].pllnh); |
380 | coeff_div[i].pllnh); | 381 | snd_soc_update_bits(codec, ML26124_PLLML, 0xff, coeff_div[i].pllml); |
381 | snd_soc_update_bits(codec, ML26124_PLLML, 0xff, | 382 | snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, coeff_div[i].pllmh); |
382 | coeff_div[i].pllml); | 383 | snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, coeff_div[i].plldiv); |
383 | snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, | ||
384 | coeff_div[i].pllmh); | ||
385 | snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, | ||
386 | coeff_div[i].plldiv); | ||
387 | break; | ||
388 | case 32000: | ||
389 | snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, | ||
390 | get_srate(params_rate(hw_params))); | ||
391 | snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, | ||
392 | coeff_div[i].pllnl); | ||
393 | snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, | ||
394 | coeff_div[i].pllnh); | ||
395 | snd_soc_update_bits(codec, ML26124_PLLML, 0xff, | ||
396 | coeff_div[i].pllml); | ||
397 | snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, | ||
398 | coeff_div[i].pllmh); | ||
399 | snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, | ||
400 | coeff_div[i].plldiv); | ||
401 | break; | ||
402 | case 48000: | ||
403 | snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, | ||
404 | get_srate(params_rate(hw_params))); | ||
405 | snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, | ||
406 | coeff_div[i].pllnl); | ||
407 | snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, | ||
408 | coeff_div[i].pllnh); | ||
409 | snd_soc_update_bits(codec, ML26124_PLLML, 0xff, | ||
410 | coeff_div[i].pllml); | ||
411 | snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, | ||
412 | coeff_div[i].pllmh); | ||
413 | snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, | ||
414 | coeff_div[i].plldiv); | ||
415 | break; | ||
416 | default: | ||
417 | pr_err("%s:this rate is no support for ml26124\n", __func__); | ||
418 | return -EINVAL; | ||
419 | } | ||
420 | 384 | ||
421 | return 0; | 385 | return 0; |
422 | } | 386 | } |
@@ -523,7 +487,7 @@ static int ml26124_set_bias_level(struct snd_soc_codec *codec, | |||
523 | break; | 487 | break; |
524 | case SND_SOC_BIAS_STANDBY: | 488 | case SND_SOC_BIAS_STANDBY: |
525 | /* VMID ON */ | 489 | /* VMID ON */ |
526 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 490 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
527 | snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG, | 491 | snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG, |
528 | ML26124_VMID, ML26124_VMID); | 492 | ML26124_VMID, ML26124_VMID); |
529 | msleep(500); | 493 | msleep(500); |
@@ -536,7 +500,6 @@ static int ml26124_set_bias_level(struct snd_soc_codec *codec, | |||
536 | ML26124_VMID, 0); | 500 | ML26124_VMID, 0); |
537 | break; | 501 | break; |
538 | } | 502 | } |
539 | codec->dapm.bias_level = level; | ||
540 | return 0; | 503 | return 0; |
541 | } | 504 | } |
542 | 505 | ||
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 477e13d30971..e7ba557979cb 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c | |||
@@ -102,7 +102,7 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec) | |||
102 | 102 | ||
103 | if (val != -1) { | 103 | if (val != -1) { |
104 | regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, | 104 | regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, |
105 | PCM1681_DEEMPH_RATE_MASK, val); | 105 | PCM1681_DEEMPH_RATE_MASK, val << 3); |
106 | enable = 1; | 106 | enable = 1; |
107 | } else | 107 | } else |
108 | enable = 0; | 108 | enable = 0; |
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index e12764d15431..de16429f0a43 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c | |||
@@ -242,7 +242,7 @@ static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol, | |||
242 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 242 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
243 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | 243 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); |
244 | 244 | ||
245 | switch (codec->dapm.bias_level) { | 245 | switch (snd_soc_codec_get_bias_level(codec)) { |
246 | case SND_SOC_BIAS_OFF: | 246 | case SND_SOC_BIAS_OFF: |
247 | case SND_SOC_BIAS_STANDBY: | 247 | case SND_SOC_BIAS_STANDBY: |
248 | break; | 248 | break; |
@@ -270,7 +270,7 @@ static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol, | |||
270 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 270 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
271 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | 271 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); |
272 | 272 | ||
273 | switch (codec->dapm.bias_level) { | 273 | switch (snd_soc_codec_get_bias_level(codec)) { |
274 | case SND_SOC_BIAS_OFF: | 274 | case SND_SOC_BIAS_OFF: |
275 | case SND_SOC_BIAS_STANDBY: | 275 | case SND_SOC_BIAS_STANDBY: |
276 | break; | 276 | break; |
@@ -298,7 +298,7 @@ static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol, | |||
298 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 298 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
299 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | 299 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); |
300 | 300 | ||
301 | switch (codec->dapm.bias_level) { | 301 | switch (snd_soc_codec_get_bias_level(codec)) { |
302 | case SND_SOC_BIAS_OFF: | 302 | case SND_SOC_BIAS_OFF: |
303 | case SND_SOC_BIAS_STANDBY: | 303 | case SND_SOC_BIAS_STANDBY: |
304 | break; | 304 | break; |
@@ -641,8 +641,6 @@ static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | |||
641 | break; | 641 | break; |
642 | } | 642 | } |
643 | 643 | ||
644 | codec->dapm.bias_level = level; | ||
645 | |||
646 | return 0; | 644 | return 0; |
647 | } | 645 | } |
648 | 646 | ||
diff --git a/sound/soc/codecs/rl6347a.c b/sound/soc/codecs/rl6347a.c new file mode 100644 index 000000000000..91d5166bd3a1 --- /dev/null +++ b/sound/soc/codecs/rl6347a.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * rl6347a.c - RL6347A class device shared support | ||
3 | * | ||
4 | * Copyright 2015 Realtek Semiconductor Corp. | ||
5 | * | ||
6 | * Author: Oder Chiou <oder_chiou@realtek.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/spi/spi.h> | ||
21 | #include <linux/dmi.h> | ||
22 | #include <linux/acpi.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <sound/jack.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | #include <sound/hda_verbs.h> | ||
33 | |||
34 | #include "rl6347a.h" | ||
35 | |||
36 | int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value) | ||
37 | { | ||
38 | struct i2c_client *client = context; | ||
39 | struct rl6347a_priv *rl6347a = i2c_get_clientdata(client); | ||
40 | u8 data[4]; | ||
41 | int ret, i; | ||
42 | |||
43 | /* handle index registers */ | ||
44 | if (reg <= 0xff) { | ||
45 | rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg); | ||
46 | for (i = 0; i < rl6347a->index_cache_size; i++) { | ||
47 | if (reg == rl6347a->index_cache[i].reg) { | ||
48 | rl6347a->index_cache[i].def = value; | ||
49 | break; | ||
50 | } | ||
51 | |||
52 | } | ||
53 | reg = RL6347A_PROC_COEF; | ||
54 | } | ||
55 | |||
56 | data[0] = (reg >> 24) & 0xff; | ||
57 | data[1] = (reg >> 16) & 0xff; | ||
58 | /* | ||
59 | * 4 bit VID: reg should be 0 | ||
60 | * 12 bit VID: value should be 0 | ||
61 | * So we use an OR operator to handle it rather than use if condition. | ||
62 | */ | ||
63 | data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); | ||
64 | data[3] = value & 0xff; | ||
65 | |||
66 | ret = i2c_master_send(client, data, 4); | ||
67 | |||
68 | if (ret == 4) | ||
69 | return 0; | ||
70 | else | ||
71 | pr_err("ret=%d\n", ret); | ||
72 | if (ret < 0) | ||
73 | return ret; | ||
74 | else | ||
75 | return -EIO; | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(rl6347a_hw_write); | ||
78 | |||
79 | int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value) | ||
80 | { | ||
81 | struct i2c_client *client = context; | ||
82 | struct i2c_msg xfer[2]; | ||
83 | int ret; | ||
84 | __be32 be_reg; | ||
85 | unsigned int index, vid, buf = 0x0; | ||
86 | |||
87 | /* handle index registers */ | ||
88 | if (reg <= 0xff) { | ||
89 | rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg); | ||
90 | reg = RL6347A_PROC_COEF; | ||
91 | } | ||
92 | |||
93 | reg = reg | 0x80000; | ||
94 | vid = (reg >> 8) & 0xfff; | ||
95 | |||
96 | if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { | ||
97 | index = (reg >> 8) & 0xf; | ||
98 | reg = (reg & ~0xf0f) | index; | ||
99 | } | ||
100 | be_reg = cpu_to_be32(reg); | ||
101 | |||
102 | /* Write register */ | ||
103 | xfer[0].addr = client->addr; | ||
104 | xfer[0].flags = 0; | ||
105 | xfer[0].len = 4; | ||
106 | xfer[0].buf = (u8 *)&be_reg; | ||
107 | |||
108 | /* Read data */ | ||
109 | xfer[1].addr = client->addr; | ||
110 | xfer[1].flags = I2C_M_RD; | ||
111 | xfer[1].len = 4; | ||
112 | xfer[1].buf = (u8 *)&buf; | ||
113 | |||
114 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | else if (ret != 2) | ||
118 | return -EIO; | ||
119 | |||
120 | *value = be32_to_cpu(buf); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(rl6347a_hw_read); | ||
125 | |||
126 | MODULE_DESCRIPTION("RL6347A class device shared support"); | ||
127 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | ||
128 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/rl6347a.h b/sound/soc/codecs/rl6347a.h new file mode 100644 index 000000000000..1cb56e50b7f3 --- /dev/null +++ b/sound/soc/codecs/rl6347a.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * rl6347a.h - RL6347A class device shared support | ||
3 | * | ||
4 | * Copyright 2015 Realtek Semiconductor Corp. | ||
5 | * | ||
6 | * Author: Oder Chiou <oder_chiou@realtek.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __RL6347A_H__ | ||
13 | #define __RL6347A_H__ | ||
14 | |||
15 | #define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) | ||
16 | |||
17 | #define RL6347A_VENDOR_REGISTERS 0x20 | ||
18 | |||
19 | #define RL6347A_COEF_INDEX\ | ||
20 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RL6347A_VENDOR_REGISTERS, 0) | ||
21 | #define RL6347A_PROC_COEF\ | ||
22 | VERB_CMD(AC_VERB_SET_PROC_COEF, RL6347A_VENDOR_REGISTERS, 0) | ||
23 | |||
24 | struct rl6347a_priv { | ||
25 | struct reg_default *index_cache; | ||
26 | int index_cache_size; | ||
27 | }; | ||
28 | |||
29 | int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value); | ||
30 | int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value); | ||
31 | |||
32 | #endif /* __RL6347A_H__ */ | ||
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 0fcda35a3a93..5c43e263b2c1 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -31,12 +31,15 @@ | |||
31 | #include <sound/rt286.h> | 31 | #include <sound/rt286.h> |
32 | #include <sound/hda_verbs.h> | 32 | #include <sound/hda_verbs.h> |
33 | 33 | ||
34 | #include "rl6347a.h" | ||
34 | #include "rt286.h" | 35 | #include "rt286.h" |
35 | 36 | ||
36 | #define RT286_VENDOR_ID 0x10ec0286 | 37 | #define RT286_VENDOR_ID 0x10ec0286 |
37 | #define RT288_VENDOR_ID 0x10ec0288 | 38 | #define RT288_VENDOR_ID 0x10ec0288 |
38 | 39 | ||
39 | struct rt286_priv { | 40 | struct rt286_priv { |
41 | struct reg_default *index_cache; | ||
42 | int index_cache_size; | ||
40 | struct regmap *regmap; | 43 | struct regmap *regmap; |
41 | struct snd_soc_codec *codec; | 44 | struct snd_soc_codec *codec; |
42 | struct rt286_platform_data pdata; | 45 | struct rt286_platform_data pdata; |
@@ -45,7 +48,6 @@ struct rt286_priv { | |||
45 | struct delayed_work jack_detect_work; | 48 | struct delayed_work jack_detect_work; |
46 | int sys_clk; | 49 | int sys_clk; |
47 | int clk_id; | 50 | int clk_id; |
48 | struct reg_default *index_cache; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static struct reg_default rt286_index_def[] = { | 53 | static struct reg_default rt286_index_def[] = { |
@@ -185,94 +187,6 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg) | |||
185 | } | 187 | } |
186 | } | 188 | } |
187 | 189 | ||
188 | static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) | ||
189 | { | ||
190 | struct i2c_client *client = context; | ||
191 | struct rt286_priv *rt286 = i2c_get_clientdata(client); | ||
192 | u8 data[4]; | ||
193 | int ret, i; | ||
194 | |||
195 | /* handle index registers */ | ||
196 | if (reg <= 0xff) { | ||
197 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
198 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
199 | if (reg == rt286->index_cache[i].reg) { | ||
200 | rt286->index_cache[i].def = value; | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | } | ||
205 | reg = RT286_PROC_COEF; | ||
206 | } | ||
207 | |||
208 | data[0] = (reg >> 24) & 0xff; | ||
209 | data[1] = (reg >> 16) & 0xff; | ||
210 | /* | ||
211 | * 4 bit VID: reg should be 0 | ||
212 | * 12 bit VID: value should be 0 | ||
213 | * So we use an OR operator to handle it rather than use if condition. | ||
214 | */ | ||
215 | data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); | ||
216 | data[3] = value & 0xff; | ||
217 | |||
218 | ret = i2c_master_send(client, data, 4); | ||
219 | |||
220 | if (ret == 4) | ||
221 | return 0; | ||
222 | else | ||
223 | pr_err("ret=%d\n", ret); | ||
224 | if (ret < 0) | ||
225 | return ret; | ||
226 | else | ||
227 | return -EIO; | ||
228 | } | ||
229 | |||
230 | static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | ||
231 | { | ||
232 | struct i2c_client *client = context; | ||
233 | struct i2c_msg xfer[2]; | ||
234 | int ret; | ||
235 | __be32 be_reg; | ||
236 | unsigned int index, vid, buf = 0x0; | ||
237 | |||
238 | /* handle index registers */ | ||
239 | if (reg <= 0xff) { | ||
240 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
241 | reg = RT286_PROC_COEF; | ||
242 | } | ||
243 | |||
244 | reg = reg | 0x80000; | ||
245 | vid = (reg >> 8) & 0xfff; | ||
246 | |||
247 | if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { | ||
248 | index = (reg >> 8) & 0xf; | ||
249 | reg = (reg & ~0xf0f) | index; | ||
250 | } | ||
251 | be_reg = cpu_to_be32(reg); | ||
252 | |||
253 | /* Write register */ | ||
254 | xfer[0].addr = client->addr; | ||
255 | xfer[0].flags = 0; | ||
256 | xfer[0].len = 4; | ||
257 | xfer[0].buf = (u8 *)&be_reg; | ||
258 | |||
259 | /* Read data */ | ||
260 | xfer[1].addr = client->addr; | ||
261 | xfer[1].flags = I2C_M_RD; | ||
262 | xfer[1].len = 4; | ||
263 | xfer[1].buf = (u8 *)&buf; | ||
264 | |||
265 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
266 | if (ret < 0) | ||
267 | return ret; | ||
268 | else if (ret != 2) | ||
269 | return -EIO; | ||
270 | |||
271 | *value = be32_to_cpu(buf); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | #ifdef CONFIG_PM | 190 | #ifdef CONFIG_PM |
277 | static void rt286_index_sync(struct snd_soc_codec *codec) | 191 | static void rt286_index_sync(struct snd_soc_codec *codec) |
278 | { | 192 | { |
@@ -301,6 +215,7 @@ static int rt286_support_power_controls[] = { | |||
301 | 215 | ||
302 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | 216 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) |
303 | { | 217 | { |
218 | struct snd_soc_dapm_context *dapm; | ||
304 | unsigned int val, buf; | 219 | unsigned int val, buf; |
305 | 220 | ||
306 | *hp = false; | 221 | *hp = false; |
@@ -308,6 +223,9 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
308 | 223 | ||
309 | if (!rt286->codec) | 224 | if (!rt286->codec) |
310 | return -EINVAL; | 225 | return -EINVAL; |
226 | |||
227 | dapm = snd_soc_codec_get_dapm(rt286->codec); | ||
228 | |||
311 | if (rt286->pdata.cbj_en) { | 229 | if (rt286->pdata.cbj_en) { |
312 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 230 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
313 | *hp = buf & 0x80000000; | 231 | *hp = buf & 0x80000000; |
@@ -316,14 +234,11 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
316 | regmap_update_bits(rt286->regmap, | 234 | regmap_update_bits(rt286->regmap, |
317 | RT286_DC_GAIN, 0x200, 0x200); | 235 | RT286_DC_GAIN, 0x200, 0x200); |
318 | 236 | ||
319 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | 237 | snd_soc_dapm_force_enable_pin(dapm, "HV"); |
320 | "HV"); | 238 | snd_soc_dapm_force_enable_pin(dapm, "VREF"); |
321 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
322 | "VREF"); | ||
323 | /* power LDO1 */ | 239 | /* power LDO1 */ |
324 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | 240 | snd_soc_dapm_force_enable_pin(dapm, "LDO1"); |
325 | "LDO1"); | 241 | snd_soc_dapm_sync(dapm); |
326 | snd_soc_dapm_sync(&rt286->codec->dapm); | ||
327 | 242 | ||
328 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | 243 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); |
329 | msleep(50); | 244 | msleep(50); |
@@ -360,11 +275,11 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
360 | *mic = buf & 0x80000000; | 275 | *mic = buf & 0x80000000; |
361 | } | 276 | } |
362 | 277 | ||
363 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "HV"); | 278 | snd_soc_dapm_disable_pin(dapm, "HV"); |
364 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "VREF"); | 279 | snd_soc_dapm_disable_pin(dapm, "VREF"); |
365 | if (!*hp) | 280 | if (!*hp) |
366 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "LDO1"); | 281 | snd_soc_dapm_disable_pin(dapm, "LDO1"); |
367 | snd_soc_dapm_sync(&rt286->codec->dapm); | 282 | snd_soc_dapm_sync(dapm); |
368 | 283 | ||
369 | return 0; | 284 | return 0; |
370 | } | 285 | } |
@@ -391,6 +306,7 @@ static void rt286_jack_detect_work(struct work_struct *work) | |||
391 | 306 | ||
392 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | 307 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) |
393 | { | 308 | { |
309 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
394 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | 310 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); |
395 | 311 | ||
396 | rt286->jack = jack; | 312 | rt286->jack = jack; |
@@ -398,7 +314,7 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
398 | if (jack) { | 314 | if (jack) { |
399 | /* enable IRQ */ | 315 | /* enable IRQ */ |
400 | if (rt286->jack->status & SND_JACK_HEADPHONE) | 316 | if (rt286->jack->status & SND_JACK_HEADPHONE) |
401 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO1"); | 317 | snd_soc_dapm_force_enable_pin(dapm, "LDO1"); |
402 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2); | 318 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2); |
403 | /* Send an initial empty report */ | 319 | /* Send an initial empty report */ |
404 | snd_soc_jack_report(rt286->jack, rt286->jack->status, | 320 | snd_soc_jack_report(rt286->jack, rt286->jack->status, |
@@ -406,9 +322,9 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
406 | } else { | 322 | } else { |
407 | /* disable IRQ */ | 323 | /* disable IRQ */ |
408 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0); | 324 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0); |
409 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO1"); | 325 | snd_soc_dapm_disable_pin(dapm, "LDO1"); |
410 | } | 326 | } |
411 | snd_soc_dapm_sync(&codec->dapm); | 327 | snd_soc_dapm_sync(dapm); |
412 | 328 | ||
413 | return 0; | 329 | return 0; |
414 | } | 330 | } |
@@ -985,7 +901,7 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, | |||
985 | { | 901 | { |
986 | switch (level) { | 902 | switch (level) { |
987 | case SND_SOC_BIAS_PREPARE: | 903 | case SND_SOC_BIAS_PREPARE: |
988 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 904 | if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) { |
989 | snd_soc_write(codec, | 905 | snd_soc_write(codec, |
990 | RT286_SET_AUDIO_POWER, AC_PWRST_D0); | 906 | RT286_SET_AUDIO_POWER, AC_PWRST_D0); |
991 | snd_soc_update_bits(codec, | 907 | snd_soc_update_bits(codec, |
@@ -1012,7 +928,6 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, | |||
1012 | default: | 928 | default: |
1013 | break; | 929 | break; |
1014 | } | 930 | } |
1015 | codec->dapm.bias_level = level; | ||
1016 | 931 | ||
1017 | return 0; | 932 | return 0; |
1018 | } | 933 | } |
@@ -1173,8 +1088,8 @@ static const struct regmap_config rt286_regmap = { | |||
1173 | .max_register = 0x02370100, | 1088 | .max_register = 0x02370100, |
1174 | .volatile_reg = rt286_volatile_register, | 1089 | .volatile_reg = rt286_volatile_register, |
1175 | .readable_reg = rt286_readable_register, | 1090 | .readable_reg = rt286_readable_register, |
1176 | .reg_write = rt286_hw_write, | 1091 | .reg_write = rl6347a_hw_write, |
1177 | .reg_read = rt286_hw_read, | 1092 | .reg_read = rl6347a_hw_read, |
1178 | .cache_type = REGCACHE_RBTREE, | 1093 | .cache_type = REGCACHE_RBTREE, |
1179 | .reg_defaults = rt286_reg, | 1094 | .reg_defaults = rt286_reg, |
1180 | .num_reg_defaults = ARRAY_SIZE(rt286_reg), | 1095 | .num_reg_defaults = ARRAY_SIZE(rt286_reg), |
@@ -1247,6 +1162,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1247 | } | 1162 | } |
1248 | 1163 | ||
1249 | rt286->index_cache = rt286_index_def; | 1164 | rt286->index_cache = rt286_index_def; |
1165 | rt286->index_cache_size = INDEX_CACHE_SIZE; | ||
1250 | rt286->i2c = i2c; | 1166 | rt286->i2c = i2c; |
1251 | i2c_set_clientdata(i2c, rt286); | 1167 | i2c_set_clientdata(i2c, rt286); |
1252 | 1168 | ||
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 2c10d77727af..058167c80d71 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -1546,7 +1546,7 @@ static int rt5631_set_bias_level(struct snd_soc_codec *codec, | |||
1546 | break; | 1546 | break; |
1547 | 1547 | ||
1548 | case SND_SOC_BIAS_STANDBY: | 1548 | case SND_SOC_BIAS_STANDBY: |
1549 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1549 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1550 | snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, | 1550 | snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, |
1551 | RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, | 1551 | RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, |
1552 | RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); | 1552 | RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); |
@@ -1569,7 +1569,6 @@ static int rt5631_set_bias_level(struct snd_soc_codec *codec, | |||
1569 | default: | 1569 | default: |
1570 | break; | 1570 | break; |
1571 | } | 1571 | } |
1572 | codec->dapm.bias_level = level; | ||
1573 | 1572 | ||
1574 | return 0; | 1573 | return 0; |
1575 | } | 1574 | } |
@@ -1615,7 +1614,7 @@ static int rt5631_probe(struct snd_soc_codec *codec) | |||
1615 | RT5631_DMIC_R_CH_LATCH_RISING); | 1614 | RT5631_DMIC_R_CH_LATCH_RISING); |
1616 | } | 1615 | } |
1617 | 1616 | ||
1618 | codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; | 1617 | snd_soc_codec_init_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1619 | 1618 | ||
1620 | return 0; | 1619 | return 0; |
1621 | } | 1620 | } |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 178e55d4d481..9bc78e57513d 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = { | |||
51 | .window_len = 0x1, }, | 51 | .window_len = 0x1, }, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct reg_default init_list[] = { | 54 | static const struct reg_default init_list[] = { |
55 | {RT5640_PR_BASE + 0x3d, 0x3600}, | 55 | {RT5640_PR_BASE + 0x3d, 0x3600}, |
56 | {RT5640_PR_BASE + 0x12, 0x0aa8}, | 56 | {RT5640_PR_BASE + 0x12, 0x0aa8}, |
57 | {RT5640_PR_BASE + 0x14, 0x0aaa}, | 57 | {RT5640_PR_BASE + 0x14, 0x0aaa}, |
@@ -59,7 +59,6 @@ static struct reg_default init_list[] = { | |||
59 | {RT5640_PR_BASE + 0x21, 0xe0e0}, | 59 | {RT5640_PR_BASE + 0x21, 0xe0e0}, |
60 | {RT5640_PR_BASE + 0x23, 0x1804}, | 60 | {RT5640_PR_BASE + 0x23, 0x1804}, |
61 | }; | 61 | }; |
62 | #define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list) | ||
63 | 62 | ||
64 | static const struct reg_default rt5640_reg[] = { | 63 | static const struct reg_default rt5640_reg[] = { |
65 | { 0x00, 0x000e }, | 64 | { 0x00, 0x000e }, |
@@ -1870,7 +1869,7 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, | |||
1870 | { | 1869 | { |
1871 | switch (level) { | 1870 | switch (level) { |
1872 | case SND_SOC_BIAS_STANDBY: | 1871 | case SND_SOC_BIAS_STANDBY: |
1873 | if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) { | 1872 | if (SND_SOC_BIAS_OFF == snd_soc_codec_get_bias_level(codec)) { |
1874 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, | 1873 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, |
1875 | RT5640_PWR_VREF1 | RT5640_PWR_MB | | 1874 | RT5640_PWR_VREF1 | RT5640_PWR_MB | |
1876 | RT5640_PWR_BG | RT5640_PWR_VREF2, | 1875 | RT5640_PWR_BG | RT5640_PWR_VREF2, |
@@ -1902,7 +1901,6 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, | |||
1902 | default: | 1901 | default: |
1903 | break; | 1902 | break; |
1904 | } | 1903 | } |
1905 | codec->dapm.bias_level = level; | ||
1906 | 1904 | ||
1907 | return 0; | 1905 | return 0; |
1908 | } | 1906 | } |
@@ -1935,11 +1933,12 @@ EXPORT_SYMBOL_GPL(rt5640_dmic_enable); | |||
1935 | 1933 | ||
1936 | static int rt5640_probe(struct snd_soc_codec *codec) | 1934 | static int rt5640_probe(struct snd_soc_codec *codec) |
1937 | { | 1935 | { |
1936 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1938 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1937 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
1939 | 1938 | ||
1940 | rt5640->codec = codec; | 1939 | rt5640->codec = codec; |
1941 | 1940 | ||
1942 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1941 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
1943 | 1942 | ||
1944 | snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301); | 1943 | snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301); |
1945 | snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030); | 1944 | snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030); |
@@ -1951,18 +1950,18 @@ static int rt5640_probe(struct snd_soc_codec *codec) | |||
1951 | snd_soc_add_codec_controls(codec, | 1950 | snd_soc_add_codec_controls(codec, |
1952 | rt5640_specific_snd_controls, | 1951 | rt5640_specific_snd_controls, |
1953 | ARRAY_SIZE(rt5640_specific_snd_controls)); | 1952 | ARRAY_SIZE(rt5640_specific_snd_controls)); |
1954 | snd_soc_dapm_new_controls(&codec->dapm, | 1953 | snd_soc_dapm_new_controls(dapm, |
1955 | rt5640_specific_dapm_widgets, | 1954 | rt5640_specific_dapm_widgets, |
1956 | ARRAY_SIZE(rt5640_specific_dapm_widgets)); | 1955 | ARRAY_SIZE(rt5640_specific_dapm_widgets)); |
1957 | snd_soc_dapm_add_routes(&codec->dapm, | 1956 | snd_soc_dapm_add_routes(dapm, |
1958 | rt5640_specific_dapm_routes, | 1957 | rt5640_specific_dapm_routes, |
1959 | ARRAY_SIZE(rt5640_specific_dapm_routes)); | 1958 | ARRAY_SIZE(rt5640_specific_dapm_routes)); |
1960 | break; | 1959 | break; |
1961 | case RT5640_ID_5639: | 1960 | case RT5640_ID_5639: |
1962 | snd_soc_dapm_new_controls(&codec->dapm, | 1961 | snd_soc_dapm_new_controls(dapm, |
1963 | rt5639_specific_dapm_widgets, | 1962 | rt5639_specific_dapm_widgets, |
1964 | ARRAY_SIZE(rt5639_specific_dapm_widgets)); | 1963 | ARRAY_SIZE(rt5639_specific_dapm_widgets)); |
1965 | snd_soc_dapm_add_routes(&codec->dapm, | 1964 | snd_soc_dapm_add_routes(dapm, |
1966 | rt5639_specific_dapm_routes, | 1965 | rt5639_specific_dapm_routes, |
1967 | ARRAY_SIZE(rt5639_specific_dapm_routes)); | 1966 | ARRAY_SIZE(rt5639_specific_dapm_routes)); |
1968 | break; | 1967 | break; |
@@ -1991,7 +1990,7 @@ static int rt5640_suspend(struct snd_soc_codec *codec) | |||
1991 | { | 1990 | { |
1992 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1991 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
1993 | 1992 | ||
1994 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1993 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
1995 | rt5640_reset(codec); | 1994 | rt5640_reset(codec); |
1996 | regcache_cache_only(rt5640->regmap, true); | 1995 | regcache_cache_only(rt5640->regmap, true); |
1997 | regcache_mark_dirty(rt5640->regmap); | 1996 | regcache_mark_dirty(rt5640->regmap); |
@@ -2122,7 +2121,7 @@ MODULE_DEVICE_TABLE(of, rt5640_of_match); | |||
2122 | #endif | 2121 | #endif |
2123 | 2122 | ||
2124 | #ifdef CONFIG_ACPI | 2123 | #ifdef CONFIG_ACPI |
2125 | static struct acpi_device_id rt5640_acpi_match[] = { | 2124 | static const struct acpi_device_id rt5640_acpi_match[] = { |
2126 | { "INT33CA", 0 }, | 2125 | { "INT33CA", 0 }, |
2127 | { "10EC5640", 0 }, | 2126 | { "10EC5640", 0 }, |
2128 | { "10EC5642", 0 }, | 2127 | { "10EC5642", 0 }, |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 69528ae5410c..e9cc3aae5366 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
21 | #include <linux/gpio/consumer.h> | ||
22 | #include <linux/acpi.h> | ||
23 | #include <linux/dmi.h> | ||
21 | #include <sound/core.h> | 24 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -346,6 +349,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
346 | case RT5645_TDM_CTRL_1: | 349 | case RT5645_TDM_CTRL_1: |
347 | case RT5645_TDM_CTRL_2: | 350 | case RT5645_TDM_CTRL_2: |
348 | case RT5645_TDM_CTRL_3: | 351 | case RT5645_TDM_CTRL_3: |
352 | case RT5650_TDM_CTRL_4: | ||
349 | case RT5645_GLB_CLK: | 353 | case RT5645_GLB_CLK: |
350 | case RT5645_PLL_CTRL1: | 354 | case RT5645_PLL_CTRL1: |
351 | case RT5645_PLL_CTRL2: | 355 | case RT5645_PLL_CTRL2: |
@@ -414,9 +418,9 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
414 | } | 418 | } |
415 | 419 | ||
416 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | 420 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); |
417 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | 421 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); |
418 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | 422 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); |
419 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | 423 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); |
420 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 424 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
421 | 425 | ||
422 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 426 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
@@ -431,30 +435,6 @@ static unsigned int bst_tlv[] = { | |||
431 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 435 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), |
432 | }; | 436 | }; |
433 | 437 | ||
434 | static const char * const rt5645_tdm_data_swap_select[] = { | ||
435 | "L/R", "R/L", "L/L", "R/R" | ||
436 | }; | ||
437 | |||
438 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum, | ||
439 | RT5645_TDM_CTRL_1, 6, rt5645_tdm_data_swap_select); | ||
440 | |||
441 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum, | ||
442 | RT5645_TDM_CTRL_1, 4, rt5645_tdm_data_swap_select); | ||
443 | |||
444 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum, | ||
445 | RT5645_TDM_CTRL_1, 2, rt5645_tdm_data_swap_select); | ||
446 | |||
447 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot6_7_enum, | ||
448 | RT5645_TDM_CTRL_1, 0, rt5645_tdm_data_swap_select); | ||
449 | |||
450 | static const char * const rt5645_tdm_adc_data_select[] = { | ||
451 | "1/2/R", "2/1/R", "R/1/2", "R/2/1" | ||
452 | }; | ||
453 | |||
454 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum, | ||
455 | RT5645_TDM_CTRL_1, 8, | ||
456 | rt5645_tdm_adc_data_select); | ||
457 | |||
458 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { | 438 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { |
459 | /* Speaker Output Volume */ | 439 | /* Speaker Output Volume */ |
460 | SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, | 440 | SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, |
@@ -463,9 +443,9 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { | |||
463 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv), | 443 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv), |
464 | 444 | ||
465 | /* Headphone Output Volume */ | 445 | /* Headphone Output Volume */ |
466 | SOC_DOUBLE("HP Channel Switch", RT5645_HP_VOL, | 446 | SOC_DOUBLE("Headphone Channel Switch", RT5645_HP_VOL, |
467 | RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1), | 447 | RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1), |
468 | SOC_DOUBLE_TLV("HP Playback Volume", RT5645_HP_VOL, | 448 | SOC_DOUBLE_TLV("Headphone Playback Volume", RT5645_HP_VOL, |
469 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv), | 449 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv), |
470 | 450 | ||
471 | /* OUTPUT Control */ | 451 | /* OUTPUT Control */ |
@@ -480,9 +460,9 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { | |||
480 | SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL, | 460 | SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL, |
481 | RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1), | 461 | RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1), |
482 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL, | 462 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL, |
483 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv), | 463 | RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 87, 0, dac_vol_tlv), |
484 | SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5645_DAC2_DIG_VOL, | 464 | SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5645_DAC2_DIG_VOL, |
485 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv), | 465 | RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 87, 0, dac_vol_tlv), |
486 | 466 | ||
487 | /* IN1/IN2 Control */ | 467 | /* IN1/IN2 Control */ |
488 | SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1, | 468 | SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1, |
@@ -498,11 +478,11 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { | |||
498 | SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL, | 478 | SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL, |
499 | RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), | 479 | RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), |
500 | SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL, | 480 | SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL, |
501 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv), | 481 | RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv), |
502 | SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL, | 482 | SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL, |
503 | RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), | 483 | RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), |
504 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL, | 484 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL, |
505 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv), | 485 | RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv), |
506 | 486 | ||
507 | /* ADC Boost Volume Control */ | 487 | /* ADC Boost Volume Control */ |
508 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1, | 488 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1, |
@@ -515,17 +495,6 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { | |||
515 | /* I2S2 function select */ | 495 | /* I2S2 function select */ |
516 | SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT, | 496 | SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT, |
517 | 1, 1), | 497 | 1, 1), |
518 | |||
519 | /* TDM */ | ||
520 | SOC_ENUM("TDM Adc Slot0 1 Data", rt5645_tdm_adc_slot0_1_enum), | ||
521 | SOC_ENUM("TDM Adc Slot2 3 Data", rt5645_tdm_adc_slot2_3_enum), | ||
522 | SOC_ENUM("TDM Adc Slot4 5 Data", rt5645_tdm_adc_slot4_5_enum), | ||
523 | SOC_ENUM("TDM Adc Slot6 7 Data", rt5645_tdm_adc_slot6_7_enum), | ||
524 | SOC_ENUM("TDM IF1 ADC DATA Sel", rt5645_tdm_adc_sel_enum), | ||
525 | SOC_SINGLE("TDM IF1_DAC1_L Sel", RT5645_TDM_CTRL_3, 12, 7, 0), | ||
526 | SOC_SINGLE("TDM IF1_DAC1_R Sel", RT5645_TDM_CTRL_3, 8, 7, 0), | ||
527 | SOC_SINGLE("TDM IF1_DAC2_L Sel", RT5645_TDM_CTRL_3, 4, 7, 0), | ||
528 | SOC_SINGLE("TDM IF1_DAC2_R Sel", RT5645_TDM_CTRL_3, 0, 7, 0), | ||
529 | }; | 498 | }; |
530 | 499 | ||
531 | /** | 500 | /** |
@@ -1092,7 +1061,8 @@ static const struct snd_kcontrol_new rt5645_mono_adc_r2_mux = | |||
1092 | 1061 | ||
1093 | /* MX-77 [9:8] */ | 1062 | /* MX-77 [9:8] */ |
1094 | static const char * const rt5645_if1_adc_in_src[] = { | 1063 | static const char * const rt5645_if1_adc_in_src[] = { |
1095 | "IF_ADC1", "IF_ADC2", "VAD_ADC" | 1064 | "IF_ADC1/IF_ADC2/VAD_ADC", "IF_ADC2/IF_ADC1/VAD_ADC", |
1065 | "VAD_ADC/IF_ADC1/IF_ADC2", "VAD_ADC/IF_ADC2/IF_ADC1" | ||
1096 | }; | 1066 | }; |
1097 | 1067 | ||
1098 | static SOC_ENUM_SINGLE_DECL( | 1068 | static SOC_ENUM_SINGLE_DECL( |
@@ -1102,6 +1072,140 @@ static SOC_ENUM_SINGLE_DECL( | |||
1102 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = | 1072 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = |
1103 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); | 1073 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); |
1104 | 1074 | ||
1075 | /* MX-78 [4:0] */ | ||
1076 | static const char * const rt5650_if1_adc_in_src[] = { | ||
1077 | "IF_ADC1/IF_ADC2/DAC_REF/Null", | ||
1078 | "IF_ADC1/IF_ADC2/Null/DAC_REF", | ||
1079 | "IF_ADC1/DAC_REF/IF_ADC2/Null", | ||
1080 | "IF_ADC1/DAC_REF/Null/IF_ADC2", | ||
1081 | "IF_ADC1/Null/DAC_REF/IF_ADC2", | ||
1082 | "IF_ADC1/Null/IF_ADC2/DAC_REF", | ||
1083 | |||
1084 | "IF_ADC2/IF_ADC1/DAC_REF/Null", | ||
1085 | "IF_ADC2/IF_ADC1/Null/DAC_REF", | ||
1086 | "IF_ADC2/DAC_REF/IF_ADC1/Null", | ||
1087 | "IF_ADC2/DAC_REF/Null/IF_ADC1", | ||
1088 | "IF_ADC2/Null/DAC_REF/IF_ADC1", | ||
1089 | "IF_ADC2/Null/IF_ADC1/DAC_REF", | ||
1090 | |||
1091 | "DAC_REF/IF_ADC1/IF_ADC2/Null", | ||
1092 | "DAC_REF/IF_ADC1/Null/IF_ADC2", | ||
1093 | "DAC_REF/IF_ADC2/IF_ADC1/Null", | ||
1094 | "DAC_REF/IF_ADC2/Null/IF_ADC1", | ||
1095 | "DAC_REF/Null/IF_ADC1/IF_ADC2", | ||
1096 | "DAC_REF/Null/IF_ADC2/IF_ADC1", | ||
1097 | |||
1098 | "Null/IF_ADC1/IF_ADC2/DAC_REF", | ||
1099 | "Null/IF_ADC1/DAC_REF/IF_ADC2", | ||
1100 | "Null/IF_ADC2/IF_ADC1/DAC_REF", | ||
1101 | "Null/IF_ADC2/DAC_REF/IF_ADC1", | ||
1102 | "Null/DAC_REF/IF_ADC1/IF_ADC2", | ||
1103 | "Null/DAC_REF/IF_ADC2/IF_ADC1", | ||
1104 | }; | ||
1105 | |||
1106 | static SOC_ENUM_SINGLE_DECL( | ||
1107 | rt5650_if1_adc_in_enum, RT5645_TDM_CTRL_2, | ||
1108 | 0, rt5650_if1_adc_in_src); | ||
1109 | |||
1110 | static const struct snd_kcontrol_new rt5650_if1_adc_in_mux = | ||
1111 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5650_if1_adc_in_enum); | ||
1112 | |||
1113 | /* MX-78 [15:14][13:12][11:10] */ | ||
1114 | static const char * const rt5645_tdm_adc_swap_select[] = { | ||
1115 | "L/R", "R/L", "L/L", "R/R" | ||
1116 | }; | ||
1117 | |||
1118 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot0_1_enum, | ||
1119 | RT5645_TDM_CTRL_2, 14, rt5645_tdm_adc_swap_select); | ||
1120 | |||
1121 | static const struct snd_kcontrol_new rt5650_if1_adc1_in_mux = | ||
1122 | SOC_DAPM_ENUM("IF1 ADC1 IN source", rt5650_tdm_adc_slot0_1_enum); | ||
1123 | |||
1124 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot2_3_enum, | ||
1125 | RT5645_TDM_CTRL_2, 12, rt5645_tdm_adc_swap_select); | ||
1126 | |||
1127 | static const struct snd_kcontrol_new rt5650_if1_adc2_in_mux = | ||
1128 | SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5650_tdm_adc_slot2_3_enum); | ||
1129 | |||
1130 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot4_5_enum, | ||
1131 | RT5645_TDM_CTRL_2, 10, rt5645_tdm_adc_swap_select); | ||
1132 | |||
1133 | static const struct snd_kcontrol_new rt5650_if1_adc3_in_mux = | ||
1134 | SOC_DAPM_ENUM("IF1 ADC3 IN source", rt5650_tdm_adc_slot4_5_enum); | ||
1135 | |||
1136 | /* MX-77 [7:6][5:4][3:2] */ | ||
1137 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum, | ||
1138 | RT5645_TDM_CTRL_1, 6, rt5645_tdm_adc_swap_select); | ||
1139 | |||
1140 | static const struct snd_kcontrol_new rt5645_if1_adc1_in_mux = | ||
1141 | SOC_DAPM_ENUM("IF1 ADC1 IN source", rt5645_tdm_adc_slot0_1_enum); | ||
1142 | |||
1143 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum, | ||
1144 | RT5645_TDM_CTRL_1, 4, rt5645_tdm_adc_swap_select); | ||
1145 | |||
1146 | static const struct snd_kcontrol_new rt5645_if1_adc2_in_mux = | ||
1147 | SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5645_tdm_adc_slot2_3_enum); | ||
1148 | |||
1149 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum, | ||
1150 | RT5645_TDM_CTRL_1, 2, rt5645_tdm_adc_swap_select); | ||
1151 | |||
1152 | static const struct snd_kcontrol_new rt5645_if1_adc3_in_mux = | ||
1153 | SOC_DAPM_ENUM("IF1 ADC3 IN source", rt5645_tdm_adc_slot4_5_enum); | ||
1154 | |||
1155 | /* MX-79 [14:12][10:8][6:4][2:0] */ | ||
1156 | static const char * const rt5645_tdm_dac_swap_select[] = { | ||
1157 | "Slot0", "Slot1", "Slot2", "Slot3" | ||
1158 | }; | ||
1159 | |||
1160 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac0_enum, | ||
1161 | RT5645_TDM_CTRL_3, 12, rt5645_tdm_dac_swap_select); | ||
1162 | |||
1163 | static const struct snd_kcontrol_new rt5645_if1_dac0_tdm_sel_mux = | ||
1164 | SOC_DAPM_ENUM("IF1 DAC0 source", rt5645_tdm_dac0_enum); | ||
1165 | |||
1166 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac1_enum, | ||
1167 | RT5645_TDM_CTRL_3, 8, rt5645_tdm_dac_swap_select); | ||
1168 | |||
1169 | static const struct snd_kcontrol_new rt5645_if1_dac1_tdm_sel_mux = | ||
1170 | SOC_DAPM_ENUM("IF1 DAC1 source", rt5645_tdm_dac1_enum); | ||
1171 | |||
1172 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac2_enum, | ||
1173 | RT5645_TDM_CTRL_3, 4, rt5645_tdm_dac_swap_select); | ||
1174 | |||
1175 | static const struct snd_kcontrol_new rt5645_if1_dac2_tdm_sel_mux = | ||
1176 | SOC_DAPM_ENUM("IF1 DAC2 source", rt5645_tdm_dac2_enum); | ||
1177 | |||
1178 | static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac3_enum, | ||
1179 | RT5645_TDM_CTRL_3, 0, rt5645_tdm_dac_swap_select); | ||
1180 | |||
1181 | static const struct snd_kcontrol_new rt5645_if1_dac3_tdm_sel_mux = | ||
1182 | SOC_DAPM_ENUM("IF1 DAC3 source", rt5645_tdm_dac3_enum); | ||
1183 | |||
1184 | /* MX-7a [14:12][10:8][6:4][2:0] */ | ||
1185 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac0_enum, | ||
1186 | RT5650_TDM_CTRL_4, 12, rt5645_tdm_dac_swap_select); | ||
1187 | |||
1188 | static const struct snd_kcontrol_new rt5650_if1_dac0_tdm_sel_mux = | ||
1189 | SOC_DAPM_ENUM("IF1 DAC0 source", rt5650_tdm_dac0_enum); | ||
1190 | |||
1191 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac1_enum, | ||
1192 | RT5650_TDM_CTRL_4, 8, rt5645_tdm_dac_swap_select); | ||
1193 | |||
1194 | static const struct snd_kcontrol_new rt5650_if1_dac1_tdm_sel_mux = | ||
1195 | SOC_DAPM_ENUM("IF1 DAC1 source", rt5650_tdm_dac1_enum); | ||
1196 | |||
1197 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac2_enum, | ||
1198 | RT5650_TDM_CTRL_4, 4, rt5645_tdm_dac_swap_select); | ||
1199 | |||
1200 | static const struct snd_kcontrol_new rt5650_if1_dac2_tdm_sel_mux = | ||
1201 | SOC_DAPM_ENUM("IF1 DAC2 source", rt5650_tdm_dac2_enum); | ||
1202 | |||
1203 | static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac3_enum, | ||
1204 | RT5650_TDM_CTRL_4, 0, rt5645_tdm_dac_swap_select); | ||
1205 | |||
1206 | static const struct snd_kcontrol_new rt5650_if1_dac3_tdm_sel_mux = | ||
1207 | SOC_DAPM_ENUM("IF1 DAC3 source", rt5650_tdm_dac3_enum); | ||
1208 | |||
1105 | /* MX-2d [3] [2] */ | 1209 | /* MX-2d [3] [2] */ |
1106 | static const char * const rt5650_a_dac1_src[] = { | 1210 | static const char * const rt5650_a_dac1_src[] = { |
1107 | "DAC1", "Stereo DAC Mixer" | 1211 | "DAC1", "Stereo DAC Mixer" |
@@ -1226,52 +1330,79 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on) | |||
1226 | 1330 | ||
1227 | if (on) { | 1331 | if (on) { |
1228 | if (hp_amp_power_count <= 0) { | 1332 | if (hp_amp_power_count <= 0) { |
1229 | /* depop parameters */ | 1333 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1230 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, | 1334 | snd_soc_write(codec, RT5645_CHARGE_PUMP, |
1231 | RT5645_DEPOP_MASK, RT5645_DEPOP_MAN); | 1335 | 0x0e06); |
1232 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d); | 1336 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x001d); |
1233 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | 1337 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1234 | RT5645_HP_DCC_INT1, 0x9f01); | 1338 | 0x3e, 0x7400); |
1235 | mdelay(150); | 1339 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1236 | /* headphone amp power on */ | 1340 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1237 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 1341 | RT5645_MAMP_INT_REG2, 0xfc00); |
1238 | RT5645_PWR_FV1 | RT5645_PWR_FV2 , 0); | 1342 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140); |
1239 | snd_soc_update_bits(codec, RT5645_PWR_VOL, | 1343 | } else { |
1240 | RT5645_PWR_HV_L | RT5645_PWR_HV_R, | 1344 | /* depop parameters */ |
1241 | RT5645_PWR_HV_L | RT5645_PWR_HV_R); | 1345 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, |
1242 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 1346 | RT5645_DEPOP_MASK, RT5645_DEPOP_MAN); |
1243 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | | 1347 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d); |
1244 | RT5645_PWR_HA, | 1348 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1245 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | | 1349 | RT5645_HP_DCC_INT1, 0x9f01); |
1246 | RT5645_PWR_HA); | 1350 | mdelay(150); |
1247 | mdelay(5); | 1351 | /* headphone amp power on */ |
1248 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 1352 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
1249 | RT5645_PWR_FV1 | RT5645_PWR_FV2, | 1353 | RT5645_PWR_FV1 | RT5645_PWR_FV2, 0); |
1250 | RT5645_PWR_FV1 | RT5645_PWR_FV2); | 1354 | snd_soc_update_bits(codec, RT5645_PWR_VOL, |
1251 | 1355 | RT5645_PWR_HV_L | RT5645_PWR_HV_R, | |
1252 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1356 | RT5645_PWR_HV_L | RT5645_PWR_HV_R); |
1253 | RT5645_HP_CO_MASK | RT5645_HP_SG_MASK, | 1357 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
1254 | RT5645_HP_CO_EN | RT5645_HP_SG_EN); | 1358 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | |
1255 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | 1359 | RT5645_PWR_HA, |
1256 | 0x14, 0x1aaa); | 1360 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | |
1257 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | 1361 | RT5645_PWR_HA); |
1258 | 0x24, 0x0430); | 1362 | mdelay(5); |
1363 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | ||
1364 | RT5645_PWR_FV1 | RT5645_PWR_FV2, | ||
1365 | RT5645_PWR_FV1 | RT5645_PWR_FV2); | ||
1366 | |||
1367 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1368 | RT5645_HP_CO_MASK | RT5645_HP_SG_MASK, | ||
1369 | RT5645_HP_CO_EN | RT5645_HP_SG_EN); | ||
1370 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | ||
1371 | 0x14, 0x1aaa); | ||
1372 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | ||
1373 | 0x24, 0x0430); | ||
1374 | } | ||
1259 | } | 1375 | } |
1260 | hp_amp_power_count++; | 1376 | hp_amp_power_count++; |
1261 | } else { | 1377 | } else { |
1262 | hp_amp_power_count--; | 1378 | hp_amp_power_count--; |
1263 | if (hp_amp_power_count <= 0) { | 1379 | if (hp_amp_power_count <= 0) { |
1264 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1380 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1265 | RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK | | 1381 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1266 | RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS | | 1382 | 0x3e, 0x7400); |
1267 | RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS); | 1383 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1268 | /* headphone amp power down */ | 1384 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1269 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x0000); | 1385 | RT5645_MAMP_INT_REG2, 0xfc00); |
1270 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 1386 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140); |
1271 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | | 1387 | msleep(100); |
1272 | RT5645_PWR_HA, 0); | 1388 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x0001); |
1273 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, | 1389 | |
1274 | RT5645_DEPOP_MASK, 0); | 1390 | } else { |
1391 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1392 | RT5645_HP_SG_MASK | | ||
1393 | RT5645_HP_L_SMT_MASK | | ||
1394 | RT5645_HP_R_SMT_MASK, | ||
1395 | RT5645_HP_SG_DIS | | ||
1396 | RT5645_HP_L_SMT_DIS | | ||
1397 | RT5645_HP_R_SMT_DIS); | ||
1398 | /* headphone amp power down */ | ||
1399 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x0000); | ||
1400 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | ||
1401 | RT5645_PWR_HP_L | RT5645_PWR_HP_R | | ||
1402 | RT5645_PWR_HA, 0); | ||
1403 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, | ||
1404 | RT5645_DEPOP_MASK, 0); | ||
1405 | } | ||
1275 | } | 1406 | } |
1276 | } | 1407 | } |
1277 | } | 1408 | } |
@@ -1286,56 +1417,52 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | |||
1286 | case SND_SOC_DAPM_POST_PMU: | 1417 | case SND_SOC_DAPM_POST_PMU: |
1287 | hp_amp_power(codec, 1); | 1418 | hp_amp_power(codec, 1); |
1288 | /* headphone unmute sequence */ | 1419 | /* headphone unmute sequence */ |
1289 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | 1420 | if (rt5645->codec_type == CODEC_TYPE_RT5645) { |
1290 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); | ||
1291 | } else { | ||
1292 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, | 1421 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1293 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | | 1422 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1294 | RT5645_CP_FQ3_MASK, | 1423 | RT5645_CP_FQ3_MASK, |
1295 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | | 1424 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | |
1296 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1425 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | |
1297 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); | 1426 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); |
1427 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | ||
1428 | RT5645_MAMP_INT_REG2, 0xfc00); | ||
1429 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1430 | RT5645_SMT_TRIG_MASK, RT5645_SMT_TRIG_EN); | ||
1431 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1432 | RT5645_RSTN_MASK, RT5645_RSTN_EN); | ||
1433 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1434 | RT5645_RSTN_MASK | RT5645_HP_L_SMT_MASK | | ||
1435 | RT5645_HP_R_SMT_MASK, RT5645_RSTN_DIS | | ||
1436 | RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN); | ||
1437 | msleep(40); | ||
1438 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1439 | RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK | | ||
1440 | RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS | | ||
1441 | RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS); | ||
1298 | } | 1442 | } |
1299 | regmap_write(rt5645->regmap, | ||
1300 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | ||
1301 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1302 | RT5645_SMT_TRIG_MASK, RT5645_SMT_TRIG_EN); | ||
1303 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1304 | RT5645_RSTN_MASK, RT5645_RSTN_EN); | ||
1305 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1306 | RT5645_RSTN_MASK | RT5645_HP_L_SMT_MASK | | ||
1307 | RT5645_HP_R_SMT_MASK, RT5645_RSTN_DIS | | ||
1308 | RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN); | ||
1309 | msleep(40); | ||
1310 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1311 | RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK | | ||
1312 | RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS | | ||
1313 | RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS); | ||
1314 | break; | 1443 | break; |
1315 | 1444 | ||
1316 | case SND_SOC_DAPM_PRE_PMD: | 1445 | case SND_SOC_DAPM_PRE_PMD: |
1317 | /* headphone mute sequence */ | 1446 | /* headphone mute sequence */ |
1318 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | 1447 | if (rt5645->codec_type == CODEC_TYPE_RT5645) { |
1319 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); | ||
1320 | } else { | ||
1321 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, | 1448 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1322 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | | 1449 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1323 | RT5645_CP_FQ3_MASK, | 1450 | RT5645_CP_FQ3_MASK, |
1324 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | | 1451 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | |
1325 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1452 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | |
1326 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); | 1453 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); |
1454 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | ||
1455 | RT5645_MAMP_INT_REG2, 0xfc00); | ||
1456 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1457 | RT5645_HP_SG_MASK, RT5645_HP_SG_EN); | ||
1458 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1459 | RT5645_RSTP_MASK, RT5645_RSTP_EN); | ||
1460 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1461 | RT5645_RSTP_MASK | RT5645_HP_L_SMT_MASK | | ||
1462 | RT5645_HP_R_SMT_MASK, RT5645_RSTP_DIS | | ||
1463 | RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN); | ||
1464 | msleep(30); | ||
1327 | } | 1465 | } |
1328 | regmap_write(rt5645->regmap, | ||
1329 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | ||
1330 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1331 | RT5645_HP_SG_MASK, RT5645_HP_SG_EN); | ||
1332 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1333 | RT5645_RSTP_MASK, RT5645_RSTP_EN); | ||
1334 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1335 | RT5645_RSTP_MASK | RT5645_HP_L_SMT_MASK | | ||
1336 | RT5645_HP_R_SMT_MASK, RT5645_RSTP_DIS | | ||
1337 | RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN); | ||
1338 | msleep(30); | ||
1339 | hp_amp_power(codec, 0); | 1466 | hp_amp_power(codec, 0); |
1340 | break; | 1467 | break; |
1341 | 1468 | ||
@@ -1570,20 +1697,33 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1570 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | 1697 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), |
1571 | 1698 | ||
1572 | /* IF1 2 Mux */ | 1699 | /* IF1 2 Mux */ |
1573 | SND_SOC_DAPM_MUX("IF1 ADC Mux", SND_SOC_NOPM, | 1700 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM, |
1701 | 0, 0, &rt5645_if1_adc1_in_mux), | ||
1702 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM, | ||
1703 | 0, 0, &rt5645_if1_adc2_in_mux), | ||
1704 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM, | ||
1705 | 0, 0, &rt5645_if1_adc3_in_mux), | ||
1706 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM, | ||
1574 | 0, 0, &rt5645_if1_adc_in_mux), | 1707 | 0, 0, &rt5645_if1_adc_in_mux), |
1708 | |||
1575 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, | 1709 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, |
1576 | 0, 0, &rt5645_if2_adc_in_mux), | 1710 | 0, 0, &rt5645_if2_adc_in_mux), |
1577 | 1711 | ||
1578 | /* Digital Interface */ | 1712 | /* Digital Interface */ |
1579 | SND_SOC_DAPM_SUPPLY("I2S1", RT5645_PWR_DIG1, | 1713 | SND_SOC_DAPM_SUPPLY("I2S1", RT5645_PWR_DIG1, |
1580 | RT5645_PWR_I2S1_BIT, 0, NULL, 0), | 1714 | RT5645_PWR_I2S1_BIT, 0, NULL, 0), |
1715 | SND_SOC_DAPM_PGA("IF1 DAC0", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1581 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), | 1716 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), |
1582 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), | 1717 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), |
1583 | SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), | 1718 | SND_SOC_DAPM_PGA("IF1 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0), |
1584 | SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), | 1719 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, |
1585 | SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0), | 1720 | &rt5645_if1_dac0_tdm_sel_mux), |
1586 | SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0), | 1721 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, |
1722 | &rt5645_if1_dac1_tdm_sel_mux), | ||
1723 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, | ||
1724 | &rt5645_if1_dac2_tdm_sel_mux), | ||
1725 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, | ||
1726 | &rt5645_if1_dac3_tdm_sel_mux), | ||
1587 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | 1727 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), |
1588 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | 1728 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), |
1589 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | 1729 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), |
@@ -1725,6 +1865,24 @@ static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = { | |||
1725 | 0, 0, &rt5650_a_dac2_l_mux), | 1865 | 0, 0, &rt5650_a_dac2_l_mux), |
1726 | SND_SOC_DAPM_MUX("A DAC2 R Mux", SND_SOC_NOPM, | 1866 | SND_SOC_DAPM_MUX("A DAC2 R Mux", SND_SOC_NOPM, |
1727 | 0, 0, &rt5650_a_dac2_r_mux), | 1867 | 0, 0, &rt5650_a_dac2_r_mux), |
1868 | |||
1869 | SND_SOC_DAPM_MUX("RT5650 IF1 ADC1 Swap Mux", SND_SOC_NOPM, | ||
1870 | 0, 0, &rt5650_if1_adc1_in_mux), | ||
1871 | SND_SOC_DAPM_MUX("RT5650 IF1 ADC2 Swap Mux", SND_SOC_NOPM, | ||
1872 | 0, 0, &rt5650_if1_adc2_in_mux), | ||
1873 | SND_SOC_DAPM_MUX("RT5650 IF1 ADC3 Swap Mux", SND_SOC_NOPM, | ||
1874 | 0, 0, &rt5650_if1_adc3_in_mux), | ||
1875 | SND_SOC_DAPM_MUX("RT5650 IF1 ADC Mux", SND_SOC_NOPM, | ||
1876 | 0, 0, &rt5650_if1_adc_in_mux), | ||
1877 | |||
1878 | SND_SOC_DAPM_MUX("RT5650 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, | ||
1879 | &rt5650_if1_dac0_tdm_sel_mux), | ||
1880 | SND_SOC_DAPM_MUX("RT5650 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, | ||
1881 | &rt5650_if1_dac1_tdm_sel_mux), | ||
1882 | SND_SOC_DAPM_MUX("RT5650 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, | ||
1883 | &rt5650_if1_dac2_tdm_sel_mux), | ||
1884 | SND_SOC_DAPM_MUX("RT5650 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, | ||
1885 | &rt5650_if1_dac3_tdm_sel_mux), | ||
1728 | }; | 1886 | }; |
1729 | 1887 | ||
1730 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | 1888 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { |
@@ -1847,42 +2005,32 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1847 | { "IF_ADC2", NULL, "Mono ADC MIXR" }, | 2005 | { "IF_ADC2", NULL, "Mono ADC MIXR" }, |
1848 | { "VAD_ADC", NULL, "VAD ADC Mux" }, | 2006 | { "VAD_ADC", NULL, "VAD ADC Mux" }, |
1849 | 2007 | ||
1850 | { "IF1 ADC Mux", "IF_ADC1", "IF_ADC1" }, | ||
1851 | { "IF1 ADC Mux", "IF_ADC2", "IF_ADC2" }, | ||
1852 | { "IF1 ADC Mux", "VAD_ADC", "VAD_ADC" }, | ||
1853 | |||
1854 | { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" }, | 2008 | { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" }, |
1855 | { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, | 2009 | { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, |
1856 | { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, | 2010 | { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, |
1857 | 2011 | ||
1858 | { "IF1 ADC", NULL, "I2S1" }, | 2012 | { "IF1 ADC", NULL, "I2S1" }, |
1859 | { "IF1 ADC", NULL, "IF1 ADC Mux" }, | ||
1860 | { "IF2 ADC", NULL, "I2S2" }, | 2013 | { "IF2 ADC", NULL, "I2S2" }, |
1861 | { "IF2 ADC", NULL, "IF2 ADC Mux" }, | 2014 | { "IF2 ADC", NULL, "IF2 ADC Mux" }, |
1862 | 2015 | ||
1863 | { "AIF1TX", NULL, "IF1 ADC" }, | ||
1864 | { "AIF1TX", NULL, "IF2 ADC" }, | ||
1865 | { "AIF2TX", NULL, "IF2 ADC" }, | 2016 | { "AIF2TX", NULL, "IF2 ADC" }, |
1866 | 2017 | ||
2018 | { "IF1 DAC0", NULL, "AIF1RX" }, | ||
1867 | { "IF1 DAC1", NULL, "AIF1RX" }, | 2019 | { "IF1 DAC1", NULL, "AIF1RX" }, |
1868 | { "IF1 DAC2", NULL, "AIF1RX" }, | 2020 | { "IF1 DAC2", NULL, "AIF1RX" }, |
2021 | { "IF1 DAC3", NULL, "AIF1RX" }, | ||
1869 | { "IF2 DAC", NULL, "AIF2RX" }, | 2022 | { "IF2 DAC", NULL, "AIF2RX" }, |
1870 | 2023 | ||
2024 | { "IF1 DAC0", NULL, "I2S1" }, | ||
1871 | { "IF1 DAC1", NULL, "I2S1" }, | 2025 | { "IF1 DAC1", NULL, "I2S1" }, |
1872 | { "IF1 DAC2", NULL, "I2S1" }, | 2026 | { "IF1 DAC2", NULL, "I2S1" }, |
2027 | { "IF1 DAC3", NULL, "I2S1" }, | ||
1873 | { "IF2 DAC", NULL, "I2S2" }, | 2028 | { "IF2 DAC", NULL, "I2S2" }, |
1874 | 2029 | ||
1875 | { "IF1 DAC2 L", NULL, "IF1 DAC2" }, | ||
1876 | { "IF1 DAC2 R", NULL, "IF1 DAC2" }, | ||
1877 | { "IF1 DAC1 L", NULL, "IF1 DAC1" }, | ||
1878 | { "IF1 DAC1 R", NULL, "IF1 DAC1" }, | ||
1879 | { "IF2 DAC L", NULL, "IF2 DAC" }, | 2030 | { "IF2 DAC L", NULL, "IF2 DAC" }, |
1880 | { "IF2 DAC R", NULL, "IF2 DAC" }, | 2031 | { "IF2 DAC R", NULL, "IF2 DAC" }, |
1881 | 2032 | ||
1882 | { "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" }, | ||
1883 | { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" }, | 2033 | { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" }, |
1884 | |||
1885 | { "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" }, | ||
1886 | { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, | 2034 | { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, |
1887 | 2035 | ||
1888 | { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, | 2036 | { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, |
@@ -1892,14 +2040,12 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1892 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, | 2040 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, |
1893 | { "DAC1 MIXR", NULL, "dac stereo1 filter" }, | 2041 | { "DAC1 MIXR", NULL, "dac stereo1 filter" }, |
1894 | 2042 | ||
1895 | { "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" }, | ||
1896 | { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" }, | 2043 | { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" }, |
1897 | { "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" }, | 2044 | { "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" }, |
1898 | { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, | 2045 | { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, |
1899 | { "DAC L2 Volume", NULL, "DAC L2 Mux" }, | 2046 | { "DAC L2 Volume", NULL, "DAC L2 Mux" }, |
1900 | { "DAC L2 Volume", NULL, "dac mono left filter" }, | 2047 | { "DAC L2 Volume", NULL, "dac mono left filter" }, |
1901 | 2048 | ||
1902 | { "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" }, | ||
1903 | { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" }, | 2049 | { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" }, |
1904 | { "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" }, | 2050 | { "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" }, |
1905 | { "DAC R2 Mux", "Haptic", "Haptic Generator" }, | 2051 | { "DAC R2 Mux", "Haptic", "Haptic Generator" }, |
@@ -2037,6 +2183,80 @@ static const struct snd_soc_dapm_route rt5650_specific_dapm_routes[] = { | |||
2037 | { "DAC R1", NULL, "A DAC1 R Mux" }, | 2183 | { "DAC R1", NULL, "A DAC1 R Mux" }, |
2038 | { "DAC L2", NULL, "A DAC2 L Mux" }, | 2184 | { "DAC L2", NULL, "A DAC2 L Mux" }, |
2039 | { "DAC R2", NULL, "A DAC2 R Mux" }, | 2185 | { "DAC R2", NULL, "A DAC2 R Mux" }, |
2186 | |||
2187 | { "RT5650 IF1 ADC1 Swap Mux", "L/R", "IF_ADC1" }, | ||
2188 | { "RT5650 IF1 ADC1 Swap Mux", "R/L", "IF_ADC1" }, | ||
2189 | { "RT5650 IF1 ADC1 Swap Mux", "L/L", "IF_ADC1" }, | ||
2190 | { "RT5650 IF1 ADC1 Swap Mux", "R/R", "IF_ADC1" }, | ||
2191 | |||
2192 | { "RT5650 IF1 ADC2 Swap Mux", "L/R", "IF_ADC2" }, | ||
2193 | { "RT5650 IF1 ADC2 Swap Mux", "R/L", "IF_ADC2" }, | ||
2194 | { "RT5650 IF1 ADC2 Swap Mux", "L/L", "IF_ADC2" }, | ||
2195 | { "RT5650 IF1 ADC2 Swap Mux", "R/R", "IF_ADC2" }, | ||
2196 | |||
2197 | { "RT5650 IF1 ADC3 Swap Mux", "L/R", "VAD_ADC" }, | ||
2198 | { "RT5650 IF1 ADC3 Swap Mux", "R/L", "VAD_ADC" }, | ||
2199 | { "RT5650 IF1 ADC3 Swap Mux", "L/L", "VAD_ADC" }, | ||
2200 | { "RT5650 IF1 ADC3 Swap Mux", "R/R", "VAD_ADC" }, | ||
2201 | |||
2202 | { "IF1 ADC", NULL, "RT5650 IF1 ADC1 Swap Mux" }, | ||
2203 | { "IF1 ADC", NULL, "RT5650 IF1 ADC2 Swap Mux" }, | ||
2204 | { "IF1 ADC", NULL, "RT5650 IF1 ADC3 Swap Mux" }, | ||
2205 | |||
2206 | { "RT5650 IF1 ADC Mux", "IF_ADC1/IF_ADC2/DAC_REF/Null", "IF1 ADC" }, | ||
2207 | { "RT5650 IF1 ADC Mux", "IF_ADC1/IF_ADC2/Null/DAC_REF", "IF1 ADC" }, | ||
2208 | { "RT5650 IF1 ADC Mux", "IF_ADC1/DAC_REF/IF_ADC2/Null", "IF1 ADC" }, | ||
2209 | { "RT5650 IF1 ADC Mux", "IF_ADC1/DAC_REF/Null/IF_ADC2", "IF1 ADC" }, | ||
2210 | { "RT5650 IF1 ADC Mux", "IF_ADC1/Null/DAC_REF/IF_ADC2", "IF1 ADC" }, | ||
2211 | { "RT5650 IF1 ADC Mux", "IF_ADC1/Null/IF_ADC2/DAC_REF", "IF1 ADC" }, | ||
2212 | |||
2213 | { "RT5650 IF1 ADC Mux", "IF_ADC2/IF_ADC1/DAC_REF/Null", "IF1 ADC" }, | ||
2214 | { "RT5650 IF1 ADC Mux", "IF_ADC2/IF_ADC1/Null/DAC_REF", "IF1 ADC" }, | ||
2215 | { "RT5650 IF1 ADC Mux", "IF_ADC2/DAC_REF/IF_ADC1/Null", "IF1 ADC" }, | ||
2216 | { "RT5650 IF1 ADC Mux", "IF_ADC2/DAC_REF/Null/IF_ADC1", "IF1 ADC" }, | ||
2217 | { "RT5650 IF1 ADC Mux", "IF_ADC2/Null/DAC_REF/IF_ADC1", "IF1 ADC" }, | ||
2218 | { "RT5650 IF1 ADC Mux", "IF_ADC2/Null/IF_ADC1/DAC_REF", "IF1 ADC" }, | ||
2219 | |||
2220 | { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC1/IF_ADC2/Null", "IF1 ADC" }, | ||
2221 | { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC1/Null/IF_ADC2", "IF1 ADC" }, | ||
2222 | { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC2/IF_ADC1/Null", "IF1 ADC" }, | ||
2223 | { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC2/Null/IF_ADC1", "IF1 ADC" }, | ||
2224 | { "RT5650 IF1 ADC Mux", "DAC_REF/Null/IF_ADC1/IF_ADC2", "IF1 ADC" }, | ||
2225 | { "RT5650 IF1 ADC Mux", "DAC_REF/Null/IF_ADC2/IF_ADC1", "IF1 ADC" }, | ||
2226 | |||
2227 | { "RT5650 IF1 ADC Mux", "Null/IF_ADC1/IF_ADC2/DAC_REF", "IF1 ADC" }, | ||
2228 | { "RT5650 IF1 ADC Mux", "Null/IF_ADC1/DAC_REF/IF_ADC2", "IF1 ADC" }, | ||
2229 | { "RT5650 IF1 ADC Mux", "Null/IF_ADC2/IF_ADC1/DAC_REF", "IF1 ADC" }, | ||
2230 | { "RT5650 IF1 ADC Mux", "Null/IF_ADC2/DAC_REF/IF_ADC1", "IF1 ADC" }, | ||
2231 | { "RT5650 IF1 ADC Mux", "Null/DAC_REF/IF_ADC1/IF_ADC2", "IF1 ADC" }, | ||
2232 | { "RT5650 IF1 ADC Mux", "Null/DAC_REF/IF_ADC2/IF_ADC1", "IF1 ADC" }, | ||
2233 | { "AIF1TX", NULL, "RT5650 IF1 ADC Mux" }, | ||
2234 | |||
2235 | { "RT5650 IF1 DAC1 L Mux", "Slot0", "IF1 DAC0" }, | ||
2236 | { "RT5650 IF1 DAC1 L Mux", "Slot1", "IF1 DAC1" }, | ||
2237 | { "RT5650 IF1 DAC1 L Mux", "Slot2", "IF1 DAC2" }, | ||
2238 | { "RT5650 IF1 DAC1 L Mux", "Slot3", "IF1 DAC3" }, | ||
2239 | |||
2240 | { "RT5650 IF1 DAC1 R Mux", "Slot0", "IF1 DAC0" }, | ||
2241 | { "RT5650 IF1 DAC1 R Mux", "Slot1", "IF1 DAC1" }, | ||
2242 | { "RT5650 IF1 DAC1 R Mux", "Slot2", "IF1 DAC2" }, | ||
2243 | { "RT5650 IF1 DAC1 R Mux", "Slot3", "IF1 DAC3" }, | ||
2244 | |||
2245 | { "RT5650 IF1 DAC2 L Mux", "Slot0", "IF1 DAC0" }, | ||
2246 | { "RT5650 IF1 DAC2 L Mux", "Slot1", "IF1 DAC1" }, | ||
2247 | { "RT5650 IF1 DAC2 L Mux", "Slot2", "IF1 DAC2" }, | ||
2248 | { "RT5650 IF1 DAC2 L Mux", "Slot3", "IF1 DAC3" }, | ||
2249 | |||
2250 | { "RT5650 IF1 DAC2 R Mux", "Slot0", "IF1 DAC0" }, | ||
2251 | { "RT5650 IF1 DAC2 R Mux", "Slot1", "IF1 DAC1" }, | ||
2252 | { "RT5650 IF1 DAC2 R Mux", "Slot2", "IF1 DAC2" }, | ||
2253 | { "RT5650 IF1 DAC2 R Mux", "Slot3", "IF1 DAC3" }, | ||
2254 | |||
2255 | { "DAC1 L Mux", "IF1 DAC", "RT5650 IF1 DAC1 L Mux" }, | ||
2256 | { "DAC1 R Mux", "IF1 DAC", "RT5650 IF1 DAC1 R Mux" }, | ||
2257 | |||
2258 | { "DAC L2 Mux", "IF1 DAC", "RT5650 IF1 DAC2 L Mux" }, | ||
2259 | { "DAC R2 Mux", "IF1 DAC", "RT5650 IF1 DAC2 R Mux" }, | ||
2040 | }; | 2260 | }; |
2041 | 2261 | ||
2042 | static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { | 2262 | static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { |
@@ -2044,6 +2264,57 @@ static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { | |||
2044 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | 2264 | { "DAC R1", NULL, "Stereo DAC MIXR" }, |
2045 | { "DAC L2", NULL, "Mono DAC MIXL" }, | 2265 | { "DAC L2", NULL, "Mono DAC MIXL" }, |
2046 | { "DAC R2", NULL, "Mono DAC MIXR" }, | 2266 | { "DAC R2", NULL, "Mono DAC MIXR" }, |
2267 | |||
2268 | { "RT5645 IF1 ADC1 Swap Mux", "L/R", "IF_ADC1" }, | ||
2269 | { "RT5645 IF1 ADC1 Swap Mux", "R/L", "IF_ADC1" }, | ||
2270 | { "RT5645 IF1 ADC1 Swap Mux", "L/L", "IF_ADC1" }, | ||
2271 | { "RT5645 IF1 ADC1 Swap Mux", "R/R", "IF_ADC1" }, | ||
2272 | |||
2273 | { "RT5645 IF1 ADC2 Swap Mux", "L/R", "IF_ADC2" }, | ||
2274 | { "RT5645 IF1 ADC2 Swap Mux", "R/L", "IF_ADC2" }, | ||
2275 | { "RT5645 IF1 ADC2 Swap Mux", "L/L", "IF_ADC2" }, | ||
2276 | { "RT5645 IF1 ADC2 Swap Mux", "R/R", "IF_ADC2" }, | ||
2277 | |||
2278 | { "RT5645 IF1 ADC3 Swap Mux", "L/R", "VAD_ADC" }, | ||
2279 | { "RT5645 IF1 ADC3 Swap Mux", "R/L", "VAD_ADC" }, | ||
2280 | { "RT5645 IF1 ADC3 Swap Mux", "L/L", "VAD_ADC" }, | ||
2281 | { "RT5645 IF1 ADC3 Swap Mux", "R/R", "VAD_ADC" }, | ||
2282 | |||
2283 | { "IF1 ADC", NULL, "RT5645 IF1 ADC1 Swap Mux" }, | ||
2284 | { "IF1 ADC", NULL, "RT5645 IF1 ADC2 Swap Mux" }, | ||
2285 | { "IF1 ADC", NULL, "RT5645 IF1 ADC3 Swap Mux" }, | ||
2286 | |||
2287 | { "RT5645 IF1 ADC Mux", "IF_ADC1/IF_ADC2/VAD_ADC", "IF1 ADC" }, | ||
2288 | { "RT5645 IF1 ADC Mux", "IF_ADC2/IF_ADC1/VAD_ADC", "IF1 ADC" }, | ||
2289 | { "RT5645 IF1 ADC Mux", "VAD_ADC/IF_ADC1/IF_ADC2", "IF1 ADC" }, | ||
2290 | { "RT5645 IF1 ADC Mux", "VAD_ADC/IF_ADC2/IF_ADC1", "IF1 ADC" }, | ||
2291 | { "AIF1TX", NULL, "RT5645 IF1 ADC Mux" }, | ||
2292 | |||
2293 | { "RT5645 IF1 DAC1 L Mux", "Slot0", "IF1 DAC0" }, | ||
2294 | { "RT5645 IF1 DAC1 L Mux", "Slot1", "IF1 DAC1" }, | ||
2295 | { "RT5645 IF1 DAC1 L Mux", "Slot2", "IF1 DAC2" }, | ||
2296 | { "RT5645 IF1 DAC1 L Mux", "Slot3", "IF1 DAC3" }, | ||
2297 | |||
2298 | { "RT5645 IF1 DAC1 R Mux", "Slot0", "IF1 DAC0" }, | ||
2299 | { "RT5645 IF1 DAC1 R Mux", "Slot1", "IF1 DAC1" }, | ||
2300 | { "RT5645 IF1 DAC1 R Mux", "Slot2", "IF1 DAC2" }, | ||
2301 | { "RT5645 IF1 DAC1 R Mux", "Slot3", "IF1 DAC3" }, | ||
2302 | |||
2303 | { "RT5645 IF1 DAC2 L Mux", "Slot0", "IF1 DAC0" }, | ||
2304 | { "RT5645 IF1 DAC2 L Mux", "Slot1", "IF1 DAC1" }, | ||
2305 | { "RT5645 IF1 DAC2 L Mux", "Slot2", "IF1 DAC2" }, | ||
2306 | { "RT5645 IF1 DAC2 L Mux", "Slot3", "IF1 DAC3" }, | ||
2307 | |||
2308 | { "RT5645 IF1 DAC2 R Mux", "Slot0", "IF1 DAC0" }, | ||
2309 | { "RT5645 IF1 DAC2 R Mux", "Slot1", "IF1 DAC1" }, | ||
2310 | { "RT5645 IF1 DAC2 R Mux", "Slot2", "IF1 DAC2" }, | ||
2311 | { "RT5645 IF1 DAC2 R Mux", "Slot3", "IF1 DAC3" }, | ||
2312 | |||
2313 | { "DAC1 L Mux", "IF1 DAC", "RT5645 IF1 DAC1 L Mux" }, | ||
2314 | { "DAC1 R Mux", "IF1 DAC", "RT5645 IF1 DAC1 R Mux" }, | ||
2315 | |||
2316 | { "DAC L2 Mux", "IF1 DAC", "RT5645 IF1 DAC2 L Mux" }, | ||
2317 | { "DAC R2 Mux", "IF1 DAC", "RT5645 IF1 DAC2 R Mux" }, | ||
2047 | }; | 2318 | }; |
2048 | 2319 | ||
2049 | static int rt5645_hw_params(struct snd_pcm_substream *substream, | 2320 | static int rt5645_hw_params(struct snd_pcm_substream *substream, |
@@ -2101,9 +2372,8 @@ static int rt5645_hw_params(struct snd_pcm_substream *substream, | |||
2101 | 2372 | ||
2102 | switch (dai->id) { | 2373 | switch (dai->id) { |
2103 | case RT5645_AIF1: | 2374 | case RT5645_AIF1: |
2104 | mask_clk = RT5645_I2S_BCLK_MS1_MASK | RT5645_I2S_PD1_MASK; | 2375 | mask_clk = RT5645_I2S_PD1_MASK; |
2105 | val_clk = bclk_ms << RT5645_I2S_BCLK_MS1_SFT | | 2376 | val_clk = pre_div << RT5645_I2S_PD1_SFT; |
2106 | pre_div << RT5645_I2S_PD1_SFT; | ||
2107 | snd_soc_update_bits(codec, RT5645_I2S1_SDP, | 2377 | snd_soc_update_bits(codec, RT5645_I2S1_SDP, |
2108 | (0x3 << dl_sft), (val_len << dl_sft)); | 2378 | (0x3 << dl_sft), (val_len << dl_sft)); |
2109 | snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk); | 2379 | snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk); |
@@ -2368,6 +2638,8 @@ static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
2368 | static int rt5645_set_bias_level(struct snd_soc_codec *codec, | 2638 | static int rt5645_set_bias_level(struct snd_soc_codec *codec, |
2369 | enum snd_soc_bias_level level) | 2639 | enum snd_soc_bias_level level) |
2370 | { | 2640 | { |
2641 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2642 | |||
2371 | switch (level) { | 2643 | switch (level) { |
2372 | case SND_SOC_BIAS_PREPARE: | 2644 | case SND_SOC_BIAS_PREPARE: |
2373 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 2645 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { |
@@ -2398,8 +2670,9 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2398 | 2670 | ||
2399 | case SND_SOC_BIAS_OFF: | 2671 | case SND_SOC_BIAS_OFF: |
2400 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); | 2672 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); |
2401 | snd_soc_update_bits(codec, RT5645_GEN_CTRL1, | 2673 | if (!rt5645->en_button_func) |
2402 | RT5645_DIG_GATE_CTRL, 0); | 2674 | snd_soc_update_bits(codec, RT5645_GEN_CTRL1, |
2675 | RT5645_DIG_GATE_CTRL, 0); | ||
2403 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 2676 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
2404 | RT5645_PWR_VREF1 | RT5645_PWR_MB | | 2677 | RT5645_PWR_VREF1 | RT5645_PWR_MB | |
2405 | RT5645_PWR_BG | RT5645_PWR_VREF2 | | 2678 | RT5645_PWR_BG | RT5645_PWR_VREF2 | |
@@ -2409,72 +2682,228 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2409 | default: | 2682 | default: |
2410 | break; | 2683 | break; |
2411 | } | 2684 | } |
2412 | codec->dapm.bias_level = level; | ||
2413 | 2685 | ||
2414 | return 0; | 2686 | return 0; |
2415 | } | 2687 | } |
2416 | 2688 | ||
2417 | static int rt5645_jack_detect(struct snd_soc_codec *codec) | 2689 | static int rt5650_calibration(struct rt5645_priv *rt5645) |
2418 | { | 2690 | { |
2419 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2691 | int val, i; |
2420 | int gpio_state, jack_type = 0; | 2692 | int ret = -1; |
2421 | unsigned int val; | ||
2422 | 2693 | ||
2423 | if (!gpio_is_valid(rt5645->pdata.hp_det_gpio)) { | 2694 | regcache_cache_bypass(rt5645->regmap, true); |
2424 | dev_err(codec->dev, "invalid gpio\n"); | 2695 | regmap_write(rt5645->regmap, RT5645_RESET, 0); |
2425 | return -EINVAL; | 2696 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0800); |
2697 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_CHOP_DAC_ADC, | ||
2698 | 0x3600); | ||
2699 | regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x25, 0x7000); | ||
2700 | regmap_write(rt5645->regmap, RT5645_I2S1_SDP, 0x8008); | ||
2701 | /* headset type */ | ||
2702 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL1, 0x2061); | ||
2703 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); | ||
2704 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0x2012); | ||
2705 | regmap_write(rt5645->regmap, RT5645_PWR_MIXER, 0x0002); | ||
2706 | regmap_write(rt5645->regmap, RT5645_PWR_VOL, 0x0020); | ||
2707 | regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0); | ||
2708 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006); | ||
2709 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x1827); | ||
2710 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x0827); | ||
2711 | msleep(400); | ||
2712 | /* Inline command */ | ||
2713 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0001); | ||
2714 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000); | ||
2715 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008); | ||
2716 | /* Calbration */ | ||
2717 | regmap_write(rt5645->regmap, RT5645_GLB_CLK, 0x8000); | ||
2718 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000); | ||
2719 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000); | ||
2720 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008); | ||
2721 | regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x8800); | ||
2722 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0xe8fa); | ||
2723 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x8c04); | ||
2724 | regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x3100); | ||
2725 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0e06); | ||
2726 | regmap_write(rt5645->regmap, RT5645_BASS_BACK, 0x8a13); | ||
2727 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0820); | ||
2728 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x000d); | ||
2729 | /* Power on and Calbration */ | ||
2730 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_HP_DCC_INT1, | ||
2731 | 0x9f01); | ||
2732 | msleep(200); | ||
2733 | for (i = 0; i < 5; i++) { | ||
2734 | regmap_read(rt5645->regmap, RT5645_PR_BASE + 0x7a, &val); | ||
2735 | if (val != 0 && val != 0x3f3f) { | ||
2736 | ret = 0; | ||
2737 | break; | ||
2738 | } | ||
2739 | msleep(50); | ||
2426 | } | 2740 | } |
2427 | gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); | 2741 | pr_debug("%s: PR-7A = 0x%x\n", __func__, val); |
2742 | |||
2743 | /* mute */ | ||
2744 | regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x3e, 0x7400); | ||
2745 | regmap_write(rt5645->regmap, RT5645_DEPOP_M3, 0x0737); | ||
2746 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_MAMP_INT_REG2, | ||
2747 | 0xfc00); | ||
2748 | regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x1140); | ||
2749 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000); | ||
2750 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL2, 0x4020); | ||
2751 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x0006); | ||
2752 | regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x0000); | ||
2753 | msleep(350); | ||
2754 | |||
2755 | regcache_cache_bypass(rt5645->regmap, false); | ||
2756 | |||
2757 | return ret; | ||
2758 | } | ||
2428 | 2759 | ||
2429 | dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, | 2760 | static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec, |
2430 | gpio_state); | 2761 | bool enable) |
2762 | { | ||
2763 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2431 | 2764 | ||
2432 | if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || | 2765 | if (enable) { |
2433 | (!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) { | 2766 | snd_soc_dapm_mutex_lock(&codec->dapm); |
2434 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1"); | 2767 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, |
2435 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2"); | 2768 | "ADC L power"); |
2436 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | 2769 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, |
2437 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power"); | 2770 | "ADC R power"); |
2438 | snd_soc_dapm_sync(&codec->dapm); | 2771 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, |
2772 | "LDO2"); | ||
2773 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, | ||
2774 | "Mic Det Power"); | ||
2775 | snd_soc_dapm_sync_unlocked(&codec->dapm); | ||
2776 | snd_soc_dapm_mutex_unlock(&codec->dapm); | ||
2777 | |||
2778 | snd_soc_update_bits(codec, | ||
2779 | RT5645_INT_IRQ_ST, 0x8, 0x8); | ||
2780 | snd_soc_update_bits(codec, | ||
2781 | RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); | ||
2782 | snd_soc_read(codec, RT5650_4BTN_IL_CMD1); | ||
2783 | pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, | ||
2784 | snd_soc_read(codec, RT5650_4BTN_IL_CMD1)); | ||
2785 | } else { | ||
2786 | snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); | ||
2787 | snd_soc_update_bits(codec, RT5645_INT_IRQ_ST, 0x8, 0x0); | ||
2788 | |||
2789 | snd_soc_dapm_mutex_lock(&codec->dapm); | ||
2790 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2791 | "ADC L power"); | ||
2792 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2793 | "ADC R power"); | ||
2794 | if (rt5645->pdata.jd_mode == 0) | ||
2795 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2796 | "LDO2"); | ||
2797 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2798 | "Mic Det Power"); | ||
2799 | snd_soc_dapm_sync_unlocked(&codec->dapm); | ||
2800 | snd_soc_dapm_mutex_unlock(&codec->dapm); | ||
2801 | } | ||
2802 | } | ||
2439 | 2803 | ||
2440 | snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006); | 2804 | static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) |
2441 | snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0); | 2805 | { |
2806 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2807 | unsigned int val; | ||
2442 | 2808 | ||
2443 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | 2809 | if (jack_insert) { |
2444 | RT5645_CBJ_MN_JD, 0); | 2810 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); |
2445 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | ||
2446 | RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD); | ||
2447 | 2811 | ||
2448 | msleep(400); | 2812 | if (codec->component.card->instantiated) { |
2449 | val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7; | 2813 | /* for jack type detect */ |
2814 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | ||
2815 | snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
2816 | "Mic Det Power"); | ||
2817 | snd_soc_dapm_sync(&codec->dapm); | ||
2818 | } else { | ||
2819 | /* Power up necessary bits for JD if dapm is | ||
2820 | not ready yet */ | ||
2821 | regmap_update_bits(rt5645->regmap, RT5645_PWR_ANLG1, | ||
2822 | RT5645_PWR_MB | RT5645_PWR_VREF2, | ||
2823 | RT5645_PWR_MB | RT5645_PWR_VREF2); | ||
2824 | regmap_update_bits(rt5645->regmap, RT5645_PWR_MIXER, | ||
2825 | RT5645_PWR_LDO2, RT5645_PWR_LDO2); | ||
2826 | regmap_update_bits(rt5645->regmap, RT5645_PWR_VOL, | ||
2827 | RT5645_PWR_MIC_DET, RT5645_PWR_MIC_DET); | ||
2828 | } | ||
2829 | |||
2830 | regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0); | ||
2831 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006); | ||
2832 | regmap_update_bits(rt5645->regmap, | ||
2833 | RT5645_IN1_CTRL2, 0x1000, 0x1000); | ||
2834 | msleep(100); | ||
2835 | regmap_update_bits(rt5645->regmap, | ||
2836 | RT5645_IN1_CTRL2, 0x1000, 0x0000); | ||
2837 | |||
2838 | msleep(450); | ||
2839 | regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val); | ||
2840 | val &= 0x7; | ||
2450 | dev_dbg(codec->dev, "val = %d\n", val); | 2841 | dev_dbg(codec->dev, "val = %d\n", val); |
2451 | 2842 | ||
2452 | if (val == 1 || val == 2) | 2843 | if (val == 1 || val == 2) { |
2453 | jack_type = SND_JACK_HEADSET; | 2844 | rt5645->jack_type = SND_JACK_HEADSET; |
2454 | else | 2845 | if (rt5645->en_button_func) { |
2455 | jack_type = SND_JACK_HEADPHONE; | 2846 | rt5645_enable_push_button_irq(codec, true); |
2847 | } | ||
2848 | } else { | ||
2849 | if (codec->component.card->instantiated) { | ||
2850 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
2851 | "Mic Det Power"); | ||
2852 | snd_soc_dapm_sync(&codec->dapm); | ||
2853 | } else | ||
2854 | regmap_update_bits(rt5645->regmap, | ||
2855 | RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0); | ||
2856 | rt5645->jack_type = SND_JACK_HEADPHONE; | ||
2857 | } | ||
2456 | 2858 | ||
2457 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); | 2859 | } else { /* jack out */ |
2458 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); | 2860 | rt5645->jack_type = 0; |
2459 | if (rt5645->pdata.jd_mode == 0) | 2861 | if (rt5645->en_button_func) |
2460 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); | 2862 | rt5645_enable_push_button_irq(codec, false); |
2461 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | 2863 | else { |
2462 | snd_soc_dapm_sync(&codec->dapm); | 2864 | if (codec->component.card->instantiated) { |
2865 | if (rt5645->pdata.jd_mode == 0) | ||
2866 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
2867 | "LDO2"); | ||
2868 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
2869 | "Mic Det Power"); | ||
2870 | snd_soc_dapm_sync(&codec->dapm); | ||
2871 | } else { | ||
2872 | if (rt5645->pdata.jd_mode == 0) | ||
2873 | regmap_update_bits(rt5645->regmap, | ||
2874 | RT5645_PWR_MIXER, | ||
2875 | RT5645_PWR_LDO2, 0); | ||
2876 | regmap_update_bits(rt5645->regmap, | ||
2877 | RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0); | ||
2878 | } | ||
2879 | } | ||
2463 | } | 2880 | } |
2464 | 2881 | ||
2465 | snd_soc_jack_report(rt5645->hp_jack, jack_type, SND_JACK_HEADPHONE); | 2882 | return rt5645->jack_type; |
2466 | snd_soc_jack_report(rt5645->mic_jack, jack_type, SND_JACK_MICROPHONE); | ||
2467 | return 0; | ||
2468 | } | 2883 | } |
2469 | 2884 | ||
2885 | static int rt5645_irq_detection(struct rt5645_priv *rt5645); | ||
2886 | static irqreturn_t rt5645_irq(int irq, void *data); | ||
2887 | |||
2470 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2888 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
2471 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack) | 2889 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, |
2890 | struct snd_soc_jack *btn_jack) | ||
2472 | { | 2891 | { |
2473 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2892 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
2474 | 2893 | ||
2475 | rt5645->hp_jack = hp_jack; | 2894 | rt5645->hp_jack = hp_jack; |
2476 | rt5645->mic_jack = mic_jack; | 2895 | rt5645->mic_jack = mic_jack; |
2477 | rt5645_jack_detect(codec); | 2896 | rt5645->btn_jack = btn_jack; |
2897 | if (rt5645->btn_jack && rt5645->codec_type == CODEC_TYPE_RT5650) { | ||
2898 | rt5645->en_button_func = true; | ||
2899 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
2900 | RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ); | ||
2901 | regmap_update_bits(rt5645->regmap, RT5645_DEPOP_M1, | ||
2902 | RT5645_HP_CB_MASK, RT5645_HP_CB_PU); | ||
2903 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL1, | ||
2904 | RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL); | ||
2905 | } | ||
2906 | rt5645_irq(0, rt5645); | ||
2478 | 2907 | ||
2479 | return 0; | 2908 | return 0; |
2480 | } | 2909 | } |
@@ -2485,7 +2914,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
2485 | struct rt5645_priv *rt5645 = | 2914 | struct rt5645_priv *rt5645 = |
2486 | container_of(work, struct rt5645_priv, jack_detect_work.work); | 2915 | container_of(work, struct rt5645_priv, jack_detect_work.work); |
2487 | 2916 | ||
2488 | rt5645_jack_detect(rt5645->codec); | 2917 | rt5645_irq_detection(rt5645); |
2489 | } | 2918 | } |
2490 | 2919 | ||
2491 | static irqreturn_t rt5645_irq(int irq, void *data) | 2920 | static irqreturn_t rt5645_irq(int irq, void *data) |
@@ -2498,6 +2927,123 @@ static irqreturn_t rt5645_irq(int irq, void *data) | |||
2498 | return IRQ_HANDLED; | 2927 | return IRQ_HANDLED; |
2499 | } | 2928 | } |
2500 | 2929 | ||
2930 | static int rt5645_button_detect(struct snd_soc_codec *codec) | ||
2931 | { | ||
2932 | int btn_type, val; | ||
2933 | |||
2934 | val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1); | ||
2935 | pr_debug("val=0x%x\n", val); | ||
2936 | btn_type = val & 0xfff0; | ||
2937 | snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val); | ||
2938 | |||
2939 | return btn_type; | ||
2940 | } | ||
2941 | |||
2942 | static int rt5645_irq_detection(struct rt5645_priv *rt5645) | ||
2943 | { | ||
2944 | int val, btn_type, gpio_state = 0, report = 0; | ||
2945 | |||
2946 | if (!rt5645->codec) | ||
2947 | return -EINVAL; | ||
2948 | |||
2949 | switch (rt5645->pdata.jd_mode) { | ||
2950 | case 0: /* Not using rt5645 JD */ | ||
2951 | if (rt5645->gpiod_hp_det) { | ||
2952 | gpio_state = gpiod_get_value(rt5645->gpiod_hp_det); | ||
2953 | dev_dbg(rt5645->codec->dev, "gpio_state = %d\n", | ||
2954 | gpio_state); | ||
2955 | report = rt5645_jack_detect(rt5645->codec, gpio_state); | ||
2956 | } | ||
2957 | snd_soc_jack_report(rt5645->hp_jack, | ||
2958 | report, SND_JACK_HEADPHONE); | ||
2959 | snd_soc_jack_report(rt5645->mic_jack, | ||
2960 | report, SND_JACK_MICROPHONE); | ||
2961 | return report; | ||
2962 | case 1: /* 2 port */ | ||
2963 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; | ||
2964 | break; | ||
2965 | default: /* 1 port */ | ||
2966 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0020; | ||
2967 | break; | ||
2968 | |||
2969 | } | ||
2970 | |||
2971 | switch (val) { | ||
2972 | /* jack in */ | ||
2973 | case 0x30: /* 2 port */ | ||
2974 | case 0x0: /* 1 port or 2 port */ | ||
2975 | if (rt5645->jack_type == 0) { | ||
2976 | report = rt5645_jack_detect(rt5645->codec, 1); | ||
2977 | /* for push button and jack out */ | ||
2978 | break; | ||
2979 | } | ||
2980 | btn_type = 0; | ||
2981 | if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { | ||
2982 | /* button pressed */ | ||
2983 | report = SND_JACK_HEADSET; | ||
2984 | btn_type = rt5645_button_detect(rt5645->codec); | ||
2985 | /* rt5650 can report three kinds of button behavior, | ||
2986 | one click, double click and hold. However, | ||
2987 | currently we will report button pressed/released | ||
2988 | event. So all the three button behaviors are | ||
2989 | treated as button pressed. */ | ||
2990 | switch (btn_type) { | ||
2991 | case 0x8000: | ||
2992 | case 0x4000: | ||
2993 | case 0x2000: | ||
2994 | report |= SND_JACK_BTN_0; | ||
2995 | break; | ||
2996 | case 0x1000: | ||
2997 | case 0x0800: | ||
2998 | case 0x0400: | ||
2999 | report |= SND_JACK_BTN_1; | ||
3000 | break; | ||
3001 | case 0x0200: | ||
3002 | case 0x0100: | ||
3003 | case 0x0080: | ||
3004 | report |= SND_JACK_BTN_2; | ||
3005 | break; | ||
3006 | case 0x0040: | ||
3007 | case 0x0020: | ||
3008 | case 0x0010: | ||
3009 | report |= SND_JACK_BTN_3; | ||
3010 | break; | ||
3011 | case 0x0000: /* unpressed */ | ||
3012 | break; | ||
3013 | default: | ||
3014 | dev_err(rt5645->codec->dev, | ||
3015 | "Unexpected button code 0x%04x\n", | ||
3016 | btn_type); | ||
3017 | break; | ||
3018 | } | ||
3019 | } | ||
3020 | if (btn_type == 0)/* button release */ | ||
3021 | report = rt5645->jack_type; | ||
3022 | |||
3023 | break; | ||
3024 | /* jack out */ | ||
3025 | case 0x70: /* 2 port */ | ||
3026 | case 0x10: /* 2 port */ | ||
3027 | case 0x20: /* 1 port */ | ||
3028 | report = 0; | ||
3029 | snd_soc_update_bits(rt5645->codec, | ||
3030 | RT5645_INT_IRQ_ST, 0x1, 0x0); | ||
3031 | rt5645_jack_detect(rt5645->codec, 0); | ||
3032 | break; | ||
3033 | default: | ||
3034 | break; | ||
3035 | } | ||
3036 | |||
3037 | snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); | ||
3038 | snd_soc_jack_report(rt5645->mic_jack, report, SND_JACK_MICROPHONE); | ||
3039 | if (rt5645->en_button_func) | ||
3040 | snd_soc_jack_report(rt5645->btn_jack, | ||
3041 | report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
3042 | SND_JACK_BTN_2 | SND_JACK_BTN_3); | ||
3043 | |||
3044 | return report; | ||
3045 | } | ||
3046 | |||
2501 | static int rt5645_probe(struct snd_soc_codec *codec) | 3047 | static int rt5645_probe(struct snd_soc_codec *codec) |
2502 | { | 3048 | { |
2503 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 3049 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
@@ -2520,12 +3066,10 @@ static int rt5645_probe(struct snd_soc_codec *codec) | |||
2520 | break; | 3066 | break; |
2521 | } | 3067 | } |
2522 | 3068 | ||
2523 | rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF); | 3069 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
2524 | |||
2525 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); | ||
2526 | 3070 | ||
2527 | /* for JD function */ | 3071 | /* for JD function */ |
2528 | if (rt5645->pdata.en_jd_func) { | 3072 | if (rt5645->pdata.jd_mode) { |
2529 | snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power"); | 3073 | snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power"); |
2530 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | 3074 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); |
2531 | snd_soc_dapm_sync(&codec->dapm); | 3075 | snd_soc_dapm_sync(&codec->dapm); |
@@ -2656,6 +3200,55 @@ static const struct i2c_device_id rt5645_i2c_id[] = { | |||
2656 | }; | 3200 | }; |
2657 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); | 3201 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); |
2658 | 3202 | ||
3203 | #ifdef CONFIG_ACPI | ||
3204 | static struct acpi_device_id rt5645_acpi_match[] = { | ||
3205 | { "10EC5645", 0 }, | ||
3206 | { "10EC5650", 0 }, | ||
3207 | {}, | ||
3208 | }; | ||
3209 | MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); | ||
3210 | #endif | ||
3211 | |||
3212 | static struct rt5645_platform_data *rt5645_pdata; | ||
3213 | |||
3214 | static struct rt5645_platform_data strago_platform_data = { | ||
3215 | .dmic1_data_pin = RT5645_DMIC1_DISABLE, | ||
3216 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, | ||
3217 | .jd_mode = 3, | ||
3218 | }; | ||
3219 | |||
3220 | static int strago_quirk_cb(const struct dmi_system_id *id) | ||
3221 | { | ||
3222 | rt5645_pdata = &strago_platform_data; | ||
3223 | |||
3224 | return 1; | ||
3225 | } | ||
3226 | |||
3227 | static struct dmi_system_id dmi_platform_intel_braswell[] = { | ||
3228 | { | ||
3229 | .ident = "Intel Strago", | ||
3230 | .callback = strago_quirk_cb, | ||
3231 | .matches = { | ||
3232 | DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), | ||
3233 | }, | ||
3234 | }, | ||
3235 | { } | ||
3236 | }; | ||
3237 | |||
3238 | static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev) | ||
3239 | { | ||
3240 | rt5645->pdata.in2_diff = device_property_read_bool(dev, | ||
3241 | "realtek,in2-differential"); | ||
3242 | device_property_read_u32(dev, | ||
3243 | "realtek,dmic1-data-pin", &rt5645->pdata.dmic1_data_pin); | ||
3244 | device_property_read_u32(dev, | ||
3245 | "realtek,dmic2-data-pin", &rt5645->pdata.dmic2_data_pin); | ||
3246 | device_property_read_u32(dev, | ||
3247 | "realtek,jd-mode", &rt5645->pdata.jd_mode); | ||
3248 | |||
3249 | return 0; | ||
3250 | } | ||
3251 | |||
2659 | static int rt5645_i2c_probe(struct i2c_client *i2c, | 3252 | static int rt5645_i2c_probe(struct i2c_client *i2c, |
2660 | const struct i2c_device_id *id) | 3253 | const struct i2c_device_id *id) |
2661 | { | 3254 | { |
@@ -2674,6 +3267,18 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2674 | 3267 | ||
2675 | if (pdata) | 3268 | if (pdata) |
2676 | rt5645->pdata = *pdata; | 3269 | rt5645->pdata = *pdata; |
3270 | else if (dmi_check_system(dmi_platform_intel_braswell)) | ||
3271 | rt5645->pdata = *rt5645_pdata; | ||
3272 | else | ||
3273 | rt5645_parse_dt(rt5645, &i2c->dev); | ||
3274 | |||
3275 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", | ||
3276 | GPIOD_IN); | ||
3277 | |||
3278 | if (IS_ERR(rt5645->gpiod_hp_det)) { | ||
3279 | dev_err(&i2c->dev, "failed to initialize gpiod\n"); | ||
3280 | return PTR_ERR(rt5645->gpiod_hp_det); | ||
3281 | } | ||
2677 | 3282 | ||
2678 | rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap); | 3283 | rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap); |
2679 | if (IS_ERR(rt5645->regmap)) { | 3284 | if (IS_ERR(rt5645->regmap)) { |
@@ -2699,6 +3304,13 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2699 | return -ENODEV; | 3304 | return -ENODEV; |
2700 | } | 3305 | } |
2701 | 3306 | ||
3307 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | ||
3308 | ret = rt5650_calibration(rt5645); | ||
3309 | |||
3310 | if (ret < 0) | ||
3311 | pr_err("calibration failed!\n"); | ||
3312 | } | ||
3313 | |||
2702 | regmap_write(rt5645->regmap, RT5645_RESET, 0); | 3314 | regmap_write(rt5645->regmap, RT5645_RESET, 0); |
2703 | 3315 | ||
2704 | ret = regmap_register_patch(rt5645->regmap, init_list, | 3316 | ret = regmap_register_patch(rt5645->regmap, init_list, |
@@ -2718,84 +3330,76 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2718 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, | 3330 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, |
2719 | RT5645_IN_DF2, RT5645_IN_DF2); | 3331 | RT5645_IN_DF2, RT5645_IN_DF2); |
2720 | 3332 | ||
2721 | if (rt5645->pdata.dmic_en) { | 3333 | if (rt5645->pdata.dmic1_data_pin || rt5645->pdata.dmic2_data_pin) { |
2722 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | 3334 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, |
2723 | RT5645_GP2_PIN_MASK, RT5645_GP2_PIN_DMIC1_SCL); | 3335 | RT5645_GP2_PIN_MASK, RT5645_GP2_PIN_DMIC1_SCL); |
3336 | } | ||
3337 | switch (rt5645->pdata.dmic1_data_pin) { | ||
3338 | case RT5645_DMIC_DATA_IN2N: | ||
3339 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | ||
3340 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_IN2N); | ||
3341 | break; | ||
2724 | 3342 | ||
2725 | switch (rt5645->pdata.dmic1_data_pin) { | 3343 | case RT5645_DMIC_DATA_GPIO5: |
2726 | case RT5645_DMIC_DATA_IN2N: | 3344 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2727 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | 3345 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO5); |
2728 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_IN2N); | 3346 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, |
2729 | break; | 3347 | RT5645_GP5_PIN_MASK, RT5645_GP5_PIN_DMIC1_SDA); |
2730 | 3348 | break; | |
2731 | case RT5645_DMIC_DATA_GPIO5: | ||
2732 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | ||
2733 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO5); | ||
2734 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
2735 | RT5645_GP5_PIN_MASK, RT5645_GP5_PIN_DMIC1_SDA); | ||
2736 | break; | ||
2737 | |||
2738 | case RT5645_DMIC_DATA_GPIO11: | ||
2739 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | ||
2740 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO11); | ||
2741 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
2742 | RT5645_GP11_PIN_MASK, | ||
2743 | RT5645_GP11_PIN_DMIC1_SDA); | ||
2744 | break; | ||
2745 | 3349 | ||
2746 | default: | 3350 | case RT5645_DMIC_DATA_GPIO11: |
2747 | break; | 3351 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2748 | } | 3352 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO11); |
3353 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
3354 | RT5645_GP11_PIN_MASK, | ||
3355 | RT5645_GP11_PIN_DMIC1_SDA); | ||
3356 | break; | ||
2749 | 3357 | ||
2750 | switch (rt5645->pdata.dmic2_data_pin) { | 3358 | default: |
2751 | case RT5645_DMIC_DATA_IN2P: | 3359 | break; |
2752 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | 3360 | } |
2753 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_IN2P); | ||
2754 | break; | ||
2755 | 3361 | ||
2756 | case RT5645_DMIC_DATA_GPIO6: | 3362 | switch (rt5645->pdata.dmic2_data_pin) { |
2757 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | 3363 | case RT5645_DMIC_DATA_IN2P: |
2758 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO6); | 3364 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2759 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | 3365 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_IN2P); |
2760 | RT5645_GP6_PIN_MASK, RT5645_GP6_PIN_DMIC2_SDA); | 3366 | break; |
2761 | break; | ||
2762 | 3367 | ||
2763 | case RT5645_DMIC_DATA_GPIO10: | 3368 | case RT5645_DMIC_DATA_GPIO6: |
2764 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | 3369 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2765 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO10); | 3370 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO6); |
2766 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | 3371 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, |
2767 | RT5645_GP10_PIN_MASK, | 3372 | RT5645_GP6_PIN_MASK, RT5645_GP6_PIN_DMIC2_SDA); |
2768 | RT5645_GP10_PIN_DMIC2_SDA); | 3373 | break; |
2769 | break; | ||
2770 | 3374 | ||
2771 | case RT5645_DMIC_DATA_GPIO12: | 3375 | case RT5645_DMIC_DATA_GPIO10: |
2772 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, | 3376 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2773 | RT5645_DMIC_1_DP_MASK, RT5645_DMIC_2_DP_GPIO12); | 3377 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO10); |
2774 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | 3378 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, |
2775 | RT5645_GP12_PIN_MASK, | 3379 | RT5645_GP10_PIN_MASK, |
2776 | RT5645_GP12_PIN_DMIC2_SDA); | 3380 | RT5645_GP10_PIN_DMIC2_SDA); |
2777 | break; | 3381 | break; |
2778 | 3382 | ||
2779 | default: | 3383 | case RT5645_DMIC_DATA_GPIO12: |
2780 | break; | 3384 | regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, |
2781 | } | 3385 | RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO12); |
3386 | regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, | ||
3387 | RT5645_GP12_PIN_MASK, | ||
3388 | RT5645_GP12_PIN_DMIC2_SDA); | ||
3389 | break; | ||
2782 | 3390 | ||
3391 | default: | ||
3392 | break; | ||
2783 | } | 3393 | } |
2784 | 3394 | ||
2785 | if (rt5645->pdata.en_jd_func) { | 3395 | if (rt5645->pdata.jd_mode) { |
2786 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | 3396 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, |
2787 | RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU, | 3397 | RT5645_IRQ_CLK_GATE_CTRL, |
2788 | RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU); | 3398 | RT5645_IRQ_CLK_GATE_CTRL); |
2789 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, | 3399 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, |
2790 | RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); | 3400 | RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); |
2791 | regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3, | ||
2792 | RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL, | ||
2793 | RT5645_JD_CBJ_EN | RT5645_JD_CBJ_POL); | ||
2794 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | 3401 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, |
2795 | RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); | 3402 | RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); |
2796 | } | ||
2797 | |||
2798 | if (rt5645->pdata.jd_mode) { | ||
2799 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3403 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
2800 | RT5645_IRQ_JD_1_1_EN, RT5645_IRQ_JD_1_1_EN); | 3404 | RT5645_IRQ_JD_1_1_EN, RT5645_IRQ_JD_1_1_EN); |
2801 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | 3405 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, |
@@ -2827,6 +3431,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2827 | } | 3431 | } |
2828 | } | 3432 | } |
2829 | 3433 | ||
3434 | INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); | ||
3435 | |||
2830 | if (rt5645->i2c->irq) { | 3436 | if (rt5645->i2c->irq) { |
2831 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | 3437 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, |
2832 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 3438 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
@@ -2835,18 +3441,6 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2835 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); | 3441 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); |
2836 | } | 3442 | } |
2837 | 3443 | ||
2838 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) { | ||
2839 | ret = gpio_request(rt5645->pdata.hp_det_gpio, "rt5645"); | ||
2840 | if (ret) | ||
2841 | dev_err(&i2c->dev, "Fail gpio_request hp_det_gpio\n"); | ||
2842 | |||
2843 | ret = gpio_direction_input(rt5645->pdata.hp_det_gpio); | ||
2844 | if (ret) | ||
2845 | dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); | ||
2846 | } | ||
2847 | |||
2848 | INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); | ||
2849 | |||
2850 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 3444 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2851 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 3445 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2852 | } | 3446 | } |
@@ -2860,9 +3454,6 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
2860 | 3454 | ||
2861 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | 3455 | cancel_delayed_work_sync(&rt5645->jack_detect_work); |
2862 | 3456 | ||
2863 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) | ||
2864 | gpio_free(rt5645->pdata.hp_det_gpio); | ||
2865 | |||
2866 | snd_soc_unregister_codec(&i2c->dev); | 3457 | snd_soc_unregister_codec(&i2c->dev); |
2867 | 3458 | ||
2868 | return 0; | 3459 | return 0; |
@@ -2872,6 +3463,7 @@ static struct i2c_driver rt5645_i2c_driver = { | |||
2872 | .driver = { | 3463 | .driver = { |
2873 | .name = "rt5645", | 3464 | .name = "rt5645", |
2874 | .owner = THIS_MODULE, | 3465 | .owner = THIS_MODULE, |
3466 | .acpi_match_table = ACPI_PTR(rt5645_acpi_match), | ||
2875 | }, | 3467 | }, |
2876 | .probe = rt5645_i2c_probe, | 3468 | .probe = rt5645_i2c_probe, |
2877 | .remove = rt5645_i2c_remove, | 3469 | .remove = rt5645_i2c_remove, |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index db78e9462876..0353a6a273ab 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -105,6 +105,7 @@ | |||
105 | #define RT5645_TDM_CTRL_1 0x77 | 105 | #define RT5645_TDM_CTRL_1 0x77 |
106 | #define RT5645_TDM_CTRL_2 0x78 | 106 | #define RT5645_TDM_CTRL_2 0x78 |
107 | #define RT5645_TDM_CTRL_3 0x79 | 107 | #define RT5645_TDM_CTRL_3 0x79 |
108 | #define RT5650_TDM_CTRL_4 0x7a | ||
108 | 109 | ||
109 | /* Function - Analog */ | 110 | /* Function - Analog */ |
110 | #define RT5645_GLB_CLK 0x80 | 111 | #define RT5645_GLB_CLK 0x80 |
@@ -942,10 +943,6 @@ | |||
942 | #define RT5645_I2S2_SDI_I2S2 (0x1 << 6) | 943 | #define RT5645_I2S2_SDI_I2S2 (0x1 << 6) |
943 | 944 | ||
944 | /* ADC/DAC Clock Control 1 (0x73) */ | 945 | /* ADC/DAC Clock Control 1 (0x73) */ |
945 | #define RT5645_I2S_BCLK_MS1_MASK (0x1 << 15) | ||
946 | #define RT5645_I2S_BCLK_MS1_SFT 15 | ||
947 | #define RT5645_I2S_BCLK_MS1_32 (0x0 << 15) | ||
948 | #define RT5645_I2S_BCLK_MS1_64 (0x1 << 15) | ||
949 | #define RT5645_I2S_PD1_MASK (0x7 << 12) | 946 | #define RT5645_I2S_PD1_MASK (0x7 << 12) |
950 | #define RT5645_I2S_PD1_SFT 12 | 947 | #define RT5645_I2S_PD1_SFT 12 |
951 | #define RT5645_I2S_PD1_1 (0x0 << 12) | 948 | #define RT5645_I2S_PD1_1 (0x0 << 12) |
@@ -1067,13 +1064,14 @@ | |||
1067 | #define RT5645_SCLK_SRC_SFT 14 | 1064 | #define RT5645_SCLK_SRC_SFT 14 |
1068 | #define RT5645_SCLK_SRC_MCLK (0x0 << 14) | 1065 | #define RT5645_SCLK_SRC_MCLK (0x0 << 14) |
1069 | #define RT5645_SCLK_SRC_PLL1 (0x1 << 14) | 1066 | #define RT5645_SCLK_SRC_PLL1 (0x1 << 14) |
1070 | #define RT5645_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */ | 1067 | #define RT5645_SCLK_SRC_RCCLK (0x2 << 14) |
1071 | #define RT5645_PLL1_SRC_MASK (0x3 << 12) | 1068 | #define RT5645_PLL1_SRC_MASK (0x7 << 11) |
1072 | #define RT5645_PLL1_SRC_SFT 12 | 1069 | #define RT5645_PLL1_SRC_SFT 11 |
1073 | #define RT5645_PLL1_SRC_MCLK (0x0 << 12) | 1070 | #define RT5645_PLL1_SRC_MCLK (0x0 << 11) |
1074 | #define RT5645_PLL1_SRC_BCLK1 (0x1 << 12) | 1071 | #define RT5645_PLL1_SRC_BCLK1 (0x1 << 11) |
1075 | #define RT5645_PLL1_SRC_BCLK2 (0x2 << 12) | 1072 | #define RT5645_PLL1_SRC_BCLK2 (0x2 << 11) |
1076 | #define RT5645_PLL1_SRC_BCLK3 (0x3 << 12) | 1073 | #define RT5645_PLL1_SRC_BCLK3 (0x3 << 11) |
1074 | #define RT5645_PLL1_SRC_RCCLK (0x4 << 11) | ||
1077 | #define RT5645_PLL1_PD_MASK (0x1 << 3) | 1075 | #define RT5645_PLL1_PD_MASK (0x1 << 3) |
1078 | #define RT5645_PLL1_PD_SFT 3 | 1076 | #define RT5645_PLL1_PD_SFT 3 |
1079 | #define RT5645_PLL1_PD_1 (0x0 << 3) | 1077 | #define RT5645_PLL1_PD_1 (0x0 << 3) |
@@ -2147,6 +2145,7 @@ enum { | |||
2147 | }; | 2145 | }; |
2148 | 2146 | ||
2149 | enum { | 2147 | enum { |
2148 | RT5645_DMIC1_DISABLE, | ||
2150 | RT5645_DMIC_DATA_IN2P, | 2149 | RT5645_DMIC_DATA_IN2P, |
2151 | RT5645_DMIC_DATA_GPIO6, | 2150 | RT5645_DMIC_DATA_GPIO6, |
2152 | RT5645_DMIC_DATA_GPIO10, | 2151 | RT5645_DMIC_DATA_GPIO10, |
@@ -2154,6 +2153,7 @@ enum { | |||
2154 | }; | 2153 | }; |
2155 | 2154 | ||
2156 | enum { | 2155 | enum { |
2156 | RT5645_DMIC2_DISABLE, | ||
2157 | RT5645_DMIC_DATA_IN2N, | 2157 | RT5645_DMIC_DATA_IN2N, |
2158 | RT5645_DMIC_DATA_GPIO5, | 2158 | RT5645_DMIC_DATA_GPIO5, |
2159 | RT5645_DMIC_DATA_GPIO11, | 2159 | RT5645_DMIC_DATA_GPIO11, |
@@ -2182,8 +2182,10 @@ struct rt5645_priv { | |||
2182 | struct rt5645_platform_data pdata; | 2182 | struct rt5645_platform_data pdata; |
2183 | struct regmap *regmap; | 2183 | struct regmap *regmap; |
2184 | struct i2c_client *i2c; | 2184 | struct i2c_client *i2c; |
2185 | struct gpio_desc *gpiod_hp_det; | ||
2185 | struct snd_soc_jack *hp_jack; | 2186 | struct snd_soc_jack *hp_jack; |
2186 | struct snd_soc_jack *mic_jack; | 2187 | struct snd_soc_jack *mic_jack; |
2188 | struct snd_soc_jack *btn_jack; | ||
2187 | struct delayed_work jack_detect_work; | 2189 | struct delayed_work jack_detect_work; |
2188 | 2190 | ||
2189 | int codec_type; | 2191 | int codec_type; |
@@ -2196,9 +2198,12 @@ struct rt5645_priv { | |||
2196 | int pll_src; | 2198 | int pll_src; |
2197 | int pll_in; | 2199 | int pll_in; |
2198 | int pll_out; | 2200 | int pll_out; |
2201 | |||
2202 | int jack_type; | ||
2203 | bool en_button_func; | ||
2199 | }; | 2204 | }; |
2200 | 2205 | ||
2201 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2206 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
2202 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack); | 2207 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, |
2203 | 2208 | struct snd_soc_jack *btn_jack); | |
2204 | #endif /* __RT5645_H__ */ | 2209 | #endif /* __RT5645_H__ */ |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 9f4c7be6d798..a3506e193abc 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -1571,7 +1571,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec, | |||
1571 | { | 1571 | { |
1572 | switch (level) { | 1572 | switch (level) { |
1573 | case SND_SOC_BIAS_PREPARE: | 1573 | case SND_SOC_BIAS_PREPARE: |
1574 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 1574 | if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) { |
1575 | snd_soc_update_bits(codec, RT5651_PWR_ANLG1, | 1575 | snd_soc_update_bits(codec, RT5651_PWR_ANLG1, |
1576 | RT5651_PWR_VREF1 | RT5651_PWR_MB | | 1576 | RT5651_PWR_VREF1 | RT5651_PWR_MB | |
1577 | RT5651_PWR_BG | RT5651_PWR_VREF2, | 1577 | RT5651_PWR_BG | RT5651_PWR_VREF2, |
@@ -1604,7 +1604,6 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec, | |||
1604 | default: | 1604 | default: |
1605 | break; | 1605 | break; |
1606 | } | 1606 | } |
1607 | codec->dapm.bias_level = level; | ||
1608 | 1607 | ||
1609 | return 0; | 1608 | return 0; |
1610 | } | 1609 | } |
@@ -1625,7 +1624,7 @@ static int rt5651_probe(struct snd_soc_codec *codec) | |||
1625 | RT5651_PWR_FV1 | RT5651_PWR_FV2, | 1624 | RT5651_PWR_FV1 | RT5651_PWR_FV2, |
1626 | RT5651_PWR_FV1 | RT5651_PWR_FV2); | 1625 | RT5651_PWR_FV1 | RT5651_PWR_FV2); |
1627 | 1626 | ||
1628 | rt5651_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1627 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
1629 | 1628 | ||
1630 | return 0; | 1629 | return 0; |
1631 | } | 1630 | } |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index cc7f84a150a7..a9123d414178 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -51,12 +51,11 @@ static const struct regmap_range_cfg rt5670_ranges[] = { | |||
51 | .window_len = 0x1, }, | 51 | .window_len = 0x1, }, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct reg_default init_list[] = { | 54 | static const struct reg_default init_list[] = { |
55 | { RT5670_PR_BASE + 0x14, 0x9a8a }, | 55 | { RT5670_PR_BASE + 0x14, 0x9a8a }, |
56 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, | 56 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, |
57 | { RT5670_PR_BASE + 0x3d, 0x3640 }, | 57 | { RT5670_PR_BASE + 0x3d, 0x3640 }, |
58 | }; | 58 | }; |
59 | #define RT5670_INIT_REG_LEN ARRAY_SIZE(init_list) | ||
60 | 59 | ||
61 | static const struct reg_default rt5670_reg[] = { | 60 | static const struct reg_default rt5670_reg[] = { |
62 | { 0x00, 0x0000 }, | 61 | { 0x00, 0x0000 }, |
@@ -416,12 +415,12 @@ static bool rt5670_readable_register(struct device *dev, unsigned int reg) | |||
416 | static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert) | 415 | static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert) |
417 | { | 416 | { |
418 | int val; | 417 | int val; |
418 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
419 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 419 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
420 | 420 | ||
421 | if (jack_insert) { | 421 | if (jack_insert) { |
422 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 422 | snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); |
423 | "Mic Det Power"); | 423 | snd_soc_dapm_sync(dapm); |
424 | snd_soc_dapm_sync(&codec->dapm); | ||
425 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x0); | 424 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x0); |
426 | snd_soc_update_bits(codec, RT5670_CJ_CTRL2, | 425 | snd_soc_update_bits(codec, RT5670_CJ_CTRL2, |
427 | RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD, | 426 | RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD, |
@@ -447,15 +446,15 @@ static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert) | |||
447 | } else { | 446 | } else { |
448 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); | 447 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); |
449 | rt5670->jack_type = SND_JACK_HEADPHONE; | 448 | rt5670->jack_type = SND_JACK_HEADPHONE; |
450 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | 449 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
451 | snd_soc_dapm_sync(&codec->dapm); | 450 | snd_soc_dapm_sync(dapm); |
452 | } | 451 | } |
453 | } else { | 452 | } else { |
454 | snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x0); | 453 | snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x0); |
455 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); | 454 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); |
456 | rt5670->jack_type = 0; | 455 | rt5670->jack_type = 0; |
457 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | 456 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
458 | snd_soc_dapm_sync(&codec->dapm); | 457 | snd_soc_dapm_sync(dapm); |
459 | } | 458 | } |
460 | 459 | ||
461 | return rt5670->jack_type; | 460 | return rt5670->jack_type; |
@@ -2603,7 +2602,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, | |||
2603 | 2602 | ||
2604 | switch (level) { | 2603 | switch (level) { |
2605 | case SND_SOC_BIAS_PREPARE: | 2604 | case SND_SOC_BIAS_PREPARE: |
2606 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 2605 | if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) { |
2607 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | 2606 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, |
2608 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | 2607 | RT5670_PWR_VREF1 | RT5670_PWR_MB | |
2609 | RT5670_PWR_BG | RT5670_PWR_VREF2, | 2608 | RT5670_PWR_BG | RT5670_PWR_VREF2, |
@@ -2647,30 +2646,30 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, | |||
2647 | default: | 2646 | default: |
2648 | break; | 2647 | break; |
2649 | } | 2648 | } |
2650 | codec->dapm.bias_level = level; | ||
2651 | 2649 | ||
2652 | return 0; | 2650 | return 0; |
2653 | } | 2651 | } |
2654 | 2652 | ||
2655 | static int rt5670_probe(struct snd_soc_codec *codec) | 2653 | static int rt5670_probe(struct snd_soc_codec *codec) |
2656 | { | 2654 | { |
2655 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2657 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 2656 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
2658 | 2657 | ||
2659 | switch (snd_soc_read(codec, RT5670_RESET) & RT5670_ID_MASK) { | 2658 | switch (snd_soc_read(codec, RT5670_RESET) & RT5670_ID_MASK) { |
2660 | case RT5670_ID_5670: | 2659 | case RT5670_ID_5670: |
2661 | case RT5670_ID_5671: | 2660 | case RT5670_ID_5671: |
2662 | snd_soc_dapm_new_controls(&codec->dapm, | 2661 | snd_soc_dapm_new_controls(dapm, |
2663 | rt5670_specific_dapm_widgets, | 2662 | rt5670_specific_dapm_widgets, |
2664 | ARRAY_SIZE(rt5670_specific_dapm_widgets)); | 2663 | ARRAY_SIZE(rt5670_specific_dapm_widgets)); |
2665 | snd_soc_dapm_add_routes(&codec->dapm, | 2664 | snd_soc_dapm_add_routes(dapm, |
2666 | rt5670_specific_dapm_routes, | 2665 | rt5670_specific_dapm_routes, |
2667 | ARRAY_SIZE(rt5670_specific_dapm_routes)); | 2666 | ARRAY_SIZE(rt5670_specific_dapm_routes)); |
2668 | break; | 2667 | break; |
2669 | case RT5670_ID_5672: | 2668 | case RT5670_ID_5672: |
2670 | snd_soc_dapm_new_controls(&codec->dapm, | 2669 | snd_soc_dapm_new_controls(dapm, |
2671 | rt5672_specific_dapm_widgets, | 2670 | rt5672_specific_dapm_widgets, |
2672 | ARRAY_SIZE(rt5672_specific_dapm_widgets)); | 2671 | ARRAY_SIZE(rt5672_specific_dapm_widgets)); |
2673 | snd_soc_dapm_add_routes(&codec->dapm, | 2672 | snd_soc_dapm_add_routes(dapm, |
2674 | rt5672_specific_dapm_routes, | 2673 | rt5672_specific_dapm_routes, |
2675 | ARRAY_SIZE(rt5672_specific_dapm_routes)); | 2674 | ARRAY_SIZE(rt5672_specific_dapm_routes)); |
2676 | break; | 2675 | break; |
@@ -2809,7 +2808,7 @@ static const struct i2c_device_id rt5670_i2c_id[] = { | |||
2809 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | 2808 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); |
2810 | 2809 | ||
2811 | #ifdef CONFIG_ACPI | 2810 | #ifdef CONFIG_ACPI |
2812 | static struct acpi_device_id rt5670_acpi_match[] = { | 2811 | static const struct acpi_device_id rt5670_acpi_match[] = { |
2813 | { "10EC5670", 0}, | 2812 | { "10EC5670", 0}, |
2814 | { }, | 2813 | { }, |
2815 | }; | 2814 | }; |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index af182586712d..31d969ac1192 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -62,6 +62,9 @@ static const struct reg_default init_list[] = { | |||
62 | {RT5677_PR_BASE + 0x1e, 0x0000}, | 62 | {RT5677_PR_BASE + 0x1e, 0x0000}, |
63 | {RT5677_PR_BASE + 0x12, 0x0eaa}, | 63 | {RT5677_PR_BASE + 0x12, 0x0eaa}, |
64 | {RT5677_PR_BASE + 0x14, 0x018a}, | 64 | {RT5677_PR_BASE + 0x14, 0x018a}, |
65 | {RT5677_PR_BASE + 0x15, 0x0490}, | ||
66 | {RT5677_PR_BASE + 0x38, 0x0f71}, | ||
67 | {RT5677_PR_BASE + 0x39, 0x0f71}, | ||
65 | }; | 68 | }; |
66 | #define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list) | 69 | #define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list) |
67 | 70 | ||
@@ -817,7 +820,7 @@ static int rt5677_dsp_vad_put(struct snd_kcontrol *kcontrol, | |||
817 | 820 | ||
818 | rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0]; | 821 | rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0]; |
819 | 822 | ||
820 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 823 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
821 | rt5677_set_dsp_vad(codec, rt5677->dsp_vad_en); | 824 | rt5677_set_dsp_vad(codec, rt5677->dsp_vad_en); |
822 | 825 | ||
823 | return 0; | 826 | return 0; |
@@ -914,7 +917,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
914 | { | 917 | { |
915 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 918 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
916 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 919 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
917 | int idx = rl6231_calc_dmic_clk(rt5677->sysclk); | 920 | int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8); |
918 | 921 | ||
919 | if (idx < 0) | 922 | if (idx < 0) |
920 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 923 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
@@ -1057,6 +1060,7 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec, | |||
1057 | unsigned int asrc5_mask = 0, asrc5_value = 0; | 1060 | unsigned int asrc5_mask = 0, asrc5_value = 0; |
1058 | unsigned int asrc6_mask = 0, asrc6_value = 0; | 1061 | unsigned int asrc6_mask = 0, asrc6_value = 0; |
1059 | unsigned int asrc7_mask = 0, asrc7_value = 0; | 1062 | unsigned int asrc7_mask = 0, asrc7_value = 0; |
1063 | unsigned int asrc8_mask = 0, asrc8_value = 0; | ||
1060 | 1064 | ||
1061 | switch (clk_src) { | 1065 | switch (clk_src) { |
1062 | case RT5677_CLK_SEL_SYS: | 1066 | case RT5677_CLK_SEL_SYS: |
@@ -1193,10 +1197,108 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec, | |||
1193 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask, | 1197 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask, |
1194 | asrc7_value); | 1198 | asrc7_value); |
1195 | 1199 | ||
1200 | /* ASRC 8 */ | ||
1201 | if (filter_mask & RT5677_I2S1_SOURCE) { | ||
1202 | asrc8_mask |= RT5677_I2S1_CLK_SEL_MASK; | ||
1203 | asrc8_value = (asrc8_value & ~RT5677_I2S1_CLK_SEL_MASK) | ||
1204 | | ((clk_src - 1) << RT5677_I2S1_CLK_SEL_SFT); | ||
1205 | } | ||
1206 | |||
1207 | if (filter_mask & RT5677_I2S2_SOURCE) { | ||
1208 | asrc8_mask |= RT5677_I2S2_CLK_SEL_MASK; | ||
1209 | asrc8_value = (asrc8_value & ~RT5677_I2S2_CLK_SEL_MASK) | ||
1210 | | ((clk_src - 1) << RT5677_I2S2_CLK_SEL_SFT); | ||
1211 | } | ||
1212 | |||
1213 | if (filter_mask & RT5677_I2S3_SOURCE) { | ||
1214 | asrc8_mask |= RT5677_I2S3_CLK_SEL_MASK; | ||
1215 | asrc8_value = (asrc8_value & ~RT5677_I2S3_CLK_SEL_MASK) | ||
1216 | | ((clk_src - 1) << RT5677_I2S3_CLK_SEL_SFT); | ||
1217 | } | ||
1218 | |||
1219 | if (filter_mask & RT5677_I2S4_SOURCE) { | ||
1220 | asrc8_mask |= RT5677_I2S4_CLK_SEL_MASK; | ||
1221 | asrc8_value = (asrc8_value & ~RT5677_I2S4_CLK_SEL_MASK) | ||
1222 | | ((clk_src - 1) << RT5677_I2S4_CLK_SEL_SFT); | ||
1223 | } | ||
1224 | |||
1225 | if (asrc8_mask) | ||
1226 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_8, asrc8_mask, | ||
1227 | asrc8_value); | ||
1228 | |||
1196 | return 0; | 1229 | return 0; |
1197 | } | 1230 | } |
1198 | EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src); | 1231 | EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src); |
1199 | 1232 | ||
1233 | static int rt5677_dmic_use_asrc(struct snd_soc_dapm_widget *source, | ||
1234 | struct snd_soc_dapm_widget *sink) | ||
1235 | { | ||
1236 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
1237 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
1238 | unsigned int asrc_setting; | ||
1239 | |||
1240 | switch (source->shift) { | ||
1241 | case 11: | ||
1242 | regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); | ||
1243 | asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >> | ||
1244 | RT5677_AD_STO1_CLK_SEL_SFT; | ||
1245 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1246 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1247 | return 1; | ||
1248 | break; | ||
1249 | |||
1250 | case 10: | ||
1251 | regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); | ||
1252 | asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >> | ||
1253 | RT5677_AD_STO2_CLK_SEL_SFT; | ||
1254 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1255 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1256 | return 1; | ||
1257 | break; | ||
1258 | |||
1259 | case 9: | ||
1260 | regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); | ||
1261 | asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >> | ||
1262 | RT5677_AD_STO3_CLK_SEL_SFT; | ||
1263 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1264 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1265 | return 1; | ||
1266 | break; | ||
1267 | |||
1268 | case 8: | ||
1269 | regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); | ||
1270 | asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >> | ||
1271 | RT5677_AD_STO4_CLK_SEL_SFT; | ||
1272 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1273 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1274 | return 1; | ||
1275 | break; | ||
1276 | |||
1277 | case 7: | ||
1278 | regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); | ||
1279 | asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >> | ||
1280 | RT5677_AD_MONOL_CLK_SEL_SFT; | ||
1281 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1282 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1283 | return 1; | ||
1284 | break; | ||
1285 | |||
1286 | case 6: | ||
1287 | regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); | ||
1288 | asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >> | ||
1289 | RT5677_AD_MONOR_CLK_SEL_SFT; | ||
1290 | if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && | ||
1291 | asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) | ||
1292 | return 1; | ||
1293 | break; | ||
1294 | |||
1295 | default: | ||
1296 | break; | ||
1297 | } | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1200 | /* Digital Mixer */ | 1302 | /* Digital Mixer */ |
1201 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { | 1303 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { |
1202 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, | 1304 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, |
@@ -2476,7 +2578,7 @@ static int rt5677_vref_event(struct snd_soc_dapm_widget *w, | |||
2476 | 2578 | ||
2477 | switch (event) { | 2579 | switch (event) { |
2478 | case SND_SOC_DAPM_POST_PMU: | 2580 | case SND_SOC_DAPM_POST_PMU: |
2479 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON && | 2581 | if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_ON && |
2480 | !rt5677->is_vref_slow) { | 2582 | !rt5677->is_vref_slow) { |
2481 | mdelay(20); | 2583 | mdelay(20); |
2482 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | 2584 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, |
@@ -3054,12 +3156,12 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
3054 | }; | 3156 | }; |
3055 | 3157 | ||
3056 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | 3158 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { |
3057 | { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc }, | 3159 | { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", rt5677_dmic_use_asrc }, |
3058 | { "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc }, | 3160 | { "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", rt5677_dmic_use_asrc }, |
3059 | { "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", can_use_asrc }, | 3161 | { "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", rt5677_dmic_use_asrc }, |
3060 | { "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", can_use_asrc }, | 3162 | { "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", rt5677_dmic_use_asrc }, |
3061 | { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc }, | 3163 | { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", rt5677_dmic_use_asrc }, |
3062 | { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc }, | 3164 | { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", rt5677_dmic_use_asrc }, |
3063 | { "I2S1", NULL, "I2S1 ASRC", can_use_asrc}, | 3165 | { "I2S1", NULL, "I2S1 ASRC", can_use_asrc}, |
3064 | { "I2S2", NULL, "I2S2 ASRC", can_use_asrc}, | 3166 | { "I2S2", NULL, "I2S2 ASRC", can_use_asrc}, |
3065 | { "I2S3", NULL, "I2S3 ASRC", can_use_asrc}, | 3167 | { "I2S3", NULL, "I2S3 ASRC", can_use_asrc}, |
@@ -4350,7 +4452,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
4350 | break; | 4452 | break; |
4351 | 4453 | ||
4352 | case SND_SOC_BIAS_PREPARE: | 4454 | case SND_SOC_BIAS_PREPARE: |
4353 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 4455 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { |
4354 | rt5677_set_dsp_vad(codec, false); | 4456 | rt5677_set_dsp_vad(codec, false); |
4355 | 4457 | ||
4356 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | 4458 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, |
@@ -4392,7 +4494,6 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
4392 | default: | 4494 | default: |
4393 | break; | 4495 | break; |
4394 | } | 4496 | } |
4395 | codec->dapm.bias_level = level; | ||
4396 | 4497 | ||
4397 | return 0; | 4498 | return 0; |
4398 | } | 4499 | } |
@@ -4603,22 +4704,23 @@ static void rt5677_free_gpio(struct i2c_client *i2c) | |||
4603 | 4704 | ||
4604 | static int rt5677_probe(struct snd_soc_codec *codec) | 4705 | static int rt5677_probe(struct snd_soc_codec *codec) |
4605 | { | 4706 | { |
4707 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
4606 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4708 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4607 | int i; | 4709 | int i; |
4608 | 4710 | ||
4609 | rt5677->codec = codec; | 4711 | rt5677->codec = codec; |
4610 | 4712 | ||
4611 | if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) { | 4713 | if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) { |
4612 | snd_soc_dapm_add_routes(&codec->dapm, | 4714 | snd_soc_dapm_add_routes(dapm, |
4613 | rt5677_dmic2_clk_2, | 4715 | rt5677_dmic2_clk_2, |
4614 | ARRAY_SIZE(rt5677_dmic2_clk_2)); | 4716 | ARRAY_SIZE(rt5677_dmic2_clk_2)); |
4615 | } else { /*use dmic1 clock by default*/ | 4717 | } else { /*use dmic1 clock by default*/ |
4616 | snd_soc_dapm_add_routes(&codec->dapm, | 4718 | snd_soc_dapm_add_routes(dapm, |
4617 | rt5677_dmic2_clk_1, | 4719 | rt5677_dmic2_clk_1, |
4618 | ARRAY_SIZE(rt5677_dmic2_clk_1)); | 4720 | ARRAY_SIZE(rt5677_dmic2_clk_1)); |
4619 | } | 4721 | } |
4620 | 4722 | ||
4621 | rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF); | 4723 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
4622 | 4724 | ||
4623 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); | 4725 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); |
4624 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); | 4726 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); |
@@ -4664,6 +4766,8 @@ static int rt5677_remove(struct snd_soc_codec *codec) | |||
4664 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); | 4766 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); |
4665 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4767 | if (gpio_is_valid(rt5677->pow_ldo2)) |
4666 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | 4768 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); |
4769 | if (gpio_is_valid(rt5677->reset_pin)) | ||
4770 | gpio_set_value_cansleep(rt5677->reset_pin, 0); | ||
4667 | 4771 | ||
4668 | return 0; | 4772 | return 0; |
4669 | } | 4773 | } |
@@ -4679,6 +4783,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec) | |||
4679 | 4783 | ||
4680 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4784 | if (gpio_is_valid(rt5677->pow_ldo2)) |
4681 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | 4785 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); |
4786 | if (gpio_is_valid(rt5677->reset_pin)) | ||
4787 | gpio_set_value_cansleep(rt5677->reset_pin, 0); | ||
4682 | } | 4788 | } |
4683 | 4789 | ||
4684 | return 0; | 4790 | return 0; |
@@ -4689,10 +4795,13 @@ static int rt5677_resume(struct snd_soc_codec *codec) | |||
4689 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4795 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4690 | 4796 | ||
4691 | if (!rt5677->dsp_vad_en) { | 4797 | if (!rt5677->dsp_vad_en) { |
4692 | if (gpio_is_valid(rt5677->pow_ldo2)) { | 4798 | if (gpio_is_valid(rt5677->pow_ldo2)) |
4693 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); | 4799 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); |
4800 | if (gpio_is_valid(rt5677->reset_pin)) | ||
4801 | gpio_set_value_cansleep(rt5677->reset_pin, 1); | ||
4802 | if (gpio_is_valid(rt5677->pow_ldo2) || | ||
4803 | gpio_is_valid(rt5677->reset_pin)) | ||
4694 | msleep(10); | 4804 | msleep(10); |
4695 | } | ||
4696 | 4805 | ||
4697 | regcache_cache_only(rt5677->regmap, false); | 4806 | regcache_cache_only(rt5677->regmap, false); |
4698 | regcache_sync(rt5677->regmap); | 4807 | regcache_sync(rt5677->regmap); |
@@ -4930,6 +5039,8 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | |||
4930 | 5039 | ||
4931 | rt5677->pow_ldo2 = of_get_named_gpio(np, | 5040 | rt5677->pow_ldo2 = of_get_named_gpio(np, |
4932 | "realtek,pow-ldo2-gpio", 0); | 5041 | "realtek,pow-ldo2-gpio", 0); |
5042 | rt5677->reset_pin = of_get_named_gpio(np, | ||
5043 | "realtek,reset-gpio", 0); | ||
4933 | 5044 | ||
4934 | /* | 5045 | /* |
4935 | * POW_LDO2 is optional (it may be statically tied on the board). | 5046 | * POW_LDO2 is optional (it may be statically tied on the board). |
@@ -4940,6 +5051,9 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | |||
4940 | if (!gpio_is_valid(rt5677->pow_ldo2) && | 5051 | if (!gpio_is_valid(rt5677->pow_ldo2) && |
4941 | (rt5677->pow_ldo2 != -ENOENT)) | 5052 | (rt5677->pow_ldo2 != -ENOENT)) |
4942 | return rt5677->pow_ldo2; | 5053 | return rt5677->pow_ldo2; |
5054 | if (!gpio_is_valid(rt5677->reset_pin) && | ||
5055 | (rt5677->reset_pin != -ENOENT)) | ||
5056 | return rt5677->reset_pin; | ||
4943 | 5057 | ||
4944 | of_property_read_u8_array(np, "realtek,gpio-config", | 5058 | of_property_read_u8_array(np, "realtek,gpio-config", |
4945 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); | 5059 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); |
@@ -5041,6 +5155,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
5041 | } | 5155 | } |
5042 | } else { | 5156 | } else { |
5043 | rt5677->pow_ldo2 = -EINVAL; | 5157 | rt5677->pow_ldo2 = -EINVAL; |
5158 | rt5677->reset_pin = -EINVAL; | ||
5044 | } | 5159 | } |
5045 | 5160 | ||
5046 | if (gpio_is_valid(rt5677->pow_ldo2)) { | 5161 | if (gpio_is_valid(rt5677->pow_ldo2)) { |
@@ -5052,6 +5167,21 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
5052 | rt5677->pow_ldo2, ret); | 5167 | rt5677->pow_ldo2, ret); |
5053 | return ret; | 5168 | return ret; |
5054 | } | 5169 | } |
5170 | } | ||
5171 | |||
5172 | if (gpio_is_valid(rt5677->reset_pin)) { | ||
5173 | ret = devm_gpio_request_one(&i2c->dev, rt5677->reset_pin, | ||
5174 | GPIOF_OUT_INIT_HIGH, | ||
5175 | "RT5677 RESET"); | ||
5176 | if (ret < 0) { | ||
5177 | dev_err(&i2c->dev, "Failed to request RESET %d: %d\n", | ||
5178 | rt5677->reset_pin, ret); | ||
5179 | return ret; | ||
5180 | } | ||
5181 | } | ||
5182 | |||
5183 | if (gpio_is_valid(rt5677->pow_ldo2) || | ||
5184 | gpio_is_valid(rt5677->reset_pin)) { | ||
5055 | /* Wait a while until I2C bus becomes available. The datasheet | 5185 | /* Wait a while until I2C bus becomes available. The datasheet |
5056 | * does not specify the exact we should wait but startup | 5186 | * does not specify the exact we should wait but startup |
5057 | * sequence mentiones at least a few milliseconds. | 5187 | * sequence mentiones at least a few milliseconds. |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 9dceb41d18ea..7eca38a23255 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -1446,6 +1446,16 @@ | |||
1446 | #define RT5677_DSP_OB_4_7_CLK_SEL_MASK (0xf << 8) | 1446 | #define RT5677_DSP_OB_4_7_CLK_SEL_MASK (0xf << 8) |
1447 | #define RT5677_DSP_OB_4_7_CLK_SEL_SFT 8 | 1447 | #define RT5677_DSP_OB_4_7_CLK_SEL_SFT 8 |
1448 | 1448 | ||
1449 | /* ASRC Control 8 (0x8a) */ | ||
1450 | #define RT5677_I2S1_CLK_SEL_MASK (0xf << 12) | ||
1451 | #define RT5677_I2S1_CLK_SEL_SFT 12 | ||
1452 | #define RT5677_I2S2_CLK_SEL_MASK (0xf << 8) | ||
1453 | #define RT5677_I2S2_CLK_SEL_SFT 8 | ||
1454 | #define RT5677_I2S3_CLK_SEL_MASK (0xf << 4) | ||
1455 | #define RT5677_I2S3_CLK_SEL_SFT 4 | ||
1456 | #define RT5677_I2S4_CLK_SEL_MASK (0xf) | ||
1457 | #define RT5677_I2S4_CLK_SEL_SFT 0 | ||
1458 | |||
1449 | /* VAD Function Control 4 (0x9f) */ | 1459 | /* VAD Function Control 4 (0x9f) */ |
1450 | #define RT5677_VAD_SRC_MASK (0x7 << 8) | 1460 | #define RT5677_VAD_SRC_MASK (0x7 << 8) |
1451 | #define RT5677_VAD_SRC_SFT 8 | 1461 | #define RT5677_VAD_SRC_SFT 8 |
@@ -1744,6 +1754,10 @@ enum { | |||
1744 | RT5677_AD_MONO_R_FILTER = (0x1 << 12), | 1754 | RT5677_AD_MONO_R_FILTER = (0x1 << 12), |
1745 | RT5677_DSP_OB_0_3_FILTER = (0x1 << 13), | 1755 | RT5677_DSP_OB_0_3_FILTER = (0x1 << 13), |
1746 | RT5677_DSP_OB_4_7_FILTER = (0x1 << 14), | 1756 | RT5677_DSP_OB_4_7_FILTER = (0x1 << 14), |
1757 | RT5677_I2S1_SOURCE = (0x1 << 15), | ||
1758 | RT5677_I2S2_SOURCE = (0x1 << 16), | ||
1759 | RT5677_I2S3_SOURCE = (0x1 << 17), | ||
1760 | RT5677_I2S4_SOURCE = (0x1 << 18), | ||
1747 | }; | 1761 | }; |
1748 | 1762 | ||
1749 | struct rt5677_priv { | 1763 | struct rt5677_priv { |
@@ -1762,6 +1776,7 @@ struct rt5677_priv { | |||
1762 | int pll_in; | 1776 | int pll_in; |
1763 | int pll_out; | 1777 | int pll_out; |
1764 | int pow_ldo2; /* POW_LDO2 pin */ | 1778 | int pow_ldo2; /* POW_LDO2 pin */ |
1779 | int reset_pin; /* RESET pin */ | ||
1765 | enum rt5677_type type; | 1780 | enum rt5677_type type; |
1766 | #ifdef CONFIG_GPIOLIB | 1781 | #ifdef CONFIG_GPIOLIB |
1767 | struct gpio_chip gpio_chip; | 1782 | struct gpio_chip gpio_chip; |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3593a1496056..e673f6ceb521 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -948,7 +948,7 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, | |||
948 | case SND_SOC_BIAS_PREPARE: | 948 | case SND_SOC_BIAS_PREPARE: |
949 | break; | 949 | break; |
950 | case SND_SOC_BIAS_STANDBY: | 950 | case SND_SOC_BIAS_STANDBY: |
951 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 951 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
952 | ret = regulator_bulk_enable( | 952 | ret = regulator_bulk_enable( |
953 | ARRAY_SIZE(sgtl5000->supplies), | 953 | ARRAY_SIZE(sgtl5000->supplies), |
954 | sgtl5000->supplies); | 954 | sgtl5000->supplies); |
@@ -979,7 +979,6 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, | |||
979 | break; | 979 | break; |
980 | } | 980 | } |
981 | 981 | ||
982 | codec->dapm.bias_level = level; | ||
983 | return 0; | 982 | return 0; |
984 | } | 983 | } |
985 | 984 | ||
@@ -1092,6 +1091,19 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg) | |||
1092 | } | 1091 | } |
1093 | 1092 | ||
1094 | /* | 1093 | /* |
1094 | * This precalculated table contains all (vag_val * 100 / lo_calcntrl) results | ||
1095 | * to select an appropriate lo_vol_* in SGTL5000_CHIP_LINE_OUT_VOL | ||
1096 | * The calculatation was done for all possible register values which | ||
1097 | * is the array index and the following formula: 10^((idx−15)/40) * 100 | ||
1098 | */ | ||
1099 | static const u8 vol_quot_table[] = { | ||
1100 | 42, 45, 47, 50, 53, 56, 60, 63, | ||
1101 | 67, 71, 75, 79, 84, 89, 94, 100, | ||
1102 | 106, 112, 119, 126, 133, 141, 150, 158, | ||
1103 | 168, 178, 188, 200, 211, 224, 237, 251 | ||
1104 | }; | ||
1105 | |||
1106 | /* | ||
1095 | * sgtl5000 has 3 internal power supplies: | 1107 | * sgtl5000 has 3 internal power supplies: |
1096 | * 1. VAG, normally set to vdda/2 | 1108 | * 1. VAG, normally set to vdda/2 |
1097 | * 2. charge pump, set to different value | 1109 | * 2. charge pump, set to different value |
@@ -1111,6 +1123,10 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) | |||
1111 | u16 ana_pwr; | 1123 | u16 ana_pwr; |
1112 | u16 lreg_ctrl; | 1124 | u16 lreg_ctrl; |
1113 | int vag; | 1125 | int vag; |
1126 | int lo_vag; | ||
1127 | int vol_quot; | ||
1128 | int lo_vol; | ||
1129 | size_t i; | ||
1114 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1130 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1115 | 1131 | ||
1116 | vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); | 1132 | vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); |
@@ -1198,23 +1214,45 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) | |||
1198 | SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT); | 1214 | SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT); |
1199 | 1215 | ||
1200 | /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */ | 1216 | /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */ |
1201 | vag = vddio / 2; | 1217 | lo_vag = vddio / 2; |
1202 | if (vag <= SGTL5000_LINE_OUT_GND_BASE) | 1218 | if (lo_vag <= SGTL5000_LINE_OUT_GND_BASE) |
1203 | vag = 0; | 1219 | lo_vag = 0; |
1204 | else if (vag >= SGTL5000_LINE_OUT_GND_BASE + | 1220 | else if (lo_vag >= SGTL5000_LINE_OUT_GND_BASE + |
1205 | SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX) | 1221 | SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX) |
1206 | vag = SGTL5000_LINE_OUT_GND_MAX; | 1222 | lo_vag = SGTL5000_LINE_OUT_GND_MAX; |
1207 | else | 1223 | else |
1208 | vag = (vag - SGTL5000_LINE_OUT_GND_BASE) / | 1224 | lo_vag = (lo_vag - SGTL5000_LINE_OUT_GND_BASE) / |
1209 | SGTL5000_LINE_OUT_GND_STP; | 1225 | SGTL5000_LINE_OUT_GND_STP; |
1210 | 1226 | ||
1211 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL, | 1227 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL, |
1212 | SGTL5000_LINE_OUT_CURRENT_MASK | | 1228 | SGTL5000_LINE_OUT_CURRENT_MASK | |
1213 | SGTL5000_LINE_OUT_GND_MASK, | 1229 | SGTL5000_LINE_OUT_GND_MASK, |
1214 | vag << SGTL5000_LINE_OUT_GND_SHIFT | | 1230 | lo_vag << SGTL5000_LINE_OUT_GND_SHIFT | |
1215 | SGTL5000_LINE_OUT_CURRENT_360u << | 1231 | SGTL5000_LINE_OUT_CURRENT_360u << |
1216 | SGTL5000_LINE_OUT_CURRENT_SHIFT); | 1232 | SGTL5000_LINE_OUT_CURRENT_SHIFT); |
1217 | 1233 | ||
1234 | /* | ||
1235 | * Set lineout output level in range (0..31) | ||
1236 | * the same value is used for right and left channel | ||
1237 | * | ||
1238 | * Searching for a suitable index solving this formula: | ||
1239 | * idx = 40 * log10(vag_val / lo_cagcntrl) + 15 | ||
1240 | */ | ||
1241 | vol_quot = (vag * 100) / lo_vag; | ||
1242 | lo_vol = 0; | ||
1243 | for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) { | ||
1244 | if (vol_quot >= vol_quot_table[i]) | ||
1245 | lo_vol = i; | ||
1246 | else | ||
1247 | break; | ||
1248 | } | ||
1249 | |||
1250 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_VOL, | ||
1251 | SGTL5000_LINE_OUT_VOL_RIGHT_MASK | | ||
1252 | SGTL5000_LINE_OUT_VOL_LEFT_MASK, | ||
1253 | lo_vol << SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT | | ||
1254 | lo_vol << SGTL5000_LINE_OUT_VOL_LEFT_SHIFT); | ||
1255 | |||
1218 | return 0; | 1256 | return 0; |
1219 | } | 1257 | } |
1220 | 1258 | ||
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 0a8e43c98a07..29cb44256044 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -395,7 +395,7 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = { | |||
395 | 395 | ||
396 | static int sirf_audio_codec_probe(struct snd_soc_codec *codec) | 396 | static int sirf_audio_codec_probe(struct snd_soc_codec *codec) |
397 | { | 397 | { |
398 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 398 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
399 | 399 | ||
400 | pm_runtime_enable(codec->dev); | 400 | pm_runtime_enable(codec->dev); |
401 | 401 | ||
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 7947c0ebb1ed..3a7de0159f24 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -194,7 +194,7 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, | |||
194 | break; | 194 | break; |
195 | 195 | ||
196 | case SND_SOC_BIAS_PREPARE: | 196 | case SND_SOC_BIAS_PREPARE: |
197 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 197 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { |
198 | pr_debug("vaud_bias powering up pll\n"); | 198 | pr_debug("vaud_bias powering up pll\n"); |
199 | /* power up the pll */ | 199 | /* power up the pll */ |
200 | snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5)); | 200 | snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5)); |
@@ -205,17 +205,22 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, | |||
205 | break; | 205 | break; |
206 | 206 | ||
207 | case SND_SOC_BIAS_STANDBY: | 207 | case SND_SOC_BIAS_STANDBY: |
208 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 208 | switch (snd_soc_codec_get_bias_level(codec)) { |
209 | case SND_SOC_BIAS_OFF: | ||
209 | pr_debug("vaud_bias power up rail\n"); | 210 | pr_debug("vaud_bias power up rail\n"); |
210 | /* power up the rail */ | 211 | /* power up the rail */ |
211 | snd_soc_write(codec, SN95031_VAUD, | 212 | snd_soc_write(codec, SN95031_VAUD, |
212 | BIT(2)|BIT(1)|BIT(0)); | 213 | BIT(2)|BIT(1)|BIT(0)); |
213 | msleep(1); | 214 | msleep(1); |
214 | } else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | 215 | break; |
216 | case SND_SOC_BIAS_PREPARE: | ||
215 | /* turn off pcm */ | 217 | /* turn off pcm */ |
216 | pr_debug("vaud_bias power dn pcm\n"); | 218 | pr_debug("vaud_bias power dn pcm\n"); |
217 | snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0); | 219 | snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0); |
218 | snd_soc_write(codec, SN95031_AUDPLLCTRL, 0); | 220 | snd_soc_write(codec, SN95031_AUDPLLCTRL, 0); |
221 | break; | ||
222 | default: | ||
223 | break; | ||
219 | } | 224 | } |
220 | break; | 225 | break; |
221 | 226 | ||
@@ -226,7 +231,6 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, | |||
226 | break; | 231 | break; |
227 | } | 232 | } |
228 | 233 | ||
229 | codec->dapm.bias_level = level; | ||
230 | return 0; | 234 | return 0; |
231 | } | 235 | } |
232 | 236 | ||
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 67ea55adb307..f30de7639bb9 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -510,7 +510,7 @@ static int ssm2518_set_bias_level(struct snd_soc_codec *codec, | |||
510 | case SND_SOC_BIAS_PREPARE: | 510 | case SND_SOC_BIAS_PREPARE: |
511 | break; | 511 | break; |
512 | case SND_SOC_BIAS_STANDBY: | 512 | case SND_SOC_BIAS_STANDBY: |
513 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 513 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
514 | ret = ssm2518_set_power(ssm2518, true); | 514 | ret = ssm2518_set_power(ssm2518, true); |
515 | break; | 515 | break; |
516 | case SND_SOC_BIAS_OFF: | 516 | case SND_SOC_BIAS_OFF: |
@@ -518,12 +518,7 @@ static int ssm2518_set_bias_level(struct snd_soc_codec *codec, | |||
518 | break; | 518 | break; |
519 | } | 519 | } |
520 | 520 | ||
521 | if (ret) | 521 | return ret; |
522 | return ret; | ||
523 | |||
524 | codec->dapm.bias_level = level; | ||
525 | |||
526 | return 0; | ||
527 | } | 522 | } |
528 | 523 | ||
529 | static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | 524 | static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 314eaece1b7d..69a773aeb13d 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -473,7 +473,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
473 | break; | 473 | break; |
474 | 474 | ||
475 | } | 475 | } |
476 | codec->dapm.bias_level = level; | ||
477 | return 0; | 476 | return 0; |
478 | } | 477 | } |
479 | 478 | ||
@@ -524,8 +523,8 @@ static int ssm2602_resume(struct snd_soc_codec *codec) | |||
524 | 523 | ||
525 | static int ssm2602_codec_probe(struct snd_soc_codec *codec) | 524 | static int ssm2602_codec_probe(struct snd_soc_codec *codec) |
526 | { | 525 | { |
526 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
527 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 527 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
528 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
529 | int ret; | 528 | int ret; |
530 | 529 | ||
531 | regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V, | 530 | regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V, |
@@ -549,7 +548,7 @@ static int ssm2602_codec_probe(struct snd_soc_codec *codec) | |||
549 | 548 | ||
550 | static int ssm2604_codec_probe(struct snd_soc_codec *codec) | 549 | static int ssm2604_codec_probe(struct snd_soc_codec *codec) |
551 | { | 550 | { |
552 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 551 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
553 | int ret; | 552 | int ret; |
554 | 553 | ||
555 | ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, | 554 | ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, |
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index a984485108cd..84a4f5ad8064 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -315,7 +315,13 @@ static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
315 | if (invert_fclk) | 315 | if (invert_fclk) |
316 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; | 316 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; |
317 | 317 | ||
318 | return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1); | 318 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, |
319 | SSM4567_SAI_CTRL_1_BCLK | | ||
320 | SSM4567_SAI_CTRL_1_FSYNC | | ||
321 | SSM4567_SAI_CTRL_1_LJ | | ||
322 | SSM4567_SAI_CTRL_1_TDM | | ||
323 | SSM4567_SAI_CTRL_1_PDM, | ||
324 | ctrl1); | ||
319 | } | 325 | } |
320 | 326 | ||
321 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) | 327 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) |
@@ -353,7 +359,7 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | |||
353 | case SND_SOC_BIAS_PREPARE: | 359 | case SND_SOC_BIAS_PREPARE: |
354 | break; | 360 | break; |
355 | case SND_SOC_BIAS_STANDBY: | 361 | case SND_SOC_BIAS_STANDBY: |
356 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 362 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
357 | ret = ssm4567_set_power(ssm4567, true); | 363 | ret = ssm4567_set_power(ssm4567, true); |
358 | break; | 364 | break; |
359 | case SND_SOC_BIAS_OFF: | 365 | case SND_SOC_BIAS_OFF: |
@@ -361,12 +367,7 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | |||
361 | break; | 367 | break; |
362 | } | 368 | } |
363 | 369 | ||
364 | if (ret) | 370 | return ret; |
365 | return ret; | ||
366 | |||
367 | codec->dapm.bias_level = level; | ||
368 | |||
369 | return 0; | ||
370 | } | 371 | } |
371 | 372 | ||
372 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { | 373 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 007a0e3bc273..60eff36260cb 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -819,7 +819,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, | |||
819 | break; | 819 | break; |
820 | 820 | ||
821 | case SND_SOC_BIAS_STANDBY: | 821 | case SND_SOC_BIAS_STANDBY: |
822 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 822 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
823 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 823 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
824 | sta32x->supplies); | 824 | sta32x->supplies); |
825 | if (ret != 0) { | 825 | if (ret != 0) { |
@@ -854,7 +854,6 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, | |||
854 | sta32x->supplies); | 854 | sta32x->supplies); |
855 | break; | 855 | break; |
856 | } | 856 | } |
857 | codec->dapm.bias_level = level; | ||
858 | return 0; | 857 | return 0; |
859 | } | 858 | } |
860 | 859 | ||
@@ -970,7 +969,7 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
970 | if (sta32x->pdata->needs_esd_watchdog) | 969 | if (sta32x->pdata->needs_esd_watchdog) |
971 | INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); | 970 | INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); |
972 | 971 | ||
973 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 972 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
974 | /* Bias level configuration will have done an extra enable */ | 973 | /* Bias level configuration will have done an extra enable */ |
975 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 974 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
976 | 975 | ||
@@ -1096,16 +1095,10 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, | |||
1096 | #endif | 1095 | #endif |
1097 | 1096 | ||
1098 | /* GPIOs */ | 1097 | /* GPIOs */ |
1099 | sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset"); | 1098 | sta32x->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", |
1100 | if (IS_ERR(sta32x->gpiod_nreset)) { | 1099 | GPIOD_OUT_LOW); |
1101 | ret = PTR_ERR(sta32x->gpiod_nreset); | 1100 | if (IS_ERR(sta32x->gpiod_nreset)) |
1102 | if (ret != -ENOENT && ret != -ENOSYS) | 1101 | return PTR_ERR(sta32x->gpiod_nreset); |
1103 | return ret; | ||
1104 | |||
1105 | sta32x->gpiod_nreset = NULL; | ||
1106 | } else { | ||
1107 | gpiod_direction_output(sta32x->gpiod_nreset, 0); | ||
1108 | } | ||
1109 | 1102 | ||
1110 | /* regulators */ | 1103 | /* regulators */ |
1111 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | 1104 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) |
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 669e3228241e..bd819a3f205a 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c | |||
@@ -853,7 +853,7 @@ static int sta350_set_bias_level(struct snd_soc_codec *codec, | |||
853 | break; | 853 | break; |
854 | 854 | ||
855 | case SND_SOC_BIAS_STANDBY: | 855 | case SND_SOC_BIAS_STANDBY: |
856 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 856 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
857 | ret = regulator_bulk_enable( | 857 | ret = regulator_bulk_enable( |
858 | ARRAY_SIZE(sta350->supplies), | 858 | ARRAY_SIZE(sta350->supplies), |
859 | sta350->supplies); | 859 | sta350->supplies); |
@@ -890,7 +890,6 @@ static int sta350_set_bias_level(struct snd_soc_codec *codec, | |||
890 | sta350->supplies); | 890 | sta350->supplies); |
891 | break; | 891 | break; |
892 | } | 892 | } |
893 | codec->dapm.bias_level = level; | ||
894 | return 0; | 893 | return 0; |
895 | } | 894 | } |
896 | 895 | ||
@@ -1037,7 +1036,7 @@ static int sta350_probe(struct snd_soc_codec *codec) | |||
1037 | sta350->coef_shadow[60] = 0x400000; | 1036 | sta350->coef_shadow[60] = 0x400000; |
1038 | sta350->coef_shadow[61] = 0x400000; | 1037 | sta350->coef_shadow[61] = 0x400000; |
1039 | 1038 | ||
1040 | sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1039 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1041 | /* Bias level configuration will have done an extra enable */ | 1040 | /* Bias level configuration will have done an extra enable */ |
1042 | regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); | 1041 | regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); |
1043 | 1042 | ||
@@ -1218,8 +1217,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c, | |||
1218 | if (IS_ERR(sta350->gpiod_nreset)) | 1217 | if (IS_ERR(sta350->gpiod_nreset)) |
1219 | return PTR_ERR(sta350->gpiod_nreset); | 1218 | return PTR_ERR(sta350->gpiod_nreset); |
1220 | 1219 | ||
1221 | sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down", | 1220 | sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down", |
1222 | GPIOD_OUT_LOW); | 1221 | GPIOD_OUT_LOW); |
1223 | if (IS_ERR(sta350->gpiod_power_down)) | 1222 | if (IS_ERR(sta350->gpiod_power_down)) |
1224 | return PTR_ERR(sta350->gpiod_power_down); | 1223 | return PTR_ERR(sta350->gpiod_power_down); |
1225 | 1224 | ||
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index b0f436d10125..4f70378b2cfb 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -165,7 +165,7 @@ static int sta529_set_bias_level(struct snd_soc_codec *codec, enum | |||
165 | FFX_CLK_ENB); | 165 | FFX_CLK_ENB); |
166 | break; | 166 | break; |
167 | case SND_SOC_BIAS_STANDBY: | 167 | case SND_SOC_BIAS_STANDBY: |
168 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 168 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
169 | regcache_sync(sta529->regmap); | 169 | regcache_sync(sta529->regmap); |
170 | snd_soc_update_bits(codec, STA529_FFXCFG0, | 170 | snd_soc_update_bits(codec, STA529_FFXCFG0, |
171 | POWER_CNTLMSAK, POWER_STDBY); | 171 | POWER_CNTLMSAK, POWER_STDBY); |
@@ -179,12 +179,6 @@ static int sta529_set_bias_level(struct snd_soc_codec *codec, enum | |||
179 | break; | 179 | break; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* | ||
183 | * store the label for powers down audio subsystem for suspend.This is | ||
184 | * used by soc core layer | ||
185 | */ | ||
186 | codec->dapm.bias_level = level; | ||
187 | |||
188 | return 0; | 182 | return 0; |
189 | 183 | ||
190 | } | 184 | } |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 6464caf72b21..ed4cca7f6779 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -236,7 +236,6 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
236 | stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff); | 236 | stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff); |
237 | break; | 237 | break; |
238 | } | 238 | } |
239 | codec->dapm.bias_level = level; | ||
240 | return 0; | 239 | return 0; |
241 | } | 240 | } |
242 | 241 | ||
@@ -321,7 +320,7 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
321 | .channels_max = 2, | 320 | .channels_max = 2, |
322 | .rates = SNDRV_PCM_RATE_32000 | \ | 321 | .rates = SNDRV_PCM_RATE_32000 | \ |
323 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | 322 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, |
324 | .formats = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, | 323 | .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE, |
325 | }, | 324 | }, |
326 | /* alsa ops */ | 325 | /* alsa ops */ |
327 | .ops = &stac9766_dai_ops_digital, | 326 | .ops = &stac9766_dai_ops_digital, |
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index dfb4ff5cc9ea..4f25a7d0efa2 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <sound/soc-dapm.h> | 34 | #include <sound/soc-dapm.h> |
35 | #include <sound/tlv.h> | 35 | #include <sound/tlv.h> |
36 | #include <sound/tas2552-plat.h> | 36 | #include <sound/tas2552-plat.h> |
37 | #include <dt-bindings/sound/tas2552.h> | ||
37 | 38 | ||
38 | #include "tas2552.h" | 39 | #include "tas2552.h" |
39 | 40 | ||
@@ -44,8 +45,8 @@ static struct reg_default tas2552_reg_defs[] = { | |||
44 | {TAS2552_OUTPUT_DATA, 0xc0}, | 45 | {TAS2552_OUTPUT_DATA, 0xc0}, |
45 | {TAS2552_PDM_CFG, 0x01}, | 46 | {TAS2552_PDM_CFG, 0x01}, |
46 | {TAS2552_PGA_GAIN, 0x00}, | 47 | {TAS2552_PGA_GAIN, 0x00}, |
47 | {TAS2552_BOOST_PT_CTRL, 0x0f}, | 48 | {TAS2552_BOOST_APT_CTRL, 0x0f}, |
48 | {TAS2552_RESERVED_0D, 0x00}, | 49 | {TAS2552_RESERVED_0D, 0xbe}, |
49 | {TAS2552_LIMIT_RATE_HYS, 0x08}, | 50 | {TAS2552_LIMIT_RATE_HYS, 0x08}, |
50 | {TAS2552_CFG_2, 0xef}, | 51 | {TAS2552_CFG_2, 0xef}, |
51 | {TAS2552_SER_CTRL_1, 0x00}, | 52 | {TAS2552_SER_CTRL_1, 0x00}, |
@@ -75,20 +76,47 @@ struct tas2552_data { | |||
75 | struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES]; | 76 | struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES]; |
76 | struct gpio_desc *enable_gpio; | 77 | struct gpio_desc *enable_gpio; |
77 | unsigned char regs[TAS2552_VBAT_DATA]; | 78 | unsigned char regs[TAS2552_VBAT_DATA]; |
78 | unsigned int mclk; | 79 | unsigned int pll_clkin; |
79 | }; | 80 | int pll_clk_id; |
81 | unsigned int pdm_clk; | ||
82 | int pdm_clk_id; | ||
80 | 83 | ||
81 | /* Input mux controls */ | 84 | unsigned int dai_fmt; |
82 | static const char *tas2552_input_texts[] = { | 85 | unsigned int tdm_delay; |
83 | "Digital", "Analog" | ||
84 | }; | 86 | }; |
85 | 87 | ||
88 | static int tas2552_post_event(struct snd_soc_dapm_widget *w, | ||
89 | struct snd_kcontrol *kcontrol, int event) | ||
90 | { | ||
91 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
92 | |||
93 | switch (event) { | ||
94 | case SND_SOC_DAPM_POST_PMU: | ||
95 | snd_soc_write(codec, TAS2552_RESERVED_0D, 0xc0); | ||
96 | snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), | ||
97 | (1 << 5)); | ||
98 | snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 0); | ||
99 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 0); | ||
100 | break; | ||
101 | case SND_SOC_DAPM_POST_PMD: | ||
102 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, | ||
103 | TAS2552_SWS); | ||
104 | snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 1); | ||
105 | snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 0); | ||
106 | snd_soc_write(codec, TAS2552_RESERVED_0D, 0xbe); | ||
107 | break; | ||
108 | } | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /* Input mux controls */ | ||
113 | static const char * const tas2552_input_texts[] = { | ||
114 | "Digital", "Analog" }; | ||
86 | static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, | 115 | static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, |
87 | tas2552_input_texts); | 116 | tas2552_input_texts); |
88 | 117 | ||
89 | static const struct snd_kcontrol_new tas2552_input_mux_control[] = { | 118 | static const struct snd_kcontrol_new tas2552_input_mux_control = |
90 | SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum) | 119 | SOC_DAPM_ENUM("Route", tas2552_input_mux_enum); |
91 | }; | ||
92 | 120 | ||
93 | static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = | 121 | static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = |
94 | { | 122 | { |
@@ -96,12 +124,13 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = | |||
96 | 124 | ||
97 | /* MUX Controls */ | 125 | /* MUX Controls */ |
98 | SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, | 126 | SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, |
99 | tas2552_input_mux_control), | 127 | &tas2552_input_mux_control), |
100 | 128 | ||
101 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), | 129 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), |
102 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | 130 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), |
103 | SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), | 131 | SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), |
104 | SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), | 132 | SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), |
133 | SND_SOC_DAPM_POST("Post Event", tas2552_post_event), | ||
105 | 134 | ||
106 | SND_SOC_DAPM_OUTPUT("OUT") | 135 | SND_SOC_DAPM_OUTPUT("OUT") |
107 | }; | 136 | }; |
@@ -116,125 +145,253 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = { | |||
116 | }; | 145 | }; |
117 | 146 | ||
118 | #ifdef CONFIG_PM | 147 | #ifdef CONFIG_PM |
119 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | 148 | static void tas2552_sw_shutdown(struct tas2552_data *tas2552, int sw_shutdown) |
120 | { | 149 | { |
121 | u8 cfg1_reg; | 150 | u8 cfg1_reg = 0; |
151 | |||
152 | if (!tas2552->codec) | ||
153 | return; | ||
122 | 154 | ||
123 | if (sw_shutdown) | 155 | if (sw_shutdown) |
124 | cfg1_reg = 0; | 156 | cfg1_reg = TAS2552_SWS; |
125 | else | ||
126 | cfg1_reg = TAS2552_SWS_MASK; | ||
127 | 157 | ||
128 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, | 158 | snd_soc_update_bits(tas2552->codec, TAS2552_CFG_1, TAS2552_SWS, |
129 | TAS2552_SWS_MASK, cfg1_reg); | 159 | cfg1_reg); |
130 | } | 160 | } |
131 | #endif | 161 | #endif |
132 | 162 | ||
133 | static int tas2552_hw_params(struct snd_pcm_substream *substream, | 163 | static int tas2552_setup_pll(struct snd_soc_codec *codec, |
134 | struct snd_pcm_hw_params *params, | 164 | struct snd_pcm_hw_params *params) |
135 | struct snd_soc_dai *dai) | ||
136 | { | 165 | { |
137 | struct snd_soc_codec *codec = dai->codec; | ||
138 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | 166 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); |
139 | int sample_rate, pll_clk; | 167 | bool bypass_pll = false; |
140 | int d; | 168 | unsigned int pll_clk = params_rate(params) * 512; |
141 | u8 p, j; | 169 | unsigned int pll_clkin = tas2552->pll_clkin; |
170 | u8 pll_enable; | ||
142 | 171 | ||
143 | if (!tas2552->mclk) | 172 | if (!pll_clkin) { |
144 | return -EINVAL; | 173 | if (tas2552->pll_clk_id != TAS2552_PLL_CLKIN_BCLK) |
174 | return -EINVAL; | ||
175 | |||
176 | pll_clkin = snd_soc_params_to_bclk(params); | ||
177 | pll_clkin += tas2552->tdm_delay; | ||
178 | } | ||
145 | 179 | ||
180 | pll_enable = snd_soc_read(codec, TAS2552_CFG_2) & TAS2552_PLL_ENABLE; | ||
146 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); | 181 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); |
147 | 182 | ||
148 | if (tas2552->mclk == TAS2552_245MHZ_CLK || | 183 | if (pll_clkin == pll_clk) |
149 | tas2552->mclk == TAS2552_225MHZ_CLK) { | 184 | bypass_pll = true; |
185 | |||
186 | if (bypass_pll) { | ||
150 | /* By pass the PLL configuration */ | 187 | /* By pass the PLL configuration */ |
151 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2, | 188 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2, |
152 | TAS2552_PLL_BYPASS_MASK, | 189 | TAS2552_PLL_BYPASS, TAS2552_PLL_BYPASS); |
153 | TAS2552_PLL_BYPASS); | ||
154 | } else { | 190 | } else { |
155 | /* Fill in the PLL control registers for J & D | 191 | /* Fill in the PLL control registers for J & D |
156 | * PLL_CLK = (.5 * freq * J.D) / 2^p | 192 | * pll_clk = (.5 * pll_clkin * J.D) / 2^p |
157 | * Need to fill in J and D here based on incoming freq | 193 | * Need to fill in J and D here based on incoming freq |
158 | */ | 194 | */ |
159 | p = snd_soc_read(codec, TAS2552_PLL_CTRL_1); | 195 | unsigned int d; |
196 | u8 j; | ||
197 | u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK; | ||
198 | u8 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1); | ||
199 | |||
160 | p = (p >> 7); | 200 | p = (p >> 7); |
161 | sample_rate = params_rate(params); | 201 | |
162 | 202 | recalc: | |
163 | if (sample_rate == 48000) | 203 | j = (pll_clk * 2 * (1 << p)) / pll_clkin; |
164 | pll_clk = TAS2552_245MHZ_CLK; | 204 | d = (pll_clk * 2 * (1 << p)) % pll_clkin; |
165 | else if (sample_rate == 44100) | 205 | d /= (pll_clkin / 10000); |
166 | pll_clk = TAS2552_225MHZ_CLK; | 206 | |
167 | else { | 207 | if (d && (pll_clkin < 512000 || pll_clkin > 9200000)) { |
168 | dev_vdbg(codec->dev, "Substream sample rate is not found %i\n", | 208 | if (tas2552->pll_clk_id == TAS2552_PLL_CLKIN_BCLK) { |
169 | params_rate(params)); | 209 | pll_clkin = 1800000; |
170 | return -EINVAL; | 210 | pll_sel = (TAS2552_PLL_CLKIN_1_8_FIXED << 3) & |
211 | TAS2552_PLL_SRC_MASK; | ||
212 | } else { | ||
213 | pll_clkin = snd_soc_params_to_bclk(params); | ||
214 | pll_clkin += tas2552->tdm_delay; | ||
215 | pll_sel = (TAS2552_PLL_CLKIN_BCLK << 3) & | ||
216 | TAS2552_PLL_SRC_MASK; | ||
217 | } | ||
218 | goto recalc; | ||
171 | } | 219 | } |
172 | 220 | ||
173 | j = (pll_clk * 2 * (1 << p)) / tas2552->mclk; | 221 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_PLL_SRC_MASK, |
174 | d = (pll_clk * 2 * (1 << p)) % tas2552->mclk; | 222 | pll_sel); |
175 | 223 | ||
176 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1, | 224 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1, |
177 | TAS2552_PLL_J_MASK, j); | 225 | TAS2552_PLL_J_MASK, j); |
226 | /* Will clear the PLL_BYPASS bit */ | ||
178 | snd_soc_write(codec, TAS2552_PLL_CTRL_2, | 227 | snd_soc_write(codec, TAS2552_PLL_CTRL_2, |
179 | (d >> 7) & TAS2552_PLL_D_UPPER_MASK); | 228 | TAS2552_PLL_D_UPPER(d)); |
180 | snd_soc_write(codec, TAS2552_PLL_CTRL_3, | 229 | snd_soc_write(codec, TAS2552_PLL_CTRL_3, |
181 | d & TAS2552_PLL_D_LOWER_MASK); | 230 | TAS2552_PLL_D_LOWER(d)); |
231 | } | ||
232 | |||
233 | /* Restore PLL status */ | ||
234 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, | ||
235 | pll_enable); | ||
182 | 236 | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int tas2552_hw_params(struct snd_pcm_substream *substream, | ||
241 | struct snd_pcm_hw_params *params, | ||
242 | struct snd_soc_dai *dai) | ||
243 | { | ||
244 | struct snd_soc_codec *codec = dai->codec; | ||
245 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | ||
246 | int cpf; | ||
247 | u8 ser_ctrl1_reg, wclk_rate; | ||
248 | |||
249 | switch (params_width(params)) { | ||
250 | case 16: | ||
251 | ser_ctrl1_reg = TAS2552_WORDLENGTH_16BIT; | ||
252 | cpf = 32 + tas2552->tdm_delay; | ||
253 | break; | ||
254 | case 20: | ||
255 | ser_ctrl1_reg = TAS2552_WORDLENGTH_20BIT; | ||
256 | cpf = 64 + tas2552->tdm_delay; | ||
257 | break; | ||
258 | case 24: | ||
259 | ser_ctrl1_reg = TAS2552_WORDLENGTH_24BIT; | ||
260 | cpf = 64 + tas2552->tdm_delay; | ||
261 | break; | ||
262 | case 32: | ||
263 | ser_ctrl1_reg = TAS2552_WORDLENGTH_32BIT; | ||
264 | cpf = 64 + tas2552->tdm_delay; | ||
265 | break; | ||
266 | default: | ||
267 | dev_err(codec->dev, "Not supported sample size: %d\n", | ||
268 | params_width(params)); | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | |||
272 | if (cpf <= 32) | ||
273 | ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_32; | ||
274 | else if (cpf <= 64) | ||
275 | ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_64; | ||
276 | else if (cpf <= 128) | ||
277 | ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_128; | ||
278 | else | ||
279 | ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_256; | ||
280 | |||
281 | snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, | ||
282 | TAS2552_WORDLENGTH_MASK | TAS2552_CLKSPERFRAME_MASK, | ||
283 | ser_ctrl1_reg); | ||
284 | |||
285 | switch (params_rate(params)) { | ||
286 | case 8000: | ||
287 | wclk_rate = TAS2552_WCLK_FREQ_8KHZ; | ||
288 | break; | ||
289 | case 11025: | ||
290 | case 12000: | ||
291 | wclk_rate = TAS2552_WCLK_FREQ_11_12KHZ; | ||
292 | break; | ||
293 | case 16000: | ||
294 | wclk_rate = TAS2552_WCLK_FREQ_16KHZ; | ||
295 | break; | ||
296 | case 22050: | ||
297 | case 24000: | ||
298 | wclk_rate = TAS2552_WCLK_FREQ_22_24KHZ; | ||
299 | break; | ||
300 | case 32000: | ||
301 | wclk_rate = TAS2552_WCLK_FREQ_32KHZ; | ||
302 | break; | ||
303 | case 44100: | ||
304 | case 48000: | ||
305 | wclk_rate = TAS2552_WCLK_FREQ_44_48KHZ; | ||
306 | break; | ||
307 | case 88200: | ||
308 | case 96000: | ||
309 | wclk_rate = TAS2552_WCLK_FREQ_88_96KHZ; | ||
310 | break; | ||
311 | case 176400: | ||
312 | case 192000: | ||
313 | wclk_rate = TAS2552_WCLK_FREQ_176_192KHZ; | ||
314 | break; | ||
315 | default: | ||
316 | dev_err(codec->dev, "Not supported sample rate: %d\n", | ||
317 | params_rate(params)); | ||
318 | return -EINVAL; | ||
183 | } | 319 | } |
184 | 320 | ||
321 | snd_soc_update_bits(codec, TAS2552_CFG_3, TAS2552_WCLK_FREQ_MASK, | ||
322 | wclk_rate); | ||
323 | |||
324 | return tas2552_setup_pll(codec, params); | ||
325 | } | ||
326 | |||
327 | #define TAS2552_DAI_FMT_MASK (TAS2552_BCLKDIR | \ | ||
328 | TAS2552_WCLKDIR | \ | ||
329 | TAS2552_DATAFORMAT_MASK) | ||
330 | static int tas2552_prepare(struct snd_pcm_substream *substream, | ||
331 | struct snd_soc_dai *dai) | ||
332 | { | ||
333 | struct snd_soc_codec *codec = dai->codec; | ||
334 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
335 | int delay = 0; | ||
336 | |||
337 | /* TDM slot selection only valid in DSP_A/_B mode */ | ||
338 | if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_A) | ||
339 | delay += (tas2552->tdm_delay + 1); | ||
340 | else if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_B) | ||
341 | delay += tas2552->tdm_delay; | ||
342 | |||
343 | /* Configure data delay */ | ||
344 | snd_soc_write(codec, TAS2552_SER_CTRL_2, delay); | ||
345 | |||
185 | return 0; | 346 | return 0; |
186 | } | 347 | } |
187 | 348 | ||
188 | static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 349 | static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
189 | { | 350 | { |
190 | struct snd_soc_codec *codec = dai->codec; | 351 | struct snd_soc_codec *codec = dai->codec; |
352 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | ||
191 | u8 serial_format; | 353 | u8 serial_format; |
192 | u8 serial_control_mask; | ||
193 | 354 | ||
194 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 355 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
195 | case SND_SOC_DAIFMT_CBS_CFS: | 356 | case SND_SOC_DAIFMT_CBS_CFS: |
196 | serial_format = 0x00; | 357 | serial_format = 0x00; |
197 | break; | 358 | break; |
198 | case SND_SOC_DAIFMT_CBS_CFM: | 359 | case SND_SOC_DAIFMT_CBS_CFM: |
199 | serial_format = TAS2552_WORD_CLK_MASK; | 360 | serial_format = TAS2552_WCLKDIR; |
200 | break; | 361 | break; |
201 | case SND_SOC_DAIFMT_CBM_CFS: | 362 | case SND_SOC_DAIFMT_CBM_CFS: |
202 | serial_format = TAS2552_BIT_CLK_MASK; | 363 | serial_format = TAS2552_BCLKDIR; |
203 | break; | 364 | break; |
204 | case SND_SOC_DAIFMT_CBM_CFM: | 365 | case SND_SOC_DAIFMT_CBM_CFM: |
205 | serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK); | 366 | serial_format = (TAS2552_BCLKDIR | TAS2552_WCLKDIR); |
206 | break; | 367 | break; |
207 | default: | 368 | default: |
208 | dev_vdbg(codec->dev, "DAI Format master is not found\n"); | 369 | dev_vdbg(codec->dev, "DAI Format master is not found\n"); |
209 | return -EINVAL; | 370 | return -EINVAL; |
210 | } | 371 | } |
211 | 372 | ||
212 | serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK; | 373 | switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | |
213 | 374 | SND_SOC_DAIFMT_INV_MASK)) { | |
214 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 375 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): |
215 | case SND_SOC_DAIFMT_I2S: | ||
216 | serial_format &= TAS2552_DAIFMT_I2S_MASK; | ||
217 | break; | 376 | break; |
218 | case SND_SOC_DAIFMT_DSP_A: | 377 | case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): |
219 | serial_format |= TAS2552_DAIFMT_DSP; | 378 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): |
379 | serial_format |= TAS2552_DATAFORMAT_DSP; | ||
220 | break; | 380 | break; |
221 | case SND_SOC_DAIFMT_RIGHT_J: | 381 | case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF): |
222 | serial_format |= TAS2552_DAIFMT_RIGHT_J; | 382 | serial_format |= TAS2552_DATAFORMAT_RIGHT_J; |
223 | break; | 383 | break; |
224 | case SND_SOC_DAIFMT_LEFT_J: | 384 | case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): |
225 | serial_format |= TAS2552_DAIFMT_LEFT_J; | 385 | serial_format |= TAS2552_DATAFORMAT_LEFT_J; |
226 | break; | 386 | break; |
227 | default: | 387 | default: |
228 | dev_vdbg(codec->dev, "DAI Format is not found\n"); | 388 | dev_vdbg(codec->dev, "DAI Format is not found\n"); |
229 | return -EINVAL; | 389 | return -EINVAL; |
230 | } | 390 | } |
391 | tas2552->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
231 | 392 | ||
232 | if (fmt & SND_SOC_DAIFMT_FORMAT_MASK) | 393 | snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, TAS2552_DAI_FMT_MASK, |
233 | serial_control_mask |= TAS2552_DATA_FORMAT_MASK; | 394 | serial_format); |
234 | |||
235 | snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask, | ||
236 | serial_format); | ||
237 | |||
238 | return 0; | 395 | return 0; |
239 | } | 396 | } |
240 | 397 | ||
@@ -243,23 +400,85 @@ static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
243 | { | 400 | { |
244 | struct snd_soc_codec *codec = dai->codec; | 401 | struct snd_soc_codec *codec = dai->codec; |
245 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | 402 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); |
403 | u8 reg, mask, val; | ||
404 | |||
405 | switch (clk_id) { | ||
406 | case TAS2552_PLL_CLKIN_MCLK: | ||
407 | case TAS2552_PLL_CLKIN_IVCLKIN: | ||
408 | if (freq < 512000 || freq > 24576000) { | ||
409 | /* out of range PLL_CLKIN, fall back to use BCLK */ | ||
410 | dev_warn(codec->dev, "Out of range PLL_CLKIN: %u\n", | ||
411 | freq); | ||
412 | clk_id = TAS2552_PLL_CLKIN_BCLK; | ||
413 | freq = 0; | ||
414 | } | ||
415 | /* fall through */ | ||
416 | case TAS2552_PLL_CLKIN_BCLK: | ||
417 | case TAS2552_PLL_CLKIN_1_8_FIXED: | ||
418 | mask = TAS2552_PLL_SRC_MASK; | ||
419 | val = (clk_id << 3) & mask; /* bit 4:5 in the register */ | ||
420 | reg = TAS2552_CFG_1; | ||
421 | tas2552->pll_clk_id = clk_id; | ||
422 | tas2552->pll_clkin = freq; | ||
423 | break; | ||
424 | case TAS2552_PDM_CLK_PLL: | ||
425 | case TAS2552_PDM_CLK_IVCLKIN: | ||
426 | case TAS2552_PDM_CLK_BCLK: | ||
427 | case TAS2552_PDM_CLK_MCLK: | ||
428 | mask = TAS2552_PDM_CLK_SEL_MASK; | ||
429 | val = (clk_id >> 1) & mask; /* bit 0:1 in the register */ | ||
430 | reg = TAS2552_PDM_CFG; | ||
431 | tas2552->pdm_clk_id = clk_id; | ||
432 | tas2552->pdm_clk = freq; | ||
433 | break; | ||
434 | default: | ||
435 | dev_err(codec->dev, "Invalid clk id: %d\n", clk_id); | ||
436 | return -EINVAL; | ||
437 | } | ||
246 | 438 | ||
247 | tas2552->mclk = freq; | 439 | snd_soc_update_bits(codec, reg, mask, val); |
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai, | ||
445 | unsigned int tx_mask, unsigned int rx_mask, | ||
446 | int slots, int slot_width) | ||
447 | { | ||
448 | struct snd_soc_codec *codec = dai->codec; | ||
449 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
450 | unsigned int lsb; | ||
451 | |||
452 | if (unlikely(!tx_mask)) { | ||
453 | dev_err(codec->dev, "tx masks need to be non 0\n"); | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | /* TDM based on DSP mode requires slots to be adjacent */ | ||
458 | lsb = __ffs(tx_mask); | ||
459 | if ((lsb + 1) != __fls(tx_mask)) { | ||
460 | dev_err(codec->dev, "Invalid mask, slots must be adjacent\n"); | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | |||
464 | tas2552->tdm_delay = lsb * slot_width; | ||
465 | |||
466 | /* DOUT in high-impedance on inactive bit clocks */ | ||
467 | snd_soc_update_bits(codec, TAS2552_DOUT, | ||
468 | TAS2552_SDOUT_TRISTATE, TAS2552_SDOUT_TRISTATE); | ||
248 | 469 | ||
249 | return 0; | 470 | return 0; |
250 | } | 471 | } |
251 | 472 | ||
252 | static int tas2552_mute(struct snd_soc_dai *dai, int mute) | 473 | static int tas2552_mute(struct snd_soc_dai *dai, int mute) |
253 | { | 474 | { |
254 | u8 cfg1_reg; | 475 | u8 cfg1_reg = 0; |
255 | struct snd_soc_codec *codec = dai->codec; | 476 | struct snd_soc_codec *codec = dai->codec; |
256 | 477 | ||
257 | if (mute) | 478 | if (mute) |
258 | cfg1_reg = TAS2552_MUTE_MASK; | 479 | cfg1_reg |= TAS2552_MUTE; |
259 | else | ||
260 | cfg1_reg = ~TAS2552_MUTE_MASK; | ||
261 | 480 | ||
262 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg); | 481 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, cfg1_reg); |
263 | 482 | ||
264 | return 0; | 483 | return 0; |
265 | } | 484 | } |
@@ -269,7 +488,7 @@ static int tas2552_runtime_suspend(struct device *dev) | |||
269 | { | 488 | { |
270 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); | 489 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); |
271 | 490 | ||
272 | tas2552_sw_shutdown(tas2552, 0); | 491 | tas2552_sw_shutdown(tas2552, 1); |
273 | 492 | ||
274 | regcache_cache_only(tas2552->regmap, true); | 493 | regcache_cache_only(tas2552->regmap, true); |
275 | regcache_mark_dirty(tas2552->regmap); | 494 | regcache_mark_dirty(tas2552->regmap); |
@@ -287,7 +506,7 @@ static int tas2552_runtime_resume(struct device *dev) | |||
287 | if (tas2552->enable_gpio) | 506 | if (tas2552->enable_gpio) |
288 | gpiod_set_value(tas2552->enable_gpio, 1); | 507 | gpiod_set_value(tas2552->enable_gpio, 1); |
289 | 508 | ||
290 | tas2552_sw_shutdown(tas2552, 1); | 509 | tas2552_sw_shutdown(tas2552, 0); |
291 | 510 | ||
292 | regcache_cache_only(tas2552->regmap, false); | 511 | regcache_cache_only(tas2552->regmap, false); |
293 | regcache_sync(tas2552->regmap); | 512 | regcache_sync(tas2552->regmap); |
@@ -303,8 +522,10 @@ static const struct dev_pm_ops tas2552_pm = { | |||
303 | 522 | ||
304 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { | 523 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { |
305 | .hw_params = tas2552_hw_params, | 524 | .hw_params = tas2552_hw_params, |
525 | .prepare = tas2552_prepare, | ||
306 | .set_sysclk = tas2552_set_dai_sysclk, | 526 | .set_sysclk = tas2552_set_dai_sysclk, |
307 | .set_fmt = tas2552_set_dai_fmt, | 527 | .set_fmt = tas2552_set_dai_fmt, |
528 | .set_tdm_slot = tas2552_set_dai_tdm_slot, | ||
308 | .digital_mute = tas2552_mute, | 529 | .digital_mute = tas2552_mute, |
309 | }; | 530 | }; |
310 | 531 | ||
@@ -330,16 +551,22 @@ static struct snd_soc_dai_driver tas2552_dai[] = { | |||
330 | /* | 551 | /* |
331 | * DAC digital volumes. From -7 to 24 dB in 1 dB steps | 552 | * DAC digital volumes. From -7 to 24 dB in 1 dB steps |
332 | */ | 553 | */ |
333 | static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); | 554 | static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 0); |
334 | 555 | ||
335 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { | 556 | static const char * const tas2552_din_source_select[] = { |
336 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", | 557 | "Muted", |
337 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), | 558 | "Left", |
338 | SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0), | 559 | "Right", |
560 | "Left + Right average", | ||
339 | }; | 561 | }; |
562 | static SOC_ENUM_SINGLE_DECL(tas2552_din_source_enum, | ||
563 | TAS2552_CFG_3, 3, | ||
564 | tas2552_din_source_select); | ||
340 | 565 | ||
341 | static const struct reg_default tas2552_init_regs[] = { | 566 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { |
342 | { TAS2552_RESERVED_0D, 0xc0 }, | 567 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", |
568 | TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv), | ||
569 | SOC_ENUM("DIN source", tas2552_din_source_enum), | ||
343 | }; | 570 | }; |
344 | 571 | ||
345 | static int tas2552_codec_probe(struct snd_soc_codec *codec) | 572 | static int tas2552_codec_probe(struct snd_soc_codec *codec) |
@@ -368,31 +595,20 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
368 | goto probe_fail; | 595 | goto probe_fail; |
369 | } | 596 | } |
370 | 597 | ||
371 | snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK | | 598 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, TAS2552_MUTE); |
372 | TAS2552_PLL_SRC_BCLK); | ||
373 | snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | | 599 | snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | |
374 | TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ); | 600 | TAS2552_DIN_SRC_SEL_AVG_L_R); |
375 | snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I); | 601 | snd_soc_write(codec, TAS2552_OUTPUT_DATA, |
376 | snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8); | 602 | TAS2552_PDM_DATA_SEL_V_I | |
377 | snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL); | 603 | TAS2552_R_DATA_OUT(TAS2552_DATA_OUT_V_DATA)); |
378 | snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 | | 604 | snd_soc_write(codec, TAS2552_BOOST_APT_CTRL, TAS2552_APT_DELAY_200 | |
379 | TAS2552_APT_THRESH_2_1_7); | 605 | TAS2552_APT_THRESH_20_17); |
380 | |||
381 | ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs, | ||
382 | ARRAY_SIZE(tas2552_init_regs)); | ||
383 | if (ret != 0) { | ||
384 | dev_err(codec->dev, "Failed to write init registers: %d\n", | ||
385 | ret); | ||
386 | goto patch_fail; | ||
387 | } | ||
388 | 606 | ||
389 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | | 607 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | TAS2552_APT_EN | |
390 | TAS2552_APT_EN | TAS2552_LIM_EN); | 608 | TAS2552_LIM_EN); |
391 | 609 | ||
392 | return 0; | 610 | return 0; |
393 | 611 | ||
394 | patch_fail: | ||
395 | pm_runtime_put(codec->dev); | ||
396 | probe_fail: | 612 | probe_fail: |
397 | if (tas2552->enable_gpio) | 613 | if (tas2552->enable_gpio) |
398 | gpiod_set_value(tas2552->enable_gpio, 0); | 614 | gpiod_set_value(tas2552->enable_gpio, 0); |
@@ -454,6 +670,8 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { | |||
454 | .remove = tas2552_codec_remove, | 670 | .remove = tas2552_codec_remove, |
455 | .suspend = tas2552_suspend, | 671 | .suspend = tas2552_suspend, |
456 | .resume = tas2552_resume, | 672 | .resume = tas2552_resume, |
673 | .ignore_pmdown_time = true, | ||
674 | |||
457 | .controls = tas2552_snd_controls, | 675 | .controls = tas2552_snd_controls, |
458 | .num_controls = ARRAY_SIZE(tas2552_snd_controls), | 676 | .num_controls = ARRAY_SIZE(tas2552_snd_controls), |
459 | .dapm_widgets = tas2552_dapm_widgets, | 677 | .dapm_widgets = tas2552_dapm_widgets, |
@@ -485,7 +703,8 @@ static int tas2552_probe(struct i2c_client *client, | |||
485 | if (data == NULL) | 703 | if (data == NULL) |
486 | return -ENOMEM; | 704 | return -ENOMEM; |
487 | 705 | ||
488 | data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); | 706 | data->enable_gpio = devm_gpiod_get_optional(dev, "enable", |
707 | GPIOD_OUT_LOW); | ||
489 | if (IS_ERR(data->enable_gpio)) | 708 | if (IS_ERR(data->enable_gpio)) |
490 | return PTR_ERR(data->enable_gpio); | 709 | return PTR_ERR(data->enable_gpio); |
491 | 710 | ||
@@ -529,6 +748,7 @@ static int tas2552_probe(struct i2c_client *client, | |||
529 | static int tas2552_i2c_remove(struct i2c_client *client) | 748 | static int tas2552_i2c_remove(struct i2c_client *client) |
530 | { | 749 | { |
531 | snd_soc_unregister_codec(&client->dev); | 750 | snd_soc_unregister_codec(&client->dev); |
751 | pm_runtime_disable(&client->dev); | ||
532 | return 0; | 752 | return 0; |
533 | } | 753 | } |
534 | 754 | ||
diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h index 6cea8f31bf88..5746f8fd0afd 100644 --- a/sound/soc/codecs/tas2552.h +++ b/sound/soc/codecs/tas2552.h | |||
@@ -19,7 +19,7 @@ | |||
19 | #define __TAS2552_H__ | 19 | #define __TAS2552_H__ |
20 | 20 | ||
21 | /* Register Address Map */ | 21 | /* Register Address Map */ |
22 | #define TAS2552_DEVICE_STATUS 0x00 | 22 | #define TAS2552_DEVICE_STATUS 0x00 |
23 | #define TAS2552_CFG_1 0x01 | 23 | #define TAS2552_CFG_1 0x01 |
24 | #define TAS2552_CFG_2 0x02 | 24 | #define TAS2552_CFG_2 0x02 |
25 | #define TAS2552_CFG_3 0x03 | 25 | #define TAS2552_CFG_3 0x03 |
@@ -33,22 +33,26 @@ | |||
33 | #define TAS2552_BTIP 0x0b | 33 | #define TAS2552_BTIP 0x0b |
34 | #define TAS2552_BTS_CTRL 0x0c | 34 | #define TAS2552_BTS_CTRL 0x0c |
35 | #define TAS2552_RESERVED_0D 0x0d | 35 | #define TAS2552_RESERVED_0D 0x0d |
36 | #define TAS2552_LIMIT_RATE_HYS 0x0e | 36 | #define TAS2552_LIMIT_RATE_HYS 0x0e |
37 | #define TAS2552_LIMIT_RELEASE 0x0f | 37 | #define TAS2552_LIMIT_RELEASE 0x0f |
38 | #define TAS2552_LIMIT_INT_COUNT 0x10 | 38 | #define TAS2552_LIMIT_INT_COUNT 0x10 |
39 | #define TAS2552_PDM_CFG 0x11 | 39 | #define TAS2552_PDM_CFG 0x11 |
40 | #define TAS2552_PGA_GAIN 0x12 | 40 | #define TAS2552_PGA_GAIN 0x12 |
41 | #define TAS2552_EDGE_RATE_CTRL 0x13 | 41 | #define TAS2552_EDGE_RATE_CTRL 0x13 |
42 | #define TAS2552_BOOST_PT_CTRL 0x14 | 42 | #define TAS2552_BOOST_APT_CTRL 0x14 |
43 | #define TAS2552_VER_NUM 0x16 | 43 | #define TAS2552_VER_NUM 0x16 |
44 | #define TAS2552_VBAT_DATA 0x19 | 44 | #define TAS2552_VBAT_DATA 0x19 |
45 | #define TAS2552_MAX_REG 0x20 | 45 | #define TAS2552_MAX_REG 0x20 |
46 | 46 | ||
47 | /* CFG1 Register Masks */ | 47 | /* CFG1 Register Masks */ |
48 | #define TAS2552_MUTE_MASK (1 << 2) | 48 | #define TAS2552_DEV_RESET (1 << 0) |
49 | #define TAS2552_SWS_MASK (1 << 1) | 49 | #define TAS2552_SWS (1 << 1) |
50 | #define TAS2552_WCLK_MASK 0x07 | 50 | #define TAS2552_MUTE (1 << 2) |
51 | #define TAS2552_CLASSD_EN_MASK (1 << 7) | 51 | #define TAS2552_PLL_SRC_MCLK (0x0 << 4) |
52 | #define TAS2552_PLL_SRC_BCLK (0x1 << 4) | ||
53 | #define TAS2552_PLL_SRC_IVCLKIN (0x2 << 4) | ||
54 | #define TAS2552_PLL_SRC_1_8_FIXED (0x3 << 4) | ||
55 | #define TAS2552_PLL_SRC_MASK TAS2552_PLL_SRC_1_8_FIXED | ||
52 | 56 | ||
53 | /* CFG2 Register Masks */ | 57 | /* CFG2 Register Masks */ |
54 | #define TAS2552_CLASSD_EN (1 << 7) | 58 | #define TAS2552_CLASSD_EN (1 << 7) |
@@ -59,71 +63,84 @@ | |||
59 | #define TAS2552_IVSENSE_EN (1 << 1) | 63 | #define TAS2552_IVSENSE_EN (1 << 1) |
60 | 64 | ||
61 | /* CFG3 Register Masks */ | 65 | /* CFG3 Register Masks */ |
62 | #define TAS2552_WORD_CLK_MASK (1 << 7) | 66 | #define TAS2552_WCLK_FREQ_8KHZ (0x0 << 0) |
63 | #define TAS2552_BIT_CLK_MASK (1 << 6) | 67 | #define TAS2552_WCLK_FREQ_11_12KHZ (0x1 << 0) |
64 | #define TAS2552_DATA_FORMAT_MASK (0x11 << 2) | 68 | #define TAS2552_WCLK_FREQ_16KHZ (0x2 << 0) |
65 | 69 | #define TAS2552_WCLK_FREQ_22_24KHZ (0x3 << 0) | |
66 | #define TAS2552_DAIFMT_I2S_MASK 0xf3 | 70 | #define TAS2552_WCLK_FREQ_32KHZ (0x4 << 0) |
67 | #define TAS2552_DAIFMT_DSP (1 << 3) | 71 | #define TAS2552_WCLK_FREQ_44_48KHZ (0x5 << 0) |
68 | #define TAS2552_DAIFMT_RIGHT_J (1 << 4) | 72 | #define TAS2552_WCLK_FREQ_88_96KHZ (0x6 << 0) |
69 | #define TAS2552_DAIFMT_LEFT_J (0x11 << 3) | 73 | #define TAS2552_WCLK_FREQ_176_192KHZ (0x7 << 0) |
70 | 74 | #define TAS2552_WCLK_FREQ_MASK TAS2552_WCLK_FREQ_176_192KHZ | |
71 | #define TAS2552_PLL_SRC_MCLK 0x00 | 75 | #define TAS2552_DIN_SRC_SEL_MUTED (0x0 << 3) |
72 | #define TAS2552_PLL_SRC_BCLK (1 << 3) | 76 | #define TAS2552_DIN_SRC_SEL_LEFT (0x1 << 3) |
73 | #define TAS2552_PLL_SRC_IVCLKIN (1 << 4) | 77 | #define TAS2552_DIN_SRC_SEL_RIGHT (0x2 << 3) |
74 | #define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3) | 78 | #define TAS2552_DIN_SRC_SEL_AVG_L_R (0x3 << 3) |
75 | |||
76 | #define TAS2552_DIN_SRC_SEL_MUTED 0x00 | ||
77 | #define TAS2552_DIN_SRC_SEL_LEFT (1 << 4) | ||
78 | #define TAS2552_DIN_SRC_SEL_RIGHT (1 << 5) | ||
79 | #define TAS2552_DIN_SRC_SEL_AVG_L_R (0x11 << 4) | ||
80 | |||
81 | #define TAS2552_PDM_IN_SEL (1 << 5) | 79 | #define TAS2552_PDM_IN_SEL (1 << 5) |
82 | #define TAS2552_I2S_OUT_SEL (1 << 6) | 80 | #define TAS2552_I2S_OUT_SEL (1 << 6) |
83 | #define TAS2552_ANALOG_IN_SEL (1 << 7) | 81 | #define TAS2552_ANALOG_IN_SEL (1 << 7) |
84 | 82 | ||
85 | /* CFG3 WCLK Dividers */ | 83 | /* DOUT Register Masks */ |
86 | #define TAS2552_8KHZ 0x00 | 84 | #define TAS2552_SDOUT_TRISTATE (1 << 2) |
87 | #define TAS2552_11_12KHZ (1 << 1) | 85 | |
88 | #define TAS2552_16KHZ (1 << 2) | 86 | /* Serial Interface Control Register Masks */ |
89 | #define TAS2552_22_24KHZ (1 << 3) | 87 | #define TAS2552_WORDLENGTH_16BIT (0x0 << 0) |
90 | #define TAS2552_32KHZ (1 << 4) | 88 | #define TAS2552_WORDLENGTH_20BIT (0x1 << 0) |
91 | #define TAS2552_44_48KHZ (1 << 5) | 89 | #define TAS2552_WORDLENGTH_24BIT (0x2 << 0) |
92 | #define TAS2552_88_96KHZ (1 << 6) | 90 | #define TAS2552_WORDLENGTH_32BIT (0x3 << 0) |
93 | #define TAS2552_176_192KHZ (1 << 7) | 91 | #define TAS2552_WORDLENGTH_MASK TAS2552_WORDLENGTH_32BIT |
92 | #define TAS2552_DATAFORMAT_I2S (0x0 << 2) | ||
93 | #define TAS2552_DATAFORMAT_DSP (0x1 << 2) | ||
94 | #define TAS2552_DATAFORMAT_RIGHT_J (0x2 << 2) | ||
95 | #define TAS2552_DATAFORMAT_LEFT_J (0x3 << 2) | ||
96 | #define TAS2552_DATAFORMAT_MASK TAS2552_DATAFORMAT_LEFT_J | ||
97 | #define TAS2552_CLKSPERFRAME_32 (0x0 << 4) | ||
98 | #define TAS2552_CLKSPERFRAME_64 (0x1 << 4) | ||
99 | #define TAS2552_CLKSPERFRAME_128 (0x2 << 4) | ||
100 | #define TAS2552_CLKSPERFRAME_256 (0x3 << 4) | ||
101 | #define TAS2552_CLKSPERFRAME_MASK TAS2552_CLKSPERFRAME_256 | ||
102 | #define TAS2552_BCLKDIR (1 << 6) | ||
103 | #define TAS2552_WCLKDIR (1 << 7) | ||
94 | 104 | ||
95 | /* OUTPUT_DATA register */ | 105 | /* OUTPUT_DATA register */ |
96 | #define TAS2552_PDM_DATA_I 0x00 | 106 | #define TAS2552_DATA_OUT_I_DATA (0x0) |
97 | #define TAS2552_PDM_DATA_V (1 << 6) | 107 | #define TAS2552_DATA_OUT_V_DATA (0x1) |
98 | #define TAS2552_PDM_DATA_I_V (1 << 7) | 108 | #define TAS2552_DATA_OUT_VBAT_DATA (0x2) |
99 | #define TAS2552_PDM_DATA_V_I (0x11 << 6) | 109 | #define TAS2552_DATA_OUT_VBOOST_DATA (0x3) |
110 | #define TAS2552_DATA_OUT_PGA_GAIN (0x4) | ||
111 | #define TAS2552_DATA_OUT_IV_DATA (0x5) | ||
112 | #define TAS2552_DATA_OUT_VBAT_VBOOST_GAIN (0x6) | ||
113 | #define TAS2552_DATA_OUT_DISABLED (0x7) | ||
114 | #define TAS2552_L_DATA_OUT(x) ((x) << 0) | ||
115 | #define TAS2552_R_DATA_OUT(x) ((x) << 3) | ||
116 | #define TAS2552_PDM_DATA_SEL_I (0x0 << 6) | ||
117 | #define TAS2552_PDM_DATA_SEL_V (0x1 << 6) | ||
118 | #define TAS2552_PDM_DATA_SEL_I_V (0x2 << 6) | ||
119 | #define TAS2552_PDM_DATA_SEL_V_I (0x3 << 6) | ||
120 | #define TAS2552_PDM_DATA_SEL_MASK TAS2552_PDM_DATA_SEL_V_I | ||
100 | 121 | ||
101 | /* PDM CFG Register */ | 122 | /* PDM CFG Register */ |
102 | #define TAS2552_PDM_DATA_ES_RISE 0x4 | 123 | #define TAS2552_PDM_CLK_SEL_PLL (0x0 << 0) |
103 | 124 | #define TAS2552_PDM_CLK_SEL_IVCLKIN (0x1 << 0) | |
104 | #define TAS2552_PDM_PLL_CLK_SEL 0x00 | 125 | #define TAS2552_PDM_CLK_SEL_BCLK (0x2 << 0) |
105 | #define TAS2552_PDM_IV_CLK_SEL (1 << 1) | 126 | #define TAS2552_PDM_CLK_SEL_MCLK (0x3 << 0) |
106 | #define TAS2552_PDM_BCLK_SEL (1 << 2) | 127 | #define TAS2552_PDM_CLK_SEL_MASK TAS2552_PDM_CLK_SEL_MCLK |
107 | #define TAS2552_PDM_MCLK_SEL (1 << 3) | 128 | #define TAS2552_PDM_DATA_ES (1 << 2) |
108 | 129 | ||
109 | /* Boost pass-through register */ | 130 | /* Boost Auto-pass through register */ |
110 | #define TAS2552_APT_DELAY_50 0x00 | 131 | #define TAS2552_APT_DELAY_50 (0x0 << 0) |
111 | #define TAS2552_APT_DELAY_75 (1 << 1) | 132 | #define TAS2552_APT_DELAY_75 (0x1 << 0) |
112 | #define TAS2552_APT_DELAY_125 (1 << 2) | 133 | #define TAS2552_APT_DELAY_125 (0x2 << 0) |
113 | #define TAS2552_APT_DELAY_200 (1 << 3) | 134 | #define TAS2552_APT_DELAY_200 (0x3 << 0) |
114 | 135 | #define TAS2552_APT_THRESH_05_02 (0x0 << 2) | |
115 | #define TAS2552_APT_THRESH_2_5 0x00 | 136 | #define TAS2552_APT_THRESH_10_07 (0x1 << 2) |
116 | #define TAS2552_APT_THRESH_1_7 (1 << 3) | 137 | #define TAS2552_APT_THRESH_14_11 (0x2 << 2) |
117 | #define TAS2552_APT_THRESH_1_4_1_1 (1 << 4) | 138 | #define TAS2552_APT_THRESH_20_17 (0x3 << 2) |
118 | #define TAS2552_APT_THRESH_2_1_7 (0x11 << 2) | ||
119 | 139 | ||
120 | /* PLL Control Register */ | 140 | /* PLL Control Register */ |
121 | #define TAS2552_245MHZ_CLK 24576000 | 141 | #define TAS2552_PLL_J_MASK 0x7f |
122 | #define TAS2552_225MHZ_CLK 22579200 | 142 | #define TAS2552_PLL_D_UPPER(x) (((x) >> 8) & 0x3f) |
123 | #define TAS2552_PLL_J_MASK 0x7f | 143 | #define TAS2552_PLL_D_LOWER(x) ((x) & 0xff) |
124 | #define TAS2552_PLL_D_UPPER_MASK 0x3f | 144 | #define TAS2552_PLL_BYPASS (1 << 7) |
125 | #define TAS2552_PLL_D_LOWER_MASK 0xff | ||
126 | #define TAS2552_PLL_BYPASS_MASK 0x80 | ||
127 | #define TAS2552_PLL_BYPASS 0x80 | ||
128 | 145 | ||
129 | #endif | 146 | #endif |
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c new file mode 100644 index 000000000000..85bcc374c8e8 --- /dev/null +++ b/sound/soc/codecs/tas571x.c | |||
@@ -0,0 +1,514 @@ | |||
1 | /* | ||
2 | * TAS571x amplifier audio driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Google, Inc. | ||
5 | * Copyright (c) 2013 Daniel Mack <zonque@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/gpio/consumer.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <linux/stddef.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/tlv.h> | ||
28 | |||
29 | #include "tas571x.h" | ||
30 | |||
31 | #define TAS571X_MAX_SUPPLIES 6 | ||
32 | |||
33 | struct tas571x_chip { | ||
34 | const char *const *supply_names; | ||
35 | int num_supply_names; | ||
36 | const struct snd_kcontrol_new *controls; | ||
37 | int num_controls; | ||
38 | const struct regmap_config *regmap_config; | ||
39 | int vol_reg_size; | ||
40 | }; | ||
41 | |||
42 | struct tas571x_private { | ||
43 | const struct tas571x_chip *chip; | ||
44 | struct regmap *regmap; | ||
45 | struct regulator_bulk_data supplies[TAS571X_MAX_SUPPLIES]; | ||
46 | struct clk *mclk; | ||
47 | unsigned int format; | ||
48 | struct gpio_desc *reset_gpio; | ||
49 | struct gpio_desc *pdn_gpio; | ||
50 | struct snd_soc_codec_driver codec_driver; | ||
51 | }; | ||
52 | |||
53 | static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg) | ||
54 | { | ||
55 | switch (reg) { | ||
56 | case TAS571X_MVOL_REG: | ||
57 | case TAS571X_CH1_VOL_REG: | ||
58 | case TAS571X_CH2_VOL_REG: | ||
59 | return priv->chip->vol_reg_size; | ||
60 | default: | ||
61 | return 1; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static int tas571x_reg_write(void *context, unsigned int reg, | ||
66 | unsigned int value) | ||
67 | { | ||
68 | struct i2c_client *client = context; | ||
69 | struct tas571x_private *priv = i2c_get_clientdata(client); | ||
70 | unsigned int i, size; | ||
71 | uint8_t buf[5]; | ||
72 | int ret; | ||
73 | |||
74 | size = tas571x_register_size(priv, reg); | ||
75 | buf[0] = reg; | ||
76 | |||
77 | for (i = size; i >= 1; --i) { | ||
78 | buf[i] = value; | ||
79 | value >>= 8; | ||
80 | } | ||
81 | |||
82 | ret = i2c_master_send(client, buf, size + 1); | ||
83 | if (ret == size + 1) | ||
84 | return 0; | ||
85 | else if (ret < 0) | ||
86 | return ret; | ||
87 | else | ||
88 | return -EIO; | ||
89 | } | ||
90 | |||
91 | static int tas571x_reg_read(void *context, unsigned int reg, | ||
92 | unsigned int *value) | ||
93 | { | ||
94 | struct i2c_client *client = context; | ||
95 | struct tas571x_private *priv = i2c_get_clientdata(client); | ||
96 | uint8_t send_buf, recv_buf[4]; | ||
97 | struct i2c_msg msgs[2]; | ||
98 | unsigned int size; | ||
99 | unsigned int i; | ||
100 | int ret; | ||
101 | |||
102 | size = tas571x_register_size(priv, reg); | ||
103 | send_buf = reg; | ||
104 | |||
105 | msgs[0].addr = client->addr; | ||
106 | msgs[0].len = sizeof(send_buf); | ||
107 | msgs[0].buf = &send_buf; | ||
108 | msgs[0].flags = 0; | ||
109 | |||
110 | msgs[1].addr = client->addr; | ||
111 | msgs[1].len = size; | ||
112 | msgs[1].buf = recv_buf; | ||
113 | msgs[1].flags = I2C_M_RD; | ||
114 | |||
115 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
116 | if (ret < 0) | ||
117 | return ret; | ||
118 | else if (ret != ARRAY_SIZE(msgs)) | ||
119 | return -EIO; | ||
120 | |||
121 | *value = 0; | ||
122 | |||
123 | for (i = 0; i < size; i++) { | ||
124 | *value <<= 8; | ||
125 | *value |= recv_buf[i]; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) | ||
132 | { | ||
133 | struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec); | ||
134 | |||
135 | priv->format = format; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int tas571x_hw_params(struct snd_pcm_substream *substream, | ||
141 | struct snd_pcm_hw_params *params, | ||
142 | struct snd_soc_dai *dai) | ||
143 | { | ||
144 | struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec); | ||
145 | u32 val; | ||
146 | |||
147 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
148 | case SND_SOC_DAIFMT_RIGHT_J: | ||
149 | val = 0x00; | ||
150 | break; | ||
151 | case SND_SOC_DAIFMT_I2S: | ||
152 | val = 0x03; | ||
153 | break; | ||
154 | case SND_SOC_DAIFMT_LEFT_J: | ||
155 | val = 0x06; | ||
156 | break; | ||
157 | default: | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | if (params_width(params) >= 24) | ||
162 | val += 2; | ||
163 | else if (params_width(params) >= 20) | ||
164 | val += 1; | ||
165 | |||
166 | return regmap_update_bits(priv->regmap, TAS571X_SDI_REG, | ||
167 | TAS571X_SDI_FMT_MASK, val); | ||
168 | } | ||
169 | |||
170 | static int tas571x_set_bias_level(struct snd_soc_codec *codec, | ||
171 | enum snd_soc_bias_level level) | ||
172 | { | ||
173 | struct tas571x_private *priv = snd_soc_codec_get_drvdata(codec); | ||
174 | int ret; | ||
175 | |||
176 | switch (level) { | ||
177 | case SND_SOC_BIAS_ON: | ||
178 | break; | ||
179 | case SND_SOC_BIAS_PREPARE: | ||
180 | break; | ||
181 | case SND_SOC_BIAS_STANDBY: | ||
182 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
183 | if (!IS_ERR(priv->mclk)) { | ||
184 | ret = clk_prepare_enable(priv->mclk); | ||
185 | if (ret) { | ||
186 | dev_err(codec->dev, | ||
187 | "Failed to enable master clock: %d\n", | ||
188 | ret); | ||
189 | return ret; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | gpiod_set_value(priv->pdn_gpio, 0); | ||
194 | usleep_range(5000, 6000); | ||
195 | |||
196 | regcache_cache_only(priv->regmap, false); | ||
197 | ret = regcache_sync(priv->regmap); | ||
198 | if (ret) | ||
199 | return ret; | ||
200 | } | ||
201 | break; | ||
202 | case SND_SOC_BIAS_OFF: | ||
203 | regcache_cache_only(priv->regmap, true); | ||
204 | gpiod_set_value(priv->pdn_gpio, 1); | ||
205 | |||
206 | if (!IS_ERR(priv->mclk)) | ||
207 | clk_disable_unprepare(priv->mclk); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static const struct snd_soc_dai_ops tas571x_dai_ops = { | ||
215 | .set_fmt = tas571x_set_dai_fmt, | ||
216 | .hw_params = tas571x_hw_params, | ||
217 | }; | ||
218 | |||
219 | static const char *const tas5711_supply_names[] = { | ||
220 | "AVDD", | ||
221 | "DVDD", | ||
222 | "PVDD_A", | ||
223 | "PVDD_B", | ||
224 | "PVDD_C", | ||
225 | "PVDD_D", | ||
226 | }; | ||
227 | |||
228 | static const DECLARE_TLV_DB_SCALE(tas5711_volume_tlv, -10350, 50, 1); | ||
229 | |||
230 | static const struct snd_kcontrol_new tas5711_controls[] = { | ||
231 | SOC_SINGLE_TLV("Master Volume", | ||
232 | TAS571X_MVOL_REG, | ||
233 | 0, 0xff, 1, tas5711_volume_tlv), | ||
234 | SOC_DOUBLE_R_TLV("Speaker Volume", | ||
235 | TAS571X_CH1_VOL_REG, | ||
236 | TAS571X_CH2_VOL_REG, | ||
237 | 0, 0xff, 1, tas5711_volume_tlv), | ||
238 | SOC_DOUBLE("Speaker Switch", | ||
239 | TAS571X_SOFT_MUTE_REG, | ||
240 | TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, | ||
241 | 1, 1), | ||
242 | }; | ||
243 | |||
244 | static const struct reg_default tas5711_reg_defaults[] = { | ||
245 | { 0x04, 0x05 }, | ||
246 | { 0x05, 0x40 }, | ||
247 | { 0x06, 0x00 }, | ||
248 | { 0x07, 0xff }, | ||
249 | { 0x08, 0x30 }, | ||
250 | { 0x09, 0x30 }, | ||
251 | { 0x1b, 0x82 }, | ||
252 | }; | ||
253 | |||
254 | static const struct regmap_config tas5711_regmap_config = { | ||
255 | .reg_bits = 8, | ||
256 | .val_bits = 32, | ||
257 | .max_register = 0xff, | ||
258 | .reg_read = tas571x_reg_read, | ||
259 | .reg_write = tas571x_reg_write, | ||
260 | .reg_defaults = tas5711_reg_defaults, | ||
261 | .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults), | ||
262 | .cache_type = REGCACHE_RBTREE, | ||
263 | }; | ||
264 | |||
265 | static const struct tas571x_chip tas5711_chip = { | ||
266 | .supply_names = tas5711_supply_names, | ||
267 | .num_supply_names = ARRAY_SIZE(tas5711_supply_names), | ||
268 | .controls = tas5711_controls, | ||
269 | .num_controls = ARRAY_SIZE(tas5711_controls), | ||
270 | .regmap_config = &tas5711_regmap_config, | ||
271 | .vol_reg_size = 1, | ||
272 | }; | ||
273 | |||
274 | static const char *const tas5717_supply_names[] = { | ||
275 | "AVDD", | ||
276 | "DVDD", | ||
277 | "HPVDD", | ||
278 | "PVDD_AB", | ||
279 | "PVDD_CD", | ||
280 | }; | ||
281 | |||
282 | static const DECLARE_TLV_DB_SCALE(tas5717_volume_tlv, -10375, 25, 0); | ||
283 | |||
284 | static const struct snd_kcontrol_new tas5717_controls[] = { | ||
285 | /* MVOL LSB is ignored - see comments in tas571x_i2c_probe() */ | ||
286 | SOC_SINGLE_TLV("Master Volume", | ||
287 | TAS571X_MVOL_REG, 1, 0x1ff, 1, | ||
288 | tas5717_volume_tlv), | ||
289 | SOC_DOUBLE_R_TLV("Speaker Volume", | ||
290 | TAS571X_CH1_VOL_REG, TAS571X_CH2_VOL_REG, | ||
291 | 1, 0x1ff, 1, tas5717_volume_tlv), | ||
292 | SOC_DOUBLE("Speaker Switch", | ||
293 | TAS571X_SOFT_MUTE_REG, | ||
294 | TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, | ||
295 | 1, 1), | ||
296 | }; | ||
297 | |||
298 | static const struct reg_default tas5717_reg_defaults[] = { | ||
299 | { 0x04, 0x05 }, | ||
300 | { 0x05, 0x40 }, | ||
301 | { 0x06, 0x00 }, | ||
302 | { 0x07, 0x03ff }, | ||
303 | { 0x08, 0x00c0 }, | ||
304 | { 0x09, 0x00c0 }, | ||
305 | { 0x1b, 0x82 }, | ||
306 | }; | ||
307 | |||
308 | static const struct regmap_config tas5717_regmap_config = { | ||
309 | .reg_bits = 8, | ||
310 | .val_bits = 32, | ||
311 | .max_register = 0xff, | ||
312 | .reg_read = tas571x_reg_read, | ||
313 | .reg_write = tas571x_reg_write, | ||
314 | .reg_defaults = tas5717_reg_defaults, | ||
315 | .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults), | ||
316 | .cache_type = REGCACHE_RBTREE, | ||
317 | }; | ||
318 | |||
319 | /* This entry is reused for tas5719 as the software interface is identical. */ | ||
320 | static const struct tas571x_chip tas5717_chip = { | ||
321 | .supply_names = tas5717_supply_names, | ||
322 | .num_supply_names = ARRAY_SIZE(tas5717_supply_names), | ||
323 | .controls = tas5717_controls, | ||
324 | .num_controls = ARRAY_SIZE(tas5717_controls), | ||
325 | .regmap_config = &tas5717_regmap_config, | ||
326 | .vol_reg_size = 2, | ||
327 | }; | ||
328 | |||
329 | static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = { | ||
330 | SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), | ||
331 | SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), | ||
332 | |||
333 | SND_SOC_DAPM_OUTPUT("OUT_A"), | ||
334 | SND_SOC_DAPM_OUTPUT("OUT_B"), | ||
335 | SND_SOC_DAPM_OUTPUT("OUT_C"), | ||
336 | SND_SOC_DAPM_OUTPUT("OUT_D"), | ||
337 | }; | ||
338 | |||
339 | static const struct snd_soc_dapm_route tas571x_dapm_routes[] = { | ||
340 | { "DACL", NULL, "Playback" }, | ||
341 | { "DACR", NULL, "Playback" }, | ||
342 | |||
343 | { "OUT_A", NULL, "DACL" }, | ||
344 | { "OUT_B", NULL, "DACL" }, | ||
345 | { "OUT_C", NULL, "DACR" }, | ||
346 | { "OUT_D", NULL, "DACR" }, | ||
347 | }; | ||
348 | |||
349 | static const struct snd_soc_codec_driver tas571x_codec = { | ||
350 | .set_bias_level = tas571x_set_bias_level, | ||
351 | .idle_bias_off = true, | ||
352 | |||
353 | .dapm_widgets = tas571x_dapm_widgets, | ||
354 | .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), | ||
355 | .dapm_routes = tas571x_dapm_routes, | ||
356 | .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), | ||
357 | }; | ||
358 | |||
359 | static struct snd_soc_dai_driver tas571x_dai = { | ||
360 | .name = "tas571x-hifi", | ||
361 | .playback = { | ||
362 | .stream_name = "Playback", | ||
363 | .channels_min = 2, | ||
364 | .channels_max = 2, | ||
365 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
366 | .formats = SNDRV_PCM_FMTBIT_S32_LE | | ||
367 | SNDRV_PCM_FMTBIT_S24_LE | | ||
368 | SNDRV_PCM_FMTBIT_S16_LE, | ||
369 | }, | ||
370 | .ops = &tas571x_dai_ops, | ||
371 | }; | ||
372 | |||
373 | static const struct of_device_id tas571x_of_match[]; | ||
374 | |||
375 | static int tas571x_i2c_probe(struct i2c_client *client, | ||
376 | const struct i2c_device_id *id) | ||
377 | { | ||
378 | struct tas571x_private *priv; | ||
379 | struct device *dev = &client->dev; | ||
380 | const struct of_device_id *of_id; | ||
381 | int i, ret; | ||
382 | |||
383 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
384 | if (!priv) | ||
385 | return -ENOMEM; | ||
386 | i2c_set_clientdata(client, priv); | ||
387 | |||
388 | of_id = of_match_device(tas571x_of_match, dev); | ||
389 | if (!of_id) { | ||
390 | dev_err(dev, "Unknown device type\n"); | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | priv->chip = of_id->data; | ||
394 | |||
395 | priv->mclk = devm_clk_get(dev, "mclk"); | ||
396 | if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) { | ||
397 | dev_err(dev, "Failed to request mclk: %ld\n", | ||
398 | PTR_ERR(priv->mclk)); | ||
399 | return PTR_ERR(priv->mclk); | ||
400 | } | ||
401 | |||
402 | BUG_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES); | ||
403 | for (i = 0; i < priv->chip->num_supply_names; i++) | ||
404 | priv->supplies[i].supply = priv->chip->supply_names[i]; | ||
405 | |||
406 | ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names, | ||
407 | priv->supplies); | ||
408 | if (ret) { | ||
409 | dev_err(dev, "Failed to get supplies: %d\n", ret); | ||
410 | return ret; | ||
411 | } | ||
412 | ret = regulator_bulk_enable(priv->chip->num_supply_names, | ||
413 | priv->supplies); | ||
414 | if (ret) { | ||
415 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | priv->regmap = devm_regmap_init(dev, NULL, client, | ||
420 | priv->chip->regmap_config); | ||
421 | if (IS_ERR(priv->regmap)) | ||
422 | return PTR_ERR(priv->regmap); | ||
423 | |||
424 | priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW); | ||
425 | if (IS_ERR(priv->pdn_gpio)) { | ||
426 | dev_err(dev, "error requesting pdn_gpio: %ld\n", | ||
427 | PTR_ERR(priv->pdn_gpio)); | ||
428 | return PTR_ERR(priv->pdn_gpio); | ||
429 | } | ||
430 | |||
431 | priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", | ||
432 | GPIOD_OUT_HIGH); | ||
433 | if (IS_ERR(priv->reset_gpio)) { | ||
434 | dev_err(dev, "error requesting reset_gpio: %ld\n", | ||
435 | PTR_ERR(priv->reset_gpio)); | ||
436 | return PTR_ERR(priv->reset_gpio); | ||
437 | } else if (priv->reset_gpio) { | ||
438 | /* pulse the active low reset line for ~100us */ | ||
439 | usleep_range(100, 200); | ||
440 | gpiod_set_value(priv->reset_gpio, 0); | ||
441 | usleep_range(12000, 20000); | ||
442 | } | ||
443 | |||
444 | ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0); | ||
445 | if (ret) | ||
446 | return ret; | ||
447 | |||
448 | ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG, | ||
449 | TAS571X_SYS_CTRL_2_SDN_MASK, 0); | ||
450 | if (ret) | ||
451 | return ret; | ||
452 | |||
453 | memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); | ||
454 | priv->codec_driver.controls = priv->chip->controls; | ||
455 | priv->codec_driver.num_controls = priv->chip->num_controls; | ||
456 | |||
457 | if (priv->chip->vol_reg_size == 2) { | ||
458 | /* | ||
459 | * The master volume defaults to 0x3ff (mute), but we ignore | ||
460 | * (zero) the LSB because the hardware step size is 0.125 dB | ||
461 | * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB. | ||
462 | */ | ||
463 | ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0); | ||
464 | if (ret) | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | regcache_cache_only(priv->regmap, true); | ||
469 | gpiod_set_value(priv->pdn_gpio, 1); | ||
470 | |||
471 | return snd_soc_register_codec(&client->dev, &priv->codec_driver, | ||
472 | &tas571x_dai, 1); | ||
473 | } | ||
474 | |||
475 | static int tas571x_i2c_remove(struct i2c_client *client) | ||
476 | { | ||
477 | struct tas571x_private *priv = i2c_get_clientdata(client); | ||
478 | |||
479 | snd_soc_unregister_codec(&client->dev); | ||
480 | regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies); | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static const struct of_device_id tas571x_of_match[] = { | ||
486 | { .compatible = "ti,tas5711", .data = &tas5711_chip, }, | ||
487 | { .compatible = "ti,tas5717", .data = &tas5717_chip, }, | ||
488 | { .compatible = "ti,tas5719", .data = &tas5717_chip, }, | ||
489 | { } | ||
490 | }; | ||
491 | MODULE_DEVICE_TABLE(of, tas571x_of_match); | ||
492 | |||
493 | static const struct i2c_device_id tas571x_i2c_id[] = { | ||
494 | { "tas5711", 0 }, | ||
495 | { "tas5717", 0 }, | ||
496 | { "tas5719", 0 }, | ||
497 | { } | ||
498 | }; | ||
499 | MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); | ||
500 | |||
501 | static struct i2c_driver tas571x_i2c_driver = { | ||
502 | .driver = { | ||
503 | .name = "tas571x", | ||
504 | .of_match_table = of_match_ptr(tas571x_of_match), | ||
505 | }, | ||
506 | .probe = tas571x_i2c_probe, | ||
507 | .remove = tas571x_i2c_remove, | ||
508 | .id_table = tas571x_i2c_id, | ||
509 | }; | ||
510 | module_i2c_driver(tas571x_i2c_driver); | ||
511 | |||
512 | MODULE_DESCRIPTION("ASoC TAS571x driver"); | ||
513 | MODULE_AUTHOR("Kevin Cernekee <cernekee@chromium.org>"); | ||
514 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h new file mode 100644 index 000000000000..0aee471232cd --- /dev/null +++ b/sound/soc/codecs/tas571x.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * TAS571x amplifier audio driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Google, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _TAS571X_H | ||
13 | #define _TAS571X_H | ||
14 | |||
15 | /* device registers */ | ||
16 | #define TAS571X_SDI_REG 0x04 | ||
17 | #define TAS571X_SDI_FMT_MASK 0x0f | ||
18 | |||
19 | #define TAS571X_SYS_CTRL_2_REG 0x05 | ||
20 | #define TAS571X_SYS_CTRL_2_SDN_MASK 0x40 | ||
21 | |||
22 | #define TAS571X_SOFT_MUTE_REG 0x06 | ||
23 | #define TAS571X_SOFT_MUTE_CH1_SHIFT 0 | ||
24 | #define TAS571X_SOFT_MUTE_CH2_SHIFT 1 | ||
25 | #define TAS571X_SOFT_MUTE_CH3_SHIFT 2 | ||
26 | |||
27 | #define TAS571X_MVOL_REG 0x07 | ||
28 | #define TAS571X_CH1_VOL_REG 0x08 | ||
29 | #define TAS571X_CH2_VOL_REG 0x09 | ||
30 | |||
31 | #define TAS571X_OSC_TRIM_REG 0x1b | ||
32 | |||
33 | #endif /* _TAS571X_H */ | ||
diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index 16f1b71edb55..aab0af681e8c 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c | |||
@@ -280,8 +280,8 @@ static int tfa9879_i2c_probe(struct i2c_client *i2c, | |||
280 | int i; | 280 | int i; |
281 | 281 | ||
282 | tfa9879 = devm_kzalloc(&i2c->dev, sizeof(*tfa9879), GFP_KERNEL); | 282 | tfa9879 = devm_kzalloc(&i2c->dev, sizeof(*tfa9879), GFP_KERNEL); |
283 | if (IS_ERR(tfa9879)) | 283 | if (!tfa9879) |
284 | return PTR_ERR(tfa9879); | 284 | return -ENOMEM; |
285 | 285 | ||
286 | i2c_set_clientdata(i2c, tfa9879); | 286 | i2c_set_clientdata(i2c, tfa9879); |
287 | 287 | ||
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cc17e7e5126e..cd8c02b6e4de 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -506,7 +506,6 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, | |||
506 | snd_soc_write(codec, TLV320AIC23_PWR, 0x1ff); | 506 | snd_soc_write(codec, TLV320AIC23_PWR, 0x1ff); |
507 | break; | 507 | break; |
508 | } | 508 | } |
509 | codec->dapm.bias_level = level; | ||
510 | return 0; | 509 | return 0; |
511 | } | 510 | } |
512 | 511 | ||
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index c86dd9aae157..c4c960f592a1 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -646,7 +646,7 @@ static int aic31xx_add_controls(struct snd_soc_codec *codec) | |||
646 | 646 | ||
647 | static int aic31xx_add_widgets(struct snd_soc_codec *codec) | 647 | static int aic31xx_add_widgets(struct snd_soc_codec *codec) |
648 | { | 648 | { |
649 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 649 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
650 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 650 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
651 | int ret = 0; | 651 | int ret = 0; |
652 | 652 | ||
@@ -1027,17 +1027,17 @@ static int aic31xx_set_bias_level(struct snd_soc_codec *codec, | |||
1027 | enum snd_soc_bias_level level) | 1027 | enum snd_soc_bias_level level) |
1028 | { | 1028 | { |
1029 | dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, | 1029 | dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, |
1030 | codec->dapm.bias_level, level); | 1030 | snd_soc_codec_get_bias_level(codec), level); |
1031 | 1031 | ||
1032 | switch (level) { | 1032 | switch (level) { |
1033 | case SND_SOC_BIAS_ON: | 1033 | case SND_SOC_BIAS_ON: |
1034 | break; | 1034 | break; |
1035 | case SND_SOC_BIAS_PREPARE: | 1035 | case SND_SOC_BIAS_PREPARE: |
1036 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 1036 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) |
1037 | aic31xx_clk_on(codec); | 1037 | aic31xx_clk_on(codec); |
1038 | break; | 1038 | break; |
1039 | case SND_SOC_BIAS_STANDBY: | 1039 | case SND_SOC_BIAS_STANDBY: |
1040 | switch (codec->dapm.bias_level) { | 1040 | switch (snd_soc_codec_get_bias_level(codec)) { |
1041 | case SND_SOC_BIAS_OFF: | 1041 | case SND_SOC_BIAS_OFF: |
1042 | aic31xx_power_on(codec); | 1042 | aic31xx_power_on(codec); |
1043 | break; | 1043 | break; |
@@ -1049,11 +1049,10 @@ static int aic31xx_set_bias_level(struct snd_soc_codec *codec, | |||
1049 | } | 1049 | } |
1050 | break; | 1050 | break; |
1051 | case SND_SOC_BIAS_OFF: | 1051 | case SND_SOC_BIAS_OFF: |
1052 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 1052 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) |
1053 | aic31xx_power_off(codec); | 1053 | aic31xx_power_off(codec); |
1054 | break; | 1054 | break; |
1055 | } | 1055 | } |
1056 | codec->dapm.bias_level = level; | ||
1057 | 1056 | ||
1058 | return 0; | 1057 | return 0; |
1059 | } | 1058 | } |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 015467ed606b..ad6cb90e5f9b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -564,7 +564,6 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | |||
564 | case SND_SOC_BIAS_OFF: | 564 | case SND_SOC_BIAS_OFF: |
565 | break; | 565 | break; |
566 | } | 566 | } |
567 | codec->dapm.bias_level = level; | ||
568 | return 0; | 567 | return 0; |
569 | } | 568 | } |
570 | 569 | ||
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 51c4713ac6e3..a7cf19b53fb2 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -147,6 +147,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
147 | struct snd_ctl_elem_value *ucontrol) | 147 | struct snd_ctl_elem_value *ucontrol) |
148 | { | 148 | { |
149 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 149 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
150 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
150 | struct soc_mixer_control *mc = | 151 | struct soc_mixer_control *mc = |
151 | (struct soc_mixer_control *)kcontrol->private_value; | 152 | (struct soc_mixer_control *)kcontrol->private_value; |
152 | unsigned int reg = mc->reg; | 153 | unsigned int reg = mc->reg; |
@@ -179,7 +180,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
179 | update.mask = mask; | 180 | update.mask = mask; |
180 | update.val = val; | 181 | update.val = val; |
181 | 182 | ||
182 | snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect, | 183 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, connect, |
183 | &update); | 184 | &update); |
184 | } | 185 | } |
185 | 186 | ||
@@ -979,7 +980,7 @@ static const struct snd_soc_dapm_route intercon_3007[] = { | |||
979 | static int aic3x_add_widgets(struct snd_soc_codec *codec) | 980 | static int aic3x_add_widgets(struct snd_soc_codec *codec) |
980 | { | 981 | { |
981 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 982 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
982 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 983 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
983 | 984 | ||
984 | switch (aic3x->model) { | 985 | switch (aic3x->model) { |
985 | case AIC3X_MODEL_3X: | 986 | case AIC3X_MODEL_3X: |
@@ -1384,7 +1385,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, | |||
1384 | case SND_SOC_BIAS_ON: | 1385 | case SND_SOC_BIAS_ON: |
1385 | break; | 1386 | break; |
1386 | case SND_SOC_BIAS_PREPARE: | 1387 | case SND_SOC_BIAS_PREPARE: |
1387 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY && | 1388 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY && |
1388 | aic3x->master) { | 1389 | aic3x->master) { |
1389 | /* enable pll */ | 1390 | /* enable pll */ |
1390 | snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, | 1391 | snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, |
@@ -1394,7 +1395,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, | |||
1394 | case SND_SOC_BIAS_STANDBY: | 1395 | case SND_SOC_BIAS_STANDBY: |
1395 | if (!aic3x->power) | 1396 | if (!aic3x->power) |
1396 | aic3x_set_power(codec, 1); | 1397 | aic3x_set_power(codec, 1); |
1397 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE && | 1398 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE && |
1398 | aic3x->master) { | 1399 | aic3x->master) { |
1399 | /* disable pll */ | 1400 | /* disable pll */ |
1400 | snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, | 1401 | snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, |
@@ -1406,7 +1407,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, | |||
1406 | aic3x_set_power(codec, 0); | 1407 | aic3x_set_power(codec, 0); |
1407 | break; | 1408 | break; |
1408 | } | 1409 | } |
1409 | codec->dapm.bias_level = level; | ||
1410 | 1410 | ||
1411 | return 0; | 1411 | return 0; |
1412 | } | 1412 | } |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4e3e607dec13..d67a311f0e75 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -633,7 +633,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
633 | case SND_SOC_BIAS_PREPARE: | 633 | case SND_SOC_BIAS_PREPARE: |
634 | break; | 634 | break; |
635 | case SND_SOC_BIAS_STANDBY: | 635 | case SND_SOC_BIAS_STANDBY: |
636 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 636 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
637 | /* Coming from OFF, switch on the codec */ | 637 | /* Coming from OFF, switch on the codec */ |
638 | ret = dac33_hard_power(codec, 1); | 638 | ret = dac33_hard_power(codec, 1); |
639 | if (ret != 0) | 639 | if (ret != 0) |
@@ -644,14 +644,13 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
644 | break; | 644 | break; |
645 | case SND_SOC_BIAS_OFF: | 645 | case SND_SOC_BIAS_OFF: |
646 | /* Do not power off, when the codec is already off */ | 646 | /* Do not power off, when the codec is already off */ |
647 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 647 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
648 | return 0; | 648 | return 0; |
649 | ret = dac33_hard_power(codec, 0); | 649 | ret = dac33_hard_power(codec, 0); |
650 | if (ret != 0) | 650 | if (ret != 0) |
651 | return ret; | 651 | return ret; |
652 | break; | 652 | break; |
653 | } | 653 | } |
654 | codec->dapm.bias_level = level; | ||
655 | 654 | ||
656 | return 0; | 655 | return 0; |
657 | } | 656 | } |
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index 9fd80ac1897f..12232d7db4c5 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c | |||
@@ -254,12 +254,13 @@ static const struct regmap_config ts3a227e_regmap_config = { | |||
254 | .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), | 254 | .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), |
255 | }; | 255 | }; |
256 | 256 | ||
257 | static int ts3a227e_parse_dt(struct ts3a227e *ts3a227e, struct device_node *np) | 257 | static int ts3a227e_parse_device_property(struct ts3a227e *ts3a227e, |
258 | struct device *dev) | ||
258 | { | 259 | { |
259 | u32 micbias; | 260 | u32 micbias; |
260 | int err; | 261 | int err; |
261 | 262 | ||
262 | err = of_property_read_u32(np, "ti,micbias", &micbias); | 263 | err = device_property_read_u32(dev, "ti,micbias", &micbias); |
263 | if (!err) { | 264 | if (!err) { |
264 | regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_SETTING_3, | 265 | regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_SETTING_3, |
265 | MICBIAS_SETTING_MASK, | 266 | MICBIAS_SETTING_MASK, |
@@ -287,12 +288,10 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c, | |||
287 | if (IS_ERR(ts3a227e->regmap)) | 288 | if (IS_ERR(ts3a227e->regmap)) |
288 | return PTR_ERR(ts3a227e->regmap); | 289 | return PTR_ERR(ts3a227e->regmap); |
289 | 290 | ||
290 | if (dev->of_node) { | 291 | ret = ts3a227e_parse_device_property(ts3a227e, dev); |
291 | ret = ts3a227e_parse_dt(ts3a227e, dev->of_node); | 292 | if (ret) { |
292 | if (ret) { | 293 | dev_err(dev, "Failed to parse device property: %d\n", ret); |
293 | dev_err(dev, "Failed to parse device tree: %d\n", ret); | 294 | return ret; |
294 | return ret; | ||
295 | } | ||
296 | } | 295 | } |
297 | 296 | ||
298 | ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt, | 297 | ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt, |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index d04693e9cf9f..90f5f04eca2d 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -1588,14 +1588,13 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec, | |||
1588 | case SND_SOC_BIAS_PREPARE: | 1588 | case SND_SOC_BIAS_PREPARE: |
1589 | break; | 1589 | break; |
1590 | case SND_SOC_BIAS_STANDBY: | 1590 | case SND_SOC_BIAS_STANDBY: |
1591 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 1591 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
1592 | twl4030_codec_enable(codec, 1); | 1592 | twl4030_codec_enable(codec, 1); |
1593 | break; | 1593 | break; |
1594 | case SND_SOC_BIAS_OFF: | 1594 | case SND_SOC_BIAS_OFF: |
1595 | twl4030_codec_enable(codec, 0); | 1595 | twl4030_codec_enable(codec, 0); |
1596 | break; | 1596 | break; |
1597 | } | 1597 | } |
1598 | codec->dapm.bias_level = level; | ||
1599 | 1598 | ||
1600 | return 0; | 1599 | return 0; |
1601 | } | 1600 | } |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index aeec27b6f1af..4cad8929d262 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -533,7 +533,7 @@ static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol, | |||
533 | 533 | ||
534 | int twl6040_get_dl1_gain(struct snd_soc_codec *codec) | 534 | int twl6040_get_dl1_gain(struct snd_soc_codec *codec) |
535 | { | 535 | { |
536 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 536 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
537 | 537 | ||
538 | if (snd_soc_dapm_get_pin_status(dapm, "EP")) | 538 | if (snd_soc_dapm_get_pin_status(dapm, "EP")) |
539 | return -1; /* -1dB */ | 539 | return -1; /* -1dB */ |
@@ -853,8 +853,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, | |||
853 | break; | 853 | break; |
854 | } | 854 | } |
855 | 855 | ||
856 | codec->dapm.bias_level = level; | ||
857 | |||
858 | return 0; | 856 | return 0; |
859 | } | 857 | } |
860 | 858 | ||
@@ -1123,14 +1121,15 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1123 | mutex_init(&priv->mutex); | 1121 | mutex_init(&priv->mutex); |
1124 | 1122 | ||
1125 | ret = request_threaded_irq(priv->plug_irq, NULL, | 1123 | ret = request_threaded_irq(priv->plug_irq, NULL, |
1126 | twl6040_audio_handler, IRQF_NO_SUSPEND, | 1124 | twl6040_audio_handler, |
1125 | IRQF_NO_SUSPEND | IRQF_ONESHOT, | ||
1127 | "twl6040_irq_plug", codec); | 1126 | "twl6040_irq_plug", codec); |
1128 | if (ret) { | 1127 | if (ret) { |
1129 | dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); | 1128 | dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); |
1130 | return ret; | 1129 | return ret; |
1131 | } | 1130 | } |
1132 | 1131 | ||
1133 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1132 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1134 | twl6040_init_chip(codec); | 1133 | twl6040_init_chip(codec); |
1135 | 1134 | ||
1136 | return 0; | 1135 | return 0; |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index f883308c00de..913edf283239 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -350,7 +350,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec, | |||
350 | pd->power(0); | 350 | pd->power(0); |
351 | break; | 351 | break; |
352 | } | 352 | } |
353 | codec->dapm.bias_level = level; | ||
354 | return 0; | 353 | return 0; |
355 | } | 354 | } |
356 | 355 | ||
@@ -478,6 +477,7 @@ static struct snd_soc_dai_driver uda134x_dai = { | |||
478 | 477 | ||
479 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | 478 | static int uda134x_soc_probe(struct snd_soc_codec *codec) |
480 | { | 479 | { |
480 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
481 | struct uda134x_priv *uda134x; | 481 | struct uda134x_priv *uda134x; |
482 | struct uda134x_platform_data *pd = codec->component.card->dev->platform_data; | 482 | struct uda134x_platform_data *pd = codec->component.card->dev->platform_data; |
483 | const struct snd_soc_dapm_widget *widgets; | 483 | const struct snd_soc_dapm_widget *widgets; |
@@ -526,7 +526,7 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec) | |||
526 | num_widgets = ARRAY_SIZE(uda1340_dapm_widgets); | 526 | num_widgets = ARRAY_SIZE(uda1340_dapm_widgets); |
527 | } | 527 | } |
528 | 528 | ||
529 | ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets); | 529 | ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets); |
530 | if (ret) { | 530 | if (ret) { |
531 | printk(KERN_ERR "%s failed to register dapm controls: %d", | 531 | printk(KERN_ERR "%s failed to register dapm controls: %d", |
532 | __func__, ret); | 532 | __func__, ret); |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index dc7778b6dd7f..6e159f59d219 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -437,7 +437,7 @@ static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, | |||
437 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) | 437 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) |
438 | return -EINVAL; | 438 | return -EINVAL; |
439 | 439 | ||
440 | uda1380_write(codec, UDA1380_IFACE, iface); | 440 | uda1380_write_reg_cache(codec, UDA1380_IFACE, iface); |
441 | 441 | ||
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
@@ -590,9 +590,6 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, | |||
590 | int reg; | 590 | int reg; |
591 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | 591 | struct uda1380_platform_data *pdata = codec->dev->platform_data; |
592 | 592 | ||
593 | if (codec->dapm.bias_level == level) | ||
594 | return 0; | ||
595 | |||
596 | switch (level) { | 593 | switch (level) { |
597 | case SND_SOC_BIAS_ON: | 594 | case SND_SOC_BIAS_ON: |
598 | case SND_SOC_BIAS_PREPARE: | 595 | case SND_SOC_BIAS_PREPARE: |
@@ -600,7 +597,7 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, | |||
600 | uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); | 597 | uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); |
601 | break; | 598 | break; |
602 | case SND_SOC_BIAS_STANDBY: | 599 | case SND_SOC_BIAS_STANDBY: |
603 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 600 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
604 | if (gpio_is_valid(pdata->gpio_power)) { | 601 | if (gpio_is_valid(pdata->gpio_power)) { |
605 | gpio_set_value(pdata->gpio_power, 1); | 602 | gpio_set_value(pdata->gpio_power, 1); |
606 | mdelay(1); | 603 | mdelay(1); |
@@ -623,7 +620,6 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, | |||
623 | for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) | 620 | for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) |
624 | set_bit(reg - 0x10, &uda1380_cache_dirty); | 621 | set_bit(reg - 0x10, &uda1380_cache_dirty); |
625 | } | 622 | } |
626 | codec->dapm.bias_level = level; | ||
627 | return 0; | 623 | return 0; |
628 | } | 624 | } |
629 | 625 | ||
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index f37989ec7cba..6560a66b3f35 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -751,13 +751,13 @@ static int wm0010_set_bias_level(struct snd_soc_codec *codec, | |||
751 | 751 | ||
752 | switch (level) { | 752 | switch (level) { |
753 | case SND_SOC_BIAS_ON: | 753 | case SND_SOC_BIAS_ON: |
754 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | 754 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) |
755 | wm0010_boot(codec); | 755 | wm0010_boot(codec); |
756 | break; | 756 | break; |
757 | case SND_SOC_BIAS_PREPARE: | 757 | case SND_SOC_BIAS_PREPARE: |
758 | break; | 758 | break; |
759 | case SND_SOC_BIAS_STANDBY: | 759 | case SND_SOC_BIAS_STANDBY: |
760 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | 760 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { |
761 | mutex_lock(&wm0010->lock); | 761 | mutex_lock(&wm0010->lock); |
762 | wm0010_halt(codec); | 762 | wm0010_halt(codec); |
763 | mutex_unlock(&wm0010->lock); | 763 | mutex_unlock(&wm0010->lock); |
@@ -767,8 +767,6 @@ static int wm0010_set_bias_level(struct snd_soc_codec *codec, | |||
767 | break; | 767 | break; |
768 | } | 768 | } |
769 | 769 | ||
770 | codec->dapm.bias_level = level; | ||
771 | |||
772 | return 0; | 770 | return 0; |
773 | } | 771 | } |
774 | 772 | ||
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 8011f75fb6cb..048f00568260 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -61,8 +61,6 @@ static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec, | |||
61 | break; | 61 | break; |
62 | } | 62 | } |
63 | 63 | ||
64 | codec->dapm.bias_level = level; | ||
65 | |||
66 | return 0; | 64 | return 0; |
67 | } | 65 | } |
68 | 66 | ||
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 5a9da28f4f33..c83083285e53 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1555,7 +1555,7 @@ static int wm2200_probe(struct snd_soc_codec *codec) | |||
1555 | 1555 | ||
1556 | wm2200->codec = codec; | 1556 | wm2200->codec = codec; |
1557 | 1557 | ||
1558 | ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); | 1558 | ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2); |
1559 | if (ret != 0) | 1559 | if (ret != 0) |
1560 | return ret; | 1560 | return ret; |
1561 | 1561 | ||
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 96740379b711..4c10cd88c1af 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -2101,7 +2101,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) | |||
2101 | int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | 2101 | int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) |
2102 | { | 2102 | { |
2103 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2103 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
2104 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2104 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2105 | 2105 | ||
2106 | if (jack) { | 2106 | if (jack) { |
2107 | wm5100->jack = jack; | 2107 | wm5100->jack = jack; |
@@ -2336,6 +2336,7 @@ static void wm5100_free_gpio(struct i2c_client *i2c) | |||
2336 | 2336 | ||
2337 | static int wm5100_probe(struct snd_soc_codec *codec) | 2337 | static int wm5100_probe(struct snd_soc_codec *codec) |
2338 | { | 2338 | { |
2339 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2339 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2340 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2340 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2341 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
2341 | int ret, i; | 2342 | int ret, i; |
@@ -2353,8 +2354,7 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2353 | /* TODO: check if we're symmetric */ | 2354 | /* TODO: check if we're symmetric */ |
2354 | 2355 | ||
2355 | if (i2c->irq) | 2356 | if (i2c->irq) |
2356 | snd_soc_dapm_new_controls(&codec->dapm, | 2357 | snd_soc_dapm_new_controls(dapm, wm5100_dapm_widgets_noirq, |
2357 | wm5100_dapm_widgets_noirq, | ||
2358 | ARRAY_SIZE(wm5100_dapm_widgets_noirq)); | 2358 | ARRAY_SIZE(wm5100_dapm_widgets_noirq)); |
2359 | 2359 | ||
2360 | if (wm5100->pdata.hp_pol) { | 2360 | if (wm5100->pdata.hp_pol) { |
@@ -2570,11 +2570,13 @@ static int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2570 | 2570 | ||
2571 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | 2571 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2572 | ret = request_threaded_irq(i2c->irq, NULL, | 2572 | ret = request_threaded_irq(i2c->irq, NULL, |
2573 | wm5100_edge_irq, irq_flags, | 2573 | wm5100_edge_irq, |
2574 | irq_flags | IRQF_ONESHOT, | ||
2574 | "wm5100", wm5100); | 2575 | "wm5100", wm5100); |
2575 | else | 2576 | else |
2576 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, | 2577 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, |
2577 | irq_flags, "wm5100", | 2578 | irq_flags | IRQF_ONESHOT, |
2579 | "wm5100", | ||
2578 | wm5100); | 2580 | wm5100); |
2579 | 2581 | ||
2580 | if (ret != 0) { | 2582 | if (ret != 0) { |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 0c6d1bc0526e..d097f09e50f2 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -42,7 +42,7 @@ struct wm5102_priv { | |||
42 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | 42 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); |
43 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 43 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
44 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 44 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
45 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | 45 | static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); |
46 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | 46 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); |
47 | 47 | ||
48 | static const struct wm_adsp_region wm5102_dsp1_regions[] = { | 48 | static const struct wm_adsp_region wm5102_dsp1_regions[] = { |
@@ -605,12 +605,56 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
605 | regmap_write_async(regmap, patch[i].reg, | 605 | regmap_write_async(regmap, patch[i].reg, |
606 | patch[i].def); | 606 | patch[i].def); |
607 | break; | 607 | break; |
608 | case SND_SOC_DAPM_PRE_PMD: | ||
609 | break; | ||
610 | default: | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | return arizona_dvfs_sysclk_ev(w, kcontrol, event); | ||
615 | } | ||
616 | |||
617 | static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, | ||
618 | struct snd_kcontrol *kcontrol, int event) | ||
619 | { | ||
620 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
621 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
622 | unsigned int v; | ||
623 | int ret; | ||
624 | |||
625 | switch (event) { | ||
626 | case SND_SOC_DAPM_PRE_PMU: | ||
627 | ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v); | ||
628 | if (ret != 0) { | ||
629 | dev_err(codec->dev, | ||
630 | "Failed to read SYSCLK state: %d\n", ret); | ||
631 | return -EIO; | ||
632 | } | ||
633 | |||
634 | v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT; | ||
635 | |||
636 | if (v >= 3) { | ||
637 | ret = arizona_dvfs_up(codec, ARIZONA_DVFS_ADSP1_RQ); | ||
638 | if (ret) { | ||
639 | dev_err(codec->dev, | ||
640 | "Failed to raise DVFS: %d\n", ret); | ||
641 | return ret; | ||
642 | } | ||
643 | } | ||
644 | break; | ||
645 | |||
646 | case SND_SOC_DAPM_POST_PMD: | ||
647 | ret = arizona_dvfs_down(codec, ARIZONA_DVFS_ADSP1_RQ); | ||
648 | if (ret) | ||
649 | dev_warn(codec->dev, | ||
650 | "Failed to lower DVFS: %d\n", ret); | ||
651 | break; | ||
608 | 652 | ||
609 | default: | 653 | default: |
610 | break; | 654 | break; |
611 | } | 655 | } |
612 | 656 | ||
613 | return 0; | 657 | return wm_adsp2_early_event(w, kcontrol, event); |
614 | } | 658 | } |
615 | 659 | ||
616 | static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | 660 | static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, |
@@ -1036,7 +1080,8 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux = | |||
1036 | 1080 | ||
1037 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | 1081 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { |
1038 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 1082 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
1039 | 0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU), | 1083 | 0, wm5102_sysclk_ev, |
1084 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
1040 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 1085 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
1041 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 1086 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
1042 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | 1087 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, |
@@ -1367,7 +1412,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | |||
1367 | ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | 1412 | ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), |
1368 | ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | 1413 | ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), |
1369 | 1414 | ||
1370 | WM_ADSP2("DSP1", 0), | 1415 | WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev), |
1371 | 1416 | ||
1372 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | 1417 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), |
1373 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 1418 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
@@ -1827,19 +1872,25 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1827 | 1872 | ||
1828 | static int wm5102_codec_probe(struct snd_soc_codec *codec) | 1873 | static int wm5102_codec_probe(struct snd_soc_codec *codec) |
1829 | { | 1874 | { |
1875 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1830 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | 1876 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); |
1831 | int ret; | 1877 | int ret; |
1832 | 1878 | ||
1833 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2); | 1879 | ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec); |
1834 | if (ret != 0) | 1880 | if (ret) |
1881 | return ret; | ||
1882 | |||
1883 | ret = snd_soc_add_codec_controls(codec, | ||
1884 | arizona_adsp2_rate_controls, 1); | ||
1885 | if (ret) | ||
1835 | return ret; | 1886 | return ret; |
1836 | 1887 | ||
1837 | arizona_init_spk(codec); | 1888 | arizona_init_spk(codec); |
1838 | arizona_init_gpio(codec); | 1889 | arizona_init_gpio(codec); |
1839 | 1890 | ||
1840 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1891 | snd_soc_dapm_disable_pin(dapm, "HAPTICS"); |
1841 | 1892 | ||
1842 | priv->core.arizona->dapm = &codec->dapm; | 1893 | priv->core.arizona->dapm = dapm; |
1843 | 1894 | ||
1844 | return 0; | 1895 | return 0; |
1845 | } | 1896 | } |
@@ -1848,6 +1899,8 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec) | |||
1848 | { | 1899 | { |
1849 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | 1900 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); |
1850 | 1901 | ||
1902 | wm_adsp2_codec_remove(&priv->core.adsp[0], codec); | ||
1903 | |||
1851 | priv->core.arizona->dapm = NULL; | 1904 | priv->core.arizona->dapm = NULL; |
1852 | 1905 | ||
1853 | return 0; | 1906 | return 0; |
@@ -1909,6 +1962,8 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1909 | wm5102->core.arizona = arizona; | 1962 | wm5102->core.arizona = arizona; |
1910 | wm5102->core.num_inputs = 6; | 1963 | wm5102->core.num_inputs = 6; |
1911 | 1964 | ||
1965 | arizona_init_dvfs(&wm5102->core); | ||
1966 | |||
1912 | wm5102->core.adsp[0].part = "wm5102"; | 1967 | wm5102->core.adsp[0].part = "wm5102"; |
1913 | wm5102->core.adsp[0].num = 1; | 1968 | wm5102->core.adsp[0].num = 1; |
1914 | wm5102->core.adsp[0].type = WMFW_ADSP2; | 1969 | wm5102->core.adsp[0].type = WMFW_ADSP2; |
@@ -1918,7 +1973,7 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1918 | wm5102->core.adsp[0].mem = wm5102_dsp1_regions; | 1973 | wm5102->core.adsp[0].mem = wm5102_dsp1_regions; |
1919 | wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions); | 1974 | wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions); |
1920 | 1975 | ||
1921 | ret = wm_adsp2_init(&wm5102->core.adsp[0], true); | 1976 | ret = wm_adsp2_init(&wm5102->core.adsp[0]); |
1922 | if (ret != 0) | 1977 | if (ret != 0) |
1923 | return ret; | 1978 | return ret; |
1924 | 1979 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index fbaeddb3e903..709fcc6169d8 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -167,7 +167,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
167 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | 167 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); |
168 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 168 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
169 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 169 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
170 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | 170 | static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); |
171 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | 171 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); |
172 | 172 | ||
173 | #define WM5110_NG_SRC(name, base) \ | 173 | #define WM5110_NG_SRC(name, base) \ |
@@ -1598,22 +1598,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1598 | 1598 | ||
1599 | static int wm5110_codec_probe(struct snd_soc_codec *codec) | 1599 | static int wm5110_codec_probe(struct snd_soc_codec *codec) |
1600 | { | 1600 | { |
1601 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1601 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | 1602 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); |
1602 | int ret; | 1603 | int i, ret; |
1603 | 1604 | ||
1604 | priv->core.arizona->dapm = &codec->dapm; | 1605 | priv->core.arizona->dapm = dapm; |
1605 | 1606 | ||
1606 | arizona_init_spk(codec); | 1607 | arizona_init_spk(codec); |
1607 | arizona_init_gpio(codec); | 1608 | arizona_init_gpio(codec); |
1608 | arizona_init_mono(codec); | 1609 | arizona_init_mono(codec); |
1609 | 1610 | ||
1610 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); | 1611 | for (i = 0; i < WM5110_NUM_ADSP; ++i) { |
1611 | if (ret != 0) | 1612 | ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec); |
1612 | return ret; | 1613 | if (ret) |
1614 | return ret; | ||
1615 | } | ||
1613 | 1616 | ||
1614 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1617 | ret = snd_soc_add_codec_controls(codec, |
1618 | arizona_adsp2_rate_controls, | ||
1619 | WM5110_NUM_ADSP); | ||
1620 | if (ret) | ||
1621 | return ret; | ||
1615 | 1622 | ||
1616 | priv->core.arizona->dapm = &codec->dapm; | 1623 | snd_soc_dapm_disable_pin(dapm, "HAPTICS"); |
1617 | 1624 | ||
1618 | return 0; | 1625 | return 0; |
1619 | } | 1626 | } |
@@ -1621,6 +1628,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1621 | static int wm5110_codec_remove(struct snd_soc_codec *codec) | 1628 | static int wm5110_codec_remove(struct snd_soc_codec *codec) |
1622 | { | 1629 | { |
1623 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | 1630 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); |
1631 | int i; | ||
1632 | |||
1633 | for (i = 0; i < WM5110_NUM_ADSP; ++i) | ||
1634 | wm_adsp2_codec_remove(&priv->core.adsp[i], codec); | ||
1624 | 1635 | ||
1625 | priv->core.arizona->dapm = NULL; | 1636 | priv->core.arizona->dapm = NULL; |
1626 | 1637 | ||
@@ -1697,7 +1708,7 @@ static int wm5110_probe(struct platform_device *pdev) | |||
1697 | wm5110->core.adsp[i].num_mems | 1708 | wm5110->core.adsp[i].num_mems |
1698 | = ARRAY_SIZE(wm5110_dsp1_regions); | 1709 | = ARRAY_SIZE(wm5110_dsp1_regions); |
1699 | 1710 | ||
1700 | ret = wm_adsp2_init(&wm5110->core.adsp[i], false); | 1711 | ret = wm_adsp2_init(&wm5110->core.adsp[i]); |
1701 | if (ret != 0) | 1712 | if (ret != 0) |
1702 | return ret; | 1713 | return ret; |
1703 | } | 1714 | } |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index c65e5a75fc1a..41c62c1e62db 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1102,7 +1102,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1102 | break; | 1102 | break; |
1103 | 1103 | ||
1104 | case SND_SOC_BIAS_STANDBY: | 1104 | case SND_SOC_BIAS_STANDBY: |
1105 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1105 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1106 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), | 1106 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), |
1107 | priv->supplies); | 1107 | priv->supplies); |
1108 | if (ret != 0) | 1108 | if (ret != 0) |
@@ -1235,7 +1235,6 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1235 | priv->supplies); | 1235 | priv->supplies); |
1236 | break; | 1236 | break; |
1237 | } | 1237 | } |
1238 | codec->dapm.bias_level = level; | ||
1239 | return 0; | 1238 | return 0; |
1240 | } | 1239 | } |
1241 | 1240 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b0d84e552fca..d7555085e7f4 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1145,7 +1145,7 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec, | |||
1145 | break; | 1145 | break; |
1146 | 1146 | ||
1147 | case SND_SOC_BIAS_STANDBY: | 1147 | case SND_SOC_BIAS_STANDBY: |
1148 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1148 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1149 | ret = regulator_bulk_enable(ARRAY_SIZE(power), | 1149 | ret = regulator_bulk_enable(ARRAY_SIZE(power), |
1150 | &power[0]); | 1150 | &power[0]); |
1151 | if (ret != 0) { | 1151 | if (ret != 0) { |
@@ -1232,7 +1232,6 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec, | |||
1232 | break; | 1232 | break; |
1233 | } | 1233 | } |
1234 | 1234 | ||
1235 | codec->dapm.bias_level = level; | ||
1236 | return 0; | 1235 | return 0; |
1237 | } | 1236 | } |
1238 | 1237 | ||
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 8736ad094b24..dac5beb4d023 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -519,7 +519,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, | |||
519 | case SND_SOC_BIAS_STANDBY: | 519 | case SND_SOC_BIAS_STANDBY: |
520 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; | 520 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; |
521 | 521 | ||
522 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 522 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
523 | regcache_sync(wm8510->regmap); | 523 | regcache_sync(wm8510->regmap); |
524 | 524 | ||
525 | /* Initial cap charge at VMID 5k */ | 525 | /* Initial cap charge at VMID 5k */ |
@@ -538,7 +538,6 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, | |||
538 | break; | 538 | break; |
539 | } | 539 | } |
540 | 540 | ||
541 | codec->dapm.bias_level = level; | ||
542 | return 0; | 541 | return 0; |
543 | } | 542 | } |
544 | 543 | ||
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index b1cc94f5fc4b..43ea8ae5f871 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -113,6 +113,15 @@ static struct { | |||
113 | { 7, 1152 }, | 113 | { 7, 1152 }, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static struct { | ||
117 | int value; | ||
118 | int ratio; | ||
119 | } bclk_ratios[WM8523_NUM_RATES] = { | ||
120 | { 2, 32 }, | ||
121 | { 3, 64 }, | ||
122 | { 4, 128 }, | ||
123 | }; | ||
124 | |||
116 | static int wm8523_startup(struct snd_pcm_substream *substream, | 125 | static int wm8523_startup(struct snd_pcm_substream *substream, |
117 | struct snd_soc_dai *dai) | 126 | struct snd_soc_dai *dai) |
118 | { | 127 | { |
@@ -162,6 +171,23 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, | |||
162 | aifctrl2 &= ~WM8523_SR_MASK; | 171 | aifctrl2 &= ~WM8523_SR_MASK; |
163 | aifctrl2 |= lrclk_ratios[i].value; | 172 | aifctrl2 |= lrclk_ratios[i].value; |
164 | 173 | ||
174 | if (aifctrl1 & WM8523_AIF_MSTR) { | ||
175 | /* Find a fs->bclk ratio */ | ||
176 | for (i = 0; i < ARRAY_SIZE(bclk_ratios); i++) | ||
177 | if (params_width(params) * 2 <= bclk_ratios[i].ratio) | ||
178 | break; | ||
179 | |||
180 | if (i == ARRAY_SIZE(bclk_ratios)) { | ||
181 | dev_err(codec->dev, | ||
182 | "No matching BCLK/fs ratio for word length %d\n", | ||
183 | params_width(params)); | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | |||
187 | aifctrl2 &= ~WM8523_BCLKDIV_MASK; | ||
188 | aifctrl2 |= bclk_ratios[i].value << WM8523_BCLKDIV_SHIFT; | ||
189 | } | ||
190 | |||
165 | aifctrl1 &= ~WM8523_WL_MASK; | 191 | aifctrl1 &= ~WM8523_WL_MASK; |
166 | switch (params_width(params)) { | 192 | switch (params_width(params)) { |
167 | case 16: | 193 | case 16: |
@@ -308,7 +334,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
308 | break; | 334 | break; |
309 | 335 | ||
310 | case SND_SOC_BIAS_STANDBY: | 336 | case SND_SOC_BIAS_STANDBY: |
311 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 337 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
312 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | 338 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), |
313 | wm8523->supplies); | 339 | wm8523->supplies); |
314 | if (ret != 0) { | 340 | if (ret != 0) { |
@@ -344,7 +370,6 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
344 | wm8523->supplies); | 370 | wm8523->supplies); |
345 | break; | 371 | break; |
346 | } | 372 | } |
347 | codec->dapm.bias_level = level; | ||
348 | return 0; | 373 | return 0; |
349 | } | 374 | } |
350 | 375 | ||
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 0a887c5ec83a..759a7928ac3e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -795,7 +795,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
795 | break; | 795 | break; |
796 | 796 | ||
797 | case SND_SOC_BIAS_STANDBY: | 797 | case SND_SOC_BIAS_STANDBY: |
798 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 798 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
799 | /* Power up and get individual control of the DACs */ | 799 | /* Power up and get individual control of the DACs */ |
800 | snd_soc_update_bits(codec, WM8580_PWRDN1, | 800 | snd_soc_update_bits(codec, WM8580_PWRDN1, |
801 | WM8580_PWRDN1_PWDN | | 801 | WM8580_PWRDN1_PWDN | |
@@ -812,7 +812,6 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
812 | WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN); | 812 | WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN); |
813 | break; | 813 | break; |
814 | } | 814 | } |
815 | codec->dapm.bias_level = level; | ||
816 | return 0; | 815 | return 0; |
817 | } | 816 | } |
818 | 817 | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 121e46d53779..cc8251f09f8a 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -310,7 +310,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, | |||
310 | case SND_SOC_BIAS_PREPARE: | 310 | case SND_SOC_BIAS_PREPARE: |
311 | break; | 311 | break; |
312 | case SND_SOC_BIAS_STANDBY: | 312 | case SND_SOC_BIAS_STANDBY: |
313 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 313 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
314 | regcache_sync(wm8711->regmap); | 314 | regcache_sync(wm8711->regmap); |
315 | 315 | ||
316 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); | 316 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); |
@@ -320,7 +320,6 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, | |||
320 | snd_soc_write(codec, WM8711_PWR, 0xffff); | 320 | snd_soc_write(codec, WM8711_PWR, 0xffff); |
321 | break; | 321 | break; |
322 | } | 322 | } |
323 | codec->dapm.bias_level = level; | ||
324 | return 0; | 323 | return 0; |
325 | } | 324 | } |
326 | 325 | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 55c7fb4fc786..f1a173e6ec33 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -170,7 +170,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, | |||
170 | case SND_SOC_BIAS_ON: | 170 | case SND_SOC_BIAS_ON: |
171 | case SND_SOC_BIAS_PREPARE: | 171 | case SND_SOC_BIAS_PREPARE: |
172 | case SND_SOC_BIAS_STANDBY: | 172 | case SND_SOC_BIAS_STANDBY: |
173 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 173 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
174 | /* Power everything up... */ | 174 | /* Power everything up... */ |
175 | reg = snd_soc_read(codec, WM8728_DACCTL); | 175 | reg = snd_soc_read(codec, WM8728_DACCTL); |
176 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); | 176 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); |
@@ -185,7 +185,6 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, | |||
185 | snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); | 185 | snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); |
186 | break; | 186 | break; |
187 | } | 187 | } |
188 | codec->dapm.bias_level = level; | ||
189 | return 0; | 188 | return 0; |
190 | } | 189 | } |
191 | 190 | ||
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 2245b6a32f3d..915ea11ad4b6 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -387,6 +387,7 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
387 | int clk_id, unsigned int freq, int dir) | 387 | int clk_id, unsigned int freq, int dir) |
388 | { | 388 | { |
389 | struct snd_soc_codec *codec = codec_dai->codec; | 389 | struct snd_soc_codec *codec = codec_dai->codec; |
390 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
390 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 391 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
391 | 392 | ||
392 | switch (clk_id) { | 393 | switch (clk_id) { |
@@ -421,7 +422,7 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
421 | 422 | ||
422 | wm8731->sysclk = freq; | 423 | wm8731->sysclk = freq; |
423 | 424 | ||
424 | snd_soc_dapm_sync(&codec->dapm); | 425 | snd_soc_dapm_sync(dapm); |
425 | 426 | ||
426 | return 0; | 427 | return 0; |
427 | } | 428 | } |
@@ -501,7 +502,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
501 | case SND_SOC_BIAS_PREPARE: | 502 | case SND_SOC_BIAS_PREPARE: |
502 | break; | 503 | break; |
503 | case SND_SOC_BIAS_STANDBY: | 504 | case SND_SOC_BIAS_STANDBY: |
504 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 505 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
505 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | 506 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), |
506 | wm8731->supplies); | 507 | wm8731->supplies); |
507 | if (ret != 0) | 508 | if (ret != 0) |
@@ -523,7 +524,6 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
523 | regcache_mark_dirty(wm8731->regmap); | 524 | regcache_mark_dirty(wm8731->regmap); |
524 | break; | 525 | break; |
525 | } | 526 | } |
526 | codec->dapm.bias_level = level; | ||
527 | return 0; | 527 | return 0; |
528 | } | 528 | } |
529 | 529 | ||
@@ -599,7 +599,7 @@ static int wm8731_probe(struct snd_soc_codec *codec) | |||
599 | goto err_regulator_enable; | 599 | goto err_regulator_enable; |
600 | } | 600 | } |
601 | 601 | ||
602 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 602 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
603 | 603 | ||
604 | /* Latch the update bits */ | 604 | /* Latch the update bits */ |
605 | snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); | 605 | snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index ada9ac1ba2c6..6ad606fd8b69 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -469,7 +469,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
469 | break; | 469 | break; |
470 | 470 | ||
471 | case SND_SOC_BIAS_STANDBY: | 471 | case SND_SOC_BIAS_STANDBY: |
472 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 472 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
473 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), | 473 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), |
474 | wm8737->supplies); | 474 | wm8737->supplies); |
475 | if (ret != 0) { | 475 | if (ret != 0) { |
@@ -483,7 +483,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
483 | 483 | ||
484 | /* Fast VMID ramp at 2*2.5k */ | 484 | /* Fast VMID ramp at 2*2.5k */ |
485 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, | 485 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, |
486 | WM8737_VMIDSEL_MASK, 0x4); | 486 | WM8737_VMIDSEL_MASK, |
487 | 2 << WM8737_VMIDSEL_SHIFT); | ||
487 | 488 | ||
488 | /* Bring VMID up */ | 489 | /* Bring VMID up */ |
489 | snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, | 490 | snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, |
@@ -497,7 +498,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
497 | 498 | ||
498 | /* VMID at 2*300k */ | 499 | /* VMID at 2*300k */ |
499 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, | 500 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, |
500 | WM8737_VMIDSEL_MASK, 2); | 501 | WM8737_VMIDSEL_MASK, |
502 | 1 << WM8737_VMIDSEL_SHIFT); | ||
501 | 503 | ||
502 | break; | 504 | break; |
503 | 505 | ||
@@ -510,7 +512,6 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
510 | break; | 512 | break; |
511 | } | 513 | } |
512 | 514 | ||
513 | codec->dapm.bias_level = level; | ||
514 | return 0; | 515 | return 0; |
515 | } | 516 | } |
516 | 517 | ||
@@ -560,7 +561,7 @@ static int wm8737_probe(struct snd_soc_codec *codec) | |||
560 | snd_soc_update_bits(codec, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU, | 561 | snd_soc_update_bits(codec, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU, |
561 | WM8737_RVU); | 562 | WM8737_RVU); |
562 | 563 | ||
563 | wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 564 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
564 | 565 | ||
565 | /* Bias level configuration will have done an extra enable */ | 566 | /* Bias level configuration will have done an extra enable */ |
566 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | 567 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 9e71c768966f..b34623786e35 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -41,6 +41,7 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
41 | 41 | ||
42 | /* codec private data */ | 42 | /* codec private data */ |
43 | struct wm8741_priv { | 43 | struct wm8741_priv { |
44 | struct wm8741_platform_data pdata; | ||
44 | struct regmap *regmap; | 45 | struct regmap *regmap; |
45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 46 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
46 | unsigned int sysclk; | 47 | unsigned int sysclk; |
@@ -87,13 +88,27 @@ static int wm8741_reset(struct snd_soc_codec *codec) | |||
87 | static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0); | 88 | static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0); |
88 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0); | 89 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0); |
89 | 90 | ||
90 | static const struct snd_kcontrol_new wm8741_snd_controls[] = { | 91 | static const struct snd_kcontrol_new wm8741_snd_controls_stereo[] = { |
91 | SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, | 92 | SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, |
92 | WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine), | 93 | WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine), |
93 | SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, | 94 | SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, |
94 | WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv), | 95 | WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv), |
95 | }; | 96 | }; |
96 | 97 | ||
98 | static const struct snd_kcontrol_new wm8741_snd_controls_mono_left[] = { | ||
99 | SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, | ||
100 | 1, 255, 1, dac_tlv_fine), | ||
101 | SOC_SINGLE_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, | ||
102 | 0, 511, 1, dac_tlv), | ||
103 | }; | ||
104 | |||
105 | static const struct snd_kcontrol_new wm8741_snd_controls_mono_right[] = { | ||
106 | SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACRLSB_ATTENUATION, | ||
107 | 1, 255, 1, dac_tlv_fine), | ||
108 | SOC_SINGLE_TLV("Playback Volume", WM8741_DACRMSB_ATTENUATION, | ||
109 | 0, 511, 1, dac_tlv), | ||
110 | }; | ||
111 | |||
97 | static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = { | 112 | static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = { |
98 | SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0), | 113 | SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0), |
99 | SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0), | 114 | SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0), |
@@ -110,18 +125,6 @@ static const struct snd_soc_dapm_route wm8741_dapm_routes[] = { | |||
110 | { "VOUTRN", NULL, "DACR" }, | 125 | { "VOUTRN", NULL, "DACR" }, |
111 | }; | 126 | }; |
112 | 127 | ||
113 | static struct { | ||
114 | int value; | ||
115 | int ratio; | ||
116 | } lrclk_ratios[WM8741_NUM_RATES] = { | ||
117 | { 1, 128 }, | ||
118 | { 2, 192 }, | ||
119 | { 3, 256 }, | ||
120 | { 4, 384 }, | ||
121 | { 5, 512 }, | ||
122 | { 6, 768 }, | ||
123 | }; | ||
124 | |||
125 | static const unsigned int rates_11289[] = { | 128 | static const unsigned int rates_11289[] = { |
126 | 44100, 88200, | 129 | 44100, 88200, |
127 | }; | 130 | }; |
@@ -194,25 +197,16 @@ static const struct snd_pcm_hw_constraint_list constraints_36864 = { | |||
194 | .list = rates_36864, | 197 | .list = rates_36864, |
195 | }; | 198 | }; |
196 | 199 | ||
197 | |||
198 | static int wm8741_startup(struct snd_pcm_substream *substream, | 200 | static int wm8741_startup(struct snd_pcm_substream *substream, |
199 | struct snd_soc_dai *dai) | 201 | struct snd_soc_dai *dai) |
200 | { | 202 | { |
201 | struct snd_soc_codec *codec = dai->codec; | 203 | struct snd_soc_codec *codec = dai->codec; |
202 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 204 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
203 | 205 | ||
204 | /* The set of sample rates that can be supported depends on the | 206 | if (wm8741->sysclk) |
205 | * MCLK supplied to the CODEC - enforce this. | 207 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
206 | */ | 208 | SNDRV_PCM_HW_PARAM_RATE, |
207 | if (!wm8741->sysclk) { | 209 | wm8741->sysclk_constraints); |
208 | dev_err(codec->dev, | ||
209 | "No MCLK configured, call set_sysclk() on init\n"); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
214 | SNDRV_PCM_HW_PARAM_RATE, | ||
215 | wm8741->sysclk_constraints); | ||
216 | 210 | ||
217 | return 0; | 211 | return 0; |
218 | } | 212 | } |
@@ -226,17 +220,24 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, | |||
226 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; | 220 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; |
227 | int i; | 221 | int i; |
228 | 222 | ||
229 | /* Find a supported LRCLK ratio */ | 223 | /* The set of sample rates that can be supported depends on the |
230 | for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { | 224 | * MCLK supplied to the CODEC - enforce this. |
231 | if (wm8741->sysclk / params_rate(params) == | 225 | */ |
232 | lrclk_ratios[i].ratio) | 226 | if (!wm8741->sysclk) { |
227 | dev_err(codec->dev, | ||
228 | "No MCLK configured, call set_sysclk() on init or in hw_params\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | /* Find a supported LRCLK rate */ | ||
233 | for (i = 0; i < wm8741->sysclk_constraints->count; i++) { | ||
234 | if (wm8741->sysclk_constraints->list[i] == params_rate(params)) | ||
233 | break; | 235 | break; |
234 | } | 236 | } |
235 | 237 | ||
236 | /* Should never happen, should be handled by constraints */ | 238 | if (i == wm8741->sysclk_constraints->count) { |
237 | if (i == ARRAY_SIZE(lrclk_ratios)) { | 239 | dev_err(codec->dev, "LRCLK %d unsupported with MCLK %d\n", |
238 | dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", | 240 | params_rate(params), wm8741->sysclk); |
239 | wm8741->sysclk / params_rate(params)); | ||
240 | return -EINVAL; | 241 | return -EINVAL; |
241 | } | 242 | } |
242 | 243 | ||
@@ -259,8 +260,8 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, | |||
259 | return -EINVAL; | 260 | return -EINVAL; |
260 | } | 261 | } |
261 | 262 | ||
262 | dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", | 263 | dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d, rate param = %d", |
263 | params_width(params)); | 264 | params_width(params), params_rate(params)); |
264 | 265 | ||
265 | snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); | 266 | snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); |
266 | return 0; | 267 | return 0; |
@@ -275,6 +276,11 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
275 | dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); | 276 | dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); |
276 | 277 | ||
277 | switch (freq) { | 278 | switch (freq) { |
279 | case 0: | ||
280 | wm8741->sysclk_constraints = NULL; | ||
281 | wm8741->sysclk = freq; | ||
282 | return 0; | ||
283 | |||
278 | case 11289600: | 284 | case 11289600: |
279 | wm8741->sysclk_constraints = &constraints_11289; | 285 | wm8741->sysclk_constraints = &constraints_11289; |
280 | wm8741->sysclk = freq; | 286 | wm8741->sysclk = freq; |
@@ -398,7 +404,7 @@ static struct snd_soc_dai_driver wm8741_dai = { | |||
398 | .name = "wm8741", | 404 | .name = "wm8741", |
399 | .playback = { | 405 | .playback = { |
400 | .stream_name = "Playback", | 406 | .stream_name = "Playback", |
401 | .channels_min = 2, /* Mono modes not yet supported */ | 407 | .channels_min = 2, |
402 | .channels_max = 2, | 408 | .channels_max = 2, |
403 | .rates = WM8741_RATES, | 409 | .rates = WM8741_RATES, |
404 | .formats = WM8741_FORMATS, | 410 | .formats = WM8741_FORMATS, |
@@ -416,6 +422,65 @@ static int wm8741_resume(struct snd_soc_codec *codec) | |||
416 | #define wm8741_resume NULL | 422 | #define wm8741_resume NULL |
417 | #endif | 423 | #endif |
418 | 424 | ||
425 | static int wm8741_configure(struct snd_soc_codec *codec) | ||
426 | { | ||
427 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | ||
428 | |||
429 | /* Configure differential mode */ | ||
430 | switch (wm8741->pdata.diff_mode) { | ||
431 | case WM8741_DIFF_MODE_STEREO: | ||
432 | case WM8741_DIFF_MODE_STEREO_REVERSED: | ||
433 | case WM8741_DIFF_MODE_MONO_LEFT: | ||
434 | case WM8741_DIFF_MODE_MONO_RIGHT: | ||
435 | snd_soc_update_bits(codec, WM8741_MODE_CONTROL_2, | ||
436 | WM8741_DIFF_MASK, | ||
437 | wm8741->pdata.diff_mode << WM8741_DIFF_SHIFT); | ||
438 | break; | ||
439 | default: | ||
440 | return -EINVAL; | ||
441 | } | ||
442 | |||
443 | /* Change some default settings - latch VU */ | ||
444 | snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION, | ||
445 | WM8741_UPDATELL, WM8741_UPDATELL); | ||
446 | snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION, | ||
447 | WM8741_UPDATELM, WM8741_UPDATELM); | ||
448 | snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, | ||
449 | WM8741_UPDATERL, WM8741_UPDATERL); | ||
450 | snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION, | ||
451 | WM8741_UPDATERM, WM8741_UPDATERM); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int wm8741_add_controls(struct snd_soc_codec *codec) | ||
457 | { | ||
458 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | ||
459 | |||
460 | switch (wm8741->pdata.diff_mode) { | ||
461 | case WM8741_DIFF_MODE_STEREO: | ||
462 | case WM8741_DIFF_MODE_STEREO_REVERSED: | ||
463 | snd_soc_add_codec_controls(codec, | ||
464 | wm8741_snd_controls_stereo, | ||
465 | ARRAY_SIZE(wm8741_snd_controls_stereo)); | ||
466 | break; | ||
467 | case WM8741_DIFF_MODE_MONO_LEFT: | ||
468 | snd_soc_add_codec_controls(codec, | ||
469 | wm8741_snd_controls_mono_left, | ||
470 | ARRAY_SIZE(wm8741_snd_controls_mono_left)); | ||
471 | break; | ||
472 | case WM8741_DIFF_MODE_MONO_RIGHT: | ||
473 | snd_soc_add_codec_controls(codec, | ||
474 | wm8741_snd_controls_mono_right, | ||
475 | ARRAY_SIZE(wm8741_snd_controls_mono_right)); | ||
476 | break; | ||
477 | default: | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
419 | static int wm8741_probe(struct snd_soc_codec *codec) | 484 | static int wm8741_probe(struct snd_soc_codec *codec) |
420 | { | 485 | { |
421 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 486 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
@@ -434,15 +499,17 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
434 | goto err_enable; | 499 | goto err_enable; |
435 | } | 500 | } |
436 | 501 | ||
437 | /* Change some default settings - latch VU */ | 502 | ret = wm8741_configure(codec); |
438 | snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION, | 503 | if (ret < 0) { |
439 | WM8741_UPDATELL, WM8741_UPDATELL); | 504 | dev_err(codec->dev, "Failed to change default settings\n"); |
440 | snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION, | 505 | goto err_enable; |
441 | WM8741_UPDATELM, WM8741_UPDATELM); | 506 | } |
442 | snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, | 507 | |
443 | WM8741_UPDATERL, WM8741_UPDATERL); | 508 | ret = wm8741_add_controls(codec); |
444 | snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION, | 509 | if (ret < 0) { |
445 | WM8741_UPDATERM, WM8741_UPDATERM); | 510 | dev_err(codec->dev, "Failed to add controls\n"); |
511 | goto err_enable; | ||
512 | } | ||
446 | 513 | ||
447 | dev_dbg(codec->dev, "Successful registration\n"); | 514 | dev_dbg(codec->dev, "Successful registration\n"); |
448 | return ret; | 515 | return ret; |
@@ -467,8 +534,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { | |||
467 | .remove = wm8741_remove, | 534 | .remove = wm8741_remove, |
468 | .resume = wm8741_resume, | 535 | .resume = wm8741_resume, |
469 | 536 | ||
470 | .controls = wm8741_snd_controls, | ||
471 | .num_controls = ARRAY_SIZE(wm8741_snd_controls), | ||
472 | .dapm_widgets = wm8741_dapm_widgets, | 537 | .dapm_widgets = wm8741_dapm_widgets, |
473 | .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), | 538 | .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), |
474 | .dapm_routes = wm8741_dapm_routes, | 539 | .dapm_routes = wm8741_dapm_routes, |
@@ -493,6 +558,23 @@ static const struct regmap_config wm8741_regmap = { | |||
493 | .readable_reg = wm8741_readable, | 558 | .readable_reg = wm8741_readable, |
494 | }; | 559 | }; |
495 | 560 | ||
561 | static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) | ||
562 | { | ||
563 | const struct wm8741_platform_data *pdata = dev_get_platdata(dev); | ||
564 | u32 diff_mode; | ||
565 | |||
566 | if (dev->of_node) { | ||
567 | if (of_property_read_u32(dev->of_node, "diff-mode", &diff_mode) | ||
568 | >= 0) | ||
569 | wm8741->pdata.diff_mode = diff_mode; | ||
570 | } else { | ||
571 | if (pdata != NULL) | ||
572 | memcpy(&wm8741->pdata, pdata, sizeof(wm8741->pdata)); | ||
573 | } | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
496 | #if IS_ENABLED(CONFIG_I2C) | 578 | #if IS_ENABLED(CONFIG_I2C) |
497 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 579 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
498 | const struct i2c_device_id *id) | 580 | const struct i2c_device_id *id) |
@@ -522,6 +604,12 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, | |||
522 | return ret; | 604 | return ret; |
523 | } | 605 | } |
524 | 606 | ||
607 | ret = wm8741_set_pdata(&i2c->dev, wm8741); | ||
608 | if (ret != 0) { | ||
609 | dev_err(&i2c->dev, "Failed to set pdata: %d\n", ret); | ||
610 | return ret; | ||
611 | } | ||
612 | |||
525 | i2c_set_clientdata(i2c, wm8741); | 613 | i2c_set_clientdata(i2c, wm8741); |
526 | 614 | ||
527 | ret = snd_soc_register_codec(&i2c->dev, | 615 | ret = snd_soc_register_codec(&i2c->dev, |
@@ -582,6 +670,12 @@ static int wm8741_spi_probe(struct spi_device *spi) | |||
582 | return ret; | 670 | return ret; |
583 | } | 671 | } |
584 | 672 | ||
673 | ret = wm8741_set_pdata(&spi->dev, wm8741); | ||
674 | if (ret != 0) { | ||
675 | dev_err(&spi->dev, "Failed to set pdata: %d\n", ret); | ||
676 | return ret; | ||
677 | } | ||
678 | |||
585 | spi_set_drvdata(spi, wm8741); | 679 | spi_set_drvdata(spi, wm8741); |
586 | 680 | ||
587 | ret = snd_soc_register_codec(&spi->dev, | 681 | ret = snd_soc_register_codec(&spi->dev, |
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h index 56c1b1d4a681..c8835f65f342 100644 --- a/sound/soc/codecs/wm8741.h +++ b/sound/soc/codecs/wm8741.h | |||
@@ -194,6 +194,12 @@ | |||
194 | #define WM8741_DITHER_SHIFT 0 /* DITHER - [1:0] */ | 194 | #define WM8741_DITHER_SHIFT 0 /* DITHER - [1:0] */ |
195 | #define WM8741_DITHER_WIDTH 2 /* DITHER - [1:0] */ | 195 | #define WM8741_DITHER_WIDTH 2 /* DITHER - [1:0] */ |
196 | 196 | ||
197 | /* DIFF field values */ | ||
198 | #define WM8741_DIFF_MODE_STEREO 0 /* stereo normal */ | ||
199 | #define WM8741_DIFF_MODE_STEREO_REVERSED 2 /* stereo reversed */ | ||
200 | #define WM8741_DIFF_MODE_MONO_LEFT 1 /* mono left */ | ||
201 | #define WM8741_DIFF_MODE_MONO_RIGHT 3 /* mono right */ | ||
202 | |||
197 | /* | 203 | /* |
198 | * R32 (0x20) - ADDITONAL_CONTROL_1 | 204 | * R32 (0x20) - ADDITONAL_CONTROL_1 |
199 | */ | 205 | */ |
@@ -208,4 +214,8 @@ | |||
208 | 214 | ||
209 | #define WM8741_SYSCLK 0 | 215 | #define WM8741_SYSCLK 0 |
210 | 216 | ||
217 | struct wm8741_platform_data { | ||
218 | u32 diff_mode; /* Differential Output Mode */ | ||
219 | }; | ||
220 | |||
211 | #endif | 221 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index eb0a1644ba11..56d89b0865fa 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -634,7 +634,7 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, | |||
634 | case SND_SOC_BIAS_PREPARE: | 634 | case SND_SOC_BIAS_PREPARE: |
635 | break; | 635 | break; |
636 | case SND_SOC_BIAS_STANDBY: | 636 | case SND_SOC_BIAS_STANDBY: |
637 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 637 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
638 | snd_soc_cache_sync(codec); | 638 | snd_soc_cache_sync(codec); |
639 | 639 | ||
640 | /* Set VMID to 5k */ | 640 | /* Set VMID to 5k */ |
@@ -651,7 +651,6 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, | |||
651 | snd_soc_write(codec, WM8750_PWR1, 0x0001); | 651 | snd_soc_write(codec, WM8750_PWR1, 0x0001); |
652 | break; | 652 | break; |
653 | } | 653 | } |
654 | codec->dapm.bias_level = level; | ||
655 | return 0; | 654 | return 0; |
656 | } | 655 | } |
657 | 656 | ||
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index c50a5959345f..feb2997a377a 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -1352,7 +1352,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1352 | flush_delayed_work(&wm8753->charge_work); | 1352 | flush_delayed_work(&wm8753->charge_work); |
1353 | break; | 1353 | break; |
1354 | case SND_SOC_BIAS_STANDBY: | 1354 | case SND_SOC_BIAS_STANDBY: |
1355 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1355 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1356 | /* set vmid to 5k for quick power up */ | 1356 | /* set vmid to 5k for quick power up */ |
1357 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); | 1357 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); |
1358 | schedule_delayed_work(&wm8753->charge_work, | 1358 | schedule_delayed_work(&wm8753->charge_work, |
@@ -1367,7 +1367,6 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1367 | snd_soc_write(codec, WM8753_PWR1, 0x0001); | 1367 | snd_soc_write(codec, WM8753_PWR1, 0x0001); |
1368 | break; | 1368 | break; |
1369 | } | 1369 | } |
1370 | codec->dapm.bias_level = level; | ||
1371 | return 0; | 1370 | return 0; |
1372 | } | 1371 | } |
1373 | 1372 | ||
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 53e977da2f86..66c1f151071d 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -510,7 +510,7 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec, | |||
510 | case SND_SOC_BIAS_PREPARE: | 510 | case SND_SOC_BIAS_PREPARE: |
511 | break; | 511 | break; |
512 | case SND_SOC_BIAS_STANDBY: | 512 | case SND_SOC_BIAS_STANDBY: |
513 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 513 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
514 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), | 514 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), |
515 | wm8770->supplies); | 515 | wm8770->supplies); |
516 | if (ret) { | 516 | if (ret) { |
@@ -534,7 +534,6 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec, | |||
534 | break; | 534 | break; |
535 | } | 535 | } |
536 | 536 | ||
537 | codec->dapm.bias_level = level; | ||
538 | return 0; | 537 | return 0; |
539 | } | 538 | } |
540 | 539 | ||
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index c13050b77931..ece9b4456767 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -344,7 +344,7 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
344 | case SND_SOC_BIAS_PREPARE: | 344 | case SND_SOC_BIAS_PREPARE: |
345 | break; | 345 | break; |
346 | case SND_SOC_BIAS_STANDBY: | 346 | case SND_SOC_BIAS_STANDBY: |
347 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 347 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
348 | regcache_sync(wm8776->regmap); | 348 | regcache_sync(wm8776->regmap); |
349 | 349 | ||
350 | /* Disable the global powerdown; DAPM does the rest */ | 350 | /* Disable the global powerdown; DAPM does the rest */ |
@@ -357,7 +357,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
357 | break; | 357 | break; |
358 | } | 358 | } |
359 | 359 | ||
360 | codec->dapm.bias_level = level; | ||
361 | return 0; | 360 | return 0; |
362 | } | 361 | } |
363 | 362 | ||
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 1e403f67cf16..c195c2e8af07 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -162,7 +162,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol, | |||
162 | struct snd_ctl_elem_value *ucontrol) | 162 | struct snd_ctl_elem_value *ucontrol) |
163 | { | 163 | { |
164 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 164 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
165 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 165 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
166 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 166 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
167 | unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l; | 167 | unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l; |
168 | unsigned int mask = 1 << e->shift_l; | 168 | unsigned int mask = 1 << e->shift_l; |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 2eb986c19b88..f3759ec5a863 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -998,8 +998,8 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
998 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | 998 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) |
999 | 999 | ||
1000 | #define WM8900_PCM_FORMATS \ | 1000 | #define WM8900_PCM_FORMATS \ |
1001 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ | 1001 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1002 | SNDRV_PCM_FORMAT_S24_LE) | 1002 | SNDRV_PCM_FMTBIT_S24_LE) |
1003 | 1003 | ||
1004 | static const struct snd_soc_dai_ops wm8900_dai_ops = { | 1004 | static const struct snd_soc_dai_ops wm8900_dai_ops = { |
1005 | .hw_params = wm8900_hw_params, | 1005 | .hw_params = wm8900_hw_params, |
@@ -1049,7 +1049,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1049 | 1049 | ||
1050 | case SND_SOC_BIAS_STANDBY: | 1050 | case SND_SOC_BIAS_STANDBY: |
1051 | /* Charge capacitors if initial power up */ | 1051 | /* Charge capacitors if initial power up */ |
1052 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1052 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1053 | /* STARTUP_BIAS_ENA on */ | 1053 | /* STARTUP_BIAS_ENA on */ |
1054 | snd_soc_write(codec, WM8900_REG_POWER1, | 1054 | snd_soc_write(codec, WM8900_REG_POWER1, |
1055 | WM8900_REG_POWER1_STARTUP_BIAS_ENA); | 1055 | WM8900_REG_POWER1_STARTUP_BIAS_ENA); |
@@ -1117,7 +1117,6 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1117 | WM8900_REG_POWER2_SYSCLK_ENA); | 1117 | WM8900_REG_POWER2_SYSCLK_ENA); |
1118 | break; | 1118 | break; |
1119 | } | 1119 | } |
1120 | codec->dapm.bias_level = level; | ||
1121 | return 0; | 1120 | return 0; |
1122 | } | 1121 | } |
1123 | 1122 | ||
@@ -1138,7 +1137,7 @@ static int wm8900_suspend(struct snd_soc_codec *codec) | |||
1138 | wm8900->fll_out = fll_out; | 1137 | wm8900->fll_out = fll_out; |
1139 | wm8900->fll_in = fll_in; | 1138 | wm8900->fll_in = fll_in; |
1140 | 1139 | ||
1141 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1140 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
1142 | 1141 | ||
1143 | return 0; | 1142 | return 0; |
1144 | } | 1143 | } |
@@ -1156,7 +1155,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
1156 | return ret; | 1155 | return ret; |
1157 | } | 1156 | } |
1158 | 1157 | ||
1159 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1158 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1160 | 1159 | ||
1161 | /* Restart the FLL? */ | 1160 | /* Restart the FLL? */ |
1162 | if (wm8900->fll_out) { | 1161 | if (wm8900->fll_out) { |
@@ -1189,7 +1188,7 @@ static int wm8900_probe(struct snd_soc_codec *codec) | |||
1189 | wm8900_reset(codec); | 1188 | wm8900_reset(codec); |
1190 | 1189 | ||
1191 | /* Turn the chip on */ | 1190 | /* Turn the chip on */ |
1192 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1191 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1193 | 1192 | ||
1194 | /* Latch the volume update bits */ | 1193 | /* Latch the volume update bits */ |
1195 | snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100); | 1194 | snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100); |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 04b04f8e147c..b5322c1544fb 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -1105,7 +1105,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1105 | break; | 1105 | break; |
1106 | 1106 | ||
1107 | case SND_SOC_BIAS_STANDBY: | 1107 | case SND_SOC_BIAS_STANDBY: |
1108 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1108 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1109 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, | 1109 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, |
1110 | WM8903_POBCTRL | WM8903_ISEL_MASK | | 1110 | WM8903_POBCTRL | WM8903_ISEL_MASK | |
1111 | WM8903_STARTUP_BIAS_ENA | | 1111 | WM8903_STARTUP_BIAS_ENA | |
@@ -1200,8 +1200,6 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1200 | break; | 1200 | break; |
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | codec->dapm.bias_level = level; | ||
1204 | |||
1205 | return 0; | 1203 | return 0; |
1206 | } | 1204 | } |
1207 | 1205 | ||
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index db949311c0f2..0bb4a647755d 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h | |||
@@ -172,7 +172,7 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec, | |||
172 | #define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ | 172 | #define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ |
173 | 173 | ||
174 | #define WM8903_VMID_RES_50K 2 | 174 | #define WM8903_VMID_RES_50K 2 |
175 | #define WM8903_VMID_RES_250K 3 | 175 | #define WM8903_VMID_RES_250K 4 |
176 | #define WM8903_VMID_RES_5K 6 | 176 | #define WM8903_VMID_RES_5K 6 |
177 | 177 | ||
178 | /* | 178 | /* |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 215e93c1ddf0..265a4a58a2d1 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1168,7 +1168,7 @@ static const struct snd_soc_dapm_route wm8912_intercon[] = { | |||
1168 | static int wm8904_add_widgets(struct snd_soc_codec *codec) | 1168 | static int wm8904_add_widgets(struct snd_soc_codec *codec) |
1169 | { | 1169 | { |
1170 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 1170 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
1171 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1171 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1172 | 1172 | ||
1173 | snd_soc_dapm_new_controls(dapm, wm8904_core_dapm_widgets, | 1173 | snd_soc_dapm_new_controls(dapm, wm8904_core_dapm_widgets, |
1174 | ARRAY_SIZE(wm8904_core_dapm_widgets)); | 1174 | ARRAY_SIZE(wm8904_core_dapm_widgets)); |
@@ -1852,7 +1852,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1852 | break; | 1852 | break; |
1853 | 1853 | ||
1854 | case SND_SOC_BIAS_STANDBY: | 1854 | case SND_SOC_BIAS_STANDBY: |
1855 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1855 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1856 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | 1856 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), |
1857 | wm8904->supplies); | 1857 | wm8904->supplies); |
1858 | if (ret != 0) { | 1858 | if (ret != 0) { |
@@ -1907,7 +1907,6 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1907 | clk_disable_unprepare(wm8904->mclk); | 1907 | clk_disable_unprepare(wm8904->mclk); |
1908 | break; | 1908 | break; |
1909 | } | 1909 | } |
1910 | codec->dapm.bias_level = level; | ||
1911 | return 0; | 1910 | return 0; |
1912 | } | 1911 | } |
1913 | 1912 | ||
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index e4142b4309eb..98ef0ba5c2a4 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -492,7 +492,7 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, | |||
492 | ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); | 492 | ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); |
493 | break; | 493 | break; |
494 | case SND_SOC_BIAS_STANDBY: | 494 | case SND_SOC_BIAS_STANDBY: |
495 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 495 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
496 | ret = regcache_sync(wm8940->regmap); | 496 | ret = regcache_sync(wm8940->regmap); |
497 | if (ret < 0) { | 497 | if (ret < 0) { |
498 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 498 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
@@ -510,8 +510,6 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, | |||
510 | break; | 510 | break; |
511 | } | 511 | } |
512 | 512 | ||
513 | codec->dapm.bias_level = level; | ||
514 | |||
515 | return ret; | 513 | return ret; |
516 | } | 514 | } |
517 | 515 | ||
@@ -707,7 +705,7 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
707 | return ret; | 705 | return ret; |
708 | } | 706 | } |
709 | 707 | ||
710 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 708 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
711 | 709 | ||
712 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); | 710 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); |
713 | if (ret < 0) | 711 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 00bec915d652..2d591c24704b 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -298,7 +298,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec) | |||
298 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, | 298 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, |
299 | WM8955_K_17_9_MASK, | 299 | WM8955_K_17_9_MASK, |
300 | (pll.k >> 9) & WM8955_K_17_9_MASK); | 300 | (pll.k >> 9) & WM8955_K_17_9_MASK); |
301 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, | 301 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_3, |
302 | WM8955_K_8_0_MASK, | 302 | WM8955_K_8_0_MASK, |
303 | pll.k & WM8955_K_8_0_MASK); | 303 | pll.k & WM8955_K_8_0_MASK); |
304 | if (pll.k) | 304 | if (pll.k) |
@@ -785,7 +785,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, | |||
785 | break; | 785 | break; |
786 | 786 | ||
787 | case SND_SOC_BIAS_STANDBY: | 787 | case SND_SOC_BIAS_STANDBY: |
788 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 788 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
789 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), | 789 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), |
790 | wm8955->supplies); | 790 | wm8955->supplies); |
791 | if (ret != 0) { | 791 | if (ret != 0) { |
@@ -838,7 +838,6 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, | |||
838 | wm8955->supplies); | 838 | wm8955->supplies); |
839 | break; | 839 | break; |
840 | } | 840 | } |
841 | codec->dapm.bias_level = level; | ||
842 | return 0; | 841 | return 0; |
843 | } | 842 | } |
844 | 843 | ||
@@ -929,7 +928,7 @@ static int wm8955_probe(struct snd_soc_codec *codec) | |||
929 | WM8955_DMEN, WM8955_DMEN); | 928 | WM8955_DMEN, WM8955_DMEN); |
930 | } | 929 | } |
931 | 930 | ||
932 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 931 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
933 | 932 | ||
934 | /* Bias level configuration will have done an extra enable */ | 933 | /* Bias level configuration will have done an extra enable */ |
935 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 934 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3035d9856415..94c5c4681ce5 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -127,6 +127,8 @@ struct wm8960_priv { | |||
127 | struct snd_soc_dapm_widget *out3; | 127 | struct snd_soc_dapm_widget *out3; |
128 | bool deemph; | 128 | bool deemph; |
129 | int playback_fs; | 129 | int playback_fs; |
130 | int bclk; | ||
131 | int sysclk; | ||
130 | struct wm8960_data pdata; | 132 | struct wm8960_data pdata; |
131 | }; | 133 | }; |
132 | 134 | ||
@@ -245,7 +247,7 @@ SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), | |||
245 | SOC_ENUM("ADC Polarity", wm8960_enum[0]), | 247 | SOC_ENUM("ADC Polarity", wm8960_enum[0]), |
246 | SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), | 248 | SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), |
247 | 249 | ||
248 | SOC_ENUM("DAC Polarity", wm8960_enum[2]), | 250 | SOC_ENUM("DAC Polarity", wm8960_enum[1]), |
249 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, | 251 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, |
250 | wm8960_get_deemph, wm8960_put_deemph), | 252 | wm8960_get_deemph, wm8960_put_deemph), |
251 | 253 | ||
@@ -395,7 +397,7 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
395 | { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, | 397 | { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, |
396 | { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ | 398 | { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ |
397 | { "Right Input Mixer", NULL, "RINPUT2" }, | 399 | { "Right Input Mixer", NULL, "RINPUT2" }, |
398 | { "Right Input Mixer", NULL, "LINPUT3" }, | 400 | { "Right Input Mixer", NULL, "RINPUT3" }, |
399 | 401 | ||
400 | { "Left ADC", NULL, "Left Input Mixer" }, | 402 | { "Left ADC", NULL, "Left Input Mixer" }, |
401 | { "Right ADC", NULL, "Right Input Mixer" }, | 403 | { "Right ADC", NULL, "Right Input Mixer" }, |
@@ -445,7 +447,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec) | |||
445 | { | 447 | { |
446 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 448 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
447 | struct wm8960_data *pdata = &wm8960->pdata; | 449 | struct wm8960_data *pdata = &wm8960->pdata; |
448 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 450 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
449 | struct snd_soc_dapm_widget *w; | 451 | struct snd_soc_dapm_widget *w; |
450 | 452 | ||
451 | snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets, | 453 | snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets, |
@@ -476,7 +478,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec) | |||
476 | * and save the result. | 478 | * and save the result. |
477 | */ | 479 | */ |
478 | list_for_each_entry(w, &codec->component.card->widgets, list) { | 480 | list_for_each_entry(w, &codec->component.card->widgets, list) { |
479 | if (w->dapm != &codec->dapm) | 481 | if (w->dapm != dapm) |
480 | continue; | 482 | continue; |
481 | if (strcmp(w->name, "LOUT1 PGA") == 0) | 483 | if (strcmp(w->name, "LOUT1 PGA") == 0) |
482 | wm8960->lout1 = w; | 484 | wm8960->lout1 = w; |
@@ -563,6 +565,72 @@ static struct { | |||
563 | { 8000, 5 }, | 565 | { 8000, 5 }, |
564 | }; | 566 | }; |
565 | 567 | ||
568 | /* Multiply 256 for internal 256 div */ | ||
569 | static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; | ||
570 | |||
571 | /* Multiply 10 to eliminate decimials */ | ||
572 | static const int bclk_divs[] = { | ||
573 | 10, 15, 20, 30, 40, 55, 60, 80, 110, | ||
574 | 120, 160, 220, 240, 320, 320, 320 | ||
575 | }; | ||
576 | |||
577 | static void wm8960_configure_clocking(struct snd_soc_codec *codec, | ||
578 | bool tx, int lrclk) | ||
579 | { | ||
580 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
581 | u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); | ||
582 | u16 iface2 = snd_soc_read(codec, WM8960_IFACE2); | ||
583 | u32 sysclk; | ||
584 | int i, j; | ||
585 | |||
586 | if (!(iface1 & (1<<6))) { | ||
587 | dev_dbg(codec->dev, | ||
588 | "Codec is slave mode, no need to configure clock\n"); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | if (!wm8960->sysclk) { | ||
593 | dev_dbg(codec->dev, "No SYSCLK configured\n"); | ||
594 | return; | ||
595 | } | ||
596 | |||
597 | if (!wm8960->bclk || !lrclk) { | ||
598 | dev_dbg(codec->dev, "No audio clocks configured\n"); | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) { | ||
603 | if (wm8960->sysclk == lrclk * dac_divs[i]) { | ||
604 | for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) { | ||
605 | sysclk = wm8960->bclk * bclk_divs[j] / 10; | ||
606 | if (wm8960->sysclk == sysclk) | ||
607 | break; | ||
608 | } | ||
609 | if(j != ARRAY_SIZE(bclk_divs)) | ||
610 | break; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | if (i == ARRAY_SIZE(dac_divs)) { | ||
615 | dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk); | ||
616 | return; | ||
617 | } | ||
618 | |||
619 | /* | ||
620 | * configure frame clock. If ADCLRC configure as GPIO pin, DACLRC | ||
621 | * pin is used as a frame clock for ADCs and DACs. | ||
622 | */ | ||
623 | if (iface2 & (1<<6)) | ||
624 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | ||
625 | else if (tx) | ||
626 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | ||
627 | else if (!tx) | ||
628 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6); | ||
629 | |||
630 | /* configure bit clock */ | ||
631 | snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j); | ||
632 | } | ||
633 | |||
566 | static int wm8960_hw_params(struct snd_pcm_substream *substream, | 634 | static int wm8960_hw_params(struct snd_pcm_substream *substream, |
567 | struct snd_pcm_hw_params *params, | 635 | struct snd_pcm_hw_params *params, |
568 | struct snd_soc_dai *dai) | 636 | struct snd_soc_dai *dai) |
@@ -570,8 +638,13 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
570 | struct snd_soc_codec *codec = dai->codec; | 638 | struct snd_soc_codec *codec = dai->codec; |
571 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 639 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
572 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 640 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
641 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
573 | int i; | 642 | int i; |
574 | 643 | ||
644 | wm8960->bclk = snd_soc_params_to_bclk(params); | ||
645 | if (params_channels(params) == 1) | ||
646 | wm8960->bclk *= 2; | ||
647 | |||
575 | /* bit size */ | 648 | /* bit size */ |
576 | switch (params_width(params)) { | 649 | switch (params_width(params)) { |
577 | case 16: | 650 | case 16: |
@@ -582,6 +655,12 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
582 | case 24: | 655 | case 24: |
583 | iface |= 0x0008; | 656 | iface |= 0x0008; |
584 | break; | 657 | break; |
658 | case 32: | ||
659 | /* right justify mode does not support 32 word length */ | ||
660 | if ((iface & 0x3) != 0) { | ||
661 | iface |= 0x000c; | ||
662 | break; | ||
663 | } | ||
585 | default: | 664 | default: |
586 | dev_err(codec->dev, "unsupported width %d\n", | 665 | dev_err(codec->dev, "unsupported width %d\n", |
587 | params_width(params)); | 666 | params_width(params)); |
@@ -602,6 +681,9 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
602 | 681 | ||
603 | /* set iface */ | 682 | /* set iface */ |
604 | snd_soc_write(codec, WM8960_IFACE1, iface); | 683 | snd_soc_write(codec, WM8960_IFACE1, iface); |
684 | |||
685 | wm8960_configure_clocking(codec, tx, params_rate(params)); | ||
686 | |||
605 | return 0; | 687 | return 0; |
606 | } | 688 | } |
607 | 689 | ||
@@ -627,7 +709,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
627 | break; | 709 | break; |
628 | 710 | ||
629 | case SND_SOC_BIAS_PREPARE: | 711 | case SND_SOC_BIAS_PREPARE: |
630 | switch (codec->dapm.bias_level) { | 712 | switch (snd_soc_codec_get_bias_level(codec)) { |
631 | case SND_SOC_BIAS_STANDBY: | 713 | case SND_SOC_BIAS_STANDBY: |
632 | if (!IS_ERR(wm8960->mclk)) { | 714 | if (!IS_ERR(wm8960->mclk)) { |
633 | ret = clk_prepare_enable(wm8960->mclk); | 715 | ret = clk_prepare_enable(wm8960->mclk); |
@@ -655,7 +737,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
655 | break; | 737 | break; |
656 | 738 | ||
657 | case SND_SOC_BIAS_STANDBY: | 739 | case SND_SOC_BIAS_STANDBY: |
658 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 740 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
659 | regcache_sync(wm8960->regmap); | 741 | regcache_sync(wm8960->regmap); |
660 | 742 | ||
661 | /* Enable anti-pop features */ | 743 | /* Enable anti-pop features */ |
@@ -691,8 +773,6 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
691 | break; | 773 | break; |
692 | } | 774 | } |
693 | 775 | ||
694 | codec->dapm.bias_level = level; | ||
695 | |||
696 | return 0; | 776 | return 0; |
697 | } | 777 | } |
698 | 778 | ||
@@ -707,7 +787,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
707 | break; | 787 | break; |
708 | 788 | ||
709 | case SND_SOC_BIAS_PREPARE: | 789 | case SND_SOC_BIAS_PREPARE: |
710 | switch (codec->dapm.bias_level) { | 790 | switch (snd_soc_codec_get_bias_level(codec)) { |
711 | case SND_SOC_BIAS_STANDBY: | 791 | case SND_SOC_BIAS_STANDBY: |
712 | /* Enable anti pop mode */ | 792 | /* Enable anti pop mode */ |
713 | snd_soc_update_bits(codec, WM8960_APOP1, | 793 | snd_soc_update_bits(codec, WM8960_APOP1, |
@@ -778,7 +858,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
778 | break; | 858 | break; |
779 | 859 | ||
780 | case SND_SOC_BIAS_STANDBY: | 860 | case SND_SOC_BIAS_STANDBY: |
781 | switch (codec->dapm.bias_level) { | 861 | switch (snd_soc_codec_get_bias_level(codec)) { |
782 | case SND_SOC_BIAS_PREPARE: | 862 | case SND_SOC_BIAS_PREPARE: |
783 | /* Disable HP discharge */ | 863 | /* Disable HP discharge */ |
784 | snd_soc_update_bits(codec, WM8960_APOP2, | 864 | snd_soc_update_bits(codec, WM8960_APOP2, |
@@ -802,8 +882,6 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
802 | break; | 882 | break; |
803 | } | 883 | } |
804 | 884 | ||
805 | codec->dapm.bias_level = level; | ||
806 | |||
807 | return 0; | 885 | return 0; |
808 | } | 886 | } |
809 | 887 | ||
@@ -950,11 +1028,35 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
950 | return wm8960->set_bias_level(codec, level); | 1028 | return wm8960->set_bias_level(codec, level); |
951 | } | 1029 | } |
952 | 1030 | ||
1031 | static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
1032 | unsigned int freq, int dir) | ||
1033 | { | ||
1034 | struct snd_soc_codec *codec = dai->codec; | ||
1035 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
1036 | |||
1037 | switch (clk_id) { | ||
1038 | case WM8960_SYSCLK_MCLK: | ||
1039 | snd_soc_update_bits(codec, WM8960_CLOCK1, | ||
1040 | 0x1, WM8960_SYSCLK_MCLK); | ||
1041 | break; | ||
1042 | case WM8960_SYSCLK_PLL: | ||
1043 | snd_soc_update_bits(codec, WM8960_CLOCK1, | ||
1044 | 0x1, WM8960_SYSCLK_PLL); | ||
1045 | break; | ||
1046 | default: | ||
1047 | return -EINVAL; | ||
1048 | } | ||
1049 | |||
1050 | wm8960->sysclk = freq; | ||
1051 | |||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
953 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 | 1055 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 |
954 | 1056 | ||
955 | #define WM8960_FORMATS \ | 1057 | #define WM8960_FORMATS \ |
956 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1058 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
957 | SNDRV_PCM_FMTBIT_S24_LE) | 1059 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
958 | 1060 | ||
959 | static const struct snd_soc_dai_ops wm8960_dai_ops = { | 1061 | static const struct snd_soc_dai_ops wm8960_dai_ops = { |
960 | .hw_params = wm8960_hw_params, | 1062 | .hw_params = wm8960_hw_params, |
@@ -962,6 +1064,7 @@ static const struct snd_soc_dai_ops wm8960_dai_ops = { | |||
962 | .set_fmt = wm8960_set_dai_fmt, | 1064 | .set_fmt = wm8960_set_dai_fmt, |
963 | .set_clkdiv = wm8960_set_dai_clkdiv, | 1065 | .set_clkdiv = wm8960_set_dai_clkdiv, |
964 | .set_pll = wm8960_set_dai_pll, | 1066 | .set_pll = wm8960_set_dai_pll, |
1067 | .set_sysclk = wm8960_set_dai_sysclk, | ||
965 | }; | 1068 | }; |
966 | 1069 | ||
967 | static struct snd_soc_dai_driver wm8960_dai = { | 1070 | static struct snd_soc_dai_driver wm8960_dai = { |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 95e2c1bfc809..a057662632ff 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -758,7 +758,7 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec, | |||
758 | break; | 758 | break; |
759 | 759 | ||
760 | case SND_SOC_BIAS_PREPARE: | 760 | case SND_SOC_BIAS_PREPARE: |
761 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 761 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { |
762 | /* Enable bias generation */ | 762 | /* Enable bias generation */ |
763 | reg = snd_soc_read(codec, WM8961_ANTI_POP); | 763 | reg = snd_soc_read(codec, WM8961_ANTI_POP); |
764 | reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; | 764 | reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; |
@@ -773,7 +773,7 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec, | |||
773 | break; | 773 | break; |
774 | 774 | ||
775 | case SND_SOC_BIAS_STANDBY: | 775 | case SND_SOC_BIAS_STANDBY: |
776 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | 776 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { |
777 | /* VREF off */ | 777 | /* VREF off */ |
778 | reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); | 778 | reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); |
779 | reg &= ~WM8961_VREF; | 779 | reg &= ~WM8961_VREF; |
@@ -795,8 +795,6 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec, | |||
795 | break; | 795 | break; |
796 | } | 796 | } |
797 | 797 | ||
798 | codec->dapm.bias_level = level; | ||
799 | |||
800 | return 0; | 798 | return 0; |
801 | } | 799 | } |
802 | 800 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 118b0034ba23..c5748fd4f296 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -2361,7 +2361,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
2361 | { | 2361 | { |
2362 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 2362 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2363 | struct wm8962_pdata *pdata = &wm8962->pdata; | 2363 | struct wm8962_pdata *pdata = &wm8962->pdata; |
2364 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2364 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2365 | 2365 | ||
2366 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, | 2366 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, |
2367 | ARRAY_SIZE(wm8962_snd_controls)); | 2367 | ARRAY_SIZE(wm8962_snd_controls)); |
@@ -2446,13 +2446,13 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec) | |||
2446 | * So we here provisionally enable it and then disable it afterward | 2446 | * So we here provisionally enable it and then disable it afterward |
2447 | * if current bias_level hasn't reached SND_SOC_BIAS_ON. | 2447 | * if current bias_level hasn't reached SND_SOC_BIAS_ON. |
2448 | */ | 2448 | */ |
2449 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | 2449 | if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_ON) |
2450 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | 2450 | snd_soc_update_bits(codec, WM8962_CLOCKING2, |
2451 | WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); | 2451 | WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); |
2452 | 2452 | ||
2453 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); | 2453 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); |
2454 | 2454 | ||
2455 | if (codec->dapm.bias_level != SND_SOC_BIAS_ON) | 2455 | if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_ON) |
2456 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | 2456 | snd_soc_update_bits(codec, WM8962_CLOCKING2, |
2457 | WM8962_SYSCLK_ENA_MASK, 0); | 2457 | WM8962_SYSCLK_ENA_MASK, 0); |
2458 | 2458 | ||
@@ -2510,9 +2510,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec) | |||
2510 | static int wm8962_set_bias_level(struct snd_soc_codec *codec, | 2510 | static int wm8962_set_bias_level(struct snd_soc_codec *codec, |
2511 | enum snd_soc_bias_level level) | 2511 | enum snd_soc_bias_level level) |
2512 | { | 2512 | { |
2513 | if (level == codec->dapm.bias_level) | ||
2514 | return 0; | ||
2515 | |||
2516 | switch (level) { | 2513 | switch (level) { |
2517 | case SND_SOC_BIAS_ON: | 2514 | case SND_SOC_BIAS_ON: |
2518 | break; | 2515 | break; |
@@ -2530,7 +2527,7 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2530 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, | 2527 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, |
2531 | WM8962_VMID_SEL_MASK, 0x100); | 2528 | WM8962_VMID_SEL_MASK, 0x100); |
2532 | 2529 | ||
2533 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 2530 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) |
2534 | msleep(100); | 2531 | msleep(100); |
2535 | break; | 2532 | break; |
2536 | 2533 | ||
@@ -2538,7 +2535,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2538 | break; | 2535 | break; |
2539 | } | 2536 | } |
2540 | 2537 | ||
2541 | codec->dapm.bias_level = level; | ||
2542 | return 0; | 2538 | return 0; |
2543 | } | 2539 | } |
2544 | 2540 | ||
@@ -2614,7 +2610,7 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2614 | dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n", | 2610 | dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n", |
2615 | wm8962->bclk, wm8962->lrclk); | 2611 | wm8962->bclk, wm8962->lrclk); |
2616 | 2612 | ||
2617 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 2613 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) |
2618 | wm8962_configure_bclk(codec); | 2614 | wm8962_configure_bclk(codec); |
2619 | 2615 | ||
2620 | return 0; | 2616 | return 0; |
@@ -3118,7 +3114,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3118 | int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | 3114 | int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) |
3119 | { | 3115 | { |
3120 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3116 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3121 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 3117 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
3122 | int irq_mask, enable; | 3118 | int irq_mask, enable; |
3123 | 3119 | ||
3124 | wm8962->jack = jack; | 3120 | wm8962->jack = jack; |
@@ -3164,7 +3160,7 @@ static void wm8962_beep_work(struct work_struct *work) | |||
3164 | struct wm8962_priv *wm8962 = | 3160 | struct wm8962_priv *wm8962 = |
3165 | container_of(work, struct wm8962_priv, beep_work); | 3161 | container_of(work, struct wm8962_priv, beep_work); |
3166 | struct snd_soc_codec *codec = wm8962->codec; | 3162 | struct snd_soc_codec *codec = wm8962->codec; |
3167 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 3163 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
3168 | int i; | 3164 | int i; |
3169 | int reg = 0; | 3165 | int reg = 0; |
3170 | int best = 0; | 3166 | int best = 0; |
@@ -3415,6 +3411,7 @@ static void wm8962_free_gpio(struct snd_soc_codec *codec) | |||
3415 | 3411 | ||
3416 | static int wm8962_probe(struct snd_soc_codec *codec) | 3412 | static int wm8962_probe(struct snd_soc_codec *codec) |
3417 | { | 3413 | { |
3414 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3418 | int ret; | 3415 | int ret; |
3419 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3416 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3420 | int i; | 3417 | int i; |
@@ -3462,7 +3459,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3462 | } | 3459 | } |
3463 | if (!dmicclk || !dmicdat) { | 3460 | if (!dmicclk || !dmicdat) { |
3464 | dev_dbg(codec->dev, "DMIC not in use, disabling\n"); | 3461 | dev_dbg(codec->dev, "DMIC not in use, disabling\n"); |
3465 | snd_soc_dapm_nc_pin(&codec->dapm, "DMICDAT"); | 3462 | snd_soc_dapm_nc_pin(dapm, "DMICDAT"); |
3466 | } | 3463 | } |
3467 | if (dmicclk != dmicdat) | 3464 | if (dmicclk != dmicdat) |
3468 | dev_warn(codec->dev, "DMIC GPIOs partially configured\n"); | 3465 | dev_warn(codec->dev, "DMIC GPIOs partially configured\n"); |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index f9cbabdc6238..b51184c4e816 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -577,7 +577,7 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, | |||
577 | flush_delayed_work(&wm8971->charge_work); | 577 | flush_delayed_work(&wm8971->charge_work); |
578 | break; | 578 | break; |
579 | case SND_SOC_BIAS_STANDBY: | 579 | case SND_SOC_BIAS_STANDBY: |
580 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 580 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
581 | snd_soc_cache_sync(codec); | 581 | snd_soc_cache_sync(codec); |
582 | /* charge output caps - set vmid to 5k for quick power up */ | 582 | /* charge output caps - set vmid to 5k for quick power up */ |
583 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x01c0); | 583 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x01c0); |
@@ -594,7 +594,6 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, | |||
594 | snd_soc_write(codec, WM8971_PWR1, 0x0001); | 594 | snd_soc_write(codec, WM8971_PWR1, 0x0001); |
595 | break; | 595 | break; |
596 | } | 596 | } |
597 | codec->dapm.bias_level = level; | ||
598 | return 0; | 597 | return 0; |
599 | } | 598 | } |
600 | 599 | ||
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index ff0e4646b934..33b16a7ba82e 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -514,7 +514,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, | |||
514 | case SND_SOC_BIAS_STANDBY: | 514 | case SND_SOC_BIAS_STANDBY: |
515 | power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; | 515 | power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; |
516 | 516 | ||
517 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 517 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
518 | regcache_sync(dev_get_regmap(codec->dev, NULL)); | 518 | regcache_sync(dev_get_regmap(codec->dev, NULL)); |
519 | 519 | ||
520 | /* Initial cap charge at VMID 5k */ | 520 | /* Initial cap charge at VMID 5k */ |
@@ -533,7 +533,6 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, | |||
533 | break; | 533 | break; |
534 | } | 534 | } |
535 | 535 | ||
536 | codec->dapm.bias_level = level; | ||
537 | return 0; | 536 | return 0; |
538 | } | 537 | } |
539 | 538 | ||
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index cf7032911721..cfc8cdf49970 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -868,7 +868,7 @@ static int wm8978_set_bias_level(struct snd_soc_codec *codec, | |||
868 | /* bit 3: enable bias, bit 2: enable I/O tie off buffer */ | 868 | /* bit 3: enable bias, bit 2: enable I/O tie off buffer */ |
869 | power1 |= 0xc; | 869 | power1 |= 0xc; |
870 | 870 | ||
871 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 871 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
872 | /* Initial cap charge at VMID 5k */ | 872 | /* Initial cap charge at VMID 5k */ |
873 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, | 873 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, |
874 | power1 | 0x3); | 874 | power1 | 0x3); |
@@ -888,7 +888,6 @@ static int wm8978_set_bias_level(struct snd_soc_codec *codec, | |||
888 | 888 | ||
889 | dev_dbg(codec->dev, "%s: %d, %x\n", __func__, level, power1); | 889 | dev_dbg(codec->dev, "%s: %d, %x\n", __func__, level, power1); |
890 | 890 | ||
891 | codec->dapm.bias_level = level; | ||
892 | return 0; | 891 | return 0; |
893 | } | 892 | } |
894 | 893 | ||
@@ -928,7 +927,7 @@ static int wm8978_suspend(struct snd_soc_codec *codec) | |||
928 | { | 927 | { |
929 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 928 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
930 | 929 | ||
931 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); | 930 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
932 | /* Also switch PLL off */ | 931 | /* Also switch PLL off */ |
933 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); | 932 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); |
934 | 933 | ||
@@ -944,7 +943,7 @@ static int wm8978_resume(struct snd_soc_codec *codec) | |||
944 | /* Sync reg_cache with the hardware */ | 943 | /* Sync reg_cache with the hardware */ |
945 | regcache_sync(wm8978->regmap); | 944 | regcache_sync(wm8978->regmap); |
946 | 945 | ||
947 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 946 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
948 | 947 | ||
949 | if (wm8978->f_pllout) | 948 | if (wm8978->f_pllout) |
950 | /* Switch PLL on */ | 949 | /* Switch PLL on */ |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 5d1cf08a72b8..2fdd2c6cc09d 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -915,7 +915,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
915 | 1 << WM8983_VMIDSEL_SHIFT); | 915 | 1 << WM8983_VMIDSEL_SHIFT); |
916 | break; | 916 | break; |
917 | case SND_SOC_BIAS_STANDBY: | 917 | case SND_SOC_BIAS_STANDBY: |
918 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 918 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
919 | ret = regcache_sync(wm8983->regmap); | 919 | ret = regcache_sync(wm8983->regmap); |
920 | if (ret < 0) { | 920 | if (ret < 0) { |
921 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 921 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
@@ -963,7 +963,6 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
963 | break; | 963 | break; |
964 | } | 964 | } |
965 | 965 | ||
966 | codec->dapm.bias_level = level; | ||
967 | return 0; | 966 | return 0; |
968 | } | 967 | } |
969 | 968 | ||
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 0b3b54c9971d..8a85f5004d41 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -897,7 +897,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec, | |||
897 | 1 << WM8985_VMIDSEL_SHIFT); | 897 | 1 << WM8985_VMIDSEL_SHIFT); |
898 | break; | 898 | break; |
899 | case SND_SOC_BIAS_STANDBY: | 899 | case SND_SOC_BIAS_STANDBY: |
900 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 900 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
901 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies), | 901 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies), |
902 | wm8985->supplies); | 902 | wm8985->supplies); |
903 | if (ret) { | 903 | if (ret) { |
@@ -957,7 +957,6 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec, | |||
957 | break; | 957 | break; |
958 | } | 958 | } |
959 | 959 | ||
960 | codec->dapm.bias_level = level; | ||
961 | return 0; | 960 | return 0; |
962 | } | 961 | } |
963 | 962 | ||
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 24968aa8618a..f13a995af277 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -738,7 +738,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, | |||
738 | break; | 738 | break; |
739 | 739 | ||
740 | case SND_SOC_BIAS_STANDBY: | 740 | case SND_SOC_BIAS_STANDBY: |
741 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 741 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
742 | regcache_sync(wm8988->regmap); | 742 | regcache_sync(wm8988->regmap); |
743 | 743 | ||
744 | /* VREF, VMID=2x5k */ | 744 | /* VREF, VMID=2x5k */ |
@@ -756,7 +756,6 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, | |||
756 | snd_soc_write(codec, WM8988_PWR1, 0x0000); | 756 | snd_soc_write(codec, WM8988_PWR1, 0x0000); |
757 | break; | 757 | break; |
758 | } | 758 | } |
759 | codec->dapm.bias_level = level; | ||
760 | return 0; | 759 | return 0; |
761 | } | 760 | } |
762 | 761 | ||
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index c93bffcb3cfb..1993fd2a6f15 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -1124,7 +1124,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1124 | break; | 1124 | break; |
1125 | 1125 | ||
1126 | case SND_SOC_BIAS_STANDBY: | 1126 | case SND_SOC_BIAS_STANDBY: |
1127 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1127 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1128 | ret = regcache_sync(wm8990->regmap); | 1128 | ret = regcache_sync(wm8990->regmap); |
1129 | if (ret < 0) { | 1129 | if (ret < 0) { |
1130 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 1130 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
@@ -1227,7 +1227,6 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1227 | break; | 1227 | break; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | codec->dapm.bias_level = level; | ||
1231 | return 0; | 1230 | return 0; |
1232 | } | 1231 | } |
1233 | 1232 | ||
@@ -1281,7 +1280,7 @@ static int wm8990_probe(struct snd_soc_codec *codec) | |||
1281 | wm8990_reset(codec); | 1280 | wm8990_reset(codec); |
1282 | 1281 | ||
1283 | /* charge output caps */ | 1282 | /* charge output caps */ |
1284 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1283 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1285 | 1284 | ||
1286 | snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4, | 1285 | snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4, |
1287 | WM8990_ALRCGPIO1, WM8990_ALRCGPIO1); | 1286 | WM8990_ALRCGPIO1, WM8990_ALRCGPIO1); |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 49df0dc607e6..44a677720828 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -1131,7 +1131,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1131 | break; | 1131 | break; |
1132 | 1132 | ||
1133 | case SND_SOC_BIAS_STANDBY: | 1133 | case SND_SOC_BIAS_STANDBY: |
1134 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1134 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1135 | regcache_sync(wm8991->regmap); | 1135 | regcache_sync(wm8991->regmap); |
1136 | /* Enable all output discharge bits */ | 1136 | /* Enable all output discharge bits */ |
1137 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | | 1137 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | |
@@ -1224,7 +1224,6 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1224 | break; | 1224 | break; |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | codec->dapm.bias_level = level; | ||
1228 | return 0; | 1227 | return 0; |
1229 | } | 1228 | } |
1230 | 1229 | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 2e70a270eb28..8a8db8605dc2 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -992,7 +992,7 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
992 | break; | 992 | break; |
993 | 993 | ||
994 | case SND_SOC_BIAS_STANDBY: | 994 | case SND_SOC_BIAS_STANDBY: |
995 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 995 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
996 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | 996 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), |
997 | wm8993->supplies); | 997 | wm8993->supplies); |
998 | if (ret != 0) | 998 | if (ret != 0) |
@@ -1065,8 +1065,6 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
1065 | break; | 1065 | break; |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | codec->dapm.bias_level = level; | ||
1069 | |||
1070 | return 0; | 1068 | return 0; |
1071 | } | 1069 | } |
1072 | 1070 | ||
@@ -1485,7 +1483,7 @@ static struct snd_soc_dai_driver wm8993_dai = { | |||
1485 | static int wm8993_probe(struct snd_soc_codec *codec) | 1483 | static int wm8993_probe(struct snd_soc_codec *codec) |
1486 | { | 1484 | { |
1487 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1485 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1488 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1486 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1489 | 1487 | ||
1490 | wm8993->hubs_data.hp_startup_mode = 1; | 1488 | wm8993->hubs_data.hp_startup_mode = 1; |
1491 | wm8993->hubs_data.dcs_codes_l = -2; | 1489 | wm8993->hubs_data.dcs_codes_l = -2; |
@@ -1539,7 +1537,7 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1539 | * VMID as an output and can disable it. | 1537 | * VMID as an output and can disable it. |
1540 | */ | 1538 | */ |
1541 | if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff) | 1539 | if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff) |
1542 | codec->dapm.idle_bias_off = 1; | 1540 | dapm->idle_bias_off = 1; |
1543 | 1541 | ||
1544 | return 0; | 1542 | return 0; |
1545 | 1543 | ||
@@ -1563,7 +1561,7 @@ static int wm8993_suspend(struct snd_soc_codec *codec) | |||
1563 | wm8993->fll_fout = fll_fout; | 1561 | wm8993->fll_fout = fll_fout; |
1564 | wm8993->fll_fref = fll_fref; | 1562 | wm8993->fll_fref = fll_fref; |
1565 | 1563 | ||
1566 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1564 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
1567 | 1565 | ||
1568 | return 0; | 1566 | return 0; |
1569 | } | 1567 | } |
@@ -1573,7 +1571,7 @@ static int wm8993_resume(struct snd_soc_codec *codec) | |||
1573 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1571 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1574 | int ret; | 1572 | int ret; |
1575 | 1573 | ||
1576 | wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1574 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1577 | 1575 | ||
1578 | /* Restart the FLL? */ | 1576 | /* Restart the FLL? */ |
1579 | if (wm8993->fll_fout) { | 1577 | if (wm8993->fll_fout) { |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 4fbc7689339a..962e1d31a629 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -212,6 +212,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) | |||
212 | 212 | ||
213 | static int configure_clock(struct snd_soc_codec *codec) | 213 | static int configure_clock(struct snd_soc_codec *codec) |
214 | { | 214 | { |
215 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
215 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 216 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
216 | int change, new; | 217 | int change, new; |
217 | 218 | ||
@@ -239,7 +240,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
239 | change = snd_soc_update_bits(codec, WM8994_CLOCKING_1, | 240 | change = snd_soc_update_bits(codec, WM8994_CLOCKING_1, |
240 | WM8994_SYSCLK_SRC, new); | 241 | WM8994_SYSCLK_SRC, new); |
241 | if (change) | 242 | if (change) |
242 | snd_soc_dapm_sync(&codec->dapm); | 243 | snd_soc_dapm_sync(dapm); |
243 | 244 | ||
244 | wm8958_micd_set_rate(codec); | 245 | wm8958_micd_set_rate(codec); |
245 | 246 | ||
@@ -2492,12 +2493,12 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2492 | break; | 2493 | break; |
2493 | } | 2494 | } |
2494 | 2495 | ||
2495 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 2496 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) |
2496 | active_reference(codec); | 2497 | active_reference(codec); |
2497 | break; | 2498 | break; |
2498 | 2499 | ||
2499 | case SND_SOC_BIAS_STANDBY: | 2500 | case SND_SOC_BIAS_STANDBY: |
2500 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 2501 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
2501 | switch (control->type) { | 2502 | switch (control->type) { |
2502 | case WM8958: | 2503 | case WM8958: |
2503 | if (control->revision == 0) { | 2504 | if (control->revision == 0) { |
@@ -2521,7 +2522,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2521 | WM8994_LINEOUT2_DISCH); | 2522 | WM8994_LINEOUT2_DISCH); |
2522 | } | 2523 | } |
2523 | 2524 | ||
2524 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | 2525 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) |
2525 | active_dereference(codec); | 2526 | active_dereference(codec); |
2526 | 2527 | ||
2527 | /* MICBIAS into bypass mode on newer devices */ | 2528 | /* MICBIAS into bypass mode on newer devices */ |
@@ -2541,20 +2542,18 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2541 | break; | 2542 | break; |
2542 | 2543 | ||
2543 | case SND_SOC_BIAS_OFF: | 2544 | case SND_SOC_BIAS_OFF: |
2544 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 2545 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) |
2545 | wm8994->cur_fw = NULL; | 2546 | wm8994->cur_fw = NULL; |
2546 | break; | 2547 | break; |
2547 | } | 2548 | } |
2548 | 2549 | ||
2549 | codec->dapm.bias_level = level; | ||
2550 | |||
2551 | return 0; | 2550 | return 0; |
2552 | } | 2551 | } |
2553 | 2552 | ||
2554 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) | 2553 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) |
2555 | { | 2554 | { |
2556 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2555 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2557 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2556 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2558 | 2557 | ||
2559 | switch (mode) { | 2558 | switch (mode) { |
2560 | case WM8994_VMID_NORMAL: | 2559 | case WM8994_VMID_NORMAL: |
@@ -2754,7 +2753,7 @@ static struct { | |||
2754 | }; | 2753 | }; |
2755 | 2754 | ||
2756 | static int fs_ratios[] = { | 2755 | static int fs_ratios[] = { |
2757 | 64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536 | 2756 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536 |
2758 | }; | 2757 | }; |
2759 | 2758 | ||
2760 | static int bclk_divs[] = { | 2759 | static int bclk_divs[] = { |
@@ -3163,7 +3162,7 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec) | |||
3163 | i + 1, ret); | 3162 | i + 1, ret); |
3164 | } | 3163 | } |
3165 | 3164 | ||
3166 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 3165 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
3167 | 3166 | ||
3168 | return 0; | 3167 | return 0; |
3169 | } | 3168 | } |
@@ -3356,6 +3355,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3356 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 3355 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
3357 | int micbias) | 3356 | int micbias) |
3358 | { | 3357 | { |
3358 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3359 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3359 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3360 | struct wm8994_micdet *micdet; | 3360 | struct wm8994_micdet *micdet; |
3361 | struct wm8994 *control = wm8994->wm8994; | 3361 | struct wm8994 *control = wm8994->wm8994; |
@@ -3370,20 +3370,16 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3370 | case 1: | 3370 | case 1: |
3371 | micdet = &wm8994->micdet[0]; | 3371 | micdet = &wm8994->micdet[0]; |
3372 | if (jack) | 3372 | if (jack) |
3373 | ret = snd_soc_dapm_force_enable_pin(&codec->dapm, | 3373 | ret = snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); |
3374 | "MICBIAS1"); | ||
3375 | else | 3374 | else |
3376 | ret = snd_soc_dapm_disable_pin(&codec->dapm, | 3375 | ret = snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); |
3377 | "MICBIAS1"); | ||
3378 | break; | 3376 | break; |
3379 | case 2: | 3377 | case 2: |
3380 | micdet = &wm8994->micdet[1]; | 3378 | micdet = &wm8994->micdet[1]; |
3381 | if (jack) | 3379 | if (jack) |
3382 | ret = snd_soc_dapm_force_enable_pin(&codec->dapm, | 3380 | ret = snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); |
3383 | "MICBIAS1"); | ||
3384 | else | 3381 | else |
3385 | ret = snd_soc_dapm_disable_pin(&codec->dapm, | 3382 | ret = snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); |
3386 | "MICBIAS1"); | ||
3387 | break; | 3383 | break; |
3388 | default: | 3384 | default: |
3389 | dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias); | 3385 | dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias); |
@@ -3415,7 +3411,7 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3415 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, | 3411 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, |
3416 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); | 3412 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); |
3417 | 3413 | ||
3418 | snd_soc_dapm_sync(&codec->dapm); | 3414 | snd_soc_dapm_sync(dapm); |
3419 | 3415 | ||
3420 | return 0; | 3416 | return 0; |
3421 | } | 3417 | } |
@@ -3505,6 +3501,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3505 | /* Should be called with accdet_lock held */ | 3501 | /* Should be called with accdet_lock held */ |
3506 | static void wm1811_micd_stop(struct snd_soc_codec *codec) | 3502 | static void wm1811_micd_stop(struct snd_soc_codec *codec) |
3507 | { | 3503 | { |
3504 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3508 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3505 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3509 | 3506 | ||
3510 | if (!wm8994->jackdet) | 3507 | if (!wm8994->jackdet) |
@@ -3515,8 +3512,7 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec) | |||
3515 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | 3512 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); |
3516 | 3513 | ||
3517 | if (wm8994->wm8994->pdata.jd_ext_cap) | 3514 | if (wm8994->wm8994->pdata.jd_ext_cap) |
3518 | snd_soc_dapm_disable_pin(&codec->dapm, | 3515 | snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); |
3519 | "MICBIAS2"); | ||
3520 | } | 3516 | } |
3521 | 3517 | ||
3522 | static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) | 3518 | static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) |
@@ -3625,14 +3621,14 @@ static void wm1811_mic_work(struct work_struct *work) | |||
3625 | mic_work.work); | 3621 | mic_work.work); |
3626 | struct wm8994 *control = wm8994->wm8994; | 3622 | struct wm8994 *control = wm8994->wm8994; |
3627 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3623 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3624 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3628 | 3625 | ||
3629 | pm_runtime_get_sync(codec->dev); | 3626 | pm_runtime_get_sync(codec->dev); |
3630 | 3627 | ||
3631 | /* If required for an external cap force MICBIAS on */ | 3628 | /* If required for an external cap force MICBIAS on */ |
3632 | if (control->pdata.jd_ext_cap) { | 3629 | if (control->pdata.jd_ext_cap) { |
3633 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 3630 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS2"); |
3634 | "MICBIAS2"); | 3631 | snd_soc_dapm_sync(dapm); |
3635 | snd_soc_dapm_sync(&codec->dapm); | ||
3636 | } | 3632 | } |
3637 | 3633 | ||
3638 | mutex_lock(&wm8994->accdet_lock); | 3634 | mutex_lock(&wm8994->accdet_lock); |
@@ -3664,6 +3660,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3664 | struct wm8994_priv *wm8994 = data; | 3660 | struct wm8994_priv *wm8994 = data; |
3665 | struct wm8994 *control = wm8994->wm8994; | 3661 | struct wm8994 *control = wm8994->wm8994; |
3666 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3662 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3663 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3667 | int reg, delay; | 3664 | int reg, delay; |
3668 | bool present; | 3665 | bool present; |
3669 | 3666 | ||
@@ -3724,7 +3721,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3724 | 3721 | ||
3725 | /* Turn off MICBIAS if it was on for an external cap */ | 3722 | /* Turn off MICBIAS if it was on for an external cap */ |
3726 | if (control->pdata.jd_ext_cap && !present) | 3723 | if (control->pdata.jd_ext_cap && !present) |
3727 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2"); | 3724 | snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); |
3728 | 3725 | ||
3729 | if (present) | 3726 | if (present) |
3730 | snd_soc_jack_report(wm8994->micdet[0].jack, | 3727 | snd_soc_jack_report(wm8994->micdet[0].jack, |
@@ -3770,6 +3767,7 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3770 | wm1811_micdet_cb det_cb, void *det_cb_data, | 3767 | wm1811_micdet_cb det_cb, void *det_cb_data, |
3771 | wm1811_mic_id_cb id_cb, void *id_cb_data) | 3768 | wm1811_mic_id_cb id_cb, void *id_cb_data) |
3772 | { | 3769 | { |
3770 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3773 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3771 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3774 | struct wm8994 *control = wm8994->wm8994; | 3772 | struct wm8994 *control = wm8994->wm8994; |
3775 | u16 micd_lvl_sel; | 3773 | u16 micd_lvl_sel; |
@@ -3783,8 +3781,8 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3783 | } | 3781 | } |
3784 | 3782 | ||
3785 | if (jack) { | 3783 | if (jack) { |
3786 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); | 3784 | snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS"); |
3787 | snd_soc_dapm_sync(&codec->dapm); | 3785 | snd_soc_dapm_sync(dapm); |
3788 | 3786 | ||
3789 | wm8994->micdet[0].jack = jack; | 3787 | wm8994->micdet[0].jack = jack; |
3790 | 3788 | ||
@@ -3819,7 +3817,7 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3819 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_2, | 3817 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_2, |
3820 | WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel); | 3818 | WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel); |
3821 | 3819 | ||
3822 | WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY); | 3820 | WARN_ON(snd_soc_codec_get_bias_level(codec) > SND_SOC_BIAS_STANDBY); |
3823 | 3821 | ||
3824 | /* | 3822 | /* |
3825 | * If we can use jack detection start off with that, | 3823 | * If we can use jack detection start off with that, |
@@ -3846,8 +3844,8 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3846 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 3844 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
3847 | WM8958_MICD_ENA, 0); | 3845 | WM8958_MICD_ENA, 0); |
3848 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE); | 3846 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE); |
3849 | snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS"); | 3847 | snd_soc_dapm_disable_pin(dapm, "CLK_SYS"); |
3850 | snd_soc_dapm_sync(&codec->dapm); | 3848 | snd_soc_dapm_sync(dapm); |
3851 | } | 3849 | } |
3852 | 3850 | ||
3853 | return 0; | 3851 | return 0; |
@@ -3985,9 +3983,9 @@ static irqreturn_t wm8994_temp_shut(int irq, void *data) | |||
3985 | 3983 | ||
3986 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 3984 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
3987 | { | 3985 | { |
3986 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3988 | struct wm8994 *control = dev_get_drvdata(codec->dev->parent); | 3987 | struct wm8994 *control = dev_get_drvdata(codec->dev->parent); |
3989 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3988 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3990 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
3991 | unsigned int reg; | 3989 | unsigned int reg; |
3992 | int ret, i; | 3990 | int ret, i; |
3993 | 3991 | ||
@@ -4018,7 +4016,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4018 | wm8994->micdet_irq = control->pdata.micdet_irq; | 4016 | wm8994->micdet_irq = control->pdata.micdet_irq; |
4019 | 4017 | ||
4020 | /* By default use idle_bias_off, will override for WM8994 */ | 4018 | /* By default use idle_bias_off, will override for WM8994 */ |
4021 | codec->dapm.idle_bias_off = 1; | 4019 | dapm->idle_bias_off = 1; |
4022 | 4020 | ||
4023 | /* Set revision-specific configuration */ | 4021 | /* Set revision-specific configuration */ |
4024 | switch (control->type) { | 4022 | switch (control->type) { |
@@ -4026,7 +4024,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4026 | /* Single ended line outputs should have VMID on. */ | 4024 | /* Single ended line outputs should have VMID on. */ |
4027 | if (!control->pdata.lineout1_diff || | 4025 | if (!control->pdata.lineout1_diff || |
4028 | !control->pdata.lineout2_diff) | 4026 | !control->pdata.lineout2_diff) |
4029 | codec->dapm.idle_bias_off = 0; | 4027 | dapm->idle_bias_off = 0; |
4030 | 4028 | ||
4031 | switch (control->revision) { | 4029 | switch (control->revision) { |
4032 | case 2: | 4030 | case 2: |
@@ -4086,7 +4084,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4086 | if (wm8994->micdet_irq) | 4084 | if (wm8994->micdet_irq) |
4087 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, | 4085 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
4088 | wm8994_mic_irq, | 4086 | wm8994_mic_irq, |
4089 | IRQF_TRIGGER_RISING, | 4087 | IRQF_TRIGGER_RISING | |
4088 | IRQF_ONESHOT, | ||
4090 | "Mic1 detect", | 4089 | "Mic1 detect", |
4091 | wm8994); | 4090 | wm8994); |
4092 | else | 4091 | else |
@@ -4134,7 +4133,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4134 | if (wm8994->micdet_irq) { | 4133 | if (wm8994->micdet_irq) { |
4135 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, | 4134 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
4136 | wm8958_mic_irq, | 4135 | wm8958_mic_irq, |
4137 | IRQF_TRIGGER_RISING, | 4136 | IRQF_TRIGGER_RISING | |
4137 | IRQF_ONESHOT, | ||
4138 | "Mic detect", | 4138 | "Mic detect", |
4139 | wm8994); | 4139 | wm8994); |
4140 | if (ret != 0) | 4140 | if (ret != 0) |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 66103c2b012e..505b65f5734f 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -721,6 +721,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) | |||
721 | 721 | ||
722 | static int configure_clock(struct snd_soc_codec *codec) | 722 | static int configure_clock(struct snd_soc_codec *codec) |
723 | { | 723 | { |
724 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
724 | struct wm8995_priv *wm8995; | 725 | struct wm8995_priv *wm8995; |
725 | int change, new; | 726 | int change, new; |
726 | 727 | ||
@@ -751,7 +752,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
751 | if (!change) | 752 | if (!change) |
752 | return 0; | 753 | return 0; |
753 | 754 | ||
754 | snd_soc_dapm_sync(&codec->dapm); | 755 | snd_soc_dapm_sync(dapm); |
755 | 756 | ||
756 | return 0; | 757 | return 0; |
757 | } | 758 | } |
@@ -1929,7 +1930,7 @@ static int wm8995_set_dai_sysclk(struct snd_soc_dai *dai, | |||
1929 | dai->id + 1, freq); | 1930 | dai->id + 1, freq); |
1930 | break; | 1931 | break; |
1931 | case WM8995_SYSCLK_MCLK2: | 1932 | case WM8995_SYSCLK_MCLK2: |
1932 | wm8995->sysclk[dai->id] = WM8995_SYSCLK_MCLK1; | 1933 | wm8995->sysclk[dai->id] = WM8995_SYSCLK_MCLK2; |
1933 | wm8995->mclk[1] = freq; | 1934 | wm8995->mclk[1] = freq; |
1934 | dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", | 1935 | dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", |
1935 | dai->id + 1, freq); | 1936 | dai->id + 1, freq); |
@@ -1965,7 +1966,7 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, | |||
1965 | case SND_SOC_BIAS_PREPARE: | 1966 | case SND_SOC_BIAS_PREPARE: |
1966 | break; | 1967 | break; |
1967 | case SND_SOC_BIAS_STANDBY: | 1968 | case SND_SOC_BIAS_STANDBY: |
1968 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1969 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1969 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), | 1970 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), |
1970 | wm8995->supplies); | 1971 | wm8995->supplies); |
1971 | if (ret) | 1972 | if (ret) |
@@ -1990,7 +1991,6 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, | |||
1990 | break; | 1991 | break; |
1991 | } | 1992 | } |
1992 | 1993 | ||
1993 | codec->dapm.bias_level = level; | ||
1994 | return 0; | 1994 | return 0; |
1995 | } | 1995 | } |
1996 | 1996 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 308748a022c5..3dd063f682b2 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -1590,7 +1590,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1590 | break; | 1590 | break; |
1591 | 1591 | ||
1592 | case SND_SOC_BIAS_STANDBY: | 1592 | case SND_SOC_BIAS_STANDBY: |
1593 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1593 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
1594 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), | 1594 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), |
1595 | wm8996->supplies); | 1595 | wm8996->supplies); |
1596 | if (ret != 0) { | 1596 | if (ret != 0) { |
@@ -1628,8 +1628,6 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1628 | break; | 1628 | break; |
1629 | } | 1629 | } |
1630 | 1630 | ||
1631 | codec->dapm.bias_level = level; | ||
1632 | |||
1633 | return 0; | 1631 | return 0; |
1634 | } | 1632 | } |
1635 | 1633 | ||
@@ -2247,7 +2245,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2247 | wm8996_polarity_fn polarity_cb) | 2245 | wm8996_polarity_fn polarity_cb) |
2248 | { | 2246 | { |
2249 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2247 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2250 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2248 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2251 | 2249 | ||
2252 | wm8996->jack = jack; | 2250 | wm8996->jack = jack; |
2253 | wm8996->detecting = true; | 2251 | wm8996->detecting = true; |
@@ -2292,6 +2290,7 @@ EXPORT_SYMBOL_GPL(wm8996_detect); | |||
2292 | 2290 | ||
2293 | static void wm8996_hpdet_irq(struct snd_soc_codec *codec) | 2291 | static void wm8996_hpdet_irq(struct snd_soc_codec *codec) |
2294 | { | 2292 | { |
2293 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2295 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2294 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2296 | int val, reg, report; | 2295 | int val, reg, report; |
2297 | 2296 | ||
@@ -2345,12 +2344,14 @@ out: | |||
2345 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, | 2344 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, |
2346 | WM8996_MICD_ENA); | 2345 | WM8996_MICD_ENA); |
2347 | 2346 | ||
2348 | snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap"); | 2347 | snd_soc_dapm_disable_pin(dapm, "Bandgap"); |
2349 | snd_soc_dapm_sync(&codec->dapm); | 2348 | snd_soc_dapm_sync(dapm); |
2350 | } | 2349 | } |
2351 | 2350 | ||
2352 | static void wm8996_hpdet_start(struct snd_soc_codec *codec) | 2351 | static void wm8996_hpdet_start(struct snd_soc_codec *codec) |
2353 | { | 2352 | { |
2353 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2354 | |||
2354 | /* Unclamp the output, we can't measure while we're shorting it */ | 2355 | /* Unclamp the output, we can't measure while we're shorting it */ |
2355 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, | 2356 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, |
2356 | WM8996_HPOUT1L_RMV_SHORT | | 2357 | WM8996_HPOUT1L_RMV_SHORT | |
@@ -2359,8 +2360,8 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec) | |||
2359 | WM8996_HPOUT1R_RMV_SHORT); | 2360 | WM8996_HPOUT1R_RMV_SHORT); |
2360 | 2361 | ||
2361 | /* We need bandgap for HPDET */ | 2362 | /* We need bandgap for HPDET */ |
2362 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap"); | 2363 | snd_soc_dapm_force_enable_pin(dapm, "Bandgap"); |
2363 | snd_soc_dapm_sync(&codec->dapm); | 2364 | snd_soc_dapm_sync(dapm); |
2364 | 2365 | ||
2365 | /* Go into headphone detect left mode */ | 2366 | /* Go into headphone detect left mode */ |
2366 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); | 2367 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); |
@@ -2646,10 +2647,12 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2646 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | 2647 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2647 | ret = request_threaded_irq(i2c->irq, NULL, | 2648 | ret = request_threaded_irq(i2c->irq, NULL, |
2648 | wm8996_edge_irq, | 2649 | wm8996_edge_irq, |
2649 | irq_flags, "wm8996", codec); | 2650 | irq_flags | IRQF_ONESHOT, |
2651 | "wm8996", codec); | ||
2650 | else | 2652 | else |
2651 | ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq, | 2653 | ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq, |
2652 | irq_flags, "wm8996", codec); | 2654 | irq_flags | IRQF_ONESHOT, |
2655 | "wm8996", codec); | ||
2653 | 2656 | ||
2654 | if (ret == 0) { | 2657 | if (ret == 0) { |
2655 | /* Unmask the interrupt */ | 2658 | /* Unmask the interrupt */ |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index a4d11770630c..4134dc7e1243 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -40,7 +40,7 @@ struct wm8997_priv { | |||
40 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | 40 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); |
41 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 41 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | 43 | static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); |
44 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | 44 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); |
45 | 45 | ||
46 | static const struct reg_default wm8997_sysclk_reva_patch[] = { | 46 | static const struct reg_default wm8997_sysclk_reva_patch[] = { |
@@ -106,11 +106,13 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
106 | regmap_write_async(regmap, patch[i].reg, | 106 | regmap_write_async(regmap, patch[i].reg, |
107 | patch[i].def); | 107 | patch[i].def); |
108 | break; | 108 | break; |
109 | default: | 109 | case SND_SOC_DAPM_PRE_PMD: |
110 | break; | 110 | break; |
111 | default: | ||
112 | return 0; | ||
111 | } | 113 | } |
112 | 114 | ||
113 | return 0; | 115 | return arizona_dvfs_sysclk_ev(w, kcontrol, event); |
114 | } | 116 | } |
115 | 117 | ||
116 | static const char *wm8997_osr_text[] = { | 118 | static const char *wm8997_osr_text[] = { |
@@ -409,7 +411,8 @@ static const struct snd_kcontrol_new wm8997_aec_loopback_mux = | |||
409 | 411 | ||
410 | static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = { | 412 | static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = { |
411 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 413 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
412 | 0, wm8997_sysclk_ev, SND_SOC_DAPM_POST_PMU), | 414 | 0, wm8997_sysclk_ev, |
415 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
413 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 416 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
414 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 417 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
415 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | 418 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, |
@@ -1055,13 +1058,14 @@ static struct snd_soc_dai_driver wm8997_dai[] = { | |||
1055 | 1058 | ||
1056 | static int wm8997_codec_probe(struct snd_soc_codec *codec) | 1059 | static int wm8997_codec_probe(struct snd_soc_codec *codec) |
1057 | { | 1060 | { |
1061 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
1058 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); | 1062 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); |
1059 | 1063 | ||
1060 | arizona_init_spk(codec); | 1064 | arizona_init_spk(codec); |
1061 | 1065 | ||
1062 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1066 | snd_soc_dapm_disable_pin(dapm, "HAPTICS"); |
1063 | 1067 | ||
1064 | priv->core.arizona->dapm = &codec->dapm; | 1068 | priv->core.arizona->dapm = dapm; |
1065 | 1069 | ||
1066 | return 0; | 1070 | return 0; |
1067 | } | 1071 | } |
@@ -1126,6 +1130,8 @@ static int wm8997_probe(struct platform_device *pdev) | |||
1126 | wm8997->core.arizona = arizona; | 1130 | wm8997->core.arizona = arizona; |
1127 | wm8997->core.num_inputs = 4; | 1131 | wm8997->core.num_inputs = 4; |
1128 | 1132 | ||
1133 | arizona_init_dvfs(&wm8997->core); | ||
1134 | |||
1129 | for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++) | 1135 | for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++) |
1130 | wm8997->fll[i].vco_mult = 1; | 1136 | wm8997->fll[i].vco_mult = 1; |
1131 | 1137 | ||
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 13a3f335ea5b..8a8b1c0f9142 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -838,7 +838,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, | |||
838 | 838 | ||
839 | case SND_SOC_BIAS_STANDBY: | 839 | case SND_SOC_BIAS_STANDBY: |
840 | /* Initial cold start */ | 840 | /* Initial cold start */ |
841 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 841 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
842 | regcache_cache_only(wm9081->regmap, false); | 842 | regcache_cache_only(wm9081->regmap, false); |
843 | regcache_sync(wm9081->regmap); | 843 | regcache_sync(wm9081->regmap); |
844 | 844 | ||
@@ -898,8 +898,6 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, | |||
898 | break; | 898 | break; |
899 | } | 899 | } |
900 | 900 | ||
901 | codec->dapm.bias_level = level; | ||
902 | |||
903 | return 0; | 901 | return 0; |
904 | } | 902 | } |
905 | 903 | ||
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 60d243c904f5..13d23fc797db 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -425,7 +425,7 @@ static const struct snd_soc_dapm_route audio_map_in2_diff[] = { | |||
425 | static int wm9090_add_controls(struct snd_soc_codec *codec) | 425 | static int wm9090_add_controls(struct snd_soc_codec *codec) |
426 | { | 426 | { |
427 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); | 427 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); |
428 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 428 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
429 | int i; | 429 | int i; |
430 | 430 | ||
431 | snd_soc_dapm_new_controls(dapm, wm9090_dapm_widgets, | 431 | snd_soc_dapm_new_controls(dapm, wm9090_dapm_widgets, |
@@ -496,7 +496,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
496 | break; | 496 | break; |
497 | 497 | ||
498 | case SND_SOC_BIAS_STANDBY: | 498 | case SND_SOC_BIAS_STANDBY: |
499 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 499 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
500 | /* Restore the register cache */ | 500 | /* Restore the register cache */ |
501 | regcache_sync(wm9090->regmap); | 501 | regcache_sync(wm9090->regmap); |
502 | } | 502 | } |
@@ -515,8 +515,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
515 | break; | 515 | break; |
516 | } | 516 | } |
517 | 517 | ||
518 | codec->dapm.bias_level = level; | ||
519 | |||
520 | return 0; | 518 | return 0; |
521 | } | 519 | } |
522 | 520 | ||
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 98c9525bd751..1fda104dfc45 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -610,7 +610,6 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
610 | ac97_write(codec, AC97_POWERDOWN, 0xffff); | 610 | ac97_write(codec, AC97_POWERDOWN, 0xffff); |
611 | break; | 611 | break; |
612 | } | 612 | } |
613 | codec->dapm.bias_level = level; | ||
614 | return 0; | 613 | return 0; |
615 | } | 614 | } |
616 | 615 | ||
@@ -646,7 +645,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
646 | if (ret < 0) | 645 | if (ret < 0) |
647 | return ret; | 646 | return ret; |
648 | 647 | ||
649 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 648 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
650 | 649 | ||
651 | if (ret == 0) { | 650 | if (ret == 0) { |
652 | /* Sync reg_cache with the hardware after cold reset */ | 651 | /* Sync reg_cache with the hardware after cold reset */ |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 79552953e1bd..89cd2d6f57c0 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -1054,8 +1054,8 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
1054 | SNDRV_PCM_RATE_48000) | 1054 | SNDRV_PCM_RATE_48000) |
1055 | 1055 | ||
1056 | #define WM9713_PCM_FORMATS \ | 1056 | #define WM9713_PCM_FORMATS \ |
1057 | (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ | 1057 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1058 | SNDRV_PCM_FORMAT_S24_LE) | 1058 | SNDRV_PCM_FMTBIT_S24_LE) |
1059 | 1059 | ||
1060 | static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = { | 1060 | static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = { |
1061 | .prepare = ac97_hifi_prepare, | 1061 | .prepare = ac97_hifi_prepare, |
@@ -1171,7 +1171,6 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec, | |||
1171 | ac97_write(codec, AC97_POWERDOWN, 0xffff); | 1171 | ac97_write(codec, AC97_POWERDOWN, 0xffff); |
1172 | break; | 1172 | break; |
1173 | } | 1173 | } |
1174 | codec->dapm.bias_level = level; | ||
1175 | return 0; | 1174 | return 0; |
1176 | } | 1175 | } |
1177 | 1176 | ||
@@ -1201,7 +1200,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1201 | if (ret < 0) | 1200 | if (ret < 0) |
1202 | return ret; | 1201 | return ret; |
1203 | 1202 | ||
1204 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1203 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1205 | 1204 | ||
1206 | /* do we need to re-start the PLL ? */ | 1205 | /* do we need to re-start the PLL ? */ |
1207 | if (wm9713->pll_in) | 1206 | if (wm9713->pll_in) |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d01c2095452f..0bb415a28723 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <linux/debugfs.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
28 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
@@ -121,6 +122,11 @@ | |||
121 | #define ADSP2_WDMA_CONFIG_2 0x31 | 122 | #define ADSP2_WDMA_CONFIG_2 0x31 |
122 | #define ADSP2_RDMA_CONFIG_1 0x34 | 123 | #define ADSP2_RDMA_CONFIG_1 0x34 |
123 | 124 | ||
125 | #define ADSP2_SCRATCH0 0x40 | ||
126 | #define ADSP2_SCRATCH1 0x41 | ||
127 | #define ADSP2_SCRATCH2 0x42 | ||
128 | #define ADSP2_SCRATCH3 0x43 | ||
129 | |||
124 | /* | 130 | /* |
125 | * ADSP2 Control | 131 | * ADSP2 Control |
126 | */ | 132 | */ |
@@ -229,26 +235,197 @@ struct wm_coeff_ctl_ops { | |||
229 | 235 | ||
230 | struct wm_coeff_ctl { | 236 | struct wm_coeff_ctl { |
231 | const char *name; | 237 | const char *name; |
232 | struct wm_adsp_alg_region region; | 238 | const char *fw_name; |
239 | struct wm_adsp_alg_region alg_region; | ||
233 | struct wm_coeff_ctl_ops ops; | 240 | struct wm_coeff_ctl_ops ops; |
234 | struct wm_adsp *adsp; | 241 | struct wm_adsp *dsp; |
235 | void *private; | ||
236 | unsigned int enabled:1; | 242 | unsigned int enabled:1; |
237 | struct list_head list; | 243 | struct list_head list; |
238 | void *cache; | 244 | void *cache; |
245 | unsigned int offset; | ||
239 | size_t len; | 246 | size_t len; |
240 | unsigned int set:1; | 247 | unsigned int set:1; |
241 | struct snd_kcontrol *kcontrol; | 248 | struct snd_kcontrol *kcontrol; |
249 | unsigned int flags; | ||
242 | }; | 250 | }; |
243 | 251 | ||
252 | #ifdef CONFIG_DEBUG_FS | ||
253 | static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) | ||
254 | { | ||
255 | char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); | ||
256 | |||
257 | mutex_lock(&dsp->debugfs_lock); | ||
258 | kfree(dsp->wmfw_file_name); | ||
259 | dsp->wmfw_file_name = tmp; | ||
260 | mutex_unlock(&dsp->debugfs_lock); | ||
261 | } | ||
262 | |||
263 | static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) | ||
264 | { | ||
265 | char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); | ||
266 | |||
267 | mutex_lock(&dsp->debugfs_lock); | ||
268 | kfree(dsp->bin_file_name); | ||
269 | dsp->bin_file_name = tmp; | ||
270 | mutex_unlock(&dsp->debugfs_lock); | ||
271 | } | ||
272 | |||
273 | static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) | ||
274 | { | ||
275 | mutex_lock(&dsp->debugfs_lock); | ||
276 | kfree(dsp->wmfw_file_name); | ||
277 | kfree(dsp->bin_file_name); | ||
278 | dsp->wmfw_file_name = NULL; | ||
279 | dsp->bin_file_name = NULL; | ||
280 | mutex_unlock(&dsp->debugfs_lock); | ||
281 | } | ||
282 | |||
283 | static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, | ||
284 | char __user *user_buf, | ||
285 | size_t count, loff_t *ppos) | ||
286 | { | ||
287 | struct wm_adsp *dsp = file->private_data; | ||
288 | ssize_t ret; | ||
289 | |||
290 | mutex_lock(&dsp->debugfs_lock); | ||
291 | |||
292 | if (!dsp->wmfw_file_name || !dsp->running) | ||
293 | ret = 0; | ||
294 | else | ||
295 | ret = simple_read_from_buffer(user_buf, count, ppos, | ||
296 | dsp->wmfw_file_name, | ||
297 | strlen(dsp->wmfw_file_name)); | ||
298 | |||
299 | mutex_unlock(&dsp->debugfs_lock); | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static ssize_t wm_adsp_debugfs_bin_read(struct file *file, | ||
304 | char __user *user_buf, | ||
305 | size_t count, loff_t *ppos) | ||
306 | { | ||
307 | struct wm_adsp *dsp = file->private_data; | ||
308 | ssize_t ret; | ||
309 | |||
310 | mutex_lock(&dsp->debugfs_lock); | ||
311 | |||
312 | if (!dsp->bin_file_name || !dsp->running) | ||
313 | ret = 0; | ||
314 | else | ||
315 | ret = simple_read_from_buffer(user_buf, count, ppos, | ||
316 | dsp->bin_file_name, | ||
317 | strlen(dsp->bin_file_name)); | ||
318 | |||
319 | mutex_unlock(&dsp->debugfs_lock); | ||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static const struct { | ||
324 | const char *name; | ||
325 | const struct file_operations fops; | ||
326 | } wm_adsp_debugfs_fops[] = { | ||
327 | { | ||
328 | .name = "wmfw_file_name", | ||
329 | .fops = { | ||
330 | .open = simple_open, | ||
331 | .read = wm_adsp_debugfs_wmfw_read, | ||
332 | }, | ||
333 | }, | ||
334 | { | ||
335 | .name = "bin_file_name", | ||
336 | .fops = { | ||
337 | .open = simple_open, | ||
338 | .read = wm_adsp_debugfs_bin_read, | ||
339 | }, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, | ||
344 | struct snd_soc_codec *codec) | ||
345 | { | ||
346 | struct dentry *root = NULL; | ||
347 | char *root_name; | ||
348 | int i; | ||
349 | |||
350 | if (!codec->component.debugfs_root) { | ||
351 | adsp_err(dsp, "No codec debugfs root\n"); | ||
352 | goto err; | ||
353 | } | ||
354 | |||
355 | root_name = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
356 | if (!root_name) | ||
357 | goto err; | ||
358 | |||
359 | snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num); | ||
360 | root = debugfs_create_dir(root_name, codec->component.debugfs_root); | ||
361 | kfree(root_name); | ||
362 | |||
363 | if (!root) | ||
364 | goto err; | ||
365 | |||
366 | if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) | ||
367 | goto err; | ||
368 | |||
369 | if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id)) | ||
370 | goto err; | ||
371 | |||
372 | if (!debugfs_create_x32("fw_version", S_IRUGO, root, | ||
373 | &dsp->fw_id_version)) | ||
374 | goto err; | ||
375 | |||
376 | for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { | ||
377 | if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, | ||
378 | S_IRUGO, root, dsp, | ||
379 | &wm_adsp_debugfs_fops[i].fops)) | ||
380 | goto err; | ||
381 | } | ||
382 | |||
383 | dsp->debugfs_root = root; | ||
384 | return; | ||
385 | |||
386 | err: | ||
387 | debugfs_remove_recursive(root); | ||
388 | adsp_err(dsp, "Failed to create debugfs\n"); | ||
389 | } | ||
390 | |||
391 | static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) | ||
392 | { | ||
393 | wm_adsp_debugfs_clear(dsp); | ||
394 | debugfs_remove_recursive(dsp->debugfs_root); | ||
395 | } | ||
396 | #else | ||
397 | static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, | ||
398 | struct snd_soc_codec *codec) | ||
399 | { | ||
400 | } | ||
401 | |||
402 | static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) | ||
403 | { | ||
404 | } | ||
405 | |||
406 | static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, | ||
407 | const char *s) | ||
408 | { | ||
409 | } | ||
410 | |||
411 | static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, | ||
412 | const char *s) | ||
413 | { | ||
414 | } | ||
415 | |||
416 | static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) | ||
417 | { | ||
418 | } | ||
419 | #endif | ||
420 | |||
244 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 421 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, |
245 | struct snd_ctl_elem_value *ucontrol) | 422 | struct snd_ctl_elem_value *ucontrol) |
246 | { | 423 | { |
247 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 424 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
248 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 425 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
249 | struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); | 426 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); |
250 | 427 | ||
251 | ucontrol->value.integer.value[0] = adsp[e->shift_l].fw; | 428 | ucontrol->value.integer.value[0] = dsp[e->shift_l].fw; |
252 | 429 | ||
253 | return 0; | 430 | return 0; |
254 | } | 431 | } |
@@ -258,18 +435,18 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, | |||
258 | { | 435 | { |
259 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 436 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
260 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 437 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
261 | struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec); | 438 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); |
262 | 439 | ||
263 | if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw) | 440 | if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw) |
264 | return 0; | 441 | return 0; |
265 | 442 | ||
266 | if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) | 443 | if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) |
267 | return -EINVAL; | 444 | return -EINVAL; |
268 | 445 | ||
269 | if (adsp[e->shift_l].running) | 446 | if (dsp[e->shift_l].running) |
270 | return -EBUSY; | 447 | return -EBUSY; |
271 | 448 | ||
272 | adsp[e->shift_l].fw = ucontrol->value.integer.value[0]; | 449 | dsp[e->shift_l].fw = ucontrol->value.integer.value[0]; |
273 | 450 | ||
274 | return 0; | 451 | return 0; |
275 | } | 452 | } |
@@ -281,52 +458,17 @@ static const struct soc_enum wm_adsp_fw_enum[] = { | |||
281 | SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), | 458 | SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), |
282 | }; | 459 | }; |
283 | 460 | ||
284 | const struct snd_kcontrol_new wm_adsp1_fw_controls[] = { | 461 | const struct snd_kcontrol_new wm_adsp_fw_controls[] = { |
285 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], | ||
286 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
287 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], | ||
288 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
289 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], | ||
290 | wm_adsp_fw_get, wm_adsp_fw_put), | ||
291 | }; | ||
292 | EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls); | ||
293 | |||
294 | #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA) | ||
295 | static const struct soc_enum wm_adsp2_rate_enum[] = { | ||
296 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, | ||
297 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
298 | ARIZONA_RATE_ENUM_SIZE, | ||
299 | arizona_rate_text, arizona_rate_val), | ||
300 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1, | ||
301 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
302 | ARIZONA_RATE_ENUM_SIZE, | ||
303 | arizona_rate_text, arizona_rate_val), | ||
304 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, | ||
305 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
306 | ARIZONA_RATE_ENUM_SIZE, | ||
307 | arizona_rate_text, arizona_rate_val), | ||
308 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1, | ||
309 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | ||
310 | ARIZONA_RATE_ENUM_SIZE, | ||
311 | arizona_rate_text, arizona_rate_val), | ||
312 | }; | ||
313 | |||
314 | const struct snd_kcontrol_new wm_adsp2_fw_controls[] = { | ||
315 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], | 462 | SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], |
316 | wm_adsp_fw_get, wm_adsp_fw_put), | 463 | wm_adsp_fw_get, wm_adsp_fw_put), |
317 | SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]), | ||
318 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], | 464 | SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], |
319 | wm_adsp_fw_get, wm_adsp_fw_put), | 465 | wm_adsp_fw_get, wm_adsp_fw_put), |
320 | SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]), | ||
321 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], | 466 | SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], |
322 | wm_adsp_fw_get, wm_adsp_fw_put), | 467 | wm_adsp_fw_get, wm_adsp_fw_put), |
323 | SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]), | ||
324 | SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], | 468 | SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], |
325 | wm_adsp_fw_get, wm_adsp_fw_put), | 469 | wm_adsp_fw_get, wm_adsp_fw_put), |
326 | SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]), | ||
327 | }; | 470 | }; |
328 | EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls); | 471 | EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); |
329 | #endif | ||
330 | 472 | ||
331 | static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, | 473 | static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, |
332 | int type) | 474 | int type) |
@@ -340,28 +482,47 @@ static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, | |||
340 | return NULL; | 482 | return NULL; |
341 | } | 483 | } |
342 | 484 | ||
343 | static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region, | 485 | static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem, |
344 | unsigned int offset) | 486 | unsigned int offset) |
345 | { | 487 | { |
346 | if (WARN_ON(!region)) | 488 | if (WARN_ON(!mem)) |
347 | return offset; | 489 | return offset; |
348 | switch (region->type) { | 490 | switch (mem->type) { |
349 | case WMFW_ADSP1_PM: | 491 | case WMFW_ADSP1_PM: |
350 | return region->base + (offset * 3); | 492 | return mem->base + (offset * 3); |
351 | case WMFW_ADSP1_DM: | 493 | case WMFW_ADSP1_DM: |
352 | return region->base + (offset * 2); | 494 | return mem->base + (offset * 2); |
353 | case WMFW_ADSP2_XM: | 495 | case WMFW_ADSP2_XM: |
354 | return region->base + (offset * 2); | 496 | return mem->base + (offset * 2); |
355 | case WMFW_ADSP2_YM: | 497 | case WMFW_ADSP2_YM: |
356 | return region->base + (offset * 2); | 498 | return mem->base + (offset * 2); |
357 | case WMFW_ADSP1_ZM: | 499 | case WMFW_ADSP1_ZM: |
358 | return region->base + (offset * 2); | 500 | return mem->base + (offset * 2); |
359 | default: | 501 | default: |
360 | WARN(1, "Unknown memory region type"); | 502 | WARN(1, "Unknown memory region type"); |
361 | return offset; | 503 | return offset; |
362 | } | 504 | } |
363 | } | 505 | } |
364 | 506 | ||
507 | static void wm_adsp2_show_fw_status(struct wm_adsp *dsp) | ||
508 | { | ||
509 | u16 scratch[4]; | ||
510 | int ret; | ||
511 | |||
512 | ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0, | ||
513 | scratch, sizeof(scratch)); | ||
514 | if (ret) { | ||
515 | adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret); | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n", | ||
520 | be16_to_cpu(scratch[0]), | ||
521 | be16_to_cpu(scratch[1]), | ||
522 | be16_to_cpu(scratch[2]), | ||
523 | be16_to_cpu(scratch[3])); | ||
524 | } | ||
525 | |||
365 | static int wm_coeff_info(struct snd_kcontrol *kcontrol, | 526 | static int wm_coeff_info(struct snd_kcontrol *kcontrol, |
366 | struct snd_ctl_elem_info *uinfo) | 527 | struct snd_ctl_elem_info *uinfo) |
367 | { | 528 | { |
@@ -372,40 +533,39 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol, | |||
372 | return 0; | 533 | return 0; |
373 | } | 534 | } |
374 | 535 | ||
375 | static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, | 536 | static int wm_coeff_write_control(struct wm_coeff_ctl *ctl, |
376 | const void *buf, size_t len) | 537 | const void *buf, size_t len) |
377 | { | 538 | { |
378 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | 539 | struct wm_adsp_alg_region *alg_region = &ctl->alg_region; |
379 | struct wm_adsp_alg_region *region = &ctl->region; | ||
380 | const struct wm_adsp_region *mem; | 540 | const struct wm_adsp_region *mem; |
381 | struct wm_adsp *adsp = ctl->adsp; | 541 | struct wm_adsp *dsp = ctl->dsp; |
382 | void *scratch; | 542 | void *scratch; |
383 | int ret; | 543 | int ret; |
384 | unsigned int reg; | 544 | unsigned int reg; |
385 | 545 | ||
386 | mem = wm_adsp_find_region(adsp, region->type); | 546 | mem = wm_adsp_find_region(dsp, alg_region->type); |
387 | if (!mem) { | 547 | if (!mem) { |
388 | adsp_err(adsp, "No base for region %x\n", | 548 | adsp_err(dsp, "No base for region %x\n", |
389 | region->type); | 549 | alg_region->type); |
390 | return -EINVAL; | 550 | return -EINVAL; |
391 | } | 551 | } |
392 | 552 | ||
393 | reg = ctl->region.base; | 553 | reg = ctl->alg_region.base + ctl->offset; |
394 | reg = wm_adsp_region_to_reg(mem, reg); | 554 | reg = wm_adsp_region_to_reg(mem, reg); |
395 | 555 | ||
396 | scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); | 556 | scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); |
397 | if (!scratch) | 557 | if (!scratch) |
398 | return -ENOMEM; | 558 | return -ENOMEM; |
399 | 559 | ||
400 | ret = regmap_raw_write(adsp->regmap, reg, scratch, | 560 | ret = regmap_raw_write(dsp->regmap, reg, scratch, |
401 | ctl->len); | 561 | ctl->len); |
402 | if (ret) { | 562 | if (ret) { |
403 | adsp_err(adsp, "Failed to write %zu bytes to %x: %d\n", | 563 | adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n", |
404 | ctl->len, reg, ret); | 564 | ctl->len, reg, ret); |
405 | kfree(scratch); | 565 | kfree(scratch); |
406 | return ret; | 566 | return ret; |
407 | } | 567 | } |
408 | adsp_dbg(adsp, "Wrote %zu bytes to %x\n", ctl->len, reg); | 568 | adsp_dbg(dsp, "Wrote %zu bytes to %x\n", ctl->len, reg); |
409 | 569 | ||
410 | kfree(scratch); | 570 | kfree(scratch); |
411 | 571 | ||
@@ -424,42 +584,41 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol, | |||
424 | if (!ctl->enabled) | 584 | if (!ctl->enabled) |
425 | return 0; | 585 | return 0; |
426 | 586 | ||
427 | return wm_coeff_write_control(kcontrol, p, ctl->len); | 587 | return wm_coeff_write_control(ctl, p, ctl->len); |
428 | } | 588 | } |
429 | 589 | ||
430 | static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, | 590 | static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, |
431 | void *buf, size_t len) | 591 | void *buf, size_t len) |
432 | { | 592 | { |
433 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | 593 | struct wm_adsp_alg_region *alg_region = &ctl->alg_region; |
434 | struct wm_adsp_alg_region *region = &ctl->region; | ||
435 | const struct wm_adsp_region *mem; | 594 | const struct wm_adsp_region *mem; |
436 | struct wm_adsp *adsp = ctl->adsp; | 595 | struct wm_adsp *dsp = ctl->dsp; |
437 | void *scratch; | 596 | void *scratch; |
438 | int ret; | 597 | int ret; |
439 | unsigned int reg; | 598 | unsigned int reg; |
440 | 599 | ||
441 | mem = wm_adsp_find_region(adsp, region->type); | 600 | mem = wm_adsp_find_region(dsp, alg_region->type); |
442 | if (!mem) { | 601 | if (!mem) { |
443 | adsp_err(adsp, "No base for region %x\n", | 602 | adsp_err(dsp, "No base for region %x\n", |
444 | region->type); | 603 | alg_region->type); |
445 | return -EINVAL; | 604 | return -EINVAL; |
446 | } | 605 | } |
447 | 606 | ||
448 | reg = ctl->region.base; | 607 | reg = ctl->alg_region.base + ctl->offset; |
449 | reg = wm_adsp_region_to_reg(mem, reg); | 608 | reg = wm_adsp_region_to_reg(mem, reg); |
450 | 609 | ||
451 | scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); | 610 | scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); |
452 | if (!scratch) | 611 | if (!scratch) |
453 | return -ENOMEM; | 612 | return -ENOMEM; |
454 | 613 | ||
455 | ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len); | 614 | ret = regmap_raw_read(dsp->regmap, reg, scratch, ctl->len); |
456 | if (ret) { | 615 | if (ret) { |
457 | adsp_err(adsp, "Failed to read %zu bytes from %x: %d\n", | 616 | adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n", |
458 | ctl->len, reg, ret); | 617 | ctl->len, reg, ret); |
459 | kfree(scratch); | 618 | kfree(scratch); |
460 | return ret; | 619 | return ret; |
461 | } | 620 | } |
462 | adsp_dbg(adsp, "Read %zu bytes from %x\n", ctl->len, reg); | 621 | adsp_dbg(dsp, "Read %zu bytes from %x\n", ctl->len, reg); |
463 | 622 | ||
464 | memcpy(buf, scratch, ctl->len); | 623 | memcpy(buf, scratch, ctl->len); |
465 | kfree(scratch); | 624 | kfree(scratch); |
@@ -473,17 +632,25 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol, | |||
473 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | 632 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; |
474 | char *p = ucontrol->value.bytes.data; | 633 | char *p = ucontrol->value.bytes.data; |
475 | 634 | ||
635 | if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { | ||
636 | if (ctl->enabled) | ||
637 | return wm_coeff_read_control(ctl, p, ctl->len); | ||
638 | else | ||
639 | return -EPERM; | ||
640 | } | ||
641 | |||
476 | memcpy(p, ctl->cache, ctl->len); | 642 | memcpy(p, ctl->cache, ctl->len); |
643 | |||
477 | return 0; | 644 | return 0; |
478 | } | 645 | } |
479 | 646 | ||
480 | struct wmfw_ctl_work { | 647 | struct wmfw_ctl_work { |
481 | struct wm_adsp *adsp; | 648 | struct wm_adsp *dsp; |
482 | struct wm_coeff_ctl *ctl; | 649 | struct wm_coeff_ctl *ctl; |
483 | struct work_struct work; | 650 | struct work_struct work; |
484 | }; | 651 | }; |
485 | 652 | ||
486 | static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl) | 653 | static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl) |
487 | { | 654 | { |
488 | struct snd_kcontrol_new *kcontrol; | 655 | struct snd_kcontrol_new *kcontrol; |
489 | int ret; | 656 | int ret; |
@@ -502,17 +669,25 @@ static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl) | |||
502 | kcontrol->put = wm_coeff_put; | 669 | kcontrol->put = wm_coeff_put; |
503 | kcontrol->private_value = (unsigned long)ctl; | 670 | kcontrol->private_value = (unsigned long)ctl; |
504 | 671 | ||
505 | ret = snd_soc_add_card_controls(adsp->card, | 672 | if (ctl->flags) { |
673 | if (ctl->flags & WMFW_CTL_FLAG_WRITEABLE) | ||
674 | kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
675 | if (ctl->flags & WMFW_CTL_FLAG_READABLE) | ||
676 | kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ; | ||
677 | if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) | ||
678 | kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE; | ||
679 | } | ||
680 | |||
681 | ret = snd_soc_add_card_controls(dsp->card, | ||
506 | kcontrol, 1); | 682 | kcontrol, 1); |
507 | if (ret < 0) | 683 | if (ret < 0) |
508 | goto err_kcontrol; | 684 | goto err_kcontrol; |
509 | 685 | ||
510 | kfree(kcontrol); | 686 | kfree(kcontrol); |
511 | 687 | ||
512 | ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card, | 688 | ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, |
513 | ctl->name); | 689 | ctl->name); |
514 | 690 | ||
515 | list_add(&ctl->list, &adsp->ctl_list); | ||
516 | return 0; | 691 | return 0; |
517 | 692 | ||
518 | err_kcontrol: | 693 | err_kcontrol: |
@@ -520,6 +695,358 @@ err_kcontrol: | |||
520 | return ret; | 695 | return ret; |
521 | } | 696 | } |
522 | 697 | ||
698 | static int wm_coeff_init_control_caches(struct wm_adsp *dsp) | ||
699 | { | ||
700 | struct wm_coeff_ctl *ctl; | ||
701 | int ret; | ||
702 | |||
703 | list_for_each_entry(ctl, &dsp->ctl_list, list) { | ||
704 | if (!ctl->enabled || ctl->set) | ||
705 | continue; | ||
706 | if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) | ||
707 | continue; | ||
708 | |||
709 | ret = wm_coeff_read_control(ctl, | ||
710 | ctl->cache, | ||
711 | ctl->len); | ||
712 | if (ret < 0) | ||
713 | return ret; | ||
714 | } | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | static int wm_coeff_sync_controls(struct wm_adsp *dsp) | ||
720 | { | ||
721 | struct wm_coeff_ctl *ctl; | ||
722 | int ret; | ||
723 | |||
724 | list_for_each_entry(ctl, &dsp->ctl_list, list) { | ||
725 | if (!ctl->enabled) | ||
726 | continue; | ||
727 | if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) { | ||
728 | ret = wm_coeff_write_control(ctl, | ||
729 | ctl->cache, | ||
730 | ctl->len); | ||
731 | if (ret < 0) | ||
732 | return ret; | ||
733 | } | ||
734 | } | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static void wm_adsp_ctl_work(struct work_struct *work) | ||
740 | { | ||
741 | struct wmfw_ctl_work *ctl_work = container_of(work, | ||
742 | struct wmfw_ctl_work, | ||
743 | work); | ||
744 | |||
745 | wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl); | ||
746 | kfree(ctl_work); | ||
747 | } | ||
748 | |||
749 | static int wm_adsp_create_control(struct wm_adsp *dsp, | ||
750 | const struct wm_adsp_alg_region *alg_region, | ||
751 | unsigned int offset, unsigned int len, | ||
752 | const char *subname, unsigned int subname_len, | ||
753 | unsigned int flags) | ||
754 | { | ||
755 | struct wm_coeff_ctl *ctl; | ||
756 | struct wmfw_ctl_work *ctl_work; | ||
757 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
758 | char *region_name; | ||
759 | int ret; | ||
760 | |||
761 | if (flags & WMFW_CTL_FLAG_SYS) | ||
762 | return 0; | ||
763 | |||
764 | switch (alg_region->type) { | ||
765 | case WMFW_ADSP1_PM: | ||
766 | region_name = "PM"; | ||
767 | break; | ||
768 | case WMFW_ADSP1_DM: | ||
769 | region_name = "DM"; | ||
770 | break; | ||
771 | case WMFW_ADSP2_XM: | ||
772 | region_name = "XM"; | ||
773 | break; | ||
774 | case WMFW_ADSP2_YM: | ||
775 | region_name = "YM"; | ||
776 | break; | ||
777 | case WMFW_ADSP1_ZM: | ||
778 | region_name = "ZM"; | ||
779 | break; | ||
780 | default: | ||
781 | adsp_err(dsp, "Unknown region type: %d\n", alg_region->type); | ||
782 | return -EINVAL; | ||
783 | } | ||
784 | |||
785 | switch (dsp->fw_ver) { | ||
786 | case 0: | ||
787 | case 1: | ||
788 | snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x", | ||
789 | dsp->num, region_name, alg_region->alg); | ||
790 | break; | ||
791 | default: | ||
792 | ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, | ||
793 | "DSP%d%c %.12s %x", dsp->num, *region_name, | ||
794 | wm_adsp_fw_text[dsp->fw], alg_region->alg); | ||
795 | |||
796 | /* Truncate the subname from the start if it is too long */ | ||
797 | if (subname) { | ||
798 | int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; | ||
799 | int skip = 0; | ||
800 | |||
801 | if (subname_len > avail) | ||
802 | skip = subname_len - avail; | ||
803 | |||
804 | snprintf(name + ret, | ||
805 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s", | ||
806 | subname_len - skip, subname + skip); | ||
807 | } | ||
808 | break; | ||
809 | } | ||
810 | |||
811 | list_for_each_entry(ctl, &dsp->ctl_list, | ||
812 | list) { | ||
813 | if (!strcmp(ctl->name, name)) { | ||
814 | if (!ctl->enabled) | ||
815 | ctl->enabled = 1; | ||
816 | return 0; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); | ||
821 | if (!ctl) | ||
822 | return -ENOMEM; | ||
823 | ctl->fw_name = wm_adsp_fw_text[dsp->fw]; | ||
824 | ctl->alg_region = *alg_region; | ||
825 | ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); | ||
826 | if (!ctl->name) { | ||
827 | ret = -ENOMEM; | ||
828 | goto err_ctl; | ||
829 | } | ||
830 | ctl->enabled = 1; | ||
831 | ctl->set = 0; | ||
832 | ctl->ops.xget = wm_coeff_get; | ||
833 | ctl->ops.xput = wm_coeff_put; | ||
834 | ctl->dsp = dsp; | ||
835 | |||
836 | ctl->flags = flags; | ||
837 | ctl->offset = offset; | ||
838 | if (len > 512) { | ||
839 | adsp_warn(dsp, "Truncating control %s from %d\n", | ||
840 | ctl->name, len); | ||
841 | len = 512; | ||
842 | } | ||
843 | ctl->len = len; | ||
844 | ctl->cache = kzalloc(ctl->len, GFP_KERNEL); | ||
845 | if (!ctl->cache) { | ||
846 | ret = -ENOMEM; | ||
847 | goto err_ctl_name; | ||
848 | } | ||
849 | |||
850 | list_add(&ctl->list, &dsp->ctl_list); | ||
851 | |||
852 | ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); | ||
853 | if (!ctl_work) { | ||
854 | ret = -ENOMEM; | ||
855 | goto err_ctl_cache; | ||
856 | } | ||
857 | |||
858 | ctl_work->dsp = dsp; | ||
859 | ctl_work->ctl = ctl; | ||
860 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); | ||
861 | schedule_work(&ctl_work->work); | ||
862 | |||
863 | return 0; | ||
864 | |||
865 | err_ctl_cache: | ||
866 | kfree(ctl->cache); | ||
867 | err_ctl_name: | ||
868 | kfree(ctl->name); | ||
869 | err_ctl: | ||
870 | kfree(ctl); | ||
871 | |||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | struct wm_coeff_parsed_alg { | ||
876 | int id; | ||
877 | const u8 *name; | ||
878 | int name_len; | ||
879 | int ncoeff; | ||
880 | }; | ||
881 | |||
882 | struct wm_coeff_parsed_coeff { | ||
883 | int offset; | ||
884 | int mem_type; | ||
885 | const u8 *name; | ||
886 | int name_len; | ||
887 | int ctl_type; | ||
888 | int flags; | ||
889 | int len; | ||
890 | }; | ||
891 | |||
892 | static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str) | ||
893 | { | ||
894 | int length; | ||
895 | |||
896 | switch (bytes) { | ||
897 | case 1: | ||
898 | length = **pos; | ||
899 | break; | ||
900 | case 2: | ||
901 | length = le16_to_cpu(*((__le16 *)*pos)); | ||
902 | break; | ||
903 | default: | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | if (str) | ||
908 | *str = *pos + bytes; | ||
909 | |||
910 | *pos += ((length + bytes) + 3) & ~0x03; | ||
911 | |||
912 | return length; | ||
913 | } | ||
914 | |||
915 | static int wm_coeff_parse_int(int bytes, const u8 **pos) | ||
916 | { | ||
917 | int val = 0; | ||
918 | |||
919 | switch (bytes) { | ||
920 | case 2: | ||
921 | val = le16_to_cpu(*((__le16 *)*pos)); | ||
922 | break; | ||
923 | case 4: | ||
924 | val = le32_to_cpu(*((__le32 *)*pos)); | ||
925 | break; | ||
926 | default: | ||
927 | break; | ||
928 | } | ||
929 | |||
930 | *pos += bytes; | ||
931 | |||
932 | return val; | ||
933 | } | ||
934 | |||
935 | static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data, | ||
936 | struct wm_coeff_parsed_alg *blk) | ||
937 | { | ||
938 | const struct wmfw_adsp_alg_data *raw; | ||
939 | |||
940 | switch (dsp->fw_ver) { | ||
941 | case 0: | ||
942 | case 1: | ||
943 | raw = (const struct wmfw_adsp_alg_data *)*data; | ||
944 | *data = raw->data; | ||
945 | |||
946 | blk->id = le32_to_cpu(raw->id); | ||
947 | blk->name = raw->name; | ||
948 | blk->name_len = strlen(raw->name); | ||
949 | blk->ncoeff = le32_to_cpu(raw->ncoeff); | ||
950 | break; | ||
951 | default: | ||
952 | blk->id = wm_coeff_parse_int(sizeof(raw->id), data); | ||
953 | blk->name_len = wm_coeff_parse_string(sizeof(u8), data, | ||
954 | &blk->name); | ||
955 | wm_coeff_parse_string(sizeof(u16), data, NULL); | ||
956 | blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data); | ||
957 | break; | ||
958 | } | ||
959 | |||
960 | adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); | ||
961 | adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); | ||
962 | adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff); | ||
963 | } | ||
964 | |||
965 | static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, | ||
966 | struct wm_coeff_parsed_coeff *blk) | ||
967 | { | ||
968 | const struct wmfw_adsp_coeff_data *raw; | ||
969 | const u8 *tmp; | ||
970 | int length; | ||
971 | |||
972 | switch (dsp->fw_ver) { | ||
973 | case 0: | ||
974 | case 1: | ||
975 | raw = (const struct wmfw_adsp_coeff_data *)*data; | ||
976 | *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); | ||
977 | |||
978 | blk->offset = le16_to_cpu(raw->hdr.offset); | ||
979 | blk->mem_type = le16_to_cpu(raw->hdr.type); | ||
980 | blk->name = raw->name; | ||
981 | blk->name_len = strlen(raw->name); | ||
982 | blk->ctl_type = le16_to_cpu(raw->ctl_type); | ||
983 | blk->flags = le16_to_cpu(raw->flags); | ||
984 | blk->len = le32_to_cpu(raw->len); | ||
985 | break; | ||
986 | default: | ||
987 | tmp = *data; | ||
988 | blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp); | ||
989 | blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp); | ||
990 | length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp); | ||
991 | blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp, | ||
992 | &blk->name); | ||
993 | wm_coeff_parse_string(sizeof(u8), &tmp, NULL); | ||
994 | wm_coeff_parse_string(sizeof(u16), &tmp, NULL); | ||
995 | blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); | ||
996 | blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); | ||
997 | blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); | ||
998 | |||
999 | *data = *data + sizeof(raw->hdr) + length; | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); | ||
1004 | adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); | ||
1005 | adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name); | ||
1006 | adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags); | ||
1007 | adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type); | ||
1008 | adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len); | ||
1009 | } | ||
1010 | |||
1011 | static int wm_adsp_parse_coeff(struct wm_adsp *dsp, | ||
1012 | const struct wmfw_region *region) | ||
1013 | { | ||
1014 | struct wm_adsp_alg_region alg_region = {}; | ||
1015 | struct wm_coeff_parsed_alg alg_blk; | ||
1016 | struct wm_coeff_parsed_coeff coeff_blk; | ||
1017 | const u8 *data = region->data; | ||
1018 | int i, ret; | ||
1019 | |||
1020 | wm_coeff_parse_alg(dsp, &data, &alg_blk); | ||
1021 | for (i = 0; i < alg_blk.ncoeff; i++) { | ||
1022 | wm_coeff_parse_coeff(dsp, &data, &coeff_blk); | ||
1023 | |||
1024 | switch (coeff_blk.ctl_type) { | ||
1025 | case SNDRV_CTL_ELEM_TYPE_BYTES: | ||
1026 | break; | ||
1027 | default: | ||
1028 | adsp_err(dsp, "Unknown control type: %d\n", | ||
1029 | coeff_blk.ctl_type); | ||
1030 | return -EINVAL; | ||
1031 | } | ||
1032 | |||
1033 | alg_region.type = coeff_blk.mem_type; | ||
1034 | alg_region.alg = alg_blk.id; | ||
1035 | |||
1036 | ret = wm_adsp_create_control(dsp, &alg_region, | ||
1037 | coeff_blk.offset, | ||
1038 | coeff_blk.len, | ||
1039 | coeff_blk.name, | ||
1040 | coeff_blk.name_len, | ||
1041 | coeff_blk.flags); | ||
1042 | if (ret < 0) | ||
1043 | adsp_err(dsp, "Failed to create control: %.*s, %d\n", | ||
1044 | coeff_blk.name_len, coeff_blk.name, ret); | ||
1045 | } | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
523 | static int wm_adsp_load(struct wm_adsp *dsp) | 1050 | static int wm_adsp_load(struct wm_adsp *dsp) |
524 | { | 1051 | { |
525 | LIST_HEAD(buf_list); | 1052 | LIST_HEAD(buf_list); |
@@ -568,12 +1095,22 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
568 | goto out_fw; | 1095 | goto out_fw; |
569 | } | 1096 | } |
570 | 1097 | ||
571 | if (header->ver != 0) { | 1098 | switch (header->ver) { |
1099 | case 0: | ||
1100 | adsp_warn(dsp, "%s: Depreciated file format %d\n", | ||
1101 | file, header->ver); | ||
1102 | break; | ||
1103 | case 1: | ||
1104 | case 2: | ||
1105 | break; | ||
1106 | default: | ||
572 | adsp_err(dsp, "%s: unknown file format %d\n", | 1107 | adsp_err(dsp, "%s: unknown file format %d\n", |
573 | file, header->ver); | 1108 | file, header->ver); |
574 | goto out_fw; | 1109 | goto out_fw; |
575 | } | 1110 | } |
1111 | |||
576 | adsp_info(dsp, "Firmware version: %d\n", header->ver); | 1112 | adsp_info(dsp, "Firmware version: %d\n", header->ver); |
1113 | dsp->fw_ver = header->ver; | ||
577 | 1114 | ||
578 | if (header->core != dsp->type) { | 1115 | if (header->core != dsp->type) { |
579 | adsp_err(dsp, "%s: invalid core %d != %d\n", | 1116 | adsp_err(dsp, "%s: invalid core %d != %d\n", |
@@ -638,6 +1175,12 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
638 | text = kzalloc(le32_to_cpu(region->len) + 1, | 1175 | text = kzalloc(le32_to_cpu(region->len) + 1, |
639 | GFP_KERNEL); | 1176 | GFP_KERNEL); |
640 | break; | 1177 | break; |
1178 | case WMFW_ALGORITHM_DATA: | ||
1179 | region_name = "Algorithm"; | ||
1180 | ret = wm_adsp_parse_coeff(dsp, region); | ||
1181 | if (ret != 0) | ||
1182 | goto out_fw; | ||
1183 | break; | ||
641 | case WMFW_INFO_TEXT: | 1184 | case WMFW_INFO_TEXT: |
642 | region_name = "Information"; | 1185 | region_name = "Information"; |
643 | text = kzalloc(le32_to_cpu(region->len) + 1, | 1186 | text = kzalloc(le32_to_cpu(region->len) + 1, |
@@ -720,6 +1263,8 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
720 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", | 1263 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", |
721 | file, regions, pos - firmware->size); | 1264 | file, regions, pos - firmware->size); |
722 | 1265 | ||
1266 | wm_adsp_debugfs_save_wmfwname(dsp, file); | ||
1267 | |||
723 | out_fw: | 1268 | out_fw: |
724 | regmap_async_complete(regmap); | 1269 | regmap_async_complete(regmap); |
725 | wm_adsp_buf_free(&buf_list); | 1270 | wm_adsp_buf_free(&buf_list); |
@@ -730,444 +1275,317 @@ out: | |||
730 | return ret; | 1275 | return ret; |
731 | } | 1276 | } |
732 | 1277 | ||
733 | static int wm_coeff_init_control_caches(struct wm_adsp *adsp) | 1278 | static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp, |
1279 | const struct wm_adsp_alg_region *alg_region) | ||
734 | { | 1280 | { |
735 | struct wm_coeff_ctl *ctl; | 1281 | struct wm_coeff_ctl *ctl; |
736 | int ret; | ||
737 | 1282 | ||
738 | list_for_each_entry(ctl, &adsp->ctl_list, list) { | 1283 | list_for_each_entry(ctl, &dsp->ctl_list, list) { |
739 | if (!ctl->enabled || ctl->set) | 1284 | if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] && |
740 | continue; | 1285 | alg_region->alg == ctl->alg_region.alg && |
741 | ret = wm_coeff_read_control(ctl->kcontrol, | 1286 | alg_region->type == ctl->alg_region.type) { |
742 | ctl->cache, | 1287 | ctl->alg_region.base = alg_region->base; |
743 | ctl->len); | 1288 | } |
744 | if (ret < 0) | ||
745 | return ret; | ||
746 | } | 1289 | } |
747 | |||
748 | return 0; | ||
749 | } | 1290 | } |
750 | 1291 | ||
751 | static int wm_coeff_sync_controls(struct wm_adsp *adsp) | 1292 | static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, |
1293 | unsigned int pos, unsigned int len) | ||
752 | { | 1294 | { |
753 | struct wm_coeff_ctl *ctl; | 1295 | void *alg; |
754 | int ret; | 1296 | int ret; |
1297 | __be32 val; | ||
755 | 1298 | ||
756 | list_for_each_entry(ctl, &adsp->ctl_list, list) { | 1299 | if (n_algs == 0) { |
757 | if (!ctl->enabled) | 1300 | adsp_err(dsp, "No algorithms\n"); |
758 | continue; | 1301 | return ERR_PTR(-EINVAL); |
759 | if (ctl->set) { | ||
760 | ret = wm_coeff_write_control(ctl->kcontrol, | ||
761 | ctl->cache, | ||
762 | ctl->len); | ||
763 | if (ret < 0) | ||
764 | return ret; | ||
765 | } | ||
766 | } | 1302 | } |
767 | 1303 | ||
768 | return 0; | 1304 | if (n_algs > 1024) { |
769 | } | 1305 | adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs); |
770 | 1306 | return ERR_PTR(-EINVAL); | |
771 | static void wm_adsp_ctl_work(struct work_struct *work) | 1307 | } |
772 | { | ||
773 | struct wmfw_ctl_work *ctl_work = container_of(work, | ||
774 | struct wmfw_ctl_work, | ||
775 | work); | ||
776 | |||
777 | wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl); | ||
778 | kfree(ctl_work); | ||
779 | } | ||
780 | |||
781 | static int wm_adsp_create_control(struct wm_adsp *dsp, | ||
782 | const struct wm_adsp_alg_region *region) | ||
783 | |||
784 | { | ||
785 | struct wm_coeff_ctl *ctl; | ||
786 | struct wmfw_ctl_work *ctl_work; | ||
787 | char *name; | ||
788 | char *region_name; | ||
789 | int ret; | ||
790 | |||
791 | name = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
792 | if (!name) | ||
793 | return -ENOMEM; | ||
794 | 1308 | ||
795 | switch (region->type) { | 1309 | /* Read the terminator first to validate the length */ |
796 | case WMFW_ADSP1_PM: | 1310 | ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val)); |
797 | region_name = "PM"; | 1311 | if (ret != 0) { |
798 | break; | 1312 | adsp_err(dsp, "Failed to read algorithm list end: %d\n", |
799 | case WMFW_ADSP1_DM: | 1313 | ret); |
800 | region_name = "DM"; | 1314 | return ERR_PTR(ret); |
801 | break; | ||
802 | case WMFW_ADSP2_XM: | ||
803 | region_name = "XM"; | ||
804 | break; | ||
805 | case WMFW_ADSP2_YM: | ||
806 | region_name = "YM"; | ||
807 | break; | ||
808 | case WMFW_ADSP1_ZM: | ||
809 | region_name = "ZM"; | ||
810 | break; | ||
811 | default: | ||
812 | ret = -EINVAL; | ||
813 | goto err_name; | ||
814 | } | 1315 | } |
815 | 1316 | ||
816 | snprintf(name, PAGE_SIZE, "DSP%d %s %x", | 1317 | if (be32_to_cpu(val) != 0xbedead) |
817 | dsp->num, region_name, region->alg); | 1318 | adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", |
1319 | pos + len, be32_to_cpu(val)); | ||
818 | 1320 | ||
819 | list_for_each_entry(ctl, &dsp->ctl_list, | 1321 | alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA); |
820 | list) { | 1322 | if (!alg) |
821 | if (!strcmp(ctl->name, name)) { | 1323 | return ERR_PTR(-ENOMEM); |
822 | if (!ctl->enabled) | ||
823 | ctl->enabled = 1; | ||
824 | goto found; | ||
825 | } | ||
826 | } | ||
827 | 1324 | ||
828 | ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); | 1325 | ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2); |
829 | if (!ctl) { | 1326 | if (ret != 0) { |
830 | ret = -ENOMEM; | 1327 | adsp_err(dsp, "Failed to read algorithm list: %d\n", |
831 | goto err_name; | 1328 | ret); |
832 | } | 1329 | kfree(alg); |
833 | ctl->region = *region; | 1330 | return ERR_PTR(ret); |
834 | ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); | ||
835 | if (!ctl->name) { | ||
836 | ret = -ENOMEM; | ||
837 | goto err_ctl; | ||
838 | } | 1331 | } |
839 | ctl->enabled = 1; | ||
840 | ctl->set = 0; | ||
841 | ctl->ops.xget = wm_coeff_get; | ||
842 | ctl->ops.xput = wm_coeff_put; | ||
843 | ctl->adsp = dsp; | ||
844 | 1332 | ||
845 | ctl->len = region->len; | 1333 | return alg; |
846 | ctl->cache = kzalloc(ctl->len, GFP_KERNEL); | 1334 | } |
847 | if (!ctl->cache) { | ||
848 | ret = -ENOMEM; | ||
849 | goto err_ctl_name; | ||
850 | } | ||
851 | 1335 | ||
852 | ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); | 1336 | static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp, |
853 | if (!ctl_work) { | 1337 | int type, __be32 id, |
854 | ret = -ENOMEM; | 1338 | __be32 base) |
855 | goto err_ctl_cache; | 1339 | { |
856 | } | 1340 | struct wm_adsp_alg_region *alg_region; |
857 | 1341 | ||
858 | ctl_work->adsp = dsp; | 1342 | alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL); |
859 | ctl_work->ctl = ctl; | 1343 | if (!alg_region) |
860 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); | 1344 | return ERR_PTR(-ENOMEM); |
861 | schedule_work(&ctl_work->work); | ||
862 | 1345 | ||
863 | found: | 1346 | alg_region->type = type; |
864 | kfree(name); | 1347 | alg_region->alg = be32_to_cpu(id); |
1348 | alg_region->base = be32_to_cpu(base); | ||
865 | 1349 | ||
866 | return 0; | 1350 | list_add_tail(&alg_region->list, &dsp->alg_regions); |
867 | 1351 | ||
868 | err_ctl_cache: | 1352 | if (dsp->fw_ver > 0) |
869 | kfree(ctl->cache); | 1353 | wm_adsp_ctl_fixup_base(dsp, alg_region); |
870 | err_ctl_name: | 1354 | |
871 | kfree(ctl->name); | 1355 | return alg_region; |
872 | err_ctl: | ||
873 | kfree(ctl); | ||
874 | err_name: | ||
875 | kfree(name); | ||
876 | return ret; | ||
877 | } | 1356 | } |
878 | 1357 | ||
879 | static int wm_adsp_setup_algs(struct wm_adsp *dsp) | 1358 | static int wm_adsp1_setup_algs(struct wm_adsp *dsp) |
880 | { | 1359 | { |
881 | struct regmap *regmap = dsp->regmap; | ||
882 | struct wmfw_adsp1_id_hdr adsp1_id; | 1360 | struct wmfw_adsp1_id_hdr adsp1_id; |
883 | struct wmfw_adsp2_id_hdr adsp2_id; | ||
884 | struct wmfw_adsp1_alg_hdr *adsp1_alg; | 1361 | struct wmfw_adsp1_alg_hdr *adsp1_alg; |
885 | struct wmfw_adsp2_alg_hdr *adsp2_alg; | 1362 | struct wm_adsp_alg_region *alg_region; |
886 | void *alg, *buf; | ||
887 | struct wm_adsp_alg_region *region; | ||
888 | const struct wm_adsp_region *mem; | 1363 | const struct wm_adsp_region *mem; |
889 | unsigned int pos, term; | 1364 | unsigned int pos, len; |
890 | size_t algs, buf_size; | 1365 | size_t n_algs; |
891 | __be32 val; | ||
892 | int i, ret; | 1366 | int i, ret; |
893 | 1367 | ||
894 | switch (dsp->type) { | 1368 | mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); |
895 | case WMFW_ADSP1: | ||
896 | mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM); | ||
897 | break; | ||
898 | case WMFW_ADSP2: | ||
899 | mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); | ||
900 | break; | ||
901 | default: | ||
902 | mem = NULL; | ||
903 | break; | ||
904 | } | ||
905 | |||
906 | if (WARN_ON(!mem)) | 1369 | if (WARN_ON(!mem)) |
907 | return -EINVAL; | 1370 | return -EINVAL; |
908 | 1371 | ||
909 | switch (dsp->type) { | 1372 | ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id, |
910 | case WMFW_ADSP1: | 1373 | sizeof(adsp1_id)); |
911 | ret = regmap_raw_read(regmap, mem->base, &adsp1_id, | ||
912 | sizeof(adsp1_id)); | ||
913 | if (ret != 0) { | ||
914 | adsp_err(dsp, "Failed to read algorithm info: %d\n", | ||
915 | ret); | ||
916 | return ret; | ||
917 | } | ||
918 | |||
919 | buf = &adsp1_id; | ||
920 | buf_size = sizeof(adsp1_id); | ||
921 | |||
922 | algs = be32_to_cpu(adsp1_id.algs); | ||
923 | dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); | ||
924 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", | ||
925 | dsp->fw_id, | ||
926 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, | ||
927 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, | ||
928 | be32_to_cpu(adsp1_id.fw.ver) & 0xff, | ||
929 | algs); | ||
930 | |||
931 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
932 | if (!region) | ||
933 | return -ENOMEM; | ||
934 | region->type = WMFW_ADSP1_ZM; | ||
935 | region->alg = be32_to_cpu(adsp1_id.fw.id); | ||
936 | region->base = be32_to_cpu(adsp1_id.zm); | ||
937 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
938 | |||
939 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
940 | if (!region) | ||
941 | return -ENOMEM; | ||
942 | region->type = WMFW_ADSP1_DM; | ||
943 | region->alg = be32_to_cpu(adsp1_id.fw.id); | ||
944 | region->base = be32_to_cpu(adsp1_id.dm); | ||
945 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
946 | |||
947 | pos = sizeof(adsp1_id) / 2; | ||
948 | term = pos + ((sizeof(*adsp1_alg) * algs) / 2); | ||
949 | break; | ||
950 | |||
951 | case WMFW_ADSP2: | ||
952 | ret = regmap_raw_read(regmap, mem->base, &adsp2_id, | ||
953 | sizeof(adsp2_id)); | ||
954 | if (ret != 0) { | ||
955 | adsp_err(dsp, "Failed to read algorithm info: %d\n", | ||
956 | ret); | ||
957 | return ret; | ||
958 | } | ||
959 | |||
960 | buf = &adsp2_id; | ||
961 | buf_size = sizeof(adsp2_id); | ||
962 | |||
963 | algs = be32_to_cpu(adsp2_id.algs); | ||
964 | dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); | ||
965 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", | ||
966 | dsp->fw_id, | ||
967 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, | ||
968 | (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, | ||
969 | be32_to_cpu(adsp2_id.fw.ver) & 0xff, | ||
970 | algs); | ||
971 | |||
972 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
973 | if (!region) | ||
974 | return -ENOMEM; | ||
975 | region->type = WMFW_ADSP2_XM; | ||
976 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
977 | region->base = be32_to_cpu(adsp2_id.xm); | ||
978 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
979 | |||
980 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
981 | if (!region) | ||
982 | return -ENOMEM; | ||
983 | region->type = WMFW_ADSP2_YM; | ||
984 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
985 | region->base = be32_to_cpu(adsp2_id.ym); | ||
986 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
987 | |||
988 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
989 | if (!region) | ||
990 | return -ENOMEM; | ||
991 | region->type = WMFW_ADSP2_ZM; | ||
992 | region->alg = be32_to_cpu(adsp2_id.fw.id); | ||
993 | region->base = be32_to_cpu(adsp2_id.zm); | ||
994 | list_add_tail(®ion->list, &dsp->alg_regions); | ||
995 | |||
996 | pos = sizeof(adsp2_id) / 2; | ||
997 | term = pos + ((sizeof(*adsp2_alg) * algs) / 2); | ||
998 | break; | ||
999 | |||
1000 | default: | ||
1001 | WARN(1, "Unknown DSP type"); | ||
1002 | return -EINVAL; | ||
1003 | } | ||
1004 | |||
1005 | if (algs == 0) { | ||
1006 | adsp_err(dsp, "No algorithms\n"); | ||
1007 | return -EINVAL; | ||
1008 | } | ||
1009 | |||
1010 | if (algs > 1024) { | ||
1011 | adsp_err(dsp, "Algorithm count %zx excessive\n", algs); | ||
1012 | print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET, | ||
1013 | buf, buf_size); | ||
1014 | return -EINVAL; | ||
1015 | } | ||
1016 | |||
1017 | /* Read the terminator first to validate the length */ | ||
1018 | ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val)); | ||
1019 | if (ret != 0) { | 1374 | if (ret != 0) { |
1020 | adsp_err(dsp, "Failed to read algorithm list end: %d\n", | 1375 | adsp_err(dsp, "Failed to read algorithm info: %d\n", |
1021 | ret); | 1376 | ret); |
1022 | return ret; | 1377 | return ret; |
1023 | } | 1378 | } |
1024 | 1379 | ||
1025 | if (be32_to_cpu(val) != 0xbedead) | 1380 | n_algs = be32_to_cpu(adsp1_id.n_algs); |
1026 | adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", | 1381 | dsp->fw_id = be32_to_cpu(adsp1_id.fw.id); |
1027 | term, be32_to_cpu(val)); | 1382 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", |
1028 | 1383 | dsp->fw_id, | |
1029 | alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA); | 1384 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, |
1030 | if (!alg) | 1385 | (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, |
1031 | return -ENOMEM; | 1386 | be32_to_cpu(adsp1_id.fw.ver) & 0xff, |
1032 | 1387 | n_algs); | |
1033 | ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2); | 1388 | |
1034 | if (ret != 0) { | 1389 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, |
1035 | adsp_err(dsp, "Failed to read algorithm list: %d\n", | 1390 | adsp1_id.fw.id, adsp1_id.zm); |
1036 | ret); | 1391 | if (IS_ERR(alg_region)) |
1037 | goto out; | 1392 | return PTR_ERR(alg_region); |
1038 | } | 1393 | |
1039 | 1394 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, | |
1040 | adsp1_alg = alg; | 1395 | adsp1_id.fw.id, adsp1_id.dm); |
1041 | adsp2_alg = alg; | 1396 | if (IS_ERR(alg_region)) |
1042 | 1397 | return PTR_ERR(alg_region); | |
1043 | for (i = 0; i < algs; i++) { | 1398 | |
1044 | switch (dsp->type) { | 1399 | pos = sizeof(adsp1_id) / 2; |
1045 | case WMFW_ADSP1: | 1400 | len = (sizeof(*adsp1_alg) * n_algs) / 2; |
1046 | adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", | 1401 | |
1047 | i, be32_to_cpu(adsp1_alg[i].alg.id), | 1402 | adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); |
1048 | (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, | 1403 | if (IS_ERR(adsp1_alg)) |
1049 | (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, | 1404 | return PTR_ERR(adsp1_alg); |
1050 | be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, | 1405 | |
1051 | be32_to_cpu(adsp1_alg[i].dm), | 1406 | for (i = 0; i < n_algs; i++) { |
1052 | be32_to_cpu(adsp1_alg[i].zm)); | 1407 | adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n", |
1053 | 1408 | i, be32_to_cpu(adsp1_alg[i].alg.id), | |
1054 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1409 | (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, |
1055 | if (!region) { | 1410 | (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, |
1056 | ret = -ENOMEM; | 1411 | be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff, |
1057 | goto out; | 1412 | be32_to_cpu(adsp1_alg[i].dm), |
1058 | } | 1413 | be32_to_cpu(adsp1_alg[i].zm)); |
1059 | region->type = WMFW_ADSP1_DM; | 1414 | |
1060 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1415 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM, |
1061 | region->base = be32_to_cpu(adsp1_alg[i].dm); | 1416 | adsp1_alg[i].alg.id, |
1062 | region->len = 0; | 1417 | adsp1_alg[i].dm); |
1063 | list_add_tail(®ion->list, &dsp->alg_regions); | 1418 | if (IS_ERR(alg_region)) { |
1064 | if (i + 1 < algs) { | 1419 | ret = PTR_ERR(alg_region); |
1065 | region->len = be32_to_cpu(adsp1_alg[i + 1].dm); | 1420 | goto out; |
1066 | region->len -= be32_to_cpu(adsp1_alg[i].dm); | 1421 | } |
1067 | region->len *= 4; | 1422 | if (dsp->fw_ver == 0) { |
1068 | wm_adsp_create_control(dsp, region); | 1423 | if (i + 1 < n_algs) { |
1424 | len = be32_to_cpu(adsp1_alg[i + 1].dm); | ||
1425 | len -= be32_to_cpu(adsp1_alg[i].dm); | ||
1426 | len *= 4; | ||
1427 | wm_adsp_create_control(dsp, alg_region, 0, | ||
1428 | len, NULL, 0, 0); | ||
1069 | } else { | 1429 | } else { |
1070 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", | 1430 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", |
1071 | be32_to_cpu(adsp1_alg[i].alg.id)); | 1431 | be32_to_cpu(adsp1_alg[i].alg.id)); |
1072 | } | 1432 | } |
1433 | } | ||
1073 | 1434 | ||
1074 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1435 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM, |
1075 | if (!region) { | 1436 | adsp1_alg[i].alg.id, |
1076 | ret = -ENOMEM; | 1437 | adsp1_alg[i].zm); |
1077 | goto out; | 1438 | if (IS_ERR(alg_region)) { |
1078 | } | 1439 | ret = PTR_ERR(alg_region); |
1079 | region->type = WMFW_ADSP1_ZM; | 1440 | goto out; |
1080 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1441 | } |
1081 | region->base = be32_to_cpu(adsp1_alg[i].zm); | 1442 | if (dsp->fw_ver == 0) { |
1082 | region->len = 0; | 1443 | if (i + 1 < n_algs) { |
1083 | list_add_tail(®ion->list, &dsp->alg_regions); | 1444 | len = be32_to_cpu(adsp1_alg[i + 1].zm); |
1084 | if (i + 1 < algs) { | 1445 | len -= be32_to_cpu(adsp1_alg[i].zm); |
1085 | region->len = be32_to_cpu(adsp1_alg[i + 1].zm); | 1446 | len *= 4; |
1086 | region->len -= be32_to_cpu(adsp1_alg[i].zm); | 1447 | wm_adsp_create_control(dsp, alg_region, 0, |
1087 | region->len *= 4; | 1448 | len, NULL, 0, 0); |
1088 | wm_adsp_create_control(dsp, region); | ||
1089 | } else { | 1449 | } else { |
1090 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | 1450 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", |
1091 | be32_to_cpu(adsp1_alg[i].alg.id)); | 1451 | be32_to_cpu(adsp1_alg[i].alg.id)); |
1092 | } | 1452 | } |
1093 | break; | 1453 | } |
1454 | } | ||
1094 | 1455 | ||
1095 | case WMFW_ADSP2: | 1456 | out: |
1096 | adsp_info(dsp, | 1457 | kfree(adsp1_alg); |
1097 | "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", | 1458 | return ret; |
1098 | i, be32_to_cpu(adsp2_alg[i].alg.id), | 1459 | } |
1099 | (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, | 1460 | |
1100 | (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, | 1461 | static int wm_adsp2_setup_algs(struct wm_adsp *dsp) |
1101 | be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, | 1462 | { |
1102 | be32_to_cpu(adsp2_alg[i].xm), | 1463 | struct wmfw_adsp2_id_hdr adsp2_id; |
1103 | be32_to_cpu(adsp2_alg[i].ym), | 1464 | struct wmfw_adsp2_alg_hdr *adsp2_alg; |
1104 | be32_to_cpu(adsp2_alg[i].zm)); | 1465 | struct wm_adsp_alg_region *alg_region; |
1105 | 1466 | const struct wm_adsp_region *mem; | |
1106 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1467 | unsigned int pos, len; |
1107 | if (!region) { | 1468 | size_t n_algs; |
1108 | ret = -ENOMEM; | 1469 | int i, ret; |
1109 | goto out; | 1470 | |
1110 | } | 1471 | mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM); |
1111 | region->type = WMFW_ADSP2_XM; | 1472 | if (WARN_ON(!mem)) |
1112 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1473 | return -EINVAL; |
1113 | region->base = be32_to_cpu(adsp2_alg[i].xm); | 1474 | |
1114 | region->len = 0; | 1475 | ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id, |
1115 | list_add_tail(®ion->list, &dsp->alg_regions); | 1476 | sizeof(adsp2_id)); |
1116 | if (i + 1 < algs) { | 1477 | if (ret != 0) { |
1117 | region->len = be32_to_cpu(adsp2_alg[i + 1].xm); | 1478 | adsp_err(dsp, "Failed to read algorithm info: %d\n", |
1118 | region->len -= be32_to_cpu(adsp2_alg[i].xm); | 1479 | ret); |
1119 | region->len *= 4; | 1480 | return ret; |
1120 | wm_adsp_create_control(dsp, region); | 1481 | } |
1482 | |||
1483 | n_algs = be32_to_cpu(adsp2_id.n_algs); | ||
1484 | dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); | ||
1485 | dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); | ||
1486 | adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", | ||
1487 | dsp->fw_id, | ||
1488 | (dsp->fw_id_version & 0xff0000) >> 16, | ||
1489 | (dsp->fw_id_version & 0xff00) >> 8, | ||
1490 | dsp->fw_id_version & 0xff, | ||
1491 | n_algs); | ||
1492 | |||
1493 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, | ||
1494 | adsp2_id.fw.id, adsp2_id.xm); | ||
1495 | if (IS_ERR(alg_region)) | ||
1496 | return PTR_ERR(alg_region); | ||
1497 | |||
1498 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, | ||
1499 | adsp2_id.fw.id, adsp2_id.ym); | ||
1500 | if (IS_ERR(alg_region)) | ||
1501 | return PTR_ERR(alg_region); | ||
1502 | |||
1503 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, | ||
1504 | adsp2_id.fw.id, adsp2_id.zm); | ||
1505 | if (IS_ERR(alg_region)) | ||
1506 | return PTR_ERR(alg_region); | ||
1507 | |||
1508 | pos = sizeof(adsp2_id) / 2; | ||
1509 | len = (sizeof(*adsp2_alg) * n_algs) / 2; | ||
1510 | |||
1511 | adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len); | ||
1512 | if (IS_ERR(adsp2_alg)) | ||
1513 | return PTR_ERR(adsp2_alg); | ||
1514 | |||
1515 | for (i = 0; i < n_algs; i++) { | ||
1516 | adsp_info(dsp, | ||
1517 | "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", | ||
1518 | i, be32_to_cpu(adsp2_alg[i].alg.id), | ||
1519 | (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, | ||
1520 | (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, | ||
1521 | be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, | ||
1522 | be32_to_cpu(adsp2_alg[i].xm), | ||
1523 | be32_to_cpu(adsp2_alg[i].ym), | ||
1524 | be32_to_cpu(adsp2_alg[i].zm)); | ||
1525 | |||
1526 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, | ||
1527 | adsp2_alg[i].alg.id, | ||
1528 | adsp2_alg[i].xm); | ||
1529 | if (IS_ERR(alg_region)) { | ||
1530 | ret = PTR_ERR(alg_region); | ||
1531 | goto out; | ||
1532 | } | ||
1533 | if (dsp->fw_ver == 0) { | ||
1534 | if (i + 1 < n_algs) { | ||
1535 | len = be32_to_cpu(adsp2_alg[i + 1].xm); | ||
1536 | len -= be32_to_cpu(adsp2_alg[i].xm); | ||
1537 | len *= 4; | ||
1538 | wm_adsp_create_control(dsp, alg_region, 0, | ||
1539 | len, NULL, 0, 0); | ||
1121 | } else { | 1540 | } else { |
1122 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", | 1541 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", |
1123 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1542 | be32_to_cpu(adsp2_alg[i].alg.id)); |
1124 | } | 1543 | } |
1544 | } | ||
1125 | 1545 | ||
1126 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1546 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM, |
1127 | if (!region) { | 1547 | adsp2_alg[i].alg.id, |
1128 | ret = -ENOMEM; | 1548 | adsp2_alg[i].ym); |
1129 | goto out; | 1549 | if (IS_ERR(alg_region)) { |
1130 | } | 1550 | ret = PTR_ERR(alg_region); |
1131 | region->type = WMFW_ADSP2_YM; | 1551 | goto out; |
1132 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1552 | } |
1133 | region->base = be32_to_cpu(adsp2_alg[i].ym); | 1553 | if (dsp->fw_ver == 0) { |
1134 | region->len = 0; | 1554 | if (i + 1 < n_algs) { |
1135 | list_add_tail(®ion->list, &dsp->alg_regions); | 1555 | len = be32_to_cpu(adsp2_alg[i + 1].ym); |
1136 | if (i + 1 < algs) { | 1556 | len -= be32_to_cpu(adsp2_alg[i].ym); |
1137 | region->len = be32_to_cpu(adsp2_alg[i + 1].ym); | 1557 | len *= 4; |
1138 | region->len -= be32_to_cpu(adsp2_alg[i].ym); | 1558 | wm_adsp_create_control(dsp, alg_region, 0, |
1139 | region->len *= 4; | 1559 | len, NULL, 0, 0); |
1140 | wm_adsp_create_control(dsp, region); | ||
1141 | } else { | 1560 | } else { |
1142 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", | 1561 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", |
1143 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1562 | be32_to_cpu(adsp2_alg[i].alg.id)); |
1144 | } | 1563 | } |
1564 | } | ||
1145 | 1565 | ||
1146 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1566 | alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM, |
1147 | if (!region) { | 1567 | adsp2_alg[i].alg.id, |
1148 | ret = -ENOMEM; | 1568 | adsp2_alg[i].zm); |
1149 | goto out; | 1569 | if (IS_ERR(alg_region)) { |
1150 | } | 1570 | ret = PTR_ERR(alg_region); |
1151 | region->type = WMFW_ADSP2_ZM; | 1571 | goto out; |
1152 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1572 | } |
1153 | region->base = be32_to_cpu(adsp2_alg[i].zm); | 1573 | if (dsp->fw_ver == 0) { |
1154 | region->len = 0; | 1574 | if (i + 1 < n_algs) { |
1155 | list_add_tail(®ion->list, &dsp->alg_regions); | 1575 | len = be32_to_cpu(adsp2_alg[i + 1].zm); |
1156 | if (i + 1 < algs) { | 1576 | len -= be32_to_cpu(adsp2_alg[i].zm); |
1157 | region->len = be32_to_cpu(adsp2_alg[i + 1].zm); | 1577 | len *= 4; |
1158 | region->len -= be32_to_cpu(adsp2_alg[i].zm); | 1578 | wm_adsp_create_control(dsp, alg_region, 0, |
1159 | region->len *= 4; | 1579 | len, NULL, 0, 0); |
1160 | wm_adsp_create_control(dsp, region); | ||
1161 | } else { | 1580 | } else { |
1162 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | 1581 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", |
1163 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1582 | be32_to_cpu(adsp2_alg[i].alg.id)); |
1164 | } | 1583 | } |
1165 | break; | ||
1166 | } | 1584 | } |
1167 | } | 1585 | } |
1168 | 1586 | ||
1169 | out: | 1587 | out: |
1170 | kfree(alg); | 1588 | kfree(adsp2_alg); |
1171 | return ret; | 1589 | return ret; |
1172 | } | 1590 | } |
1173 | 1591 | ||
@@ -1345,6 +1763,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
1345 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", | 1763 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", |
1346 | file, blocks, pos - firmware->size); | 1764 | file, blocks, pos - firmware->size); |
1347 | 1765 | ||
1766 | wm_adsp_debugfs_save_binname(dsp, file); | ||
1767 | |||
1348 | out_fw: | 1768 | out_fw: |
1349 | regmap_async_complete(regmap); | 1769 | regmap_async_complete(regmap); |
1350 | release_firmware(firmware); | 1770 | release_firmware(firmware); |
@@ -1354,10 +1774,13 @@ out: | |||
1354 | return ret; | 1774 | return ret; |
1355 | } | 1775 | } |
1356 | 1776 | ||
1357 | int wm_adsp1_init(struct wm_adsp *adsp) | 1777 | int wm_adsp1_init(struct wm_adsp *dsp) |
1358 | { | 1778 | { |
1359 | INIT_LIST_HEAD(&adsp->alg_regions); | 1779 | INIT_LIST_HEAD(&dsp->alg_regions); |
1360 | 1780 | ||
1781 | #ifdef CONFIG_DEBUG_FS | ||
1782 | mutex_init(&dsp->debugfs_lock); | ||
1783 | #endif | ||
1361 | return 0; | 1784 | return 0; |
1362 | } | 1785 | } |
1363 | EXPORT_SYMBOL_GPL(wm_adsp1_init); | 1786 | EXPORT_SYMBOL_GPL(wm_adsp1_init); |
@@ -1410,7 +1833,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1410 | if (ret != 0) | 1833 | if (ret != 0) |
1411 | goto err; | 1834 | goto err; |
1412 | 1835 | ||
1413 | ret = wm_adsp_setup_algs(dsp); | 1836 | ret = wm_adsp1_setup_algs(dsp); |
1414 | if (ret != 0) | 1837 | if (ret != 0) |
1415 | goto err; | 1838 | goto err; |
1416 | 1839 | ||
@@ -1531,35 +1954,6 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
1531 | return; | 1954 | return; |
1532 | } | 1955 | } |
1533 | 1956 | ||
1534 | if (dsp->dvfs) { | ||
1535 | ret = regmap_read(dsp->regmap, | ||
1536 | dsp->base + ADSP2_CLOCKING, &val); | ||
1537 | if (ret != 0) { | ||
1538 | adsp_err(dsp, "Failed to read clocking: %d\n", ret); | ||
1539 | return; | ||
1540 | } | ||
1541 | |||
1542 | if ((val & ADSP2_CLK_SEL_MASK) >= 3) { | ||
1543 | ret = regulator_enable(dsp->dvfs); | ||
1544 | if (ret != 0) { | ||
1545 | adsp_err(dsp, | ||
1546 | "Failed to enable supply: %d\n", | ||
1547 | ret); | ||
1548 | return; | ||
1549 | } | ||
1550 | |||
1551 | ret = regulator_set_voltage(dsp->dvfs, | ||
1552 | 1800000, | ||
1553 | 1800000); | ||
1554 | if (ret != 0) { | ||
1555 | adsp_err(dsp, | ||
1556 | "Failed to raise supply: %d\n", | ||
1557 | ret); | ||
1558 | return; | ||
1559 | } | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1563 | ret = wm_adsp2_ena(dsp); | 1957 | ret = wm_adsp2_ena(dsp); |
1564 | if (ret != 0) | 1958 | if (ret != 0) |
1565 | return; | 1959 | return; |
@@ -1568,7 +1962,7 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
1568 | if (ret != 0) | 1962 | if (ret != 0) |
1569 | goto err; | 1963 | goto err; |
1570 | 1964 | ||
1571 | ret = wm_adsp_setup_algs(dsp); | 1965 | ret = wm_adsp2_setup_algs(dsp); |
1572 | if (ret != 0) | 1966 | if (ret != 0) |
1573 | goto err; | 1967 | goto err; |
1574 | 1968 | ||
@@ -1642,6 +2036,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1642 | break; | 2036 | break; |
1643 | 2037 | ||
1644 | case SND_SOC_DAPM_PRE_PMD: | 2038 | case SND_SOC_DAPM_PRE_PMD: |
2039 | /* Log firmware state, it can be useful for analysis */ | ||
2040 | wm_adsp2_show_fw_status(dsp); | ||
2041 | |||
2042 | wm_adsp_debugfs_clear(dsp); | ||
2043 | |||
2044 | dsp->fw_id = 0; | ||
2045 | dsp->fw_id_version = 0; | ||
1645 | dsp->running = false; | 2046 | dsp->running = false; |
1646 | 2047 | ||
1647 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | 2048 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, |
@@ -1653,21 +2054,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1653 | regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); | 2054 | regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); |
1654 | regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); | 2055 | regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); |
1655 | 2056 | ||
1656 | if (dsp->dvfs) { | ||
1657 | ret = regulator_set_voltage(dsp->dvfs, 1200000, | ||
1658 | 1800000); | ||
1659 | if (ret != 0) | ||
1660 | adsp_warn(dsp, | ||
1661 | "Failed to lower supply: %d\n", | ||
1662 | ret); | ||
1663 | |||
1664 | ret = regulator_disable(dsp->dvfs); | ||
1665 | if (ret != 0) | ||
1666 | adsp_err(dsp, | ||
1667 | "Failed to enable supply: %d\n", | ||
1668 | ret); | ||
1669 | } | ||
1670 | |||
1671 | list_for_each_entry(ctl, &dsp->ctl_list, list) | 2057 | list_for_each_entry(ctl, &dsp->ctl_list, list) |
1672 | ctl->enabled = 0; | 2058 | ctl->enabled = 0; |
1673 | 2059 | ||
@@ -1694,7 +2080,25 @@ err: | |||
1694 | } | 2080 | } |
1695 | EXPORT_SYMBOL_GPL(wm_adsp2_event); | 2081 | EXPORT_SYMBOL_GPL(wm_adsp2_event); |
1696 | 2082 | ||
1697 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | 2083 | int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) |
2084 | { | ||
2085 | wm_adsp2_init_debugfs(dsp, codec); | ||
2086 | |||
2087 | return snd_soc_add_codec_controls(codec, | ||
2088 | &wm_adsp_fw_controls[dsp->num - 1], | ||
2089 | 1); | ||
2090 | } | ||
2091 | EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe); | ||
2092 | |||
2093 | int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) | ||
2094 | { | ||
2095 | wm_adsp2_cleanup_debugfs(dsp); | ||
2096 | |||
2097 | return 0; | ||
2098 | } | ||
2099 | EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); | ||
2100 | |||
2101 | int wm_adsp2_init(struct wm_adsp *dsp) | ||
1698 | { | 2102 | { |
1699 | int ret; | 2103 | int ret; |
1700 | 2104 | ||
@@ -1702,44 +2106,20 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
1702 | * Disable the DSP memory by default when in reset for a small | 2106 | * Disable the DSP memory by default when in reset for a small |
1703 | * power saving. | 2107 | * power saving. |
1704 | */ | 2108 | */ |
1705 | ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL, | 2109 | ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, |
1706 | ADSP2_MEM_ENA, 0); | 2110 | ADSP2_MEM_ENA, 0); |
1707 | if (ret != 0) { | 2111 | if (ret != 0) { |
1708 | adsp_err(adsp, "Failed to clear memory retention: %d\n", ret); | 2112 | adsp_err(dsp, "Failed to clear memory retention: %d\n", ret); |
1709 | return ret; | 2113 | return ret; |
1710 | } | 2114 | } |
1711 | 2115 | ||
1712 | INIT_LIST_HEAD(&adsp->alg_regions); | 2116 | INIT_LIST_HEAD(&dsp->alg_regions); |
1713 | INIT_LIST_HEAD(&adsp->ctl_list); | 2117 | INIT_LIST_HEAD(&dsp->ctl_list); |
1714 | INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work); | 2118 | INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); |
1715 | |||
1716 | if (dvfs) { | ||
1717 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | ||
1718 | if (IS_ERR(adsp->dvfs)) { | ||
1719 | ret = PTR_ERR(adsp->dvfs); | ||
1720 | adsp_err(adsp, "Failed to get DCVDD: %d\n", ret); | ||
1721 | return ret; | ||
1722 | } | ||
1723 | |||
1724 | ret = regulator_enable(adsp->dvfs); | ||
1725 | if (ret != 0) { | ||
1726 | adsp_err(adsp, "Failed to enable DCVDD: %d\n", ret); | ||
1727 | return ret; | ||
1728 | } | ||
1729 | |||
1730 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); | ||
1731 | if (ret != 0) { | ||
1732 | adsp_err(adsp, "Failed to initialise DVFS: %d\n", ret); | ||
1733 | return ret; | ||
1734 | } | ||
1735 | |||
1736 | ret = regulator_disable(adsp->dvfs); | ||
1737 | if (ret != 0) { | ||
1738 | adsp_err(adsp, "Failed to disable DCVDD: %d\n", ret); | ||
1739 | return ret; | ||
1740 | } | ||
1741 | } | ||
1742 | 2119 | ||
2120 | #ifdef CONFIG_DEBUG_FS | ||
2121 | mutex_init(&dsp->debugfs_lock); | ||
2122 | #endif | ||
1743 | return 0; | 2123 | return 0; |
1744 | } | 2124 | } |
1745 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 2125 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index a4f6b64deb61..579a6350fb01 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -18,8 +18,6 @@ | |||
18 | 18 | ||
19 | #include "wmfw.h" | 19 | #include "wmfw.h" |
20 | 20 | ||
21 | struct regulator; | ||
22 | |||
23 | struct wm_adsp_region { | 21 | struct wm_adsp_region { |
24 | int type; | 22 | int type; |
25 | unsigned int base; | 23 | unsigned int base; |
@@ -30,7 +28,6 @@ struct wm_adsp_alg_region { | |||
30 | unsigned int alg; | 28 | unsigned int alg; |
31 | int type; | 29 | int type; |
32 | unsigned int base; | 30 | unsigned int base; |
33 | size_t len; | ||
34 | }; | 31 | }; |
35 | 32 | ||
36 | struct wm_adsp { | 33 | struct wm_adsp { |
@@ -49,37 +46,49 @@ struct wm_adsp { | |||
49 | struct list_head alg_regions; | 46 | struct list_head alg_regions; |
50 | 47 | ||
51 | int fw_id; | 48 | int fw_id; |
49 | int fw_id_version; | ||
52 | 50 | ||
53 | const struct wm_adsp_region *mem; | 51 | const struct wm_adsp_region *mem; |
54 | int num_mems; | 52 | int num_mems; |
55 | 53 | ||
56 | int fw; | 54 | int fw; |
57 | bool running; | 55 | int fw_ver; |
58 | 56 | u32 running; | |
59 | struct regulator *dvfs; | ||
60 | 57 | ||
61 | struct list_head ctl_list; | 58 | struct list_head ctl_list; |
62 | 59 | ||
63 | struct work_struct boot_work; | 60 | struct work_struct boot_work; |
61 | |||
62 | #ifdef CONFIG_DEBUG_FS | ||
63 | struct dentry *debugfs_root; | ||
64 | struct mutex debugfs_lock; | ||
65 | char *wmfw_file_name; | ||
66 | char *bin_file_name; | ||
67 | #endif | ||
68 | |||
64 | }; | 69 | }; |
65 | 70 | ||
66 | #define WM_ADSP1(wname, num) \ | 71 | #define WM_ADSP1(wname, num) \ |
67 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ | 72 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
68 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) | 73 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
69 | 74 | ||
70 | #define WM_ADSP2(wname, num) \ | 75 | #define WM_ADSP2_E(wname, num, event_fn) \ |
71 | { .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ | 76 | { .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ |
72 | .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \ | 77 | .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ |
73 | .event_flags = SND_SOC_DAPM_PRE_PMU }, \ | 78 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ |
74 | { .id = snd_soc_dapm_out_drv, .name = wname, \ | 79 | { .id = snd_soc_dapm_out_drv, .name = wname, \ |
75 | .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ | 80 | .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ |
76 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | 81 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } |
77 | 82 | ||
78 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; | 83 | #define WM_ADSP2(wname, num) \ |
79 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; | 84 | WM_ADSP2_E(wname, num, wm_adsp2_early_event) |
85 | |||
86 | extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; | ||
80 | 87 | ||
81 | int wm_adsp1_init(struct wm_adsp *adsp); | 88 | int wm_adsp1_init(struct wm_adsp *dsp); |
82 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); | 89 | int wm_adsp2_init(struct wm_adsp *dsp); |
90 | int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec); | ||
91 | int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec); | ||
83 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, | 92 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, |
84 | struct snd_kcontrol *kcontrol, int event); | 93 | struct snd_kcontrol *kcontrol, int event); |
85 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | 94 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 8366e19657a7..fd86bd105460 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -1116,7 +1116,7 @@ static const struct snd_soc_dapm_route lineout2_se_routes[] = { | |||
1116 | 1116 | ||
1117 | int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) | 1117 | int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) |
1118 | { | 1118 | { |
1119 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1119 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1120 | 1120 | ||
1121 | /* Latch volume update bits & default ZC on */ | 1121 | /* Latch volume update bits & default ZC on */ |
1122 | snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, | 1122 | snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, |
@@ -1160,7 +1160,7 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
1160 | int lineout1_diff, int lineout2_diff) | 1160 | int lineout1_diff, int lineout2_diff) |
1161 | { | 1161 | { |
1162 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1162 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
1163 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1163 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1164 | 1164 | ||
1165 | hubs->codec = codec; | 1165 | hubs->codec = codec; |
1166 | 1166 | ||
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index ef163360a745..7613d60d62ea 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h | |||
@@ -15,6 +15,17 @@ | |||
15 | 15 | ||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | #define WMFW_MAX_ALG_NAME 256 | ||
19 | #define WMFW_MAX_ALG_DESCR_NAME 256 | ||
20 | |||
21 | #define WMFW_MAX_COEFF_NAME 256 | ||
22 | #define WMFW_MAX_COEFF_DESCR_NAME 256 | ||
23 | |||
24 | #define WMFW_CTL_FLAG_SYS 0x8000 | ||
25 | #define WMFW_CTL_FLAG_VOLATILE 0x0004 | ||
26 | #define WMFW_CTL_FLAG_WRITEABLE 0x0002 | ||
27 | #define WMFW_CTL_FLAG_READABLE 0x0001 | ||
28 | |||
18 | struct wmfw_header { | 29 | struct wmfw_header { |
19 | char magic[4]; | 30 | char magic[4]; |
20 | __le32 len; | 31 | __le32 len; |
@@ -61,7 +72,7 @@ struct wmfw_adsp1_id_hdr { | |||
61 | struct wmfw_id_hdr fw; | 72 | struct wmfw_id_hdr fw; |
62 | __be32 zm; | 73 | __be32 zm; |
63 | __be32 dm; | 74 | __be32 dm; |
64 | __be32 algs; | 75 | __be32 n_algs; |
65 | } __packed; | 76 | } __packed; |
66 | 77 | ||
67 | struct wmfw_adsp2_id_hdr { | 78 | struct wmfw_adsp2_id_hdr { |
@@ -69,7 +80,7 @@ struct wmfw_adsp2_id_hdr { | |||
69 | __be32 zm; | 80 | __be32 zm; |
70 | __be32 xm; | 81 | __be32 xm; |
71 | __be32 ym; | 82 | __be32 ym; |
72 | __be32 algs; | 83 | __be32 n_algs; |
73 | } __packed; | 84 | } __packed; |
74 | 85 | ||
75 | struct wmfw_alg_hdr { | 86 | struct wmfw_alg_hdr { |
@@ -90,6 +101,28 @@ struct wmfw_adsp2_alg_hdr { | |||
90 | __be32 ym; | 101 | __be32 ym; |
91 | } __packed; | 102 | } __packed; |
92 | 103 | ||
104 | struct wmfw_adsp_alg_data { | ||
105 | __le32 id; | ||
106 | u8 name[WMFW_MAX_ALG_NAME]; | ||
107 | u8 descr[WMFW_MAX_ALG_DESCR_NAME]; | ||
108 | __le32 ncoeff; | ||
109 | u8 data[]; | ||
110 | } __packed; | ||
111 | |||
112 | struct wmfw_adsp_coeff_data { | ||
113 | struct { | ||
114 | __le16 offset; | ||
115 | __le16 type; | ||
116 | __le32 size; | ||
117 | } hdr; | ||
118 | u8 name[WMFW_MAX_COEFF_NAME]; | ||
119 | u8 descr[WMFW_MAX_COEFF_DESCR_NAME]; | ||
120 | __le16 ctl_type; | ||
121 | __le16 flags; | ||
122 | __le32 len; | ||
123 | u8 data[]; | ||
124 | } __packed; | ||
125 | |||
93 | struct wmfw_coeff_hdr { | 126 | struct wmfw_coeff_hdr { |
94 | u8 magic[4]; | 127 | u8 magic[4]; |
95 | __le32 len; | 128 | __le32 len; |
@@ -117,9 +150,10 @@ struct wmfw_coeff_item { | |||
117 | #define WMFW_ADSP1 1 | 150 | #define WMFW_ADSP1 1 |
118 | #define WMFW_ADSP2 2 | 151 | #define WMFW_ADSP2 2 |
119 | 152 | ||
120 | #define WMFW_ABSOLUTE 0xf0 | 153 | #define WMFW_ABSOLUTE 0xf0 |
121 | #define WMFW_NAME_TEXT 0xfe | 154 | #define WMFW_ALGORITHM_DATA 0xf2 |
122 | #define WMFW_INFO_TEXT 0xff | 155 | #define WMFW_NAME_TEXT 0xfe |
156 | #define WMFW_INFO_TEXT 0xff | ||
123 | 157 | ||
124 | #define WMFW_ADSP1_PM 2 | 158 | #define WMFW_ADSP1_PM 2 |
125 | #define WMFW_ADSP1_DM 3 | 159 | #define WMFW_ADSP1_DM 3 |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index bb4b78eada58..b960e626dad9 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -107,6 +107,7 @@ struct davinci_mcasp { | |||
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | struct davinci_mcasp_ruledata ruledata[2]; | 109 | struct davinci_mcasp_ruledata ruledata[2]; |
110 | struct snd_pcm_hw_constraint_list chconstr[2]; | ||
110 | }; | 111 | }; |
111 | 112 | ||
112 | static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset, | 113 | static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset, |
@@ -685,6 +686,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, | |||
685 | if (mcasp->serial_dir[i] == TX_MODE && | 686 | if (mcasp->serial_dir[i] == TX_MODE && |
686 | tx_ser < max_active_serializers) { | 687 | tx_ser < max_active_serializers) { |
687 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i)); | 688 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i)); |
689 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), | ||
690 | DISMOD_LOW, DISMOD_MASK); | ||
688 | tx_ser++; | 691 | tx_ser++; |
689 | } else if (mcasp->serial_dir[i] == RX_MODE && | 692 | } else if (mcasp->serial_dir[i] == RX_MODE && |
690 | rx_ser < max_active_serializers) { | 693 | rx_ser < max_active_serializers) { |
@@ -915,15 +918,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
915 | * the machine driver, we need to calculate the ratio. | 918 | * the machine driver, we need to calculate the ratio. |
916 | */ | 919 | */ |
917 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { | 920 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { |
918 | int channels = params_channels(params); | 921 | int slots = mcasp->tdm_slots; |
919 | int rate = params_rate(params); | 922 | int rate = params_rate(params); |
920 | int sbits = params_width(params); | 923 | int sbits = params_width(params); |
921 | int ppm, div; | 924 | int ppm, div; |
922 | 925 | ||
923 | if (channels > mcasp->tdm_slots) | 926 | div = davinci_mcasp_calc_clk_div(mcasp, rate*sbits*slots, |
924 | channels = mcasp->tdm_slots; | ||
925 | |||
926 | div = davinci_mcasp_calc_clk_div(mcasp, rate*sbits*channels, | ||
927 | &ppm); | 927 | &ppm); |
928 | if (ppm) | 928 | if (ppm) |
929 | dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", | 929 | dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", |
@@ -1024,31 +1024,36 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params, | |||
1024 | struct snd_interval *ri = | 1024 | struct snd_interval *ri = |
1025 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 1025 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
1026 | int sbits = params_width(params); | 1026 | int sbits = params_width(params); |
1027 | int channels = params_channels(params); | 1027 | int slots = rd->mcasp->tdm_slots; |
1028 | unsigned int list[ARRAY_SIZE(davinci_mcasp_dai_rates)]; | 1028 | struct snd_interval range; |
1029 | int i, count = 0; | 1029 | int i; |
1030 | 1030 | ||
1031 | if (channels > rd->mcasp->tdm_slots) | 1031 | snd_interval_any(&range); |
1032 | channels = rd->mcasp->tdm_slots; | 1032 | range.empty = 1; |
1033 | 1033 | ||
1034 | for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) { | 1034 | for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) { |
1035 | if (ri->min <= davinci_mcasp_dai_rates[i] && | 1035 | if (snd_interval_test(ri, davinci_mcasp_dai_rates[i])) { |
1036 | ri->max >= davinci_mcasp_dai_rates[i]) { | 1036 | uint bclk_freq = sbits*slots* |
1037 | uint bclk_freq = sbits*channels* | ||
1038 | davinci_mcasp_dai_rates[i]; | 1037 | davinci_mcasp_dai_rates[i]; |
1039 | int ppm; | 1038 | int ppm; |
1040 | 1039 | ||
1041 | davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm); | 1040 | davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm); |
1042 | if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) | 1041 | if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { |
1043 | list[count++] = davinci_mcasp_dai_rates[i]; | 1042 | if (range.empty) { |
1043 | range.min = davinci_mcasp_dai_rates[i]; | ||
1044 | range.empty = 0; | ||
1045 | } | ||
1046 | range.max = davinci_mcasp_dai_rates[i]; | ||
1047 | } | ||
1044 | } | 1048 | } |
1045 | } | 1049 | } |
1050 | |||
1046 | dev_dbg(rd->mcasp->dev, | 1051 | dev_dbg(rd->mcasp->dev, |
1047 | "%d frequencies (%d-%d) for %d sbits and %d channels\n", | 1052 | "Frequencies %d-%d -> %d-%d for %d sbits and %d tdm slots\n", |
1048 | count, ri->min, ri->max, sbits, channels); | 1053 | ri->min, ri->max, range.min, range.max, sbits, slots); |
1049 | 1054 | ||
1050 | return snd_interval_list(hw_param_interval(params, rule->var), | 1055 | return snd_interval_refine(hw_param_interval(params, rule->var), |
1051 | count, list, 0); | 1056 | &range); |
1052 | } | 1057 | } |
1053 | 1058 | ||
1054 | static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, | 1059 | static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, |
@@ -1058,17 +1063,14 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, | |||
1058 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 1063 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); |
1059 | struct snd_mask nfmt; | 1064 | struct snd_mask nfmt; |
1060 | int rate = params_rate(params); | 1065 | int rate = params_rate(params); |
1061 | int channels = params_channels(params); | 1066 | int slots = rd->mcasp->tdm_slots; |
1062 | int i, count = 0; | 1067 | int i, count = 0; |
1063 | 1068 | ||
1064 | snd_mask_none(&nfmt); | 1069 | snd_mask_none(&nfmt); |
1065 | 1070 | ||
1066 | if (channels > rd->mcasp->tdm_slots) | ||
1067 | channels = rd->mcasp->tdm_slots; | ||
1068 | |||
1069 | for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { | 1071 | for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { |
1070 | if (snd_mask_test(fmt, i)) { | 1072 | if (snd_mask_test(fmt, i)) { |
1071 | uint bclk_freq = snd_pcm_format_width(i)*channels*rate; | 1073 | uint bclk_freq = snd_pcm_format_width(i)*slots*rate; |
1072 | int ppm; | 1074 | int ppm; |
1073 | 1075 | ||
1074 | davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm); | 1076 | davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm); |
@@ -1079,51 +1081,12 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, | |||
1079 | } | 1081 | } |
1080 | } | 1082 | } |
1081 | dev_dbg(rd->mcasp->dev, | 1083 | dev_dbg(rd->mcasp->dev, |
1082 | "%d possible sample format for %d Hz and %d channels\n", | 1084 | "%d possible sample format for %d Hz and %d tdm slots\n", |
1083 | count, rate, channels); | 1085 | count, rate, slots); |
1084 | 1086 | ||
1085 | return snd_mask_refine(fmt, &nfmt); | 1087 | return snd_mask_refine(fmt, &nfmt); |
1086 | } | 1088 | } |
1087 | 1089 | ||
1088 | static int davinci_mcasp_hw_rule_channels(struct snd_pcm_hw_params *params, | ||
1089 | struct snd_pcm_hw_rule *rule) | ||
1090 | { | ||
1091 | struct davinci_mcasp_ruledata *rd = rule->private; | ||
1092 | struct snd_interval *ci = | ||
1093 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
1094 | int sbits = params_width(params); | ||
1095 | int rate = params_rate(params); | ||
1096 | int max_chan_per_wire = rd->mcasp->tdm_slots < ci->max ? | ||
1097 | rd->mcasp->tdm_slots : ci->max; | ||
1098 | unsigned int list[ci->max - ci->min + 1]; | ||
1099 | int c1, c, count = 0; | ||
1100 | |||
1101 | for (c1 = ci->min; c1 <= max_chan_per_wire; c1++) { | ||
1102 | uint bclk_freq = c1*sbits*rate; | ||
1103 | int ppm; | ||
1104 | |||
1105 | davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm); | ||
1106 | if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { | ||
1107 | /* If we can use all tdm_slots, we can put any | ||
1108 | amount of channels to remaining wires as | ||
1109 | long as they fit in. */ | ||
1110 | if (c1 == rd->mcasp->tdm_slots) { | ||
1111 | for (c = c1; c <= rd->serializers*c1 && | ||
1112 | c <= ci->max; c++) | ||
1113 | list[count++] = c; | ||
1114 | } else { | ||
1115 | list[count++] = c1; | ||
1116 | } | ||
1117 | } | ||
1118 | } | ||
1119 | dev_dbg(rd->mcasp->dev, | ||
1120 | "%d possible channel counts (%d-%d) for %d Hz and %d sbits\n", | ||
1121 | count, ci->min, ci->max, rate, sbits); | ||
1122 | |||
1123 | return snd_interval_list(hw_param_interval(params, rule->var), | ||
1124 | count, list, 0); | ||
1125 | } | ||
1126 | |||
1127 | static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | 1090 | static int davinci_mcasp_startup(struct snd_pcm_substream *substream, |
1128 | struct snd_soc_dai *cpu_dai) | 1091 | struct snd_soc_dai *cpu_dai) |
1129 | { | 1092 | { |
@@ -1167,6 +1130,11 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1167 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1130 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1168 | 2, max_channels); | 1131 | 2, max_channels); |
1169 | 1132 | ||
1133 | if (mcasp->chconstr[substream->stream].count) | ||
1134 | snd_pcm_hw_constraint_list(substream->runtime, | ||
1135 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
1136 | &mcasp->chconstr[substream->stream]); | ||
1137 | |||
1170 | /* | 1138 | /* |
1171 | * If we rely on implicit BCLK divider setting we should | 1139 | * If we rely on implicit BCLK divider setting we should |
1172 | * set constraints based on what we can provide. | 1140 | * set constraints based on what we can provide. |
@@ -1180,24 +1148,14 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1180 | SNDRV_PCM_HW_PARAM_RATE, | 1148 | SNDRV_PCM_HW_PARAM_RATE, |
1181 | davinci_mcasp_hw_rule_rate, | 1149 | davinci_mcasp_hw_rule_rate, |
1182 | ruledata, | 1150 | ruledata, |
1183 | SNDRV_PCM_HW_PARAM_FORMAT, | 1151 | SNDRV_PCM_HW_PARAM_FORMAT, -1); |
1184 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
1185 | if (ret) | 1152 | if (ret) |
1186 | return ret; | 1153 | return ret; |
1187 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | 1154 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
1188 | SNDRV_PCM_HW_PARAM_FORMAT, | 1155 | SNDRV_PCM_HW_PARAM_FORMAT, |
1189 | davinci_mcasp_hw_rule_format, | 1156 | davinci_mcasp_hw_rule_format, |
1190 | ruledata, | 1157 | ruledata, |
1191 | SNDRV_PCM_HW_PARAM_RATE, | 1158 | SNDRV_PCM_HW_PARAM_RATE, -1); |
1192 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
1193 | if (ret) | ||
1194 | return ret; | ||
1195 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | ||
1196 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
1197 | davinci_mcasp_hw_rule_channels, | ||
1198 | ruledata, | ||
1199 | SNDRV_PCM_HW_PARAM_RATE, | ||
1200 | SNDRV_PCM_HW_PARAM_FORMAT, -1); | ||
1201 | if (ret) | 1159 | if (ret) |
1202 | return ret; | 1160 | return ret; |
1203 | } | 1161 | } |
@@ -1247,7 +1205,7 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai) | |||
1247 | u32 reg; | 1205 | u32 reg; |
1248 | int i; | 1206 | int i; |
1249 | 1207 | ||
1250 | context->pm_state = pm_runtime_enabled(mcasp->dev); | 1208 | context->pm_state = pm_runtime_active(mcasp->dev); |
1251 | if (!context->pm_state) | 1209 | if (!context->pm_state) |
1252 | pm_runtime_get_sync(mcasp->dev); | 1210 | pm_runtime_get_sync(mcasp->dev); |
1253 | 1211 | ||
@@ -1556,6 +1514,102 @@ nodata: | |||
1556 | return pdata; | 1514 | return pdata; |
1557 | } | 1515 | } |
1558 | 1516 | ||
1517 | /* All serializers must have equal number of channels */ | ||
1518 | static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, | ||
1519 | struct snd_pcm_hw_constraint_list *cl, | ||
1520 | int serializers) | ||
1521 | { | ||
1522 | unsigned int *list; | ||
1523 | int i, count = 0; | ||
1524 | |||
1525 | if (serializers <= 1) | ||
1526 | return 0; | ||
1527 | |||
1528 | list = devm_kzalloc(mcasp->dev, sizeof(unsigned int) * | ||
1529 | (mcasp->tdm_slots + serializers - 2), | ||
1530 | GFP_KERNEL); | ||
1531 | if (!list) | ||
1532 | return -ENOMEM; | ||
1533 | |||
1534 | for (i = 2; i <= mcasp->tdm_slots; i++) | ||
1535 | list[count++] = i; | ||
1536 | |||
1537 | for (i = 2; i <= serializers; i++) | ||
1538 | list[count++] = i*mcasp->tdm_slots; | ||
1539 | |||
1540 | cl->count = count; | ||
1541 | cl->list = list; | ||
1542 | |||
1543 | return 0; | ||
1544 | } | ||
1545 | |||
1546 | |||
1547 | static int davinci_mcasp_init_ch_constraints(struct davinci_mcasp *mcasp) | ||
1548 | { | ||
1549 | int rx_serializers = 0, tx_serializers = 0, ret, i; | ||
1550 | |||
1551 | for (i = 0; i < mcasp->num_serializer; i++) | ||
1552 | if (mcasp->serial_dir[i] == TX_MODE) | ||
1553 | tx_serializers++; | ||
1554 | else if (mcasp->serial_dir[i] == RX_MODE) | ||
1555 | rx_serializers++; | ||
1556 | |||
1557 | ret = davinci_mcasp_ch_constraint(mcasp, &mcasp->chconstr[ | ||
1558 | SNDRV_PCM_STREAM_PLAYBACK], | ||
1559 | tx_serializers); | ||
1560 | if (ret) | ||
1561 | return ret; | ||
1562 | |||
1563 | ret = davinci_mcasp_ch_constraint(mcasp, &mcasp->chconstr[ | ||
1564 | SNDRV_PCM_STREAM_CAPTURE], | ||
1565 | rx_serializers); | ||
1566 | |||
1567 | return ret; | ||
1568 | } | ||
1569 | |||
1570 | enum { | ||
1571 | PCM_EDMA, | ||
1572 | PCM_SDMA, | ||
1573 | }; | ||
1574 | static const char *sdma_prefix = "ti,omap"; | ||
1575 | |||
1576 | static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp) | ||
1577 | { | ||
1578 | struct dma_chan *chan; | ||
1579 | const char *tmp; | ||
1580 | int ret = PCM_EDMA; | ||
1581 | |||
1582 | if (!mcasp->dev->of_node) | ||
1583 | return PCM_EDMA; | ||
1584 | |||
1585 | tmp = mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data; | ||
1586 | chan = dma_request_slave_channel_reason(mcasp->dev, tmp); | ||
1587 | if (IS_ERR(chan)) { | ||
1588 | if (PTR_ERR(chan) != -EPROBE_DEFER) | ||
1589 | dev_err(mcasp->dev, | ||
1590 | "Can't verify DMA configuration (%ld)\n", | ||
1591 | PTR_ERR(chan)); | ||
1592 | return PTR_ERR(chan); | ||
1593 | } | ||
1594 | BUG_ON(!chan->device || !chan->device->dev); | ||
1595 | |||
1596 | if (chan->device->dev->of_node) | ||
1597 | ret = of_property_read_string(chan->device->dev->of_node, | ||
1598 | "compatible", &tmp); | ||
1599 | else | ||
1600 | dev_dbg(mcasp->dev, "DMA controller has no of-node\n"); | ||
1601 | |||
1602 | dma_release_channel(chan); | ||
1603 | if (ret) | ||
1604 | return ret; | ||
1605 | |||
1606 | dev_dbg(mcasp->dev, "DMA controller compatible = \"%s\"\n", tmp); | ||
1607 | if (!strncmp(tmp, sdma_prefix, strlen(sdma_prefix))) | ||
1608 | return PCM_SDMA; | ||
1609 | |||
1610 | return PCM_EDMA; | ||
1611 | } | ||
1612 | |||
1559 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1613 | static int davinci_mcasp_probe(struct platform_device *pdev) |
1560 | { | 1614 | { |
1561 | struct snd_dmaengine_dai_dma_data *dma_data; | 1615 | struct snd_dmaengine_dai_dma_data *dma_data; |
@@ -1739,6 +1793,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1739 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; | 1793 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; |
1740 | } | 1794 | } |
1741 | 1795 | ||
1796 | ret = davinci_mcasp_init_ch_constraints(mcasp); | ||
1797 | if (ret) | ||
1798 | goto err; | ||
1799 | |||
1742 | dev_set_drvdata(&pdev->dev, mcasp); | 1800 | dev_set_drvdata(&pdev->dev, mcasp); |
1743 | 1801 | ||
1744 | mcasp_reparent_fck(pdev); | 1802 | mcasp_reparent_fck(pdev); |
@@ -1750,27 +1808,34 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1750 | if (ret != 0) | 1808 | if (ret != 0) |
1751 | goto err; | 1809 | goto err; |
1752 | 1810 | ||
1753 | switch (mcasp->version) { | 1811 | ret = davinci_mcasp_get_dma_type(mcasp); |
1812 | switch (ret) { | ||
1813 | case PCM_EDMA: | ||
1754 | #if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ | 1814 | #if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ |
1755 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | 1815 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ |
1756 | IS_MODULE(CONFIG_SND_EDMA_SOC)) | 1816 | IS_MODULE(CONFIG_SND_EDMA_SOC)) |
1757 | case MCASP_VERSION_1: | ||
1758 | case MCASP_VERSION_2: | ||
1759 | case MCASP_VERSION_3: | ||
1760 | ret = edma_pcm_platform_register(&pdev->dev); | 1817 | ret = edma_pcm_platform_register(&pdev->dev); |
1761 | break; | 1818 | #else |
1819 | dev_err(&pdev->dev, "Missing SND_EDMA_SOC\n"); | ||
1820 | ret = -EINVAL; | ||
1821 | goto err; | ||
1762 | #endif | 1822 | #endif |
1823 | break; | ||
1824 | case PCM_SDMA: | ||
1763 | #if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \ | 1825 | #if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \ |
1764 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | 1826 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ |
1765 | IS_MODULE(CONFIG_SND_OMAP_SOC)) | 1827 | IS_MODULE(CONFIG_SND_OMAP_SOC)) |
1766 | case MCASP_VERSION_4: | ||
1767 | ret = omap_pcm_platform_register(&pdev->dev); | 1828 | ret = omap_pcm_platform_register(&pdev->dev); |
1768 | break; | 1829 | #else |
1830 | dev_err(&pdev->dev, "Missing SND_SDMA_SOC\n"); | ||
1831 | ret = -EINVAL; | ||
1832 | goto err; | ||
1769 | #endif | 1833 | #endif |
1834 | break; | ||
1770 | default: | 1835 | default: |
1771 | dev_err(&pdev->dev, "Invalid McASP version: %d\n", | 1836 | dev_err(&pdev->dev, "No DMA controller found (%d)\n", ret); |
1772 | mcasp->version); | 1837 | case -EPROBE_DEFER: |
1773 | ret = -EINVAL; | 1838 | goto err; |
1774 | break; | 1839 | break; |
1775 | } | 1840 | } |
1776 | 1841 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 79dc511180bf..a3be108a8c17 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -215,7 +215,10 @@ | |||
215 | * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits | 215 | * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits |
216 | */ | 216 | */ |
217 | #define MODE(val) (val) | 217 | #define MODE(val) (val) |
218 | #define DISMOD (val)(val<<2) | 218 | #define DISMOD_3STATE (0x0) |
219 | #define DISMOD_LOW (0x2 << 2) | ||
220 | #define DISMOD_HIGH (0x3 << 2) | ||
221 | #define DISMOD_MASK DISMOD_HIGH | ||
219 | #define TXSTATE BIT(4) | 222 | #define TXSTATE BIT(4) |
220 | #define RXSTATE BIT(5) | 223 | #define RXSTATE BIT(5) |
221 | #define SRMOD_MASK 3 | 224 | #define SRMOD_MASK 3 |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 93d7e56c6066..ccadefceeff2 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -445,7 +445,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
445 | return ret; | 445 | return ret; |
446 | } | 446 | } |
447 | 447 | ||
448 | dma->assigned = 1; | 448 | dma->assigned = true; |
449 | 449 | ||
450 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 450 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
451 | snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); | 451 | snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); |
@@ -814,7 +814,7 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) | |||
814 | substream->runtime->private_data = NULL; | 814 | substream->runtime->private_data = NULL; |
815 | } | 815 | } |
816 | 816 | ||
817 | dma->assigned = 0; | 817 | dma->assigned = false; |
818 | 818 | ||
819 | return 0; | 819 | return 0; |
820 | } | 820 | } |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index ec79c3d5e65e..5c73bea7b11e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale ALSA SoC Digital Audio Interface (SAI) driver. | 2 | * Freescale ALSA SoC Digital Audio Interface (SAI) driver. |
3 | * | 3 | * |
4 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | 4 | * Copyright 2012-2015 Freescale Semiconductor, Inc. |
5 | * | 5 | * |
6 | * This program is free software, you can redistribute it and/or modify it | 6 | * This program is free software, you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -27,6 +27,17 @@ | |||
27 | #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\ | 27 | #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\ |
28 | FSL_SAI_CSR_FEIE) | 28 | FSL_SAI_CSR_FEIE) |
29 | 29 | ||
30 | static u32 fsl_sai_rates[] = { | ||
31 | 8000, 11025, 12000, 16000, 22050, | ||
32 | 24000, 32000, 44100, 48000, 64000, | ||
33 | 88200, 96000, 176400, 192000 | ||
34 | }; | ||
35 | |||
36 | static struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = { | ||
37 | .count = ARRAY_SIZE(fsl_sai_rates), | ||
38 | .list = fsl_sai_rates, | ||
39 | }; | ||
40 | |||
30 | static irqreturn_t fsl_sai_isr(int irq, void *devid) | 41 | static irqreturn_t fsl_sai_isr(int irq, void *devid) |
31 | { | 42 | { |
32 | struct fsl_sai *sai = (struct fsl_sai *)devid; | 43 | struct fsl_sai *sai = (struct fsl_sai *)devid; |
@@ -251,12 +262,14 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
251 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; | 262 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; |
252 | break; | 263 | break; |
253 | case SND_SOC_DAIFMT_CBM_CFM: | 264 | case SND_SOC_DAIFMT_CBM_CFM: |
265 | sai->is_slave_mode = true; | ||
254 | break; | 266 | break; |
255 | case SND_SOC_DAIFMT_CBS_CFM: | 267 | case SND_SOC_DAIFMT_CBS_CFM: |
256 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; | 268 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; |
257 | break; | 269 | break; |
258 | case SND_SOC_DAIFMT_CBM_CFS: | 270 | case SND_SOC_DAIFMT_CBM_CFS: |
259 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; | 271 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; |
272 | sai->is_slave_mode = true; | ||
260 | break; | 273 | break; |
261 | default: | 274 | default: |
262 | return -EINVAL; | 275 | return -EINVAL; |
@@ -288,6 +301,79 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
288 | return ret; | 301 | return ret; |
289 | } | 302 | } |
290 | 303 | ||
304 | static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) | ||
305 | { | ||
306 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); | ||
307 | unsigned long clk_rate; | ||
308 | u32 savediv = 0, ratio, savesub = freq; | ||
309 | u32 id; | ||
310 | int ret = 0; | ||
311 | |||
312 | /* Don't apply to slave mode */ | ||
313 | if (sai->is_slave_mode) | ||
314 | return 0; | ||
315 | |||
316 | for (id = 0; id < FSL_SAI_MCLK_MAX; id++) { | ||
317 | clk_rate = clk_get_rate(sai->mclk_clk[id]); | ||
318 | if (!clk_rate) | ||
319 | continue; | ||
320 | |||
321 | ratio = clk_rate / freq; | ||
322 | |||
323 | ret = clk_rate - ratio * freq; | ||
324 | |||
325 | /* | ||
326 | * Drop the source that can not be | ||
327 | * divided into the required rate. | ||
328 | */ | ||
329 | if (ret != 0 && clk_rate / ret < 1000) | ||
330 | continue; | ||
331 | |||
332 | dev_dbg(dai->dev, | ||
333 | "ratio %d for freq %dHz based on clock %ldHz\n", | ||
334 | ratio, freq, clk_rate); | ||
335 | |||
336 | if (ratio % 2 == 0 && ratio >= 2 && ratio <= 512) | ||
337 | ratio /= 2; | ||
338 | else | ||
339 | continue; | ||
340 | |||
341 | if (ret < savesub) { | ||
342 | savediv = ratio; | ||
343 | sai->mclk_id[tx] = id; | ||
344 | savesub = ret; | ||
345 | } | ||
346 | |||
347 | if (ret == 0) | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | if (savediv == 0) { | ||
352 | dev_err(dai->dev, "failed to derive required %cx rate: %d\n", | ||
353 | tx ? 'T' : 'R', freq); | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | |||
357 | if ((tx && sai->synchronous[TX]) || (!tx && !sai->synchronous[RX])) { | ||
358 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, | ||
359 | FSL_SAI_CR2_MSEL_MASK, | ||
360 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); | ||
361 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, | ||
362 | FSL_SAI_CR2_DIV_MASK, savediv - 1); | ||
363 | } else { | ||
364 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, | ||
365 | FSL_SAI_CR2_MSEL_MASK, | ||
366 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); | ||
367 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, | ||
368 | FSL_SAI_CR2_DIV_MASK, savediv - 1); | ||
369 | } | ||
370 | |||
371 | dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n", | ||
372 | sai->mclk_id[tx], savediv, savesub); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
291 | static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | 377 | static int fsl_sai_hw_params(struct snd_pcm_substream *substream, |
292 | struct snd_pcm_hw_params *params, | 378 | struct snd_pcm_hw_params *params, |
293 | struct snd_soc_dai *cpu_dai) | 379 | struct snd_soc_dai *cpu_dai) |
@@ -297,6 +383,24 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
297 | unsigned int channels = params_channels(params); | 383 | unsigned int channels = params_channels(params); |
298 | u32 word_width = snd_pcm_format_width(params_format(params)); | 384 | u32 word_width = snd_pcm_format_width(params_format(params)); |
299 | u32 val_cr4 = 0, val_cr5 = 0; | 385 | u32 val_cr4 = 0, val_cr5 = 0; |
386 | int ret; | ||
387 | |||
388 | if (!sai->is_slave_mode) { | ||
389 | ret = fsl_sai_set_bclk(cpu_dai, tx, | ||
390 | 2 * word_width * params_rate(params)); | ||
391 | if (ret) | ||
392 | return ret; | ||
393 | |||
394 | /* Do not enable the clock if it is already enabled */ | ||
395 | if (!(sai->mclk_streams & BIT(substream->stream))) { | ||
396 | ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[tx]]); | ||
397 | if (ret) | ||
398 | return ret; | ||
399 | |||
400 | sai->mclk_streams |= BIT(substream->stream); | ||
401 | } | ||
402 | |||
403 | } | ||
300 | 404 | ||
301 | if (!sai->is_dsp_mode) | 405 | if (!sai->is_dsp_mode) |
302 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); | 406 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); |
@@ -322,6 +426,22 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
322 | return 0; | 426 | return 0; |
323 | } | 427 | } |
324 | 428 | ||
429 | static int fsl_sai_hw_free(struct snd_pcm_substream *substream, | ||
430 | struct snd_soc_dai *cpu_dai) | ||
431 | { | ||
432 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
433 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
434 | |||
435 | if (!sai->is_slave_mode && | ||
436 | sai->mclk_streams & BIT(substream->stream)) { | ||
437 | clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]); | ||
438 | sai->mclk_streams &= ~BIT(substream->stream); | ||
439 | } | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | |||
325 | static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | 445 | static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, |
326 | struct snd_soc_dai *cpu_dai) | 446 | struct snd_soc_dai *cpu_dai) |
327 | { | 447 | { |
@@ -410,7 +530,10 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, | |||
410 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, | 530 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, |
411 | FSL_SAI_CR3_TRCE); | 531 | FSL_SAI_CR3_TRCE); |
412 | 532 | ||
413 | return 0; | 533 | ret = snd_pcm_hw_constraint_list(substream->runtime, 0, |
534 | SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints); | ||
535 | |||
536 | return ret; | ||
414 | } | 537 | } |
415 | 538 | ||
416 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, | 539 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, |
@@ -428,6 +551,7 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | |||
428 | .set_sysclk = fsl_sai_set_dai_sysclk, | 551 | .set_sysclk = fsl_sai_set_dai_sysclk, |
429 | .set_fmt = fsl_sai_set_dai_fmt, | 552 | .set_fmt = fsl_sai_set_dai_fmt, |
430 | .hw_params = fsl_sai_hw_params, | 553 | .hw_params = fsl_sai_hw_params, |
554 | .hw_free = fsl_sai_hw_free, | ||
431 | .trigger = fsl_sai_trigger, | 555 | .trigger = fsl_sai_trigger, |
432 | .startup = fsl_sai_startup, | 556 | .startup = fsl_sai_startup, |
433 | .shutdown = fsl_sai_shutdown, | 557 | .shutdown = fsl_sai_shutdown, |
@@ -463,14 +587,18 @@ static struct snd_soc_dai_driver fsl_sai_dai = { | |||
463 | .stream_name = "CPU-Playback", | 587 | .stream_name = "CPU-Playback", |
464 | .channels_min = 1, | 588 | .channels_min = 1, |
465 | .channels_max = 2, | 589 | .channels_max = 2, |
466 | .rates = SNDRV_PCM_RATE_8000_96000, | 590 | .rate_min = 8000, |
591 | .rate_max = 192000, | ||
592 | .rates = SNDRV_PCM_RATE_KNOT, | ||
467 | .formats = FSL_SAI_FORMATS, | 593 | .formats = FSL_SAI_FORMATS, |
468 | }, | 594 | }, |
469 | .capture = { | 595 | .capture = { |
470 | .stream_name = "CPU-Capture", | 596 | .stream_name = "CPU-Capture", |
471 | .channels_min = 1, | 597 | .channels_min = 1, |
472 | .channels_max = 2, | 598 | .channels_max = 2, |
473 | .rates = SNDRV_PCM_RATE_8000_96000, | 599 | .rate_min = 8000, |
600 | .rate_max = 192000, | ||
601 | .rates = SNDRV_PCM_RATE_KNOT, | ||
474 | .formats = FSL_SAI_FORMATS, | 602 | .formats = FSL_SAI_FORMATS, |
475 | }, | 603 | }, |
476 | .ops = &fsl_sai_pcm_dai_ops, | 604 | .ops = &fsl_sai_pcm_dai_ops, |
@@ -600,8 +728,9 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
600 | sai->bus_clk = NULL; | 728 | sai->bus_clk = NULL; |
601 | } | 729 | } |
602 | 730 | ||
603 | for (i = 0; i < FSL_SAI_MCLK_MAX; i++) { | 731 | sai->mclk_clk[0] = sai->bus_clk; |
604 | sprintf(tmp, "mclk%d", i + 1); | 732 | for (i = 1; i < FSL_SAI_MCLK_MAX; i++) { |
733 | sprintf(tmp, "mclk%d", i); | ||
605 | sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp); | 734 | sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp); |
606 | if (IS_ERR(sai->mclk_clk[i])) { | 735 | if (IS_ERR(sai->mclk_clk[i])) { |
607 | dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n", | 736 | dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n", |
@@ -664,8 +793,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
664 | if (sai->sai_on_imx) | 793 | if (sai->sai_on_imx) |
665 | return imx_pcm_dma_init(pdev); | 794 | return imx_pcm_dma_init(pdev); |
666 | else | 795 | else |
667 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, | 796 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
668 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
669 | } | 797 | } |
670 | 798 | ||
671 | static const struct of_device_id fsl_sai_ids[] = { | 799 | static const struct of_device_id fsl_sai_ids[] = { |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 34667209b607..066280953c85 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -72,13 +72,15 @@ | |||
72 | 72 | ||
73 | /* SAI Transmit and Recieve Configuration 2 Register */ | 73 | /* SAI Transmit and Recieve Configuration 2 Register */ |
74 | #define FSL_SAI_CR2_SYNC BIT(30) | 74 | #define FSL_SAI_CR2_SYNC BIT(30) |
75 | #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) | 75 | #define FSL_SAI_CR2_MSEL_MASK (0x3 << 26) |
76 | #define FSL_SAI_CR2_MSEL_BUS 0 | 76 | #define FSL_SAI_CR2_MSEL_BUS 0 |
77 | #define FSL_SAI_CR2_MSEL_MCLK1 BIT(26) | 77 | #define FSL_SAI_CR2_MSEL_MCLK1 BIT(26) |
78 | #define FSL_SAI_CR2_MSEL_MCLK2 BIT(27) | 78 | #define FSL_SAI_CR2_MSEL_MCLK2 BIT(27) |
79 | #define FSL_SAI_CR2_MSEL_MCLK3 (BIT(26) | BIT(27)) | 79 | #define FSL_SAI_CR2_MSEL_MCLK3 (BIT(26) | BIT(27)) |
80 | #define FSL_SAI_CR2_MSEL(ID) ((ID) << 26) | ||
80 | #define FSL_SAI_CR2_BCP BIT(25) | 81 | #define FSL_SAI_CR2_BCP BIT(25) |
81 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) | 82 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) |
83 | #define FSL_SAI_CR2_DIV_MASK 0xff | ||
82 | 84 | ||
83 | /* SAI Transmit and Recieve Configuration 3 Register */ | 85 | /* SAI Transmit and Recieve Configuration 3 Register */ |
84 | #define FSL_SAI_CR3_TRCE BIT(16) | 86 | #define FSL_SAI_CR3_TRCE BIT(16) |
@@ -120,7 +122,7 @@ | |||
120 | #define FSL_SAI_CLK_MAST2 2 | 122 | #define FSL_SAI_CLK_MAST2 2 |
121 | #define FSL_SAI_CLK_MAST3 3 | 123 | #define FSL_SAI_CLK_MAST3 3 |
122 | 124 | ||
123 | #define FSL_SAI_MCLK_MAX 3 | 125 | #define FSL_SAI_MCLK_MAX 4 |
124 | 126 | ||
125 | /* SAI data transfer numbers per DMA request */ | 127 | /* SAI data transfer numbers per DMA request */ |
126 | #define FSL_SAI_MAXBURST_TX 6 | 128 | #define FSL_SAI_MAXBURST_TX 6 |
@@ -132,11 +134,14 @@ struct fsl_sai { | |||
132 | struct clk *bus_clk; | 134 | struct clk *bus_clk; |
133 | struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; | 135 | struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; |
134 | 136 | ||
137 | bool is_slave_mode; | ||
135 | bool is_lsb_first; | 138 | bool is_lsb_first; |
136 | bool is_dsp_mode; | 139 | bool is_dsp_mode; |
137 | bool sai_on_imx; | 140 | bool sai_on_imx; |
138 | bool synchronous[2]; | 141 | bool synchronous[2]; |
139 | 142 | ||
143 | unsigned int mclk_id[2]; | ||
144 | unsigned int mclk_streams; | ||
140 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 145 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
141 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 146 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
142 | }; | 147 | }; |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 91eb3aef7f02..8e932219cb3a 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -417,11 +417,9 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, | |||
417 | if (clk != STC_TXCLK_SPDIF_ROOT) | 417 | if (clk != STC_TXCLK_SPDIF_ROOT) |
418 | goto clk_set_bypass; | 418 | goto clk_set_bypass; |
419 | 419 | ||
420 | /* | 420 | /* The S/PDIF block needs a clock of 64 * fs * txclk_df */ |
421 | * The S/PDIF block needs a clock of 64 * fs * txclk_df. | 421 | ret = clk_set_rate(spdif_priv->txclk[rate], |
422 | * So request 64 * fs * (txclk_df + 1) to get rounded. | 422 | 64 * sample_rate * txclk_df); |
423 | */ | ||
424 | ret = clk_set_rate(spdif_priv->txclk[rate], 64 * sample_rate * (txclk_df + 1)); | ||
425 | if (ret) { | 423 | if (ret) { |
426 | dev_err(&pdev->dev, "failed to set tx clock rate\n"); | 424 | dev_err(&pdev->dev, "failed to set tx clock rate\n"); |
427 | return ret; | 425 | return ret; |
@@ -1060,7 +1058,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1060 | 1058 | ||
1061 | for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) { | 1059 | for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) { |
1062 | for (txclk_df = 1; txclk_df <= 128; txclk_df++) { | 1060 | for (txclk_df = 1; txclk_df <= 128; txclk_df++) { |
1063 | rate_ideal = rate[index] * (txclk_df + 1) * 64; | 1061 | rate_ideal = rate[index] * txclk_df * 64; |
1064 | if (round) | 1062 | if (round) |
1065 | rate_actual = clk_round_rate(clk, rate_ideal); | 1063 | rate_actual = clk_round_rate(clk, rate_ideal); |
1066 | else | 1064 | else |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index e8bb8eef1d16..c0b940e2019f 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -633,7 +633,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, | |||
633 | sub *= 100000; | 633 | sub *= 100000; |
634 | do_div(sub, freq); | 634 | do_div(sub, freq); |
635 | 635 | ||
636 | if (sub < savesub) { | 636 | if (sub < savesub && !(i == 0 && psr == 0 && div2 == 0)) { |
637 | baudrate = tmprate; | 637 | baudrate = tmprate; |
638 | savesub = sub; | 638 | savesub = sub; |
639 | pm = i; | 639 | pm = i; |
@@ -1292,13 +1292,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1292 | void __iomem *iomem; | 1292 | void __iomem *iomem; |
1293 | char name[64]; | 1293 | char name[64]; |
1294 | 1294 | ||
1295 | /* SSIs that are not connected on the board should have a | ||
1296 | * status = "disabled" | ||
1297 | * property in their device tree nodes. | ||
1298 | */ | ||
1299 | if (!of_device_is_available(np)) | ||
1300 | return -ENODEV; | ||
1301 | |||
1302 | of_id = of_match_device(fsl_ssi_ids, &pdev->dev); | 1295 | of_id = of_match_device(fsl_ssi_ids, &pdev->dev); |
1303 | if (!of_id || !of_id->data) | 1296 | if (!of_id || !of_id->data) |
1304 | return -EINVAL; | 1297 | return -EINVAL; |
@@ -1357,7 +1350,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1357 | } | 1350 | } |
1358 | 1351 | ||
1359 | ssi_private->irq = platform_get_irq(pdev, 0); | 1352 | ssi_private->irq = platform_get_irq(pdev, 0); |
1360 | if (!ssi_private->irq) { | 1353 | if (ssi_private->irq < 0) { |
1361 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | 1354 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
1362 | return ssi_private->irq; | 1355 | return ssi_private->irq; |
1363 | } | 1356 | } |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index d9050d946ae7..fc57da341d61 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -184,7 +184,7 @@ static enum imx_audmux_type { | |||
184 | IMX31_AUDMUX, | 184 | IMX31_AUDMUX, |
185 | } audmux_type; | 185 | } audmux_type; |
186 | 186 | ||
187 | static struct platform_device_id imx_audmux_ids[] = { | 187 | static const struct platform_device_id imx_audmux_ids[] = { |
188 | { | 188 | { |
189 | .name = "imx21-audmux", | 189 | .name = "imx21-audmux", |
190 | .driver_data = IMX21_AUDMUX, | 190 | .driver_data = IMX21_AUDMUX, |
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 9e6493d4e7ff..bb0459018b45 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
@@ -45,11 +45,7 @@ static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, | |||
45 | if (ret) | 45 | if (ret) |
46 | return ret; | 46 | return ret; |
47 | 47 | ||
48 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 16); | 48 | return snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 16); |
49 | if (ret) | ||
50 | return ret; | ||
51 | |||
52 | return 0; | ||
53 | } | 49 | } |
54 | 50 | ||
55 | static struct snd_soc_ops imx_mc13783_hifi_ops = { | 51 | static struct snd_soc_ops imx_mc13783_hifi_ops = { |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index cd146d4fa805..b38b98cae855 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c | |||
@@ -190,7 +190,7 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
190 | dev_err(&pdev->dev, "audmux internal port setup failed\n"); | 190 | dev_err(&pdev->dev, "audmux internal port setup failed\n"); |
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | imx_audmux_v2_configure_port(ext_port, | 193 | ret = imx_audmux_v2_configure_port(ext_port, |
194 | IMX_AUDMUX_V2_PTCR_SYN, | 194 | IMX_AUDMUX_V2_PTCR_SYN, |
195 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | 195 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); |
196 | if (ret) { | 196 | if (ret) { |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 33feee9ca8c3..d5554939146e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -26,6 +26,7 @@ struct simple_card_data { | |||
26 | struct simple_dai_props { | 26 | struct simple_dai_props { |
27 | struct asoc_simple_dai cpu_dai; | 27 | struct asoc_simple_dai cpu_dai; |
28 | struct asoc_simple_dai codec_dai; | 28 | struct asoc_simple_dai codec_dai; |
29 | unsigned int mclk_fs; | ||
29 | } *dai_props; | 30 | } *dai_props; |
30 | unsigned int mclk_fs; | 31 | unsigned int mclk_fs; |
31 | int gpio_hp_det; | 32 | int gpio_hp_det; |
@@ -76,11 +77,18 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | |||
76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
77 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
78 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 79 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
79 | unsigned int mclk; | 80 | struct simple_dai_props *dai_props = |
81 | &priv->dai_props[rtd - rtd->card->rtd]; | ||
82 | unsigned int mclk, mclk_fs = 0; | ||
80 | int ret = 0; | 83 | int ret = 0; |
81 | 84 | ||
82 | if (priv->mclk_fs) { | 85 | if (priv->mclk_fs) |
83 | mclk = params_rate(params) * priv->mclk_fs; | 86 | mclk_fs = priv->mclk_fs; |
87 | else if (dai_props->mclk_fs) | ||
88 | mclk_fs = dai_props->mclk_fs; | ||
89 | |||
90 | if (mclk_fs) { | ||
91 | mclk = params_rate(params) * mclk_fs; | ||
84 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | 92 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
85 | SND_SOC_CLOCK_IN); | 93 | SND_SOC_CLOCK_IN); |
86 | } | 94 | } |
@@ -307,11 +315,13 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
307 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); | 315 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); |
308 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); | 316 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); |
309 | struct device_node *cpu = NULL; | 317 | struct device_node *cpu = NULL; |
318 | struct device_node *plat = NULL; | ||
310 | struct device_node *codec = NULL; | 319 | struct device_node *codec = NULL; |
311 | char *name; | 320 | char *name; |
312 | char prop[128]; | 321 | char prop[128]; |
313 | char *prefix = ""; | 322 | char *prefix = ""; |
314 | int ret, cpu_args; | 323 | int ret, cpu_args; |
324 | u32 val; | ||
315 | 325 | ||
316 | /* For single DAI link & old style of DT node */ | 326 | /* For single DAI link & old style of DT node */ |
317 | if (is_top_level_node) | 327 | if (is_top_level_node) |
@@ -320,6 +330,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
320 | snprintf(prop, sizeof(prop), "%scpu", prefix); | 330 | snprintf(prop, sizeof(prop), "%scpu", prefix); |
321 | cpu = of_get_child_by_name(node, prop); | 331 | cpu = of_get_child_by_name(node, prop); |
322 | 332 | ||
333 | snprintf(prop, sizeof(prop), "%splat", prefix); | ||
334 | plat = of_get_child_by_name(node, prop); | ||
335 | |||
323 | snprintf(prop, sizeof(prop), "%scodec", prefix); | 336 | snprintf(prop, sizeof(prop), "%scodec", prefix); |
324 | codec = of_get_child_by_name(node, prop); | 337 | codec = of_get_child_by_name(node, prop); |
325 | 338 | ||
@@ -334,6 +347,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
334 | if (ret < 0) | 347 | if (ret < 0) |
335 | goto dai_link_of_err; | 348 | goto dai_link_of_err; |
336 | 349 | ||
350 | if (!of_property_read_u32(node, "mclk-fs", &val)) | ||
351 | dai_props->mclk_fs = val; | ||
352 | |||
337 | ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, | 353 | ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, |
338 | &dai_link->cpu_of_node, | 354 | &dai_link->cpu_of_node, |
339 | &dai_link->cpu_dai_name, | 355 | &dai_link->cpu_dai_name, |
@@ -352,8 +368,16 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
352 | goto dai_link_of_err; | 368 | goto dai_link_of_err; |
353 | } | 369 | } |
354 | 370 | ||
355 | /* Simple Card assumes platform == cpu */ | 371 | if (plat) { |
356 | dai_link->platform_of_node = dai_link->cpu_of_node; | 372 | struct of_phandle_args args; |
373 | |||
374 | ret = of_parse_phandle_with_args(plat, "sound-dai", | ||
375 | "#sound-dai-cells", 0, &args); | ||
376 | dai_link->platform_of_node = args.np; | ||
377 | } else { | ||
378 | /* Assumes platform == cpu */ | ||
379 | dai_link->platform_of_node = dai_link->cpu_of_node; | ||
380 | } | ||
357 | 381 | ||
358 | /* DAI link name is created from CPU/CODEC dai name */ | 382 | /* DAI link name is created from CPU/CODEC dai name */ |
359 | name = devm_kzalloc(dev, | 383 | name = devm_kzalloc(dev, |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index ee03dbdda235..f3060a4ca040 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -79,7 +79,6 @@ config SND_SOC_INTEL_BROADWELL_MACH | |||
79 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \ | 79 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \ |
80 | I2C_DESIGNWARE_PLATFORM | 80 | I2C_DESIGNWARE_PLATFORM |
81 | select SND_SOC_INTEL_HASWELL | 81 | select SND_SOC_INTEL_HASWELL |
82 | select SND_COMPRESS_OFFLOAD | ||
83 | select SND_SOC_RT286 | 82 | select SND_SOC_RT286 |
84 | help | 83 | help |
85 | This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell | 84 | This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell |
@@ -112,12 +111,24 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | |||
112 | If unsure select "N". | 111 | If unsure select "N". |
113 | 112 | ||
114 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | 113 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH |
115 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645 codec" | 114 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" |
116 | depends on X86_INTEL_LPSS | 115 | depends on X86_INTEL_LPSS && I2C |
117 | select SND_SOC_RT5645 | 116 | select SND_SOC_RT5645 |
118 | select SND_SST_MFLD_PLATFORM | 117 | select SND_SST_MFLD_PLATFORM |
119 | select SND_SST_IPC_ACPI | 118 | select SND_SST_IPC_ACPI |
120 | help | 119 | help |
121 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | 120 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell |
122 | platforms with RT5645 audio codec. | 121 | platforms with RT5645/5650 audio codec. |
123 | If unsure select "N". | 122 | If unsure select "N". |
123 | |||
124 | config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH | ||
125 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with MAX98090 & TI codec" | ||
126 | depends on X86_INTEL_LPSS && I2C | ||
127 | select SND_SOC_MAX98090 | ||
128 | select SND_SOC_TS3A227E | ||
129 | select SND_SST_MFLD_PLATFORM | ||
130 | select SND_SST_IPC_ACPI | ||
131 | help | ||
132 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | ||
133 | platforms with MAX98090 audio codec it also can support TI jack chip as aux device. | ||
134 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index cd9aee9871a3..6de5d5cd3280 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -4,7 +4,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SST) += common/ | |||
4 | # Platform Support | 4 | # Platform Support |
5 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ | 5 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ |
6 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ | 6 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ |
7 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += atom/ | 7 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/ |
8 | 8 | ||
9 | # Machine support | 9 | # Machine support |
10 | obj-$(CONFIG_SND_SOC_INTEL_SST) += boards/ | 10 | obj-$(CONFIG_SND_SOC) += boards/ |
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 90aa5c0476f3..31e9b9ecbb8a 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c | |||
@@ -774,8 +774,120 @@ int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable) | |||
774 | return ret; | 774 | return ret; |
775 | } | 775 | } |
776 | 776 | ||
777 | int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
778 | unsigned int rx_mask, int slots, int slot_width) | ||
779 | { | ||
780 | struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
781 | |||
782 | ctx->ssp_cmd.nb_slots = slots; | ||
783 | ctx->ssp_cmd.active_tx_slot_map = tx_mask; | ||
784 | ctx->ssp_cmd.active_rx_slot_map = rx_mask; | ||
785 | ctx->ssp_cmd.nb_bits_per_slots = slot_width; | ||
786 | |||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai, | ||
791 | unsigned int fmt) | ||
792 | { | ||
793 | int format; | ||
794 | |||
795 | format = fmt & SND_SOC_DAIFMT_INV_MASK; | ||
796 | dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); | ||
797 | |||
798 | switch (format) { | ||
799 | case SND_SOC_DAIFMT_NB_NF: | ||
800 | return SSP_FS_ACTIVE_LOW; | ||
801 | case SND_SOC_DAIFMT_NB_IF: | ||
802 | return SSP_FS_ACTIVE_HIGH; | ||
803 | case SND_SOC_DAIFMT_IB_IF: | ||
804 | return SSP_FS_ACTIVE_LOW; | ||
805 | case SND_SOC_DAIFMT_IB_NF: | ||
806 | return SSP_FS_ACTIVE_HIGH; | ||
807 | default: | ||
808 | dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); | ||
809 | } | ||
810 | |||
811 | return -EINVAL; | ||
812 | } | ||
813 | |||
814 | static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt) | ||
815 | { | ||
816 | int format; | ||
817 | |||
818 | format = (fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
819 | dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); | ||
820 | |||
821 | switch (format) { | ||
822 | case SND_SOC_DAIFMT_CBS_CFS: | ||
823 | return SSP_MODE_MASTER; | ||
824 | case SND_SOC_DAIFMT_CBM_CFM: | ||
825 | return SSP_MODE_SLAVE; | ||
826 | default: | ||
827 | dev_err(dai->dev, "Invalid ssp protocol: %d\n", format); | ||
828 | } | ||
829 | |||
830 | return -EINVAL; | ||
831 | } | ||
832 | |||
833 | |||
834 | int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt) | ||
835 | { | ||
836 | unsigned int mode; | ||
837 | int fs_polarity; | ||
838 | struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
839 | |||
840 | mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
841 | |||
842 | switch (mode) { | ||
843 | case SND_SOC_DAIFMT_DSP_B: | ||
844 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; | ||
845 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); | ||
846 | ctx->ssp_cmd.start_delay = 0; | ||
847 | ctx->ssp_cmd.data_polarity = 1; | ||
848 | ctx->ssp_cmd.frame_sync_width = 1; | ||
849 | break; | ||
850 | |||
851 | case SND_SOC_DAIFMT_DSP_A: | ||
852 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; | ||
853 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); | ||
854 | ctx->ssp_cmd.start_delay = 1; | ||
855 | ctx->ssp_cmd.data_polarity = 1; | ||
856 | ctx->ssp_cmd.frame_sync_width = 1; | ||
857 | break; | ||
858 | |||
859 | case SND_SOC_DAIFMT_I2S: | ||
860 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; | ||
861 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); | ||
862 | ctx->ssp_cmd.start_delay = 1; | ||
863 | ctx->ssp_cmd.data_polarity = 0; | ||
864 | ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; | ||
865 | break; | ||
866 | |||
867 | case SND_SOC_DAIFMT_LEFT_J: | ||
868 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; | ||
869 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); | ||
870 | ctx->ssp_cmd.start_delay = 0; | ||
871 | ctx->ssp_cmd.data_polarity = 0; | ||
872 | ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; | ||
873 | break; | ||
874 | |||
875 | default: | ||
876 | dev_dbg(dai->dev, "using default ssp configs\n"); | ||
877 | } | ||
878 | |||
879 | fs_polarity = sst_get_frame_sync_polarity(dai, fmt); | ||
880 | if (fs_polarity < 0) | ||
881 | return fs_polarity; | ||
882 | |||
883 | ctx->ssp_cmd.frame_sync_polarity = fs_polarity; | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
777 | /** | 888 | /** |
778 | * sst_ssp_config - contains SSP configuration for media UC | 889 | * sst_ssp_config - contains SSP configuration for media UC |
890 | * this can be overwritten by set_dai_xxx APIs | ||
779 | */ | 891 | */ |
780 | static const struct sst_ssp_config sst_ssp_configs = { | 892 | static const struct sst_ssp_config sst_ssp_configs = { |
781 | .ssp_id = SSP_CODEC, | 893 | .ssp_id = SSP_CODEC, |
@@ -789,47 +901,56 @@ static const struct sst_ssp_config sst_ssp_configs = { | |||
789 | .fs_frequency = SSP_FS_48_KHZ, | 901 | .fs_frequency = SSP_FS_48_KHZ, |
790 | .active_slot_map = 0xF, | 902 | .active_slot_map = 0xF, |
791 | .start_delay = 0, | 903 | .start_delay = 0, |
904 | .frame_sync_polarity = SSP_FS_ACTIVE_HIGH, | ||
905 | .data_polarity = 1, | ||
792 | }; | 906 | }; |
793 | 907 | ||
908 | void sst_fill_ssp_defaults(struct snd_soc_dai *dai) | ||
909 | { | ||
910 | const struct sst_ssp_config *config; | ||
911 | struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
912 | |||
913 | config = &sst_ssp_configs; | ||
914 | |||
915 | ctx->ssp_cmd.selection = config->ssp_id; | ||
916 | ctx->ssp_cmd.nb_bits_per_slots = config->bits_per_slot; | ||
917 | ctx->ssp_cmd.nb_slots = config->slots; | ||
918 | ctx->ssp_cmd.mode = config->ssp_mode | (config->pcm_mode << 1); | ||
919 | ctx->ssp_cmd.duplex = config->duplex; | ||
920 | ctx->ssp_cmd.active_tx_slot_map = config->active_slot_map; | ||
921 | ctx->ssp_cmd.active_rx_slot_map = config->active_slot_map; | ||
922 | ctx->ssp_cmd.frame_sync_frequency = config->fs_frequency; | ||
923 | ctx->ssp_cmd.frame_sync_polarity = config->frame_sync_polarity; | ||
924 | ctx->ssp_cmd.data_polarity = config->data_polarity; | ||
925 | ctx->ssp_cmd.frame_sync_width = config->fs_width; | ||
926 | ctx->ssp_cmd.ssp_protocol = config->ssp_protocol; | ||
927 | ctx->ssp_cmd.start_delay = config->start_delay; | ||
928 | ctx->ssp_cmd.reserved1 = ctx->ssp_cmd.reserved2 = 0xFF; | ||
929 | } | ||
930 | |||
794 | int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable) | 931 | int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable) |
795 | { | 932 | { |
796 | struct sst_cmd_sba_hw_set_ssp cmd; | ||
797 | struct sst_data *drv = snd_soc_dai_get_drvdata(dai); | 933 | struct sst_data *drv = snd_soc_dai_get_drvdata(dai); |
798 | const struct sst_ssp_config *config; | 934 | const struct sst_ssp_config *config; |
799 | 935 | ||
800 | dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id); | 936 | dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id); |
801 | 937 | ||
802 | SST_FILL_DEFAULT_DESTINATION(cmd.header.dst); | 938 | SST_FILL_DEFAULT_DESTINATION(drv->ssp_cmd.header.dst); |
803 | cmd.header.command_id = SBA_HW_SET_SSP; | 939 | drv->ssp_cmd.header.command_id = SBA_HW_SET_SSP; |
804 | cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp) | 940 | drv->ssp_cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp) |
805 | - sizeof(struct sst_dsp_header); | 941 | - sizeof(struct sst_dsp_header); |
806 | 942 | ||
807 | config = &sst_ssp_configs; | 943 | config = &sst_ssp_configs; |
808 | dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id); | 944 | dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id); |
809 | 945 | ||
810 | if (enable) | 946 | if (enable) |
811 | cmd.switch_state = SST_SWITCH_ON; | 947 | drv->ssp_cmd.switch_state = SST_SWITCH_ON; |
812 | else | 948 | else |
813 | cmd.switch_state = SST_SWITCH_OFF; | 949 | drv->ssp_cmd.switch_state = SST_SWITCH_OFF; |
814 | |||
815 | cmd.selection = config->ssp_id; | ||
816 | cmd.nb_bits_per_slots = config->bits_per_slot; | ||
817 | cmd.nb_slots = config->slots; | ||
818 | cmd.mode = config->ssp_mode | (config->pcm_mode << 1); | ||
819 | cmd.duplex = config->duplex; | ||
820 | cmd.active_tx_slot_map = config->active_slot_map; | ||
821 | cmd.active_rx_slot_map = config->active_slot_map; | ||
822 | cmd.frame_sync_frequency = config->fs_frequency; | ||
823 | cmd.frame_sync_polarity = SSP_FS_ACTIVE_HIGH; | ||
824 | cmd.data_polarity = 1; | ||
825 | cmd.frame_sync_width = config->fs_width; | ||
826 | cmd.ssp_protocol = config->ssp_protocol; | ||
827 | cmd.start_delay = config->start_delay; | ||
828 | cmd.reserved1 = cmd.reserved2 = 0xFF; | ||
829 | 950 | ||
830 | return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED, | 951 | return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED, |
831 | SST_TASK_SBA, 0, &cmd, | 952 | SST_TASK_SBA, 0, &drv->ssp_cmd, |
832 | sizeof(cmd.header) + cmd.header.length); | 953 | sizeof(drv->ssp_cmd.header) + drv->ssp_cmd.header.length); |
833 | } | 954 | } |
834 | 955 | ||
835 | static int sst_set_be_modules(struct snd_soc_dapm_widget *w, | 956 | static int sst_set_be_modules(struct snd_soc_dapm_widget *w, |
@@ -1280,36 +1401,32 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w, | |||
1280 | down_read(&card->controls_rwsem); | 1401 | down_read(&card->controls_rwsem); |
1281 | 1402 | ||
1282 | list_for_each_entry(kctl, &card->controls, list) { | 1403 | list_for_each_entry(kctl, &card->controls, list) { |
1283 | idx = strstr(kctl->id.name, " "); | 1404 | idx = strchr(kctl->id.name, ' '); |
1284 | if (idx == NULL) | 1405 | if (idx == NULL) |
1285 | continue; | 1406 | continue; |
1286 | index = strlen(kctl->id.name) - strlen(idx); | 1407 | index = idx - (char*)kctl->id.name; |
1408 | if (strncmp(kctl->id.name, w->name, index)) | ||
1409 | continue; | ||
1287 | 1410 | ||
1288 | if (strstr(kctl->id.name, "Volume") && | 1411 | if (strstr(kctl->id.name, "Volume")) |
1289 | !strncmp(kctl->id.name, w->name, index)) | ||
1290 | ret = sst_fill_module_list(kctl, w, SST_MODULE_GAIN); | 1412 | ret = sst_fill_module_list(kctl, w, SST_MODULE_GAIN); |
1291 | 1413 | ||
1292 | else if (strstr(kctl->id.name, "params") && | 1414 | else if (strstr(kctl->id.name, "params")) |
1293 | !strncmp(kctl->id.name, w->name, index)) | ||
1294 | ret = sst_fill_module_list(kctl, w, SST_MODULE_ALGO); | 1415 | ret = sst_fill_module_list(kctl, w, SST_MODULE_ALGO); |
1295 | 1416 | ||
1296 | else if (strstr(kctl->id.name, "Switch") && | 1417 | else if (strstr(kctl->id.name, "Switch") && |
1297 | !strncmp(kctl->id.name, w->name, index) && | ||
1298 | strstr(kctl->id.name, "Gain")) { | 1418 | strstr(kctl->id.name, "Gain")) { |
1299 | struct sst_gain_mixer_control *mc = | 1419 | struct sst_gain_mixer_control *mc = |
1300 | (void *)kctl->private_value; | 1420 | (void *)kctl->private_value; |
1301 | 1421 | ||
1302 | mc->w = w; | 1422 | mc->w = w; |
1303 | 1423 | ||
1304 | } else if (strstr(kctl->id.name, "interleaver") && | 1424 | } else if (strstr(kctl->id.name, "interleaver")) { |
1305 | !strncmp(kctl->id.name, w->name, index)) { | ||
1306 | struct sst_enum *e = (void *)kctl->private_value; | 1425 | struct sst_enum *e = (void *)kctl->private_value; |
1307 | 1426 | ||
1308 | e->w = w; | 1427 | e->w = w; |
1309 | 1428 | ||
1310 | } else if (strstr(kctl->id.name, "deinterleaver") && | 1429 | } else if (strstr(kctl->id.name, "deinterleaver")) { |
1311 | !strncmp(kctl->id.name, w->name, index)) { | ||
1312 | |||
1313 | struct sst_enum *e = (void *)kctl->private_value; | 1430 | struct sst_enum *e = (void *)kctl->private_value; |
1314 | 1431 | ||
1315 | e->w = w; | 1432 | e->w = w; |
diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h index daecc58f28af..93de8045d4e1 100644 --- a/sound/soc/intel/atom/sst-atom-controls.h +++ b/sound/soc/intel/atom/sst-atom-controls.h | |||
@@ -562,6 +562,8 @@ struct sst_ssp_config { | |||
562 | u8 active_slot_map; | 562 | u8 active_slot_map; |
563 | u8 start_delay; | 563 | u8 start_delay; |
564 | u16 fs_width; | 564 | u16 fs_width; |
565 | u8 frame_sync_polarity; | ||
566 | u8 data_polarity; | ||
565 | }; | 567 | }; |
566 | 568 | ||
567 | struct sst_ssp_cfg { | 569 | struct sst_ssp_cfg { |
@@ -695,7 +697,7 @@ struct sst_gain_mixer_control { | |||
695 | u16 module_id; | 697 | u16 module_id; |
696 | u16 pipe_id; | 698 | u16 pipe_id; |
697 | u16 task_id; | 699 | u16 task_id; |
698 | char pname[44]; | 700 | char pname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
699 | struct snd_soc_dapm_widget *w; | 701 | struct snd_soc_dapm_widget *w; |
700 | }; | 702 | }; |
701 | 703 | ||
@@ -867,4 +869,9 @@ struct sst_enum { | |||
867 | SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \ | 869 | SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \ |
868 | SST_SSP_MUX_ENUM(xreg, xshift, xtexts)) | 870 | SST_SSP_MUX_ENUM(xreg, xshift, xtexts)) |
869 | 871 | ||
872 | int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
873 | unsigned int rx_mask, int slots, int slot_width); | ||
874 | int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt); | ||
875 | void sst_fill_ssp_defaults(struct snd_soc_dai *dai); | ||
876 | |||
870 | #endif | 877 | #endif |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 2fbaf2c75d17..641ebe61dc08 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -434,13 +434,51 @@ static int sst_enable_ssp(struct snd_pcm_substream *substream, | |||
434 | 434 | ||
435 | if (!dai->active) { | 435 | if (!dai->active) { |
436 | ret = sst_handle_vb_timer(dai, true); | 436 | ret = sst_handle_vb_timer(dai, true); |
437 | if (ret) | 437 | sst_fill_ssp_defaults(dai); |
438 | return ret; | ||
439 | ret = send_ssp_cmd(dai, dai->name, 1); | ||
440 | } | 438 | } |
441 | return ret; | 439 | return ret; |
442 | } | 440 | } |
443 | 441 | ||
442 | static int sst_be_hw_params(struct snd_pcm_substream *substream, | ||
443 | struct snd_pcm_hw_params *params, | ||
444 | struct snd_soc_dai *dai) | ||
445 | { | ||
446 | int ret = 0; | ||
447 | |||
448 | if (dai->active == 1) | ||
449 | ret = send_ssp_cmd(dai, dai->name, 1); | ||
450 | return ret; | ||
451 | } | ||
452 | |||
453 | static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt) | ||
454 | { | ||
455 | int ret = 0; | ||
456 | |||
457 | if (!dai->active) | ||
458 | return 0; | ||
459 | |||
460 | ret = sst_fill_ssp_config(dai, fmt); | ||
461 | if (ret < 0) | ||
462 | dev_err(dai->dev, "sst_set_format failed..\n"); | ||
463 | |||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai, | ||
468 | unsigned int tx_mask, unsigned int rx_mask, | ||
469 | int slots, int slot_width) { | ||
470 | int ret = 0; | ||
471 | |||
472 | if (!dai->active) | ||
473 | return ret; | ||
474 | |||
475 | ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width); | ||
476 | if (ret < 0) | ||
477 | dev_err(dai->dev, "sst_fill_ssp_slot failed..%d\n", ret); | ||
478 | |||
479 | return ret; | ||
480 | } | ||
481 | |||
444 | static void sst_disable_ssp(struct snd_pcm_substream *substream, | 482 | static void sst_disable_ssp(struct snd_pcm_substream *substream, |
445 | struct snd_soc_dai *dai) | 483 | struct snd_soc_dai *dai) |
446 | { | 484 | { |
@@ -465,6 +503,9 @@ static struct snd_soc_dai_ops sst_compr_dai_ops = { | |||
465 | 503 | ||
466 | static struct snd_soc_dai_ops sst_be_dai_ops = { | 504 | static struct snd_soc_dai_ops sst_be_dai_ops = { |
467 | .startup = sst_enable_ssp, | 505 | .startup = sst_enable_ssp, |
506 | .hw_params = sst_be_hw_params, | ||
507 | .set_fmt = sst_set_format, | ||
508 | .set_tdm_slot = sst_platform_set_ssp_slot, | ||
468 | .shutdown = sst_disable_ssp, | 509 | .shutdown = sst_disable_ssp, |
469 | }; | 510 | }; |
470 | 511 | ||
diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index 9094314be2b0..2409b23eeacf 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define __SST_PLATFORMDRV_H__ | 22 | #define __SST_PLATFORMDRV_H__ |
23 | 23 | ||
24 | #include "sst-mfld-dsp.h" | 24 | #include "sst-mfld-dsp.h" |
25 | #include "sst-atom-controls.h" | ||
25 | 26 | ||
26 | extern struct sst_device *sst; | 27 | extern struct sst_device *sst; |
27 | 28 | ||
@@ -175,6 +176,7 @@ struct sst_data { | |||
175 | struct snd_sst_bytes_v2 *byte_stream; | 176 | struct snd_sst_bytes_v2 *byte_stream; |
176 | struct mutex lock; | 177 | struct mutex lock; |
177 | struct snd_soc_card *soc_card; | 178 | struct snd_soc_card *soc_card; |
179 | struct sst_cmd_sba_hw_set_ssp ssp_cmd; | ||
178 | }; | 180 | }; |
179 | int sst_register_dsp(struct sst_device *sst); | 181 | int sst_register_dsp(struct sst_device *sst); |
180 | int sst_unregister_dsp(struct sst_device *sst); | 182 | int sst_unregister_dsp(struct sst_device *sst); |
diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index 96c2e420cce6..a4b458e77089 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c | |||
@@ -368,8 +368,8 @@ static inline void sst_restore_shim64(struct intel_sst_drv *ctx, | |||
368 | * initialize by FW or driver when firmware is loaded | 368 | * initialize by FW or driver when firmware is loaded |
369 | */ | 369 | */ |
370 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | 370 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); |
371 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx), | 371 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx); |
372 | sst_shim_write64(shim, SST_CSR, shim_regs->csr), | 372 | sst_shim_write64(shim, SST_CSR, shim_regs->csr); |
373 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | 373 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); |
374 | } | 374 | } |
375 | 375 | ||
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 05f693083911..bb19b5801466 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c | |||
@@ -354,6 +354,10 @@ static struct sst_machines sst_acpi_chv[] = { | |||
354 | &chv_platform_data }, | 354 | &chv_platform_data }, |
355 | {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin", | 355 | {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin", |
356 | &chv_platform_data }, | 356 | &chv_platform_data }, |
357 | {"10EC5650", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin", | ||
358 | &chv_platform_data }, | ||
359 | {"193C9890", "cht-bsw", "cht-bsw-max98090", NULL, | ||
360 | "intel/fw_sst_22a8.bin", &chv_platform_data }, | ||
357 | {}, | 361 | {}, |
358 | }; | 362 | }; |
359 | 363 | ||
diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c index 7b50a9d17ec1..0e0e4d9c021f 100644 --- a/sound/soc/intel/atom/sst/sst_drv_interface.c +++ b/sound/soc/intel/atom/sst/sst_drv_interface.c | |||
@@ -42,6 +42,11 @@ | |||
42 | #define MIN_FRAGMENT_SIZE (50 * 1024) | 42 | #define MIN_FRAGMENT_SIZE (50 * 1024) |
43 | #define MAX_FRAGMENT_SIZE (1024 * 1024) | 43 | #define MAX_FRAGMENT_SIZE (1024 * 1024) |
44 | #define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz) (((pcm_wd_sz + 15) >> 4) << 1) | 44 | #define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz) (((pcm_wd_sz + 15) >> 4) << 1) |
45 | #ifdef CONFIG_PM | ||
46 | #define GET_USAGE_COUNT(dev) (atomic_read(&dev->power.usage_count)) | ||
47 | #else | ||
48 | #define GET_USAGE_COUNT(dev) 1 | ||
49 | #endif | ||
45 | 50 | ||
46 | int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id) | 51 | int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id) |
47 | { | 52 | { |
@@ -141,15 +146,9 @@ static int sst_power_control(struct device *dev, bool state) | |||
141 | int ret = 0; | 146 | int ret = 0; |
142 | int usage_count = 0; | 147 | int usage_count = 0; |
143 | 148 | ||
144 | #ifdef CONFIG_PM | ||
145 | usage_count = atomic_read(&dev->power.usage_count); | ||
146 | #else | ||
147 | usage_count = 1; | ||
148 | #endif | ||
149 | |||
150 | if (state == true) { | 149 | if (state == true) { |
151 | ret = pm_runtime_get_sync(dev); | 150 | ret = pm_runtime_get_sync(dev); |
152 | 151 | usage_count = GET_USAGE_COUNT(dev); | |
153 | dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count); | 152 | dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count); |
154 | if (ret < 0) { | 153 | if (ret < 0) { |
155 | dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret); | 154 | dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret); |
@@ -164,6 +163,7 @@ static int sst_power_control(struct device *dev, bool state) | |||
164 | } | 163 | } |
165 | } | 164 | } |
166 | } else { | 165 | } else { |
166 | usage_count = GET_USAGE_COUNT(dev); | ||
167 | dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count); | 167 | dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count); |
168 | return sst_pm_runtime_put(ctx); | 168 | return sst_pm_runtime_put(ctx); |
169 | } | 169 | } |
@@ -533,7 +533,7 @@ static inline int sst_calc_tstamp(struct intel_sst_drv *ctx, | |||
533 | 533 | ||
534 | info->buffer_ptr = pointer_samples / substream->runtime->channels; | 534 | info->buffer_ptr = pointer_samples / substream->runtime->channels; |
535 | 535 | ||
536 | info->pcm_delay = delay_frames / substream->runtime->channels; | 536 | info->pcm_delay = delay_frames; |
537 | dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n", | 537 | dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n", |
538 | info->buffer_ptr, info->pcm_delay); | 538 | info->buffer_ptr, info->pcm_delay); |
539 | return 0; | 539 | return 0; |
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 1efb33b36303..4c01bb43928d 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c | |||
@@ -679,6 +679,14 @@ static u64 byt_reply_msg_match(u64 header, u64 *mask) | |||
679 | return header; | 679 | return header; |
680 | } | 680 | } |
681 | 681 | ||
682 | static bool byt_is_dsp_busy(struct sst_dsp *dsp) | ||
683 | { | ||
684 | u64 ipcx; | ||
685 | |||
686 | ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); | ||
687 | return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); | ||
688 | } | ||
689 | |||
682 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | 690 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) |
683 | { | 691 | { |
684 | struct sst_byt *byt; | 692 | struct sst_byt *byt; |
@@ -699,6 +707,9 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
699 | ipc->ops.shim_dbg = byt_shim_dbg; | 707 | ipc->ops.shim_dbg = byt_shim_dbg; |
700 | ipc->ops.tx_data_copy = byt_tx_data_copy; | 708 | ipc->ops.tx_data_copy = byt_tx_data_copy; |
701 | ipc->ops.reply_msg_match = byt_reply_msg_match; | 709 | ipc->ops.reply_msg_match = byt_reply_msg_match; |
710 | ipc->ops.is_dsp_busy = byt_is_dsp_busy; | ||
711 | ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES; | ||
712 | ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES; | ||
702 | 713 | ||
703 | err = sst_ipc_init(ipc); | 714 | err = sst_ipc_init(ipc); |
704 | if (err != 0) | 715 | if (err != 0) |
@@ -759,7 +770,6 @@ fw_err: | |||
759 | dsp_new_err: | 770 | dsp_new_err: |
760 | sst_ipc_fini(ipc); | 771 | sst_ipc_fini(ipc); |
761 | ipc_init_err: | 772 | ipc_init_err: |
762 | kfree(byt); | ||
763 | 773 | ||
764 | return err; | 774 | return err; |
765 | } | 775 | } |
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index f8237f0044eb..cb94895c9edb 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
@@ -5,6 +5,7 @@ snd-soc-sst-broadwell-objs := broadwell.o | |||
5 | snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o | 5 | snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o |
6 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | 6 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o |
7 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | 7 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o |
8 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o | ||
8 | 9 | ||
9 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 10 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
10 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 11 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
@@ -13,3 +14,4 @@ obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | |||
13 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o | 14 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o |
14 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | 15 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o |
15 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | 16 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o |
17 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o | ||
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c new file mode 100644 index 000000000000..70f832114a5a --- /dev/null +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c | |||
@@ -0,0 +1,348 @@ | |||
1 | /* | ||
2 | * cht-bsw-max98090.c - ASoc Machine driver for Intel Cherryview-based | ||
3 | * platforms Cherrytrail and Braswell, with max98090 & TI codec. | ||
4 | * | ||
5 | * Copyright (C) 2015 Intel Corp | ||
6 | * Author: Fang, Yang A <yang.a.fang@intel.com> | ||
7 | * This file is modified from cht_bsw_rt5645.c | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; version 2 of the License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/acpi.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/jack.h> | ||
30 | #include "../../codecs/max98090.h" | ||
31 | #include "../atom/sst-atom-controls.h" | ||
32 | #include "../../codecs/ts3a227e.h" | ||
33 | |||
34 | #define CHT_PLAT_CLK_3_HZ 19200000 | ||
35 | #define CHT_CODEC_DAI "HiFi" | ||
36 | |||
37 | struct cht_mc_private { | ||
38 | struct snd_soc_jack jack; | ||
39 | bool ts3a227e_present; | ||
40 | }; | ||
41 | |||
42 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | ||
43 | { | ||
44 | int i; | ||
45 | |||
46 | for (i = 0; i < card->num_rtd; i++) { | ||
47 | struct snd_soc_pcm_runtime *rtd; | ||
48 | |||
49 | rtd = card->rtd + i; | ||
50 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | ||
51 | strlen(CHT_CODEC_DAI))) | ||
52 | return rtd->codec_dai; | ||
53 | } | ||
54 | return NULL; | ||
55 | } | ||
56 | |||
57 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | ||
58 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
59 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
60 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
61 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
62 | }; | ||
63 | |||
64 | static const struct snd_soc_dapm_route cht_audio_map[] = { | ||
65 | {"IN34", NULL, "Headset Mic"}, | ||
66 | {"Headset Mic", NULL, "MICBIAS"}, | ||
67 | {"DMICL", NULL, "Int Mic"}, | ||
68 | {"Headphone", NULL, "HPL"}, | ||
69 | {"Headphone", NULL, "HPR"}, | ||
70 | {"Ext Spk", NULL, "SPKL"}, | ||
71 | {"Ext Spk", NULL, "SPKR"}, | ||
72 | {"HiFi Playback", NULL, "ssp2 Tx"}, | ||
73 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
74 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
75 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
76 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
77 | {"ssp2 Rx", NULL, "HiFi Capture"}, | ||
78 | }; | ||
79 | |||
80 | static const struct snd_kcontrol_new cht_mc_controls[] = { | ||
81 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
82 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
83 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
84 | SOC_DAPM_PIN_SWITCH("Ext Spk"), | ||
85 | }; | ||
86 | |||
87 | static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | ||
88 | struct snd_pcm_hw_params *params) | ||
89 | { | ||
90 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
91 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
92 | int ret; | ||
93 | |||
94 | ret = snd_soc_dai_set_sysclk(codec_dai, M98090_REG_SYSTEM_CLOCK, | ||
95 | CHT_PLAT_CLK_3_HZ, SND_SOC_CLOCK_IN); | ||
96 | if (ret < 0) { | ||
97 | dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int cht_ti_jack_event(struct notifier_block *nb, | ||
105 | unsigned long event, void *data) | ||
106 | { | ||
107 | |||
108 | struct snd_soc_jack *jack = (struct snd_soc_jack *)data; | ||
109 | struct snd_soc_dai *codec_dai = jack->card->rtd->codec_dai; | ||
110 | struct snd_soc_codec *codec = codec_dai->codec; | ||
111 | |||
112 | if (event & SND_JACK_MICROPHONE) { | ||
113 | |||
114 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SHDN"); | ||
115 | snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); | ||
116 | snd_soc_dapm_sync(&codec->dapm); | ||
117 | } else { | ||
118 | |||
119 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); | ||
120 | snd_soc_dapm_disable_pin(&codec->dapm, "SHDN"); | ||
121 | snd_soc_dapm_sync(&codec->dapm); | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static struct notifier_block cht_jack_nb = { | ||
128 | .notifier_call = cht_ti_jack_event, | ||
129 | }; | ||
130 | |||
131 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | ||
132 | { | ||
133 | int ret; | ||
134 | int jack_type; | ||
135 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | ||
136 | struct snd_soc_jack *jack = &ctx->jack; | ||
137 | |||
138 | /** | ||
139 | * TI supports 4 butons headset detection | ||
140 | * KEY_MEDIA | ||
141 | * KEY_VOICECOMMAND | ||
142 | * KEY_VOLUMEUP | ||
143 | * KEY_VOLUMEDOWN | ||
144 | */ | ||
145 | if (ctx->ts3a227e_present) | ||
146 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | ||
147 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
148 | SND_JACK_BTN_2 | SND_JACK_BTN_3; | ||
149 | else | ||
150 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE; | ||
151 | |||
152 | ret = snd_soc_card_jack_new(runtime->card, "Headset Jack", | ||
153 | jack_type, jack, NULL, 0); | ||
154 | |||
155 | if (ret) { | ||
156 | dev_err(runtime->dev, "Headset Jack creation failed %d\n", ret); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | if (ctx->ts3a227e_present) | ||
161 | snd_soc_jack_notifier_register(jack, &cht_jack_nb); | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | ||
167 | struct snd_pcm_hw_params *params) | ||
168 | { | ||
169 | struct snd_interval *rate = hw_param_interval(params, | ||
170 | SNDRV_PCM_HW_PARAM_RATE); | ||
171 | struct snd_interval *channels = hw_param_interval(params, | ||
172 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
173 | int ret = 0; | ||
174 | unsigned int fmt = 0; | ||
175 | |||
176 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); | ||
177 | if (ret < 0) { | ||
178 | dev_err(rtd->dev, "can't set cpu_dai slot fmt: %d\n", ret); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | ||
183 | | SND_SOC_DAIFMT_CBS_CFS; | ||
184 | |||
185 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt); | ||
186 | if (ret < 0) { | ||
187 | dev_err(rtd->dev, "can't set cpu_dai set fmt: %d\n", ret); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | /* The DSP will covert the FE rate to 48k, stereo, 24bits */ | ||
192 | rate->min = rate->max = 48000; | ||
193 | channels->min = channels->max = 2; | ||
194 | |||
195 | /* set SSP2 to 24-bit */ | ||
196 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static unsigned int rates_48000[] = { | ||
201 | 48000, | ||
202 | }; | ||
203 | |||
204 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | ||
205 | .count = ARRAY_SIZE(rates_48000), | ||
206 | .list = rates_48000, | ||
207 | }; | ||
208 | |||
209 | static int cht_aif1_startup(struct snd_pcm_substream *substream) | ||
210 | { | ||
211 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
212 | SNDRV_PCM_HW_PARAM_RATE, | ||
213 | &constraints_48000); | ||
214 | } | ||
215 | |||
216 | static int cht_max98090_headset_init(struct snd_soc_component *component) | ||
217 | { | ||
218 | struct snd_soc_card *card = component->card; | ||
219 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | ||
220 | |||
221 | return ts3a227e_enable_jack_detect(component, &ctx->jack); | ||
222 | } | ||
223 | |||
224 | static struct snd_soc_ops cht_aif1_ops = { | ||
225 | .startup = cht_aif1_startup, | ||
226 | }; | ||
227 | |||
228 | static struct snd_soc_ops cht_be_ssp2_ops = { | ||
229 | .hw_params = cht_aif1_hw_params, | ||
230 | }; | ||
231 | |||
232 | static struct snd_soc_aux_dev cht_max98090_headset_dev = { | ||
233 | .name = "Headset Chip", | ||
234 | .init = cht_max98090_headset_init, | ||
235 | .codec_name = "i2c-104C227E:00", | ||
236 | }; | ||
237 | |||
238 | static struct snd_soc_dai_link cht_dailink[] = { | ||
239 | [MERR_DPCM_AUDIO] = { | ||
240 | .name = "Audio Port", | ||
241 | .stream_name = "Audio", | ||
242 | .cpu_dai_name = "media-cpu-dai", | ||
243 | .codec_dai_name = "snd-soc-dummy-dai", | ||
244 | .codec_name = "snd-soc-dummy", | ||
245 | .platform_name = "sst-mfld-platform", | ||
246 | .nonatomic = true, | ||
247 | .dynamic = 1, | ||
248 | .dpcm_playback = 1, | ||
249 | .dpcm_capture = 1, | ||
250 | .ops = &cht_aif1_ops, | ||
251 | }, | ||
252 | [MERR_DPCM_COMPR] = { | ||
253 | .name = "Compressed Port", | ||
254 | .stream_name = "Compress", | ||
255 | .cpu_dai_name = "compress-cpu-dai", | ||
256 | .codec_dai_name = "snd-soc-dummy-dai", | ||
257 | .codec_name = "snd-soc-dummy", | ||
258 | .platform_name = "sst-mfld-platform", | ||
259 | }, | ||
260 | /* back ends */ | ||
261 | { | ||
262 | .name = "SSP2-Codec", | ||
263 | .be_id = 1, | ||
264 | .cpu_dai_name = "ssp2-port", | ||
265 | .platform_name = "sst-mfld-platform", | ||
266 | .no_pcm = 1, | ||
267 | .codec_dai_name = "HiFi", | ||
268 | .codec_name = "i2c-193C9890:00", | ||
269 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
270 | | SND_SOC_DAIFMT_CBS_CFS, | ||
271 | .init = cht_codec_init, | ||
272 | .be_hw_params_fixup = cht_codec_fixup, | ||
273 | .dpcm_playback = 1, | ||
274 | .dpcm_capture = 1, | ||
275 | .ops = &cht_be_ssp2_ops, | ||
276 | }, | ||
277 | }; | ||
278 | |||
279 | /* SoC card */ | ||
280 | static struct snd_soc_card snd_soc_card_cht = { | ||
281 | .name = "chtmax98090", | ||
282 | .dai_link = cht_dailink, | ||
283 | .num_links = ARRAY_SIZE(cht_dailink), | ||
284 | .aux_dev = &cht_max98090_headset_dev, | ||
285 | .num_aux_devs = 1, | ||
286 | .dapm_widgets = cht_dapm_widgets, | ||
287 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | ||
288 | .dapm_routes = cht_audio_map, | ||
289 | .num_dapm_routes = ARRAY_SIZE(cht_audio_map), | ||
290 | .controls = cht_mc_controls, | ||
291 | .num_controls = ARRAY_SIZE(cht_mc_controls), | ||
292 | }; | ||
293 | |||
294 | static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level, | ||
295 | void *context, void **ret) | ||
296 | { | ||
297 | *(bool *)context = true; | ||
298 | return AE_OK; | ||
299 | } | ||
300 | |||
301 | static int snd_cht_mc_probe(struct platform_device *pdev) | ||
302 | { | ||
303 | int ret_val = 0; | ||
304 | bool found = false; | ||
305 | struct cht_mc_private *drv; | ||
306 | |||
307 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | ||
308 | if (!drv) | ||
309 | return -ENOMEM; | ||
310 | |||
311 | if (ACPI_SUCCESS(acpi_get_devices( | ||
312 | "104C227E", | ||
313 | snd_acpi_codec_match, | ||
314 | &found, NULL)) && found) { | ||
315 | drv->ts3a227e_present = true; | ||
316 | } else { | ||
317 | /* no need probe TI jack detection chip */ | ||
318 | snd_soc_card_cht.aux_dev = NULL; | ||
319 | snd_soc_card_cht.num_aux_devs = 0; | ||
320 | drv->ts3a227e_present = false; | ||
321 | } | ||
322 | |||
323 | /* register the soc card */ | ||
324 | snd_soc_card_cht.dev = &pdev->dev; | ||
325 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | ||
326 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | ||
327 | if (ret_val) { | ||
328 | dev_err(&pdev->dev, | ||
329 | "snd_soc_register_card failed %d\n", ret_val); | ||
330 | return ret_val; | ||
331 | } | ||
332 | platform_set_drvdata(pdev, &snd_soc_card_cht); | ||
333 | return ret_val; | ||
334 | } | ||
335 | |||
336 | static struct platform_driver snd_cht_mc_driver = { | ||
337 | .driver = { | ||
338 | .name = "cht-bsw-max98090", | ||
339 | }, | ||
340 | .probe = snd_cht_mc_probe, | ||
341 | }; | ||
342 | |||
343 | module_platform_driver(snd_cht_mc_driver) | ||
344 | |||
345 | MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver"); | ||
346 | MODULE_AUTHOR("Fang, Yang A <yang.a.fang@intel.com>"); | ||
347 | MODULE_LICENSE("GPL v2"); | ||
348 | MODULE_ALIAS("platform:cht-bsw-max98090"); | ||
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 20a28b22e30f..bdcaf467842a 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/acpi.h> | ||
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -33,9 +34,15 @@ | |||
33 | #define CHT_PLAT_CLK_3_HZ 19200000 | 34 | #define CHT_PLAT_CLK_3_HZ 19200000 |
34 | #define CHT_CODEC_DAI "rt5645-aif1" | 35 | #define CHT_CODEC_DAI "rt5645-aif1" |
35 | 36 | ||
37 | struct cht_acpi_card { | ||
38 | char *codec_id; | ||
39 | int codec_type; | ||
40 | struct snd_soc_card *soc_card; | ||
41 | }; | ||
42 | |||
36 | struct cht_mc_private { | 43 | struct cht_mc_private { |
37 | struct snd_soc_jack hp_jack; | 44 | struct snd_soc_jack jack; |
38 | struct snd_soc_jack mic_jack; | 45 | struct cht_acpi_card *acpi_card; |
39 | }; | 46 | }; |
40 | 47 | ||
41 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | 48 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) |
@@ -94,7 +101,7 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | |||
94 | platform_clock_control, SND_SOC_DAPM_POST_PMD), | 101 | platform_clock_control, SND_SOC_DAPM_POST_PMD), |
95 | }; | 102 | }; |
96 | 103 | ||
97 | static const struct snd_soc_dapm_route cht_audio_map[] = { | 104 | static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = { |
98 | {"IN1P", NULL, "Headset Mic"}, | 105 | {"IN1P", NULL, "Headset Mic"}, |
99 | {"IN1N", NULL, "Headset Mic"}, | 106 | {"IN1N", NULL, "Headset Mic"}, |
100 | {"DMIC L1", NULL, "Int Mic"}, | 107 | {"DMIC L1", NULL, "Int Mic"}, |
@@ -115,6 +122,27 @@ static const struct snd_soc_dapm_route cht_audio_map[] = { | |||
115 | {"Ext Spk", NULL, "Platform Clock"}, | 122 | {"Ext Spk", NULL, "Platform Clock"}, |
116 | }; | 123 | }; |
117 | 124 | ||
125 | static const struct snd_soc_dapm_route cht_rt5650_audio_map[] = { | ||
126 | {"IN1P", NULL, "Headset Mic"}, | ||
127 | {"IN1N", NULL, "Headset Mic"}, | ||
128 | {"DMIC L2", NULL, "Int Mic"}, | ||
129 | {"DMIC R2", NULL, "Int Mic"}, | ||
130 | {"Headphone", NULL, "HPOL"}, | ||
131 | {"Headphone", NULL, "HPOR"}, | ||
132 | {"Ext Spk", NULL, "SPOL"}, | ||
133 | {"Ext Spk", NULL, "SPOR"}, | ||
134 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | ||
135 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
136 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
137 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
138 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
139 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | ||
140 | {"Headphone", NULL, "Platform Clock"}, | ||
141 | {"Headset Mic", NULL, "Platform Clock"}, | ||
142 | {"Int Mic", NULL, "Platform Clock"}, | ||
143 | {"Ext Spk", NULL, "Platform Clock"}, | ||
144 | }; | ||
145 | |||
118 | static const struct snd_kcontrol_new cht_mc_controls[] = { | 146 | static const struct snd_kcontrol_new cht_mc_controls[] = { |
119 | SOC_DAPM_PIN_SWITCH("Headphone"), | 147 | SOC_DAPM_PIN_SWITCH("Headphone"), |
120 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | 148 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
@@ -150,6 +178,7 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | |||
150 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | 178 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) |
151 | { | 179 | { |
152 | int ret; | 180 | int ret; |
181 | int jack_type; | ||
153 | struct snd_soc_codec *codec = runtime->codec; | 182 | struct snd_soc_codec *codec = runtime->codec; |
154 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 183 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
155 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | 184 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); |
@@ -169,23 +198,22 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
169 | return ret; | 198 | return ret; |
170 | } | 199 | } |
171 | 200 | ||
172 | ret = snd_soc_card_jack_new(runtime->card, "Headphone Jack", | 201 | if (ctx->acpi_card->codec_type == CODEC_TYPE_RT5650) |
173 | SND_JACK_HEADPHONE, &ctx->hp_jack, | 202 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | |
174 | NULL, 0); | 203 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
175 | if (ret) { | 204 | SND_JACK_BTN_2 | SND_JACK_BTN_3; |
176 | dev_err(runtime->dev, "HP jack creation failed %d\n", ret); | 205 | else |
177 | return ret; | 206 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE; |
178 | } | ||
179 | 207 | ||
180 | ret = snd_soc_card_jack_new(runtime->card, "Mic Jack", | 208 | ret = snd_soc_card_jack_new(runtime->card, "Headset Jack", |
181 | SND_JACK_MICROPHONE, &ctx->mic_jack, | 209 | jack_type, &ctx->jack, |
182 | NULL, 0); | 210 | NULL, 0); |
183 | if (ret) { | 211 | if (ret) { |
184 | dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); | 212 | dev_err(runtime->dev, "Headset jack creation failed %d\n", ret); |
185 | return ret; | 213 | return ret; |
186 | } | 214 | } |
187 | 215 | ||
188 | rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack); | 216 | rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack); |
189 | 217 | ||
190 | return ret; | 218 | return ret; |
191 | } | 219 | } |
@@ -239,7 +267,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
239 | .codec_dai_name = "snd-soc-dummy-dai", | 267 | .codec_dai_name = "snd-soc-dummy-dai", |
240 | .codec_name = "snd-soc-dummy", | 268 | .codec_name = "snd-soc-dummy", |
241 | .platform_name = "sst-mfld-platform", | 269 | .platform_name = "sst-mfld-platform", |
242 | .ignore_suspend = 1, | 270 | .nonatomic = true, |
243 | .dynamic = 1, | 271 | .dynamic = 1, |
244 | .dpcm_playback = 1, | 272 | .dpcm_playback = 1, |
245 | .dpcm_capture = 1, | 273 | .dpcm_capture = 1, |
@@ -267,7 +295,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
267 | | SND_SOC_DAIFMT_CBS_CFS, | 295 | | SND_SOC_DAIFMT_CBS_CFS, |
268 | .init = cht_codec_init, | 296 | .init = cht_codec_init, |
269 | .be_hw_params_fixup = cht_codec_fixup, | 297 | .be_hw_params_fixup = cht_codec_fixup, |
270 | .ignore_suspend = 1, | 298 | .nonatomic = true, |
271 | .dpcm_playback = 1, | 299 | .dpcm_playback = 1, |
272 | .dpcm_capture = 1, | 300 | .dpcm_capture = 1, |
273 | .ops = &cht_be_ssp2_ops, | 301 | .ops = &cht_be_ssp2_ops, |
@@ -275,43 +303,85 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
275 | }; | 303 | }; |
276 | 304 | ||
277 | /* SoC card */ | 305 | /* SoC card */ |
278 | static struct snd_soc_card snd_soc_card_cht = { | 306 | static struct snd_soc_card snd_soc_card_chtrt5645 = { |
279 | .name = "chtrt5645", | 307 | .name = "chtrt5645", |
280 | .dai_link = cht_dailink, | 308 | .dai_link = cht_dailink, |
281 | .num_links = ARRAY_SIZE(cht_dailink), | 309 | .num_links = ARRAY_SIZE(cht_dailink), |
282 | .dapm_widgets = cht_dapm_widgets, | 310 | .dapm_widgets = cht_dapm_widgets, |
283 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | 311 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), |
284 | .dapm_routes = cht_audio_map, | 312 | .dapm_routes = cht_rt5645_audio_map, |
285 | .num_dapm_routes = ARRAY_SIZE(cht_audio_map), | 313 | .num_dapm_routes = ARRAY_SIZE(cht_rt5645_audio_map), |
286 | .controls = cht_mc_controls, | 314 | .controls = cht_mc_controls, |
287 | .num_controls = ARRAY_SIZE(cht_mc_controls), | 315 | .num_controls = ARRAY_SIZE(cht_mc_controls), |
288 | }; | 316 | }; |
289 | 317 | ||
318 | static struct snd_soc_card snd_soc_card_chtrt5650 = { | ||
319 | .name = "chtrt5650", | ||
320 | .dai_link = cht_dailink, | ||
321 | .num_links = ARRAY_SIZE(cht_dailink), | ||
322 | .dapm_widgets = cht_dapm_widgets, | ||
323 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | ||
324 | .dapm_routes = cht_rt5650_audio_map, | ||
325 | .num_dapm_routes = ARRAY_SIZE(cht_rt5650_audio_map), | ||
326 | .controls = cht_mc_controls, | ||
327 | .num_controls = ARRAY_SIZE(cht_mc_controls), | ||
328 | }; | ||
329 | |||
330 | static struct cht_acpi_card snd_soc_cards[] = { | ||
331 | {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | ||
332 | {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, | ||
333 | }; | ||
334 | |||
335 | static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level, | ||
336 | void *context, void **ret) | ||
337 | { | ||
338 | *(bool *)context = true; | ||
339 | return AE_OK; | ||
340 | } | ||
341 | |||
290 | static int snd_cht_mc_probe(struct platform_device *pdev) | 342 | static int snd_cht_mc_probe(struct platform_device *pdev) |
291 | { | 343 | { |
292 | int ret_val = 0; | 344 | int ret_val = 0; |
345 | int i; | ||
293 | struct cht_mc_private *drv; | 346 | struct cht_mc_private *drv; |
347 | struct snd_soc_card *card = snd_soc_cards[0].soc_card; | ||
348 | bool found = false; | ||
349 | char codec_name[16]; | ||
294 | 350 | ||
295 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | 351 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); |
296 | if (!drv) | 352 | if (!drv) |
297 | return -ENOMEM; | 353 | return -ENOMEM; |
298 | 354 | ||
299 | snd_soc_card_cht.dev = &pdev->dev; | 355 | for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { |
300 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | 356 | if (ACPI_SUCCESS(acpi_get_devices( |
301 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | 357 | snd_soc_cards[i].codec_id, |
358 | snd_acpi_codec_match, | ||
359 | &found, NULL)) && found) { | ||
360 | dev_dbg(&pdev->dev, | ||
361 | "found codec %s\n", snd_soc_cards[i].codec_id); | ||
362 | card = snd_soc_cards[i].soc_card; | ||
363 | drv->acpi_card = &snd_soc_cards[i]; | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | card->dev = &pdev->dev; | ||
368 | sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id); | ||
369 | /* set correct codec name */ | ||
370 | strcpy((char *)card->dai_link[2].codec_name, codec_name); | ||
371 | snd_soc_card_set_drvdata(card, drv); | ||
372 | ret_val = devm_snd_soc_register_card(&pdev->dev, card); | ||
302 | if (ret_val) { | 373 | if (ret_val) { |
303 | dev_err(&pdev->dev, | 374 | dev_err(&pdev->dev, |
304 | "snd_soc_register_card failed %d\n", ret_val); | 375 | "snd_soc_register_card failed %d\n", ret_val); |
305 | return ret_val; | 376 | return ret_val; |
306 | } | 377 | } |
307 | platform_set_drvdata(pdev, &snd_soc_card_cht); | 378 | platform_set_drvdata(pdev, card); |
308 | return ret_val; | 379 | return ret_val; |
309 | } | 380 | } |
310 | 381 | ||
311 | static struct platform_driver snd_cht_mc_driver = { | 382 | static struct platform_driver snd_cht_mc_driver = { |
312 | .driver = { | 383 | .driver = { |
313 | .name = "cht-bsw-rt5645", | 384 | .name = "cht-bsw-rt5645", |
314 | .pm = &snd_soc_pm_ops, | ||
315 | }, | 385 | }, |
316 | .probe = snd_cht_mc_probe, | 386 | .probe = snd_cht_mc_probe, |
317 | }; | 387 | }; |
diff --git a/sound/soc/intel/common/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c index 42f293f9c6e2..67b6d3d52f57 100644 --- a/sound/soc/intel/common/sst-acpi.c +++ b/sound/soc/intel/common/sst-acpi.c | |||
@@ -263,7 +263,7 @@ static struct sst_acpi_desc sst_acpi_baytrail_desc = { | |||
263 | .resindex_dma_base = -1, | 263 | .resindex_dma_base = -1, |
264 | }; | 264 | }; |
265 | 265 | ||
266 | static struct acpi_device_id sst_acpi_match[] = { | 266 | static const struct acpi_device_id sst_acpi_match[] = { |
267 | { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, | 267 | { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, |
268 | { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, | 268 | { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, |
269 | { "80860F28", (unsigned long)&sst_acpi_baytrail_desc }, | 269 | { "80860F28", (unsigned long)&sst_acpi_baytrail_desc }, |
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index 4b62a553823c..a12c7bb08d3b 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c | |||
@@ -129,11 +129,31 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) | |||
129 | return -ENOMEM; | 129 | return -ENOMEM; |
130 | 130 | ||
131 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | 131 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { |
132 | ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); | ||
133 | if (ipc->msg[i].tx_data == NULL) | ||
134 | goto free_mem; | ||
135 | |||
136 | ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); | ||
137 | if (ipc->msg[i].rx_data == NULL) { | ||
138 | kfree(ipc->msg[i].tx_data); | ||
139 | goto free_mem; | ||
140 | } | ||
141 | |||
132 | init_waitqueue_head(&ipc->msg[i].waitq); | 142 | init_waitqueue_head(&ipc->msg[i].waitq); |
133 | list_add(&ipc->msg[i].list, &ipc->empty_list); | 143 | list_add(&ipc->msg[i].list, &ipc->empty_list); |
134 | } | 144 | } |
135 | 145 | ||
136 | return 0; | 146 | return 0; |
147 | |||
148 | free_mem: | ||
149 | while (i > 0) { | ||
150 | kfree(ipc->msg[i-1].tx_data); | ||
151 | kfree(ipc->msg[i-1].rx_data); | ||
152 | --i; | ||
153 | } | ||
154 | kfree(ipc->msg); | ||
155 | |||
156 | return -ENOMEM; | ||
137 | } | 157 | } |
138 | 158 | ||
139 | static void ipc_tx_msgs(struct kthread_work *work) | 159 | static void ipc_tx_msgs(struct kthread_work *work) |
@@ -142,7 +162,6 @@ static void ipc_tx_msgs(struct kthread_work *work) | |||
142 | container_of(work, struct sst_generic_ipc, kwork); | 162 | container_of(work, struct sst_generic_ipc, kwork); |
143 | struct ipc_message *msg; | 163 | struct ipc_message *msg; |
144 | unsigned long flags; | 164 | unsigned long flags; |
145 | u64 ipcx; | ||
146 | 165 | ||
147 | spin_lock_irqsave(&ipc->dsp->spinlock, flags); | 166 | spin_lock_irqsave(&ipc->dsp->spinlock, flags); |
148 | 167 | ||
@@ -153,8 +172,8 @@ static void ipc_tx_msgs(struct kthread_work *work) | |||
153 | 172 | ||
154 | /* if the DSP is busy, we will TX messages after IRQ. | 173 | /* if the DSP is busy, we will TX messages after IRQ. |
155 | * also postpone if we are in the middle of procesing completion irq*/ | 174 | * also postpone if we are in the middle of procesing completion irq*/ |
156 | ipcx = sst_dsp_shim_read_unlocked(ipc->dsp, SST_IPCX); | 175 | if (ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) { |
157 | if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) { | 176 | dev_dbg(ipc->dev, "ipc_tx_msgs dsp busy\n"); |
158 | spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); | 177 | spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); |
159 | return; | 178 | return; |
160 | } | 179 | } |
@@ -280,11 +299,18 @@ EXPORT_SYMBOL_GPL(sst_ipc_init); | |||
280 | 299 | ||
281 | void sst_ipc_fini(struct sst_generic_ipc *ipc) | 300 | void sst_ipc_fini(struct sst_generic_ipc *ipc) |
282 | { | 301 | { |
302 | int i; | ||
303 | |||
283 | if (ipc->tx_thread) | 304 | if (ipc->tx_thread) |
284 | kthread_stop(ipc->tx_thread); | 305 | kthread_stop(ipc->tx_thread); |
285 | 306 | ||
286 | if (ipc->msg) | 307 | if (ipc->msg) { |
308 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | ||
309 | kfree(ipc->msg[i].tx_data); | ||
310 | kfree(ipc->msg[i].rx_data); | ||
311 | } | ||
287 | kfree(ipc->msg); | 312 | kfree(ipc->msg); |
313 | } | ||
288 | } | 314 | } |
289 | EXPORT_SYMBOL_GPL(sst_ipc_fini); | 315 | EXPORT_SYMBOL_GPL(sst_ipc_fini); |
290 | 316 | ||
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 125ea451a373..ceb7e468a3fa 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h | |||
@@ -32,9 +32,9 @@ struct ipc_message { | |||
32 | u64 header; | 32 | u64 header; |
33 | 33 | ||
34 | /* direction wrt host CPU */ | 34 | /* direction wrt host CPU */ |
35 | char tx_data[IPC_MAX_MAILBOX_BYTES]; | 35 | char *tx_data; |
36 | size_t tx_size; | 36 | size_t tx_size; |
37 | char rx_data[IPC_MAX_MAILBOX_BYTES]; | 37 | char *rx_data; |
38 | size_t rx_size; | 38 | size_t rx_size; |
39 | 39 | ||
40 | wait_queue_head_t waitq; | 40 | wait_queue_head_t waitq; |
@@ -51,6 +51,7 @@ struct sst_plat_ipc_ops { | |||
51 | void (*shim_dbg)(struct sst_generic_ipc *, const char *); | 51 | void (*shim_dbg)(struct sst_generic_ipc *, const char *); |
52 | void (*tx_data_copy)(struct ipc_message *, char *, size_t); | 52 | void (*tx_data_copy)(struct ipc_message *, char *, size_t); |
53 | u64 (*reply_msg_match)(u64 header, u64 *mask); | 53 | u64 (*reply_msg_match)(u64 header, u64 *mask); |
54 | bool (*is_dsp_busy)(struct sst_dsp *dsp); | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | /* SST generic IPC data */ | 57 | /* SST generic IPC data */ |
@@ -68,6 +69,8 @@ struct sst_generic_ipc { | |||
68 | struct kthread_work kwork; | 69 | struct kthread_work kwork; |
69 | bool pending; | 70 | bool pending; |
70 | struct ipc_message *msg; | 71 | struct ipc_message *msg; |
72 | int tx_data_max_size; | ||
73 | int rx_data_max_size; | ||
71 | 74 | ||
72 | struct sst_plat_ipc_ops ops; | 75 | struct sst_plat_ipc_ops ops; |
73 | }; | 76 | }; |
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 344a1e9bbce5..f95f271aab0c 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c | |||
@@ -2098,6 +2098,14 @@ static u64 hsw_reply_msg_match(u64 header, u64 *mask) | |||
2098 | return header; | 2098 | return header; |
2099 | } | 2099 | } |
2100 | 2100 | ||
2101 | static bool hsw_is_dsp_busy(struct sst_dsp *dsp) | ||
2102 | { | ||
2103 | u64 ipcx; | ||
2104 | |||
2105 | ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); | ||
2106 | return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); | ||
2107 | } | ||
2108 | |||
2101 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | 2109 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) |
2102 | { | 2110 | { |
2103 | struct sst_hsw_ipc_fw_version version; | 2111 | struct sst_hsw_ipc_fw_version version; |
@@ -2117,6 +2125,10 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
2117 | ipc->ops.shim_dbg = hsw_shim_dbg; | 2125 | ipc->ops.shim_dbg = hsw_shim_dbg; |
2118 | ipc->ops.tx_data_copy = hsw_tx_data_copy; | 2126 | ipc->ops.tx_data_copy = hsw_tx_data_copy; |
2119 | ipc->ops.reply_msg_match = hsw_reply_msg_match; | 2127 | ipc->ops.reply_msg_match = hsw_reply_msg_match; |
2128 | ipc->ops.is_dsp_busy = hsw_is_dsp_busy; | ||
2129 | |||
2130 | ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES; | ||
2131 | ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES; | ||
2120 | 2132 | ||
2121 | ret = sst_ipc_init(ipc); | 2133 | ret = sst_ipc_init(ipc); |
2122 | if (ret != 0) | 2134 | if (ret != 0) |
@@ -2201,7 +2213,6 @@ dma_err: | |||
2201 | dsp_new_err: | 2213 | dsp_new_err: |
2202 | sst_ipc_fini(ipc); | 2214 | sst_ipc_fini(ipc); |
2203 | ipc_init_err: | 2215 | ipc_init_err: |
2204 | kfree(hsw); | ||
2205 | return ret; | 2216 | return ret; |
2206 | } | 2217 | } |
2207 | EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); | 2218 | EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); |
diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 23ae0400d6db..1aa819c7e09b 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c | |||
@@ -928,10 +928,15 @@ static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) | |||
928 | 928 | ||
929 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { | 929 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
930 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; | 930 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
931 | sst_hsw_runtime_module_free(pcm_data->runtime); | 931 | if (pcm_data->runtime){ |
932 | sst_hsw_runtime_module_free(pcm_data->runtime); | ||
933 | pcm_data->runtime = NULL; | ||
934 | } | ||
932 | } | 935 | } |
933 | if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) { | 936 | if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES) && |
937 | pdata->runtime_waves) { | ||
934 | sst_hsw_runtime_module_free(pdata->runtime_waves); | 938 | sst_hsw_runtime_module_free(pdata->runtime_waves); |
939 | pdata->runtime_waves = NULL; | ||
935 | } | 940 | } |
936 | } | 941 | } |
937 | 942 | ||
@@ -1204,6 +1209,20 @@ static int hsw_pcm_runtime_idle(struct device *dev) | |||
1204 | return 0; | 1209 | return 0; |
1205 | } | 1210 | } |
1206 | 1211 | ||
1212 | static int hsw_pcm_suspend(struct device *dev) | ||
1213 | { | ||
1214 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); | ||
1215 | struct sst_hsw *hsw = pdata->hsw; | ||
1216 | |||
1217 | /* enter D3 state and stall */ | ||
1218 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1219 | /* free all runtime modules */ | ||
1220 | hsw_pcm_free_modules(pdata); | ||
1221 | /* put the DSP to sleep, fw unloaded after runtime modules freed */ | ||
1222 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1223 | return 0; | ||
1224 | } | ||
1225 | |||
1207 | static int hsw_pcm_runtime_suspend(struct device *dev) | 1226 | static int hsw_pcm_runtime_suspend(struct device *dev) |
1208 | { | 1227 | { |
1209 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); | 1228 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); |
@@ -1220,8 +1239,7 @@ static int hsw_pcm_runtime_suspend(struct device *dev) | |||
1220 | return ret; | 1239 | return ret; |
1221 | sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES); | 1240 | sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES); |
1222 | } | 1241 | } |
1223 | sst_hsw_dsp_runtime_suspend(hsw); | 1242 | hsw_pcm_suspend(dev); |
1224 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1225 | pdata->pm_state = HSW_PM_STATE_RTD3; | 1243 | pdata->pm_state = HSW_PM_STATE_RTD3; |
1226 | 1244 | ||
1227 | return 0; | 1245 | return 0; |
@@ -1328,7 +1346,6 @@ static void hsw_pcm_complete(struct device *dev) | |||
1328 | static int hsw_pcm_prepare(struct device *dev) | 1346 | static int hsw_pcm_prepare(struct device *dev) |
1329 | { | 1347 | { |
1330 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); | 1348 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); |
1331 | struct sst_hsw *hsw = pdata->hsw; | ||
1332 | struct hsw_pcm_data *pcm_data; | 1349 | struct hsw_pcm_data *pcm_data; |
1333 | int i, err; | 1350 | int i, err; |
1334 | 1351 | ||
@@ -1361,10 +1378,7 @@ static int hsw_pcm_prepare(struct device *dev) | |||
1361 | if (err < 0) | 1378 | if (err < 0) |
1362 | dev_err(dev, "failed to save context for PCM %d\n", i); | 1379 | dev_err(dev, "failed to save context for PCM %d\n", i); |
1363 | } | 1380 | } |
1364 | /* enter D3 state and stall */ | 1381 | hsw_pcm_suspend(dev); |
1365 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1366 | /* put the DSP to sleep */ | ||
1367 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1368 | } | 1382 | } |
1369 | 1383 | ||
1370 | snd_soc_suspend(pdata->soc_card->dev); | 1384 | snd_soc_suspend(pdata->soc_card->dev); |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 6768e4f7d7d0..30d0109703a9 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -100,12 +100,13 @@ config SND_OMAP_SOC_OMAP_TWL4030 | |||
100 | 100 | ||
101 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 | 101 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 |
102 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" | 102 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" |
103 | depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST) | 103 | depends on TWL6040_CORE && SND_OMAP_SOC |
104 | depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST | ||
104 | select SND_OMAP_SOC_DMIC | 105 | select SND_OMAP_SOC_DMIC |
105 | select SND_OMAP_SOC_MCPDM | 106 | select SND_OMAP_SOC_MCPDM |
106 | select SND_SOC_TWL6040 | 107 | select SND_SOC_TWL6040 |
107 | select SND_SOC_DMIC | 108 | select SND_SOC_DMIC |
108 | select COMMON_CLK_PALMAS if MFD_PALMAS | 109 | select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS) |
109 | help | 110 | help |
110 | Say Y if you want to add support for SoC audio on OMAP boards using | 111 | Say Y if you want to add support for SoC audio on OMAP boards using |
111 | ABE and twl6040 codec. This driver currently supports: | 112 | ABE and twl6040 codec. This driver currently supports: |
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c index 4775da4c4db5..aeef25c0cb3d 100644 --- a/sound/soc/omap/omap-hdmi-audio.c +++ b/sound/soc/omap/omap-hdmi-audio.c | |||
@@ -210,16 +210,18 @@ static int hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
210 | 210 | ||
211 | cea->db3 = 0; /* not used, all zeros */ | 211 | cea->db3 = 0; /* not used, all zeros */ |
212 | 212 | ||
213 | /* | ||
214 | * The OMAP HDMI IP requires to use the 8-channel channel code when | ||
215 | * transmitting more than two channels. | ||
216 | */ | ||
217 | if (params_channels(params) == 2) | 213 | if (params_channels(params) == 2) |
218 | cea->db4_ca = 0x0; | 214 | cea->db4_ca = 0x0; |
215 | else if (params_channels(params) == 6) | ||
216 | cea->db4_ca = 0xb; | ||
219 | else | 217 | else |
220 | cea->db4_ca = 0x13; | 218 | cea->db4_ca = 0x13; |
221 | 219 | ||
222 | cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED; | 220 | if (cea->db4_ca == 0x00) |
221 | cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PERMITTED; | ||
222 | else | ||
223 | cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED; | ||
224 | |||
223 | /* the expression is trivial but makes clear what we are doing */ | 225 | /* the expression is trivial but makes clear what we are doing */ |
224 | cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV); | 226 | cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV); |
225 | 227 | ||
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 3673ada43bfb..743131473056 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c | |||
@@ -159,9 +159,8 @@ static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm, | |||
159 | 159 | ||
160 | static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) | 160 | static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) |
161 | { | 161 | { |
162 | struct snd_soc_codec *codec = rtd->codec; | ||
163 | struct snd_soc_card *card = rtd->card; | 162 | struct snd_soc_card *card = rtd->card; |
164 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 163 | struct snd_soc_dapm_context *dapm = &card->dapm; |
165 | struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev); | 164 | struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev); |
166 | struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); | 165 | struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); |
167 | int ret = 0; | 166 | int ret = 0; |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index c2ddf0fbfa28..3bebfb1d3a6f 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -245,6 +245,8 @@ static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { | |||
245 | static const struct snd_soc_dapm_route audio_map[] = { | 245 | static const struct snd_soc_dapm_route audio_map[] = { |
246 | {"Ext Spk", NULL, "HPLOUT"}, | 246 | {"Ext Spk", NULL, "HPLOUT"}, |
247 | {"Ext Spk", NULL, "HPROUT"}, | 247 | {"Ext Spk", NULL, "HPROUT"}, |
248 | {"Ext Spk", NULL, "HPLCOM"}, | ||
249 | {"Ext Spk", NULL, "HPRCOM"}, | ||
248 | {"Headphone Jack", NULL, "LLOUT"}, | 250 | {"Headphone Jack", NULL, "LLOUT"}, |
249 | {"Headphone Jack", NULL, "RLOUT"}, | 251 | {"Headphone Jack", NULL, "RLOUT"}, |
250 | {"FM Transmitter", NULL, "LLOUT"}, | 252 | {"FM Transmitter", NULL, "LLOUT"}, |
@@ -288,15 +290,8 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) | |||
288 | struct snd_soc_codec *codec = rtd->codec; | 290 | struct snd_soc_codec *codec = rtd->codec; |
289 | struct snd_soc_card *card = rtd->card; | 291 | struct snd_soc_card *card = rtd->card; |
290 | struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); | 292 | struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); |
291 | |||
292 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
293 | int err; | 293 | int err; |
294 | 294 | ||
295 | /* Set up NC codec pins */ | ||
296 | snd_soc_dapm_nc_pin(dapm, "MIC3L"); | ||
297 | snd_soc_dapm_nc_pin(dapm, "MIC3R"); | ||
298 | snd_soc_dapm_nc_pin(dapm, "LINE1R"); | ||
299 | |||
300 | err = tpa6130a2_add_controls(codec); | 295 | err = tpa6130a2_add_controls(codec); |
301 | if (err < 0) { | 296 | if (err < 0) { |
302 | dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); | 297 | dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); |
@@ -383,6 +378,7 @@ static struct snd_soc_card rx51_sound_card = { | |||
383 | .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), | 378 | .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), |
384 | .codec_conf = rx51_codec_conf, | 379 | .codec_conf = rx51_codec_conf, |
385 | .num_configs = ARRAY_SIZE(rx51_codec_conf), | 380 | .num_configs = ARRAY_SIZE(rx51_codec_conf), |
381 | .fully_routed = true, | ||
386 | 382 | ||
387 | .controls = aic34_rx51_controls, | 383 | .controls = aic34_rx51_controls, |
388 | .num_controls = ARRAY_SIZE(aic34_rx51_controls), | 384 | .num_controls = ARRAY_SIZE(aic34_rx51_controls), |
@@ -455,50 +451,36 @@ static int rx51_soc_probe(struct platform_device *pdev) | |||
455 | snd_soc_card_set_drvdata(card, pdata); | 451 | snd_soc_card_set_drvdata(card, pdata); |
456 | 452 | ||
457 | pdata->tvout_selection_gpio = devm_gpiod_get(card->dev, | 453 | pdata->tvout_selection_gpio = devm_gpiod_get(card->dev, |
458 | "tvout-selection"); | 454 | "tvout-selection", |
455 | GPIOD_OUT_LOW); | ||
459 | if (IS_ERR(pdata->tvout_selection_gpio)) { | 456 | if (IS_ERR(pdata->tvout_selection_gpio)) { |
460 | dev_err(card->dev, "could not get tvout selection gpio\n"); | 457 | dev_err(card->dev, "could not get tvout selection gpio\n"); |
461 | return PTR_ERR(pdata->tvout_selection_gpio); | 458 | return PTR_ERR(pdata->tvout_selection_gpio); |
462 | } | 459 | } |
463 | 460 | ||
464 | err = gpiod_direction_output(pdata->tvout_selection_gpio, 0); | ||
465 | if (err) { | ||
466 | dev_err(card->dev, "could not setup tvout selection gpio\n"); | ||
467 | return err; | ||
468 | } | ||
469 | |||
470 | pdata->jack_detection_gpio = devm_gpiod_get(card->dev, | 461 | pdata->jack_detection_gpio = devm_gpiod_get(card->dev, |
471 | "jack-detection"); | 462 | "jack-detection", |
463 | GPIOD_ASIS); | ||
472 | if (IS_ERR(pdata->jack_detection_gpio)) { | 464 | if (IS_ERR(pdata->jack_detection_gpio)) { |
473 | dev_err(card->dev, "could not get jack detection gpio\n"); | 465 | dev_err(card->dev, "could not get jack detection gpio\n"); |
474 | return PTR_ERR(pdata->jack_detection_gpio); | 466 | return PTR_ERR(pdata->jack_detection_gpio); |
475 | } | 467 | } |
476 | 468 | ||
477 | pdata->eci_sw_gpio = devm_gpiod_get(card->dev, "eci-switch"); | 469 | pdata->eci_sw_gpio = devm_gpiod_get(card->dev, "eci-switch", |
470 | GPIOD_OUT_HIGH); | ||
478 | if (IS_ERR(pdata->eci_sw_gpio)) { | 471 | if (IS_ERR(pdata->eci_sw_gpio)) { |
479 | dev_err(card->dev, "could not get eci switch gpio\n"); | 472 | dev_err(card->dev, "could not get eci switch gpio\n"); |
480 | return PTR_ERR(pdata->eci_sw_gpio); | 473 | return PTR_ERR(pdata->eci_sw_gpio); |
481 | } | 474 | } |
482 | 475 | ||
483 | err = gpiod_direction_output(pdata->eci_sw_gpio, 1); | ||
484 | if (err) { | ||
485 | dev_err(card->dev, "could not setup eci switch gpio\n"); | ||
486 | return err; | ||
487 | } | ||
488 | |||
489 | pdata->speaker_amp_gpio = devm_gpiod_get(card->dev, | 476 | pdata->speaker_amp_gpio = devm_gpiod_get(card->dev, |
490 | "speaker-amplifier"); | 477 | "speaker-amplifier", |
478 | GPIOD_OUT_LOW); | ||
491 | if (IS_ERR(pdata->speaker_amp_gpio)) { | 479 | if (IS_ERR(pdata->speaker_amp_gpio)) { |
492 | dev_err(card->dev, "could not get speaker enable gpio\n"); | 480 | dev_err(card->dev, "could not get speaker enable gpio\n"); |
493 | return PTR_ERR(pdata->speaker_amp_gpio); | 481 | return PTR_ERR(pdata->speaker_amp_gpio); |
494 | } | 482 | } |
495 | 483 | ||
496 | err = gpiod_direction_output(pdata->speaker_amp_gpio, 0); | ||
497 | if (err) { | ||
498 | dev_err(card->dev, "could not setup speaker enable gpio\n"); | ||
499 | return err; | ||
500 | } | ||
501 | |||
502 | err = devm_snd_soc_register_card(card->dev, card); | 484 | err = devm_snd_soc_register_card(card->dev, card); |
503 | if (err) { | 485 | if (err) { |
504 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err); | 486 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err); |
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 79936e3e80e7..2b26318bc200 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c | |||
@@ -45,29 +45,6 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = { | |||
45 | {"MICBIAS1", NULL, "Main Mic"}, | 45 | {"MICBIAS1", NULL, "Main Mic"}, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
49 | { | ||
50 | struct snd_soc_codec *codec = rtd->codec; | ||
51 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
52 | |||
53 | /* set endpoints to not connected */ | ||
54 | snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); | ||
55 | snd_soc_dapm_nc_pin(dapm, "HPOUT2N"); | ||
56 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); | ||
57 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); | ||
58 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); | ||
59 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); | ||
60 | snd_soc_dapm_nc_pin(dapm, "IN1LN"); | ||
61 | snd_soc_dapm_nc_pin(dapm, "IN1LP"); | ||
62 | snd_soc_dapm_nc_pin(dapm, "IN1RP"); | ||
63 | snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); | ||
64 | snd_soc_dapm_nc_pin(dapm, "IN2RN"); | ||
65 | snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); | ||
66 | snd_soc_dapm_nc_pin(dapm, "IN2LN"); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, | 48 | static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, |
72 | struct snd_pcm_hw_params *params) | 49 | struct snd_pcm_hw_params *params) |
73 | { | 50 | { |
@@ -115,7 +92,6 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = { | |||
115 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 92 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
116 | SND_SOC_DAIFMT_CBS_CFS, | 93 | SND_SOC_DAIFMT_CBS_CFS, |
117 | .ops = &brownstone_ops, | 94 | .ops = &brownstone_ops, |
118 | .init = brownstone_wm8994_init, | ||
119 | }, | 95 | }, |
120 | }; | 96 | }; |
121 | 97 | ||
@@ -132,6 +108,7 @@ static struct snd_soc_card brownstone = { | |||
132 | .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), | 108 | .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), |
133 | .dapm_routes = brownstone_audio_map, | 109 | .dapm_routes = brownstone_audio_map, |
134 | .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), | 110 | .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), |
111 | .fully_routed = true, | ||
135 | }; | 112 | }; |
136 | 113 | ||
137 | static int brownstone_probe(struct platform_device *pdev) | 114 | static int brownstone_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 0fce8c420e96..80b457ac522a 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -192,6 +192,7 @@ static int poodle_amp_event(struct snd_soc_dapm_widget *w, | |||
192 | static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { | 192 | static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { |
193 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 193 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
194 | SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), | 194 | SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), |
195 | SND_SOC_DAPM_MIC("Microphone", NULL), | ||
195 | }; | 196 | }; |
196 | 197 | ||
197 | /* Corgi machine connections to the codec pins */ | 198 | /* Corgi machine connections to the codec pins */ |
@@ -204,6 +205,8 @@ static const struct snd_soc_dapm_route poodle_audio_map[] = { | |||
204 | /* speaker connected to LOUT, ROUT */ | 205 | /* speaker connected to LOUT, ROUT */ |
205 | {"Ext Spk", NULL, "ROUT"}, | 206 | {"Ext Spk", NULL, "ROUT"}, |
206 | {"Ext Spk", NULL, "LOUT"}, | 207 | {"Ext Spk", NULL, "LOUT"}, |
208 | |||
209 | {"MICIN", NULL, "Microphone"}, | ||
207 | }; | 210 | }; |
208 | 211 | ||
209 | static const char *jack_function[] = {"Off", "Headphone"}; | 212 | static const char *jack_function[] = {"Off", "Headphone"}; |
@@ -220,20 +223,6 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { | |||
220 | poodle_set_spk), | 223 | poodle_set_spk), |
221 | }; | 224 | }; |
222 | 225 | ||
223 | /* | ||
224 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device | ||
225 | */ | ||
226 | static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) | ||
227 | { | ||
228 | struct snd_soc_codec *codec = rtd->codec; | ||
229 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
230 | |||
231 | snd_soc_dapm_nc_pin(dapm, "LLINEIN"); | ||
232 | snd_soc_dapm_nc_pin(dapm, "RLINEIN"); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | /* poodle digital audio interface glue - connects codec <--> CPU */ | 226 | /* poodle digital audio interface glue - connects codec <--> CPU */ |
238 | static struct snd_soc_dai_link poodle_dai = { | 227 | static struct snd_soc_dai_link poodle_dai = { |
239 | .name = "WM8731", | 228 | .name = "WM8731", |
@@ -242,7 +231,6 @@ static struct snd_soc_dai_link poodle_dai = { | |||
242 | .codec_dai_name = "wm8731-hifi", | 231 | .codec_dai_name = "wm8731-hifi", |
243 | .platform_name = "pxa-pcm-audio", | 232 | .platform_name = "pxa-pcm-audio", |
244 | .codec_name = "wm8731.0-001b", | 233 | .codec_name = "wm8731.0-001b", |
245 | .init = poodle_wm8731_init, | ||
246 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 234 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
247 | SND_SOC_DAIFMT_CBS_CFS, | 235 | SND_SOC_DAIFMT_CBS_CFS, |
248 | .ops = &poodle_ops, | 236 | .ops = &poodle_ops, |
@@ -261,6 +249,7 @@ static struct snd_soc_card poodle = { | |||
261 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), | 249 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), |
262 | .dapm_routes = poodle_audio_map, | 250 | .dapm_routes = poodle_audio_map, |
263 | .num_dapm_routes = ARRAY_SIZE(poodle_audio_map), | 251 | .num_dapm_routes = ARRAY_SIZE(poodle_audio_map), |
252 | .fully_routed = true, | ||
264 | }; | 253 | }; |
265 | 254 | ||
266 | static int poodle_probe(struct platform_device *pdev) | 255 | static int poodle_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index cb49284e853a..f59f566551ef 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -185,17 +185,6 @@ static const struct snd_kcontrol_new tosa_controls[] = { | |||
185 | tosa_set_spk), | 185 | tosa_set_spk), |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) | ||
189 | { | ||
190 | struct snd_soc_codec *codec = rtd->codec; | ||
191 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
192 | |||
193 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | ||
194 | snd_soc_dapm_nc_pin(dapm, "MONOOUT"); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static struct snd_soc_dai_link tosa_dai[] = { | 188 | static struct snd_soc_dai_link tosa_dai[] = { |
200 | { | 189 | { |
201 | .name = "AC97", | 190 | .name = "AC97", |
@@ -204,7 +193,6 @@ static struct snd_soc_dai_link tosa_dai[] = { | |||
204 | .codec_dai_name = "wm9712-hifi", | 193 | .codec_dai_name = "wm9712-hifi", |
205 | .platform_name = "pxa-pcm-audio", | 194 | .platform_name = "pxa-pcm-audio", |
206 | .codec_name = "wm9712-codec", | 195 | .codec_name = "wm9712-codec", |
207 | .init = tosa_ac97_init, | ||
208 | .ops = &tosa_ops, | 196 | .ops = &tosa_ops, |
209 | }, | 197 | }, |
210 | { | 198 | { |
@@ -230,6 +218,7 @@ static struct snd_soc_card tosa = { | |||
230 | .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), | 218 | .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), |
231 | .dapm_routes = audio_map, | 219 | .dapm_routes = audio_map, |
232 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 220 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
221 | .fully_routed = true, | ||
233 | }; | 222 | }; |
234 | 223 | ||
235 | static int tosa_probe(struct platform_device *pdev) | 224 | static int tosa_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index bcbfbe8303f7..990b1aa6d7f6 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c | |||
@@ -132,16 +132,8 @@ static const struct snd_soc_dapm_route z2_audio_map[] = { | |||
132 | */ | 132 | */ |
133 | static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) | 133 | static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) |
134 | { | 134 | { |
135 | struct snd_soc_codec *codec = rtd->codec; | ||
136 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
137 | int ret; | 135 | int ret; |
138 | 136 | ||
139 | /* NC codec pins */ | ||
140 | snd_soc_dapm_disable_pin(dapm, "LINPUT3"); | ||
141 | snd_soc_dapm_disable_pin(dapm, "RINPUT3"); | ||
142 | snd_soc_dapm_disable_pin(dapm, "OUT3"); | ||
143 | snd_soc_dapm_disable_pin(dapm, "MONO1"); | ||
144 | |||
145 | /* Jack detection API stuff */ | 137 | /* Jack detection API stuff */ |
146 | ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET, | 138 | ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET, |
147 | &hs_jack, hs_jack_pins, | 139 | &hs_jack, hs_jack_pins, |
@@ -189,6 +181,7 @@ static struct snd_soc_card snd_soc_z2 = { | |||
189 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), | 181 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), |
190 | .dapm_routes = z2_audio_map, | 182 | .dapm_routes = z2_audio_map, |
191 | .num_dapm_routes = ARRAY_SIZE(z2_audio_map), | 183 | .num_dapm_routes = ARRAY_SIZE(z2_audio_map), |
184 | .fully_routed = true, | ||
192 | }; | 185 | }; |
193 | 186 | ||
194 | static struct platform_device *z2_snd_device; | 187 | static struct platform_device *z2_snd_device; |
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 5f58e4f1bca9..807fedfa1c76 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig | |||
@@ -6,20 +6,38 @@ config SND_SOC_QCOM | |||
6 | 6 | ||
7 | config SND_SOC_LPASS_CPU | 7 | config SND_SOC_LPASS_CPU |
8 | tristate | 8 | tristate |
9 | depends on SND_SOC_QCOM | ||
10 | select REGMAP_MMIO | 9 | select REGMAP_MMIO |
11 | 10 | ||
12 | config SND_SOC_LPASS_PLATFORM | 11 | config SND_SOC_LPASS_PLATFORM |
13 | tristate | 12 | tristate |
14 | depends on SND_SOC_QCOM | ||
15 | select REGMAP_MMIO | 13 | select REGMAP_MMIO |
16 | 14 | ||
17 | config SND_SOC_STORM | 15 | config SND_SOC_LPASS_IPQ806X |
18 | tristate "ASoC I2S support for Storm boards" | 16 | tristate |
19 | depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST | 17 | depends on SND_SOC_QCOM |
18 | select SND_SOC_LPASS_CPU | ||
19 | select SND_SOC_LPASS_PLATFORM | ||
20 | |||
21 | config SND_SOC_LPASS_APQ8016 | ||
22 | tristate | ||
23 | depends on SND_SOC_QCOM | ||
20 | select SND_SOC_LPASS_CPU | 24 | select SND_SOC_LPASS_CPU |
21 | select SND_SOC_LPASS_PLATFORM | 25 | select SND_SOC_LPASS_PLATFORM |
26 | |||
27 | config SND_SOC_STORM | ||
28 | tristate "ASoC I2S support for Storm boards" | ||
29 | depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) | ||
30 | select SND_SOC_LPASS_IPQ806X | ||
22 | select SND_SOC_MAX98357A | 31 | select SND_SOC_MAX98357A |
23 | help | 32 | help |
24 | Say Y or M if you want add support for SoC audio on the | 33 | Say Y or M if you want add support for SoC audio on the |
25 | Qualcomm Technologies IPQ806X-based Storm board. | 34 | Qualcomm Technologies IPQ806X-based Storm board. |
35 | |||
36 | config SND_SOC_APQ8016_SBC | ||
37 | tristate "SoC Audio support for APQ8016 SBC platforms" | ||
38 | depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) | ||
39 | select SND_SOC_LPASS_APQ8016 | ||
40 | help | ||
41 | Support for Qualcomm Technologies LPASS audio block in | ||
42 | APQ8016 SOC-based systems. | ||
43 | Say Y if you want to use audio devices on MI2S. | ||
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index c5ce96c761c4..79e5c50a8f71 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile | |||
@@ -1,11 +1,17 @@ | |||
1 | # Platform | 1 | # Platform |
2 | snd-soc-lpass-cpu-objs := lpass-cpu.o | 2 | snd-soc-lpass-cpu-objs := lpass-cpu.o |
3 | snd-soc-lpass-platform-objs := lpass-platform.o | 3 | snd-soc-lpass-platform-objs := lpass-platform.o |
4 | snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o | ||
5 | snd-soc-lpass-apq8016-objs := lpass-apq8016.o | ||
4 | 6 | ||
5 | obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o | 7 | obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o |
6 | obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o | 8 | obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o |
9 | obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o | ||
10 | obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o | ||
7 | 11 | ||
8 | # Machine | 12 | # Machine |
9 | snd-soc-storm-objs := storm.o | 13 | snd-soc-storm-objs := storm.o |
14 | snd-soc-apq8016-sbc-objs := apq8016_sbc.o | ||
10 | 15 | ||
11 | obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o | 16 | obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o |
17 | obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o | ||
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c new file mode 100644 index 000000000000..1efdf0088ecd --- /dev/null +++ b/sound/soc/qcom/apq8016_sbc.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <dt-bindings/sound/apq8016-lpass.h> | ||
26 | |||
27 | struct apq8016_sbc_data { | ||
28 | void __iomem *mic_iomux; | ||
29 | void __iomem *spkr_iomux; | ||
30 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ | ||
31 | }; | ||
32 | |||
33 | #define MIC_CTRL_QUA_WS_SLAVE_SEL_10 BIT(17) | ||
34 | #define MIC_CTRL_TLMM_SCLK_EN BIT(1) | ||
35 | #define SPKR_CTL_PRI_WS_SLAVE_SEL_11 (BIT(17) | BIT(16)) | ||
36 | |||
37 | static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
38 | { | ||
39 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
40 | struct snd_soc_card *card = rtd->card; | ||
41 | struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); | ||
42 | int rval = 0; | ||
43 | |||
44 | switch (cpu_dai->id) { | ||
45 | case MI2S_PRIMARY: | ||
46 | writel(readl(pdata->spkr_iomux) | SPKR_CTL_PRI_WS_SLAVE_SEL_11, | ||
47 | pdata->spkr_iomux); | ||
48 | break; | ||
49 | |||
50 | case MI2S_QUATERNARY: | ||
51 | /* Configure the Quat MI2S to TLMM */ | ||
52 | writel(readl(pdata->mic_iomux) | MIC_CTRL_QUA_WS_SLAVE_SEL_10 | | ||
53 | MIC_CTRL_TLMM_SCLK_EN, | ||
54 | pdata->mic_iomux); | ||
55 | break; | ||
56 | |||
57 | default: | ||
58 | dev_err(card->dev, "unsupported cpu dai configuration\n"); | ||
59 | rval = -EINVAL; | ||
60 | break; | ||
61 | |||
62 | } | ||
63 | |||
64 | return rval; | ||
65 | } | ||
66 | |||
67 | static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) | ||
68 | { | ||
69 | struct device *dev = card->dev; | ||
70 | struct snd_soc_dai_link *link; | ||
71 | struct device_node *np, *codec, *cpu, *node = dev->of_node; | ||
72 | struct apq8016_sbc_data *data; | ||
73 | int ret, num_links; | ||
74 | |||
75 | ret = snd_soc_of_parse_card_name(card, "qcom,model"); | ||
76 | if (ret) { | ||
77 | dev_err(dev, "Error parsing card name: %d\n", ret); | ||
78 | return ERR_PTR(ret); | ||
79 | } | ||
80 | |||
81 | /* Populate links */ | ||
82 | num_links = of_get_child_count(node); | ||
83 | |||
84 | /* Allocate the private data and the DAI link array */ | ||
85 | data = devm_kzalloc(dev, sizeof(*data) + sizeof(*link) * num_links, | ||
86 | GFP_KERNEL); | ||
87 | if (!data) | ||
88 | return ERR_PTR(-ENOMEM); | ||
89 | |||
90 | card->dai_link = &data->dai_link[0]; | ||
91 | card->num_links = num_links; | ||
92 | |||
93 | link = data->dai_link; | ||
94 | |||
95 | for_each_child_of_node(node, np) { | ||
96 | cpu = of_get_child_by_name(np, "cpu"); | ||
97 | codec = of_get_child_by_name(np, "codec"); | ||
98 | |||
99 | if (!cpu || !codec) { | ||
100 | dev_err(dev, "Can't find cpu/codec DT node\n"); | ||
101 | return ERR_PTR(-EINVAL); | ||
102 | } | ||
103 | |||
104 | link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); | ||
105 | if (!link->cpu_of_node) { | ||
106 | dev_err(card->dev, "error getting cpu phandle\n"); | ||
107 | return ERR_PTR(-EINVAL); | ||
108 | } | ||
109 | |||
110 | link->codec_of_node = of_parse_phandle(codec, "sound-dai", 0); | ||
111 | if (!link->codec_of_node) { | ||
112 | dev_err(card->dev, "error getting codec phandle\n"); | ||
113 | return ERR_PTR(-EINVAL); | ||
114 | } | ||
115 | |||
116 | ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); | ||
117 | if (ret) { | ||
118 | dev_err(card->dev, "error getting cpu dai name\n"); | ||
119 | return ERR_PTR(ret); | ||
120 | } | ||
121 | |||
122 | ret = snd_soc_of_get_dai_name(codec, &link->codec_dai_name); | ||
123 | if (ret) { | ||
124 | dev_err(card->dev, "error getting codec dai name\n"); | ||
125 | return ERR_PTR(ret); | ||
126 | } | ||
127 | |||
128 | link->platform_of_node = link->cpu_of_node; | ||
129 | /* For now we only support playback */ | ||
130 | link->playback_only = true; | ||
131 | |||
132 | ret = of_property_read_string(np, "link-name", &link->name); | ||
133 | if (ret) { | ||
134 | dev_err(card->dev, "error getting codec dai_link name\n"); | ||
135 | return ERR_PTR(ret); | ||
136 | } | ||
137 | |||
138 | link->stream_name = link->name; | ||
139 | link->init = apq8016_sbc_dai_init; | ||
140 | link++; | ||
141 | } | ||
142 | |||
143 | return data; | ||
144 | } | ||
145 | |||
146 | static int apq8016_sbc_platform_probe(struct platform_device *pdev) | ||
147 | { | ||
148 | struct device *dev = &pdev->dev; | ||
149 | struct snd_soc_card *card; | ||
150 | struct apq8016_sbc_data *data; | ||
151 | struct resource *res; | ||
152 | |||
153 | card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); | ||
154 | if (!card) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | card->dev = dev; | ||
158 | data = apq8016_sbc_parse_of(card); | ||
159 | if (IS_ERR(data)) { | ||
160 | dev_err(&pdev->dev, "Error resolving dai links: %ld\n", | ||
161 | PTR_ERR(data)); | ||
162 | return PTR_ERR(data); | ||
163 | } | ||
164 | |||
165 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mic-iomux"); | ||
166 | data->mic_iomux = devm_ioremap_resource(dev, res); | ||
167 | if (IS_ERR(data->mic_iomux)) | ||
168 | return PTR_ERR(data->mic_iomux); | ||
169 | |||
170 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spkr-iomux"); | ||
171 | data->spkr_iomux = devm_ioremap_resource(dev, res); | ||
172 | if (IS_ERR(data->spkr_iomux)) | ||
173 | return PTR_ERR(data->spkr_iomux); | ||
174 | |||
175 | platform_set_drvdata(pdev, data); | ||
176 | snd_soc_card_set_drvdata(card, data); | ||
177 | |||
178 | return devm_snd_soc_register_card(&pdev->dev, card); | ||
179 | } | ||
180 | |||
181 | static const struct of_device_id apq8016_sbc_device_id[] = { | ||
182 | { .compatible = "qcom,apq8016-sbc-sndcard" }, | ||
183 | {}, | ||
184 | }; | ||
185 | MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id); | ||
186 | |||
187 | static struct platform_driver apq8016_sbc_platform_driver = { | ||
188 | .driver = { | ||
189 | .name = "qcom-apq8016-sbc", | ||
190 | .of_match_table = of_match_ptr(apq8016_sbc_device_id), | ||
191 | }, | ||
192 | .probe = apq8016_sbc_platform_probe, | ||
193 | }; | ||
194 | module_platform_driver(apq8016_sbc_platform_driver); | ||
195 | |||
196 | MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org"); | ||
197 | MODULE_DESCRIPTION("APQ8016 ASoC Machine Driver"); | ||
198 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c new file mode 100644 index 000000000000..94efc01020c4 --- /dev/null +++ b/sound/soc/qcom/lpass-apq8016.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * lpass-apq8016.c -- ALSA SoC CPU DAI driver for APQ8016 LPASS | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dai.h> | ||
29 | |||
30 | #include <dt-bindings/sound/apq8016-lpass.h> | ||
31 | #include "lpass-lpaif-reg.h" | ||
32 | #include "lpass.h" | ||
33 | |||
34 | static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = { | ||
35 | [MI2S_PRIMARY] = { | ||
36 | .id = MI2S_PRIMARY, | ||
37 | .name = "Primary MI2S", | ||
38 | .playback = { | ||
39 | .stream_name = "Primary Playback", | ||
40 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
41 | SNDRV_PCM_FMTBIT_S24 | | ||
42 | SNDRV_PCM_FMTBIT_S32, | ||
43 | .rates = SNDRV_PCM_RATE_8000 | | ||
44 | SNDRV_PCM_RATE_16000 | | ||
45 | SNDRV_PCM_RATE_32000 | | ||
46 | SNDRV_PCM_RATE_48000 | | ||
47 | SNDRV_PCM_RATE_96000, | ||
48 | .rate_min = 8000, | ||
49 | .rate_max = 96000, | ||
50 | .channels_min = 1, | ||
51 | .channels_max = 8, | ||
52 | }, | ||
53 | .probe = &asoc_qcom_lpass_cpu_dai_probe, | ||
54 | .ops = &asoc_qcom_lpass_cpu_dai_ops, | ||
55 | }, | ||
56 | [MI2S_SECONDARY] = { | ||
57 | .id = MI2S_SECONDARY, | ||
58 | .name = "Secondary MI2S", | ||
59 | .playback = { | ||
60 | .stream_name = "Secondary Playback", | ||
61 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
62 | SNDRV_PCM_FMTBIT_S24 | | ||
63 | SNDRV_PCM_FMTBIT_S32, | ||
64 | .rates = SNDRV_PCM_RATE_8000 | | ||
65 | SNDRV_PCM_RATE_16000 | | ||
66 | SNDRV_PCM_RATE_32000 | | ||
67 | SNDRV_PCM_RATE_48000 | | ||
68 | SNDRV_PCM_RATE_96000, | ||
69 | .rate_min = 8000, | ||
70 | .rate_max = 96000, | ||
71 | .channels_min = 1, | ||
72 | .channels_max = 8, | ||
73 | }, | ||
74 | .probe = &asoc_qcom_lpass_cpu_dai_probe, | ||
75 | .ops = &asoc_qcom_lpass_cpu_dai_ops, | ||
76 | }, | ||
77 | [MI2S_TERTIARY] = { | ||
78 | .id = MI2S_TERTIARY, | ||
79 | .name = "Tertiary MI2S", | ||
80 | .capture = { | ||
81 | .stream_name = "Tertiary Capture", | ||
82 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
83 | SNDRV_PCM_FMTBIT_S24 | | ||
84 | SNDRV_PCM_FMTBIT_S32, | ||
85 | .rates = SNDRV_PCM_RATE_8000 | | ||
86 | SNDRV_PCM_RATE_16000 | | ||
87 | SNDRV_PCM_RATE_32000 | | ||
88 | SNDRV_PCM_RATE_48000 | | ||
89 | SNDRV_PCM_RATE_96000, | ||
90 | .rate_min = 8000, | ||
91 | .rate_max = 96000, | ||
92 | .channels_min = 1, | ||
93 | .channels_max = 8, | ||
94 | }, | ||
95 | .probe = &asoc_qcom_lpass_cpu_dai_probe, | ||
96 | .ops = &asoc_qcom_lpass_cpu_dai_ops, | ||
97 | }, | ||
98 | [MI2S_QUATERNARY] = { | ||
99 | .id = MI2S_QUATERNARY, | ||
100 | .name = "Quatenary MI2S", | ||
101 | .playback = { | ||
102 | .stream_name = "Quatenary Playback", | ||
103 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
104 | SNDRV_PCM_FMTBIT_S24 | | ||
105 | SNDRV_PCM_FMTBIT_S32, | ||
106 | .rates = SNDRV_PCM_RATE_8000 | | ||
107 | SNDRV_PCM_RATE_16000 | | ||
108 | SNDRV_PCM_RATE_32000 | | ||
109 | SNDRV_PCM_RATE_48000 | | ||
110 | SNDRV_PCM_RATE_96000, | ||
111 | .rate_min = 8000, | ||
112 | .rate_max = 96000, | ||
113 | .channels_min = 1, | ||
114 | .channels_max = 8, | ||
115 | }, | ||
116 | .capture = { | ||
117 | .stream_name = "Quatenary Capture", | ||
118 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
119 | SNDRV_PCM_FMTBIT_S24 | | ||
120 | SNDRV_PCM_FMTBIT_S32, | ||
121 | .rates = SNDRV_PCM_RATE_8000 | | ||
122 | SNDRV_PCM_RATE_16000 | | ||
123 | SNDRV_PCM_RATE_32000 | | ||
124 | SNDRV_PCM_RATE_48000 | | ||
125 | SNDRV_PCM_RATE_96000, | ||
126 | .rate_min = 8000, | ||
127 | .rate_max = 96000, | ||
128 | .channels_min = 1, | ||
129 | .channels_max = 8, | ||
130 | }, | ||
131 | .probe = &asoc_qcom_lpass_cpu_dai_probe, | ||
132 | .ops = &asoc_qcom_lpass_cpu_dai_ops, | ||
133 | }, | ||
134 | }; | ||
135 | |||
136 | static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata) | ||
137 | { | ||
138 | struct lpass_variant *v = drvdata->variant; | ||
139 | int chan = find_first_zero_bit(&drvdata->rdma_ch_bit_map, | ||
140 | v->rdma_channels); | ||
141 | |||
142 | if (chan >= v->rdma_channels) | ||
143 | return -EBUSY; | ||
144 | |||
145 | set_bit(chan, &drvdata->rdma_ch_bit_map); | ||
146 | |||
147 | return chan; | ||
148 | } | ||
149 | |||
150 | static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) | ||
151 | { | ||
152 | clear_bit(chan, &drvdata->rdma_ch_bit_map); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int apq8016_lpass_init(struct platform_device *pdev) | ||
158 | { | ||
159 | struct lpass_data *drvdata = platform_get_drvdata(pdev); | ||
160 | struct device *dev = &pdev->dev; | ||
161 | int ret; | ||
162 | |||
163 | drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); | ||
164 | if (IS_ERR(drvdata->pcnoc_mport_clk)) { | ||
165 | dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n", | ||
166 | __func__, PTR_ERR(drvdata->pcnoc_mport_clk)); | ||
167 | return PTR_ERR(drvdata->pcnoc_mport_clk); | ||
168 | } | ||
169 | |||
170 | ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); | ||
171 | if (ret) { | ||
172 | dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n", | ||
173 | __func__, ret); | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); | ||
178 | if (IS_ERR(drvdata->pcnoc_sway_clk)) { | ||
179 | dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n", | ||
180 | __func__, PTR_ERR(drvdata->pcnoc_sway_clk)); | ||
181 | return PTR_ERR(drvdata->pcnoc_sway_clk); | ||
182 | } | ||
183 | |||
184 | ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); | ||
185 | if (ret) { | ||
186 | dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n", | ||
187 | __func__, ret); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int apq8016_lpass_exit(struct platform_device *pdev) | ||
195 | { | ||
196 | struct lpass_data *drvdata = platform_get_drvdata(pdev); | ||
197 | |||
198 | clk_disable_unprepare(drvdata->pcnoc_mport_clk); | ||
199 | clk_disable_unprepare(drvdata->pcnoc_sway_clk); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | |||
205 | static struct lpass_variant apq8016_data = { | ||
206 | .i2sctrl_reg_base = 0x1000, | ||
207 | .i2sctrl_reg_stride = 0x1000, | ||
208 | .i2s_ports = 4, | ||
209 | .irq_reg_base = 0x6000, | ||
210 | .irq_reg_stride = 0x1000, | ||
211 | .irq_ports = 3, | ||
212 | .rdma_reg_base = 0x8400, | ||
213 | .rdma_reg_stride = 0x1000, | ||
214 | .rdma_channels = 2, | ||
215 | .rdmactl_audif_start = 1, | ||
216 | .dai_driver = apq8016_lpass_cpu_dai_driver, | ||
217 | .num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver), | ||
218 | .init = apq8016_lpass_init, | ||
219 | .exit = apq8016_lpass_exit, | ||
220 | .alloc_dma_channel = apq8016_lpass_alloc_dma_channel, | ||
221 | .free_dma_channel = apq8016_lpass_free_dma_channel, | ||
222 | }; | ||
223 | |||
224 | static const struct of_device_id apq8016_lpass_cpu_device_id[] = { | ||
225 | { .compatible = "qcom,lpass-cpu-apq8016", .data = &apq8016_data }, | ||
226 | {} | ||
227 | }; | ||
228 | MODULE_DEVICE_TABLE(of, apq8016_lpass_cpu_device_id); | ||
229 | |||
230 | static struct platform_driver apq8016_lpass_cpu_platform_driver = { | ||
231 | .driver = { | ||
232 | .name = "apq8016-lpass-cpu", | ||
233 | .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id), | ||
234 | }, | ||
235 | .probe = asoc_qcom_lpass_cpu_platform_probe, | ||
236 | .remove = asoc_qcom_lpass_cpu_platform_remove, | ||
237 | }; | ||
238 | module_platform_driver(apq8016_lpass_cpu_platform_driver); | ||
239 | |||
240 | MODULE_DESCRIPTION("APQ8016 LPASS CPU Driver"); | ||
241 | MODULE_LICENSE("GPL v2"); | ||
242 | |||
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 6698d058de29..23f3d59e6d09 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c | |||
@@ -14,21 +14,17 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/compiler.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/ioport.h> | ||
21 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
22 | #include <linux/mod_devicetable.h> | ||
23 | #include <linux/module.h> | 18 | #include <linux/module.h> |
24 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_device.h> | ||
25 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
26 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
28 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
29 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
30 | #include <sound/soc-dai.h> | 26 | #include <sound/soc-dai.h> |
31 | #include "lpass-lpaif-ipq806x.h" | 27 | #include "lpass-lpaif-reg.h" |
32 | #include "lpass.h" | 28 | #include "lpass.h" |
33 | 29 | ||
34 | static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 30 | static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
@@ -37,7 +33,10 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
37 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 33 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
38 | int ret; | 34 | int ret; |
39 | 35 | ||
40 | ret = clk_set_rate(drvdata->mi2s_osr_clk, freq); | 36 | if (IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) |
37 | return 0; | ||
38 | |||
39 | ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); | ||
41 | if (ret) | 40 | if (ret) |
42 | dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", | 41 | dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", |
43 | __func__, freq, ret); | 42 | __func__, freq, ret); |
@@ -51,18 +50,23 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, | |||
51 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 50 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
52 | int ret; | 51 | int ret; |
53 | 52 | ||
54 | ret = clk_prepare_enable(drvdata->mi2s_osr_clk); | 53 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) { |
55 | if (ret) { | 54 | ret = clk_prepare_enable( |
56 | dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", | 55 | drvdata->mi2s_osr_clk[dai->driver->id]); |
57 | __func__, ret); | 56 | if (ret) { |
58 | return ret; | 57 | dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", |
58 | __func__, ret); | ||
59 | return ret; | ||
60 | } | ||
59 | } | 61 | } |
60 | 62 | ||
61 | ret = clk_prepare_enable(drvdata->mi2s_bit_clk); | 63 | ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); |
62 | if (ret) { | 64 | if (ret) { |
63 | dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", | 65 | dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", |
64 | __func__, ret); | 66 | __func__, ret); |
65 | clk_disable_unprepare(drvdata->mi2s_osr_clk); | 67 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) |
68 | clk_disable_unprepare( | ||
69 | drvdata->mi2s_osr_clk[dai->driver->id]); | ||
66 | return ret; | 70 | return ret; |
67 | } | 71 | } |
68 | 72 | ||
@@ -74,8 +78,10 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, | |||
74 | { | 78 | { |
75 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 79 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
76 | 80 | ||
77 | clk_disable_unprepare(drvdata->mi2s_bit_clk); | 81 | clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); |
78 | clk_disable_unprepare(drvdata->mi2s_osr_clk); | 82 | |
83 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) | ||
84 | clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); | ||
79 | } | 85 | } |
80 | 86 | ||
81 | static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | 87 | static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, |
@@ -142,14 +148,16 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
142 | } | 148 | } |
143 | 149 | ||
144 | ret = regmap_write(drvdata->lpaif_map, | 150 | ret = regmap_write(drvdata->lpaif_map, |
145 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), regval); | 151 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
152 | regval); | ||
146 | if (ret) { | 153 | if (ret) { |
147 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 154 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", |
148 | __func__, ret); | 155 | __func__, ret); |
149 | return ret; | 156 | return ret; |
150 | } | 157 | } |
151 | 158 | ||
152 | ret = clk_set_rate(drvdata->mi2s_bit_clk, rate * bitwidth * 2); | 159 | ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], |
160 | rate * bitwidth * 2); | ||
153 | if (ret) { | 161 | if (ret) { |
154 | dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", | 162 | dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", |
155 | __func__, rate * bitwidth * 2, ret); | 163 | __func__, rate * bitwidth * 2, ret); |
@@ -166,7 +174,8 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, | |||
166 | int ret; | 174 | int ret; |
167 | 175 | ||
168 | ret = regmap_write(drvdata->lpaif_map, | 176 | ret = regmap_write(drvdata->lpaif_map, |
169 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); | 177 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
178 | 0); | ||
170 | if (ret) | 179 | if (ret) |
171 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 180 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", |
172 | __func__, ret); | 181 | __func__, ret); |
@@ -181,7 +190,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, | |||
181 | int ret; | 190 | int ret; |
182 | 191 | ||
183 | ret = regmap_update_bits(drvdata->lpaif_map, | 192 | ret = regmap_update_bits(drvdata->lpaif_map, |
184 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), | 193 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
185 | LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); | 194 | LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); |
186 | if (ret) | 195 | if (ret) |
187 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 196 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", |
@@ -194,14 +203,15 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
194 | int cmd, struct snd_soc_dai *dai) | 203 | int cmd, struct snd_soc_dai *dai) |
195 | { | 204 | { |
196 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 205 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
197 | int ret; | 206 | int ret = -EINVAL; |
198 | 207 | ||
199 | switch (cmd) { | 208 | switch (cmd) { |
200 | case SNDRV_PCM_TRIGGER_START: | 209 | case SNDRV_PCM_TRIGGER_START: |
201 | case SNDRV_PCM_TRIGGER_RESUME: | 210 | case SNDRV_PCM_TRIGGER_RESUME: |
202 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 211 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
203 | ret = regmap_update_bits(drvdata->lpaif_map, | 212 | ret = regmap_update_bits(drvdata->lpaif_map, |
204 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), | 213 | LPAIF_I2SCTL_REG(drvdata->variant, |
214 | dai->driver->id), | ||
205 | LPAIF_I2SCTL_SPKEN_MASK, | 215 | LPAIF_I2SCTL_SPKEN_MASK, |
206 | LPAIF_I2SCTL_SPKEN_ENABLE); | 216 | LPAIF_I2SCTL_SPKEN_ENABLE); |
207 | if (ret) | 217 | if (ret) |
@@ -212,7 +222,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
212 | case SNDRV_PCM_TRIGGER_SUSPEND: | 222 | case SNDRV_PCM_TRIGGER_SUSPEND: |
213 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 223 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
214 | ret = regmap_update_bits(drvdata->lpaif_map, | 224 | ret = regmap_update_bits(drvdata->lpaif_map, |
215 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), | 225 | LPAIF_I2SCTL_REG(drvdata->variant, |
226 | dai->driver->id), | ||
216 | LPAIF_I2SCTL_SPKEN_MASK, | 227 | LPAIF_I2SCTL_SPKEN_MASK, |
217 | LPAIF_I2SCTL_SPKEN_DISABLE); | 228 | LPAIF_I2SCTL_SPKEN_DISABLE); |
218 | if (ret) | 229 | if (ret) |
@@ -224,7 +235,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
224 | return ret; | 235 | return ret; |
225 | } | 236 | } |
226 | 237 | ||
227 | static struct snd_soc_dai_ops lpass_cpu_dai_ops = { | 238 | struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { |
228 | .set_sysclk = lpass_cpu_daiops_set_sysclk, | 239 | .set_sysclk = lpass_cpu_daiops_set_sysclk, |
229 | .startup = lpass_cpu_daiops_startup, | 240 | .startup = lpass_cpu_daiops_startup, |
230 | .shutdown = lpass_cpu_daiops_shutdown, | 241 | .shutdown = lpass_cpu_daiops_shutdown, |
@@ -233,41 +244,23 @@ static struct snd_soc_dai_ops lpass_cpu_dai_ops = { | |||
233 | .prepare = lpass_cpu_daiops_prepare, | 244 | .prepare = lpass_cpu_daiops_prepare, |
234 | .trigger = lpass_cpu_daiops_trigger, | 245 | .trigger = lpass_cpu_daiops_trigger, |
235 | }; | 246 | }; |
247 | EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops); | ||
236 | 248 | ||
237 | static int lpass_cpu_dai_probe(struct snd_soc_dai *dai) | 249 | int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) |
238 | { | 250 | { |
239 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 251 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
240 | int ret; | 252 | int ret; |
241 | 253 | ||
242 | /* ensure audio hardware is disabled */ | 254 | /* ensure audio hardware is disabled */ |
243 | ret = regmap_write(drvdata->lpaif_map, | 255 | ret = regmap_write(drvdata->lpaif_map, |
244 | LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); | 256 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); |
245 | if (ret) | 257 | if (ret) |
246 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 258 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", |
247 | __func__, ret); | 259 | __func__, ret); |
248 | 260 | ||
249 | return ret; | 261 | return ret; |
250 | } | 262 | } |
251 | 263 | EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe); | |
252 | static struct snd_soc_dai_driver lpass_cpu_dai_driver = { | ||
253 | .playback = { | ||
254 | .stream_name = "lpass-cpu-playback", | ||
255 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
256 | SNDRV_PCM_FMTBIT_S24 | | ||
257 | SNDRV_PCM_FMTBIT_S32, | ||
258 | .rates = SNDRV_PCM_RATE_8000 | | ||
259 | SNDRV_PCM_RATE_16000 | | ||
260 | SNDRV_PCM_RATE_32000 | | ||
261 | SNDRV_PCM_RATE_48000 | | ||
262 | SNDRV_PCM_RATE_96000, | ||
263 | .rate_min = 8000, | ||
264 | .rate_max = 96000, | ||
265 | .channels_min = 1, | ||
266 | .channels_max = 8, | ||
267 | }, | ||
268 | .probe = &lpass_cpu_dai_probe, | ||
269 | .ops = &lpass_cpu_dai_ops, | ||
270 | }; | ||
271 | 264 | ||
272 | static const struct snd_soc_component_driver lpass_cpu_comp_driver = { | 265 | static const struct snd_soc_component_driver lpass_cpu_comp_driver = { |
273 | .name = "lpass-cpu", | 266 | .name = "lpass-cpu", |
@@ -275,27 +268,29 @@ static const struct snd_soc_component_driver lpass_cpu_comp_driver = { | |||
275 | 268 | ||
276 | static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) | 269 | static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) |
277 | { | 270 | { |
271 | struct lpass_data *drvdata = dev_get_drvdata(dev); | ||
272 | struct lpass_variant *v = drvdata->variant; | ||
278 | int i; | 273 | int i; |
279 | 274 | ||
280 | for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) | 275 | for (i = 0; i < v->i2s_ports; ++i) |
281 | if (reg == LPAIF_I2SCTL_REG(i)) | 276 | if (reg == LPAIF_I2SCTL_REG(v, i)) |
282 | return true; | 277 | return true; |
283 | 278 | ||
284 | for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { | 279 | for (i = 0; i < v->irq_ports; ++i) { |
285 | if (reg == LPAIF_IRQEN_REG(i)) | 280 | if (reg == LPAIF_IRQEN_REG(v, i)) |
286 | return true; | 281 | return true; |
287 | if (reg == LPAIF_IRQCLEAR_REG(i)) | 282 | if (reg == LPAIF_IRQCLEAR_REG(v, i)) |
288 | return true; | 283 | return true; |
289 | } | 284 | } |
290 | 285 | ||
291 | for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { | 286 | for (i = 0; i < v->rdma_channels; ++i) { |
292 | if (reg == LPAIF_RDMACTL_REG(i)) | 287 | if (reg == LPAIF_RDMACTL_REG(v, i)) |
293 | return true; | 288 | return true; |
294 | if (reg == LPAIF_RDMABASE_REG(i)) | 289 | if (reg == LPAIF_RDMABASE_REG(v, i)) |
295 | return true; | 290 | return true; |
296 | if (reg == LPAIF_RDMABUFF_REG(i)) | 291 | if (reg == LPAIF_RDMABUFF_REG(v, i)) |
297 | return true; | 292 | return true; |
298 | if (reg == LPAIF_RDMAPER_REG(i)) | 293 | if (reg == LPAIF_RDMAPER_REG(v, i)) |
299 | return true; | 294 | return true; |
300 | } | 295 | } |
301 | 296 | ||
@@ -304,29 +299,31 @@ static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) | |||
304 | 299 | ||
305 | static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) | 300 | static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) |
306 | { | 301 | { |
302 | struct lpass_data *drvdata = dev_get_drvdata(dev); | ||
303 | struct lpass_variant *v = drvdata->variant; | ||
307 | int i; | 304 | int i; |
308 | 305 | ||
309 | for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) | 306 | for (i = 0; i < v->i2s_ports; ++i) |
310 | if (reg == LPAIF_I2SCTL_REG(i)) | 307 | if (reg == LPAIF_I2SCTL_REG(v, i)) |
311 | return true; | 308 | return true; |
312 | 309 | ||
313 | for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { | 310 | for (i = 0; i < v->irq_ports; ++i) { |
314 | if (reg == LPAIF_IRQEN_REG(i)) | 311 | if (reg == LPAIF_IRQEN_REG(v, i)) |
315 | return true; | 312 | return true; |
316 | if (reg == LPAIF_IRQSTAT_REG(i)) | 313 | if (reg == LPAIF_IRQSTAT_REG(v, i)) |
317 | return true; | 314 | return true; |
318 | } | 315 | } |
319 | 316 | ||
320 | for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { | 317 | for (i = 0; i < v->rdma_channels; ++i) { |
321 | if (reg == LPAIF_RDMACTL_REG(i)) | 318 | if (reg == LPAIF_RDMACTL_REG(v, i)) |
322 | return true; | 319 | return true; |
323 | if (reg == LPAIF_RDMABASE_REG(i)) | 320 | if (reg == LPAIF_RDMABASE_REG(v, i)) |
324 | return true; | 321 | return true; |
325 | if (reg == LPAIF_RDMABUFF_REG(i)) | 322 | if (reg == LPAIF_RDMABUFF_REG(v, i)) |
326 | return true; | 323 | return true; |
327 | if (reg == LPAIF_RDMACURR_REG(i)) | 324 | if (reg == LPAIF_RDMACURR_REG(v, i)) |
328 | return true; | 325 | return true; |
329 | if (reg == LPAIF_RDMAPER_REG(i)) | 326 | if (reg == LPAIF_RDMAPER_REG(v, i)) |
330 | return true; | 327 | return true; |
331 | } | 328 | } |
332 | 329 | ||
@@ -335,36 +332,41 @@ static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) | |||
335 | 332 | ||
336 | static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) | 333 | static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) |
337 | { | 334 | { |
335 | struct lpass_data *drvdata = dev_get_drvdata(dev); | ||
336 | struct lpass_variant *v = drvdata->variant; | ||
338 | int i; | 337 | int i; |
339 | 338 | ||
340 | for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) | 339 | for (i = 0; i < v->irq_ports; ++i) |
341 | if (reg == LPAIF_IRQSTAT_REG(i)) | 340 | if (reg == LPAIF_IRQSTAT_REG(v, i)) |
342 | return true; | 341 | return true; |
343 | 342 | ||
344 | for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) | 343 | for (i = 0; i < v->rdma_channels; ++i) |
345 | if (reg == LPAIF_RDMACURR_REG(i)) | 344 | if (reg == LPAIF_RDMACURR_REG(v, i)) |
346 | return true; | 345 | return true; |
347 | 346 | ||
348 | return false; | 347 | return false; |
349 | } | 348 | } |
350 | 349 | ||
351 | static const struct regmap_config lpass_cpu_regmap_config = { | 350 | static struct regmap_config lpass_cpu_regmap_config = { |
352 | .reg_bits = 32, | 351 | .reg_bits = 32, |
353 | .reg_stride = 4, | 352 | .reg_stride = 4, |
354 | .val_bits = 32, | 353 | .val_bits = 32, |
355 | .max_register = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MAX), | ||
356 | .writeable_reg = lpass_cpu_regmap_writeable, | 354 | .writeable_reg = lpass_cpu_regmap_writeable, |
357 | .readable_reg = lpass_cpu_regmap_readable, | 355 | .readable_reg = lpass_cpu_regmap_readable, |
358 | .volatile_reg = lpass_cpu_regmap_volatile, | 356 | .volatile_reg = lpass_cpu_regmap_volatile, |
359 | .cache_type = REGCACHE_FLAT, | 357 | .cache_type = REGCACHE_FLAT, |
360 | }; | 358 | }; |
361 | 359 | ||
362 | static int lpass_cpu_platform_probe(struct platform_device *pdev) | 360 | int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) |
363 | { | 361 | { |
364 | struct lpass_data *drvdata; | 362 | struct lpass_data *drvdata; |
365 | struct device_node *dsp_of_node; | 363 | struct device_node *dsp_of_node; |
366 | struct resource *res; | 364 | struct resource *res; |
367 | int ret; | 365 | struct lpass_variant *variant; |
366 | struct device *dev = &pdev->dev; | ||
367 | const struct of_device_id *match; | ||
368 | char clk_name[16]; | ||
369 | int ret, i, dai_id; | ||
368 | 370 | ||
369 | dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); | 371 | dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); |
370 | if (dsp_of_node) { | 372 | if (dsp_of_node) { |
@@ -379,11 +381,14 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) | |||
379 | return -ENOMEM; | 381 | return -ENOMEM; |
380 | platform_set_drvdata(pdev, drvdata); | 382 | platform_set_drvdata(pdev, drvdata); |
381 | 383 | ||
384 | match = of_match_device(dev->driver->of_match_table, dev); | ||
385 | if (!match || !match->data) | ||
386 | return -EINVAL; | ||
387 | |||
388 | drvdata->variant = (struct lpass_variant *)match->data; | ||
389 | variant = drvdata->variant; | ||
390 | |||
382 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); | 391 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); |
383 | if (!res) { | ||
384 | dev_err(&pdev->dev, "%s() error getting resource\n", __func__); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | 392 | ||
388 | drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); | 393 | drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); |
389 | if (IS_ERR((void const __force *)drvdata->lpaif)) { | 394 | if (IS_ERR((void const __force *)drvdata->lpaif)) { |
@@ -393,6 +398,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) | |||
393 | return PTR_ERR((void const __force *)drvdata->lpaif); | 398 | return PTR_ERR((void const __force *)drvdata->lpaif); |
394 | } | 399 | } |
395 | 400 | ||
401 | lpass_cpu_regmap_config.max_register = LPAIF_RDMAPER_REG(variant, | ||
402 | variant->rdma_channels); | ||
403 | |||
396 | drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, | 404 | drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, |
397 | &lpass_cpu_regmap_config); | 405 | &lpass_cpu_regmap_config); |
398 | if (IS_ERR(drvdata->lpaif_map)) { | 406 | if (IS_ERR(drvdata->lpaif_map)) { |
@@ -401,18 +409,38 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) | |||
401 | return PTR_ERR(drvdata->lpaif_map); | 409 | return PTR_ERR(drvdata->lpaif_map); |
402 | } | 410 | } |
403 | 411 | ||
404 | drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk"); | 412 | if (variant->init) |
405 | if (IS_ERR(drvdata->mi2s_osr_clk)) { | 413 | variant->init(pdev); |
406 | dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", | 414 | |
407 | __func__, PTR_ERR(drvdata->mi2s_osr_clk)); | 415 | for (i = 0; i < variant->num_dai; i++) { |
408 | return PTR_ERR(drvdata->mi2s_osr_clk); | 416 | dai_id = variant->dai_driver[i].id; |
409 | } | 417 | if (variant->num_dai > 1) |
410 | 418 | sprintf(clk_name, "mi2s-osr-clk%d", i); | |
411 | drvdata->mi2s_bit_clk = devm_clk_get(&pdev->dev, "mi2s-bit-clk"); | 419 | else |
412 | if (IS_ERR(drvdata->mi2s_bit_clk)) { | 420 | sprintf(clk_name, "mi2s-osr-clk"); |
413 | dev_err(&pdev->dev, "%s() error getting mi2s-bit-clk: %ld\n", | 421 | |
414 | __func__, PTR_ERR(drvdata->mi2s_bit_clk)); | 422 | drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev, |
415 | return PTR_ERR(drvdata->mi2s_bit_clk); | 423 | clk_name); |
424 | if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { | ||
425 | dev_warn(&pdev->dev, | ||
426 | "%s() error getting mi2s-osr-clk: %ld\n", | ||
427 | __func__, | ||
428 | PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); | ||
429 | } | ||
430 | |||
431 | if (variant->num_dai > 1) | ||
432 | sprintf(clk_name, "mi2s-bit-clk%d", i); | ||
433 | else | ||
434 | sprintf(clk_name, "mi2s-bit-clk"); | ||
435 | |||
436 | drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev, | ||
437 | clk_name); | ||
438 | if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { | ||
439 | dev_err(&pdev->dev, | ||
440 | "%s() error getting mi2s-bit-clk: %ld\n", | ||
441 | __func__, PTR_ERR(drvdata->mi2s_bit_clk[i])); | ||
442 | return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); | ||
443 | } | ||
416 | } | 444 | } |
417 | 445 | ||
418 | drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); | 446 | drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); |
@@ -439,7 +467,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) | |||
439 | } | 467 | } |
440 | 468 | ||
441 | ret = devm_snd_soc_register_component(&pdev->dev, | 469 | ret = devm_snd_soc_register_component(&pdev->dev, |
442 | &lpass_cpu_comp_driver, &lpass_cpu_dai_driver, 1); | 470 | &lpass_cpu_comp_driver, |
471 | variant->dai_driver, | ||
472 | variant->num_dai); | ||
443 | if (ret) { | 473 | if (ret) { |
444 | dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", | 474 | dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", |
445 | __func__, ret); | 475 | __func__, ret); |
@@ -459,33 +489,17 @@ err_clk: | |||
459 | clk_disable_unprepare(drvdata->ahbix_clk); | 489 | clk_disable_unprepare(drvdata->ahbix_clk); |
460 | return ret; | 490 | return ret; |
461 | } | 491 | } |
492 | EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe); | ||
462 | 493 | ||
463 | static int lpass_cpu_platform_remove(struct platform_device *pdev) | 494 | int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) |
464 | { | 495 | { |
465 | struct lpass_data *drvdata = platform_get_drvdata(pdev); | 496 | struct lpass_data *drvdata = platform_get_drvdata(pdev); |
466 | 497 | ||
498 | if (drvdata->variant->exit) | ||
499 | drvdata->variant->exit(pdev); | ||
500 | |||
467 | clk_disable_unprepare(drvdata->ahbix_clk); | 501 | clk_disable_unprepare(drvdata->ahbix_clk); |
468 | 502 | ||
469 | return 0; | 503 | return 0; |
470 | } | 504 | } |
471 | 505 | EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); | |
472 | #ifdef CONFIG_OF | ||
473 | static const struct of_device_id lpass_cpu_device_id[] = { | ||
474 | { .compatible = "qcom,lpass-cpu" }, | ||
475 | {} | ||
476 | }; | ||
477 | MODULE_DEVICE_TABLE(of, lpass_cpu_device_id); | ||
478 | #endif | ||
479 | |||
480 | static struct platform_driver lpass_cpu_platform_driver = { | ||
481 | .driver = { | ||
482 | .name = "lpass-cpu", | ||
483 | .of_match_table = of_match_ptr(lpass_cpu_device_id), | ||
484 | }, | ||
485 | .probe = lpass_cpu_platform_probe, | ||
486 | .remove = lpass_cpu_platform_remove, | ||
487 | }; | ||
488 | module_platform_driver(lpass_cpu_platform_driver); | ||
489 | |||
490 | MODULE_DESCRIPTION("QTi LPASS CPU Driver"); | ||
491 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c new file mode 100644 index 000000000000..7356d3a766d6 --- /dev/null +++ b/sound/soc/qcom/lpass-ipq806x.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * lpass-ipq806x.c -- ALSA SoC CPU DAI driver for QTi LPASS | ||
14 | * Splited out the IPQ8064 soc specific from lpass-cpu.c | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dai.h> | ||
27 | |||
28 | #include "lpass-lpaif-reg.h" | ||
29 | #include "lpass.h" | ||
30 | |||
31 | enum lpaif_i2s_ports { | ||
32 | IPQ806X_LPAIF_I2S_PORT_CODEC_SPK, | ||
33 | IPQ806X_LPAIF_I2S_PORT_CODEC_MIC, | ||
34 | IPQ806X_LPAIF_I2S_PORT_SEC_SPK, | ||
35 | IPQ806X_LPAIF_I2S_PORT_SEC_MIC, | ||
36 | IPQ806X_LPAIF_I2S_PORT_MI2S, | ||
37 | }; | ||
38 | |||
39 | enum lpaif_dma_channels { | ||
40 | IPQ806X_LPAIF_RDMA_CHAN_MI2S, | ||
41 | IPQ806X_LPAIF_RDMA_CHAN_PCM0, | ||
42 | IPQ806X_LPAIF_RDMA_CHAN_PCM1, | ||
43 | }; | ||
44 | |||
45 | static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { | ||
46 | .id = IPQ806X_LPAIF_I2S_PORT_MI2S, | ||
47 | .playback = { | ||
48 | .stream_name = "lpass-cpu-playback", | ||
49 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
50 | SNDRV_PCM_FMTBIT_S24 | | ||
51 | SNDRV_PCM_FMTBIT_S32, | ||
52 | .rates = SNDRV_PCM_RATE_8000 | | ||
53 | SNDRV_PCM_RATE_16000 | | ||
54 | SNDRV_PCM_RATE_32000 | | ||
55 | SNDRV_PCM_RATE_48000 | | ||
56 | SNDRV_PCM_RATE_96000, | ||
57 | .rate_min = 8000, | ||
58 | .rate_max = 96000, | ||
59 | .channels_min = 1, | ||
60 | .channels_max = 8, | ||
61 | }, | ||
62 | .probe = &asoc_qcom_lpass_cpu_dai_probe, | ||
63 | .ops = &asoc_qcom_lpass_cpu_dai_ops, | ||
64 | }; | ||
65 | |||
66 | static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata) | ||
67 | { | ||
68 | return IPQ806X_LPAIF_RDMA_CHAN_MI2S; | ||
69 | } | ||
70 | |||
71 | static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) | ||
72 | { | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | struct lpass_variant ipq806x_data = { | ||
77 | .i2sctrl_reg_base = 0x0010, | ||
78 | .i2sctrl_reg_stride = 0x04, | ||
79 | .i2s_ports = 5, | ||
80 | .irq_reg_base = 0x3000, | ||
81 | .irq_reg_stride = 0x1000, | ||
82 | .irq_ports = 3, | ||
83 | .rdma_reg_base = 0x6000, | ||
84 | .rdma_reg_stride = 0x1000, | ||
85 | .rdma_channels = 4, | ||
86 | .dai_driver = &ipq806x_lpass_cpu_dai_driver, | ||
87 | .num_dai = 1, | ||
88 | .alloc_dma_channel = ipq806x_lpass_alloc_dma_channel, | ||
89 | .free_dma_channel = ipq806x_lpass_free_dma_channel, | ||
90 | }; | ||
91 | |||
92 | static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { | ||
93 | { .compatible = "qcom,lpass-cpu", .data = &ipq806x_data }, | ||
94 | {} | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE(of, ipq806x_lpass_cpu_device_id); | ||
97 | |||
98 | static struct platform_driver ipq806x_lpass_cpu_platform_driver = { | ||
99 | .driver = { | ||
100 | .name = "lpass-cpu", | ||
101 | .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id), | ||
102 | }, | ||
103 | .probe = asoc_qcom_lpass_cpu_platform_probe, | ||
104 | .remove = asoc_qcom_lpass_cpu_platform_remove, | ||
105 | }; | ||
106 | module_platform_driver(ipq806x_lpass_cpu_platform_driver); | ||
107 | |||
108 | MODULE_DESCRIPTION("QTi LPASS CPU Driver"); | ||
109 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/qcom/lpass-lpaif-ipq806x.h b/sound/soc/qcom/lpass-lpaif-reg.h index dc423b888842..95e22f131052 100644 --- a/sound/soc/qcom/lpass-lpaif-ipq806x.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h | |||
@@ -9,37 +9,17 @@ | |||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. | 11 | * GNU General Public License for more details. |
12 | * | ||
13 | * lpass-lpaif-ipq806x.h -- Definitions for the QTi LPAIF in the ipq806x LPASS | ||
14 | */ | 12 | */ |
15 | 13 | ||
16 | #ifndef __LPASS_LPAIF_H__ | 14 | #ifndef __LPASS_LPAIF_REG_H__ |
17 | #define __LPASS_LPAIF_H__ | 15 | #define __LPASS_LPAIF_REG_H__ |
18 | |||
19 | #define LPAIF_BANK_OFFSET 0x1000 | ||
20 | 16 | ||
21 | /* LPAIF I2S */ | 17 | /* LPAIF I2S */ |
22 | 18 | ||
23 | #define LPAIF_I2SCTL_REG_BASE 0x0010 | 19 | #define LPAIF_I2SCTL_REG_ADDR(v, addr, port) \ |
24 | #define LPAIF_I2SCTL_REG_STRIDE 0x4 | 20 | (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port)) |
25 | #define LPAIF_I2SCTL_REG_ADDR(addr, port) \ | ||
26 | (LPAIF_I2SCTL_REG_BASE + (addr) + (LPAIF_I2SCTL_REG_STRIDE * (port))) | ||
27 | |||
28 | enum lpaif_i2s_ports { | ||
29 | LPAIF_I2S_PORT_MIN = 0, | ||
30 | |||
31 | LPAIF_I2S_PORT_CODEC_SPK = 0, | ||
32 | LPAIF_I2S_PORT_CODEC_MIC = 1, | ||
33 | LPAIF_I2S_PORT_SEC_SPK = 2, | ||
34 | LPAIF_I2S_PORT_SEC_MIC = 3, | ||
35 | LPAIF_I2S_PORT_MI2S = 4, | ||
36 | |||
37 | LPAIF_I2S_PORT_MAX = 4, | ||
38 | LPAIF_I2S_PORT_NUM = 5, | ||
39 | }; | ||
40 | |||
41 | #define LPAIF_I2SCTL_REG(port) LPAIF_I2SCTL_REG_ADDR(0x0, (port)) | ||
42 | 21 | ||
22 | #define LPAIF_I2SCTL_REG(v, port) LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port)) | ||
43 | #define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 | 23 | #define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 |
44 | #define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 | 24 | #define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 |
45 | #define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) | 25 | #define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) |
@@ -79,55 +59,36 @@ enum lpaif_i2s_ports { | |||
79 | #define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) | 59 | #define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) |
80 | 60 | ||
81 | /* LPAIF IRQ */ | 61 | /* LPAIF IRQ */ |
62 | #define LPAIF_IRQ_REG_ADDR(v, addr, port) \ | ||
63 | (v->irq_reg_base + (addr) + v->irq_reg_stride * (port)) | ||
82 | 64 | ||
83 | #define LPAIF_IRQ_REG_BASE 0x3000 | 65 | #define LPAIF_IRQ_PORT_HOST 0 |
84 | #define LPAIF_IRQ_REG_STRIDE 0x1000 | ||
85 | #define LPAIF_IRQ_REG_ADDR(addr, port) \ | ||
86 | (LPAIF_IRQ_REG_BASE + (addr) + (LPAIF_IRQ_REG_STRIDE * (port))) | ||
87 | |||
88 | enum lpaif_irq_ports { | ||
89 | LPAIF_IRQ_PORT_MIN = 0, | ||
90 | 66 | ||
91 | LPAIF_IRQ_PORT_HOST = 0, | 67 | #define LPAIF_IRQEN_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x0, (port)) |
92 | LPAIF_IRQ_PORT_ADSP = 1, | 68 | #define LPAIF_IRQSTAT_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x4, (port)) |
93 | 69 | #define LPAIF_IRQCLEAR_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0xC, (port)) | |
94 | LPAIF_IRQ_PORT_MAX = 2, | ||
95 | LPAIF_IRQ_PORT_NUM = 3, | ||
96 | }; | ||
97 | |||
98 | #define LPAIF_IRQEN_REG(port) LPAIF_IRQ_REG_ADDR(0x0, (port)) | ||
99 | #define LPAIF_IRQSTAT_REG(port) LPAIF_IRQ_REG_ADDR(0x4, (port)) | ||
100 | #define LPAIF_IRQCLEAR_REG(port) LPAIF_IRQ_REG_ADDR(0xC, (port)) | ||
101 | 70 | ||
102 | #define LPAIF_IRQ_BITSTRIDE 3 | 71 | #define LPAIF_IRQ_BITSTRIDE 3 |
72 | |||
103 | #define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) | 73 | #define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) |
104 | #define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) | 74 | #define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) |
105 | #define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) | 75 | #define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) |
76 | |||
106 | #define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) | 77 | #define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) |
107 | 78 | ||
108 | /* LPAIF DMA */ | 79 | /* LPAIF DMA */ |
109 | 80 | ||
110 | #define LPAIF_RDMA_REG_BASE 0x6000 | 81 | #define LPAIF_RDMA_REG_ADDR(v, addr, chan) \ |
111 | #define LPAIF_RDMA_REG_STRIDE 0x1000 | 82 | (v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan)) |
112 | #define LPAIF_RDMA_REG_ADDR(addr, chan) \ | ||
113 | (LPAIF_RDMA_REG_BASE + (addr) + (LPAIF_RDMA_REG_STRIDE * (chan))) | ||
114 | |||
115 | enum lpaif_dma_channels { | ||
116 | LPAIF_RDMA_CHAN_MIN = 0, | ||
117 | |||
118 | LPAIF_RDMA_CHAN_MI2S = 0, | ||
119 | LPAIF_RDMA_CHAN_PCM0 = 1, | ||
120 | LPAIF_RDMA_CHAN_PCM1 = 2, | ||
121 | 83 | ||
122 | LPAIF_RDMA_CHAN_MAX = 4, | 84 | #define LPAIF_RDMACTL_AUDINTF(id) (id << LPAIF_RDMACTL_AUDINTF_SHIFT) |
123 | LPAIF_RDMA_CHAN_NUM = 5, | ||
124 | }; | ||
125 | 85 | ||
126 | #define LPAIF_RDMACTL_REG(chan) LPAIF_RDMA_REG_ADDR(0x00, (chan)) | 86 | #define LPAIF_RDMACTL_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x00, (chan)) |
127 | #define LPAIF_RDMABASE_REG(chan) LPAIF_RDMA_REG_ADDR(0x04, (chan)) | 87 | #define LPAIF_RDMABASE_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x04, (chan)) |
128 | #define LPAIF_RDMABUFF_REG(chan) LPAIF_RDMA_REG_ADDR(0x08, (chan)) | 88 | #define LPAIF_RDMABUFF_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x08, (chan)) |
129 | #define LPAIF_RDMACURR_REG(chan) LPAIF_RDMA_REG_ADDR(0x0C, (chan)) | 89 | #define LPAIF_RDMACURR_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x0C, (chan)) |
130 | #define LPAIF_RDMAPER_REG(chan) LPAIF_RDMA_REG_ADDR(0x10, (chan)) | 90 | #define LPAIF_RDMAPER_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x10, (chan)) |
91 | #define LPAIF_RDMAPERCNT_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x14, (chan)) | ||
131 | 92 | ||
132 | #define LPAIF_RDMACTL_BURSTEN_MASK 0x800 | 93 | #define LPAIF_RDMACTL_BURSTEN_MASK 0x800 |
133 | #define LPAIF_RDMACTL_BURSTEN_SHIFT 11 | 94 | #define LPAIF_RDMACTL_BURSTEN_SHIFT 11 |
@@ -145,13 +106,6 @@ enum lpaif_dma_channels { | |||
145 | 106 | ||
146 | #define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 | 107 | #define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 |
147 | #define LPAIF_RDMACTL_AUDINTF_SHIFT 4 | 108 | #define LPAIF_RDMACTL_AUDINTF_SHIFT 4 |
148 | #define LPAIF_RDMACTL_AUDINTF_NONE (0 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
149 | #define LPAIF_RDMACTL_AUDINTF_CODEC (1 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
150 | #define LPAIF_RDMACTL_AUDINTF_PCM (2 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
151 | #define LPAIF_RDMACTL_AUDINTF_SEC_I2S (3 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
152 | #define LPAIF_RDMACTL_AUDINTF_MI2S (4 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
153 | #define LPAIF_RDMACTL_AUDINTF_HDMI (5 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
154 | #define LPAIF_RDMACTL_AUDINTF_SEC_PCM (7 << LPAIF_RDMACTL_AUDINTF_SHIFT) | ||
155 | 109 | ||
156 | #define LPAIF_RDMACTL_FIFOWM_MASK 0x00E | 110 | #define LPAIF_RDMACTL_FIFOWM_MASK 0x00E |
157 | #define LPAIF_RDMACTL_FIFOWM_SHIFT 1 | 111 | #define LPAIF_RDMACTL_FIFOWM_SHIFT 1 |
@@ -169,4 +123,4 @@ enum lpaif_dma_channels { | |||
169 | #define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) | 123 | #define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) |
170 | #define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) | 124 | #define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) |
171 | 125 | ||
172 | #endif /* __LPASS_LPAIF_H__ */ | 126 | #endif /* __LPASS_LPAIF_REG_H__ */ |
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 2fa6280dfb23..79688aa1941a 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c | |||
@@ -13,23 +13,22 @@ | |||
13 | * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS | 13 | * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/compiler.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
19 | #include <linux/err.h> | ||
20 | #include <linux/export.h> | 17 | #include <linux/export.h> |
21 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 19 | #include <linux/module.h> |
23 | #include <linux/io.h> | ||
24 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
25 | #include <sound/memalloc.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | 21 | #include <sound/pcm_params.h> |
28 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
29 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
30 | #include "lpass-lpaif-ipq806x.h" | 24 | #include "lpass-lpaif-reg.h" |
31 | #include "lpass.h" | 25 | #include "lpass.h" |
32 | 26 | ||
27 | struct lpass_pcm_data { | ||
28 | int rdma_ch; | ||
29 | int i2s_port; | ||
30 | }; | ||
31 | |||
33 | #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) | 32 | #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) |
34 | #define LPASS_PLATFORM_PERIODS 2 | 33 | #define LPASS_PLATFORM_PERIODS 2 |
35 | 34 | ||
@@ -84,13 +83,15 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
84 | struct snd_pcm_hw_params *params) | 83 | struct snd_pcm_hw_params *params) |
85 | { | 84 | { |
86 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 85 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
86 | struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
87 | struct lpass_data *drvdata = | 87 | struct lpass_data *drvdata = |
88 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 88 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
89 | struct lpass_variant *v = drvdata->variant; | ||
89 | snd_pcm_format_t format = params_format(params); | 90 | snd_pcm_format_t format = params_format(params); |
90 | unsigned int channels = params_channels(params); | 91 | unsigned int channels = params_channels(params); |
91 | unsigned int regval; | 92 | unsigned int regval; |
92 | int bitwidth; | 93 | int bitwidth; |
93 | int ret; | 94 | int ret, rdma_port = pcm_data->i2s_port + v->rdmactl_audif_start; |
94 | 95 | ||
95 | bitwidth = snd_pcm_format_width(format); | 96 | bitwidth = snd_pcm_format_width(format); |
96 | if (bitwidth < 0) { | 97 | if (bitwidth < 0) { |
@@ -100,7 +101,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
100 | } | 101 | } |
101 | 102 | ||
102 | regval = LPAIF_RDMACTL_BURSTEN_INCR4 | | 103 | regval = LPAIF_RDMACTL_BURSTEN_INCR4 | |
103 | LPAIF_RDMACTL_AUDINTF_MI2S | | 104 | LPAIF_RDMACTL_AUDINTF(rdma_port) | |
104 | LPAIF_RDMACTL_FIFOWM_8; | 105 | LPAIF_RDMACTL_FIFOWM_8; |
105 | 106 | ||
106 | switch (bitwidth) { | 107 | switch (bitwidth) { |
@@ -156,7 +157,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
156 | } | 157 | } |
157 | 158 | ||
158 | ret = regmap_write(drvdata->lpaif_map, | 159 | ret = regmap_write(drvdata->lpaif_map, |
159 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), regval); | 160 | LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), regval); |
160 | if (ret) { | 161 | if (ret) { |
161 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 162 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", |
162 | __func__, ret); | 163 | __func__, ret); |
@@ -169,12 +170,14 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
169 | static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) | 170 | static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) |
170 | { | 171 | { |
171 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 172 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
173 | struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
172 | struct lpass_data *drvdata = | 174 | struct lpass_data *drvdata = |
173 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 175 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
176 | struct lpass_variant *v = drvdata->variant; | ||
174 | int ret; | 177 | int ret; |
175 | 178 | ||
176 | ret = regmap_write(drvdata->lpaif_map, | 179 | ret = regmap_write(drvdata->lpaif_map, |
177 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); | 180 | LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), 0); |
178 | if (ret) | 181 | if (ret) |
179 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 182 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", |
180 | __func__, ret); | 183 | __func__, ret); |
@@ -186,12 +189,14 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
186 | { | 189 | { |
187 | struct snd_pcm_runtime *runtime = substream->runtime; | 190 | struct snd_pcm_runtime *runtime = substream->runtime; |
188 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 191 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
192 | struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
189 | struct lpass_data *drvdata = | 193 | struct lpass_data *drvdata = |
190 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 194 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
191 | int ret; | 195 | struct lpass_variant *v = drvdata->variant; |
196 | int ret, ch = pcm_data->rdma_ch; | ||
192 | 197 | ||
193 | ret = regmap_write(drvdata->lpaif_map, | 198 | ret = regmap_write(drvdata->lpaif_map, |
194 | LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), | 199 | LPAIF_RDMABASE_REG(v, ch), |
195 | runtime->dma_addr); | 200 | runtime->dma_addr); |
196 | if (ret) { | 201 | if (ret) { |
197 | dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", | 202 | dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", |
@@ -200,7 +205,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
200 | } | 205 | } |
201 | 206 | ||
202 | ret = regmap_write(drvdata->lpaif_map, | 207 | ret = regmap_write(drvdata->lpaif_map, |
203 | LPAIF_RDMABUFF_REG(LPAIF_RDMA_CHAN_MI2S), | 208 | LPAIF_RDMABUFF_REG(v, ch), |
204 | (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); | 209 | (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); |
205 | if (ret) { | 210 | if (ret) { |
206 | dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", | 211 | dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", |
@@ -209,7 +214,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
209 | } | 214 | } |
210 | 215 | ||
211 | ret = regmap_write(drvdata->lpaif_map, | 216 | ret = regmap_write(drvdata->lpaif_map, |
212 | LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MI2S), | 217 | LPAIF_RDMAPER_REG(v, ch), |
213 | (snd_pcm_lib_period_bytes(substream) >> 2) - 1); | 218 | (snd_pcm_lib_period_bytes(substream) >> 2) - 1); |
214 | if (ret) { | 219 | if (ret) { |
215 | dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", | 220 | dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", |
@@ -218,7 +223,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
218 | } | 223 | } |
219 | 224 | ||
220 | ret = regmap_update_bits(drvdata->lpaif_map, | 225 | ret = regmap_update_bits(drvdata->lpaif_map, |
221 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), | 226 | LPAIF_RDMACTL_REG(v, ch), |
222 | LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); | 227 | LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); |
223 | if (ret) { | 228 | if (ret) { |
224 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 229 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", |
@@ -233,9 +238,11 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
233 | int cmd) | 238 | int cmd) |
234 | { | 239 | { |
235 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 240 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
241 | struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
236 | struct lpass_data *drvdata = | 242 | struct lpass_data *drvdata = |
237 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 243 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
238 | int ret; | 244 | struct lpass_variant *v = drvdata->variant; |
245 | int ret, ch = pcm_data->rdma_ch; | ||
239 | 246 | ||
240 | switch (cmd) { | 247 | switch (cmd) { |
241 | case SNDRV_PCM_TRIGGER_START: | 248 | case SNDRV_PCM_TRIGGER_START: |
@@ -243,8 +250,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
243 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 250 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
244 | /* clear status before enabling interrupts */ | 251 | /* clear status before enabling interrupts */ |
245 | ret = regmap_write(drvdata->lpaif_map, | 252 | ret = regmap_write(drvdata->lpaif_map, |
246 | LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), | 253 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
247 | LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); | 254 | LPAIF_IRQ_ALL(ch)); |
248 | if (ret) { | 255 | if (ret) { |
249 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 256 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", |
250 | __func__, ret); | 257 | __func__, ret); |
@@ -252,9 +259,9 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
252 | } | 259 | } |
253 | 260 | ||
254 | ret = regmap_update_bits(drvdata->lpaif_map, | 261 | ret = regmap_update_bits(drvdata->lpaif_map, |
255 | LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), | 262 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), |
256 | LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), | 263 | LPAIF_IRQ_ALL(ch), |
257 | LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); | 264 | LPAIF_IRQ_ALL(ch)); |
258 | if (ret) { | 265 | if (ret) { |
259 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", | 266 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", |
260 | __func__, ret); | 267 | __func__, ret); |
@@ -262,7 +269,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
262 | } | 269 | } |
263 | 270 | ||
264 | ret = regmap_update_bits(drvdata->lpaif_map, | 271 | ret = regmap_update_bits(drvdata->lpaif_map, |
265 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), | 272 | LPAIF_RDMACTL_REG(v, ch), |
266 | LPAIF_RDMACTL_ENABLE_MASK, | 273 | LPAIF_RDMACTL_ENABLE_MASK, |
267 | LPAIF_RDMACTL_ENABLE_ON); | 274 | LPAIF_RDMACTL_ENABLE_ON); |
268 | if (ret) { | 275 | if (ret) { |
@@ -275,7 +282,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
275 | case SNDRV_PCM_TRIGGER_SUSPEND: | 282 | case SNDRV_PCM_TRIGGER_SUSPEND: |
276 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 283 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
277 | ret = regmap_update_bits(drvdata->lpaif_map, | 284 | ret = regmap_update_bits(drvdata->lpaif_map, |
278 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), | 285 | LPAIF_RDMACTL_REG(v, ch), |
279 | LPAIF_RDMACTL_ENABLE_MASK, | 286 | LPAIF_RDMACTL_ENABLE_MASK, |
280 | LPAIF_RDMACTL_ENABLE_OFF); | 287 | LPAIF_RDMACTL_ENABLE_OFF); |
281 | if (ret) { | 288 | if (ret) { |
@@ -285,8 +292,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
285 | } | 292 | } |
286 | 293 | ||
287 | ret = regmap_update_bits(drvdata->lpaif_map, | 294 | ret = regmap_update_bits(drvdata->lpaif_map, |
288 | LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), | 295 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), |
289 | LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0); | 296 | LPAIF_IRQ_ALL(ch), 0); |
290 | if (ret) { | 297 | if (ret) { |
291 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", | 298 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", |
292 | __func__, ret); | 299 | __func__, ret); |
@@ -302,13 +309,15 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( | |||
302 | struct snd_pcm_substream *substream) | 309 | struct snd_pcm_substream *substream) |
303 | { | 310 | { |
304 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 311 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
312 | struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
305 | struct lpass_data *drvdata = | 313 | struct lpass_data *drvdata = |
306 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 314 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
315 | struct lpass_variant *v = drvdata->variant; | ||
307 | unsigned int base_addr, curr_addr; | 316 | unsigned int base_addr, curr_addr; |
308 | int ret; | 317 | int ret, ch = pcm_data->rdma_ch; |
309 | 318 | ||
310 | ret = regmap_read(drvdata->lpaif_map, | 319 | ret = regmap_read(drvdata->lpaif_map, |
311 | LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), &base_addr); | 320 | LPAIF_RDMABASE_REG(v, ch), &base_addr); |
312 | if (ret) { | 321 | if (ret) { |
313 | dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", | 322 | dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", |
314 | __func__, ret); | 323 | __func__, ret); |
@@ -316,7 +325,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( | |||
316 | } | 325 | } |
317 | 326 | ||
318 | ret = regmap_read(drvdata->lpaif_map, | 327 | ret = regmap_read(drvdata->lpaif_map, |
319 | LPAIF_RDMACURR_REG(LPAIF_RDMA_CHAN_MI2S), &curr_addr); | 328 | LPAIF_RDMACURR_REG(v, ch), &curr_addr); |
320 | if (ret) { | 329 | if (ret) { |
321 | dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", | 330 | dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", |
322 | __func__, ret); | 331 | __func__, ret); |
@@ -347,29 +356,20 @@ static struct snd_pcm_ops lpass_platform_pcm_ops = { | |||
347 | .mmap = lpass_platform_pcmops_mmap, | 356 | .mmap = lpass_platform_pcmops_mmap, |
348 | }; | 357 | }; |
349 | 358 | ||
350 | static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | 359 | static irqreturn_t lpass_dma_interrupt_handler( |
360 | struct snd_pcm_substream *substream, | ||
361 | struct lpass_data *drvdata, | ||
362 | int chan, u32 interrupts) | ||
351 | { | 363 | { |
352 | struct snd_pcm_substream *substream = data; | ||
353 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 364 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
354 | struct lpass_data *drvdata = | 365 | struct lpass_variant *v = drvdata->variant; |
355 | snd_soc_platform_get_drvdata(soc_runtime->platform); | ||
356 | unsigned int interrupts; | ||
357 | irqreturn_t ret = IRQ_NONE; | 366 | irqreturn_t ret = IRQ_NONE; |
358 | int rv; | 367 | int rv; |
359 | 368 | ||
360 | rv = regmap_read(drvdata->lpaif_map, | 369 | if (interrupts & LPAIF_IRQ_PER(chan)) { |
361 | LPAIF_IRQSTAT_REG(LPAIF_IRQ_PORT_HOST), &interrupts); | ||
362 | if (rv) { | ||
363 | dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n", | ||
364 | __func__, rv); | ||
365 | return IRQ_NONE; | ||
366 | } | ||
367 | interrupts &= LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S); | ||
368 | |||
369 | if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) { | ||
370 | rv = regmap_write(drvdata->lpaif_map, | 370 | rv = regmap_write(drvdata->lpaif_map, |
371 | LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), | 371 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
372 | LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)); | 372 | LPAIF_IRQ_PER(chan)); |
373 | if (rv) { | 373 | if (rv) { |
374 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 374 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", |
375 | __func__, rv); | 375 | __func__, rv); |
@@ -379,10 +379,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | |||
379 | ret = IRQ_HANDLED; | 379 | ret = IRQ_HANDLED; |
380 | } | 380 | } |
381 | 381 | ||
382 | if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) { | 382 | if (interrupts & LPAIF_IRQ_XRUN(chan)) { |
383 | rv = regmap_write(drvdata->lpaif_map, | 383 | rv = regmap_write(drvdata->lpaif_map, |
384 | LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), | 384 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
385 | LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)); | 385 | LPAIF_IRQ_XRUN(chan)); |
386 | if (rv) { | 386 | if (rv) { |
387 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 387 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", |
388 | __func__, rv); | 388 | __func__, rv); |
@@ -393,10 +393,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | |||
393 | ret = IRQ_HANDLED; | 393 | ret = IRQ_HANDLED; |
394 | } | 394 | } |
395 | 395 | ||
396 | if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) { | 396 | if (interrupts & LPAIF_IRQ_ERR(chan)) { |
397 | rv = regmap_write(drvdata->lpaif_map, | 397 | rv = regmap_write(drvdata->lpaif_map, |
398 | LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), | 398 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
399 | LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)); | 399 | LPAIF_IRQ_ERR(chan)); |
400 | if (rv) { | 400 | if (rv) { |
401 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 401 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", |
402 | __func__, rv); | 402 | __func__, rv); |
@@ -410,6 +410,35 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | |||
410 | return ret; | 410 | return ret; |
411 | } | 411 | } |
412 | 412 | ||
413 | static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | ||
414 | { | ||
415 | struct lpass_data *drvdata = data; | ||
416 | struct lpass_variant *v = drvdata->variant; | ||
417 | unsigned int irqs; | ||
418 | int rv, chan; | ||
419 | |||
420 | rv = regmap_read(drvdata->lpaif_map, | ||
421 | LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); | ||
422 | if (rv) { | ||
423 | pr_err("%s() error reading from irqstat reg: %d\n", | ||
424 | __func__, rv); | ||
425 | return IRQ_NONE; | ||
426 | } | ||
427 | |||
428 | /* Handle per channel interrupts */ | ||
429 | for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) { | ||
430 | if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) { | ||
431 | rv = lpass_dma_interrupt_handler( | ||
432 | drvdata->substream[chan], | ||
433 | drvdata, chan, irqs); | ||
434 | if (rv != IRQ_HANDLED) | ||
435 | return rv; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | return IRQ_HANDLED; | ||
440 | } | ||
441 | |||
413 | static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream, | 442 | static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream, |
414 | struct snd_soc_pcm_runtime *soc_runtime) | 443 | struct snd_soc_pcm_runtime *soc_runtime) |
415 | { | 444 | { |
@@ -448,9 +477,27 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) | |||
448 | struct snd_pcm *pcm = soc_runtime->pcm; | 477 | struct snd_pcm *pcm = soc_runtime->pcm; |
449 | struct snd_pcm_substream *substream = | 478 | struct snd_pcm_substream *substream = |
450 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | 479 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
480 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
451 | struct lpass_data *drvdata = | 481 | struct lpass_data *drvdata = |
452 | snd_soc_platform_get_drvdata(soc_runtime->platform); | 482 | snd_soc_platform_get_drvdata(soc_runtime->platform); |
483 | struct lpass_variant *v = drvdata->variant; | ||
453 | int ret; | 484 | int ret; |
485 | struct lpass_pcm_data *data; | ||
486 | |||
487 | data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); | ||
488 | if (!data) | ||
489 | return -ENOMEM; | ||
490 | |||
491 | if (v->alloc_dma_channel) | ||
492 | data->rdma_ch = v->alloc_dma_channel(drvdata); | ||
493 | |||
494 | if (IS_ERR_VALUE(data->rdma_ch)) | ||
495 | return data->rdma_ch; | ||
496 | |||
497 | drvdata->substream[data->rdma_ch] = substream; | ||
498 | data->i2s_port = cpu_dai->driver->id; | ||
499 | |||
500 | snd_soc_pcm_set_drvdata(soc_runtime, data); | ||
454 | 501 | ||
455 | soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 502 | soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
456 | soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask; | 503 | soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask; |
@@ -459,29 +506,12 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) | |||
459 | if (ret) | 506 | if (ret) |
460 | return ret; | 507 | return ret; |
461 | 508 | ||
462 | ret = devm_request_irq(soc_runtime->dev, drvdata->lpaif_irq, | ||
463 | lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, | ||
464 | "lpass-irq-lpaif", substream); | ||
465 | if (ret) { | ||
466 | dev_err(soc_runtime->dev, "%s() irq request failed: %d\n", | ||
467 | __func__, ret); | ||
468 | goto err_buf; | ||
469 | } | ||
470 | |||
471 | /* ensure audio hardware is disabled */ | ||
472 | ret = regmap_write(drvdata->lpaif_map, | 509 | ret = regmap_write(drvdata->lpaif_map, |
473 | LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 0); | 510 | LPAIF_RDMACTL_REG(v, data->rdma_ch), 0); |
474 | if (ret) { | ||
475 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", | ||
476 | __func__, ret); | ||
477 | return ret; | ||
478 | } | ||
479 | ret = regmap_write(drvdata->lpaif_map, | ||
480 | LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); | ||
481 | if (ret) { | 511 | if (ret) { |
482 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 512 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", |
483 | __func__, ret); | 513 | __func__, ret); |
484 | return ret; | 514 | goto err_buf; |
485 | } | 515 | } |
486 | 516 | ||
487 | return 0; | 517 | return 0; |
@@ -496,6 +526,15 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm) | |||
496 | struct snd_pcm_substream *substream = | 526 | struct snd_pcm_substream *substream = |
497 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | 527 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
498 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 528 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
529 | struct lpass_data *drvdata = | ||
530 | snd_soc_platform_get_drvdata(soc_runtime->platform); | ||
531 | struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime); | ||
532 | struct lpass_variant *v = drvdata->variant; | ||
533 | |||
534 | drvdata->substream[data->rdma_ch] = NULL; | ||
535 | |||
536 | if (v->free_dma_channel) | ||
537 | v->free_dma_channel(drvdata, data->rdma_ch); | ||
499 | 538 | ||
500 | lpass_platform_free_buffer(substream, soc_runtime); | 539 | lpass_platform_free_buffer(substream, soc_runtime); |
501 | } | 540 | } |
@@ -509,6 +548,8 @@ static struct snd_soc_platform_driver lpass_platform_driver = { | |||
509 | int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | 548 | int asoc_qcom_lpass_platform_register(struct platform_device *pdev) |
510 | { | 549 | { |
511 | struct lpass_data *drvdata = platform_get_drvdata(pdev); | 550 | struct lpass_data *drvdata = platform_get_drvdata(pdev); |
551 | struct lpass_variant *v = drvdata->variant; | ||
552 | int ret; | ||
512 | 553 | ||
513 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); | 554 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); |
514 | if (drvdata->lpaif_irq < 0) { | 555 | if (drvdata->lpaif_irq < 0) { |
@@ -517,6 +558,25 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | |||
517 | return -ENODEV; | 558 | return -ENODEV; |
518 | } | 559 | } |
519 | 560 | ||
561 | /* ensure audio hardware is disabled */ | ||
562 | ret = regmap_write(drvdata->lpaif_map, | ||
563 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); | ||
564 | if (ret) { | ||
565 | dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n", | ||
566 | __func__, ret); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, | ||
571 | lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, | ||
572 | "lpass-irq-lpaif", drvdata); | ||
573 | if (ret) { | ||
574 | dev_err(&pdev->dev, "%s() irq request failed: %d\n", | ||
575 | __func__, ret); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | |||
520 | return devm_snd_soc_register_platform(&pdev->dev, | 580 | return devm_snd_soc_register_platform(&pdev->dev, |
521 | &lpass_platform_driver); | 581 | &lpass_platform_driver); |
522 | } | 582 | } |
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 5c99b3dace86..d6e86c119e74 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
23 | 23 | ||
24 | #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 | 24 | #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 |
25 | #define LPASS_MAX_MI2S_PORTS (8) | ||
26 | #define LPASS_MAX_DMA_CHANNELS (8) | ||
25 | 27 | ||
26 | /* Both the CPU DAI and platform drivers will access this data */ | 28 | /* Both the CPU DAI and platform drivers will access this data */ |
27 | struct lpass_data { | 29 | struct lpass_data { |
@@ -30,10 +32,10 @@ struct lpass_data { | |||
30 | struct clk *ahbix_clk; | 32 | struct clk *ahbix_clk; |
31 | 33 | ||
32 | /* MI2S system clock */ | 34 | /* MI2S system clock */ |
33 | struct clk *mi2s_osr_clk; | 35 | struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS]; |
34 | 36 | ||
35 | /* MI2S bit clock (derived from system clock by a divider */ | 37 | /* MI2S bit clock (derived from system clock by a divider */ |
36 | struct clk *mi2s_bit_clk; | 38 | struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; |
37 | 39 | ||
38 | /* low-power audio interface (LPAIF) registers */ | 40 | /* low-power audio interface (LPAIF) registers */ |
39 | void __iomem *lpaif; | 41 | void __iomem *lpaif; |
@@ -43,9 +45,54 @@ struct lpass_data { | |||
43 | 45 | ||
44 | /* interrupts from the low-power audio interface (LPAIF) */ | 46 | /* interrupts from the low-power audio interface (LPAIF) */ |
45 | int lpaif_irq; | 47 | int lpaif_irq; |
48 | |||
49 | /* SOC specific variations in the LPASS IP integration */ | ||
50 | struct lpass_variant *variant; | ||
51 | |||
52 | /* bit map to keep track of static channel allocations */ | ||
53 | unsigned long rdma_ch_bit_map; | ||
54 | |||
55 | /* used it for handling interrupt per dma channel */ | ||
56 | struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; | ||
57 | |||
58 | /* 8016 specific */ | ||
59 | struct clk *pcnoc_mport_clk; | ||
60 | struct clk *pcnoc_sway_clk; | ||
61 | }; | ||
62 | |||
63 | /* Vairant data per each SOC */ | ||
64 | struct lpass_variant { | ||
65 | u32 i2sctrl_reg_base; | ||
66 | u32 i2sctrl_reg_stride; | ||
67 | u32 i2s_ports; | ||
68 | u32 irq_reg_base; | ||
69 | u32 irq_reg_stride; | ||
70 | u32 irq_ports; | ||
71 | u32 rdma_reg_base; | ||
72 | u32 rdma_reg_stride; | ||
73 | u32 rdma_channels; | ||
74 | |||
75 | /** | ||
76 | * on SOCs like APQ8016 the channel control bits start | ||
77 | * at different offset to ipq806x | ||
78 | **/ | ||
79 | u32 rdmactl_audif_start; | ||
80 | /* SOC specific intialization like clocks */ | ||
81 | int (*init)(struct platform_device *pdev); | ||
82 | int (*exit)(struct platform_device *pdev); | ||
83 | int (*alloc_dma_channel)(struct lpass_data *data); | ||
84 | int (*free_dma_channel)(struct lpass_data *data, int ch); | ||
85 | |||
86 | /* SOC specific dais */ | ||
87 | struct snd_soc_dai_driver *dai_driver; | ||
88 | int num_dai; | ||
46 | }; | 89 | }; |
47 | 90 | ||
48 | /* register the platform driver from the CPU DAI driver */ | 91 | /* register the platform driver from the CPU DAI driver */ |
49 | int asoc_qcom_lpass_platform_register(struct platform_device *); | 92 | int asoc_qcom_lpass_platform_register(struct platform_device *); |
93 | int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); | ||
94 | int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev); | ||
95 | int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai); | ||
96 | extern struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops; | ||
50 | 97 | ||
51 | #endif /* __LPASS_H__ */ | 98 | #endif /* __LPASS_H__ */ |
diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index b8bd296190ad..2d833bffdba0 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c | |||
@@ -69,11 +69,6 @@ static struct snd_soc_dai_link storm_dai_link = { | |||
69 | .ops = &storm_soc_ops, | 69 | .ops = &storm_soc_ops, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static struct snd_soc_card storm_soc_card = { | ||
73 | .name = "ipq806x-storm", | ||
74 | .dev = NULL, | ||
75 | }; | ||
76 | |||
77 | static int storm_parse_of(struct snd_soc_card *card) | 72 | static int storm_parse_of(struct snd_soc_card *card) |
78 | { | 73 | { |
79 | struct snd_soc_dai_link *dai_link = card->dai_link; | 74 | struct snd_soc_dai_link *dai_link = card->dai_link; |
@@ -99,14 +94,13 @@ static int storm_parse_of(struct snd_soc_card *card) | |||
99 | 94 | ||
100 | static int storm_platform_probe(struct platform_device *pdev) | 95 | static int storm_platform_probe(struct platform_device *pdev) |
101 | { | 96 | { |
102 | struct snd_soc_card *card = &storm_soc_card; | 97 | struct snd_soc_card *card; |
103 | int ret; | 98 | int ret; |
104 | 99 | ||
105 | if (card->dev) { | 100 | card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); |
106 | dev_err(&pdev->dev, "%s() error, existing soundcard\n", | 101 | if (!card) |
107 | __func__); | 102 | return -ENOMEM; |
108 | return -ENODEV; | 103 | |
109 | } | ||
110 | card->dev = &pdev->dev; | 104 | card->dev = &pdev->dev; |
111 | platform_set_drvdata(pdev, card); | 105 | platform_set_drvdata(pdev, card); |
112 | 106 | ||
@@ -128,16 +122,12 @@ static int storm_platform_probe(struct platform_device *pdev) | |||
128 | } | 122 | } |
129 | 123 | ||
130 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 124 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
131 | if (ret == -EPROBE_DEFER) { | 125 | if (ret) |
132 | card->dev = NULL; | ||
133 | return ret; | ||
134 | } else if (ret) { | ||
135 | dev_err(&pdev->dev, "%s() error registering soundcard: %d\n", | 126 | dev_err(&pdev->dev, "%s() error registering soundcard: %d\n", |
136 | __func__, ret); | 127 | __func__, ret); |
137 | return ret; | ||
138 | } | ||
139 | 128 | ||
140 | return 0; | 129 | return ret; |
130 | |||
141 | } | 131 | } |
142 | 132 | ||
143 | #ifdef CONFIG_OF | 133 | #ifdef CONFIG_OF |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 0632a36852c8..3744c9ed5370 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -174,7 +174,8 @@ config SND_SOC_SMDK_WM8994_PCM | |||
174 | 174 | ||
175 | config SND_SOC_SPEYSIDE | 175 | config SND_SOC_SPEYSIDE |
176 | tristate "Audio support for Wolfson Speyside" | 176 | tristate "Audio support for Wolfson Speyside" |
177 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C && SPI_MASTER | 177 | depends on SND_SOC_SAMSUNG && I2C && SPI_MASTER |
178 | depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST | ||
178 | select SND_SAMSUNG_I2S | 179 | select SND_SAMSUNG_I2S |
179 | select SND_SOC_WM8996 | 180 | select SND_SOC_WM8996 |
180 | select SND_SOC_WM9081 | 181 | select SND_SOC_WM9081 |
@@ -183,13 +184,15 @@ config SND_SOC_SPEYSIDE | |||
183 | 184 | ||
184 | config SND_SOC_TOBERMORY | 185 | config SND_SOC_TOBERMORY |
185 | tristate "Audio support for Wolfson Tobermory" | 186 | tristate "Audio support for Wolfson Tobermory" |
186 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C | 187 | depends on SND_SOC_SAMSUNG && INPUT && I2C |
188 | depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST | ||
187 | select SND_SAMSUNG_I2S | 189 | select SND_SAMSUNG_I2S |
188 | select SND_SOC_WM8962 | 190 | select SND_SOC_WM8962 |
189 | 191 | ||
190 | config SND_SOC_BELLS | 192 | config SND_SOC_BELLS |
191 | tristate "Audio support for Wolfson Bells" | 193 | tristate "Audio support for Wolfson Bells" |
192 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && MFD_ARIZONA && I2C && SPI_MASTER | 194 | depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER |
195 | depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST | ||
193 | select SND_SAMSUNG_I2S | 196 | select SND_SAMSUNG_I2S |
194 | select SND_SOC_WM5102 | 197 | select SND_SOC_WM5102 |
195 | select SND_SOC_WM5110 | 198 | select SND_SOC_WM5110 |
@@ -199,14 +202,16 @@ config SND_SOC_BELLS | |||
199 | 202 | ||
200 | config SND_SOC_LOWLAND | 203 | config SND_SOC_LOWLAND |
201 | tristate "Audio support for Wolfson Lowland" | 204 | tristate "Audio support for Wolfson Lowland" |
202 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C | 205 | depends on SND_SOC_SAMSUNG && I2C |
206 | depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST | ||
203 | select SND_SAMSUNG_I2S | 207 | select SND_SAMSUNG_I2S |
204 | select SND_SOC_WM5100 | 208 | select SND_SOC_WM5100 |
205 | select SND_SOC_WM9081 | 209 | select SND_SOC_WM9081 |
206 | 210 | ||
207 | config SND_SOC_LITTLEMILL | 211 | config SND_SOC_LITTLEMILL |
208 | tristate "Audio support for Wolfson Littlemill" | 212 | tristate "Audio support for Wolfson Littlemill" |
209 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C | 213 | depends on SND_SOC_SAMSUNG && I2C |
214 | depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST | ||
210 | select SND_SAMSUNG_I2S | 215 | select SND_SAMSUNG_I2S |
211 | select MFD_WM8994 | 216 | select MFD_WM8994 |
212 | select SND_SOC_WM8994 | 217 | select SND_SOC_WM8994 |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index b92ab40d2be6..ea4ab374a223 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -1493,7 +1493,7 @@ static const struct samsung_i2s_dai_data samsung_dai_type_sec = { | |||
1493 | .dai_type = TYPE_SEC, | 1493 | .dai_type = TYPE_SEC, |
1494 | }; | 1494 | }; |
1495 | 1495 | ||
1496 | static struct platform_device_id samsung_i2s_driver_ids[] = { | 1496 | static const struct platform_device_id samsung_i2s_driver_ids[] = { |
1497 | { | 1497 | { |
1498 | .name = "samsung-i2s", | 1498 | .name = "samsung-i2s", |
1499 | .driver_data = (kernel_ulong_t)&i2sv3_dai_type, | 1499 | .driver_data = (kernel_ulong_t)&i2sv3_dai_type, |
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 5f156093101e..0d0f58208b75 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c | |||
@@ -72,7 +72,7 @@ static int lowland_wm9081_init(struct snd_soc_pcm_runtime *rtd) | |||
72 | { | 72 | { |
73 | struct snd_soc_codec *codec = rtd->codec; | 73 | struct snd_soc_codec *codec = rtd->codec; |
74 | 74 | ||
75 | snd_soc_dapm_nc_pin(&codec->dapm, "LINEOUT"); | 75 | snd_soc_dapm_nc_pin(&rtd->card->dapm, "LINEOUT"); |
76 | 76 | ||
77 | /* At any time the WM9081 is active it will have this clock */ | 77 | /* At any time the WM9081 is active it will have this clock */ |
78 | return snd_soc_codec_set_sysclk(codec, WM9081_SYSCLK_MCLK, 0, | 78 | return snd_soc_codec_set_sysclk(codec, WM9081_SYSCLK_MCLK, 0, |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 326d3c3804e3..5bf723689692 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -461,8 +461,8 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | |||
461 | return -ENOENT; | 461 | return -ENOENT; |
462 | } | 462 | } |
463 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | 463 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); |
464 | if (s3c24xx_i2s.regs == NULL) | 464 | if (IS_ERR(s3c24xx_i2s.regs)) |
465 | return -ENXIO; | 465 | return PTR_ERR(s3c24xx_i2s.regs); |
466 | 466 | ||
467 | s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; | 467 | s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; |
468 | s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; | 468 | s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; |
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index dfbe2db1c407..a0fe37fbed9f 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c | |||
@@ -137,8 +137,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
137 | 137 | ||
138 | static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) | 138 | static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) |
139 | { | 139 | { |
140 | struct snd_soc_codec *codec = rtd->codec; | 140 | struct snd_soc_dapm_context *dapm = &rtd->card->dapm; |
141 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
142 | int err = 0; | 141 | int err = 0; |
143 | 142 | ||
144 | /* set endpoints to not connected */ | 143 | /* set endpoints to not connected */ |
@@ -147,9 +146,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd) | |||
147 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | 146 | snd_soc_dapm_nc_pin(dapm, "OUT3"); |
148 | snd_soc_dapm_nc_pin(dapm, "ROUT1"); | 147 | snd_soc_dapm_nc_pin(dapm, "ROUT1"); |
149 | 148 | ||
150 | /* set endpoints to default off mode */ | ||
151 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | ||
152 | |||
153 | /* Headphone jack detection */ | 149 | /* Headphone jack detection */ |
154 | err = snd_soc_card_jack_new(rtd->card, "Headphone Jack", | 150 | err = snd_soc_card_jack_new(rtd->card, "Headphone Jack", |
155 | SND_JACK_HEADPHONE, &smartq_jack, | 151 | SND_JACK_HEADPHONE, &smartq_jack, |
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index d38595fbdab7..ff57b192d37d 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c | |||
@@ -86,8 +86,7 @@ static struct snd_soc_ops smdk_ops = { | |||
86 | 86 | ||
87 | static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) | 87 | static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd) |
88 | { | 88 | { |
89 | struct snd_soc_codec *codec = rtd->codec; | 89 | struct snd_soc_dapm_context *dapm = &rtd->card->dapm; |
90 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
91 | 90 | ||
92 | /* Other pins NC */ | 91 | /* Other pins NC */ |
93 | snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); | 92 | snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); |
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 2dcb988bdff2..d1ae21c5e253 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -123,7 +123,7 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, | |||
123 | gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); | 123 | gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); |
124 | 124 | ||
125 | /* Re-run DAPM to make sure we're using the correct mic bias */ | 125 | /* Re-run DAPM to make sure we're using the correct mic bias */ |
126 | snd_soc_dapm_sync(&codec->dapm); | 126 | snd_soc_dapm_sync(snd_soc_codec_get_dapm(codec)); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) | 129 | static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) |
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 82f582344fe7..672bcd4c252b 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c | |||
@@ -162,12 +162,11 @@ static int __init migor_init(void) | |||
162 | if (ret < 0) | 162 | if (ret < 0) |
163 | return ret; | 163 | return ret; |
164 | 164 | ||
165 | siumckb_lookup = clkdev_alloc(&siumckb_clk, "siumckb_clk", NULL); | 165 | siumckb_lookup = clkdev_create(&siumckb_clk, "siumckb_clk", NULL); |
166 | if (!siumckb_lookup) { | 166 | if (!siumckb_lookup) { |
167 | ret = -ENOMEM; | 167 | ret = -ENOMEM; |
168 | goto eclkdevalloc; | 168 | goto eclkdevalloc; |
169 | } | 169 | } |
170 | clkdev_add(siumckb_lookup); | ||
171 | 170 | ||
172 | /* Port number used on this machine: port B */ | 171 | /* Port number used on this machine: port B */ |
173 | migor_snd_device = platform_device_alloc("soc-audio", 1); | 172 | migor_snd_device = platform_device_alloc("soc-audio", 1); |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 9f48d75fa992..f1e5920654f6 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -137,15 +137,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
137 | return mod->ops->name; | 137 | return mod->ops->name; |
138 | } | 138 | } |
139 | 139 | ||
140 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod) | 140 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, |
141 | struct rsnd_mod *mod) | ||
141 | { | 142 | { |
142 | if (!mod || !mod->ops || !mod->ops->dma_req) | 143 | if (!mod || !mod->ops || !mod->ops->dma_req) |
143 | return NULL; | 144 | return NULL; |
144 | 145 | ||
145 | return mod->ops->dma_req(mod); | 146 | return mod->ops->dma_req(io, mod); |
146 | } | 147 | } |
147 | 148 | ||
148 | int rsnd_mod_init(struct rsnd_mod *mod, | 149 | int rsnd_mod_init(struct rsnd_priv *priv, |
150 | struct rsnd_mod *mod, | ||
149 | struct rsnd_mod_ops *ops, | 151 | struct rsnd_mod_ops *ops, |
150 | struct clk *clk, | 152 | struct clk *clk, |
151 | enum rsnd_mod_type type, | 153 | enum rsnd_mod_type type, |
@@ -160,6 +162,7 @@ int rsnd_mod_init(struct rsnd_mod *mod, | |||
160 | mod->ops = ops; | 162 | mod->ops = ops; |
161 | mod->type = type; | 163 | mod->type = type; |
162 | mod->clk = clk; | 164 | mod->clk = clk; |
165 | mod->priv = priv; | ||
163 | 166 | ||
164 | return ret; | 167 | return ret; |
165 | } | 168 | } |
@@ -170,13 +173,41 @@ void rsnd_mod_quit(struct rsnd_mod *mod) | |||
170 | clk_unprepare(mod->clk); | 173 | clk_unprepare(mod->clk); |
171 | } | 174 | } |
172 | 175 | ||
176 | void rsnd_mod_interrupt(struct rsnd_mod *mod, | ||
177 | void (*callback)(struct rsnd_mod *mod, | ||
178 | struct rsnd_dai_stream *io)) | ||
179 | { | ||
180 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
181 | struct rsnd_dai_stream *io; | ||
182 | struct rsnd_dai *rdai; | ||
183 | int i, j; | ||
184 | |||
185 | for_each_rsnd_dai(rdai, priv, j) { | ||
186 | |||
187 | for (i = 0; i < RSND_MOD_MAX; i++) { | ||
188 | io = &rdai->playback; | ||
189 | if (mod == io->mod[i]) | ||
190 | callback(mod, io); | ||
191 | |||
192 | io = &rdai->capture; | ||
193 | if (mod == io->mod[i]) | ||
194 | callback(mod, io); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | int rsnd_io_is_working(struct rsnd_dai_stream *io) | ||
200 | { | ||
201 | /* see rsnd_dai_stream_init/quit() */ | ||
202 | return !!io->substream; | ||
203 | } | ||
204 | |||
173 | /* | 205 | /* |
174 | * settting function | 206 | * settting function |
175 | */ | 207 | */ |
176 | u32 rsnd_get_adinr(struct rsnd_mod *mod) | 208 | u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) |
177 | { | 209 | { |
178 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 210 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
179 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
180 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 211 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
181 | struct device *dev = rsnd_priv_to_dev(priv); | 212 | struct device *dev = rsnd_priv_to_dev(priv); |
182 | u32 adinr = runtime->channels; | 213 | u32 adinr = runtime->channels; |
@@ -199,26 +230,31 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
199 | /* | 230 | /* |
200 | * rsnd_dai functions | 231 | * rsnd_dai functions |
201 | */ | 232 | */ |
202 | #define __rsnd_mod_call(mod, func, param...) \ | 233 | #define __rsnd_mod_call(mod, io, func, param...) \ |
203 | ({ \ | 234 | ({ \ |
204 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ | 235 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ |
205 | struct device *dev = rsnd_priv_to_dev(priv); \ | 236 | struct device *dev = rsnd_priv_to_dev(priv); \ |
206 | u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \ | 237 | u32 mask = 0xF << __rsnd_mod_shift_##func; \ |
207 | u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func; \ | 238 | u8 val = (mod->status >> __rsnd_mod_shift_##func) & 0xF; \ |
239 | u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ | ||
208 | int ret = 0; \ | 240 | int ret = 0; \ |
209 | if ((mod->status & mask) == call) { \ | 241 | int called = 0; \ |
210 | dev_dbg(dev, "%s[%d] %s\n", \ | 242 | if (val == __rsnd_mod_call_##func) { \ |
211 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ | 243 | called = 1; \ |
212 | ret = (mod)->ops->func(mod, param); \ | 244 | ret = (mod)->ops->func(mod, io, param); \ |
213 | mod->status = (mod->status & ~mask) | (~call & mask); \ | 245 | mod->status = (mod->status & ~mask) + \ |
246 | (add << __rsnd_mod_shift_##func); \ | ||
214 | } \ | 247 | } \ |
248 | dev_dbg(dev, "%s[%d] 0x%08x %s\n", \ | ||
249 | rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \ | ||
250 | called ? #func : ""); \ | ||
215 | ret; \ | 251 | ret; \ |
216 | }) | 252 | }) |
217 | 253 | ||
218 | #define rsnd_mod_call(mod, func, param...) \ | 254 | #define rsnd_mod_call(mod, io, func, param...) \ |
219 | (!(mod) ? -ENODEV : \ | 255 | (!(mod) ? -ENODEV : \ |
220 | !((mod)->ops->func) ? 0 : \ | 256 | !((mod)->ops->func) ? 0 : \ |
221 | __rsnd_mod_call(mod, func, param)) | 257 | __rsnd_mod_call(mod, io, func, param)) |
222 | 258 | ||
223 | #define rsnd_dai_call(fn, io, param...) \ | 259 | #define rsnd_dai_call(fn, io, param...) \ |
224 | ({ \ | 260 | ({ \ |
@@ -228,7 +264,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
228 | mod = (io)->mod[i]; \ | 264 | mod = (io)->mod[i]; \ |
229 | if (!mod) \ | 265 | if (!mod) \ |
230 | continue; \ | 266 | continue; \ |
231 | ret = rsnd_mod_call(mod, fn, param); \ | 267 | ret = rsnd_mod_call(mod, io, fn, param); \ |
232 | if (ret < 0) \ | 268 | if (ret < 0) \ |
233 | break; \ | 269 | break; \ |
234 | } \ | 270 | } \ |
@@ -252,7 +288,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, | |||
252 | } | 288 | } |
253 | 289 | ||
254 | io->mod[mod->type] = mod; | 290 | io->mod[mod->type] = mod; |
255 | mod->io = io; | ||
256 | 291 | ||
257 | return 0; | 292 | return 0; |
258 | } | 293 | } |
@@ -260,7 +295,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, | |||
260 | static void rsnd_dai_disconnect(struct rsnd_mod *mod, | 295 | static void rsnd_dai_disconnect(struct rsnd_mod *mod, |
261 | struct rsnd_dai_stream *io) | 296 | struct rsnd_dai_stream *io) |
262 | { | 297 | { |
263 | mod->io = NULL; | ||
264 | io->mod[mod->type] = NULL; | 298 | io->mod[mod->type] = NULL; |
265 | } | 299 | } |
266 | 300 | ||
@@ -272,9 +306,10 @@ struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) | |||
272 | return priv->rdai + id; | 306 | return priv->rdai + id; |
273 | } | 307 | } |
274 | 308 | ||
309 | #define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai) | ||
275 | static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) | 310 | static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) |
276 | { | 311 | { |
277 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); | 312 | struct rsnd_priv *priv = rsnd_dai_to_priv(dai); |
278 | 313 | ||
279 | return rsnd_rdai_get(priv, dai->id); | 314 | return rsnd_rdai_get(priv, dai->id); |
280 | } | 315 | } |
@@ -293,7 +328,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional) | |||
293 | return pos; | 328 | return pos; |
294 | } | 329 | } |
295 | 330 | ||
296 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) | 331 | bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) |
297 | { | 332 | { |
298 | io->byte_pos += byte; | 333 | io->byte_pos += byte; |
299 | 334 | ||
@@ -310,11 +345,27 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) | |||
310 | io->next_period_byte = io->byte_per_period; | 345 | io->next_period_byte = io->byte_per_period; |
311 | } | 346 | } |
312 | 347 | ||
313 | snd_pcm_period_elapsed(substream); | 348 | return true; |
314 | } | 349 | } |
350 | |||
351 | return false; | ||
315 | } | 352 | } |
316 | 353 | ||
317 | static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, | 354 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) |
355 | { | ||
356 | struct snd_pcm_substream *substream = io->substream; | ||
357 | |||
358 | /* | ||
359 | * this function should be called... | ||
360 | * | ||
361 | * - if rsnd_dai_pointer_update() returns true | ||
362 | * - without spin lock | ||
363 | */ | ||
364 | |||
365 | snd_pcm_period_elapsed(substream); | ||
366 | } | ||
367 | |||
368 | static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, | ||
318 | struct snd_pcm_substream *substream) | 369 | struct snd_pcm_substream *substream) |
319 | { | 370 | { |
320 | struct snd_pcm_runtime *runtime = substream->runtime; | 371 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -326,8 +377,11 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, | |||
326 | runtime->channels * | 377 | runtime->channels * |
327 | samples_to_bytes(runtime, 1); | 378 | samples_to_bytes(runtime, 1); |
328 | io->next_period_byte = io->byte_per_period; | 379 | io->next_period_byte = io->byte_per_period; |
380 | } | ||
329 | 381 | ||
330 | return 0; | 382 | static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) |
383 | { | ||
384 | io->substream = NULL; | ||
331 | } | 385 | } |
332 | 386 | ||
333 | static | 387 | static |
@@ -351,20 +405,18 @@ struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai, | |||
351 | static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 405 | static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
352 | struct snd_soc_dai *dai) | 406 | struct snd_soc_dai *dai) |
353 | { | 407 | { |
354 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); | 408 | struct rsnd_priv *priv = rsnd_dai_to_priv(dai); |
355 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 409 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
356 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | 410 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
357 | int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io)); | 411 | int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io)); |
358 | int ret; | 412 | int ret; |
359 | unsigned long flags; | 413 | unsigned long flags; |
360 | 414 | ||
361 | rsnd_lock(priv, flags); | 415 | spin_lock_irqsave(&priv->lock, flags); |
362 | 416 | ||
363 | switch (cmd) { | 417 | switch (cmd) { |
364 | case SNDRV_PCM_TRIGGER_START: | 418 | case SNDRV_PCM_TRIGGER_START: |
365 | ret = rsnd_dai_stream_init(io, substream); | 419 | rsnd_dai_stream_init(io, substream); |
366 | if (ret < 0) | ||
367 | goto dai_trigger_end; | ||
368 | 420 | ||
369 | ret = rsnd_platform_call(priv, dai, start, ssi_id); | 421 | ret = rsnd_platform_call(priv, dai, start, ssi_id); |
370 | if (ret < 0) | 422 | if (ret < 0) |
@@ -390,13 +442,15 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
390 | ret = rsnd_platform_call(priv, dai, stop, ssi_id); | 442 | ret = rsnd_platform_call(priv, dai, stop, ssi_id); |
391 | if (ret < 0) | 443 | if (ret < 0) |
392 | goto dai_trigger_end; | 444 | goto dai_trigger_end; |
445 | |||
446 | rsnd_dai_stream_quit(io); | ||
393 | break; | 447 | break; |
394 | default: | 448 | default: |
395 | ret = -EINVAL; | 449 | ret = -EINVAL; |
396 | } | 450 | } |
397 | 451 | ||
398 | dai_trigger_end: | 452 | dai_trigger_end: |
399 | rsnd_unlock(priv, flags); | 453 | spin_unlock_irqrestore(&priv->lock, flags); |
400 | 454 | ||
401 | return ret; | 455 | return ret; |
402 | } | 456 | } |
@@ -822,23 +876,27 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, | |||
822 | } | 876 | } |
823 | 877 | ||
824 | if (change) | 878 | if (change) |
825 | cfg->update(mod); | 879 | cfg->update(cfg->io, mod); |
826 | 880 | ||
827 | return change; | 881 | return change; |
828 | } | 882 | } |
829 | 883 | ||
830 | static int __rsnd_kctrl_new(struct rsnd_mod *mod, | 884 | static int __rsnd_kctrl_new(struct rsnd_mod *mod, |
885 | struct rsnd_dai_stream *io, | ||
831 | struct snd_soc_pcm_runtime *rtd, | 886 | struct snd_soc_pcm_runtime *rtd, |
832 | const unsigned char *name, | 887 | const unsigned char *name, |
833 | struct rsnd_kctrl_cfg *cfg, | 888 | struct rsnd_kctrl_cfg *cfg, |
834 | void (*update)(struct rsnd_mod *mod)) | 889 | void (*update)(struct rsnd_dai_stream *io, |
890 | struct rsnd_mod *mod)) | ||
835 | { | 891 | { |
892 | struct snd_soc_card *soc_card = rtd->card; | ||
836 | struct snd_card *card = rtd->card->snd_card; | 893 | struct snd_card *card = rtd->card->snd_card; |
837 | struct snd_kcontrol *kctrl; | 894 | struct snd_kcontrol *kctrl; |
838 | struct snd_kcontrol_new knew = { | 895 | struct snd_kcontrol_new knew = { |
839 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 896 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
840 | .name = name, | 897 | .name = name, |
841 | .info = rsnd_kctrl_info, | 898 | .info = rsnd_kctrl_info, |
899 | .index = rtd - soc_card->rtd, | ||
842 | .get = rsnd_kctrl_get, | 900 | .get = rsnd_kctrl_get, |
843 | .put = rsnd_kctrl_put, | 901 | .put = rsnd_kctrl_put, |
844 | .private_value = (unsigned long)cfg, | 902 | .private_value = (unsigned long)cfg, |
@@ -858,6 +916,7 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, | |||
858 | cfg->update = update; | 916 | cfg->update = update; |
859 | cfg->card = card; | 917 | cfg->card = card; |
860 | cfg->kctrl = kctrl; | 918 | cfg->kctrl = kctrl; |
919 | cfg->io = io; | ||
861 | 920 | ||
862 | return 0; | 921 | return 0; |
863 | } | 922 | } |
@@ -868,36 +927,42 @@ void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg) | |||
868 | } | 927 | } |
869 | 928 | ||
870 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | 929 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, |
930 | struct rsnd_dai_stream *io, | ||
871 | struct snd_soc_pcm_runtime *rtd, | 931 | struct snd_soc_pcm_runtime *rtd, |
872 | const unsigned char *name, | 932 | const unsigned char *name, |
873 | void (*update)(struct rsnd_mod *mod), | 933 | void (*update)(struct rsnd_dai_stream *io, |
934 | struct rsnd_mod *mod), | ||
874 | struct rsnd_kctrl_cfg_m *_cfg, | 935 | struct rsnd_kctrl_cfg_m *_cfg, |
875 | u32 max) | 936 | u32 max) |
876 | { | 937 | { |
877 | _cfg->cfg.max = max; | 938 | _cfg->cfg.max = max; |
878 | _cfg->cfg.size = RSND_DVC_CHANNELS; | 939 | _cfg->cfg.size = RSND_DVC_CHANNELS; |
879 | _cfg->cfg.val = _cfg->val; | 940 | _cfg->cfg.val = _cfg->val; |
880 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); | 941 | return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); |
881 | } | 942 | } |
882 | 943 | ||
883 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | 944 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, |
945 | struct rsnd_dai_stream *io, | ||
884 | struct snd_soc_pcm_runtime *rtd, | 946 | struct snd_soc_pcm_runtime *rtd, |
885 | const unsigned char *name, | 947 | const unsigned char *name, |
886 | void (*update)(struct rsnd_mod *mod), | 948 | void (*update)(struct rsnd_dai_stream *io, |
949 | struct rsnd_mod *mod), | ||
887 | struct rsnd_kctrl_cfg_s *_cfg, | 950 | struct rsnd_kctrl_cfg_s *_cfg, |
888 | u32 max) | 951 | u32 max) |
889 | { | 952 | { |
890 | _cfg->cfg.max = max; | 953 | _cfg->cfg.max = max; |
891 | _cfg->cfg.size = 1; | 954 | _cfg->cfg.size = 1; |
892 | _cfg->cfg.val = &_cfg->val; | 955 | _cfg->cfg.val = &_cfg->val; |
893 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); | 956 | return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); |
894 | } | 957 | } |
895 | 958 | ||
896 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | 959 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, |
960 | struct rsnd_dai_stream *io, | ||
897 | struct snd_soc_pcm_runtime *rtd, | 961 | struct snd_soc_pcm_runtime *rtd, |
898 | const unsigned char *name, | 962 | const unsigned char *name, |
899 | struct rsnd_kctrl_cfg_s *_cfg, | 963 | struct rsnd_kctrl_cfg_s *_cfg, |
900 | void (*update)(struct rsnd_mod *mod), | 964 | void (*update)(struct rsnd_dai_stream *io, |
965 | struct rsnd_mod *mod), | ||
901 | const char * const *texts, | 966 | const char * const *texts, |
902 | u32 max) | 967 | u32 max) |
903 | { | 968 | { |
@@ -905,7 +970,7 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod, | |||
905 | _cfg->cfg.size = 1; | 970 | _cfg->cfg.size = 1; |
906 | _cfg->cfg.val = &_cfg->val; | 971 | _cfg->cfg.val = &_cfg->val; |
907 | _cfg->cfg.texts = texts; | 972 | _cfg->cfg.texts = texts; |
908 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); | 973 | return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); |
909 | } | 974 | } |
910 | 975 | ||
911 | /* | 976 | /* |
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index ac3756f6af60..d306e298c63d 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -32,11 +32,12 @@ struct rsnd_dma_ctrl { | |||
32 | /* | 32 | /* |
33 | * Audio DMAC | 33 | * Audio DMAC |
34 | */ | 34 | */ |
35 | static void rsnd_dmaen_complete(void *data) | 35 | static void __rsnd_dmaen_complete(struct rsnd_mod *mod, |
36 | struct rsnd_dai_stream *io) | ||
36 | { | 37 | { |
37 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 38 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
38 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 39 | bool elapsed = false; |
39 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 40 | unsigned long flags; |
40 | 41 | ||
41 | /* | 42 | /* |
42 | * Renesas sound Gen1 needs 1 DMAC, | 43 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -49,23 +50,36 @@ static void rsnd_dmaen_complete(void *data) | |||
49 | * rsnd_dai_pointer_update() will be called twice, | 50 | * rsnd_dai_pointer_update() will be called twice, |
50 | * ant it will breaks io->byte_pos | 51 | * ant it will breaks io->byte_pos |
51 | */ | 52 | */ |
53 | spin_lock_irqsave(&priv->lock, flags); | ||
54 | |||
55 | if (rsnd_io_is_working(io)) | ||
56 | elapsed = rsnd_dai_pointer_update(io, io->byte_per_period); | ||
52 | 57 | ||
53 | rsnd_dai_pointer_update(io, io->byte_per_period); | 58 | spin_unlock_irqrestore(&priv->lock, flags); |
59 | |||
60 | if (elapsed) | ||
61 | rsnd_dai_period_elapsed(io); | ||
54 | } | 62 | } |
55 | 63 | ||
56 | static void rsnd_dmaen_stop(struct rsnd_dma *dma) | 64 | static void rsnd_dmaen_complete(void *data) |
65 | { | ||
66 | struct rsnd_mod *mod = data; | ||
67 | |||
68 | rsnd_mod_interrupt(mod, __rsnd_dmaen_complete); | ||
69 | } | ||
70 | |||
71 | static void rsnd_dmaen_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | ||
57 | { | 72 | { |
58 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 73 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
59 | 74 | ||
60 | dmaengine_terminate_all(dmaen->chan); | 75 | dmaengine_terminate_all(dmaen->chan); |
61 | } | 76 | } |
62 | 77 | ||
63 | static void rsnd_dmaen_start(struct rsnd_dma *dma) | 78 | static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
64 | { | 79 | { |
65 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 80 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
66 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 81 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
67 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 82 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
68 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
69 | struct snd_pcm_substream *substream = io->substream; | 83 | struct snd_pcm_substream *substream = io->substream; |
70 | struct device *dev = rsnd_priv_to_dev(priv); | 84 | struct device *dev = rsnd_priv_to_dev(priv); |
71 | struct dma_async_tx_descriptor *desc; | 85 | struct dma_async_tx_descriptor *desc; |
@@ -84,7 +98,7 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) | |||
84 | } | 98 | } |
85 | 99 | ||
86 | desc->callback = rsnd_dmaen_complete; | 100 | desc->callback = rsnd_dmaen_complete; |
87 | desc->callback_param = dma; | 101 | desc->callback_param = mod; |
88 | 102 | ||
89 | if (dmaengine_submit(desc) < 0) { | 103 | if (dmaengine_submit(desc) < 0) { |
90 | dev_err(dev, "dmaengine_submit() fail\n"); | 104 | dev_err(dev, "dmaengine_submit() fail\n"); |
@@ -115,7 +129,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, | |||
115 | return chan; | 129 | return chan; |
116 | } | 130 | } |
117 | 131 | ||
118 | static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_mod *mod_from, | 132 | static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io, |
133 | struct rsnd_mod *mod_from, | ||
119 | struct rsnd_mod *mod_to) | 134 | struct rsnd_mod *mod_to) |
120 | { | 135 | { |
121 | if ((!mod_from && !mod_to) || | 136 | if ((!mod_from && !mod_to) || |
@@ -123,19 +138,19 @@ static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_mod *mod_from, | |||
123 | return NULL; | 138 | return NULL; |
124 | 139 | ||
125 | if (mod_from) | 140 | if (mod_from) |
126 | return rsnd_mod_dma_req(mod_from); | 141 | return rsnd_mod_dma_req(io, mod_from); |
127 | else | 142 | else |
128 | return rsnd_mod_dma_req(mod_to); | 143 | return rsnd_mod_dma_req(io, mod_to); |
129 | } | 144 | } |
130 | 145 | ||
131 | static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | 146 | static int rsnd_dmaen_init(struct rsnd_dai_stream *io, |
147 | struct rsnd_dma *dma, int id, | ||
132 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) | 148 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) |
133 | { | 149 | { |
134 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 150 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
151 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | ||
135 | struct device *dev = rsnd_priv_to_dev(priv); | 152 | struct device *dev = rsnd_priv_to_dev(priv); |
136 | struct dma_slave_config cfg = {}; | 153 | struct dma_slave_config cfg = {}; |
137 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | ||
138 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
139 | int is_play = rsnd_io_is_play(io); | 154 | int is_play = rsnd_io_is_play(io); |
140 | int ret; | 155 | int ret; |
141 | 156 | ||
@@ -145,7 +160,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | |||
145 | } | 160 | } |
146 | 161 | ||
147 | if (dev->of_node) { | 162 | if (dev->of_node) { |
148 | dmaen->chan = rsnd_dmaen_request_channel(mod_from, mod_to); | 163 | dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to); |
149 | } else { | 164 | } else { |
150 | dma_cap_mask_t mask; | 165 | dma_cap_mask_t mask; |
151 | 166 | ||
@@ -156,6 +171,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | |||
156 | (void *)id); | 171 | (void *)id); |
157 | } | 172 | } |
158 | if (IS_ERR_OR_NULL(dmaen->chan)) { | 173 | if (IS_ERR_OR_NULL(dmaen->chan)) { |
174 | dmaen->chan = NULL; | ||
159 | dev_err(dev, "can't get dma channel\n"); | 175 | dev_err(dev, "can't get dma channel\n"); |
160 | goto rsnd_dma_channel_err; | 176 | goto rsnd_dma_channel_err; |
161 | } | 177 | } |
@@ -176,7 +192,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | |||
176 | return 0; | 192 | return 0; |
177 | 193 | ||
178 | rsnd_dma_init_err: | 194 | rsnd_dma_init_err: |
179 | rsnd_dma_quit(dma); | 195 | rsnd_dma_quit(io, dma); |
180 | rsnd_dma_channel_err: | 196 | rsnd_dma_channel_err: |
181 | 197 | ||
182 | /* | 198 | /* |
@@ -188,7 +204,7 @@ rsnd_dma_channel_err: | |||
188 | return -EAGAIN; | 204 | return -EAGAIN; |
189 | } | 205 | } |
190 | 206 | ||
191 | static void rsnd_dmaen_quit(struct rsnd_dma *dma) | 207 | static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
192 | { | 208 | { |
193 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 209 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
194 | 210 | ||
@@ -237,9 +253,9 @@ static const u8 gen2_id_table_cmd[] = { | |||
237 | 0x38, /* SCU_CMD1 */ | 253 | 0x38, /* SCU_CMD1 */ |
238 | }; | 254 | }; |
239 | 255 | ||
240 | static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod) | 256 | static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io, |
257 | struct rsnd_mod *mod) | ||
241 | { | 258 | { |
242 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
243 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); | 259 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); |
244 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 260 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
245 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 261 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
@@ -267,11 +283,12 @@ static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod) | |||
267 | return entry[id]; | 283 | return entry[id]; |
268 | } | 284 | } |
269 | 285 | ||
270 | static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from, | 286 | static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io, |
287 | struct rsnd_mod *mod_from, | ||
271 | struct rsnd_mod *mod_to) | 288 | struct rsnd_mod *mod_to) |
272 | { | 289 | { |
273 | return (rsnd_dmapp_get_id(mod_from) << 24) + | 290 | return (rsnd_dmapp_get_id(io, mod_from) << 24) + |
274 | (rsnd_dmapp_get_id(mod_to) << 16); | 291 | (rsnd_dmapp_get_id(io, mod_to) << 16); |
275 | } | 292 | } |
276 | 293 | ||
277 | #define rsnd_dmapp_addr(dmac, dma, reg) \ | 294 | #define rsnd_dmapp_addr(dmac, dma, reg) \ |
@@ -298,7 +315,7 @@ static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg) | |||
298 | return ioread32(rsnd_dmapp_addr(dmac, dma, reg)); | 315 | return ioread32(rsnd_dmapp_addr(dmac, dma, reg)); |
299 | } | 316 | } |
300 | 317 | ||
301 | static void rsnd_dmapp_stop(struct rsnd_dma *dma) | 318 | static void rsnd_dmapp_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
302 | { | 319 | { |
303 | int i; | 320 | int i; |
304 | 321 | ||
@@ -311,7 +328,7 @@ static void rsnd_dmapp_stop(struct rsnd_dma *dma) | |||
311 | } | 328 | } |
312 | } | 329 | } |
313 | 330 | ||
314 | static void rsnd_dmapp_start(struct rsnd_dma *dma) | 331 | static void rsnd_dmapp_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
315 | { | 332 | { |
316 | struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); | 333 | struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); |
317 | 334 | ||
@@ -320,19 +337,21 @@ static void rsnd_dmapp_start(struct rsnd_dma *dma) | |||
320 | rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); | 337 | rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); |
321 | } | 338 | } |
322 | 339 | ||
323 | static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | 340 | static int rsnd_dmapp_init(struct rsnd_dai_stream *io, |
341 | struct rsnd_dma *dma, int id, | ||
324 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) | 342 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) |
325 | { | 343 | { |
326 | struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); | 344 | struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); |
345 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | ||
327 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 346 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
328 | struct device *dev = rsnd_priv_to_dev(priv); | 347 | struct device *dev = rsnd_priv_to_dev(priv); |
329 | 348 | ||
330 | dmapp->dmapp_id = dmac->dmapp_num; | 349 | dmapp->dmapp_id = dmac->dmapp_num; |
331 | dmapp->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE; | 350 | dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE; |
332 | 351 | ||
333 | dmac->dmapp_num++; | 352 | dmac->dmapp_num++; |
334 | 353 | ||
335 | rsnd_dmapp_stop(dma); | 354 | rsnd_dmapp_stop(io, dma); |
336 | 355 | ||
337 | dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n", | 356 | dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n", |
338 | dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr); | 357 | dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr); |
@@ -385,12 +404,12 @@ static struct rsnd_dma_ops rsnd_dmapp_ops = { | |||
385 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) | 404 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) |
386 | 405 | ||
387 | static dma_addr_t | 406 | static dma_addr_t |
388 | rsnd_gen2_dma_addr(struct rsnd_priv *priv, | 407 | rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, |
389 | struct rsnd_mod *mod, | 408 | struct rsnd_mod *mod, |
390 | int is_play, int is_from) | 409 | int is_play, int is_from) |
391 | { | 410 | { |
411 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | ||
392 | struct device *dev = rsnd_priv_to_dev(priv); | 412 | struct device *dev = rsnd_priv_to_dev(priv); |
393 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
394 | phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); | 413 | phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); |
395 | phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); | 414 | phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); |
396 | int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); | 415 | int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); |
@@ -437,7 +456,7 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv, | |||
437 | dev_err(dev, "DVC is selected without SRC\n"); | 456 | dev_err(dev, "DVC is selected without SRC\n"); |
438 | 457 | ||
439 | /* use SSIU or SSI ? */ | 458 | /* use SSIU or SSI ? */ |
440 | if (is_ssi && rsnd_ssi_use_busif(mod)) | 459 | if (is_ssi && rsnd_ssi_use_busif(io, mod)) |
441 | is_ssi++; | 460 | is_ssi++; |
442 | 461 | ||
443 | return (is_from) ? | 462 | return (is_from) ? |
@@ -445,10 +464,12 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv, | |||
445 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | 464 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; |
446 | } | 465 | } |
447 | 466 | ||
448 | static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, | 467 | static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, |
449 | struct rsnd_mod *mod, | 468 | struct rsnd_mod *mod, |
450 | int is_play, int is_from) | 469 | int is_play, int is_from) |
451 | { | 470 | { |
471 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | ||
472 | |||
452 | /* | 473 | /* |
453 | * gen1 uses default DMA addr | 474 | * gen1 uses default DMA addr |
454 | */ | 475 | */ |
@@ -458,17 +479,17 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, | |||
458 | if (!mod) | 479 | if (!mod) |
459 | return 0; | 480 | return 0; |
460 | 481 | ||
461 | return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); | 482 | return rsnd_gen2_dma_addr(io, mod, is_play, is_from); |
462 | } | 483 | } |
463 | 484 | ||
464 | #define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ | 485 | #define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ |
465 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | 486 | static void rsnd_dma_of_path(struct rsnd_dma *dma, |
487 | struct rsnd_dai_stream *io, | ||
466 | int is_play, | 488 | int is_play, |
467 | struct rsnd_mod **mod_from, | 489 | struct rsnd_mod **mod_from, |
468 | struct rsnd_mod **mod_to) | 490 | struct rsnd_mod **mod_to) |
469 | { | 491 | { |
470 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 492 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
471 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); | ||
472 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); | 493 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); |
473 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 494 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
474 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 495 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
@@ -523,17 +544,17 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, | |||
523 | } | 544 | } |
524 | } | 545 | } |
525 | 546 | ||
526 | void rsnd_dma_stop(struct rsnd_dma *dma) | 547 | void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
527 | { | 548 | { |
528 | dma->ops->stop(dma); | 549 | dma->ops->stop(io, dma); |
529 | } | 550 | } |
530 | 551 | ||
531 | void rsnd_dma_start(struct rsnd_dma *dma) | 552 | void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
532 | { | 553 | { |
533 | dma->ops->start(dma); | 554 | dma->ops->start(io, dma); |
534 | } | 555 | } |
535 | 556 | ||
536 | void rsnd_dma_quit(struct rsnd_dma *dma) | 557 | void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) |
537 | { | 558 | { |
538 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 559 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
539 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 560 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
@@ -542,15 +563,14 @@ void rsnd_dma_quit(struct rsnd_dma *dma) | |||
542 | if (!dmac) | 563 | if (!dmac) |
543 | return; | 564 | return; |
544 | 565 | ||
545 | dma->ops->quit(dma); | 566 | dma->ops->quit(io, dma); |
546 | } | 567 | } |
547 | 568 | ||
548 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) | 569 | int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) |
549 | { | 570 | { |
550 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | ||
551 | struct rsnd_mod *mod_from; | 571 | struct rsnd_mod *mod_from; |
552 | struct rsnd_mod *mod_to; | 572 | struct rsnd_mod *mod_to; |
553 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 573 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
554 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 574 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
555 | int is_play = rsnd_io_is_play(io); | 575 | int is_play = rsnd_io_is_play(io); |
556 | 576 | ||
@@ -563,10 +583,10 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) | |||
563 | if (!dmac) | 583 | if (!dmac) |
564 | return -EAGAIN; | 584 | return -EAGAIN; |
565 | 585 | ||
566 | rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); | 586 | rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to); |
567 | 587 | ||
568 | dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); | 588 | dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); |
569 | dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); | 589 | dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); |
570 | 590 | ||
571 | /* for Gen2 */ | 591 | /* for Gen2 */ |
572 | if (mod_from && mod_to) | 592 | if (mod_from && mod_to) |
@@ -578,7 +598,7 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) | |||
578 | if (rsnd_is_gen1(priv)) | 598 | if (rsnd_is_gen1(priv)) |
579 | dma->ops = &rsnd_dmaen_ops; | 599 | dma->ops = &rsnd_dmaen_ops; |
580 | 600 | ||
581 | return dma->ops->init(priv, dma, id, mod_from, mod_to); | 601 | return dma->ops->init(io, dma, id, mod_from, mod_to); |
582 | } | 602 | } |
583 | 603 | ||
584 | int rsnd_dma_probe(struct platform_device *pdev, | 604 | int rsnd_dma_probe(struct platform_device *pdev, |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index e5fcb062ad77..36fc020cbc18 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -63,7 +63,8 @@ static const char * const dvc_ramp_rate[] = { | |||
63 | "0.125 dB/8192 steps", /* 10111 */ | 63 | "0.125 dB/8192 steps", /* 10111 */ |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | 66 | static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, |
67 | struct rsnd_mod *mod) | ||
67 | { | 68 | { |
68 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 69 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
69 | u32 val[RSND_DVC_CHANNELS]; | 70 | u32 val[RSND_DVC_CHANNELS]; |
@@ -120,6 +121,7 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | |||
120 | } | 121 | } |
121 | 122 | ||
122 | static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, | 123 | static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, |
124 | struct rsnd_dai_stream *io, | ||
123 | struct rsnd_priv *priv) | 125 | struct rsnd_priv *priv) |
124 | { | 126 | { |
125 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 127 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
@@ -134,9 +136,9 @@ static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, | |||
134 | } | 136 | } |
135 | 137 | ||
136 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | 138 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, |
139 | struct rsnd_dai_stream *io, | ||
137 | struct rsnd_priv *priv) | 140 | struct rsnd_priv *priv) |
138 | { | 141 | { |
139 | struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); | ||
140 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 142 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); |
141 | struct device *dev = rsnd_priv_to_dev(priv); | 143 | struct device *dev = rsnd_priv_to_dev(priv); |
142 | int dvc_id = rsnd_mod_id(dvc_mod); | 144 | int dvc_id = rsnd_mod_id(dvc_mod); |
@@ -168,10 +170,10 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
168 | 170 | ||
169 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); | 171 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); |
170 | 172 | ||
171 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | 173 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io)); |
172 | 174 | ||
173 | /* ch0/ch1 Volume */ | 175 | /* ch0/ch1 Volume */ |
174 | rsnd_dvc_volume_update(dvc_mod); | 176 | rsnd_dvc_volume_update(io, dvc_mod); |
175 | 177 | ||
176 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); | 178 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); |
177 | 179 | ||
@@ -181,6 +183,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
181 | } | 183 | } |
182 | 184 | ||
183 | static int rsnd_dvc_quit(struct rsnd_mod *mod, | 185 | static int rsnd_dvc_quit(struct rsnd_mod *mod, |
186 | struct rsnd_dai_stream *io, | ||
184 | struct rsnd_priv *priv) | 187 | struct rsnd_priv *priv) |
185 | { | 188 | { |
186 | rsnd_mod_hw_stop(mod); | 189 | rsnd_mod_hw_stop(mod); |
@@ -189,6 +192,7 @@ static int rsnd_dvc_quit(struct rsnd_mod *mod, | |||
189 | } | 192 | } |
190 | 193 | ||
191 | static int rsnd_dvc_start(struct rsnd_mod *mod, | 194 | static int rsnd_dvc_start(struct rsnd_mod *mod, |
195 | struct rsnd_dai_stream *io, | ||
192 | struct rsnd_priv *priv) | 196 | struct rsnd_priv *priv) |
193 | { | 197 | { |
194 | rsnd_mod_write(mod, CMD_CTRL, 0x10); | 198 | rsnd_mod_write(mod, CMD_CTRL, 0x10); |
@@ -197,6 +201,7 @@ static int rsnd_dvc_start(struct rsnd_mod *mod, | |||
197 | } | 201 | } |
198 | 202 | ||
199 | static int rsnd_dvc_stop(struct rsnd_mod *mod, | 203 | static int rsnd_dvc_stop(struct rsnd_mod *mod, |
204 | struct rsnd_dai_stream *io, | ||
200 | struct rsnd_priv *priv) | 205 | struct rsnd_priv *priv) |
201 | { | 206 | { |
202 | rsnd_mod_write(mod, CMD_CTRL, 0); | 207 | rsnd_mod_write(mod, CMD_CTRL, 0); |
@@ -205,15 +210,15 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
205 | } | 210 | } |
206 | 211 | ||
207 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 212 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
213 | struct rsnd_dai_stream *io, | ||
208 | struct snd_soc_pcm_runtime *rtd) | 214 | struct snd_soc_pcm_runtime *rtd) |
209 | { | 215 | { |
210 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
211 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 216 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
212 | int is_play = rsnd_io_is_play(io); | 217 | int is_play = rsnd_io_is_play(io); |
213 | int ret; | 218 | int ret; |
214 | 219 | ||
215 | /* Volume */ | 220 | /* Volume */ |
216 | ret = rsnd_kctrl_new_m(mod, rtd, | 221 | ret = rsnd_kctrl_new_m(mod, io, rtd, |
217 | is_play ? | 222 | is_play ? |
218 | "DVC Out Playback Volume" : "DVC In Capture Volume", | 223 | "DVC Out Playback Volume" : "DVC In Capture Volume", |
219 | rsnd_dvc_volume_update, | 224 | rsnd_dvc_volume_update, |
@@ -222,7 +227,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
222 | return ret; | 227 | return ret; |
223 | 228 | ||
224 | /* Mute */ | 229 | /* Mute */ |
225 | ret = rsnd_kctrl_new_m(mod, rtd, | 230 | ret = rsnd_kctrl_new_m(mod, io, rtd, |
226 | is_play ? | 231 | is_play ? |
227 | "DVC Out Mute Switch" : "DVC In Mute Switch", | 232 | "DVC Out Mute Switch" : "DVC In Mute Switch", |
228 | rsnd_dvc_volume_update, | 233 | rsnd_dvc_volume_update, |
@@ -231,7 +236,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
231 | return ret; | 236 | return ret; |
232 | 237 | ||
233 | /* Ramp */ | 238 | /* Ramp */ |
234 | ret = rsnd_kctrl_new_s(mod, rtd, | 239 | ret = rsnd_kctrl_new_s(mod, io, rtd, |
235 | is_play ? | 240 | is_play ? |
236 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", | 241 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", |
237 | rsnd_dvc_volume_update, | 242 | rsnd_dvc_volume_update, |
@@ -239,7 +244,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
239 | if (ret < 0) | 244 | if (ret < 0) |
240 | return ret; | 245 | return ret; |
241 | 246 | ||
242 | ret = rsnd_kctrl_new_e(mod, rtd, | 247 | ret = rsnd_kctrl_new_e(mod, io, rtd, |
243 | is_play ? | 248 | is_play ? |
244 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", | 249 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", |
245 | &dvc->rup, | 250 | &dvc->rup, |
@@ -248,7 +253,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
248 | if (ret < 0) | 253 | if (ret < 0) |
249 | return ret; | 254 | return ret; |
250 | 255 | ||
251 | ret = rsnd_kctrl_new_e(mod, rtd, | 256 | ret = rsnd_kctrl_new_e(mod, io, rtd, |
252 | is_play ? | 257 | is_play ? |
253 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", | 258 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", |
254 | &dvc->rdown, | 259 | &dvc->rdown, |
@@ -261,7 +266,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
261 | return 0; | 266 | return 0; |
262 | } | 267 | } |
263 | 268 | ||
264 | static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_mod *mod) | 269 | static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io, |
270 | struct rsnd_mod *mod) | ||
265 | { | 271 | { |
266 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 272 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
267 | 273 | ||
@@ -366,7 +372,7 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
366 | 372 | ||
367 | dvc->info = &info->dvc_info[i]; | 373 | dvc->info = &info->dvc_info[i]; |
368 | 374 | ||
369 | ret = rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops, | 375 | ret = rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, |
370 | clk, RSND_MOD_DVC, i); | 376 | clk, RSND_MOD_DVC, i); |
371 | if (ret) | 377 | if (ret) |
372 | return ret; | 378 | return ret; |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4e6de6804cfb..09fcc54a8ee0 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -165,18 +165,18 @@ void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
165 | enum rsnd_reg reg, u32 data); | 165 | enum rsnd_reg reg, u32 data); |
166 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, | 166 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, |
167 | u32 mask, u32 data); | 167 | u32 mask, u32 data); |
168 | u32 rsnd_get_adinr(struct rsnd_mod *mod); | 168 | u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io); |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * R-Car DMA | 171 | * R-Car DMA |
172 | */ | 172 | */ |
173 | struct rsnd_dma; | 173 | struct rsnd_dma; |
174 | struct rsnd_dma_ops { | 174 | struct rsnd_dma_ops { |
175 | void (*start)(struct rsnd_dma *dma); | 175 | void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
176 | void (*stop)(struct rsnd_dma *dma); | 176 | void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
177 | int (*init)(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, | 177 | int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, |
178 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); | 178 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); |
179 | void (*quit)(struct rsnd_dma *dma); | 179 | void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
180 | }; | 180 | }; |
181 | 181 | ||
182 | struct rsnd_dmaen { | 182 | struct rsnd_dmaen { |
@@ -200,10 +200,10 @@ struct rsnd_dma { | |||
200 | #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) | 200 | #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) |
201 | #define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) | 201 | #define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) |
202 | 202 | ||
203 | void rsnd_dma_start(struct rsnd_dma *dma); | 203 | void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
204 | void rsnd_dma_stop(struct rsnd_dma *dma); | 204 | void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
205 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); | 205 | int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id); |
206 | void rsnd_dma_quit(struct rsnd_dma *dma); | 206 | void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma); |
207 | int rsnd_dma_probe(struct platform_device *pdev, | 207 | int rsnd_dma_probe(struct platform_device *pdev, |
208 | const struct rsnd_of_data *of_data, | 208 | const struct rsnd_of_data *of_data, |
209 | struct rsnd_priv *priv); | 209 | struct rsnd_priv *priv); |
@@ -224,25 +224,35 @@ enum rsnd_mod_type { | |||
224 | 224 | ||
225 | struct rsnd_mod_ops { | 225 | struct rsnd_mod_ops { |
226 | char *name; | 226 | char *name; |
227 | struct dma_chan* (*dma_req)(struct rsnd_mod *mod); | 227 | struct dma_chan* (*dma_req)(struct rsnd_dai_stream *io, |
228 | struct rsnd_mod *mod); | ||
228 | int (*probe)(struct rsnd_mod *mod, | 229 | int (*probe)(struct rsnd_mod *mod, |
230 | struct rsnd_dai_stream *io, | ||
229 | struct rsnd_priv *priv); | 231 | struct rsnd_priv *priv); |
230 | int (*remove)(struct rsnd_mod *mod, | 232 | int (*remove)(struct rsnd_mod *mod, |
233 | struct rsnd_dai_stream *io, | ||
231 | struct rsnd_priv *priv); | 234 | struct rsnd_priv *priv); |
232 | int (*init)(struct rsnd_mod *mod, | 235 | int (*init)(struct rsnd_mod *mod, |
236 | struct rsnd_dai_stream *io, | ||
233 | struct rsnd_priv *priv); | 237 | struct rsnd_priv *priv); |
234 | int (*quit)(struct rsnd_mod *mod, | 238 | int (*quit)(struct rsnd_mod *mod, |
239 | struct rsnd_dai_stream *io, | ||
235 | struct rsnd_priv *priv); | 240 | struct rsnd_priv *priv); |
236 | int (*start)(struct rsnd_mod *mod, | 241 | int (*start)(struct rsnd_mod *mod, |
242 | struct rsnd_dai_stream *io, | ||
237 | struct rsnd_priv *priv); | 243 | struct rsnd_priv *priv); |
238 | int (*stop)(struct rsnd_mod *mod, | 244 | int (*stop)(struct rsnd_mod *mod, |
245 | struct rsnd_dai_stream *io, | ||
239 | struct rsnd_priv *priv); | 246 | struct rsnd_priv *priv); |
240 | int (*pcm_new)(struct rsnd_mod *mod, | 247 | int (*pcm_new)(struct rsnd_mod *mod, |
248 | struct rsnd_dai_stream *io, | ||
241 | struct snd_soc_pcm_runtime *rtd); | 249 | struct snd_soc_pcm_runtime *rtd); |
242 | int (*hw_params)(struct rsnd_mod *mod, | 250 | int (*hw_params)(struct rsnd_mod *mod, |
251 | struct rsnd_dai_stream *io, | ||
243 | struct snd_pcm_substream *substream, | 252 | struct snd_pcm_substream *substream, |
244 | struct snd_pcm_hw_params *hw_params); | 253 | struct snd_pcm_hw_params *hw_params); |
245 | int (*fallback)(struct rsnd_mod *mod, | 254 | int (*fallback)(struct rsnd_mod *mod, |
255 | struct rsnd_dai_stream *io, | ||
246 | struct rsnd_priv *priv); | 256 | struct rsnd_priv *priv); |
247 | }; | 257 | }; |
248 | 258 | ||
@@ -252,32 +262,43 @@ struct rsnd_mod { | |||
252 | enum rsnd_mod_type type; | 262 | enum rsnd_mod_type type; |
253 | struct rsnd_mod_ops *ops; | 263 | struct rsnd_mod_ops *ops; |
254 | struct rsnd_dma dma; | 264 | struct rsnd_dma dma; |
255 | struct rsnd_dai_stream *io; | 265 | struct rsnd_priv *priv; |
256 | struct clk *clk; | 266 | struct clk *clk; |
257 | u32 status; | 267 | u32 status; |
258 | }; | 268 | }; |
259 | /* | 269 | /* |
260 | * status | 270 | * status |
261 | * | 271 | * |
262 | * bit | 272 | * 0xH0000CBA |
263 | * 0 0: probe 1: remove | 273 | * |
264 | * 1 0: init 1: quit | 274 | * A 0: probe 1: remove |
265 | * 2 0: start 1: stop | 275 | * B 0: init 1: quit |
266 | * 3 0: pcm_new | 276 | * C 0: start 1: stop |
267 | * 4 0: fallback | ||
268 | * | 277 | * |
269 | * 31 bit is always called (see __rsnd_mod_call) | 278 | * H is always called (see __rsnd_mod_call) |
270 | * 31 0: hw_params | 279 | * H 0: pcm_new |
280 | * H 0: fallback | ||
281 | * H 0: hw_params | ||
271 | */ | 282 | */ |
272 | #define __rsnd_mod_shift_probe 0 | 283 | #define __rsnd_mod_shift_probe 0 |
273 | #define __rsnd_mod_shift_remove 0 | 284 | #define __rsnd_mod_shift_remove 0 |
274 | #define __rsnd_mod_shift_init 1 | 285 | #define __rsnd_mod_shift_init 4 |
275 | #define __rsnd_mod_shift_quit 1 | 286 | #define __rsnd_mod_shift_quit 4 |
276 | #define __rsnd_mod_shift_start 2 | 287 | #define __rsnd_mod_shift_start 8 |
277 | #define __rsnd_mod_shift_stop 2 | 288 | #define __rsnd_mod_shift_stop 8 |
278 | #define __rsnd_mod_shift_pcm_new 3 | 289 | #define __rsnd_mod_shift_pcm_new 28 /* always called */ |
279 | #define __rsnd_mod_shift_fallback 4 | 290 | #define __rsnd_mod_shift_fallback 28 /* always called */ |
280 | #define __rsnd_mod_shift_hw_params 31 /* always called */ | 291 | #define __rsnd_mod_shift_hw_params 28 /* always called */ |
292 | |||
293 | #define __rsnd_mod_add_probe 1 | ||
294 | #define __rsnd_mod_add_remove -1 | ||
295 | #define __rsnd_mod_add_init 1 | ||
296 | #define __rsnd_mod_add_quit -1 | ||
297 | #define __rsnd_mod_add_start 1 | ||
298 | #define __rsnd_mod_add_stop -1 | ||
299 | #define __rsnd_mod_add_pcm_new 0 | ||
300 | #define __rsnd_mod_add_fallback 0 | ||
301 | #define __rsnd_mod_add_hw_params 0 | ||
281 | 302 | ||
282 | #define __rsnd_mod_call_probe 0 | 303 | #define __rsnd_mod_call_probe 0 |
283 | #define __rsnd_mod_call_remove 1 | 304 | #define __rsnd_mod_call_remove 1 |
@@ -289,21 +310,25 @@ struct rsnd_mod { | |||
289 | #define __rsnd_mod_call_fallback 0 | 310 | #define __rsnd_mod_call_fallback 0 |
290 | #define __rsnd_mod_call_hw_params 0 | 311 | #define __rsnd_mod_call_hw_params 0 |
291 | 312 | ||
292 | #define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod))) | 313 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
293 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | 314 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
294 | #define rsnd_mod_to_io(mod) ((mod)->io) | ||
295 | #define rsnd_mod_id(mod) ((mod)->id) | 315 | #define rsnd_mod_id(mod) ((mod)->id) |
296 | #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) | 316 | #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) |
297 | #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk) | 317 | #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk) |
298 | 318 | ||
299 | int rsnd_mod_init(struct rsnd_mod *mod, | 319 | int rsnd_mod_init(struct rsnd_priv *priv, |
320 | struct rsnd_mod *mod, | ||
300 | struct rsnd_mod_ops *ops, | 321 | struct rsnd_mod_ops *ops, |
301 | struct clk *clk, | 322 | struct clk *clk, |
302 | enum rsnd_mod_type type, | 323 | enum rsnd_mod_type type, |
303 | int id); | 324 | int id); |
304 | void rsnd_mod_quit(struct rsnd_mod *mod); | 325 | void rsnd_mod_quit(struct rsnd_mod *mod); |
305 | char *rsnd_mod_name(struct rsnd_mod *mod); | 326 | char *rsnd_mod_name(struct rsnd_mod *mod); |
306 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod); | 327 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, |
328 | struct rsnd_mod *mod); | ||
329 | void rsnd_mod_interrupt(struct rsnd_mod *mod, | ||
330 | void (*callback)(struct rsnd_mod *mod, | ||
331 | struct rsnd_dai_stream *io)); | ||
307 | 332 | ||
308 | /* | 333 | /* |
309 | * R-Car sound DAI | 334 | * R-Car sound DAI |
@@ -328,7 +353,7 @@ struct rsnd_dai_stream { | |||
328 | #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) | 353 | #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) |
329 | #define rsnd_io_to_runtime(io) ((io)->substream ? \ | 354 | #define rsnd_io_to_runtime(io) ((io)->substream ? \ |
330 | (io)->substream->runtime : NULL) | 355 | (io)->substream->runtime : NULL) |
331 | 356 | int rsnd_io_is_working(struct rsnd_dai_stream *io); | |
332 | 357 | ||
333 | struct rsnd_dai { | 358 | struct rsnd_dai { |
334 | char name[RSND_DAI_NAME_SIZE]; | 359 | char name[RSND_DAI_NAME_SIZE]; |
@@ -354,7 +379,8 @@ struct rsnd_dai { | |||
354 | 379 | ||
355 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); | 380 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); |
356 | 381 | ||
357 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | 382 | bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); |
383 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); | ||
358 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | 384 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); |
359 | 385 | ||
360 | /* | 386 | /* |
@@ -449,8 +475,6 @@ struct rsnd_priv { | |||
449 | #define rsnd_priv_to_pdev(priv) ((priv)->pdev) | 475 | #define rsnd_priv_to_pdev(priv) ((priv)->pdev) |
450 | #define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev)) | 476 | #define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev)) |
451 | #define rsnd_priv_to_info(priv) ((priv)->info) | 477 | #define rsnd_priv_to_info(priv) ((priv)->info) |
452 | #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) | ||
453 | #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) | ||
454 | 478 | ||
455 | /* | 479 | /* |
456 | * rsnd_kctrl | 480 | * rsnd_kctrl |
@@ -460,7 +484,8 @@ struct rsnd_kctrl_cfg { | |||
460 | unsigned int size; | 484 | unsigned int size; |
461 | u32 *val; | 485 | u32 *val; |
462 | const char * const *texts; | 486 | const char * const *texts; |
463 | void (*update)(struct rsnd_mod *mod); | 487 | void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod); |
488 | struct rsnd_dai_stream *io; | ||
464 | struct snd_card *card; | 489 | struct snd_card *card; |
465 | struct snd_kcontrol *kctrl; | 490 | struct snd_kcontrol *kctrl; |
466 | }; | 491 | }; |
@@ -480,22 +505,28 @@ void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg); | |||
480 | #define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg)) | 505 | #define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg)) |
481 | 506 | ||
482 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | 507 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, |
508 | struct rsnd_dai_stream *io, | ||
483 | struct snd_soc_pcm_runtime *rtd, | 509 | struct snd_soc_pcm_runtime *rtd, |
484 | const unsigned char *name, | 510 | const unsigned char *name, |
485 | void (*update)(struct rsnd_mod *mod), | 511 | void (*update)(struct rsnd_dai_stream *io, |
512 | struct rsnd_mod *mod), | ||
486 | struct rsnd_kctrl_cfg_m *_cfg, | 513 | struct rsnd_kctrl_cfg_m *_cfg, |
487 | u32 max); | 514 | u32 max); |
488 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | 515 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, |
516 | struct rsnd_dai_stream *io, | ||
489 | struct snd_soc_pcm_runtime *rtd, | 517 | struct snd_soc_pcm_runtime *rtd, |
490 | const unsigned char *name, | 518 | const unsigned char *name, |
491 | void (*update)(struct rsnd_mod *mod), | 519 | void (*update)(struct rsnd_dai_stream *io, |
520 | struct rsnd_mod *mod), | ||
492 | struct rsnd_kctrl_cfg_s *_cfg, | 521 | struct rsnd_kctrl_cfg_s *_cfg, |
493 | u32 max); | 522 | u32 max); |
494 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | 523 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, |
524 | struct rsnd_dai_stream *io, | ||
495 | struct snd_soc_pcm_runtime *rtd, | 525 | struct snd_soc_pcm_runtime *rtd, |
496 | const unsigned char *name, | 526 | const unsigned char *name, |
497 | struct rsnd_kctrl_cfg_s *_cfg, | 527 | struct rsnd_kctrl_cfg_s *_cfg, |
498 | void (*update)(struct rsnd_mod *mod), | 528 | void (*update)(struct rsnd_dai_stream *io, |
529 | struct rsnd_mod *mod), | ||
499 | const char * const *texts, | 530 | const char * const *texts, |
500 | u32 max); | 531 | u32 max); |
501 | 532 | ||
@@ -512,8 +543,10 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | |||
512 | struct rsnd_dai_stream *io, | 543 | struct rsnd_dai_stream *io, |
513 | struct snd_pcm_runtime *runtime); | 544 | struct snd_pcm_runtime *runtime); |
514 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | 545 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
546 | struct rsnd_dai_stream *io, | ||
515 | int use_busif); | 547 | int use_busif); |
516 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod); | 548 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, |
549 | struct rsnd_dai_stream *io); | ||
517 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); | 550 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); |
518 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); | 551 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); |
519 | 552 | ||
@@ -530,7 +563,7 @@ void rsnd_ssi_remove(struct platform_device *pdev, | |||
530 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 563 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
531 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | 564 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); |
532 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | 565 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); |
533 | int rsnd_ssi_use_busif(struct rsnd_mod *mod); | 566 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod); |
534 | 567 | ||
535 | /* | 568 | /* |
536 | * R-Car DVC | 569 | * R-Car DVC |
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index a68517afe615..84e935711e29 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c | |||
@@ -45,61 +45,48 @@ static const struct of_device_id rsrc_card_of_match[] = { | |||
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(of, rsrc_card_of_match); | 46 | MODULE_DEVICE_TABLE(of, rsrc_card_of_match); |
47 | 47 | ||
48 | #define DAI_NAME_NUM 32 | ||
48 | struct rsrc_card_dai { | 49 | struct rsrc_card_dai { |
49 | const char *name; | ||
50 | unsigned int fmt; | 50 | unsigned int fmt; |
51 | unsigned int sysclk; | 51 | unsigned int sysclk; |
52 | struct clk *clk; | 52 | struct clk *clk; |
53 | char dai_name[DAI_NAME_NUM]; | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | #define RSRC_FB_NUM 2 /* FE/BE */ | ||
56 | #define IDX_CPU 0 | 56 | #define IDX_CPU 0 |
57 | #define IDX_CODEC 1 | 57 | #define IDX_CODEC 1 |
58 | struct rsrc_card_priv { | 58 | struct rsrc_card_priv { |
59 | struct snd_soc_card snd_card; | 59 | struct snd_soc_card snd_card; |
60 | struct rsrc_card_dai_props { | ||
61 | struct rsrc_card_dai cpu_dai; | ||
62 | struct rsrc_card_dai codec_dai; | ||
63 | } dai_props[RSRC_FB_NUM]; | ||
64 | struct snd_soc_codec_conf codec_conf; | 60 | struct snd_soc_codec_conf codec_conf; |
65 | struct snd_soc_dai_link dai_link[RSRC_FB_NUM]; | 61 | struct rsrc_card_dai *dai_props; |
62 | struct snd_soc_dai_link *dai_link; | ||
63 | int dai_num; | ||
66 | u32 convert_rate; | 64 | u32 convert_rate; |
67 | }; | 65 | }; |
68 | 66 | ||
69 | #define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) | 67 | #define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) |
70 | #define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) | 68 | #define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) |
71 | #define rsrc_priv_to_props(priv, i) ((priv)->dai_props + i) | 69 | #define rsrc_priv_to_props(priv, i) ((priv)->dai_props + (i)) |
72 | #define rsrc_dev_to_of_data(dev) (of_match_device(rsrc_card_of_match, (dev))->data) | 70 | #define rsrc_dev_to_of_data(dev) (of_match_device(rsrc_card_of_match, (dev))->data) |
73 | 71 | ||
74 | static int rsrc_card_startup(struct snd_pcm_substream *substream) | 72 | static int rsrc_card_startup(struct snd_pcm_substream *substream) |
75 | { | 73 | { |
76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 74 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
77 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 75 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); |
78 | struct rsrc_card_dai_props *dai_props = | 76 | struct rsrc_card_dai *dai_props = |
79 | &priv->dai_props[rtd - rtd->card->rtd]; | 77 | rsrc_priv_to_props(priv, rtd - rtd->card->rtd); |
80 | int ret; | ||
81 | |||
82 | ret = clk_prepare_enable(dai_props->cpu_dai.clk); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | 78 | ||
86 | ret = clk_prepare_enable(dai_props->codec_dai.clk); | 79 | return clk_prepare_enable(dai_props->clk); |
87 | if (ret) | ||
88 | clk_disable_unprepare(dai_props->cpu_dai.clk); | ||
89 | |||
90 | return ret; | ||
91 | } | 80 | } |
92 | 81 | ||
93 | static void rsrc_card_shutdown(struct snd_pcm_substream *substream) | 82 | static void rsrc_card_shutdown(struct snd_pcm_substream *substream) |
94 | { | 83 | { |
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
96 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 85 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); |
97 | struct rsrc_card_dai_props *dai_props = | 86 | struct rsrc_card_dai *dai_props = |
98 | &priv->dai_props[rtd - rtd->card->rtd]; | 87 | rsrc_priv_to_props(priv, rtd - rtd->card->rtd); |
99 | |||
100 | clk_disable_unprepare(dai_props->cpu_dai.clk); | ||
101 | 88 | ||
102 | clk_disable_unprepare(dai_props->codec_dai.clk); | 89 | clk_disable_unprepare(dai_props->clk); |
103 | } | 90 | } |
104 | 91 | ||
105 | static struct snd_soc_ops rsrc_card_ops = { | 92 | static struct snd_soc_ops rsrc_card_ops = { |
@@ -107,21 +94,31 @@ static struct snd_soc_ops rsrc_card_ops = { | |||
107 | .shutdown = rsrc_card_shutdown, | 94 | .shutdown = rsrc_card_shutdown, |
108 | }; | 95 | }; |
109 | 96 | ||
110 | static int __rsrc_card_dai_init(struct snd_soc_dai *dai, | 97 | static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) |
111 | struct rsrc_card_dai *set) | ||
112 | { | 98 | { |
99 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
100 | struct snd_soc_dai *dai; | ||
101 | struct snd_soc_dai_link *dai_link; | ||
102 | struct rsrc_card_dai *dai_props; | ||
103 | int num = rtd - rtd->card->rtd; | ||
113 | int ret; | 104 | int ret; |
114 | 105 | ||
115 | if (set->fmt) { | 106 | dai_link = rsrc_priv_to_link(priv, num); |
116 | ret = snd_soc_dai_set_fmt(dai, set->fmt); | 107 | dai_props = rsrc_priv_to_props(priv, num); |
108 | dai = dai_link->dynamic ? | ||
109 | rtd->cpu_dai : | ||
110 | rtd->codec_dai; | ||
111 | |||
112 | if (dai_props->fmt) { | ||
113 | ret = snd_soc_dai_set_fmt(dai, dai_props->fmt); | ||
117 | if (ret && ret != -ENOTSUPP) { | 114 | if (ret && ret != -ENOTSUPP) { |
118 | dev_err(dai->dev, "set_fmt error\n"); | 115 | dev_err(dai->dev, "set_fmt error\n"); |
119 | goto err; | 116 | goto err; |
120 | } | 117 | } |
121 | } | 118 | } |
122 | 119 | ||
123 | if (set->sysclk) { | 120 | if (dai_props->sysclk) { |
124 | ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); | 121 | ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0); |
125 | if (ret && ret != -ENOTSUPP) { | 122 | if (ret && ret != -ENOTSUPP) { |
126 | dev_err(dai->dev, "set_sysclk error\n"); | 123 | dev_err(dai->dev, "set_sysclk error\n"); |
127 | goto err; | 124 | goto err; |
@@ -134,27 +131,6 @@ err: | |||
134 | return ret; | 131 | return ret; |
135 | } | 132 | } |
136 | 133 | ||
137 | static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
138 | { | ||
139 | struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
140 | struct snd_soc_dai *codec = rtd->codec_dai; | ||
141 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
142 | struct rsrc_card_dai_props *dai_props; | ||
143 | int num, ret; | ||
144 | |||
145 | num = rtd - rtd->card->rtd; | ||
146 | dai_props = &priv->dai_props[num]; | ||
147 | ret = __rsrc_card_dai_init(codec, &dai_props->codec_dai); | ||
148 | if (ret < 0) | ||
149 | return ret; | ||
150 | |||
151 | ret = __rsrc_card_dai_init(cpu, &dai_props->cpu_dai); | ||
152 | if (ret < 0) | ||
153 | return ret; | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 134 | static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
159 | struct snd_pcm_hw_params *params) | 135 | struct snd_pcm_hw_params *params) |
160 | { | 136 | { |
@@ -170,40 +146,47 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
170 | return 0; | 146 | return 0; |
171 | } | 147 | } |
172 | 148 | ||
173 | static int | 149 | static int rsrc_card_parse_daifmt(struct device_node *node, |
174 | rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, | 150 | struct device_node *np, |
175 | struct device_node *np, | 151 | struct rsrc_card_priv *priv, |
176 | struct rsrc_card_dai *dai, | 152 | int idx, bool is_fe) |
177 | struct snd_soc_dai_link *dai_link, | ||
178 | int *args_count) | ||
179 | { | 153 | { |
180 | struct device *dev = rsrc_priv_to_dev(priv); | 154 | struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); |
181 | const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); | 155 | struct device_node *bitclkmaster = NULL; |
182 | struct of_phandle_args args; | 156 | struct device_node *framemaster = NULL; |
183 | struct device_node **p_node; | 157 | struct device_node *codec = is_fe ? NULL : np; |
184 | struct clk *clk; | 158 | unsigned int daifmt; |
185 | const char **dai_name; | ||
186 | const char **name; | ||
187 | u32 val; | ||
188 | int ret; | ||
189 | 159 | ||
190 | if (args_count) { | 160 | daifmt = snd_soc_of_parse_daifmt(node, NULL, |
191 | p_node = &dai_link->cpu_of_node; | 161 | &bitclkmaster, &framemaster); |
192 | dai_name = &dai_link->cpu_dai_name; | 162 | daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; |
193 | name = &dai_link->cpu_name; | ||
194 | } else { | ||
195 | p_node = &dai_link->codec_of_node; | ||
196 | dai_name = &dai_link->codec_dai_name; | ||
197 | name = &dai_link->codec_name; | ||
198 | } | ||
199 | 163 | ||
200 | if (!np) { | 164 | if (!bitclkmaster && !framemaster) |
201 | /* use snd-soc-dummy */ | 165 | return -EINVAL; |
202 | *p_node = NULL; | 166 | |
203 | *dai_name = "snd-soc-dummy-dai"; | 167 | if (codec == bitclkmaster) |
204 | *name = "snd-soc-dummy"; | 168 | daifmt |= (codec == framemaster) ? |
205 | return 0; | 169 | SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; |
206 | } | 170 | else |
171 | daifmt |= (codec == framemaster) ? | ||
172 | SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; | ||
173 | |||
174 | dai_props->fmt = daifmt; | ||
175 | |||
176 | of_node_put(bitclkmaster); | ||
177 | of_node_put(framemaster); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int rsrc_card_parse_links(struct device_node *np, | ||
183 | struct rsrc_card_priv *priv, | ||
184 | int idx, bool is_fe) | ||
185 | { | ||
186 | struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); | ||
187 | struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); | ||
188 | struct of_phandle_args args; | ||
189 | int ret; | ||
207 | 190 | ||
208 | /* | 191 | /* |
209 | * Get node via "sound-dai = <&phandle port>" | 192 | * Get node via "sound-dai = <&phandle port>" |
@@ -214,30 +197,82 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, | |||
214 | if (ret) | 197 | if (ret) |
215 | return ret; | 198 | return ret; |
216 | 199 | ||
217 | *p_node = args.np; | 200 | if (is_fe) { |
201 | /* BE is dummy */ | ||
202 | dai_link->codec_of_node = NULL; | ||
203 | dai_link->codec_dai_name = "snd-soc-dummy-dai"; | ||
204 | dai_link->codec_name = "snd-soc-dummy"; | ||
205 | |||
206 | /* FE settings */ | ||
207 | dai_link->dynamic = 1; | ||
208 | dai_link->dpcm_merged_format = 1; | ||
209 | dai_link->cpu_of_node = args.np; | ||
210 | snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name); | ||
211 | |||
212 | /* set dai_name */ | ||
213 | snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s", | ||
214 | dai_link->cpu_dai_name); | ||
215 | |||
216 | /* | ||
217 | * In soc_bind_dai_link() will check cpu name after | ||
218 | * of_node matching if dai_link has cpu_dai_name. | ||
219 | * but, it will never match if name was created by | ||
220 | * fmt_single_name() remove cpu_dai_name if cpu_args | ||
221 | * was 0. See: | ||
222 | * fmt_single_name() | ||
223 | * fmt_multiple_name() | ||
224 | */ | ||
225 | if (!args.args_count) | ||
226 | dai_link->cpu_dai_name = NULL; | ||
227 | } else { | ||
228 | struct device *dev = rsrc_priv_to_dev(priv); | ||
229 | const struct rsrc_card_of_data *of_data; | ||
218 | 230 | ||
219 | /* Get dai->name */ | 231 | of_data = rsrc_dev_to_of_data(dev); |
220 | ret = snd_soc_of_get_dai_name(np, dai_name); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | 232 | ||
224 | /* | 233 | /* FE is dummy */ |
225 | * FIXME | 234 | dai_link->cpu_of_node = NULL; |
226 | * | 235 | dai_link->cpu_dai_name = "snd-soc-dummy-dai"; |
227 | * rsrc assumes DPCM playback/capture | 236 | dai_link->cpu_name = "snd-soc-dummy"; |
228 | */ | ||
229 | dai_link->dpcm_playback = 1; | ||
230 | dai_link->dpcm_capture = 1; | ||
231 | 237 | ||
232 | if (args_count) { | 238 | /* BE settings */ |
233 | *args_count = args.args_count; | 239 | dai_link->no_pcm = 1; |
234 | dai_link->dynamic = 1; | 240 | dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; |
235 | } else { | 241 | dai_link->codec_of_node = args.np; |
236 | dai_link->no_pcm = 1; | 242 | snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); |
237 | priv->codec_conf.of_node = (*p_node); | 243 | |
238 | priv->codec_conf.name_prefix = of_data->prefix; | 244 | /* additional name prefix */ |
245 | priv->codec_conf.of_node = dai_link->codec_of_node; | ||
246 | priv->codec_conf.name_prefix = of_data->prefix; | ||
247 | |||
248 | /* set dai_name */ | ||
249 | snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s", | ||
250 | dai_link->codec_dai_name); | ||
239 | } | 251 | } |
240 | 252 | ||
253 | /* Simple Card assumes platform == cpu */ | ||
254 | dai_link->platform_of_node = dai_link->cpu_of_node; | ||
255 | dai_link->dpcm_playback = 1; | ||
256 | dai_link->dpcm_capture = 1; | ||
257 | dai_link->name = dai_props->dai_name; | ||
258 | dai_link->stream_name = dai_props->dai_name; | ||
259 | dai_link->ops = &rsrc_card_ops; | ||
260 | dai_link->init = rsrc_card_dai_init; | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int rsrc_card_parse_clk(struct device_node *np, | ||
266 | struct rsrc_card_priv *priv, | ||
267 | int idx, bool is_fe) | ||
268 | { | ||
269 | struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); | ||
270 | struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); | ||
271 | struct clk *clk; | ||
272 | struct device_node *of_np = is_fe ? dai_link->cpu_of_node : | ||
273 | dai_link->codec_of_node; | ||
274 | u32 val; | ||
275 | |||
241 | /* | 276 | /* |
242 | * Parse dai->sysclk come from "clocks = <&xxx>" | 277 | * Parse dai->sysclk come from "clocks = <&xxx>" |
243 | * (if system has common clock) | 278 | * (if system has common clock) |
@@ -246,173 +281,92 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, | |||
246 | */ | 281 | */ |
247 | if (of_property_read_bool(np, "clocks")) { | 282 | if (of_property_read_bool(np, "clocks")) { |
248 | clk = of_clk_get(np, 0); | 283 | clk = of_clk_get(np, 0); |
249 | if (IS_ERR(clk)) { | 284 | if (IS_ERR(clk)) |
250 | ret = PTR_ERR(clk); | 285 | return PTR_ERR(clk); |
251 | return ret; | ||
252 | } | ||
253 | 286 | ||
254 | dai->sysclk = clk_get_rate(clk); | 287 | dai_props->sysclk = clk_get_rate(clk); |
255 | dai->clk = clk; | 288 | dai_props->clk = clk; |
256 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { | 289 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
257 | dai->sysclk = val; | 290 | dai_props->sysclk = val; |
258 | } else { | 291 | } else { |
259 | clk = of_clk_get(args.np, 0); | 292 | clk = of_clk_get(of_np, 0); |
260 | if (!IS_ERR(clk)) | 293 | if (!IS_ERR(clk)) |
261 | dai->sysclk = clk_get_rate(clk); | 294 | dai_props->sysclk = clk_get_rate(clk); |
262 | } | 295 | } |
263 | 296 | ||
264 | return 0; | 297 | return 0; |
265 | } | 298 | } |
266 | 299 | ||
267 | static int rsrc_card_parse_daifmt(struct device_node *node, | ||
268 | struct rsrc_card_priv *priv, | ||
269 | struct device_node *codec, | ||
270 | int idx) | ||
271 | { | ||
272 | struct device_node *bitclkmaster = NULL; | ||
273 | struct device_node *framemaster = NULL; | ||
274 | struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); | ||
275 | struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai; | ||
276 | struct rsrc_card_dai *codec_dai = &dai_props->codec_dai; | ||
277 | unsigned int daifmt; | ||
278 | |||
279 | daifmt = snd_soc_of_parse_daifmt(node, NULL, | ||
280 | &bitclkmaster, &framemaster); | ||
281 | daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; | ||
282 | |||
283 | if (!bitclkmaster && !framemaster) | ||
284 | return -EINVAL; | ||
285 | |||
286 | if (codec == bitclkmaster) | ||
287 | daifmt |= (codec == framemaster) ? | ||
288 | SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; | ||
289 | else | ||
290 | daifmt |= (codec == framemaster) ? | ||
291 | SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; | ||
292 | |||
293 | cpu_dai->fmt = daifmt; | ||
294 | codec_dai->fmt = daifmt; | ||
295 | |||
296 | of_node_put(bitclkmaster); | ||
297 | of_node_put(framemaster); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int rsrc_card_dai_link_of(struct device_node *node, | 300 | static int rsrc_card_dai_link_of(struct device_node *node, |
301 | struct device_node *np, | ||
303 | struct rsrc_card_priv *priv, | 302 | struct rsrc_card_priv *priv, |
304 | int idx) | 303 | int idx) |
305 | { | 304 | { |
306 | struct device *dev = rsrc_priv_to_dev(priv); | 305 | struct device *dev = rsrc_priv_to_dev(priv); |
307 | struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); | 306 | struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); |
308 | struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); | 307 | bool is_fe = false; |
309 | struct device_node *cpu = NULL; | 308 | int ret; |
310 | struct device_node *codec = NULL; | ||
311 | char *name; | ||
312 | char prop[128]; | ||
313 | int ret, cpu_args; | ||
314 | |||
315 | cpu = of_get_child_by_name(node, "cpu"); | ||
316 | codec = of_get_child_by_name(node, "codec"); | ||
317 | |||
318 | if (!cpu || !codec) { | ||
319 | ret = -EINVAL; | ||
320 | dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); | ||
321 | goto dai_link_of_err; | ||
322 | } | ||
323 | 309 | ||
324 | ret = rsrc_card_parse_daifmt(node, priv, codec, idx); | 310 | if (0 == strcmp(np->name, "cpu")) |
325 | if (ret < 0) | 311 | is_fe = true; |
326 | goto dai_link_of_err; | ||
327 | 312 | ||
328 | ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CPU) ? cpu : NULL, | 313 | ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe); |
329 | &dai_props->cpu_dai, | ||
330 | dai_link, | ||
331 | &cpu_args); | ||
332 | if (ret < 0) | 314 | if (ret < 0) |
333 | goto dai_link_of_err; | 315 | return ret; |
334 | 316 | ||
335 | ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CODEC) ? codec : NULL, | 317 | ret = rsrc_card_parse_links(np, priv, idx, is_fe); |
336 | &dai_props->codec_dai, | ||
337 | dai_link, | ||
338 | NULL); | ||
339 | if (ret < 0) | 318 | if (ret < 0) |
340 | goto dai_link_of_err; | 319 | return ret; |
341 | |||
342 | if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { | ||
343 | ret = -EINVAL; | ||
344 | goto dai_link_of_err; | ||
345 | } | ||
346 | |||
347 | /* Simple Card assumes platform == cpu */ | ||
348 | dai_link->platform_of_node = dai_link->cpu_of_node; | ||
349 | |||
350 | /* DAI link name is created from CPU/CODEC dai name */ | ||
351 | name = devm_kzalloc(dev, | ||
352 | strlen(dai_link->cpu_dai_name) + | ||
353 | strlen(dai_link->codec_dai_name) + 2, | ||
354 | GFP_KERNEL); | ||
355 | if (!name) { | ||
356 | ret = -ENOMEM; | ||
357 | goto dai_link_of_err; | ||
358 | } | ||
359 | |||
360 | sprintf(name, "%s-%s", dai_link->cpu_dai_name, | ||
361 | dai_link->codec_dai_name); | ||
362 | dai_link->name = dai_link->stream_name = name; | ||
363 | dai_link->ops = &rsrc_card_ops; | ||
364 | dai_link->init = rsrc_card_dai_init; | ||
365 | |||
366 | if (idx == IDX_CODEC) | ||
367 | dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; | ||
368 | |||
369 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); | ||
370 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", | ||
371 | dai_link->cpu_dai_name, | ||
372 | dai_props->cpu_dai.fmt, | ||
373 | dai_props->cpu_dai.sysclk); | ||
374 | dev_dbg(dev, "\tcodec : %s / %04x / %d\n", | ||
375 | dai_link->codec_dai_name, | ||
376 | dai_props->codec_dai.fmt, | ||
377 | dai_props->codec_dai.sysclk); | ||
378 | 320 | ||
379 | /* | 321 | ret = rsrc_card_parse_clk(np, priv, idx, is_fe); |
380 | * In soc_bind_dai_link() will check cpu name after | 322 | if (ret < 0) |
381 | * of_node matching if dai_link has cpu_dai_name. | 323 | return ret; |
382 | * but, it will never match if name was created by | ||
383 | * fmt_single_name() remove cpu_dai_name if cpu_args | ||
384 | * was 0. See: | ||
385 | * fmt_single_name() | ||
386 | * fmt_multiple_name() | ||
387 | */ | ||
388 | if (!cpu_args) | ||
389 | dai_link->cpu_dai_name = NULL; | ||
390 | 324 | ||
391 | dai_link_of_err: | 325 | dev_dbg(dev, "\t%s / %04x / %d\n", |
392 | of_node_put(cpu); | 326 | dai_props->dai_name, |
393 | of_node_put(codec); | 327 | dai_props->fmt, |
328 | dai_props->sysclk); | ||
394 | 329 | ||
395 | return ret; | 330 | return ret; |
396 | } | 331 | } |
397 | 332 | ||
398 | static int rsrc_card_parse_of(struct device_node *node, | 333 | static int rsrc_card_parse_of(struct device_node *node, |
399 | struct rsrc_card_priv *priv) | 334 | struct rsrc_card_priv *priv, |
335 | struct device *dev) | ||
400 | { | 336 | { |
401 | struct device *dev = rsrc_priv_to_dev(priv); | ||
402 | const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); | 337 | const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); |
338 | struct rsrc_card_dai *props; | ||
339 | struct snd_soc_dai_link *links; | ||
340 | struct device_node *np; | ||
403 | int ret; | 341 | int ret; |
404 | int i; | 342 | int i, num; |
405 | 343 | ||
406 | if (!node) | 344 | if (!node) |
407 | return -EINVAL; | 345 | return -EINVAL; |
408 | 346 | ||
409 | /* Parse the card name from DT */ | 347 | num = of_get_child_count(node); |
410 | snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); | 348 | props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); |
349 | links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); | ||
350 | if (!props || !links) | ||
351 | return -ENOMEM; | ||
352 | |||
353 | priv->dai_props = props; | ||
354 | priv->dai_link = links; | ||
355 | priv->dai_num = num; | ||
411 | 356 | ||
412 | /* DAPM routes */ | 357 | /* Init snd_soc_card */ |
358 | priv->snd_card.owner = THIS_MODULE; | ||
359 | priv->snd_card.dev = dev; | ||
360 | priv->snd_card.dai_link = priv->dai_link; | ||
361 | priv->snd_card.num_links = num; | ||
362 | priv->snd_card.codec_conf = &priv->codec_conf; | ||
363 | priv->snd_card.num_configs = 1; | ||
413 | priv->snd_card.of_dapm_routes = of_data->routes; | 364 | priv->snd_card.of_dapm_routes = of_data->routes; |
414 | priv->snd_card.num_of_dapm_routes = of_data->num_routes; | 365 | priv->snd_card.num_of_dapm_routes = of_data->num_routes; |
415 | 366 | ||
367 | /* Parse the card name from DT */ | ||
368 | snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); | ||
369 | |||
416 | /* sampling rate convert */ | 370 | /* sampling rate convert */ |
417 | of_property_read_u32(node, "convert-rate", &priv->convert_rate); | 371 | of_property_read_u32(node, "convert-rate", &priv->convert_rate); |
418 | 372 | ||
@@ -420,11 +374,12 @@ static int rsrc_card_parse_of(struct device_node *node, | |||
420 | priv->snd_card.name ? priv->snd_card.name : "", | 374 | priv->snd_card.name ? priv->snd_card.name : "", |
421 | priv->convert_rate); | 375 | priv->convert_rate); |
422 | 376 | ||
423 | /* FE/BE */ | 377 | i = 0; |
424 | for (i = 0; i < RSRC_FB_NUM; i++) { | 378 | for_each_child_of_node(node, np) { |
425 | ret = rsrc_card_dai_link_of(node, priv, i); | 379 | ret = rsrc_card_dai_link_of(node, np, priv, i); |
426 | if (ret < 0) | 380 | if (ret < 0) |
427 | return ret; | 381 | return ret; |
382 | i++; | ||
428 | } | 383 | } |
429 | 384 | ||
430 | if (!priv->snd_card.name) | 385 | if (!priv->snd_card.name) |
@@ -451,7 +406,6 @@ static int rsrc_card_unref(struct snd_soc_card *card) | |||
451 | static int rsrc_card_probe(struct platform_device *pdev) | 406 | static int rsrc_card_probe(struct platform_device *pdev) |
452 | { | 407 | { |
453 | struct rsrc_card_priv *priv; | 408 | struct rsrc_card_priv *priv; |
454 | struct snd_soc_dai_link *dai_link; | ||
455 | struct device_node *np = pdev->dev.of_node; | 409 | struct device_node *np = pdev->dev.of_node; |
456 | struct device *dev = &pdev->dev; | 410 | struct device *dev = &pdev->dev; |
457 | int ret; | 411 | int ret; |
@@ -461,16 +415,7 @@ static int rsrc_card_probe(struct platform_device *pdev) | |||
461 | if (!priv) | 415 | if (!priv) |
462 | return -ENOMEM; | 416 | return -ENOMEM; |
463 | 417 | ||
464 | /* Init snd_soc_card */ | 418 | ret = rsrc_card_parse_of(np, priv, dev); |
465 | priv->snd_card.owner = THIS_MODULE; | ||
466 | priv->snd_card.dev = dev; | ||
467 | dai_link = priv->dai_link; | ||
468 | priv->snd_card.dai_link = dai_link; | ||
469 | priv->snd_card.num_links = RSRC_FB_NUM; | ||
470 | priv->snd_card.codec_conf = &priv->codec_conf; | ||
471 | priv->snd_card.num_configs = 1; | ||
472 | |||
473 | ret = rsrc_card_parse_of(np, priv); | ||
474 | if (ret < 0) { | 419 | if (ret < 0) { |
475 | if (ret != -EPROBE_DEFER) | 420 | if (ret != -EPROBE_DEFER) |
476 | dev_err(dev, "parse error %d\n", ret); | 421 | dev_err(dev, "parse error %d\n", ret); |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 3beb32eb412a..c61c17180142 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -117,10 +117,10 @@ struct rsnd_src { | |||
117 | /* | 117 | /* |
118 | * Gen1/Gen2 common functions | 118 | * Gen1/Gen2 common functions |
119 | */ | 119 | */ |
120 | static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) | 120 | static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, |
121 | struct rsnd_mod *mod) | ||
121 | { | 122 | { |
122 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 123 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
123 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
124 | int is_play = rsnd_io_is_play(io); | 124 | int is_play = rsnd_io_is_play(io); |
125 | 125 | ||
126 | return rsnd_dma_request_channel(rsnd_src_of_node(priv), | 126 | return rsnd_dma_request_channel(rsnd_src_of_node(priv), |
@@ -129,9 +129,9 @@ static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | 131 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
132 | struct rsnd_dai_stream *io, | ||
132 | int use_busif) | 133 | int use_busif) |
133 | { | 134 | { |
134 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); | ||
135 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 135 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
136 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 136 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
137 | int ssi_id = rsnd_mod_id(ssi_mod); | 137 | int ssi_id = rsnd_mod_id(ssi_mod); |
@@ -174,7 +174,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
174 | u32 mask = ~0; | 174 | u32 mask = ~0; |
175 | 175 | ||
176 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, | 176 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, |
177 | rsnd_get_adinr(ssi_mod)); | 177 | rsnd_get_adinr(ssi_mod, io)); |
178 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); | 178 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); |
179 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); | 179 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); |
180 | 180 | ||
@@ -196,7 +196,8 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | 198 | ||
199 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod) | 199 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, |
200 | struct rsnd_dai_stream *io) | ||
200 | { | 201 | { |
201 | /* | 202 | /* |
202 | * DMA settings for SSIU | 203 | * DMA settings for SSIU |
@@ -235,10 +236,9 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) | |||
235 | return 0; | 236 | return 0; |
236 | } | 237 | } |
237 | 238 | ||
238 | static u32 rsnd_src_convert_rate(struct rsnd_src *src) | 239 | static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, |
240 | struct rsnd_src *src) | ||
239 | { | 241 | { |
240 | struct rsnd_mod *mod = &src->mod; | ||
241 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
242 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 242 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
243 | u32 convert_rate; | 243 | u32 convert_rate; |
244 | 244 | ||
@@ -274,7 +274,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | |||
274 | * return convert rate if SRC is used, | 274 | * return convert rate if SRC is used, |
275 | * otherwise, return runtime->rate as usual | 275 | * otherwise, return runtime->rate as usual |
276 | */ | 276 | */ |
277 | rate = rsnd_src_convert_rate(src); | 277 | rate = rsnd_src_convert_rate(io, src); |
278 | } | 278 | } |
279 | 279 | ||
280 | if (!rate) | 280 | if (!rate) |
@@ -283,12 +283,12 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | |||
283 | return rate; | 283 | return rate; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) | 286 | static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, |
287 | struct rsnd_dai_stream *io) | ||
287 | { | 288 | { |
288 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
289 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 289 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
290 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 290 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
291 | u32 convert_rate = rsnd_src_convert_rate(src); | 291 | u32 convert_rate = rsnd_src_convert_rate(io, src); |
292 | u32 fsrate = 0; | 292 | u32 fsrate = 0; |
293 | 293 | ||
294 | if (convert_rate) | 294 | if (convert_rate) |
@@ -299,7 +299,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) | |||
299 | rsnd_mod_write(mod, SRC_SWRSR, 1); | 299 | rsnd_mod_write(mod, SRC_SWRSR, 1); |
300 | 300 | ||
301 | /* Set channel number and output bit length */ | 301 | /* Set channel number and output bit length */ |
302 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); | 302 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io)); |
303 | 303 | ||
304 | /* Enable the initial value of IFS */ | 304 | /* Enable the initial value of IFS */ |
305 | if (fsrate) { | 305 | if (fsrate) { |
@@ -316,6 +316,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | static int rsnd_src_hw_params(struct rsnd_mod *mod, | 318 | static int rsnd_src_hw_params(struct rsnd_mod *mod, |
319 | struct rsnd_dai_stream *io, | ||
319 | struct snd_pcm_substream *substream, | 320 | struct snd_pcm_substream *substream, |
320 | struct snd_pcm_hw_params *fe_params) | 321 | struct snd_pcm_hw_params *fe_params) |
321 | { | 322 | { |
@@ -372,6 +373,7 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
372 | } | 373 | } |
373 | 374 | ||
374 | static int rsnd_src_quit(struct rsnd_mod *mod, | 375 | static int rsnd_src_quit(struct rsnd_mod *mod, |
376 | struct rsnd_dai_stream *io, | ||
375 | struct rsnd_priv *priv) | 377 | struct rsnd_priv *priv) |
376 | { | 378 | { |
377 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 379 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
@@ -411,9 +413,9 @@ static int rsnd_src_stop(struct rsnd_mod *mod) | |||
411 | /* | 413 | /* |
412 | * Gen1 functions | 414 | * Gen1 functions |
413 | */ | 415 | */ |
414 | static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) | 416 | static int rsnd_src_set_route_gen1(struct rsnd_dai_stream *io, |
417 | struct rsnd_mod *mod) | ||
415 | { | 418 | { |
416 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
417 | struct src_route_config { | 419 | struct src_route_config { |
418 | u32 mask; | 420 | u32 mask; |
419 | int shift; | 421 | int shift; |
@@ -448,13 +450,13 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) | |||
448 | return 0; | 450 | return 0; |
449 | } | 451 | } |
450 | 452 | ||
451 | static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) | 453 | static int rsnd_src_set_convert_timing_gen1(struct rsnd_dai_stream *io, |
454 | struct rsnd_mod *mod) | ||
452 | { | 455 | { |
453 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
454 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 456 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
455 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 457 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
456 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 458 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
457 | u32 convert_rate = rsnd_src_convert_rate(src); | 459 | u32 convert_rate = rsnd_src_convert_rate(io, src); |
458 | u32 mask; | 460 | u32 mask; |
459 | u32 val; | 461 | u32 val; |
460 | int shift; | 462 | int shift; |
@@ -506,12 +508,13 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) | |||
506 | return 0; | 508 | return 0; |
507 | } | 509 | } |
508 | 510 | ||
509 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) | 511 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, |
512 | struct rsnd_dai_stream *io) | ||
510 | { | 513 | { |
511 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 514 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
512 | int ret; | 515 | int ret; |
513 | 516 | ||
514 | ret = rsnd_src_set_convert_rate(mod); | 517 | ret = rsnd_src_set_convert_rate(mod, io); |
515 | if (ret < 0) | 518 | if (ret < 0) |
516 | return ret; | 519 | return ret; |
517 | 520 | ||
@@ -523,7 +526,7 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) | |||
523 | rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); | 526 | rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); |
524 | 527 | ||
525 | /* Gen1/Gen2 are not compatible */ | 528 | /* Gen1/Gen2 are not compatible */ |
526 | if (rsnd_src_convert_rate(src)) | 529 | if (rsnd_src_convert_rate(io, src)) |
527 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | 530 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); |
528 | 531 | ||
529 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ | 532 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ |
@@ -532,6 +535,7 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) | |||
532 | } | 535 | } |
533 | 536 | ||
534 | static int rsnd_src_init_gen1(struct rsnd_mod *mod, | 537 | static int rsnd_src_init_gen1(struct rsnd_mod *mod, |
538 | struct rsnd_dai_stream *io, | ||
535 | struct rsnd_priv *priv) | 539 | struct rsnd_priv *priv) |
536 | { | 540 | { |
537 | int ret; | 541 | int ret; |
@@ -540,15 +544,15 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, | |||
540 | if (ret < 0) | 544 | if (ret < 0) |
541 | return ret; | 545 | return ret; |
542 | 546 | ||
543 | ret = rsnd_src_set_route_gen1(mod); | 547 | ret = rsnd_src_set_route_gen1(io, mod); |
544 | if (ret < 0) | 548 | if (ret < 0) |
545 | return ret; | 549 | return ret; |
546 | 550 | ||
547 | ret = rsnd_src_set_convert_rate_gen1(mod); | 551 | ret = rsnd_src_set_convert_rate_gen1(mod, io); |
548 | if (ret < 0) | 552 | if (ret < 0) |
549 | return ret; | 553 | return ret; |
550 | 554 | ||
551 | ret = rsnd_src_set_convert_timing_gen1(mod); | 555 | ret = rsnd_src_set_convert_timing_gen1(io, mod); |
552 | if (ret < 0) | 556 | if (ret < 0) |
553 | return ret; | 557 | return ret; |
554 | 558 | ||
@@ -556,6 +560,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, | |||
556 | } | 560 | } |
557 | 561 | ||
558 | static int rsnd_src_start_gen1(struct rsnd_mod *mod, | 562 | static int rsnd_src_start_gen1(struct rsnd_mod *mod, |
563 | struct rsnd_dai_stream *io, | ||
559 | struct rsnd_priv *priv) | 564 | struct rsnd_priv *priv) |
560 | { | 565 | { |
561 | int id = rsnd_mod_id(mod); | 566 | int id = rsnd_mod_id(mod); |
@@ -566,6 +571,7 @@ static int rsnd_src_start_gen1(struct rsnd_mod *mod, | |||
566 | } | 571 | } |
567 | 572 | ||
568 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, | 573 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, |
574 | struct rsnd_dai_stream *io, | ||
569 | struct rsnd_priv *priv) | 575 | struct rsnd_priv *priv) |
570 | { | 576 | { |
571 | int id = rsnd_mod_id(mod); | 577 | int id = rsnd_mod_id(mod); |
@@ -643,9 +649,9 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) | |||
643 | return ret; | 649 | return ret; |
644 | } | 650 | } |
645 | 651 | ||
646 | static int _rsnd_src_start_gen2(struct rsnd_mod *mod) | 652 | static int _rsnd_src_start_gen2(struct rsnd_mod *mod, |
653 | struct rsnd_dai_stream *io) | ||
647 | { | 654 | { |
648 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
649 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; | 655 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; |
650 | 656 | ||
651 | rsnd_mod_write(mod, SRC_CTRL, val); | 657 | rsnd_mod_write(mod, SRC_CTRL, val); |
@@ -670,13 +676,16 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) | |||
670 | return rsnd_src_stop(mod); | 676 | return rsnd_src_stop(mod); |
671 | } | 677 | } |
672 | 678 | ||
673 | static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) | 679 | static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, |
680 | struct rsnd_dai_stream *io) | ||
674 | { | 681 | { |
675 | struct rsnd_mod *mod = data; | 682 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
676 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
677 | 683 | ||
678 | if (!io) | 684 | spin_lock(&priv->lock); |
679 | return IRQ_NONE; | 685 | |
686 | /* ignore all cases if not working */ | ||
687 | if (!rsnd_io_is_working(io)) | ||
688 | goto rsnd_src_interrupt_gen2_out; | ||
680 | 689 | ||
681 | if (rsnd_src_error_record_gen2(mod)) { | 690 | if (rsnd_src_error_record_gen2(mod)) { |
682 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 691 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
@@ -688,22 +697,32 @@ static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) | |||
688 | 697 | ||
689 | _rsnd_src_stop_gen2(mod); | 698 | _rsnd_src_stop_gen2(mod); |
690 | if (src->err < 1024) | 699 | if (src->err < 1024) |
691 | _rsnd_src_start_gen2(mod); | 700 | _rsnd_src_start_gen2(mod, io); |
692 | else | 701 | else |
693 | dev_warn(dev, "no more SRC restart\n"); | 702 | dev_warn(dev, "no more SRC restart\n"); |
694 | } | 703 | } |
695 | 704 | ||
705 | rsnd_src_interrupt_gen2_out: | ||
706 | spin_unlock(&priv->lock); | ||
707 | } | ||
708 | |||
709 | static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) | ||
710 | { | ||
711 | struct rsnd_mod *mod = data; | ||
712 | |||
713 | rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2); | ||
714 | |||
696 | return IRQ_HANDLED; | 715 | return IRQ_HANDLED; |
697 | } | 716 | } |
698 | 717 | ||
699 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) | 718 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, |
719 | struct rsnd_dai_stream *io) | ||
700 | { | 720 | { |
701 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 721 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
702 | struct device *dev = rsnd_priv_to_dev(priv); | 722 | struct device *dev = rsnd_priv_to_dev(priv); |
703 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
704 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 723 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
705 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 724 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
706 | u32 convert_rate = rsnd_src_convert_rate(src); | 725 | u32 convert_rate = rsnd_src_convert_rate(io, src); |
707 | u32 cr, route; | 726 | u32 cr, route; |
708 | uint ratio; | 727 | uint ratio; |
709 | int ret; | 728 | int ret; |
@@ -721,7 +740,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) | |||
721 | return -EINVAL; | 740 | return -EINVAL; |
722 | } | 741 | } |
723 | 742 | ||
724 | ret = rsnd_src_set_convert_rate(mod); | 743 | ret = rsnd_src_set_convert_rate(mod, io); |
725 | if (ret < 0) | 744 | if (ret < 0) |
726 | return ret; | 745 | return ret; |
727 | 746 | ||
@@ -757,12 +776,12 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) | |||
757 | return 0; | 776 | return 0; |
758 | } | 777 | } |
759 | 778 | ||
760 | static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) | 779 | static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io, |
780 | struct rsnd_mod *mod) | ||
761 | { | 781 | { |
762 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
763 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 782 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
764 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 783 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
765 | u32 convert_rate = rsnd_src_convert_rate(src); | 784 | u32 convert_rate = rsnd_src_convert_rate(io, src); |
766 | int ret; | 785 | int ret; |
767 | 786 | ||
768 | if (convert_rate) | 787 | if (convert_rate) |
@@ -776,6 +795,7 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) | |||
776 | } | 795 | } |
777 | 796 | ||
778 | static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | 797 | static int rsnd_src_probe_gen2(struct rsnd_mod *mod, |
798 | struct rsnd_dai_stream *io, | ||
779 | struct rsnd_priv *priv) | 799 | struct rsnd_priv *priv) |
780 | { | 800 | { |
781 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 801 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
@@ -797,7 +817,7 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | |||
797 | return ret; | 817 | return ret; |
798 | } | 818 | } |
799 | 819 | ||
800 | ret = rsnd_dma_init(priv, | 820 | ret = rsnd_dma_init(io, |
801 | rsnd_mod_to_dma(mod), | 821 | rsnd_mod_to_dma(mod), |
802 | src->info->dma_id); | 822 | src->info->dma_id); |
803 | 823 | ||
@@ -805,14 +825,16 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | |||
805 | } | 825 | } |
806 | 826 | ||
807 | static int rsnd_src_remove_gen2(struct rsnd_mod *mod, | 827 | static int rsnd_src_remove_gen2(struct rsnd_mod *mod, |
828 | struct rsnd_dai_stream *io, | ||
808 | struct rsnd_priv *priv) | 829 | struct rsnd_priv *priv) |
809 | { | 830 | { |
810 | rsnd_dma_quit(rsnd_mod_to_dma(mod)); | 831 | rsnd_dma_quit(io, rsnd_mod_to_dma(mod)); |
811 | 832 | ||
812 | return 0; | 833 | return 0; |
813 | } | 834 | } |
814 | 835 | ||
815 | static int rsnd_src_init_gen2(struct rsnd_mod *mod, | 836 | static int rsnd_src_init_gen2(struct rsnd_mod *mod, |
837 | struct rsnd_dai_stream *io, | ||
816 | struct rsnd_priv *priv) | 838 | struct rsnd_priv *priv) |
817 | { | 839 | { |
818 | int ret; | 840 | int ret; |
@@ -821,11 +843,11 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, | |||
821 | if (ret < 0) | 843 | if (ret < 0) |
822 | return ret; | 844 | return ret; |
823 | 845 | ||
824 | ret = rsnd_src_set_convert_rate_gen2(mod); | 846 | ret = rsnd_src_set_convert_rate_gen2(mod, io); |
825 | if (ret < 0) | 847 | if (ret < 0) |
826 | return ret; | 848 | return ret; |
827 | 849 | ||
828 | ret = rsnd_src_set_convert_timing_gen2(mod); | 850 | ret = rsnd_src_set_convert_timing_gen2(io, mod); |
829 | if (ret < 0) | 851 | if (ret < 0) |
830 | return ret; | 852 | return ret; |
831 | 853 | ||
@@ -833,31 +855,33 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, | |||
833 | } | 855 | } |
834 | 856 | ||
835 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, | 857 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, |
858 | struct rsnd_dai_stream *io, | ||
836 | struct rsnd_priv *priv) | 859 | struct rsnd_priv *priv) |
837 | { | 860 | { |
838 | rsnd_dma_start(rsnd_mod_to_dma(mod)); | 861 | rsnd_dma_start(io, rsnd_mod_to_dma(mod)); |
839 | 862 | ||
840 | return _rsnd_src_start_gen2(mod); | 863 | return _rsnd_src_start_gen2(mod, io); |
841 | } | 864 | } |
842 | 865 | ||
843 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | 866 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, |
867 | struct rsnd_dai_stream *io, | ||
844 | struct rsnd_priv *priv) | 868 | struct rsnd_priv *priv) |
845 | { | 869 | { |
846 | int ret; | 870 | int ret; |
847 | 871 | ||
848 | ret = _rsnd_src_stop_gen2(mod); | 872 | ret = _rsnd_src_stop_gen2(mod); |
849 | 873 | ||
850 | rsnd_dma_stop(rsnd_mod_to_dma(mod)); | 874 | rsnd_dma_stop(io, rsnd_mod_to_dma(mod)); |
851 | 875 | ||
852 | return ret; | 876 | return ret; |
853 | } | 877 | } |
854 | 878 | ||
855 | static void rsnd_src_reconvert_update(struct rsnd_mod *mod) | 879 | static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, |
880 | struct rsnd_mod *mod) | ||
856 | { | 881 | { |
857 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
858 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 882 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
859 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 883 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
860 | u32 convert_rate = rsnd_src_convert_rate(src); | 884 | u32 convert_rate = rsnd_src_convert_rate(io, src); |
861 | u32 fsrate; | 885 | u32 fsrate; |
862 | 886 | ||
863 | if (!runtime) | 887 | if (!runtime) |
@@ -873,10 +897,10 @@ static void rsnd_src_reconvert_update(struct rsnd_mod *mod) | |||
873 | } | 897 | } |
874 | 898 | ||
875 | static int rsnd_src_pcm_new(struct rsnd_mod *mod, | 899 | static int rsnd_src_pcm_new(struct rsnd_mod *mod, |
900 | struct rsnd_dai_stream *io, | ||
876 | struct snd_soc_pcm_runtime *rtd) | 901 | struct snd_soc_pcm_runtime *rtd) |
877 | { | 902 | { |
878 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 903 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
879 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
880 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 904 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
881 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 905 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
882 | int ret; | 906 | int ret; |
@@ -907,7 +931,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, | |||
907 | /* | 931 | /* |
908 | * enable sync convert | 932 | * enable sync convert |
909 | */ | 933 | */ |
910 | ret = rsnd_kctrl_new_s(mod, rtd, | 934 | ret = rsnd_kctrl_new_s(mod, io, rtd, |
911 | rsnd_io_is_play(io) ? | 935 | rsnd_io_is_play(io) ? |
912 | "SRC Out Rate Switch" : | 936 | "SRC Out Rate Switch" : |
913 | "SRC In Rate Switch", | 937 | "SRC In Rate Switch", |
@@ -916,7 +940,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, | |||
916 | if (ret < 0) | 940 | if (ret < 0) |
917 | return ret; | 941 | return ret; |
918 | 942 | ||
919 | ret = rsnd_kctrl_new_s(mod, rtd, | 943 | ret = rsnd_kctrl_new_s(mod, io, rtd, |
920 | rsnd_io_is_play(io) ? | 944 | rsnd_io_is_play(io) ? |
921 | "SRC Out Rate" : | 945 | "SRC Out Rate" : |
922 | "SRC In Rate", | 946 | "SRC In Rate", |
@@ -1041,7 +1065,7 @@ int rsnd_src_probe(struct platform_device *pdev, | |||
1041 | 1065 | ||
1042 | src->info = &info->src_info[i]; | 1066 | src->info = &info->src_info[i]; |
1043 | 1067 | ||
1044 | ret = rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i); | 1068 | ret = rsnd_mod_init(priv, &src->mod, ops, clk, RSND_MOD_SRC, i); |
1045 | if (ret) | 1069 | if (ret) |
1046 | return ret; | 1070 | return ret; |
1047 | } | 1071 | } |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 7bb9c087f3dc..2fbe59f7f9b5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -66,6 +66,7 @@ struct rsnd_ssi { | |||
66 | 66 | ||
67 | u32 cr_own; | 67 | u32 cr_own; |
68 | u32 cr_clk; | 68 | u32 cr_clk; |
69 | int chan; | ||
69 | int err; | 70 | int err; |
70 | unsigned int usrcnt; | 71 | unsigned int usrcnt; |
71 | }; | 72 | }; |
@@ -80,16 +81,15 @@ struct rsnd_ssi { | |||
80 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | 81 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) |
81 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) | 82 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) |
82 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) | 83 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) |
83 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) | 84 | #define rsnd_ssi_parent(ssi) ((ssi)->parent) |
84 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 85 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
85 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 86 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
86 | #define rsnd_ssi_of_node(priv) \ | 87 | #define rsnd_ssi_of_node(priv) \ |
87 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi") | 88 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi") |
88 | 89 | ||
89 | int rsnd_ssi_use_busif(struct rsnd_mod *mod) | 90 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod) |
90 | { | 91 | { |
91 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 92 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
92 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
93 | int use_busif = 0; | 93 | int use_busif = 0; |
94 | 94 | ||
95 | if (!rsnd_ssi_is_dma_mode(mod)) | 95 | if (!rsnd_ssi_is_dma_mode(mod)) |
@@ -189,22 +189,26 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
189 | rsnd_mod_hw_start(&ssi->mod); | 189 | rsnd_mod_hw_start(&ssi->mod); |
190 | 190 | ||
191 | if (rsnd_rdai_is_clk_master(rdai)) { | 191 | if (rsnd_rdai_is_clk_master(rdai)) { |
192 | if (rsnd_ssi_clk_from_parent(ssi)) | 192 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); |
193 | rsnd_ssi_hw_start(ssi->parent, io); | 193 | |
194 | if (ssi_parent) | ||
195 | rsnd_ssi_hw_start(ssi_parent, io); | ||
194 | else | 196 | else |
195 | rsnd_ssi_master_clk_start(ssi, io); | 197 | rsnd_ssi_master_clk_start(ssi, io); |
196 | } | 198 | } |
197 | } | 199 | } |
198 | 200 | ||
199 | cr_mode = rsnd_ssi_is_dma_mode(&ssi->mod) ? | 201 | if (rsnd_ssi_is_dma_mode(&ssi->mod)) { |
200 | DMEN : /* DMA : enable DMA */ | 202 | cr_mode = UIEN | OIEN | /* over/under run */ |
201 | DIEN; /* PIO : enable Data interrupt */ | 203 | DMEN; /* DMA : enable DMA */ |
202 | 204 | } else { | |
205 | cr_mode = DIEN; /* PIO : enable Data interrupt */ | ||
206 | } | ||
203 | 207 | ||
204 | cr = ssi->cr_own | | 208 | cr = ssi->cr_own | |
205 | ssi->cr_clk | | 209 | ssi->cr_clk | |
206 | cr_mode | | 210 | cr_mode | |
207 | UIEN | OIEN | EN; | 211 | EN; |
208 | 212 | ||
209 | rsnd_mod_write(&ssi->mod, SSICR, cr); | 213 | rsnd_mod_write(&ssi->mod, SSICR, cr); |
210 | 214 | ||
@@ -221,16 +225,17 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
221 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); | 225 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); |
222 | } | 226 | } |
223 | 227 | ||
224 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | 228 | static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi) |
225 | { | 229 | { |
226 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 230 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); |
227 | struct rsnd_dai_stream *io = rsnd_mod_to_io(&ssi->mod); | ||
228 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 231 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
229 | struct device *dev = rsnd_priv_to_dev(priv); | 232 | struct device *dev = rsnd_priv_to_dev(priv); |
230 | u32 cr; | 233 | u32 cr; |
231 | 234 | ||
232 | if (0 == ssi->usrcnt) /* stop might be called without start */ | 235 | if (0 == ssi->usrcnt) { |
236 | dev_err(dev, "%s called without starting\n", __func__); | ||
233 | return; | 237 | return; |
238 | } | ||
234 | 239 | ||
235 | ssi->usrcnt--; | 240 | ssi->usrcnt--; |
236 | 241 | ||
@@ -253,13 +258,17 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | |||
253 | rsnd_ssi_status_check(&ssi->mod, IIRQ); | 258 | rsnd_ssi_status_check(&ssi->mod, IIRQ); |
254 | 259 | ||
255 | if (rsnd_rdai_is_clk_master(rdai)) { | 260 | if (rsnd_rdai_is_clk_master(rdai)) { |
256 | if (rsnd_ssi_clk_from_parent(ssi)) | 261 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); |
257 | rsnd_ssi_hw_stop(ssi->parent); | 262 | |
263 | if (ssi_parent) | ||
264 | rsnd_ssi_hw_stop(io, ssi_parent); | ||
258 | else | 265 | else |
259 | rsnd_ssi_master_clk_stop(ssi); | 266 | rsnd_ssi_master_clk_stop(ssi); |
260 | } | 267 | } |
261 | 268 | ||
262 | rsnd_mod_hw_stop(&ssi->mod); | 269 | rsnd_mod_hw_stop(&ssi->mod); |
270 | |||
271 | ssi->chan = 0; | ||
263 | } | 272 | } |
264 | 273 | ||
265 | dev_dbg(dev, "%s[%d] hw stopped\n", | 274 | dev_dbg(dev, "%s[%d] hw stopped\n", |
@@ -270,10 +279,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | |||
270 | * SSI mod common functions | 279 | * SSI mod common functions |
271 | */ | 280 | */ |
272 | static int rsnd_ssi_init(struct rsnd_mod *mod, | 281 | static int rsnd_ssi_init(struct rsnd_mod *mod, |
282 | struct rsnd_dai_stream *io, | ||
273 | struct rsnd_priv *priv) | 283 | struct rsnd_priv *priv) |
274 | { | 284 | { |
275 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 285 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
276 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
277 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 286 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
278 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 287 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
279 | u32 cr; | 288 | u32 cr; |
@@ -321,6 +330,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
321 | } | 330 | } |
322 | 331 | ||
323 | static int rsnd_ssi_quit(struct rsnd_mod *mod, | 332 | static int rsnd_ssi_quit(struct rsnd_mod *mod, |
333 | struct rsnd_dai_stream *io, | ||
324 | struct rsnd_priv *priv) | 334 | struct rsnd_priv *priv) |
325 | { | 335 | { |
326 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 336 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -336,6 +346,37 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, | |||
336 | return 0; | 346 | return 0; |
337 | } | 347 | } |
338 | 348 | ||
349 | static int rsnd_ssi_hw_params(struct rsnd_mod *mod, | ||
350 | struct rsnd_dai_stream *io, | ||
351 | struct snd_pcm_substream *substream, | ||
352 | struct snd_pcm_hw_params *params) | ||
353 | { | ||
354 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
355 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); | ||
356 | int chan = params_channels(params); | ||
357 | |||
358 | /* | ||
359 | * Already working. | ||
360 | * It will happen if SSI has parent/child connection. | ||
361 | */ | ||
362 | if (ssi->usrcnt) { | ||
363 | /* | ||
364 | * it is error if child <-> parent SSI uses | ||
365 | * different channels. | ||
366 | */ | ||
367 | if (ssi->chan != chan) | ||
368 | return -EIO; | ||
369 | } | ||
370 | |||
371 | /* It will be removed on rsnd_ssi_hw_stop */ | ||
372 | ssi->chan = chan; | ||
373 | if (ssi_parent) | ||
374 | return rsnd_ssi_hw_params(&ssi_parent->mod, io, | ||
375 | substream, params); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
339 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | 380 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) |
340 | { | 381 | { |
341 | /* under/over flow error */ | 382 | /* under/over flow error */ |
@@ -348,12 +389,12 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | |||
348 | } | 389 | } |
349 | 390 | ||
350 | static int rsnd_ssi_start(struct rsnd_mod *mod, | 391 | static int rsnd_ssi_start(struct rsnd_mod *mod, |
392 | struct rsnd_dai_stream *io, | ||
351 | struct rsnd_priv *priv) | 393 | struct rsnd_priv *priv) |
352 | { | 394 | { |
353 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 395 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
354 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
355 | 396 | ||
356 | rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod)); | 397 | rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(io, mod)); |
357 | 398 | ||
358 | rsnd_ssi_hw_start(ssi, io); | 399 | rsnd_ssi_hw_start(ssi, io); |
359 | 400 | ||
@@ -363,6 +404,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, | |||
363 | } | 404 | } |
364 | 405 | ||
365 | static int rsnd_ssi_stop(struct rsnd_mod *mod, | 406 | static int rsnd_ssi_stop(struct rsnd_mod *mod, |
407 | struct rsnd_dai_stream *io, | ||
366 | struct rsnd_priv *priv) | 408 | struct rsnd_priv *priv) |
367 | { | 409 | { |
368 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 410 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -371,24 +413,29 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, | |||
371 | 413 | ||
372 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | 414 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); |
373 | 415 | ||
374 | rsnd_ssi_hw_stop(ssi); | 416 | rsnd_ssi_hw_stop(io, ssi); |
375 | 417 | ||
376 | rsnd_src_ssiu_stop(mod); | 418 | rsnd_src_ssiu_stop(mod, io); |
377 | 419 | ||
378 | return 0; | 420 | return 0; |
379 | } | 421 | } |
380 | 422 | ||
381 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | 423 | static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, |
424 | struct rsnd_dai_stream *io) | ||
382 | { | 425 | { |
383 | struct rsnd_ssi *ssi = data; | 426 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
384 | struct rsnd_mod *mod = &ssi->mod; | ||
385 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 427 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
386 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
387 | int is_dma = rsnd_ssi_is_dma_mode(mod); | 428 | int is_dma = rsnd_ssi_is_dma_mode(mod); |
388 | u32 status = rsnd_mod_read(mod, SSISR); | 429 | u32 status; |
430 | bool elapsed = false; | ||
431 | |||
432 | spin_lock(&priv->lock); | ||
433 | |||
434 | /* ignore all cases if not working */ | ||
435 | if (!rsnd_io_is_working(io)) | ||
436 | goto rsnd_ssi_interrupt_out; | ||
389 | 437 | ||
390 | if (!io) | 438 | status = rsnd_mod_read(mod, SSISR); |
391 | return IRQ_NONE; | ||
392 | 439 | ||
393 | /* PIO only */ | 440 | /* PIO only */ |
394 | if (!is_dma && (status & DIRQ)) { | 441 | if (!is_dma && (status & DIRQ)) { |
@@ -406,11 +453,11 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
406 | else | 453 | else |
407 | *buf = rsnd_mod_read(mod, SSIRDR); | 454 | *buf = rsnd_mod_read(mod, SSIRDR); |
408 | 455 | ||
409 | rsnd_dai_pointer_update(io, sizeof(*buf)); | 456 | elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); |
410 | } | 457 | } |
411 | 458 | ||
412 | /* PIO / DMA */ | 459 | /* DMA only */ |
413 | if (status & (UIRQ | OIRQ)) { | 460 | if (is_dma && (status & (UIRQ | OIRQ))) { |
414 | struct device *dev = rsnd_priv_to_dev(priv); | 461 | struct device *dev = rsnd_priv_to_dev(priv); |
415 | 462 | ||
416 | /* | 463 | /* |
@@ -419,15 +466,28 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
419 | dev_dbg(dev, "%s[%d] restart\n", | 466 | dev_dbg(dev, "%s[%d] restart\n", |
420 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 467 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
421 | 468 | ||
422 | rsnd_ssi_stop(mod, priv); | 469 | rsnd_ssi_stop(mod, io, priv); |
423 | if (ssi->err < 1024) | 470 | if (ssi->err < 1024) |
424 | rsnd_ssi_start(mod, priv); | 471 | rsnd_ssi_start(mod, io, priv); |
425 | else | 472 | else |
426 | dev_warn(dev, "no more SSI restart\n"); | 473 | dev_warn(dev, "no more SSI restart\n"); |
427 | } | 474 | } |
428 | 475 | ||
429 | rsnd_ssi_record_error(ssi, status); | 476 | rsnd_ssi_record_error(ssi, status); |
430 | 477 | ||
478 | rsnd_ssi_interrupt_out: | ||
479 | spin_unlock(&priv->lock); | ||
480 | |||
481 | if (elapsed) | ||
482 | rsnd_dai_period_elapsed(io); | ||
483 | } | ||
484 | |||
485 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | ||
486 | { | ||
487 | struct rsnd_mod *mod = data; | ||
488 | |||
489 | rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt); | ||
490 | |||
431 | return IRQ_HANDLED; | 491 | return IRQ_HANDLED; |
432 | } | 492 | } |
433 | 493 | ||
@@ -435,6 +495,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
435 | * SSI PIO | 495 | * SSI PIO |
436 | */ | 496 | */ |
437 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | 497 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, |
498 | struct rsnd_dai_stream *io, | ||
438 | struct rsnd_priv *priv) | 499 | struct rsnd_priv *priv) |
439 | { | 500 | { |
440 | struct device *dev = rsnd_priv_to_dev(priv); | 501 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -444,7 +505,7 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | |||
444 | ret = devm_request_irq(dev, ssi->info->irq, | 505 | ret = devm_request_irq(dev, ssi->info->irq, |
445 | rsnd_ssi_interrupt, | 506 | rsnd_ssi_interrupt, |
446 | IRQF_SHARED, | 507 | IRQF_SHARED, |
447 | dev_name(dev), ssi); | 508 | dev_name(dev), mod); |
448 | 509 | ||
449 | return ret; | 510 | return ret; |
450 | } | 511 | } |
@@ -456,9 +517,11 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | |||
456 | .quit = rsnd_ssi_quit, | 517 | .quit = rsnd_ssi_quit, |
457 | .start = rsnd_ssi_start, | 518 | .start = rsnd_ssi_start, |
458 | .stop = rsnd_ssi_stop, | 519 | .stop = rsnd_ssi_stop, |
520 | .hw_params = rsnd_ssi_hw_params, | ||
459 | }; | 521 | }; |
460 | 522 | ||
461 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | 523 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
524 | struct rsnd_dai_stream *io, | ||
462 | struct rsnd_priv *priv) | 525 | struct rsnd_priv *priv) |
463 | { | 526 | { |
464 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 527 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -469,25 +532,26 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
469 | ret = devm_request_irq(dev, ssi->info->irq, | 532 | ret = devm_request_irq(dev, ssi->info->irq, |
470 | rsnd_ssi_interrupt, | 533 | rsnd_ssi_interrupt, |
471 | IRQF_SHARED, | 534 | IRQF_SHARED, |
472 | dev_name(dev), ssi); | 535 | dev_name(dev), mod); |
473 | if (ret) | 536 | if (ret) |
474 | return ret; | 537 | return ret; |
475 | 538 | ||
476 | ret = rsnd_dma_init( | 539 | ret = rsnd_dma_init( |
477 | priv, rsnd_mod_to_dma(mod), | 540 | io, rsnd_mod_to_dma(mod), |
478 | dma_id); | 541 | dma_id); |
479 | 542 | ||
480 | return ret; | 543 | return ret; |
481 | } | 544 | } |
482 | 545 | ||
483 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | 546 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, |
547 | struct rsnd_dai_stream *io, | ||
484 | struct rsnd_priv *priv) | 548 | struct rsnd_priv *priv) |
485 | { | 549 | { |
486 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 550 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
487 | struct device *dev = rsnd_priv_to_dev(priv); | 551 | struct device *dev = rsnd_priv_to_dev(priv); |
488 | int irq = ssi->info->irq; | 552 | int irq = ssi->info->irq; |
489 | 553 | ||
490 | rsnd_dma_quit(rsnd_mod_to_dma(mod)); | 554 | rsnd_dma_quit(io, rsnd_mod_to_dma(mod)); |
491 | 555 | ||
492 | /* PIO will request IRQ again */ | 556 | /* PIO will request IRQ again */ |
493 | devm_free_irq(dev, irq, ssi); | 557 | devm_free_irq(dev, irq, ssi); |
@@ -496,6 +560,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | |||
496 | } | 560 | } |
497 | 561 | ||
498 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, | 562 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, |
563 | struct rsnd_dai_stream *io, | ||
499 | struct rsnd_priv *priv) | 564 | struct rsnd_priv *priv) |
500 | { | 565 | { |
501 | struct device *dev = rsnd_priv_to_dev(priv); | 566 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -516,37 +581,39 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod, | |||
516 | } | 581 | } |
517 | 582 | ||
518 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | 583 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, |
584 | struct rsnd_dai_stream *io, | ||
519 | struct rsnd_priv *priv) | 585 | struct rsnd_priv *priv) |
520 | { | 586 | { |
521 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 587 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
522 | 588 | ||
523 | rsnd_dma_start(dma); | 589 | rsnd_dma_start(io, dma); |
524 | 590 | ||
525 | rsnd_ssi_start(mod, priv); | 591 | rsnd_ssi_start(mod, io, priv); |
526 | 592 | ||
527 | return 0; | 593 | return 0; |
528 | } | 594 | } |
529 | 595 | ||
530 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | 596 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, |
597 | struct rsnd_dai_stream *io, | ||
531 | struct rsnd_priv *priv) | 598 | struct rsnd_priv *priv) |
532 | { | 599 | { |
533 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 600 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
534 | 601 | ||
535 | rsnd_ssi_stop(mod, priv); | 602 | rsnd_ssi_stop(mod, io, priv); |
536 | 603 | ||
537 | rsnd_dma_stop(dma); | 604 | rsnd_dma_stop(io, dma); |
538 | 605 | ||
539 | return 0; | 606 | return 0; |
540 | } | 607 | } |
541 | 608 | ||
542 | static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_mod *mod) | 609 | static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, |
610 | struct rsnd_mod *mod) | ||
543 | { | 611 | { |
544 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 612 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
545 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
546 | int is_play = rsnd_io_is_play(io); | 613 | int is_play = rsnd_io_is_play(io); |
547 | char *name; | 614 | char *name; |
548 | 615 | ||
549 | if (rsnd_ssi_use_busif(mod)) | 616 | if (rsnd_ssi_use_busif(io, mod)) |
550 | name = is_play ? "rxu" : "txu"; | 617 | name = is_play ? "rxu" : "txu"; |
551 | else | 618 | else |
552 | name = is_play ? "rx" : "tx"; | 619 | name = is_play ? "rx" : "tx"; |
@@ -565,6 +632,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | |||
565 | .start = rsnd_ssi_dma_start, | 632 | .start = rsnd_ssi_dma_start, |
566 | .stop = rsnd_ssi_dma_stop, | 633 | .stop = rsnd_ssi_dma_stop, |
567 | .fallback = rsnd_ssi_fallback, | 634 | .fallback = rsnd_ssi_fallback, |
635 | .hw_params = rsnd_ssi_hw_params, | ||
568 | }; | 636 | }; |
569 | 637 | ||
570 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) | 638 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) |
@@ -598,7 +666,7 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) | |||
598 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); | 666 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); |
599 | } | 667 | } |
600 | 668 | ||
601 | static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) | 669 | static void rsnd_ssi_parent_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) |
602 | { | 670 | { |
603 | if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) | 671 | if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) |
604 | return; | 672 | return; |
@@ -728,11 +796,11 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
728 | else if (rsnd_ssi_pio_available(ssi)) | 796 | else if (rsnd_ssi_pio_available(ssi)) |
729 | ops = &rsnd_ssi_pio_ops; | 797 | ops = &rsnd_ssi_pio_ops; |
730 | 798 | ||
731 | ret = rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); | 799 | ret = rsnd_mod_init(priv, &ssi->mod, ops, clk, RSND_MOD_SSI, i); |
732 | if (ret) | 800 | if (ret) |
733 | return ret; | 801 | return ret; |
734 | 802 | ||
735 | rsnd_ssi_parent_clk_setup(priv, ssi); | 803 | rsnd_ssi_parent_setup(priv, ssi); |
736 | } | 804 | } |
737 | 805 | ||
738 | return 0; | 806 | return 0; |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 23732523f87c..0e1e69c7abd5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | #include <sound/soc-dpcm.h> | 42 | #include <sound/soc-dpcm.h> |
43 | #include <sound/soc-topology.h> | ||
43 | #include <sound/initval.h> | 44 | #include <sound/initval.h> |
44 | 45 | ||
45 | #define CREATE_TRACE_POINTS | 46 | #define CREATE_TRACE_POINTS |
@@ -92,30 +93,21 @@ static int format_register_str(struct snd_soc_codec *codec, | |||
92 | int wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; | 93 | int wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; |
93 | int regsize = codec->driver->reg_word_size * 2; | 94 | int regsize = codec->driver->reg_word_size * 2; |
94 | int ret; | 95 | int ret; |
95 | char tmpbuf[len + 1]; | ||
96 | char regbuf[regsize + 1]; | ||
97 | |||
98 | /* since tmpbuf is allocated on the stack, warn the callers if they | ||
99 | * try to abuse this function */ | ||
100 | WARN_ON(len > 63); | ||
101 | 96 | ||
102 | /* +2 for ': ' and + 1 for '\n' */ | 97 | /* +2 for ': ' and + 1 for '\n' */ |
103 | if (wordsize + regsize + 2 + 1 != len) | 98 | if (wordsize + regsize + 2 + 1 != len) |
104 | return -EINVAL; | 99 | return -EINVAL; |
105 | 100 | ||
106 | ret = snd_soc_read(codec, reg); | 101 | sprintf(buf, "%.*x: ", wordsize, reg); |
107 | if (ret < 0) { | 102 | buf += wordsize + 2; |
108 | memset(regbuf, 'X', regsize); | ||
109 | regbuf[regsize] = '\0'; | ||
110 | } else { | ||
111 | snprintf(regbuf, regsize + 1, "%.*x", regsize, ret); | ||
112 | } | ||
113 | |||
114 | /* prepare the buffer */ | ||
115 | snprintf(tmpbuf, len + 1, "%.*x: %s\n", wordsize, reg, regbuf); | ||
116 | /* copy it back to the caller without the '\0' */ | ||
117 | memcpy(buf, tmpbuf, len); | ||
118 | 103 | ||
104 | ret = snd_soc_read(codec, reg); | ||
105 | if (ret < 0) | ||
106 | memset(buf, 'X', regsize); | ||
107 | else | ||
108 | sprintf(buf, "%.*x", regsize, ret); | ||
109 | buf[regsize] = '\n'; | ||
110 | /* no NUL-termination needed */ | ||
119 | return 0; | 111 | return 0; |
120 | } | 112 | } |
121 | 113 | ||
@@ -750,23 +742,10 @@ static void soc_resume_deferred(struct work_struct *work) | |||
750 | } | 742 | } |
751 | 743 | ||
752 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 744 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
753 | /* If the CODEC was idle over suspend then it will have been | ||
754 | * left with bias OFF or STANDBY and suspended so we must now | ||
755 | * resume. Otherwise the suspend was suppressed. | ||
756 | */ | ||
757 | if (codec->suspended) { | 745 | if (codec->suspended) { |
758 | switch (codec->dapm.bias_level) { | 746 | if (codec->driver->resume) |
759 | case SND_SOC_BIAS_STANDBY: | 747 | codec->driver->resume(codec); |
760 | case SND_SOC_BIAS_OFF: | 748 | codec->suspended = 0; |
761 | if (codec->driver->resume) | ||
762 | codec->driver->resume(codec); | ||
763 | codec->suspended = 0; | ||
764 | break; | ||
765 | default: | ||
766 | dev_dbg(codec->dev, | ||
767 | "ASoC: CODEC was on over suspend\n"); | ||
768 | break; | ||
769 | } | ||
770 | } | 749 | } |
771 | } | 750 | } |
772 | 751 | ||
@@ -904,12 +883,17 @@ static struct snd_soc_dai *snd_soc_find_dai( | |||
904 | { | 883 | { |
905 | struct snd_soc_component *component; | 884 | struct snd_soc_component *component; |
906 | struct snd_soc_dai *dai; | 885 | struct snd_soc_dai *dai; |
886 | struct device_node *component_of_node; | ||
907 | 887 | ||
908 | lockdep_assert_held(&client_mutex); | 888 | lockdep_assert_held(&client_mutex); |
909 | 889 | ||
910 | /* Find CPU DAI from registered DAIs*/ | 890 | /* Find CPU DAI from registered DAIs*/ |
911 | list_for_each_entry(component, &component_list, list) { | 891 | list_for_each_entry(component, &component_list, list) { |
912 | if (dlc->of_node && component->dev->of_node != dlc->of_node) | 892 | component_of_node = component->dev->of_node; |
893 | if (!component_of_node && component->dev->parent) | ||
894 | component_of_node = component->dev->parent->of_node; | ||
895 | |||
896 | if (dlc->of_node && component_of_node != dlc->of_node) | ||
913 | continue; | 897 | continue; |
914 | if (dlc->name && strcmp(component->name, dlc->name)) | 898 | if (dlc->name && strcmp(component->name, dlc->name)) |
915 | continue; | 899 | continue; |
@@ -1732,6 +1716,7 @@ card_probe_error: | |||
1732 | if (card->remove) | 1716 | if (card->remove) |
1733 | card->remove(card); | 1717 | card->remove(card); |
1734 | 1718 | ||
1719 | snd_soc_dapm_free(&card->dapm); | ||
1735 | soc_cleanup_card_debugfs(card); | 1720 | soc_cleanup_card_debugfs(card); |
1736 | snd_card_free(card->snd_card); | 1721 | snd_card_free(card->snd_card); |
1737 | 1722 | ||
@@ -2435,6 +2420,7 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2435 | card->rtd_aux[i].card = card; | 2420 | card->rtd_aux[i].card = card; |
2436 | 2421 | ||
2437 | INIT_LIST_HEAD(&card->dapm_dirty); | 2422 | INIT_LIST_HEAD(&card->dapm_dirty); |
2423 | INIT_LIST_HEAD(&card->dobj_list); | ||
2438 | card->instantiated = 0; | 2424 | card->instantiated = 0; |
2439 | mutex_init(&card->mutex); | 2425 | mutex_init(&card->mutex); |
2440 | mutex_init(&card->dapm_mutex); | 2426 | mutex_init(&card->dapm_mutex); |
@@ -2599,7 +2585,8 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
2599 | * the same naming style even though those DAIs are not | 2585 | * the same naming style even though those DAIs are not |
2600 | * component-less anymore. | 2586 | * component-less anymore. |
2601 | */ | 2587 | */ |
2602 | if (count == 1 && legacy_dai_naming) { | 2588 | if (count == 1 && legacy_dai_naming && |
2589 | (dai_drv[i].id == 0 || dai_drv[i].name == NULL)) { | ||
2603 | dai->name = fmt_single_name(dev, &dai->id); | 2590 | dai->name = fmt_single_name(dev, &dai->id); |
2604 | } else { | 2591 | } else { |
2605 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | 2592 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); |
@@ -2749,6 +2736,7 @@ static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | |||
2749 | } | 2736 | } |
2750 | 2737 | ||
2751 | list_add(&component->list, &component_list); | 2738 | list_add(&component->list, &component_list); |
2739 | INIT_LIST_HEAD(&component->dobj_list); | ||
2752 | } | 2740 | } |
2753 | 2741 | ||
2754 | static void snd_soc_component_add(struct snd_soc_component *component) | 2742 | static void snd_soc_component_add(struct snd_soc_component *component) |
@@ -2825,6 +2813,7 @@ void snd_soc_unregister_component(struct device *dev) | |||
2825 | return; | 2813 | return; |
2826 | 2814 | ||
2827 | found: | 2815 | found: |
2816 | snd_soc_tplg_component_remove(cmpnt, SND_SOC_TPLG_INDEX_ALL); | ||
2828 | snd_soc_component_del_unlocked(cmpnt); | 2817 | snd_soc_component_del_unlocked(cmpnt); |
2829 | mutex_unlock(&client_mutex); | 2818 | mutex_unlock(&client_mutex); |
2830 | snd_soc_component_cleanup(cmpnt); | 2819 | snd_soc_component_cleanup(cmpnt); |
@@ -3488,11 +3477,16 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args, | |||
3488 | const char **dai_name) | 3477 | const char **dai_name) |
3489 | { | 3478 | { |
3490 | struct snd_soc_component *pos; | 3479 | struct snd_soc_component *pos; |
3480 | struct device_node *component_of_node; | ||
3491 | int ret = -EPROBE_DEFER; | 3481 | int ret = -EPROBE_DEFER; |
3492 | 3482 | ||
3493 | mutex_lock(&client_mutex); | 3483 | mutex_lock(&client_mutex); |
3494 | list_for_each_entry(pos, &component_list, list) { | 3484 | list_for_each_entry(pos, &component_list, list) { |
3495 | if (pos->dev->of_node != args->np) | 3485 | component_of_node = pos->dev->of_node; |
3486 | if (!component_of_node && pos->dev->parent) | ||
3487 | component_of_node = pos->dev->parent->of_node; | ||
3488 | |||
3489 | if (component_of_node != args->np) | ||
3496 | continue; | 3490 | continue; |
3497 | 3491 | ||
3498 | if (pos->driver->of_xlate_dai_name) { | 3492 | if (pos->driver->of_xlate_dai_name) { |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index defe0f0082b5..e0de8072c514 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -52,10 +52,15 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
52 | const char *control, | 52 | const char *control, |
53 | int (*connected)(struct snd_soc_dapm_widget *source, | 53 | int (*connected)(struct snd_soc_dapm_widget *source, |
54 | struct snd_soc_dapm_widget *sink)); | 54 | struct snd_soc_dapm_widget *sink)); |
55 | static struct snd_soc_dapm_widget * | 55 | |
56 | struct snd_soc_dapm_widget * | ||
56 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | 57 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, |
57 | const struct snd_soc_dapm_widget *widget); | 58 | const struct snd_soc_dapm_widget *widget); |
58 | 59 | ||
60 | struct snd_soc_dapm_widget * | ||
61 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | ||
62 | const struct snd_soc_dapm_widget *widget); | ||
63 | |||
59 | /* dapm power sequences - make this per codec in the future */ | 64 | /* dapm power sequences - make this per codec in the future */ |
60 | static int dapm_up_seq[] = { | 65 | static int dapm_up_seq[] = { |
61 | [snd_soc_dapm_pre] = 0, | 66 | [snd_soc_dapm_pre] = 0, |
@@ -70,6 +75,7 @@ static int dapm_up_seq[] = { | |||
70 | [snd_soc_dapm_aif_out] = 4, | 75 | [snd_soc_dapm_aif_out] = 4, |
71 | [snd_soc_dapm_mic] = 5, | 76 | [snd_soc_dapm_mic] = 5, |
72 | [snd_soc_dapm_mux] = 6, | 77 | [snd_soc_dapm_mux] = 6, |
78 | [snd_soc_dapm_demux] = 6, | ||
73 | [snd_soc_dapm_dac] = 7, | 79 | [snd_soc_dapm_dac] = 7, |
74 | [snd_soc_dapm_switch] = 8, | 80 | [snd_soc_dapm_switch] = 8, |
75 | [snd_soc_dapm_mixer] = 8, | 81 | [snd_soc_dapm_mixer] = 8, |
@@ -100,6 +106,7 @@ static int dapm_down_seq[] = { | |||
100 | [snd_soc_dapm_mic] = 7, | 106 | [snd_soc_dapm_mic] = 7, |
101 | [snd_soc_dapm_micbias] = 8, | 107 | [snd_soc_dapm_micbias] = 8, |
102 | [snd_soc_dapm_mux] = 9, | 108 | [snd_soc_dapm_mux] = 9, |
109 | [snd_soc_dapm_demux] = 9, | ||
103 | [snd_soc_dapm_aif_in] = 10, | 110 | [snd_soc_dapm_aif_in] = 10, |
104 | [snd_soc_dapm_aif_out] = 10, | 111 | [snd_soc_dapm_aif_out] = 10, |
105 | [snd_soc_dapm_dai_in] = 10, | 112 | [snd_soc_dapm_dai_in] = 10, |
@@ -308,14 +315,13 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
308 | { | 315 | { |
309 | struct dapm_kcontrol_data *data; | 316 | struct dapm_kcontrol_data *data; |
310 | struct soc_mixer_control *mc; | 317 | struct soc_mixer_control *mc; |
318 | struct soc_enum *e; | ||
319 | const char *name; | ||
320 | int ret; | ||
311 | 321 | ||
312 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 322 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
313 | if (!data) { | 323 | if (!data) |
314 | dev_err(widget->dapm->dev, | ||
315 | "ASoC: can't allocate kcontrol data for %s\n", | ||
316 | widget->name); | ||
317 | return -ENOMEM; | 324 | return -ENOMEM; |
318 | } | ||
319 | 325 | ||
320 | INIT_LIST_HEAD(&data->paths); | 326 | INIT_LIST_HEAD(&data->paths); |
321 | 327 | ||
@@ -328,6 +334,13 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
328 | if (mc->autodisable) { | 334 | if (mc->autodisable) { |
329 | struct snd_soc_dapm_widget template; | 335 | struct snd_soc_dapm_widget template; |
330 | 336 | ||
337 | name = kasprintf(GFP_KERNEL, "%s %s", kcontrol->id.name, | ||
338 | "Autodisable"); | ||
339 | if (!name) { | ||
340 | ret = -ENOMEM; | ||
341 | goto err_data; | ||
342 | } | ||
343 | |||
331 | memset(&template, 0, sizeof(template)); | 344 | memset(&template, 0, sizeof(template)); |
332 | template.reg = mc->reg; | 345 | template.reg = mc->reg; |
333 | template.mask = (1 << fls(mc->max)) - 1; | 346 | template.mask = (1 << fls(mc->max)) - 1; |
@@ -338,18 +351,57 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
338 | template.off_val = 0; | 351 | template.off_val = 0; |
339 | template.on_val = template.off_val; | 352 | template.on_val = template.off_val; |
340 | template.id = snd_soc_dapm_kcontrol; | 353 | template.id = snd_soc_dapm_kcontrol; |
341 | template.name = kcontrol->id.name; | 354 | template.name = name; |
342 | 355 | ||
343 | data->value = template.on_val; | 356 | data->value = template.on_val; |
344 | 357 | ||
345 | data->widget = snd_soc_dapm_new_control(widget->dapm, | 358 | data->widget = |
359 | snd_soc_dapm_new_control_unlocked(widget->dapm, | ||
346 | &template); | 360 | &template); |
361 | kfree(name); | ||
347 | if (!data->widget) { | 362 | if (!data->widget) { |
348 | kfree(data); | 363 | ret = -ENOMEM; |
349 | return -ENOMEM; | 364 | goto err_data; |
350 | } | 365 | } |
351 | } | 366 | } |
352 | break; | 367 | break; |
368 | case snd_soc_dapm_demux: | ||
369 | case snd_soc_dapm_mux: | ||
370 | e = (struct soc_enum *)kcontrol->private_value; | ||
371 | |||
372 | if (e->autodisable) { | ||
373 | struct snd_soc_dapm_widget template; | ||
374 | |||
375 | name = kasprintf(GFP_KERNEL, "%s %s", kcontrol->id.name, | ||
376 | "Autodisable"); | ||
377 | if (!name) { | ||
378 | ret = -ENOMEM; | ||
379 | goto err_data; | ||
380 | } | ||
381 | |||
382 | memset(&template, 0, sizeof(template)); | ||
383 | template.reg = e->reg; | ||
384 | template.mask = e->mask << e->shift_l; | ||
385 | template.shift = e->shift_l; | ||
386 | template.off_val = snd_soc_enum_item_to_val(e, 0); | ||
387 | template.on_val = template.off_val; | ||
388 | template.id = snd_soc_dapm_kcontrol; | ||
389 | template.name = name; | ||
390 | |||
391 | data->value = template.on_val; | ||
392 | |||
393 | data->widget = snd_soc_dapm_new_control_unlocked( | ||
394 | widget->dapm, &template); | ||
395 | kfree(name); | ||
396 | if (!data->widget) { | ||
397 | ret = -ENOMEM; | ||
398 | goto err_data; | ||
399 | } | ||
400 | |||
401 | snd_soc_dapm_add_path(widget->dapm, data->widget, | ||
402 | widget, NULL, NULL); | ||
403 | } | ||
404 | break; | ||
353 | default: | 405 | default: |
354 | break; | 406 | break; |
355 | } | 407 | } |
@@ -357,6 +409,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
357 | kcontrol->private_data = data; | 409 | kcontrol->private_data = data; |
358 | 410 | ||
359 | return 0; | 411 | return 0; |
412 | |||
413 | err_data: | ||
414 | kfree(data); | ||
415 | return ret; | ||
360 | } | 416 | } |
361 | 417 | ||
362 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) | 418 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) |
@@ -405,11 +461,6 @@ static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol, | |||
405 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | 461 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); |
406 | 462 | ||
407 | list_add_tail(&path->list_kcontrol, &data->paths); | 463 | list_add_tail(&path->list_kcontrol, &data->paths); |
408 | |||
409 | if (data->widget) { | ||
410 | snd_soc_dapm_add_path(data->widget->dapm, data->widget, | ||
411 | path->source, NULL, NULL); | ||
412 | } | ||
413 | } | 464 | } |
414 | 465 | ||
415 | static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol) | 466 | static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol) |
@@ -525,6 +576,67 @@ static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) | |||
525 | snd_soc_component_async_complete(dapm->component); | 576 | snd_soc_component_async_complete(dapm->component); |
526 | } | 577 | } |
527 | 578 | ||
579 | static struct snd_soc_dapm_widget * | ||
580 | dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name) | ||
581 | { | ||
582 | struct snd_soc_dapm_widget *w = wcache->widget; | ||
583 | struct list_head *wlist; | ||
584 | const int depth = 2; | ||
585 | int i = 0; | ||
586 | |||
587 | if (w) { | ||
588 | wlist = &w->dapm->card->widgets; | ||
589 | |||
590 | list_for_each_entry_from(w, wlist, list) { | ||
591 | if (!strcmp(name, w->name)) | ||
592 | return w; | ||
593 | |||
594 | if (++i == depth) | ||
595 | break; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | return NULL; | ||
600 | } | ||
601 | |||
602 | static inline void dapm_wcache_update(struct snd_soc_dapm_wcache *wcache, | ||
603 | struct snd_soc_dapm_widget *w) | ||
604 | { | ||
605 | wcache->widget = w; | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * snd_soc_dapm_force_bias_level() - Sets the DAPM bias level | ||
610 | * @dapm: The DAPM context for which to set the level | ||
611 | * @level: The level to set | ||
612 | * | ||
613 | * Forces the DAPM bias level to a specific state. It will call the bias level | ||
614 | * callback of DAPM context with the specified level. This will even happen if | ||
615 | * the context is already at the same level. Furthermore it will not go through | ||
616 | * the normal bias level sequencing, meaning any intermediate states between the | ||
617 | * current and the target state will not be entered. | ||
618 | * | ||
619 | * Note that the change in bias level is only temporary and the next time | ||
620 | * snd_soc_dapm_sync() is called the state will be set to the level as | ||
621 | * determined by the DAPM core. The function is mainly intended to be used to | ||
622 | * used during probe or resume from suspend to power up the device so | ||
623 | * initialization can be done, before the DAPM core takes over. | ||
624 | */ | ||
625 | int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, | ||
626 | enum snd_soc_bias_level level) | ||
627 | { | ||
628 | int ret = 0; | ||
629 | |||
630 | if (dapm->set_bias_level) | ||
631 | ret = dapm->set_bias_level(dapm, level); | ||
632 | |||
633 | if (ret == 0) | ||
634 | dapm->bias_level = level; | ||
635 | |||
636 | return ret; | ||
637 | } | ||
638 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level); | ||
639 | |||
528 | /** | 640 | /** |
529 | * snd_soc_dapm_set_bias_level - set the bias level for the system | 641 | * snd_soc_dapm_set_bias_level - set the bias level for the system |
530 | * @dapm: DAPM context | 642 | * @dapm: DAPM context |
@@ -547,10 +659,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
547 | if (ret != 0) | 659 | if (ret != 0) |
548 | goto out; | 660 | goto out; |
549 | 661 | ||
550 | if (dapm->set_bias_level) | 662 | if (!card || dapm != &card->dapm) |
551 | ret = dapm->set_bias_level(dapm, level); | 663 | ret = snd_soc_dapm_force_bias_level(dapm, level); |
552 | else if (!card || dapm != &card->dapm) | ||
553 | dapm->bias_level = level; | ||
554 | 664 | ||
555 | if (ret != 0) | 665 | if (ret != 0) |
556 | goto out; | 666 | goto out; |
@@ -565,9 +675,10 @@ out: | |||
565 | 675 | ||
566 | /* connect mux widget to its interconnecting audio paths */ | 676 | /* connect mux widget to its interconnecting audio paths */ |
567 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | 677 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
568 | struct snd_soc_dapm_path *path, const char *control_name) | 678 | struct snd_soc_dapm_path *path, const char *control_name, |
679 | struct snd_soc_dapm_widget *w) | ||
569 | { | 680 | { |
570 | const struct snd_kcontrol_new *kcontrol = &path->sink->kcontrol_news[0]; | 681 | const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0]; |
571 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 682 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
572 | unsigned int val, item; | 683 | unsigned int val, item; |
573 | int i; | 684 | int i; |
@@ -707,6 +818,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
707 | wname_in_long_name = false; | 818 | wname_in_long_name = false; |
708 | kcname_in_long_name = true; | 819 | kcname_in_long_name = true; |
709 | break; | 820 | break; |
821 | case snd_soc_dapm_demux: | ||
710 | case snd_soc_dapm_mux: | 822 | case snd_soc_dapm_mux: |
711 | wname_in_long_name = true; | 823 | wname_in_long_name = true; |
712 | kcname_in_long_name = false; | 824 | kcname_in_long_name = false; |
@@ -777,6 +889,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
777 | { | 889 | { |
778 | int i, ret; | 890 | int i, ret; |
779 | struct snd_soc_dapm_path *path; | 891 | struct snd_soc_dapm_path *path; |
892 | struct dapm_kcontrol_data *data; | ||
780 | 893 | ||
781 | /* add kcontrol */ | 894 | /* add kcontrol */ |
782 | for (i = 0; i < w->num_kcontrols; i++) { | 895 | for (i = 0; i < w->num_kcontrols; i++) { |
@@ -786,16 +899,20 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
786 | if (path->name != (char *)w->kcontrol_news[i].name) | 899 | if (path->name != (char *)w->kcontrol_news[i].name) |
787 | continue; | 900 | continue; |
788 | 901 | ||
789 | if (w->kcontrols[i]) { | 902 | if (!w->kcontrols[i]) { |
790 | dapm_kcontrol_add_path(w->kcontrols[i], path); | 903 | ret = dapm_create_or_share_mixmux_kcontrol(w, i); |
791 | continue; | 904 | if (ret < 0) |
905 | return ret; | ||
792 | } | 906 | } |
793 | 907 | ||
794 | ret = dapm_create_or_share_mixmux_kcontrol(w, i); | ||
795 | if (ret < 0) | ||
796 | return ret; | ||
797 | |||
798 | dapm_kcontrol_add_path(w->kcontrols[i], path); | 908 | dapm_kcontrol_add_path(w->kcontrols[i], path); |
909 | |||
910 | data = snd_kcontrol_chip(w->kcontrols[i]); | ||
911 | if (data->widget) | ||
912 | snd_soc_dapm_add_path(data->widget->dapm, | ||
913 | data->widget, | ||
914 | path->source, | ||
915 | NULL, NULL); | ||
799 | } | 916 | } |
800 | } | 917 | } |
801 | 918 | ||
@@ -807,17 +924,32 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
807 | { | 924 | { |
808 | struct snd_soc_dapm_context *dapm = w->dapm; | 925 | struct snd_soc_dapm_context *dapm = w->dapm; |
809 | struct snd_soc_dapm_path *path; | 926 | struct snd_soc_dapm_path *path; |
927 | struct list_head *paths; | ||
928 | const char *type; | ||
810 | int ret; | 929 | int ret; |
811 | 930 | ||
931 | switch (w->id) { | ||
932 | case snd_soc_dapm_mux: | ||
933 | paths = &w->sources; | ||
934 | type = "mux"; | ||
935 | break; | ||
936 | case snd_soc_dapm_demux: | ||
937 | paths = &w->sinks; | ||
938 | type = "demux"; | ||
939 | break; | ||
940 | default: | ||
941 | return -EINVAL; | ||
942 | } | ||
943 | |||
812 | if (w->num_kcontrols != 1) { | 944 | if (w->num_kcontrols != 1) { |
813 | dev_err(dapm->dev, | 945 | dev_err(dapm->dev, |
814 | "ASoC: mux %s has incorrect number of controls\n", | 946 | "ASoC: %s %s has incorrect number of controls\n", type, |
815 | w->name); | 947 | w->name); |
816 | return -EINVAL; | 948 | return -EINVAL; |
817 | } | 949 | } |
818 | 950 | ||
819 | if (list_empty(&w->sources)) { | 951 | if (list_empty(paths)) { |
820 | dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name); | 952 | dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name); |
821 | return -EINVAL; | 953 | return -EINVAL; |
822 | } | 954 | } |
823 | 955 | ||
@@ -825,9 +957,16 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
825 | if (ret < 0) | 957 | if (ret < 0) |
826 | return ret; | 958 | return ret; |
827 | 959 | ||
828 | list_for_each_entry(path, &w->sources, list_sink) { | 960 | if (w->id == snd_soc_dapm_mux) { |
829 | if (path->name) | 961 | list_for_each_entry(path, &w->sources, list_sink) { |
830 | dapm_kcontrol_add_path(w->kcontrols[0], path); | 962 | if (path->name) |
963 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
964 | } | ||
965 | } else { | ||
966 | list_for_each_entry(path, &w->sinks, list_source) { | ||
967 | if (path->name) | ||
968 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
969 | } | ||
831 | } | 970 | } |
832 | 971 | ||
833 | return 0; | 972 | return 0; |
@@ -1811,6 +1950,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1811 | size_t count, loff_t *ppos) | 1950 | size_t count, loff_t *ppos) |
1812 | { | 1951 | { |
1813 | struct snd_soc_dapm_widget *w = file->private_data; | 1952 | struct snd_soc_dapm_widget *w = file->private_data; |
1953 | struct snd_soc_card *card = w->dapm->card; | ||
1814 | char *buf; | 1954 | char *buf; |
1815 | int in, out; | 1955 | int in, out; |
1816 | ssize_t ret; | 1956 | ssize_t ret; |
@@ -1820,6 +1960,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1820 | if (!buf) | 1960 | if (!buf) |
1821 | return -ENOMEM; | 1961 | return -ENOMEM; |
1822 | 1962 | ||
1963 | mutex_lock(&card->dapm_mutex); | ||
1964 | |||
1823 | /* Supply widgets are not handled by is_connected_{input,output}_ep() */ | 1965 | /* Supply widgets are not handled by is_connected_{input,output}_ep() */ |
1824 | if (w->is_supply) { | 1966 | if (w->is_supply) { |
1825 | in = 0; | 1967 | in = 0; |
@@ -1866,6 +2008,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1866 | p->sink->name); | 2008 | p->sink->name); |
1867 | } | 2009 | } |
1868 | 2010 | ||
2011 | mutex_unlock(&card->dapm_mutex); | ||
2012 | |||
1869 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | 2013 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); |
1870 | 2014 | ||
1871 | kfree(buf); | 2015 | kfree(buf); |
@@ -2140,11 +2284,15 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2140 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | 2284 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); |
2141 | int i, count = 0; | 2285 | int i, count = 0; |
2142 | 2286 | ||
2287 | mutex_lock(&rtd->card->dapm_mutex); | ||
2288 | |||
2143 | for (i = 0; i < rtd->num_codecs; i++) { | 2289 | for (i = 0; i < rtd->num_codecs; i++) { |
2144 | struct snd_soc_codec *codec = rtd->codec_dais[i]->codec; | 2290 | struct snd_soc_codec *codec = rtd->codec_dais[i]->codec; |
2145 | count += dapm_widget_show_codec(codec, buf + count); | 2291 | count += dapm_widget_show_codec(codec, buf + count); |
2146 | } | 2292 | } |
2147 | 2293 | ||
2294 | mutex_unlock(&rtd->card->dapm_mutex); | ||
2295 | |||
2148 | return count; | 2296 | return count; |
2149 | } | 2297 | } |
2150 | 2298 | ||
@@ -2335,6 +2483,50 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | |||
2335 | } | 2483 | } |
2336 | } | 2484 | } |
2337 | 2485 | ||
2486 | static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm, | ||
2487 | struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink, | ||
2488 | const char *control) | ||
2489 | { | ||
2490 | bool dynamic_source = false; | ||
2491 | bool dynamic_sink = false; | ||
2492 | |||
2493 | if (!control) | ||
2494 | return 0; | ||
2495 | |||
2496 | switch (source->id) { | ||
2497 | case snd_soc_dapm_demux: | ||
2498 | dynamic_source = true; | ||
2499 | break; | ||
2500 | default: | ||
2501 | break; | ||
2502 | } | ||
2503 | |||
2504 | switch (sink->id) { | ||
2505 | case snd_soc_dapm_mux: | ||
2506 | case snd_soc_dapm_switch: | ||
2507 | case snd_soc_dapm_mixer: | ||
2508 | case snd_soc_dapm_mixer_named_ctl: | ||
2509 | dynamic_sink = true; | ||
2510 | break; | ||
2511 | default: | ||
2512 | break; | ||
2513 | } | ||
2514 | |||
2515 | if (dynamic_source && dynamic_sink) { | ||
2516 | dev_err(dapm->dev, | ||
2517 | "Direct connection between demux and mixer/mux not supported for path %s -> [%s] -> %s\n", | ||
2518 | source->name, control, sink->name); | ||
2519 | return -EINVAL; | ||
2520 | } else if (!dynamic_source && !dynamic_sink) { | ||
2521 | dev_err(dapm->dev, | ||
2522 | "Control not supported for path %s -> [%s] -> %s\n", | ||
2523 | source->name, control, sink->name); | ||
2524 | return -EINVAL; | ||
2525 | } | ||
2526 | |||
2527 | return 0; | ||
2528 | } | ||
2529 | |||
2338 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | 2530 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, |
2339 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, | 2531 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, |
2340 | const char *control, | 2532 | const char *control, |
@@ -2365,6 +2557,10 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2365 | return -EINVAL; | 2557 | return -EINVAL; |
2366 | } | 2558 | } |
2367 | 2559 | ||
2560 | ret = snd_soc_dapm_check_dynamic_path(dapm, wsource, wsink, control); | ||
2561 | if (ret) | ||
2562 | return ret; | ||
2563 | |||
2368 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); | 2564 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); |
2369 | if (!path) | 2565 | if (!path) |
2370 | return -ENOMEM; | 2566 | return -ENOMEM; |
@@ -2384,10 +2580,19 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2384 | if (control == NULL) { | 2580 | if (control == NULL) { |
2385 | path->connect = 1; | 2581 | path->connect = 1; |
2386 | } else { | 2582 | } else { |
2387 | /* connect dynamic paths */ | 2583 | switch (wsource->id) { |
2584 | case snd_soc_dapm_demux: | ||
2585 | ret = dapm_connect_mux(dapm, path, control, wsource); | ||
2586 | if (ret) | ||
2587 | goto err; | ||
2588 | break; | ||
2589 | default: | ||
2590 | break; | ||
2591 | } | ||
2592 | |||
2388 | switch (wsink->id) { | 2593 | switch (wsink->id) { |
2389 | case snd_soc_dapm_mux: | 2594 | case snd_soc_dapm_mux: |
2390 | ret = dapm_connect_mux(dapm, path, control); | 2595 | ret = dapm_connect_mux(dapm, path, control, wsink); |
2391 | if (ret != 0) | 2596 | if (ret != 0) |
2392 | goto err; | 2597 | goto err; |
2393 | break; | 2598 | break; |
@@ -2399,11 +2604,7 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2399 | goto err; | 2604 | goto err; |
2400 | break; | 2605 | break; |
2401 | default: | 2606 | default: |
2402 | dev_err(dapm->dev, | 2607 | break; |
2403 | "Control not supported for path %s -> [%s] -> %s\n", | ||
2404 | wsource->name, control, wsink->name); | ||
2405 | ret = -EINVAL; | ||
2406 | goto err; | ||
2407 | } | 2608 | } |
2408 | } | 2609 | } |
2409 | 2610 | ||
@@ -2451,6 +2652,12 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2451 | source = route->source; | 2652 | source = route->source; |
2452 | } | 2653 | } |
2453 | 2654 | ||
2655 | wsource = dapm_wcache_lookup(&dapm->path_source_cache, source); | ||
2656 | wsink = dapm_wcache_lookup(&dapm->path_sink_cache, sink); | ||
2657 | |||
2658 | if (wsink && wsource) | ||
2659 | goto skip_search; | ||
2660 | |||
2454 | /* | 2661 | /* |
2455 | * find src and dest widgets over all widgets but favor a widget from | 2662 | * find src and dest widgets over all widgets but favor a widget from |
2456 | * current DAPM context | 2663 | * current DAPM context |
@@ -2458,14 +2665,20 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2458 | list_for_each_entry(w, &dapm->card->widgets, list) { | 2665 | list_for_each_entry(w, &dapm->card->widgets, list) { |
2459 | if (!wsink && !(strcmp(w->name, sink))) { | 2666 | if (!wsink && !(strcmp(w->name, sink))) { |
2460 | wtsink = w; | 2667 | wtsink = w; |
2461 | if (w->dapm == dapm) | 2668 | if (w->dapm == dapm) { |
2462 | wsink = w; | 2669 | wsink = w; |
2670 | if (wsource) | ||
2671 | break; | ||
2672 | } | ||
2463 | continue; | 2673 | continue; |
2464 | } | 2674 | } |
2465 | if (!wsource && !(strcmp(w->name, source))) { | 2675 | if (!wsource && !(strcmp(w->name, source))) { |
2466 | wtsource = w; | 2676 | wtsource = w; |
2467 | if (w->dapm == dapm) | 2677 | if (w->dapm == dapm) { |
2468 | wsource = w; | 2678 | wsource = w; |
2679 | if (wsink) | ||
2680 | break; | ||
2681 | } | ||
2469 | } | 2682 | } |
2470 | } | 2683 | } |
2471 | /* use widget from another DAPM context if not found from this */ | 2684 | /* use widget from another DAPM context if not found from this */ |
@@ -2485,6 +2698,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2485 | return -ENODEV; | 2698 | return -ENODEV; |
2486 | } | 2699 | } |
2487 | 2700 | ||
2701 | skip_search: | ||
2702 | dapm_wcache_update(&dapm->path_sink_cache, wsink); | ||
2703 | dapm_wcache_update(&dapm->path_source_cache, wsource); | ||
2704 | |||
2488 | ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control, | 2705 | ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control, |
2489 | route->connected); | 2706 | route->connected); |
2490 | if (ret) | 2707 | if (ret) |
@@ -2736,6 +2953,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
2736 | dapm_new_mixer(w); | 2953 | dapm_new_mixer(w); |
2737 | break; | 2954 | break; |
2738 | case snd_soc_dapm_mux: | 2955 | case snd_soc_dapm_mux: |
2956 | case snd_soc_dapm_demux: | ||
2739 | dapm_new_mux(w); | 2957 | dapm_new_mux(w); |
2740 | break; | 2958 | break; |
2741 | case snd_soc_dapm_pga: | 2959 | case snd_soc_dapm_pga: |
@@ -2902,16 +3120,21 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2902 | struct snd_ctl_elem_value *ucontrol) | 3120 | struct snd_ctl_elem_value *ucontrol) |
2903 | { | 3121 | { |
2904 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); | 3122 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
3123 | struct snd_soc_card *card = dapm->card; | ||
2905 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 3124 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2906 | unsigned int reg_val, val; | 3125 | unsigned int reg_val, val; |
2907 | 3126 | ||
2908 | if (e->reg != SND_SOC_NOPM) { | 3127 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
3128 | if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) { | ||
2909 | int ret = soc_dapm_read(dapm, e->reg, ®_val); | 3129 | int ret = soc_dapm_read(dapm, e->reg, ®_val); |
2910 | if (ret) | 3130 | if (ret) { |
3131 | mutex_unlock(&card->dapm_mutex); | ||
2911 | return ret; | 3132 | return ret; |
3133 | } | ||
2912 | } else { | 3134 | } else { |
2913 | reg_val = dapm_kcontrol_get_value(kcontrol); | 3135 | reg_val = dapm_kcontrol_get_value(kcontrol); |
2914 | } | 3136 | } |
3137 | mutex_unlock(&card->dapm_mutex); | ||
2915 | 3138 | ||
2916 | val = (reg_val >> e->shift_l) & e->mask; | 3139 | val = (reg_val >> e->shift_l) & e->mask; |
2917 | ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); | 3140 | ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); |
@@ -2941,7 +3164,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2941 | struct snd_soc_card *card = dapm->card; | 3164 | struct snd_soc_card *card = dapm->card; |
2942 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 3165 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2943 | unsigned int *item = ucontrol->value.enumerated.item; | 3166 | unsigned int *item = ucontrol->value.enumerated.item; |
2944 | unsigned int val, change; | 3167 | unsigned int val, change, reg_change = 0; |
2945 | unsigned int mask; | 3168 | unsigned int mask; |
2946 | struct snd_soc_dapm_update update; | 3169 | struct snd_soc_dapm_update update; |
2947 | int ret = 0; | 3170 | int ret = 0; |
@@ -2960,19 +3183,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2960 | 3183 | ||
2961 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 3184 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2962 | 3185 | ||
3186 | change = dapm_kcontrol_set_value(kcontrol, val); | ||
3187 | |||
2963 | if (e->reg != SND_SOC_NOPM) | 3188 | if (e->reg != SND_SOC_NOPM) |
2964 | change = soc_dapm_test_bits(dapm, e->reg, mask, val); | 3189 | reg_change = soc_dapm_test_bits(dapm, e->reg, mask, val); |
2965 | else | ||
2966 | change = dapm_kcontrol_set_value(kcontrol, val); | ||
2967 | 3190 | ||
2968 | if (change) { | 3191 | if (change || reg_change) { |
2969 | if (e->reg != SND_SOC_NOPM) { | 3192 | if (reg_change) { |
2970 | update.kcontrol = kcontrol; | 3193 | update.kcontrol = kcontrol; |
2971 | update.reg = e->reg; | 3194 | update.reg = e->reg; |
2972 | update.mask = mask; | 3195 | update.mask = mask; |
2973 | update.val = val; | 3196 | update.val = val; |
2974 | card->update = &update; | 3197 | card->update = &update; |
2975 | } | 3198 | } |
3199 | change |= reg_change; | ||
2976 | 3200 | ||
2977 | ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); | 3201 | ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); |
2978 | 3202 | ||
@@ -3053,8 +3277,25 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | |||
3053 | } | 3277 | } |
3054 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | 3278 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); |
3055 | 3279 | ||
3056 | static struct snd_soc_dapm_widget * | 3280 | struct snd_soc_dapm_widget * |
3057 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | 3281 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, |
3282 | const struct snd_soc_dapm_widget *widget) | ||
3283 | { | ||
3284 | struct snd_soc_dapm_widget *w; | ||
3285 | |||
3286 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3287 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | ||
3288 | if (!w) | ||
3289 | dev_err(dapm->dev, | ||
3290 | "ASoC: Failed to create DAPM control %s\n", | ||
3291 | widget->name); | ||
3292 | |||
3293 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3294 | return w; | ||
3295 | } | ||
3296 | |||
3297 | struct snd_soc_dapm_widget * | ||
3298 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | ||
3058 | const struct snd_soc_dapm_widget *widget) | 3299 | const struct snd_soc_dapm_widget *widget) |
3059 | { | 3300 | { |
3060 | struct snd_soc_dapm_widget *w; | 3301 | struct snd_soc_dapm_widget *w; |
@@ -3104,7 +3345,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3104 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); | 3345 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); |
3105 | else | 3346 | else |
3106 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); | 3347 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); |
3107 | |||
3108 | if (w->name == NULL) { | 3348 | if (w->name == NULL) { |
3109 | kfree(w); | 3349 | kfree(w); |
3110 | return NULL; | 3350 | return NULL; |
@@ -3136,6 +3376,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3136 | w->power_check = dapm_always_on_check_power; | 3376 | w->power_check = dapm_always_on_check_power; |
3137 | break; | 3377 | break; |
3138 | case snd_soc_dapm_mux: | 3378 | case snd_soc_dapm_mux: |
3379 | case snd_soc_dapm_demux: | ||
3139 | case snd_soc_dapm_switch: | 3380 | case snd_soc_dapm_switch: |
3140 | case snd_soc_dapm_mixer: | 3381 | case snd_soc_dapm_mixer: |
3141 | case snd_soc_dapm_mixer_named_ctl: | 3382 | case snd_soc_dapm_mixer_named_ctl: |
@@ -3169,7 +3410,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3169 | INIT_LIST_HEAD(&w->sinks); | 3410 | INIT_LIST_HEAD(&w->sinks); |
3170 | INIT_LIST_HEAD(&w->list); | 3411 | INIT_LIST_HEAD(&w->list); |
3171 | INIT_LIST_HEAD(&w->dirty); | 3412 | INIT_LIST_HEAD(&w->dirty); |
3172 | list_add(&w->list, &dapm->card->widgets); | 3413 | list_add_tail(&w->list, &dapm->card->widgets); |
3173 | 3414 | ||
3174 | w->inputs = -1; | 3415 | w->inputs = -1; |
3175 | w->outputs = -1; | 3416 | w->outputs = -1; |
@@ -3199,7 +3440,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, | |||
3199 | 3440 | ||
3200 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | 3441 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); |
3201 | for (i = 0; i < num; i++) { | 3442 | for (i = 0; i < num; i++) { |
3202 | w = snd_soc_dapm_new_control(dapm, widget); | 3443 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); |
3203 | if (!w) { | 3444 | if (!w) { |
3204 | dev_err(dapm->dev, | 3445 | dev_err(dapm->dev, |
3205 | "ASoC: Failed to create DAPM control %s\n", | 3446 | "ASoC: Failed to create DAPM control %s\n", |
@@ -3437,7 +3678,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3437 | 3678 | ||
3438 | dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); | 3679 | dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); |
3439 | 3680 | ||
3440 | w = snd_soc_dapm_new_control(&card->dapm, &template); | 3681 | w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); |
3441 | if (!w) { | 3682 | if (!w) { |
3442 | dev_err(card->dev, "ASoC: Failed to create %s widget\n", | 3683 | dev_err(card->dev, "ASoC: Failed to create %s widget\n", |
3443 | link_name); | 3684 | link_name); |
@@ -3488,7 +3729,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
3488 | dev_dbg(dai->dev, "ASoC: adding %s widget\n", | 3729 | dev_dbg(dai->dev, "ASoC: adding %s widget\n", |
3489 | template.name); | 3730 | template.name); |
3490 | 3731 | ||
3491 | w = snd_soc_dapm_new_control(dapm, &template); | 3732 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
3492 | if (!w) { | 3733 | if (!w) { |
3493 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | 3734 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", |
3494 | dai->driver->playback.stream_name); | 3735 | dai->driver->playback.stream_name); |
@@ -3507,7 +3748,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
3507 | dev_dbg(dai->dev, "ASoC: adding %s widget\n", | 3748 | dev_dbg(dai->dev, "ASoC: adding %s widget\n", |
3508 | template.name); | 3749 | template.name); |
3509 | 3750 | ||
3510 | w = snd_soc_dapm_new_control(dapm, &template); | 3751 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
3511 | if (!w) { | 3752 | if (!w) { |
3512 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | 3753 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", |
3513 | dai->driver->capture.stream_name); | 3754 | dai->driver->capture.stream_name); |
@@ -3552,7 +3793,7 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
3552 | break; | 3793 | break; |
3553 | } | 3794 | } |
3554 | 3795 | ||
3555 | if (!w->sname || !strstr(w->sname, dai_w->name)) | 3796 | if (!w->sname || !strstr(w->sname, dai_w->sname)) |
3556 | continue; | 3797 | continue; |
3557 | 3798 | ||
3558 | if (dai_w->id == snd_soc_dapm_dai_in) { | 3799 | if (dai_w->id == snd_soc_dapm_dai_in) { |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index c9917ca5de1a..6fd1906af387 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -24,6 +24,12 @@ | |||
24 | 24 | ||
25 | #include <sound/dmaengine_pcm.h> | 25 | #include <sound/dmaengine_pcm.h> |
26 | 26 | ||
27 | /* | ||
28 | * The platforms dmaengine driver does not support reporting the amount of | ||
29 | * bytes that are still left to transfer. | ||
30 | */ | ||
31 | #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31) | ||
32 | |||
27 | struct dmaengine_pcm { | 33 | struct dmaengine_pcm { |
28 | struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; | 34 | struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; |
29 | const struct snd_dmaengine_pcm_config *config; | 35 | const struct snd_dmaengine_pcm_config *config; |
@@ -222,14 +228,18 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( | |||
222 | return snd_dmaengine_pcm_request_channel(fn, dma_data->filter_data); | 228 | return snd_dmaengine_pcm_request_channel(fn, dma_data->filter_data); |
223 | } | 229 | } |
224 | 230 | ||
225 | static bool dmaengine_pcm_can_report_residue(struct dma_chan *chan) | 231 | static bool dmaengine_pcm_can_report_residue(struct device *dev, |
232 | struct dma_chan *chan) | ||
226 | { | 233 | { |
227 | struct dma_slave_caps dma_caps; | 234 | struct dma_slave_caps dma_caps; |
228 | int ret; | 235 | int ret; |
229 | 236 | ||
230 | ret = dma_get_slave_caps(chan, &dma_caps); | 237 | ret = dma_get_slave_caps(chan, &dma_caps); |
231 | if (ret != 0) | 238 | if (ret != 0) { |
232 | return true; | 239 | dev_warn(dev, "Failed to get DMA channel capabilities, falling back to period counting: %d\n", |
240 | ret); | ||
241 | return false; | ||
242 | } | ||
233 | 243 | ||
234 | if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) | 244 | if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) |
235 | return false; | 245 | return false; |
@@ -289,14 +299,7 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
289 | if (ret) | 299 | if (ret) |
290 | return ret; | 300 | return ret; |
291 | 301 | ||
292 | /* | 302 | if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i])) |
293 | * This will only return false if we know for sure that at least | ||
294 | * one channel does not support residue reporting. If the DMA | ||
295 | * driver does not implement the slave_caps API we rely having | ||
296 | * the NO_RESIDUE flag set manually in case residue reporting is | ||
297 | * not supported. | ||
298 | */ | ||
299 | if (!dmaengine_pcm_can_report_residue(pcm->chan[i])) | ||
300 | pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; | 303 | pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; |
301 | } | 304 | } |
302 | 305 | ||
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 9f60c25c4568..fbaa1bb41102 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -48,7 +48,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, | |||
48 | INIT_LIST_HEAD(&jack->jack_zones); | 48 | INIT_LIST_HEAD(&jack->jack_zones); |
49 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | 49 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); |
50 | 50 | ||
51 | ret = snd_jack_new(card->snd_card, id, type, &jack->jack); | 51 | ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); |
52 | if (ret) | 52 | if (ret) |
53 | return ret; | 53 | return ret; |
54 | 54 | ||
@@ -197,6 +197,7 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, | |||
197 | 197 | ||
198 | INIT_LIST_HEAD(&pins[i].list); | 198 | INIT_LIST_HEAD(&pins[i].list); |
199 | list_add(&(pins[i].list), &jack->pins); | 199 | list_add(&(pins[i].list), &jack->pins); |
200 | snd_jack_add_new_kctl(jack->jack, pins[i].pin, pins[i].mask); | ||
200 | } | 201 | } |
201 | 202 | ||
202 | /* Update to reflect the last reported status; canned jack | 203 | /* Update to reflect the last reported status; canned jack |
@@ -315,8 +316,11 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
315 | goto undo; | 316 | goto undo; |
316 | } | 317 | } |
317 | 318 | ||
318 | if (gpios[i].gpiod_dev) { | 319 | if (gpios[i].desc) { |
319 | /* GPIO descriptor */ | 320 | /* Already have a GPIO descriptor. */ |
321 | goto got_gpio; | ||
322 | } else if (gpios[i].gpiod_dev) { | ||
323 | /* Get a GPIO descriptor */ | ||
320 | gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev, | 324 | gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev, |
321 | gpios[i].name, | 325 | gpios[i].name, |
322 | gpios[i].idx, GPIOD_IN); | 326 | gpios[i].idx, GPIOD_IN); |
@@ -344,7 +348,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
344 | 348 | ||
345 | gpios[i].desc = gpio_to_desc(gpios[i].gpio); | 349 | gpios[i].desc = gpio_to_desc(gpios[i].gpio); |
346 | } | 350 | } |
347 | 351 | got_gpio: | |
348 | INIT_DELAYED_WORK(&gpios[i].work, gpio_work); | 352 | INIT_DELAYED_WORK(&gpios[i].work, gpio_work); |
349 | gpios[i].jack = jack; | 353 | gpios[i].jack = jack; |
350 | 354 | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 35fe58f4fa86..256b9c91aa94 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -1485,30 +1485,67 @@ unwind: | |||
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | 1487 | static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, |
1488 | struct snd_soc_pcm_stream *stream) | 1488 | struct snd_soc_pcm_stream *stream, |
1489 | u64 formats) | ||
1489 | { | 1490 | { |
1490 | runtime->hw.rate_min = stream->rate_min; | 1491 | runtime->hw.rate_min = stream->rate_min; |
1491 | runtime->hw.rate_max = stream->rate_max; | 1492 | runtime->hw.rate_max = stream->rate_max; |
1492 | runtime->hw.channels_min = stream->channels_min; | 1493 | runtime->hw.channels_min = stream->channels_min; |
1493 | runtime->hw.channels_max = stream->channels_max; | 1494 | runtime->hw.channels_max = stream->channels_max; |
1494 | if (runtime->hw.formats) | 1495 | if (runtime->hw.formats) |
1495 | runtime->hw.formats &= stream->formats; | 1496 | runtime->hw.formats &= formats & stream->formats; |
1496 | else | 1497 | else |
1497 | runtime->hw.formats = stream->formats; | 1498 | runtime->hw.formats = formats & stream->formats; |
1498 | runtime->hw.rates = stream->rates; | 1499 | runtime->hw.rates = stream->rates; |
1499 | } | 1500 | } |
1500 | 1501 | ||
1502 | static u64 dpcm_runtime_base_format(struct snd_pcm_substream *substream) | ||
1503 | { | ||
1504 | struct snd_soc_pcm_runtime *fe = substream->private_data; | ||
1505 | struct snd_soc_dpcm *dpcm; | ||
1506 | u64 formats = ULLONG_MAX; | ||
1507 | int stream = substream->stream; | ||
1508 | |||
1509 | if (!fe->dai_link->dpcm_merged_format) | ||
1510 | return formats; | ||
1511 | |||
1512 | /* | ||
1513 | * It returns merged BE codec format | ||
1514 | * if FE want to use it (= dpcm_merged_format) | ||
1515 | */ | ||
1516 | |||
1517 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | ||
1518 | struct snd_soc_pcm_runtime *be = dpcm->be; | ||
1519 | struct snd_soc_dai_driver *codec_dai_drv; | ||
1520 | struct snd_soc_pcm_stream *codec_stream; | ||
1521 | int i; | ||
1522 | |||
1523 | for (i = 0; i < be->num_codecs; i++) { | ||
1524 | codec_dai_drv = be->codec_dais[i]->driver; | ||
1525 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1526 | codec_stream = &codec_dai_drv->playback; | ||
1527 | else | ||
1528 | codec_stream = &codec_dai_drv->capture; | ||
1529 | |||
1530 | formats &= codec_stream->formats; | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | return formats; | ||
1535 | } | ||
1536 | |||
1501 | static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) | 1537 | static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) |
1502 | { | 1538 | { |
1503 | struct snd_pcm_runtime *runtime = substream->runtime; | 1539 | struct snd_pcm_runtime *runtime = substream->runtime; |
1504 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1540 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1505 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1541 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1506 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | 1542 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; |
1543 | u64 format = dpcm_runtime_base_format(substream); | ||
1507 | 1544 | ||
1508 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1545 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1509 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); | 1546 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback, format); |
1510 | else | 1547 | else |
1511 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); | 1548 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture, format); |
1512 | } | 1549 | } |
1513 | 1550 | ||
1514 | static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); | 1551 | static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c new file mode 100644 index 000000000000..d0960683c409 --- /dev/null +++ b/sound/soc/soc-topology.c | |||
@@ -0,0 +1,1826 @@ | |||
1 | /* | ||
2 | * soc-topology.c -- ALSA SoC Topology | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments Inc. | ||
5 | * Copyright (C) 2015 Intel Corporation. | ||
6 | * | ||
7 | * Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> | ||
8 | * K, Mythri P <mythri.p.k@intel.com> | ||
9 | * Prusty, Subhransu S <subhransu.s.prusty@intel.com> | ||
10 | * B, Jayachandran <jayachandran.b@intel.com> | ||
11 | * Abdullah, Omair M <omair.m.abdullah@intel.com> | ||
12 | * Jin, Yao <yao.jin@intel.com> | ||
13 | * Lin, Mengdong <mengdong.lin@intel.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * Add support to read audio firmware topology alongside firmware text. The | ||
21 | * topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links, | ||
22 | * equalizers, firmware, coefficients etc. | ||
23 | * | ||
24 | * This file only manages the core ALSA and ASoC components, all other bespoke | ||
25 | * firmware topology data is passed to component drivers for bespoke handling. | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/export.h> | ||
30 | #include <linux/list.h> | ||
31 | #include <linux/firmware.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/soc-topology.h> | ||
36 | |||
37 | /* | ||
38 | * We make several passes over the data (since it wont necessarily be ordered) | ||
39 | * and process objects in the following order. This guarantees the component | ||
40 | * drivers will be ready with any vendor data before the mixers and DAPM objects | ||
41 | * are loaded (that may make use of the vendor data). | ||
42 | */ | ||
43 | #define SOC_TPLG_PASS_MANIFEST 0 | ||
44 | #define SOC_TPLG_PASS_VENDOR 1 | ||
45 | #define SOC_TPLG_PASS_MIXER 2 | ||
46 | #define SOC_TPLG_PASS_WIDGET 3 | ||
47 | #define SOC_TPLG_PASS_GRAPH 4 | ||
48 | #define SOC_TPLG_PASS_PINS 5 | ||
49 | #define SOC_TPLG_PASS_PCM_DAI 6 | ||
50 | |||
51 | #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST | ||
52 | #define SOC_TPLG_PASS_END SOC_TPLG_PASS_PCM_DAI | ||
53 | |||
54 | struct soc_tplg { | ||
55 | const struct firmware *fw; | ||
56 | |||
57 | /* runtime FW parsing */ | ||
58 | const u8 *pos; /* read postion */ | ||
59 | const u8 *hdr_pos; /* header position */ | ||
60 | unsigned int pass; /* pass number */ | ||
61 | |||
62 | /* component caller */ | ||
63 | struct device *dev; | ||
64 | struct snd_soc_component *comp; | ||
65 | u32 index; /* current block index */ | ||
66 | u32 req_index; /* required index, only loaded/free matching blocks */ | ||
67 | |||
68 | /* kcontrol operations */ | ||
69 | const struct snd_soc_tplg_kcontrol_ops *io_ops; | ||
70 | int io_ops_count; | ||
71 | |||
72 | /* optional fw loading callbacks to component drivers */ | ||
73 | struct snd_soc_tplg_ops *ops; | ||
74 | }; | ||
75 | |||
76 | static int soc_tplg_process_headers(struct soc_tplg *tplg); | ||
77 | static void soc_tplg_complete(struct soc_tplg *tplg); | ||
78 | struct snd_soc_dapm_widget * | ||
79 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | ||
80 | const struct snd_soc_dapm_widget *widget); | ||
81 | struct snd_soc_dapm_widget * | ||
82 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | ||
83 | const struct snd_soc_dapm_widget *widget); | ||
84 | |||
85 | /* check we dont overflow the data for this control chunk */ | ||
86 | static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size, | ||
87 | unsigned int count, size_t bytes, const char *elem_type) | ||
88 | { | ||
89 | const u8 *end = tplg->pos + elem_size * count; | ||
90 | |||
91 | if (end > tplg->fw->data + tplg->fw->size) { | ||
92 | dev_err(tplg->dev, "ASoC: %s overflow end of data\n", | ||
93 | elem_type); | ||
94 | return -EINVAL; | ||
95 | } | ||
96 | |||
97 | /* check there is enough room in chunk for control. | ||
98 | extra bytes at the end of control are for vendor data here */ | ||
99 | if (elem_size * count > bytes) { | ||
100 | dev_err(tplg->dev, | ||
101 | "ASoC: %s count %d of size %zu is bigger than chunk %zu\n", | ||
102 | elem_type, count, elem_size, bytes); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline int soc_tplg_is_eof(struct soc_tplg *tplg) | ||
110 | { | ||
111 | const u8 *end = tplg->hdr_pos; | ||
112 | |||
113 | if (end >= tplg->fw->data + tplg->fw->size) | ||
114 | return 1; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg *tplg) | ||
119 | { | ||
120 | return (unsigned long)(tplg->hdr_pos - tplg->fw->data); | ||
121 | } | ||
122 | |||
123 | static inline unsigned long soc_tplg_get_offset(struct soc_tplg *tplg) | ||
124 | { | ||
125 | return (unsigned long)(tplg->pos - tplg->fw->data); | ||
126 | } | ||
127 | |||
128 | /* mapping of Kcontrol types and associated operations. */ | ||
129 | static const struct snd_soc_tplg_kcontrol_ops io_ops[] = { | ||
130 | {SND_SOC_TPLG_CTL_VOLSW, snd_soc_get_volsw, | ||
131 | snd_soc_put_volsw, snd_soc_info_volsw}, | ||
132 | {SND_SOC_TPLG_CTL_VOLSW_SX, snd_soc_get_volsw_sx, | ||
133 | snd_soc_put_volsw_sx, NULL}, | ||
134 | {SND_SOC_TPLG_CTL_ENUM, snd_soc_get_enum_double, | ||
135 | snd_soc_put_enum_double, snd_soc_info_enum_double}, | ||
136 | {SND_SOC_TPLG_CTL_ENUM_VALUE, snd_soc_get_enum_double, | ||
137 | snd_soc_put_enum_double, NULL}, | ||
138 | {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get, | ||
139 | snd_soc_bytes_put, snd_soc_bytes_info}, | ||
140 | {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range, | ||
141 | snd_soc_put_volsw_range, snd_soc_info_volsw_range}, | ||
142 | {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx, | ||
143 | snd_soc_put_xr_sx, snd_soc_info_xr_sx}, | ||
144 | {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe, | ||
145 | snd_soc_put_strobe, NULL}, | ||
146 | {SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw, | ||
147 | snd_soc_dapm_put_volsw, NULL}, | ||
148 | {SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double, | ||
149 | snd_soc_dapm_put_enum_double, snd_soc_info_enum_double}, | ||
150 | {SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double, | ||
151 | snd_soc_dapm_put_enum_double, NULL}, | ||
152 | {SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE, snd_soc_dapm_get_enum_double, | ||
153 | snd_soc_dapm_put_enum_double, NULL}, | ||
154 | {SND_SOC_TPLG_DAPM_CTL_PIN, snd_soc_dapm_get_pin_switch, | ||
155 | snd_soc_dapm_put_pin_switch, snd_soc_dapm_info_pin_switch}, | ||
156 | }; | ||
157 | |||
158 | struct soc_tplg_map { | ||
159 | int uid; | ||
160 | int kid; | ||
161 | }; | ||
162 | |||
163 | /* mapping of widget types from UAPI IDs to kernel IDs */ | ||
164 | static const struct soc_tplg_map dapm_map[] = { | ||
165 | {SND_SOC_TPLG_DAPM_INPUT, snd_soc_dapm_input}, | ||
166 | {SND_SOC_TPLG_DAPM_OUTPUT, snd_soc_dapm_output}, | ||
167 | {SND_SOC_TPLG_DAPM_MUX, snd_soc_dapm_mux}, | ||
168 | {SND_SOC_TPLG_DAPM_MIXER, snd_soc_dapm_mixer}, | ||
169 | {SND_SOC_TPLG_DAPM_PGA, snd_soc_dapm_pga}, | ||
170 | {SND_SOC_TPLG_DAPM_OUT_DRV, snd_soc_dapm_out_drv}, | ||
171 | {SND_SOC_TPLG_DAPM_ADC, snd_soc_dapm_adc}, | ||
172 | {SND_SOC_TPLG_DAPM_DAC, snd_soc_dapm_dac}, | ||
173 | {SND_SOC_TPLG_DAPM_SWITCH, snd_soc_dapm_switch}, | ||
174 | {SND_SOC_TPLG_DAPM_PRE, snd_soc_dapm_pre}, | ||
175 | {SND_SOC_TPLG_DAPM_POST, snd_soc_dapm_post}, | ||
176 | {SND_SOC_TPLG_DAPM_AIF_IN, snd_soc_dapm_aif_in}, | ||
177 | {SND_SOC_TPLG_DAPM_AIF_OUT, snd_soc_dapm_aif_out}, | ||
178 | {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in}, | ||
179 | {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out}, | ||
180 | {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link}, | ||
181 | }; | ||
182 | |||
183 | static int tplc_chan_get_reg(struct soc_tplg *tplg, | ||
184 | struct snd_soc_tplg_channel *chan, int map) | ||
185 | { | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) { | ||
189 | if (chan[i].id == map) | ||
190 | return chan[i].reg; | ||
191 | } | ||
192 | |||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | static int tplc_chan_get_shift(struct soc_tplg *tplg, | ||
197 | struct snd_soc_tplg_channel *chan, int map) | ||
198 | { | ||
199 | int i; | ||
200 | |||
201 | for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) { | ||
202 | if (chan[i].id == map) | ||
203 | return chan[i].shift; | ||
204 | } | ||
205 | |||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | static int get_widget_id(int tplg_type) | ||
210 | { | ||
211 | int i; | ||
212 | |||
213 | for (i = 0; i < ARRAY_SIZE(dapm_map); i++) { | ||
214 | if (tplg_type == dapm_map[i].uid) | ||
215 | return dapm_map[i].kid; | ||
216 | } | ||
217 | |||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | static enum snd_soc_dobj_type get_dobj_mixer_type( | ||
222 | struct snd_soc_tplg_ctl_hdr *control_hdr) | ||
223 | { | ||
224 | if (control_hdr == NULL) | ||
225 | return SND_SOC_DOBJ_NONE; | ||
226 | |||
227 | switch (control_hdr->ops.info) { | ||
228 | case SND_SOC_TPLG_CTL_VOLSW: | ||
229 | case SND_SOC_TPLG_CTL_VOLSW_SX: | ||
230 | case SND_SOC_TPLG_CTL_VOLSW_XR_SX: | ||
231 | case SND_SOC_TPLG_CTL_RANGE: | ||
232 | case SND_SOC_TPLG_CTL_STROBE: | ||
233 | return SND_SOC_DOBJ_MIXER; | ||
234 | case SND_SOC_TPLG_CTL_ENUM: | ||
235 | case SND_SOC_TPLG_CTL_ENUM_VALUE: | ||
236 | return SND_SOC_DOBJ_ENUM; | ||
237 | case SND_SOC_TPLG_CTL_BYTES: | ||
238 | return SND_SOC_DOBJ_BYTES; | ||
239 | default: | ||
240 | return SND_SOC_DOBJ_NONE; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | static enum snd_soc_dobj_type get_dobj_type(struct snd_soc_tplg_hdr *hdr, | ||
245 | struct snd_soc_tplg_ctl_hdr *control_hdr) | ||
246 | { | ||
247 | switch (hdr->type) { | ||
248 | case SND_SOC_TPLG_TYPE_MIXER: | ||
249 | return get_dobj_mixer_type(control_hdr); | ||
250 | case SND_SOC_TPLG_TYPE_DAPM_GRAPH: | ||
251 | case SND_SOC_TPLG_TYPE_MANIFEST: | ||
252 | return SND_SOC_DOBJ_NONE; | ||
253 | case SND_SOC_TPLG_TYPE_DAPM_WIDGET: | ||
254 | return SND_SOC_DOBJ_WIDGET; | ||
255 | case SND_SOC_TPLG_TYPE_DAI_LINK: | ||
256 | return SND_SOC_DOBJ_DAI_LINK; | ||
257 | case SND_SOC_TPLG_TYPE_PCM: | ||
258 | return SND_SOC_DOBJ_PCM; | ||
259 | case SND_SOC_TPLG_TYPE_CODEC_LINK: | ||
260 | return SND_SOC_DOBJ_CODEC_LINK; | ||
261 | default: | ||
262 | return SND_SOC_DOBJ_NONE; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static inline void soc_bind_err(struct soc_tplg *tplg, | ||
267 | struct snd_soc_tplg_ctl_hdr *hdr, int index) | ||
268 | { | ||
269 | dev_err(tplg->dev, | ||
270 | "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n", | ||
271 | hdr->ops.get, hdr->ops.put, hdr->ops.info, index, | ||
272 | soc_tplg_get_offset(tplg)); | ||
273 | } | ||
274 | |||
275 | static inline void soc_control_err(struct soc_tplg *tplg, | ||
276 | struct snd_soc_tplg_ctl_hdr *hdr, const char *name) | ||
277 | { | ||
278 | dev_err(tplg->dev, | ||
279 | "ASoC: no complete mixer IO handler for %s type (g,p,i) %d:%d:%d at 0x%lx\n", | ||
280 | name, hdr->ops.get, hdr->ops.put, hdr->ops.info, | ||
281 | soc_tplg_get_offset(tplg)); | ||
282 | } | ||
283 | |||
284 | /* pass vendor data to component driver for processing */ | ||
285 | static int soc_tplg_vendor_load_(struct soc_tplg *tplg, | ||
286 | struct snd_soc_tplg_hdr *hdr) | ||
287 | { | ||
288 | int ret = 0; | ||
289 | |||
290 | if (tplg->comp && tplg->ops && tplg->ops->vendor_load) | ||
291 | ret = tplg->ops->vendor_load(tplg->comp, hdr); | ||
292 | else { | ||
293 | dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", | ||
294 | hdr->vendor_type); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | if (ret < 0) | ||
299 | dev_err(tplg->dev, | ||
300 | "ASoC: vendor load failed at hdr offset %ld/0x%lx for type %d:%d\n", | ||
301 | soc_tplg_get_hdr_offset(tplg), | ||
302 | soc_tplg_get_hdr_offset(tplg), | ||
303 | hdr->type, hdr->vendor_type); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | /* pass vendor data to component driver for processing */ | ||
308 | static int soc_tplg_vendor_load(struct soc_tplg *tplg, | ||
309 | struct snd_soc_tplg_hdr *hdr) | ||
310 | { | ||
311 | if (tplg->pass != SOC_TPLG_PASS_VENDOR) | ||
312 | return 0; | ||
313 | |||
314 | return soc_tplg_vendor_load_(tplg, hdr); | ||
315 | } | ||
316 | |||
317 | /* optionally pass new dynamic widget to component driver. This is mainly for | ||
318 | * external widgets where we can assign private data/ops */ | ||
319 | static int soc_tplg_widget_load(struct soc_tplg *tplg, | ||
320 | struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w) | ||
321 | { | ||
322 | if (tplg->comp && tplg->ops && tplg->ops->widget_load) | ||
323 | return tplg->ops->widget_load(tplg->comp, w, tplg_w); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /* pass dynamic FEs configurations to component driver */ | ||
329 | static int soc_tplg_pcm_dai_load(struct soc_tplg *tplg, | ||
330 | struct snd_soc_tplg_pcm_dai *pcm_dai, int num_pcm_dai) | ||
331 | { | ||
332 | if (tplg->comp && tplg->ops && tplg->ops->pcm_dai_load) | ||
333 | return tplg->ops->pcm_dai_load(tplg->comp, pcm_dai, num_pcm_dai); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /* tell the component driver that all firmware has been loaded in this request */ | ||
339 | static void soc_tplg_complete(struct soc_tplg *tplg) | ||
340 | { | ||
341 | if (tplg->comp && tplg->ops && tplg->ops->complete) | ||
342 | tplg->ops->complete(tplg->comp); | ||
343 | } | ||
344 | |||
345 | /* add a dynamic kcontrol */ | ||
346 | static int soc_tplg_add_dcontrol(struct snd_card *card, struct device *dev, | ||
347 | const struct snd_kcontrol_new *control_new, const char *prefix, | ||
348 | void *data, struct snd_kcontrol **kcontrol) | ||
349 | { | ||
350 | int err; | ||
351 | |||
352 | *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix); | ||
353 | if (*kcontrol == NULL) { | ||
354 | dev_err(dev, "ASoC: Failed to create new kcontrol %s\n", | ||
355 | control_new->name); | ||
356 | return -ENOMEM; | ||
357 | } | ||
358 | |||
359 | err = snd_ctl_add(card, *kcontrol); | ||
360 | if (err < 0) { | ||
361 | dev_err(dev, "ASoC: Failed to add %s: %d\n", | ||
362 | control_new->name, err); | ||
363 | return err; | ||
364 | } | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* add a dynamic kcontrol for component driver */ | ||
370 | static int soc_tplg_add_kcontrol(struct soc_tplg *tplg, | ||
371 | struct snd_kcontrol_new *k, struct snd_kcontrol **kcontrol) | ||
372 | { | ||
373 | struct snd_soc_component *comp = tplg->comp; | ||
374 | |||
375 | return soc_tplg_add_dcontrol(comp->card->snd_card, | ||
376 | comp->dev, k, NULL, comp, kcontrol); | ||
377 | } | ||
378 | |||
379 | /* remove a mixer kcontrol */ | ||
380 | static void remove_mixer(struct snd_soc_component *comp, | ||
381 | struct snd_soc_dobj *dobj, int pass) | ||
382 | { | ||
383 | struct snd_card *card = comp->card->snd_card; | ||
384 | struct soc_mixer_control *sm = | ||
385 | container_of(dobj, struct soc_mixer_control, dobj); | ||
386 | const unsigned int *p = NULL; | ||
387 | |||
388 | if (pass != SOC_TPLG_PASS_MIXER) | ||
389 | return; | ||
390 | |||
391 | if (dobj->ops && dobj->ops->control_unload) | ||
392 | dobj->ops->control_unload(comp, dobj); | ||
393 | |||
394 | if (sm->dobj.control.kcontrol->tlv.p) | ||
395 | p = sm->dobj.control.kcontrol->tlv.p; | ||
396 | snd_ctl_remove(card, sm->dobj.control.kcontrol); | ||
397 | list_del(&sm->dobj.list); | ||
398 | kfree(sm); | ||
399 | kfree(p); | ||
400 | } | ||
401 | |||
402 | /* remove an enum kcontrol */ | ||
403 | static void remove_enum(struct snd_soc_component *comp, | ||
404 | struct snd_soc_dobj *dobj, int pass) | ||
405 | { | ||
406 | struct snd_card *card = comp->card->snd_card; | ||
407 | struct soc_enum *se = container_of(dobj, struct soc_enum, dobj); | ||
408 | int i; | ||
409 | |||
410 | if (pass != SOC_TPLG_PASS_MIXER) | ||
411 | return; | ||
412 | |||
413 | if (dobj->ops && dobj->ops->control_unload) | ||
414 | dobj->ops->control_unload(comp, dobj); | ||
415 | |||
416 | snd_ctl_remove(card, se->dobj.control.kcontrol); | ||
417 | list_del(&se->dobj.list); | ||
418 | |||
419 | kfree(se->dobj.control.dvalues); | ||
420 | for (i = 0; i < se->items; i++) | ||
421 | kfree(se->dobj.control.dtexts[i]); | ||
422 | kfree(se); | ||
423 | } | ||
424 | |||
425 | /* remove a byte kcontrol */ | ||
426 | static void remove_bytes(struct snd_soc_component *comp, | ||
427 | struct snd_soc_dobj *dobj, int pass) | ||
428 | { | ||
429 | struct snd_card *card = comp->card->snd_card; | ||
430 | struct soc_bytes_ext *sb = | ||
431 | container_of(dobj, struct soc_bytes_ext, dobj); | ||
432 | |||
433 | if (pass != SOC_TPLG_PASS_MIXER) | ||
434 | return; | ||
435 | |||
436 | if (dobj->ops && dobj->ops->control_unload) | ||
437 | dobj->ops->control_unload(comp, dobj); | ||
438 | |||
439 | snd_ctl_remove(card, sb->dobj.control.kcontrol); | ||
440 | list_del(&sb->dobj.list); | ||
441 | kfree(sb); | ||
442 | } | ||
443 | |||
444 | /* remove a widget and it's kcontrols - routes must be removed first */ | ||
445 | static void remove_widget(struct snd_soc_component *comp, | ||
446 | struct snd_soc_dobj *dobj, int pass) | ||
447 | { | ||
448 | struct snd_card *card = comp->card->snd_card; | ||
449 | struct snd_soc_dapm_widget *w = | ||
450 | container_of(dobj, struct snd_soc_dapm_widget, dobj); | ||
451 | int i; | ||
452 | |||
453 | if (pass != SOC_TPLG_PASS_WIDGET) | ||
454 | return; | ||
455 | |||
456 | if (dobj->ops && dobj->ops->widget_unload) | ||
457 | dobj->ops->widget_unload(comp, dobj); | ||
458 | |||
459 | /* | ||
460 | * Dynamic Widgets either have 1 enum kcontrol or 1..N mixers. | ||
461 | * The enum may either have an array of values or strings. | ||
462 | */ | ||
463 | if (dobj->widget.kcontrol_enum) { | ||
464 | /* enumerated widget mixer */ | ||
465 | struct soc_enum *se = | ||
466 | (struct soc_enum *)w->kcontrols[0]->private_value; | ||
467 | |||
468 | snd_ctl_remove(card, w->kcontrols[0]); | ||
469 | |||
470 | kfree(se->dobj.control.dvalues); | ||
471 | for (i = 0; i < se->items; i++) | ||
472 | kfree(se->dobj.control.dtexts[i]); | ||
473 | |||
474 | kfree(se); | ||
475 | kfree(w->kcontrol_news); | ||
476 | } else { | ||
477 | /* non enumerated widget mixer */ | ||
478 | for (i = 0; i < w->num_kcontrols; i++) { | ||
479 | struct snd_kcontrol *kcontrol = w->kcontrols[i]; | ||
480 | struct soc_mixer_control *sm = | ||
481 | (struct soc_mixer_control *) kcontrol->private_value; | ||
482 | |||
483 | kfree(w->kcontrols[i]->tlv.p); | ||
484 | |||
485 | snd_ctl_remove(card, w->kcontrols[i]); | ||
486 | kfree(sm); | ||
487 | } | ||
488 | kfree(w->kcontrol_news); | ||
489 | } | ||
490 | /* widget w is freed by soc-dapm.c */ | ||
491 | } | ||
492 | |||
493 | /* remove PCM DAI configurations */ | ||
494 | static void remove_pcm_dai(struct snd_soc_component *comp, | ||
495 | struct snd_soc_dobj *dobj, int pass) | ||
496 | { | ||
497 | if (pass != SOC_TPLG_PASS_PCM_DAI) | ||
498 | return; | ||
499 | |||
500 | if (dobj->ops && dobj->ops->pcm_dai_unload) | ||
501 | dobj->ops->pcm_dai_unload(comp, dobj); | ||
502 | |||
503 | list_del(&dobj->list); | ||
504 | kfree(dobj); | ||
505 | } | ||
506 | |||
507 | /* bind a kcontrol to it's IO handlers */ | ||
508 | static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, | ||
509 | struct snd_kcontrol_new *k, | ||
510 | const struct snd_soc_tplg_kcontrol_ops *ops, int num_ops, | ||
511 | const struct snd_soc_tplg_kcontrol_ops *bops, int num_bops) | ||
512 | { | ||
513 | int i; | ||
514 | |||
515 | /* try and map standard kcontrols handler first */ | ||
516 | for (i = 0; i < num_ops; i++) { | ||
517 | |||
518 | if (ops[i].id == hdr->ops.put) | ||
519 | k->put = ops[i].put; | ||
520 | if (ops[i].id == hdr->ops.get) | ||
521 | k->get = ops[i].get; | ||
522 | if (ops[i].id == hdr->ops.info) | ||
523 | k->info = ops[i].info; | ||
524 | } | ||
525 | |||
526 | /* standard handlers found ? */ | ||
527 | if (k->put && k->get && k->info) | ||
528 | return 0; | ||
529 | |||
530 | /* none found so try bespoke handlers */ | ||
531 | for (i = 0; i < num_bops; i++) { | ||
532 | |||
533 | if (k->put == NULL && bops[i].id == hdr->ops.put) | ||
534 | k->put = bops[i].put; | ||
535 | if (k->get == NULL && bops[i].id == hdr->ops.get) | ||
536 | k->get = bops[i].get; | ||
537 | if (k->info == NULL && ops[i].id == hdr->ops.info) | ||
538 | k->info = bops[i].info; | ||
539 | } | ||
540 | |||
541 | /* bespoke handlers found ? */ | ||
542 | if (k->put && k->get && k->info) | ||
543 | return 0; | ||
544 | |||
545 | /* nothing to bind */ | ||
546 | return -EINVAL; | ||
547 | } | ||
548 | |||
549 | /* bind a widgets to it's evnt handlers */ | ||
550 | int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, | ||
551 | const struct snd_soc_tplg_widget_events *events, | ||
552 | int num_events, u16 event_type) | ||
553 | { | ||
554 | int i; | ||
555 | |||
556 | w->event = NULL; | ||
557 | |||
558 | for (i = 0; i < num_events; i++) { | ||
559 | if (event_type == events[i].type) { | ||
560 | |||
561 | /* found - so assign event */ | ||
562 | w->event = events[i].event_handler; | ||
563 | return 0; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | /* not found */ | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event); | ||
571 | |||
572 | /* optionally pass new dynamic kcontrol to component driver. */ | ||
573 | static int soc_tplg_init_kcontrol(struct soc_tplg *tplg, | ||
574 | struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr) | ||
575 | { | ||
576 | if (tplg->comp && tplg->ops && tplg->ops->control_load) | ||
577 | return tplg->ops->control_load(tplg->comp, k, hdr); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int soc_tplg_create_tlv(struct soc_tplg *tplg, | ||
583 | struct snd_kcontrol_new *kc, u32 tlv_size) | ||
584 | { | ||
585 | struct snd_soc_tplg_ctl_tlv *tplg_tlv; | ||
586 | struct snd_ctl_tlv *tlv; | ||
587 | |||
588 | if (tlv_size == 0) | ||
589 | return 0; | ||
590 | |||
591 | tplg_tlv = (struct snd_soc_tplg_ctl_tlv *) tplg->pos; | ||
592 | tplg->pos += tlv_size; | ||
593 | |||
594 | tlv = kzalloc(sizeof(*tlv) + tlv_size, GFP_KERNEL); | ||
595 | if (tlv == NULL) | ||
596 | return -ENOMEM; | ||
597 | |||
598 | dev_dbg(tplg->dev, " created TLV type %d size %d bytes\n", | ||
599 | tplg_tlv->numid, tplg_tlv->size); | ||
600 | |||
601 | tlv->numid = tplg_tlv->numid; | ||
602 | tlv->length = tplg_tlv->size; | ||
603 | memcpy(tlv->tlv, tplg_tlv + 1, tplg_tlv->size); | ||
604 | kc->tlv.p = (void *)tlv; | ||
605 | |||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static inline void soc_tplg_free_tlv(struct soc_tplg *tplg, | ||
610 | struct snd_kcontrol_new *kc) | ||
611 | { | ||
612 | kfree(kc->tlv.p); | ||
613 | } | ||
614 | |||
615 | static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, | ||
616 | size_t size) | ||
617 | { | ||
618 | struct snd_soc_tplg_bytes_control *be; | ||
619 | struct soc_bytes_ext *sbe; | ||
620 | struct snd_kcontrol_new kc; | ||
621 | int i, err; | ||
622 | |||
623 | if (soc_tplg_check_elem_count(tplg, | ||
624 | sizeof(struct snd_soc_tplg_bytes_control), count, | ||
625 | size, "mixer bytes")) { | ||
626 | dev_err(tplg->dev, "ASoC: Invalid count %d for byte control\n", | ||
627 | count); | ||
628 | return -EINVAL; | ||
629 | } | ||
630 | |||
631 | for (i = 0; i < count; i++) { | ||
632 | be = (struct snd_soc_tplg_bytes_control *)tplg->pos; | ||
633 | |||
634 | /* validate kcontrol */ | ||
635 | if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
636 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
637 | return -EINVAL; | ||
638 | |||
639 | sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); | ||
640 | if (sbe == NULL) | ||
641 | return -ENOMEM; | ||
642 | |||
643 | tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + | ||
644 | be->priv.size); | ||
645 | |||
646 | dev_dbg(tplg->dev, | ||
647 | "ASoC: adding bytes kcontrol %s with access 0x%x\n", | ||
648 | be->hdr.name, be->hdr.access); | ||
649 | |||
650 | memset(&kc, 0, sizeof(kc)); | ||
651 | kc.name = be->hdr.name; | ||
652 | kc.private_value = (long)sbe; | ||
653 | kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
654 | kc.access = be->hdr.access; | ||
655 | |||
656 | sbe->max = be->max; | ||
657 | sbe->dobj.type = SND_SOC_DOBJ_BYTES; | ||
658 | sbe->dobj.ops = tplg->ops; | ||
659 | INIT_LIST_HEAD(&sbe->dobj.list); | ||
660 | |||
661 | /* map io handlers */ | ||
662 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, io_ops, | ||
663 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
664 | if (err) { | ||
665 | soc_control_err(tplg, &be->hdr, be->hdr.name); | ||
666 | kfree(sbe); | ||
667 | continue; | ||
668 | } | ||
669 | |||
670 | /* pass control to driver for optional further init */ | ||
671 | err = soc_tplg_init_kcontrol(tplg, &kc, | ||
672 | (struct snd_soc_tplg_ctl_hdr *)be); | ||
673 | if (err < 0) { | ||
674 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
675 | be->hdr.name); | ||
676 | kfree(sbe); | ||
677 | continue; | ||
678 | } | ||
679 | |||
680 | /* register control here */ | ||
681 | err = soc_tplg_add_kcontrol(tplg, &kc, | ||
682 | &sbe->dobj.control.kcontrol); | ||
683 | if (err < 0) { | ||
684 | dev_err(tplg->dev, "ASoC: failed to add %s\n", | ||
685 | be->hdr.name); | ||
686 | kfree(sbe); | ||
687 | continue; | ||
688 | } | ||
689 | |||
690 | list_add(&sbe->dobj.list, &tplg->comp->dobj_list); | ||
691 | } | ||
692 | return 0; | ||
693 | |||
694 | } | ||
695 | |||
696 | static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, | ||
697 | size_t size) | ||
698 | { | ||
699 | struct snd_soc_tplg_mixer_control *mc; | ||
700 | struct soc_mixer_control *sm; | ||
701 | struct snd_kcontrol_new kc; | ||
702 | int i, err; | ||
703 | |||
704 | if (soc_tplg_check_elem_count(tplg, | ||
705 | sizeof(struct snd_soc_tplg_mixer_control), | ||
706 | count, size, "mixers")) { | ||
707 | |||
708 | dev_err(tplg->dev, "ASoC: invalid count %d for controls\n", | ||
709 | count); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | for (i = 0; i < count; i++) { | ||
714 | mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; | ||
715 | |||
716 | /* validate kcontrol */ | ||
717 | if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
718 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
719 | return -EINVAL; | ||
720 | |||
721 | sm = kzalloc(sizeof(*sm), GFP_KERNEL); | ||
722 | if (sm == NULL) | ||
723 | return -ENOMEM; | ||
724 | tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + | ||
725 | mc->priv.size); | ||
726 | |||
727 | dev_dbg(tplg->dev, | ||
728 | "ASoC: adding mixer kcontrol %s with access 0x%x\n", | ||
729 | mc->hdr.name, mc->hdr.access); | ||
730 | |||
731 | memset(&kc, 0, sizeof(kc)); | ||
732 | kc.name = mc->hdr.name; | ||
733 | kc.private_value = (long)sm; | ||
734 | kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
735 | kc.access = mc->hdr.access; | ||
736 | |||
737 | /* we only support FL/FR channel mapping atm */ | ||
738 | sm->reg = tplc_chan_get_reg(tplg, mc->channel, | ||
739 | SNDRV_CHMAP_FL); | ||
740 | sm->rreg = tplc_chan_get_reg(tplg, mc->channel, | ||
741 | SNDRV_CHMAP_FR); | ||
742 | sm->shift = tplc_chan_get_shift(tplg, mc->channel, | ||
743 | SNDRV_CHMAP_FL); | ||
744 | sm->rshift = tplc_chan_get_shift(tplg, mc->channel, | ||
745 | SNDRV_CHMAP_FR); | ||
746 | |||
747 | sm->max = mc->max; | ||
748 | sm->min = mc->min; | ||
749 | sm->invert = mc->invert; | ||
750 | sm->platform_max = mc->platform_max; | ||
751 | sm->dobj.index = tplg->index; | ||
752 | sm->dobj.ops = tplg->ops; | ||
753 | sm->dobj.type = SND_SOC_DOBJ_MIXER; | ||
754 | INIT_LIST_HEAD(&sm->dobj.list); | ||
755 | |||
756 | /* map io handlers */ | ||
757 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, io_ops, | ||
758 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
759 | if (err) { | ||
760 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); | ||
761 | kfree(sm); | ||
762 | continue; | ||
763 | } | ||
764 | |||
765 | /* pass control to driver for optional further init */ | ||
766 | err = soc_tplg_init_kcontrol(tplg, &kc, | ||
767 | (struct snd_soc_tplg_ctl_hdr *) mc); | ||
768 | if (err < 0) { | ||
769 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
770 | mc->hdr.name); | ||
771 | kfree(sm); | ||
772 | continue; | ||
773 | } | ||
774 | |||
775 | /* create any TLV data */ | ||
776 | soc_tplg_create_tlv(tplg, &kc, mc->hdr.tlv_size); | ||
777 | |||
778 | /* register control here */ | ||
779 | err = soc_tplg_add_kcontrol(tplg, &kc, | ||
780 | &sm->dobj.control.kcontrol); | ||
781 | if (err < 0) { | ||
782 | dev_err(tplg->dev, "ASoC: failed to add %s\n", | ||
783 | mc->hdr.name); | ||
784 | soc_tplg_free_tlv(tplg, &kc); | ||
785 | kfree(sm); | ||
786 | continue; | ||
787 | } | ||
788 | |||
789 | list_add(&sm->dobj.list, &tplg->comp->dobj_list); | ||
790 | } | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | static int soc_tplg_denum_create_texts(struct soc_enum *se, | ||
796 | struct snd_soc_tplg_enum_control *ec) | ||
797 | { | ||
798 | int i, ret; | ||
799 | |||
800 | se->dobj.control.dtexts = | ||
801 | kzalloc(sizeof(char *) * ec->items, GFP_KERNEL); | ||
802 | if (se->dobj.control.dtexts == NULL) | ||
803 | return -ENOMEM; | ||
804 | |||
805 | for (i = 0; i < ec->items; i++) { | ||
806 | |||
807 | if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
808 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) { | ||
809 | ret = -EINVAL; | ||
810 | goto err; | ||
811 | } | ||
812 | |||
813 | se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL); | ||
814 | if (!se->dobj.control.dtexts[i]) { | ||
815 | ret = -ENOMEM; | ||
816 | goto err; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | return 0; | ||
821 | |||
822 | err: | ||
823 | for (--i; i >= 0; i--) | ||
824 | kfree(se->dobj.control.dtexts[i]); | ||
825 | kfree(se->dobj.control.dtexts); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | static int soc_tplg_denum_create_values(struct soc_enum *se, | ||
830 | struct snd_soc_tplg_enum_control *ec) | ||
831 | { | ||
832 | if (ec->items > sizeof(*ec->values)) | ||
833 | return -EINVAL; | ||
834 | |||
835 | se->dobj.control.dvalues = | ||
836 | kmalloc(ec->items * sizeof(u32), GFP_KERNEL); | ||
837 | if (!se->dobj.control.dvalues) | ||
838 | return -ENOMEM; | ||
839 | |||
840 | memcpy(se->dobj.control.dvalues, ec->values, ec->items * sizeof(u32)); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, | ||
845 | size_t size) | ||
846 | { | ||
847 | struct snd_soc_tplg_enum_control *ec; | ||
848 | struct soc_enum *se; | ||
849 | struct snd_kcontrol_new kc; | ||
850 | int i, ret, err; | ||
851 | |||
852 | if (soc_tplg_check_elem_count(tplg, | ||
853 | sizeof(struct snd_soc_tplg_enum_control), | ||
854 | count, size, "enums")) { | ||
855 | |||
856 | dev_err(tplg->dev, "ASoC: invalid count %d for enum controls\n", | ||
857 | count); | ||
858 | return -EINVAL; | ||
859 | } | ||
860 | |||
861 | for (i = 0; i < count; i++) { | ||
862 | ec = (struct snd_soc_tplg_enum_control *)tplg->pos; | ||
863 | tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + | ||
864 | ec->priv.size); | ||
865 | |||
866 | /* validate kcontrol */ | ||
867 | if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
868 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
869 | return -EINVAL; | ||
870 | |||
871 | se = kzalloc((sizeof(*se)), GFP_KERNEL); | ||
872 | if (se == NULL) | ||
873 | return -ENOMEM; | ||
874 | |||
875 | dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", | ||
876 | ec->hdr.name, ec->items); | ||
877 | |||
878 | memset(&kc, 0, sizeof(kc)); | ||
879 | kc.name = ec->hdr.name; | ||
880 | kc.private_value = (long)se; | ||
881 | kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
882 | kc.access = ec->hdr.access; | ||
883 | |||
884 | se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); | ||
885 | se->shift_l = tplc_chan_get_shift(tplg, ec->channel, | ||
886 | SNDRV_CHMAP_FL); | ||
887 | se->shift_r = tplc_chan_get_shift(tplg, ec->channel, | ||
888 | SNDRV_CHMAP_FL); | ||
889 | |||
890 | se->items = ec->items; | ||
891 | se->mask = ec->mask; | ||
892 | se->dobj.index = tplg->index; | ||
893 | se->dobj.type = SND_SOC_DOBJ_ENUM; | ||
894 | se->dobj.ops = tplg->ops; | ||
895 | INIT_LIST_HEAD(&se->dobj.list); | ||
896 | |||
897 | switch (ec->hdr.ops.info) { | ||
898 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: | ||
899 | case SND_SOC_TPLG_CTL_ENUM_VALUE: | ||
900 | err = soc_tplg_denum_create_values(se, ec); | ||
901 | if (err < 0) { | ||
902 | dev_err(tplg->dev, | ||
903 | "ASoC: could not create values for %s\n", | ||
904 | ec->hdr.name); | ||
905 | kfree(se); | ||
906 | continue; | ||
907 | } | ||
908 | /* fall through and create texts */ | ||
909 | case SND_SOC_TPLG_CTL_ENUM: | ||
910 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | ||
911 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | ||
912 | err = soc_tplg_denum_create_texts(se, ec); | ||
913 | if (err < 0) { | ||
914 | dev_err(tplg->dev, | ||
915 | "ASoC: could not create texts for %s\n", | ||
916 | ec->hdr.name); | ||
917 | kfree(se); | ||
918 | continue; | ||
919 | } | ||
920 | break; | ||
921 | default: | ||
922 | dev_err(tplg->dev, | ||
923 | "ASoC: invalid enum control type %d for %s\n", | ||
924 | ec->hdr.ops.info, ec->hdr.name); | ||
925 | kfree(se); | ||
926 | continue; | ||
927 | } | ||
928 | |||
929 | /* map io handlers */ | ||
930 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, io_ops, | ||
931 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
932 | if (err) { | ||
933 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); | ||
934 | kfree(se); | ||
935 | continue; | ||
936 | } | ||
937 | |||
938 | /* pass control to driver for optional further init */ | ||
939 | err = soc_tplg_init_kcontrol(tplg, &kc, | ||
940 | (struct snd_soc_tplg_ctl_hdr *) ec); | ||
941 | if (err < 0) { | ||
942 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
943 | ec->hdr.name); | ||
944 | kfree(se); | ||
945 | continue; | ||
946 | } | ||
947 | |||
948 | /* register control here */ | ||
949 | ret = soc_tplg_add_kcontrol(tplg, | ||
950 | &kc, &se->dobj.control.kcontrol); | ||
951 | if (ret < 0) { | ||
952 | dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", | ||
953 | ec->hdr.name); | ||
954 | kfree(se); | ||
955 | continue; | ||
956 | } | ||
957 | |||
958 | list_add(&se->dobj.list, &tplg->comp->dobj_list); | ||
959 | } | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, | ||
965 | struct snd_soc_tplg_hdr *hdr) | ||
966 | { | ||
967 | struct snd_soc_tplg_ctl_hdr *control_hdr; | ||
968 | int i; | ||
969 | |||
970 | if (tplg->pass != SOC_TPLG_PASS_MIXER) { | ||
971 | tplg->pos += hdr->size + hdr->payload_size; | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, | ||
976 | soc_tplg_get_offset(tplg)); | ||
977 | |||
978 | for (i = 0; i < hdr->count; i++) { | ||
979 | |||
980 | control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; | ||
981 | |||
982 | switch (control_hdr->ops.info) { | ||
983 | case SND_SOC_TPLG_CTL_VOLSW: | ||
984 | case SND_SOC_TPLG_CTL_STROBE: | ||
985 | case SND_SOC_TPLG_CTL_VOLSW_SX: | ||
986 | case SND_SOC_TPLG_CTL_VOLSW_XR_SX: | ||
987 | case SND_SOC_TPLG_CTL_RANGE: | ||
988 | case SND_SOC_TPLG_DAPM_CTL_VOLSW: | ||
989 | case SND_SOC_TPLG_DAPM_CTL_PIN: | ||
990 | soc_tplg_dmixer_create(tplg, 1, hdr->payload_size); | ||
991 | break; | ||
992 | case SND_SOC_TPLG_CTL_ENUM: | ||
993 | case SND_SOC_TPLG_CTL_ENUM_VALUE: | ||
994 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | ||
995 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | ||
996 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: | ||
997 | soc_tplg_denum_create(tplg, 1, hdr->payload_size); | ||
998 | break; | ||
999 | case SND_SOC_TPLG_CTL_BYTES: | ||
1000 | soc_tplg_dbytes_create(tplg, 1, hdr->payload_size); | ||
1001 | break; | ||
1002 | default: | ||
1003 | soc_bind_err(tplg, control_hdr, i); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, | ||
1012 | struct snd_soc_tplg_hdr *hdr) | ||
1013 | { | ||
1014 | struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; | ||
1015 | struct snd_soc_dapm_route route; | ||
1016 | struct snd_soc_tplg_dapm_graph_elem *elem; | ||
1017 | int count = hdr->count, i; | ||
1018 | |||
1019 | if (tplg->pass != SOC_TPLG_PASS_GRAPH) { | ||
1020 | tplg->pos += hdr->size + hdr->payload_size; | ||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
1024 | if (soc_tplg_check_elem_count(tplg, | ||
1025 | sizeof(struct snd_soc_tplg_dapm_graph_elem), | ||
1026 | count, hdr->payload_size, "graph")) { | ||
1027 | |||
1028 | dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n", | ||
1029 | count); | ||
1030 | return -EINVAL; | ||
1031 | } | ||
1032 | |||
1033 | dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes\n", count); | ||
1034 | |||
1035 | for (i = 0; i < count; i++) { | ||
1036 | elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; | ||
1037 | tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); | ||
1038 | |||
1039 | /* validate routes */ | ||
1040 | if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1041 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1042 | return -EINVAL; | ||
1043 | if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1044 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1045 | return -EINVAL; | ||
1046 | if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1047 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1048 | return -EINVAL; | ||
1049 | |||
1050 | route.source = elem->source; | ||
1051 | route.sink = elem->sink; | ||
1052 | route.connected = NULL; /* set to NULL atm for tplg users */ | ||
1053 | if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0) | ||
1054 | route.control = NULL; | ||
1055 | else | ||
1056 | route.control = elem->control; | ||
1057 | |||
1058 | /* add route, but keep going if some fail */ | ||
1059 | snd_soc_dapm_add_routes(dapm, &route, 1); | ||
1060 | } | ||
1061 | |||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( | ||
1066 | struct soc_tplg *tplg, int num_kcontrols) | ||
1067 | { | ||
1068 | struct snd_kcontrol_new *kc; | ||
1069 | struct soc_mixer_control *sm; | ||
1070 | struct snd_soc_tplg_mixer_control *mc; | ||
1071 | int i, err; | ||
1072 | |||
1073 | kc = kzalloc(sizeof(*kc) * num_kcontrols, GFP_KERNEL); | ||
1074 | if (kc == NULL) | ||
1075 | return NULL; | ||
1076 | |||
1077 | for (i = 0; i < num_kcontrols; i++) { | ||
1078 | mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; | ||
1079 | sm = kzalloc(sizeof(*sm), GFP_KERNEL); | ||
1080 | if (sm == NULL) | ||
1081 | goto err; | ||
1082 | |||
1083 | tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + | ||
1084 | mc->priv.size); | ||
1085 | |||
1086 | /* validate kcontrol */ | ||
1087 | if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1088 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1089 | goto err_str; | ||
1090 | |||
1091 | dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n", | ||
1092 | mc->hdr.name, i); | ||
1093 | |||
1094 | kc[i].name = mc->hdr.name; | ||
1095 | kc[i].private_value = (long)sm; | ||
1096 | kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
1097 | kc[i].access = mc->hdr.access; | ||
1098 | |||
1099 | /* we only support FL/FR channel mapping atm */ | ||
1100 | sm->reg = tplc_chan_get_reg(tplg, mc->channel, | ||
1101 | SNDRV_CHMAP_FL); | ||
1102 | sm->rreg = tplc_chan_get_reg(tplg, mc->channel, | ||
1103 | SNDRV_CHMAP_FR); | ||
1104 | sm->shift = tplc_chan_get_shift(tplg, mc->channel, | ||
1105 | SNDRV_CHMAP_FL); | ||
1106 | sm->rshift = tplc_chan_get_shift(tplg, mc->channel, | ||
1107 | SNDRV_CHMAP_FR); | ||
1108 | |||
1109 | sm->max = mc->max; | ||
1110 | sm->min = mc->min; | ||
1111 | sm->invert = mc->invert; | ||
1112 | sm->platform_max = mc->platform_max; | ||
1113 | sm->dobj.index = tplg->index; | ||
1114 | INIT_LIST_HEAD(&sm->dobj.list); | ||
1115 | |||
1116 | /* map io handlers */ | ||
1117 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], io_ops, | ||
1118 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
1119 | if (err) { | ||
1120 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); | ||
1121 | kfree(sm); | ||
1122 | continue; | ||
1123 | } | ||
1124 | |||
1125 | /* pass control to driver for optional further init */ | ||
1126 | err = soc_tplg_init_kcontrol(tplg, &kc[i], | ||
1127 | (struct snd_soc_tplg_ctl_hdr *)mc); | ||
1128 | if (err < 0) { | ||
1129 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
1130 | mc->hdr.name); | ||
1131 | kfree(sm); | ||
1132 | continue; | ||
1133 | } | ||
1134 | } | ||
1135 | return kc; | ||
1136 | |||
1137 | err_str: | ||
1138 | kfree(sm); | ||
1139 | err: | ||
1140 | for (--i; i >= 0; i--) | ||
1141 | kfree((void *)kc[i].private_value); | ||
1142 | kfree(kc); | ||
1143 | return NULL; | ||
1144 | } | ||
1145 | |||
1146 | static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( | ||
1147 | struct soc_tplg *tplg) | ||
1148 | { | ||
1149 | struct snd_kcontrol_new *kc; | ||
1150 | struct snd_soc_tplg_enum_control *ec; | ||
1151 | struct soc_enum *se; | ||
1152 | int i, err; | ||
1153 | |||
1154 | ec = (struct snd_soc_tplg_enum_control *)tplg->pos; | ||
1155 | tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + | ||
1156 | ec->priv.size); | ||
1157 | |||
1158 | /* validate kcontrol */ | ||
1159 | if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1160 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1161 | return NULL; | ||
1162 | |||
1163 | kc = kzalloc(sizeof(*kc), GFP_KERNEL); | ||
1164 | if (kc == NULL) | ||
1165 | return NULL; | ||
1166 | |||
1167 | se = kzalloc(sizeof(*se), GFP_KERNEL); | ||
1168 | if (se == NULL) | ||
1169 | goto err; | ||
1170 | |||
1171 | dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", | ||
1172 | ec->hdr.name); | ||
1173 | |||
1174 | kc->name = ec->hdr.name; | ||
1175 | kc->private_value = (long)se; | ||
1176 | kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
1177 | kc->access = ec->hdr.access; | ||
1178 | |||
1179 | /* we only support FL/FR channel mapping atm */ | ||
1180 | se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); | ||
1181 | se->shift_l = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); | ||
1182 | se->shift_r = tplc_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); | ||
1183 | |||
1184 | se->items = ec->items; | ||
1185 | se->mask = ec->mask; | ||
1186 | se->dobj.index = tplg->index; | ||
1187 | |||
1188 | switch (ec->hdr.ops.info) { | ||
1189 | case SND_SOC_TPLG_CTL_ENUM_VALUE: | ||
1190 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: | ||
1191 | err = soc_tplg_denum_create_values(se, ec); | ||
1192 | if (err < 0) { | ||
1193 | dev_err(tplg->dev, "ASoC: could not create values for %s\n", | ||
1194 | ec->hdr.name); | ||
1195 | goto err_se; | ||
1196 | } | ||
1197 | /* fall through to create texts */ | ||
1198 | case SND_SOC_TPLG_CTL_ENUM: | ||
1199 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | ||
1200 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | ||
1201 | err = soc_tplg_denum_create_texts(se, ec); | ||
1202 | if (err < 0) { | ||
1203 | dev_err(tplg->dev, "ASoC: could not create texts for %s\n", | ||
1204 | ec->hdr.name); | ||
1205 | goto err_se; | ||
1206 | } | ||
1207 | break; | ||
1208 | default: | ||
1209 | dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", | ||
1210 | ec->hdr.ops.info, ec->hdr.name); | ||
1211 | goto err_se; | ||
1212 | } | ||
1213 | |||
1214 | /* map io handlers */ | ||
1215 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, io_ops, | ||
1216 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
1217 | if (err) { | ||
1218 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); | ||
1219 | goto err_se; | ||
1220 | } | ||
1221 | |||
1222 | /* pass control to driver for optional further init */ | ||
1223 | err = soc_tplg_init_kcontrol(tplg, kc, | ||
1224 | (struct snd_soc_tplg_ctl_hdr *)ec); | ||
1225 | if (err < 0) { | ||
1226 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
1227 | ec->hdr.name); | ||
1228 | goto err_se; | ||
1229 | } | ||
1230 | |||
1231 | return kc; | ||
1232 | |||
1233 | err_se: | ||
1234 | /* free values and texts */ | ||
1235 | kfree(se->dobj.control.dvalues); | ||
1236 | for (i = 0; i < ec->items; i++) | ||
1237 | kfree(se->dobj.control.dtexts[i]); | ||
1238 | |||
1239 | kfree(se); | ||
1240 | err: | ||
1241 | kfree(kc); | ||
1242 | |||
1243 | return NULL; | ||
1244 | } | ||
1245 | |||
1246 | static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( | ||
1247 | struct soc_tplg *tplg, int count) | ||
1248 | { | ||
1249 | struct snd_soc_tplg_bytes_control *be; | ||
1250 | struct soc_bytes_ext *sbe; | ||
1251 | struct snd_kcontrol_new *kc; | ||
1252 | int i, err; | ||
1253 | |||
1254 | kc = kzalloc(sizeof(*kc) * count, GFP_KERNEL); | ||
1255 | if (!kc) | ||
1256 | return NULL; | ||
1257 | |||
1258 | for (i = 0; i < count; i++) { | ||
1259 | be = (struct snd_soc_tplg_bytes_control *)tplg->pos; | ||
1260 | |||
1261 | /* validate kcontrol */ | ||
1262 | if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1263 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1264 | goto err; | ||
1265 | |||
1266 | sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); | ||
1267 | if (sbe == NULL) | ||
1268 | goto err; | ||
1269 | |||
1270 | tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + | ||
1271 | be->priv.size); | ||
1272 | |||
1273 | dev_dbg(tplg->dev, | ||
1274 | "ASoC: adding bytes kcontrol %s with access 0x%x\n", | ||
1275 | be->hdr.name, be->hdr.access); | ||
1276 | |||
1277 | memset(kc, 0, sizeof(*kc)); | ||
1278 | kc[i].name = be->hdr.name; | ||
1279 | kc[i].private_value = (long)sbe; | ||
1280 | kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
1281 | kc[i].access = be->hdr.access; | ||
1282 | |||
1283 | sbe->max = be->max; | ||
1284 | INIT_LIST_HEAD(&sbe->dobj.list); | ||
1285 | |||
1286 | /* map standard io handlers and check for external handlers */ | ||
1287 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], io_ops, | ||
1288 | ARRAY_SIZE(io_ops), tplg->io_ops, | ||
1289 | tplg->io_ops_count); | ||
1290 | if (err) { | ||
1291 | soc_control_err(tplg, &be->hdr, be->hdr.name); | ||
1292 | kfree(sbe); | ||
1293 | continue; | ||
1294 | } | ||
1295 | |||
1296 | /* pass control to driver for optional further init */ | ||
1297 | err = soc_tplg_init_kcontrol(tplg, &kc[i], | ||
1298 | (struct snd_soc_tplg_ctl_hdr *)be); | ||
1299 | if (err < 0) { | ||
1300 | dev_err(tplg->dev, "ASoC: failed to init %s\n", | ||
1301 | be->hdr.name); | ||
1302 | kfree(sbe); | ||
1303 | continue; | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | return kc; | ||
1308 | |||
1309 | err: | ||
1310 | for (--i; i >= 0; i--) | ||
1311 | kfree((void *)kc[i].private_value); | ||
1312 | |||
1313 | kfree(kc); | ||
1314 | return NULL; | ||
1315 | } | ||
1316 | |||
1317 | static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, | ||
1318 | struct snd_soc_tplg_dapm_widget *w) | ||
1319 | { | ||
1320 | struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; | ||
1321 | struct snd_soc_dapm_widget template, *widget; | ||
1322 | struct snd_soc_tplg_ctl_hdr *control_hdr; | ||
1323 | struct snd_soc_card *card = tplg->comp->card; | ||
1324 | int ret = 0; | ||
1325 | |||
1326 | if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1327 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1328 | return -EINVAL; | ||
1329 | if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == | ||
1330 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN) | ||
1331 | return -EINVAL; | ||
1332 | |||
1333 | dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n", | ||
1334 | w->name, w->id); | ||
1335 | |||
1336 | memset(&template, 0, sizeof(template)); | ||
1337 | |||
1338 | /* map user to kernel widget ID */ | ||
1339 | template.id = get_widget_id(w->id); | ||
1340 | if (template.id < 0) | ||
1341 | return template.id; | ||
1342 | |||
1343 | template.name = kstrdup(w->name, GFP_KERNEL); | ||
1344 | if (!template.name) | ||
1345 | return -ENOMEM; | ||
1346 | template.sname = kstrdup(w->sname, GFP_KERNEL); | ||
1347 | if (!template.sname) { | ||
1348 | ret = -ENOMEM; | ||
1349 | goto err; | ||
1350 | } | ||
1351 | template.reg = w->reg; | ||
1352 | template.shift = w->shift; | ||
1353 | template.mask = w->mask; | ||
1354 | template.on_val = w->invert ? 0 : 1; | ||
1355 | template.off_val = w->invert ? 1 : 0; | ||
1356 | template.ignore_suspend = w->ignore_suspend; | ||
1357 | template.event_flags = w->event_flags; | ||
1358 | template.dobj.index = tplg->index; | ||
1359 | |||
1360 | tplg->pos += | ||
1361 | (sizeof(struct snd_soc_tplg_dapm_widget) + w->priv.size); | ||
1362 | if (w->num_kcontrols == 0) { | ||
1363 | template.num_kcontrols = 0; | ||
1364 | goto widget; | ||
1365 | } | ||
1366 | |||
1367 | control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; | ||
1368 | dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n", | ||
1369 | w->name, w->num_kcontrols, control_hdr->type); | ||
1370 | |||
1371 | switch (control_hdr->ops.info) { | ||
1372 | case SND_SOC_TPLG_CTL_VOLSW: | ||
1373 | case SND_SOC_TPLG_CTL_STROBE: | ||
1374 | case SND_SOC_TPLG_CTL_VOLSW_SX: | ||
1375 | case SND_SOC_TPLG_CTL_VOLSW_XR_SX: | ||
1376 | case SND_SOC_TPLG_CTL_RANGE: | ||
1377 | case SND_SOC_TPLG_DAPM_CTL_VOLSW: | ||
1378 | template.num_kcontrols = w->num_kcontrols; | ||
1379 | template.kcontrol_news = | ||
1380 | soc_tplg_dapm_widget_dmixer_create(tplg, | ||
1381 | template.num_kcontrols); | ||
1382 | if (!template.kcontrol_news) { | ||
1383 | ret = -ENOMEM; | ||
1384 | goto hdr_err; | ||
1385 | } | ||
1386 | break; | ||
1387 | case SND_SOC_TPLG_CTL_ENUM: | ||
1388 | case SND_SOC_TPLG_CTL_ENUM_VALUE: | ||
1389 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | ||
1390 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | ||
1391 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: | ||
1392 | template.dobj.widget.kcontrol_enum = 1; | ||
1393 | template.num_kcontrols = 1; | ||
1394 | template.kcontrol_news = | ||
1395 | soc_tplg_dapm_widget_denum_create(tplg); | ||
1396 | if (!template.kcontrol_news) { | ||
1397 | ret = -ENOMEM; | ||
1398 | goto hdr_err; | ||
1399 | } | ||
1400 | break; | ||
1401 | case SND_SOC_TPLG_CTL_BYTES: | ||
1402 | template.num_kcontrols = w->num_kcontrols; | ||
1403 | template.kcontrol_news = | ||
1404 | soc_tplg_dapm_widget_dbytes_create(tplg, | ||
1405 | template.num_kcontrols); | ||
1406 | if (!template.kcontrol_news) { | ||
1407 | ret = -ENOMEM; | ||
1408 | goto hdr_err; | ||
1409 | } | ||
1410 | break; | ||
1411 | default: | ||
1412 | dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n", | ||
1413 | control_hdr->ops.get, control_hdr->ops.put, | ||
1414 | control_hdr->ops.info); | ||
1415 | ret = -EINVAL; | ||
1416 | goto hdr_err; | ||
1417 | } | ||
1418 | |||
1419 | widget: | ||
1420 | ret = soc_tplg_widget_load(tplg, &template, w); | ||
1421 | if (ret < 0) | ||
1422 | goto hdr_err; | ||
1423 | |||
1424 | /* card dapm mutex is held by the core if we are loading topology | ||
1425 | * data during sound card init. */ | ||
1426 | if (card->instantiated) | ||
1427 | widget = snd_soc_dapm_new_control(dapm, &template); | ||
1428 | else | ||
1429 | widget = snd_soc_dapm_new_control_unlocked(dapm, &template); | ||
1430 | if (widget == NULL) { | ||
1431 | dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", | ||
1432 | w->name); | ||
1433 | goto hdr_err; | ||
1434 | } | ||
1435 | |||
1436 | widget->dobj.type = SND_SOC_DOBJ_WIDGET; | ||
1437 | widget->dobj.ops = tplg->ops; | ||
1438 | widget->dobj.index = tplg->index; | ||
1439 | list_add(&widget->dobj.list, &tplg->comp->dobj_list); | ||
1440 | return 0; | ||
1441 | |||
1442 | hdr_err: | ||
1443 | kfree(template.sname); | ||
1444 | err: | ||
1445 | kfree(template.name); | ||
1446 | return ret; | ||
1447 | } | ||
1448 | |||
1449 | static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, | ||
1450 | struct snd_soc_tplg_hdr *hdr) | ||
1451 | { | ||
1452 | struct snd_soc_tplg_dapm_widget *widget; | ||
1453 | int ret, count = hdr->count, i; | ||
1454 | |||
1455 | if (tplg->pass != SOC_TPLG_PASS_WIDGET) | ||
1456 | return 0; | ||
1457 | |||
1458 | dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); | ||
1459 | |||
1460 | for (i = 0; i < count; i++) { | ||
1461 | widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; | ||
1462 | ret = soc_tplg_dapm_widget_create(tplg, widget); | ||
1463 | if (ret < 0) | ||
1464 | dev_err(tplg->dev, "ASoC: failed to load widget %s\n", | ||
1465 | widget->name); | ||
1466 | } | ||
1467 | |||
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | static int soc_tplg_dapm_complete(struct soc_tplg *tplg) | ||
1472 | { | ||
1473 | struct snd_soc_card *card = tplg->comp->card; | ||
1474 | int ret; | ||
1475 | |||
1476 | /* Card might not have been registered at this point. | ||
1477 | * If so, just return success. | ||
1478 | */ | ||
1479 | if (!card || !card->instantiated) { | ||
1480 | dev_warn(tplg->dev, "ASoC: Parent card not yet available," | ||
1481 | "Do not add new widgets now\n"); | ||
1482 | return 0; | ||
1483 | } | ||
1484 | |||
1485 | ret = snd_soc_dapm_new_widgets(card); | ||
1486 | if (ret < 0) | ||
1487 | dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", | ||
1488 | ret); | ||
1489 | |||
1490 | return 0; | ||
1491 | } | ||
1492 | |||
1493 | static int soc_tplg_pcm_dai_elems_load(struct soc_tplg *tplg, | ||
1494 | struct snd_soc_tplg_hdr *hdr) | ||
1495 | { | ||
1496 | struct snd_soc_tplg_pcm_dai *pcm_dai; | ||
1497 | struct snd_soc_dobj *dobj; | ||
1498 | int count = hdr->count; | ||
1499 | int ret; | ||
1500 | |||
1501 | if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) | ||
1502 | return 0; | ||
1503 | |||
1504 | pcm_dai = (struct snd_soc_tplg_pcm_dai *)tplg->pos; | ||
1505 | |||
1506 | if (soc_tplg_check_elem_count(tplg, | ||
1507 | sizeof(struct snd_soc_tplg_pcm_dai), count, | ||
1508 | hdr->payload_size, "PCM DAI")) { | ||
1509 | dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n", | ||
1510 | count); | ||
1511 | return -EINVAL; | ||
1512 | } | ||
1513 | |||
1514 | dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); | ||
1515 | tplg->pos += sizeof(struct snd_soc_tplg_pcm_dai) * count; | ||
1516 | |||
1517 | dobj = kzalloc(sizeof(struct snd_soc_dobj), GFP_KERNEL); | ||
1518 | if (dobj == NULL) | ||
1519 | return -ENOMEM; | ||
1520 | |||
1521 | /* Call the platform driver call back to register the dais */ | ||
1522 | ret = soc_tplg_pcm_dai_load(tplg, pcm_dai, count); | ||
1523 | if (ret < 0) { | ||
1524 | dev_err(tplg->comp->dev, "ASoC: PCM DAI loading failed\n"); | ||
1525 | goto err; | ||
1526 | } | ||
1527 | |||
1528 | dobj->type = get_dobj_type(hdr, NULL); | ||
1529 | dobj->pcm_dai.count = count; | ||
1530 | dobj->pcm_dai.pd = pcm_dai; | ||
1531 | dobj->ops = tplg->ops; | ||
1532 | dobj->index = tplg->index; | ||
1533 | list_add(&dobj->list, &tplg->comp->dobj_list); | ||
1534 | return 0; | ||
1535 | |||
1536 | err: | ||
1537 | kfree(dobj); | ||
1538 | return ret; | ||
1539 | } | ||
1540 | |||
1541 | static int soc_tplg_manifest_load(struct soc_tplg *tplg, | ||
1542 | struct snd_soc_tplg_hdr *hdr) | ||
1543 | { | ||
1544 | struct snd_soc_tplg_manifest *manifest; | ||
1545 | |||
1546 | if (tplg->pass != SOC_TPLG_PASS_MANIFEST) | ||
1547 | return 0; | ||
1548 | |||
1549 | manifest = (struct snd_soc_tplg_manifest *)tplg->pos; | ||
1550 | tplg->pos += sizeof(struct snd_soc_tplg_manifest); | ||
1551 | |||
1552 | if (tplg->comp && tplg->ops && tplg->ops->manifest) | ||
1553 | return tplg->ops->manifest(tplg->comp, manifest); | ||
1554 | |||
1555 | dev_err(tplg->dev, "ASoC: Firmware manifest not supported\n"); | ||
1556 | return 0; | ||
1557 | } | ||
1558 | |||
1559 | /* validate header magic, size and type */ | ||
1560 | static int soc_valid_header(struct soc_tplg *tplg, | ||
1561 | struct snd_soc_tplg_hdr *hdr) | ||
1562 | { | ||
1563 | if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) | ||
1564 | return 0; | ||
1565 | |||
1566 | /* big endian firmware objects not supported atm */ | ||
1567 | if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { | ||
1568 | dev_err(tplg->dev, | ||
1569 | "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n", | ||
1570 | tplg->pass, hdr->magic, | ||
1571 | soc_tplg_get_hdr_offset(tplg), tplg->fw->size); | ||
1572 | return -EINVAL; | ||
1573 | } | ||
1574 | |||
1575 | if (hdr->magic != SND_SOC_TPLG_MAGIC) { | ||
1576 | dev_err(tplg->dev, | ||
1577 | "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n", | ||
1578 | tplg->pass, hdr->magic, | ||
1579 | soc_tplg_get_hdr_offset(tplg), tplg->fw->size); | ||
1580 | return -EINVAL; | ||
1581 | } | ||
1582 | |||
1583 | if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) { | ||
1584 | dev_err(tplg->dev, | ||
1585 | "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n", | ||
1586 | tplg->pass, hdr->abi, | ||
1587 | SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg), | ||
1588 | tplg->fw->size); | ||
1589 | return -EINVAL; | ||
1590 | } | ||
1591 | |||
1592 | if (hdr->payload_size == 0) { | ||
1593 | dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n", | ||
1594 | soc_tplg_get_hdr_offset(tplg)); | ||
1595 | return -EINVAL; | ||
1596 | } | ||
1597 | |||
1598 | if (tplg->pass == hdr->type) | ||
1599 | dev_dbg(tplg->dev, | ||
1600 | "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n", | ||
1601 | hdr->payload_size, hdr->type, hdr->version, | ||
1602 | hdr->vendor_type, tplg->pass); | ||
1603 | |||
1604 | return 1; | ||
1605 | } | ||
1606 | |||
1607 | /* check header type and call appropriate handler */ | ||
1608 | static int soc_tplg_load_header(struct soc_tplg *tplg, | ||
1609 | struct snd_soc_tplg_hdr *hdr) | ||
1610 | { | ||
1611 | tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); | ||
1612 | |||
1613 | /* check for matching ID */ | ||
1614 | if (hdr->index != tplg->req_index && | ||
1615 | hdr->index != SND_SOC_TPLG_INDEX_ALL) | ||
1616 | return 0; | ||
1617 | |||
1618 | tplg->index = hdr->index; | ||
1619 | |||
1620 | switch (hdr->type) { | ||
1621 | case SND_SOC_TPLG_TYPE_MIXER: | ||
1622 | case SND_SOC_TPLG_TYPE_ENUM: | ||
1623 | case SND_SOC_TPLG_TYPE_BYTES: | ||
1624 | return soc_tplg_kcontrol_elems_load(tplg, hdr); | ||
1625 | case SND_SOC_TPLG_TYPE_DAPM_GRAPH: | ||
1626 | return soc_tplg_dapm_graph_elems_load(tplg, hdr); | ||
1627 | case SND_SOC_TPLG_TYPE_DAPM_WIDGET: | ||
1628 | return soc_tplg_dapm_widget_elems_load(tplg, hdr); | ||
1629 | case SND_SOC_TPLG_TYPE_PCM: | ||
1630 | case SND_SOC_TPLG_TYPE_DAI_LINK: | ||
1631 | case SND_SOC_TPLG_TYPE_CODEC_LINK: | ||
1632 | return soc_tplg_pcm_dai_elems_load(tplg, hdr); | ||
1633 | case SND_SOC_TPLG_TYPE_MANIFEST: | ||
1634 | return soc_tplg_manifest_load(tplg, hdr); | ||
1635 | default: | ||
1636 | /* bespoke vendor data object */ | ||
1637 | return soc_tplg_vendor_load(tplg, hdr); | ||
1638 | } | ||
1639 | |||
1640 | return 0; | ||
1641 | } | ||
1642 | |||
1643 | /* process the topology file headers */ | ||
1644 | static int soc_tplg_process_headers(struct soc_tplg *tplg) | ||
1645 | { | ||
1646 | struct snd_soc_tplg_hdr *hdr; | ||
1647 | int ret; | ||
1648 | |||
1649 | tplg->pass = SOC_TPLG_PASS_START; | ||
1650 | |||
1651 | /* process the header types from start to end */ | ||
1652 | while (tplg->pass <= SOC_TPLG_PASS_END) { | ||
1653 | |||
1654 | tplg->hdr_pos = tplg->fw->data; | ||
1655 | hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; | ||
1656 | |||
1657 | while (!soc_tplg_is_eof(tplg)) { | ||
1658 | |||
1659 | /* make sure header is valid before loading */ | ||
1660 | ret = soc_valid_header(tplg, hdr); | ||
1661 | if (ret < 0) | ||
1662 | return ret; | ||
1663 | else if (ret == 0) | ||
1664 | break; | ||
1665 | |||
1666 | /* load the header object */ | ||
1667 | ret = soc_tplg_load_header(tplg, hdr); | ||
1668 | if (ret < 0) | ||
1669 | return ret; | ||
1670 | |||
1671 | /* goto next header */ | ||
1672 | tplg->hdr_pos += hdr->payload_size + | ||
1673 | sizeof(struct snd_soc_tplg_hdr); | ||
1674 | hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; | ||
1675 | } | ||
1676 | |||
1677 | /* next data type pass */ | ||
1678 | tplg->pass++; | ||
1679 | } | ||
1680 | |||
1681 | /* signal DAPM we are complete */ | ||
1682 | ret = soc_tplg_dapm_complete(tplg); | ||
1683 | if (ret < 0) | ||
1684 | dev_err(tplg->dev, | ||
1685 | "ASoC: failed to initialise DAPM from Firmware\n"); | ||
1686 | |||
1687 | return ret; | ||
1688 | } | ||
1689 | |||
1690 | static int soc_tplg_load(struct soc_tplg *tplg) | ||
1691 | { | ||
1692 | int ret; | ||
1693 | |||
1694 | ret = soc_tplg_process_headers(tplg); | ||
1695 | if (ret == 0) | ||
1696 | soc_tplg_complete(tplg); | ||
1697 | |||
1698 | return ret; | ||
1699 | } | ||
1700 | |||
1701 | /* load audio component topology from "firmware" file */ | ||
1702 | int snd_soc_tplg_component_load(struct snd_soc_component *comp, | ||
1703 | struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id) | ||
1704 | { | ||
1705 | struct soc_tplg tplg; | ||
1706 | |||
1707 | /* setup parsing context */ | ||
1708 | memset(&tplg, 0, sizeof(tplg)); | ||
1709 | tplg.fw = fw; | ||
1710 | tplg.dev = comp->dev; | ||
1711 | tplg.comp = comp; | ||
1712 | tplg.ops = ops; | ||
1713 | tplg.req_index = id; | ||
1714 | tplg.io_ops = ops->io_ops; | ||
1715 | tplg.io_ops_count = ops->io_ops_count; | ||
1716 | |||
1717 | return soc_tplg_load(&tplg); | ||
1718 | } | ||
1719 | EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load); | ||
1720 | |||
1721 | /* remove this dynamic widget */ | ||
1722 | void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w) | ||
1723 | { | ||
1724 | /* make sure we are a widget */ | ||
1725 | if (w->dobj.type != SND_SOC_DOBJ_WIDGET) | ||
1726 | return; | ||
1727 | |||
1728 | remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET); | ||
1729 | } | ||
1730 | EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove); | ||
1731 | |||
1732 | /* remove all dynamic widgets from this DAPM context */ | ||
1733 | void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, | ||
1734 | u32 index) | ||
1735 | { | ||
1736 | struct snd_soc_dapm_widget *w, *next_w; | ||
1737 | struct snd_soc_dapm_path *p, *next_p; | ||
1738 | |||
1739 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { | ||
1740 | |||
1741 | /* make sure we are a widget with correct context */ | ||
1742 | if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm) | ||
1743 | continue; | ||
1744 | |||
1745 | /* match ID */ | ||
1746 | if (w->dobj.index != index && | ||
1747 | w->dobj.index != SND_SOC_TPLG_INDEX_ALL) | ||
1748 | continue; | ||
1749 | |||
1750 | list_del(&w->list); | ||
1751 | |||
1752 | /* | ||
1753 | * remove source and sink paths associated to this widget. | ||
1754 | * While removing the path, remove reference to it from both | ||
1755 | * source and sink widgets so that path is removed only once. | ||
1756 | */ | ||
1757 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { | ||
1758 | list_del(&p->list_sink); | ||
1759 | list_del(&p->list_source); | ||
1760 | list_del(&p->list); | ||
1761 | kfree(p); | ||
1762 | } | ||
1763 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { | ||
1764 | list_del(&p->list_sink); | ||
1765 | list_del(&p->list_source); | ||
1766 | list_del(&p->list); | ||
1767 | kfree(p); | ||
1768 | } | ||
1769 | /* check and free and dynamic widget kcontrols */ | ||
1770 | snd_soc_tplg_widget_remove(w); | ||
1771 | kfree(w->kcontrols); | ||
1772 | kfree(w->name); | ||
1773 | kfree(w); | ||
1774 | } | ||
1775 | } | ||
1776 | EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); | ||
1777 | |||
1778 | /* remove dynamic controls from the component driver */ | ||
1779 | int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) | ||
1780 | { | ||
1781 | struct snd_soc_dobj *dobj, *next_dobj; | ||
1782 | int pass = SOC_TPLG_PASS_END; | ||
1783 | |||
1784 | /* process the header types from end to start */ | ||
1785 | while (pass >= SOC_TPLG_PASS_START) { | ||
1786 | |||
1787 | /* remove mixer controls */ | ||
1788 | list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, | ||
1789 | list) { | ||
1790 | |||
1791 | /* match index */ | ||
1792 | if (dobj->index != index && | ||
1793 | dobj->index != SND_SOC_TPLG_INDEX_ALL) | ||
1794 | continue; | ||
1795 | |||
1796 | switch (dobj->type) { | ||
1797 | case SND_SOC_DOBJ_MIXER: | ||
1798 | remove_mixer(comp, dobj, pass); | ||
1799 | break; | ||
1800 | case SND_SOC_DOBJ_ENUM: | ||
1801 | remove_enum(comp, dobj, pass); | ||
1802 | break; | ||
1803 | case SND_SOC_DOBJ_BYTES: | ||
1804 | remove_bytes(comp, dobj, pass); | ||
1805 | break; | ||
1806 | case SND_SOC_DOBJ_WIDGET: | ||
1807 | remove_widget(comp, dobj, pass); | ||
1808 | break; | ||
1809 | case SND_SOC_DOBJ_PCM: | ||
1810 | case SND_SOC_DOBJ_DAI_LINK: | ||
1811 | case SND_SOC_DOBJ_CODEC_LINK: | ||
1812 | remove_pcm_dai(comp, dobj, pass); | ||
1813 | break; | ||
1814 | default: | ||
1815 | dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", | ||
1816 | dobj->type); | ||
1817 | break; | ||
1818 | } | ||
1819 | } | ||
1820 | pass--; | ||
1821 | } | ||
1822 | |||
1823 | /* let caller know if FW can be freed when no objects are left */ | ||
1824 | return !list_empty(&comp->dobj_list); | ||
1825 | } | ||
1826 | EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove); | ||
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index b81a7a4c938b..85d810d7667c 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c | |||
@@ -372,6 +372,10 @@ int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) | |||
372 | /* Create driver private-data struct */ | 372 | /* Create driver private-data struct */ |
373 | drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), | 373 | drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), |
374 | GFP_KERNEL); | 374 | GFP_KERNEL); |
375 | |||
376 | if (!drvdata) | ||
377 | return -ENOMEM; | ||
378 | |||
375 | snd_soc_card_set_drvdata(rtd->card, drvdata); | 379 | snd_soc_card_set_drvdata(rtd->card, drvdata); |
376 | 380 | ||
377 | /* Setup clocks */ | 381 | /* Setup clocks */ |
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 51a66a87305a..f12c01dddc8d 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c | |||
@@ -147,7 +147,6 @@ int ux500_pcm_register_platform(struct platform_device *pdev) | |||
147 | pcm_config = &ux500_dmaengine_pcm_config; | 147 | pcm_config = &ux500_dmaengine_pcm_config; |
148 | 148 | ||
149 | ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, | 149 | ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, |
150 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
151 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 150 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
152 | if (ret < 0) { | 151 | if (ret < 0) { |
153 | dev_err(&pdev->dev, | 152 | dev_err(&pdev->dev, |
diff --git a/sound/soc/zte/Kconfig b/sound/soc/zte/Kconfig new file mode 100644 index 000000000000..c47eb25e441f --- /dev/null +++ b/sound/soc/zte/Kconfig | |||
@@ -0,0 +1,17 @@ | |||
1 | config ZX296702_SPDIF | ||
2 | tristate "ZX296702 spdif" | ||
3 | depends on SOC_ZX296702 || COMPILE_TEST | ||
4 | depends on COMMON_CLK | ||
5 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
6 | help | ||
7 | Say Y or M if you want to add support for codecs attached to the | ||
8 | zx296702 spdif interface | ||
9 | |||
10 | config ZX296702_I2S | ||
11 | tristate "ZX296702 i2s" | ||
12 | depends on SOC_ZX296702 || COMPILE_TEST | ||
13 | depends on COMMON_CLK | ||
14 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
15 | help | ||
16 | Say Y or M if you want to add support for codecs attached to the | ||
17 | zx296702 i2s interface | ||
diff --git a/sound/soc/zte/Makefile b/sound/soc/zte/Makefile new file mode 100644 index 000000000000..254ed2c8c1a0 --- /dev/null +++ b/sound/soc/zte/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_ZX296702_SPDIF) += zx296702-spdif.o | ||
2 | obj-$(CONFIG_ZX296702_I2S) += zx296702-i2s.o | ||
diff --git a/sound/soc/zte/zx296702-i2s.c b/sound/soc/zte/zx296702-i2s.c new file mode 100644 index 000000000000..98d96e1b17e0 --- /dev/null +++ b/sound/soc/zte/zx296702-i2s.c | |||
@@ -0,0 +1,436 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Linaro | ||
3 | * | ||
4 | * Author: Jun Nie <jun.nie@linaro.org> | ||
5 | * | ||
6 | * License terms: GNU General Public License (GPL) version 2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/clk.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/pcm_params.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <sound/soc-dai.h> | ||
19 | |||
20 | #include <sound/core.h> | ||
21 | #include <sound/dmaengine_pcm.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #define ZX_I2S_PROCESS_CTRL 0x04 | ||
28 | #define ZX_I2S_TIMING_CTRL 0x08 | ||
29 | #define ZX_I2S_FIFO_CTRL 0x0C | ||
30 | #define ZX_I2S_FIFO_STATUS 0x10 | ||
31 | #define ZX_I2S_INT_EN 0x14 | ||
32 | #define ZX_I2S_INT_STATUS 0x18 | ||
33 | #define ZX_I2S_DATA 0x1C | ||
34 | #define ZX_I2S_FRAME_CNTR 0x20 | ||
35 | |||
36 | #define I2S_DEAGULT_FIFO_THRES (0x10) | ||
37 | #define I2S_MAX_FIFO_THRES (0x20) | ||
38 | |||
39 | #define ZX_I2S_PROCESS_TX_EN (1 << 0) | ||
40 | #define ZX_I2S_PROCESS_TX_DIS (0 << 0) | ||
41 | #define ZX_I2S_PROCESS_RX_EN (1 << 1) | ||
42 | #define ZX_I2S_PROCESS_RX_DIS (0 << 1) | ||
43 | #define ZX_I2S_PROCESS_I2S_EN (1 << 2) | ||
44 | #define ZX_I2S_PROCESS_I2S_DIS (0 << 2) | ||
45 | |||
46 | #define ZX_I2S_TIMING_MAST (1 << 0) | ||
47 | #define ZX_I2S_TIMING_SLAVE (0 << 0) | ||
48 | #define ZX_I2S_TIMING_MS_MASK (1 << 0) | ||
49 | #define ZX_I2S_TIMING_LOOP (1 << 1) | ||
50 | #define ZX_I2S_TIMING_NOR (0 << 1) | ||
51 | #define ZX_I2S_TIMING_LOOP_MASK (1 << 1) | ||
52 | #define ZX_I2S_TIMING_PTNR (1 << 2) | ||
53 | #define ZX_I2S_TIMING_NTPR (0 << 2) | ||
54 | #define ZX_I2S_TIMING_PHASE_MASK (1 << 2) | ||
55 | #define ZX_I2S_TIMING_TDM (1 << 3) | ||
56 | #define ZX_I2S_TIMING_I2S (0 << 3) | ||
57 | #define ZX_I2S_TIMING_TIMING_MASK (1 << 3) | ||
58 | #define ZX_I2S_TIMING_LONG_SYNC (1 << 4) | ||
59 | #define ZX_I2S_TIMING_SHORT_SYNC (0 << 4) | ||
60 | #define ZX_I2S_TIMING_SYNC_MASK (1 << 4) | ||
61 | #define ZX_I2S_TIMING_TEAK_EN (1 << 5) | ||
62 | #define ZX_I2S_TIMING_TEAK_DIS (0 << 5) | ||
63 | #define ZX_I2S_TIMING_TEAK_MASK (1 << 5) | ||
64 | #define ZX_I2S_TIMING_STD_I2S (0 << 6) | ||
65 | #define ZX_I2S_TIMING_MSB_JUSTIF (1 << 6) | ||
66 | #define ZX_I2S_TIMING_LSB_JUSTIF (2 << 6) | ||
67 | #define ZX_I2S_TIMING_ALIGN_MASK (3 << 6) | ||
68 | #define ZX_I2S_TIMING_CHN_MASK (7 << 8) | ||
69 | #define ZX_I2S_TIMING_CHN(x) ((x - 1) << 8) | ||
70 | #define ZX_I2S_TIMING_LANE_MASK (3 << 11) | ||
71 | #define ZX_I2S_TIMING_LANE(x) ((x - 1) << 11) | ||
72 | #define ZX_I2S_TIMING_TSCFG_MASK (7 << 13) | ||
73 | #define ZX_I2S_TIMING_TSCFG(x) (x << 13) | ||
74 | #define ZX_I2S_TIMING_TS_WIDTH_MASK (0x1f << 16) | ||
75 | #define ZX_I2S_TIMING_TS_WIDTH(x) ((x - 1) << 16) | ||
76 | #define ZX_I2S_TIMING_DATA_SIZE_MASK (0x1f << 21) | ||
77 | #define ZX_I2S_TIMING_DATA_SIZE(x) ((x - 1) << 21) | ||
78 | #define ZX_I2S_TIMING_CFG_ERR_MASK (1 << 31) | ||
79 | |||
80 | #define ZX_I2S_FIFO_CTRL_TX_RST (1 << 0) | ||
81 | #define ZX_I2S_FIFO_CTRL_TX_RST_MASK (1 << 0) | ||
82 | #define ZX_I2S_FIFO_CTRL_RX_RST (1 << 1) | ||
83 | #define ZX_I2S_FIFO_CTRL_RX_RST_MASK (1 << 1) | ||
84 | #define ZX_I2S_FIFO_CTRL_TX_DMA_EN (1 << 4) | ||
85 | #define ZX_I2S_FIFO_CTRL_TX_DMA_DIS (0 << 4) | ||
86 | #define ZX_I2S_FIFO_CTRL_TX_DMA_MASK (1 << 4) | ||
87 | #define ZX_I2S_FIFO_CTRL_RX_DMA_EN (1 << 5) | ||
88 | #define ZX_I2S_FIFO_CTRL_RX_DMA_DIS (0 << 5) | ||
89 | #define ZX_I2S_FIFO_CTRL_RX_DMA_MASK (1 << 5) | ||
90 | #define ZX_I2S_FIFO_CTRL_TX_THRES_MASK (0x1F << 8) | ||
91 | #define ZX_I2S_FIFO_CTRL_RX_THRES_MASK (0x1F << 16) | ||
92 | |||
93 | #define CLK_RAT (32 * 4) | ||
94 | |||
95 | struct zx_i2s_info { | ||
96 | struct snd_dmaengine_dai_dma_data dma_playback; | ||
97 | struct snd_dmaengine_dai_dma_data dma_capture; | ||
98 | struct clk *dai_clk; | ||
99 | void __iomem *reg_base; | ||
100 | int master; | ||
101 | resource_size_t mapbase; | ||
102 | }; | ||
103 | |||
104 | static void zx_i2s_tx_en(void __iomem *base, bool on) | ||
105 | { | ||
106 | unsigned long val; | ||
107 | |||
108 | val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL); | ||
109 | if (on) | ||
110 | val |= ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN; | ||
111 | else | ||
112 | val &= ~(ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN); | ||
113 | writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL); | ||
114 | } | ||
115 | |||
116 | static void zx_i2s_rx_en(void __iomem *base, bool on) | ||
117 | { | ||
118 | unsigned long val; | ||
119 | |||
120 | val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL); | ||
121 | if (on) | ||
122 | val |= ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN; | ||
123 | else | ||
124 | val &= ~(ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN); | ||
125 | writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL); | ||
126 | } | ||
127 | |||
128 | static void zx_i2s_tx_dma_en(void __iomem *base, bool on) | ||
129 | { | ||
130 | unsigned long val; | ||
131 | |||
132 | val = readl_relaxed(base + ZX_I2S_FIFO_CTRL); | ||
133 | val |= ZX_I2S_FIFO_CTRL_TX_RST | (I2S_DEAGULT_FIFO_THRES << 8); | ||
134 | if (on) | ||
135 | val |= ZX_I2S_FIFO_CTRL_TX_DMA_EN; | ||
136 | else | ||
137 | val &= ~ZX_I2S_FIFO_CTRL_TX_DMA_EN; | ||
138 | writel_relaxed(val, base + ZX_I2S_FIFO_CTRL); | ||
139 | } | ||
140 | |||
141 | static void zx_i2s_rx_dma_en(void __iomem *base, bool on) | ||
142 | { | ||
143 | unsigned long val; | ||
144 | |||
145 | val = readl_relaxed(base + ZX_I2S_FIFO_CTRL); | ||
146 | val |= ZX_I2S_FIFO_CTRL_RX_RST | (I2S_DEAGULT_FIFO_THRES << 16); | ||
147 | if (on) | ||
148 | val |= ZX_I2S_FIFO_CTRL_RX_DMA_EN; | ||
149 | else | ||
150 | val &= ~ZX_I2S_FIFO_CTRL_RX_DMA_EN; | ||
151 | writel_relaxed(val, base + ZX_I2S_FIFO_CTRL); | ||
152 | } | ||
153 | |||
154 | #define ZX_I2S_RATES \ | ||
155 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
156 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
157 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000| \ | ||
158 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | ||
159 | |||
160 | #define ZX_I2S_FMTBIT \ | ||
161 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
162 | SNDRV_PCM_FMTBIT_S32_LE) | ||
163 | |||
164 | static int zx_i2s_dai_probe(struct snd_soc_dai *dai) | ||
165 | { | ||
166 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | ||
167 | |||
168 | snd_soc_dai_set_drvdata(dai, zx_i2s); | ||
169 | zx_i2s->dma_playback.addr = zx_i2s->mapbase + ZX_I2S_DATA; | ||
170 | zx_i2s->dma_playback.maxburst = 16; | ||
171 | zx_i2s->dma_capture.addr = zx_i2s->mapbase + ZX_I2S_DATA; | ||
172 | zx_i2s->dma_capture.maxburst = 16; | ||
173 | snd_soc_dai_init_dma_data(dai, &zx_i2s->dma_playback, | ||
174 | &zx_i2s->dma_capture); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
179 | { | ||
180 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
181 | unsigned long val; | ||
182 | |||
183 | val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); | ||
184 | val &= ~(ZX_I2S_TIMING_TIMING_MASK | ZX_I2S_TIMING_ALIGN_MASK | | ||
185 | ZX_I2S_TIMING_TEAK_MASK | ZX_I2S_TIMING_SYNC_MASK | | ||
186 | ZX_I2S_TIMING_MS_MASK); | ||
187 | |||
188 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
189 | case SND_SOC_DAIFMT_I2S: | ||
190 | val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_STD_I2S); | ||
191 | break; | ||
192 | case SND_SOC_DAIFMT_LEFT_J: | ||
193 | val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_MSB_JUSTIF); | ||
194 | break; | ||
195 | case SND_SOC_DAIFMT_RIGHT_J: | ||
196 | val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_LSB_JUSTIF); | ||
197 | break; | ||
198 | default: | ||
199 | dev_err(cpu_dai->dev, "Unknown i2s timeing\n"); | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
204 | case SND_SOC_DAIFMT_CBM_CFM: | ||
205 | i2s->master = 1; | ||
206 | val |= ZX_I2S_TIMING_MAST; | ||
207 | break; | ||
208 | case SND_SOC_DAIFMT_CBS_CFS: | ||
209 | i2s->master = 0; | ||
210 | val |= ZX_I2S_TIMING_SLAVE; | ||
211 | break; | ||
212 | default: | ||
213 | dev_err(cpu_dai->dev, "Unknown master/slave format\n"); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | ||
222 | struct snd_pcm_hw_params *params, | ||
223 | struct snd_soc_dai *socdai) | ||
224 | { | ||
225 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); | ||
226 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
227 | unsigned int lane, ch_num, len, ret = 0; | ||
228 | unsigned long val, format; | ||
229 | unsigned long chn_cfg; | ||
230 | |||
231 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); | ||
232 | dma_data->addr_width = params_width(params) >> 3; | ||
233 | |||
234 | val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); | ||
235 | val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK | | ||
236 | ZX_I2S_TIMING_LANE_MASK | ZX_I2S_TIMING_CHN_MASK | | ||
237 | ZX_I2S_TIMING_TSCFG_MASK); | ||
238 | |||
239 | switch (params_format(params)) { | ||
240 | case SNDRV_PCM_FORMAT_S16_LE: | ||
241 | format = 0; | ||
242 | len = 16; | ||
243 | break; | ||
244 | case SNDRV_PCM_FORMAT_S24_LE: | ||
245 | format = 1; | ||
246 | len = 24; | ||
247 | break; | ||
248 | case SNDRV_PCM_FORMAT_S32_LE: | ||
249 | format = 2; | ||
250 | len = 32; | ||
251 | break; | ||
252 | default: | ||
253 | dev_err(socdai->dev, "Unknown data format\n"); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | val |= ZX_I2S_TIMING_TS_WIDTH(len) | ZX_I2S_TIMING_DATA_SIZE(len); | ||
257 | |||
258 | ch_num = params_channels(params); | ||
259 | switch (ch_num) { | ||
260 | case 1: | ||
261 | lane = 1; | ||
262 | chn_cfg = 2; | ||
263 | break; | ||
264 | case 2: | ||
265 | case 4: | ||
266 | case 6: | ||
267 | case 8: | ||
268 | lane = ch_num / 2; | ||
269 | chn_cfg = 3; | ||
270 | break; | ||
271 | default: | ||
272 | dev_err(socdai->dev, "Not support channel num %d\n", ch_num); | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | val |= ZX_I2S_TIMING_LANE(lane); | ||
276 | val |= ZX_I2S_TIMING_TSCFG(chn_cfg); | ||
277 | val |= ZX_I2S_TIMING_CHN(ch_num); | ||
278 | writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); | ||
279 | |||
280 | if (i2s->master) | ||
281 | ret = clk_set_rate(i2s->dai_clk, | ||
282 | params_rate(params) * ch_num * CLK_RAT); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
287 | struct snd_soc_dai *dai) | ||
288 | { | ||
289 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | ||
290 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | ||
291 | int ret = 0; | ||
292 | |||
293 | switch (cmd) { | ||
294 | case SNDRV_PCM_TRIGGER_START: | ||
295 | if (capture) | ||
296 | zx_i2s_rx_dma_en(zx_i2s->reg_base, true); | ||
297 | else | ||
298 | zx_i2s_tx_dma_en(zx_i2s->reg_base, true); | ||
299 | /* fall thru */ | ||
300 | case SNDRV_PCM_TRIGGER_RESUME: | ||
301 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
302 | if (capture) | ||
303 | zx_i2s_rx_en(zx_i2s->reg_base, true); | ||
304 | else | ||
305 | zx_i2s_tx_en(zx_i2s->reg_base, true); | ||
306 | break; | ||
307 | |||
308 | case SNDRV_PCM_TRIGGER_STOP: | ||
309 | if (capture) | ||
310 | zx_i2s_rx_dma_en(zx_i2s->reg_base, false); | ||
311 | else | ||
312 | zx_i2s_tx_dma_en(zx_i2s->reg_base, false); | ||
313 | /* fall thru */ | ||
314 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
315 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
316 | if (capture) | ||
317 | zx_i2s_rx_en(zx_i2s->reg_base, false); | ||
318 | else | ||
319 | zx_i2s_tx_en(zx_i2s->reg_base, false); | ||
320 | break; | ||
321 | |||
322 | default: | ||
323 | ret = -EINVAL; | ||
324 | break; | ||
325 | } | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | static int zx_i2s_startup(struct snd_pcm_substream *substream, | ||
331 | struct snd_soc_dai *dai) | ||
332 | { | ||
333 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | ||
334 | |||
335 | return clk_prepare_enable(zx_i2s->dai_clk); | ||
336 | } | ||
337 | |||
338 | static void zx_i2s_shutdown(struct snd_pcm_substream *substream, | ||
339 | struct snd_soc_dai *dai) | ||
340 | { | ||
341 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | ||
342 | |||
343 | clk_disable_unprepare(zx_i2s->dai_clk); | ||
344 | } | ||
345 | |||
346 | static struct snd_soc_dai_ops zx_i2s_dai_ops = { | ||
347 | .trigger = zx_i2s_trigger, | ||
348 | .hw_params = zx_i2s_hw_params, | ||
349 | .set_fmt = zx_i2s_set_fmt, | ||
350 | .startup = zx_i2s_startup, | ||
351 | .shutdown = zx_i2s_shutdown, | ||
352 | }; | ||
353 | |||
354 | static const struct snd_soc_component_driver zx_i2s_component = { | ||
355 | .name = "zx-i2s", | ||
356 | }; | ||
357 | |||
358 | static struct snd_soc_dai_driver zx_i2s_dai = { | ||
359 | .name = "zx-i2s-dai", | ||
360 | .id = 0, | ||
361 | .probe = zx_i2s_dai_probe, | ||
362 | .playback = { | ||
363 | .channels_min = 1, | ||
364 | .channels_max = 8, | ||
365 | .rates = ZX_I2S_RATES, | ||
366 | .formats = ZX_I2S_FMTBIT, | ||
367 | }, | ||
368 | .capture = { | ||
369 | .channels_min = 1, | ||
370 | .channels_max = 2, | ||
371 | .rates = ZX_I2S_RATES, | ||
372 | .formats = ZX_I2S_FMTBIT, | ||
373 | }, | ||
374 | .ops = &zx_i2s_dai_ops, | ||
375 | }; | ||
376 | |||
377 | static int zx_i2s_probe(struct platform_device *pdev) | ||
378 | { | ||
379 | struct resource *res; | ||
380 | struct zx_i2s_info *zx_i2s; | ||
381 | int ret; | ||
382 | |||
383 | zx_i2s = kzalloc(sizeof(*zx_i2s), GFP_KERNEL); | ||
384 | if (!zx_i2s) | ||
385 | return -ENOMEM; | ||
386 | |||
387 | zx_i2s->dai_clk = devm_clk_get(&pdev->dev, "tx"); | ||
388 | if (IS_ERR(zx_i2s->dai_clk)) { | ||
389 | dev_err(&pdev->dev, "Fail to get clk\n"); | ||
390 | return PTR_ERR(zx_i2s->dai_clk); | ||
391 | } | ||
392 | |||
393 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
394 | zx_i2s->mapbase = res->start; | ||
395 | zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res); | ||
396 | if (!zx_i2s->reg_base) { | ||
397 | dev_err(&pdev->dev, "ioremap failed!\n"); | ||
398 | return -EIO; | ||
399 | } | ||
400 | |||
401 | writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL); | ||
402 | platform_set_drvdata(pdev, zx_i2s); | ||
403 | |||
404 | ret = snd_soc_register_component(&pdev->dev, &zx_i2s_component, | ||
405 | &zx_i2s_dai, 1); | ||
406 | if (ret) { | ||
407 | dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
412 | if (ret) | ||
413 | dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); | ||
414 | |||
415 | return ret; | ||
416 | } | ||
417 | |||
418 | static const struct of_device_id zx_i2s_dt_ids[] = { | ||
419 | { .compatible = "zte,zx296702-i2s", }, | ||
420 | {} | ||
421 | }; | ||
422 | MODULE_DEVICE_TABLE(of, zx_i2s_dt_ids); | ||
423 | |||
424 | static struct platform_driver i2s_driver = { | ||
425 | .probe = zx_i2s_probe, | ||
426 | .driver = { | ||
427 | .name = "zx-i2s", | ||
428 | .of_match_table = zx_i2s_dt_ids, | ||
429 | }, | ||
430 | }; | ||
431 | |||
432 | module_platform_driver(i2s_driver); | ||
433 | |||
434 | MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>"); | ||
435 | MODULE_DESCRIPTION("ZTE I2S SoC DAI"); | ||
436 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/zte/zx296702-spdif.c b/sound/soc/zte/zx296702-spdif.c new file mode 100644 index 000000000000..11a0e46a1156 --- /dev/null +++ b/sound/soc/zte/zx296702-spdif.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Linaro | ||
3 | * | ||
4 | * Author: Jun Nie <jun.nie@linaro.org> | ||
5 | * | ||
6 | * License terms: GNU General Public License (GPL) version 2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/clk.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/dmaengine.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <sound/asoundef.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/dmaengine_pcm.h> | ||
20 | #include <sound/initval.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/soc-dai.h> | ||
25 | |||
26 | #define ZX_CTRL 0x04 | ||
27 | #define ZX_FIFOCTRL 0x08 | ||
28 | #define ZX_INT_STATUS 0x10 | ||
29 | #define ZX_INT_MASK 0x14 | ||
30 | #define ZX_DATA 0x18 | ||
31 | #define ZX_VALID_BIT 0x1c | ||
32 | #define ZX_CH_STA_1 0x20 | ||
33 | #define ZX_CH_STA_2 0x24 | ||
34 | #define ZX_CH_STA_3 0x28 | ||
35 | #define ZX_CH_STA_4 0x2c | ||
36 | #define ZX_CH_STA_5 0x30 | ||
37 | #define ZX_CH_STA_6 0x34 | ||
38 | |||
39 | #define ZX_CTRL_MODA_16 (0 << 6) | ||
40 | #define ZX_CTRL_MODA_18 BIT(6) | ||
41 | #define ZX_CTRL_MODA_20 (2 << 6) | ||
42 | #define ZX_CTRL_MODA_24 (3 << 6) | ||
43 | #define ZX_CTRL_MODA_MASK (3 << 6) | ||
44 | |||
45 | #define ZX_CTRL_ENB BIT(4) | ||
46 | #define ZX_CTRL_DNB (0 << 4) | ||
47 | #define ZX_CTRL_ENB_MASK BIT(4) | ||
48 | |||
49 | #define ZX_CTRL_TX_OPEN BIT(0) | ||
50 | #define ZX_CTRL_TX_CLOSE (0 << 0) | ||
51 | #define ZX_CTRL_TX_MASK BIT(0) | ||
52 | |||
53 | #define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB) | ||
54 | #define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB) | ||
55 | |||
56 | #define ZX_CTRL_DOUBLE_TRACK (0 << 8) | ||
57 | #define ZX_CTRL_LEFT_TRACK BIT(8) | ||
58 | #define ZX_CTRL_RIGHT_TRACK (2 << 8) | ||
59 | #define ZX_CTRL_TRACK_MASK (3 << 8) | ||
60 | |||
61 | #define ZX_FIFOCTRL_TXTH_MASK (0x1f << 8) | ||
62 | #define ZX_FIFOCTRL_TXTH(x) (x << 8) | ||
63 | #define ZX_FIFOCTRL_TX_DMA_EN BIT(2) | ||
64 | #define ZX_FIFOCTRL_TX_DMA_DIS (0 << 2) | ||
65 | #define ZX_FIFOCTRL_TX_DMA_EN_MASK BIT(2) | ||
66 | #define ZX_FIFOCTRL_TX_FIFO_RST BIT(0) | ||
67 | #define ZX_FIFOCTRL_TX_FIFO_RST_MASK BIT(0) | ||
68 | |||
69 | #define ZX_VALID_DOUBLE_TRACK (0 << 0) | ||
70 | #define ZX_VALID_LEFT_TRACK BIT(1) | ||
71 | #define ZX_VALID_RIGHT_TRACK (2 << 0) | ||
72 | #define ZX_VALID_TRACK_MASK (3 << 0) | ||
73 | |||
74 | #define ZX_SPDIF_CLK_RAT (4 * 32) | ||
75 | |||
76 | struct zx_spdif_info { | ||
77 | struct snd_dmaengine_dai_dma_data dma_data; | ||
78 | struct clk *dai_clk; | ||
79 | void __iomem *reg_base; | ||
80 | resource_size_t mapbase; | ||
81 | }; | ||
82 | |||
83 | static int zx_spdif_dai_probe(struct snd_soc_dai *dai) | ||
84 | { | ||
85 | struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); | ||
86 | |||
87 | snd_soc_dai_set_drvdata(dai, zx_spdif); | ||
88 | zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA; | ||
89 | zx_spdif->dma_data.maxburst = 8; | ||
90 | snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int zx_spdif_chanstats(void __iomem *base, unsigned int rate) | ||
95 | { | ||
96 | u32 cstas1; | ||
97 | |||
98 | switch (rate) { | ||
99 | case 22050: | ||
100 | cstas1 = IEC958_AES3_CON_FS_22050; | ||
101 | break; | ||
102 | case 24000: | ||
103 | cstas1 = IEC958_AES3_CON_FS_24000; | ||
104 | break; | ||
105 | case 32000: | ||
106 | cstas1 = IEC958_AES3_CON_FS_32000; | ||
107 | break; | ||
108 | case 44100: | ||
109 | cstas1 = IEC958_AES3_CON_FS_44100; | ||
110 | break; | ||
111 | case 48000: | ||
112 | cstas1 = IEC958_AES3_CON_FS_48000; | ||
113 | break; | ||
114 | case 88200: | ||
115 | cstas1 = IEC958_AES3_CON_FS_88200; | ||
116 | break; | ||
117 | case 96000: | ||
118 | cstas1 = IEC958_AES3_CON_FS_96000; | ||
119 | break; | ||
120 | case 176400: | ||
121 | cstas1 = IEC958_AES3_CON_FS_176400; | ||
122 | break; | ||
123 | case 192000: | ||
124 | cstas1 = IEC958_AES3_CON_FS_192000; | ||
125 | break; | ||
126 | default: | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | cstas1 = cstas1 << 24; | ||
130 | cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT; | ||
131 | |||
132 | writel_relaxed(cstas1, base + ZX_CH_STA_1); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int zx_spdif_hw_params(struct snd_pcm_substream *substream, | ||
137 | struct snd_pcm_hw_params *params, | ||
138 | struct snd_soc_dai *socdai) | ||
139 | { | ||
140 | struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev); | ||
141 | struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai); | ||
142 | struct snd_dmaengine_dai_dma_data *dma_data = &zx_spdif->dma_data; | ||
143 | u32 val, ch_num, rate; | ||
144 | int ret; | ||
145 | |||
146 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); | ||
147 | dma_data->addr_width = params_width(params) >> 3; | ||
148 | |||
149 | val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL); | ||
150 | val &= ~ZX_CTRL_MODA_MASK; | ||
151 | switch (params_format(params)) { | ||
152 | case SNDRV_PCM_FORMAT_S16_LE: | ||
153 | val |= ZX_CTRL_MODA_16; | ||
154 | break; | ||
155 | |||
156 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
157 | val |= ZX_CTRL_MODA_18; | ||
158 | break; | ||
159 | |||
160 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
161 | val |= ZX_CTRL_MODA_20; | ||
162 | break; | ||
163 | |||
164 | case SNDRV_PCM_FORMAT_S24_LE: | ||
165 | val |= ZX_CTRL_MODA_24; | ||
166 | break; | ||
167 | default: | ||
168 | dev_err(socdai->dev, "Format not support!\n"); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | ch_num = params_channels(params); | ||
173 | if (ch_num == 2) | ||
174 | val |= ZX_CTRL_DOUBLE_TRACK; | ||
175 | else | ||
176 | val |= ZX_CTRL_LEFT_TRACK; | ||
177 | writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL); | ||
178 | |||
179 | val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT); | ||
180 | val &= ~ZX_VALID_TRACK_MASK; | ||
181 | if (ch_num == 2) | ||
182 | val |= ZX_VALID_DOUBLE_TRACK; | ||
183 | else | ||
184 | val |= ZX_VALID_RIGHT_TRACK; | ||
185 | writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT); | ||
186 | |||
187 | rate = params_rate(params); | ||
188 | ret = zx_spdif_chanstats(zx_spdif->reg_base, rate); | ||
189 | if (ret) | ||
190 | return ret; | ||
191 | return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT); | ||
192 | } | ||
193 | |||
194 | static void zx_spdif_cfg_tx(void __iomem *base, int on) | ||
195 | { | ||
196 | u32 val; | ||
197 | |||
198 | val = readl_relaxed(base + ZX_CTRL); | ||
199 | val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK); | ||
200 | val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE; | ||
201 | writel_relaxed(val, base + ZX_CTRL); | ||
202 | |||
203 | val = readl_relaxed(base + ZX_FIFOCTRL); | ||
204 | val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK; | ||
205 | if (on) | ||
206 | val |= ZX_FIFOCTRL_TX_DMA_EN; | ||
207 | writel_relaxed(val, base + ZX_FIFOCTRL); | ||
208 | } | ||
209 | |||
210 | static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
211 | struct snd_soc_dai *dai) | ||
212 | { | ||
213 | u32 val; | ||
214 | struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); | ||
215 | int ret = 0; | ||
216 | |||
217 | switch (cmd) { | ||
218 | case SNDRV_PCM_TRIGGER_START: | ||
219 | val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL); | ||
220 | val |= ZX_FIFOCTRL_TX_FIFO_RST; | ||
221 | writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL); | ||
222 | /* fall thru */ | ||
223 | case SNDRV_PCM_TRIGGER_RESUME: | ||
224 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
225 | zx_spdif_cfg_tx(zx_spdif->reg_base, true); | ||
226 | break; | ||
227 | |||
228 | case SNDRV_PCM_TRIGGER_STOP: | ||
229 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
230 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
231 | zx_spdif_cfg_tx(zx_spdif->reg_base, false); | ||
232 | break; | ||
233 | |||
234 | default: | ||
235 | ret = -EINVAL; | ||
236 | break; | ||
237 | } | ||
238 | |||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static int zx_spdif_startup(struct snd_pcm_substream *substream, | ||
243 | struct snd_soc_dai *dai) | ||
244 | { | ||
245 | struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); | ||
246 | |||
247 | return clk_prepare_enable(zx_spdif->dai_clk); | ||
248 | } | ||
249 | |||
250 | static void zx_spdif_shutdown(struct snd_pcm_substream *substream, | ||
251 | struct snd_soc_dai *dai) | ||
252 | { | ||
253 | struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); | ||
254 | |||
255 | clk_disable_unprepare(zx_spdif->dai_clk); | ||
256 | } | ||
257 | |||
258 | #define ZX_RATES \ | ||
259 | (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
260 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ | ||
261 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | ||
262 | |||
263 | #define ZX_FORMAT \ | ||
264 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ | ||
265 | | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
266 | |||
267 | static struct snd_soc_dai_ops zx_spdif_dai_ops = { | ||
268 | .trigger = zx_spdif_trigger, | ||
269 | .startup = zx_spdif_startup, | ||
270 | .shutdown = zx_spdif_shutdown, | ||
271 | .hw_params = zx_spdif_hw_params, | ||
272 | }; | ||
273 | |||
274 | static struct snd_soc_dai_driver zx_spdif_dai = { | ||
275 | .name = "spdif", | ||
276 | .id = 0, | ||
277 | .probe = zx_spdif_dai_probe, | ||
278 | .playback = { | ||
279 | .channels_min = 1, | ||
280 | .channels_max = 2, | ||
281 | .rates = ZX_RATES, | ||
282 | .formats = ZX_FORMAT, | ||
283 | }, | ||
284 | .ops = &zx_spdif_dai_ops, | ||
285 | }; | ||
286 | |||
287 | static const struct snd_soc_component_driver zx_spdif_component = { | ||
288 | .name = "spdif", | ||
289 | }; | ||
290 | |||
291 | static void zx_spdif_dev_init(void __iomem *base) | ||
292 | { | ||
293 | u32 val; | ||
294 | |||
295 | writel_relaxed(0, base + ZX_CTRL); | ||
296 | writel_relaxed(0, base + ZX_INT_MASK); | ||
297 | writel_relaxed(0xf, base + ZX_INT_STATUS); | ||
298 | writel_relaxed(0x1, base + ZX_FIFOCTRL); | ||
299 | |||
300 | val = readl_relaxed(base + ZX_FIFOCTRL); | ||
301 | val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK); | ||
302 | val |= ZX_FIFOCTRL_TXTH(8); | ||
303 | writel_relaxed(val, base + ZX_FIFOCTRL); | ||
304 | } | ||
305 | |||
306 | static int zx_spdif_probe(struct platform_device *pdev) | ||
307 | { | ||
308 | struct resource *res; | ||
309 | struct zx_spdif_info *zx_spdif; | ||
310 | int ret; | ||
311 | |||
312 | zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL); | ||
313 | if (!zx_spdif) | ||
314 | return -ENOMEM; | ||
315 | |||
316 | zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx"); | ||
317 | if (IS_ERR(zx_spdif->dai_clk)) { | ||
318 | dev_err(&pdev->dev, "Fail to get clk\n"); | ||
319 | return PTR_ERR(zx_spdif->dai_clk); | ||
320 | } | ||
321 | |||
322 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
323 | zx_spdif->mapbase = res->start; | ||
324 | zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res); | ||
325 | if (!zx_spdif->reg_base) { | ||
326 | dev_err(&pdev->dev, "ioremap failed!\n"); | ||
327 | return -EIO; | ||
328 | } | ||
329 | |||
330 | zx_spdif_dev_init(zx_spdif->reg_base); | ||
331 | platform_set_drvdata(pdev, zx_spdif); | ||
332 | |||
333 | ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component, | ||
334 | &zx_spdif_dai, 1); | ||
335 | if (ret) { | ||
336 | dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
341 | if (ret) | ||
342 | dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); | ||
343 | |||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | static const struct of_device_id zx_spdif_dt_ids[] = { | ||
348 | { .compatible = "zte,zx296702-spdif", }, | ||
349 | {} | ||
350 | }; | ||
351 | MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids); | ||
352 | |||
353 | static struct platform_driver spdif_driver = { | ||
354 | .probe = zx_spdif_probe, | ||
355 | .driver = { | ||
356 | .name = "zx-spdif", | ||
357 | .of_match_table = zx_spdif_dt_ids, | ||
358 | }, | ||
359 | }; | ||
360 | |||
361 | module_platform_driver(spdif_driver); | ||
362 | |||
363 | MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>"); | ||
364 | MODULE_DESCRIPTION("ZTE SPDIF SoC DAI"); | ||
365 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c index b155137ee312..026347643c81 100644 --- a/sound/sound_firmware.c +++ b/sound/sound_firmware.c | |||
@@ -12,7 +12,6 @@ static int do_mod_firmware_load(const char *fn, char **fp) | |||
12 | struct file* filp; | 12 | struct file* filp; |
13 | long l; | 13 | long l; |
14 | char *dp; | 14 | char *dp; |
15 | loff_t pos; | ||
16 | 15 | ||
17 | filp = filp_open(fn, 0, 0); | 16 | filp = filp_open(fn, 0, 0); |
18 | if (IS_ERR(filp)) | 17 | if (IS_ERR(filp)) |
@@ -34,8 +33,7 @@ static int do_mod_firmware_load(const char *fn, char **fp) | |||
34 | fput(filp); | 33 | fput(filp); |
35 | return 0; | 34 | return 0; |
36 | } | 35 | } |
37 | pos = 0; | 36 | if (kernel_read(filp, 0, dp, l) != l) |
38 | if (vfs_read(filp, dp, l, &pos) != l) | ||
39 | { | 37 | { |
40 | printk(KERN_INFO "Failed to read '%s'.\n", fn); | 38 | printk(KERN_INFO "Failed to read '%s'.\n", fn); |
41 | vfree(dp); | 39 | vfree(dp); |
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile index 328594e6152d..fb761c2c2b50 100644 --- a/sound/synth/emux/Makefile +++ b/sound/synth/emux/Makefile | |||
@@ -4,8 +4,9 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ | 6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ |
7 | emux_effect.o emux_proc.o emux_hwdep.o soundfont.o \ | 7 | emux_effect.o emux_hwdep.o soundfont.o |
8 | $(if $(CONFIG_SND_SEQUENCER_OSS),emux_oss.o) | 8 | snd-emux-synth-$(CONFIG_SND_PROC_FS) += emux_proc.o |
9 | snd-emux-synth-$(CONFIG_SND_SEQUENCER_OSS) += emux_oss.o | ||
9 | 10 | ||
10 | # Toplevel Module Dependencies | 11 | # Toplevel Module Dependencies |
11 | obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emux-synth.o | 12 | obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emux-synth.o |
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 49195325fdf6..9312cd8a6fdd 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c | |||
@@ -128,9 +128,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch | |||
128 | #endif | 128 | #endif |
129 | snd_emux_init_virmidi(emu, card); | 129 | snd_emux_init_virmidi(emu, card); |
130 | 130 | ||
131 | #ifdef CONFIG_PROC_FS | ||
132 | snd_emux_proc_init(emu, card, index); | 131 | snd_emux_proc_init(emu, card, index); |
133 | #endif | ||
134 | return 0; | 132 | return 0; |
135 | } | 133 | } |
136 | 134 | ||
@@ -150,9 +148,7 @@ int snd_emux_free(struct snd_emux *emu) | |||
150 | del_timer(&emu->tlist); | 148 | del_timer(&emu->tlist); |
151 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 149 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
152 | 150 | ||
153 | #ifdef CONFIG_PROC_FS | ||
154 | snd_emux_proc_free(emu); | 151 | snd_emux_proc_free(emu); |
155 | #endif | ||
156 | snd_emux_delete_virmidi(emu); | 152 | snd_emux_delete_virmidi(emu); |
157 | #ifdef CONFIG_SND_SEQUENCER_OSS | 153 | #ifdef CONFIG_SND_SEQUENCER_OSS |
158 | snd_emux_detach_seq_oss(emu); | 154 | snd_emux_detach_seq_oss(emu); |
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index ab37add269ae..82e350e9501c 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c | |||
@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) | |||
118 | if (snd_BUG_ON(!arg || !emu)) | 118 | if (snd_BUG_ON(!arg || !emu)) |
119 | return -ENXIO; | 119 | return -ENXIO; |
120 | 120 | ||
121 | mutex_lock(&emu->register_mutex); | 121 | if (!snd_emux_inc_count(emu)) |
122 | |||
123 | if (!snd_emux_inc_count(emu)) { | ||
124 | mutex_unlock(&emu->register_mutex); | ||
125 | return -EFAULT; | 122 | return -EFAULT; |
126 | } | ||
127 | 123 | ||
128 | memset(&callback, 0, sizeof(callback)); | 124 | memset(&callback, 0, sizeof(callback)); |
129 | callback.owner = THIS_MODULE; | 125 | callback.owner = THIS_MODULE; |
@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) | |||
135 | if (p == NULL) { | 131 | if (p == NULL) { |
136 | snd_printk(KERN_ERR "can't create port\n"); | 132 | snd_printk(KERN_ERR "can't create port\n"); |
137 | snd_emux_dec_count(emu); | 133 | snd_emux_dec_count(emu); |
138 | mutex_unlock(&emu->register_mutex); | ||
139 | return -ENOMEM; | 134 | return -ENOMEM; |
140 | } | 135 | } |
141 | 136 | ||
@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) | |||
148 | reset_port_mode(p, arg->seq_mode); | 143 | reset_port_mode(p, arg->seq_mode); |
149 | 144 | ||
150 | snd_emux_reset_port(p); | 145 | snd_emux_reset_port(p); |
151 | |||
152 | mutex_unlock(&emu->register_mutex); | ||
153 | return 0; | 146 | return 0; |
154 | } | 147 | } |
155 | 148 | ||
@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) | |||
195 | if (snd_BUG_ON(!emu)) | 188 | if (snd_BUG_ON(!emu)) |
196 | return -ENXIO; | 189 | return -ENXIO; |
197 | 190 | ||
198 | mutex_lock(&emu->register_mutex); | ||
199 | snd_emux_sounds_off_all(p); | 191 | snd_emux_sounds_off_all(p); |
200 | snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); | 192 | snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); |
201 | snd_seq_event_port_detach(p->chset.client, p->chset.port); | 193 | snd_seq_event_port_detach(p->chset.client, p->chset.port); |
202 | snd_emux_dec_count(emu); | 194 | snd_emux_dec_count(emu); |
203 | 195 | ||
204 | mutex_unlock(&emu->register_mutex); | ||
205 | return 0; | 196 | return 0; |
206 | } | 197 | } |
207 | 198 | ||
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index 58a32a10d115..a82b4053bee8 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include <sound/info.h> | 24 | #include <sound/info.h> |
25 | #include "emux_voice.h" | 25 | #include "emux_voice.h" |
26 | 26 | ||
27 | #ifdef CONFIG_PROC_FS | ||
28 | |||
29 | static void | 27 | static void |
30 | snd_emux_proc_info_read(struct snd_info_entry *entry, | 28 | snd_emux_proc_info_read(struct snd_info_entry *entry, |
31 | struct snd_info_buffer *buf) | 29 | struct snd_info_buffer *buf) |
@@ -128,5 +126,3 @@ void snd_emux_proc_free(struct snd_emux *emu) | |||
128 | snd_info_free_entry(emu->proc); | 126 | snd_info_free_entry(emu->proc); |
129 | emu->proc = NULL; | 127 | emu->proc = NULL; |
130 | } | 128 | } |
131 | |||
132 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 7778b8e19782..a0209204ae48 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c | |||
@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu) | |||
124 | if (emu->voices) | 124 | if (emu->voices) |
125 | snd_emux_terminate_all(emu); | 125 | snd_emux_terminate_all(emu); |
126 | 126 | ||
127 | mutex_lock(&emu->register_mutex); | ||
128 | if (emu->client >= 0) { | 127 | if (emu->client >= 0) { |
129 | snd_seq_delete_kernel_client(emu->client); | 128 | snd_seq_delete_kernel_client(emu->client); |
130 | emu->client = -1; | 129 | emu->client = -1; |
131 | } | 130 | } |
132 | mutex_unlock(&emu->register_mutex); | ||
133 | } | 131 | } |
134 | 132 | ||
135 | 133 | ||
@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, | |||
269 | /* | 267 | /* |
270 | * increment usage count | 268 | * increment usage count |
271 | */ | 269 | */ |
272 | int | 270 | static int |
273 | snd_emux_inc_count(struct snd_emux *emu) | 271 | __snd_emux_inc_count(struct snd_emux *emu) |
274 | { | 272 | { |
275 | emu->used++; | 273 | emu->used++; |
276 | if (!try_module_get(emu->ops.owner)) | 274 | if (!try_module_get(emu->ops.owner)) |
@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu) | |||
284 | return 1; | 282 | return 1; |
285 | } | 283 | } |
286 | 284 | ||
285 | int snd_emux_inc_count(struct snd_emux *emu) | ||
286 | { | ||
287 | int ret; | ||
288 | |||
289 | mutex_lock(&emu->register_mutex); | ||
290 | ret = __snd_emux_inc_count(emu); | ||
291 | mutex_unlock(&emu->register_mutex); | ||
292 | return ret; | ||
293 | } | ||
287 | 294 | ||
288 | /* | 295 | /* |
289 | * decrease usage count | 296 | * decrease usage count |
290 | */ | 297 | */ |
291 | void | 298 | static void |
292 | snd_emux_dec_count(struct snd_emux *emu) | 299 | __snd_emux_dec_count(struct snd_emux *emu) |
293 | { | 300 | { |
294 | module_put(emu->card->module); | 301 | module_put(emu->card->module); |
295 | emu->used--; | 302 | emu->used--; |
@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu) | |||
298 | module_put(emu->ops.owner); | 305 | module_put(emu->ops.owner); |
299 | } | 306 | } |
300 | 307 | ||
308 | void snd_emux_dec_count(struct snd_emux *emu) | ||
309 | { | ||
310 | mutex_lock(&emu->register_mutex); | ||
311 | __snd_emux_dec_count(emu); | ||
312 | mutex_unlock(&emu->register_mutex); | ||
313 | } | ||
301 | 314 | ||
302 | /* | 315 | /* |
303 | * Routine that is called upon a first use of a particular port | 316 | * Routine that is called upon a first use of a particular port |
@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) | |||
317 | 330 | ||
318 | mutex_lock(&emu->register_mutex); | 331 | mutex_lock(&emu->register_mutex); |
319 | snd_emux_init_port(p); | 332 | snd_emux_init_port(p); |
320 | snd_emux_inc_count(emu); | 333 | __snd_emux_inc_count(emu); |
321 | mutex_unlock(&emu->register_mutex); | 334 | mutex_unlock(&emu->register_mutex); |
322 | return 0; | 335 | return 0; |
323 | } | 336 | } |
@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) | |||
340 | 353 | ||
341 | mutex_lock(&emu->register_mutex); | 354 | mutex_lock(&emu->register_mutex); |
342 | snd_emux_sounds_off_all(p); | 355 | snd_emux_sounds_off_all(p); |
343 | snd_emux_dec_count(emu); | 356 | __snd_emux_dec_count(emu); |
344 | mutex_unlock(&emu->register_mutex); | 357 | mutex_unlock(&emu->register_mutex); |
345 | return 0; | 358 | return 0; |
346 | } | 359 | } |
diff --git a/sound/synth/emux/emux_voice.h b/sound/synth/emux/emux_voice.h index 09711f84ed30..a7073c371bcc 100644 --- a/sound/synth/emux/emux_voice.h +++ b/sound/synth/emux/emux_voice.h | |||
@@ -82,9 +82,13 @@ void snd_emux_init_seq_oss(struct snd_emux *emu); | |||
82 | void snd_emux_detach_seq_oss(struct snd_emux *emu); | 82 | void snd_emux_detach_seq_oss(struct snd_emux *emu); |
83 | 83 | ||
84 | /* emux_proc.c */ | 84 | /* emux_proc.c */ |
85 | #ifdef CONFIG_PROC_FS | 85 | #ifdef CONFIG_SND_PROC_FS |
86 | void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device); | 86 | void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device); |
87 | void snd_emux_proc_free(struct snd_emux *emu); | 87 | void snd_emux_proc_free(struct snd_emux *emu); |
88 | #else | ||
89 | static inline void snd_emux_proc_init(struct snd_emux *emu, | ||
90 | struct snd_card *card, int device) {} | ||
91 | static inline void snd_emux_proc_free(struct snd_emux *emu) {} | ||
88 | #endif | 92 | #endif |
89 | 93 | ||
90 | #define STATE_IS_PLAYING(s) ((s) & SNDRV_EMUX_ST_ON) | 94 | #define STATE_IS_PLAYING(s) ((s) & SNDRV_EMUX_ST_ON) |
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c index 820d6ca8c458..d060dddcc52d 100644 --- a/sound/usb/bcd2000/bcd2000.c +++ b/sound/usb/bcd2000/bcd2000.c | |||
@@ -70,7 +70,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | |||
70 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 70 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
71 | 71 | ||
72 | static DEFINE_MUTEX(devices_mutex); | 72 | static DEFINE_MUTEX(devices_mutex); |
73 | DECLARE_BITMAP(devices_used, SNDRV_CARDS); | 73 | static DECLARE_BITMAP(devices_used, SNDRV_CARDS); |
74 | static struct usb_driver bcd2000_driver; | 74 | static struct usb_driver bcd2000_driver; |
75 | 75 | ||
76 | #ifdef CONFIG_SND_DEBUG | 76 | #ifdef CONFIG_SND_DEBUG |
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 8461d6bf992f..204cc074adb9 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c | |||
@@ -186,12 +186,8 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, | |||
186 | int ret = 0; | 186 | int ret = 0; |
187 | 187 | ||
188 | spin_lock_irqsave(&pstr->lock, flags); | 188 | spin_lock_irqsave(&pstr->lock, flags); |
189 | if (!test_and_set_bit(type, &pstr->running)) { | 189 | if (!test_and_set_bit(type, &pstr->running) && |
190 | if (pstr->active_urbs || pstr->unlink_urbs) { | 190 | !(pstr->active_urbs || pstr->unlink_urbs)) { |
191 | ret = -EBUSY; | ||
192 | goto error; | ||
193 | } | ||
194 | |||
195 | pstr->count = 0; | 191 | pstr->count = 0; |
196 | /* Submit all currently available URBs */ | 192 | /* Submit all currently available URBs */ |
197 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) | 193 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -199,7 +195,6 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, | |||
199 | else | 195 | else |
200 | ret = line6_submit_audio_in_all_urbs(line6pcm); | 196 | ret = line6_submit_audio_in_all_urbs(line6pcm); |
201 | } | 197 | } |
202 | error: | ||
203 | if (ret < 0) | 198 | if (ret < 0) |
204 | clear_bit(type, &pstr->running); | 199 | clear_bit(type, &pstr->running); |
205 | spin_unlock_irqrestore(&pstr->lock, flags); | 200 | spin_unlock_irqrestore(&pstr->lock, flags); |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 3e2ef61c627b..6b3acba5da7a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -809,12 +809,12 @@ static struct usb_feature_control_info audio_feature_info[] = { | |||
809 | { "Tone Control - Treble", USB_MIXER_S8 }, | 809 | { "Tone Control - Treble", USB_MIXER_S8 }, |
810 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ | 810 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ |
811 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, | 811 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, |
812 | { "Delay Control", USB_MIXER_U16 }, | 812 | { "Delay Control", USB_MIXER_U16 }, /* FIXME: U32 in UAC2 */ |
813 | { "Bass Boost", USB_MIXER_BOOLEAN }, | 813 | { "Bass Boost", USB_MIXER_BOOLEAN }, |
814 | { "Loudness", USB_MIXER_BOOLEAN }, | 814 | { "Loudness", USB_MIXER_BOOLEAN }, |
815 | /* UAC2 specific */ | 815 | /* UAC2 specific */ |
816 | { "Input Gain Control", USB_MIXER_U16 }, | 816 | { "Input Gain Control", USB_MIXER_S16 }, |
817 | { "Input Gain Pad Control", USB_MIXER_BOOLEAN }, | 817 | { "Input Gain Pad Control", USB_MIXER_S16 }, |
818 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, | 818 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, |
819 | }; | 819 | }; |
820 | 820 | ||
@@ -918,6 +918,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
918 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ | 918 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ |
919 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ | 919 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ |
920 | case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ | 920 | case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ |
921 | case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ | ||
921 | case USB_ID(0x046d, 0x0991): | 922 | case USB_ID(0x046d, 0x0991): |
922 | /* Most audio usb devices lie about volume resolution. | 923 | /* Most audio usb devices lie about volume resolution. |
923 | * Most Logitech webcams have res = 384. | 924 | * Most Logitech webcams have res = 384. |
@@ -1582,12 +1583,6 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, | |||
1582 | unitid); | 1583 | unitid); |
1583 | return -EINVAL; | 1584 | return -EINVAL; |
1584 | } | 1585 | } |
1585 | /* no bmControls field (e.g. Maya44) -> ignore */ | ||
1586 | if (desc->bLength <= 10 + input_pins) { | ||
1587 | usb_audio_dbg(state->chip, "MU %d has no bmControls field\n", | ||
1588 | unitid); | ||
1589 | return 0; | ||
1590 | } | ||
1591 | 1586 | ||
1592 | num_ins = 0; | 1587 | num_ins = 0; |
1593 | ich = 0; | 1588 | ich = 0; |
@@ -1595,6 +1590,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, | |||
1595 | err = parse_audio_unit(state, desc->baSourceID[pin]); | 1590 | err = parse_audio_unit(state, desc->baSourceID[pin]); |
1596 | if (err < 0) | 1591 | if (err < 0) |
1597 | continue; | 1592 | continue; |
1593 | /* no bmControls field (e.g. Maya44) -> ignore */ | ||
1594 | if (desc->bLength <= 10 + input_pins) | ||
1595 | continue; | ||
1598 | err = check_input_term(state, desc->baSourceID[pin], &iterm); | 1596 | err = check_input_term(state, desc->baSourceID[pin], &iterm); |
1599 | if (err < 0) | 1597 | if (err < 0) |
1600 | return err; | 1598 | return err; |
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index b703cb3cda19..e5000da9e9d7 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c | |||
@@ -437,6 +437,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
437 | .map = ebox44_map, | 437 | .map = ebox44_map, |
438 | }, | 438 | }, |
439 | { | 439 | { |
440 | /* MAYA44 USB+ */ | ||
441 | .id = USB_ID(0x2573, 0x0008), | ||
442 | .map = maya44_map, | ||
443 | }, | ||
444 | { | ||
440 | /* KEF X300A */ | 445 | /* KEF X300A */ |
441 | .id = USB_ID(0x27ac, 0x1000), | 446 | .id = USB_ID(0x27ac, 0x1000), |
442 | .map = scms_usb3318_map, | 447 | .map = scms_usb3318_map, |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 2f6d3e9a1bcd..e4756651a52c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -2512,6 +2512,74 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2512 | } | 2512 | } |
2513 | }, | 2513 | }, |
2514 | 2514 | ||
2515 | /* Steinberg devices */ | ||
2516 | { | ||
2517 | /* Steinberg MI2 */ | ||
2518 | USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040), | ||
2519 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2520 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2521 | .type = QUIRK_COMPOSITE, | ||
2522 | .data = & (const struct snd_usb_audio_quirk[]) { | ||
2523 | { | ||
2524 | .ifnum = 0, | ||
2525 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2526 | }, | ||
2527 | { | ||
2528 | .ifnum = 1, | ||
2529 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2530 | }, | ||
2531 | { | ||
2532 | .ifnum = 2, | ||
2533 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2534 | }, | ||
2535 | { | ||
2536 | .ifnum = 3, | ||
2537 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
2538 | .data = &(const struct snd_usb_midi_endpoint_info) { | ||
2539 | .out_cables = 0x0001, | ||
2540 | .in_cables = 0x0001 | ||
2541 | } | ||
2542 | }, | ||
2543 | { | ||
2544 | .ifnum = -1 | ||
2545 | } | ||
2546 | } | ||
2547 | } | ||
2548 | }, | ||
2549 | { | ||
2550 | /* Steinberg MI4 */ | ||
2551 | USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040), | ||
2552 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2553 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2554 | .type = QUIRK_COMPOSITE, | ||
2555 | .data = & (const struct snd_usb_audio_quirk[]) { | ||
2556 | { | ||
2557 | .ifnum = 0, | ||
2558 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2559 | }, | ||
2560 | { | ||
2561 | .ifnum = 1, | ||
2562 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2563 | }, | ||
2564 | { | ||
2565 | .ifnum = 2, | ||
2566 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2567 | }, | ||
2568 | { | ||
2569 | .ifnum = 3, | ||
2570 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
2571 | .data = &(const struct snd_usb_midi_endpoint_info) { | ||
2572 | .out_cables = 0x0001, | ||
2573 | .in_cables = 0x0001 | ||
2574 | } | ||
2575 | }, | ||
2576 | { | ||
2577 | .ifnum = -1 | ||
2578 | } | ||
2579 | } | ||
2580 | } | ||
2581 | }, | ||
2582 | |||
2515 | /* TerraTec devices */ | 2583 | /* TerraTec devices */ |
2516 | { | 2584 | { |
2517 | USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), | 2585 | USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 7c5a70139278..754e689596a2 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1117,7 +1117,10 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) | |||
1117 | switch (chip->usb_id) { | 1117 | switch (chip->usb_id) { |
1118 | case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema */ | 1118 | case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema */ |
1119 | case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */ | 1119 | case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */ |
1120 | case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */ | ||
1121 | case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */ | ||
1120 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ | 1122 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ |
1123 | case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ | ||
1121 | return true; | 1124 | return true; |
1122 | } | 1125 | } |
1123 | return false; | 1126 | return false; |
@@ -1264,8 +1267,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | |||
1264 | if (fp->altsetting == 2) | 1267 | if (fp->altsetting == 2) |
1265 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; | 1268 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; |
1266 | break; | 1269 | break; |
1267 | /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */ | 1270 | |
1268 | case USB_ID(0x20b1, 0x2009): | 1271 | case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */ |
1272 | case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */ | ||
1269 | if (fp->altsetting == 3) | 1273 | if (fp->altsetting == 3) |
1270 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; | 1274 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; |
1271 | break; | 1275 | break; |