diff options
Diffstat (limited to 'sound')
152 files changed, 20055 insertions, 6731 deletions
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 58804c7acfcf..fd2188c3df2b 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c | |||
@@ -170,7 +170,7 @@ static void tas_set_volume(struct tas *tas) | |||
170 | /* analysing the volume and mixer tables shows | 170 | /* analysing the volume and mixer tables shows |
171 | * that they are similar enough when we shift | 171 | * that they are similar enough when we shift |
172 | * the mixer table down by 4 bits. The error | 172 | * the mixer table down by 4 bits. The error |
173 | * is minuscule, in just one item the error | 173 | * is miniscule, in just one item the error |
174 | * is 1, at a value of 0x07f17b (mixer table | 174 | * is 1, at a value of 0x07f17b (mixer table |
175 | * value is 0x07f17a) */ | 175 | * value is 0x07f17a) */ |
176 | tmp = tas_gaintable[left]; | 176 | tmp = tas_gaintable[left]; |
diff --git a/sound/core/control.c b/sound/core/control.c index a08ad57c49b6..5d98194bcad5 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -366,6 +366,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
366 | EXPORT_SYMBOL(snd_ctl_add); | 366 | EXPORT_SYMBOL(snd_ctl_add); |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * snd_ctl_replace - replace the control instance of the card | ||
370 | * @card: the card instance | ||
371 | * @kcontrol: the control instance to replace | ||
372 | * @add_on_replace: add the control if not already added | ||
373 | * | ||
374 | * Replaces the given control. If the given control does not exist | ||
375 | * and the add_on_replace flag is set, the control is added. If the | ||
376 | * control exists, it is destroyed first. | ||
377 | * | ||
378 | * Returns zero if successful, or a negative error code on failure. | ||
379 | * | ||
380 | * It frees automatically the control which cannot be added or replaced. | ||
381 | */ | ||
382 | int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, | ||
383 | bool add_on_replace) | ||
384 | { | ||
385 | struct snd_ctl_elem_id id; | ||
386 | unsigned int idx; | ||
387 | struct snd_kcontrol *old; | ||
388 | int ret; | ||
389 | |||
390 | if (!kcontrol) | ||
391 | return -EINVAL; | ||
392 | if (snd_BUG_ON(!card || !kcontrol->info)) { | ||
393 | ret = -EINVAL; | ||
394 | goto error; | ||
395 | } | ||
396 | id = kcontrol->id; | ||
397 | down_write(&card->controls_rwsem); | ||
398 | old = snd_ctl_find_id(card, &id); | ||
399 | if (!old) { | ||
400 | if (add_on_replace) | ||
401 | goto add; | ||
402 | up_write(&card->controls_rwsem); | ||
403 | ret = -EINVAL; | ||
404 | goto error; | ||
405 | } | ||
406 | ret = snd_ctl_remove(card, old); | ||
407 | if (ret < 0) { | ||
408 | up_write(&card->controls_rwsem); | ||
409 | goto error; | ||
410 | } | ||
411 | add: | ||
412 | if (snd_ctl_find_hole(card, kcontrol->count) < 0) { | ||
413 | up_write(&card->controls_rwsem); | ||
414 | ret = -ENOMEM; | ||
415 | goto error; | ||
416 | } | ||
417 | list_add_tail(&kcontrol->list, &card->controls); | ||
418 | card->controls_count += kcontrol->count; | ||
419 | kcontrol->id.numid = card->last_numid + 1; | ||
420 | card->last_numid += kcontrol->count; | ||
421 | up_write(&card->controls_rwsem); | ||
422 | for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) | ||
423 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); | ||
424 | return 0; | ||
425 | |||
426 | error: | ||
427 | snd_ctl_free_one(kcontrol); | ||
428 | return ret; | ||
429 | } | ||
430 | EXPORT_SYMBOL(snd_ctl_replace); | ||
431 | |||
432 | /** | ||
369 | * snd_ctl_remove - remove the control from the card and release it | 433 | * snd_ctl_remove - remove the control from the card and release it |
370 | * @card: the card instance | 434 | * @card: the card instance |
371 | * @kcontrol: the control instance to remove | 435 | * @kcontrol: the control instance to remove |
diff --git a/sound/core/init.c b/sound/core/init.c index a0080aa45ae9..30ecad41403c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) | |||
514 | id = card->id; | 514 | id = card->id; |
515 | 515 | ||
516 | if (*id == '\0') | 516 | if (*id == '\0') |
517 | strcpy(id, "default"); | 517 | strcpy(id, "Default"); |
518 | 518 | ||
519 | while (1) { | 519 | while (1) { |
520 | if (loops-- == 0) { | 520 | if (loops-- == 0) { |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 64449cb8f873..abfeff1611ce 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream) | |||
189 | #define XRUN_LOG_CNT 10 | 189 | #define XRUN_LOG_CNT 10 |
190 | 190 | ||
191 | struct hwptr_log_entry { | 191 | struct hwptr_log_entry { |
192 | unsigned int in_interrupt; | ||
192 | unsigned long jiffies; | 193 | unsigned long jiffies; |
193 | snd_pcm_uframes_t pos; | 194 | snd_pcm_uframes_t pos; |
194 | snd_pcm_uframes_t period_size; | 195 | snd_pcm_uframes_t period_size; |
@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log { | |||
204 | }; | 205 | }; |
205 | 206 | ||
206 | static void xrun_log(struct snd_pcm_substream *substream, | 207 | static void xrun_log(struct snd_pcm_substream *substream, |
207 | snd_pcm_uframes_t pos) | 208 | snd_pcm_uframes_t pos, int in_interrupt) |
208 | { | 209 | { |
209 | struct snd_pcm_runtime *runtime = substream->runtime; | 210 | struct snd_pcm_runtime *runtime = substream->runtime; |
210 | struct snd_pcm_hwptr_log *log = runtime->hwptr_log; | 211 | struct snd_pcm_hwptr_log *log = runtime->hwptr_log; |
@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream, | |||
220 | return; | 221 | return; |
221 | } | 222 | } |
222 | entry = &log->entries[log->idx]; | 223 | entry = &log->entries[log->idx]; |
224 | entry->in_interrupt = in_interrupt; | ||
223 | entry->jiffies = jiffies; | 225 | entry->jiffies = jiffies; |
224 | entry->pos = pos; | 226 | entry->pos = pos; |
225 | entry->period_size = runtime->period_size; | 227 | entry->period_size = runtime->period_size; |
@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
246 | entry = &log->entries[idx]; | 248 | entry = &log->entries[idx]; |
247 | if (entry->period_size == 0) | 249 | if (entry->period_size == 0) |
248 | break; | 250 | break; |
249 | snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, " | 251 | snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, " |
250 | "hwptr=%ld/%ld\n", | 252 | "hwptr=%ld/%ld\n", |
251 | name, entry->jiffies, (unsigned long)entry->pos, | 253 | name, entry->in_interrupt ? "[Q] " : "", |
254 | entry->jiffies, | ||
255 | (unsigned long)entry->pos, | ||
252 | (unsigned long)entry->period_size, | 256 | (unsigned long)entry->period_size, |
253 | (unsigned long)entry->buffer_size, | 257 | (unsigned long)entry->buffer_size, |
254 | (unsigned long)entry->old_hw_ptr, | 258 | (unsigned long)entry->old_hw_ptr, |
@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
262 | #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ | 266 | #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ |
263 | 267 | ||
264 | #define hw_ptr_error(substream, fmt, args...) do { } while (0) | 268 | #define hw_ptr_error(substream, fmt, args...) do { } while (0) |
265 | #define xrun_log(substream, pos) do { } while (0) | 269 | #define xrun_log(substream, pos, in_interrupt) do { } while (0) |
266 | #define xrun_log_show(substream) do { } while (0) | 270 | #define xrun_log_show(substream) do { } while (0) |
267 | 271 | ||
268 | #endif | 272 | #endif |
@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
326 | } | 330 | } |
327 | pos -= pos % runtime->min_align; | 331 | pos -= pos % runtime->min_align; |
328 | if (xrun_debug(substream, XRUN_DEBUG_LOG)) | 332 | if (xrun_debug(substream, XRUN_DEBUG_LOG)) |
329 | xrun_log(substream, pos); | 333 | xrun_log(substream, pos, in_interrupt); |
330 | hw_base = runtime->hw_ptr_base; | 334 | hw_base = runtime->hw_ptr_base; |
331 | new_hw_ptr = hw_base + pos; | 335 | new_hw_ptr = hw_base + pos; |
332 | if (in_interrupt) { | 336 | if (in_interrupt) { |
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index e486f48660fb..26071489970b 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS | |||
22 | To compile this driver as a module, choose M here: the module | 22 | To compile this driver as a module, choose M here: the module |
23 | will be called snd-firewire-speakers. | 23 | will be called snd-firewire-speakers. |
24 | 24 | ||
25 | config SND_ISIGHT | ||
26 | tristate "Apple iSight microphone" | ||
27 | select SND_PCM | ||
28 | select SND_FIREWIRE_LIB | ||
29 | help | ||
30 | Say Y here to include support for the front and rear microphones | ||
31 | of the Apple iSight web camera. | ||
32 | |||
33 | To compile this driver as a module, choose M here: the module | ||
34 | will be called snd-isight. | ||
35 | |||
25 | endif # SND_FIREWIRE | 36 | endif # SND_FIREWIRE |
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile index e5b1634d9ad4..d71ed8935f76 100644 --- a/sound/firewire/Makefile +++ b/sound/firewire/Makefile | |||
@@ -1,6 +1,8 @@ | |||
1 | snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ | 1 | snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ |
2 | fcp.o cmp.o amdtp.o | 2 | fcp.o cmp.o amdtp.o |
3 | snd-firewire-speakers-objs := speakers.o | 3 | snd-firewire-speakers-objs := speakers.o |
4 | snd-isight-objs := isight.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o | 6 | obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o |
6 | obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o | 7 | obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o |
8 | obj-$(CONFIG_SND_ISIGHT) += snd-isight.o | ||
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c new file mode 100644 index 000000000000..86ee16ca365e --- /dev/null +++ b/sound/firewire/isight.c | |||
@@ -0,0 +1,755 @@ | |||
1 | /* | ||
2 | * Apple iSight audio driver | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <asm/byteorder.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/firewire.h> | ||
12 | #include <linux/firewire-constants.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/mod_devicetable.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <sound/control.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/initval.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/tlv.h> | ||
22 | #include "lib.h" | ||
23 | #include "iso-resources.h" | ||
24 | #include "packets-buffer.h" | ||
25 | |||
26 | #define OUI_APPLE 0x000a27 | ||
27 | #define MODEL_APPLE_ISIGHT 0x000008 | ||
28 | #define SW_ISIGHT_AUDIO 0x000010 | ||
29 | |||
30 | #define REG_AUDIO_ENABLE 0x000 | ||
31 | #define AUDIO_ENABLE 0x80000000 | ||
32 | #define REG_DEF_AUDIO_GAIN 0x204 | ||
33 | #define REG_GAIN_RAW_START 0x210 | ||
34 | #define REG_GAIN_RAW_END 0x214 | ||
35 | #define REG_GAIN_DB_START 0x218 | ||
36 | #define REG_GAIN_DB_END 0x21c | ||
37 | #define REG_SAMPLE_RATE_INQUIRY 0x280 | ||
38 | #define REG_ISO_TX_CONFIG 0x300 | ||
39 | #define SPEED_SHIFT 16 | ||
40 | #define REG_SAMPLE_RATE 0x400 | ||
41 | #define RATE_48000 0x80000000 | ||
42 | #define REG_GAIN 0x500 | ||
43 | #define REG_MUTE 0x504 | ||
44 | |||
45 | #define MAX_FRAMES_PER_PACKET 475 | ||
46 | |||
47 | #define QUEUE_LENGTH 20 | ||
48 | |||
49 | struct isight { | ||
50 | struct snd_card *card; | ||
51 | struct fw_unit *unit; | ||
52 | struct fw_device *device; | ||
53 | u64 audio_base; | ||
54 | struct fw_address_handler iris_handler; | ||
55 | struct snd_pcm_substream *pcm; | ||
56 | struct mutex mutex; | ||
57 | struct iso_packets_buffer buffer; | ||
58 | struct fw_iso_resources resources; | ||
59 | struct fw_iso_context *context; | ||
60 | bool pcm_active; | ||
61 | bool pcm_running; | ||
62 | bool first_packet; | ||
63 | int packet_index; | ||
64 | u32 total_samples; | ||
65 | unsigned int buffer_pointer; | ||
66 | unsigned int period_counter; | ||
67 | s32 gain_min, gain_max; | ||
68 | unsigned int gain_tlv[4]; | ||
69 | }; | ||
70 | |||
71 | struct audio_payload { | ||
72 | __be32 sample_count; | ||
73 | __be32 signature; | ||
74 | __be32 sample_total; | ||
75 | __be32 reserved; | ||
76 | __be16 samples[2 * MAX_FRAMES_PER_PACKET]; | ||
77 | }; | ||
78 | |||
79 | MODULE_DESCRIPTION("iSight audio driver"); | ||
80 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
81 | MODULE_LICENSE("GPL v2"); | ||
82 | |||
83 | static struct fw_iso_packet audio_packet = { | ||
84 | .payload_length = sizeof(struct audio_payload), | ||
85 | .interrupt = 1, | ||
86 | .header_length = 4, | ||
87 | }; | ||
88 | |||
89 | static void isight_update_pointers(struct isight *isight, unsigned int count) | ||
90 | { | ||
91 | struct snd_pcm_runtime *runtime = isight->pcm->runtime; | ||
92 | unsigned int ptr; | ||
93 | |||
94 | smp_wmb(); /* update buffer data before buffer pointer */ | ||
95 | |||
96 | ptr = isight->buffer_pointer; | ||
97 | ptr += count; | ||
98 | if (ptr >= runtime->buffer_size) | ||
99 | ptr -= runtime->buffer_size; | ||
100 | ACCESS_ONCE(isight->buffer_pointer) = ptr; | ||
101 | |||
102 | isight->period_counter += count; | ||
103 | if (isight->period_counter >= runtime->period_size) { | ||
104 | isight->period_counter -= runtime->period_size; | ||
105 | snd_pcm_period_elapsed(isight->pcm); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static void isight_samples(struct isight *isight, | ||
110 | const __be16 *samples, unsigned int count) | ||
111 | { | ||
112 | struct snd_pcm_runtime *runtime; | ||
113 | unsigned int count1; | ||
114 | |||
115 | if (!ACCESS_ONCE(isight->pcm_running)) | ||
116 | return; | ||
117 | |||
118 | runtime = isight->pcm->runtime; | ||
119 | if (isight->buffer_pointer + count <= runtime->buffer_size) { | ||
120 | memcpy(runtime->dma_area + isight->buffer_pointer * 4, | ||
121 | samples, count * 4); | ||
122 | } else { | ||
123 | count1 = runtime->buffer_size - isight->buffer_pointer; | ||
124 | memcpy(runtime->dma_area + isight->buffer_pointer * 4, | ||
125 | samples, count1 * 4); | ||
126 | samples += count1 * 2; | ||
127 | memcpy(runtime->dma_area, samples, (count - count1) * 4); | ||
128 | } | ||
129 | |||
130 | isight_update_pointers(isight, count); | ||
131 | } | ||
132 | |||
133 | static void isight_pcm_abort(struct isight *isight) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | |||
137 | if (ACCESS_ONCE(isight->pcm_active)) { | ||
138 | snd_pcm_stream_lock_irqsave(isight->pcm, flags); | ||
139 | if (snd_pcm_running(isight->pcm)) | ||
140 | snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); | ||
141 | snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void isight_dropped_samples(struct isight *isight, unsigned int total) | ||
146 | { | ||
147 | struct snd_pcm_runtime *runtime; | ||
148 | u32 dropped; | ||
149 | unsigned int count1; | ||
150 | |||
151 | if (!ACCESS_ONCE(isight->pcm_running)) | ||
152 | return; | ||
153 | |||
154 | runtime = isight->pcm->runtime; | ||
155 | dropped = total - isight->total_samples; | ||
156 | if (dropped < runtime->buffer_size) { | ||
157 | if (isight->buffer_pointer + dropped <= runtime->buffer_size) { | ||
158 | memset(runtime->dma_area + isight->buffer_pointer * 4, | ||
159 | 0, dropped * 4); | ||
160 | } else { | ||
161 | count1 = runtime->buffer_size - isight->buffer_pointer; | ||
162 | memset(runtime->dma_area + isight->buffer_pointer * 4, | ||
163 | 0, count1 * 4); | ||
164 | memset(runtime->dma_area, 0, (dropped - count1) * 4); | ||
165 | } | ||
166 | isight_update_pointers(isight, dropped); | ||
167 | } else { | ||
168 | isight_pcm_abort(isight); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static void isight_packet(struct fw_iso_context *context, u32 cycle, | ||
173 | size_t header_length, void *header, void *data) | ||
174 | { | ||
175 | struct isight *isight = data; | ||
176 | const struct audio_payload *payload; | ||
177 | unsigned int index, length, count, total; | ||
178 | int err; | ||
179 | |||
180 | if (isight->packet_index < 0) | ||
181 | return; | ||
182 | index = isight->packet_index; | ||
183 | payload = isight->buffer.packets[index].buffer; | ||
184 | length = be32_to_cpup(header) >> 16; | ||
185 | |||
186 | if (likely(length >= 16 && | ||
187 | payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) { | ||
188 | count = be32_to_cpu(payload->sample_count); | ||
189 | if (likely(count <= (length - 16) / 4)) { | ||
190 | total = be32_to_cpu(payload->sample_total); | ||
191 | if (unlikely(total != isight->total_samples)) { | ||
192 | if (!isight->first_packet) | ||
193 | isight_dropped_samples(isight, total); | ||
194 | isight->first_packet = false; | ||
195 | isight->total_samples = total; | ||
196 | } | ||
197 | |||
198 | isight_samples(isight, payload->samples, count); | ||
199 | isight->total_samples += count; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | err = fw_iso_context_queue(isight->context, &audio_packet, | ||
204 | &isight->buffer.iso_buffer, | ||
205 | isight->buffer.packets[index].offset); | ||
206 | if (err < 0) { | ||
207 | dev_err(&isight->unit->device, "queueing error: %d\n", err); | ||
208 | isight_pcm_abort(isight); | ||
209 | isight->packet_index = -1; | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | if (++index >= QUEUE_LENGTH) | ||
214 | index = 0; | ||
215 | isight->packet_index = index; | ||
216 | } | ||
217 | |||
218 | static int isight_connect(struct isight *isight) | ||
219 | { | ||
220 | int ch, err, rcode, errors = 0; | ||
221 | __be32 value; | ||
222 | |||
223 | retry_after_bus_reset: | ||
224 | ch = fw_iso_resources_allocate(&isight->resources, | ||
225 | sizeof(struct audio_payload), | ||
226 | isight->device->max_speed); | ||
227 | if (ch < 0) { | ||
228 | err = ch; | ||
229 | goto error; | ||
230 | } | ||
231 | |||
232 | value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); | ||
233 | for (;;) { | ||
234 | rcode = fw_run_transaction( | ||
235 | isight->device->card, | ||
236 | TCODE_WRITE_QUADLET_REQUEST, | ||
237 | isight->device->node_id, | ||
238 | isight->resources.generation, | ||
239 | isight->device->max_speed, | ||
240 | isight->audio_base + REG_ISO_TX_CONFIG, | ||
241 | &value, 4); | ||
242 | if (rcode == RCODE_COMPLETE) { | ||
243 | return 0; | ||
244 | } else if (rcode == RCODE_GENERATION) { | ||
245 | fw_iso_resources_free(&isight->resources); | ||
246 | goto retry_after_bus_reset; | ||
247 | } else if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
248 | err = -EIO; | ||
249 | goto err_resources; | ||
250 | } | ||
251 | msleep(5); | ||
252 | } | ||
253 | |||
254 | err_resources: | ||
255 | fw_iso_resources_free(&isight->resources); | ||
256 | error: | ||
257 | return err; | ||
258 | } | ||
259 | |||
260 | static int isight_open(struct snd_pcm_substream *substream) | ||
261 | { | ||
262 | static const struct snd_pcm_hardware hardware = { | ||
263 | .info = SNDRV_PCM_INFO_MMAP | | ||
264 | SNDRV_PCM_INFO_MMAP_VALID | | ||
265 | SNDRV_PCM_INFO_BATCH | | ||
266 | SNDRV_PCM_INFO_INTERLEAVED | | ||
267 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
268 | .formats = SNDRV_PCM_FMTBIT_S16_BE, | ||
269 | .rates = SNDRV_PCM_RATE_48000, | ||
270 | .rate_min = 48000, | ||
271 | .rate_max = 48000, | ||
272 | .channels_min = 2, | ||
273 | .channels_max = 2, | ||
274 | .buffer_bytes_max = 4 * 1024 * 1024, | ||
275 | .period_bytes_min = MAX_FRAMES_PER_PACKET * 4, | ||
276 | .period_bytes_max = 1024 * 1024, | ||
277 | .periods_min = 2, | ||
278 | .periods_max = UINT_MAX, | ||
279 | }; | ||
280 | struct isight *isight = substream->private_data; | ||
281 | |||
282 | substream->runtime->hw = hardware; | ||
283 | |||
284 | return iso_packets_buffer_init(&isight->buffer, isight->unit, | ||
285 | QUEUE_LENGTH, | ||
286 | sizeof(struct audio_payload), | ||
287 | DMA_FROM_DEVICE); | ||
288 | } | ||
289 | |||
290 | static int isight_close(struct snd_pcm_substream *substream) | ||
291 | { | ||
292 | struct isight *isight = substream->private_data; | ||
293 | |||
294 | iso_packets_buffer_destroy(&isight->buffer, isight->unit); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int isight_hw_params(struct snd_pcm_substream *substream, | ||
300 | struct snd_pcm_hw_params *hw_params) | ||
301 | { | ||
302 | struct isight *isight = substream->private_data; | ||
303 | int err; | ||
304 | |||
305 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
306 | params_buffer_bytes(hw_params)); | ||
307 | if (err < 0) | ||
308 | return err; | ||
309 | |||
310 | ACCESS_ONCE(isight->pcm_active) = true; | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int reg_read(struct isight *isight, int offset, __be32 *value) | ||
316 | { | ||
317 | return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, | ||
318 | isight->audio_base + offset, value, 4); | ||
319 | } | ||
320 | |||
321 | static int reg_write(struct isight *isight, int offset, __be32 value) | ||
322 | { | ||
323 | return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, | ||
324 | isight->audio_base + offset, &value, 4); | ||
325 | } | ||
326 | |||
327 | static void isight_stop_streaming(struct isight *isight) | ||
328 | { | ||
329 | if (!isight->context) | ||
330 | return; | ||
331 | |||
332 | fw_iso_context_stop(isight->context); | ||
333 | fw_iso_context_destroy(isight->context); | ||
334 | isight->context = NULL; | ||
335 | fw_iso_resources_free(&isight->resources); | ||
336 | reg_write(isight, REG_AUDIO_ENABLE, 0); | ||
337 | } | ||
338 | |||
339 | static int isight_hw_free(struct snd_pcm_substream *substream) | ||
340 | { | ||
341 | struct isight *isight = substream->private_data; | ||
342 | |||
343 | ACCESS_ONCE(isight->pcm_active) = false; | ||
344 | |||
345 | mutex_lock(&isight->mutex); | ||
346 | isight_stop_streaming(isight); | ||
347 | mutex_unlock(&isight->mutex); | ||
348 | |||
349 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
350 | } | ||
351 | |||
352 | static int isight_start_streaming(struct isight *isight) | ||
353 | { | ||
354 | unsigned int i; | ||
355 | int err; | ||
356 | |||
357 | if (isight->context) { | ||
358 | if (isight->packet_index < 0) | ||
359 | isight_stop_streaming(isight); | ||
360 | else | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | err = reg_write(isight, REG_SAMPLE_RATE, cpu_to_be32(RATE_48000)); | ||
365 | if (err < 0) | ||
366 | goto error; | ||
367 | |||
368 | err = isight_connect(isight); | ||
369 | if (err < 0) | ||
370 | goto error; | ||
371 | |||
372 | err = reg_write(isight, REG_AUDIO_ENABLE, cpu_to_be32(AUDIO_ENABLE)); | ||
373 | if (err < 0) | ||
374 | goto err_resources; | ||
375 | |||
376 | isight->context = fw_iso_context_create(isight->device->card, | ||
377 | FW_ISO_CONTEXT_RECEIVE, | ||
378 | isight->resources.channel, | ||
379 | isight->device->max_speed, | ||
380 | 4, isight_packet, isight); | ||
381 | if (IS_ERR(isight->context)) { | ||
382 | err = PTR_ERR(isight->context); | ||
383 | isight->context = NULL; | ||
384 | goto err_resources; | ||
385 | } | ||
386 | |||
387 | for (i = 0; i < QUEUE_LENGTH; ++i) { | ||
388 | err = fw_iso_context_queue(isight->context, &audio_packet, | ||
389 | &isight->buffer.iso_buffer, | ||
390 | isight->buffer.packets[i].offset); | ||
391 | if (err < 0) | ||
392 | goto err_context; | ||
393 | } | ||
394 | |||
395 | isight->first_packet = true; | ||
396 | isight->packet_index = 0; | ||
397 | |||
398 | err = fw_iso_context_start(isight->context, -1, 0, | ||
399 | FW_ISO_CONTEXT_MATCH_ALL_TAGS/*?*/); | ||
400 | if (err < 0) | ||
401 | goto err_context; | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | err_context: | ||
406 | fw_iso_context_destroy(isight->context); | ||
407 | isight->context = NULL; | ||
408 | err_resources: | ||
409 | fw_iso_resources_free(&isight->resources); | ||
410 | reg_write(isight, REG_AUDIO_ENABLE, 0); | ||
411 | error: | ||
412 | return err; | ||
413 | } | ||
414 | |||
415 | static int isight_prepare(struct snd_pcm_substream *substream) | ||
416 | { | ||
417 | struct isight *isight = substream->private_data; | ||
418 | int err; | ||
419 | |||
420 | isight->buffer_pointer = 0; | ||
421 | isight->period_counter = 0; | ||
422 | |||
423 | mutex_lock(&isight->mutex); | ||
424 | err = isight_start_streaming(isight); | ||
425 | mutex_unlock(&isight->mutex); | ||
426 | |||
427 | return err; | ||
428 | } | ||
429 | |||
430 | static int isight_trigger(struct snd_pcm_substream *substream, int cmd) | ||
431 | { | ||
432 | struct isight *isight = substream->private_data; | ||
433 | |||
434 | switch (cmd) { | ||
435 | case SNDRV_PCM_TRIGGER_START: | ||
436 | ACCESS_ONCE(isight->pcm_running) = true; | ||
437 | break; | ||
438 | case SNDRV_PCM_TRIGGER_STOP: | ||
439 | ACCESS_ONCE(isight->pcm_running) = false; | ||
440 | break; | ||
441 | default: | ||
442 | return -EINVAL; | ||
443 | } | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static snd_pcm_uframes_t isight_pointer(struct snd_pcm_substream *substream) | ||
448 | { | ||
449 | struct isight *isight = substream->private_data; | ||
450 | |||
451 | return ACCESS_ONCE(isight->buffer_pointer); | ||
452 | } | ||
453 | |||
454 | static int isight_create_pcm(struct isight *isight) | ||
455 | { | ||
456 | static struct snd_pcm_ops ops = { | ||
457 | .open = isight_open, | ||
458 | .close = isight_close, | ||
459 | .ioctl = snd_pcm_lib_ioctl, | ||
460 | .hw_params = isight_hw_params, | ||
461 | .hw_free = isight_hw_free, | ||
462 | .prepare = isight_prepare, | ||
463 | .trigger = isight_trigger, | ||
464 | .pointer = isight_pointer, | ||
465 | .page = snd_pcm_lib_get_vmalloc_page, | ||
466 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
467 | }; | ||
468 | struct snd_pcm *pcm; | ||
469 | int err; | ||
470 | |||
471 | err = snd_pcm_new(isight->card, "iSight", 0, 0, 1, &pcm); | ||
472 | if (err < 0) | ||
473 | return err; | ||
474 | pcm->private_data = isight; | ||
475 | strcpy(pcm->name, "iSight"); | ||
476 | isight->pcm = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; | ||
477 | isight->pcm->ops = &ops; | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int isight_gain_info(struct snd_kcontrol *ctl, | ||
483 | struct snd_ctl_elem_info *info) | ||
484 | { | ||
485 | struct isight *isight = ctl->private_data; | ||
486 | |||
487 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
488 | info->count = 1; | ||
489 | info->value.integer.min = isight->gain_min; | ||
490 | info->value.integer.max = isight->gain_max; | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int isight_gain_get(struct snd_kcontrol *ctl, | ||
496 | struct snd_ctl_elem_value *value) | ||
497 | { | ||
498 | struct isight *isight = ctl->private_data; | ||
499 | __be32 gain; | ||
500 | int err; | ||
501 | |||
502 | err = reg_read(isight, REG_GAIN, &gain); | ||
503 | if (err < 0) | ||
504 | return err; | ||
505 | |||
506 | value->value.integer.value[0] = (s32)be32_to_cpu(gain); | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static int isight_gain_put(struct snd_kcontrol *ctl, | ||
512 | struct snd_ctl_elem_value *value) | ||
513 | { | ||
514 | struct isight *isight = ctl->private_data; | ||
515 | |||
516 | if (value->value.integer.value[0] < isight->gain_min || | ||
517 | value->value.integer.value[0] > isight->gain_max) | ||
518 | return -EINVAL; | ||
519 | |||
520 | return reg_write(isight, REG_GAIN, | ||
521 | cpu_to_be32(value->value.integer.value[0])); | ||
522 | } | ||
523 | |||
524 | static int isight_mute_get(struct snd_kcontrol *ctl, | ||
525 | struct snd_ctl_elem_value *value) | ||
526 | { | ||
527 | struct isight *isight = ctl->private_data; | ||
528 | __be32 mute; | ||
529 | int err; | ||
530 | |||
531 | err = reg_read(isight, REG_MUTE, &mute); | ||
532 | if (err < 0) | ||
533 | return err; | ||
534 | |||
535 | value->value.integer.value[0] = !mute; | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int isight_mute_put(struct snd_kcontrol *ctl, | ||
541 | struct snd_ctl_elem_value *value) | ||
542 | { | ||
543 | struct isight *isight = ctl->private_data; | ||
544 | |||
545 | return reg_write(isight, REG_MUTE, | ||
546 | (__force __be32)!value->value.integer.value[0]); | ||
547 | } | ||
548 | |||
549 | static int isight_create_mixer(struct isight *isight) | ||
550 | { | ||
551 | static const struct snd_kcontrol_new gain_control = { | ||
552 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
553 | .name = "Mic Capture Volume", | ||
554 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
555 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
556 | .info = isight_gain_info, | ||
557 | .get = isight_gain_get, | ||
558 | .put = isight_gain_put, | ||
559 | }; | ||
560 | static const struct snd_kcontrol_new mute_control = { | ||
561 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
562 | .name = "Mic Capture Switch", | ||
563 | .info = snd_ctl_boolean_mono_info, | ||
564 | .get = isight_mute_get, | ||
565 | .put = isight_mute_put, | ||
566 | }; | ||
567 | __be32 value; | ||
568 | struct snd_kcontrol *ctl; | ||
569 | int err; | ||
570 | |||
571 | err = reg_read(isight, REG_GAIN_RAW_START, &value); | ||
572 | if (err < 0) | ||
573 | return err; | ||
574 | isight->gain_min = be32_to_cpu(value); | ||
575 | |||
576 | err = reg_read(isight, REG_GAIN_RAW_END, &value); | ||
577 | if (err < 0) | ||
578 | return err; | ||
579 | isight->gain_max = be32_to_cpu(value); | ||
580 | |||
581 | isight->gain_tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX; | ||
582 | isight->gain_tlv[1] = 2 * sizeof(unsigned int); | ||
583 | |||
584 | err = reg_read(isight, REG_GAIN_DB_START, &value); | ||
585 | if (err < 0) | ||
586 | return err; | ||
587 | isight->gain_tlv[2] = (s32)be32_to_cpu(value) * 100; | ||
588 | |||
589 | err = reg_read(isight, REG_GAIN_DB_END, &value); | ||
590 | if (err < 0) | ||
591 | return err; | ||
592 | isight->gain_tlv[3] = (s32)be32_to_cpu(value) * 100; | ||
593 | |||
594 | ctl = snd_ctl_new1(&gain_control, isight); | ||
595 | if (ctl) | ||
596 | ctl->tlv.p = isight->gain_tlv; | ||
597 | err = snd_ctl_add(isight->card, ctl); | ||
598 | if (err < 0) | ||
599 | return err; | ||
600 | |||
601 | err = snd_ctl_add(isight->card, snd_ctl_new1(&mute_control, isight)); | ||
602 | if (err < 0) | ||
603 | return err; | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static void isight_card_free(struct snd_card *card) | ||
609 | { | ||
610 | struct isight *isight = card->private_data; | ||
611 | |||
612 | fw_iso_resources_destroy(&isight->resources); | ||
613 | fw_unit_put(isight->unit); | ||
614 | fw_device_put(isight->device); | ||
615 | mutex_destroy(&isight->mutex); | ||
616 | } | ||
617 | |||
618 | static u64 get_unit_base(struct fw_unit *unit) | ||
619 | { | ||
620 | struct fw_csr_iterator i; | ||
621 | int key, value; | ||
622 | |||
623 | fw_csr_iterator_init(&i, unit->directory); | ||
624 | while (fw_csr_iterator_next(&i, &key, &value)) | ||
625 | if (key == CSR_OFFSET) | ||
626 | return CSR_REGISTER_BASE + value * 4; | ||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int isight_probe(struct device *unit_dev) | ||
631 | { | ||
632 | struct fw_unit *unit = fw_unit(unit_dev); | ||
633 | struct fw_device *fw_dev = fw_parent_device(unit); | ||
634 | struct snd_card *card; | ||
635 | struct isight *isight; | ||
636 | int err; | ||
637 | |||
638 | err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card); | ||
639 | if (err < 0) | ||
640 | return err; | ||
641 | snd_card_set_dev(card, unit_dev); | ||
642 | |||
643 | isight = card->private_data; | ||
644 | isight->card = card; | ||
645 | mutex_init(&isight->mutex); | ||
646 | isight->unit = fw_unit_get(unit); | ||
647 | isight->device = fw_device_get(fw_dev); | ||
648 | isight->audio_base = get_unit_base(unit); | ||
649 | if (!isight->audio_base) { | ||
650 | dev_err(&unit->device, "audio unit base not found\n"); | ||
651 | err = -ENXIO; | ||
652 | goto err_unit; | ||
653 | } | ||
654 | fw_iso_resources_init(&isight->resources, unit); | ||
655 | |||
656 | card->private_free = isight_card_free; | ||
657 | |||
658 | strcpy(card->driver, "iSight"); | ||
659 | strcpy(card->shortname, "Apple iSight"); | ||
660 | snprintf(card->longname, sizeof(card->longname), | ||
661 | "Apple iSight (GUID %08x%08x) at %s, S%d", | ||
662 | fw_dev->config_rom[3], fw_dev->config_rom[4], | ||
663 | dev_name(&unit->device), 100 << fw_dev->max_speed); | ||
664 | strcpy(card->mixername, "iSight"); | ||
665 | |||
666 | err = isight_create_pcm(isight); | ||
667 | if (err < 0) | ||
668 | goto error; | ||
669 | |||
670 | err = isight_create_mixer(isight); | ||
671 | if (err < 0) | ||
672 | goto error; | ||
673 | |||
674 | err = snd_card_register(card); | ||
675 | if (err < 0) | ||
676 | goto error; | ||
677 | |||
678 | dev_set_drvdata(unit_dev, isight); | ||
679 | |||
680 | return 0; | ||
681 | |||
682 | err_unit: | ||
683 | fw_unit_put(isight->unit); | ||
684 | fw_device_put(isight->device); | ||
685 | mutex_destroy(&isight->mutex); | ||
686 | error: | ||
687 | snd_card_free(card); | ||
688 | return err; | ||
689 | } | ||
690 | |||
691 | static int isight_remove(struct device *dev) | ||
692 | { | ||
693 | struct isight *isight = dev_get_drvdata(dev); | ||
694 | |||
695 | isight_pcm_abort(isight); | ||
696 | |||
697 | snd_card_disconnect(isight->card); | ||
698 | |||
699 | mutex_lock(&isight->mutex); | ||
700 | isight_stop_streaming(isight); | ||
701 | mutex_unlock(&isight->mutex); | ||
702 | |||
703 | snd_card_free_when_closed(isight->card); | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static void isight_bus_reset(struct fw_unit *unit) | ||
709 | { | ||
710 | struct isight *isight = dev_get_drvdata(&unit->device); | ||
711 | |||
712 | if (fw_iso_resources_update(&isight->resources) < 0) { | ||
713 | isight_pcm_abort(isight); | ||
714 | |||
715 | mutex_lock(&isight->mutex); | ||
716 | isight_stop_streaming(isight); | ||
717 | mutex_unlock(&isight->mutex); | ||
718 | } | ||
719 | } | ||
720 | |||
721 | static const struct ieee1394_device_id isight_id_table[] = { | ||
722 | { | ||
723 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | | ||
724 | IEEE1394_MATCH_VERSION, | ||
725 | .specifier_id = OUI_APPLE, | ||
726 | .version = SW_ISIGHT_AUDIO, | ||
727 | }, | ||
728 | { } | ||
729 | }; | ||
730 | MODULE_DEVICE_TABLE(ieee1394, isight_id_table); | ||
731 | |||
732 | static struct fw_driver isight_driver = { | ||
733 | .driver = { | ||
734 | .owner = THIS_MODULE, | ||
735 | .name = KBUILD_MODNAME, | ||
736 | .bus = &fw_bus_type, | ||
737 | .probe = isight_probe, | ||
738 | .remove = isight_remove, | ||
739 | }, | ||
740 | .update = isight_bus_reset, | ||
741 | .id_table = isight_id_table, | ||
742 | }; | ||
743 | |||
744 | static int __init alsa_isight_init(void) | ||
745 | { | ||
746 | return driver_register(&isight_driver.driver); | ||
747 | } | ||
748 | |||
749 | static void __exit alsa_isight_exit(void) | ||
750 | { | ||
751 | driver_unregister(&isight_driver.driver); | ||
752 | } | ||
753 | |||
754 | module_init(alsa_isight_init); | ||
755 | module_exit(alsa_isight_exit); | ||
diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c index 775dbd5f3445..9d4a6714f9ec 100644 --- a/sound/firewire/iso-resources.c +++ b/sound/firewire/iso-resources.c | |||
@@ -36,6 +36,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) | |||
36 | 36 | ||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | EXPORT_SYMBOL(fw_iso_resources_init); | ||
39 | 40 | ||
40 | /** | 41 | /** |
41 | * fw_iso_resources_destroy - destroy a resource manager | 42 | * fw_iso_resources_destroy - destroy a resource manager |
@@ -48,6 +49,7 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r) | |||
48 | mutex_destroy(&r->mutex); | 49 | mutex_destroy(&r->mutex); |
49 | fw_unit_put(r->unit); | 50 | fw_unit_put(r->unit); |
50 | } | 51 | } |
52 | EXPORT_SYMBOL(fw_iso_resources_destroy); | ||
51 | 53 | ||
52 | static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed) | 54 | static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed) |
53 | { | 55 | { |
@@ -152,6 +154,7 @@ retry_after_bus_reset: | |||
152 | 154 | ||
153 | return channel; | 155 | return channel; |
154 | } | 156 | } |
157 | EXPORT_SYMBOL(fw_iso_resources_allocate); | ||
155 | 158 | ||
156 | /** | 159 | /** |
157 | * fw_iso_resources_update - update resource allocations after a bus reset | 160 | * fw_iso_resources_update - update resource allocations after a bus reset |
@@ -203,6 +206,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r) | |||
203 | 206 | ||
204 | return channel; | 207 | return channel; |
205 | } | 208 | } |
209 | EXPORT_SYMBOL(fw_iso_resources_update); | ||
206 | 210 | ||
207 | /** | 211 | /** |
208 | * fw_iso_resources_free - frees allocated resources | 212 | * fw_iso_resources_free - frees allocated resources |
@@ -230,3 +234,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r) | |||
230 | 234 | ||
231 | mutex_unlock(&r->mutex); | 235 | mutex_unlock(&r->mutex); |
232 | } | 236 | } |
237 | EXPORT_SYMBOL(fw_iso_resources_free); | ||
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c index 1e20e60ba6a6..3c61ca2e6152 100644 --- a/sound/firewire/packets-buffer.c +++ b/sound/firewire/packets-buffer.c | |||
@@ -60,6 +60,7 @@ err_packets: | |||
60 | error: | 60 | error: |
61 | return err; | 61 | return err; |
62 | } | 62 | } |
63 | EXPORT_SYMBOL(iso_packets_buffer_init); | ||
63 | 64 | ||
64 | /** | 65 | /** |
65 | * iso_packets_buffer_destroy - frees packet buffer resources | 66 | * iso_packets_buffer_destroy - frees packet buffer resources |
@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | |||
72 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); | 73 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); |
73 | kfree(b->packets); | 74 | kfree(b->packets); |
74 | } | 75 | } |
76 | EXPORT_SYMBOL(iso_packets_buffer_destroy); | ||
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 2dad40f3f622..c95d8f1aae87 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o | |||
14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o | 16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
17 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o | 17 | obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o |
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index ee538f1ae846..4831800239d3 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c | |||
@@ -37,8 +37,8 @@ static int radio_nr = -1; | |||
37 | module_param(radio_nr, int, 0); | 37 | module_param(radio_nr, int, 0); |
38 | 38 | ||
39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | 39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) |
40 | #define FREQ_LO (87 * 16000) | 40 | #define FREQ_LO (50UL * 16000) |
41 | #define FREQ_HI (108 * 16000) | 41 | #define FREQ_HI (150UL * 16000) |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * definitions | 44 | * definitions |
@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
77 | * lowlevel part | 77 | * lowlevel part |
78 | */ | 78 | */ |
79 | 79 | ||
80 | static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) | ||
81 | { | ||
82 | u16 l; | ||
83 | u8 data; | ||
84 | |||
85 | tea->ops->set_direction(tea, 1); | ||
86 | udelay(16); | ||
87 | |||
88 | for (l = 25; l > 0; l--) { | ||
89 | data = (val >> 24) & TEA575X_DATA; | ||
90 | val <<= 1; /* shift data */ | ||
91 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
92 | udelay(2); | ||
93 | tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); | ||
94 | udelay(2); | ||
95 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
96 | udelay(2); | ||
97 | } | ||
98 | |||
99 | if (!tea->mute) | ||
100 | tea->ops->set_pins(tea, 0); | ||
101 | } | ||
102 | |||
103 | static unsigned int snd_tea575x_read(struct snd_tea575x *tea) | ||
104 | { | ||
105 | u16 l, rdata; | ||
106 | u32 data = 0; | ||
107 | |||
108 | tea->ops->set_direction(tea, 0); | ||
109 | tea->ops->set_pins(tea, 0); | ||
110 | udelay(16); | ||
111 | |||
112 | for (l = 24; l--;) { | ||
113 | tea->ops->set_pins(tea, TEA575X_CLK); | ||
114 | udelay(2); | ||
115 | if (!l) | ||
116 | tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; | ||
117 | tea->ops->set_pins(tea, 0); | ||
118 | udelay(2); | ||
119 | data <<= 1; /* shift data */ | ||
120 | rdata = tea->ops->get_pins(tea); | ||
121 | if (!l) | ||
122 | tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; | ||
123 | if (rdata & TEA575X_DATA) | ||
124 | data++; | ||
125 | udelay(2); | ||
126 | } | ||
127 | |||
128 | if (tea->mute) | ||
129 | tea->ops->set_pins(tea, TEA575X_WREN); | ||
130 | |||
131 | return data; | ||
132 | } | ||
133 | |||
134 | static void snd_tea575x_get_freq(struct snd_tea575x *tea) | ||
135 | { | ||
136 | unsigned long freq; | ||
137 | |||
138 | freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; | ||
139 | /* freq *= 12.5 */ | ||
140 | freq *= 125; | ||
141 | freq /= 10; | ||
142 | /* crystal fixup */ | ||
143 | if (tea->tea5759) | ||
144 | freq += TEA575X_FMIF; | ||
145 | else | ||
146 | freq -= TEA575X_FMIF; | ||
147 | |||
148 | tea->freq = freq * 16; /* from kHz */ | ||
149 | } | ||
150 | |||
80 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) | 151 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) |
81 | { | 152 | { |
82 | unsigned long freq; | 153 | unsigned long freq; |
83 | 154 | ||
84 | freq = tea->freq / 16; /* to kHz */ | 155 | freq = clamp(tea->freq, FREQ_LO, FREQ_HI); |
85 | if (freq > 108000) | 156 | freq /= 16; /* to kHz */ |
86 | freq = 108000; | ||
87 | if (freq < 87000) | ||
88 | freq = 87000; | ||
89 | /* crystal fixup */ | 157 | /* crystal fixup */ |
90 | if (tea->tea5759) | 158 | if (tea->tea5759) |
91 | freq -= tea->freq_fixup; | 159 | freq -= TEA575X_FMIF; |
92 | else | 160 | else |
93 | freq += tea->freq_fixup; | 161 | freq += TEA575X_FMIF; |
94 | /* freq /= 12.5 */ | 162 | /* freq /= 12.5 */ |
95 | freq *= 10; | 163 | freq *= 10; |
96 | freq /= 125; | 164 | freq /= 125; |
97 | 165 | ||
98 | tea->val &= ~TEA575X_BIT_FREQ_MASK; | 166 | tea->val &= ~TEA575X_BIT_FREQ_MASK; |
99 | tea->val |= freq & TEA575X_BIT_FREQ_MASK; | 167 | tea->val |= freq & TEA575X_BIT_FREQ_MASK; |
100 | tea->ops->write(tea, tea->val); | 168 | snd_tea575x_write(tea, tea->val); |
101 | } | 169 | } |
102 | 170 | ||
103 | /* | 171 | /* |
@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
109 | { | 177 | { |
110 | struct snd_tea575x *tea = video_drvdata(file); | 178 | struct snd_tea575x *tea = video_drvdata(file); |
111 | 179 | ||
112 | strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757"); | ||
113 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); | 180 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); |
114 | strlcpy(v->card, "Maestro Radio", sizeof(v->card)); | 181 | strlcpy(v->card, tea->card, sizeof(v->card)); |
115 | sprintf(v->bus_info, "PCI"); | 182 | strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); |
183 | strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); | ||
116 | v->version = RADIO_VERSION; | 184 | v->version = RADIO_VERSION; |
117 | v->capabilities = V4L2_CAP_TUNER; | 185 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
118 | return 0; | 186 | return 0; |
119 | } | 187 | } |
120 | 188 | ||
121 | static int vidioc_g_tuner(struct file *file, void *priv, | 189 | static int vidioc_g_tuner(struct file *file, void *priv, |
122 | struct v4l2_tuner *v) | 190 | struct v4l2_tuner *v) |
123 | { | 191 | { |
192 | struct snd_tea575x *tea = video_drvdata(file); | ||
193 | |||
124 | if (v->index > 0) | 194 | if (v->index > 0) |
125 | return -EINVAL; | 195 | return -EINVAL; |
126 | 196 | ||
197 | snd_tea575x_read(tea); | ||
198 | |||
127 | strcpy(v->name, "FM"); | 199 | strcpy(v->name, "FM"); |
128 | v->type = V4L2_TUNER_RADIO; | 200 | v->type = V4L2_TUNER_RADIO; |
201 | v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
129 | v->rangelow = FREQ_LO; | 202 | v->rangelow = FREQ_LO; |
130 | v->rangehigh = FREQ_HI; | 203 | v->rangehigh = FREQ_HI; |
131 | v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | 204 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
132 | v->capability = V4L2_TUNER_CAP_LOW; | 205 | v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; |
133 | v->audmode = V4L2_TUNER_MODE_MONO; | 206 | v->signal = tea->tuned ? 0xffff : 0; |
134 | v->signal = 0xffff; | 207 | |
135 | return 0; | 208 | return 0; |
136 | } | 209 | } |
137 | 210 | ||
@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
148 | { | 221 | { |
149 | struct snd_tea575x *tea = video_drvdata(file); | 222 | struct snd_tea575x *tea = video_drvdata(file); |
150 | 223 | ||
224 | if (f->tuner != 0) | ||
225 | return -EINVAL; | ||
151 | f->type = V4L2_TUNER_RADIO; | 226 | f->type = V4L2_TUNER_RADIO; |
227 | snd_tea575x_get_freq(tea); | ||
152 | f->frequency = tea->freq; | 228 | f->frequency = tea->freq; |
153 | return 0; | 229 | return 0; |
154 | } | 230 | } |
@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
158 | { | 234 | { |
159 | struct snd_tea575x *tea = video_drvdata(file); | 235 | struct snd_tea575x *tea = video_drvdata(file); |
160 | 236 | ||
237 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
238 | return -EINVAL; | ||
239 | |||
161 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 240 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) |
162 | return -EINVAL; | 241 | return -EINVAL; |
163 | 242 | ||
@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
209 | 288 | ||
210 | switch (ctrl->id) { | 289 | switch (ctrl->id) { |
211 | case V4L2_CID_AUDIO_MUTE: | 290 | case V4L2_CID_AUDIO_MUTE: |
212 | if (tea->ops->mute) { | 291 | ctrl->value = tea->mute; |
213 | ctrl->value = tea->mute; | 292 | return 0; |
214 | return 0; | ||
215 | } | ||
216 | } | 293 | } |
217 | return -EINVAL; | 294 | return -EINVAL; |
218 | } | 295 | } |
@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
224 | 301 | ||
225 | switch (ctrl->id) { | 302 | switch (ctrl->id) { |
226 | case V4L2_CID_AUDIO_MUTE: | 303 | case V4L2_CID_AUDIO_MUTE: |
227 | if (tea->ops->mute) { | 304 | if (tea->mute != ctrl->value) { |
228 | tea->ops->mute(tea, ctrl->value); | ||
229 | tea->mute = ctrl->value; | 305 | tea->mute = ctrl->value; |
230 | return 0; | 306 | snd_tea575x_set_freq(tea); |
231 | } | 307 | } |
308 | return 0; | ||
232 | } | 309 | } |
233 | return -EINVAL; | 310 | return -EINVAL; |
234 | } | 311 | } |
@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = { | |||
293 | /* | 370 | /* |
294 | * initialize all the tea575x chips | 371 | * initialize all the tea575x chips |
295 | */ | 372 | */ |
296 | void snd_tea575x_init(struct snd_tea575x *tea) | 373 | int snd_tea575x_init(struct snd_tea575x *tea) |
297 | { | 374 | { |
298 | int retval; | 375 | int retval; |
299 | unsigned int val; | ||
300 | struct video_device *tea575x_radio_inst; | 376 | struct video_device *tea575x_radio_inst; |
301 | 377 | ||
302 | val = tea->ops->read(tea); | 378 | tea->mute = 1; |
303 | if (val == 0x1ffffff || val == 0) { | 379 | |
304 | snd_printk(KERN_ERR | 380 | snd_tea575x_write(tea, 0x55AA); |
305 | "tea575x-tuner: Cannot find TEA575x chip\n"); | 381 | if (snd_tea575x_read(tea) != 0x55AA) |
306 | return; | 382 | return -ENODEV; |
307 | } | ||
308 | 383 | ||
309 | tea->in_use = 0; | 384 | tea->in_use = 0; |
310 | tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; | 385 | tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; |
@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea) | |||
313 | tea575x_radio_inst = video_device_alloc(); | 388 | tea575x_radio_inst = video_device_alloc(); |
314 | if (tea575x_radio_inst == NULL) { | 389 | if (tea575x_radio_inst == NULL) { |
315 | printk(KERN_ERR "tea575x-tuner: not enough memory\n"); | 390 | printk(KERN_ERR "tea575x-tuner: not enough memory\n"); |
316 | return; | 391 | return -ENOMEM; |
317 | } | 392 | } |
318 | 393 | ||
319 | memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); | 394 | memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); |
@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea) | |||
328 | if (retval) { | 403 | if (retval) { |
329 | printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); | 404 | printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); |
330 | kfree(tea575x_radio_inst); | 405 | kfree(tea575x_radio_inst); |
331 | return; | 406 | return retval; |
332 | } | 407 | } |
333 | 408 | ||
334 | snd_tea575x_set_freq(tea); | 409 | snd_tea575x_set_freq(tea); |
335 | |||
336 | /* mute on init */ | ||
337 | if (tea->ops->mute) { | ||
338 | tea->ops->mute(tea, 1); | ||
339 | tea->mute = 1; | ||
340 | } | ||
341 | tea->vd = tea575x_radio_inst; | 410 | tea->vd = tea575x_radio_inst; |
411 | |||
412 | return 0; | ||
342 | } | 413 | } |
343 | 414 | ||
344 | void snd_tea575x_exit(struct snd_tea575x *tea) | 415 | void snd_tea575x_exit(struct snd_tea575x *tea) |
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 76c090218073..6c93e051f9ae 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig | |||
@@ -22,10 +22,6 @@ config SOUND_VWSND | |||
22 | <file:Documentation/sound/oss/vwsnd> for more info on this driver's | 22 | <file:Documentation/sound/oss/vwsnd> for more info on this driver's |
23 | capabilities. | 23 | capabilities. |
24 | 24 | ||
25 | config SOUND_AU1550_AC97 | ||
26 | tristate "Au1550/Au1200 AC97 Sound" | ||
27 | depends on SOC_AU1550 || SOC_AU1200 | ||
28 | |||
29 | config SOUND_MSNDCLAS | 25 | config SOUND_MSNDCLAS |
30 | tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" | 26 | tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" |
31 | depends on (m || !STANDALONE) && ISA | 27 | depends on (m || !STANDALONE) && ISA |
diff --git a/sound/oss/Makefile b/sound/oss/Makefile index 90ffb99c6b17..77f21b68bf0f 100644 --- a/sound/oss/Makefile +++ b/sound/oss/Makefile | |||
@@ -25,7 +25,6 @@ obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o | |||
25 | obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o | 25 | obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o |
26 | obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o | 26 | obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o |
27 | obj-$(CONFIG_SOUND_VWSND) += vwsnd.o | 27 | obj-$(CONFIG_SOUND_VWSND) += vwsnd.o |
28 | obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o | ||
29 | obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o | 28 | obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o |
30 | 29 | ||
31 | obj-$(CONFIG_DMASOUND) += dmasound/ | 30 | obj-$(CONFIG_DMASOUND) += dmasound/ |
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c deleted file mode 100644 index 0cd23d94888f..000000000000 --- a/sound/oss/ac97_codec.c +++ /dev/null | |||
@@ -1,1203 +0,0 @@ | |||
1 | /* | ||
2 | * ac97_codec.c: Generic AC97 mixer/modem module | ||
3 | * | ||
4 | * Derived from ac97 mixer in maestro and trident driver. | ||
5 | * | ||
6 | * Copyright 2000 Silicon Integrated System Corporation | ||
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; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | ************************************************************************** | ||
23 | * | ||
24 | * The Intel Audio Codec '97 specification is available at: | ||
25 | * http://download.intel.com/support/motherboards/desktop/sb/ac97_r23.pdf | ||
26 | * | ||
27 | ************************************************************************** | ||
28 | * | ||
29 | * History | ||
30 | * May 02, 2003 Liam Girdwood <lrg@slimlogic.co.uk> | ||
31 | * Removed non existent WM9700 | ||
32 | * Added support for WM9705, WM9708, WM9709, WM9710, WM9711 | ||
33 | * WM9712 and WM9717 | ||
34 | * Mar 28, 2002 Randolph Bentson <bentson@holmsjoen.com> | ||
35 | * corrections to support WM9707 in ViewPad 1000 | ||
36 | * v0.4 Mar 15 2000 Ollie Lho | ||
37 | * dual codecs support verified with 4 channels output | ||
38 | * v0.3 Feb 22 2000 Ollie Lho | ||
39 | * bug fix for record mask setting | ||
40 | * v0.2 Feb 10 2000 Ollie Lho | ||
41 | * add ac97_read_proc for /proc/driver/{vendor}/ac97 | ||
42 | * v0.1 Jan 14 2000 Ollie Lho <ollie@sis.com.tw> | ||
43 | * Isolated from trident.c to support multiple ac97 codec | ||
44 | */ | ||
45 | #include <linux/module.h> | ||
46 | #include <linux/kernel.h> | ||
47 | #include <linux/slab.h> | ||
48 | #include <linux/string.h> | ||
49 | #include <linux/errno.h> | ||
50 | #include <linux/bitops.h> | ||
51 | #include <linux/delay.h> | ||
52 | #include <linux/pci.h> | ||
53 | #include <linux/ac97_codec.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | #include <linux/mutex.h> | ||
56 | |||
57 | #define CODEC_ID_BUFSZ 14 | ||
58 | |||
59 | static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel); | ||
60 | static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel, | ||
61 | unsigned int left, unsigned int right); | ||
62 | static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val ); | ||
63 | static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask); | ||
64 | static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg); | ||
65 | |||
66 | static int ac97_init_mixer(struct ac97_codec *codec); | ||
67 | |||
68 | static int wolfson_init03(struct ac97_codec * codec); | ||
69 | static int wolfson_init04(struct ac97_codec * codec); | ||
70 | static int wolfson_init05(struct ac97_codec * codec); | ||
71 | static int wolfson_init11(struct ac97_codec * codec); | ||
72 | static int wolfson_init13(struct ac97_codec * codec); | ||
73 | static int tritech_init(struct ac97_codec * codec); | ||
74 | static int tritech_maestro_init(struct ac97_codec * codec); | ||
75 | static int sigmatel_9708_init(struct ac97_codec *codec); | ||
76 | static int sigmatel_9721_init(struct ac97_codec *codec); | ||
77 | static int sigmatel_9744_init(struct ac97_codec *codec); | ||
78 | static int ad1886_init(struct ac97_codec *codec); | ||
79 | static int eapd_control(struct ac97_codec *codec, int); | ||
80 | static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); | ||
81 | static int cmedia_init(struct ac97_codec * codec); | ||
82 | static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); | ||
83 | static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); | ||
84 | |||
85 | |||
86 | /* | ||
87 | * AC97 operations. | ||
88 | * | ||
89 | * If you are adding a codec then you should be able to use | ||
90 | * eapd_ops - any codec that supports EAPD amp control (most) | ||
91 | * null_ops - any ancient codec that supports nothing | ||
92 | * | ||
93 | * The three functions are | ||
94 | * init - used for non AC97 standard initialisation | ||
95 | * amplifier - used to do amplifier control (1=on 0=off) | ||
96 | * digital - switch to digital modes (0 = analog) | ||
97 | * | ||
98 | * Not all codecs support all features, not all drivers use all the | ||
99 | * operations yet | ||
100 | */ | ||
101 | |||
102 | static struct ac97_ops null_ops = { NULL, NULL, NULL }; | ||
103 | static struct ac97_ops default_ops = { NULL, eapd_control, NULL }; | ||
104 | static struct ac97_ops default_digital_ops = { NULL, eapd_control, generic_digital_control}; | ||
105 | static struct ac97_ops wolfson_ops03 = { wolfson_init03, NULL, NULL }; | ||
106 | static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL }; | ||
107 | static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL }; | ||
108 | static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL }; | ||
109 | static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL }; | ||
110 | static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL }; | ||
111 | static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL }; | ||
112 | static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL }; | ||
113 | static struct ac97_ops sigmatel_9721_ops = { sigmatel_9721_init, NULL, NULL }; | ||
114 | static struct ac97_ops sigmatel_9744_ops = { sigmatel_9744_init, NULL, NULL }; | ||
115 | static struct ac97_ops crystal_digital_ops = { NULL, eapd_control, crystal_digital_control }; | ||
116 | static struct ac97_ops ad1886_ops = { ad1886_init, eapd_control, NULL }; | ||
117 | static struct ac97_ops cmedia_ops = { NULL, eapd_control, NULL}; | ||
118 | static struct ac97_ops cmedia_digital_ops = { cmedia_init, eapd_control, cmedia_digital_control}; | ||
119 | |||
120 | /* sorted by vendor/device id */ | ||
121 | static const struct { | ||
122 | u32 id; | ||
123 | char *name; | ||
124 | struct ac97_ops *ops; | ||
125 | int flags; | ||
126 | } ac97_codec_ids[] = { | ||
127 | {0x41445303, "Analog Devices AD1819", &null_ops}, | ||
128 | {0x41445340, "Analog Devices AD1881", &null_ops}, | ||
129 | {0x41445348, "Analog Devices AD1881A", &null_ops}, | ||
130 | {0x41445360, "Analog Devices AD1885", &default_ops}, | ||
131 | {0x41445361, "Analog Devices AD1886", &ad1886_ops}, | ||
132 | {0x41445370, "Analog Devices AD1981", &null_ops}, | ||
133 | {0x41445372, "Analog Devices AD1981A", &null_ops}, | ||
134 | {0x41445374, "Analog Devices AD1981B", &null_ops}, | ||
135 | {0x41445460, "Analog Devices AD1885", &default_ops}, | ||
136 | {0x41445461, "Analog Devices AD1886", &ad1886_ops}, | ||
137 | {0x414B4D00, "Asahi Kasei AK4540", &null_ops}, | ||
138 | {0x414B4D01, "Asahi Kasei AK4542", &null_ops}, | ||
139 | {0x414B4D02, "Asahi Kasei AK4543", &null_ops}, | ||
140 | {0x414C4326, "ALC100P", &null_ops}, | ||
141 | {0x414C4710, "ALC200/200P", &null_ops}, | ||
142 | {0x414C4720, "ALC650", &default_digital_ops}, | ||
143 | {0x434D4941, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME }, | ||
144 | {0x434D4942, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME }, | ||
145 | {0x434D4961, "CMedia", &cmedia_digital_ops, AC97_NO_PCM_VOLUME }, | ||
146 | {0x43525900, "Cirrus Logic CS4297", &default_ops}, | ||
147 | {0x43525903, "Cirrus Logic CS4297", &default_ops}, | ||
148 | {0x43525913, "Cirrus Logic CS4297A rev A", &default_ops}, | ||
149 | {0x43525914, "Cirrus Logic CS4297A rev B", &default_ops}, | ||
150 | {0x43525923, "Cirrus Logic CS4298", &null_ops}, | ||
151 | {0x4352592B, "Cirrus Logic CS4294", &null_ops}, | ||
152 | {0x4352592D, "Cirrus Logic CS4294", &null_ops}, | ||
153 | {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops}, | ||
154 | {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops}, | ||
155 | {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops}, | ||
156 | {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM }, | ||
157 | {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM }, | ||
158 | {0x44543031, "Diamond Technology DT0893", &default_ops}, | ||
159 | {0x45838308, "ESS Allegro ES1988", &null_ops}, | ||
160 | {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */ | ||
161 | {0x4e534331, "National Semiconductor LM4549", &null_ops}, | ||
162 | {0x53494c22, "Silicon Laboratory Si3036", &null_ops}, | ||
163 | {0x53494c23, "Silicon Laboratory Si3038", &null_ops}, | ||
164 | {0x545200FF, "TriTech TR?????", &tritech_m_ops}, | ||
165 | {0x54524102, "TriTech TR28022", &null_ops}, | ||
166 | {0x54524103, "TriTech TR28023", &null_ops}, | ||
167 | {0x54524106, "TriTech TR28026", &null_ops}, | ||
168 | {0x54524108, "TriTech TR28028", &tritech_ops}, | ||
169 | {0x54524123, "TriTech TR A5", &null_ops}, | ||
170 | {0x574D4C03, "Wolfson WM9703/07/08/17", &wolfson_ops03}, | ||
171 | {0x574D4C04, "Wolfson WM9704M/WM9704Q", &wolfson_ops04}, | ||
172 | {0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05}, | ||
173 | {0x574D4C09, "Wolfson WM9709", &null_ops}, | ||
174 | {0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11}, | ||
175 | {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF}, | ||
176 | {0x83847600, "SigmaTel STAC????", &null_ops}, | ||
177 | {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops}, | ||
178 | {0x83847605, "SigmaTel STAC9704", &null_ops}, | ||
179 | {0x83847608, "SigmaTel STAC9708", &sigmatel_9708_ops}, | ||
180 | {0x83847609, "SigmaTel STAC9721/23", &sigmatel_9721_ops}, | ||
181 | {0x83847644, "SigmaTel STAC9744/45", &sigmatel_9744_ops}, | ||
182 | {0x83847652, "SigmaTel STAC9752/53", &default_ops}, | ||
183 | {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops}, | ||
184 | {0x83847666, "SigmaTel STAC9750T", &sigmatel_9744_ops}, | ||
185 | {0x83847684, "SigmaTel STAC9783/84?", &null_ops}, | ||
186 | {0x57454301, "Winbond 83971D", &null_ops}, | ||
187 | }; | ||
188 | |||
189 | /* this table has default mixer values for all OSS mixers. */ | ||
190 | static struct mixer_defaults { | ||
191 | int mixer; | ||
192 | unsigned int value; | ||
193 | } mixer_defaults[SOUND_MIXER_NRDEVICES] = { | ||
194 | /* all values 0 -> 100 in bytes */ | ||
195 | {SOUND_MIXER_VOLUME, 0x4343}, | ||
196 | {SOUND_MIXER_BASS, 0x4343}, | ||
197 | {SOUND_MIXER_TREBLE, 0x4343}, | ||
198 | {SOUND_MIXER_PCM, 0x4343}, | ||
199 | {SOUND_MIXER_SPEAKER, 0x4343}, | ||
200 | {SOUND_MIXER_LINE, 0x4343}, | ||
201 | {SOUND_MIXER_MIC, 0x0000}, | ||
202 | {SOUND_MIXER_CD, 0x4343}, | ||
203 | {SOUND_MIXER_ALTPCM, 0x4343}, | ||
204 | {SOUND_MIXER_IGAIN, 0x4343}, | ||
205 | {SOUND_MIXER_LINE1, 0x4343}, | ||
206 | {SOUND_MIXER_PHONEIN, 0x4343}, | ||
207 | {SOUND_MIXER_PHONEOUT, 0x4343}, | ||
208 | {SOUND_MIXER_VIDEO, 0x4343}, | ||
209 | {-1,0} | ||
210 | }; | ||
211 | |||
212 | /* table to scale scale from OSS mixer value to AC97 mixer register value */ | ||
213 | static struct ac97_mixer_hw { | ||
214 | unsigned char offset; | ||
215 | int scale; | ||
216 | } ac97_hw[SOUND_MIXER_NRDEVICES]= { | ||
217 | [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,64}, | ||
218 | [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 16}, | ||
219 | [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 16}, | ||
220 | [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 32}, | ||
221 | [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 16}, | ||
222 | [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 32}, | ||
223 | [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 32}, | ||
224 | [SOUND_MIXER_CD] = {AC97_CD_VOL, 32}, | ||
225 | [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 64}, | ||
226 | [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 16}, | ||
227 | [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 32}, | ||
228 | [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 32}, | ||
229 | [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 64}, | ||
230 | [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 32}, | ||
231 | }; | ||
232 | |||
233 | /* the following tables allow us to go from OSS <-> ac97 quickly. */ | ||
234 | enum ac97_recsettings { | ||
235 | AC97_REC_MIC=0, | ||
236 | AC97_REC_CD, | ||
237 | AC97_REC_VIDEO, | ||
238 | AC97_REC_AUX, | ||
239 | AC97_REC_LINE, | ||
240 | AC97_REC_STEREO, /* combination of all enabled outputs.. */ | ||
241 | AC97_REC_MONO, /*.. or the mono equivalent */ | ||
242 | AC97_REC_PHONE | ||
243 | }; | ||
244 | |||
245 | static const unsigned int ac97_rm2oss[] = { | ||
246 | [AC97_REC_MIC] = SOUND_MIXER_MIC, | ||
247 | [AC97_REC_CD] = SOUND_MIXER_CD, | ||
248 | [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, | ||
249 | [AC97_REC_AUX] = SOUND_MIXER_LINE1, | ||
250 | [AC97_REC_LINE] = SOUND_MIXER_LINE, | ||
251 | [AC97_REC_STEREO]= SOUND_MIXER_IGAIN, | ||
252 | [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN | ||
253 | }; | ||
254 | |||
255 | /* indexed by bit position */ | ||
256 | static const unsigned int ac97_oss_rm[] = { | ||
257 | [SOUND_MIXER_MIC] = AC97_REC_MIC, | ||
258 | [SOUND_MIXER_CD] = AC97_REC_CD, | ||
259 | [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO, | ||
260 | [SOUND_MIXER_LINE1] = AC97_REC_AUX, | ||
261 | [SOUND_MIXER_LINE] = AC97_REC_LINE, | ||
262 | [SOUND_MIXER_IGAIN] = AC97_REC_STEREO, | ||
263 | [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE | ||
264 | }; | ||
265 | |||
266 | static LIST_HEAD(codecs); | ||
267 | static LIST_HEAD(codec_drivers); | ||
268 | static DEFINE_MUTEX(codec_mutex); | ||
269 | |||
270 | /* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows | ||
271 | about that given mixer, and should be holding a spinlock for the card */ | ||
272 | static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel) | ||
273 | { | ||
274 | u16 val; | ||
275 | int ret = 0; | ||
276 | int scale; | ||
277 | struct ac97_mixer_hw *mh = &ac97_hw[oss_channel]; | ||
278 | |||
279 | val = codec->codec_read(codec , mh->offset); | ||
280 | |||
281 | if (val & AC97_MUTE) { | ||
282 | ret = 0; | ||
283 | } else if (AC97_STEREO_MASK & (1 << oss_channel)) { | ||
284 | /* nice stereo mixers .. */ | ||
285 | int left,right; | ||
286 | |||
287 | left = (val >> 8) & 0x7f; | ||
288 | right = val & 0x7f; | ||
289 | |||
290 | if (oss_channel == SOUND_MIXER_IGAIN) { | ||
291 | right = (right * 100) / mh->scale; | ||
292 | left = (left * 100) / mh->scale; | ||
293 | } else { | ||
294 | /* these may have 5 or 6 bit resolution */ | ||
295 | if(oss_channel == SOUND_MIXER_VOLUME || oss_channel == SOUND_MIXER_ALTPCM) | ||
296 | scale = (1 << codec->bit_resolution); | ||
297 | else | ||
298 | scale = mh->scale; | ||
299 | |||
300 | right = 100 - ((right * 100) / scale); | ||
301 | left = 100 - ((left * 100) / scale); | ||
302 | } | ||
303 | ret = left | (right << 8); | ||
304 | } else if (oss_channel == SOUND_MIXER_SPEAKER) { | ||
305 | ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale); | ||
306 | } else if (oss_channel == SOUND_MIXER_PHONEIN) { | ||
307 | ret = 100 - (((val & 0x1f) * 100) / mh->scale); | ||
308 | } else if (oss_channel == SOUND_MIXER_PHONEOUT) { | ||
309 | scale = (1 << codec->bit_resolution); | ||
310 | ret = 100 - (((val & 0x1f) * 100) / scale); | ||
311 | } else if (oss_channel == SOUND_MIXER_MIC) { | ||
312 | ret = 100 - (((val & 0x1f) * 100) / mh->scale); | ||
313 | /* the low bit is optional in the tone sliders and masking | ||
314 | it lets us avoid the 0xf 'bypass'.. */ | ||
315 | } else if (oss_channel == SOUND_MIXER_BASS) { | ||
316 | ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale); | ||
317 | } else if (oss_channel == SOUND_MIXER_TREBLE) { | ||
318 | ret = 100 - (((val & 0xe) * 100) / mh->scale); | ||
319 | } | ||
320 | |||
321 | #ifdef DEBUG | ||
322 | printk("ac97_codec: read OSS mixer %2d (%s ac97 register 0x%02x), " | ||
323 | "0x%04x -> 0x%04x\n", | ||
324 | oss_channel, codec->id ? "Secondary" : "Primary", | ||
325 | mh->offset, val, ret); | ||
326 | #endif | ||
327 | |||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | /* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to | ||
332 | make sure all is well in arg land, call with spinlock held */ | ||
333 | static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel, | ||
334 | unsigned int left, unsigned int right) | ||
335 | { | ||
336 | u16 val = 0; | ||
337 | int scale; | ||
338 | struct ac97_mixer_hw *mh = &ac97_hw[oss_channel]; | ||
339 | |||
340 | #ifdef DEBUG | ||
341 | printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), " | ||
342 | "left vol:%2d, right vol:%2d:", | ||
343 | oss_channel, codec->id ? "Secondary" : "Primary", | ||
344 | mh->offset, left, right); | ||
345 | #endif | ||
346 | |||
347 | if (AC97_STEREO_MASK & (1 << oss_channel)) { | ||
348 | /* stereo mixers */ | ||
349 | if (left == 0 && right == 0) { | ||
350 | val = AC97_MUTE; | ||
351 | } else { | ||
352 | if (oss_channel == SOUND_MIXER_IGAIN) { | ||
353 | right = (right * mh->scale) / 100; | ||
354 | left = (left * mh->scale) / 100; | ||
355 | if (right >= mh->scale) | ||
356 | right = mh->scale-1; | ||
357 | if (left >= mh->scale) | ||
358 | left = mh->scale-1; | ||
359 | } else { | ||
360 | /* these may have 5 or 6 bit resolution */ | ||
361 | if (oss_channel == SOUND_MIXER_VOLUME || | ||
362 | oss_channel == SOUND_MIXER_ALTPCM) | ||
363 | scale = (1 << codec->bit_resolution); | ||
364 | else | ||
365 | scale = mh->scale; | ||
366 | |||
367 | right = ((100 - right) * scale) / 100; | ||
368 | left = ((100 - left) * scale) / 100; | ||
369 | if (right >= scale) | ||
370 | right = scale-1; | ||
371 | if (left >= scale) | ||
372 | left = scale-1; | ||
373 | } | ||
374 | val = (left << 8) | right; | ||
375 | } | ||
376 | } else if (oss_channel == SOUND_MIXER_BASS) { | ||
377 | val = codec->codec_read(codec , mh->offset) & ~0x0f00; | ||
378 | left = ((100 - left) * mh->scale) / 100; | ||
379 | if (left >= mh->scale) | ||
380 | left = mh->scale-1; | ||
381 | val |= (left << 8) & 0x0e00; | ||
382 | } else if (oss_channel == SOUND_MIXER_TREBLE) { | ||
383 | val = codec->codec_read(codec , mh->offset) & ~0x000f; | ||
384 | left = ((100 - left) * mh->scale) / 100; | ||
385 | if (left >= mh->scale) | ||
386 | left = mh->scale-1; | ||
387 | val |= left & 0x000e; | ||
388 | } else if(left == 0) { | ||
389 | val = AC97_MUTE; | ||
390 | } else if (oss_channel == SOUND_MIXER_SPEAKER) { | ||
391 | left = ((100 - left) * mh->scale) / 100; | ||
392 | if (left >= mh->scale) | ||
393 | left = mh->scale-1; | ||
394 | val = left << 1; | ||
395 | } else if (oss_channel == SOUND_MIXER_PHONEIN) { | ||
396 | left = ((100 - left) * mh->scale) / 100; | ||
397 | if (left >= mh->scale) | ||
398 | left = mh->scale-1; | ||
399 | val = left; | ||
400 | } else if (oss_channel == SOUND_MIXER_PHONEOUT) { | ||
401 | scale = (1 << codec->bit_resolution); | ||
402 | left = ((100 - left) * scale) / 100; | ||
403 | if (left >= mh->scale) | ||
404 | left = mh->scale-1; | ||
405 | val = left; | ||
406 | } else if (oss_channel == SOUND_MIXER_MIC) { | ||
407 | val = codec->codec_read(codec , mh->offset) & ~0x801f; | ||
408 | left = ((100 - left) * mh->scale) / 100; | ||
409 | if (left >= mh->scale) | ||
410 | left = mh->scale-1; | ||
411 | val |= left; | ||
412 | /* the low bit is optional in the tone sliders and masking | ||
413 | it lets us avoid the 0xf 'bypass'.. */ | ||
414 | } | ||
415 | #ifdef DEBUG | ||
416 | printk(" 0x%04x", val); | ||
417 | #endif | ||
418 | |||
419 | codec->codec_write(codec, mh->offset, val); | ||
420 | |||
421 | #ifdef DEBUG | ||
422 | val = codec->codec_read(codec, mh->offset); | ||
423 | printk(" -> 0x%04x\n", val); | ||
424 | #endif | ||
425 | } | ||
426 | |||
427 | /* a thin wrapper for write_mixer */ | ||
428 | static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val ) | ||
429 | { | ||
430 | unsigned int left,right; | ||
431 | |||
432 | /* cleanse input a little */ | ||
433 | right = ((val >> 8) & 0xff) ; | ||
434 | left = (val & 0xff) ; | ||
435 | |||
436 | if (right > 100) right = 100; | ||
437 | if (left > 100) left = 100; | ||
438 | |||
439 | codec->mixer_state[oss_mixer] = (right << 8) | left; | ||
440 | codec->write_mixer(codec, oss_mixer, left, right); | ||
441 | } | ||
442 | |||
443 | /* read or write the recmask, the ac97 can really have left and right recording | ||
444 | inputs independently set, but OSS doesn't seem to want us to express that to | ||
445 | the user. the caller guarantees that we have a supported bit set, and they | ||
446 | must be holding the card's spinlock */ | ||
447 | static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask) | ||
448 | { | ||
449 | unsigned int val; | ||
450 | |||
451 | if (rw) { | ||
452 | /* read it from the card */ | ||
453 | val = codec->codec_read(codec, AC97_RECORD_SELECT); | ||
454 | #ifdef DEBUG | ||
455 | printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val); | ||
456 | #endif | ||
457 | return (1 << ac97_rm2oss[val & 0x07]); | ||
458 | } | ||
459 | |||
460 | /* else, write the first set in the mask as the | ||
461 | output */ | ||
462 | /* clear out current set value first (AC97 supports only 1 input!) */ | ||
463 | val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT) & 0x07]); | ||
464 | if (mask != val) | ||
465 | mask &= ~val; | ||
466 | |||
467 | val = ffs(mask); | ||
468 | val = ac97_oss_rm[val-1]; | ||
469 | val |= val << 8; /* set both channels */ | ||
470 | |||
471 | #ifdef DEBUG | ||
472 | printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val); | ||
473 | #endif | ||
474 | |||
475 | codec->codec_write(codec, AC97_RECORD_SELECT, val); | ||
476 | |||
477 | return 0; | ||
478 | }; | ||
479 | |||
480 | static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg) | ||
481 | { | ||
482 | int i, val = 0; | ||
483 | |||
484 | if (cmd == SOUND_MIXER_INFO) { | ||
485 | mixer_info info; | ||
486 | memset(&info, 0, sizeof(info)); | ||
487 | strlcpy(info.id, codec->name, sizeof(info.id)); | ||
488 | strlcpy(info.name, codec->name, sizeof(info.name)); | ||
489 | info.modify_counter = codec->modcnt; | ||
490 | if (copy_to_user((void __user *)arg, &info, sizeof(info))) | ||
491 | return -EFAULT; | ||
492 | return 0; | ||
493 | } | ||
494 | if (cmd == SOUND_OLD_MIXER_INFO) { | ||
495 | _old_mixer_info info; | ||
496 | memset(&info, 0, sizeof(info)); | ||
497 | strlcpy(info.id, codec->name, sizeof(info.id)); | ||
498 | strlcpy(info.name, codec->name, sizeof(info.name)); | ||
499 | if (copy_to_user((void __user *)arg, &info, sizeof(info))) | ||
500 | return -EFAULT; | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) | ||
505 | return -EINVAL; | ||
506 | |||
507 | if (cmd == OSS_GETVERSION) | ||
508 | return put_user(SOUND_VERSION, (int __user *)arg); | ||
509 | |||
510 | if (_SIOC_DIR(cmd) == _SIOC_READ) { | ||
511 | switch (_IOC_NR(cmd)) { | ||
512 | case SOUND_MIXER_RECSRC: /* give them the current record source */ | ||
513 | if (!codec->recmask_io) { | ||
514 | val = 0; | ||
515 | } else { | ||
516 | val = codec->recmask_io(codec, 1, 0); | ||
517 | } | ||
518 | break; | ||
519 | |||
520 | case SOUND_MIXER_DEVMASK: /* give them the supported mixers */ | ||
521 | val = codec->supported_mixers; | ||
522 | break; | ||
523 | |||
524 | case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ | ||
525 | val = codec->record_sources; | ||
526 | break; | ||
527 | |||
528 | case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ | ||
529 | val = codec->stereo_mixers; | ||
530 | break; | ||
531 | |||
532 | case SOUND_MIXER_CAPS: | ||
533 | val = SOUND_CAP_EXCL_INPUT; | ||
534 | break; | ||
535 | |||
536 | default: /* read a specific mixer */ | ||
537 | i = _IOC_NR(cmd); | ||
538 | |||
539 | if (!supported_mixer(codec, i)) | ||
540 | return -EINVAL; | ||
541 | |||
542 | /* do we ever want to touch the hardware? */ | ||
543 | /* val = codec->read_mixer(codec, i); */ | ||
544 | val = codec->mixer_state[i]; | ||
545 | break; | ||
546 | } | ||
547 | return put_user(val, (int __user *)arg); | ||
548 | } | ||
549 | |||
550 | if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) { | ||
551 | codec->modcnt++; | ||
552 | if (get_user(val, (int __user *)arg)) | ||
553 | return -EFAULT; | ||
554 | |||
555 | switch (_IOC_NR(cmd)) { | ||
556 | case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ | ||
557 | if (!codec->recmask_io) return -EINVAL; | ||
558 | if (!val) return 0; | ||
559 | if (!(val &= codec->record_sources)) return -EINVAL; | ||
560 | |||
561 | codec->recmask_io(codec, 0, val); | ||
562 | |||
563 | return 0; | ||
564 | default: /* write a specific mixer */ | ||
565 | i = _IOC_NR(cmd); | ||
566 | |||
567 | if (!supported_mixer(codec, i)) | ||
568 | return -EINVAL; | ||
569 | |||
570 | ac97_set_mixer(codec, i, val); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | } | ||
575 | return -EINVAL; | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * codec_id - Turn id1/id2 into a PnP string | ||
580 | * @id1: Vendor ID1 | ||
581 | * @id2: Vendor ID2 | ||
582 | * @buf: CODEC_ID_BUFSZ byte buffer | ||
583 | * | ||
584 | * Fills buf with a zero terminated PnP ident string for the id1/id2 | ||
585 | * pair. For convenience the return is the passed in buffer pointer. | ||
586 | */ | ||
587 | |||
588 | static char *codec_id(u16 id1, u16 id2, char *buf) | ||
589 | { | ||
590 | if(id1&0x8080) { | ||
591 | snprintf(buf, CODEC_ID_BUFSZ, "0x%04x:0x%04x", id1, id2); | ||
592 | } else { | ||
593 | buf[0] = (id1 >> 8); | ||
594 | buf[1] = (id1 & 0xFF); | ||
595 | buf[2] = (id2 >> 8); | ||
596 | snprintf(buf+3, CODEC_ID_BUFSZ - 3, "%d", id2&0xFF); | ||
597 | } | ||
598 | return buf; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * ac97_check_modem - Check if the Codec is a modem | ||
603 | * @codec: codec to check | ||
604 | * | ||
605 | * Return true if the device is an AC97 1.0 or AC97 2.0 modem | ||
606 | */ | ||
607 | |||
608 | static int ac97_check_modem(struct ac97_codec *codec) | ||
609 | { | ||
610 | /* Check for an AC97 1.0 soft modem (ID1) */ | ||
611 | if(codec->codec_read(codec, AC97_RESET) & 2) | ||
612 | return 1; | ||
613 | /* Check for an AC97 2.x soft modem */ | ||
614 | codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L); | ||
615 | if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID) & 1) | ||
616 | return 1; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | |||
621 | /** | ||
622 | * ac97_alloc_codec - Allocate an AC97 codec | ||
623 | * | ||
624 | * Returns a new AC97 codec structure. AC97 codecs may become | ||
625 | * refcounted soon so this interface is needed. Returns with | ||
626 | * one reference taken. | ||
627 | */ | ||
628 | |||
629 | struct ac97_codec *ac97_alloc_codec(void) | ||
630 | { | ||
631 | struct ac97_codec *codec = kzalloc(sizeof(struct ac97_codec), GFP_KERNEL); | ||
632 | if(!codec) | ||
633 | return NULL; | ||
634 | |||
635 | spin_lock_init(&codec->lock); | ||
636 | INIT_LIST_HEAD(&codec->list); | ||
637 | return codec; | ||
638 | } | ||
639 | |||
640 | EXPORT_SYMBOL(ac97_alloc_codec); | ||
641 | |||
642 | /** | ||
643 | * ac97_release_codec - Release an AC97 codec | ||
644 | * @codec: codec to release | ||
645 | * | ||
646 | * Release an allocated AC97 codec. This will be refcounted in | ||
647 | * time but for the moment is trivial. Calls the unregister | ||
648 | * handler if the codec is now defunct. | ||
649 | */ | ||
650 | |||
651 | void ac97_release_codec(struct ac97_codec *codec) | ||
652 | { | ||
653 | /* Remove from the list first, we don't want to be | ||
654 | "rediscovered" */ | ||
655 | mutex_lock(&codec_mutex); | ||
656 | list_del(&codec->list); | ||
657 | mutex_unlock(&codec_mutex); | ||
658 | /* | ||
659 | * The driver needs to deal with internal | ||
660 | * locking to avoid accidents here. | ||
661 | */ | ||
662 | if(codec->driver) | ||
663 | codec->driver->remove(codec, codec->driver); | ||
664 | kfree(codec); | ||
665 | } | ||
666 | |||
667 | EXPORT_SYMBOL(ac97_release_codec); | ||
668 | |||
669 | /** | ||
670 | * ac97_probe_codec - Initialize and setup AC97-compatible codec | ||
671 | * @codec: (in/out) Kernel info for a single AC97 codec | ||
672 | * | ||
673 | * Reset the AC97 codec, then initialize the mixer and | ||
674 | * the rest of the @codec structure. | ||
675 | * | ||
676 | * The codec_read and codec_write fields of @codec are | ||
677 | * required to be setup and working when this function | ||
678 | * is called. All other fields are set by this function. | ||
679 | * | ||
680 | * codec_wait field of @codec can optionally be provided | ||
681 | * when calling this function. If codec_wait is not %NULL, | ||
682 | * this function will call codec_wait any time it is | ||
683 | * necessary to wait for the audio chip to reach the | ||
684 | * codec-ready state. If codec_wait is %NULL, then | ||
685 | * the default behavior is to call schedule_timeout. | ||
686 | * Currently codec_wait is used to wait for AC97 codec | ||
687 | * reset to complete. | ||
688 | * | ||
689 | * Some codecs will power down when a register reset is | ||
690 | * performed. We now check for such codecs. | ||
691 | * | ||
692 | * Returns 1 (true) on success, or 0 (false) on failure. | ||
693 | */ | ||
694 | |||
695 | int ac97_probe_codec(struct ac97_codec *codec) | ||
696 | { | ||
697 | u16 id1, id2; | ||
698 | u16 audio; | ||
699 | int i; | ||
700 | char cidbuf[CODEC_ID_BUFSZ]; | ||
701 | u16 f; | ||
702 | struct list_head *l; | ||
703 | struct ac97_driver *d; | ||
704 | |||
705 | /* wait for codec-ready state */ | ||
706 | if (codec->codec_wait) | ||
707 | codec->codec_wait(codec); | ||
708 | else | ||
709 | udelay(10); | ||
710 | |||
711 | /* will the codec power down if register reset ? */ | ||
712 | id1 = codec->codec_read(codec, AC97_VENDOR_ID1); | ||
713 | id2 = codec->codec_read(codec, AC97_VENDOR_ID2); | ||
714 | codec->name = NULL; | ||
715 | codec->codec_ops = &null_ops; | ||
716 | for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) { | ||
717 | if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) { | ||
718 | codec->type = ac97_codec_ids[i].id; | ||
719 | codec->name = ac97_codec_ids[i].name; | ||
720 | codec->codec_ops = ac97_codec_ids[i].ops; | ||
721 | codec->flags = ac97_codec_ids[i].flags; | ||
722 | break; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | codec->model = (id1 << 16) | id2; | ||
727 | if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) { | ||
728 | /* reset codec and wait for the ready bit before we continue */ | ||
729 | codec->codec_write(codec, AC97_RESET, 0L); | ||
730 | if (codec->codec_wait) | ||
731 | codec->codec_wait(codec); | ||
732 | else | ||
733 | udelay(10); | ||
734 | } | ||
735 | |||
736 | /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should | ||
737 | * be read zero. | ||
738 | * | ||
739 | * FIXME: is the following comment outdated? -jgarzik | ||
740 | * Probing of AC97 in this way is not reliable, it is not even SAFE !! | ||
741 | */ | ||
742 | if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { | ||
743 | printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", | ||
744 | (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") | ||
745 | : (codec->id&1 ? "Secondary": "Primary")); | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | /* probe for Modem Codec */ | ||
750 | codec->modem = ac97_check_modem(codec); | ||
751 | |||
752 | /* enable SPDIF */ | ||
753 | f = codec->codec_read(codec, AC97_EXTENDED_STATUS); | ||
754 | if((codec->codec_ops == &null_ops) && (f & 4)) | ||
755 | codec->codec_ops = &default_digital_ops; | ||
756 | |||
757 | /* A device which thinks its a modem but isn't */ | ||
758 | if(codec->flags & AC97_DELUDED_MODEM) | ||
759 | codec->modem = 0; | ||
760 | |||
761 | if (codec->name == NULL) | ||
762 | codec->name = "Unknown"; | ||
763 | printk(KERN_INFO "ac97_codec: AC97 %s codec, id: %s (%s)\n", | ||
764 | codec->modem ? "Modem" : (audio ? "Audio" : ""), | ||
765 | codec_id(id1, id2, cidbuf), codec->name); | ||
766 | |||
767 | if(!ac97_init_mixer(codec)) | ||
768 | return 0; | ||
769 | |||
770 | /* | ||
771 | * Attach last so the caller can override the mixer | ||
772 | * callbacks. | ||
773 | */ | ||
774 | |||
775 | mutex_lock(&codec_mutex); | ||
776 | list_add(&codec->list, &codecs); | ||
777 | |||
778 | list_for_each(l, &codec_drivers) { | ||
779 | d = list_entry(l, struct ac97_driver, list); | ||
780 | if ((codec->model ^ d->codec_id) & d->codec_mask) | ||
781 | continue; | ||
782 | if(d->probe(codec, d) == 0) | ||
783 | { | ||
784 | codec->driver = d; | ||
785 | break; | ||
786 | } | ||
787 | } | ||
788 | |||
789 | mutex_unlock(&codec_mutex); | ||
790 | return 1; | ||
791 | } | ||
792 | |||
793 | static int ac97_init_mixer(struct ac97_codec *codec) | ||
794 | { | ||
795 | u16 cap; | ||
796 | int i; | ||
797 | |||
798 | cap = codec->codec_read(codec, AC97_RESET); | ||
799 | |||
800 | /* mixer masks */ | ||
801 | codec->supported_mixers = AC97_SUPPORTED_MASK; | ||
802 | codec->stereo_mixers = AC97_STEREO_MASK; | ||
803 | codec->record_sources = AC97_RECORD_MASK; | ||
804 | if (!(cap & 0x04)) | ||
805 | codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE); | ||
806 | if (!(cap & 0x10)) | ||
807 | codec->supported_mixers &= ~SOUND_MASK_ALTPCM; | ||
808 | |||
809 | |||
810 | /* detect bit resolution */ | ||
811 | codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0x2020); | ||
812 | if(codec->codec_read(codec, AC97_MASTER_VOL_STEREO) == 0x2020) | ||
813 | codec->bit_resolution = 6; | ||
814 | else | ||
815 | codec->bit_resolution = 5; | ||
816 | |||
817 | /* generic OSS to AC97 wrapper */ | ||
818 | codec->read_mixer = ac97_read_mixer; | ||
819 | codec->write_mixer = ac97_write_mixer; | ||
820 | codec->recmask_io = ac97_recmask_io; | ||
821 | codec->mixer_ioctl = ac97_mixer_ioctl; | ||
822 | |||
823 | /* initialize mixer channel volumes */ | ||
824 | for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { | ||
825 | struct mixer_defaults *md = &mixer_defaults[i]; | ||
826 | if (md->mixer == -1) | ||
827 | break; | ||
828 | if (!supported_mixer(codec, md->mixer)) | ||
829 | continue; | ||
830 | ac97_set_mixer(codec, md->mixer, md->value); | ||
831 | } | ||
832 | |||
833 | /* codec specific initialization for 4-6 channel output or secondary codec stuff */ | ||
834 | if (codec->codec_ops->init != NULL) { | ||
835 | codec->codec_ops->init(codec); | ||
836 | } | ||
837 | |||
838 | /* | ||
839 | * Volume is MUTE only on this device. We have to initialise | ||
840 | * it but its useless beyond that. | ||
841 | */ | ||
842 | if(codec->flags & AC97_NO_PCM_VOLUME) | ||
843 | { | ||
844 | codec->supported_mixers &= ~SOUND_MASK_PCM; | ||
845 | printk(KERN_WARNING "AC97 codec does not have proper volume support.\n"); | ||
846 | } | ||
847 | return 1; | ||
848 | } | ||
849 | |||
850 | #define AC97_SIGMATEL_ANALOG 0x6c /* Analog Special */ | ||
851 | #define AC97_SIGMATEL_DAC2INVERT 0x6e | ||
852 | #define AC97_SIGMATEL_BIAS1 0x70 | ||
853 | #define AC97_SIGMATEL_BIAS2 0x72 | ||
854 | #define AC97_SIGMATEL_MULTICHN 0x74 /* Multi-Channel programming */ | ||
855 | #define AC97_SIGMATEL_CIC1 0x76 | ||
856 | #define AC97_SIGMATEL_CIC2 0x78 | ||
857 | |||
858 | |||
859 | static int sigmatel_9708_init(struct ac97_codec * codec) | ||
860 | { | ||
861 | u16 codec72, codec6c; | ||
862 | |||
863 | codec72 = codec->codec_read(codec, AC97_SIGMATEL_BIAS2) & 0x8000; | ||
864 | codec6c = codec->codec_read(codec, AC97_SIGMATEL_ANALOG); | ||
865 | |||
866 | if ((codec72==0) && (codec6c==0)) { | ||
867 | codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); | ||
868 | codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1000); | ||
869 | codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba); | ||
870 | codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0007); | ||
871 | } else if ((codec72==0x8000) && (codec6c==0)) { | ||
872 | codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); | ||
873 | codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1001); | ||
874 | codec->codec_write(codec, AC97_SIGMATEL_DAC2INVERT, 0x0008); | ||
875 | } else if ((codec72==0x8000) && (codec6c==0x0080)) { | ||
876 | /* nothing */ | ||
877 | } | ||
878 | codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000); | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | |||
883 | static int sigmatel_9721_init(struct ac97_codec * codec) | ||
884 | { | ||
885 | /* Only set up secondary codec */ | ||
886 | if (codec->id == 0) | ||
887 | return 0; | ||
888 | |||
889 | codec->codec_write(codec, AC97_SURROUND_MASTER, 0L); | ||
890 | |||
891 | /* initialize SigmaTel STAC9721/23 as secondary codec, decoding AC link | ||
892 | sloc 3,4 = 0x01, slot 7,8 = 0x00, */ | ||
893 | codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x00); | ||
894 | |||
895 | /* we don't have the crystal when we are on an AMR card, so use | ||
896 | BIT_CLK as our clock source. Write the magic word ABBA and read | ||
897 | back to enable register 0x78 */ | ||
898 | codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); | ||
899 | codec->codec_read(codec, AC97_SIGMATEL_CIC1); | ||
900 | |||
901 | /* sync all the clocks*/ | ||
902 | codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x3802); | ||
903 | |||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | |||
908 | static int sigmatel_9744_init(struct ac97_codec * codec) | ||
909 | { | ||
910 | // patch for SigmaTel | ||
911 | codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); | ||
912 | codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x0000); // is this correct? --jk | ||
913 | codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba); | ||
914 | codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0002); | ||
915 | codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000); | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static int cmedia_init(struct ac97_codec *codec) | ||
920 | { | ||
921 | /* Initialise the CMedia 9739 */ | ||
922 | /* | ||
923 | We could set various options here | ||
924 | Register 0x20 bit 0x100 sets mic as center bass | ||
925 | Also do multi_channel_ctrl &=~0x3000 |=0x1000 | ||
926 | |||
927 | For now we set up the GPIO and PC beep | ||
928 | */ | ||
929 | |||
930 | u16 v; | ||
931 | |||
932 | /* MIC */ | ||
933 | codec->codec_write(codec, 0x64, 0x3000); | ||
934 | v = codec->codec_read(codec, 0x64); | ||
935 | v &= ~0x8000; | ||
936 | codec->codec_write(codec, 0x64, v); | ||
937 | codec->codec_write(codec, 0x70, 0x0100); | ||
938 | codec->codec_write(codec, 0x72, 0x0020); | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | #define AC97_WM97XX_FMIXER_VOL 0x72 | ||
943 | #define AC97_WM97XX_RMIXER_VOL 0x74 | ||
944 | #define AC97_WM97XX_TEST 0x5a | ||
945 | #define AC97_WM9704_RPCM_VOL 0x70 | ||
946 | #define AC97_WM9711_OUT3VOL 0x16 | ||
947 | |||
948 | static int wolfson_init03(struct ac97_codec * codec) | ||
949 | { | ||
950 | /* this is known to work for the ViewSonic ViewPad 1000 */ | ||
951 | codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); | ||
952 | codec->codec_write(codec, AC97_GENERAL_PURPOSE, 0x8000); | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int wolfson_init04(struct ac97_codec * codec) | ||
957 | { | ||
958 | codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); | ||
959 | codec->codec_write(codec, AC97_WM97XX_RMIXER_VOL, 0x0808); | ||
960 | |||
961 | // patch for DVD noise | ||
962 | codec->codec_write(codec, AC97_WM97XX_TEST, 0x0200); | ||
963 | |||
964 | // init vol as PCM vol | ||
965 | codec->codec_write(codec, AC97_WM9704_RPCM_VOL, | ||
966 | codec->codec_read(codec, AC97_PCMOUT_VOL)); | ||
967 | |||
968 | /* set rear surround volume */ | ||
969 | codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000); | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | /* WM9705, WM9710 */ | ||
974 | static int wolfson_init05(struct ac97_codec * codec) | ||
975 | { | ||
976 | /* set front mixer volume */ | ||
977 | codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* WM9711, WM9712 */ | ||
982 | static int wolfson_init11(struct ac97_codec * codec) | ||
983 | { | ||
984 | /* stop pop's during suspend/resume */ | ||
985 | codec->codec_write(codec, AC97_WM97XX_TEST, | ||
986 | codec->codec_read(codec, AC97_WM97XX_TEST) & 0xffbf); | ||
987 | |||
988 | /* set out3 volume */ | ||
989 | codec->codec_write(codec, AC97_WM9711_OUT3VOL, 0x0808); | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | /* WM9713 */ | ||
994 | static int wolfson_init13(struct ac97_codec * codec) | ||
995 | { | ||
996 | codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0); | ||
997 | codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000); | ||
998 | codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00); | ||
999 | codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810); | ||
1000 | codec->codec_write(codec, AC97_PHONE_VOL, 0x0808); | ||
1001 | codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808); | ||
1002 | |||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | static int tritech_init(struct ac97_codec * codec) | ||
1007 | { | ||
1008 | codec->codec_write(codec, 0x26, 0x0300); | ||
1009 | codec->codec_write(codec, 0x26, 0x0000); | ||
1010 | codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000); | ||
1011 | codec->codec_write(codec, AC97_RESERVED_3A, 0x0000); | ||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /* copied from drivers/sound/maestro.c */ | ||
1017 | static int tritech_maestro_init(struct ac97_codec * codec) | ||
1018 | { | ||
1019 | /* no idea what this does */ | ||
1020 | codec->codec_write(codec, 0x2A, 0x0001); | ||
1021 | codec->codec_write(codec, 0x2C, 0x0000); | ||
1022 | codec->codec_write(codec, 0x2C, 0XFFFF); | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | |||
1028 | /* | ||
1029 | * Presario700 workaround | ||
1030 | * for Jack Sense/SPDIF Register mis-setting causing | ||
1031 | * no audible output | ||
1032 | * by Santiago Nullo 04/05/2002 | ||
1033 | */ | ||
1034 | |||
1035 | #define AC97_AD1886_JACK_SENSE 0x72 | ||
1036 | |||
1037 | static int ad1886_init(struct ac97_codec * codec) | ||
1038 | { | ||
1039 | /* from AD1886 Specs */ | ||
1040 | codec->codec_write(codec, AC97_AD1886_JACK_SENSE, 0x0010); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | |||
1045 | |||
1046 | |||
1047 | /* | ||
1048 | * This is basically standard AC97. It should work as a default for | ||
1049 | * almost all modern codecs. Note that some cards wire EAPD *backwards* | ||
1050 | * That side of it is up to the card driver not us to cope with. | ||
1051 | * | ||
1052 | */ | ||
1053 | |||
1054 | static int eapd_control(struct ac97_codec * codec, int on) | ||
1055 | { | ||
1056 | if(on) | ||
1057 | codec->codec_write(codec, AC97_POWER_CONTROL, | ||
1058 | codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000); | ||
1059 | else | ||
1060 | codec->codec_write(codec, AC97_POWER_CONTROL, | ||
1061 | codec->codec_read(codec, AC97_POWER_CONTROL)&~0x8000); | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) | ||
1066 | { | ||
1067 | u16 reg; | ||
1068 | |||
1069 | reg = codec->codec_read(codec, AC97_SPDIF_CONTROL); | ||
1070 | |||
1071 | switch(rate) | ||
1072 | { | ||
1073 | /* Off by default */ | ||
1074 | default: | ||
1075 | case 0: | ||
1076 | reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); | ||
1077 | codec->codec_write(codec, AC97_EXTENDED_STATUS, (reg & ~AC97_EA_SPDIF)); | ||
1078 | if(rate == 0) | ||
1079 | return 0; | ||
1080 | return -EINVAL; | ||
1081 | case 1: | ||
1082 | reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K; | ||
1083 | break; | ||
1084 | case 2: | ||
1085 | reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K; | ||
1086 | break; | ||
1087 | case 3: | ||
1088 | reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K; | ||
1089 | break; | ||
1090 | } | ||
1091 | |||
1092 | reg &= ~AC97_SC_CC_MASK; | ||
1093 | reg |= (mode & AUDIO_CCMASK) << 6; | ||
1094 | |||
1095 | if(mode & AUDIO_DIGITAL) | ||
1096 | reg |= 2; | ||
1097 | if(mode & AUDIO_PRO) | ||
1098 | reg |= 1; | ||
1099 | if(mode & AUDIO_DRS) | ||
1100 | reg |= 0x4000; | ||
1101 | |||
1102 | codec->codec_write(codec, AC97_SPDIF_CONTROL, reg); | ||
1103 | |||
1104 | reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); | ||
1105 | reg &= (AC97_EA_SLOT_MASK); | ||
1106 | reg |= AC97_EA_VRA | AC97_EA_SPDIF | slots; | ||
1107 | codec->codec_write(codec, AC97_EXTENDED_STATUS, reg); | ||
1108 | |||
1109 | reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); | ||
1110 | if(!(reg & 0x0400)) | ||
1111 | { | ||
1112 | codec->codec_write(codec, AC97_EXTENDED_STATUS, reg & ~ AC97_EA_SPDIF); | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | * Crystal digital audio control (CS4299) | ||
1120 | */ | ||
1121 | |||
1122 | static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) | ||
1123 | { | ||
1124 | u16 cv; | ||
1125 | |||
1126 | if(mode & AUDIO_DIGITAL) | ||
1127 | return -EINVAL; | ||
1128 | |||
1129 | switch(rate) | ||
1130 | { | ||
1131 | case 0: cv = 0x0; break; /* SPEN off */ | ||
1132 | case 48000: cv = 0x8004; break; /* 48KHz digital */ | ||
1133 | case 44100: cv = 0x8104; break; /* 44.1KHz digital */ | ||
1134 | case 32768: /* 32Khz */ | ||
1135 | default: | ||
1136 | return -EINVAL; | ||
1137 | } | ||
1138 | codec->codec_write(codec, 0x68, cv); | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | /* | ||
1143 | * CMedia digital audio control | ||
1144 | * Needs more work. | ||
1145 | */ | ||
1146 | |||
1147 | static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) | ||
1148 | { | ||
1149 | u16 cv; | ||
1150 | |||
1151 | if(mode & AUDIO_DIGITAL) | ||
1152 | return -EINVAL; | ||
1153 | |||
1154 | switch(rate) | ||
1155 | { | ||
1156 | case 0: cv = 0x0001; break; /* SPEN off */ | ||
1157 | case 48000: cv = 0x0009; break; /* 48KHz digital */ | ||
1158 | default: | ||
1159 | return -EINVAL; | ||
1160 | } | ||
1161 | codec->codec_write(codec, 0x2A, 0x05c4); | ||
1162 | codec->codec_write(codec, 0x6C, cv); | ||
1163 | |||
1164 | /* Switch on mix to surround */ | ||
1165 | cv = codec->codec_read(codec, 0x64); | ||
1166 | cv &= ~0x0200; | ||
1167 | if(mode) | ||
1168 | cv |= 0x0200; | ||
1169 | codec->codec_write(codec, 0x64, cv); | ||
1170 | return 0; | ||
1171 | } | ||
1172 | |||
1173 | |||
1174 | /* copied from drivers/sound/maestro.c */ | ||
1175 | #if 0 /* there has been 1 person on the planet with a pt101 that we | ||
1176 | know of. If they care, they can put this back in :) */ | ||
1177 | static int pt101_init(struct ac97_codec * codec) | ||
1178 | { | ||
1179 | printk(KERN_INFO "ac97_codec: PT101 Codec detected, initializing but _not_ installing mixer device.\n"); | ||
1180 | /* who knows.. */ | ||
1181 | codec->codec_write(codec, 0x2A, 0x0001); | ||
1182 | codec->codec_write(codec, 0x2C, 0x0000); | ||
1183 | codec->codec_write(codec, 0x2C, 0xFFFF); | ||
1184 | codec->codec_write(codec, 0x10, 0x9F1F); | ||
1185 | codec->codec_write(codec, 0x12, 0x0808); | ||
1186 | codec->codec_write(codec, 0x14, 0x9F1F); | ||
1187 | codec->codec_write(codec, 0x16, 0x9F1F); | ||
1188 | codec->codec_write(codec, 0x18, 0x0404); | ||
1189 | codec->codec_write(codec, 0x1A, 0x0000); | ||
1190 | codec->codec_write(codec, 0x1C, 0x0000); | ||
1191 | codec->codec_write(codec, 0x02, 0x0404); | ||
1192 | codec->codec_write(codec, 0x04, 0x0808); | ||
1193 | codec->codec_write(codec, 0x0C, 0x801F); | ||
1194 | codec->codec_write(codec, 0x0E, 0x801F); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | #endif | ||
1198 | |||
1199 | |||
1200 | EXPORT_SYMBOL(ac97_probe_codec); | ||
1201 | |||
1202 | MODULE_LICENSE("GPL"); | ||
1203 | |||
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c deleted file mode 100644 index a8f626d99c5b..000000000000 --- a/sound/oss/au1550_ac97.c +++ /dev/null | |||
@@ -1,2147 +0,0 @@ | |||
1 | /* | ||
2 | * au1550_ac97.c -- Sound driver for Alchemy Au1550 MIPS Internet Edge | ||
3 | * Processor. | ||
4 | * | ||
5 | * Copyright 2004 Embedded Edge, LLC | ||
6 | * dan@embeddededge.com | ||
7 | * | ||
8 | * Mostly copied from the au1000.c driver and some from the | ||
9 | * PowerMac dbdma driver. | ||
10 | * We assume the processor can do memory coherent DMA. | ||
11 | * | ||
12 | * Ported to 2.6 by Matt Porter <mporter@kernel.crashing.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
22 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
25 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | #undef DEBUG | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/ioport.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/sound.h> | ||
44 | #include <linux/slab.h> | ||
45 | #include <linux/soundcard.h> | ||
46 | #include <linux/init.h> | ||
47 | #include <linux/interrupt.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/poll.h> | ||
50 | #include <linux/bitops.h> | ||
51 | #include <linux/spinlock.h> | ||
52 | #include <linux/ac97_codec.h> | ||
53 | #include <linux/mutex.h> | ||
54 | |||
55 | #include <asm/io.h> | ||
56 | #include <asm/uaccess.h> | ||
57 | #include <asm/hardirq.h> | ||
58 | #include <asm/mach-au1x00/au1xxx_psc.h> | ||
59 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | ||
60 | #include <asm/mach-au1x00/au1xxx.h> | ||
61 | |||
62 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | ||
63 | |||
64 | /* misc stuff */ | ||
65 | #define POLL_COUNT 0x50000 | ||
66 | #define AC97_EXT_DACS (AC97_EXTID_SDAC | AC97_EXTID_CDAC | AC97_EXTID_LDAC) | ||
67 | |||
68 | /* The number of DBDMA ring descriptors to allocate. No sense making | ||
69 | * this too large....if you can't keep up with a few you aren't likely | ||
70 | * to be able to with lots of them, either. | ||
71 | */ | ||
72 | #define NUM_DBDMA_DESCRIPTORS 4 | ||
73 | |||
74 | #define err(format, arg...) printk(KERN_ERR format "\n" , ## arg) | ||
75 | |||
76 | /* Boot options | ||
77 | * 0 = no VRA, 1 = use VRA if codec supports it | ||
78 | */ | ||
79 | static DEFINE_MUTEX(au1550_ac97_mutex); | ||
80 | static int vra = 1; | ||
81 | module_param(vra, bool, 0); | ||
82 | MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it"); | ||
83 | |||
84 | static struct au1550_state { | ||
85 | /* soundcore stuff */ | ||
86 | int dev_audio; | ||
87 | |||
88 | struct ac97_codec *codec; | ||
89 | unsigned codec_base_caps; /* AC'97 reg 00h, "Reset Register" */ | ||
90 | unsigned codec_ext_caps; /* AC'97 reg 28h, "Extended Audio ID" */ | ||
91 | int no_vra; /* do not use VRA */ | ||
92 | |||
93 | spinlock_t lock; | ||
94 | struct mutex open_mutex; | ||
95 | struct mutex sem; | ||
96 | fmode_t open_mode; | ||
97 | wait_queue_head_t open_wait; | ||
98 | |||
99 | struct dmabuf { | ||
100 | u32 dmanr; | ||
101 | unsigned sample_rate; | ||
102 | unsigned src_factor; | ||
103 | unsigned sample_size; | ||
104 | int num_channels; | ||
105 | int dma_bytes_per_sample; | ||
106 | int user_bytes_per_sample; | ||
107 | int cnt_factor; | ||
108 | |||
109 | void *rawbuf; | ||
110 | unsigned buforder; | ||
111 | unsigned numfrag; | ||
112 | unsigned fragshift; | ||
113 | void *nextIn; | ||
114 | void *nextOut; | ||
115 | int count; | ||
116 | unsigned total_bytes; | ||
117 | unsigned error; | ||
118 | wait_queue_head_t wait; | ||
119 | |||
120 | /* redundant, but makes calculations easier */ | ||
121 | unsigned fragsize; | ||
122 | unsigned dma_fragsize; | ||
123 | unsigned dmasize; | ||
124 | unsigned dma_qcount; | ||
125 | |||
126 | /* OSS stuff */ | ||
127 | unsigned mapped:1; | ||
128 | unsigned ready:1; | ||
129 | unsigned stopped:1; | ||
130 | unsigned ossfragshift; | ||
131 | int ossmaxfrags; | ||
132 | unsigned subdivision; | ||
133 | } dma_dac, dma_adc; | ||
134 | } au1550_state; | ||
135 | |||
136 | static unsigned | ||
137 | ld2(unsigned int x) | ||
138 | { | ||
139 | unsigned r = 0; | ||
140 | |||
141 | if (x >= 0x10000) { | ||
142 | x >>= 16; | ||
143 | r += 16; | ||
144 | } | ||
145 | if (x >= 0x100) { | ||
146 | x >>= 8; | ||
147 | r += 8; | ||
148 | } | ||
149 | if (x >= 0x10) { | ||
150 | x >>= 4; | ||
151 | r += 4; | ||
152 | } | ||
153 | if (x >= 4) { | ||
154 | x >>= 2; | ||
155 | r += 2; | ||
156 | } | ||
157 | if (x >= 2) | ||
158 | r++; | ||
159 | return r; | ||
160 | } | ||
161 | |||
162 | static void | ||
163 | au1550_delay(int msec) | ||
164 | { | ||
165 | if (in_interrupt()) | ||
166 | return; | ||
167 | |||
168 | schedule_timeout_uninterruptible(msecs_to_jiffies(msec)); | ||
169 | } | ||
170 | |||
171 | static u16 | ||
172 | rdcodec(struct ac97_codec *codec, u8 addr) | ||
173 | { | ||
174 | struct au1550_state *s = codec->private_data; | ||
175 | unsigned long flags; | ||
176 | u32 cmd, val; | ||
177 | u16 data; | ||
178 | int i; | ||
179 | |||
180 | spin_lock_irqsave(&s->lock, flags); | ||
181 | |||
182 | for (i = 0; i < POLL_COUNT; i++) { | ||
183 | val = au_readl(PSC_AC97STAT); | ||
184 | au_sync(); | ||
185 | if (!(val & PSC_AC97STAT_CP)) | ||
186 | break; | ||
187 | } | ||
188 | if (i == POLL_COUNT) | ||
189 | err("rdcodec: codec cmd pending expired!"); | ||
190 | |||
191 | cmd = (u32)PSC_AC97CDC_INDX(addr); | ||
192 | cmd |= PSC_AC97CDC_RD; /* read command */ | ||
193 | au_writel(cmd, PSC_AC97CDC); | ||
194 | au_sync(); | ||
195 | |||
196 | /* now wait for the data | ||
197 | */ | ||
198 | for (i = 0; i < POLL_COUNT; i++) { | ||
199 | val = au_readl(PSC_AC97STAT); | ||
200 | au_sync(); | ||
201 | if (!(val & PSC_AC97STAT_CP)) | ||
202 | break; | ||
203 | } | ||
204 | if (i == POLL_COUNT) { | ||
205 | err("rdcodec: read poll expired!"); | ||
206 | data = 0; | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | /* wait for command done? | ||
211 | */ | ||
212 | for (i = 0; i < POLL_COUNT; i++) { | ||
213 | val = au_readl(PSC_AC97EVNT); | ||
214 | au_sync(); | ||
215 | if (val & PSC_AC97EVNT_CD) | ||
216 | break; | ||
217 | } | ||
218 | if (i == POLL_COUNT) { | ||
219 | err("rdcodec: read cmdwait expired!"); | ||
220 | data = 0; | ||
221 | goto out; | ||
222 | } | ||
223 | |||
224 | data = au_readl(PSC_AC97CDC) & 0xffff; | ||
225 | au_sync(); | ||
226 | |||
227 | /* Clear command done event. | ||
228 | */ | ||
229 | au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT); | ||
230 | au_sync(); | ||
231 | |||
232 | out: | ||
233 | spin_unlock_irqrestore(&s->lock, flags); | ||
234 | |||
235 | return data; | ||
236 | } | ||
237 | |||
238 | |||
239 | static void | ||
240 | wrcodec(struct ac97_codec *codec, u8 addr, u16 data) | ||
241 | { | ||
242 | struct au1550_state *s = codec->private_data; | ||
243 | unsigned long flags; | ||
244 | u32 cmd, val; | ||
245 | int i; | ||
246 | |||
247 | spin_lock_irqsave(&s->lock, flags); | ||
248 | |||
249 | for (i = 0; i < POLL_COUNT; i++) { | ||
250 | val = au_readl(PSC_AC97STAT); | ||
251 | au_sync(); | ||
252 | if (!(val & PSC_AC97STAT_CP)) | ||
253 | break; | ||
254 | } | ||
255 | if (i == POLL_COUNT) | ||
256 | err("wrcodec: codec cmd pending expired!"); | ||
257 | |||
258 | cmd = (u32)PSC_AC97CDC_INDX(addr); | ||
259 | cmd |= (u32)data; | ||
260 | au_writel(cmd, PSC_AC97CDC); | ||
261 | au_sync(); | ||
262 | |||
263 | for (i = 0; i < POLL_COUNT; i++) { | ||
264 | val = au_readl(PSC_AC97STAT); | ||
265 | au_sync(); | ||
266 | if (!(val & PSC_AC97STAT_CP)) | ||
267 | break; | ||
268 | } | ||
269 | if (i == POLL_COUNT) | ||
270 | err("wrcodec: codec cmd pending expired!"); | ||
271 | |||
272 | for (i = 0; i < POLL_COUNT; i++) { | ||
273 | val = au_readl(PSC_AC97EVNT); | ||
274 | au_sync(); | ||
275 | if (val & PSC_AC97EVNT_CD) | ||
276 | break; | ||
277 | } | ||
278 | if (i == POLL_COUNT) | ||
279 | err("wrcodec: read cmdwait expired!"); | ||
280 | |||
281 | /* Clear command done event. | ||
282 | */ | ||
283 | au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT); | ||
284 | au_sync(); | ||
285 | |||
286 | spin_unlock_irqrestore(&s->lock, flags); | ||
287 | } | ||
288 | |||
289 | static void | ||
290 | waitcodec(struct ac97_codec *codec) | ||
291 | { | ||
292 | u16 temp; | ||
293 | u32 val; | ||
294 | int i; | ||
295 | |||
296 | /* codec_wait is used to wait for a ready state after | ||
297 | * an AC97C_RESET. | ||
298 | */ | ||
299 | au1550_delay(10); | ||
300 | |||
301 | /* first poll the CODEC_READY tag bit | ||
302 | */ | ||
303 | for (i = 0; i < POLL_COUNT; i++) { | ||
304 | val = au_readl(PSC_AC97STAT); | ||
305 | au_sync(); | ||
306 | if (val & PSC_AC97STAT_CR) | ||
307 | break; | ||
308 | } | ||
309 | if (i == POLL_COUNT) { | ||
310 | err("waitcodec: CODEC_READY poll expired!"); | ||
311 | return; | ||
312 | } | ||
313 | |||
314 | /* get AC'97 powerdown control/status register | ||
315 | */ | ||
316 | temp = rdcodec(codec, AC97_POWER_CONTROL); | ||
317 | |||
318 | /* If anything is powered down, power'em up | ||
319 | */ | ||
320 | if (temp & 0x7f00) { | ||
321 | /* Power on | ||
322 | */ | ||
323 | wrcodec(codec, AC97_POWER_CONTROL, 0); | ||
324 | au1550_delay(100); | ||
325 | |||
326 | /* Reread | ||
327 | */ | ||
328 | temp = rdcodec(codec, AC97_POWER_CONTROL); | ||
329 | } | ||
330 | |||
331 | /* Check if Codec REF,ANL,DAC,ADC ready | ||
332 | */ | ||
333 | if ((temp & 0x7f0f) != 0x000f) | ||
334 | err("codec reg 26 status (0x%x) not ready!!", temp); | ||
335 | } | ||
336 | |||
337 | /* stop the ADC before calling */ | ||
338 | static void | ||
339 | set_adc_rate(struct au1550_state *s, unsigned rate) | ||
340 | { | ||
341 | struct dmabuf *adc = &s->dma_adc; | ||
342 | struct dmabuf *dac = &s->dma_dac; | ||
343 | unsigned adc_rate, dac_rate; | ||
344 | u16 ac97_extstat; | ||
345 | |||
346 | if (s->no_vra) { | ||
347 | /* calc SRC factor | ||
348 | */ | ||
349 | adc->src_factor = ((96000 / rate) + 1) >> 1; | ||
350 | adc->sample_rate = 48000 / adc->src_factor; | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | adc->src_factor = 1; | ||
355 | |||
356 | ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS); | ||
357 | |||
358 | rate = rate > 48000 ? 48000 : rate; | ||
359 | |||
360 | /* enable VRA | ||
361 | */ | ||
362 | wrcodec(s->codec, AC97_EXTENDED_STATUS, | ||
363 | ac97_extstat | AC97_EXTSTAT_VRA); | ||
364 | |||
365 | /* now write the sample rate | ||
366 | */ | ||
367 | wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, (u16) rate); | ||
368 | |||
369 | /* read it back for actual supported rate | ||
370 | */ | ||
371 | adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE); | ||
372 | |||
373 | pr_debug("set_adc_rate: set to %d Hz\n", adc_rate); | ||
374 | |||
375 | /* some codec's don't allow unequal DAC and ADC rates, in which case | ||
376 | * writing one rate reg actually changes both. | ||
377 | */ | ||
378 | dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE); | ||
379 | if (dac->num_channels > 2) | ||
380 | wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, dac_rate); | ||
381 | if (dac->num_channels > 4) | ||
382 | wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, dac_rate); | ||
383 | |||
384 | adc->sample_rate = adc_rate; | ||
385 | dac->sample_rate = dac_rate; | ||
386 | } | ||
387 | |||
388 | /* stop the DAC before calling */ | ||
389 | static void | ||
390 | set_dac_rate(struct au1550_state *s, unsigned rate) | ||
391 | { | ||
392 | struct dmabuf *dac = &s->dma_dac; | ||
393 | struct dmabuf *adc = &s->dma_adc; | ||
394 | unsigned adc_rate, dac_rate; | ||
395 | u16 ac97_extstat; | ||
396 | |||
397 | if (s->no_vra) { | ||
398 | /* calc SRC factor | ||
399 | */ | ||
400 | dac->src_factor = ((96000 / rate) + 1) >> 1; | ||
401 | dac->sample_rate = 48000 / dac->src_factor; | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | dac->src_factor = 1; | ||
406 | |||
407 | ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS); | ||
408 | |||
409 | rate = rate > 48000 ? 48000 : rate; | ||
410 | |||
411 | /* enable VRA | ||
412 | */ | ||
413 | wrcodec(s->codec, AC97_EXTENDED_STATUS, | ||
414 | ac97_extstat | AC97_EXTSTAT_VRA); | ||
415 | |||
416 | /* now write the sample rate | ||
417 | */ | ||
418 | wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, (u16) rate); | ||
419 | |||
420 | /* I don't support different sample rates for multichannel, | ||
421 | * so make these channels the same. | ||
422 | */ | ||
423 | if (dac->num_channels > 2) | ||
424 | wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, (u16) rate); | ||
425 | if (dac->num_channels > 4) | ||
426 | wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, (u16) rate); | ||
427 | /* read it back for actual supported rate | ||
428 | */ | ||
429 | dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE); | ||
430 | |||
431 | pr_debug("set_dac_rate: set to %d Hz\n", dac_rate); | ||
432 | |||
433 | /* some codec's don't allow unequal DAC and ADC rates, in which case | ||
434 | * writing one rate reg actually changes both. | ||
435 | */ | ||
436 | adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE); | ||
437 | |||
438 | dac->sample_rate = dac_rate; | ||
439 | adc->sample_rate = adc_rate; | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | stop_dac(struct au1550_state *s) | ||
444 | { | ||
445 | struct dmabuf *db = &s->dma_dac; | ||
446 | u32 stat; | ||
447 | unsigned long flags; | ||
448 | |||
449 | if (db->stopped) | ||
450 | return; | ||
451 | |||
452 | spin_lock_irqsave(&s->lock, flags); | ||
453 | |||
454 | au_writel(PSC_AC97PCR_TP, PSC_AC97PCR); | ||
455 | au_sync(); | ||
456 | |||
457 | /* Wait for Transmit Busy to show disabled. | ||
458 | */ | ||
459 | do { | ||
460 | stat = au_readl(PSC_AC97STAT); | ||
461 | au_sync(); | ||
462 | } while ((stat & PSC_AC97STAT_TB) != 0); | ||
463 | |||
464 | au1xxx_dbdma_reset(db->dmanr); | ||
465 | |||
466 | db->stopped = 1; | ||
467 | |||
468 | spin_unlock_irqrestore(&s->lock, flags); | ||
469 | } | ||
470 | |||
471 | static void | ||
472 | stop_adc(struct au1550_state *s) | ||
473 | { | ||
474 | struct dmabuf *db = &s->dma_adc; | ||
475 | unsigned long flags; | ||
476 | u32 stat; | ||
477 | |||
478 | if (db->stopped) | ||
479 | return; | ||
480 | |||
481 | spin_lock_irqsave(&s->lock, flags); | ||
482 | |||
483 | au_writel(PSC_AC97PCR_RP, PSC_AC97PCR); | ||
484 | au_sync(); | ||
485 | |||
486 | /* Wait for Receive Busy to show disabled. | ||
487 | */ | ||
488 | do { | ||
489 | stat = au_readl(PSC_AC97STAT); | ||
490 | au_sync(); | ||
491 | } while ((stat & PSC_AC97STAT_RB) != 0); | ||
492 | |||
493 | au1xxx_dbdma_reset(db->dmanr); | ||
494 | |||
495 | db->stopped = 1; | ||
496 | |||
497 | spin_unlock_irqrestore(&s->lock, flags); | ||
498 | } | ||
499 | |||
500 | |||
501 | static void | ||
502 | set_xmit_slots(int num_channels) | ||
503 | { | ||
504 | u32 ac97_config, stat; | ||
505 | |||
506 | ac97_config = au_readl(PSC_AC97CFG); | ||
507 | au_sync(); | ||
508 | ac97_config &= ~(PSC_AC97CFG_TXSLOT_MASK | PSC_AC97CFG_DE_ENABLE); | ||
509 | au_writel(ac97_config, PSC_AC97CFG); | ||
510 | au_sync(); | ||
511 | |||
512 | switch (num_channels) { | ||
513 | case 6: /* stereo with surround and center/LFE, | ||
514 | * slots 3,4,6,7,8,9 | ||
515 | */ | ||
516 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(6); | ||
517 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(9); | ||
518 | |||
519 | case 4: /* stereo with surround, slots 3,4,7,8 */ | ||
520 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(7); | ||
521 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(8); | ||
522 | |||
523 | case 2: /* stereo, slots 3,4 */ | ||
524 | case 1: /* mono */ | ||
525 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(3); | ||
526 | ac97_config |= PSC_AC97CFG_TXSLOT_ENA(4); | ||
527 | } | ||
528 | |||
529 | au_writel(ac97_config, PSC_AC97CFG); | ||
530 | au_sync(); | ||
531 | |||
532 | ac97_config |= PSC_AC97CFG_DE_ENABLE; | ||
533 | au_writel(ac97_config, PSC_AC97CFG); | ||
534 | au_sync(); | ||
535 | |||
536 | /* Wait for Device ready. | ||
537 | */ | ||
538 | do { | ||
539 | stat = au_readl(PSC_AC97STAT); | ||
540 | au_sync(); | ||
541 | } while ((stat & PSC_AC97STAT_DR) == 0); | ||
542 | } | ||
543 | |||
544 | static void | ||
545 | set_recv_slots(int num_channels) | ||
546 | { | ||
547 | u32 ac97_config, stat; | ||
548 | |||
549 | ac97_config = au_readl(PSC_AC97CFG); | ||
550 | au_sync(); | ||
551 | ac97_config &= ~(PSC_AC97CFG_RXSLOT_MASK | PSC_AC97CFG_DE_ENABLE); | ||
552 | au_writel(ac97_config, PSC_AC97CFG); | ||
553 | au_sync(); | ||
554 | |||
555 | /* Always enable slots 3 and 4 (stereo). Slot 6 is | ||
556 | * optional Mic ADC, which we don't support yet. | ||
557 | */ | ||
558 | ac97_config |= PSC_AC97CFG_RXSLOT_ENA(3); | ||
559 | ac97_config |= PSC_AC97CFG_RXSLOT_ENA(4); | ||
560 | |||
561 | au_writel(ac97_config, PSC_AC97CFG); | ||
562 | au_sync(); | ||
563 | |||
564 | ac97_config |= PSC_AC97CFG_DE_ENABLE; | ||
565 | au_writel(ac97_config, PSC_AC97CFG); | ||
566 | au_sync(); | ||
567 | |||
568 | /* Wait for Device ready. | ||
569 | */ | ||
570 | do { | ||
571 | stat = au_readl(PSC_AC97STAT); | ||
572 | au_sync(); | ||
573 | } while ((stat & PSC_AC97STAT_DR) == 0); | ||
574 | } | ||
575 | |||
576 | /* Hold spinlock for both start_dac() and start_adc() calls */ | ||
577 | static void | ||
578 | start_dac(struct au1550_state *s) | ||
579 | { | ||
580 | struct dmabuf *db = &s->dma_dac; | ||
581 | |||
582 | if (!db->stopped) | ||
583 | return; | ||
584 | |||
585 | set_xmit_slots(db->num_channels); | ||
586 | au_writel(PSC_AC97PCR_TC, PSC_AC97PCR); | ||
587 | au_sync(); | ||
588 | au_writel(PSC_AC97PCR_TS, PSC_AC97PCR); | ||
589 | au_sync(); | ||
590 | |||
591 | au1xxx_dbdma_start(db->dmanr); | ||
592 | |||
593 | db->stopped = 0; | ||
594 | } | ||
595 | |||
596 | static void | ||
597 | start_adc(struct au1550_state *s) | ||
598 | { | ||
599 | struct dmabuf *db = &s->dma_adc; | ||
600 | int i; | ||
601 | |||
602 | if (!db->stopped) | ||
603 | return; | ||
604 | |||
605 | /* Put two buffers on the ring to get things started. | ||
606 | */ | ||
607 | for (i=0; i<2; i++) { | ||
608 | au1xxx_dbdma_put_dest(db->dmanr, virt_to_phys(db->nextIn), | ||
609 | db->dma_fragsize, DDMA_FLAGS_IE); | ||
610 | |||
611 | db->nextIn += db->dma_fragsize; | ||
612 | if (db->nextIn >= db->rawbuf + db->dmasize) | ||
613 | db->nextIn -= db->dmasize; | ||
614 | } | ||
615 | |||
616 | set_recv_slots(db->num_channels); | ||
617 | au1xxx_dbdma_start(db->dmanr); | ||
618 | au_writel(PSC_AC97PCR_RC, PSC_AC97PCR); | ||
619 | au_sync(); | ||
620 | au_writel(PSC_AC97PCR_RS, PSC_AC97PCR); | ||
621 | au_sync(); | ||
622 | |||
623 | db->stopped = 0; | ||
624 | } | ||
625 | |||
626 | static int | ||
627 | prog_dmabuf(struct au1550_state *s, struct dmabuf *db) | ||
628 | { | ||
629 | unsigned user_bytes_per_sec; | ||
630 | unsigned bufs; | ||
631 | unsigned rate = db->sample_rate; | ||
632 | |||
633 | if (!db->rawbuf) { | ||
634 | db->ready = db->mapped = 0; | ||
635 | db->buforder = 5; /* 32 * PAGE_SIZE */ | ||
636 | db->rawbuf = kmalloc((PAGE_SIZE << db->buforder), GFP_KERNEL); | ||
637 | if (!db->rawbuf) | ||
638 | return -ENOMEM; | ||
639 | } | ||
640 | |||
641 | db->cnt_factor = 1; | ||
642 | if (db->sample_size == 8) | ||
643 | db->cnt_factor *= 2; | ||
644 | if (db->num_channels == 1) | ||
645 | db->cnt_factor *= 2; | ||
646 | db->cnt_factor *= db->src_factor; | ||
647 | |||
648 | db->count = 0; | ||
649 | db->dma_qcount = 0; | ||
650 | db->nextIn = db->nextOut = db->rawbuf; | ||
651 | |||
652 | db->user_bytes_per_sample = (db->sample_size>>3) * db->num_channels; | ||
653 | db->dma_bytes_per_sample = 2 * ((db->num_channels == 1) ? | ||
654 | 2 : db->num_channels); | ||
655 | |||
656 | user_bytes_per_sec = rate * db->user_bytes_per_sample; | ||
657 | bufs = PAGE_SIZE << db->buforder; | ||
658 | if (db->ossfragshift) { | ||
659 | if ((1000 << db->ossfragshift) < user_bytes_per_sec) | ||
660 | db->fragshift = ld2(user_bytes_per_sec/1000); | ||
661 | else | ||
662 | db->fragshift = db->ossfragshift; | ||
663 | } else { | ||
664 | db->fragshift = ld2(user_bytes_per_sec / 100 / | ||
665 | (db->subdivision ? db->subdivision : 1)); | ||
666 | if (db->fragshift < 3) | ||
667 | db->fragshift = 3; | ||
668 | } | ||
669 | |||
670 | db->fragsize = 1 << db->fragshift; | ||
671 | db->dma_fragsize = db->fragsize * db->cnt_factor; | ||
672 | db->numfrag = bufs / db->dma_fragsize; | ||
673 | |||
674 | while (db->numfrag < 4 && db->fragshift > 3) { | ||
675 | db->fragshift--; | ||
676 | db->fragsize = 1 << db->fragshift; | ||
677 | db->dma_fragsize = db->fragsize * db->cnt_factor; | ||
678 | db->numfrag = bufs / db->dma_fragsize; | ||
679 | } | ||
680 | |||
681 | if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) | ||
682 | db->numfrag = db->ossmaxfrags; | ||
683 | |||
684 | db->dmasize = db->dma_fragsize * db->numfrag; | ||
685 | memset(db->rawbuf, 0, bufs); | ||
686 | |||
687 | pr_debug("prog_dmabuf: rate=%d, samplesize=%d, channels=%d\n", | ||
688 | rate, db->sample_size, db->num_channels); | ||
689 | pr_debug("prog_dmabuf: fragsize=%d, cnt_factor=%d, dma_fragsize=%d\n", | ||
690 | db->fragsize, db->cnt_factor, db->dma_fragsize); | ||
691 | pr_debug("prog_dmabuf: numfrag=%d, dmasize=%d\n", db->numfrag, db->dmasize); | ||
692 | |||
693 | db->ready = 1; | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int | ||
698 | prog_dmabuf_adc(struct au1550_state *s) | ||
699 | { | ||
700 | stop_adc(s); | ||
701 | return prog_dmabuf(s, &s->dma_adc); | ||
702 | |||
703 | } | ||
704 | |||
705 | static int | ||
706 | prog_dmabuf_dac(struct au1550_state *s) | ||
707 | { | ||
708 | stop_dac(s); | ||
709 | return prog_dmabuf(s, &s->dma_dac); | ||
710 | } | ||
711 | |||
712 | |||
713 | static void dac_dma_interrupt(int irq, void *dev_id) | ||
714 | { | ||
715 | struct au1550_state *s = (struct au1550_state *) dev_id; | ||
716 | struct dmabuf *db = &s->dma_dac; | ||
717 | u32 ac97c_stat; | ||
718 | |||
719 | spin_lock(&s->lock); | ||
720 | |||
721 | ac97c_stat = au_readl(PSC_AC97STAT); | ||
722 | if (ac97c_stat & (AC97C_XU | AC97C_XO | AC97C_TE)) | ||
723 | pr_debug("AC97C status = 0x%08x\n", ac97c_stat); | ||
724 | db->dma_qcount--; | ||
725 | |||
726 | if (db->count >= db->fragsize) { | ||
727 | if (au1xxx_dbdma_put_source(db->dmanr, | ||
728 | virt_to_phys(db->nextOut), db->fragsize, | ||
729 | DDMA_FLAGS_IE) == 0) { | ||
730 | err("qcount < 2 and no ring room!"); | ||
731 | } | ||
732 | db->nextOut += db->fragsize; | ||
733 | if (db->nextOut >= db->rawbuf + db->dmasize) | ||
734 | db->nextOut -= db->dmasize; | ||
735 | db->count -= db->fragsize; | ||
736 | db->total_bytes += db->dma_fragsize; | ||
737 | db->dma_qcount++; | ||
738 | } | ||
739 | |||
740 | /* wake up anybody listening */ | ||
741 | if (waitqueue_active(&db->wait)) | ||
742 | wake_up(&db->wait); | ||
743 | |||
744 | spin_unlock(&s->lock); | ||
745 | } | ||
746 | |||
747 | |||
748 | static void adc_dma_interrupt(int irq, void *dev_id) | ||
749 | { | ||
750 | struct au1550_state *s = (struct au1550_state *)dev_id; | ||
751 | struct dmabuf *dp = &s->dma_adc; | ||
752 | u32 obytes; | ||
753 | char *obuf; | ||
754 | |||
755 | spin_lock(&s->lock); | ||
756 | |||
757 | /* Pull the buffer from the dma queue. | ||
758 | */ | ||
759 | au1xxx_dbdma_get_dest(dp->dmanr, (void *)(&obuf), &obytes); | ||
760 | |||
761 | if ((dp->count + obytes) > dp->dmasize) { | ||
762 | /* Overrun. Stop ADC and log the error | ||
763 | */ | ||
764 | spin_unlock(&s->lock); | ||
765 | stop_adc(s); | ||
766 | dp->error++; | ||
767 | err("adc overrun"); | ||
768 | return; | ||
769 | } | ||
770 | |||
771 | /* Put a new empty buffer on the destination DMA. | ||
772 | */ | ||
773 | au1xxx_dbdma_put_dest(dp->dmanr, virt_to_phys(dp->nextIn), | ||
774 | dp->dma_fragsize, DDMA_FLAGS_IE); | ||
775 | |||
776 | dp->nextIn += dp->dma_fragsize; | ||
777 | if (dp->nextIn >= dp->rawbuf + dp->dmasize) | ||
778 | dp->nextIn -= dp->dmasize; | ||
779 | |||
780 | dp->count += obytes; | ||
781 | dp->total_bytes += obytes; | ||
782 | |||
783 | /* wake up anybody listening | ||
784 | */ | ||
785 | if (waitqueue_active(&dp->wait)) | ||
786 | wake_up(&dp->wait); | ||
787 | |||
788 | spin_unlock(&s->lock); | ||
789 | } | ||
790 | |||
791 | static loff_t | ||
792 | au1550_llseek(struct file *file, loff_t offset, int origin) | ||
793 | { | ||
794 | return -ESPIPE; | ||
795 | } | ||
796 | |||
797 | |||
798 | static int | ||
799 | au1550_open_mixdev(struct inode *inode, struct file *file) | ||
800 | { | ||
801 | mutex_lock(&au1550_ac97_mutex); | ||
802 | file->private_data = &au1550_state; | ||
803 | mutex_unlock(&au1550_ac97_mutex); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | static int | ||
808 | au1550_release_mixdev(struct inode *inode, struct file *file) | ||
809 | { | ||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int | ||
814 | mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, | ||
815 | unsigned long arg) | ||
816 | { | ||
817 | return codec->mixer_ioctl(codec, cmd, arg); | ||
818 | } | ||
819 | |||
820 | static long | ||
821 | au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) | ||
822 | { | ||
823 | struct au1550_state *s = file->private_data; | ||
824 | struct ac97_codec *codec = s->codec; | ||
825 | int ret; | ||
826 | |||
827 | mutex_lock(&au1550_ac97_mutex); | ||
828 | ret = mixdev_ioctl(codec, cmd, arg); | ||
829 | mutex_unlock(&au1550_ac97_mutex); | ||
830 | |||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static /*const */ struct file_operations au1550_mixer_fops = { | ||
835 | .owner = THIS_MODULE, | ||
836 | .llseek = au1550_llseek, | ||
837 | .unlocked_ioctl = au1550_ioctl_mixdev, | ||
838 | .open = au1550_open_mixdev, | ||
839 | .release = au1550_release_mixdev, | ||
840 | }; | ||
841 | |||
842 | static int | ||
843 | drain_dac(struct au1550_state *s, int nonblock) | ||
844 | { | ||
845 | unsigned long flags; | ||
846 | int count, tmo; | ||
847 | |||
848 | if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped) | ||
849 | return 0; | ||
850 | |||
851 | for (;;) { | ||
852 | spin_lock_irqsave(&s->lock, flags); | ||
853 | count = s->dma_dac.count; | ||
854 | spin_unlock_irqrestore(&s->lock, flags); | ||
855 | if (count <= s->dma_dac.fragsize) | ||
856 | break; | ||
857 | if (signal_pending(current)) | ||
858 | break; | ||
859 | if (nonblock) | ||
860 | return -EBUSY; | ||
861 | tmo = 1000 * count / (s->no_vra ? | ||
862 | 48000 : s->dma_dac.sample_rate); | ||
863 | tmo /= s->dma_dac.dma_bytes_per_sample; | ||
864 | au1550_delay(tmo); | ||
865 | } | ||
866 | if (signal_pending(current)) | ||
867 | return -ERESTARTSYS; | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static inline u8 S16_TO_U8(s16 ch) | ||
872 | { | ||
873 | return (u8) (ch >> 8) + 0x80; | ||
874 | } | ||
875 | static inline s16 U8_TO_S16(u8 ch) | ||
876 | { | ||
877 | return (s16) (ch - 0x80) << 8; | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * Translates user samples to dma buffer suitable for AC'97 DAC data: | ||
882 | * If mono, copy left channel to right channel in dma buffer. | ||
883 | * If 8 bit samples, cvt to 16-bit before writing to dma buffer. | ||
884 | * If interpolating (no VRA), duplicate every audio frame src_factor times. | ||
885 | */ | ||
886 | static int | ||
887 | translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf, | ||
888 | int dmacount) | ||
889 | { | ||
890 | int sample, i; | ||
891 | int interp_bytes_per_sample; | ||
892 | int num_samples; | ||
893 | int mono = (db->num_channels == 1); | ||
894 | char usersample[12]; | ||
895 | s16 ch, dmasample[6]; | ||
896 | |||
897 | if (db->sample_size == 16 && !mono && db->src_factor == 1) { | ||
898 | /* no translation necessary, just copy | ||
899 | */ | ||
900 | if (copy_from_user(dmabuf, userbuf, dmacount)) | ||
901 | return -EFAULT; | ||
902 | return dmacount; | ||
903 | } | ||
904 | |||
905 | interp_bytes_per_sample = db->dma_bytes_per_sample * db->src_factor; | ||
906 | num_samples = dmacount / interp_bytes_per_sample; | ||
907 | |||
908 | for (sample = 0; sample < num_samples; sample++) { | ||
909 | if (copy_from_user(usersample, userbuf, | ||
910 | db->user_bytes_per_sample)) { | ||
911 | return -EFAULT; | ||
912 | } | ||
913 | |||
914 | for (i = 0; i < db->num_channels; i++) { | ||
915 | if (db->sample_size == 8) | ||
916 | ch = U8_TO_S16(usersample[i]); | ||
917 | else | ||
918 | ch = *((s16 *) (&usersample[i * 2])); | ||
919 | dmasample[i] = ch; | ||
920 | if (mono) | ||
921 | dmasample[i + 1] = ch; /* right channel */ | ||
922 | } | ||
923 | |||
924 | /* duplicate every audio frame src_factor times | ||
925 | */ | ||
926 | for (i = 0; i < db->src_factor; i++) | ||
927 | memcpy(dmabuf, dmasample, db->dma_bytes_per_sample); | ||
928 | |||
929 | userbuf += db->user_bytes_per_sample; | ||
930 | dmabuf += interp_bytes_per_sample; | ||
931 | } | ||
932 | |||
933 | return num_samples * interp_bytes_per_sample; | ||
934 | } | ||
935 | |||
936 | /* | ||
937 | * Translates AC'97 ADC samples to user buffer: | ||
938 | * If mono, send only left channel to user buffer. | ||
939 | * If 8 bit samples, cvt from 16 to 8 bit before writing to user buffer. | ||
940 | * If decimating (no VRA), skip over src_factor audio frames. | ||
941 | */ | ||
942 | static int | ||
943 | translate_to_user(struct dmabuf *db, char* userbuf, char* dmabuf, | ||
944 | int dmacount) | ||
945 | { | ||
946 | int sample, i; | ||
947 | int interp_bytes_per_sample; | ||
948 | int num_samples; | ||
949 | int mono = (db->num_channels == 1); | ||
950 | char usersample[12]; | ||
951 | |||
952 | if (db->sample_size == 16 && !mono && db->src_factor == 1) { | ||
953 | /* no translation necessary, just copy | ||
954 | */ | ||
955 | if (copy_to_user(userbuf, dmabuf, dmacount)) | ||
956 | return -EFAULT; | ||
957 | return dmacount; | ||
958 | } | ||
959 | |||
960 | interp_bytes_per_sample = db->dma_bytes_per_sample * db->src_factor; | ||
961 | num_samples = dmacount / interp_bytes_per_sample; | ||
962 | |||
963 | for (sample = 0; sample < num_samples; sample++) { | ||
964 | for (i = 0; i < db->num_channels; i++) { | ||
965 | if (db->sample_size == 8) | ||
966 | usersample[i] = | ||
967 | S16_TO_U8(*((s16 *) (&dmabuf[i * 2]))); | ||
968 | else | ||
969 | *((s16 *) (&usersample[i * 2])) = | ||
970 | *((s16 *) (&dmabuf[i * 2])); | ||
971 | } | ||
972 | |||
973 | if (copy_to_user(userbuf, usersample, | ||
974 | db->user_bytes_per_sample)) { | ||
975 | return -EFAULT; | ||
976 | } | ||
977 | |||
978 | userbuf += db->user_bytes_per_sample; | ||
979 | dmabuf += interp_bytes_per_sample; | ||
980 | } | ||
981 | |||
982 | return num_samples * interp_bytes_per_sample; | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * Copy audio data to/from user buffer from/to dma buffer, taking care | ||
987 | * that we wrap when reading/writing the dma buffer. Returns actual byte | ||
988 | * count written to or read from the dma buffer. | ||
989 | */ | ||
990 | static int | ||
991 | copy_dmabuf_user(struct dmabuf *db, char* userbuf, int count, int to_user) | ||
992 | { | ||
993 | char *bufptr = to_user ? db->nextOut : db->nextIn; | ||
994 | char *bufend = db->rawbuf + db->dmasize; | ||
995 | int cnt, ret; | ||
996 | |||
997 | if (bufptr + count > bufend) { | ||
998 | int partial = (int) (bufend - bufptr); | ||
999 | if (to_user) { | ||
1000 | if ((cnt = translate_to_user(db, userbuf, | ||
1001 | bufptr, partial)) < 0) | ||
1002 | return cnt; | ||
1003 | ret = cnt; | ||
1004 | if ((cnt = translate_to_user(db, userbuf + partial, | ||
1005 | db->rawbuf, | ||
1006 | count - partial)) < 0) | ||
1007 | return cnt; | ||
1008 | ret += cnt; | ||
1009 | } else { | ||
1010 | if ((cnt = translate_from_user(db, bufptr, userbuf, | ||
1011 | partial)) < 0) | ||
1012 | return cnt; | ||
1013 | ret = cnt; | ||
1014 | if ((cnt = translate_from_user(db, db->rawbuf, | ||
1015 | userbuf + partial, | ||
1016 | count - partial)) < 0) | ||
1017 | return cnt; | ||
1018 | ret += cnt; | ||
1019 | } | ||
1020 | } else { | ||
1021 | if (to_user) | ||
1022 | ret = translate_to_user(db, userbuf, bufptr, count); | ||
1023 | else | ||
1024 | ret = translate_from_user(db, bufptr, userbuf, count); | ||
1025 | } | ||
1026 | |||
1027 | return ret; | ||
1028 | } | ||
1029 | |||
1030 | |||
1031 | static ssize_t | ||
1032 | au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos) | ||
1033 | { | ||
1034 | struct au1550_state *s = file->private_data; | ||
1035 | struct dmabuf *db = &s->dma_adc; | ||
1036 | DECLARE_WAITQUEUE(wait, current); | ||
1037 | ssize_t ret; | ||
1038 | unsigned long flags; | ||
1039 | int cnt, usercnt, avail; | ||
1040 | |||
1041 | if (db->mapped) | ||
1042 | return -ENXIO; | ||
1043 | if (!access_ok(VERIFY_WRITE, buffer, count)) | ||
1044 | return -EFAULT; | ||
1045 | ret = 0; | ||
1046 | |||
1047 | count *= db->cnt_factor; | ||
1048 | |||
1049 | mutex_lock(&s->sem); | ||
1050 | add_wait_queue(&db->wait, &wait); | ||
1051 | |||
1052 | while (count > 0) { | ||
1053 | /* wait for samples in ADC dma buffer | ||
1054 | */ | ||
1055 | do { | ||
1056 | spin_lock_irqsave(&s->lock, flags); | ||
1057 | if (db->stopped) | ||
1058 | start_adc(s); | ||
1059 | avail = db->count; | ||
1060 | if (avail <= 0) | ||
1061 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1062 | spin_unlock_irqrestore(&s->lock, flags); | ||
1063 | if (avail <= 0) { | ||
1064 | if (file->f_flags & O_NONBLOCK) { | ||
1065 | if (!ret) | ||
1066 | ret = -EAGAIN; | ||
1067 | goto out; | ||
1068 | } | ||
1069 | mutex_unlock(&s->sem); | ||
1070 | schedule(); | ||
1071 | if (signal_pending(current)) { | ||
1072 | if (!ret) | ||
1073 | ret = -ERESTARTSYS; | ||
1074 | goto out2; | ||
1075 | } | ||
1076 | mutex_lock(&s->sem); | ||
1077 | } | ||
1078 | } while (avail <= 0); | ||
1079 | |||
1080 | /* copy from nextOut to user | ||
1081 | */ | ||
1082 | if ((cnt = copy_dmabuf_user(db, buffer, | ||
1083 | count > avail ? | ||
1084 | avail : count, 1)) < 0) { | ||
1085 | if (!ret) | ||
1086 | ret = -EFAULT; | ||
1087 | goto out; | ||
1088 | } | ||
1089 | |||
1090 | spin_lock_irqsave(&s->lock, flags); | ||
1091 | db->count -= cnt; | ||
1092 | db->nextOut += cnt; | ||
1093 | if (db->nextOut >= db->rawbuf + db->dmasize) | ||
1094 | db->nextOut -= db->dmasize; | ||
1095 | spin_unlock_irqrestore(&s->lock, flags); | ||
1096 | |||
1097 | count -= cnt; | ||
1098 | usercnt = cnt / db->cnt_factor; | ||
1099 | buffer += usercnt; | ||
1100 | ret += usercnt; | ||
1101 | } /* while (count > 0) */ | ||
1102 | |||
1103 | out: | ||
1104 | mutex_unlock(&s->sem); | ||
1105 | out2: | ||
1106 | remove_wait_queue(&db->wait, &wait); | ||
1107 | set_current_state(TASK_RUNNING); | ||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | static ssize_t | ||
1112 | au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos) | ||
1113 | { | ||
1114 | struct au1550_state *s = file->private_data; | ||
1115 | struct dmabuf *db = &s->dma_dac; | ||
1116 | DECLARE_WAITQUEUE(wait, current); | ||
1117 | ssize_t ret = 0; | ||
1118 | unsigned long flags; | ||
1119 | int cnt, usercnt, avail; | ||
1120 | |||
1121 | pr_debug("write: count=%d\n", count); | ||
1122 | |||
1123 | if (db->mapped) | ||
1124 | return -ENXIO; | ||
1125 | if (!access_ok(VERIFY_READ, buffer, count)) | ||
1126 | return -EFAULT; | ||
1127 | |||
1128 | count *= db->cnt_factor; | ||
1129 | |||
1130 | mutex_lock(&s->sem); | ||
1131 | add_wait_queue(&db->wait, &wait); | ||
1132 | |||
1133 | while (count > 0) { | ||
1134 | /* wait for space in playback buffer | ||
1135 | */ | ||
1136 | do { | ||
1137 | spin_lock_irqsave(&s->lock, flags); | ||
1138 | avail = (int) db->dmasize - db->count; | ||
1139 | if (avail <= 0) | ||
1140 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1141 | spin_unlock_irqrestore(&s->lock, flags); | ||
1142 | if (avail <= 0) { | ||
1143 | if (file->f_flags & O_NONBLOCK) { | ||
1144 | if (!ret) | ||
1145 | ret = -EAGAIN; | ||
1146 | goto out; | ||
1147 | } | ||
1148 | mutex_unlock(&s->sem); | ||
1149 | schedule(); | ||
1150 | if (signal_pending(current)) { | ||
1151 | if (!ret) | ||
1152 | ret = -ERESTARTSYS; | ||
1153 | goto out2; | ||
1154 | } | ||
1155 | mutex_lock(&s->sem); | ||
1156 | } | ||
1157 | } while (avail <= 0); | ||
1158 | |||
1159 | /* copy from user to nextIn | ||
1160 | */ | ||
1161 | if ((cnt = copy_dmabuf_user(db, (char *) buffer, | ||
1162 | count > avail ? | ||
1163 | avail : count, 0)) < 0) { | ||
1164 | if (!ret) | ||
1165 | ret = -EFAULT; | ||
1166 | goto out; | ||
1167 | } | ||
1168 | |||
1169 | spin_lock_irqsave(&s->lock, flags); | ||
1170 | db->count += cnt; | ||
1171 | db->nextIn += cnt; | ||
1172 | if (db->nextIn >= db->rawbuf + db->dmasize) | ||
1173 | db->nextIn -= db->dmasize; | ||
1174 | |||
1175 | /* If the data is available, we want to keep two buffers | ||
1176 | * on the dma queue. If the queue count reaches zero, | ||
1177 | * we know the dma has stopped. | ||
1178 | */ | ||
1179 | while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) { | ||
1180 | if (au1xxx_dbdma_put_source(db->dmanr, | ||
1181 | virt_to_phys(db->nextOut), db->fragsize, | ||
1182 | DDMA_FLAGS_IE) == 0) { | ||
1183 | err("qcount < 2 and no ring room!"); | ||
1184 | } | ||
1185 | db->nextOut += db->fragsize; | ||
1186 | if (db->nextOut >= db->rawbuf + db->dmasize) | ||
1187 | db->nextOut -= db->dmasize; | ||
1188 | db->total_bytes += db->dma_fragsize; | ||
1189 | if (db->dma_qcount == 0) | ||
1190 | start_dac(s); | ||
1191 | db->dma_qcount++; | ||
1192 | } | ||
1193 | spin_unlock_irqrestore(&s->lock, flags); | ||
1194 | |||
1195 | count -= cnt; | ||
1196 | usercnt = cnt / db->cnt_factor; | ||
1197 | buffer += usercnt; | ||
1198 | ret += usercnt; | ||
1199 | } /* while (count > 0) */ | ||
1200 | |||
1201 | out: | ||
1202 | mutex_unlock(&s->sem); | ||
1203 | out2: | ||
1204 | remove_wait_queue(&db->wait, &wait); | ||
1205 | set_current_state(TASK_RUNNING); | ||
1206 | return ret; | ||
1207 | } | ||
1208 | |||
1209 | |||
1210 | /* No kernel lock - we have our own spinlock */ | ||
1211 | static unsigned int | ||
1212 | au1550_poll(struct file *file, struct poll_table_struct *wait) | ||
1213 | { | ||
1214 | struct au1550_state *s = file->private_data; | ||
1215 | unsigned long flags; | ||
1216 | unsigned int mask = 0; | ||
1217 | |||
1218 | if (file->f_mode & FMODE_WRITE) { | ||
1219 | if (!s->dma_dac.ready) | ||
1220 | return 0; | ||
1221 | poll_wait(file, &s->dma_dac.wait, wait); | ||
1222 | } | ||
1223 | if (file->f_mode & FMODE_READ) { | ||
1224 | if (!s->dma_adc.ready) | ||
1225 | return 0; | ||
1226 | poll_wait(file, &s->dma_adc.wait, wait); | ||
1227 | } | ||
1228 | |||
1229 | spin_lock_irqsave(&s->lock, flags); | ||
1230 | |||
1231 | if (file->f_mode & FMODE_READ) { | ||
1232 | if (s->dma_adc.count >= (signed)s->dma_adc.dma_fragsize) | ||
1233 | mask |= POLLIN | POLLRDNORM; | ||
1234 | } | ||
1235 | if (file->f_mode & FMODE_WRITE) { | ||
1236 | if (s->dma_dac.mapped) { | ||
1237 | if (s->dma_dac.count >= | ||
1238 | (signed)s->dma_dac.dma_fragsize) | ||
1239 | mask |= POLLOUT | POLLWRNORM; | ||
1240 | } else { | ||
1241 | if ((signed) s->dma_dac.dmasize >= | ||
1242 | s->dma_dac.count + (signed)s->dma_dac.dma_fragsize) | ||
1243 | mask |= POLLOUT | POLLWRNORM; | ||
1244 | } | ||
1245 | } | ||
1246 | spin_unlock_irqrestore(&s->lock, flags); | ||
1247 | return mask; | ||
1248 | } | ||
1249 | |||
1250 | static int | ||
1251 | au1550_mmap(struct file *file, struct vm_area_struct *vma) | ||
1252 | { | ||
1253 | struct au1550_state *s = file->private_data; | ||
1254 | struct dmabuf *db; | ||
1255 | unsigned long size; | ||
1256 | int ret = 0; | ||
1257 | |||
1258 | mutex_lock(&au1550_ac97_mutex); | ||
1259 | mutex_lock(&s->sem); | ||
1260 | if (vma->vm_flags & VM_WRITE) | ||
1261 | db = &s->dma_dac; | ||
1262 | else if (vma->vm_flags & VM_READ) | ||
1263 | db = &s->dma_adc; | ||
1264 | else { | ||
1265 | ret = -EINVAL; | ||
1266 | goto out; | ||
1267 | } | ||
1268 | if (vma->vm_pgoff != 0) { | ||
1269 | ret = -EINVAL; | ||
1270 | goto out; | ||
1271 | } | ||
1272 | size = vma->vm_end - vma->vm_start; | ||
1273 | if (size > (PAGE_SIZE << db->buforder)) { | ||
1274 | ret = -EINVAL; | ||
1275 | goto out; | ||
1276 | } | ||
1277 | if (remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(db->rawbuf)), | ||
1278 | size, vma->vm_page_prot)) { | ||
1279 | ret = -EAGAIN; | ||
1280 | goto out; | ||
1281 | } | ||
1282 | vma->vm_flags &= ~VM_IO; | ||
1283 | db->mapped = 1; | ||
1284 | out: | ||
1285 | mutex_unlock(&s->sem); | ||
1286 | mutex_unlock(&au1550_ac97_mutex); | ||
1287 | return ret; | ||
1288 | } | ||
1289 | |||
1290 | #ifdef DEBUG | ||
1291 | static struct ioctl_str_t { | ||
1292 | unsigned int cmd; | ||
1293 | const char *str; | ||
1294 | } ioctl_str[] = { | ||
1295 | {SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"}, | ||
1296 | {SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"}, | ||
1297 | {SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"}, | ||
1298 | {SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"}, | ||
1299 | {SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"}, | ||
1300 | {SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"}, | ||
1301 | {SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"}, | ||
1302 | {SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"}, | ||
1303 | {SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"}, | ||
1304 | {SNDCTL_DSP_POST, "SNDCTL_DSP_POST"}, | ||
1305 | {SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"}, | ||
1306 | {SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"}, | ||
1307 | {SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"}, | ||
1308 | {SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"}, | ||
1309 | {SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"}, | ||
1310 | {SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"}, | ||
1311 | {SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"}, | ||
1312 | {SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"}, | ||
1313 | {SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"}, | ||
1314 | {SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"}, | ||
1315 | {SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"}, | ||
1316 | {SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"}, | ||
1317 | {SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"}, | ||
1318 | {SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"}, | ||
1319 | {SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"}, | ||
1320 | {SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"}, | ||
1321 | {SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"}, | ||
1322 | {SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"}, | ||
1323 | {SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"}, | ||
1324 | {OSS_GETVERSION, "OSS_GETVERSION"}, | ||
1325 | {SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"}, | ||
1326 | {SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"}, | ||
1327 | {SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"}, | ||
1328 | {SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"} | ||
1329 | }; | ||
1330 | #endif | ||
1331 | |||
1332 | static int | ||
1333 | dma_count_done(struct dmabuf *db) | ||
1334 | { | ||
1335 | if (db->stopped) | ||
1336 | return 0; | ||
1337 | |||
1338 | return db->dma_fragsize - au1xxx_get_dma_residue(db->dmanr); | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | static int | ||
1343 | au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1344 | { | ||
1345 | struct au1550_state *s = file->private_data; | ||
1346 | unsigned long flags; | ||
1347 | audio_buf_info abinfo; | ||
1348 | count_info cinfo; | ||
1349 | int count; | ||
1350 | int val, mapped, ret, diff; | ||
1351 | |||
1352 | mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || | ||
1353 | ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); | ||
1354 | |||
1355 | #ifdef DEBUG | ||
1356 | for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) { | ||
1357 | if (ioctl_str[count].cmd == cmd) | ||
1358 | break; | ||
1359 | } | ||
1360 | if (count < ARRAY_SIZE(ioctl_str)) | ||
1361 | pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg); | ||
1362 | else | ||
1363 | pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg); | ||
1364 | #endif | ||
1365 | |||
1366 | switch (cmd) { | ||
1367 | case OSS_GETVERSION: | ||
1368 | return put_user(SOUND_VERSION, (int *) arg); | ||
1369 | |||
1370 | case SNDCTL_DSP_SYNC: | ||
1371 | if (file->f_mode & FMODE_WRITE) | ||
1372 | return drain_dac(s, file->f_flags & O_NONBLOCK); | ||
1373 | return 0; | ||
1374 | |||
1375 | case SNDCTL_DSP_SETDUPLEX: | ||
1376 | return 0; | ||
1377 | |||
1378 | case SNDCTL_DSP_GETCAPS: | ||
1379 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | | ||
1380 | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); | ||
1381 | |||
1382 | case SNDCTL_DSP_RESET: | ||
1383 | if (file->f_mode & FMODE_WRITE) { | ||
1384 | stop_dac(s); | ||
1385 | synchronize_irq(); | ||
1386 | s->dma_dac.count = s->dma_dac.total_bytes = 0; | ||
1387 | s->dma_dac.nextIn = s->dma_dac.nextOut = | ||
1388 | s->dma_dac.rawbuf; | ||
1389 | } | ||
1390 | if (file->f_mode & FMODE_READ) { | ||
1391 | stop_adc(s); | ||
1392 | synchronize_irq(); | ||
1393 | s->dma_adc.count = s->dma_adc.total_bytes = 0; | ||
1394 | s->dma_adc.nextIn = s->dma_adc.nextOut = | ||
1395 | s->dma_adc.rawbuf; | ||
1396 | } | ||
1397 | return 0; | ||
1398 | |||
1399 | case SNDCTL_DSP_SPEED: | ||
1400 | if (get_user(val, (int *) arg)) | ||
1401 | return -EFAULT; | ||
1402 | if (val >= 0) { | ||
1403 | if (file->f_mode & FMODE_READ) { | ||
1404 | stop_adc(s); | ||
1405 | set_adc_rate(s, val); | ||
1406 | } | ||
1407 | if (file->f_mode & FMODE_WRITE) { | ||
1408 | stop_dac(s); | ||
1409 | set_dac_rate(s, val); | ||
1410 | } | ||
1411 | if (s->open_mode & FMODE_READ) | ||
1412 | if ((ret = prog_dmabuf_adc(s))) | ||
1413 | return ret; | ||
1414 | if (s->open_mode & FMODE_WRITE) | ||
1415 | if ((ret = prog_dmabuf_dac(s))) | ||
1416 | return ret; | ||
1417 | } | ||
1418 | return put_user((file->f_mode & FMODE_READ) ? | ||
1419 | s->dma_adc.sample_rate : | ||
1420 | s->dma_dac.sample_rate, | ||
1421 | (int *)arg); | ||
1422 | |||
1423 | case SNDCTL_DSP_STEREO: | ||
1424 | if (get_user(val, (int *) arg)) | ||
1425 | return -EFAULT; | ||
1426 | if (file->f_mode & FMODE_READ) { | ||
1427 | stop_adc(s); | ||
1428 | s->dma_adc.num_channels = val ? 2 : 1; | ||
1429 | if ((ret = prog_dmabuf_adc(s))) | ||
1430 | return ret; | ||
1431 | } | ||
1432 | if (file->f_mode & FMODE_WRITE) { | ||
1433 | stop_dac(s); | ||
1434 | s->dma_dac.num_channels = val ? 2 : 1; | ||
1435 | if (s->codec_ext_caps & AC97_EXT_DACS) { | ||
1436 | /* disable surround and center/lfe in AC'97 | ||
1437 | */ | ||
1438 | u16 ext_stat = rdcodec(s->codec, | ||
1439 | AC97_EXTENDED_STATUS); | ||
1440 | wrcodec(s->codec, AC97_EXTENDED_STATUS, | ||
1441 | ext_stat | (AC97_EXTSTAT_PRI | | ||
1442 | AC97_EXTSTAT_PRJ | | ||
1443 | AC97_EXTSTAT_PRK)); | ||
1444 | } | ||
1445 | if ((ret = prog_dmabuf_dac(s))) | ||
1446 | return ret; | ||
1447 | } | ||
1448 | return 0; | ||
1449 | |||
1450 | case SNDCTL_DSP_CHANNELS: | ||
1451 | if (get_user(val, (int *) arg)) | ||
1452 | return -EFAULT; | ||
1453 | if (val != 0) { | ||
1454 | if (file->f_mode & FMODE_READ) { | ||
1455 | if (val < 0 || val > 2) | ||
1456 | return -EINVAL; | ||
1457 | stop_adc(s); | ||
1458 | s->dma_adc.num_channels = val; | ||
1459 | if ((ret = prog_dmabuf_adc(s))) | ||
1460 | return ret; | ||
1461 | } | ||
1462 | if (file->f_mode & FMODE_WRITE) { | ||
1463 | switch (val) { | ||
1464 | case 1: | ||
1465 | case 2: | ||
1466 | break; | ||
1467 | case 3: | ||
1468 | case 5: | ||
1469 | return -EINVAL; | ||
1470 | case 4: | ||
1471 | if (!(s->codec_ext_caps & | ||
1472 | AC97_EXTID_SDAC)) | ||
1473 | return -EINVAL; | ||
1474 | break; | ||
1475 | case 6: | ||
1476 | if ((s->codec_ext_caps & | ||
1477 | AC97_EXT_DACS) != AC97_EXT_DACS) | ||
1478 | return -EINVAL; | ||
1479 | break; | ||
1480 | default: | ||
1481 | return -EINVAL; | ||
1482 | } | ||
1483 | |||
1484 | stop_dac(s); | ||
1485 | if (val <= 2 && | ||
1486 | (s->codec_ext_caps & AC97_EXT_DACS)) { | ||
1487 | /* disable surround and center/lfe | ||
1488 | * channels in AC'97 | ||
1489 | */ | ||
1490 | u16 ext_stat = | ||
1491 | rdcodec(s->codec, | ||
1492 | AC97_EXTENDED_STATUS); | ||
1493 | wrcodec(s->codec, | ||
1494 | AC97_EXTENDED_STATUS, | ||
1495 | ext_stat | (AC97_EXTSTAT_PRI | | ||
1496 | AC97_EXTSTAT_PRJ | | ||
1497 | AC97_EXTSTAT_PRK)); | ||
1498 | } else if (val >= 4) { | ||
1499 | /* enable surround, center/lfe | ||
1500 | * channels in AC'97 | ||
1501 | */ | ||
1502 | u16 ext_stat = | ||
1503 | rdcodec(s->codec, | ||
1504 | AC97_EXTENDED_STATUS); | ||
1505 | ext_stat &= ~AC97_EXTSTAT_PRJ; | ||
1506 | if (val == 6) | ||
1507 | ext_stat &= | ||
1508 | ~(AC97_EXTSTAT_PRI | | ||
1509 | AC97_EXTSTAT_PRK); | ||
1510 | wrcodec(s->codec, | ||
1511 | AC97_EXTENDED_STATUS, | ||
1512 | ext_stat); | ||
1513 | } | ||
1514 | |||
1515 | s->dma_dac.num_channels = val; | ||
1516 | if ((ret = prog_dmabuf_dac(s))) | ||
1517 | return ret; | ||
1518 | } | ||
1519 | } | ||
1520 | return put_user(val, (int *) arg); | ||
1521 | |||
1522 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ | ||
1523 | return put_user(AFMT_S16_LE | AFMT_U8, (int *) arg); | ||
1524 | |||
1525 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ | ||
1526 | if (get_user(val, (int *) arg)) | ||
1527 | return -EFAULT; | ||
1528 | if (val != AFMT_QUERY) { | ||
1529 | if (file->f_mode & FMODE_READ) { | ||
1530 | stop_adc(s); | ||
1531 | if (val == AFMT_S16_LE) | ||
1532 | s->dma_adc.sample_size = 16; | ||
1533 | else { | ||
1534 | val = AFMT_U8; | ||
1535 | s->dma_adc.sample_size = 8; | ||
1536 | } | ||
1537 | if ((ret = prog_dmabuf_adc(s))) | ||
1538 | return ret; | ||
1539 | } | ||
1540 | if (file->f_mode & FMODE_WRITE) { | ||
1541 | stop_dac(s); | ||
1542 | if (val == AFMT_S16_LE) | ||
1543 | s->dma_dac.sample_size = 16; | ||
1544 | else { | ||
1545 | val = AFMT_U8; | ||
1546 | s->dma_dac.sample_size = 8; | ||
1547 | } | ||
1548 | if ((ret = prog_dmabuf_dac(s))) | ||
1549 | return ret; | ||
1550 | } | ||
1551 | } else { | ||
1552 | if (file->f_mode & FMODE_READ) | ||
1553 | val = (s->dma_adc.sample_size == 16) ? | ||
1554 | AFMT_S16_LE : AFMT_U8; | ||
1555 | else | ||
1556 | val = (s->dma_dac.sample_size == 16) ? | ||
1557 | AFMT_S16_LE : AFMT_U8; | ||
1558 | } | ||
1559 | return put_user(val, (int *) arg); | ||
1560 | |||
1561 | case SNDCTL_DSP_POST: | ||
1562 | return 0; | ||
1563 | |||
1564 | case SNDCTL_DSP_GETTRIGGER: | ||
1565 | val = 0; | ||
1566 | spin_lock_irqsave(&s->lock, flags); | ||
1567 | if (file->f_mode & FMODE_READ && !s->dma_adc.stopped) | ||
1568 | val |= PCM_ENABLE_INPUT; | ||
1569 | if (file->f_mode & FMODE_WRITE && !s->dma_dac.stopped) | ||
1570 | val |= PCM_ENABLE_OUTPUT; | ||
1571 | spin_unlock_irqrestore(&s->lock, flags); | ||
1572 | return put_user(val, (int *) arg); | ||
1573 | |||
1574 | case SNDCTL_DSP_SETTRIGGER: | ||
1575 | if (get_user(val, (int *) arg)) | ||
1576 | return -EFAULT; | ||
1577 | if (file->f_mode & FMODE_READ) { | ||
1578 | if (val & PCM_ENABLE_INPUT) { | ||
1579 | spin_lock_irqsave(&s->lock, flags); | ||
1580 | start_adc(s); | ||
1581 | spin_unlock_irqrestore(&s->lock, flags); | ||
1582 | } else | ||
1583 | stop_adc(s); | ||
1584 | } | ||
1585 | if (file->f_mode & FMODE_WRITE) { | ||
1586 | if (val & PCM_ENABLE_OUTPUT) { | ||
1587 | spin_lock_irqsave(&s->lock, flags); | ||
1588 | start_dac(s); | ||
1589 | spin_unlock_irqrestore(&s->lock, flags); | ||
1590 | } else | ||
1591 | stop_dac(s); | ||
1592 | } | ||
1593 | return 0; | ||
1594 | |||
1595 | case SNDCTL_DSP_GETOSPACE: | ||
1596 | if (!(file->f_mode & FMODE_WRITE)) | ||
1597 | return -EINVAL; | ||
1598 | abinfo.fragsize = s->dma_dac.fragsize; | ||
1599 | spin_lock_irqsave(&s->lock, flags); | ||
1600 | count = s->dma_dac.count; | ||
1601 | count -= dma_count_done(&s->dma_dac); | ||
1602 | spin_unlock_irqrestore(&s->lock, flags); | ||
1603 | if (count < 0) | ||
1604 | count = 0; | ||
1605 | abinfo.bytes = (s->dma_dac.dmasize - count) / | ||
1606 | s->dma_dac.cnt_factor; | ||
1607 | abinfo.fragstotal = s->dma_dac.numfrag; | ||
1608 | abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; | ||
1609 | pr_debug("ioctl SNDCTL_DSP_GETOSPACE: bytes=%d, fragments=%d\n", abinfo.bytes, abinfo.fragments); | ||
1610 | return copy_to_user((void *) arg, &abinfo, | ||
1611 | sizeof(abinfo)) ? -EFAULT : 0; | ||
1612 | |||
1613 | case SNDCTL_DSP_GETISPACE: | ||
1614 | if (!(file->f_mode & FMODE_READ)) | ||
1615 | return -EINVAL; | ||
1616 | abinfo.fragsize = s->dma_adc.fragsize; | ||
1617 | spin_lock_irqsave(&s->lock, flags); | ||
1618 | count = s->dma_adc.count; | ||
1619 | count += dma_count_done(&s->dma_adc); | ||
1620 | spin_unlock_irqrestore(&s->lock, flags); | ||
1621 | if (count < 0) | ||
1622 | count = 0; | ||
1623 | abinfo.bytes = count / s->dma_adc.cnt_factor; | ||
1624 | abinfo.fragstotal = s->dma_adc.numfrag; | ||
1625 | abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; | ||
1626 | return copy_to_user((void *) arg, &abinfo, | ||
1627 | sizeof(abinfo)) ? -EFAULT : 0; | ||
1628 | |||
1629 | case SNDCTL_DSP_NONBLOCK: | ||
1630 | spin_lock(&file->f_lock); | ||
1631 | file->f_flags |= O_NONBLOCK; | ||
1632 | spin_unlock(&file->f_lock); | ||
1633 | return 0; | ||
1634 | |||
1635 | case SNDCTL_DSP_GETODELAY: | ||
1636 | if (!(file->f_mode & FMODE_WRITE)) | ||
1637 | return -EINVAL; | ||
1638 | spin_lock_irqsave(&s->lock, flags); | ||
1639 | count = s->dma_dac.count; | ||
1640 | count -= dma_count_done(&s->dma_dac); | ||
1641 | spin_unlock_irqrestore(&s->lock, flags); | ||
1642 | if (count < 0) | ||
1643 | count = 0; | ||
1644 | count /= s->dma_dac.cnt_factor; | ||
1645 | return put_user(count, (int *) arg); | ||
1646 | |||
1647 | case SNDCTL_DSP_GETIPTR: | ||
1648 | if (!(file->f_mode & FMODE_READ)) | ||
1649 | return -EINVAL; | ||
1650 | spin_lock_irqsave(&s->lock, flags); | ||
1651 | cinfo.bytes = s->dma_adc.total_bytes; | ||
1652 | count = s->dma_adc.count; | ||
1653 | if (!s->dma_adc.stopped) { | ||
1654 | diff = dma_count_done(&s->dma_adc); | ||
1655 | count += diff; | ||
1656 | cinfo.bytes += diff; | ||
1657 | cinfo.ptr = virt_to_phys(s->dma_adc.nextIn) + diff - | ||
1658 | virt_to_phys(s->dma_adc.rawbuf); | ||
1659 | } else | ||
1660 | cinfo.ptr = virt_to_phys(s->dma_adc.nextIn) - | ||
1661 | virt_to_phys(s->dma_adc.rawbuf); | ||
1662 | if (s->dma_adc.mapped) | ||
1663 | s->dma_adc.count &= (s->dma_adc.dma_fragsize-1); | ||
1664 | spin_unlock_irqrestore(&s->lock, flags); | ||
1665 | if (count < 0) | ||
1666 | count = 0; | ||
1667 | cinfo.blocks = count >> s->dma_adc.fragshift; | ||
1668 | return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); | ||
1669 | |||
1670 | case SNDCTL_DSP_GETOPTR: | ||
1671 | if (!(file->f_mode & FMODE_READ)) | ||
1672 | return -EINVAL; | ||
1673 | spin_lock_irqsave(&s->lock, flags); | ||
1674 | cinfo.bytes = s->dma_dac.total_bytes; | ||
1675 | count = s->dma_dac.count; | ||
1676 | if (!s->dma_dac.stopped) { | ||
1677 | diff = dma_count_done(&s->dma_dac); | ||
1678 | count -= diff; | ||
1679 | cinfo.bytes += diff; | ||
1680 | cinfo.ptr = virt_to_phys(s->dma_dac.nextOut) + diff - | ||
1681 | virt_to_phys(s->dma_dac.rawbuf); | ||
1682 | } else | ||
1683 | cinfo.ptr = virt_to_phys(s->dma_dac.nextOut) - | ||
1684 | virt_to_phys(s->dma_dac.rawbuf); | ||
1685 | if (s->dma_dac.mapped) | ||
1686 | s->dma_dac.count &= (s->dma_dac.dma_fragsize-1); | ||
1687 | spin_unlock_irqrestore(&s->lock, flags); | ||
1688 | if (count < 0) | ||
1689 | count = 0; | ||
1690 | cinfo.blocks = count >> s->dma_dac.fragshift; | ||
1691 | return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); | ||
1692 | |||
1693 | case SNDCTL_DSP_GETBLKSIZE: | ||
1694 | if (file->f_mode & FMODE_WRITE) | ||
1695 | return put_user(s->dma_dac.fragsize, (int *) arg); | ||
1696 | else | ||
1697 | return put_user(s->dma_adc.fragsize, (int *) arg); | ||
1698 | |||
1699 | case SNDCTL_DSP_SETFRAGMENT: | ||
1700 | if (get_user(val, (int *) arg)) | ||
1701 | return -EFAULT; | ||
1702 | if (file->f_mode & FMODE_READ) { | ||
1703 | stop_adc(s); | ||
1704 | s->dma_adc.ossfragshift = val & 0xffff; | ||
1705 | s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; | ||
1706 | if (s->dma_adc.ossfragshift < 4) | ||
1707 | s->dma_adc.ossfragshift = 4; | ||
1708 | if (s->dma_adc.ossfragshift > 15) | ||
1709 | s->dma_adc.ossfragshift = 15; | ||
1710 | if (s->dma_adc.ossmaxfrags < 4) | ||
1711 | s->dma_adc.ossmaxfrags = 4; | ||
1712 | if ((ret = prog_dmabuf_adc(s))) | ||
1713 | return ret; | ||
1714 | } | ||
1715 | if (file->f_mode & FMODE_WRITE) { | ||
1716 | stop_dac(s); | ||
1717 | s->dma_dac.ossfragshift = val & 0xffff; | ||
1718 | s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; | ||
1719 | if (s->dma_dac.ossfragshift < 4) | ||
1720 | s->dma_dac.ossfragshift = 4; | ||
1721 | if (s->dma_dac.ossfragshift > 15) | ||
1722 | s->dma_dac.ossfragshift = 15; | ||
1723 | if (s->dma_dac.ossmaxfrags < 4) | ||
1724 | s->dma_dac.ossmaxfrags = 4; | ||
1725 | if ((ret = prog_dmabuf_dac(s))) | ||
1726 | return ret; | ||
1727 | } | ||
1728 | return 0; | ||
1729 | |||
1730 | case SNDCTL_DSP_SUBDIVIDE: | ||
1731 | if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || | ||
1732 | (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) | ||
1733 | return -EINVAL; | ||
1734 | if (get_user(val, (int *) arg)) | ||
1735 | return -EFAULT; | ||
1736 | if (val != 1 && val != 2 && val != 4) | ||
1737 | return -EINVAL; | ||
1738 | if (file->f_mode & FMODE_READ) { | ||
1739 | stop_adc(s); | ||
1740 | s->dma_adc.subdivision = val; | ||
1741 | if ((ret = prog_dmabuf_adc(s))) | ||
1742 | return ret; | ||
1743 | } | ||
1744 | if (file->f_mode & FMODE_WRITE) { | ||
1745 | stop_dac(s); | ||
1746 | s->dma_dac.subdivision = val; | ||
1747 | if ((ret = prog_dmabuf_dac(s))) | ||
1748 | return ret; | ||
1749 | } | ||
1750 | return 0; | ||
1751 | |||
1752 | case SOUND_PCM_READ_RATE: | ||
1753 | return put_user((file->f_mode & FMODE_READ) ? | ||
1754 | s->dma_adc.sample_rate : | ||
1755 | s->dma_dac.sample_rate, | ||
1756 | (int *)arg); | ||
1757 | |||
1758 | case SOUND_PCM_READ_CHANNELS: | ||
1759 | if (file->f_mode & FMODE_READ) | ||
1760 | return put_user(s->dma_adc.num_channels, (int *)arg); | ||
1761 | else | ||
1762 | return put_user(s->dma_dac.num_channels, (int *)arg); | ||
1763 | |||
1764 | case SOUND_PCM_READ_BITS: | ||
1765 | if (file->f_mode & FMODE_READ) | ||
1766 | return put_user(s->dma_adc.sample_size, (int *)arg); | ||
1767 | else | ||
1768 | return put_user(s->dma_dac.sample_size, (int *)arg); | ||
1769 | |||
1770 | case SOUND_PCM_WRITE_FILTER: | ||
1771 | case SNDCTL_DSP_SETSYNCRO: | ||
1772 | case SOUND_PCM_READ_FILTER: | ||
1773 | return -EINVAL; | ||
1774 | } | ||
1775 | |||
1776 | return mixdev_ioctl(s->codec, cmd, arg); | ||
1777 | } | ||
1778 | |||
1779 | static long | ||
1780 | au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1781 | { | ||
1782 | int ret; | ||
1783 | |||
1784 | mutex_lock(&au1550_ac97_mutex); | ||
1785 | ret = au1550_ioctl(file, cmd, arg); | ||
1786 | mutex_unlock(&au1550_ac97_mutex); | ||
1787 | |||
1788 | return ret; | ||
1789 | } | ||
1790 | |||
1791 | static int | ||
1792 | au1550_open(struct inode *inode, struct file *file) | ||
1793 | { | ||
1794 | int minor = MINOR(inode->i_rdev); | ||
1795 | DECLARE_WAITQUEUE(wait, current); | ||
1796 | struct au1550_state *s = &au1550_state; | ||
1797 | int ret; | ||
1798 | |||
1799 | #ifdef DEBUG | ||
1800 | if (file->f_flags & O_NONBLOCK) | ||
1801 | pr_debug("open: non-blocking\n"); | ||
1802 | else | ||
1803 | pr_debug("open: blocking\n"); | ||
1804 | #endif | ||
1805 | |||
1806 | file->private_data = s; | ||
1807 | mutex_lock(&au1550_ac97_mutex); | ||
1808 | /* wait for device to become free */ | ||
1809 | mutex_lock(&s->open_mutex); | ||
1810 | while (s->open_mode & file->f_mode) { | ||
1811 | ret = -EBUSY; | ||
1812 | if (file->f_flags & O_NONBLOCK) | ||
1813 | goto out; | ||
1814 | add_wait_queue(&s->open_wait, &wait); | ||
1815 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1816 | mutex_unlock(&s->open_mutex); | ||
1817 | schedule(); | ||
1818 | remove_wait_queue(&s->open_wait, &wait); | ||
1819 | set_current_state(TASK_RUNNING); | ||
1820 | ret = -ERESTARTSYS; | ||
1821 | if (signal_pending(current)) | ||
1822 | goto out2; | ||
1823 | mutex_lock(&s->open_mutex); | ||
1824 | } | ||
1825 | |||
1826 | stop_dac(s); | ||
1827 | stop_adc(s); | ||
1828 | |||
1829 | if (file->f_mode & FMODE_READ) { | ||
1830 | s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = | ||
1831 | s->dma_adc.subdivision = s->dma_adc.total_bytes = 0; | ||
1832 | s->dma_adc.num_channels = 1; | ||
1833 | s->dma_adc.sample_size = 8; | ||
1834 | set_adc_rate(s, 8000); | ||
1835 | if ((minor & 0xf) == SND_DEV_DSP16) | ||
1836 | s->dma_adc.sample_size = 16; | ||
1837 | } | ||
1838 | |||
1839 | if (file->f_mode & FMODE_WRITE) { | ||
1840 | s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = | ||
1841 | s->dma_dac.subdivision = s->dma_dac.total_bytes = 0; | ||
1842 | s->dma_dac.num_channels = 1; | ||
1843 | s->dma_dac.sample_size = 8; | ||
1844 | set_dac_rate(s, 8000); | ||
1845 | if ((minor & 0xf) == SND_DEV_DSP16) | ||
1846 | s->dma_dac.sample_size = 16; | ||
1847 | } | ||
1848 | |||
1849 | if (file->f_mode & FMODE_READ) { | ||
1850 | if ((ret = prog_dmabuf_adc(s))) | ||
1851 | goto out; | ||
1852 | } | ||
1853 | if (file->f_mode & FMODE_WRITE) { | ||
1854 | if ((ret = prog_dmabuf_dac(s))) | ||
1855 | goto out; | ||
1856 | } | ||
1857 | |||
1858 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | ||
1859 | mutex_init(&s->sem); | ||
1860 | ret = 0; | ||
1861 | out: | ||
1862 | mutex_unlock(&s->open_mutex); | ||
1863 | out2: | ||
1864 | mutex_unlock(&au1550_ac97_mutex); | ||
1865 | return ret; | ||
1866 | } | ||
1867 | |||
1868 | static int | ||
1869 | au1550_release(struct inode *inode, struct file *file) | ||
1870 | { | ||
1871 | struct au1550_state *s = file->private_data; | ||
1872 | |||
1873 | mutex_lock(&au1550_ac97_mutex); | ||
1874 | |||
1875 | if (file->f_mode & FMODE_WRITE) { | ||
1876 | mutex_unlock(&au1550_ac97_mutex); | ||
1877 | drain_dac(s, file->f_flags & O_NONBLOCK); | ||
1878 | mutex_lock(&au1550_ac97_mutex); | ||
1879 | } | ||
1880 | |||
1881 | mutex_lock(&s->open_mutex); | ||
1882 | if (file->f_mode & FMODE_WRITE) { | ||
1883 | stop_dac(s); | ||
1884 | kfree(s->dma_dac.rawbuf); | ||
1885 | s->dma_dac.rawbuf = NULL; | ||
1886 | } | ||
1887 | if (file->f_mode & FMODE_READ) { | ||
1888 | stop_adc(s); | ||
1889 | kfree(s->dma_adc.rawbuf); | ||
1890 | s->dma_adc.rawbuf = NULL; | ||
1891 | } | ||
1892 | s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE)); | ||
1893 | mutex_unlock(&s->open_mutex); | ||
1894 | wake_up(&s->open_wait); | ||
1895 | mutex_unlock(&au1550_ac97_mutex); | ||
1896 | return 0; | ||
1897 | } | ||
1898 | |||
1899 | static /*const */ struct file_operations au1550_audio_fops = { | ||
1900 | .owner = THIS_MODULE, | ||
1901 | .llseek = au1550_llseek, | ||
1902 | .read = au1550_read, | ||
1903 | .write = au1550_write, | ||
1904 | .poll = au1550_poll, | ||
1905 | .unlocked_ioctl = au1550_unlocked_ioctl, | ||
1906 | .mmap = au1550_mmap, | ||
1907 | .open = au1550_open, | ||
1908 | .release = au1550_release, | ||
1909 | }; | ||
1910 | |||
1911 | MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); | ||
1912 | MODULE_DESCRIPTION("Au1550 AC97 Audio Driver"); | ||
1913 | MODULE_LICENSE("GPL"); | ||
1914 | |||
1915 | |||
1916 | static int __devinit | ||
1917 | au1550_probe(void) | ||
1918 | { | ||
1919 | struct au1550_state *s = &au1550_state; | ||
1920 | int val; | ||
1921 | |||
1922 | memset(s, 0, sizeof(struct au1550_state)); | ||
1923 | |||
1924 | init_waitqueue_head(&s->dma_adc.wait); | ||
1925 | init_waitqueue_head(&s->dma_dac.wait); | ||
1926 | init_waitqueue_head(&s->open_wait); | ||
1927 | mutex_init(&s->open_mutex); | ||
1928 | spin_lock_init(&s->lock); | ||
1929 | |||
1930 | s->codec = ac97_alloc_codec(); | ||
1931 | if(s->codec == NULL) { | ||
1932 | err("Out of memory"); | ||
1933 | return -1; | ||
1934 | } | ||
1935 | s->codec->private_data = s; | ||
1936 | s->codec->id = 0; | ||
1937 | s->codec->codec_read = rdcodec; | ||
1938 | s->codec->codec_write = wrcodec; | ||
1939 | s->codec->codec_wait = waitcodec; | ||
1940 | |||
1941 | if (!request_mem_region(CPHYSADDR(AC97_PSC_SEL), | ||
1942 | 0x30, "Au1550 AC97")) { | ||
1943 | err("AC'97 ports in use"); | ||
1944 | } | ||
1945 | |||
1946 | /* Allocate the DMA Channels | ||
1947 | */ | ||
1948 | if ((s->dma_dac.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_MEM_CHAN, | ||
1949 | DBDMA_AC97_TX_CHAN, dac_dma_interrupt, (void *)s)) == 0) { | ||
1950 | err("Can't get DAC DMA"); | ||
1951 | goto err_dma1; | ||
1952 | } | ||
1953 | au1xxx_dbdma_set_devwidth(s->dma_dac.dmanr, 16); | ||
1954 | if (au1xxx_dbdma_ring_alloc(s->dma_dac.dmanr, | ||
1955 | NUM_DBDMA_DESCRIPTORS) == 0) { | ||
1956 | err("Can't get DAC DMA descriptors"); | ||
1957 | goto err_dma1; | ||
1958 | } | ||
1959 | |||
1960 | if ((s->dma_adc.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_AC97_RX_CHAN, | ||
1961 | DBDMA_MEM_CHAN, adc_dma_interrupt, (void *)s)) == 0) { | ||
1962 | err("Can't get ADC DMA"); | ||
1963 | goto err_dma2; | ||
1964 | } | ||
1965 | au1xxx_dbdma_set_devwidth(s->dma_adc.dmanr, 16); | ||
1966 | if (au1xxx_dbdma_ring_alloc(s->dma_adc.dmanr, | ||
1967 | NUM_DBDMA_DESCRIPTORS) == 0) { | ||
1968 | err("Can't get ADC DMA descriptors"); | ||
1969 | goto err_dma2; | ||
1970 | } | ||
1971 | |||
1972 | pr_info("DAC: DMA%d, ADC: DMA%d", DBDMA_AC97_TX_CHAN, DBDMA_AC97_RX_CHAN); | ||
1973 | |||
1974 | /* register devices */ | ||
1975 | |||
1976 | if ((s->dev_audio = register_sound_dsp(&au1550_audio_fops, -1)) < 0) | ||
1977 | goto err_dev1; | ||
1978 | if ((s->codec->dev_mixer = | ||
1979 | register_sound_mixer(&au1550_mixer_fops, -1)) < 0) | ||
1980 | goto err_dev2; | ||
1981 | |||
1982 | /* The GPIO for the appropriate PSC was configured by the | ||
1983 | * board specific start up. | ||
1984 | * | ||
1985 | * configure PSC for AC'97 | ||
1986 | */ | ||
1987 | au_writel(0, AC97_PSC_CTRL); /* Disable PSC */ | ||
1988 | au_sync(); | ||
1989 | au_writel((PSC_SEL_CLK_SERCLK | PSC_SEL_PS_AC97MODE), AC97_PSC_SEL); | ||
1990 | au_sync(); | ||
1991 | |||
1992 | /* cold reset the AC'97 | ||
1993 | */ | ||
1994 | au_writel(PSC_AC97RST_RST, PSC_AC97RST); | ||
1995 | au_sync(); | ||
1996 | au1550_delay(10); | ||
1997 | au_writel(0, PSC_AC97RST); | ||
1998 | au_sync(); | ||
1999 | |||
2000 | /* need to delay around 500msec(bleech) to give | ||
2001 | some CODECs enough time to wakeup */ | ||
2002 | au1550_delay(500); | ||
2003 | |||
2004 | /* warm reset the AC'97 to start the bitclk | ||
2005 | */ | ||
2006 | au_writel(PSC_AC97RST_SNC, PSC_AC97RST); | ||
2007 | au_sync(); | ||
2008 | udelay(100); | ||
2009 | au_writel(0, PSC_AC97RST); | ||
2010 | au_sync(); | ||
2011 | |||
2012 | /* Enable PSC | ||
2013 | */ | ||
2014 | au_writel(PSC_CTRL_ENABLE, AC97_PSC_CTRL); | ||
2015 | au_sync(); | ||
2016 | |||
2017 | /* Wait for PSC ready. | ||
2018 | */ | ||
2019 | do { | ||
2020 | val = au_readl(PSC_AC97STAT); | ||
2021 | au_sync(); | ||
2022 | } while ((val & PSC_AC97STAT_SR) == 0); | ||
2023 | |||
2024 | /* Configure AC97 controller. | ||
2025 | * Deep FIFO, 16-bit sample, DMA, make sure DMA matches fifo size. | ||
2026 | */ | ||
2027 | val = PSC_AC97CFG_SET_LEN(16); | ||
2028 | val |= PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8; | ||
2029 | |||
2030 | /* Enable device so we can at least | ||
2031 | * talk over the AC-link. | ||
2032 | */ | ||
2033 | au_writel(val, PSC_AC97CFG); | ||
2034 | au_writel(PSC_AC97MSK_ALLMASK, PSC_AC97MSK); | ||
2035 | au_sync(); | ||
2036 | val |= PSC_AC97CFG_DE_ENABLE; | ||
2037 | au_writel(val, PSC_AC97CFG); | ||
2038 | au_sync(); | ||
2039 | |||
2040 | /* Wait for Device ready. | ||
2041 | */ | ||
2042 | do { | ||
2043 | val = au_readl(PSC_AC97STAT); | ||
2044 | au_sync(); | ||
2045 | } while ((val & PSC_AC97STAT_DR) == 0); | ||
2046 | |||
2047 | /* codec init */ | ||
2048 | if (!ac97_probe_codec(s->codec)) | ||
2049 | goto err_dev3; | ||
2050 | |||
2051 | s->codec_base_caps = rdcodec(s->codec, AC97_RESET); | ||
2052 | s->codec_ext_caps = rdcodec(s->codec, AC97_EXTENDED_ID); | ||
2053 | pr_info("AC'97 Base/Extended ID = %04x/%04x", | ||
2054 | s->codec_base_caps, s->codec_ext_caps); | ||
2055 | |||
2056 | if (!(s->codec_ext_caps & AC97_EXTID_VRA)) { | ||
2057 | /* codec does not support VRA | ||
2058 | */ | ||
2059 | s->no_vra = 1; | ||
2060 | } else if (!vra) { | ||
2061 | /* Boot option says disable VRA | ||
2062 | */ | ||
2063 | u16 ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS); | ||
2064 | wrcodec(s->codec, AC97_EXTENDED_STATUS, | ||
2065 | ac97_extstat & ~AC97_EXTSTAT_VRA); | ||
2066 | s->no_vra = 1; | ||
2067 | } | ||
2068 | if (s->no_vra) | ||
2069 | pr_info("no VRA, interpolating and decimating"); | ||
2070 | |||
2071 | /* set mic to be the recording source */ | ||
2072 | val = SOUND_MASK_MIC; | ||
2073 | mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, | ||
2074 | (unsigned long) &val); | ||
2075 | |||
2076 | return 0; | ||
2077 | |||
2078 | err_dev3: | ||
2079 | unregister_sound_mixer(s->codec->dev_mixer); | ||
2080 | err_dev2: | ||
2081 | unregister_sound_dsp(s->dev_audio); | ||
2082 | err_dev1: | ||
2083 | au1xxx_dbdma_chan_free(s->dma_adc.dmanr); | ||
2084 | err_dma2: | ||
2085 | au1xxx_dbdma_chan_free(s->dma_dac.dmanr); | ||
2086 | err_dma1: | ||
2087 | release_mem_region(CPHYSADDR(AC97_PSC_SEL), 0x30); | ||
2088 | |||
2089 | ac97_release_codec(s->codec); | ||
2090 | return -1; | ||
2091 | } | ||
2092 | |||
2093 | static void __devinit | ||
2094 | au1550_remove(void) | ||
2095 | { | ||
2096 | struct au1550_state *s = &au1550_state; | ||
2097 | |||
2098 | if (!s) | ||
2099 | return; | ||
2100 | synchronize_irq(); | ||
2101 | au1xxx_dbdma_chan_free(s->dma_adc.dmanr); | ||
2102 | au1xxx_dbdma_chan_free(s->dma_dac.dmanr); | ||
2103 | release_mem_region(CPHYSADDR(AC97_PSC_SEL), 0x30); | ||
2104 | unregister_sound_dsp(s->dev_audio); | ||
2105 | unregister_sound_mixer(s->codec->dev_mixer); | ||
2106 | ac97_release_codec(s->codec); | ||
2107 | } | ||
2108 | |||
2109 | static int __init | ||
2110 | init_au1550(void) | ||
2111 | { | ||
2112 | return au1550_probe(); | ||
2113 | } | ||
2114 | |||
2115 | static void __exit | ||
2116 | cleanup_au1550(void) | ||
2117 | { | ||
2118 | au1550_remove(); | ||
2119 | } | ||
2120 | |||
2121 | module_init(init_au1550); | ||
2122 | module_exit(cleanup_au1550); | ||
2123 | |||
2124 | #ifndef MODULE | ||
2125 | |||
2126 | static int __init | ||
2127 | au1550_setup(char *options) | ||
2128 | { | ||
2129 | char *this_opt; | ||
2130 | |||
2131 | if (!options || !*options) | ||
2132 | return 0; | ||
2133 | |||
2134 | while ((this_opt = strsep(&options, ","))) { | ||
2135 | if (!*this_opt) | ||
2136 | continue; | ||
2137 | if (!strncmp(this_opt, "vra", 3)) { | ||
2138 | vra = 1; | ||
2139 | } | ||
2140 | } | ||
2141 | |||
2142 | return 1; | ||
2143 | } | ||
2144 | |||
2145 | __setup("au1550_audio=", au1550_setup); | ||
2146 | |||
2147 | #endif /* MODULE */ | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 389cd7931668..e90d103e177e 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -534,6 +534,14 @@ config SND_ES1968_INPUT | |||
534 | If you say N the buttons will directly control the master volume. | 534 | If you say N the buttons will directly control the master volume. |
535 | It is recommended to say Y. | 535 | It is recommended to say Y. |
536 | 536 | ||
537 | config SND_ES1968_RADIO | ||
538 | bool "Enable TEA5757 radio tuner support for es1968" | ||
539 | depends on SND_ES1968 | ||
540 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 | ||
541 | help | ||
542 | Say Y here to include support for TEA5757 radio tuner integrated on | ||
543 | some MediaForte cards (e.g. SF64-PCE2). | ||
544 | |||
537 | config SND_FM801 | 545 | config SND_FM801 |
538 | tristate "ForteMedia FM801" | 546 | tristate "ForteMedia FM801" |
539 | select SND_OPL3_LIB | 547 | select SND_OPL3_LIB |
@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL | |||
552 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 | 560 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 |
553 | help | 561 | help |
554 | Say Y here to include support for soundcards based on the ForteMedia | 562 | Say Y here to include support for soundcards based on the ForteMedia |
555 | FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media | 563 | FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and |
556 | Forte SF256-PCS-02) into the snd-fm801 driver. | 564 | SF64-PCR) into the snd-fm801 driver. |
557 | 565 | ||
558 | config SND_FM801_TEA575X | 566 | config SND_TEA575X |
559 | tristate | 567 | tristate |
560 | depends on SND_FM801_TEA575X_BOOL | 568 | depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO |
561 | default SND_FM801 | 569 | default SND_FM801 || SND_ES1968 |
562 | 570 | ||
563 | source "sound/pci/hda/Kconfig" | 571 | source "sound/pci/hda/Kconfig" |
564 | 572 | ||
@@ -658,6 +666,15 @@ config SND_KORG1212 | |||
658 | To compile this driver as a module, choose M here: the module | 666 | To compile this driver as a module, choose M here: the module |
659 | will be called snd-korg1212. | 667 | will be called snd-korg1212. |
660 | 668 | ||
669 | config SND_LOLA | ||
670 | tristate "Digigram Lola" | ||
671 | select SND_PCM | ||
672 | help | ||
673 | Say Y to include support for Digigram Lola boards. | ||
674 | |||
675 | To compile this driver as a module, choose M here: the module | ||
676 | will be called snd-lola. | ||
677 | |||
661 | config SND_LX6464ES | 678 | config SND_LX6464ES |
662 | tristate "Digigram LX6464ES" | 679 | tristate "Digigram LX6464ES" |
663 | select SND_PCM | 680 | select SND_PCM |
diff --git a/sound/pci/Makefile b/sound/pci/Makefile index 9cf4348ec137..54fe325e3aa5 100644 --- a/sound/pci/Makefile +++ b/sound/pci/Makefile | |||
@@ -64,6 +64,7 @@ obj-$(CONFIG_SND) += \ | |||
64 | ca0106/ \ | 64 | ca0106/ \ |
65 | cs46xx/ \ | 65 | cs46xx/ \ |
66 | cs5535audio/ \ | 66 | cs5535audio/ \ |
67 | lola/ \ | ||
67 | lx6464es/ \ | 68 | lx6464es/ \ |
68 | echoaudio/ \ | 69 | echoaudio/ \ |
69 | emu10k1/ \ | 70 | emu10k1/ \ |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index f8ccc9677c6f..2ca6f4f85b41 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -42,10 +42,29 @@ | |||
42 | #include <sound/tlv.h> | 42 | #include <sound/tlv.h> |
43 | #include <sound/hwdep.h> | 43 | #include <sound/hwdep.h> |
44 | 44 | ||
45 | |||
45 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
46 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); | 47 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); |
47 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); | 48 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); |
48 | 49 | ||
50 | #if defined CONFIG_SND_DEBUG | ||
51 | /* copied from pcm_lib.c, hope later patch will make that version public | ||
52 | and this copy can be removed */ | ||
53 | static void pcm_debug_name(struct snd_pcm_substream *substream, | ||
54 | char *name, size_t len) | ||
55 | { | ||
56 | snprintf(name, len, "pcmC%dD%d%c:%d", | ||
57 | substream->pcm->card->number, | ||
58 | substream->pcm->device, | ||
59 | substream->stream ? 'c' : 'p', | ||
60 | substream->number); | ||
61 | } | ||
62 | #define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name)) | ||
63 | #else | ||
64 | #define pcm_debug_name(s, n, l) do { } while (0) | ||
65 | #define DEBUG_NAME(name, substream) do { } while (0) | ||
66 | #endif | ||
67 | |||
49 | #if defined CONFIG_SND_DEBUG_VERBOSE | 68 | #if defined CONFIG_SND_DEBUG_VERBOSE |
50 | /** | 69 | /** |
51 | * snd_printddd - very verbose debug printk | 70 | * snd_printddd - very verbose debug printk |
@@ -58,7 +77,7 @@ MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); | |||
58 | #define snd_printddd(format, args...) \ | 77 | #define snd_printddd(format, args...) \ |
59 | __snd_printk(3, __FILE__, __LINE__, format, ##args) | 78 | __snd_printk(3, __FILE__, __LINE__, format, ##args) |
60 | #else | 79 | #else |
61 | #define snd_printddd(format, args...) do { } while (0) | 80 | #define snd_printddd(format, args...) do { } while (0) |
62 | #endif | 81 | #endif |
63 | 82 | ||
64 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ | 83 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ |
@@ -101,13 +120,6 @@ static int adapter_fs = DEFAULT_SAMPLERATE; | |||
101 | #define PERIOD_BYTES_MIN 2048 | 120 | #define PERIOD_BYTES_MIN 2048 |
102 | #define BUFFER_BYTES_MAX (512 * 1024) | 121 | #define BUFFER_BYTES_MAX (512 * 1024) |
103 | 122 | ||
104 | /* convert stream to character */ | ||
105 | #define SCHR(s) ((s == SNDRV_PCM_STREAM_PLAYBACK) ? 'P' : 'C') | ||
106 | |||
107 | /*#define TIMER_MILLISECONDS 20 | ||
108 | #define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000) | ||
109 | */ | ||
110 | |||
111 | #define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) | 123 | #define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) |
112 | 124 | ||
113 | struct clk_source { | 125 | struct clk_source { |
@@ -136,7 +148,7 @@ struct snd_card_asihpi { | |||
136 | u32 h_mixer; | 148 | u32 h_mixer; |
137 | struct clk_cache cc; | 149 | struct clk_cache cc; |
138 | 150 | ||
139 | u16 support_mmap; | 151 | u16 can_dma; |
140 | u16 support_grouping; | 152 | u16 support_grouping; |
141 | u16 support_mrx; | 153 | u16 support_mrx; |
142 | u16 update_interval_frames; | 154 | u16 update_interval_frames; |
@@ -155,6 +167,7 @@ struct snd_card_asihpi_pcm { | |||
155 | unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ | 167 | unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ |
156 | unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ | 168 | unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ |
157 | unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ | 169 | unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ |
170 | unsigned int drained_count; | ||
158 | struct snd_pcm_substream *substream; | 171 | struct snd_pcm_substream *substream; |
159 | u32 h_stream; | 172 | u32 h_stream; |
160 | struct hpi_format format; | 173 | struct hpi_format format; |
@@ -288,19 +301,26 @@ static u16 handle_error(u16 err, int line, char *filename) | |||
288 | #define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) | 301 | #define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) |
289 | 302 | ||
290 | /***************************** GENERAL PCM ****************/ | 303 | /***************************** GENERAL PCM ****************/ |
291 | static void print_hwparams(struct snd_pcm_hw_params *p) | 304 | |
305 | static void print_hwparams(struct snd_pcm_substream *substream, | ||
306 | struct snd_pcm_hw_params *p) | ||
292 | { | 307 | { |
293 | snd_printd("HWPARAMS \n"); | 308 | DEBUG_NAME(substream, name); |
294 | snd_printd("samplerate %d \n", params_rate(p)); | 309 | snd_printd("%s HWPARAMS\n", name); |
295 | snd_printd("Channels %d \n", params_channels(p)); | 310 | snd_printd(" samplerate %d Hz\n", params_rate(p)); |
296 | snd_printd("Format %d \n", params_format(p)); | 311 | snd_printd(" channels %d\n", params_channels(p)); |
297 | snd_printd("subformat %d \n", params_subformat(p)); | 312 | snd_printd(" format %d\n", params_format(p)); |
298 | snd_printd("Buffer bytes %d \n", params_buffer_bytes(p)); | 313 | snd_printd(" subformat %d\n", params_subformat(p)); |
299 | snd_printd("Period bytes %d \n", params_period_bytes(p)); | 314 | snd_printd(" buffer %d B\n", params_buffer_bytes(p)); |
300 | snd_printd("access %d \n", params_access(p)); | 315 | snd_printd(" period %d B\n", params_period_bytes(p)); |
301 | snd_printd("period_size %d \n", params_period_size(p)); | 316 | snd_printd(" access %d\n", params_access(p)); |
302 | snd_printd("periods %d \n", params_periods(p)); | 317 | snd_printd(" period_size %d\n", params_period_size(p)); |
303 | snd_printd("buffer_size %d \n", params_buffer_size(p)); | 318 | snd_printd(" periods %d\n", params_periods(p)); |
319 | snd_printd(" buffer_size %d\n", params_buffer_size(p)); | ||
320 | snd_printd(" %d B/s\n", params_rate(p) * | ||
321 | params_channels(p) * | ||
322 | snd_pcm_format_width(params_format(p)) / 8); | ||
323 | |||
304 | } | 324 | } |
305 | 325 | ||
306 | static snd_pcm_format_t hpi_to_alsa_formats[] = { | 326 | static snd_pcm_format_t hpi_to_alsa_formats[] = { |
@@ -451,7 +471,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
451 | int width; | 471 | int width; |
452 | unsigned int bytes_per_sec; | 472 | unsigned int bytes_per_sec; |
453 | 473 | ||
454 | print_hwparams(params); | 474 | print_hwparams(substream, params); |
455 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | 475 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
456 | if (err < 0) | 476 | if (err < 0) |
457 | return err; | 477 | return err; |
@@ -459,10 +479,6 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
459 | if (err) | 479 | if (err) |
460 | return err; | 480 | return err; |
461 | 481 | ||
462 | snd_printdd("format %d, %d chans, %d_hz\n", | ||
463 | format, params_channels(params), | ||
464 | params_rate(params)); | ||
465 | |||
466 | hpi_handle_error(hpi_format_create(&dpcm->format, | 482 | hpi_handle_error(hpi_format_create(&dpcm->format, |
467 | params_channels(params), | 483 | params_channels(params), |
468 | format, params_rate(params), 0, 0)); | 484 | format, params_rate(params), 0, 0)); |
@@ -477,8 +493,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
477 | } | 493 | } |
478 | 494 | ||
479 | dpcm->hpi_buffer_attached = 0; | 495 | dpcm->hpi_buffer_attached = 0; |
480 | if (card->support_mmap) { | 496 | if (card->can_dma) { |
481 | |||
482 | err = hpi_stream_host_buffer_attach(dpcm->h_stream, | 497 | err = hpi_stream_host_buffer_attach(dpcm->h_stream, |
483 | params_buffer_bytes(params), runtime->dma_addr); | 498 | params_buffer_bytes(params), runtime->dma_addr); |
484 | if (err == 0) { | 499 | if (err == 0) { |
@@ -509,8 +524,6 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
509 | dpcm->bytes_per_sec = bytes_per_sec; | 524 | dpcm->bytes_per_sec = bytes_per_sec; |
510 | dpcm->buffer_bytes = params_buffer_bytes(params); | 525 | dpcm->buffer_bytes = params_buffer_bytes(params); |
511 | dpcm->period_bytes = params_period_bytes(params); | 526 | dpcm->period_bytes = params_period_bytes(params); |
512 | snd_printdd("buffer_bytes=%d, period_bytes=%d, bps=%d\n", | ||
513 | dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec); | ||
514 | 527 | ||
515 | return 0; | 528 | return 0; |
516 | } | 529 | } |
@@ -564,9 +577,10 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
564 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); | 577 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); |
565 | struct snd_pcm_substream *s; | 578 | struct snd_pcm_substream *s; |
566 | u16 e; | 579 | u16 e; |
580 | DEBUG_NAME(substream, name); | ||
581 | |||
582 | snd_printdd("%s trigger\n", name); | ||
567 | 583 | ||
568 | snd_printdd("%c%d trigger\n", | ||
569 | SCHR(substream->stream), substream->number); | ||
570 | switch (cmd) { | 584 | switch (cmd) { |
571 | case SNDRV_PCM_TRIGGER_START: | 585 | case SNDRV_PCM_TRIGGER_START: |
572 | snd_pcm_group_for_each_entry(s, substream) { | 586 | snd_pcm_group_for_each_entry(s, substream) { |
@@ -580,8 +594,8 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
580 | if (substream->stream != s->stream) | 594 | if (substream->stream != s->stream) |
581 | continue; | 595 | continue; |
582 | 596 | ||
583 | if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) && | 597 | ds->drained_count = 0; |
584 | (card->support_mmap)) { | 598 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
585 | /* How do I know how much valid data is present | 599 | /* How do I know how much valid data is present |
586 | * in buffer? Must be at least one period! | 600 | * in buffer? Must be at least one period! |
587 | * Guessing 2 periods, but if | 601 | * Guessing 2 periods, but if |
@@ -599,9 +613,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
599 | } | 613 | } |
600 | 614 | ||
601 | if (card->support_grouping) { | 615 | if (card->support_grouping) { |
602 | snd_printdd("\t%c%d group\n", | 616 | snd_printdd("%d group\n", s->number); |
603 | SCHR(s->stream), | ||
604 | s->number); | ||
605 | e = hpi_stream_group_add( | 617 | e = hpi_stream_group_add( |
606 | dpcm->h_stream, | 618 | dpcm->h_stream, |
607 | ds->h_stream); | 619 | ds->h_stream); |
@@ -618,7 +630,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
618 | /* start the master stream */ | 630 | /* start the master stream */ |
619 | snd_card_asihpi_pcm_timer_start(substream); | 631 | snd_card_asihpi_pcm_timer_start(substream); |
620 | if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || | 632 | if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || |
621 | !card->support_mmap) | 633 | !card->can_dma) |
622 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); | 634 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); |
623 | break; | 635 | break; |
624 | 636 | ||
@@ -636,9 +648,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
636 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; | 648 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; |
637 | 649 | ||
638 | if (card->support_grouping) { | 650 | if (card->support_grouping) { |
639 | snd_printdd("\t%c%d group\n", | 651 | snd_printdd("%d group\n", s->number); |
640 | SCHR(s->stream), | ||
641 | s->number); | ||
642 | snd_pcm_trigger_done(s, substream); | 652 | snd_pcm_trigger_done(s, substream); |
643 | } else | 653 | } else |
644 | break; | 654 | break; |
@@ -732,9 +742,9 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
732 | int loops = 0; | 742 | int loops = 0; |
733 | u16 state; | 743 | u16 state; |
734 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; | 744 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; |
745 | DEBUG_NAME(substream, name); | ||
735 | 746 | ||
736 | snd_printdd("%c%d snd_card_asihpi_timer_function\n", | 747 | snd_printdd("%s snd_card_asihpi_timer_function\n", name); |
737 | SCHR(substream->stream), substream->number); | ||
738 | 748 | ||
739 | /* find minimum newdata and buffer pos in group */ | 749 | /* find minimum newdata and buffer pos in group */ |
740 | snd_pcm_group_for_each_entry(s, substream) { | 750 | snd_pcm_group_for_each_entry(s, substream) { |
@@ -756,6 +766,9 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
756 | /* number of bytes in on-card buffer */ | 766 | /* number of bytes in on-card buffer */ |
757 | runtime->delay = on_card_bytes; | 767 | runtime->delay = on_card_bytes; |
758 | 768 | ||
769 | if (!card->can_dma) | ||
770 | on_card_bytes = bytes_avail; | ||
771 | |||
759 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 772 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
760 | pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; | 773 | pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; |
761 | if (state == HPI_STATE_STOPPED) { | 774 | if (state == HPI_STATE_STOPPED) { |
@@ -763,12 +776,18 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
763 | (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { | 776 | (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { |
764 | hpi_handle_error(hpi_stream_start(ds->h_stream)); | 777 | hpi_handle_error(hpi_stream_start(ds->h_stream)); |
765 | snd_printdd("P%d start\n", s->number); | 778 | snd_printdd("P%d start\n", s->number); |
779 | ds->drained_count = 0; | ||
766 | } | 780 | } |
767 | } else if (state == HPI_STATE_DRAINED) { | 781 | } else if (state == HPI_STATE_DRAINED) { |
768 | snd_printd(KERN_WARNING "P%d drained\n", | 782 | snd_printd(KERN_WARNING "P%d drained\n", |
769 | s->number); | 783 | s->number); |
770 | /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | 784 | ds->drained_count++; |
771 | continue; */ | 785 | if (ds->drained_count > 2) { |
786 | snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | ||
787 | continue; | ||
788 | } | ||
789 | } else { | ||
790 | ds->drained_count = 0; | ||
772 | } | 791 | } |
773 | } else | 792 | } else |
774 | pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; | 793 | pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; |
@@ -786,16 +805,18 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
786 | newdata); | 805 | newdata); |
787 | } | 806 | } |
788 | 807 | ||
789 | snd_printdd("hw_ptr x%04lX, appl_ptr x%04lX\n", | 808 | snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n", |
790 | (unsigned long)frames_to_bytes(runtime, | 809 | (unsigned long)frames_to_bytes(runtime, |
791 | runtime->status->hw_ptr), | 810 | runtime->status->hw_ptr), |
792 | (unsigned long)frames_to_bytes(runtime, | 811 | (unsigned long)frames_to_bytes(runtime, |
793 | runtime->control->appl_ptr)); | 812 | runtime->control->appl_ptr)); |
794 | 813 | ||
795 | snd_printdd("%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X," | 814 | snd_printdd("%d S=%d, " |
796 | " aux=x%04X space=x%04X\n", | 815 | "rw=0x%04X, dma=0x%04X, left=0x%04X, " |
797 | loops, SCHR(s->stream), s->number, | 816 | "aux=0x%04X space=0x%04X\n", |
798 | state, ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail, | 817 | s->number, state, |
818 | ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, | ||
819 | (int)bytes_avail, | ||
799 | (int)on_card_bytes, buffer_size-bytes_avail); | 820 | (int)on_card_bytes, buffer_size-bytes_avail); |
800 | loops++; | 821 | loops++; |
801 | } | 822 | } |
@@ -814,7 +835,7 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
814 | 835 | ||
815 | next_jiffies = max(next_jiffies, 1U); | 836 | next_jiffies = max(next_jiffies, 1U); |
816 | dpcm->timer.expires = jiffies + next_jiffies; | 837 | dpcm->timer.expires = jiffies + next_jiffies; |
817 | snd_printdd("jif %d buf pos x%04X newdata x%04X xfer x%04X\n", | 838 | snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n", |
818 | next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); | 839 | next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); |
819 | 840 | ||
820 | snd_pcm_group_for_each_entry(s, substream) { | 841 | snd_pcm_group_for_each_entry(s, substream) { |
@@ -826,30 +847,63 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
826 | 847 | ||
827 | ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; | 848 | ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; |
828 | 849 | ||
829 | if (xfercount && (on_card_bytes <= ds->period_bytes)) { | 850 | if (xfercount && |
830 | if (card->support_mmap) { | 851 | /* Limit use of on card fifo for playback */ |
831 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 852 | ((on_card_bytes <= ds->period_bytes) || |
832 | snd_printddd("P%d write x%04x\n", | 853 | (s->stream == SNDRV_PCM_STREAM_CAPTURE))) |
854 | |||
855 | { | ||
856 | |||
857 | unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes; | ||
858 | unsigned int xfer1, xfer2; | ||
859 | char *pd = &s->runtime->dma_area[buf_ofs]; | ||
860 | |||
861 | if (card->can_dma) { /* buffer wrap is handled at lower level */ | ||
862 | xfer1 = xfercount; | ||
863 | xfer2 = 0; | ||
864 | } else { | ||
865 | xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs); | ||
866 | xfer2 = xfercount - xfer1; | ||
867 | } | ||
868 | |||
869 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
870 | snd_printddd("P%d write1 0x%04X 0x%04X\n", | ||
871 | s->number, xfer1, buf_ofs); | ||
872 | hpi_handle_error( | ||
873 | hpi_outstream_write_buf( | ||
874 | ds->h_stream, pd, xfer1, | ||
875 | &ds->format)); | ||
876 | |||
877 | if (xfer2) { | ||
878 | pd = s->runtime->dma_area; | ||
879 | |||
880 | snd_printddd("P%d write2 0x%04X 0x%04X\n", | ||
833 | s->number, | 881 | s->number, |
834 | ds->period_bytes); | 882 | xfercount - xfer1, buf_ofs); |
835 | hpi_handle_error( | 883 | hpi_handle_error( |
836 | hpi_outstream_write_buf( | 884 | hpi_outstream_write_buf( |
837 | ds->h_stream, | 885 | ds->h_stream, pd, |
838 | &s->runtime-> | 886 | xfercount - xfer1, |
839 | dma_area[0], | ||
840 | xfercount, | ||
841 | &ds->format)); | 887 | &ds->format)); |
842 | } else { | 888 | } |
843 | snd_printddd("C%d read x%04x\n", | 889 | } else { |
844 | s->number, | 890 | snd_printddd("C%d read1 0x%04x\n", |
845 | xfercount); | 891 | s->number, xfer1); |
892 | hpi_handle_error( | ||
893 | hpi_instream_read_buf( | ||
894 | ds->h_stream, | ||
895 | pd, xfer1)); | ||
896 | if (xfer2) { | ||
897 | pd = s->runtime->dma_area; | ||
898 | snd_printddd("C%d read2 0x%04x\n", | ||
899 | s->number, xfer2); | ||
846 | hpi_handle_error( | 900 | hpi_handle_error( |
847 | hpi_instream_read_buf( | 901 | hpi_instream_read_buf( |
848 | ds->h_stream, | 902 | ds->h_stream, |
849 | NULL, xfercount)); | 903 | pd, xfer2)); |
850 | } | 904 | } |
851 | ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; | 905 | } |
852 | } /* else R/W will be handled by read/write callbacks */ | 906 | ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; |
853 | ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; | 907 | ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; |
854 | snd_pcm_period_elapsed(s); | 908 | snd_pcm_period_elapsed(s); |
855 | } | 909 | } |
@@ -863,7 +917,7 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
863 | static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, | 917 | static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, |
864 | unsigned int cmd, void *arg) | 918 | unsigned int cmd, void *arg) |
865 | { | 919 | { |
866 | snd_printdd(KERN_INFO "Playback ioctl %d\n", cmd); | 920 | snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd); |
867 | return snd_pcm_lib_ioctl(substream, cmd, arg); | 921 | return snd_pcm_lib_ioctl(substream, cmd, arg); |
868 | } | 922 | } |
869 | 923 | ||
@@ -873,7 +927,7 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * | |||
873 | struct snd_pcm_runtime *runtime = substream->runtime; | 927 | struct snd_pcm_runtime *runtime = substream->runtime; |
874 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 928 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
875 | 929 | ||
876 | snd_printdd("playback prepare %d\n", substream->number); | 930 | snd_printdd("P%d prepare\n", substream->number); |
877 | 931 | ||
878 | hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); | 932 | hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); |
879 | dpcm->pcm_buf_host_rw_ofs = 0; | 933 | dpcm->pcm_buf_host_rw_ofs = 0; |
@@ -890,7 +944,7 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) | |||
890 | snd_pcm_uframes_t ptr; | 944 | snd_pcm_uframes_t ptr; |
891 | 945 | ||
892 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); | 946 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); |
893 | snd_printddd("playback_pointer=x%04lx\n", (unsigned long)ptr); | 947 | snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr); |
894 | return ptr; | 948 | return ptr; |
895 | } | 949 | } |
896 | 950 | ||
@@ -986,11 +1040,9 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
986 | SNDRV_PCM_INFO_DOUBLE | | 1040 | SNDRV_PCM_INFO_DOUBLE | |
987 | SNDRV_PCM_INFO_BATCH | | 1041 | SNDRV_PCM_INFO_BATCH | |
988 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1042 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
989 | SNDRV_PCM_INFO_PAUSE; | 1043 | SNDRV_PCM_INFO_PAUSE | |
990 | 1044 | SNDRV_PCM_INFO_MMAP | | |
991 | if (card->support_mmap) | 1045 | SNDRV_PCM_INFO_MMAP_VALID; |
992 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_MMAP | | ||
993 | SNDRV_PCM_INFO_MMAP_VALID; | ||
994 | 1046 | ||
995 | if (card->support_grouping) | 1047 | if (card->support_grouping) |
996 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; | 1048 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; |
@@ -998,7 +1050,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
998 | /* struct is copied, so can create initializer dynamically */ | 1050 | /* struct is copied, so can create initializer dynamically */ |
999 | runtime->hw = snd_card_asihpi_playback; | 1051 | runtime->hw = snd_card_asihpi_playback; |
1000 | 1052 | ||
1001 | if (card->support_mmap) | 1053 | if (card->can_dma) |
1002 | err = snd_pcm_hw_constraint_pow2(runtime, 0, | 1054 | err = snd_pcm_hw_constraint_pow2(runtime, 0, |
1003 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); | 1055 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); |
1004 | if (err < 0) | 1056 | if (err < 0) |
@@ -1028,58 +1080,6 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) | |||
1028 | return 0; | 1080 | return 0; |
1029 | } | 1081 | } |
1030 | 1082 | ||
1031 | static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream, | ||
1032 | int channel, | ||
1033 | snd_pcm_uframes_t pos, | ||
1034 | void __user *src, | ||
1035 | snd_pcm_uframes_t count) | ||
1036 | { | ||
1037 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1038 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
1039 | unsigned int len; | ||
1040 | |||
1041 | len = frames_to_bytes(runtime, count); | ||
1042 | |||
1043 | if (copy_from_user(runtime->dma_area, src, len)) | ||
1044 | return -EFAULT; | ||
1045 | |||
1046 | snd_printddd("playback copy%d %u bytes\n", | ||
1047 | substream->number, len); | ||
1048 | |||
1049 | hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream, | ||
1050 | runtime->dma_area, len, &dpcm->format)); | ||
1051 | |||
1052 | dpcm->pcm_buf_host_rw_ofs += len; | ||
1053 | |||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | static int snd_card_asihpi_playback_silence(struct snd_pcm_substream * | ||
1058 | substream, int channel, | ||
1059 | snd_pcm_uframes_t pos, | ||
1060 | snd_pcm_uframes_t count) | ||
1061 | { | ||
1062 | /* Usually writes silence to DMA buffer, which should be overwritten | ||
1063 | by real audio later. Our fifos cannot be overwritten, and are not | ||
1064 | free-running DMAs. Silence is output on fifo underflow. | ||
1065 | This callback is still required to allow the copy callback to be used. | ||
1066 | */ | ||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1070 | static struct snd_pcm_ops snd_card_asihpi_playback_ops = { | ||
1071 | .open = snd_card_asihpi_playback_open, | ||
1072 | .close = snd_card_asihpi_playback_close, | ||
1073 | .ioctl = snd_card_asihpi_playback_ioctl, | ||
1074 | .hw_params = snd_card_asihpi_pcm_hw_params, | ||
1075 | .hw_free = snd_card_asihpi_hw_free, | ||
1076 | .prepare = snd_card_asihpi_playback_prepare, | ||
1077 | .trigger = snd_card_asihpi_trigger, | ||
1078 | .pointer = snd_card_asihpi_playback_pointer, | ||
1079 | .copy = snd_card_asihpi_playback_copy, | ||
1080 | .silence = snd_card_asihpi_playback_silence, | ||
1081 | }; | ||
1082 | |||
1083 | static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { | 1083 | static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { |
1084 | .open = snd_card_asihpi_playback_open, | 1084 | .open = snd_card_asihpi_playback_open, |
1085 | .close = snd_card_asihpi_playback_close, | 1085 | .close = snd_card_asihpi_playback_close, |
@@ -1211,18 +1211,16 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1211 | snd_card_asihpi_capture_format(card, dpcm->h_stream, | 1211 | snd_card_asihpi_capture_format(card, dpcm->h_stream, |
1212 | &snd_card_asihpi_capture); | 1212 | &snd_card_asihpi_capture); |
1213 | snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); | 1213 | snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); |
1214 | snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED; | 1214 | snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED | |
1215 | 1215 | SNDRV_PCM_INFO_MMAP | | |
1216 | if (card->support_mmap) | 1216 | SNDRV_PCM_INFO_MMAP_VALID; |
1217 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP | | ||
1218 | SNDRV_PCM_INFO_MMAP_VALID; | ||
1219 | 1217 | ||
1220 | if (card->support_grouping) | 1218 | if (card->support_grouping) |
1221 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; | 1219 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; |
1222 | 1220 | ||
1223 | runtime->hw = snd_card_asihpi_capture; | 1221 | runtime->hw = snd_card_asihpi_capture; |
1224 | 1222 | ||
1225 | if (card->support_mmap) | 1223 | if (card->can_dma) |
1226 | err = snd_pcm_hw_constraint_pow2(runtime, 0, | 1224 | err = snd_pcm_hw_constraint_pow2(runtime, 0, |
1227 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); | 1225 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); |
1228 | if (err < 0) | 1226 | if (err < 0) |
@@ -1246,28 +1244,6 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) | |||
1246 | return 0; | 1244 | return 0; |
1247 | } | 1245 | } |
1248 | 1246 | ||
1249 | static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream, | ||
1250 | int channel, snd_pcm_uframes_t pos, | ||
1251 | void __user *dst, snd_pcm_uframes_t count) | ||
1252 | { | ||
1253 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1254 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
1255 | u32 len; | ||
1256 | |||
1257 | len = frames_to_bytes(runtime, count); | ||
1258 | |||
1259 | snd_printddd("capture copy%d %d bytes\n", substream->number, len); | ||
1260 | hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream, | ||
1261 | runtime->dma_area, len)); | ||
1262 | |||
1263 | dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len; | ||
1264 | |||
1265 | if (copy_to_user(dst, runtime->dma_area, len)) | ||
1266 | return -EFAULT; | ||
1267 | |||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { | 1247 | static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { |
1272 | .open = snd_card_asihpi_capture_open, | 1248 | .open = snd_card_asihpi_capture_open, |
1273 | .close = snd_card_asihpi_capture_close, | 1249 | .close = snd_card_asihpi_capture_close, |
@@ -1279,18 +1255,6 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { | |||
1279 | .pointer = snd_card_asihpi_capture_pointer, | 1255 | .pointer = snd_card_asihpi_capture_pointer, |
1280 | }; | 1256 | }; |
1281 | 1257 | ||
1282 | static struct snd_pcm_ops snd_card_asihpi_capture_ops = { | ||
1283 | .open = snd_card_asihpi_capture_open, | ||
1284 | .close = snd_card_asihpi_capture_close, | ||
1285 | .ioctl = snd_card_asihpi_capture_ioctl, | ||
1286 | .hw_params = snd_card_asihpi_pcm_hw_params, | ||
1287 | .hw_free = snd_card_asihpi_hw_free, | ||
1288 | .prepare = snd_card_asihpi_capture_prepare, | ||
1289 | .trigger = snd_card_asihpi_trigger, | ||
1290 | .pointer = snd_card_asihpi_capture_pointer, | ||
1291 | .copy = snd_card_asihpi_capture_copy | ||
1292 | }; | ||
1293 | |||
1294 | static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, | 1258 | static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, |
1295 | int device, int substreams) | 1259 | int device, int substreams) |
1296 | { | 1260 | { |
@@ -1303,17 +1267,10 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, | |||
1303 | if (err < 0) | 1267 | if (err < 0) |
1304 | return err; | 1268 | return err; |
1305 | /* pointer to ops struct is stored, dont change ops afterwards! */ | 1269 | /* pointer to ops struct is stored, dont change ops afterwards! */ |
1306 | if (asihpi->support_mmap) { | ||
1307 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1270 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1308 | &snd_card_asihpi_playback_mmap_ops); | 1271 | &snd_card_asihpi_playback_mmap_ops); |
1309 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 1272 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
1310 | &snd_card_asihpi_capture_mmap_ops); | 1273 | &snd_card_asihpi_capture_mmap_ops); |
1311 | } else { | ||
1312 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1313 | &snd_card_asihpi_playback_ops); | ||
1314 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
1315 | &snd_card_asihpi_capture_ops); | ||
1316 | } | ||
1317 | 1274 | ||
1318 | pcm->private_data = asihpi; | 1275 | pcm->private_data = asihpi; |
1319 | pcm->info_flags = 0; | 1276 | pcm->info_flags = 0; |
@@ -1413,14 +1370,16 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, | |||
1413 | struct hpi_control *hpi_ctl, | 1370 | struct hpi_control *hpi_ctl, |
1414 | char *name) | 1371 | char *name) |
1415 | { | 1372 | { |
1416 | char *dir = ""; | 1373 | char *dir; |
1417 | memset(snd_control, 0, sizeof(*snd_control)); | 1374 | memset(snd_control, 0, sizeof(*snd_control)); |
1418 | snd_control->name = hpi_ctl->name; | 1375 | snd_control->name = hpi_ctl->name; |
1419 | snd_control->private_value = hpi_ctl->h_control; | 1376 | snd_control->private_value = hpi_ctl->h_control; |
1420 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1377 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1421 | snd_control->index = 0; | 1378 | snd_control->index = 0; |
1422 | 1379 | ||
1423 | if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) | 1380 | if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE) |
1381 | dir = ""; /* clock is neither capture nor playback */ | ||
1382 | else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) | ||
1424 | dir = "Capture "; /* On or towards a PCM capture destination*/ | 1383 | dir = "Capture "; /* On or towards a PCM capture destination*/ |
1425 | else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && | 1384 | else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && |
1426 | (!hpi_ctl->dst_node_type)) | 1385 | (!hpi_ctl->dst_node_type)) |
@@ -1433,7 +1392,7 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, | |||
1433 | dir = "Playback "; /* PCM Playback source, or output node */ | 1392 | dir = "Playback "; /* PCM Playback source, or output node */ |
1434 | 1393 | ||
1435 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) | 1394 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) |
1436 | sprintf(hpi_ctl->name, "%s%d %s%d %s%s", | 1395 | sprintf(hpi_ctl->name, "%s %d %s %d %s%s", |
1437 | asihpi_src_names[hpi_ctl->src_node_type], | 1396 | asihpi_src_names[hpi_ctl->src_node_type], |
1438 | hpi_ctl->src_node_index, | 1397 | hpi_ctl->src_node_index, |
1439 | asihpi_dst_names[hpi_ctl->dst_node_type], | 1398 | asihpi_dst_names[hpi_ctl->dst_node_type], |
@@ -2875,14 +2834,14 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2875 | if (err) | 2834 | if (err) |
2876 | asihpi->update_interval_frames = 512; | 2835 | asihpi->update_interval_frames = 512; |
2877 | 2836 | ||
2878 | if (!asihpi->support_mmap) | 2837 | if (!asihpi->can_dma) |
2879 | asihpi->update_interval_frames *= 2; | 2838 | asihpi->update_interval_frames *= 2; |
2880 | 2839 | ||
2881 | hpi_handle_error(hpi_instream_open(asihpi->adapter_index, | 2840 | hpi_handle_error(hpi_instream_open(asihpi->adapter_index, |
2882 | 0, &h_stream)); | 2841 | 0, &h_stream)); |
2883 | 2842 | ||
2884 | err = hpi_instream_host_buffer_free(h_stream); | 2843 | err = hpi_instream_host_buffer_free(h_stream); |
2885 | asihpi->support_mmap = (!err); | 2844 | asihpi->can_dma = (!err); |
2886 | 2845 | ||
2887 | hpi_handle_error(hpi_instream_close(h_stream)); | 2846 | hpi_handle_error(hpi_instream_close(h_stream)); |
2888 | 2847 | ||
@@ -2894,8 +2853,8 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2894 | asihpi->out_max_chans = 2; | 2853 | asihpi->out_max_chans = 2; |
2895 | } | 2854 | } |
2896 | 2855 | ||
2897 | snd_printk(KERN_INFO "supports mmap:%d grouping:%d mrx:%d\n", | 2856 | snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n", |
2898 | asihpi->support_mmap, | 2857 | asihpi->can_dma, |
2899 | asihpi->support_grouping, | 2858 | asihpi->support_grouping, |
2900 | asihpi->support_mrx | 2859 | asihpi->support_mrx |
2901 | ); | 2860 | ); |
@@ -2925,10 +2884,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2925 | by enable_hwdep module param*/ | 2884 | by enable_hwdep module param*/ |
2926 | snd_asihpi_hpi_new(asihpi, 0, NULL); | 2885 | snd_asihpi_hpi_new(asihpi, 0, NULL); |
2927 | 2886 | ||
2928 | if (asihpi->support_mmap) | 2887 | strcpy(card->driver, "ASIHPI"); |
2929 | strcpy(card->driver, "ASIHPI-MMAP"); | ||
2930 | else | ||
2931 | strcpy(card->driver, "ASIHPI"); | ||
2932 | 2888 | ||
2933 | sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); | 2889 | sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); |
2934 | sprintf(card->longname, "%s %i", | 2890 | sprintf(card->longname, "%s %i", |
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 8c8aac4c567e..df4aed5295dd 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c | |||
@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, | |||
200 | static void subsys_create_adapter(struct hpi_message *phm, | 200 | static void subsys_create_adapter(struct hpi_message *phm, |
201 | struct hpi_response *phr); | 201 | struct hpi_response *phr); |
202 | 202 | ||
203 | static void subsys_delete_adapter(struct hpi_message *phm, | 203 | static void adapter_delete(struct hpi_adapter_obj *pao, |
204 | struct hpi_response *phr); | 204 | struct hpi_message *phm, struct hpi_response *phr); |
205 | 205 | ||
206 | static void adapter_get_asserts(struct hpi_adapter_obj *pao, | 206 | static void adapter_get_asserts(struct hpi_adapter_obj *pao, |
207 | struct hpi_message *phm, struct hpi_response *phr); | 207 | struct hpi_message *phm, struct hpi_response *phr); |
@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | |||
222 | case HPI_SUBSYS_CREATE_ADAPTER: | 222 | case HPI_SUBSYS_CREATE_ADAPTER: |
223 | subsys_create_adapter(phm, phr); | 223 | subsys_create_adapter(phm, phr); |
224 | break; | 224 | break; |
225 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
226 | subsys_delete_adapter(phm, phr); | ||
227 | break; | ||
228 | default: | 225 | default: |
229 | phr->error = HPI_ERROR_INVALID_FUNC; | 226 | phr->error = HPI_ERROR_INVALID_FUNC; |
230 | break; | 227 | break; |
@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao, | |||
279 | adapter_get_asserts(pao, phm, phr); | 276 | adapter_get_asserts(pao, phm, phr); |
280 | break; | 277 | break; |
281 | 278 | ||
279 | case HPI_ADAPTER_DELETE: | ||
280 | adapter_delete(pao, phm, phr); | ||
281 | break; | ||
282 | |||
282 | default: | 283 | default: |
283 | hw_message(pao, phm, phr); | 284 | hw_message(pao, phm, phr); |
284 | break; | 285 | break; |
@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) | |||
333 | { | 334 | { |
334 | struct hpi_adapter_obj *pao = NULL; | 335 | struct hpi_adapter_obj *pao = NULL; |
335 | 336 | ||
336 | /* subsytem messages get executed by every HPI. */ | ||
337 | /* All other messages are ignored unless the adapter index matches */ | ||
338 | /* an adapter in the HPI */ | ||
339 | /*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */ | ||
340 | |||
341 | /* if Dsp has crashed then do not communicate with it any more */ | ||
342 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | 337 | if (phm->object != HPI_OBJ_SUBSYSTEM) { |
343 | pao = hpi_find_adapter(phm->adapter_index); | 338 | pao = hpi_find_adapter(phm->adapter_index); |
344 | if (!pao) { | 339 | if (!pao) { |
345 | HPI_DEBUG_LOG(DEBUG, | 340 | hpi_init_response(phr, phm->object, phm->function, |
346 | " %d,%d refused, for another HPI?\n", | 341 | HPI_ERROR_BAD_ADAPTER_NUMBER); |
347 | phm->object, phm->function); | 342 | HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n", |
343 | phm->adapter_index); | ||
348 | return; | 344 | return; |
349 | } | 345 | } |
350 | 346 | ||
347 | /* Don't even try to communicate with crashed DSP */ | ||
351 | if (pao->dsp_crashed >= 10) { | 348 | if (pao->dsp_crashed >= 10) { |
352 | hpi_init_response(phr, phm->object, phm->function, | 349 | hpi_init_response(phr, phm->object, phm->function, |
353 | HPI_ERROR_DSP_HARDWARE); | 350 | HPI_ERROR_DSP_HARDWARE); |
354 | HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n", | 351 | HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n", |
355 | phm->object, phm->function); | 352 | phm->adapter_index); |
356 | return; | 353 | return; |
357 | } | 354 | } |
358 | } | 355 | } |
@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
463 | phr->error = 0; | 460 | phr->error = 0; |
464 | } | 461 | } |
465 | 462 | ||
466 | static void subsys_delete_adapter(struct hpi_message *phm, | 463 | static void adapter_delete(struct hpi_adapter_obj *pao, |
467 | struct hpi_response *phr) | 464 | struct hpi_message *phm, struct hpi_response *phr) |
468 | { | 465 | { |
469 | struct hpi_adapter_obj *pao = NULL; | ||
470 | |||
471 | pao = hpi_find_adapter(phm->obj_index); | ||
472 | if (!pao) | ||
473 | return; | ||
474 | |||
475 | delete_adapter_obj(pao); | 466 | delete_adapter_obj(pao); |
476 | hpi_delete_adapter(pao); | 467 | hpi_delete_adapter(pao); |
477 | phr->error = 0; | 468 | phr->error = 0; |
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 22e9f08dea6d..9d5df54a6b46 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c | |||
@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
152 | 152 | ||
153 | static void subsys_create_adapter(struct hpi_message *phm, | 153 | static void subsys_create_adapter(struct hpi_message *phm, |
154 | struct hpi_response *phr); | 154 | struct hpi_response *phr); |
155 | static void subsys_delete_adapter(struct hpi_message *phm, | 155 | static void adapter_delete(struct hpi_adapter_obj *pao, |
156 | struct hpi_response *phr); | 156 | struct hpi_message *phm, struct hpi_response *phr); |
157 | 157 | ||
158 | static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | 158 | static u16 create_adapter_obj(struct hpi_adapter_obj *pao, |
159 | u32 *pos_error_code); | 159 | u32 *pos_error_code); |
@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index); | |||
223 | 223 | ||
224 | /*****************************************************************************/ | 224 | /*****************************************************************************/ |
225 | 225 | ||
226 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 226 | static void subsys_message(struct hpi_adapter_obj *pao, |
227 | struct hpi_message *phm, struct hpi_response *phr) | ||
227 | { | 228 | { |
228 | switch (phm->function) { | 229 | switch (phm->function) { |
229 | case HPI_SUBSYS_CREATE_ADAPTER: | 230 | case HPI_SUBSYS_CREATE_ADAPTER: |
230 | subsys_create_adapter(phm, phr); | 231 | subsys_create_adapter(phm, phr); |
231 | break; | 232 | break; |
232 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
233 | subsys_delete_adapter(phm, phr); | ||
234 | break; | ||
235 | default: | 233 | default: |
236 | phr->error = HPI_ERROR_INVALID_FUNC; | 234 | phr->error = HPI_ERROR_INVALID_FUNC; |
237 | break; | 235 | break; |
@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao, | |||
279 | struct hpi_message *phm, struct hpi_response *phr) | 277 | struct hpi_message *phm, struct hpi_response *phr) |
280 | { | 278 | { |
281 | switch (phm->function) { | 279 | switch (phm->function) { |
280 | case HPI_ADAPTER_DELETE: | ||
281 | adapter_delete(pao, phm, phr); | ||
282 | break; | ||
283 | |||
282 | default: | 284 | default: |
283 | hw_message(pao, phm, phr); | 285 | hw_message(pao, phm, phr); |
284 | break; | 286 | break; |
@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao, | |||
371 | /** Entry point to this HPI backend | 373 | /** Entry point to this HPI backend |
372 | * All calls to the HPI start here | 374 | * All calls to the HPI start here |
373 | */ | 375 | */ |
374 | void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | 376 | void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, |
377 | struct hpi_response *phr) | ||
375 | { | 378 | { |
376 | struct hpi_adapter_obj *pao = NULL; | 379 | if (pao && (pao->dsp_crashed >= 10) |
377 | 380 | && (phm->function != HPI_ADAPTER_DEBUG_READ)) { | |
378 | /* subsytem messages are processed by every HPI. | 381 | /* allow last resort debug read even after crash */ |
379 | * All other messages are ignored unless the adapter index matches | 382 | hpi_init_response(phr, phm->object, phm->function, |
380 | * an adapter in the HPI | 383 | HPI_ERROR_DSP_HARDWARE); |
381 | */ | 384 | HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object, |
382 | /* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject, | 385 | phm->function); |
383 | phm->wFunction); */ | 386 | return; |
384 | |||
385 | /* if Dsp has crashed then do not communicate with it any more */ | ||
386 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | ||
387 | pao = hpi_find_adapter(phm->adapter_index); | ||
388 | if (!pao) { | ||
389 | HPI_DEBUG_LOG(DEBUG, | ||
390 | " %d,%d refused, for another HPI?\n", | ||
391 | phm->object, phm->function); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | if ((pao->dsp_crashed >= 10) | ||
396 | && (phm->function != HPI_ADAPTER_DEBUG_READ)) { | ||
397 | /* allow last resort debug read even after crash */ | ||
398 | hpi_init_response(phr, phm->object, phm->function, | ||
399 | HPI_ERROR_DSP_HARDWARE); | ||
400 | HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", | ||
401 | phm->object, phm->function); | ||
402 | return; | ||
403 | } | ||
404 | } | 387 | } |
405 | 388 | ||
406 | /* Init default response */ | 389 | /* Init default response */ |
@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | |||
412 | case HPI_TYPE_MESSAGE: | 395 | case HPI_TYPE_MESSAGE: |
413 | switch (phm->object) { | 396 | switch (phm->object) { |
414 | case HPI_OBJ_SUBSYSTEM: | 397 | case HPI_OBJ_SUBSYSTEM: |
415 | subsys_message(phm, phr); | 398 | subsys_message(pao, phm, phr); |
416 | break; | 399 | break; |
417 | 400 | ||
418 | case HPI_OBJ_ADAPTER: | 401 | case HPI_OBJ_ADAPTER: |
@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | |||
444 | } | 427 | } |
445 | } | 428 | } |
446 | 429 | ||
430 | void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | ||
431 | { | ||
432 | struct hpi_adapter_obj *pao = NULL; | ||
433 | |||
434 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | ||
435 | /* normal messages must have valid adapter index */ | ||
436 | pao = hpi_find_adapter(phm->adapter_index); | ||
437 | } else { | ||
438 | /* subsys messages don't address an adapter */ | ||
439 | _HPI_6205(NULL, phm, phr); | ||
440 | return; | ||
441 | } | ||
442 | |||
443 | if (pao) | ||
444 | _HPI_6205(pao, phm, phr); | ||
445 | else | ||
446 | hpi_init_response(phr, phm->object, phm->function, | ||
447 | HPI_ERROR_BAD_ADAPTER_NUMBER); | ||
448 | } | ||
449 | |||
447 | /*****************************************************************************/ | 450 | /*****************************************************************************/ |
448 | /* SUBSYSTEM */ | 451 | /* SUBSYSTEM */ |
449 | 452 | ||
@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
491 | } | 494 | } |
492 | 495 | ||
493 | /** delete an adapter - required by WDM driver */ | 496 | /** delete an adapter - required by WDM driver */ |
494 | static void subsys_delete_adapter(struct hpi_message *phm, | 497 | static void adapter_delete(struct hpi_adapter_obj *pao, |
495 | struct hpi_response *phr) | 498 | struct hpi_message *phm, struct hpi_response *phr) |
496 | { | 499 | { |
497 | struct hpi_adapter_obj *pao; | ||
498 | struct hpi_hw_obj *phw; | 500 | struct hpi_hw_obj *phw; |
499 | 501 | ||
500 | pao = hpi_find_adapter(phm->obj_index); | ||
501 | if (!pao) { | 502 | if (!pao) { |
502 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; | 503 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; |
503 | return; | 504 | return; |
@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
563 | } | 564 | } |
564 | 565 | ||
565 | err = adapter_boot_load_dsp(pao, pos_error_code); | 566 | err = adapter_boot_load_dsp(pao, pos_error_code); |
566 | if (err) | 567 | if (err) { |
568 | HPI_DEBUG_LOG(ERROR, "DSP code load failed\n"); | ||
567 | /* no need to clean up as SubSysCreateAdapter */ | 569 | /* no need to clean up as SubSysCreateAdapter */ |
568 | /* calls DeleteAdapter on error. */ | 570 | /* calls DeleteAdapter on error. */ |
569 | return err; | 571 | return err; |
570 | 572 | } | |
571 | HPI_DEBUG_LOG(INFO, "load DSP code OK\n"); | 573 | HPI_DEBUG_LOG(INFO, "load DSP code OK\n"); |
572 | 574 | ||
573 | /* allow boot load even if mem alloc wont work */ | 575 | /* allow boot load even if mem alloc wont work */ |
@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
604 | control_cache.number_of_controls, | 606 | control_cache.number_of_controls, |
605 | interface->control_cache.size_in_bytes, | 607 | interface->control_cache.size_in_bytes, |
606 | p_control_cache_virtual); | 608 | p_control_cache_virtual); |
609 | |||
607 | if (!phw->p_cache) | 610 | if (!phw->p_cache) |
608 | err = HPI_ERROR_MEMORY_ALLOC; | 611 | err = HPI_ERROR_MEMORY_ALLOC; |
609 | } | 612 | } |
@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
675 | } | 678 | } |
676 | 679 | ||
677 | /** Free memory areas allocated by adapter | 680 | /** Free memory areas allocated by adapter |
678 | * this routine is called from SubSysDeleteAdapter, | 681 | * this routine is called from AdapterDelete, |
679 | * and SubSysCreateAdapter if duplicate index | 682 | * and SubSysCreateAdapter if duplicate index |
680 | */ | 683 | */ |
681 | static void delete_adapter_obj(struct hpi_adapter_obj *pao) | 684 | static void delete_adapter_obj(struct hpi_adapter_obj *pao) |
682 | { | 685 | { |
683 | struct hpi_hw_obj *phw; | 686 | struct hpi_hw_obj *phw = pao->priv; |
684 | int i; | 687 | int i; |
685 | 688 | ||
686 | phw = pao->priv; | ||
687 | |||
688 | if (hpios_locked_mem_valid(&phw->h_control_cache)) { | 689 | if (hpios_locked_mem_valid(&phw->h_control_cache)) { |
689 | hpios_locked_mem_free(&phw->h_control_cache); | 690 | hpios_locked_mem_free(&phw->h_control_cache); |
690 | hpi_free_control_cache(phw->p_cache); | 691 | hpi_free_control_cache(phw->p_cache); |
@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1275 | case HPI_ADAPTER_FAMILY_ASI(0x6300): | 1276 | case HPI_ADAPTER_FAMILY_ASI(0x6300): |
1276 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); | 1277 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); |
1277 | break; | 1278 | break; |
1279 | case HPI_ADAPTER_FAMILY_ASI(0x5500): | ||
1278 | case HPI_ADAPTER_FAMILY_ASI(0x5600): | 1280 | case HPI_ADAPTER_FAMILY_ASI(0x5600): |
1279 | case HPI_ADAPTER_FAMILY_ASI(0x6500): | 1281 | case HPI_ADAPTER_FAMILY_ASI(0x6500): |
1280 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); | 1282 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); |
@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us) | |||
2059 | static void send_dsp_command(struct hpi_hw_obj *phw, int cmd) | 2061 | static void send_dsp_command(struct hpi_hw_obj *phw, int cmd) |
2060 | { | 2062 | { |
2061 | struct bus_master_interface *interface = phw->p_interface_buffer; | 2063 | struct bus_master_interface *interface = phw->p_interface_buffer; |
2062 | |||
2063 | u32 r; | 2064 | u32 r; |
2064 | 2065 | ||
2065 | interface->host_cmd = cmd; | 2066 | interface->host_cmd = cmd; |
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index 3b9fd115da36..bf5eced76bac 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h | |||
@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES { | |||
294 | 294 | ||
295 | /* These defines are used to fill in protocol information for an Ethernet packet | 295 | /* These defines are used to fill in protocol information for an Ethernet packet |
296 | sent using HMI on CS18102 */ | 296 | sent using HMI on CS18102 */ |
297 | /** ID supplied by Cirrius for ASI packets. */ | 297 | /** ID supplied by Cirrus for ASI packets. */ |
298 | #define HPI_ETHERNET_PACKET_ID 0x85 | 298 | #define HPI_ETHERNET_PACKET_ID 0x85 |
299 | /** Simple packet - no special routing required */ | 299 | /** Simple packet - no special routing required */ |
300 | #define HPI_ETHERNET_PACKET_V1 0x01 | 300 | #define HPI_ETHERNET_PACKET_V1 0x01 |
@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES { | |||
307 | /** This packet must make its way to the host across the HPI interface */ | 307 | /** This packet must make its way to the host across the HPI interface */ |
308 | #define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41 | 308 | #define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41 |
309 | 309 | ||
310 | #define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */ | 310 | #define HPI_ETHERNET_UDP_PORT 44600 /**< HPI UDP service */ |
311 | 311 | ||
312 | /** Default network timeout in milli-seconds. */ | 312 | /** Default network timeout in milli-seconds. */ |
313 | #define HPI_ETHERNET_TIMEOUT_MS 500 | 313 | #define HPI_ETHERNET_TIMEOUT_MS 500 |
@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS { | |||
397 | HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1), | 397 | HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1), |
398 | HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2), | 398 | HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2), |
399 | HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3), | 399 | HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3), |
400 | HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), | 400 | /* HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), */ |
401 | HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5), | 401 | HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5), |
402 | HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6), | 402 | HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6), |
403 | HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), | 403 | /* HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), */ |
404 | HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8), | 404 | HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8), |
405 | HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9), | 405 | HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9), |
406 | HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), | 406 | /* HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), */ |
407 | HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), | 407 | /* HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), */ |
408 | HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12), | 408 | HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12), |
409 | HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13), | 409 | HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13), |
410 | HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14), | 410 | HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14), |
@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS { | |||
433 | HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18), | 433 | HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18), |
434 | HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19), | 434 | HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19), |
435 | HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20), | 435 | HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20), |
436 | #define HPI_ADAPTER_FUNCTION_COUNT 20 | 436 | HPI_ADAPTER_DELETE = HPI_FUNC_ID(ADAPTER, 21), |
437 | #define HPI_ADAPTER_FUNCTION_COUNT 21 | ||
437 | 438 | ||
438 | HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1), | 439 | HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1), |
439 | HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2), | 440 | HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2), |
@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); | |||
1561 | u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, | 1562 | u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, |
1562 | u16 *pw_adapter_index); | 1563 | u16 *pw_adapter_index); |
1563 | 1564 | ||
1564 | u16 hpi_subsys_delete_adapter(u16 adapter_index); | ||
1565 | |||
1566 | u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, | 1565 | u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, |
1567 | struct hpi_hostbuffer_status **pp_status); | 1566 | struct hpi_hostbuffer_status **pp_status); |
1568 | 1567 | ||
@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR); | |||
1584 | 1583 | ||
1585 | /*////////////////////////////////////////////////////////////////////////// */ | 1584 | /*////////////////////////////////////////////////////////////////////////// */ |
1586 | /* declarations for individual HPI entry points */ | 1585 | /* declarations for individual HPI entry points */ |
1587 | hpi_handler_func HPI_1000; | ||
1588 | hpi_handler_func HPI_6000; | 1586 | hpi_handler_func HPI_6000; |
1589 | hpi_handler_func HPI_6205; | 1587 | hpi_handler_func HPI_6205; |
1590 | hpi_handler_func HPI_COMMON; | ||
1591 | 1588 | ||
1592 | #endif /* _HPI_INTERNAL_H_ */ | 1589 | #endif /* _HPI_INTERNAL_H_ */ |
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index 3e9c5c289764..b15a02e91f82 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c | |||
@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) | |||
227 | if (info->control_type) { | 227 | if (info->control_type) { |
228 | pC->p_info[info->control_index] = info; | 228 | pC->p_info[info->control_index] = info; |
229 | cached++; | 229 | cached++; |
230 | } else /* dummy cache entry */ | 230 | } else { /* dummy cache entry */ |
231 | pC->p_info[info->control_index] = NULL; | 231 | pC->p_info[info->control_index] = NULL; |
232 | } | ||
232 | 233 | ||
233 | byte_count += info->size_in32bit_words * 4; | 234 | byte_count += info->size_in32bit_words * 4; |
234 | 235 | ||
@@ -298,7 +299,7 @@ struct pad_ofs_size { | |||
298 | unsigned int field_size; | 299 | unsigned int field_size; |
299 | }; | 300 | }; |
300 | 301 | ||
301 | static struct pad_ofs_size pad_desc[] = { | 302 | static const struct pad_ofs_size pad_desc[] = { |
302 | HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ | 303 | HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ |
303 | HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ | 304 | HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ |
304 | HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ | 305 | HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ |
@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, | |||
617 | } | 618 | } |
618 | } | 619 | } |
619 | 620 | ||
621 | /** Allocate control cache. | ||
622 | |||
623 | \return Cache pointer, or NULL if allocation fails. | ||
624 | */ | ||
620 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, | 625 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, |
621 | const u32 size_in_bytes, u8 *p_dsp_control_buffer) | 626 | const u32 size_in_bytes, u8 *p_dsp_control_buffer) |
622 | { | 627 | { |
@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | |||
667 | phr->u.s.num_adapters = adapters.gw_num_adapters; | 672 | phr->u.s.num_adapters = adapters.gw_num_adapters; |
668 | break; | 673 | break; |
669 | case HPI_SUBSYS_CREATE_ADAPTER: | 674 | case HPI_SUBSYS_CREATE_ADAPTER: |
670 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
671 | break; | 675 | break; |
672 | default: | 676 | default: |
673 | phr->error = HPI_ERROR_INVALID_FUNC; | 677 | phr->error = HPI_ERROR_INVALID_FUNC; |
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h index 590f0b69e655..d53cdf6e535f 100644 --- a/sound/pci/asihpi/hpicmn.h +++ b/sound/pci/asihpi/hpicmn.h | |||
@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC, | |||
60 | struct hpi_message *phm, struct hpi_response *phr); | 60 | struct hpi_message *phm, struct hpi_response *phr); |
61 | 61 | ||
62 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); | 62 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); |
63 | |||
64 | hpi_handler_func HPI_COMMON; | ||
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index c38fc9487560..7397b169b89f 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c | |||
@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex) | |||
105 | return hr.error; | 105 | return hr.error; |
106 | } | 106 | } |
107 | 107 | ||
108 | u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, | ||
109 | u16 *pw_adapter_index) | ||
110 | { | ||
111 | struct hpi_message hm; | ||
112 | struct hpi_response hr; | ||
113 | |||
114 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
115 | HPI_SUBSYS_CREATE_ADAPTER); | ||
116 | hm.u.s.resource = *p_resource; | ||
117 | |||
118 | hpi_send_recv(&hm, &hr); | ||
119 | |||
120 | *pw_adapter_index = hr.u.s.adapter_index; | ||
121 | return hr.error; | ||
122 | } | ||
123 | |||
124 | u16 hpi_subsys_delete_adapter(u16 adapter_index) | ||
125 | { | ||
126 | struct hpi_message hm; | ||
127 | struct hpi_response hr; | ||
128 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
129 | HPI_SUBSYS_DELETE_ADAPTER); | ||
130 | hm.obj_index = adapter_index; | ||
131 | hpi_send_recv(&hm, &hr); | ||
132 | return hr.error; | ||
133 | } | ||
134 | |||
135 | u16 hpi_subsys_get_num_adapters(int *pn_num_adapters) | 108 | u16 hpi_subsys_get_num_adapters(int *pn_num_adapters) |
136 | { | 109 | { |
137 | struct hpi_message hm; | 110 | struct hpi_message hm; |
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index 360028b9abf5..7352a5f7b4f7 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c | |||
@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, | |||
211 | HPIMSGX__init(phm, phr); | 211 | HPIMSGX__init(phm, phr); |
212 | break; | 212 | break; |
213 | 213 | ||
214 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
215 | HPIMSGX__cleanup(phm->obj_index, h_owner); | ||
216 | { | ||
217 | struct hpi_message hm; | ||
218 | struct hpi_response hr; | ||
219 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
220 | HPI_ADAPTER_CLOSE); | ||
221 | hm.adapter_index = phm->obj_index; | ||
222 | hw_entry_point(&hm, &hr); | ||
223 | } | ||
224 | if ((phm->obj_index < HPI_MAX_ADAPTERS) | ||
225 | && hpi_entry_points[phm->obj_index]) { | ||
226 | hpi_entry_points[phm->obj_index] (phm, phr); | ||
227 | hpi_entry_points[phm->obj_index] = NULL; | ||
228 | } else | ||
229 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; | ||
230 | |||
231 | break; | ||
232 | default: | 214 | default: |
233 | /* Must explicitly handle every subsys message in this switch */ | 215 | /* Must explicitly handle every subsys message in this switch */ |
234 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, | 216 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, |
@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr, | |||
247 | case HPI_ADAPTER_CLOSE: | 229 | case HPI_ADAPTER_CLOSE: |
248 | adapter_close(phm, phr); | 230 | adapter_close(phm, phr); |
249 | break; | 231 | break; |
232 | case HPI_ADAPTER_DELETE: | ||
233 | HPIMSGX__cleanup(phm->adapter_index, h_owner); | ||
234 | { | ||
235 | struct hpi_message hm; | ||
236 | struct hpi_response hr; | ||
237 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
238 | HPI_ADAPTER_CLOSE); | ||
239 | hm.adapter_index = phm->adapter_index; | ||
240 | hw_entry_point(&hm, &hr); | ||
241 | } | ||
242 | hw_entry_point(phm, phr); | ||
243 | break; | ||
244 | |||
250 | default: | 245 | default: |
251 | hw_entry_point(phm, phr); | 246 | hw_entry_point(phm, phr); |
252 | break; | 247 | break; |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index cd624f13ff8e..d8e7047512f8 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions | |||
25 | #include "hpidebug.h" | 25 | #include "hpidebug.h" |
26 | #include "hpimsgx.h" | 26 | #include "hpimsgx.h" |
27 | #include "hpioctl.h" | 27 | #include "hpioctl.h" |
28 | #include "hpicmn.h" | ||
28 | 29 | ||
29 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
161 | goto out; | 162 | goto out; |
162 | } | 163 | } |
163 | 164 | ||
164 | pa = &adapters[hm->h.adapter_index]; | 165 | switch (hm->h.function) { |
166 | case HPI_SUBSYS_CREATE_ADAPTER: | ||
167 | case HPI_ADAPTER_DELETE: | ||
168 | /* Application must not use these functions! */ | ||
169 | hr->h.size = sizeof(hr->h); | ||
170 | hr->h.error = HPI_ERROR_INVALID_OPERATION; | ||
171 | hr->h.function = hm->h.function; | ||
172 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | ||
173 | if (uncopied_bytes) | ||
174 | err = -EFAULT; | ||
175 | else | ||
176 | err = 0; | ||
177 | goto out; | ||
178 | } | ||
179 | |||
165 | hr->h.size = res_max_size; | 180 | hr->h.size = res_max_size; |
166 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { | 181 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { |
167 | switch (hm->h.function) { | 182 | hpi_send_recv_f(&hm->m0, &hr->r0, file); |
168 | case HPI_SUBSYS_CREATE_ADAPTER: | ||
169 | case HPI_SUBSYS_DELETE_ADAPTER: | ||
170 | /* Application must not use these functions! */ | ||
171 | hr->h.size = sizeof(hr->h); | ||
172 | hr->h.error = HPI_ERROR_INVALID_OPERATION; | ||
173 | hr->h.function = hm->h.function; | ||
174 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | ||
175 | if (uncopied_bytes) | ||
176 | err = -EFAULT; | ||
177 | else | ||
178 | err = 0; | ||
179 | goto out; | ||
180 | |||
181 | default: | ||
182 | hpi_send_recv_f(&hm->m0, &hr->r0, file); | ||
183 | } | ||
184 | } else { | 183 | } else { |
185 | u16 __user *ptr = NULL; | 184 | u16 __user *ptr = NULL; |
186 | u32 size = 0; | 185 | u32 size = 0; |
@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
188 | /* -1=no data 0=read from user mem, 1=write to user mem */ | 187 | /* -1=no data 0=read from user mem, 1=write to user mem */ |
189 | int wrflag = -1; | 188 | int wrflag = -1; |
190 | u32 adapter = hm->h.adapter_index; | 189 | u32 adapter = hm->h.adapter_index; |
190 | pa = &adapters[adapter]; | ||
191 | 191 | ||
192 | if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) { | 192 | if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) { |
193 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, | 193 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, |
194 | HPI_ADAPTER_OPEN, | 194 | HPI_ADAPTER_OPEN, |
195 | HPI_ERROR_BAD_ADAPTER_NUMBER); | 195 | HPI_ERROR_BAD_ADAPTER_NUMBER); |
@@ -317,7 +317,7 @@ out: | |||
317 | int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | 317 | int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, |
318 | const struct pci_device_id *pci_id) | 318 | const struct pci_device_id *pci_id) |
319 | { | 319 | { |
320 | int err, idx, nm; | 320 | int idx, nm; |
321 | unsigned int memlen; | 321 | unsigned int memlen; |
322 | struct hpi_message hm; | 322 | struct hpi_message hm; |
323 | struct hpi_response hr; | 323 | struct hpi_response hr; |
@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
351 | nm = HPI_MAX_ADAPTER_MEM_SPACES; | 351 | nm = HPI_MAX_ADAPTER_MEM_SPACES; |
352 | 352 | ||
353 | for (idx = 0; idx < nm; idx++) { | 353 | for (idx = 0; idx < nm; idx++) { |
354 | HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n", | 354 | HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, |
355 | idx, pci_dev->resource[idx].name, | 355 | &pci_dev->resource[idx]); |
356 | (unsigned long long)pci_resource_start(pci_dev, idx), | ||
357 | (unsigned long long)pci_resource_end(pci_dev, idx), | ||
358 | (unsigned long long)pci_resource_flags(pci_dev, idx)); | ||
359 | 356 | ||
360 | if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { | 357 | if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { |
361 | memlen = pci_resource_len(pci_dev, idx); | 358 | memlen = pci_resource_len(pci_dev, idx); |
@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
395 | 392 | ||
396 | adapter.index = hr.u.s.adapter_index; | 393 | adapter.index = hr.u.s.adapter_index; |
397 | adapter.type = hr.u.s.adapter_type; | 394 | adapter.type = hr.u.s.adapter_type; |
395 | |||
396 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
397 | HPI_ADAPTER_OPEN); | ||
398 | hm.adapter_index = adapter.index; | 398 | hm.adapter_index = adapter.index; |
399 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | ||
399 | 400 | ||
400 | err = hpi_adapter_open(adapter.index); | 401 | if (hr.error) |
401 | if (err) | ||
402 | goto err; | 402 | goto err; |
403 | 403 | ||
404 | adapter.snd_card_asihpi = NULL; | 404 | adapter.snd_card_asihpi = NULL; |
405 | /* WARNING can't init mutex in 'adapter' | 405 | /* WARNING can't init mutex in 'adapter' |
406 | * and then copy it to adapters[] ?!?! | 406 | * and then copy it to adapters[] ?!?! |
407 | */ | 407 | */ |
408 | adapters[hr.u.s.adapter_index] = adapter; | 408 | adapters[adapter.index] = adapter; |
409 | mutex_init(&adapters[adapter.index].mutex); | 409 | mutex_init(&adapters[adapter.index].mutex); |
410 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); | 410 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); |
411 | 411 | ||
@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
440 | struct hpi_adapter *pa; | 440 | struct hpi_adapter *pa; |
441 | pa = pci_get_drvdata(pci_dev); | 441 | pa = pci_get_drvdata(pci_dev); |
442 | 442 | ||
443 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 443 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, |
444 | HPI_SUBSYS_DELETE_ADAPTER); | 444 | HPI_ADAPTER_DELETE); |
445 | hm.obj_index = pa->index; | 445 | hm.adapter_index = pa->index; |
446 | hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; | ||
447 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | 446 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); |
448 | 447 | ||
449 | /* unmap PCI memory space, mapped during device init. */ | 448 | /* unmap PCI memory space, mapped during device init. */ |
diff --git a/sound/pci/au88x0/au8810.h b/sound/pci/au88x0/au8810.h index 5d69c31fe3f4..79fbee3845eb 100644 --- a/sound/pci/au88x0/au8810.h +++ b/sound/pci/au88x0/au8810.h | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | #define CHIP_AU8810 | 5 | #define CHIP_AU8810 |
6 | 6 | ||
7 | #define CARD_NAME "Aureal Advantage 3D Sound Processor" | 7 | #define CARD_NAME "Aureal Advantage" |
8 | #define CARD_NAME_SHORT "au8810" | 8 | #define CARD_NAME_SHORT "au8810" |
9 | 9 | ||
10 | #define NR_ADB 0x10 | 10 | #define NR_ADB 0x10 |
diff --git a/sound/pci/au88x0/au8820.h b/sound/pci/au88x0/au8820.h index abbe85e4f7a9..cafdb9668a34 100644 --- a/sound/pci/au88x0/au8820.h +++ b/sound/pci/au88x0/au8820.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #define CHIP_AU8820 | 12 | #define CHIP_AU8820 |
13 | 13 | ||
14 | #define CARD_NAME "Aureal Vortex 3D Sound Processor" | 14 | #define CARD_NAME "Aureal Vortex" |
15 | #define CARD_NAME_SHORT "au8820" | 15 | #define CARD_NAME_SHORT "au8820" |
16 | 16 | ||
17 | /* Number of ADB and WT channels */ | 17 | /* Number of ADB and WT channels */ |
diff --git a/sound/pci/au88x0/au8830.h b/sound/pci/au88x0/au8830.h index 04ece1b1c218..999b29ab34ad 100644 --- a/sound/pci/au88x0/au8830.h +++ b/sound/pci/au88x0/au8830.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #define CHIP_AU8830 | 12 | #define CHIP_AU8830 |
13 | 13 | ||
14 | #define CARD_NAME "Aureal Vortex 2 3D Sound Processor" | 14 | #define CARD_NAME "Aureal Vortex 2" |
15 | #define CARD_NAME_SHORT "au8830" | 15 | #define CARD_NAME_SHORT "au8830" |
16 | 16 | ||
17 | #define NR_ADB 0x20 | 17 | #define NR_ADB 0x20 |
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 62e959120c44..c5f7ae46afef 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c | |||
@@ -426,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = { | |||
426 | */ | 426 | */ |
427 | 427 | ||
428 | static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = { | 428 | static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = { |
429 | "AU88x0 ADB", | 429 | CARD_NAME " ADB", |
430 | "AU88x0 SPDIF", | 430 | CARD_NAME " SPDIF", |
431 | "AU88x0 A3D", | 431 | CARD_NAME " A3D", |
432 | "AU88x0 WT", | 432 | CARD_NAME " WT", |
433 | "AU88x0 I2S", | 433 | CARD_NAME " I2S", |
434 | }; | 434 | }; |
435 | static char *vortex_pcm_name[VORTEX_PCM_LAST] = { | 435 | static char *vortex_pcm_name[VORTEX_PCM_LAST] = { |
436 | "adb", | 436 | "adb", |
@@ -527,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) | |||
527 | nr_capt, &pcm); | 527 | nr_capt, &pcm); |
528 | if (err < 0) | 528 | if (err < 0) |
529 | return err; | 529 | return err; |
530 | strcpy(pcm->name, vortex_pcm_name[idx]); | 530 | snprintf(pcm->name, sizeof(pcm->name), |
531 | "%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]); | ||
531 | chip->pcm[idx] = pcm; | 532 | chip->pcm[idx] = pcm; |
532 | // This is an evil hack, but it saves a lot of duplicated code. | 533 | // This is an evil hack, but it saves a lot of duplicated code. |
533 | VORTEX_PCM_TYPE(pcm) = idx; | 534 | VORTEX_PCM_TYPE(pcm) = idx; |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7a9401462c1c..dae4050ede5c 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -303,6 +303,9 @@ static const u32 db_table[101] = { | |||
303 | static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); | 303 | static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); |
304 | static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0); | 304 | static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0); |
305 | 305 | ||
306 | /* EMU10K1 bass/treble db gain */ | ||
307 | static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0); | ||
308 | |||
306 | static const u32 onoff_table[2] = { | 309 | static const u32 onoff_table[2] = { |
307 | 0x00000000, 0x00000001 | 310 | 0x00000000, 0x00000001 |
308 | }; | 311 | }; |
@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
2163 | ctl->min = 0; | 2166 | ctl->min = 0; |
2164 | ctl->max = 40; | 2167 | ctl->max = 40; |
2165 | ctl->value[0] = ctl->value[1] = 20; | 2168 | ctl->value[0] = ctl->value[1] = 20; |
2169 | ctl->tlv = snd_emu10k1_bass_treble_db_scale; | ||
2166 | ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; | 2170 | ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; |
2167 | ctl = &controls[i + 1]; | 2171 | ctl = &controls[i + 1]; |
2168 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 2172 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
2172 | ctl->min = 0; | 2176 | ctl->min = 0; |
2173 | ctl->max = 40; | 2177 | ctl->max = 40; |
2174 | ctl->value[0] = ctl->value[1] = 20; | 2178 | ctl->value[0] = ctl->value[1] = 20; |
2179 | ctl->tlv = snd_emu10k1_bass_treble_db_scale; | ||
2175 | ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; | 2180 | ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; |
2176 | 2181 | ||
2177 | #define BASS_GPR 0x8c | 2182 | #define BASS_GPR 0x8c |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 05afe06e353a..9d890a5aec5a 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
1729 | "Master Mono Playback Volume", | 1729 | "Master Mono Playback Volume", |
1730 | "PCM Out Path & Mute", | 1730 | "PCM Out Path & Mute", |
1731 | "Mono Output Select", | 1731 | "Mono Output Select", |
1732 | "Front Playback Switch", | ||
1733 | "Front Playback Volume", | ||
1734 | "Surround Playback Switch", | 1732 | "Surround Playback Switch", |
1735 | "Surround Playback Volume", | 1733 | "Surround Playback Volume", |
1736 | "Center Playback Switch", | 1734 | "Center Playback Switch", |
@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
1879 | emu->rear_ac97 = 1; | 1877 | emu->rear_ac97 = 1; |
1880 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); | 1878 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); |
1881 | snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); | 1879 | snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); |
1880 | remove_ctl(card,"Front Playback Volume"); | ||
1881 | remove_ctl(card,"Front Playback Switch"); | ||
1882 | } | 1882 | } |
1883 | /* remove unused AC97 controls */ | 1883 | /* remove unused AC97 controls */ |
1884 | snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); | 1884 | snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); |
@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
1913 | for (; *c; c += 2) | 1913 | for (; *c; c += 2) |
1914 | rename_ctl(card, c[0], c[1]); | 1914 | rename_ctl(card, c[0], c[1]); |
1915 | 1915 | ||
1916 | if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */ | ||
1917 | remove_ctl(card, "Center Playback Volume"); | ||
1918 | remove_ctl(card, "LFE Playback Volume"); | ||
1919 | remove_ctl(card, "Wave Center Playback Volume"); | ||
1920 | remove_ctl(card, "Wave LFE Playback Volume"); | ||
1921 | } | ||
1916 | if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ | 1922 | if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ |
1917 | rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); | 1923 | rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); |
1918 | rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); | 1924 | rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 7c17f45d876d..ab0a6156a704 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -112,6 +112,10 @@ | |||
112 | #include <sound/ac97_codec.h> | 112 | #include <sound/ac97_codec.h> |
113 | #include <sound/initval.h> | 113 | #include <sound/initval.h> |
114 | 114 | ||
115 | #ifdef CONFIG_SND_ES1968_RADIO | ||
116 | #include <sound/tea575x-tuner.h> | ||
117 | #endif | ||
118 | |||
115 | #define CARD_NAME "ESS Maestro1/2" | 119 | #define CARD_NAME "ESS Maestro1/2" |
116 | #define DRIVER_NAME "ES1968" | 120 | #define DRIVER_NAME "ES1968" |
117 | 121 | ||
@@ -553,6 +557,10 @@ struct es1968 { | |||
553 | spinlock_t ac97_lock; | 557 | spinlock_t ac97_lock; |
554 | struct tasklet_struct hwvol_tq; | 558 | struct tasklet_struct hwvol_tq; |
555 | #endif | 559 | #endif |
560 | |||
561 | #ifdef CONFIG_SND_ES1968_RADIO | ||
562 | struct snd_tea575x tea; | ||
563 | #endif | ||
556 | }; | 564 | }; |
557 | 565 | ||
558 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); | 566 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); |
@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip) | |||
2571 | } | 2579 | } |
2572 | #endif /* CONFIG_SND_ES1968_INPUT */ | 2580 | #endif /* CONFIG_SND_ES1968_INPUT */ |
2573 | 2581 | ||
2582 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2583 | #define GPIO_DATA 0x60 | ||
2584 | #define IO_MASK 4 /* mask register offset from GPIO_DATA | ||
2585 | bits 1=unmask write to given bit */ | ||
2586 | #define IO_DIR 8 /* direction register offset from GPIO_DATA | ||
2587 | bits 0/1=read/write direction */ | ||
2588 | /* mask bits for GPIO lines */ | ||
2589 | #define STR_DATA 0x0040 /* GPIO6 */ | ||
2590 | #define STR_CLK 0x0080 /* GPIO7 */ | ||
2591 | #define STR_WREN 0x0100 /* GPIO8 */ | ||
2592 | #define STR_MOST 0x0200 /* GPIO9 */ | ||
2593 | |||
2594 | static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) | ||
2595 | { | ||
2596 | struct es1968 *chip = tea->private_data; | ||
2597 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2598 | u16 val = 0; | ||
2599 | |||
2600 | val |= (pins & TEA575X_DATA) ? STR_DATA : 0; | ||
2601 | val |= (pins & TEA575X_CLK) ? STR_CLK : 0; | ||
2602 | val |= (pins & TEA575X_WREN) ? STR_WREN : 0; | ||
2603 | |||
2604 | outw(val, io); | ||
2605 | } | ||
2606 | |||
2607 | static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea) | ||
2608 | { | ||
2609 | struct es1968 *chip = tea->private_data; | ||
2610 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2611 | u16 val = inw(io); | ||
2612 | |||
2613 | return (val & STR_DATA) ? TEA575X_DATA : 0 | | ||
2614 | (val & STR_MOST) ? TEA575X_MOST : 0; | ||
2615 | } | ||
2616 | |||
2617 | static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output) | ||
2618 | { | ||
2619 | struct es1968 *chip = tea->private_data; | ||
2620 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2621 | u16 odir = inw(io + IO_DIR); | ||
2622 | |||
2623 | if (output) { | ||
2624 | outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); | ||
2625 | outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR); | ||
2626 | } else { | ||
2627 | outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK); | ||
2628 | outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR); | ||
2629 | } | ||
2630 | } | ||
2631 | |||
2632 | static struct snd_tea575x_ops snd_es1968_tea_ops = { | ||
2633 | .set_pins = snd_es1968_tea575x_set_pins, | ||
2634 | .get_pins = snd_es1968_tea575x_get_pins, | ||
2635 | .set_direction = snd_es1968_tea575x_set_direction, | ||
2636 | }; | ||
2637 | #endif | ||
2638 | |||
2574 | static int snd_es1968_free(struct es1968 *chip) | 2639 | static int snd_es1968_free(struct es1968 *chip) |
2575 | { | 2640 | { |
2576 | #ifdef CONFIG_SND_ES1968_INPUT | 2641 | #ifdef CONFIG_SND_ES1968_INPUT |
@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip) | |||
2585 | outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ | 2650 | outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ |
2586 | } | 2651 | } |
2587 | 2652 | ||
2653 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2654 | snd_tea575x_exit(&chip->tea); | ||
2655 | #endif | ||
2656 | |||
2588 | if (chip->irq >= 0) | 2657 | if (chip->irq >= 0) |
2589 | free_irq(chip->irq, chip); | 2658 | free_irq(chip->irq, chip); |
2590 | snd_es1968_free_gameport(chip); | 2659 | snd_es1968_free_gameport(chip); |
@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2723 | 2792 | ||
2724 | snd_card_set_dev(card, &pci->dev); | 2793 | snd_card_set_dev(card, &pci->dev); |
2725 | 2794 | ||
2795 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2796 | chip->tea.private_data = chip; | ||
2797 | chip->tea.ops = &snd_es1968_tea_ops; | ||
2798 | strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); | ||
2799 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); | ||
2800 | if (!snd_tea575x_init(&chip->tea)) | ||
2801 | printk(KERN_INFO "es1968: detected TEA575x radio\n"); | ||
2802 | #endif | ||
2803 | |||
2726 | *chip_ret = chip; | 2804 | *chip_ret = chip; |
2727 | 2805 | ||
2728 | return 0; | 2806 | return 0; |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index e1baad74ea4b..eacd4901a308 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 39 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
40 | #include <sound/tea575x-tuner.h> | 40 | #include <sound/tea575x-tuner.h> |
41 | #define TEA575X_RADIO 1 | ||
42 | #endif | 41 | #endif |
43 | 42 | ||
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 43 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
@@ -53,7 +52,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * | |||
53 | /* | 52 | /* |
54 | * Enable TEA575x tuner | 53 | * Enable TEA575x tuner |
55 | * 1 = MediaForte 256-PCS | 54 | * 1 = MediaForte 256-PCS |
56 | * 2 = MediaForte 256-PCPR | 55 | * 2 = MediaForte 256-PCP |
57 | * 3 = MediaForte 64-PCR | 56 | * 3 = MediaForte 64-PCR |
58 | * 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card | 57 | * 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card |
59 | * High 16-bits are video (radio) device number + 1 | 58 | * High 16-bits are video (radio) device number + 1 |
@@ -67,7 +66,7 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard."); | |||
67 | module_param_array(enable, bool, NULL, 0444); | 66 | module_param_array(enable, bool, NULL, 0444); |
68 | MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); | 67 | MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); |
69 | module_param_array(tea575x_tuner, int, NULL, 0444); | 68 | module_param_array(tea575x_tuner, int, NULL, 0444); |
70 | MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (1 = SF256-PCS, 2=SF256-PCPR, 3=SF64-PCR, +16=tuner-only)."); | 69 | MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); |
71 | 70 | ||
72 | #define TUNER_ONLY (1<<4) | 71 | #define TUNER_ONLY (1<<4) |
73 | #define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF) | 72 | #define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF) |
@@ -196,7 +195,7 @@ struct fm801 { | |||
196 | spinlock_t reg_lock; | 195 | spinlock_t reg_lock; |
197 | struct snd_info_entry *proc_entry; | 196 | struct snd_info_entry *proc_entry; |
198 | 197 | ||
199 | #ifdef TEA575X_RADIO | 198 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
200 | struct snd_tea575x tea; | 199 | struct snd_tea575x tea; |
201 | #endif | 200 | #endif |
202 | 201 | ||
@@ -715,310 +714,89 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc | |||
715 | * TEA5757 radio | 714 | * TEA5757 radio |
716 | */ | 715 | */ |
717 | 716 | ||
718 | #ifdef TEA575X_RADIO | 717 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
719 | |||
720 | /* 256PCS GPIO numbers */ | ||
721 | #define TEA_256PCS_DATA 1 | ||
722 | #define TEA_256PCS_WRITE_ENABLE 2 /* inverted */ | ||
723 | #define TEA_256PCS_BUS_CLOCK 3 | ||
724 | |||
725 | static void snd_fm801_tea575x_256pcs_write(struct snd_tea575x *tea, unsigned int val) | ||
726 | { | ||
727 | struct fm801 *chip = tea->private_data; | ||
728 | unsigned short reg; | ||
729 | int i = 25; | ||
730 | 718 | ||
731 | spin_lock_irq(&chip->reg_lock); | 719 | /* GPIO to TEA575x maps */ |
732 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | 720 | struct snd_fm801_tea575x_gpio { |
733 | /* use GPIO lines and set write enable bit */ | 721 | u8 data, clk, wren, most; |
734 | reg |= FM801_GPIO_GS(TEA_256PCS_DATA) | | 722 | char *name; |
735 | FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) | | 723 | }; |
736 | FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK); | ||
737 | /* all of lines are in the write direction */ | ||
738 | /* clear data and clock lines */ | ||
739 | reg &= ~(FM801_GPIO_GD(TEA_256PCS_DATA) | | ||
740 | FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) | | ||
741 | FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) | | ||
742 | FM801_GPIO_GP(TEA_256PCS_DATA) | | ||
743 | FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK) | | ||
744 | FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE)); | ||
745 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
746 | udelay(1); | ||
747 | |||
748 | while (i--) { | ||
749 | if (val & (1 << i)) | ||
750 | reg |= FM801_GPIO_GP(TEA_256PCS_DATA); | ||
751 | else | ||
752 | reg &= ~FM801_GPIO_GP(TEA_256PCS_DATA); | ||
753 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
754 | udelay(1); | ||
755 | reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK); | ||
756 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
757 | reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK); | ||
758 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
759 | udelay(1); | ||
760 | } | ||
761 | 724 | ||
762 | /* and reset the write enable bit */ | 725 | static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { |
763 | reg |= FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE) | | 726 | { .data = 1, .clk = 3, .wren = 2, .most = 0, .name = "SF256-PCS" }, |
764 | FM801_GPIO_GP(TEA_256PCS_DATA); | 727 | { .data = 1, .clk = 0, .wren = 2, .most = 3, .name = "SF256-PCP" }, |
765 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 728 | { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" }, |
766 | spin_unlock_irq(&chip->reg_lock); | 729 | }; |
767 | } | ||
768 | 730 | ||
769 | static unsigned int snd_fm801_tea575x_256pcs_read(struct snd_tea575x *tea) | 731 | static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) |
770 | { | 732 | { |
771 | struct fm801 *chip = tea->private_data; | 733 | struct fm801 *chip = tea->private_data; |
772 | unsigned short reg; | 734 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); |
773 | unsigned int val = 0; | 735 | struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; |
774 | int i; | ||
775 | |||
776 | spin_lock_irq(&chip->reg_lock); | ||
777 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
778 | /* use GPIO lines, set data direction to input */ | ||
779 | reg |= FM801_GPIO_GS(TEA_256PCS_DATA) | | ||
780 | FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) | | ||
781 | FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK) | | ||
782 | FM801_GPIO_GD(TEA_256PCS_DATA) | | ||
783 | FM801_GPIO_GP(TEA_256PCS_DATA) | | ||
784 | FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE); | ||
785 | /* all of lines are in the write direction, except data */ | ||
786 | /* clear data, write enable and clock lines */ | ||
787 | reg &= ~(FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) | | ||
788 | FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) | | ||
789 | FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK)); | ||
790 | |||
791 | for (i = 0; i < 24; i++) { | ||
792 | reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK); | ||
793 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
794 | udelay(1); | ||
795 | reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK); | ||
796 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
797 | udelay(1); | ||
798 | val <<= 1; | ||
799 | if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCS_DATA)) | ||
800 | val |= 1; | ||
801 | } | ||
802 | 736 | ||
803 | spin_unlock_irq(&chip->reg_lock); | 737 | reg &= ~(FM801_GPIO_GP(gpio.data) | |
738 | FM801_GPIO_GP(gpio.clk) | | ||
739 | FM801_GPIO_GP(gpio.wren)); | ||
804 | 740 | ||
805 | return val; | 741 | reg |= (pins & TEA575X_DATA) ? FM801_GPIO_GP(gpio.data) : 0; |
806 | } | 742 | reg |= (pins & TEA575X_CLK) ? FM801_GPIO_GP(gpio.clk) : 0; |
743 | /* WRITE_ENABLE is inverted */ | ||
744 | reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren); | ||
807 | 745 | ||
808 | /* 256PCPR GPIO numbers */ | ||
809 | #define TEA_256PCPR_BUS_CLOCK 0 | ||
810 | #define TEA_256PCPR_DATA 1 | ||
811 | #define TEA_256PCPR_WRITE_ENABLE 2 /* inverted */ | ||
812 | |||
813 | static void snd_fm801_tea575x_256pcpr_write(struct snd_tea575x *tea, unsigned int val) | ||
814 | { | ||
815 | struct fm801 *chip = tea->private_data; | ||
816 | unsigned short reg; | ||
817 | int i = 25; | ||
818 | |||
819 | spin_lock_irq(&chip->reg_lock); | ||
820 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
821 | /* use GPIO lines and set write enable bit */ | ||
822 | reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) | | ||
823 | FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) | | ||
824 | FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK); | ||
825 | /* all of lines are in the write direction */ | ||
826 | /* clear data and clock lines */ | ||
827 | reg &= ~(FM801_GPIO_GD(TEA_256PCPR_DATA) | | ||
828 | FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) | | ||
829 | FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) | | ||
830 | FM801_GPIO_GP(TEA_256PCPR_DATA) | | ||
831 | FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK) | | ||
832 | FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE)); | ||
833 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 746 | outw(reg, FM801_REG(chip, GPIO_CTRL)); |
834 | udelay(1); | ||
835 | |||
836 | while (i--) { | ||
837 | if (val & (1 << i)) | ||
838 | reg |= FM801_GPIO_GP(TEA_256PCPR_DATA); | ||
839 | else | ||
840 | reg &= ~FM801_GPIO_GP(TEA_256PCPR_DATA); | ||
841 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
842 | udelay(1); | ||
843 | reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK); | ||
844 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
845 | reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK); | ||
846 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
847 | udelay(1); | ||
848 | } | ||
849 | |||
850 | /* and reset the write enable bit */ | ||
851 | reg |= FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE) | | ||
852 | FM801_GPIO_GP(TEA_256PCPR_DATA); | ||
853 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
854 | spin_unlock_irq(&chip->reg_lock); | ||
855 | } | 747 | } |
856 | 748 | ||
857 | static unsigned int snd_fm801_tea575x_256pcpr_read(struct snd_tea575x *tea) | 749 | static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) |
858 | { | 750 | { |
859 | struct fm801 *chip = tea->private_data; | 751 | struct fm801 *chip = tea->private_data; |
860 | unsigned short reg; | 752 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); |
861 | unsigned int val = 0; | 753 | struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; |
862 | int i; | ||
863 | |||
864 | spin_lock_irq(&chip->reg_lock); | ||
865 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
866 | /* use GPIO lines, set data direction to input */ | ||
867 | reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) | | ||
868 | FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) | | ||
869 | FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK) | | ||
870 | FM801_GPIO_GD(TEA_256PCPR_DATA) | | ||
871 | FM801_GPIO_GP(TEA_256PCPR_DATA) | | ||
872 | FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE); | ||
873 | /* all of lines are in the write direction, except data */ | ||
874 | /* clear data, write enable and clock lines */ | ||
875 | reg &= ~(FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) | | ||
876 | FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) | | ||
877 | FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK)); | ||
878 | |||
879 | for (i = 0; i < 24; i++) { | ||
880 | reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK); | ||
881 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
882 | udelay(1); | ||
883 | reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK); | ||
884 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
885 | udelay(1); | ||
886 | val <<= 1; | ||
887 | if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCPR_DATA)) | ||
888 | val |= 1; | ||
889 | } | ||
890 | 754 | ||
891 | spin_unlock_irq(&chip->reg_lock); | 755 | return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 | |
892 | 756 | (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0; | |
893 | return val; | ||
894 | } | 757 | } |
895 | 758 | ||
896 | /* 64PCR GPIO numbers */ | 759 | static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output) |
897 | #define TEA_64PCR_BUS_CLOCK 0 | ||
898 | #define TEA_64PCR_WRITE_ENABLE 1 /* inverted */ | ||
899 | #define TEA_64PCR_DATA 2 | ||
900 | |||
901 | static void snd_fm801_tea575x_64pcr_write(struct snd_tea575x *tea, unsigned int val) | ||
902 | { | 760 | { |
903 | struct fm801 *chip = tea->private_data; | 761 | struct fm801 *chip = tea->private_data; |
904 | unsigned short reg; | 762 | unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); |
905 | int i = 25; | 763 | struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; |
906 | 764 | ||
907 | spin_lock_irq(&chip->reg_lock); | ||
908 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
909 | /* use GPIO lines and set write enable bit */ | 765 | /* use GPIO lines and set write enable bit */ |
910 | reg |= FM801_GPIO_GS(TEA_64PCR_DATA) | | 766 | reg |= FM801_GPIO_GS(gpio.data) | |
911 | FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) | | 767 | FM801_GPIO_GS(gpio.wren) | |
912 | FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK); | 768 | FM801_GPIO_GS(gpio.clk) | |
913 | /* all of lines are in the write direction */ | 769 | FM801_GPIO_GS(gpio.most); |
914 | /* clear data and clock lines */ | 770 | if (output) { |
915 | reg &= ~(FM801_GPIO_GD(TEA_64PCR_DATA) | | 771 | /* all of lines are in the write direction */ |
916 | FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) | | 772 | /* clear data and clock lines */ |
917 | FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) | | 773 | reg &= ~(FM801_GPIO_GD(gpio.data) | |
918 | FM801_GPIO_GP(TEA_64PCR_DATA) | | 774 | FM801_GPIO_GD(gpio.wren) | |
919 | FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK) | | 775 | FM801_GPIO_GD(gpio.clk) | |
920 | FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE)); | 776 | FM801_GPIO_GP(gpio.data) | |
921 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 777 | FM801_GPIO_GP(gpio.clk) | |
922 | udelay(1); | 778 | FM801_GPIO_GP(gpio.wren)); |
923 | 779 | } else { | |
924 | while (i--) { | 780 | /* use GPIO lines, set data direction to input */ |
925 | if (val & (1 << i)) | 781 | reg |= FM801_GPIO_GD(gpio.data) | |
926 | reg |= FM801_GPIO_GP(TEA_64PCR_DATA); | 782 | FM801_GPIO_GD(gpio.most) | |
927 | else | 783 | FM801_GPIO_GP(gpio.data) | |
928 | reg &= ~FM801_GPIO_GP(TEA_64PCR_DATA); | 784 | FM801_GPIO_GP(gpio.most) | |
929 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 785 | FM801_GPIO_GP(gpio.wren); |
930 | udelay(1); | 786 | /* all of lines are in the write direction, except data */ |
931 | reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); | 787 | /* clear data, write enable and clock lines */ |
932 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 788 | reg &= ~(FM801_GPIO_GD(gpio.wren) | |
933 | reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); | 789 | FM801_GPIO_GD(gpio.clk) | |
934 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 790 | FM801_GPIO_GP(gpio.clk)); |
935 | udelay(1); | ||
936 | } | 791 | } |
937 | 792 | ||
938 | /* and reset the write enable bit */ | ||
939 | reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE) | | ||
940 | FM801_GPIO_GP(TEA_64PCR_DATA); | ||
941 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | 793 | outw(reg, FM801_REG(chip, GPIO_CTRL)); |
942 | spin_unlock_irq(&chip->reg_lock); | ||
943 | } | ||
944 | |||
945 | static unsigned int snd_fm801_tea575x_64pcr_read(struct snd_tea575x *tea) | ||
946 | { | ||
947 | struct fm801 *chip = tea->private_data; | ||
948 | unsigned short reg; | ||
949 | unsigned int val = 0; | ||
950 | int i; | ||
951 | |||
952 | spin_lock_irq(&chip->reg_lock); | ||
953 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
954 | /* use GPIO lines, set data direction to input */ | ||
955 | reg |= FM801_GPIO_GS(TEA_64PCR_DATA) | | ||
956 | FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) | | ||
957 | FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK) | | ||
958 | FM801_GPIO_GD(TEA_64PCR_DATA) | | ||
959 | FM801_GPIO_GP(TEA_64PCR_DATA) | | ||
960 | FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE); | ||
961 | /* all of lines are in the write direction, except data */ | ||
962 | /* clear data, write enable and clock lines */ | ||
963 | reg &= ~(FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) | | ||
964 | FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) | | ||
965 | FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK)); | ||
966 | |||
967 | for (i = 0; i < 24; i++) { | ||
968 | reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); | ||
969 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
970 | udelay(1); | ||
971 | reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); | ||
972 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
973 | udelay(1); | ||
974 | val <<= 1; | ||
975 | if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_64PCR_DATA)) | ||
976 | val |= 1; | ||
977 | } | ||
978 | |||
979 | spin_unlock_irq(&chip->reg_lock); | ||
980 | |||
981 | return val; | ||
982 | } | 794 | } |
983 | 795 | ||
984 | static void snd_fm801_tea575x_64pcr_mute(struct snd_tea575x *tea, | 796 | static struct snd_tea575x_ops snd_fm801_tea_ops = { |
985 | unsigned int mute) | 797 | .set_pins = snd_fm801_tea575x_set_pins, |
986 | { | 798 | .get_pins = snd_fm801_tea575x_get_pins, |
987 | struct fm801 *chip = tea->private_data; | 799 | .set_direction = snd_fm801_tea575x_set_direction, |
988 | unsigned short reg; | ||
989 | |||
990 | spin_lock_irq(&chip->reg_lock); | ||
991 | |||
992 | reg = inw(FM801_REG(chip, GPIO_CTRL)); | ||
993 | if (mute) | ||
994 | /* 0xf800 (mute) */ | ||
995 | reg &= ~FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE); | ||
996 | else | ||
997 | /* 0xf802 (unmute) */ | ||
998 | reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE); | ||
999 | outw(reg, FM801_REG(chip, GPIO_CTRL)); | ||
1000 | udelay(1); | ||
1001 | |||
1002 | spin_unlock_irq(&chip->reg_lock); | ||
1003 | } | ||
1004 | |||
1005 | static struct snd_tea575x_ops snd_fm801_tea_ops[3] = { | ||
1006 | { | ||
1007 | /* 1 = MediaForte 256-PCS */ | ||
1008 | .write = snd_fm801_tea575x_256pcs_write, | ||
1009 | .read = snd_fm801_tea575x_256pcs_read, | ||
1010 | }, | ||
1011 | { | ||
1012 | /* 2 = MediaForte 256-PCPR */ | ||
1013 | .write = snd_fm801_tea575x_256pcpr_write, | ||
1014 | .read = snd_fm801_tea575x_256pcpr_read, | ||
1015 | }, | ||
1016 | { | ||
1017 | /* 3 = MediaForte 64-PCR */ | ||
1018 | .write = snd_fm801_tea575x_64pcr_write, | ||
1019 | .read = snd_fm801_tea575x_64pcr_read, | ||
1020 | .mute = snd_fm801_tea575x_64pcr_mute, | ||
1021 | } | ||
1022 | }; | 800 | }; |
1023 | #endif | 801 | #endif |
1024 | 802 | ||
@@ -1371,7 +1149,7 @@ static int snd_fm801_free(struct fm801 *chip) | |||
1371 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); | 1149 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); |
1372 | 1150 | ||
1373 | __end_hw: | 1151 | __end_hw: |
1374 | #ifdef TEA575X_RADIO | 1152 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
1375 | snd_tea575x_exit(&chip->tea); | 1153 | snd_tea575x_exit(&chip->tea); |
1376 | #endif | 1154 | #endif |
1377 | if (chip->irq >= 0) | 1155 | if (chip->irq >= 0) |
@@ -1450,16 +1228,25 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1450 | 1228 | ||
1451 | snd_card_set_dev(card, &pci->dev); | 1229 | snd_card_set_dev(card, &pci->dev); |
1452 | 1230 | ||
1453 | #ifdef TEA575X_RADIO | 1231 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
1232 | chip->tea.private_data = chip; | ||
1233 | chip->tea.ops = &snd_fm801_tea_ops; | ||
1234 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); | ||
1454 | if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && | 1235 | if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && |
1455 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { | 1236 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { |
1456 | chip->tea.dev_nr = tea575x_tuner >> 16; | 1237 | if (snd_tea575x_init(&chip->tea)) |
1457 | chip->tea.card = card; | 1238 | snd_printk(KERN_ERR "TEA575x radio not found\n"); |
1458 | chip->tea.freq_fixup = 10700; | 1239 | } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) |
1459 | chip->tea.private_data = chip; | 1240 | /* autodetect tuner connection */ |
1460 | chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & TUNER_TYPE_MASK) - 1]; | 1241 | for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) { |
1461 | snd_tea575x_init(&chip->tea); | 1242 | chip->tea575x_tuner = tea575x_tuner; |
1462 | } | 1243 | if (!snd_tea575x_init(&chip->tea)) { |
1244 | snd_printk(KERN_INFO "detected TEA575x radio type %s\n", | ||
1245 | snd_fm801_tea575x_gpios[tea575x_tuner - 1].name); | ||
1246 | break; | ||
1247 | } | ||
1248 | } | ||
1249 | strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card)); | ||
1463 | #endif | 1250 | #endif |
1464 | 1251 | ||
1465 | *rchip = chip; | 1252 | *rchip = chip; |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 27709f0cd2a6..f3353b49c785 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = { | |||
235 | { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ | 235 | { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ |
236 | { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ | 236 | { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ |
237 | { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ | 237 | { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ |
238 | { PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */ | ||
238 | #if 0 | 239 | #if 0 |
239 | { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ | ||
240 | { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ | 240 | { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ |
241 | #endif | 241 | #endif |
242 | { 0, } | 242 | { 0, } |
@@ -1261,9 +1261,9 @@ static struct shortname_table { | |||
1261 | { PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" }, | 1261 | { PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" }, |
1262 | { PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" }, | 1262 | { PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" }, |
1263 | { PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" }, | 1263 | { PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" }, |
1264 | { 0x746e, "AMD AMD8111" }, | ||
1264 | #if 0 | 1265 | #if 0 |
1265 | { 0x5455, "ALi M5455" }, | 1266 | { 0x5455, "ALi M5455" }, |
1266 | { 0x746d, "AMD AMD8111" }, | ||
1267 | #endif | 1267 | #endif |
1268 | { 0 }, | 1268 | { 0 }, |
1269 | }; | 1269 | }; |
diff --git a/sound/pci/lola/Makefile b/sound/pci/lola/Makefile new file mode 100644 index 000000000000..8178a2a59d00 --- /dev/null +++ b/sound/pci/lola/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | snd-lola-y := lola.o lola_pcm.o lola_clock.o lola_mixer.o | ||
2 | snd-lola-$(CONFIG_SND_DEBUG) += lola_proc.o | ||
3 | |||
4 | obj-$(CONFIG_SND_LOLA) += snd-lola.o | ||
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c new file mode 100644 index 000000000000..34b24286d279 --- /dev/null +++ b/sound/pci/lola/lola.c | |||
@@ -0,0 +1,791 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <sound/core.h> | ||
30 | #include <sound/control.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/initval.h> | ||
33 | #include "lola.h" | ||
34 | |||
35 | /* Standard options */ | ||
36 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
37 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
38 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
39 | |||
40 | module_param_array(index, int, NULL, 0444); | ||
41 | MODULE_PARM_DESC(index, "Index value for Digigram Lola driver."); | ||
42 | module_param_array(id, charp, NULL, 0444); | ||
43 | MODULE_PARM_DESC(id, "ID string for Digigram Lola driver."); | ||
44 | module_param_array(enable, bool, NULL, 0444); | ||
45 | MODULE_PARM_DESC(enable, "Enable Digigram Lola driver."); | ||
46 | |||
47 | /* Lola-specific options */ | ||
48 | |||
49 | /* for instance use always max granularity which is compatible | ||
50 | * with all sample rates | ||
51 | */ | ||
52 | static int granularity[SNDRV_CARDS] = { | ||
53 | [0 ... (SNDRV_CARDS - 1)] = LOLA_GRANULARITY_MAX | ||
54 | }; | ||
55 | |||
56 | /* below a sample_rate of 16kHz the analogue audio quality is NOT excellent */ | ||
57 | static int sample_rate_min[SNDRV_CARDS] = { | ||
58 | [0 ... (SNDRV_CARDS - 1) ] = 16000 | ||
59 | }; | ||
60 | |||
61 | module_param_array(granularity, int, NULL, 0444); | ||
62 | MODULE_PARM_DESC(granularity, "Granularity value"); | ||
63 | module_param_array(sample_rate_min, int, NULL, 0444); | ||
64 | MODULE_PARM_DESC(sample_rate_min, "Minimal sample rate"); | ||
65 | |||
66 | /* | ||
67 | */ | ||
68 | |||
69 | MODULE_LICENSE("GPL"); | ||
70 | MODULE_SUPPORTED_DEVICE("{{Digigram, Lola}}"); | ||
71 | MODULE_DESCRIPTION("Digigram Lola driver"); | ||
72 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | ||
73 | |||
74 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
75 | static int debug; | ||
76 | module_param(debug, int, 0644); | ||
77 | #define verbose_debug(fmt, args...) \ | ||
78 | do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0) | ||
79 | #else | ||
80 | #define verbose_debug(fmt, args...) | ||
81 | #endif | ||
82 | |||
83 | /* | ||
84 | * pseudo-codec read/write via CORB/RIRB | ||
85 | */ | ||
86 | |||
87 | static int corb_send_verb(struct lola *chip, unsigned int nid, | ||
88 | unsigned int verb, unsigned int data, | ||
89 | unsigned int extdata) | ||
90 | { | ||
91 | unsigned long flags; | ||
92 | int ret = -EIO; | ||
93 | |||
94 | chip->last_cmd_nid = nid; | ||
95 | chip->last_verb = verb; | ||
96 | chip->last_data = data; | ||
97 | chip->last_extdata = extdata; | ||
98 | data |= (nid << 20) | (verb << 8); | ||
99 | |||
100 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
101 | if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { | ||
102 | unsigned int wp = chip->corb.wp + 1; | ||
103 | wp %= LOLA_CORB_ENTRIES; | ||
104 | chip->corb.wp = wp; | ||
105 | chip->corb.buf[wp * 2] = cpu_to_le32(data); | ||
106 | chip->corb.buf[wp * 2 + 1] = cpu_to_le32(extdata); | ||
107 | lola_writew(chip, BAR0, CORBWP, wp); | ||
108 | chip->rirb.cmds++; | ||
109 | smp_wmb(); | ||
110 | ret = 0; | ||
111 | } | ||
112 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static void lola_queue_unsol_event(struct lola *chip, unsigned int res, | ||
117 | unsigned int res_ex) | ||
118 | { | ||
119 | lola_update_ext_clock_freq(chip, res); | ||
120 | } | ||
121 | |||
122 | /* retrieve RIRB entry - called from interrupt handler */ | ||
123 | static void lola_update_rirb(struct lola *chip) | ||
124 | { | ||
125 | unsigned int rp, wp; | ||
126 | u32 res, res_ex; | ||
127 | |||
128 | wp = lola_readw(chip, BAR0, RIRBWP); | ||
129 | if (wp == chip->rirb.wp) | ||
130 | return; | ||
131 | chip->rirb.wp = wp; | ||
132 | |||
133 | while (chip->rirb.rp != wp) { | ||
134 | chip->rirb.rp++; | ||
135 | chip->rirb.rp %= LOLA_CORB_ENTRIES; | ||
136 | |||
137 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | ||
138 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); | ||
139 | res = le32_to_cpu(chip->rirb.buf[rp]); | ||
140 | if (res_ex & LOLA_RIRB_EX_UNSOL_EV) | ||
141 | lola_queue_unsol_event(chip, res, res_ex); | ||
142 | else if (chip->rirb.cmds) { | ||
143 | chip->res = res; | ||
144 | chip->res_ex = res_ex; | ||
145 | smp_wmb(); | ||
146 | chip->rirb.cmds--; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static int rirb_get_response(struct lola *chip, unsigned int *val, | ||
152 | unsigned int *extval) | ||
153 | { | ||
154 | unsigned long timeout; | ||
155 | |||
156 | again: | ||
157 | timeout = jiffies + msecs_to_jiffies(1000); | ||
158 | for (;;) { | ||
159 | if (chip->polling_mode) { | ||
160 | spin_lock_irq(&chip->reg_lock); | ||
161 | lola_update_rirb(chip); | ||
162 | spin_unlock_irq(&chip->reg_lock); | ||
163 | } | ||
164 | if (!chip->rirb.cmds) { | ||
165 | *val = chip->res; | ||
166 | if (extval) | ||
167 | *extval = chip->res_ex; | ||
168 | verbose_debug("get_response: %x, %x\n", | ||
169 | chip->res, chip->res_ex); | ||
170 | if (chip->res_ex & LOLA_RIRB_EX_ERROR) { | ||
171 | printk(KERN_WARNING SFX "RIRB ERROR: " | ||
172 | "NID=%x, verb=%x, data=%x, ext=%x\n", | ||
173 | chip->last_cmd_nid, | ||
174 | chip->last_verb, chip->last_data, | ||
175 | chip->last_extdata); | ||
176 | return -EIO; | ||
177 | } | ||
178 | return 0; | ||
179 | } | ||
180 | if (time_after(jiffies, timeout)) | ||
181 | break; | ||
182 | udelay(20); | ||
183 | cond_resched(); | ||
184 | } | ||
185 | printk(KERN_WARNING SFX "RIRB response error\n"); | ||
186 | if (!chip->polling_mode) { | ||
187 | printk(KERN_WARNING SFX "switching to polling mode\n"); | ||
188 | chip->polling_mode = 1; | ||
189 | goto again; | ||
190 | } | ||
191 | return -EIO; | ||
192 | } | ||
193 | |||
194 | /* aynchronous write of a codec verb with data */ | ||
195 | int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, | ||
196 | unsigned int data, unsigned int extdata) | ||
197 | { | ||
198 | verbose_debug("codec_write NID=%x, verb=%x, data=%x, ext=%x\n", | ||
199 | nid, verb, data, extdata); | ||
200 | return corb_send_verb(chip, nid, verb, data, extdata); | ||
201 | } | ||
202 | |||
203 | /* write a codec verb with data and read the returned status */ | ||
204 | int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb, | ||
205 | unsigned int data, unsigned int extdata, | ||
206 | unsigned int *val, unsigned int *extval) | ||
207 | { | ||
208 | int err; | ||
209 | |||
210 | verbose_debug("codec_read NID=%x, verb=%x, data=%x, ext=%x\n", | ||
211 | nid, verb, data, extdata); | ||
212 | err = corb_send_verb(chip, nid, verb, data, extdata); | ||
213 | if (err < 0) | ||
214 | return err; | ||
215 | err = rirb_get_response(chip, val, extval); | ||
216 | return err; | ||
217 | } | ||
218 | |||
219 | /* flush all pending codec writes */ | ||
220 | int lola_codec_flush(struct lola *chip) | ||
221 | { | ||
222 | unsigned int tmp; | ||
223 | return rirb_get_response(chip, &tmp, NULL); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * interrupt handler | ||
228 | */ | ||
229 | static irqreturn_t lola_interrupt(int irq, void *dev_id) | ||
230 | { | ||
231 | struct lola *chip = dev_id; | ||
232 | unsigned int notify_ins, notify_outs, error_ins, error_outs; | ||
233 | int handled = 0; | ||
234 | int i; | ||
235 | |||
236 | notify_ins = notify_outs = error_ins = error_outs = 0; | ||
237 | spin_lock(&chip->reg_lock); | ||
238 | for (;;) { | ||
239 | unsigned int status, in_sts, out_sts; | ||
240 | unsigned int reg; | ||
241 | |||
242 | status = lola_readl(chip, BAR1, DINTSTS); | ||
243 | if (!status || status == -1) | ||
244 | break; | ||
245 | |||
246 | in_sts = lola_readl(chip, BAR1, DIINTSTS); | ||
247 | out_sts = lola_readl(chip, BAR1, DOINTSTS); | ||
248 | |||
249 | /* clear Input Interrupts */ | ||
250 | for (i = 0; in_sts && i < chip->pcm[CAPT].num_streams; i++) { | ||
251 | if (!(in_sts & (1 << i))) | ||
252 | continue; | ||
253 | in_sts &= ~(1 << i); | ||
254 | reg = lola_dsd_read(chip, i, STS); | ||
255 | if (reg & LOLA_DSD_STS_DESE) /* error */ | ||
256 | error_ins |= (1 << i); | ||
257 | if (reg & LOLA_DSD_STS_BCIS) /* notify */ | ||
258 | notify_ins |= (1 << i); | ||
259 | /* clear */ | ||
260 | lola_dsd_write(chip, i, STS, reg); | ||
261 | } | ||
262 | |||
263 | /* clear Output Interrupts */ | ||
264 | for (i = 0; out_sts && i < chip->pcm[PLAY].num_streams; i++) { | ||
265 | if (!(out_sts & (1 << i))) | ||
266 | continue; | ||
267 | out_sts &= ~(1 << i); | ||
268 | reg = lola_dsd_read(chip, i + MAX_STREAM_IN_COUNT, STS); | ||
269 | if (reg & LOLA_DSD_STS_DESE) /* error */ | ||
270 | error_outs |= (1 << i); | ||
271 | if (reg & LOLA_DSD_STS_BCIS) /* notify */ | ||
272 | notify_outs |= (1 << i); | ||
273 | lola_dsd_write(chip, i + MAX_STREAM_IN_COUNT, STS, reg); | ||
274 | } | ||
275 | |||
276 | if (status & LOLA_DINT_CTRL) { | ||
277 | unsigned char rbsts; /* ring status is byte access */ | ||
278 | rbsts = lola_readb(chip, BAR0, RIRBSTS); | ||
279 | rbsts &= LOLA_RIRB_INT_MASK; | ||
280 | if (rbsts) | ||
281 | lola_writeb(chip, BAR0, RIRBSTS, rbsts); | ||
282 | rbsts = lola_readb(chip, BAR0, CORBSTS); | ||
283 | rbsts &= LOLA_CORB_INT_MASK; | ||
284 | if (rbsts) | ||
285 | lola_writeb(chip, BAR0, CORBSTS, rbsts); | ||
286 | |||
287 | lola_update_rirb(chip); | ||
288 | } | ||
289 | |||
290 | if (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)) { | ||
291 | /* clear global fifo error interrupt */ | ||
292 | lola_writel(chip, BAR1, DINTSTS, | ||
293 | (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR))); | ||
294 | } | ||
295 | handled = 1; | ||
296 | } | ||
297 | spin_unlock(&chip->reg_lock); | ||
298 | |||
299 | lola_pcm_update(chip, &chip->pcm[CAPT], notify_ins); | ||
300 | lola_pcm_update(chip, &chip->pcm[PLAY], notify_outs); | ||
301 | |||
302 | return IRQ_RETVAL(handled); | ||
303 | } | ||
304 | |||
305 | |||
306 | /* | ||
307 | * controller | ||
308 | */ | ||
309 | static int reset_controller(struct lola *chip) | ||
310 | { | ||
311 | unsigned int gctl = lola_readl(chip, BAR0, GCTL); | ||
312 | unsigned long end_time; | ||
313 | |||
314 | if (gctl) { | ||
315 | /* to be sure */ | ||
316 | lola_writel(chip, BAR1, BOARD_MODE, 0); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | chip->cold_reset = 1; | ||
321 | lola_writel(chip, BAR0, GCTL, LOLA_GCTL_RESET); | ||
322 | end_time = jiffies + msecs_to_jiffies(200); | ||
323 | do { | ||
324 | msleep(1); | ||
325 | gctl = lola_readl(chip, BAR0, GCTL); | ||
326 | if (gctl) | ||
327 | break; | ||
328 | } while (time_before(jiffies, end_time)); | ||
329 | if (!gctl) { | ||
330 | printk(KERN_ERR SFX "cannot reset controller\n"); | ||
331 | return -EIO; | ||
332 | } | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static void lola_irq_enable(struct lola *chip) | ||
337 | { | ||
338 | unsigned int val; | ||
339 | |||
340 | /* enalbe all I/O streams */ | ||
341 | val = (1 << chip->pcm[PLAY].num_streams) - 1; | ||
342 | lola_writel(chip, BAR1, DOINTCTL, val); | ||
343 | val = (1 << chip->pcm[CAPT].num_streams) - 1; | ||
344 | lola_writel(chip, BAR1, DIINTCTL, val); | ||
345 | |||
346 | /* enable global irqs */ | ||
347 | val = LOLA_DINT_GLOBAL | LOLA_DINT_CTRL | LOLA_DINT_FIFOERR | | ||
348 | LOLA_DINT_MUERR; | ||
349 | lola_writel(chip, BAR1, DINTCTL, val); | ||
350 | } | ||
351 | |||
352 | static void lola_irq_disable(struct lola *chip) | ||
353 | { | ||
354 | lola_writel(chip, BAR1, DINTCTL, 0); | ||
355 | lola_writel(chip, BAR1, DIINTCTL, 0); | ||
356 | lola_writel(chip, BAR1, DOINTCTL, 0); | ||
357 | } | ||
358 | |||
359 | static int setup_corb_rirb(struct lola *chip) | ||
360 | { | ||
361 | int err; | ||
362 | unsigned char tmp; | ||
363 | unsigned long end_time; | ||
364 | |||
365 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | ||
366 | snd_dma_pci_data(chip->pci), | ||
367 | PAGE_SIZE, &chip->rb); | ||
368 | if (err < 0) | ||
369 | return err; | ||
370 | |||
371 | chip->corb.addr = chip->rb.addr; | ||
372 | chip->corb.buf = (u32 *)chip->rb.area; | ||
373 | chip->rirb.addr = chip->rb.addr + 2048; | ||
374 | chip->rirb.buf = (u32 *)(chip->rb.area + 2048); | ||
375 | |||
376 | /* disable ringbuffer DMAs */ | ||
377 | lola_writeb(chip, BAR0, RIRBCTL, 0); | ||
378 | lola_writeb(chip, BAR0, CORBCTL, 0); | ||
379 | |||
380 | end_time = jiffies + msecs_to_jiffies(200); | ||
381 | do { | ||
382 | if (!lola_readb(chip, BAR0, RIRBCTL) && | ||
383 | !lola_readb(chip, BAR0, CORBCTL)) | ||
384 | break; | ||
385 | msleep(1); | ||
386 | } while (time_before(jiffies, end_time)); | ||
387 | |||
388 | /* CORB set up */ | ||
389 | lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr); | ||
390 | lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr)); | ||
391 | /* set the corb size to 256 entries */ | ||
392 | lola_writeb(chip, BAR0, CORBSIZE, 0x02); | ||
393 | /* set the corb write pointer to 0 */ | ||
394 | lola_writew(chip, BAR0, CORBWP, 0); | ||
395 | /* reset the corb hw read pointer */ | ||
396 | lola_writew(chip, BAR0, CORBRP, LOLA_RBRWP_CLR); | ||
397 | /* enable corb dma */ | ||
398 | lola_writeb(chip, BAR0, CORBCTL, LOLA_RBCTL_DMA_EN); | ||
399 | /* clear flags if set */ | ||
400 | tmp = lola_readb(chip, BAR0, CORBSTS) & LOLA_CORB_INT_MASK; | ||
401 | if (tmp) | ||
402 | lola_writeb(chip, BAR0, CORBSTS, tmp); | ||
403 | chip->corb.wp = 0; | ||
404 | |||
405 | /* RIRB set up */ | ||
406 | lola_writel(chip, BAR0, RIRBLBASE, (u32)chip->rirb.addr); | ||
407 | lola_writel(chip, BAR0, RIRBUBASE, upper_32_bits(chip->rirb.addr)); | ||
408 | /* set the rirb size to 256 entries */ | ||
409 | lola_writeb(chip, BAR0, RIRBSIZE, 0x02); | ||
410 | /* reset the rirb hw write pointer */ | ||
411 | lola_writew(chip, BAR0, RIRBWP, LOLA_RBRWP_CLR); | ||
412 | /* set N=1, get RIRB response interrupt for new entry */ | ||
413 | lola_writew(chip, BAR0, RINTCNT, 1); | ||
414 | /* enable rirb dma and response irq */ | ||
415 | lola_writeb(chip, BAR0, RIRBCTL, LOLA_RBCTL_DMA_EN | LOLA_RBCTL_IRQ_EN); | ||
416 | /* clear flags if set */ | ||
417 | tmp = lola_readb(chip, BAR0, RIRBSTS) & LOLA_RIRB_INT_MASK; | ||
418 | if (tmp) | ||
419 | lola_writeb(chip, BAR0, RIRBSTS, tmp); | ||
420 | chip->rirb.rp = chip->rirb.cmds = 0; | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static void stop_corb_rirb(struct lola *chip) | ||
426 | { | ||
427 | /* disable ringbuffer DMAs */ | ||
428 | lola_writeb(chip, BAR0, RIRBCTL, 0); | ||
429 | lola_writeb(chip, BAR0, CORBCTL, 0); | ||
430 | } | ||
431 | |||
432 | static void lola_reset_setups(struct lola *chip) | ||
433 | { | ||
434 | /* update the granularity */ | ||
435 | lola_set_granularity(chip, chip->granularity, true); | ||
436 | /* update the sample clock */ | ||
437 | lola_set_clock_index(chip, chip->clock.cur_index); | ||
438 | /* enable unsolicited events of the clock widget */ | ||
439 | lola_enable_clock_events(chip); | ||
440 | /* update the analog gains */ | ||
441 | lola_setup_all_analog_gains(chip, CAPT, false); /* input, update */ | ||
442 | /* update SRC configuration if applicable */ | ||
443 | lola_set_src_config(chip, chip->input_src_mask, false); | ||
444 | /* update the analog outputs */ | ||
445 | lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */ | ||
446 | } | ||
447 | |||
448 | static int lola_parse_tree(struct lola *chip) | ||
449 | { | ||
450 | unsigned int val; | ||
451 | int nid, err; | ||
452 | |||
453 | err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val); | ||
454 | if (err < 0) { | ||
455 | printk(KERN_ERR SFX "Can't read VENDOR_ID\n"); | ||
456 | return err; | ||
457 | } | ||
458 | val >>= 16; | ||
459 | if (val != 0x1369) { | ||
460 | printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val); | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | |||
464 | err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val); | ||
465 | if (err < 0) { | ||
466 | printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid); | ||
467 | return err; | ||
468 | } | ||
469 | if (val != 1) { | ||
470 | printk(KERN_ERR SFX "Unknown function type %d\n", val); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val); | ||
475 | if (err < 0) { | ||
476 | printk(KERN_ERR SFX "Can't read SPECCAPS\n"); | ||
477 | return err; | ||
478 | } | ||
479 | chip->lola_caps = val; | ||
480 | chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps); | ||
481 | chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps); | ||
482 | snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n", | ||
483 | chip->lola_caps, | ||
484 | chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins); | ||
485 | |||
486 | if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT || | ||
487 | chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) { | ||
488 | printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val); | ||
489 | return -EINVAL; | ||
490 | } | ||
491 | |||
492 | nid = 0x02; | ||
493 | err = lola_init_pcm(chip, CAPT, &nid); | ||
494 | if (err < 0) | ||
495 | return err; | ||
496 | err = lola_init_pcm(chip, PLAY, &nid); | ||
497 | if (err < 0) | ||
498 | return err; | ||
499 | |||
500 | err = lola_init_pins(chip, CAPT, &nid); | ||
501 | if (err < 0) | ||
502 | return err; | ||
503 | err = lola_init_pins(chip, PLAY, &nid); | ||
504 | if (err < 0) | ||
505 | return err; | ||
506 | |||
507 | if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) { | ||
508 | err = lola_init_clock_widget(chip, nid); | ||
509 | if (err < 0) | ||
510 | return err; | ||
511 | nid++; | ||
512 | } | ||
513 | if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) { | ||
514 | err = lola_init_mixer_widget(chip, nid); | ||
515 | if (err < 0) | ||
516 | return err; | ||
517 | nid++; | ||
518 | } | ||
519 | |||
520 | /* enable unsolicited events of the clock widget */ | ||
521 | err = lola_enable_clock_events(chip); | ||
522 | if (err < 0) | ||
523 | return err; | ||
524 | |||
525 | /* if last ResetController was not a ColdReset, we don't know | ||
526 | * the state of the card; initialize here again | ||
527 | */ | ||
528 | if (!chip->cold_reset) { | ||
529 | lola_reset_setups(chip); | ||
530 | chip->cold_reset = 1; | ||
531 | } else { | ||
532 | /* set the granularity if it is not the default */ | ||
533 | if (chip->granularity != LOLA_GRANULARITY_MIN) | ||
534 | lola_set_granularity(chip, chip->granularity, true); | ||
535 | } | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static void lola_stop_hw(struct lola *chip) | ||
541 | { | ||
542 | stop_corb_rirb(chip); | ||
543 | lola_irq_disable(chip); | ||
544 | } | ||
545 | |||
546 | static void lola_free(struct lola *chip) | ||
547 | { | ||
548 | if (chip->initialized) | ||
549 | lola_stop_hw(chip); | ||
550 | lola_free_pcm(chip); | ||
551 | lola_free_mixer(chip); | ||
552 | if (chip->irq >= 0) | ||
553 | free_irq(chip->irq, (void *)chip); | ||
554 | if (chip->bar[0].remap_addr) | ||
555 | iounmap(chip->bar[0].remap_addr); | ||
556 | if (chip->bar[1].remap_addr) | ||
557 | iounmap(chip->bar[1].remap_addr); | ||
558 | if (chip->rb.area) | ||
559 | snd_dma_free_pages(&chip->rb); | ||
560 | pci_release_regions(chip->pci); | ||
561 | pci_disable_device(chip->pci); | ||
562 | kfree(chip); | ||
563 | } | ||
564 | |||
565 | static int lola_dev_free(struct snd_device *device) | ||
566 | { | ||
567 | lola_free(device->device_data); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci, | ||
572 | int dev, struct lola **rchip) | ||
573 | { | ||
574 | struct lola *chip; | ||
575 | int err; | ||
576 | unsigned int dever; | ||
577 | static struct snd_device_ops ops = { | ||
578 | .dev_free = lola_dev_free, | ||
579 | }; | ||
580 | |||
581 | *rchip = NULL; | ||
582 | |||
583 | err = pci_enable_device(pci); | ||
584 | if (err < 0) | ||
585 | return err; | ||
586 | |||
587 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
588 | if (!chip) { | ||
589 | snd_printk(KERN_ERR SFX "cannot allocate chip\n"); | ||
590 | pci_disable_device(pci); | ||
591 | return -ENOMEM; | ||
592 | } | ||
593 | |||
594 | spin_lock_init(&chip->reg_lock); | ||
595 | mutex_init(&chip->open_mutex); | ||
596 | chip->card = card; | ||
597 | chip->pci = pci; | ||
598 | chip->irq = -1; | ||
599 | |||
600 | chip->granularity = granularity[dev]; | ||
601 | switch (chip->granularity) { | ||
602 | case 8: | ||
603 | chip->sample_rate_max = 48000; | ||
604 | break; | ||
605 | case 16: | ||
606 | chip->sample_rate_max = 96000; | ||
607 | break; | ||
608 | case 32: | ||
609 | chip->sample_rate_max = 192000; | ||
610 | break; | ||
611 | default: | ||
612 | snd_printk(KERN_WARNING SFX | ||
613 | "Invalid granularity %d, reset to %d\n", | ||
614 | chip->granularity, LOLA_GRANULARITY_MAX); | ||
615 | chip->granularity = LOLA_GRANULARITY_MAX; | ||
616 | chip->sample_rate_max = 192000; | ||
617 | break; | ||
618 | } | ||
619 | chip->sample_rate_min = sample_rate_min[dev]; | ||
620 | if (chip->sample_rate_min > chip->sample_rate_max) { | ||
621 | snd_printk(KERN_WARNING SFX | ||
622 | "Invalid sample_rate_min %d, reset to 16000\n", | ||
623 | chip->sample_rate_min); | ||
624 | chip->sample_rate_min = 16000; | ||
625 | } | ||
626 | |||
627 | err = pci_request_regions(pci, DRVNAME); | ||
628 | if (err < 0) { | ||
629 | kfree(chip); | ||
630 | pci_disable_device(pci); | ||
631 | return err; | ||
632 | } | ||
633 | |||
634 | chip->bar[0].addr = pci_resource_start(pci, 0); | ||
635 | chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0); | ||
636 | chip->bar[1].addr = pci_resource_start(pci, 2); | ||
637 | chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2); | ||
638 | if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) { | ||
639 | snd_printk(KERN_ERR SFX "ioremap error\n"); | ||
640 | err = -ENXIO; | ||
641 | goto errout; | ||
642 | } | ||
643 | |||
644 | pci_set_master(pci); | ||
645 | |||
646 | err = reset_controller(chip); | ||
647 | if (err < 0) | ||
648 | goto errout; | ||
649 | |||
650 | if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED, | ||
651 | DRVNAME, chip)) { | ||
652 | printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); | ||
653 | err = -EBUSY; | ||
654 | goto errout; | ||
655 | } | ||
656 | chip->irq = pci->irq; | ||
657 | synchronize_irq(chip->irq); | ||
658 | |||
659 | dever = lola_readl(chip, BAR1, DEVER); | ||
660 | chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff; | ||
661 | chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff; | ||
662 | chip->version = (dever >> 24) & 0xff; | ||
663 | snd_printdd(SFX "streams in=%d, out=%d, version=0x%x\n", | ||
664 | chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams, | ||
665 | chip->version); | ||
666 | |||
667 | /* Test LOLA_BAR1_DEVER */ | ||
668 | if (chip->pcm[CAPT].num_streams > MAX_STREAM_IN_COUNT || | ||
669 | chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT || | ||
670 | (!chip->pcm[CAPT].num_streams && | ||
671 | !chip->pcm[PLAY].num_streams)) { | ||
672 | printk(KERN_ERR SFX "invalid DEVER = %x\n", dever); | ||
673 | err = -EINVAL; | ||
674 | goto errout; | ||
675 | } | ||
676 | |||
677 | err = setup_corb_rirb(chip); | ||
678 | if (err < 0) | ||
679 | goto errout; | ||
680 | |||
681 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
682 | if (err < 0) { | ||
683 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); | ||
684 | goto errout; | ||
685 | } | ||
686 | |||
687 | strcpy(card->driver, "Lola"); | ||
688 | strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname)); | ||
689 | snprintf(card->longname, sizeof(card->longname), | ||
690 | "%s at 0x%lx irq %i", | ||
691 | card->shortname, chip->bar[0].addr, chip->irq); | ||
692 | strcpy(card->mixername, card->shortname); | ||
693 | |||
694 | lola_irq_enable(chip); | ||
695 | |||
696 | chip->initialized = 1; | ||
697 | *rchip = chip; | ||
698 | return 0; | ||
699 | |||
700 | errout: | ||
701 | lola_free(chip); | ||
702 | return err; | ||
703 | } | ||
704 | |||
705 | static int __devinit lola_probe(struct pci_dev *pci, | ||
706 | const struct pci_device_id *pci_id) | ||
707 | { | ||
708 | static int dev; | ||
709 | struct snd_card *card; | ||
710 | struct lola *chip; | ||
711 | int err; | ||
712 | |||
713 | if (dev >= SNDRV_CARDS) | ||
714 | return -ENODEV; | ||
715 | if (!enable[dev]) { | ||
716 | dev++; | ||
717 | return -ENOENT; | ||
718 | } | ||
719 | |||
720 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); | ||
721 | if (err < 0) { | ||
722 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | ||
723 | return err; | ||
724 | } | ||
725 | |||
726 | snd_card_set_dev(card, &pci->dev); | ||
727 | |||
728 | err = lola_create(card, pci, dev, &chip); | ||
729 | if (err < 0) | ||
730 | goto out_free; | ||
731 | card->private_data = chip; | ||
732 | |||
733 | err = lola_parse_tree(chip); | ||
734 | if (err < 0) | ||
735 | goto out_free; | ||
736 | |||
737 | err = lola_create_pcm(chip); | ||
738 | if (err < 0) | ||
739 | goto out_free; | ||
740 | |||
741 | err = lola_create_mixer(chip); | ||
742 | if (err < 0) | ||
743 | goto out_free; | ||
744 | |||
745 | lola_proc_debug_new(chip); | ||
746 | |||
747 | err = snd_card_register(card); | ||
748 | if (err < 0) | ||
749 | goto out_free; | ||
750 | |||
751 | pci_set_drvdata(pci, card); | ||
752 | dev++; | ||
753 | return err; | ||
754 | out_free: | ||
755 | snd_card_free(card); | ||
756 | return err; | ||
757 | } | ||
758 | |||
759 | static void __devexit lola_remove(struct pci_dev *pci) | ||
760 | { | ||
761 | snd_card_free(pci_get_drvdata(pci)); | ||
762 | pci_set_drvdata(pci, NULL); | ||
763 | } | ||
764 | |||
765 | /* PCI IDs */ | ||
766 | static DEFINE_PCI_DEVICE_TABLE(lola_ids) = { | ||
767 | { PCI_VDEVICE(DIGIGRAM, 0x0001) }, | ||
768 | { 0, } | ||
769 | }; | ||
770 | MODULE_DEVICE_TABLE(pci, lola_ids); | ||
771 | |||
772 | /* pci_driver definition */ | ||
773 | static struct pci_driver driver = { | ||
774 | .name = DRVNAME, | ||
775 | .id_table = lola_ids, | ||
776 | .probe = lola_probe, | ||
777 | .remove = __devexit_p(lola_remove), | ||
778 | }; | ||
779 | |||
780 | static int __init alsa_card_lola_init(void) | ||
781 | { | ||
782 | return pci_register_driver(&driver); | ||
783 | } | ||
784 | |||
785 | static void __exit alsa_card_lola_exit(void) | ||
786 | { | ||
787 | pci_unregister_driver(&driver); | ||
788 | } | ||
789 | |||
790 | module_init(alsa_card_lola_init) | ||
791 | module_exit(alsa_card_lola_exit) | ||
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h new file mode 100644 index 000000000000..d5708e29b16d --- /dev/null +++ b/sound/pci/lola/lola.h | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _LOLA_H | ||
22 | #define _LOLA_H | ||
23 | |||
24 | #define DRVNAME "snd-lola" | ||
25 | #define SFX DRVNAME ": " | ||
26 | |||
27 | /* | ||
28 | * Lola HD Audio Registers BAR0 | ||
29 | */ | ||
30 | #define LOLA_BAR0_GCAP 0x00 | ||
31 | #define LOLA_BAR0_VMIN 0x02 | ||
32 | #define LOLA_BAR0_VMAJ 0x03 | ||
33 | #define LOLA_BAR0_OUTPAY 0x04 | ||
34 | #define LOLA_BAR0_INPAY 0x06 | ||
35 | #define LOLA_BAR0_GCTL 0x08 | ||
36 | #define LOLA_BAR0_WAKEEN 0x0c | ||
37 | #define LOLA_BAR0_STATESTS 0x0e | ||
38 | #define LOLA_BAR0_GSTS 0x10 | ||
39 | #define LOLA_BAR0_OUTSTRMPAY 0x18 | ||
40 | #define LOLA_BAR0_INSTRMPAY 0x1a | ||
41 | #define LOLA_BAR0_INTCTL 0x20 | ||
42 | #define LOLA_BAR0_INTSTS 0x24 | ||
43 | #define LOLA_BAR0_WALCLK 0x30 | ||
44 | #define LOLA_BAR0_SSYNC 0x38 | ||
45 | |||
46 | #define LOLA_BAR0_CORBLBASE 0x40 | ||
47 | #define LOLA_BAR0_CORBUBASE 0x44 | ||
48 | #define LOLA_BAR0_CORBWP 0x48 /* no ULONG access */ | ||
49 | #define LOLA_BAR0_CORBRP 0x4a /* no ULONG access */ | ||
50 | #define LOLA_BAR0_CORBCTL 0x4c /* no ULONG access */ | ||
51 | #define LOLA_BAR0_CORBSTS 0x4d /* UCHAR access only */ | ||
52 | #define LOLA_BAR0_CORBSIZE 0x4e /* no ULONG access */ | ||
53 | |||
54 | #define LOLA_BAR0_RIRBLBASE 0x50 | ||
55 | #define LOLA_BAR0_RIRBUBASE 0x54 | ||
56 | #define LOLA_BAR0_RIRBWP 0x58 | ||
57 | #define LOLA_BAR0_RINTCNT 0x5a /* no ULONG access */ | ||
58 | #define LOLA_BAR0_RIRBCTL 0x5c | ||
59 | #define LOLA_BAR0_RIRBSTS 0x5d /* UCHAR access only */ | ||
60 | #define LOLA_BAR0_RIRBSIZE 0x5e /* no ULONG access */ | ||
61 | |||
62 | #define LOLA_BAR0_ICW 0x60 | ||
63 | #define LOLA_BAR0_IRR 0x64 | ||
64 | #define LOLA_BAR0_ICS 0x68 | ||
65 | #define LOLA_BAR0_DPLBASE 0x70 | ||
66 | #define LOLA_BAR0_DPUBASE 0x74 | ||
67 | |||
68 | /* stream register offsets from stream base 0x80 */ | ||
69 | #define LOLA_BAR0_SD0_OFFSET 0x80 | ||
70 | #define LOLA_REG0_SD_CTL 0x00 | ||
71 | #define LOLA_REG0_SD_STS 0x03 | ||
72 | #define LOLA_REG0_SD_LPIB 0x04 | ||
73 | #define LOLA_REG0_SD_CBL 0x08 | ||
74 | #define LOLA_REG0_SD_LVI 0x0c | ||
75 | #define LOLA_REG0_SD_FIFOW 0x0e | ||
76 | #define LOLA_REG0_SD_FIFOSIZE 0x10 | ||
77 | #define LOLA_REG0_SD_FORMAT 0x12 | ||
78 | #define LOLA_REG0_SD_BDLPL 0x18 | ||
79 | #define LOLA_REG0_SD_BDLPU 0x1c | ||
80 | |||
81 | /* | ||
82 | * Lola Digigram Registers BAR1 | ||
83 | */ | ||
84 | #define LOLA_BAR1_FPGAVER 0x00 | ||
85 | #define LOLA_BAR1_DEVER 0x04 | ||
86 | #define LOLA_BAR1_UCBMV 0x08 | ||
87 | #define LOLA_BAR1_JTAG 0x0c | ||
88 | #define LOLA_BAR1_UARTRX 0x10 | ||
89 | #define LOLA_BAR1_UARTTX 0x14 | ||
90 | #define LOLA_BAR1_UARTCR 0x18 | ||
91 | #define LOLA_BAR1_NVRAMVER 0x1c | ||
92 | #define LOLA_BAR1_CTRLSPI 0x20 | ||
93 | #define LOLA_BAR1_DSPI 0x24 | ||
94 | #define LOLA_BAR1_AISPI 0x28 | ||
95 | #define LOLA_BAR1_GRAN 0x2c | ||
96 | |||
97 | #define LOLA_BAR1_DINTCTL 0x80 | ||
98 | #define LOLA_BAR1_DIINTCTL 0x84 | ||
99 | #define LOLA_BAR1_DOINTCTL 0x88 | ||
100 | #define LOLA_BAR1_LRC 0x90 | ||
101 | #define LOLA_BAR1_DINTSTS 0x94 | ||
102 | #define LOLA_BAR1_DIINTSTS 0x98 | ||
103 | #define LOLA_BAR1_DOINTSTS 0x9c | ||
104 | |||
105 | #define LOLA_BAR1_DSD0_OFFSET 0xa0 | ||
106 | #define LOLA_BAR1_DSD_SIZE 0x18 | ||
107 | |||
108 | #define LOLA_BAR1_DSDnSTS 0x00 | ||
109 | #define LOLA_BAR1_DSDnLPIB 0x04 | ||
110 | #define LOLA_BAR1_DSDnCTL 0x08 | ||
111 | #define LOLA_BAR1_DSDnLVI 0x0c | ||
112 | #define LOLA_BAR1_DSDnBDPL 0x10 | ||
113 | #define LOLA_BAR1_DSDnBDPU 0x14 | ||
114 | |||
115 | #define LOLA_BAR1_SSYNC 0x03e8 | ||
116 | |||
117 | #define LOLA_BAR1_BOARD_CTRL 0x0f00 | ||
118 | #define LOLA_BAR1_BOARD_MODE 0x0f02 | ||
119 | |||
120 | #define LOLA_BAR1_SOURCE_GAIN_ENABLE 0x1000 | ||
121 | #define LOLA_BAR1_DEST00_MIX_GAIN_ENABLE 0x1004 | ||
122 | #define LOLA_BAR1_DEST31_MIX_GAIN_ENABLE 0x1080 | ||
123 | #define LOLA_BAR1_SOURCE00_01_GAIN 0x1084 | ||
124 | #define LOLA_BAR1_SOURCE30_31_GAIN 0x10c0 | ||
125 | #define LOLA_BAR1_SOURCE_GAIN(src) \ | ||
126 | (LOLA_BAR1_SOURCE00_01_GAIN + (src) * 2) | ||
127 | #define LOLA_BAR1_DEST00_MIX00_01_GAIN 0x10c4 | ||
128 | #define LOLA_BAR1_DEST00_MIX30_31_GAIN 0x1100 | ||
129 | #define LOLA_BAR1_DEST01_MIX00_01_GAIN 0x1104 | ||
130 | #define LOLA_BAR1_DEST01_MIX30_31_GAIN 0x1140 | ||
131 | #define LOLA_BAR1_DEST31_MIX00_01_GAIN 0x1884 | ||
132 | #define LOLA_BAR1_DEST31_MIX30_31_GAIN 0x18c0 | ||
133 | #define LOLA_BAR1_MIX_GAIN(dest, mix) \ | ||
134 | (LOLA_BAR1_DEST00_MIX00_01_GAIN + (dest) * 0x40 + (mix) * 2) | ||
135 | #define LOLA_BAR1_ANALOG_CLIP_IN 0x18c4 | ||
136 | #define LOLA_BAR1_PEAKMETERS_SOURCE00_01 0x18c8 | ||
137 | #define LOLA_BAR1_PEAKMETERS_SOURCE30_31 0x1904 | ||
138 | #define LOLA_BAR1_PEAKMETERS_SOURCE(src) \ | ||
139 | (LOLA_BAR1_PEAKMETERS_SOURCE00_01 + (src) * 2) | ||
140 | #define LOLA_BAR1_PEAKMETERS_DEST00_01 0x1908 | ||
141 | #define LOLA_BAR1_PEAKMETERS_DEST30_31 0x1944 | ||
142 | #define LOLA_BAR1_PEAKMETERS_DEST(dest) \ | ||
143 | (LOLA_BAR1_PEAKMETERS_DEST00_01 + (dest) * 2) | ||
144 | #define LOLA_BAR1_PEAKMETERS_AGC00_01 0x1948 | ||
145 | #define LOLA_BAR1_PEAKMETERS_AGC14_15 0x1964 | ||
146 | #define LOLA_BAR1_PEAKMETERS_AGC(x) \ | ||
147 | (LOLA_BAR1_PEAKMETERS_AGC00_01 + (x) * 2) | ||
148 | |||
149 | /* GCTL reset bit */ | ||
150 | #define LOLA_GCTL_RESET (1 << 0) | ||
151 | /* GCTL unsolicited response enable bit */ | ||
152 | #define LOLA_GCTL_UREN (1 << 8) | ||
153 | |||
154 | /* CORB/RIRB control, read/write pointer */ | ||
155 | #define LOLA_RBCTL_DMA_EN 0x02 /* enable DMA */ | ||
156 | #define LOLA_RBCTL_IRQ_EN 0x01 /* enable IRQ */ | ||
157 | #define LOLA_RBRWP_CLR 0x8000 /* read/write pointer clear */ | ||
158 | |||
159 | #define LOLA_RIRB_EX_UNSOL_EV 0x40000000 | ||
160 | #define LOLA_RIRB_EX_ERROR 0x80000000 | ||
161 | |||
162 | /* CORB int mask: CMEI[0] */ | ||
163 | #define LOLA_CORB_INT_CMEI 0x01 | ||
164 | #define LOLA_CORB_INT_MASK LOLA_CORB_INT_CMEI | ||
165 | |||
166 | /* RIRB int mask: overrun[2], response[0] */ | ||
167 | #define LOLA_RIRB_INT_RESPONSE 0x01 | ||
168 | #define LOLA_RIRB_INT_OVERRUN 0x04 | ||
169 | #define LOLA_RIRB_INT_MASK (LOLA_RIRB_INT_RESPONSE | LOLA_RIRB_INT_OVERRUN) | ||
170 | |||
171 | /* DINTCTL and DINTSTS */ | ||
172 | #define LOLA_DINT_GLOBAL 0x80000000 /* global interrupt enable bit */ | ||
173 | #define LOLA_DINT_CTRL 0x40000000 /* controller interrupt enable bit */ | ||
174 | #define LOLA_DINT_FIFOERR 0x20000000 /* global fifo error enable bit */ | ||
175 | #define LOLA_DINT_MUERR 0x10000000 /* global microcontroller underrun error */ | ||
176 | |||
177 | /* DSDnCTL bits */ | ||
178 | #define LOLA_DSD_CTL_SRST 0x01 /* stream reset bit */ | ||
179 | #define LOLA_DSD_CTL_SRUN 0x02 /* stream DMA start bit */ | ||
180 | #define LOLA_DSD_CTL_IOCE 0x04 /* interrupt on completion enable */ | ||
181 | #define LOLA_DSD_CTL_DEIE 0x10 /* descriptor error interrupt enable */ | ||
182 | #define LOLA_DSD_CTL_VLRCV 0x20 /* valid LRCountValue information in bits 8..31 */ | ||
183 | #define LOLA_LRC_MASK 0xffffff00 | ||
184 | |||
185 | /* DSDnSTS */ | ||
186 | #define LOLA_DSD_STS_BCIS 0x04 /* buffer completion interrupt status */ | ||
187 | #define LOLA_DSD_STS_DESE 0x10 /* descriptor error interrupt */ | ||
188 | #define LOLA_DSD_STS_FIFORDY 0x20 /* fifo ready */ | ||
189 | |||
190 | #define LOLA_CORB_ENTRIES 256 | ||
191 | |||
192 | #define MAX_STREAM_IN_COUNT 16 | ||
193 | #define MAX_STREAM_OUT_COUNT 16 | ||
194 | #define MAX_STREAM_COUNT 16 | ||
195 | #define MAX_PINS MAX_STREAM_COUNT | ||
196 | #define MAX_STREAM_BUFFER_COUNT 16 | ||
197 | #define MAX_AUDIO_INOUT_COUNT 16 | ||
198 | |||
199 | #define LOLA_CLOCK_TYPE_INTERNAL 0 | ||
200 | #define LOLA_CLOCK_TYPE_AES 1 | ||
201 | #define LOLA_CLOCK_TYPE_AES_SYNC 2 | ||
202 | #define LOLA_CLOCK_TYPE_WORDCLOCK 3 | ||
203 | #define LOLA_CLOCK_TYPE_ETHERSOUND 4 | ||
204 | #define LOLA_CLOCK_TYPE_VIDEO 5 | ||
205 | |||
206 | #define LOLA_CLOCK_FORMAT_NONE 0 | ||
207 | #define LOLA_CLOCK_FORMAT_NTSC 1 | ||
208 | #define LOLA_CLOCK_FORMAT_PAL 2 | ||
209 | |||
210 | #define MAX_SAMPLE_CLOCK_COUNT 48 | ||
211 | |||
212 | /* parameters used with mixer widget's mixer capabilities */ | ||
213 | #define LOLA_PEAK_METER_CAN_AGC_MASK 1 | ||
214 | #define LOLA_PEAK_METER_CAN_ANALOG_CLIP_MASK 2 | ||
215 | |||
216 | struct lola_bar { | ||
217 | unsigned long addr; | ||
218 | void __iomem *remap_addr; | ||
219 | }; | ||
220 | |||
221 | /* CORB/RIRB */ | ||
222 | struct lola_rb { | ||
223 | u32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */ | ||
224 | dma_addr_t addr; /* physical address of CORB/RIRB buffer */ | ||
225 | unsigned short rp, wp; /* read/write pointers */ | ||
226 | int cmds; /* number of pending requests */ | ||
227 | }; | ||
228 | |||
229 | /* Pin widget setup */ | ||
230 | struct lola_pin { | ||
231 | unsigned int nid; | ||
232 | bool is_analog; | ||
233 | unsigned int amp_mute; | ||
234 | unsigned int amp_step_size; | ||
235 | unsigned int amp_num_steps; | ||
236 | unsigned int amp_offset; | ||
237 | unsigned int max_level; | ||
238 | unsigned int config_default_reg; | ||
239 | unsigned int fixed_gain_list_len; | ||
240 | unsigned int cur_gain_step; | ||
241 | }; | ||
242 | |||
243 | struct lola_pin_array { | ||
244 | unsigned int num_pins; | ||
245 | unsigned int num_analog_pins; | ||
246 | struct lola_pin pins[MAX_PINS]; | ||
247 | }; | ||
248 | |||
249 | /* Clock widget setup */ | ||
250 | struct lola_sample_clock { | ||
251 | unsigned int type; | ||
252 | unsigned int format; | ||
253 | unsigned int freq; | ||
254 | }; | ||
255 | |||
256 | struct lola_clock_widget { | ||
257 | unsigned int nid; | ||
258 | unsigned int items; | ||
259 | unsigned int cur_index; | ||
260 | unsigned int cur_freq; | ||
261 | bool cur_valid; | ||
262 | struct lola_sample_clock sample_clock[MAX_SAMPLE_CLOCK_COUNT]; | ||
263 | unsigned int idx_lookup[MAX_SAMPLE_CLOCK_COUNT]; | ||
264 | }; | ||
265 | |||
266 | #define LOLA_MIXER_DIM 32 | ||
267 | struct lola_mixer_array { | ||
268 | u32 src_gain_enable; | ||
269 | u32 dest_mix_gain_enable[LOLA_MIXER_DIM]; | ||
270 | u16 src_gain[LOLA_MIXER_DIM]; | ||
271 | u16 dest_mix_gain[LOLA_MIXER_DIM][LOLA_MIXER_DIM]; | ||
272 | }; | ||
273 | |||
274 | /* Mixer widget setup */ | ||
275 | struct lola_mixer_widget { | ||
276 | unsigned int nid; | ||
277 | unsigned int caps; | ||
278 | struct lola_mixer_array __user *array; | ||
279 | struct lola_mixer_array *array_saved; | ||
280 | unsigned int src_stream_outs; | ||
281 | unsigned int src_phys_ins; | ||
282 | unsigned int dest_stream_ins; | ||
283 | unsigned int dest_phys_outs; | ||
284 | unsigned int src_stream_out_ofs; | ||
285 | unsigned int dest_phys_out_ofs; | ||
286 | unsigned int src_mask; | ||
287 | unsigned int dest_mask; | ||
288 | }; | ||
289 | |||
290 | /* Audio stream */ | ||
291 | struct lola_stream { | ||
292 | unsigned int nid; /* audio widget NID */ | ||
293 | unsigned int index; /* array index */ | ||
294 | unsigned int dsd; /* DSD index */ | ||
295 | bool can_float; | ||
296 | struct snd_pcm_substream *substream; /* assigned PCM substream */ | ||
297 | struct lola_stream *master; /* master stream (for multi-channel) */ | ||
298 | |||
299 | /* buffer setup */ | ||
300 | unsigned int bufsize; | ||
301 | unsigned int period_bytes; | ||
302 | unsigned int frags; | ||
303 | |||
304 | /* format + channel setup */ | ||
305 | unsigned int format_verb; | ||
306 | |||
307 | /* flags */ | ||
308 | unsigned int opened:1; | ||
309 | unsigned int prepared:1; | ||
310 | unsigned int paused:1; | ||
311 | unsigned int running:1; | ||
312 | }; | ||
313 | |||
314 | #define PLAY SNDRV_PCM_STREAM_PLAYBACK | ||
315 | #define CAPT SNDRV_PCM_STREAM_CAPTURE | ||
316 | |||
317 | struct lola_pcm { | ||
318 | unsigned int num_streams; | ||
319 | struct snd_dma_buffer bdl; /* BDL buffer */ | ||
320 | struct lola_stream streams[MAX_STREAM_COUNT]; | ||
321 | }; | ||
322 | |||
323 | /* card instance */ | ||
324 | struct lola { | ||
325 | struct snd_card *card; | ||
326 | struct pci_dev *pci; | ||
327 | |||
328 | /* pci resources */ | ||
329 | struct lola_bar bar[2]; | ||
330 | int irq; | ||
331 | |||
332 | /* locks */ | ||
333 | spinlock_t reg_lock; | ||
334 | struct mutex open_mutex; | ||
335 | |||
336 | /* CORB/RIRB */ | ||
337 | struct lola_rb corb; | ||
338 | struct lola_rb rirb; | ||
339 | unsigned int res, res_ex; /* last read values */ | ||
340 | /* last command (for debugging) */ | ||
341 | unsigned int last_cmd_nid, last_verb, last_data, last_extdata; | ||
342 | |||
343 | /* CORB/RIRB buffers */ | ||
344 | struct snd_dma_buffer rb; | ||
345 | |||
346 | /* unsolicited events */ | ||
347 | unsigned int last_unsol_res; | ||
348 | |||
349 | /* streams */ | ||
350 | struct lola_pcm pcm[2]; | ||
351 | |||
352 | /* input src */ | ||
353 | unsigned int input_src_caps_mask; | ||
354 | unsigned int input_src_mask; | ||
355 | |||
356 | /* pins */ | ||
357 | struct lola_pin_array pin[2]; | ||
358 | |||
359 | /* clock */ | ||
360 | struct lola_clock_widget clock; | ||
361 | int ref_count_rate; | ||
362 | unsigned int sample_rate; | ||
363 | |||
364 | /* mixer */ | ||
365 | struct lola_mixer_widget mixer; | ||
366 | |||
367 | /* hw info */ | ||
368 | unsigned int version; | ||
369 | unsigned int lola_caps; | ||
370 | |||
371 | /* parameters */ | ||
372 | unsigned int granularity; | ||
373 | unsigned int sample_rate_min; | ||
374 | unsigned int sample_rate_max; | ||
375 | |||
376 | /* flags */ | ||
377 | unsigned int initialized:1; | ||
378 | unsigned int cold_reset:1; | ||
379 | unsigned int polling_mode:1; | ||
380 | |||
381 | /* for debugging */ | ||
382 | unsigned int debug_res; | ||
383 | unsigned int debug_res_ex; | ||
384 | }; | ||
385 | |||
386 | #define BAR0 0 | ||
387 | #define BAR1 1 | ||
388 | |||
389 | /* Helper macros */ | ||
390 | #define lola_readl(chip, idx, name) \ | ||
391 | readl((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
392 | #define lola_readw(chip, idx, name) \ | ||
393 | readw((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
394 | #define lola_readb(chip, idx, name) \ | ||
395 | readb((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
396 | #define lola_writel(chip, idx, name, val) \ | ||
397 | writel((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
398 | #define lola_writew(chip, idx, name, val) \ | ||
399 | writew((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
400 | #define lola_writeb(chip, idx, name, val) \ | ||
401 | writeb((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) | ||
402 | |||
403 | #define lola_dsd_read(chip, dsd, name) \ | ||
404 | readl((chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \ | ||
405 | (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name) | ||
406 | #define lola_dsd_write(chip, dsd, name, val) \ | ||
407 | writel((val), (chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \ | ||
408 | (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name) | ||
409 | |||
410 | /* GET verbs HDAudio */ | ||
411 | #define LOLA_VERB_GET_STREAM_FORMAT 0xa00 | ||
412 | #define LOLA_VERB_GET_AMP_GAIN_MUTE 0xb00 | ||
413 | #define LOLA_VERB_PARAMETERS 0xf00 | ||
414 | #define LOLA_VERB_GET_POWER_STATE 0xf05 | ||
415 | #define LOLA_VERB_GET_CONV 0xf06 | ||
416 | #define LOLA_VERB_GET_UNSOLICITED_RESPONSE 0xf08 | ||
417 | #define LOLA_VERB_GET_DIGI_CONVERT_1 0xf0d | ||
418 | #define LOLA_VERB_GET_CONFIG_DEFAULT 0xf1c | ||
419 | #define LOLA_VERB_GET_SUBSYSTEM_ID 0xf20 | ||
420 | /* GET verbs Digigram */ | ||
421 | #define LOLA_VERB_GET_FIXED_GAIN 0xfc0 | ||
422 | #define LOLA_VERB_GET_GAIN_SELECT 0xfc1 | ||
423 | #define LOLA_VERB_GET_MAX_LEVEL 0xfc2 | ||
424 | #define LOLA_VERB_GET_CLOCK_LIST 0xfc3 | ||
425 | #define LOLA_VERB_GET_CLOCK_SELECT 0xfc4 | ||
426 | #define LOLA_VERB_GET_CLOCK_STATUS 0xfc5 | ||
427 | |||
428 | /* SET verbs HDAudio */ | ||
429 | #define LOLA_VERB_SET_STREAM_FORMAT 0x200 | ||
430 | #define LOLA_VERB_SET_AMP_GAIN_MUTE 0x300 | ||
431 | #define LOLA_VERB_SET_POWER_STATE 0x705 | ||
432 | #define LOLA_VERB_SET_CHANNEL_STREAMID 0x706 | ||
433 | #define LOLA_VERB_SET_UNSOLICITED_ENABLE 0x708 | ||
434 | #define LOLA_VERB_SET_DIGI_CONVERT_1 0x70d | ||
435 | /* SET verbs Digigram */ | ||
436 | #define LOLA_VERB_SET_GAIN_SELECT 0xf81 | ||
437 | #define LOLA_VERB_SET_CLOCK_SELECT 0xf84 | ||
438 | #define LOLA_VERB_SET_GRANULARITY_STEPS 0xf86 | ||
439 | #define LOLA_VERB_SET_SOURCE_GAIN 0xf87 | ||
440 | #define LOLA_VERB_SET_MIX_GAIN 0xf88 | ||
441 | #define LOLA_VERB_SET_DESTINATION_GAIN 0xf89 | ||
442 | #define LOLA_VERB_SET_SRC 0xf8a | ||
443 | |||
444 | /* Parameter IDs used with LOLA_VERB_PARAMETERS */ | ||
445 | #define LOLA_PAR_VENDOR_ID 0x00 | ||
446 | #define LOLA_PAR_FUNCTION_TYPE 0x05 | ||
447 | #define LOLA_PAR_AUDIO_WIDGET_CAP 0x09 | ||
448 | #define LOLA_PAR_PCM 0x0a | ||
449 | #define LOLA_PAR_STREAM_FORMATS 0x0b | ||
450 | #define LOLA_PAR_PIN_CAP 0x0c | ||
451 | #define LOLA_PAR_AMP_IN_CAP 0x0d | ||
452 | #define LOLA_PAR_CONNLIST_LEN 0x0e | ||
453 | #define LOLA_PAR_POWER_STATE 0x0f | ||
454 | #define LOLA_PAR_GPIO_CAP 0x11 | ||
455 | #define LOLA_PAR_AMP_OUT_CAP 0x12 | ||
456 | #define LOLA_PAR_SPECIFIC_CAPS 0x80 | ||
457 | #define LOLA_PAR_FIXED_GAIN_LIST 0x81 | ||
458 | |||
459 | /* extract results of LOLA_PAR_SPECIFIC_CAPS */ | ||
460 | #define LOLA_AFG_MIXER_WIDGET_PRESENT(res) ((res & (1 << 21)) != 0) | ||
461 | #define LOLA_AFG_CLOCK_WIDGET_PRESENT(res) ((res & (1 << 20)) != 0) | ||
462 | #define LOLA_AFG_INPUT_PIN_COUNT(res) ((res >> 10) & 0x2ff) | ||
463 | #define LOLA_AFG_OUTPUT_PIN_COUNT(res) ((res) & 0x2ff) | ||
464 | |||
465 | /* extract results of LOLA_PAR_AMP_IN_CAP / LOLA_PAR_AMP_OUT_CAP */ | ||
466 | #define LOLA_AMP_MUTE_CAPABLE(res) ((res & (1 << 31)) != 0) | ||
467 | #define LOLA_AMP_STEP_SIZE(res) ((res >> 24) & 0x7f) | ||
468 | #define LOLA_AMP_NUM_STEPS(res) ((res >> 12) & 0x3ff) | ||
469 | #define LOLA_AMP_OFFSET(res) ((res) & 0x3ff) | ||
470 | |||
471 | #define LOLA_GRANULARITY_MIN 8 | ||
472 | #define LOLA_GRANULARITY_MAX 32 | ||
473 | #define LOLA_GRANULARITY_STEP 8 | ||
474 | |||
475 | /* parameters used with unsolicited command/response */ | ||
476 | #define LOLA_UNSOLICITED_TAG_MASK 0x3f | ||
477 | #define LOLA_UNSOLICITED_TAG 0x1a | ||
478 | #define LOLA_UNSOLICITED_ENABLE 0x80 | ||
479 | #define LOLA_UNSOL_RESP_TAG_OFFSET 26 | ||
480 | |||
481 | /* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */ | ||
482 | #define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f) | ||
483 | #define LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(res) ((res >> 7) & 0x1f) | ||
484 | |||
485 | int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, | ||
486 | unsigned int data, unsigned int extdata); | ||
487 | int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb, | ||
488 | unsigned int data, unsigned int extdata, | ||
489 | unsigned int *val, unsigned int *extval); | ||
490 | int lola_codec_flush(struct lola *chip); | ||
491 | #define lola_read_param(chip, nid, param, val) \ | ||
492 | lola_codec_read(chip, nid, LOLA_VERB_PARAMETERS, param, 0, val, NULL) | ||
493 | |||
494 | /* PCM */ | ||
495 | int lola_create_pcm(struct lola *chip); | ||
496 | void lola_free_pcm(struct lola *chip); | ||
497 | int lola_init_pcm(struct lola *chip, int dir, int *nidp); | ||
498 | void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits); | ||
499 | |||
500 | /* clock */ | ||
501 | int lola_init_clock_widget(struct lola *chip, int nid); | ||
502 | int lola_set_granularity(struct lola *chip, unsigned int val, bool force); | ||
503 | int lola_enable_clock_events(struct lola *chip); | ||
504 | int lola_set_clock_index(struct lola *chip, unsigned int idx); | ||
505 | int lola_set_clock(struct lola *chip, int idx); | ||
506 | int lola_set_sample_rate(struct lola *chip, int rate); | ||
507 | bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val); | ||
508 | unsigned int lola_sample_rate_convert(unsigned int coded); | ||
509 | |||
510 | /* mixer */ | ||
511 | int lola_init_pins(struct lola *chip, int dir, int *nidp); | ||
512 | int lola_init_mixer_widget(struct lola *chip, int nid); | ||
513 | void lola_free_mixer(struct lola *chip); | ||
514 | int lola_create_mixer(struct lola *chip); | ||
515 | int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute); | ||
516 | void lola_save_mixer(struct lola *chip); | ||
517 | void lola_restore_mixer(struct lola *chip); | ||
518 | int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update); | ||
519 | |||
520 | /* proc */ | ||
521 | #ifdef CONFIG_SND_DEBUG | ||
522 | void lola_proc_debug_new(struct lola *chip); | ||
523 | #else | ||
524 | #define lola_proc_debug_new(chip) | ||
525 | #endif | ||
526 | |||
527 | #endif /* _LOLA_H */ | ||
diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c new file mode 100644 index 000000000000..72f8ef0ac865 --- /dev/null +++ b/sound/pci/lola/lola_clock.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include "lola.h" | ||
27 | |||
28 | unsigned int lola_sample_rate_convert(unsigned int coded) | ||
29 | { | ||
30 | unsigned int freq; | ||
31 | |||
32 | /* base frequency */ | ||
33 | switch (coded & 0x3) { | ||
34 | case 0: freq = 48000; break; | ||
35 | case 1: freq = 44100; break; | ||
36 | case 2: freq = 32000; break; | ||
37 | default: return 0; /* error */ | ||
38 | } | ||
39 | |||
40 | /* multiplier / devisor */ | ||
41 | switch (coded & 0x1c) { | ||
42 | case (0 << 2): break; | ||
43 | case (4 << 2): break; | ||
44 | case (1 << 2): freq *= 2; break; | ||
45 | case (2 << 2): freq *= 4; break; | ||
46 | case (5 << 2): freq /= 2; break; | ||
47 | case (6 << 2): freq /= 4; break; | ||
48 | default: return 0; /* error */ | ||
49 | } | ||
50 | |||
51 | /* ajustement */ | ||
52 | switch (coded & 0x60) { | ||
53 | case (0 << 5): break; | ||
54 | case (1 << 5): freq = (freq * 999) / 1000; break; | ||
55 | case (2 << 5): freq = (freq * 1001) / 1000; break; | ||
56 | default: return 0; /* error */ | ||
57 | } | ||
58 | return freq; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Granualrity | ||
63 | */ | ||
64 | |||
65 | #define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000 | ||
66 | #define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000 | ||
67 | |||
68 | static bool check_gran_clock_compatibility(struct lola *chip, | ||
69 | unsigned int val, | ||
70 | unsigned int freq) | ||
71 | { | ||
72 | if (!chip->granularity) | ||
73 | return true; | ||
74 | |||
75 | if (val < LOLA_GRANULARITY_MIN || val > LOLA_GRANULARITY_MAX || | ||
76 | (val % LOLA_GRANULARITY_STEP) != 0) | ||
77 | return false; | ||
78 | |||
79 | if (val == LOLA_GRANULARITY_MIN) { | ||
80 | if (freq > LOLA_MAXFREQ_AT_GRANULARITY_MIN) | ||
81 | return false; | ||
82 | } else if (val < LOLA_GRANULARITY_MAX) { | ||
83 | if (freq > LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX) | ||
84 | return false; | ||
85 | } | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | int lola_set_granularity(struct lola *chip, unsigned int val, bool force) | ||
90 | { | ||
91 | int err; | ||
92 | |||
93 | if (!force) { | ||
94 | if (val == chip->granularity) | ||
95 | return 0; | ||
96 | #if 0 | ||
97 | /* change Gran only if there are no streams allocated ! */ | ||
98 | if (chip->audio_in_alloc_mask || chip->audio_out_alloc_mask) | ||
99 | return -EBUSY; | ||
100 | #endif | ||
101 | if (!check_gran_clock_compatibility(chip, val, | ||
102 | chip->clock.cur_freq)) | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | chip->granularity = val; | ||
107 | val /= LOLA_GRANULARITY_STEP; | ||
108 | |||
109 | /* audio function group */ | ||
110 | err = lola_codec_write(chip, 1, LOLA_VERB_SET_GRANULARITY_STEPS, | ||
111 | val, 0); | ||
112 | if (err < 0) | ||
113 | return err; | ||
114 | /* this can be a very slow function !!! */ | ||
115 | usleep_range(400 * val, 20000); | ||
116 | return lola_codec_flush(chip); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Clock widget handling | ||
121 | */ | ||
122 | |||
123 | int __devinit lola_init_clock_widget(struct lola *chip, int nid) | ||
124 | { | ||
125 | unsigned int val; | ||
126 | int i, j, nitems, nb_verbs, idx, idx_list; | ||
127 | int err; | ||
128 | |||
129 | err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
130 | if (err < 0) { | ||
131 | printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); | ||
132 | return err; | ||
133 | } | ||
134 | |||
135 | if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */ | ||
136 | snd_printdd("No valid clock widget\n"); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | chip->clock.nid = nid; | ||
141 | chip->clock.items = val & 0xff; | ||
142 | snd_printdd("clock_list nid=%x, entries=%d\n", nid, | ||
143 | chip->clock.items); | ||
144 | if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) { | ||
145 | printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n", | ||
146 | chip->clock.items); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | nitems = chip->clock.items; | ||
151 | nb_verbs = (nitems + 3) / 4; | ||
152 | idx = 0; | ||
153 | idx_list = 0; | ||
154 | for (i = 0; i < nb_verbs; i++) { | ||
155 | unsigned int res_ex; | ||
156 | unsigned short items[4]; | ||
157 | |||
158 | err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, | ||
159 | idx, 0, &val, &res_ex); | ||
160 | if (err < 0) { | ||
161 | printk(KERN_ERR SFX "Can't read CLOCK_LIST\n"); | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | items[0] = val & 0xfff; | ||
166 | items[1] = (val >> 16) & 0xfff; | ||
167 | items[2] = res_ex & 0xfff; | ||
168 | items[3] = (res_ex >> 16) & 0xfff; | ||
169 | |||
170 | for (j = 0; j < 4; j++) { | ||
171 | unsigned char type = items[j] >> 8; | ||
172 | unsigned int freq = items[j] & 0xff; | ||
173 | int format = LOLA_CLOCK_FORMAT_NONE; | ||
174 | bool add_clock = true; | ||
175 | if (type == LOLA_CLOCK_TYPE_INTERNAL) { | ||
176 | freq = lola_sample_rate_convert(freq); | ||
177 | if (freq < chip->sample_rate_min) | ||
178 | add_clock = false; | ||
179 | else if (freq == 48000) { | ||
180 | chip->clock.cur_index = idx_list; | ||
181 | chip->clock.cur_freq = 48000; | ||
182 | chip->clock.cur_valid = true; | ||
183 | } | ||
184 | } else if (type == LOLA_CLOCK_TYPE_VIDEO) { | ||
185 | freq = lola_sample_rate_convert(freq); | ||
186 | if (freq < chip->sample_rate_min) | ||
187 | add_clock = false; | ||
188 | /* video clock has a format (0:NTSC, 1:PAL)*/ | ||
189 | if (items[j] & 0x80) | ||
190 | format = LOLA_CLOCK_FORMAT_NTSC; | ||
191 | else | ||
192 | format = LOLA_CLOCK_FORMAT_PAL; | ||
193 | } | ||
194 | if (add_clock) { | ||
195 | struct lola_sample_clock *sc; | ||
196 | sc = &chip->clock.sample_clock[idx_list]; | ||
197 | sc->type = type; | ||
198 | sc->format = format; | ||
199 | sc->freq = freq; | ||
200 | /* keep the index used with the board */ | ||
201 | chip->clock.idx_lookup[idx_list] = idx; | ||
202 | idx_list++; | ||
203 | } else { | ||
204 | chip->clock.items--; | ||
205 | } | ||
206 | if (++idx >= nitems) | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /* enable unsolicited events of the clock widget */ | ||
214 | int lola_enable_clock_events(struct lola *chip) | ||
215 | { | ||
216 | unsigned int res; | ||
217 | int err; | ||
218 | |||
219 | err = lola_codec_read(chip, chip->clock.nid, | ||
220 | LOLA_VERB_SET_UNSOLICITED_ENABLE, | ||
221 | LOLA_UNSOLICITED_ENABLE | LOLA_UNSOLICITED_TAG, | ||
222 | 0, &res, NULL); | ||
223 | if (err < 0) | ||
224 | return err; | ||
225 | if (res) { | ||
226 | printk(KERN_WARNING SFX "error in enable_clock_events %d\n", | ||
227 | res); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | int lola_set_clock_index(struct lola *chip, unsigned int idx) | ||
234 | { | ||
235 | unsigned int res; | ||
236 | int err; | ||
237 | |||
238 | err = lola_codec_read(chip, chip->clock.nid, | ||
239 | LOLA_VERB_SET_CLOCK_SELECT, | ||
240 | chip->clock.idx_lookup[idx], | ||
241 | 0, &res, NULL); | ||
242 | if (err < 0) | ||
243 | return err; | ||
244 | if (res) { | ||
245 | printk(KERN_WARNING SFX "error in set_clock %d\n", res); | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val) | ||
252 | { | ||
253 | unsigned int tag; | ||
254 | |||
255 | /* the current EXTERNAL clock information gets updated by interrupt | ||
256 | * with an unsolicited response | ||
257 | */ | ||
258 | if (!val) | ||
259 | return false; | ||
260 | tag = (val >> LOLA_UNSOL_RESP_TAG_OFFSET) & LOLA_UNSOLICITED_TAG_MASK; | ||
261 | if (tag != LOLA_UNSOLICITED_TAG) | ||
262 | return false; | ||
263 | |||
264 | /* only for current = external clocks */ | ||
265 | if (chip->clock.sample_clock[chip->clock.cur_index].type != | ||
266 | LOLA_CLOCK_TYPE_INTERNAL) { | ||
267 | chip->clock.cur_freq = lola_sample_rate_convert(val & 0x7f); | ||
268 | chip->clock.cur_valid = (val & 0x100) != 0; | ||
269 | } | ||
270 | return true; | ||
271 | } | ||
272 | |||
273 | int lola_set_clock(struct lola *chip, int idx) | ||
274 | { | ||
275 | int freq = 0; | ||
276 | bool valid = false; | ||
277 | |||
278 | if (idx == chip->clock.cur_index) { | ||
279 | /* current clock is allowed */ | ||
280 | freq = chip->clock.cur_freq; | ||
281 | valid = chip->clock.cur_valid; | ||
282 | } else if (chip->clock.sample_clock[idx].type == | ||
283 | LOLA_CLOCK_TYPE_INTERNAL) { | ||
284 | /* internal clocks allowed */ | ||
285 | freq = chip->clock.sample_clock[idx].freq; | ||
286 | valid = true; | ||
287 | } | ||
288 | |||
289 | if (!freq || !valid) | ||
290 | return -EINVAL; | ||
291 | |||
292 | if (!check_gran_clock_compatibility(chip, chip->granularity, freq)) | ||
293 | return -EINVAL; | ||
294 | |||
295 | if (idx != chip->clock.cur_index) { | ||
296 | int err = lola_set_clock_index(chip, idx); | ||
297 | if (err < 0) | ||
298 | return err; | ||
299 | /* update new settings */ | ||
300 | chip->clock.cur_index = idx; | ||
301 | chip->clock.cur_freq = freq; | ||
302 | chip->clock.cur_valid = true; | ||
303 | } | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | int lola_set_sample_rate(struct lola *chip, int rate) | ||
308 | { | ||
309 | int i; | ||
310 | |||
311 | if (chip->clock.cur_freq == rate && chip->clock.cur_valid) | ||
312 | return 0; | ||
313 | /* search for new dwClockIndex */ | ||
314 | for (i = 0; i < chip->clock.items; i++) { | ||
315 | if (chip->clock.sample_clock[i].type == LOLA_CLOCK_TYPE_INTERNAL && | ||
316 | chip->clock.sample_clock[i].freq == rate) | ||
317 | break; | ||
318 | } | ||
319 | if (i >= chip->clock.items) | ||
320 | return -EINVAL; | ||
321 | return lola_set_clock(chip, i); | ||
322 | } | ||
323 | |||
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c new file mode 100644 index 000000000000..5d518f1a712c --- /dev/null +++ b/sound/pci/lola/lola_mixer.c | |||
@@ -0,0 +1,839 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/control.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/tlv.h> | ||
29 | #include "lola.h" | ||
30 | |||
31 | static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin, | ||
32 | int dir, int nid) | ||
33 | { | ||
34 | unsigned int val; | ||
35 | int err; | ||
36 | |||
37 | pin->nid = nid; | ||
38 | err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
39 | if (err < 0) { | ||
40 | printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); | ||
41 | return err; | ||
42 | } | ||
43 | val &= 0x00f00fff; /* test TYPE and bits 0..11 */ | ||
44 | if (val == 0x00400200) /* Type = 4, Digital = 1 */ | ||
45 | pin->is_analog = false; | ||
46 | else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */ | ||
47 | pin->is_analog = true; | ||
48 | else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */ | ||
49 | pin->is_analog = true; | ||
50 | else { | ||
51 | printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid); | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | /* analog parameters only following, so continue in case of Digital pin | ||
56 | */ | ||
57 | if (!pin->is_analog) | ||
58 | return 0; | ||
59 | |||
60 | if (dir == PLAY) | ||
61 | err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val); | ||
62 | else | ||
63 | err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val); | ||
64 | if (err < 0) { | ||
65 | printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid); | ||
66 | return err; | ||
67 | } | ||
68 | |||
69 | pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val); | ||
70 | pin->amp_step_size = LOLA_AMP_STEP_SIZE(val); | ||
71 | pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val); | ||
72 | if (pin->amp_num_steps) { | ||
73 | /* zero as mute state */ | ||
74 | pin->amp_num_steps++; | ||
75 | pin->amp_step_size++; | ||
76 | } | ||
77 | pin->amp_offset = LOLA_AMP_OFFSET(val); | ||
78 | |||
79 | err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, | ||
80 | NULL); | ||
81 | if (err < 0) { | ||
82 | printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid); | ||
83 | return err; | ||
84 | } | ||
85 | pin->max_level = val & 0x3ff; /* 10 bits */ | ||
86 | |||
87 | pin->config_default_reg = 0; | ||
88 | pin->fixed_gain_list_len = 0; | ||
89 | pin->cur_gain_step = 0; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp) | ||
95 | { | ||
96 | int i, err, nid; | ||
97 | nid = *nidp; | ||
98 | for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) { | ||
99 | err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid); | ||
100 | if (err < 0) | ||
101 | return err; | ||
102 | if (chip->pin[dir].pins[i].is_analog) | ||
103 | chip->pin[dir].num_analog_pins++; | ||
104 | } | ||
105 | *nidp = nid; | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | void lola_free_mixer(struct lola *chip) | ||
110 | { | ||
111 | if (chip->mixer.array_saved) | ||
112 | vfree(chip->mixer.array_saved); | ||
113 | } | ||
114 | |||
115 | int __devinit lola_init_mixer_widget(struct lola *chip, int nid) | ||
116 | { | ||
117 | unsigned int val; | ||
118 | int err; | ||
119 | |||
120 | err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
121 | if (err < 0) { | ||
122 | printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); | ||
123 | return err; | ||
124 | } | ||
125 | |||
126 | if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */ | ||
127 | snd_printdd("No valid mixer widget\n"); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | chip->mixer.nid = nid; | ||
132 | chip->mixer.caps = val; | ||
133 | chip->mixer.array = (struct lola_mixer_array __iomem *) | ||
134 | (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE); | ||
135 | |||
136 | /* reserve memory to copy mixer data for sleep mode transitions */ | ||
137 | chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array)); | ||
138 | |||
139 | /* mixer matrix sources are physical input data and play streams */ | ||
140 | chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams; | ||
141 | chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins; | ||
142 | |||
143 | /* mixer matrix destinations are record streams and physical output */ | ||
144 | chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams; | ||
145 | chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins; | ||
146 | |||
147 | /* mixer matrix can have unused areas between PhysIn and | ||
148 | * Play or Record and PhysOut zones | ||
149 | */ | ||
150 | chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins + | ||
151 | LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val); | ||
152 | chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins + | ||
153 | LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val); | ||
154 | |||
155 | /* example : MixerMatrix of LoLa881 | ||
156 | * 0-------8------16-------8------16 | ||
157 | * | | | | | | ||
158 | * | INPUT | | INPUT | | | ||
159 | * | -> |unused | -> |unused | | ||
160 | * | RECORD| | OUTPUT| | | ||
161 | * | | | | | | ||
162 | * 8-------------------------------- | ||
163 | * | | | | | | ||
164 | * | | | | | | ||
165 | * |unused |unused |unused |unused | | ||
166 | * | | | | | | ||
167 | * | | | | | | ||
168 | * 16------------------------------- | ||
169 | * | | | | | | ||
170 | * | PLAY | | PLAY | | | ||
171 | * | -> |unused | -> |unused | | ||
172 | * | RECORD| | OUTPUT| | | ||
173 | * | | | | | | ||
174 | * 8-------------------------------- | ||
175 | * | | | | | | ||
176 | * | | | | | | ||
177 | * |unused |unused |unused |unused | | ||
178 | * | | | | | | ||
179 | * | | | | | | ||
180 | * 16------------------------------- | ||
181 | */ | ||
182 | if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || | ||
183 | chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { | ||
184 | printk(KERN_ERR SFX "Invalid mixer widget size\n"); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) | | ||
189 | (((1U << chip->mixer.src_stream_outs) - 1) | ||
190 | << chip->mixer.src_stream_out_ofs); | ||
191 | chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) | | ||
192 | (((1U << chip->mixer.dest_phys_outs) - 1) | ||
193 | << chip->mixer.dest_phys_out_ofs); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id, | ||
199 | unsigned short gain, bool on) | ||
200 | { | ||
201 | unsigned int oldval, val; | ||
202 | |||
203 | if (!(chip->mixer.src_mask & (1 << id))) | ||
204 | return -EINVAL; | ||
205 | writew(gain, &chip->mixer.array->src_gain[id]); | ||
206 | oldval = val = readl(&chip->mixer.array->src_gain_enable); | ||
207 | if (on) | ||
208 | val |= (1 << id); | ||
209 | else | ||
210 | val &= ~(1 << id); | ||
211 | writel(val, &chip->mixer.array->src_gain_enable); | ||
212 | lola_codec_flush(chip); | ||
213 | /* inform micro-controller about the new source gain */ | ||
214 | return lola_codec_write(chip, chip->mixer.nid, | ||
215 | LOLA_VERB_SET_SOURCE_GAIN, id, 0); | ||
216 | } | ||
217 | |||
218 | #if 0 /* not used */ | ||
219 | static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask, | ||
220 | unsigned short *gains) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | if ((chip->mixer.src_mask & mask) != mask) | ||
225 | return -EINVAL; | ||
226 | for (i = 0; i < LOLA_MIXER_DIM; i++) { | ||
227 | if (mask & (1 << i)) { | ||
228 | writew(*gains, &chip->mixer.array->src_gain[i]); | ||
229 | gains++; | ||
230 | } | ||
231 | } | ||
232 | writel(mask, &chip->mixer.array->src_gain_enable); | ||
233 | lola_codec_flush(chip); | ||
234 | if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) { | ||
235 | /* update for all srcs at once */ | ||
236 | return lola_codec_write(chip, chip->mixer.nid, | ||
237 | LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0); | ||
238 | } | ||
239 | /* update manually */ | ||
240 | for (i = 0; i < LOLA_MIXER_DIM; i++) { | ||
241 | if (mask & (1 << i)) { | ||
242 | lola_codec_write(chip, chip->mixer.nid, | ||
243 | LOLA_VERB_SET_SOURCE_GAIN, i, 0); | ||
244 | } | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | #endif /* not used */ | ||
249 | |||
250 | static int lola_mixer_set_mapping_gain(struct lola *chip, | ||
251 | unsigned int src, unsigned int dest, | ||
252 | unsigned short gain, bool on) | ||
253 | { | ||
254 | unsigned int val; | ||
255 | |||
256 | if (!(chip->mixer.src_mask & (1 << src)) || | ||
257 | !(chip->mixer.dest_mask & (1 << dest))) | ||
258 | return -EINVAL; | ||
259 | if (on) | ||
260 | writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]); | ||
261 | val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]); | ||
262 | if (on) | ||
263 | val |= (1 << src); | ||
264 | else | ||
265 | val &= ~(1 << src); | ||
266 | writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]); | ||
267 | lola_codec_flush(chip); | ||
268 | return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN, | ||
269 | src, dest); | ||
270 | } | ||
271 | |||
272 | static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, | ||
273 | unsigned int mask, unsigned short *gains) | ||
274 | { | ||
275 | int i; | ||
276 | |||
277 | if (!(chip->mixer.dest_mask & (1 << id)) || | ||
278 | (chip->mixer.src_mask & mask) != mask) | ||
279 | return -EINVAL; | ||
280 | for (i = 0; i < LOLA_MIXER_DIM; i++) { | ||
281 | if (mask & (1 << i)) { | ||
282 | writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]); | ||
283 | gains++; | ||
284 | } | ||
285 | } | ||
286 | writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]); | ||
287 | lola_codec_flush(chip); | ||
288 | /* update for all dests at once */ | ||
289 | return lola_codec_write(chip, chip->mixer.nid, | ||
290 | LOLA_VERB_SET_DESTINATION_GAIN, id, 0); | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | */ | ||
295 | |||
296 | static int set_analog_volume(struct lola *chip, int dir, | ||
297 | unsigned int idx, unsigned int val, | ||
298 | bool external_call); | ||
299 | |||
300 | int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute) | ||
301 | { | ||
302 | struct lola_pin *pin; | ||
303 | int idx, max_idx; | ||
304 | |||
305 | pin = chip->pin[dir].pins; | ||
306 | max_idx = chip->pin[dir].num_pins; | ||
307 | for (idx = 0; idx < max_idx; idx++) { | ||
308 | if (pin[idx].is_analog) { | ||
309 | unsigned int val = mute ? 0 : pin[idx].cur_gain_step; | ||
310 | /* set volume and do not save the value */ | ||
311 | set_analog_volume(chip, dir, idx, val, false); | ||
312 | } | ||
313 | } | ||
314 | return lola_codec_flush(chip); | ||
315 | } | ||
316 | |||
317 | void lola_save_mixer(struct lola *chip) | ||
318 | { | ||
319 | /* mute analog output */ | ||
320 | if (chip->mixer.array_saved) { | ||
321 | /* store contents of mixer array */ | ||
322 | memcpy_fromio(chip->mixer.array_saved, chip->mixer.array, | ||
323 | sizeof(*chip->mixer.array)); | ||
324 | } | ||
325 | lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */ | ||
326 | } | ||
327 | |||
328 | void lola_restore_mixer(struct lola *chip) | ||
329 | { | ||
330 | int i; | ||
331 | |||
332 | /*lola_reset_setups(chip);*/ | ||
333 | if (chip->mixer.array_saved) { | ||
334 | /* restore contents of mixer array */ | ||
335 | memcpy_toio(chip->mixer.array, chip->mixer.array_saved, | ||
336 | sizeof(*chip->mixer.array)); | ||
337 | /* inform micro-controller about all restored values | ||
338 | * and ignore return values | ||
339 | */ | ||
340 | for (i = 0; i < chip->mixer.src_phys_ins; i++) | ||
341 | lola_codec_write(chip, chip->mixer.nid, | ||
342 | LOLA_VERB_SET_SOURCE_GAIN, | ||
343 | i, 0); | ||
344 | for (i = 0; i < chip->mixer.src_stream_outs; i++) | ||
345 | lola_codec_write(chip, chip->mixer.nid, | ||
346 | LOLA_VERB_SET_SOURCE_GAIN, | ||
347 | chip->mixer.src_stream_out_ofs + i, 0); | ||
348 | for (i = 0; i < chip->mixer.dest_stream_ins; i++) | ||
349 | lola_codec_write(chip, chip->mixer.nid, | ||
350 | LOLA_VERB_SET_DESTINATION_GAIN, | ||
351 | i, 0); | ||
352 | for (i = 0; i < chip->mixer.dest_phys_outs; i++) | ||
353 | lola_codec_write(chip, chip->mixer.nid, | ||
354 | LOLA_VERB_SET_DESTINATION_GAIN, | ||
355 | chip->mixer.dest_phys_out_ofs + i, 0); | ||
356 | lola_codec_flush(chip); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | */ | ||
362 | |||
363 | static int set_analog_volume(struct lola *chip, int dir, | ||
364 | unsigned int idx, unsigned int val, | ||
365 | bool external_call) | ||
366 | { | ||
367 | struct lola_pin *pin; | ||
368 | int err; | ||
369 | |||
370 | if (idx >= chip->pin[dir].num_pins) | ||
371 | return -EINVAL; | ||
372 | pin = &chip->pin[dir].pins[idx]; | ||
373 | if (!pin->is_analog || pin->amp_num_steps <= val) | ||
374 | return -EINVAL; | ||
375 | if (external_call && pin->cur_gain_step == val) | ||
376 | return 0; | ||
377 | if (external_call) | ||
378 | lola_codec_flush(chip); | ||
379 | err = lola_codec_write(chip, pin->nid, | ||
380 | LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); | ||
381 | if (err < 0) | ||
382 | return err; | ||
383 | if (external_call) | ||
384 | pin->cur_gain_step = val; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update) | ||
389 | { | ||
390 | int ret = 0; | ||
391 | int success = 0; | ||
392 | int n, err; | ||
393 | |||
394 | /* SRC can be activated and the dwInputSRCMask is valid? */ | ||
395 | if ((chip->input_src_caps_mask & src_mask) != src_mask) | ||
396 | return -EINVAL; | ||
397 | /* handle all even Inputs - SRC is a stereo setting !!! */ | ||
398 | for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) { | ||
399 | unsigned int mask = 3U << n; /* handle the stereo case */ | ||
400 | unsigned int new_src, src_state; | ||
401 | if (!(chip->input_src_caps_mask & mask)) | ||
402 | continue; | ||
403 | /* if one IO needs SRC, both stereo IO will get SRC */ | ||
404 | new_src = (src_mask & mask) != 0; | ||
405 | if (update) { | ||
406 | src_state = (chip->input_src_mask & mask) != 0; | ||
407 | if (src_state == new_src) | ||
408 | continue; /* nothing to change for this IO */ | ||
409 | } | ||
410 | err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid, | ||
411 | LOLA_VERB_SET_SRC, new_src, 0); | ||
412 | if (!err) | ||
413 | success++; | ||
414 | else | ||
415 | ret = err; | ||
416 | } | ||
417 | if (success) | ||
418 | ret = lola_codec_flush(chip); | ||
419 | if (!ret) | ||
420 | chip->input_src_mask = src_mask; | ||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | */ | ||
426 | static int init_mixer_values(struct lola *chip) | ||
427 | { | ||
428 | int i; | ||
429 | |||
430 | /* all src on */ | ||
431 | lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false); | ||
432 | |||
433 | /* clear all matrix */ | ||
434 | memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array)); | ||
435 | /* set src gain to 0dB */ | ||
436 | for (i = 0; i < chip->mixer.src_phys_ins; i++) | ||
437 | lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */ | ||
438 | for (i = 0; i < chip->mixer.src_stream_outs; i++) | ||
439 | lola_mixer_set_src_gain(chip, | ||
440 | i + chip->mixer.src_stream_out_ofs, | ||
441 | 336, true); /* 0dB */ | ||
442 | /* set 1:1 dest gain */ | ||
443 | for (i = 0; i < chip->mixer.dest_stream_ins; i++) { | ||
444 | int src = i % chip->mixer.src_phys_ins; | ||
445 | lola_mixer_set_mapping_gain(chip, src, i, 336, true); | ||
446 | } | ||
447 | for (i = 0; i < chip->mixer.src_stream_outs; i++) { | ||
448 | int src = chip->mixer.src_stream_out_ofs + i; | ||
449 | int dst = chip->mixer.dest_phys_out_ofs + | ||
450 | i % chip->mixer.dest_phys_outs; | ||
451 | lola_mixer_set_mapping_gain(chip, src, dst, 336, true); | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | * analog mixer control element | ||
458 | */ | ||
459 | static int lola_analog_vol_info(struct snd_kcontrol *kcontrol, | ||
460 | struct snd_ctl_elem_info *uinfo) | ||
461 | { | ||
462 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
463 | int dir = kcontrol->private_value; | ||
464 | |||
465 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
466 | uinfo->count = chip->pin[dir].num_pins; | ||
467 | uinfo->value.integer.min = 0; | ||
468 | uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps; | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int lola_analog_vol_get(struct snd_kcontrol *kcontrol, | ||
473 | struct snd_ctl_elem_value *ucontrol) | ||
474 | { | ||
475 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
476 | int dir = kcontrol->private_value; | ||
477 | int i; | ||
478 | |||
479 | for (i = 0; i < chip->pin[dir].num_pins; i++) | ||
480 | ucontrol->value.integer.value[i] = | ||
481 | chip->pin[dir].pins[i].cur_gain_step; | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int lola_analog_vol_put(struct snd_kcontrol *kcontrol, | ||
486 | struct snd_ctl_elem_value *ucontrol) | ||
487 | { | ||
488 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
489 | int dir = kcontrol->private_value; | ||
490 | int i, err; | ||
491 | |||
492 | for (i = 0; i < chip->pin[dir].num_pins; i++) { | ||
493 | err = set_analog_volume(chip, dir, i, | ||
494 | ucontrol->value.integer.value[i], | ||
495 | true); | ||
496 | if (err < 0) | ||
497 | return err; | ||
498 | } | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
503 | unsigned int size, unsigned int __user *tlv) | ||
504 | { | ||
505 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
506 | int dir = kcontrol->private_value; | ||
507 | unsigned int val1, val2; | ||
508 | struct lola_pin *pin; | ||
509 | |||
510 | if (size < 4 * sizeof(unsigned int)) | ||
511 | return -ENOMEM; | ||
512 | pin = &chip->pin[dir].pins[0]; | ||
513 | |||
514 | val2 = pin->amp_step_size * 25; | ||
515 | val1 = -1 * (int)pin->amp_offset * (int)val2; | ||
516 | #ifdef TLV_DB_SCALE_MUTE | ||
517 | val2 |= TLV_DB_SCALE_MUTE; | ||
518 | #endif | ||
519 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv)) | ||
520 | return -EFAULT; | ||
521 | if (put_user(2 * sizeof(unsigned int), tlv + 1)) | ||
522 | return -EFAULT; | ||
523 | if (put_user(val1, tlv + 2)) | ||
524 | return -EFAULT; | ||
525 | if (put_user(val2, tlv + 3)) | ||
526 | return -EFAULT; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static struct snd_kcontrol_new lola_analog_mixer __devinitdata = { | ||
531 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
532 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
533 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
534 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), | ||
535 | .info = lola_analog_vol_info, | ||
536 | .get = lola_analog_vol_get, | ||
537 | .put = lola_analog_vol_put, | ||
538 | .tlv.c = lola_analog_vol_tlv, | ||
539 | }; | ||
540 | |||
541 | static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name) | ||
542 | { | ||
543 | if (!chip->pin[dir].num_pins) | ||
544 | return 0; | ||
545 | /* no analog volumes on digital only adapters */ | ||
546 | if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins) | ||
547 | return 0; | ||
548 | lola_analog_mixer.name = name; | ||
549 | lola_analog_mixer.private_value = dir; | ||
550 | return snd_ctl_add(chip->card, | ||
551 | snd_ctl_new1(&lola_analog_mixer, chip)); | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Hardware sample rate converter on digital input | ||
556 | */ | ||
557 | static int lola_input_src_info(struct snd_kcontrol *kcontrol, | ||
558 | struct snd_ctl_elem_info *uinfo) | ||
559 | { | ||
560 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
561 | |||
562 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
563 | uinfo->count = chip->pin[CAPT].num_pins; | ||
564 | uinfo->value.integer.min = 0; | ||
565 | uinfo->value.integer.max = 1; | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static int lola_input_src_get(struct snd_kcontrol *kcontrol, | ||
570 | struct snd_ctl_elem_value *ucontrol) | ||
571 | { | ||
572 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
573 | int i; | ||
574 | |||
575 | for (i = 0; i < chip->pin[CAPT].num_pins; i++) | ||
576 | ucontrol->value.integer.value[i] = | ||
577 | !!(chip->input_src_mask & (1 << i)); | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int lola_input_src_put(struct snd_kcontrol *kcontrol, | ||
582 | struct snd_ctl_elem_value *ucontrol) | ||
583 | { | ||
584 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
585 | int i; | ||
586 | unsigned int mask; | ||
587 | |||
588 | mask = 0; | ||
589 | for (i = 0; i < chip->pin[CAPT].num_pins; i++) | ||
590 | if (ucontrol->value.integer.value[i]) | ||
591 | mask |= 1 << i; | ||
592 | return lola_set_src_config(chip, mask, true); | ||
593 | } | ||
594 | |||
595 | static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = { | ||
596 | .name = "Digital SRC Capture Switch", | ||
597 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
598 | .info = lola_input_src_info, | ||
599 | .get = lola_input_src_get, | ||
600 | .put = lola_input_src_put, | ||
601 | }; | ||
602 | |||
603 | /* | ||
604 | * Lola16161 or Lola881 can have Hardware sample rate converters | ||
605 | * on its digital input pins | ||
606 | */ | ||
607 | static int __devinit create_input_src_mixer(struct lola *chip) | ||
608 | { | ||
609 | if (!chip->input_src_caps_mask) | ||
610 | return 0; | ||
611 | |||
612 | return snd_ctl_add(chip->card, | ||
613 | snd_ctl_new1(&lola_input_src_mixer, chip)); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * src gain mixer | ||
618 | */ | ||
619 | static int lola_src_gain_info(struct snd_kcontrol *kcontrol, | ||
620 | struct snd_ctl_elem_info *uinfo) | ||
621 | { | ||
622 | unsigned int count = (kcontrol->private_value >> 8) & 0xff; | ||
623 | |||
624 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
625 | uinfo->count = count; | ||
626 | uinfo->value.integer.min = 0; | ||
627 | uinfo->value.integer.max = 409; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int lola_src_gain_get(struct snd_kcontrol *kcontrol, | ||
632 | struct snd_ctl_elem_value *ucontrol) | ||
633 | { | ||
634 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
635 | unsigned int ofs = kcontrol->private_value & 0xff; | ||
636 | unsigned int count = (kcontrol->private_value >> 8) & 0xff; | ||
637 | unsigned int mask, i; | ||
638 | |||
639 | mask = readl(&chip->mixer.array->src_gain_enable); | ||
640 | for (i = 0; i < count; i++) { | ||
641 | unsigned int idx = ofs + i; | ||
642 | unsigned short val; | ||
643 | if (!(chip->mixer.src_mask & (1 << idx))) | ||
644 | return -EINVAL; | ||
645 | if (mask & (1 << idx)) | ||
646 | val = readw(&chip->mixer.array->src_gain[idx]) + 1; | ||
647 | else | ||
648 | val = 0; | ||
649 | ucontrol->value.integer.value[i] = val; | ||
650 | } | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | static int lola_src_gain_put(struct snd_kcontrol *kcontrol, | ||
655 | struct snd_ctl_elem_value *ucontrol) | ||
656 | { | ||
657 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
658 | unsigned int ofs = kcontrol->private_value & 0xff; | ||
659 | unsigned int count = (kcontrol->private_value >> 8) & 0xff; | ||
660 | int i, err; | ||
661 | |||
662 | for (i = 0; i < count; i++) { | ||
663 | unsigned int idx = ofs + i; | ||
664 | unsigned short val = ucontrol->value.integer.value[i]; | ||
665 | if (val) | ||
666 | val--; | ||
667 | err = lola_mixer_set_src_gain(chip, idx, val, !!val); | ||
668 | if (err < 0) | ||
669 | return err; | ||
670 | } | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */ | ||
675 | static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1); | ||
676 | |||
677 | static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = { | ||
678 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
679 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
680 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
681 | .info = lola_src_gain_info, | ||
682 | .get = lola_src_gain_get, | ||
683 | .put = lola_src_gain_put, | ||
684 | .tlv.p = lola_src_gain_tlv, | ||
685 | }; | ||
686 | |||
687 | static int __devinit create_src_gain_mixer(struct lola *chip, | ||
688 | int num, int ofs, char *name) | ||
689 | { | ||
690 | lola_src_gain_mixer.name = name; | ||
691 | lola_src_gain_mixer.private_value = ofs + (num << 8); | ||
692 | return snd_ctl_add(chip->card, | ||
693 | snd_ctl_new1(&lola_src_gain_mixer, chip)); | ||
694 | } | ||
695 | |||
696 | /* | ||
697 | * destination gain (matrix-like) mixer | ||
698 | */ | ||
699 | static int lola_dest_gain_info(struct snd_kcontrol *kcontrol, | ||
700 | struct snd_ctl_elem_info *uinfo) | ||
701 | { | ||
702 | unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; | ||
703 | |||
704 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
705 | uinfo->count = src_num; | ||
706 | uinfo->value.integer.min = 0; | ||
707 | uinfo->value.integer.max = 433; | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int lola_dest_gain_get(struct snd_kcontrol *kcontrol, | ||
712 | struct snd_ctl_elem_value *ucontrol) | ||
713 | { | ||
714 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
715 | unsigned int src_ofs = kcontrol->private_value & 0xff; | ||
716 | unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; | ||
717 | unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; | ||
718 | unsigned int dst, mask, i; | ||
719 | |||
720 | dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; | ||
721 | mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]); | ||
722 | for (i = 0; i < src_num; i++) { | ||
723 | unsigned int src = src_ofs + i; | ||
724 | unsigned short val; | ||
725 | if (!(chip->mixer.src_mask & (1 << src))) | ||
726 | return -EINVAL; | ||
727 | if (mask & (1 << dst)) | ||
728 | val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1; | ||
729 | else | ||
730 | val = 0; | ||
731 | ucontrol->value.integer.value[i] = val; | ||
732 | } | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int lola_dest_gain_put(struct snd_kcontrol *kcontrol, | ||
737 | struct snd_ctl_elem_value *ucontrol) | ||
738 | { | ||
739 | struct lola *chip = snd_kcontrol_chip(kcontrol); | ||
740 | unsigned int src_ofs = kcontrol->private_value & 0xff; | ||
741 | unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; | ||
742 | unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; | ||
743 | unsigned int dst, mask; | ||
744 | unsigned short gains[MAX_STREAM_COUNT]; | ||
745 | int i, num; | ||
746 | |||
747 | mask = 0; | ||
748 | num = 0; | ||
749 | for (i = 0; i < src_num; i++) { | ||
750 | unsigned short val = ucontrol->value.integer.value[i]; | ||
751 | if (val) { | ||
752 | gains[num++] = val - 1; | ||
753 | mask |= 1 << i; | ||
754 | } | ||
755 | } | ||
756 | mask <<= src_ofs; | ||
757 | dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; | ||
758 | return lola_mixer_set_dest_gains(chip, dst, mask, gains); | ||
759 | } | ||
760 | |||
761 | static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1); | ||
762 | |||
763 | static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = { | ||
764 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
765 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
766 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
767 | .info = lola_dest_gain_info, | ||
768 | .get = lola_dest_gain_get, | ||
769 | .put = lola_dest_gain_put, | ||
770 | .tlv.p = lola_dest_gain_tlv, | ||
771 | }; | ||
772 | |||
773 | static int __devinit create_dest_gain_mixer(struct lola *chip, | ||
774 | int src_num, int src_ofs, | ||
775 | int num, int ofs, char *name) | ||
776 | { | ||
777 | lola_dest_gain_mixer.count = num; | ||
778 | lola_dest_gain_mixer.name = name; | ||
779 | lola_dest_gain_mixer.private_value = | ||
780 | src_ofs + (src_num << 8) + (ofs << 16) + (num << 24); | ||
781 | return snd_ctl_add(chip->card, | ||
782 | snd_ctl_new1(&lola_dest_gain_mixer, chip)); | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | */ | ||
787 | int __devinit lola_create_mixer(struct lola *chip) | ||
788 | { | ||
789 | int err; | ||
790 | |||
791 | err = create_analog_mixer(chip, PLAY, "Analog Playback Volume"); | ||
792 | if (err < 0) | ||
793 | return err; | ||
794 | err = create_analog_mixer(chip, CAPT, "Analog Capture Volume"); | ||
795 | if (err < 0) | ||
796 | return err; | ||
797 | err = create_input_src_mixer(chip); | ||
798 | if (err < 0) | ||
799 | return err; | ||
800 | err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0, | ||
801 | "Line Source Gain Volume"); | ||
802 | if (err < 0) | ||
803 | return err; | ||
804 | err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs, | ||
805 | chip->mixer.src_stream_out_ofs, | ||
806 | "Stream Source Gain Volume"); | ||
807 | if (err < 0) | ||
808 | return err; | ||
809 | err = create_dest_gain_mixer(chip, | ||
810 | chip->mixer.src_phys_ins, 0, | ||
811 | chip->mixer.dest_stream_ins, 0, | ||
812 | "Line Capture Volume"); | ||
813 | if (err < 0) | ||
814 | return err; | ||
815 | err = create_dest_gain_mixer(chip, | ||
816 | chip->mixer.src_stream_outs, | ||
817 | chip->mixer.src_stream_out_ofs, | ||
818 | chip->mixer.dest_stream_ins, 0, | ||
819 | "Stream-Loopback Capture Volume"); | ||
820 | if (err < 0) | ||
821 | return err; | ||
822 | err = create_dest_gain_mixer(chip, | ||
823 | chip->mixer.src_phys_ins, 0, | ||
824 | chip->mixer.dest_phys_outs, | ||
825 | chip->mixer.dest_phys_out_ofs, | ||
826 | "Line-Loopback Playback Volume"); | ||
827 | if (err < 0) | ||
828 | return err; | ||
829 | err = create_dest_gain_mixer(chip, | ||
830 | chip->mixer.src_stream_outs, | ||
831 | chip->mixer.src_stream_out_ofs, | ||
832 | chip->mixer.dest_phys_outs, | ||
833 | chip->mixer.dest_phys_out_ofs, | ||
834 | "Stream Playback Volume"); | ||
835 | if (err < 0) | ||
836 | return err; | ||
837 | |||
838 | return init_mixer_values(chip); | ||
839 | } | ||
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c new file mode 100644 index 000000000000..c44db68eecb5 --- /dev/null +++ b/sound/pci/lola/lola_pcm.c | |||
@@ -0,0 +1,706 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include "lola.h" | ||
29 | |||
30 | #define LOLA_MAX_BDL_ENTRIES 8 | ||
31 | #define LOLA_MAX_BUF_SIZE (1024*1024*1024) | ||
32 | #define LOLA_BDL_ENTRY_SIZE (16 * 16) | ||
33 | |||
34 | static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream) | ||
35 | { | ||
36 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
37 | return &chip->pcm[substream->stream]; | ||
38 | } | ||
39 | |||
40 | static struct lola_stream *lola_get_stream(struct snd_pcm_substream *substream) | ||
41 | { | ||
42 | struct lola_pcm *pcm = lola_get_pcm(substream); | ||
43 | unsigned int idx = substream->number; | ||
44 | return &pcm->streams[idx]; | ||
45 | } | ||
46 | |||
47 | static unsigned int lola_get_lrc(struct lola *chip) | ||
48 | { | ||
49 | return lola_readl(chip, BAR1, LRC); | ||
50 | } | ||
51 | |||
52 | static unsigned int lola_get_tstamp(struct lola *chip, bool quick_no_sync) | ||
53 | { | ||
54 | unsigned int tstamp = lola_get_lrc(chip) >> 8; | ||
55 | if (chip->granularity) { | ||
56 | unsigned int wait_banks = quick_no_sync ? 0 : 8; | ||
57 | tstamp += (wait_banks + 1) * chip->granularity - 1; | ||
58 | tstamp -= tstamp % chip->granularity; | ||
59 | } | ||
60 | return tstamp << 8; | ||
61 | } | ||
62 | |||
63 | /* clear any pending interrupt status */ | ||
64 | static void lola_stream_clear_pending_irq(struct lola *chip, | ||
65 | struct lola_stream *str) | ||
66 | { | ||
67 | unsigned int val = lola_dsd_read(chip, str->dsd, STS); | ||
68 | val &= LOLA_DSD_STS_DESE | LOLA_DSD_STS_BCIS; | ||
69 | if (val) | ||
70 | lola_dsd_write(chip, str->dsd, STS, val); | ||
71 | } | ||
72 | |||
73 | static void lola_stream_start(struct lola *chip, struct lola_stream *str, | ||
74 | unsigned int tstamp) | ||
75 | { | ||
76 | lola_stream_clear_pending_irq(chip, str); | ||
77 | lola_dsd_write(chip, str->dsd, CTL, | ||
78 | LOLA_DSD_CTL_SRUN | | ||
79 | LOLA_DSD_CTL_IOCE | | ||
80 | LOLA_DSD_CTL_DEIE | | ||
81 | LOLA_DSD_CTL_VLRCV | | ||
82 | tstamp); | ||
83 | } | ||
84 | |||
85 | static void lola_stream_stop(struct lola *chip, struct lola_stream *str, | ||
86 | unsigned int tstamp) | ||
87 | { | ||
88 | lola_dsd_write(chip, str->dsd, CTL, | ||
89 | LOLA_DSD_CTL_IOCE | | ||
90 | LOLA_DSD_CTL_DEIE | | ||
91 | LOLA_DSD_CTL_VLRCV | | ||
92 | tstamp); | ||
93 | lola_stream_clear_pending_irq(chip, str); | ||
94 | } | ||
95 | |||
96 | static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) | ||
97 | { | ||
98 | unsigned long end_time = jiffies + msecs_to_jiffies(200); | ||
99 | while (time_before(jiffies, end_time)) { | ||
100 | unsigned int val; | ||
101 | val = lola_dsd_read(chip, str->dsd, CTL); | ||
102 | if (!(val & LOLA_DSD_CTL_SRST)) | ||
103 | return; | ||
104 | msleep(1); | ||
105 | } | ||
106 | printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); | ||
107 | } | ||
108 | |||
109 | static int lola_stream_wait_for_fifo(struct lola *chip, | ||
110 | struct lola_stream *str, | ||
111 | bool ready) | ||
112 | { | ||
113 | unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; | ||
114 | unsigned long end_time = jiffies + msecs_to_jiffies(200); | ||
115 | while (time_before(jiffies, end_time)) { | ||
116 | unsigned int reg = lola_dsd_read(chip, str->dsd, STS); | ||
117 | if ((reg & LOLA_DSD_STS_FIFORDY) == val) | ||
118 | return 0; | ||
119 | msleep(1); | ||
120 | } | ||
121 | printk(KERN_WARNING SFX "FIFO not ready (stream %d)\n", str->dsd); | ||
122 | return -EIO; | ||
123 | } | ||
124 | |||
125 | /* sync for FIFO ready/empty for all linked streams; | ||
126 | * clear paused flag when FIFO gets ready again | ||
127 | */ | ||
128 | static int lola_sync_wait_for_fifo(struct lola *chip, | ||
129 | struct snd_pcm_substream *substream, | ||
130 | bool ready) | ||
131 | { | ||
132 | unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; | ||
133 | unsigned long end_time = jiffies + msecs_to_jiffies(200); | ||
134 | struct snd_pcm_substream *s; | ||
135 | int pending = 0; | ||
136 | |||
137 | while (time_before(jiffies, end_time)) { | ||
138 | pending = 0; | ||
139 | snd_pcm_group_for_each_entry(s, substream) { | ||
140 | struct lola_stream *str; | ||
141 | if (s->pcm->card != substream->pcm->card) | ||
142 | continue; | ||
143 | str = lola_get_stream(s); | ||
144 | if (str->prepared && str->paused) { | ||
145 | unsigned int reg; | ||
146 | reg = lola_dsd_read(chip, str->dsd, STS); | ||
147 | if ((reg & LOLA_DSD_STS_FIFORDY) != val) { | ||
148 | pending = str->dsd + 1; | ||
149 | break; | ||
150 | } | ||
151 | if (ready) | ||
152 | str->paused = 0; | ||
153 | } | ||
154 | } | ||
155 | if (!pending) | ||
156 | return 0; | ||
157 | msleep(1); | ||
158 | } | ||
159 | printk(KERN_WARNING SFX "FIFO not ready (pending %d)\n", pending - 1); | ||
160 | return -EIO; | ||
161 | } | ||
162 | |||
163 | /* finish pause - prepare for a new resume */ | ||
164 | static void lola_sync_pause(struct lola *chip, | ||
165 | struct snd_pcm_substream *substream) | ||
166 | { | ||
167 | struct snd_pcm_substream *s; | ||
168 | |||
169 | lola_sync_wait_for_fifo(chip, substream, false); | ||
170 | snd_pcm_group_for_each_entry(s, substream) { | ||
171 | struct lola_stream *str; | ||
172 | if (s->pcm->card != substream->pcm->card) | ||
173 | continue; | ||
174 | str = lola_get_stream(s); | ||
175 | if (str->paused && str->prepared) | ||
176 | lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN | | ||
177 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); | ||
178 | } | ||
179 | lola_sync_wait_for_fifo(chip, substream, true); | ||
180 | } | ||
181 | |||
182 | static void lola_stream_reset(struct lola *chip, struct lola_stream *str) | ||
183 | { | ||
184 | if (str->prepared) { | ||
185 | if (str->paused) | ||
186 | lola_sync_pause(chip, str->substream); | ||
187 | str->prepared = 0; | ||
188 | lola_dsd_write(chip, str->dsd, CTL, | ||
189 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); | ||
190 | lola_stream_wait_for_fifo(chip, str, false); | ||
191 | lola_stream_clear_pending_irq(chip, str); | ||
192 | lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); | ||
193 | lola_dsd_write(chip, str->dsd, LVI, 0); | ||
194 | lola_dsd_write(chip, str->dsd, BDPU, 0); | ||
195 | lola_dsd_write(chip, str->dsd, BDPL, 0); | ||
196 | wait_for_srst_clear(chip, str); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static struct snd_pcm_hardware lola_pcm_hw = { | ||
201 | .info = (SNDRV_PCM_INFO_MMAP | | ||
202 | SNDRV_PCM_INFO_INTERLEAVED | | ||
203 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
204 | SNDRV_PCM_INFO_MMAP_VALID | | ||
205 | SNDRV_PCM_INFO_PAUSE), | ||
206 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | ||
207 | SNDRV_PCM_FMTBIT_S24_LE | | ||
208 | SNDRV_PCM_FMTBIT_S32_LE | | ||
209 | SNDRV_PCM_FMTBIT_FLOAT_LE), | ||
210 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
211 | .rate_min = 8000, | ||
212 | .rate_max = 192000, | ||
213 | .channels_min = 1, | ||
214 | .channels_max = 2, | ||
215 | .buffer_bytes_max = LOLA_MAX_BUF_SIZE, | ||
216 | .period_bytes_min = 128, | ||
217 | .period_bytes_max = LOLA_MAX_BUF_SIZE / 2, | ||
218 | .periods_min = 2, | ||
219 | .periods_max = LOLA_MAX_BDL_ENTRIES, | ||
220 | .fifo_size = 0, | ||
221 | }; | ||
222 | |||
223 | static int lola_pcm_open(struct snd_pcm_substream *substream) | ||
224 | { | ||
225 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
226 | struct lola_pcm *pcm = lola_get_pcm(substream); | ||
227 | struct lola_stream *str = lola_get_stream(substream); | ||
228 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
229 | |||
230 | mutex_lock(&chip->open_mutex); | ||
231 | if (str->opened) { | ||
232 | mutex_unlock(&chip->open_mutex); | ||
233 | return -EBUSY; | ||
234 | } | ||
235 | str->substream = substream; | ||
236 | str->master = NULL; | ||
237 | str->opened = 1; | ||
238 | runtime->hw = lola_pcm_hw; | ||
239 | runtime->hw.channels_max = pcm->num_streams - str->index; | ||
240 | if (chip->sample_rate) { | ||
241 | /* sample rate is locked */ | ||
242 | runtime->hw.rate_min = chip->sample_rate; | ||
243 | runtime->hw.rate_max = chip->sample_rate; | ||
244 | } else { | ||
245 | runtime->hw.rate_min = chip->sample_rate_min; | ||
246 | runtime->hw.rate_max = chip->sample_rate_max; | ||
247 | } | ||
248 | chip->ref_count_rate++; | ||
249 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
250 | /* period size = multiple of chip->granularity (8, 16 or 32 frames)*/ | ||
251 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
252 | chip->granularity); | ||
253 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
254 | chip->granularity); | ||
255 | mutex_unlock(&chip->open_mutex); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static void lola_cleanup_slave_streams(struct lola_pcm *pcm, | ||
260 | struct lola_stream *str) | ||
261 | { | ||
262 | int i; | ||
263 | for (i = str->index + 1; i < pcm->num_streams; i++) { | ||
264 | struct lola_stream *s = &pcm->streams[i]; | ||
265 | if (s->master != str) | ||
266 | break; | ||
267 | s->master = NULL; | ||
268 | s->opened = 0; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static int lola_pcm_close(struct snd_pcm_substream *substream) | ||
273 | { | ||
274 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
275 | struct lola_stream *str = lola_get_stream(substream); | ||
276 | |||
277 | mutex_lock(&chip->open_mutex); | ||
278 | if (str->substream == substream) { | ||
279 | str->substream = NULL; | ||
280 | str->opened = 0; | ||
281 | } | ||
282 | if (--chip->ref_count_rate == 0) { | ||
283 | /* release sample rate */ | ||
284 | chip->sample_rate = 0; | ||
285 | } | ||
286 | mutex_unlock(&chip->open_mutex); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int lola_pcm_hw_params(struct snd_pcm_substream *substream, | ||
291 | struct snd_pcm_hw_params *hw_params) | ||
292 | { | ||
293 | struct lola_stream *str = lola_get_stream(substream); | ||
294 | |||
295 | str->bufsize = 0; | ||
296 | str->period_bytes = 0; | ||
297 | str->format_verb = 0; | ||
298 | return snd_pcm_lib_malloc_pages(substream, | ||
299 | params_buffer_bytes(hw_params)); | ||
300 | } | ||
301 | |||
302 | static int lola_pcm_hw_free(struct snd_pcm_substream *substream) | ||
303 | { | ||
304 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
305 | struct lola_pcm *pcm = lola_get_pcm(substream); | ||
306 | struct lola_stream *str = lola_get_stream(substream); | ||
307 | |||
308 | mutex_lock(&chip->open_mutex); | ||
309 | lola_stream_reset(chip, str); | ||
310 | lola_cleanup_slave_streams(pcm, str); | ||
311 | mutex_unlock(&chip->open_mutex); | ||
312 | return snd_pcm_lib_free_pages(substream); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * set up a BDL entry | ||
317 | */ | ||
318 | static int setup_bdle(struct snd_pcm_substream *substream, | ||
319 | struct lola_stream *str, u32 **bdlp, | ||
320 | int ofs, int size) | ||
321 | { | ||
322 | u32 *bdl = *bdlp; | ||
323 | |||
324 | while (size > 0) { | ||
325 | dma_addr_t addr; | ||
326 | int chunk; | ||
327 | |||
328 | if (str->frags >= LOLA_MAX_BDL_ENTRIES) | ||
329 | return -EINVAL; | ||
330 | |||
331 | addr = snd_pcm_sgbuf_get_addr(substream, ofs); | ||
332 | /* program the address field of the BDL entry */ | ||
333 | bdl[0] = cpu_to_le32((u32)addr); | ||
334 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | ||
335 | /* program the size field of the BDL entry */ | ||
336 | chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); | ||
337 | bdl[2] = cpu_to_le32(chunk); | ||
338 | /* program the IOC to enable interrupt | ||
339 | * only when the whole fragment is processed | ||
340 | */ | ||
341 | size -= chunk; | ||
342 | bdl[3] = size ? 0 : cpu_to_le32(0x01); | ||
343 | bdl += 4; | ||
344 | str->frags++; | ||
345 | ofs += chunk; | ||
346 | } | ||
347 | *bdlp = bdl; | ||
348 | return ofs; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * set up BDL entries | ||
353 | */ | ||
354 | static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm, | ||
355 | struct snd_pcm_substream *substream, | ||
356 | struct lola_stream *str) | ||
357 | { | ||
358 | u32 *bdl; | ||
359 | int i, ofs, periods, period_bytes; | ||
360 | |||
361 | period_bytes = str->period_bytes; | ||
362 | periods = str->bufsize / period_bytes; | ||
363 | |||
364 | /* program the initial BDL entries */ | ||
365 | bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index); | ||
366 | ofs = 0; | ||
367 | str->frags = 0; | ||
368 | for (i = 0; i < periods; i++) { | ||
369 | ofs = setup_bdle(substream, str, &bdl, ofs, period_bytes); | ||
370 | if (ofs < 0) | ||
371 | goto error; | ||
372 | } | ||
373 | return 0; | ||
374 | |||
375 | error: | ||
376 | snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n", | ||
377 | str->bufsize, period_bytes); | ||
378 | return -EINVAL; | ||
379 | } | ||
380 | |||
381 | static unsigned int lola_get_format_verb(struct snd_pcm_substream *substream) | ||
382 | { | ||
383 | unsigned int verb; | ||
384 | |||
385 | switch (substream->runtime->format) { | ||
386 | case SNDRV_PCM_FORMAT_S16_LE: | ||
387 | verb = 0x00000000; | ||
388 | break; | ||
389 | case SNDRV_PCM_FORMAT_S24_LE: | ||
390 | verb = 0x00000200; | ||
391 | break; | ||
392 | case SNDRV_PCM_FORMAT_S32_LE: | ||
393 | verb = 0x00000300; | ||
394 | break; | ||
395 | case SNDRV_PCM_FORMAT_FLOAT_LE: | ||
396 | verb = 0x00001300; | ||
397 | break; | ||
398 | default: | ||
399 | return 0; | ||
400 | } | ||
401 | verb |= substream->runtime->channels; | ||
402 | return verb; | ||
403 | } | ||
404 | |||
405 | static int lola_set_stream_config(struct lola *chip, | ||
406 | struct lola_stream *str, | ||
407 | int channels) | ||
408 | { | ||
409 | int i, err; | ||
410 | unsigned int verb, val; | ||
411 | |||
412 | /* set format info for all channels | ||
413 | * (with only one command for the first channel) | ||
414 | */ | ||
415 | err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT, | ||
416 | str->format_verb, 0, &val, NULL); | ||
417 | if (err < 0) { | ||
418 | printk(KERN_ERR SFX "Cannot set stream format 0x%x\n", | ||
419 | str->format_verb); | ||
420 | return err; | ||
421 | } | ||
422 | |||
423 | /* update stream - channel config */ | ||
424 | for (i = 0; i < channels; i++) { | ||
425 | verb = (str->index << 6) | i; | ||
426 | err = lola_codec_read(chip, str[i].nid, | ||
427 | LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb, | ||
428 | &val, NULL); | ||
429 | if (err < 0) { | ||
430 | printk(KERN_ERR SFX "Cannot set stream channel %d\n", i); | ||
431 | return err; | ||
432 | } | ||
433 | } | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * set up the SD for streaming | ||
439 | */ | ||
440 | static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm, | ||
441 | struct lola_stream *str) | ||
442 | { | ||
443 | dma_addr_t bdl; | ||
444 | |||
445 | if (str->prepared) | ||
446 | return -EINVAL; | ||
447 | |||
448 | /* set up BDL */ | ||
449 | bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index; | ||
450 | lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl); | ||
451 | lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl)); | ||
452 | /* program the stream LVI (last valid index) of the BDL */ | ||
453 | lola_dsd_write(chip, str->dsd, LVI, str->frags - 1); | ||
454 | lola_stream_clear_pending_irq(chip, str); | ||
455 | |||
456 | lola_dsd_write(chip, str->dsd, CTL, | ||
457 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN); | ||
458 | |||
459 | str->prepared = 1; | ||
460 | |||
461 | return lola_stream_wait_for_fifo(chip, str, true); | ||
462 | } | ||
463 | |||
464 | static int lola_pcm_prepare(struct snd_pcm_substream *substream) | ||
465 | { | ||
466 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
467 | struct lola_pcm *pcm = lola_get_pcm(substream); | ||
468 | struct lola_stream *str = lola_get_stream(substream); | ||
469 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
470 | unsigned int bufsize, period_bytes, format_verb; | ||
471 | int i, err; | ||
472 | |||
473 | mutex_lock(&chip->open_mutex); | ||
474 | lola_stream_reset(chip, str); | ||
475 | lola_cleanup_slave_streams(pcm, str); | ||
476 | if (str->index + runtime->channels > pcm->num_streams) { | ||
477 | mutex_unlock(&chip->open_mutex); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | for (i = 1; i < runtime->channels; i++) { | ||
481 | str[i].master = str; | ||
482 | str[i].opened = 1; | ||
483 | } | ||
484 | mutex_unlock(&chip->open_mutex); | ||
485 | |||
486 | bufsize = snd_pcm_lib_buffer_bytes(substream); | ||
487 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
488 | format_verb = lola_get_format_verb(substream); | ||
489 | |||
490 | str->bufsize = bufsize; | ||
491 | str->period_bytes = period_bytes; | ||
492 | str->format_verb = format_verb; | ||
493 | |||
494 | err = lola_setup_periods(chip, pcm, substream, str); | ||
495 | if (err < 0) | ||
496 | return err; | ||
497 | |||
498 | err = lola_set_sample_rate(chip, runtime->rate); | ||
499 | if (err < 0) | ||
500 | return err; | ||
501 | chip->sample_rate = runtime->rate; /* sample rate gets locked */ | ||
502 | |||
503 | err = lola_set_stream_config(chip, str, runtime->channels); | ||
504 | if (err < 0) | ||
505 | return err; | ||
506 | |||
507 | err = lola_setup_controller(chip, pcm, str); | ||
508 | if (err < 0) { | ||
509 | lola_stream_reset(chip, str); | ||
510 | return err; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
517 | { | ||
518 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
519 | struct lola_stream *str; | ||
520 | struct snd_pcm_substream *s; | ||
521 | unsigned int start; | ||
522 | unsigned int tstamp; | ||
523 | bool sync_streams; | ||
524 | |||
525 | switch (cmd) { | ||
526 | case SNDRV_PCM_TRIGGER_START: | ||
527 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
528 | case SNDRV_PCM_TRIGGER_RESUME: | ||
529 | start = 1; | ||
530 | break; | ||
531 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
532 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
533 | case SNDRV_PCM_TRIGGER_STOP: | ||
534 | start = 0; | ||
535 | break; | ||
536 | default: | ||
537 | return -EINVAL; | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * sample correct synchronization is only needed starting several | ||
542 | * streams. On stop or if only one stream do as quick as possible | ||
543 | */ | ||
544 | sync_streams = (start && snd_pcm_stream_linked(substream)); | ||
545 | tstamp = lola_get_tstamp(chip, !sync_streams); | ||
546 | spin_lock(&chip->reg_lock); | ||
547 | snd_pcm_group_for_each_entry(s, substream) { | ||
548 | if (s->pcm->card != substream->pcm->card) | ||
549 | continue; | ||
550 | str = lola_get_stream(s); | ||
551 | if (start) | ||
552 | lola_stream_start(chip, str, tstamp); | ||
553 | else | ||
554 | lola_stream_stop(chip, str, tstamp); | ||
555 | str->running = start; | ||
556 | str->paused = !start; | ||
557 | snd_pcm_trigger_done(s, substream); | ||
558 | } | ||
559 | spin_unlock(&chip->reg_lock); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream) | ||
564 | { | ||
565 | struct lola *chip = snd_pcm_substream_chip(substream); | ||
566 | struct lola_stream *str = lola_get_stream(substream); | ||
567 | unsigned int pos = lola_dsd_read(chip, str->dsd, LPIB); | ||
568 | |||
569 | if (pos >= str->bufsize) | ||
570 | pos = 0; | ||
571 | return bytes_to_frames(substream->runtime, pos); | ||
572 | } | ||
573 | |||
574 | void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits) | ||
575 | { | ||
576 | int i; | ||
577 | |||
578 | for (i = 0; bits && i < pcm->num_streams; i++) { | ||
579 | if (bits & (1 << i)) { | ||
580 | struct lola_stream *str = &pcm->streams[i]; | ||
581 | if (str->substream && str->running) | ||
582 | snd_pcm_period_elapsed(str->substream); | ||
583 | bits &= ~(1 << i); | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | static struct snd_pcm_ops lola_pcm_ops = { | ||
589 | .open = lola_pcm_open, | ||
590 | .close = lola_pcm_close, | ||
591 | .ioctl = snd_pcm_lib_ioctl, | ||
592 | .hw_params = lola_pcm_hw_params, | ||
593 | .hw_free = lola_pcm_hw_free, | ||
594 | .prepare = lola_pcm_prepare, | ||
595 | .trigger = lola_pcm_trigger, | ||
596 | .pointer = lola_pcm_pointer, | ||
597 | .page = snd_pcm_sgbuf_ops_page, | ||
598 | }; | ||
599 | |||
600 | int __devinit lola_create_pcm(struct lola *chip) | ||
601 | { | ||
602 | struct snd_pcm *pcm; | ||
603 | int i, err; | ||
604 | |||
605 | for (i = 0; i < 2; i++) { | ||
606 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | ||
607 | snd_dma_pci_data(chip->pci), | ||
608 | PAGE_SIZE, &chip->pcm[i].bdl); | ||
609 | if (err < 0) | ||
610 | return err; | ||
611 | } | ||
612 | |||
613 | err = snd_pcm_new(chip->card, "Digigram Lola", 0, | ||
614 | chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams, | ||
615 | chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams, | ||
616 | &pcm); | ||
617 | if (err < 0) | ||
618 | return err; | ||
619 | strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name)); | ||
620 | pcm->private_data = chip; | ||
621 | for (i = 0; i < 2; i++) { | ||
622 | if (chip->pcm[i].num_streams) | ||
623 | snd_pcm_set_ops(pcm, i, &lola_pcm_ops); | ||
624 | } | ||
625 | /* buffer pre-allocation */ | ||
626 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | ||
627 | snd_dma_pci_data(chip->pci), | ||
628 | 1024 * 64, 32 * 1024 * 1024); | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | void lola_free_pcm(struct lola *chip) | ||
633 | { | ||
634 | snd_dma_free_pages(&chip->pcm[0].bdl); | ||
635 | snd_dma_free_pages(&chip->pcm[1].bdl); | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | */ | ||
640 | |||
641 | static int lola_init_stream(struct lola *chip, struct lola_stream *str, | ||
642 | int idx, int nid, int dir) | ||
643 | { | ||
644 | unsigned int val; | ||
645 | int err; | ||
646 | |||
647 | str->nid = nid; | ||
648 | str->index = idx; | ||
649 | str->dsd = idx; | ||
650 | if (dir == PLAY) | ||
651 | str->dsd += MAX_STREAM_IN_COUNT; | ||
652 | err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
653 | if (err < 0) { | ||
654 | printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); | ||
655 | return err; | ||
656 | } | ||
657 | if (dir == PLAY) { | ||
658 | /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */ | ||
659 | if ((val & 0x00f00dff) != 0x00000010) { | ||
660 | printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", | ||
661 | val, nid); | ||
662 | return -EINVAL; | ||
663 | } | ||
664 | } else { | ||
665 | /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) | ||
666 | * (bug : ignore bit8: Conn list = 0/1) | ||
667 | */ | ||
668 | if ((val & 0x00f00cff) != 0x00100010) { | ||
669 | printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", | ||
670 | val, nid); | ||
671 | return -EINVAL; | ||
672 | } | ||
673 | /* test bit9:DIGITAL and bit12:SRC_PRESENT*/ | ||
674 | if ((val & 0x00001200) == 0x00001200) | ||
675 | chip->input_src_caps_mask |= (1 << idx); | ||
676 | } | ||
677 | |||
678 | err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val); | ||
679 | if (err < 0) { | ||
680 | printk(KERN_ERR SFX "Can't read FORMATS 0x%x\n", nid); | ||
681 | return err; | ||
682 | } | ||
683 | val &= 3; | ||
684 | if (val == 3) | ||
685 | str->can_float = true; | ||
686 | if (!(val & 1)) { | ||
687 | printk(KERN_ERR SFX "Invalid formats 0x%x for 0x%x", val, nid); | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp) | ||
694 | { | ||
695 | struct lola_pcm *pcm = &chip->pcm[dir]; | ||
696 | int i, nid, err; | ||
697 | |||
698 | nid = *nidp; | ||
699 | for (i = 0; i < pcm->num_streams; i++, nid++) { | ||
700 | err = lola_init_stream(chip, &pcm->streams[i], i, nid, dir); | ||
701 | if (err < 0) | ||
702 | return err; | ||
703 | } | ||
704 | *nidp = nid; | ||
705 | return 0; | ||
706 | } | ||
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c new file mode 100644 index 000000000000..9d7daf897c9d --- /dev/null +++ b/sound/pci/lola/lola_proc.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * Support for Digigram Lola PCI-e boards | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
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 Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/info.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include "lola.h" | ||
28 | |||
29 | static void print_audio_widget(struct snd_info_buffer *buffer, | ||
30 | struct lola *chip, int nid, const char *name) | ||
31 | { | ||
32 | unsigned int val; | ||
33 | |||
34 | lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
35 | snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val); | ||
36 | lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val); | ||
37 | snd_iprintf(buffer, " Formats: 0x%x\n", val); | ||
38 | } | ||
39 | |||
40 | static void print_pin_widget(struct snd_info_buffer *buffer, | ||
41 | struct lola *chip, int nid, unsigned int ampcap, | ||
42 | const char *name) | ||
43 | { | ||
44 | unsigned int val; | ||
45 | |||
46 | lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
47 | snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val); | ||
48 | if (val == 0x00400200) | ||
49 | return; | ||
50 | lola_read_param(chip, nid, ampcap, &val); | ||
51 | snd_iprintf(buffer, " Amp-Caps: 0x%x\n", val); | ||
52 | snd_iprintf(buffer, " mute=%d, step-size=%d, steps=%d, ofs=%d\n", | ||
53 | LOLA_AMP_MUTE_CAPABLE(val), | ||
54 | LOLA_AMP_STEP_SIZE(val), | ||
55 | LOLA_AMP_NUM_STEPS(val), | ||
56 | LOLA_AMP_OFFSET(val)); | ||
57 | lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, NULL); | ||
58 | snd_iprintf(buffer, " Max-level: 0x%x\n", val); | ||
59 | } | ||
60 | |||
61 | static void print_clock_widget(struct snd_info_buffer *buffer, | ||
62 | struct lola *chip, int nid) | ||
63 | { | ||
64 | int i, j, num_clocks; | ||
65 | unsigned int val; | ||
66 | |||
67 | lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
68 | snd_iprintf(buffer, "Node 0x%02x [Clock] wcaps 0x%x\n", nid, val); | ||
69 | num_clocks = val & 0xff; | ||
70 | for (i = 0; i < num_clocks; i += 4) { | ||
71 | unsigned int res_ex; | ||
72 | unsigned short items[4]; | ||
73 | const char *name; | ||
74 | |||
75 | lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, | ||
76 | i, 0, &val, &res_ex); | ||
77 | items[0] = val & 0xfff; | ||
78 | items[1] = (val >> 16) & 0xfff; | ||
79 | items[2] = res_ex & 0xfff; | ||
80 | items[3] = (res_ex >> 16) & 0xfff; | ||
81 | for (j = 0; j < 4; j++) { | ||
82 | unsigned char type = items[j] >> 8; | ||
83 | unsigned int freq = items[j] & 0xff; | ||
84 | if (i + j >= num_clocks) | ||
85 | break; | ||
86 | if (type == LOLA_CLOCK_TYPE_INTERNAL) { | ||
87 | name = "Internal"; | ||
88 | freq = lola_sample_rate_convert(freq); | ||
89 | } else if (type == LOLA_CLOCK_TYPE_VIDEO) { | ||
90 | name = "Video"; | ||
91 | freq = lola_sample_rate_convert(freq); | ||
92 | } else { | ||
93 | name = "Other"; | ||
94 | } | ||
95 | snd_iprintf(buffer, " Clock %d: Type %d:%s, freq=%d\n", | ||
96 | i + j, type, name, freq); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void print_mixer_widget(struct snd_info_buffer *buffer, | ||
102 | struct lola *chip, int nid) | ||
103 | { | ||
104 | unsigned int val; | ||
105 | |||
106 | lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); | ||
107 | snd_iprintf(buffer, "Node 0x%02x [Mixer] wcaps 0x%x\n", nid, val); | ||
108 | } | ||
109 | |||
110 | static void lola_proc_codec_read(struct snd_info_entry *entry, | ||
111 | struct snd_info_buffer *buffer) | ||
112 | { | ||
113 | struct lola *chip = entry->private_data; | ||
114 | unsigned int val; | ||
115 | int i, nid; | ||
116 | |||
117 | lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val); | ||
118 | snd_iprintf(buffer, "Vendor: 0x%08x\n", val); | ||
119 | lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val); | ||
120 | snd_iprintf(buffer, "Function Type: %d\n", val); | ||
121 | lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val); | ||
122 | snd_iprintf(buffer, "Specific-Caps: 0x%08x\n", val); | ||
123 | snd_iprintf(buffer, " Pins-In %d, Pins-Out %d\n", | ||
124 | chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins); | ||
125 | nid = 2; | ||
126 | for (i = 0; i < chip->pcm[CAPT].num_streams; i++, nid++) | ||
127 | print_audio_widget(buffer, chip, nid, "[Audio-In]"); | ||
128 | for (i = 0; i < chip->pcm[PLAY].num_streams; i++, nid++) | ||
129 | print_audio_widget(buffer, chip, nid, "[Audio-Out]"); | ||
130 | for (i = 0; i < chip->pin[CAPT].num_pins; i++, nid++) | ||
131 | print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_IN_CAP, | ||
132 | "[Pin-In]"); | ||
133 | for (i = 0; i < chip->pin[PLAY].num_pins; i++, nid++) | ||
134 | print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_OUT_CAP, | ||
135 | "[Pin-Out]"); | ||
136 | if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) { | ||
137 | print_clock_widget(buffer, chip, nid); | ||
138 | nid++; | ||
139 | } | ||
140 | if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) { | ||
141 | print_mixer_widget(buffer, chip, nid); | ||
142 | nid++; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* direct codec access for debugging */ | ||
147 | static void lola_proc_codec_rw_write(struct snd_info_entry *entry, | ||
148 | struct snd_info_buffer *buffer) | ||
149 | { | ||
150 | struct lola *chip = entry->private_data; | ||
151 | char line[64]; | ||
152 | unsigned int id, verb, data, extdata; | ||
153 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
154 | if (sscanf(line, "%i %i %i %i", &id, &verb, &data, &extdata) != 4) | ||
155 | continue; | ||
156 | lola_codec_read(chip, id, verb, data, extdata, | ||
157 | &chip->debug_res, | ||
158 | &chip->debug_res_ex); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static void lola_proc_codec_rw_read(struct snd_info_entry *entry, | ||
163 | struct snd_info_buffer *buffer) | ||
164 | { | ||
165 | struct lola *chip = entry->private_data; | ||
166 | snd_iprintf(buffer, "0x%x 0x%x\n", chip->debug_res, chip->debug_res_ex); | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * dump some registers | ||
171 | */ | ||
172 | static void lola_proc_regs_read(struct snd_info_entry *entry, | ||
173 | struct snd_info_buffer *buffer) | ||
174 | { | ||
175 | struct lola *chip = entry->private_data; | ||
176 | int i; | ||
177 | |||
178 | for (i = 0; i < 0x40; i += 4) { | ||
179 | snd_iprintf(buffer, "BAR0 %02x: %08x\n", i, | ||
180 | readl(chip->bar[BAR0].remap_addr + i)); | ||
181 | } | ||
182 | snd_iprintf(buffer, "\n"); | ||
183 | for (i = 0; i < 0x30; i += 4) { | ||
184 | snd_iprintf(buffer, "BAR1 %02x: %08x\n", i, | ||
185 | readl(chip->bar[BAR1].remap_addr + i)); | ||
186 | } | ||
187 | snd_iprintf(buffer, "\n"); | ||
188 | for (i = 0x80; i < 0xa0; i += 4) { | ||
189 | snd_iprintf(buffer, "BAR1 %02x: %08x\n", i, | ||
190 | readl(chip->bar[BAR1].remap_addr + i)); | ||
191 | } | ||
192 | snd_iprintf(buffer, "\n"); | ||
193 | for (i = 0; i < 32; i++) { | ||
194 | snd_iprintf(buffer, "DSD %02x STS %08x\n", i, | ||
195 | lola_dsd_read(chip, i, STS)); | ||
196 | snd_iprintf(buffer, "DSD %02x LPIB %08x\n", i, | ||
197 | lola_dsd_read(chip, i, LPIB)); | ||
198 | snd_iprintf(buffer, "DSD %02x CTL %08x\n", i, | ||
199 | lola_dsd_read(chip, i, CTL)); | ||
200 | snd_iprintf(buffer, "DSD %02x LVIL %08x\n", i, | ||
201 | lola_dsd_read(chip, i, LVI)); | ||
202 | snd_iprintf(buffer, "DSD %02x BDPL %08x\n", i, | ||
203 | lola_dsd_read(chip, i, BDPL)); | ||
204 | snd_iprintf(buffer, "DSD %02x BDPU %08x\n", i, | ||
205 | lola_dsd_read(chip, i, BDPU)); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | void __devinit lola_proc_debug_new(struct lola *chip) | ||
210 | { | ||
211 | struct snd_info_entry *entry; | ||
212 | |||
213 | if (!snd_card_proc_new(chip->card, "codec", &entry)) | ||
214 | snd_info_set_text_ops(entry, chip, lola_proc_codec_read); | ||
215 | if (!snd_card_proc_new(chip->card, "codec_rw", &entry)) { | ||
216 | snd_info_set_text_ops(entry, chip, lola_proc_codec_rw_read); | ||
217 | entry->mode |= S_IWUSR; | ||
218 | entry->c.text.write = lola_proc_codec_rw_write; | ||
219 | } | ||
220 | if (!snd_card_proc_new(chip->card, "regs", &entry)) | ||
221 | snd_info_set_text_ops(entry, chip, lola_proc_regs_read); | ||
222 | } | ||
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 961d98297695..9cea84c3e0c6 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -1000,7 +1000,7 @@ static void device_change_handler(struct work_struct *work) | |||
1000 | chip->lineout_sw_ctl); | 1000 | chip->lineout_sw_ctl); |
1001 | if (mix->anded_reset) | 1001 | if (mix->anded_reset) |
1002 | msleep(10); | 1002 | msleep(10); |
1003 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, | 1003 | check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify, |
1004 | chip->speaker_sw_ctl); | 1004 | chip->speaker_sw_ctl); |
1005 | } else { | 1005 | } else { |
1006 | /* unmute speaker, mute others */ | 1006 | /* unmute speaker, mute others */ |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index af3c73053ee4..28afbbf69ce0 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -184,7 +184,7 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = { | |||
184 | .codec_dai_name = "wm8731-hifi", | 184 | .codec_dai_name = "wm8731-hifi", |
185 | .init = at91sam9g20ek_wm8731_init, | 185 | .init = at91sam9g20ek_wm8731_init, |
186 | .platform_name = "atmel-pcm-audio", | 186 | .platform_name = "atmel-pcm-audio", |
187 | .codec_name = "wm8731-codec.0-001b", | 187 | .codec_name = "wm8731.0-001b", |
188 | .ops = &at91sam9g20ek_ops, | 188 | .ops = &at91sam9g20ek_ops, |
189 | }; | 189 | }; |
190 | 190 | ||
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index cb99f04abe88..1d3e258c9ea8 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -77,7 +77,7 @@ static struct snd_soc_dai_link db1200_i2s_dai = { | |||
77 | .codec_dai_name = "wm8731-hifi", | 77 | .codec_dai_name = "wm8731-hifi", |
78 | .cpu_dai_name = "au1xpsc_i2s.1", | 78 | .cpu_dai_name = "au1xpsc_i2s.1", |
79 | .platform_name = "au1xpsc-pcm.1", | 79 | .platform_name = "au1xpsc-pcm.1", |
80 | .codec_name = "wm8731-codec.0-001b", | 80 | .codec_name = "wm8731.0-001b", |
81 | .ops = &db1200_i2s_wm8731_ops, | 81 | .ops = &db1200_i2s_wm8731_ops, |
82 | }; | 82 | }; |
83 | 83 | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 5a2fd8abaefa..98b44b316e78 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -243,6 +243,9 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
243 | 243 | ||
244 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 244 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
245 | { | 245 | { |
246 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
247 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
248 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
246 | struct snd_pcm_runtime *runtime = substream->runtime; | 249 | struct snd_pcm_runtime *runtime = substream->runtime; |
247 | int ret; | 250 | int ret; |
248 | 251 | ||
@@ -314,6 +317,9 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | |||
314 | 317 | ||
315 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 318 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
316 | { | 319 | { |
320 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
321 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
322 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
317 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | 323 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; |
318 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 324 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
319 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max | 325 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max |
@@ -377,6 +383,9 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
377 | struct snd_dma_buffer *buf; | 383 | struct snd_dma_buffer *buf; |
378 | int stream; | 384 | int stream; |
379 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | 385 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
386 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
387 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
388 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
380 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * | 389 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * |
381 | sizeof(struct ac97_frame) / 4; | 390 | sizeof(struct ac97_frame) / 4; |
382 | #endif | 391 | #endif |
@@ -405,8 +414,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
405 | } | 414 | } |
406 | #endif | 415 | #endif |
407 | } | 416 | } |
408 | if (sport_handle) | ||
409 | sport_done(sport_handle); | ||
410 | } | 417 | } |
411 | 418 | ||
412 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 419 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
@@ -458,7 +465,7 @@ static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) | |||
458 | 465 | ||
459 | static struct platform_driver bf5xx_pcm_driver = { | 466 | static struct platform_driver bf5xx_pcm_driver = { |
460 | .driver = { | 467 | .driver = { |
461 | .name = "bf5xx-pcm-audio", | 468 | .name = "bfin-ac97-pcm-audio", |
462 | .owner = THIS_MODULE, | 469 | .owner = THIS_MODULE, |
463 | }, | 470 | }, |
464 | 471 | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index ffbac26b9bce..6d2162590889 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -41,48 +41,7 @@ | |||
41 | * anomaly does not affect blackfin sound drivers. | 41 | * anomaly does not affect blackfin sound drivers. |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static int *cmd_count; | 44 | static struct sport_device *ac97_sport_handle; |
45 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
46 | |||
47 | #define SPORT_REQ(x) \ | ||
48 | [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ | ||
49 | P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} | ||
50 | static u16 sport_req[][7] = { | ||
51 | #ifdef SPORT0_TCR1 | ||
52 | SPORT_REQ(0), | ||
53 | #endif | ||
54 | #ifdef SPORT1_TCR1 | ||
55 | SPORT_REQ(1), | ||
56 | #endif | ||
57 | #ifdef SPORT2_TCR1 | ||
58 | SPORT_REQ(2), | ||
59 | #endif | ||
60 | #ifdef SPORT3_TCR1 | ||
61 | SPORT_REQ(3), | ||
62 | #endif | ||
63 | }; | ||
64 | |||
65 | #define SPORT_PARAMS(x) \ | ||
66 | [x] = { \ | ||
67 | .dma_rx_chan = CH_SPORT##x##_RX, \ | ||
68 | .dma_tx_chan = CH_SPORT##x##_TX, \ | ||
69 | .err_irq = IRQ_SPORT##x##_ERROR, \ | ||
70 | .regs = (struct sport_register *)SPORT##x##_TCR1, \ | ||
71 | } | ||
72 | static struct sport_param sport_params[4] = { | ||
73 | #ifdef SPORT0_TCR1 | ||
74 | SPORT_PARAMS(0), | ||
75 | #endif | ||
76 | #ifdef SPORT1_TCR1 | ||
77 | SPORT_PARAMS(1), | ||
78 | #endif | ||
79 | #ifdef SPORT2_TCR1 | ||
80 | SPORT_PARAMS(2), | ||
81 | #endif | ||
82 | #ifdef SPORT3_TCR1 | ||
83 | SPORT_PARAMS(3), | ||
84 | #endif | ||
85 | }; | ||
86 | 45 | ||
87 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, | 46 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, |
88 | size_t count, unsigned int chan_mask) | 47 | size_t count, unsigned int chan_mask) |
@@ -140,7 +99,8 @@ static unsigned int sport_tx_curr_frag(struct sport_device *sport) | |||
140 | 99 | ||
141 | static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | 100 | static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) |
142 | { | 101 | { |
143 | struct sport_device *sport = sport_handle; | 102 | struct sport_device *sport = ac97_sport_handle; |
103 | int *cmd_count = sport->private_data; | ||
144 | int nextfrag = sport_tx_curr_frag(sport); | 104 | int nextfrag = sport_tx_curr_frag(sport); |
145 | struct ac97_frame *nextwrite; | 105 | struct ac97_frame *nextwrite; |
146 | 106 | ||
@@ -161,6 +121,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | |||
161 | static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, | 121 | static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, |
162 | unsigned short reg) | 122 | unsigned short reg) |
163 | { | 123 | { |
124 | struct sport_device *sport_handle = ac97_sport_handle; | ||
164 | struct ac97_frame out_frame[2], in_frame[2]; | 125 | struct ac97_frame out_frame[2], in_frame[2]; |
165 | 126 | ||
166 | pr_debug("%s enter 0x%x\n", __func__, reg); | 127 | pr_debug("%s enter 0x%x\n", __func__, reg); |
@@ -185,6 +146,8 @@ static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, | |||
185 | void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | 146 | void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, |
186 | unsigned short val) | 147 | unsigned short val) |
187 | { | 148 | { |
149 | struct sport_device *sport_handle = ac97_sport_handle; | ||
150 | |||
188 | pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val); | 151 | pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val); |
189 | 152 | ||
190 | if (sport_handle->tx_run) { | 153 | if (sport_handle->tx_run) { |
@@ -203,28 +166,19 @@ void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
203 | 166 | ||
204 | static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97) | 167 | static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97) |
205 | { | 168 | { |
206 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF561) || \ | 169 | struct sport_device *sport_handle = ac97_sport_handle; |
207 | (defined(BF537_FAMILY) && (CONFIG_SND_BF5XX_SPORT_NUM == 1)) | 170 | u16 gpio = P_IDENT(sport_handle->pin_req[3]); |
208 | |||
209 | #define CONCAT(a, b, c) a ## b ## c | ||
210 | #define BFIN_SPORT_RFS(x) CONCAT(P_SPORT, x, _RFS) | ||
211 | |||
212 | u16 per = BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM); | ||
213 | u16 gpio = P_IDENT(BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM)); | ||
214 | 171 | ||
215 | pr_debug("%s enter\n", __func__); | 172 | pr_debug("%s enter\n", __func__); |
216 | 173 | ||
217 | peripheral_free(per); | 174 | peripheral_free_list(sport_handle->pin_req); |
218 | gpio_request(gpio, "bf5xx-ac97"); | 175 | gpio_request(gpio, "bf5xx-ac97"); |
219 | gpio_direction_output(gpio, 1); | 176 | gpio_direction_output(gpio, 1); |
220 | udelay(2); | 177 | udelay(2); |
221 | gpio_set_value(gpio, 0); | 178 | gpio_set_value(gpio, 0); |
222 | udelay(1); | 179 | udelay(1); |
223 | gpio_free(gpio); | 180 | gpio_free(gpio); |
224 | peripheral_request(per, "soc-audio"); | 181 | peripheral_request_list(sport_handle->pin_req, "soc-audio"); |
225 | #else | ||
226 | pr_info("%s: Not implemented\n", __func__); | ||
227 | #endif | ||
228 | } | 182 | } |
229 | 183 | ||
230 | static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) | 184 | static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) |
@@ -306,18 +260,32 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
306 | #define bf5xx_ac97_resume NULL | 260 | #define bf5xx_ac97_resume NULL |
307 | #endif | 261 | #endif |
308 | 262 | ||
309 | static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | 263 | static struct snd_soc_dai_driver bfin_ac97_dai = { |
264 | .ac97_control = 1, | ||
265 | .suspend = bf5xx_ac97_suspend, | ||
266 | .resume = bf5xx_ac97_resume, | ||
267 | .playback = { | ||
268 | .stream_name = "AC97 Playback", | ||
269 | .channels_min = 2, | ||
270 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
271 | .channels_max = 6, | ||
272 | #else | ||
273 | .channels_max = 2, | ||
274 | #endif | ||
275 | .rates = SNDRV_PCM_RATE_48000, | ||
276 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
277 | .capture = { | ||
278 | .stream_name = "AC97 Capture", | ||
279 | .channels_min = 2, | ||
280 | .channels_max = 2, | ||
281 | .rates = SNDRV_PCM_RATE_48000, | ||
282 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
283 | }; | ||
284 | |||
285 | static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev) | ||
310 | { | 286 | { |
311 | int ret = 0; | 287 | struct sport_device *sport_handle; |
312 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); | 288 | int ret; |
313 | if (cmd_count == NULL) | ||
314 | return -ENOMEM; | ||
315 | |||
316 | if (peripheral_request_list(sport_req[sport_num], "soc-audio")) { | ||
317 | pr_err("Requesting Peripherals failed\n"); | ||
318 | ret = -EFAULT; | ||
319 | goto peripheral_err; | ||
320 | } | ||
321 | 289 | ||
322 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 290 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
323 | /* Request PB3 as reset pin */ | 291 | /* Request PB3 as reset pin */ |
@@ -329,12 +297,14 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | |||
329 | } | 297 | } |
330 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | 298 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); |
331 | #endif | 299 | #endif |
332 | sport_handle = sport_init(&sport_params[sport_num], 2, \ | 300 | |
333 | sizeof(struct ac97_frame), NULL); | 301 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), |
302 | PAGE_SIZE); | ||
334 | if (!sport_handle) { | 303 | if (!sport_handle) { |
335 | ret = -ENODEV; | 304 | ret = -ENODEV; |
336 | goto sport_err; | 305 | goto sport_err; |
337 | } | 306 | } |
307 | |||
338 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 308 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
339 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | 309 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) |
340 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); | 310 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); |
@@ -361,67 +331,37 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | |||
361 | goto sport_config_err; | 331 | goto sport_config_err; |
362 | } | 332 | } |
363 | 333 | ||
334 | ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); | ||
335 | if (ret) { | ||
336 | pr_err("Failed to register DAI: %d\n", ret); | ||
337 | goto sport_config_err; | ||
338 | } | ||
339 | |||
340 | ac97_sport_handle = sport_handle; | ||
341 | |||
364 | return 0; | 342 | return 0; |
365 | 343 | ||
366 | sport_config_err: | 344 | sport_config_err: |
367 | kfree(sport_handle); | 345 | sport_done(sport_handle); |
368 | sport_err: | 346 | sport_err: |
369 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 347 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
370 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 348 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
371 | gpio_err: | 349 | gpio_err: |
372 | #endif | 350 | #endif |
373 | peripheral_free_list(sport_req[sport_num]); | ||
374 | peripheral_err: | ||
375 | free_page((unsigned long)cmd_count); | ||
376 | cmd_count = NULL; | ||
377 | 351 | ||
378 | return ret; | 352 | return ret; |
379 | } | 353 | } |
380 | 354 | ||
381 | static int bf5xx_ac97_remove(struct snd_soc_dai *dai) | 355 | static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) |
382 | { | 356 | { |
383 | free_page((unsigned long)cmd_count); | 357 | struct sport_device *sport_handle = platform_get_drvdata(pdev); |
384 | cmd_count = NULL; | 358 | |
385 | peripheral_free_list(sport_req[sport_num]); | 359 | snd_soc_unregister_dai(&pdev->dev); |
360 | sport_done(sport_handle); | ||
386 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 361 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
387 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 362 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
388 | #endif | 363 | #endif |
389 | return 0; | ||
390 | } | ||
391 | |||
392 | struct snd_soc_dai_driver bfin_ac97_dai = { | ||
393 | .ac97_control = 1, | ||
394 | .probe = bf5xx_ac97_probe, | ||
395 | .remove = bf5xx_ac97_remove, | ||
396 | .suspend = bf5xx_ac97_suspend, | ||
397 | .resume = bf5xx_ac97_resume, | ||
398 | .playback = { | ||
399 | .stream_name = "AC97 Playback", | ||
400 | .channels_min = 2, | ||
401 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
402 | .channels_max = 6, | ||
403 | #else | ||
404 | .channels_max = 2, | ||
405 | #endif | ||
406 | .rates = SNDRV_PCM_RATE_48000, | ||
407 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
408 | .capture = { | ||
409 | .stream_name = "AC97 Capture", | ||
410 | .channels_min = 2, | ||
411 | .channels_max = 2, | ||
412 | .rates = SNDRV_PCM_RATE_48000, | ||
413 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
414 | }; | ||
415 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); | ||
416 | |||
417 | static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev) | ||
418 | { | ||
419 | return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); | ||
420 | } | ||
421 | 364 | ||
422 | static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) | ||
423 | { | ||
424 | snd_soc_unregister_dai(&pdev->dev); | ||
425 | return 0; | 365 | return 0; |
426 | } | 366 | } |
427 | 367 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index 83012da9dfc2..ea4951cf5526 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -29,22 +29,12 @@ | |||
29 | #include <asm/portmux.h> | 29 | #include <asm/portmux.h> |
30 | 30 | ||
31 | #include "../codecs/ad1836.h" | 31 | #include "../codecs/ad1836.h" |
32 | #include "bf5xx-sport.h" | ||
33 | 32 | ||
34 | #include "bf5xx-tdm-pcm.h" | 33 | #include "bf5xx-tdm-pcm.h" |
35 | #include "bf5xx-tdm.h" | 34 | #include "bf5xx-tdm.h" |
36 | 35 | ||
37 | static struct snd_soc_card bf5xx_ad1836; | 36 | static struct snd_soc_card bf5xx_ad1836; |
38 | 37 | ||
39 | static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
43 | |||
44 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | 38 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, |
49 | struct snd_pcm_hw_params *params) | 39 | struct snd_pcm_hw_params *params) |
50 | { | 40 | { |
@@ -75,23 +65,33 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | |||
75 | } | 65 | } |
76 | 66 | ||
77 | static struct snd_soc_ops bf5xx_ad1836_ops = { | 67 | static struct snd_soc_ops bf5xx_ad1836_ops = { |
78 | .startup = bf5xx_ad1836_startup, | ||
79 | .hw_params = bf5xx_ad1836_hw_params, | 68 | .hw_params = bf5xx_ad1836_hw_params, |
80 | }; | 69 | }; |
81 | 70 | ||
82 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { | 71 | static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { |
83 | .name = "ad1836", | 72 | { |
84 | .stream_name = "AD1836", | 73 | .name = "ad1836", |
85 | .cpu_dai_name = "bf5xx-tdm", | 74 | .stream_name = "AD1836", |
86 | .codec_dai_name = "ad1836-hifi", | 75 | .cpu_dai_name = "bfin-tdm.0", |
87 | .platform_name = "bf5xx-tdm-pcm-audio", | 76 | .codec_dai_name = "ad1836-hifi", |
88 | .codec_name = "ad1836-codec.0", | 77 | .platform_name = "bfin-tdm-pcm-audio", |
89 | .ops = &bf5xx_ad1836_ops, | 78 | .codec_name = "ad1836.0", |
79 | .ops = &bf5xx_ad1836_ops, | ||
80 | }, | ||
81 | { | ||
82 | .name = "ad1836", | ||
83 | .stream_name = "AD1836", | ||
84 | .cpu_dai_name = "bfin-tdm.1", | ||
85 | .codec_dai_name = "ad1836-hifi", | ||
86 | .platform_name = "bfin-tdm-pcm-audio", | ||
87 | .codec_name = "ad1836.0", | ||
88 | .ops = &bf5xx_ad1836_ops, | ||
89 | }, | ||
90 | }; | 90 | }; |
91 | 91 | ||
92 | static struct snd_soc_card bf5xx_ad1836 = { | 92 | static struct snd_soc_card bf5xx_ad1836 = { |
93 | .name = "bf5xx_ad1836", | 93 | .name = "bfin-ad1836", |
94 | .dai_link = &bf5xx_ad1836_dai, | 94 | .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
95 | .num_links = 1, | 95 | .num_links = 1, |
96 | }; | 96 | }; |
97 | 97 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index d3ccb926b5e4..d6651c033cb7 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c | |||
@@ -38,30 +38,28 @@ | |||
38 | #include <asm/portmux.h> | 38 | #include <asm/portmux.h> |
39 | 39 | ||
40 | #include "../codecs/ad193x.h" | 40 | #include "../codecs/ad193x.h" |
41 | #include "bf5xx-sport.h" | ||
42 | 41 | ||
43 | #include "bf5xx-tdm-pcm.h" | 42 | #include "bf5xx-tdm-pcm.h" |
44 | #include "bf5xx-tdm.h" | 43 | #include "bf5xx-tdm.h" |
45 | 44 | ||
46 | static struct snd_soc_card bf5xx_ad193x; | 45 | static struct snd_soc_card bf5xx_ad193x; |
47 | 46 | ||
48 | static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) | ||
49 | { | ||
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
52 | |||
53 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | 47 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, |
58 | struct snd_pcm_hw_params *params) | 48 | struct snd_pcm_hw_params *params) |
59 | { | 49 | { |
60 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | unsigned int clk = 0; | ||
63 | unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; | 54 | unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; |
64 | int ret = 0; | 55 | int ret = 0; |
56 | |||
57 | switch (params_rate(params)) { | ||
58 | case 48000: | ||
59 | clk = 12288000; | ||
60 | break; | ||
61 | } | ||
62 | |||
65 | /* set cpu DAI configuration */ | 63 | /* set cpu DAI configuration */ |
66 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | | 64 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | |
67 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | 65 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); |
@@ -74,6 +72,12 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
74 | if (ret < 0) | 72 | if (ret < 0) |
75 | return ret; | 73 | return ret; |
76 | 74 | ||
75 | /* set the codec system clock for DAC and ADC */ | ||
76 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, | ||
77 | SND_SOC_CLOCK_IN); | ||
78 | if (ret < 0) | ||
79 | return ret; | ||
80 | |||
77 | /* set codec DAI slots, 8 channels, all channels are enabled */ | 81 | /* set codec DAI slots, 8 channels, all channels are enabled */ |
78 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32); | 82 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32); |
79 | if (ret < 0) | 83 | if (ret < 0) |
@@ -89,23 +93,33 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
89 | } | 93 | } |
90 | 94 | ||
91 | static struct snd_soc_ops bf5xx_ad193x_ops = { | 95 | static struct snd_soc_ops bf5xx_ad193x_ops = { |
92 | .startup = bf5xx_ad193x_startup, | ||
93 | .hw_params = bf5xx_ad193x_hw_params, | 96 | .hw_params = bf5xx_ad193x_hw_params, |
94 | }; | 97 | }; |
95 | 98 | ||
96 | static struct snd_soc_dai_link bf5xx_ad193x_dai = { | 99 | static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { |
97 | .name = "ad193x", | 100 | { |
98 | .stream_name = "AD193X", | 101 | .name = "ad193x", |
99 | .cpu_dai_name = "bf5xx-tdm", | 102 | .stream_name = "AD193X", |
100 | .codec_dai_name ="ad193x-hifi", | 103 | .cpu_dai_name = "bfin-tdm.0", |
101 | .platform_name = "bf5xx-tdm-pcm-audio", | 104 | .codec_dai_name ="ad193x-hifi", |
102 | .codec_name = "ad193x-codec.5", | 105 | .platform_name = "bfin-tdm-pcm-audio", |
103 | .ops = &bf5xx_ad193x_ops, | 106 | .codec_name = "ad193x.5", |
107 | .ops = &bf5xx_ad193x_ops, | ||
108 | }, | ||
109 | { | ||
110 | .name = "ad193x", | ||
111 | .stream_name = "AD193X", | ||
112 | .cpu_dai_name = "bfin-tdm.1", | ||
113 | .codec_dai_name ="ad193x-hifi", | ||
114 | .platform_name = "bfin-tdm-pcm-audio", | ||
115 | .codec_name = "ad193x.5", | ||
116 | .ops = &bf5xx_ad193x_ops, | ||
117 | }, | ||
104 | }; | 118 | }; |
105 | 119 | ||
106 | static struct snd_soc_card bf5xx_ad193x = { | 120 | static struct snd_soc_card bf5xx_ad193x = { |
107 | .name = "bf5xx_ad193x", | 121 | .name = "bfin-ad193x", |
108 | .dai_link = &bf5xx_ad193x_dai, | 122 | .dai_link = &bf5xx_ad193x_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
109 | .num_links = 1, | 123 | .num_links = 1, |
110 | }; | 124 | }; |
111 | 125 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index d57c9c9c9883..06a84b211b52 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -47,39 +47,34 @@ | |||
47 | #include <asm/portmux.h> | 47 | #include <asm/portmux.h> |
48 | 48 | ||
49 | #include "../codecs/ad1980.h" | 49 | #include "../codecs/ad1980.h" |
50 | #include "bf5xx-sport.h" | 50 | |
51 | #include "bf5xx-ac97-pcm.h" | 51 | #include "bf5xx-ac97-pcm.h" |
52 | #include "bf5xx-ac97.h" | 52 | #include "bf5xx-ac97.h" |
53 | 53 | ||
54 | static struct snd_soc_card bf5xx_board; | 54 | static struct snd_soc_card bf5xx_board; |
55 | 55 | ||
56 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) | 56 | static struct snd_soc_dai_link bf5xx_board_dai[] = { |
57 | { | 57 | { |
58 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 58 | .name = "AC97", |
59 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 59 | .stream_name = "AC97 HiFi", |
60 | 60 | .cpu_dai_name = "bfin-ac97.0", | |
61 | pr_debug("%s enter\n", __func__); | 61 | .codec_dai_name = "ad1980-hifi", |
62 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | 62 | .platform_name = "bfin-ac97-pcm-audio", |
63 | return 0; | 63 | .codec_name = "ad1980", |
64 | } | 64 | }, |
65 | 65 | { | |
66 | static struct snd_soc_ops bf5xx_board_ops = { | 66 | .name = "AC97", |
67 | .startup = bf5xx_board_startup, | 67 | .stream_name = "AC97 HiFi", |
68 | }; | 68 | .cpu_dai_name = "bfin-ac97.1", |
69 | 69 | .codec_dai_name = "ad1980-hifi", | |
70 | static struct snd_soc_dai_link bf5xx_board_dai = { | 70 | .platform_name = "bfin-ac97-pcm-audio", |
71 | .name = "AC97", | 71 | .codec_name = "ad1980", |
72 | .stream_name = "AC97 HiFi", | 72 | }, |
73 | .cpu_dai_name = "bfin-ac97", | ||
74 | .codec_dai_name = "ad1980-hifi", | ||
75 | .platform_name = "bfin-pcm-audio", | ||
76 | .codec_name = "ad1980-codec", | ||
77 | .ops = &bf5xx_board_ops, | ||
78 | }; | 73 | }; |
79 | 74 | ||
80 | static struct snd_soc_card bf5xx_board = { | 75 | static struct snd_soc_card bf5xx_board = { |
81 | .name = "bf5xx-board", | 76 | .name = "bfin-ad1980", |
82 | .dai_link = &bf5xx_board_dai, | 77 | .dai_link = &bf5xx_board_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
83 | .num_links = 1, | 78 | .num_links = 1, |
84 | }; | 79 | }; |
85 | 80 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 732fb8bad076..732a247f2527 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -145,16 +145,6 @@ static int bf5xx_probe(struct platform_device *pdev) | |||
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | 147 | ||
148 | static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) | ||
149 | { | ||
150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
151 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
152 | |||
153 | pr_debug("%s enter\n", __func__); | ||
154 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | 148 | static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, |
159 | struct snd_pcm_hw_params *params) | 149 | struct snd_pcm_hw_params *params) |
160 | { | 150 | { |
@@ -176,24 +166,34 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | |||
176 | 166 | ||
177 | 167 | ||
178 | static struct snd_soc_ops bf5xx_ad73311_ops = { | 168 | static struct snd_soc_ops bf5xx_ad73311_ops = { |
179 | .startup = bf5xx_ad73311_startup, | ||
180 | .hw_params = bf5xx_ad73311_hw_params, | 169 | .hw_params = bf5xx_ad73311_hw_params, |
181 | }; | 170 | }; |
182 | 171 | ||
183 | static struct snd_soc_dai_link bf5xx_ad73311_dai = { | 172 | static struct snd_soc_dai_link bf5xx_ad73311_dai[] = { |
184 | .name = "ad73311", | 173 | { |
185 | .stream_name = "AD73311", | 174 | .name = "ad73311", |
186 | .cpu_dai_name = "bf5xx-i2s", | 175 | .stream_name = "AD73311", |
187 | .codec_dai_name = "ad73311-hifi", | 176 | .cpu_dai_name = "bfin-i2s.0", |
188 | .platform_name = "bfin-pcm-audio", | 177 | .codec_dai_name = "ad73311-hifi", |
189 | .codec_name = "ad73311-codec", | 178 | .platform_name = "bfin-i2s-pcm-audio", |
190 | .ops = &bf5xx_ad73311_ops, | 179 | .codec_name = "ad73311", |
180 | .ops = &bf5xx_ad73311_ops, | ||
181 | }, | ||
182 | { | ||
183 | .name = "ad73311", | ||
184 | .stream_name = "AD73311", | ||
185 | .cpu_dai_name = "bfin-i2s.1", | ||
186 | .codec_dai_name = "ad73311-hifi", | ||
187 | .platform_name = "bfin-i2s-pcm-audio", | ||
188 | .codec_name = "ad73311", | ||
189 | .ops = &bf5xx_ad73311_ops, | ||
190 | }, | ||
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct snd_soc_card bf5xx_ad73311 = { | 193 | static struct snd_soc_card bf5xx_ad73311 = { |
194 | .name = "bf5xx_ad73311", | 194 | .name = "bfin-ad73311", |
195 | .probe = bf5xx_probe, | 195 | .probe = bf5xx_probe, |
196 | .dai_link = &bf5xx_ad73311_dai, | 196 | .dai_link = &bf5xx_ad73311_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
197 | .num_links = 1, | 197 | .num_links = 1, |
198 | }; | 198 | }; |
199 | 199 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 890a0dccf902..b5101efd1c87 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -148,10 +148,15 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
148 | 148 | ||
149 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 149 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
150 | { | 150 | { |
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
152 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
153 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
151 | struct snd_pcm_runtime *runtime = substream->runtime; | 154 | struct snd_pcm_runtime *runtime = substream->runtime; |
155 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
152 | int ret; | 156 | int ret; |
153 | 157 | ||
154 | pr_debug("%s enter\n", __func__); | 158 | pr_debug("%s enter\n", __func__); |
159 | |||
155 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 160 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
156 | 161 | ||
157 | ret = snd_pcm_hw_constraint_integer(runtime, \ | 162 | ret = snd_pcm_hw_constraint_integer(runtime, \ |
@@ -159,9 +164,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
159 | if (ret < 0) | 164 | if (ret < 0) |
160 | goto out; | 165 | goto out; |
161 | 166 | ||
162 | if (sport_handle != NULL) | 167 | if (sport_handle != NULL) { |
168 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
169 | sport_handle->tx_buf = buf->area; | ||
170 | else | ||
171 | sport_handle->rx_buf = buf->area; | ||
172 | |||
163 | runtime->private_data = sport_handle; | 173 | runtime->private_data = sport_handle; |
164 | else { | 174 | } else { |
165 | pr_err("sport_handle is NULL\n"); | 175 | pr_err("sport_handle is NULL\n"); |
166 | return -1; | 176 | return -1; |
167 | } | 177 | } |
@@ -214,11 +224,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
214 | pr_debug("%s, area:%p, size:0x%08lx\n", __func__, | 224 | pr_debug("%s, area:%p, size:0x%08lx\n", __func__, |
215 | buf->area, buf->bytes); | 225 | buf->area, buf->bytes); |
216 | 226 | ||
217 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
218 | sport_handle->tx_buf = buf->area; | ||
219 | else | ||
220 | sport_handle->rx_buf = buf->area; | ||
221 | |||
222 | return 0; | 227 | return 0; |
223 | } | 228 | } |
224 | 229 | ||
@@ -239,8 +244,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
239 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 244 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
240 | buf->area = NULL; | 245 | buf->area = NULL; |
241 | } | 246 | } |
242 | if (sport_handle) | ||
243 | sport_done(sport_handle); | ||
244 | } | 247 | } |
245 | 248 | ||
246 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 249 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
@@ -292,7 +295,7 @@ static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) | |||
292 | 295 | ||
293 | static struct platform_driver bfin_i2s_pcm_driver = { | 296 | static struct platform_driver bfin_i2s_pcm_driver = { |
294 | .driver = { | 297 | .driver = { |
295 | .name = "bfin-pcm-audio", | 298 | .name = "bfin-i2s-pcm-audio", |
296 | .owner = THIS_MODULE, | 299 | .owner = THIS_MODULE, |
297 | }, | 300 | }, |
298 | 301 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index d453b1e9d607..00cc3e00b2fe 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -51,59 +51,24 @@ struct bf5xx_i2s_port { | |||
51 | int configured; | 51 | int configured; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct bf5xx_i2s_port bf5xx_i2s; | ||
55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
56 | |||
57 | static struct sport_param sport_params[2] = { | ||
58 | { | ||
59 | .dma_rx_chan = CH_SPORT0_RX, | ||
60 | .dma_tx_chan = CH_SPORT0_TX, | ||
61 | .err_irq = IRQ_SPORT0_ERROR, | ||
62 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
63 | }, | ||
64 | { | ||
65 | .dma_rx_chan = CH_SPORT1_RX, | ||
66 | .dma_tx_chan = CH_SPORT1_TX, | ||
67 | .err_irq = IRQ_SPORT1_ERROR, | ||
68 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Setting the TFS pin selector for SPORT 0 based on whether the selected | ||
74 | * port id F or G. If the port is F then no conflict should exist for the | ||
75 | * TFS. When Port G is selected and EMAC then there is a conflict between | ||
76 | * the PHY interrupt line and TFS. Current settings prevent the conflict | ||
77 | * by ignoring the TFS pin when Port G is selected. This allows both | ||
78 | * codecs and EMAC using Port G concurrently. | ||
79 | */ | ||
80 | #ifdef CONFIG_BF527_SPORT0_PORTG | ||
81 | #define LOCAL_SPORT0_TFS (0) | ||
82 | #else | ||
83 | #define LOCAL_SPORT0_TFS (P_SPORT0_TFS) | ||
84 | #endif | ||
85 | |||
86 | static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, | ||
87 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, | ||
88 | {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, | ||
89 | P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; | ||
90 | |||
91 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 54 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
92 | unsigned int fmt) | 55 | unsigned int fmt) |
93 | { | 56 | { |
57 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
58 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
94 | int ret = 0; | 59 | int ret = 0; |
95 | 60 | ||
96 | /* interface format:support I2S,slave mode */ | 61 | /* interface format:support I2S,slave mode */ |
97 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 62 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
98 | case SND_SOC_DAIFMT_I2S: | 63 | case SND_SOC_DAIFMT_I2S: |
99 | bf5xx_i2s.tcr1 |= TFSR | TCKFE; | 64 | bf5xx_i2s->tcr1 |= TFSR | TCKFE; |
100 | bf5xx_i2s.rcr1 |= RFSR | RCKFE; | 65 | bf5xx_i2s->rcr1 |= RFSR | RCKFE; |
101 | bf5xx_i2s.tcr2 |= TSFSE; | 66 | bf5xx_i2s->tcr2 |= TSFSE; |
102 | bf5xx_i2s.rcr2 |= RSFSE; | 67 | bf5xx_i2s->rcr2 |= RSFSE; |
103 | break; | 68 | break; |
104 | case SND_SOC_DAIFMT_DSP_A: | 69 | case SND_SOC_DAIFMT_DSP_A: |
105 | bf5xx_i2s.tcr1 |= TFSR; | 70 | bf5xx_i2s->tcr1 |= TFSR; |
106 | bf5xx_i2s.rcr1 |= RFSR; | 71 | bf5xx_i2s->rcr1 |= RFSR; |
107 | break; | 72 | break; |
108 | case SND_SOC_DAIFMT_LEFT_J: | 73 | case SND_SOC_DAIFMT_LEFT_J: |
109 | ret = -EINVAL; | 74 | ret = -EINVAL; |
@@ -135,29 +100,35 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
135 | struct snd_pcm_hw_params *params, | 100 | struct snd_pcm_hw_params *params, |
136 | struct snd_soc_dai *dai) | 101 | struct snd_soc_dai *dai) |
137 | { | 102 | { |
103 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
104 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
138 | int ret = 0; | 105 | int ret = 0; |
139 | 106 | ||
140 | bf5xx_i2s.tcr2 &= ~0x1f; | 107 | bf5xx_i2s->tcr2 &= ~0x1f; |
141 | bf5xx_i2s.rcr2 &= ~0x1f; | 108 | bf5xx_i2s->rcr2 &= ~0x1f; |
142 | switch (params_format(params)) { | 109 | switch (params_format(params)) { |
110 | case SNDRV_PCM_FORMAT_S8: | ||
111 | bf5xx_i2s->tcr2 |= 7; | ||
112 | bf5xx_i2s->rcr2 |= 7; | ||
113 | sport_handle->wdsize = 1; | ||
143 | case SNDRV_PCM_FORMAT_S16_LE: | 114 | case SNDRV_PCM_FORMAT_S16_LE: |
144 | bf5xx_i2s.tcr2 |= 15; | 115 | bf5xx_i2s->tcr2 |= 15; |
145 | bf5xx_i2s.rcr2 |= 15; | 116 | bf5xx_i2s->rcr2 |= 15; |
146 | sport_handle->wdsize = 2; | 117 | sport_handle->wdsize = 2; |
147 | break; | 118 | break; |
148 | case SNDRV_PCM_FORMAT_S24_LE: | 119 | case SNDRV_PCM_FORMAT_S24_LE: |
149 | bf5xx_i2s.tcr2 |= 23; | 120 | bf5xx_i2s->tcr2 |= 23; |
150 | bf5xx_i2s.rcr2 |= 23; | 121 | bf5xx_i2s->rcr2 |= 23; |
151 | sport_handle->wdsize = 3; | 122 | sport_handle->wdsize = 3; |
152 | break; | 123 | break; |
153 | case SNDRV_PCM_FORMAT_S32_LE: | 124 | case SNDRV_PCM_FORMAT_S32_LE: |
154 | bf5xx_i2s.tcr2 |= 31; | 125 | bf5xx_i2s->tcr2 |= 31; |
155 | bf5xx_i2s.rcr2 |= 31; | 126 | bf5xx_i2s->rcr2 |= 31; |
156 | sport_handle->wdsize = 4; | 127 | sport_handle->wdsize = 4; |
157 | break; | 128 | break; |
158 | } | 129 | } |
159 | 130 | ||
160 | if (!bf5xx_i2s.configured) { | 131 | if (!bf5xx_i2s->configured) { |
161 | /* | 132 | /* |
162 | * TX and RX are not independent,they are enabled at the | 133 | * TX and RX are not independent,they are enabled at the |
163 | * same time, even if only one side is running. So, we | 134 | * same time, even if only one side is running. So, we |
@@ -166,16 +137,16 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
166 | * | 137 | * |
167 | * CPU DAI:slave mode. | 138 | * CPU DAI:slave mode. |
168 | */ | 139 | */ |
169 | bf5xx_i2s.configured = 1; | 140 | bf5xx_i2s->configured = 1; |
170 | ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, | 141 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
171 | bf5xx_i2s.rcr2, 0, 0); | 142 | bf5xx_i2s->rcr2, 0, 0); |
172 | if (ret) { | 143 | if (ret) { |
173 | pr_err("SPORT is busy!\n"); | 144 | pr_err("SPORT is busy!\n"); |
174 | return -EBUSY; | 145 | return -EBUSY; |
175 | } | 146 | } |
176 | 147 | ||
177 | ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1, | 148 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
178 | bf5xx_i2s.tcr2, 0, 0); | 149 | bf5xx_i2s->tcr2, 0, 0); |
179 | if (ret) { | 150 | if (ret) { |
180 | pr_err("SPORT is busy!\n"); | 151 | pr_err("SPORT is busy!\n"); |
181 | return -EBUSY; | 152 | return -EBUSY; |
@@ -188,41 +159,19 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
188 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, | 159 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, |
189 | struct snd_soc_dai *dai) | 160 | struct snd_soc_dai *dai) |
190 | { | 161 | { |
162 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
163 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
164 | |||
191 | pr_debug("%s enter\n", __func__); | 165 | pr_debug("%s enter\n", __func__); |
192 | /* No active stream, SPORT is allowed to be configured again. */ | 166 | /* No active stream, SPORT is allowed to be configured again. */ |
193 | if (!dai->active) | 167 | if (!dai->active) |
194 | bf5xx_i2s.configured = 0; | 168 | bf5xx_i2s->configured = 0; |
195 | } | ||
196 | |||
197 | static int bf5xx_i2s_probe(struct snd_soc_dai *dai) | ||
198 | { | ||
199 | pr_debug("%s enter\n", __func__); | ||
200 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | ||
201 | pr_err("Requesting Peripherals failed\n"); | ||
202 | return -EFAULT; | ||
203 | } | ||
204 | |||
205 | /* request DMA for SPORT */ | ||
206 | sport_handle = sport_init(&sport_params[sport_num], 4, \ | ||
207 | 2 * sizeof(u32), NULL); | ||
208 | if (!sport_handle) { | ||
209 | peripheral_free_list(&sport_req[sport_num][0]); | ||
210 | return -ENODEV; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int bf5xx_i2s_remove(struct snd_soc_dai *dai) | ||
217 | { | ||
218 | pr_debug("%s enter\n", __func__); | ||
219 | peripheral_free_list(&sport_req[sport_num][0]); | ||
220 | return 0; | ||
221 | } | 169 | } |
222 | 170 | ||
223 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
224 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | 172 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) |
225 | { | 173 | { |
174 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
226 | 175 | ||
227 | pr_debug("%s : sport %d\n", __func__, dai->id); | 176 | pr_debug("%s : sport %d\n", __func__, dai->id); |
228 | 177 | ||
@@ -235,19 +184,21 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | |||
235 | 184 | ||
236 | static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | 185 | static int bf5xx_i2s_resume(struct snd_soc_dai *dai) |
237 | { | 186 | { |
187 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
188 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
238 | int ret; | 189 | int ret; |
239 | 190 | ||
240 | pr_debug("%s : sport %d\n", __func__, dai->id); | 191 | pr_debug("%s : sport %d\n", __func__, dai->id); |
241 | 192 | ||
242 | ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, | 193 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
243 | bf5xx_i2s.rcr2, 0, 0); | 194 | bf5xx_i2s->rcr2, 0, 0); |
244 | if (ret) { | 195 | if (ret) { |
245 | pr_err("SPORT is busy!\n"); | 196 | pr_err("SPORT is busy!\n"); |
246 | return -EBUSY; | 197 | return -EBUSY; |
247 | } | 198 | } |
248 | 199 | ||
249 | ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1, | 200 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
250 | bf5xx_i2s.tcr2, 0, 0); | 201 | bf5xx_i2s->tcr2, 0, 0); |
251 | if (ret) { | 202 | if (ret) { |
252 | pr_err("SPORT is busy!\n"); | 203 | pr_err("SPORT is busy!\n"); |
253 | return -EBUSY; | 204 | return -EBUSY; |
@@ -266,8 +217,11 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | |||
266 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | 217 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ |
267 | SNDRV_PCM_RATE_96000) | 218 | SNDRV_PCM_RATE_96000) |
268 | 219 | ||
269 | #define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ | 220 | #define BF5XX_I2S_FORMATS \ |
270 | SNDRV_PCM_FMTBIT_S32_LE) | 221 | (SNDRV_PCM_FMTBIT_S8 | \ |
222 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
223 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
224 | SNDRV_PCM_FMTBIT_S32_LE) | ||
271 | 225 | ||
272 | static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | 226 | static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { |
273 | .shutdown = bf5xx_i2s_shutdown, | 227 | .shutdown = bf5xx_i2s_shutdown, |
@@ -276,8 +230,6 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | |||
276 | }; | 230 | }; |
277 | 231 | ||
278 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { | 232 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { |
279 | .probe = bf5xx_i2s_probe, | ||
280 | .remove = bf5xx_i2s_remove, | ||
281 | .suspend = bf5xx_i2s_suspend, | 233 | .suspend = bf5xx_i2s_suspend, |
282 | .resume = bf5xx_i2s_resume, | 234 | .resume = bf5xx_i2s_resume, |
283 | .playback = { | 235 | .playback = { |
@@ -293,23 +245,45 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = { | |||
293 | .ops = &bf5xx_i2s_dai_ops, | 245 | .ops = &bf5xx_i2s_dai_ops, |
294 | }; | 246 | }; |
295 | 247 | ||
296 | static int bfin_i2s_drv_probe(struct platform_device *pdev) | 248 | static int __devinit bf5xx_i2s_probe(struct platform_device *pdev) |
297 | { | 249 | { |
298 | return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); | 250 | struct sport_device *sport_handle; |
251 | int ret; | ||
252 | |||
253 | /* configure SPORT for I2S */ | ||
254 | sport_handle = sport_init(pdev, 4, 2 * sizeof(u32), | ||
255 | sizeof(struct bf5xx_i2s_port)); | ||
256 | if (!sport_handle) | ||
257 | return -ENODEV; | ||
258 | |||
259 | /* register with the ASoC layers */ | ||
260 | ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); | ||
261 | if (ret) { | ||
262 | pr_err("Failed to register DAI: %d\n", ret); | ||
263 | sport_done(sport_handle); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
299 | } | 268 | } |
300 | 269 | ||
301 | static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev) | 270 | static int __devexit bf5xx_i2s_remove(struct platform_device *pdev) |
302 | { | 271 | { |
272 | struct sport_device *sport_handle = platform_get_drvdata(pdev); | ||
273 | |||
274 | pr_debug("%s enter\n", __func__); | ||
275 | |||
303 | snd_soc_unregister_dai(&pdev->dev); | 276 | snd_soc_unregister_dai(&pdev->dev); |
277 | sport_done(sport_handle); | ||
278 | |||
304 | return 0; | 279 | return 0; |
305 | } | 280 | } |
306 | 281 | ||
307 | static struct platform_driver bfin_i2s_driver = { | 282 | static struct platform_driver bfin_i2s_driver = { |
308 | .probe = bfin_i2s_drv_probe, | 283 | .probe = bf5xx_i2s_probe, |
309 | .remove = __devexit_p(bfin_i2s_drv_remove), | 284 | .remove = __devexit_p(bf5xx_i2s_remove), |
310 | |||
311 | .driver = { | 285 | .driver = { |
312 | .name = "bf5xx-i2s", | 286 | .name = "bfin-i2s", |
313 | .owner = THIS_MODULE, | 287 | .owner = THIS_MODULE, |
314 | }, | 288 | }, |
315 | }; | 289 | }; |
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 99051ff0954e..a2d40349fcc4 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c | |||
@@ -42,8 +42,6 @@ | |||
42 | /* delay between frame sync pulse and first data bit in multichannel mode */ | 42 | /* delay between frame sync pulse and first data bit in multichannel mode */ |
43 | #define FRAME_DELAY (1<<12) | 43 | #define FRAME_DELAY (1<<12) |
44 | 44 | ||
45 | struct sport_device *sport_handle; | ||
46 | EXPORT_SYMBOL(sport_handle); | ||
47 | /* note: multichannel is in units of 8 channels, | 45 | /* note: multichannel is in units of 8 channels, |
48 | * tdm_count is # channels NOT / 8 ! */ | 46 | * tdm_count is # channels NOT / 8 ! */ |
49 | int sport_set_multichannel(struct sport_device *sport, | 47 | int sport_set_multichannel(struct sport_device *sport, |
@@ -798,86 +796,164 @@ int sport_set_err_callback(struct sport_device *sport, | |||
798 | } | 796 | } |
799 | EXPORT_SYMBOL(sport_set_err_callback); | 797 | EXPORT_SYMBOL(sport_set_err_callback); |
800 | 798 | ||
801 | struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | 799 | static int sport_config_pdev(struct platform_device *pdev, struct sport_param *param) |
802 | unsigned dummy_count, void *private_data) | ||
803 | { | 800 | { |
804 | int ret; | 801 | /* Extract settings from platform data */ |
802 | struct device *dev = &pdev->dev; | ||
803 | struct bfin_snd_platform_data *pdata = dev->platform_data; | ||
804 | struct resource *res; | ||
805 | |||
806 | param->num = pdev->id; | ||
807 | |||
808 | if (!pdata) { | ||
809 | dev_err(dev, "no platform_data\n"); | ||
810 | return -ENODEV; | ||
811 | } | ||
812 | param->pin_req = pdata->pin_req; | ||
813 | |||
814 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
815 | if (!res) { | ||
816 | dev_err(dev, "no MEM resource\n"); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | param->regs = (struct sport_register *)res->start; | ||
820 | |||
821 | /* first RX, then TX */ | ||
822 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
823 | if (!res) { | ||
824 | dev_err(dev, "no rx DMA resource\n"); | ||
825 | return -ENODEV; | ||
826 | } | ||
827 | param->dma_rx_chan = res->start; | ||
828 | |||
829 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
830 | if (!res) { | ||
831 | dev_err(dev, "no tx DMA resource\n"); | ||
832 | return -ENODEV; | ||
833 | } | ||
834 | param->dma_tx_chan = res->start; | ||
835 | |||
836 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
837 | if (!res) { | ||
838 | dev_err(dev, "no irq resource\n"); | ||
839 | return -ENODEV; | ||
840 | } | ||
841 | param->err_irq = res->start; | ||
842 | |||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | struct sport_device *sport_init(struct platform_device *pdev, | ||
847 | unsigned int wdsize, unsigned int dummy_count, size_t priv_size) | ||
848 | { | ||
849 | struct device *dev = &pdev->dev; | ||
850 | struct sport_param param; | ||
805 | struct sport_device *sport; | 851 | struct sport_device *sport; |
806 | pr_debug("%s enter\n", __func__); | 852 | int ret; |
807 | BUG_ON(param == NULL); | 853 | |
808 | BUG_ON(wdsize == 0 || dummy_count == 0); | 854 | dev_dbg(dev, "%s enter\n", __func__); |
809 | sport = kmalloc(sizeof(struct sport_device), GFP_KERNEL); | 855 | |
810 | if (!sport) { | 856 | param.wdsize = wdsize; |
811 | pr_err("Failed to allocate for sport device\n"); | 857 | param.dummy_count = dummy_count; |
858 | BUG_ON(param.wdsize == 0 || param.dummy_count == 0); | ||
859 | |||
860 | ret = sport_config_pdev(pdev, ¶m); | ||
861 | if (ret) | ||
862 | return NULL; | ||
863 | |||
864 | if (peripheral_request_list(param.pin_req, "soc-audio")) { | ||
865 | dev_err(dev, "requesting Peripherals failed\n"); | ||
812 | return NULL; | 866 | return NULL; |
813 | } | 867 | } |
814 | 868 | ||
815 | memset(sport, 0, sizeof(struct sport_device)); | 869 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); |
816 | sport->dma_rx_chan = param->dma_rx_chan; | 870 | if (!sport) { |
817 | sport->dma_tx_chan = param->dma_tx_chan; | 871 | dev_err(dev, "failed to allocate for sport device\n"); |
818 | sport->err_irq = param->err_irq; | 872 | goto __init_err0; |
819 | sport->regs = param->regs; | 873 | } |
820 | sport->private_data = private_data; | 874 | |
875 | sport->num = param.num; | ||
876 | sport->dma_rx_chan = param.dma_rx_chan; | ||
877 | sport->dma_tx_chan = param.dma_tx_chan; | ||
878 | sport->err_irq = param.err_irq; | ||
879 | sport->regs = param.regs; | ||
880 | sport->pin_req = param.pin_req; | ||
821 | 881 | ||
822 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { | 882 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { |
823 | pr_err("Failed to request RX dma %d\n", \ | 883 | dev_err(dev, "failed to request RX dma %d\n", sport->dma_rx_chan); |
824 | sport->dma_rx_chan); | ||
825 | goto __init_err1; | 884 | goto __init_err1; |
826 | } | 885 | } |
827 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { | 886 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { |
828 | pr_err("Failed to request RX irq %d\n", \ | 887 | dev_err(dev, "failed to request RX irq %d\n", sport->dma_rx_chan); |
829 | sport->dma_rx_chan); | ||
830 | goto __init_err2; | 888 | goto __init_err2; |
831 | } | 889 | } |
832 | 890 | ||
833 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { | 891 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { |
834 | pr_err("Failed to request TX dma %d\n", \ | 892 | dev_err(dev, "failed to request TX dma %d\n", sport->dma_tx_chan); |
835 | sport->dma_tx_chan); | ||
836 | goto __init_err2; | 893 | goto __init_err2; |
837 | } | 894 | } |
838 | 895 | ||
839 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { | 896 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { |
840 | pr_err("Failed to request TX irq %d\n", \ | 897 | dev_err(dev, "failed to request TX irq %d\n", sport->dma_tx_chan); |
841 | sport->dma_tx_chan); | ||
842 | goto __init_err3; | 898 | goto __init_err3; |
843 | } | 899 | } |
844 | 900 | ||
845 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", | 901 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", |
846 | sport) < 0) { | 902 | sport) < 0) { |
847 | pr_err("Failed to request err irq:%d\n", \ | 903 | dev_err(dev, "failed to request err irq %d\n", sport->err_irq); |
848 | sport->err_irq); | ||
849 | goto __init_err3; | 904 | goto __init_err3; |
850 | } | 905 | } |
851 | 906 | ||
852 | pr_err("dma rx:%d tx:%d, err irq:%d, regs:%p\n", | 907 | dev_info(dev, "dma rx:%d tx:%d, err irq:%d, regs:%p\n", |
853 | sport->dma_rx_chan, sport->dma_tx_chan, | 908 | sport->dma_rx_chan, sport->dma_tx_chan, |
854 | sport->err_irq, sport->regs); | 909 | sport->err_irq, sport->regs); |
855 | 910 | ||
856 | sport->wdsize = wdsize; | 911 | sport->wdsize = param.wdsize; |
857 | sport->dummy_count = dummy_count; | 912 | sport->dummy_count = param.dummy_count; |
913 | |||
914 | sport->private_data = kzalloc(priv_size, GFP_KERNEL); | ||
915 | if (!sport->private_data) { | ||
916 | dev_err(dev, "could not alloc priv data %zu bytes\n", priv_size); | ||
917 | goto __init_err4; | ||
918 | } | ||
858 | 919 | ||
859 | if (L1_DATA_A_LENGTH) | 920 | if (L1_DATA_A_LENGTH) |
860 | sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2); | 921 | sport->dummy_buf = l1_data_sram_zalloc(param.dummy_count * 2); |
861 | else | 922 | else |
862 | sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL); | 923 | sport->dummy_buf = kzalloc(param.dummy_count * 2, GFP_KERNEL); |
863 | if (sport->dummy_buf == NULL) { | 924 | if (sport->dummy_buf == NULL) { |
864 | pr_err("Failed to allocate dummy buffer\n"); | 925 | dev_err(dev, "failed to allocate dummy buffer\n"); |
865 | goto __error; | 926 | goto __error1; |
866 | } | 927 | } |
867 | 928 | ||
868 | ret = sport_config_rx_dummy(sport); | 929 | ret = sport_config_rx_dummy(sport); |
869 | if (ret) { | 930 | if (ret) { |
870 | pr_err("Failed to config rx dummy ring\n"); | 931 | dev_err(dev, "failed to config rx dummy ring\n"); |
871 | goto __error; | 932 | goto __error2; |
872 | } | 933 | } |
873 | ret = sport_config_tx_dummy(sport); | 934 | ret = sport_config_tx_dummy(sport); |
874 | if (ret) { | 935 | if (ret) { |
875 | pr_err("Failed to config tx dummy ring\n"); | 936 | dev_err(dev, "failed to config tx dummy ring\n"); |
876 | goto __error; | 937 | goto __error3; |
877 | } | 938 | } |
878 | 939 | ||
940 | platform_set_drvdata(pdev, sport); | ||
941 | |||
879 | return sport; | 942 | return sport; |
880 | __error: | 943 | __error3: |
944 | if (L1_DATA_A_LENGTH) | ||
945 | l1_data_sram_free(sport->dummy_rx_desc); | ||
946 | else | ||
947 | dma_free_coherent(NULL, 2*sizeof(struct dmasg), | ||
948 | sport->dummy_rx_desc, 0); | ||
949 | __error2: | ||
950 | if (L1_DATA_A_LENGTH) | ||
951 | l1_data_sram_free(sport->dummy_buf); | ||
952 | else | ||
953 | kfree(sport->dummy_buf); | ||
954 | __error1: | ||
955 | kfree(sport->private_data); | ||
956 | __init_err4: | ||
881 | free_irq(sport->err_irq, sport); | 957 | free_irq(sport->err_irq, sport); |
882 | __init_err3: | 958 | __init_err3: |
883 | free_dma(sport->dma_tx_chan); | 959 | free_dma(sport->dma_tx_chan); |
@@ -885,6 +961,8 @@ __init_err2: | |||
885 | free_dma(sport->dma_rx_chan); | 961 | free_dma(sport->dma_rx_chan); |
886 | __init_err1: | 962 | __init_err1: |
887 | kfree(sport); | 963 | kfree(sport); |
964 | __init_err0: | ||
965 | peripheral_free_list(param.pin_req); | ||
888 | return NULL; | 966 | return NULL; |
889 | } | 967 | } |
890 | EXPORT_SYMBOL(sport_init); | 968 | EXPORT_SYMBOL(sport_init); |
@@ -917,8 +995,9 @@ void sport_done(struct sport_device *sport) | |||
917 | free_dma(sport->dma_tx_chan); | 995 | free_dma(sport->dma_tx_chan); |
918 | free_irq(sport->err_irq, sport); | 996 | free_irq(sport->err_irq, sport); |
919 | 997 | ||
998 | kfree(sport->private_data); | ||
999 | peripheral_free_list(sport->pin_req); | ||
920 | kfree(sport); | 1000 | kfree(sport); |
921 | sport = NULL; | ||
922 | } | 1001 | } |
923 | EXPORT_SYMBOL(sport_done); | 1002 | EXPORT_SYMBOL(sport_done); |
924 | 1003 | ||
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index a86e8cc0b2d3..5ab60bd613ea 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * File: bf5xx_ac97_sport.h | 2 | * File: bf5xx_sport.h |
3 | * Based on: | 3 | * Based on: |
4 | * Author: Roy Huang <roy.huang@analog.com> | 4 | * Author: Roy Huang <roy.huang@analog.com> |
5 | * | 5 | * |
@@ -33,15 +33,18 @@ | |||
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/platform_device.h> | ||
36 | #include <asm/dma.h> | 37 | #include <asm/dma.h> |
37 | #include <asm/bfin_sport.h> | 38 | #include <asm/bfin_sport.h> |
38 | 39 | ||
39 | #define DESC_ELEMENT_COUNT 9 | 40 | #define DESC_ELEMENT_COUNT 9 |
40 | 41 | ||
41 | struct sport_device { | 42 | struct sport_device { |
43 | int num; | ||
42 | int dma_rx_chan; | 44 | int dma_rx_chan; |
43 | int dma_tx_chan; | 45 | int dma_tx_chan; |
44 | int err_irq; | 46 | int err_irq; |
47 | const unsigned short *pin_req; | ||
45 | struct sport_register *regs; | 48 | struct sport_register *regs; |
46 | 49 | ||
47 | unsigned char *rx_buf; | 50 | unsigned char *rx_buf; |
@@ -103,17 +106,20 @@ struct sport_device { | |||
103 | void *private_data; | 106 | void *private_data; |
104 | }; | 107 | }; |
105 | 108 | ||
106 | extern struct sport_device *sport_handle; | ||
107 | |||
108 | struct sport_param { | 109 | struct sport_param { |
110 | int num; | ||
109 | int dma_rx_chan; | 111 | int dma_rx_chan; |
110 | int dma_tx_chan; | 112 | int dma_tx_chan; |
111 | int err_irq; | 113 | int err_irq; |
114 | const unsigned short *pin_req; | ||
112 | struct sport_register *regs; | 115 | struct sport_register *regs; |
116 | unsigned int wdsize; | ||
117 | unsigned int dummy_count; | ||
118 | void *private_data; | ||
113 | }; | 119 | }; |
114 | 120 | ||
115 | struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | 121 | struct sport_device *sport_init(struct platform_device *pdev, |
116 | unsigned dummy_count, void *private_data); | 122 | unsigned int wdsize, unsigned int dummy_count, size_t priv_size); |
117 | 123 | ||
118 | void sport_done(struct sport_device *sport); | 124 | void sport_done(struct sport_device *sport); |
119 | 125 | ||
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index ad28663f5bbd..767e772a815d 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -44,16 +44,6 @@ | |||
44 | 44 | ||
45 | static struct snd_soc_card bf5xx_ssm2602; | 45 | static struct snd_soc_card bf5xx_ssm2602; |
46 | 46 | ||
47 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) | ||
48 | { | ||
49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
51 | |||
52 | pr_debug("%s enter\n", __func__); | ||
53 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | 47 | static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, |
58 | struct snd_pcm_hw_params *params) | 48 | struct snd_pcm_hw_params *params) |
59 | { | 49 | { |
@@ -109,23 +99,33 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
109 | } | 99 | } |
110 | 100 | ||
111 | static struct snd_soc_ops bf5xx_ssm2602_ops = { | 101 | static struct snd_soc_ops bf5xx_ssm2602_ops = { |
112 | .startup = bf5xx_ssm2602_startup, | ||
113 | .hw_params = bf5xx_ssm2602_hw_params, | 102 | .hw_params = bf5xx_ssm2602_hw_params, |
114 | }; | 103 | }; |
115 | 104 | ||
116 | static struct snd_soc_dai_link bf5xx_ssm2602_dai = { | 105 | static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = { |
117 | .name = "ssm2602", | 106 | { |
118 | .stream_name = "SSM2602", | 107 | .name = "ssm2602", |
119 | .cpu_dai_name = "bf5xx-i2s", | 108 | .stream_name = "SSM2602", |
120 | .codec_dai_name = "ssm2602-hifi", | 109 | .cpu_dai_name = "bfin-i2s.0", |
121 | .platform_name = "bf5xx-pcm-audio", | 110 | .codec_dai_name = "ssm2602-hifi", |
122 | .codec_name = "ssm2602-codec.0-001b", | 111 | .platform_name = "bfin-i2s-pcm-audio", |
123 | .ops = &bf5xx_ssm2602_ops, | 112 | .codec_name = "ssm2602.0-001b", |
113 | .ops = &bf5xx_ssm2602_ops, | ||
114 | }, | ||
115 | { | ||
116 | .name = "ssm2602", | ||
117 | .stream_name = "SSM2602", | ||
118 | .cpu_dai_name = "bfin-i2s.1", | ||
119 | .codec_dai_name = "ssm2602-hifi", | ||
120 | .platform_name = "bfin-i2s-pcm-audio", | ||
121 | .codec_name = "ssm2602.0-001b", | ||
122 | .ops = &bf5xx_ssm2602_ops, | ||
123 | }, | ||
124 | }; | 124 | }; |
125 | 125 | ||
126 | static struct snd_soc_card bf5xx_ssm2602 = { | 126 | static struct snd_soc_card bf5xx_ssm2602 = { |
127 | .name = "bf5xx_ssm2602", | 127 | .name = "bfin-ssm2602", |
128 | .dai_link = &bf5xx_ssm2602_dai, | 128 | .dai_link = &bf5xx_ssm2602_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
129 | .num_links = 1, | 129 | .num_links = 1, |
130 | }; | 130 | }; |
131 | 131 | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 74cf759b78a6..07cfc7a9e49a 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c | |||
@@ -154,7 +154,12 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
154 | 154 | ||
155 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 155 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
156 | { | 156 | { |
157 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
158 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
159 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
157 | struct snd_pcm_runtime *runtime = substream->runtime; | 160 | struct snd_pcm_runtime *runtime = substream->runtime; |
161 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
162 | |||
158 | int ret = 0; | 163 | int ret = 0; |
159 | 164 | ||
160 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 165 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
@@ -164,9 +169,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
164 | if (ret < 0) | 169 | if (ret < 0) |
165 | goto out; | 170 | goto out; |
166 | 171 | ||
167 | if (sport_handle != NULL) | 172 | if (sport_handle != NULL) { |
173 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
174 | sport_handle->tx_buf = buf->area; | ||
175 | else | ||
176 | sport_handle->rx_buf = buf->area; | ||
177 | |||
168 | runtime->private_data = sport_handle; | 178 | runtime->private_data = sport_handle; |
169 | else { | 179 | } else { |
170 | pr_err("sport_handle is NULL\n"); | 180 | pr_err("sport_handle is NULL\n"); |
171 | ret = -ENODEV; | 181 | ret = -ENODEV; |
172 | } | 182 | } |
@@ -249,11 +259,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
249 | } | 259 | } |
250 | buf->bytes = size; | 260 | buf->bytes = size; |
251 | 261 | ||
252 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
253 | sport_handle->tx_buf = buf->area; | ||
254 | else | ||
255 | sport_handle->rx_buf = buf->area; | ||
256 | |||
257 | return 0; | 262 | return 0; |
258 | } | 263 | } |
259 | 264 | ||
@@ -274,8 +279,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
274 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 279 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
275 | buf->area = NULL; | 280 | buf->area = NULL; |
276 | } | 281 | } |
277 | if (sport_handle) | ||
278 | sport_done(sport_handle); | ||
279 | } | 282 | } |
280 | 283 | ||
281 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
@@ -326,7 +329,7 @@ static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) | |||
326 | 329 | ||
327 | static struct platform_driver bfin_tdm_driver = { | 330 | static struct platform_driver bfin_tdm_driver = { |
328 | .driver = { | 331 | .driver = { |
329 | .name = "bf5xx-tdm-pcm-audio", | 332 | .name = "bfin-tdm-pcm-audio", |
330 | .owner = THIS_MODULE, | 333 | .owner = THIS_MODULE, |
331 | }, | 334 | }, |
332 | 335 | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 5515ac9e05c7..a822d1ee1380 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c | |||
@@ -46,43 +46,6 @@ | |||
46 | #include "bf5xx-sport.h" | 46 | #include "bf5xx-sport.h" |
47 | #include "bf5xx-tdm.h" | 47 | #include "bf5xx-tdm.h" |
48 | 48 | ||
49 | static struct bf5xx_tdm_port bf5xx_tdm; | ||
50 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
51 | |||
52 | static struct sport_param sport_params[2] = { | ||
53 | { | ||
54 | .dma_rx_chan = CH_SPORT0_RX, | ||
55 | .dma_tx_chan = CH_SPORT0_TX, | ||
56 | .err_irq = IRQ_SPORT0_ERROR, | ||
57 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
58 | }, | ||
59 | { | ||
60 | .dma_rx_chan = CH_SPORT1_RX, | ||
61 | .dma_tx_chan = CH_SPORT1_TX, | ||
62 | .err_irq = IRQ_SPORT1_ERROR, | ||
63 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Setting the TFS pin selector for SPORT 0 based on whether the selected | ||
69 | * port id F or G. If the port is F then no conflict should exist for the | ||
70 | * TFS. When Port G is selected and EMAC then there is a conflict between | ||
71 | * the PHY interrupt line and TFS. Current settings prevent the conflict | ||
72 | * by ignoring the TFS pin when Port G is selected. This allows both | ||
73 | * codecs and EMAC using Port G concurrently. | ||
74 | */ | ||
75 | #ifdef CONFIG_BF527_SPORT0_PORTG | ||
76 | #define LOCAL_SPORT0_TFS (0) | ||
77 | #else | ||
78 | #define LOCAL_SPORT0_TFS (P_SPORT0_TFS) | ||
79 | #endif | ||
80 | |||
81 | static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, | ||
82 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, | ||
83 | {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, | ||
84 | P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; | ||
85 | |||
86 | static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 49 | static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
87 | unsigned int fmt) | 50 | unsigned int fmt) |
88 | { | 51 | { |
@@ -119,14 +82,16 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
119 | struct snd_pcm_hw_params *params, | 82 | struct snd_pcm_hw_params *params, |
120 | struct snd_soc_dai *dai) | 83 | struct snd_soc_dai *dai) |
121 | { | 84 | { |
85 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
86 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
122 | int ret = 0; | 87 | int ret = 0; |
123 | 88 | ||
124 | bf5xx_tdm.tcr2 &= ~0x1f; | 89 | bf5xx_tdm->tcr2 &= ~0x1f; |
125 | bf5xx_tdm.rcr2 &= ~0x1f; | 90 | bf5xx_tdm->rcr2 &= ~0x1f; |
126 | switch (params_format(params)) { | 91 | switch (params_format(params)) { |
127 | case SNDRV_PCM_FORMAT_S32_LE: | 92 | case SNDRV_PCM_FORMAT_S32_LE: |
128 | bf5xx_tdm.tcr2 |= 31; | 93 | bf5xx_tdm->tcr2 |= 31; |
129 | bf5xx_tdm.rcr2 |= 31; | 94 | bf5xx_tdm->rcr2 |= 31; |
130 | sport_handle->wdsize = 4; | 95 | sport_handle->wdsize = 4; |
131 | break; | 96 | break; |
132 | /* at present, we only support 32bit transfer */ | 97 | /* at present, we only support 32bit transfer */ |
@@ -136,7 +101,7 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
136 | break; | 101 | break; |
137 | } | 102 | } |
138 | 103 | ||
139 | if (!bf5xx_tdm.configured) { | 104 | if (!bf5xx_tdm->configured) { |
140 | /* | 105 | /* |
141 | * TX and RX are not independent,they are enabled at the | 106 | * TX and RX are not independent,they are enabled at the |
142 | * same time, even if only one side is running. So, we | 107 | * same time, even if only one side is running. So, we |
@@ -145,21 +110,21 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
145 | * | 110 | * |
146 | * CPU DAI:slave mode. | 111 | * CPU DAI:slave mode. |
147 | */ | 112 | */ |
148 | ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1, | 113 | ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1, |
149 | bf5xx_tdm.rcr2, 0, 0); | 114 | bf5xx_tdm->rcr2, 0, 0); |
150 | if (ret) { | 115 | if (ret) { |
151 | pr_err("SPORT is busy!\n"); | 116 | pr_err("SPORT is busy!\n"); |
152 | return -EBUSY; | 117 | return -EBUSY; |
153 | } | 118 | } |
154 | 119 | ||
155 | ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1, | 120 | ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1, |
156 | bf5xx_tdm.tcr2, 0, 0); | 121 | bf5xx_tdm->tcr2, 0, 0); |
157 | if (ret) { | 122 | if (ret) { |
158 | pr_err("SPORT is busy!\n"); | 123 | pr_err("SPORT is busy!\n"); |
159 | return -EBUSY; | 124 | return -EBUSY; |
160 | } | 125 | } |
161 | 126 | ||
162 | bf5xx_tdm.configured = 1; | 127 | bf5xx_tdm->configured = 1; |
163 | } | 128 | } |
164 | 129 | ||
165 | return 0; | 130 | return 0; |
@@ -168,15 +133,20 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
168 | static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, | 133 | static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, |
169 | struct snd_soc_dai *dai) | 134 | struct snd_soc_dai *dai) |
170 | { | 135 | { |
136 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
137 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
138 | |||
171 | /* No active stream, SPORT is allowed to be configured again. */ | 139 | /* No active stream, SPORT is allowed to be configured again. */ |
172 | if (!dai->active) | 140 | if (!dai->active) |
173 | bf5xx_tdm.configured = 0; | 141 | bf5xx_tdm->configured = 0; |
174 | } | 142 | } |
175 | 143 | ||
176 | static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | 144 | static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, |
177 | unsigned int tx_num, unsigned int *tx_slot, | 145 | unsigned int tx_num, unsigned int *tx_slot, |
178 | unsigned int rx_num, unsigned int *rx_slot) | 146 | unsigned int rx_num, unsigned int *rx_slot) |
179 | { | 147 | { |
148 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
149 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
180 | int i; | 150 | int i; |
181 | unsigned int slot; | 151 | unsigned int slot; |
182 | unsigned int tx_mapped = 0, rx_mapped = 0; | 152 | unsigned int tx_mapped = 0, rx_mapped = 0; |
@@ -189,7 +159,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | |||
189 | slot = tx_slot[i]; | 159 | slot = tx_slot[i]; |
190 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | 160 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && |
191 | (!(tx_mapped & (1 << slot)))) { | 161 | (!(tx_mapped & (1 << slot)))) { |
192 | bf5xx_tdm.tx_map[i] = slot; | 162 | bf5xx_tdm->tx_map[i] = slot; |
193 | tx_mapped |= 1 << slot; | 163 | tx_mapped |= 1 << slot; |
194 | } else | 164 | } else |
195 | return -EINVAL; | 165 | return -EINVAL; |
@@ -198,7 +168,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | |||
198 | slot = rx_slot[i]; | 168 | slot = rx_slot[i]; |
199 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | 169 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && |
200 | (!(rx_mapped & (1 << slot)))) { | 170 | (!(rx_mapped & (1 << slot)))) { |
201 | bf5xx_tdm.rx_map[i] = slot; | 171 | bf5xx_tdm->rx_map[i] = slot; |
202 | rx_mapped |= 1 << slot; | 172 | rx_mapped |= 1 << slot; |
203 | } else | 173 | } else |
204 | return -EINVAL; | 174 | return -EINVAL; |
@@ -212,12 +182,14 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) | |||
212 | { | 182 | { |
213 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | 183 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
214 | 184 | ||
215 | if (!dai->active) | ||
216 | return 0; | ||
217 | if (dai->capture_active) | ||
218 | sport_rx_stop(sport); | ||
219 | if (dai->playback_active) | 185 | if (dai->playback_active) |
220 | sport_tx_stop(sport); | 186 | sport_tx_stop(sport); |
187 | if (dai->capture_active) | ||
188 | sport_rx_stop(sport); | ||
189 | |||
190 | /* isolate sync/clock pins from codec while sports resume */ | ||
191 | peripheral_free_list(sport->pin_req); | ||
192 | |||
221 | return 0; | 193 | return 0; |
222 | } | 194 | } |
223 | 195 | ||
@@ -226,9 +198,6 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | |||
226 | int ret; | 198 | int ret; |
227 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | 199 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
228 | 200 | ||
229 | if (!dai->active) | ||
230 | return 0; | ||
231 | |||
232 | ret = sport_set_multichannel(sport, 8, 0xFF, 1); | 201 | ret = sport_set_multichannel(sport, 8, 0xFF, 1); |
233 | if (ret) { | 202 | if (ret) { |
234 | pr_err("SPORT is busy!\n"); | 203 | pr_err("SPORT is busy!\n"); |
@@ -247,6 +216,8 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | |||
247 | ret = -EBUSY; | 216 | ret = -EBUSY; |
248 | } | 217 | } |
249 | 218 | ||
219 | peripheral_request_list(sport->pin_req, "soc-audio"); | ||
220 | |||
250 | return 0; | 221 | return 0; |
251 | } | 222 | } |
252 | 223 | ||
@@ -280,20 +251,14 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = { | |||
280 | 251 | ||
281 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) | 252 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) |
282 | { | 253 | { |
283 | int ret = 0; | 254 | struct sport_device *sport_handle; |
284 | 255 | int ret; | |
285 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | ||
286 | pr_err("Requesting Peripherals failed\n"); | ||
287 | return -EFAULT; | ||
288 | } | ||
289 | 256 | ||
290 | /* request DMA for SPORT */ | 257 | /* configure SPORT for TDM */ |
291 | sport_handle = sport_init(&sport_params[sport_num], 4, \ | 258 | sport_handle = sport_init(pdev, 4, 8 * sizeof(u32), |
292 | 8 * sizeof(u32), NULL); | 259 | sizeof(struct bf5xx_tdm_port)); |
293 | if (!sport_handle) { | 260 | if (!sport_handle) |
294 | peripheral_free_list(&sport_req[sport_num][0]); | ||
295 | return -ENODEV; | 261 | return -ENODEV; |
296 | } | ||
297 | 262 | ||
298 | /* SPORT works in TDM mode */ | 263 | /* SPORT works in TDM mode */ |
299 | ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); | 264 | ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); |
@@ -323,18 +288,19 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev) | |||
323 | goto sport_config_err; | 288 | goto sport_config_err; |
324 | } | 289 | } |
325 | 290 | ||
326 | sport_handle->private_data = &bf5xx_tdm; | ||
327 | return 0; | 291 | return 0; |
328 | 292 | ||
329 | sport_config_err: | 293 | sport_config_err: |
330 | peripheral_free_list(&sport_req[sport_num][0]); | 294 | sport_done(sport_handle); |
331 | return ret; | 295 | return ret; |
332 | } | 296 | } |
333 | 297 | ||
334 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) | 298 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) |
335 | { | 299 | { |
336 | peripheral_free_list(&sport_req[sport_num][0]); | 300 | struct sport_device *sport_handle = platform_get_drvdata(pdev); |
301 | |||
337 | snd_soc_unregister_dai(&pdev->dev); | 302 | snd_soc_unregister_dai(&pdev->dev); |
303 | sport_done(sport_handle); | ||
338 | 304 | ||
339 | return 0; | 305 | return 0; |
340 | } | 306 | } |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 06b6981b8d6d..19241576b6b5 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -120,7 +120,7 @@ | |||
120 | */ | 120 | */ |
121 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ | 121 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ |
122 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 122 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ |
123 | .shift = 0, .invert = 0, .kcontrols = NULL, \ | 123 | .shift = 0, .invert = 0, .kcontrol_news = NULL, \ |
124 | .num_kcontrols = 0, .event = wevent, \ | 124 | .num_kcontrols = 0, .event = wevent, \ |
125 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } | 125 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } |
126 | 126 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6943e24a74a1..98175a096df2 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -16,10 +16,11 @@ config SND_SOC_ALL_CODECS | |||
16 | select SND_SOC_AD1836 if SPI_MASTER | 16 | select SND_SOC_AD1836 if SPI_MASTER |
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
19 | select SND_SOC_AD73311 | ||
19 | select SND_SOC_ADS117X | 20 | select SND_SOC_ADS117X |
20 | select SND_SOC_AD73311 if I2C | ||
21 | select SND_SOC_AK4104 if SPI_MASTER | 21 | select SND_SOC_AK4104 if SPI_MASTER |
22 | select SND_SOC_AK4535 if I2C | 22 | select SND_SOC_AK4535 if I2C |
23 | select SND_SOC_AK4641 if I2C | ||
23 | select SND_SOC_AK4642 if I2C | 24 | select SND_SOC_AK4642 if I2C |
24 | select SND_SOC_AK4671 if I2C | 25 | select SND_SOC_AK4671 if I2C |
25 | select SND_SOC_ALC5623 if I2C | 26 | select SND_SOC_ALC5623 if I2C |
@@ -33,13 +34,14 @@ config SND_SOC_ALL_CODECS | |||
33 | select SND_SOC_JZ4740_CODEC if SOC_JZ4740 | 34 | select SND_SOC_JZ4740_CODEC if SOC_JZ4740 |
34 | select SND_SOC_LM4857 if I2C | 35 | select SND_SOC_LM4857 if I2C |
35 | select SND_SOC_MAX98088 if I2C | 36 | select SND_SOC_MAX98088 if I2C |
37 | select SND_SOC_MAX98095 if I2C | ||
36 | select SND_SOC_MAX9850 if I2C | 38 | select SND_SOC_MAX9850 if I2C |
37 | select SND_SOC_MAX9877 if I2C | 39 | select SND_SOC_MAX9877 if I2C |
38 | select SND_SOC_PCM3008 | 40 | select SND_SOC_PCM3008 |
39 | select SND_SOC_SGTL5000 if I2C | 41 | select SND_SOC_SGTL5000 if I2C |
40 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 42 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
41 | select SND_SOC_SPDIF | 43 | select SND_SOC_SPDIF |
42 | select SND_SOC_SSM2602 if I2C | 44 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
43 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 45 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
44 | select SND_SOC_TLV320AIC23 if I2C | 46 | select SND_SOC_TLV320AIC23 if I2C |
45 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 47 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
@@ -52,6 +54,7 @@ config SND_SOC_ALL_CODECS | |||
52 | select SND_SOC_UDA134X | 54 | select SND_SOC_UDA134X |
53 | select SND_SOC_UDA1380 if I2C | 55 | select SND_SOC_UDA1380 if I2C |
54 | select SND_SOC_WL1273 if MFD_WL1273_CORE | 56 | select SND_SOC_WL1273 if MFD_WL1273_CORE |
57 | select SND_SOC_WM1250_EV1 if I2C | ||
55 | select SND_SOC_WM2000 if I2C | 58 | select SND_SOC_WM2000 if I2C |
56 | select SND_SOC_WM8350 if MFD_WM8350 | 59 | select SND_SOC_WM8350 if MFD_WM8350 |
57 | select SND_SOC_WM8400 if MFD_WM8400 | 60 | select SND_SOC_WM8400 if MFD_WM8400 |
@@ -72,6 +75,7 @@ config SND_SOC_ALL_CODECS | |||
72 | select SND_SOC_WM8900 if I2C | 75 | select SND_SOC_WM8900 if I2C |
73 | select SND_SOC_WM8903 if I2C | 76 | select SND_SOC_WM8903 if I2C |
74 | select SND_SOC_WM8904 if I2C | 77 | select SND_SOC_WM8904 if I2C |
78 | select SND_SOC_WM8915 if I2C | ||
75 | select SND_SOC_WM8940 if I2C | 79 | select SND_SOC_WM8940 if I2C |
76 | select SND_SOC_WM8955 if I2C | 80 | select SND_SOC_WM8955 if I2C |
77 | select SND_SOC_WM8960 if I2C | 81 | select SND_SOC_WM8960 if I2C |
@@ -136,6 +140,9 @@ config SND_SOC_AK4104 | |||
136 | config SND_SOC_AK4535 | 140 | config SND_SOC_AK4535 |
137 | tristate | 141 | tristate |
138 | 142 | ||
143 | config SND_SOC_AK4641 | ||
144 | tristate | ||
145 | |||
139 | config SND_SOC_AK4642 | 146 | config SND_SOC_AK4642 |
140 | tristate | 147 | tristate |
141 | 148 | ||
@@ -187,6 +194,9 @@ config SND_SOC_DMIC | |||
187 | config SND_SOC_MAX98088 | 194 | config SND_SOC_MAX98088 |
188 | tristate | 195 | tristate |
189 | 196 | ||
197 | config SND_SOC_MAX98095 | ||
198 | tristate | ||
199 | |||
190 | config SND_SOC_MAX9850 | 200 | config SND_SOC_MAX9850 |
191 | tristate | 201 | tristate |
192 | 202 | ||
@@ -241,6 +251,9 @@ config SND_SOC_UDA1380 | |||
241 | config SND_SOC_WL1273 | 251 | config SND_SOC_WL1273 |
242 | tristate | 252 | tristate |
243 | 253 | ||
254 | config SND_SOC_WM1250_EV1 | ||
255 | tristate | ||
256 | |||
244 | config SND_SOC_WM8350 | 257 | config SND_SOC_WM8350 |
245 | tristate | 258 | tristate |
246 | 259 | ||
@@ -298,6 +311,9 @@ config SND_SOC_WM8903 | |||
298 | config SND_SOC_WM8904 | 311 | config SND_SOC_WM8904 |
299 | tristate | 312 | tristate |
300 | 313 | ||
314 | config SND_SOC_WM8915 | ||
315 | tristate | ||
316 | |||
301 | config SND_SOC_WM8940 | 317 | config SND_SOC_WM8940 |
302 | tristate | 318 | tristate |
303 | 319 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 379bc55f0723..fd8558406ef0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -7,6 +7,7 @@ snd-soc-ad73311-objs := ad73311.o | |||
7 | snd-soc-ads117x-objs := ads117x.o | 7 | snd-soc-ads117x-objs := ads117x.o |
8 | snd-soc-ak4104-objs := ak4104.o | 8 | snd-soc-ak4104-objs := ak4104.o |
9 | snd-soc-ak4535-objs := ak4535.o | 9 | snd-soc-ak4535-objs := ak4535.o |
10 | snd-soc-ak4641-objs := ak4641.o | ||
10 | snd-soc-ak4642-objs := ak4642.o | 11 | snd-soc-ak4642-objs := ak4642.o |
11 | snd-soc-ak4671-objs := ak4671.o | 12 | snd-soc-ak4671-objs := ak4671.o |
12 | snd-soc-cq93vc-objs := cq93vc.o | 13 | snd-soc-cq93vc-objs := cq93vc.o |
@@ -19,6 +20,7 @@ snd-soc-dfbmcs320-objs := dfbmcs320.o | |||
19 | snd-soc-dmic-objs := dmic.o | 20 | snd-soc-dmic-objs := dmic.o |
20 | snd-soc-l3-objs := l3.o | 21 | snd-soc-l3-objs := l3.o |
21 | snd-soc-max98088-objs := max98088.o | 22 | snd-soc-max98088-objs := max98088.o |
23 | snd-soc-max98095-objs := max98095.o | ||
22 | snd-soc-max9850-objs := max9850.o | 24 | snd-soc-max9850-objs := max9850.o |
23 | snd-soc-pcm3008-objs := pcm3008.o | 25 | snd-soc-pcm3008-objs := pcm3008.o |
24 | snd-soc-sgtl5000-objs := sgtl5000.o | 26 | snd-soc-sgtl5000-objs := sgtl5000.o |
@@ -37,6 +39,7 @@ snd-soc-twl6040-objs := twl6040.o | |||
37 | snd-soc-uda134x-objs := uda134x.o | 39 | snd-soc-uda134x-objs := uda134x.o |
38 | snd-soc-uda1380-objs := uda1380.o | 40 | snd-soc-uda1380-objs := uda1380.o |
39 | snd-soc-wl1273-objs := wl1273.o | 41 | snd-soc-wl1273-objs := wl1273.o |
42 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o | ||
40 | snd-soc-wm8350-objs := wm8350.o | 43 | snd-soc-wm8350-objs := wm8350.o |
41 | snd-soc-wm8400-objs := wm8400.o | 44 | snd-soc-wm8400-objs := wm8400.o |
42 | snd-soc-wm8510-objs := wm8510.o | 45 | snd-soc-wm8510-objs := wm8510.o |
@@ -56,6 +59,7 @@ snd-soc-wm8804-objs := wm8804.o | |||
56 | snd-soc-wm8900-objs := wm8900.o | 59 | snd-soc-wm8900-objs := wm8900.o |
57 | snd-soc-wm8903-objs := wm8903.o | 60 | snd-soc-wm8903-objs := wm8903.o |
58 | snd-soc-wm8904-objs := wm8904.o | 61 | snd-soc-wm8904-objs := wm8904.o |
62 | snd-soc-wm8915-objs := wm8915.o | ||
59 | snd-soc-wm8940-objs := wm8940.o | 63 | snd-soc-wm8940-objs := wm8940.o |
60 | snd-soc-wm8955-objs := wm8955.o | 64 | snd-soc-wm8955-objs := wm8955.o |
61 | snd-soc-wm8960-objs := wm8960.o | 65 | snd-soc-wm8960-objs := wm8960.o |
@@ -69,7 +73,7 @@ snd-soc-wm8988-objs := wm8988.o | |||
69 | snd-soc-wm8990-objs := wm8990.o | 73 | snd-soc-wm8990-objs := wm8990.o |
70 | snd-soc-wm8991-objs := wm8991.o | 74 | snd-soc-wm8991-objs := wm8991.o |
71 | snd-soc-wm8993-objs := wm8993.o | 75 | snd-soc-wm8993-objs := wm8993.o |
72 | snd-soc-wm8994-objs := wm8994.o wm8994-tables.o | 76 | snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o |
73 | snd-soc-wm8995-objs := wm8995.o | 77 | snd-soc-wm8995-objs := wm8995.o |
74 | snd-soc-wm9081-objs := wm9081.o | 78 | snd-soc-wm9081-objs := wm9081.o |
75 | snd-soc-wm9705-objs := wm9705.o | 79 | snd-soc-wm9705-objs := wm9705.o |
@@ -94,6 +98,7 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | |||
94 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 98 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
95 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 99 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
96 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 100 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
101 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o | ||
97 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 102 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
98 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 103 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
99 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | 104 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
@@ -108,6 +113,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | |||
108 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 113 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
109 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 114 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
110 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 115 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
116 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | ||
111 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 117 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
112 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 118 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
113 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 119 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
@@ -125,6 +131,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | |||
125 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 131 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
126 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 132 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
127 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o | 133 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o |
134 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o | ||
128 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o | 135 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o |
129 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o | 136 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o |
130 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o | 137 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
@@ -144,6 +151,7 @@ obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o | |||
144 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o | 151 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o |
145 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o | 152 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o |
146 | obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o | 153 | obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o |
154 | obj-$(CONFIG_SND_SOC_WM8915) += snd-soc-wm8915.o | ||
147 | obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o | 155 | obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o |
148 | obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o | 156 | obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o |
149 | obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o | 157 | obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index da46479bfcfa..2374ca5ffe68 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -23,8 +23,7 @@ | |||
23 | 23 | ||
24 | /* codec private data */ | 24 | /* codec private data */ |
25 | struct ad193x_priv { | 25 | struct ad193x_priv { |
26 | enum snd_soc_control_type bus_type; | 26 | enum snd_soc_control_type control_type; |
27 | void *control_data; | ||
28 | int sysclk; | 27 | int sysclk; |
29 | }; | 28 | }; |
30 | 29 | ||
@@ -354,14 +353,12 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
354 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 353 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
355 | int ret; | 354 | int ret; |
356 | 355 | ||
357 | codec->control_data = ad193x->control_data; | 356 | if (ad193x->control_type == SND_SOC_I2C) |
358 | if (ad193x->bus_type == SND_SOC_I2C) | 357 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type); |
359 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type); | ||
360 | else | 358 | else |
361 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type); | 359 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type); |
362 | if (ret < 0) { | 360 | if (ret < 0) { |
363 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | 361 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); |
364 | ret); | ||
365 | return ret; | 362 | return ret; |
366 | } | 363 | } |
367 | 364 | ||
@@ -408,8 +405,7 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi) | |||
408 | return -ENOMEM; | 405 | return -ENOMEM; |
409 | 406 | ||
410 | spi_set_drvdata(spi, ad193x); | 407 | spi_set_drvdata(spi, ad193x); |
411 | ad193x->control_data = spi; | 408 | ad193x->control_type = SND_SOC_SPI; |
412 | ad193x->bus_type = SND_SOC_SPI; | ||
413 | 409 | ||
414 | ret = snd_soc_register_codec(&spi->dev, | 410 | ret = snd_soc_register_codec(&spi->dev, |
415 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 411 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
@@ -427,7 +423,7 @@ static int __devexit ad193x_spi_remove(struct spi_device *spi) | |||
427 | 423 | ||
428 | static struct spi_driver ad193x_spi_driver = { | 424 | static struct spi_driver ad193x_spi_driver = { |
429 | .driver = { | 425 | .driver = { |
430 | .name = "ad193x-codec", | 426 | .name = "ad193x", |
431 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
432 | }, | 428 | }, |
433 | .probe = ad193x_spi_probe, | 429 | .probe = ad193x_spi_probe, |
@@ -454,8 +450,7 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
454 | return -ENOMEM; | 450 | return -ENOMEM; |
455 | 451 | ||
456 | i2c_set_clientdata(client, ad193x); | 452 | i2c_set_clientdata(client, ad193x); |
457 | ad193x->control_data = client; | 453 | ad193x->control_type = SND_SOC_I2C; |
458 | ad193x->bus_type = SND_SOC_I2C; | ||
459 | 454 | ||
460 | ret = snd_soc_register_codec(&client->dev, | 455 | ret = snd_soc_register_codec(&client->dev, |
461 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 456 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
@@ -473,7 +468,7 @@ static int __devexit ad193x_i2c_remove(struct i2c_client *client) | |||
473 | 468 | ||
474 | static struct i2c_driver ad193x_i2c_driver = { | 469 | static struct i2c_driver ad193x_i2c_driver = { |
475 | .driver = { | 470 | .driver = { |
476 | .name = "ad193x-codec", | 471 | .name = "ad193x", |
477 | }, | 472 | }, |
478 | .probe = ad193x_i2c_probe, | 473 | .probe = ad193x_i2c_probe, |
479 | .remove = __devexit_p(ad193x_i2c_remove), | 474 | .remove = __devexit_p(ad193x_i2c_remove), |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 34cb51ef2156..923b364a3e41 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -266,7 +266,7 @@ static int __devexit ad1980_remove(struct platform_device *pdev) | |||
266 | 266 | ||
267 | static struct platform_driver ad1980_codec_driver = { | 267 | static struct platform_driver ad1980_codec_driver = { |
268 | .driver = { | 268 | .driver = { |
269 | .name = "ad1980-codec", | 269 | .name = "ad1980", |
270 | .owner = THIS_MODULE, | 270 | .owner = THIS_MODULE, |
271 | }, | 271 | }, |
272 | 272 | ||
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index de799cd1ba72..8d793e993e9a 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -55,7 +55,7 @@ static int __devexit ad73311_remove(struct platform_device *pdev) | |||
55 | 55 | ||
56 | static struct platform_driver ad73311_codec_driver = { | 56 | static struct platform_driver ad73311_codec_driver = { |
57 | .driver = { | 57 | .driver = { |
58 | .name = "ad73311-codec", | 58 | .name = "ad73311", |
59 | .owner = THIS_MODULE, | 59 | .owner = THIS_MODULE, |
60 | }, | 60 | }, |
61 | 61 | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 8b38739c88f8..e1a214ee757f 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -230,7 +230,7 @@ static const struct snd_soc_dapm_widget ak4535_dapm_widgets[] = { | |||
230 | SND_SOC_DAPM_INPUT("AIN"), | 230 | SND_SOC_DAPM_INPUT("AIN"), |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static const struct snd_soc_dapm_route audio_map[] = { | 233 | static const struct snd_soc_dapm_route ak4535_audio_map[] = { |
234 | /*stereo mixer */ | 234 | /*stereo mixer */ |
235 | {"Stereo Mixer", "Playback Switch", "DAC"}, | 235 | {"Stereo Mixer", "Playback Switch", "DAC"}, |
236 | {"Stereo Mixer", "Mic Sidetone Switch", "Mic"}, | 236 | {"Stereo Mixer", "Mic Sidetone Switch", "Mic"}, |
@@ -287,17 +287,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
287 | {"Input Mixer", "Aux Capture Switch", "Aux In"}, | 287 | {"Input Mixer", "Aux Capture Switch", "Aux In"}, |
288 | }; | 288 | }; |
289 | 289 | ||
290 | static int ak4535_add_widgets(struct snd_soc_codec *codec) | ||
291 | { | ||
292 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
293 | |||
294 | snd_soc_dapm_new_controls(dapm, ak4535_dapm_widgets, | ||
295 | ARRAY_SIZE(ak4535_dapm_widgets)); | ||
296 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 290 | static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
302 | int clk_id, unsigned int freq, int dir) | 291 | int clk_id, unsigned int freq, int dir) |
303 | { | 292 | { |
@@ -457,8 +446,6 @@ static int ak4535_probe(struct snd_soc_codec *codec) | |||
457 | 446 | ||
458 | snd_soc_add_controls(codec, ak4535_snd_controls, | 447 | snd_soc_add_controls(codec, ak4535_snd_controls, |
459 | ARRAY_SIZE(ak4535_snd_controls)); | 448 | ARRAY_SIZE(ak4535_snd_controls)); |
460 | ak4535_add_widgets(codec); | ||
461 | |||
462 | return 0; | 449 | return 0; |
463 | } | 450 | } |
464 | 451 | ||
@@ -480,6 +467,10 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { | |||
480 | .reg_cache_size = ARRAY_SIZE(ak4535_reg), | 467 | .reg_cache_size = ARRAY_SIZE(ak4535_reg), |
481 | .reg_word_size = sizeof(u8), | 468 | .reg_word_size = sizeof(u8), |
482 | .reg_cache_default = ak4535_reg, | 469 | .reg_cache_default = ak4535_reg, |
470 | .dapm_widgets = ak4535_dapm_widgets, | ||
471 | .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), | ||
472 | .dapm_routes = ak4535_audio_map, | ||
473 | .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), | ||
483 | }; | 474 | }; |
484 | 475 | ||
485 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 476 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c new file mode 100644 index 000000000000..ed96f247c2da --- /dev/null +++ b/sound/soc/codecs/ak4641.c | |||
@@ -0,0 +1,664 @@ | |||
1 | /* | ||
2 | * ak4641.c -- AK4641 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Harald Welte <laforge@gnufiish.org> | ||
5 | * Copyright (C) 2011 Dmitry Artamonow <mad_soft@inbox.ru> | ||
6 | * | ||
7 | * Based on ak4535.c by Richard Purdie | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/ak4641.h> | ||
29 | |||
30 | #include "ak4641.h" | ||
31 | |||
32 | /* codec private data */ | ||
33 | struct ak4641_priv { | ||
34 | struct snd_soc_codec *codec; | ||
35 | unsigned int sysclk; | ||
36 | int deemph; | ||
37 | int playback_fs; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * ak4641 register cache | ||
42 | */ | ||
43 | static const u8 ak4641_reg[AK4641_CACHEREGNUM] = { | ||
44 | 0x00, 0x80, 0x00, 0x80, | ||
45 | 0x02, 0x00, 0x11, 0x05, | ||
46 | 0x00, 0x00, 0x36, 0x10, | ||
47 | 0x00, 0x00, 0x57, 0x00, | ||
48 | 0x88, 0x88, 0x08, 0x08 | ||
49 | }; | ||
50 | |||
51 | static const int deemph_settings[] = {44100, 0, 48000, 32000}; | ||
52 | |||
53 | static int ak4641_set_deemph(struct snd_soc_codec *codec) | ||
54 | { | ||
55 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
56 | int i, best = 0; | ||
57 | |||
58 | for (i = 0 ; i < ARRAY_SIZE(deemph_settings); i++) { | ||
59 | /* if deemphasis is on, select the nearest available rate */ | ||
60 | if (ak4641->deemph && deemph_settings[i] != 0 && | ||
61 | abs(deemph_settings[i] - ak4641->playback_fs) < | ||
62 | abs(deemph_settings[best] - ak4641->playback_fs)) | ||
63 | best = i; | ||
64 | |||
65 | if (!ak4641->deemph && deemph_settings[i] == 0) | ||
66 | best = i; | ||
67 | } | ||
68 | |||
69 | dev_dbg(codec->dev, "Set deemphasis %d\n", best); | ||
70 | |||
71 | return snd_soc_update_bits(codec, AK4641_DAC, 0x3, best); | ||
72 | } | ||
73 | |||
74 | static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, | ||
75 | struct snd_ctl_elem_value *ucontrol) | ||
76 | { | ||
77 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
78 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
79 | int deemph = ucontrol->value.enumerated.item[0]; | ||
80 | |||
81 | if (deemph > 1) | ||
82 | return -EINVAL; | ||
83 | |||
84 | ak4641->deemph = deemph; | ||
85 | |||
86 | return ak4641_set_deemph(codec); | ||
87 | } | ||
88 | |||
89 | static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, | ||
90 | struct snd_ctl_elem_value *ucontrol) | ||
91 | { | ||
92 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
93 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
94 | |||
95 | ucontrol->value.enumerated.item[0] = ak4641->deemph; | ||
96 | return 0; | ||
97 | }; | ||
98 | |||
99 | static const char *ak4641_mono_out[] = {"(L + R)/2", "Hi-Z"}; | ||
100 | static const char *ak4641_hp_out[] = {"Stereo", "Mono"}; | ||
101 | static const char *ak4641_mic_select[] = {"Internal", "External"}; | ||
102 | static const char *ak4641_mic_or_dac[] = {"Microphone", "Voice DAC"}; | ||
103 | |||
104 | |||
105 | static const DECLARE_TLV_DB_SCALE(mono_gain_tlv, -1700, 2300, 0); | ||
106 | static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 2000, 0); | ||
107 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1050, 150, 0); | ||
108 | static const DECLARE_TLV_DB_SCALE(master_tlv, -12750, 50, 0); | ||
109 | static const DECLARE_TLV_DB_SCALE(mic_stereo_sidetone_tlv, -2700, 300, 0); | ||
110 | static const DECLARE_TLV_DB_SCALE(mic_mono_sidetone_tlv, -400, 400, 0); | ||
111 | static const DECLARE_TLV_DB_SCALE(capture_tlv, -800, 50, 0); | ||
112 | static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); | ||
113 | static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); | ||
114 | |||
115 | |||
116 | static const struct soc_enum ak4641_mono_out_enum = | ||
117 | SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); | ||
118 | static const struct soc_enum ak4641_hp_out_enum = | ||
119 | SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); | ||
120 | static const struct soc_enum ak4641_mic_select_enum = | ||
121 | SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); | ||
122 | static const struct soc_enum ak4641_mic_or_dac_enum = | ||
123 | SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); | ||
124 | |||
125 | static const struct snd_kcontrol_new ak4641_snd_controls[] = { | ||
126 | SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), | ||
127 | SOC_SINGLE_TLV("Mono 1 Gain Volume", AK4641_SIG1, 7, 1, 1, | ||
128 | mono_gain_tlv), | ||
129 | SOC_ENUM("Headphone Output", ak4641_hp_out_enum), | ||
130 | SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, | ||
131 | ak4641_get_deemph, ak4641_put_deemph), | ||
132 | |||
133 | SOC_SINGLE_TLV("Mic Boost Volume", AK4641_MIC, 0, 1, 0, mic_boost_tlv), | ||
134 | |||
135 | SOC_SINGLE("ALC Operation Time", AK4641_TIMER, 0, 3, 0), | ||
136 | SOC_SINGLE("ALC Recovery Time", AK4641_TIMER, 2, 3, 0), | ||
137 | SOC_SINGLE("ALC ZC Time", AK4641_TIMER, 4, 3, 0), | ||
138 | |||
139 | SOC_SINGLE("ALC 1 Switch", AK4641_ALC1, 5, 1, 0), | ||
140 | |||
141 | SOC_SINGLE_TLV("ALC Volume", AK4641_ALC2, 0, 71, 0, alc_tlv), | ||
142 | SOC_SINGLE("Left Out Enable Switch", AK4641_SIG2, 1, 1, 0), | ||
143 | SOC_SINGLE("Right Out Enable Switch", AK4641_SIG2, 0, 1, 0), | ||
144 | |||
145 | SOC_SINGLE_TLV("Capture Volume", AK4641_PGA, 0, 71, 0, capture_tlv), | ||
146 | |||
147 | SOC_DOUBLE_R_TLV("Master Playback Volume", AK4641_LATT, | ||
148 | AK4641_RATT, 0, 255, 1, master_tlv), | ||
149 | |||
150 | SOC_SINGLE_TLV("AUX In Volume", AK4641_VOL, 0, 15, 0, aux_in_tlv), | ||
151 | |||
152 | SOC_SINGLE("Equalizer Switch", AK4641_DAC, 2, 1, 0), | ||
153 | SOC_SINGLE_TLV("EQ1 100 Hz Volume", AK4641_EQLO, 0, 15, 1, eq_tlv), | ||
154 | SOC_SINGLE_TLV("EQ2 250 Hz Volume", AK4641_EQLO, 4, 15, 1, eq_tlv), | ||
155 | SOC_SINGLE_TLV("EQ3 1 kHz Volume", AK4641_EQMID, 0, 15, 1, eq_tlv), | ||
156 | SOC_SINGLE_TLV("EQ4 3.5 kHz Volume", AK4641_EQMID, 4, 15, 1, eq_tlv), | ||
157 | SOC_SINGLE_TLV("EQ5 10 kHz Volume", AK4641_EQHI, 0, 15, 1, eq_tlv), | ||
158 | }; | ||
159 | |||
160 | /* Mono 1 Mixer */ | ||
161 | static const struct snd_kcontrol_new ak4641_mono1_mixer_controls[] = { | ||
162 | SOC_DAPM_SINGLE_TLV("Mic Mono Sidetone Volume", AK4641_VOL, 7, 1, 0, | ||
163 | mic_mono_sidetone_tlv), | ||
164 | SOC_DAPM_SINGLE("Mic Mono Sidetone Switch", AK4641_SIG1, 4, 1, 0), | ||
165 | SOC_DAPM_SINGLE("Mono Playback Switch", AK4641_SIG1, 5, 1, 0), | ||
166 | }; | ||
167 | |||
168 | /* Stereo Mixer */ | ||
169 | static const struct snd_kcontrol_new ak4641_stereo_mixer_controls[] = { | ||
170 | SOC_DAPM_SINGLE_TLV("Mic Sidetone Volume", AK4641_VOL, 4, 7, 0, | ||
171 | mic_stereo_sidetone_tlv), | ||
172 | SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4641_SIG2, 4, 1, 0), | ||
173 | SOC_DAPM_SINGLE("Playback Switch", AK4641_SIG2, 7, 1, 0), | ||
174 | SOC_DAPM_SINGLE("Aux Bypass Switch", AK4641_SIG2, 5, 1, 0), | ||
175 | }; | ||
176 | |||
177 | /* Input Mixer */ | ||
178 | static const struct snd_kcontrol_new ak4641_input_mixer_controls[] = { | ||
179 | SOC_DAPM_SINGLE("Mic Capture Switch", AK4641_MIC, 2, 1, 0), | ||
180 | SOC_DAPM_SINGLE("Aux Capture Switch", AK4641_MIC, 5, 1, 0), | ||
181 | }; | ||
182 | |||
183 | /* Mic mux */ | ||
184 | static const struct snd_kcontrol_new ak4641_mic_mux_control = | ||
185 | SOC_DAPM_ENUM("Mic Select", ak4641_mic_select_enum); | ||
186 | |||
187 | /* Input mux */ | ||
188 | static const struct snd_kcontrol_new ak4641_input_mux_control = | ||
189 | SOC_DAPM_ENUM("Input Select", ak4641_mic_or_dac_enum); | ||
190 | |||
191 | /* mono 2 switch */ | ||
192 | static const struct snd_kcontrol_new ak4641_mono2_control = | ||
193 | SOC_DAPM_SINGLE("Switch", AK4641_SIG1, 0, 1, 0); | ||
194 | |||
195 | /* ak4641 dapm widgets */ | ||
196 | static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = { | ||
197 | SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0, | ||
198 | &ak4641_stereo_mixer_controls[0], | ||
199 | ARRAY_SIZE(ak4641_stereo_mixer_controls)), | ||
200 | SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0, | ||
201 | &ak4641_mono1_mixer_controls[0], | ||
202 | ARRAY_SIZE(ak4641_mono1_mixer_controls)), | ||
203 | SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, | ||
204 | &ak4641_input_mixer_controls[0], | ||
205 | ARRAY_SIZE(ak4641_input_mixer_controls)), | ||
206 | SND_SOC_DAPM_MUX("Mic Mux", SND_SOC_NOPM, 0, 0, | ||
207 | &ak4641_mic_mux_control), | ||
208 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, | ||
209 | &ak4641_input_mux_control), | ||
210 | SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0, | ||
211 | &ak4641_mono2_control), | ||
212 | |||
213 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
214 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
215 | SND_SOC_DAPM_OUTPUT("MOUT1"), | ||
216 | SND_SOC_DAPM_OUTPUT("MOUT2"), | ||
217 | SND_SOC_DAPM_OUTPUT("MICOUT"), | ||
218 | |||
219 | SND_SOC_DAPM_ADC("ADC", "HiFi Capture", AK4641_PM1, 0, 0), | ||
220 | SND_SOC_DAPM_PGA("Mic", AK4641_PM1, 1, 0, NULL, 0), | ||
221 | SND_SOC_DAPM_PGA("AUX In", AK4641_PM1, 2, 0, NULL, 0), | ||
222 | SND_SOC_DAPM_PGA("Mono Out", AK4641_PM1, 3, 0, NULL, 0), | ||
223 | SND_SOC_DAPM_PGA("Line Out", AK4641_PM1, 4, 0, NULL, 0), | ||
224 | |||
225 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", AK4641_PM2, 0, 0), | ||
226 | SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0), | ||
227 | |||
228 | SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0), | ||
229 | SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0), | ||
230 | |||
231 | SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0), | ||
232 | SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0), | ||
233 | |||
234 | SND_SOC_DAPM_INPUT("MICIN"), | ||
235 | SND_SOC_DAPM_INPUT("MICEXT"), | ||
236 | SND_SOC_DAPM_INPUT("AUX"), | ||
237 | SND_SOC_DAPM_INPUT("AIN"), | ||
238 | }; | ||
239 | |||
240 | static const struct snd_soc_dapm_route ak4641_audio_map[] = { | ||
241 | /* Stereo Mixer */ | ||
242 | {"Stereo Mixer", "Playback Switch", "DAC"}, | ||
243 | {"Stereo Mixer", "Mic Sidetone Switch", "Input Mux"}, | ||
244 | {"Stereo Mixer", "Aux Bypass Switch", "AUX In"}, | ||
245 | |||
246 | /* Mono 1 Mixer */ | ||
247 | {"Mono1 Mixer", "Mic Mono Sidetone Switch", "Input Mux"}, | ||
248 | {"Mono1 Mixer", "Mono Playback Switch", "DAC"}, | ||
249 | |||
250 | /* Mic */ | ||
251 | {"Mic", NULL, "AIN"}, | ||
252 | {"Mic Mux", "Internal", "Mic Int Bias"}, | ||
253 | {"Mic Mux", "External", "Mic Ext Bias"}, | ||
254 | {"Mic Int Bias", NULL, "MICIN"}, | ||
255 | {"Mic Ext Bias", NULL, "MICEXT"}, | ||
256 | {"MICOUT", NULL, "Mic Mux"}, | ||
257 | |||
258 | /* Input Mux */ | ||
259 | {"Input Mux", "Microphone", "Mic"}, | ||
260 | {"Input Mux", "Voice DAC", "Voice DAC"}, | ||
261 | |||
262 | /* Line Out */ | ||
263 | {"LOUT", NULL, "Line Out"}, | ||
264 | {"ROUT", NULL, "Line Out"}, | ||
265 | {"Line Out", NULL, "Stereo Mixer"}, | ||
266 | |||
267 | /* Mono 1 Out */ | ||
268 | {"MOUT1", NULL, "Mono Out"}, | ||
269 | {"Mono Out", NULL, "Mono1 Mixer"}, | ||
270 | |||
271 | /* Mono 2 Out */ | ||
272 | {"MOUT2", NULL, "Mono 2 Enable"}, | ||
273 | {"Mono 2 Enable", "Switch", "Mono Out 2"}, | ||
274 | {"Mono Out 2", NULL, "Stereo Mixer"}, | ||
275 | |||
276 | {"Voice ADC", NULL, "Mono 2 Enable"}, | ||
277 | |||
278 | /* Aux In */ | ||
279 | {"AUX In", NULL, "AUX"}, | ||
280 | |||
281 | /* ADC */ | ||
282 | {"ADC", NULL, "Input Mixer"}, | ||
283 | {"Input Mixer", "Mic Capture Switch", "Mic"}, | ||
284 | {"Input Mixer", "Aux Capture Switch", "AUX In"}, | ||
285 | }; | ||
286 | |||
287 | static int ak4641_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
288 | int clk_id, unsigned int freq, int dir) | ||
289 | { | ||
290 | struct snd_soc_codec *codec = codec_dai->codec; | ||
291 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
292 | |||
293 | ak4641->sysclk = freq; | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, | ||
298 | struct snd_pcm_hw_params *params, | ||
299 | struct snd_soc_dai *dai) | ||
300 | { | ||
301 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
302 | struct snd_soc_codec *codec = rtd->codec; | ||
303 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
304 | int rate = params_rate(params), fs = 256; | ||
305 | u8 mode2; | ||
306 | |||
307 | if (rate) | ||
308 | fs = ak4641->sysclk / rate; | ||
309 | else | ||
310 | return -EINVAL; | ||
311 | |||
312 | /* set fs */ | ||
313 | switch (fs) { | ||
314 | case 1024: | ||
315 | mode2 = (0x2 << 5); | ||
316 | break; | ||
317 | case 512: | ||
318 | mode2 = (0x1 << 5); | ||
319 | break; | ||
320 | case 256: | ||
321 | mode2 = (0x0 << 5); | ||
322 | break; | ||
323 | default: | ||
324 | dev_err(codec->dev, "Error: unsupported fs=%d\n", fs); | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | |||
328 | snd_soc_update_bits(codec, AK4641_MODE2, (0x3 << 5), mode2); | ||
329 | |||
330 | /* Update de-emphasis filter for the new rate */ | ||
331 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
332 | ak4641->playback_fs = rate; | ||
333 | ak4641_set_deemph(codec); | ||
334 | }; | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
340 | unsigned int fmt) | ||
341 | { | ||
342 | struct snd_soc_codec *codec = codec_dai->codec; | ||
343 | u8 btif; | ||
344 | |||
345 | /* interface format */ | ||
346 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
347 | case SND_SOC_DAIFMT_I2S: | ||
348 | btif = (0x3 << 5); | ||
349 | break; | ||
350 | case SND_SOC_DAIFMT_LEFT_J: | ||
351 | btif = (0x2 << 5); | ||
352 | break; | ||
353 | case SND_SOC_DAIFMT_DSP_A: /* MSB after FRM */ | ||
354 | btif = (0x0 << 5); | ||
355 | break; | ||
356 | case SND_SOC_DAIFMT_DSP_B: /* MSB during FRM */ | ||
357 | btif = (0x1 << 5); | ||
358 | break; | ||
359 | default: | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | |||
363 | return snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif); | ||
364 | } | ||
365 | |||
366 | static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
367 | unsigned int fmt) | ||
368 | { | ||
369 | struct snd_soc_codec *codec = codec_dai->codec; | ||
370 | u8 mode1 = 0; | ||
371 | |||
372 | /* interface format */ | ||
373 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
374 | case SND_SOC_DAIFMT_I2S: | ||
375 | mode1 = 0x02; | ||
376 | break; | ||
377 | case SND_SOC_DAIFMT_LEFT_J: | ||
378 | mode1 = 0x01; | ||
379 | break; | ||
380 | default: | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | return snd_soc_write(codec, AK4641_MODE1, mode1); | ||
385 | } | ||
386 | |||
387 | static int ak4641_mute(struct snd_soc_dai *dai, int mute) | ||
388 | { | ||
389 | struct snd_soc_codec *codec = dai->codec; | ||
390 | |||
391 | return snd_soc_update_bits(codec, AK4641_DAC, 0x20, mute ? 0x20 : 0); | ||
392 | } | ||
393 | |||
394 | static int ak4641_set_bias_level(struct snd_soc_codec *codec, | ||
395 | enum snd_soc_bias_level level) | ||
396 | { | ||
397 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
398 | int ret; | ||
399 | |||
400 | switch (level) { | ||
401 | case SND_SOC_BIAS_ON: | ||
402 | /* unmute */ | ||
403 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0); | ||
404 | break; | ||
405 | case SND_SOC_BIAS_PREPARE: | ||
406 | /* mute */ | ||
407 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); | ||
408 | break; | ||
409 | case SND_SOC_BIAS_STANDBY: | ||
410 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
411 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
412 | gpio_set_value(pdata->gpio_power, 1); | ||
413 | mdelay(1); | ||
414 | if (pdata && gpio_is_valid(pdata->gpio_npdn)) | ||
415 | gpio_set_value(pdata->gpio_npdn, 1); | ||
416 | mdelay(1); | ||
417 | |||
418 | ret = snd_soc_cache_sync(codec); | ||
419 | if (ret) { | ||
420 | dev_err(codec->dev, | ||
421 | "Failed to sync cache: %d\n", ret); | ||
422 | return ret; | ||
423 | } | ||
424 | } | ||
425 | snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0x80); | ||
426 | snd_soc_update_bits(codec, AK4641_PM2, 0x80, 0); | ||
427 | break; | ||
428 | case SND_SOC_BIAS_OFF: | ||
429 | snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0); | ||
430 | if (pdata && gpio_is_valid(pdata->gpio_npdn)) | ||
431 | gpio_set_value(pdata->gpio_npdn, 0); | ||
432 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
433 | gpio_set_value(pdata->gpio_power, 0); | ||
434 | codec->cache_sync = 1; | ||
435 | break; | ||
436 | } | ||
437 | codec->dapm.bias_level = level; | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | #define AK4641_RATES (SNDRV_PCM_RATE_8000_48000) | ||
442 | #define AK4641_RATES_BT (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
443 | SNDRV_PCM_RATE_16000) | ||
444 | #define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | ||
445 | |||
446 | static struct snd_soc_dai_ops ak4641_i2s_dai_ops = { | ||
447 | .hw_params = ak4641_i2s_hw_params, | ||
448 | .set_fmt = ak4641_i2s_set_dai_fmt, | ||
449 | .digital_mute = ak4641_mute, | ||
450 | .set_sysclk = ak4641_set_dai_sysclk, | ||
451 | }; | ||
452 | |||
453 | static struct snd_soc_dai_ops ak4641_pcm_dai_ops = { | ||
454 | .hw_params = NULL, /* rates are controlled by BT chip */ | ||
455 | .set_fmt = ak4641_pcm_set_dai_fmt, | ||
456 | .digital_mute = ak4641_mute, | ||
457 | .set_sysclk = ak4641_set_dai_sysclk, | ||
458 | }; | ||
459 | |||
460 | struct snd_soc_dai_driver ak4641_dai[] = { | ||
461 | { | ||
462 | .name = "ak4641-hifi", | ||
463 | .id = 1, | ||
464 | .playback = { | ||
465 | .stream_name = "HiFi Playback", | ||
466 | .channels_min = 1, | ||
467 | .channels_max = 2, | ||
468 | .rates = AK4641_RATES, | ||
469 | .formats = AK4641_FORMATS, | ||
470 | }, | ||
471 | .capture = { | ||
472 | .stream_name = "HiFi Capture", | ||
473 | .channels_min = 1, | ||
474 | .channels_max = 2, | ||
475 | .rates = AK4641_RATES, | ||
476 | .formats = AK4641_FORMATS, | ||
477 | }, | ||
478 | .ops = &ak4641_i2s_dai_ops, | ||
479 | .symmetric_rates = 1, | ||
480 | }, | ||
481 | { | ||
482 | .name = "ak4641-voice", | ||
483 | .id = 1, | ||
484 | .playback = { | ||
485 | .stream_name = "Voice Playback", | ||
486 | .channels_min = 1, | ||
487 | .channels_max = 1, | ||
488 | .rates = AK4641_RATES_BT, | ||
489 | .formats = AK4641_FORMATS, | ||
490 | }, | ||
491 | .capture = { | ||
492 | .stream_name = "Voice Capture", | ||
493 | .channels_min = 1, | ||
494 | .channels_max = 1, | ||
495 | .rates = AK4641_RATES_BT, | ||
496 | .formats = AK4641_FORMATS, | ||
497 | }, | ||
498 | .ops = &ak4641_pcm_dai_ops, | ||
499 | .symmetric_rates = 1, | ||
500 | }, | ||
501 | }; | ||
502 | |||
503 | static int ak4641_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
504 | { | ||
505 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int ak4641_resume(struct snd_soc_codec *codec) | ||
510 | { | ||
511 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static int ak4641_probe(struct snd_soc_codec *codec) | ||
516 | { | ||
517 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
518 | int ret; | ||
519 | |||
520 | |||
521 | if (pdata) { | ||
522 | if (gpio_is_valid(pdata->gpio_power)) { | ||
523 | ret = gpio_request_one(pdata->gpio_power, | ||
524 | GPIOF_OUT_INIT_LOW, "ak4641 power"); | ||
525 | if (ret) | ||
526 | goto err_out; | ||
527 | } | ||
528 | if (gpio_is_valid(pdata->gpio_npdn)) { | ||
529 | ret = gpio_request_one(pdata->gpio_npdn, | ||
530 | GPIOF_OUT_INIT_LOW, "ak4641 npdn"); | ||
531 | if (ret) | ||
532 | goto err_gpio; | ||
533 | |||
534 | udelay(1); /* > 150 ns */ | ||
535 | gpio_set_value(pdata->gpio_npdn, 1); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
540 | if (ret != 0) { | ||
541 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
542 | goto err_register; | ||
543 | } | ||
544 | |||
545 | /* power on device */ | ||
546 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
547 | |||
548 | return 0; | ||
549 | |||
550 | err_register: | ||
551 | if (pdata) { | ||
552 | if (gpio_is_valid(pdata->gpio_power)) | ||
553 | gpio_set_value(pdata->gpio_power, 0); | ||
554 | if (gpio_is_valid(pdata->gpio_npdn)) | ||
555 | gpio_free(pdata->gpio_npdn); | ||
556 | } | ||
557 | err_gpio: | ||
558 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
559 | gpio_free(pdata->gpio_power); | ||
560 | err_out: | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int ak4641_remove(struct snd_soc_codec *codec) | ||
565 | { | ||
566 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
567 | |||
568 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
569 | |||
570 | if (pdata) { | ||
571 | if (gpio_is_valid(pdata->gpio_power)) { | ||
572 | gpio_set_value(pdata->gpio_power, 0); | ||
573 | gpio_free(pdata->gpio_power); | ||
574 | } | ||
575 | if (gpio_is_valid(pdata->gpio_npdn)) | ||
576 | gpio_free(pdata->gpio_npdn); | ||
577 | } | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | |||
582 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | ||
583 | .probe = ak4641_probe, | ||
584 | .remove = ak4641_remove, | ||
585 | .suspend = ak4641_suspend, | ||
586 | .resume = ak4641_resume, | ||
587 | .controls = ak4641_snd_controls, | ||
588 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), | ||
589 | .dapm_widgets = ak4641_dapm_widgets, | ||
590 | .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), | ||
591 | .dapm_routes = ak4641_audio_map, | ||
592 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), | ||
593 | .set_bias_level = ak4641_set_bias_level, | ||
594 | .reg_cache_size = ARRAY_SIZE(ak4641_reg), | ||
595 | .reg_word_size = sizeof(u8), | ||
596 | .reg_cache_default = ak4641_reg, | ||
597 | .reg_cache_step = 1, | ||
598 | }; | ||
599 | |||
600 | |||
601 | static int __devinit ak4641_i2c_probe(struct i2c_client *i2c, | ||
602 | const struct i2c_device_id *id) | ||
603 | { | ||
604 | struct ak4641_priv *ak4641; | ||
605 | int ret; | ||
606 | |||
607 | ak4641 = kzalloc(sizeof(struct ak4641_priv), GFP_KERNEL); | ||
608 | if (!ak4641) | ||
609 | return -ENOMEM; | ||
610 | |||
611 | i2c_set_clientdata(i2c, ak4641); | ||
612 | |||
613 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641, | ||
614 | ak4641_dai, ARRAY_SIZE(ak4641_dai)); | ||
615 | if (ret < 0) | ||
616 | kfree(ak4641); | ||
617 | |||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static int __devexit ak4641_i2c_remove(struct i2c_client *i2c) | ||
622 | { | ||
623 | snd_soc_unregister_codec(&i2c->dev); | ||
624 | kfree(i2c_get_clientdata(i2c)); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static const struct i2c_device_id ak4641_i2c_id[] = { | ||
629 | { "ak4641", 0 }, | ||
630 | { } | ||
631 | }; | ||
632 | MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); | ||
633 | |||
634 | static struct i2c_driver ak4641_i2c_driver = { | ||
635 | .driver = { | ||
636 | .name = "ak4641", | ||
637 | .owner = THIS_MODULE, | ||
638 | }, | ||
639 | .probe = ak4641_i2c_probe, | ||
640 | .remove = __devexit_p(ak4641_i2c_remove), | ||
641 | .id_table = ak4641_i2c_id, | ||
642 | }; | ||
643 | |||
644 | static int __init ak4641_modinit(void) | ||
645 | { | ||
646 | int ret; | ||
647 | |||
648 | ret = i2c_add_driver(&ak4641_i2c_driver); | ||
649 | if (ret != 0) | ||
650 | pr_err("Failed to register AK4641 I2C driver: %d\n", ret); | ||
651 | |||
652 | return ret; | ||
653 | } | ||
654 | module_init(ak4641_modinit); | ||
655 | |||
656 | static void __exit ak4641_exit(void) | ||
657 | { | ||
658 | i2c_del_driver(&ak4641_i2c_driver); | ||
659 | } | ||
660 | module_exit(ak4641_exit); | ||
661 | |||
662 | MODULE_DESCRIPTION("SoC AK4641 driver"); | ||
663 | MODULE_AUTHOR("Harald Welte <laforge@gnufiish.org>"); | ||
664 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ak4641.h b/sound/soc/codecs/ak4641.h new file mode 100644 index 000000000000..4a263248efea --- /dev/null +++ b/sound/soc/codecs/ak4641.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * ak4641.h -- AK4641 SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2008 Harald Welte <laforge@gnufiish.org> | ||
5 | * | ||
6 | * Based on ak4535.h | ||
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 | #ifndef _AK4641_H | ||
14 | #define _AK4641_H | ||
15 | |||
16 | /* AK4641 register space */ | ||
17 | |||
18 | #define AK4641_PM1 0x00 | ||
19 | #define AK4641_PM2 0x01 | ||
20 | #define AK4641_SIG1 0x02 | ||
21 | #define AK4641_SIG2 0x03 | ||
22 | #define AK4641_MODE1 0x04 | ||
23 | #define AK4641_MODE2 0x05 | ||
24 | #define AK4641_DAC 0x06 | ||
25 | #define AK4641_MIC 0x07 | ||
26 | #define AK4641_TIMER 0x08 | ||
27 | #define AK4641_ALC1 0x09 | ||
28 | #define AK4641_ALC2 0x0a | ||
29 | #define AK4641_PGA 0x0b | ||
30 | #define AK4641_LATT 0x0c | ||
31 | #define AK4641_RATT 0x0d | ||
32 | #define AK4641_VOL 0x0e | ||
33 | #define AK4641_STATUS 0x0f | ||
34 | #define AK4641_EQLO 0x10 | ||
35 | #define AK4641_EQMID 0x11 | ||
36 | #define AK4641_EQHI 0x12 | ||
37 | #define AK4641_BTIF 0x13 | ||
38 | |||
39 | #define AK4641_CACHEREGNUM 0x14 | ||
40 | |||
41 | |||
42 | |||
43 | #define AK4641_DAI_HIFI 0 | ||
44 | #define AK4641_DAI_VOICE 1 | ||
45 | |||
46 | |||
47 | #endif | ||
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 2ec75abfa3e9..88b29f8c748b 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -352,7 +352,7 @@ static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = { | |||
352 | SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), | 352 | SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static const struct snd_soc_dapm_route intercon[] = { | 355 | static const struct snd_soc_dapm_route ak4671_intercon[] = { |
356 | {"DAC Left", "NULL", "PMPLL"}, | 356 | {"DAC Left", "NULL", "PMPLL"}, |
357 | {"DAC Right", "NULL", "PMPLL"}, | 357 | {"DAC Right", "NULL", "PMPLL"}, |
358 | {"ADC Left", "NULL", "PMPLL"}, | 358 | {"ADC Left", "NULL", "PMPLL"}, |
@@ -433,17 +433,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
433 | {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, | 433 | {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, |
434 | }; | 434 | }; |
435 | 435 | ||
436 | static int ak4671_add_widgets(struct snd_soc_codec *codec) | ||
437 | { | ||
438 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
439 | |||
440 | snd_soc_dapm_new_controls(dapm, ak4671_dapm_widgets, | ||
441 | ARRAY_SIZE(ak4671_dapm_widgets)); | ||
442 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int ak4671_hw_params(struct snd_pcm_substream *substream, | 436 | static int ak4671_hw_params(struct snd_pcm_substream *substream, |
448 | struct snd_pcm_hw_params *params, | 437 | struct snd_pcm_hw_params *params, |
449 | struct snd_soc_dai *dai) | 438 | struct snd_soc_dai *dai) |
@@ -650,7 +639,6 @@ static int ak4671_probe(struct snd_soc_codec *codec) | |||
650 | 639 | ||
651 | snd_soc_add_controls(codec, ak4671_snd_controls, | 640 | snd_soc_add_controls(codec, ak4671_snd_controls, |
652 | ARRAY_SIZE(ak4671_snd_controls)); | 641 | ARRAY_SIZE(ak4671_snd_controls)); |
653 | ak4671_add_widgets(codec); | ||
654 | 642 | ||
655 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 643 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
656 | 644 | ||
@@ -670,6 +658,10 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { | |||
670 | .reg_cache_size = AK4671_CACHEREGNUM, | 658 | .reg_cache_size = AK4671_CACHEREGNUM, |
671 | .reg_word_size = sizeof(u8), | 659 | .reg_word_size = sizeof(u8), |
672 | .reg_cache_default = ak4671_reg, | 660 | .reg_cache_default = ak4671_reg, |
661 | .dapm_widgets = ak4671_dapm_widgets, | ||
662 | .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), | ||
663 | .dapm_routes = ak4671_intercon, | ||
664 | .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), | ||
673 | }; | 665 | }; |
674 | 666 | ||
675 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | 667 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 0bb424af956f..d68ea532cc7f 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -86,18 +86,6 @@ static const struct snd_soc_dapm_route cx20442_audio_map[] = { | |||
86 | {"ADC", NULL, "Input Mixer"}, | 86 | {"ADC", NULL, "Input Mixer"}, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static int cx20442_add_widgets(struct snd_soc_codec *codec) | ||
90 | { | ||
91 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
92 | |||
93 | snd_soc_dapm_new_controls(dapm, cx20442_dapm_widgets, | ||
94 | ARRAY_SIZE(cx20442_dapm_widgets)); | ||
95 | snd_soc_dapm_add_routes(dapm, cx20442_audio_map, | ||
96 | ARRAY_SIZE(cx20442_audio_map)); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, | 89 | static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, |
102 | unsigned int reg) | 90 | unsigned int reg) |
103 | { | 91 | { |
@@ -344,8 +332,6 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec) | |||
344 | return -ENOMEM; | 332 | return -ENOMEM; |
345 | snd_soc_codec_set_drvdata(codec, cx20442); | 333 | snd_soc_codec_set_drvdata(codec, cx20442); |
346 | 334 | ||
347 | cx20442_add_widgets(codec); | ||
348 | |||
349 | cx20442->control_data = NULL; | 335 | cx20442->control_data = NULL; |
350 | codec->hw_write = NULL; | 336 | codec->hw_write = NULL; |
351 | codec->card->pop_time = 0; | 337 | codec->card->pop_time = 0; |
@@ -377,6 +363,10 @@ static struct snd_soc_codec_driver cx20442_codec_dev = { | |||
377 | .reg_word_size = sizeof(u8), | 363 | .reg_word_size = sizeof(u8), |
378 | .read = cx20442_read_reg_cache, | 364 | .read = cx20442_read_reg_cache, |
379 | .write = cx20442_write, | 365 | .write = cx20442_write, |
366 | .dapm_widgets = cx20442_dapm_widgets, | ||
367 | .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), | ||
368 | .dapm_routes = cx20442_audio_map, | ||
369 | .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), | ||
380 | }; | 370 | }; |
381 | 371 | ||
382 | static int cx20442_platform_probe(struct platform_device *pdev) | 372 | static int cx20442_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index 57e9dac88d38..f9a87737ec16 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c | |||
@@ -39,7 +39,31 @@ static struct snd_soc_dai_driver dmic_dai = { | |||
39 | }, | 39 | }, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static struct snd_soc_codec_driver soc_dmic = {}; | 42 | static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { |
43 | SND_SOC_DAPM_AIF_OUT("DMIC AIF", "Capture", 0, | ||
44 | SND_SOC_NOPM, 0, 0), | ||
45 | SND_SOC_DAPM_INPUT("DMic"), | ||
46 | }; | ||
47 | |||
48 | static const struct snd_soc_dapm_route intercon[] = { | ||
49 | {"DMIC AIF", NULL, "DMic"}, | ||
50 | }; | ||
51 | |||
52 | static int dmic_probe(struct snd_soc_codec *codec) | ||
53 | { | ||
54 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
55 | |||
56 | snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets, | ||
57 | ARRAY_SIZE(dmic_dapm_widgets)); | ||
58 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
59 | snd_soc_dapm_new_widgets(dapm); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static struct snd_soc_codec_driver soc_dmic = { | ||
65 | .probe = dmic_probe, | ||
66 | }; | ||
43 | 67 | ||
44 | static int __devinit dmic_dev_probe(struct platform_device *pdev) | 68 | static int __devinit dmic_dev_probe(struct platform_device *pdev) |
45 | { | 69 | { |
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index f5ccdbf7ebc6..e373f8f06907 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -294,20 +294,9 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
294 | 294 | ||
295 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) | 295 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) |
296 | { | 296 | { |
297 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
298 | |||
299 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | 297 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, |
300 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); | 298 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); |
301 | 299 | ||
302 | snd_soc_add_controls(codec, jz4740_codec_controls, | ||
303 | ARRAY_SIZE(jz4740_codec_controls)); | ||
304 | |||
305 | snd_soc_dapm_new_controls(dapm, jz4740_codec_dapm_widgets, | ||
306 | ARRAY_SIZE(jz4740_codec_dapm_widgets)); | ||
307 | |||
308 | snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes, | ||
309 | ARRAY_SIZE(jz4740_codec_dapm_routes)); | ||
310 | |||
311 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 300 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
312 | 301 | ||
313 | return 0; | 302 | return 0; |
@@ -348,6 +337,13 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { | |||
348 | .reg_cache_default = jz4740_codec_regs, | 337 | .reg_cache_default = jz4740_codec_regs, |
349 | .reg_word_size = sizeof(u32), | 338 | .reg_word_size = sizeof(u32), |
350 | .reg_cache_size = 2, | 339 | .reg_cache_size = 2, |
340 | |||
341 | .controls = jz4740_codec_controls, | ||
342 | .num_controls = ARRAY_SIZE(jz4740_codec_controls), | ||
343 | .dapm_widgets = jz4740_codec_dapm_widgets, | ||
344 | .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), | ||
345 | .dapm_routes = jz4740_codec_dapm_routes, | ||
346 | .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), | ||
351 | }; | 347 | }; |
352 | 348 | ||
353 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) | 349 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index bd0517cb7980..4173b67c94d1 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -656,8 +656,6 @@ static const struct soc_enum max98088_exmode_enum = | |||
656 | ARRAY_SIZE(max98088_exmode_texts), | 656 | ARRAY_SIZE(max98088_exmode_texts), |
657 | max98088_exmode_texts, | 657 | max98088_exmode_texts, |
658 | max98088_exmode_values); | 658 | max98088_exmode_values); |
659 | static const struct snd_kcontrol_new max98088_exmode_controls = | ||
660 | SOC_DAPM_VALUE_ENUM("Route", max98088_exmode_enum); | ||
661 | 659 | ||
662 | static const char *max98088_ex_thresh[] = { /* volts PP */ | 660 | static const char *max98088_ex_thresh[] = { /* volts PP */ |
663 | "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; | 661 | "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; |
@@ -783,6 +781,7 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { | |||
783 | SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), | 781 | SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), |
784 | SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), | 782 | SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), |
785 | 783 | ||
784 | SOC_ENUM("EX Limiter Mode", max98088_exmode_enum), | ||
786 | SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), | 785 | SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), |
787 | 786 | ||
788 | SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), | 787 | SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), |
@@ -808,10 +807,10 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { | |||
808 | 807 | ||
809 | /* Left speaker mixer switch */ | 808 | /* Left speaker mixer switch */ |
810 | static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { | 809 | static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { |
811 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | 810 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), |
812 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | 811 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), |
813 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | 812 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), |
814 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | 813 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), |
815 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), | 814 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), |
816 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), | 815 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), |
817 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), | 816 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), |
@@ -836,10 +835,10 @@ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { | |||
836 | 835 | ||
837 | /* Left headphone mixer switch */ | 836 | /* Left headphone mixer switch */ |
838 | static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { | 837 | static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { |
839 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | 838 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), |
840 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | 839 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), |
841 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | 840 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), |
842 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | 841 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), |
843 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), | 842 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), |
844 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), | 843 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), |
845 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), | 844 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), |
@@ -864,10 +863,10 @@ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { | |||
864 | 863 | ||
865 | /* Left earpiece/receiver mixer switch */ | 864 | /* Left earpiece/receiver mixer switch */ |
866 | static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { | 865 | static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { |
867 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | 866 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), |
868 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | 867 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), |
869 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | 868 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), |
870 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | 869 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), |
871 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), | 870 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), |
872 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), | 871 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), |
873 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), | 872 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), |
@@ -1094,9 +1093,6 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { | |||
1094 | 1093 | ||
1095 | SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), | 1094 | SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), |
1096 | 1095 | ||
1097 | SND_SOC_DAPM_MUX("EX Limiter Mode", SND_SOC_NOPM, 0, 0, | ||
1098 | &max98088_exmode_controls), | ||
1099 | |||
1100 | SND_SOC_DAPM_OUTPUT("HPL"), | 1096 | SND_SOC_DAPM_OUTPUT("HPL"), |
1101 | SND_SOC_DAPM_OUTPUT("HPR"), | 1097 | SND_SOC_DAPM_OUTPUT("HPR"), |
1102 | SND_SOC_DAPM_OUTPUT("SPKL"), | 1098 | SND_SOC_DAPM_OUTPUT("SPKL"), |
@@ -1112,7 +1108,7 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { | |||
1112 | SND_SOC_DAPM_INPUT("INB2"), | 1108 | SND_SOC_DAPM_INPUT("INB2"), |
1113 | }; | 1109 | }; |
1114 | 1110 | ||
1115 | static const struct snd_soc_dapm_route audio_map[] = { | 1111 | static const struct snd_soc_dapm_route max98088_audio_map[] = { |
1116 | /* Left headphone output mixer */ | 1112 | /* Left headphone output mixer */ |
1117 | {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, | 1113 | {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, |
1118 | {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, | 1114 | {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, |
@@ -1226,22 +1222,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
1226 | {"MIC2 Input", NULL, "MIC2"}, | 1222 | {"MIC2 Input", NULL, "MIC2"}, |
1227 | }; | 1223 | }; |
1228 | 1224 | ||
1229 | static int max98088_add_widgets(struct snd_soc_codec *codec) | ||
1230 | { | ||
1231 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1232 | |||
1233 | snd_soc_dapm_new_controls(dapm, max98088_dapm_widgets, | ||
1234 | ARRAY_SIZE(max98088_dapm_widgets)); | ||
1235 | |||
1236 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
1237 | |||
1238 | snd_soc_add_controls(codec, max98088_snd_controls, | ||
1239 | ARRAY_SIZE(max98088_snd_controls)); | ||
1240 | |||
1241 | snd_soc_dapm_new_widgets(dapm); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | /* codec mclk clock divider coefficients */ | 1225 | /* codec mclk clock divider coefficients */ |
1246 | static const struct { | 1226 | static const struct { |
1247 | u32 rate; | 1227 | u32 rate; |
@@ -1586,6 +1566,36 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, | |||
1586 | return 0; | 1566 | return 0; |
1587 | } | 1567 | } |
1588 | 1568 | ||
1569 | static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) | ||
1570 | { | ||
1571 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1572 | int reg; | ||
1573 | |||
1574 | if (mute) | ||
1575 | reg = M98088_DAI_MUTE; | ||
1576 | else | ||
1577 | reg = 0; | ||
1578 | |||
1579 | snd_soc_update_bits(codec, M98088_REG_2F_LVL_DAI1_PLAY, | ||
1580 | M98088_DAI_MUTE_MASK, reg); | ||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) | ||
1585 | { | ||
1586 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1587 | int reg; | ||
1588 | |||
1589 | if (mute) | ||
1590 | reg = M98088_DAI_MUTE; | ||
1591 | else | ||
1592 | reg = 0; | ||
1593 | |||
1594 | snd_soc_update_bits(codec, M98088_REG_31_LVL_DAI2_PLAY, | ||
1595 | M98088_DAI_MUTE_MASK, reg); | ||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1589 | static void max98088_sync_cache(struct snd_soc_codec *codec) | 1599 | static void max98088_sync_cache(struct snd_soc_codec *codec) |
1590 | { | 1600 | { |
1591 | u16 *reg_cache = codec->reg_cache; | 1601 | u16 *reg_cache = codec->reg_cache; |
@@ -1647,12 +1657,14 @@ static struct snd_soc_dai_ops max98088_dai1_ops = { | |||
1647 | .set_sysclk = max98088_dai_set_sysclk, | 1657 | .set_sysclk = max98088_dai_set_sysclk, |
1648 | .set_fmt = max98088_dai1_set_fmt, | 1658 | .set_fmt = max98088_dai1_set_fmt, |
1649 | .hw_params = max98088_dai1_hw_params, | 1659 | .hw_params = max98088_dai1_hw_params, |
1660 | .digital_mute = max98088_dai1_digital_mute, | ||
1650 | }; | 1661 | }; |
1651 | 1662 | ||
1652 | static struct snd_soc_dai_ops max98088_dai2_ops = { | 1663 | static struct snd_soc_dai_ops max98088_dai2_ops = { |
1653 | .set_sysclk = max98088_dai_set_sysclk, | 1664 | .set_sysclk = max98088_dai_set_sysclk, |
1654 | .set_fmt = max98088_dai2_set_fmt, | 1665 | .set_fmt = max98088_dai2_set_fmt, |
1655 | .hw_params = max98088_dai2_hw_params, | 1666 | .hw_params = max98088_dai2_hw_params, |
1667 | .digital_mute = max98088_dai2_digital_mute, | ||
1656 | }; | 1668 | }; |
1657 | 1669 | ||
1658 | static struct snd_soc_dai_driver max98088_dai[] = { | 1670 | static struct snd_soc_dai_driver max98088_dai[] = { |
@@ -2010,7 +2022,8 @@ static int max98088_probe(struct snd_soc_codec *codec) | |||
2010 | 2022 | ||
2011 | max98088_handle_pdata(codec); | 2023 | max98088_handle_pdata(codec); |
2012 | 2024 | ||
2013 | max98088_add_widgets(codec); | 2025 | snd_soc_add_controls(codec, max98088_snd_controls, |
2026 | ARRAY_SIZE(max98088_snd_controls)); | ||
2014 | 2027 | ||
2015 | err_access: | 2028 | err_access: |
2016 | return ret; | 2029 | return ret; |
@@ -2036,6 +2049,10 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = { | |||
2036 | .reg_word_size = sizeof(u8), | 2049 | .reg_word_size = sizeof(u8), |
2037 | .reg_cache_default = max98088_reg, | 2050 | .reg_cache_default = max98088_reg, |
2038 | .volatile_register = max98088_volatile_register, | 2051 | .volatile_register = max98088_volatile_register, |
2052 | .dapm_widgets = max98088_dapm_widgets, | ||
2053 | .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), | ||
2054 | .dapm_routes = max98088_audio_map, | ||
2055 | .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), | ||
2039 | }; | 2056 | }; |
2040 | 2057 | ||
2041 | static int max98088_i2c_probe(struct i2c_client *i2c, | 2058 | static int max98088_i2c_probe(struct i2c_client *i2c, |
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h index 56554c797fef..be89a4f4aab8 100644 --- a/sound/soc/codecs/max98088.h +++ b/sound/soc/codecs/max98088.h | |||
@@ -133,6 +133,19 @@ | |||
133 | #define M98088_REC_LINEMODE (1<<7) | 133 | #define M98088_REC_LINEMODE (1<<7) |
134 | #define M98088_REC_LINEMODE_MASK (1<<7) | 134 | #define M98088_REC_LINEMODE_MASK (1<<7) |
135 | 135 | ||
136 | /* M98088_REG_2D_MIX_SPK_CNTL */ | ||
137 | #define M98088_MIX_SPKR_GAIN_MASK (3<<2) | ||
138 | #define M98088_MIX_SPKR_GAIN_SHIFT 2 | ||
139 | #define M98088_MIX_SPKL_GAIN_MASK (3<<0) | ||
140 | #define M98088_MIX_SPKL_GAIN_SHIFT 0 | ||
141 | |||
142 | /* M98088_REG_2F_LVL_DAI1_PLAY, M98088_REG_31_LVL_DAI2_PLAY */ | ||
143 | #define M98088_DAI_MUTE (1<<7) | ||
144 | #define M98088_DAI_MUTE_MASK (1<<7) | ||
145 | #define M98088_DAI_VOICE_GAIN_MASK (3<<4) | ||
146 | #define M98088_DAI_ATTENUATION_MASK (0xF<<0) | ||
147 | #define M98088_DAI_ATTENUATION_SHIFT 0 | ||
148 | |||
136 | /* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */ | 149 | /* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */ |
137 | #define M98088_MICPRE_MASK (3<<5) | 150 | #define M98088_MICPRE_MASK (3<<5) |
138 | #define M98088_MICPRE_SHIFT 5 | 151 | #define M98088_MICPRE_SHIFT 5 |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c new file mode 100644 index 000000000000..e1d282d477da --- /dev/null +++ b/sound/soc/codecs/max98095.c | |||
@@ -0,0 +1,2396 @@ | |||
1 | /* | ||
2 | * max98095.c -- MAX98095 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Maxim Integrated Products | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/moduleparam.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/initval.h> | ||
24 | #include <sound/tlv.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <asm/div64.h> | ||
27 | #include <sound/max98095.h> | ||
28 | #include "max98095.h" | ||
29 | |||
30 | enum max98095_type { | ||
31 | MAX98095, | ||
32 | }; | ||
33 | |||
34 | struct max98095_cdata { | ||
35 | unsigned int rate; | ||
36 | unsigned int fmt; | ||
37 | int eq_sel; | ||
38 | int bq_sel; | ||
39 | }; | ||
40 | |||
41 | struct max98095_priv { | ||
42 | enum max98095_type devtype; | ||
43 | void *control_data; | ||
44 | struct max98095_pdata *pdata; | ||
45 | unsigned int sysclk; | ||
46 | struct max98095_cdata dai[3]; | ||
47 | const char **eq_texts; | ||
48 | const char **bq_texts; | ||
49 | struct soc_enum eq_enum; | ||
50 | struct soc_enum bq_enum; | ||
51 | int eq_textcnt; | ||
52 | int bq_textcnt; | ||
53 | u8 lin_state; | ||
54 | unsigned int mic1pre; | ||
55 | unsigned int mic2pre; | ||
56 | }; | ||
57 | |||
58 | static const u8 max98095_reg_def[M98095_REG_CNT] = { | ||
59 | 0x00, /* 00 */ | ||
60 | 0x00, /* 01 */ | ||
61 | 0x00, /* 02 */ | ||
62 | 0x00, /* 03 */ | ||
63 | 0x00, /* 04 */ | ||
64 | 0x00, /* 05 */ | ||
65 | 0x00, /* 06 */ | ||
66 | 0x00, /* 07 */ | ||
67 | 0x00, /* 08 */ | ||
68 | 0x00, /* 09 */ | ||
69 | 0x00, /* 0A */ | ||
70 | 0x00, /* 0B */ | ||
71 | 0x00, /* 0C */ | ||
72 | 0x00, /* 0D */ | ||
73 | 0x00, /* 0E */ | ||
74 | 0x00, /* 0F */ | ||
75 | 0x00, /* 10 */ | ||
76 | 0x00, /* 11 */ | ||
77 | 0x00, /* 12 */ | ||
78 | 0x00, /* 13 */ | ||
79 | 0x00, /* 14 */ | ||
80 | 0x00, /* 15 */ | ||
81 | 0x00, /* 16 */ | ||
82 | 0x00, /* 17 */ | ||
83 | 0x00, /* 18 */ | ||
84 | 0x00, /* 19 */ | ||
85 | 0x00, /* 1A */ | ||
86 | 0x00, /* 1B */ | ||
87 | 0x00, /* 1C */ | ||
88 | 0x00, /* 1D */ | ||
89 | 0x00, /* 1E */ | ||
90 | 0x00, /* 1F */ | ||
91 | 0x00, /* 20 */ | ||
92 | 0x00, /* 21 */ | ||
93 | 0x00, /* 22 */ | ||
94 | 0x00, /* 23 */ | ||
95 | 0x00, /* 24 */ | ||
96 | 0x00, /* 25 */ | ||
97 | 0x00, /* 26 */ | ||
98 | 0x00, /* 27 */ | ||
99 | 0x00, /* 28 */ | ||
100 | 0x00, /* 29 */ | ||
101 | 0x00, /* 2A */ | ||
102 | 0x00, /* 2B */ | ||
103 | 0x00, /* 2C */ | ||
104 | 0x00, /* 2D */ | ||
105 | 0x00, /* 2E */ | ||
106 | 0x00, /* 2F */ | ||
107 | 0x00, /* 30 */ | ||
108 | 0x00, /* 31 */ | ||
109 | 0x00, /* 32 */ | ||
110 | 0x00, /* 33 */ | ||
111 | 0x00, /* 34 */ | ||
112 | 0x00, /* 35 */ | ||
113 | 0x00, /* 36 */ | ||
114 | 0x00, /* 37 */ | ||
115 | 0x00, /* 38 */ | ||
116 | 0x00, /* 39 */ | ||
117 | 0x00, /* 3A */ | ||
118 | 0x00, /* 3B */ | ||
119 | 0x00, /* 3C */ | ||
120 | 0x00, /* 3D */ | ||
121 | 0x00, /* 3E */ | ||
122 | 0x00, /* 3F */ | ||
123 | 0x00, /* 40 */ | ||
124 | 0x00, /* 41 */ | ||
125 | 0x00, /* 42 */ | ||
126 | 0x00, /* 43 */ | ||
127 | 0x00, /* 44 */ | ||
128 | 0x00, /* 45 */ | ||
129 | 0x00, /* 46 */ | ||
130 | 0x00, /* 47 */ | ||
131 | 0x00, /* 48 */ | ||
132 | 0x00, /* 49 */ | ||
133 | 0x00, /* 4A */ | ||
134 | 0x00, /* 4B */ | ||
135 | 0x00, /* 4C */ | ||
136 | 0x00, /* 4D */ | ||
137 | 0x00, /* 4E */ | ||
138 | 0x00, /* 4F */ | ||
139 | 0x00, /* 50 */ | ||
140 | 0x00, /* 51 */ | ||
141 | 0x00, /* 52 */ | ||
142 | 0x00, /* 53 */ | ||
143 | 0x00, /* 54 */ | ||
144 | 0x00, /* 55 */ | ||
145 | 0x00, /* 56 */ | ||
146 | 0x00, /* 57 */ | ||
147 | 0x00, /* 58 */ | ||
148 | 0x00, /* 59 */ | ||
149 | 0x00, /* 5A */ | ||
150 | 0x00, /* 5B */ | ||
151 | 0x00, /* 5C */ | ||
152 | 0x00, /* 5D */ | ||
153 | 0x00, /* 5E */ | ||
154 | 0x00, /* 5F */ | ||
155 | 0x00, /* 60 */ | ||
156 | 0x00, /* 61 */ | ||
157 | 0x00, /* 62 */ | ||
158 | 0x00, /* 63 */ | ||
159 | 0x00, /* 64 */ | ||
160 | 0x00, /* 65 */ | ||
161 | 0x00, /* 66 */ | ||
162 | 0x00, /* 67 */ | ||
163 | 0x00, /* 68 */ | ||
164 | 0x00, /* 69 */ | ||
165 | 0x00, /* 6A */ | ||
166 | 0x00, /* 6B */ | ||
167 | 0x00, /* 6C */ | ||
168 | 0x00, /* 6D */ | ||
169 | 0x00, /* 6E */ | ||
170 | 0x00, /* 6F */ | ||
171 | 0x00, /* 70 */ | ||
172 | 0x00, /* 71 */ | ||
173 | 0x00, /* 72 */ | ||
174 | 0x00, /* 73 */ | ||
175 | 0x00, /* 74 */ | ||
176 | 0x00, /* 75 */ | ||
177 | 0x00, /* 76 */ | ||
178 | 0x00, /* 77 */ | ||
179 | 0x00, /* 78 */ | ||
180 | 0x00, /* 79 */ | ||
181 | 0x00, /* 7A */ | ||
182 | 0x00, /* 7B */ | ||
183 | 0x00, /* 7C */ | ||
184 | 0x00, /* 7D */ | ||
185 | 0x00, /* 7E */ | ||
186 | 0x00, /* 7F */ | ||
187 | 0x00, /* 80 */ | ||
188 | 0x00, /* 81 */ | ||
189 | 0x00, /* 82 */ | ||
190 | 0x00, /* 83 */ | ||
191 | 0x00, /* 84 */ | ||
192 | 0x00, /* 85 */ | ||
193 | 0x00, /* 86 */ | ||
194 | 0x00, /* 87 */ | ||
195 | 0x00, /* 88 */ | ||
196 | 0x00, /* 89 */ | ||
197 | 0x00, /* 8A */ | ||
198 | 0x00, /* 8B */ | ||
199 | 0x00, /* 8C */ | ||
200 | 0x00, /* 8D */ | ||
201 | 0x00, /* 8E */ | ||
202 | 0x00, /* 8F */ | ||
203 | 0x00, /* 90 */ | ||
204 | 0x00, /* 91 */ | ||
205 | 0x30, /* 92 */ | ||
206 | 0xF0, /* 93 */ | ||
207 | 0x00, /* 94 */ | ||
208 | 0x00, /* 95 */ | ||
209 | 0x3F, /* 96 */ | ||
210 | 0x00, /* 97 */ | ||
211 | 0x00, /* 98 */ | ||
212 | 0x00, /* 99 */ | ||
213 | 0x00, /* 9A */ | ||
214 | 0x00, /* 9B */ | ||
215 | 0x00, /* 9C */ | ||
216 | 0x00, /* 9D */ | ||
217 | 0x00, /* 9E */ | ||
218 | 0x00, /* 9F */ | ||
219 | 0x00, /* A0 */ | ||
220 | 0x00, /* A1 */ | ||
221 | 0x00, /* A2 */ | ||
222 | 0x00, /* A3 */ | ||
223 | 0x00, /* A4 */ | ||
224 | 0x00, /* A5 */ | ||
225 | 0x00, /* A6 */ | ||
226 | 0x00, /* A7 */ | ||
227 | 0x00, /* A8 */ | ||
228 | 0x00, /* A9 */ | ||
229 | 0x00, /* AA */ | ||
230 | 0x00, /* AB */ | ||
231 | 0x00, /* AC */ | ||
232 | 0x00, /* AD */ | ||
233 | 0x00, /* AE */ | ||
234 | 0x00, /* AF */ | ||
235 | 0x00, /* B0 */ | ||
236 | 0x00, /* B1 */ | ||
237 | 0x00, /* B2 */ | ||
238 | 0x00, /* B3 */ | ||
239 | 0x00, /* B4 */ | ||
240 | 0x00, /* B5 */ | ||
241 | 0x00, /* B6 */ | ||
242 | 0x00, /* B7 */ | ||
243 | 0x00, /* B8 */ | ||
244 | 0x00, /* B9 */ | ||
245 | 0x00, /* BA */ | ||
246 | 0x00, /* BB */ | ||
247 | 0x00, /* BC */ | ||
248 | 0x00, /* BD */ | ||
249 | 0x00, /* BE */ | ||
250 | 0x00, /* BF */ | ||
251 | 0x00, /* C0 */ | ||
252 | 0x00, /* C1 */ | ||
253 | 0x00, /* C2 */ | ||
254 | 0x00, /* C3 */ | ||
255 | 0x00, /* C4 */ | ||
256 | 0x00, /* C5 */ | ||
257 | 0x00, /* C6 */ | ||
258 | 0x00, /* C7 */ | ||
259 | 0x00, /* C8 */ | ||
260 | 0x00, /* C9 */ | ||
261 | 0x00, /* CA */ | ||
262 | 0x00, /* CB */ | ||
263 | 0x00, /* CC */ | ||
264 | 0x00, /* CD */ | ||
265 | 0x00, /* CE */ | ||
266 | 0x00, /* CF */ | ||
267 | 0x00, /* D0 */ | ||
268 | 0x00, /* D1 */ | ||
269 | 0x00, /* D2 */ | ||
270 | 0x00, /* D3 */ | ||
271 | 0x00, /* D4 */ | ||
272 | 0x00, /* D5 */ | ||
273 | 0x00, /* D6 */ | ||
274 | 0x00, /* D7 */ | ||
275 | 0x00, /* D8 */ | ||
276 | 0x00, /* D9 */ | ||
277 | 0x00, /* DA */ | ||
278 | 0x00, /* DB */ | ||
279 | 0x00, /* DC */ | ||
280 | 0x00, /* DD */ | ||
281 | 0x00, /* DE */ | ||
282 | 0x00, /* DF */ | ||
283 | 0x00, /* E0 */ | ||
284 | 0x00, /* E1 */ | ||
285 | 0x00, /* E2 */ | ||
286 | 0x00, /* E3 */ | ||
287 | 0x00, /* E4 */ | ||
288 | 0x00, /* E5 */ | ||
289 | 0x00, /* E6 */ | ||
290 | 0x00, /* E7 */ | ||
291 | 0x00, /* E8 */ | ||
292 | 0x00, /* E9 */ | ||
293 | 0x00, /* EA */ | ||
294 | 0x00, /* EB */ | ||
295 | 0x00, /* EC */ | ||
296 | 0x00, /* ED */ | ||
297 | 0x00, /* EE */ | ||
298 | 0x00, /* EF */ | ||
299 | 0x00, /* F0 */ | ||
300 | 0x00, /* F1 */ | ||
301 | 0x00, /* F2 */ | ||
302 | 0x00, /* F3 */ | ||
303 | 0x00, /* F4 */ | ||
304 | 0x00, /* F5 */ | ||
305 | 0x00, /* F6 */ | ||
306 | 0x00, /* F7 */ | ||
307 | 0x00, /* F8 */ | ||
308 | 0x00, /* F9 */ | ||
309 | 0x00, /* FA */ | ||
310 | 0x00, /* FB */ | ||
311 | 0x00, /* FC */ | ||
312 | 0x00, /* FD */ | ||
313 | 0x00, /* FE */ | ||
314 | 0x00, /* FF */ | ||
315 | }; | ||
316 | |||
317 | static struct { | ||
318 | int readable; | ||
319 | int writable; | ||
320 | } max98095_access[M98095_REG_CNT] = { | ||
321 | { 0x00, 0x00 }, /* 00 */ | ||
322 | { 0xFF, 0x00 }, /* 01 */ | ||
323 | { 0xFF, 0x00 }, /* 02 */ | ||
324 | { 0xFF, 0x00 }, /* 03 */ | ||
325 | { 0xFF, 0x00 }, /* 04 */ | ||
326 | { 0xFF, 0x00 }, /* 05 */ | ||
327 | { 0xFF, 0x00 }, /* 06 */ | ||
328 | { 0xFF, 0x00 }, /* 07 */ | ||
329 | { 0xFF, 0x00 }, /* 08 */ | ||
330 | { 0xFF, 0x00 }, /* 09 */ | ||
331 | { 0xFF, 0x00 }, /* 0A */ | ||
332 | { 0xFF, 0x00 }, /* 0B */ | ||
333 | { 0xFF, 0x00 }, /* 0C */ | ||
334 | { 0xFF, 0x00 }, /* 0D */ | ||
335 | { 0xFF, 0x00 }, /* 0E */ | ||
336 | { 0xFF, 0x9F }, /* 0F */ | ||
337 | { 0xFF, 0xFF }, /* 10 */ | ||
338 | { 0xFF, 0xFF }, /* 11 */ | ||
339 | { 0xFF, 0xFF }, /* 12 */ | ||
340 | { 0xFF, 0xFF }, /* 13 */ | ||
341 | { 0xFF, 0xFF }, /* 14 */ | ||
342 | { 0xFF, 0xFF }, /* 15 */ | ||
343 | { 0xFF, 0xFF }, /* 16 */ | ||
344 | { 0xFF, 0xFF }, /* 17 */ | ||
345 | { 0xFF, 0xFF }, /* 18 */ | ||
346 | { 0xFF, 0xFF }, /* 19 */ | ||
347 | { 0xFF, 0xFF }, /* 1A */ | ||
348 | { 0xFF, 0xFF }, /* 1B */ | ||
349 | { 0xFF, 0xFF }, /* 1C */ | ||
350 | { 0xFF, 0xFF }, /* 1D */ | ||
351 | { 0xFF, 0x77 }, /* 1E */ | ||
352 | { 0xFF, 0x77 }, /* 1F */ | ||
353 | { 0xFF, 0x77 }, /* 20 */ | ||
354 | { 0xFF, 0x77 }, /* 21 */ | ||
355 | { 0xFF, 0x77 }, /* 22 */ | ||
356 | { 0xFF, 0x77 }, /* 23 */ | ||
357 | { 0xFF, 0xFF }, /* 24 */ | ||
358 | { 0xFF, 0x7F }, /* 25 */ | ||
359 | { 0xFF, 0x31 }, /* 26 */ | ||
360 | { 0xFF, 0xFF }, /* 27 */ | ||
361 | { 0xFF, 0xFF }, /* 28 */ | ||
362 | { 0xFF, 0xFF }, /* 29 */ | ||
363 | { 0xFF, 0xF7 }, /* 2A */ | ||
364 | { 0xFF, 0x2F }, /* 2B */ | ||
365 | { 0xFF, 0xEF }, /* 2C */ | ||
366 | { 0xFF, 0xFF }, /* 2D */ | ||
367 | { 0xFF, 0xFF }, /* 2E */ | ||
368 | { 0xFF, 0xFF }, /* 2F */ | ||
369 | { 0xFF, 0xFF }, /* 30 */ | ||
370 | { 0xFF, 0xFF }, /* 31 */ | ||
371 | { 0xFF, 0xFF }, /* 32 */ | ||
372 | { 0xFF, 0xFF }, /* 33 */ | ||
373 | { 0xFF, 0xF7 }, /* 34 */ | ||
374 | { 0xFF, 0x2F }, /* 35 */ | ||
375 | { 0xFF, 0xCF }, /* 36 */ | ||
376 | { 0xFF, 0xFF }, /* 37 */ | ||
377 | { 0xFF, 0xFF }, /* 38 */ | ||
378 | { 0xFF, 0xFF }, /* 39 */ | ||
379 | { 0xFF, 0xFF }, /* 3A */ | ||
380 | { 0xFF, 0xFF }, /* 3B */ | ||
381 | { 0xFF, 0xFF }, /* 3C */ | ||
382 | { 0xFF, 0xFF }, /* 3D */ | ||
383 | { 0xFF, 0xF7 }, /* 3E */ | ||
384 | { 0xFF, 0x2F }, /* 3F */ | ||
385 | { 0xFF, 0xCF }, /* 40 */ | ||
386 | { 0xFF, 0xFF }, /* 41 */ | ||
387 | { 0xFF, 0x77 }, /* 42 */ | ||
388 | { 0xFF, 0xFF }, /* 43 */ | ||
389 | { 0xFF, 0xFF }, /* 44 */ | ||
390 | { 0xFF, 0xFF }, /* 45 */ | ||
391 | { 0xFF, 0xFF }, /* 46 */ | ||
392 | { 0xFF, 0xFF }, /* 47 */ | ||
393 | { 0xFF, 0xFF }, /* 48 */ | ||
394 | { 0xFF, 0x0F }, /* 49 */ | ||
395 | { 0xFF, 0xFF }, /* 4A */ | ||
396 | { 0xFF, 0xFF }, /* 4B */ | ||
397 | { 0xFF, 0x3F }, /* 4C */ | ||
398 | { 0xFF, 0x3F }, /* 4D */ | ||
399 | { 0xFF, 0x3F }, /* 4E */ | ||
400 | { 0xFF, 0xFF }, /* 4F */ | ||
401 | { 0xFF, 0x7F }, /* 50 */ | ||
402 | { 0xFF, 0x7F }, /* 51 */ | ||
403 | { 0xFF, 0x0F }, /* 52 */ | ||
404 | { 0xFF, 0x3F }, /* 53 */ | ||
405 | { 0xFF, 0x3F }, /* 54 */ | ||
406 | { 0xFF, 0x3F }, /* 55 */ | ||
407 | { 0xFF, 0xFF }, /* 56 */ | ||
408 | { 0xFF, 0xFF }, /* 57 */ | ||
409 | { 0xFF, 0xBF }, /* 58 */ | ||
410 | { 0xFF, 0x1F }, /* 59 */ | ||
411 | { 0xFF, 0xBF }, /* 5A */ | ||
412 | { 0xFF, 0x1F }, /* 5B */ | ||
413 | { 0xFF, 0xBF }, /* 5C */ | ||
414 | { 0xFF, 0x3F }, /* 5D */ | ||
415 | { 0xFF, 0x3F }, /* 5E */ | ||
416 | { 0xFF, 0x7F }, /* 5F */ | ||
417 | { 0xFF, 0x7F }, /* 60 */ | ||
418 | { 0xFF, 0x47 }, /* 61 */ | ||
419 | { 0xFF, 0x9F }, /* 62 */ | ||
420 | { 0xFF, 0x9F }, /* 63 */ | ||
421 | { 0xFF, 0x9F }, /* 64 */ | ||
422 | { 0xFF, 0x9F }, /* 65 */ | ||
423 | { 0xFF, 0x9F }, /* 66 */ | ||
424 | { 0xFF, 0xBF }, /* 67 */ | ||
425 | { 0xFF, 0xBF }, /* 68 */ | ||
426 | { 0xFF, 0xFF }, /* 69 */ | ||
427 | { 0xFF, 0xFF }, /* 6A */ | ||
428 | { 0xFF, 0x7F }, /* 6B */ | ||
429 | { 0xFF, 0xF7 }, /* 6C */ | ||
430 | { 0xFF, 0xFF }, /* 6D */ | ||
431 | { 0xFF, 0xFF }, /* 6E */ | ||
432 | { 0xFF, 0x1F }, /* 6F */ | ||
433 | { 0xFF, 0xF7 }, /* 70 */ | ||
434 | { 0xFF, 0xFF }, /* 71 */ | ||
435 | { 0xFF, 0xFF }, /* 72 */ | ||
436 | { 0xFF, 0x1F }, /* 73 */ | ||
437 | { 0xFF, 0xF7 }, /* 74 */ | ||
438 | { 0xFF, 0xFF }, /* 75 */ | ||
439 | { 0xFF, 0xFF }, /* 76 */ | ||
440 | { 0xFF, 0x1F }, /* 77 */ | ||
441 | { 0xFF, 0xF7 }, /* 78 */ | ||
442 | { 0xFF, 0xFF }, /* 79 */ | ||
443 | { 0xFF, 0xFF }, /* 7A */ | ||
444 | { 0xFF, 0x1F }, /* 7B */ | ||
445 | { 0xFF, 0xF7 }, /* 7C */ | ||
446 | { 0xFF, 0xFF }, /* 7D */ | ||
447 | { 0xFF, 0xFF }, /* 7E */ | ||
448 | { 0xFF, 0x1F }, /* 7F */ | ||
449 | { 0xFF, 0xF7 }, /* 80 */ | ||
450 | { 0xFF, 0xFF }, /* 81 */ | ||
451 | { 0xFF, 0xFF }, /* 82 */ | ||
452 | { 0xFF, 0x1F }, /* 83 */ | ||
453 | { 0xFF, 0x7F }, /* 84 */ | ||
454 | { 0xFF, 0x0F }, /* 85 */ | ||
455 | { 0xFF, 0xD8 }, /* 86 */ | ||
456 | { 0xFF, 0xFF }, /* 87 */ | ||
457 | { 0xFF, 0xEF }, /* 88 */ | ||
458 | { 0xFF, 0xFE }, /* 89 */ | ||
459 | { 0xFF, 0xFE }, /* 8A */ | ||
460 | { 0xFF, 0xFF }, /* 8B */ | ||
461 | { 0xFF, 0xFF }, /* 8C */ | ||
462 | { 0xFF, 0x3F }, /* 8D */ | ||
463 | { 0xFF, 0xFF }, /* 8E */ | ||
464 | { 0xFF, 0x3F }, /* 8F */ | ||
465 | { 0xFF, 0x8F }, /* 90 */ | ||
466 | { 0xFF, 0xFF }, /* 91 */ | ||
467 | { 0xFF, 0x3F }, /* 92 */ | ||
468 | { 0xFF, 0xFF }, /* 93 */ | ||
469 | { 0xFF, 0xFF }, /* 94 */ | ||
470 | { 0xFF, 0x0F }, /* 95 */ | ||
471 | { 0xFF, 0x3F }, /* 96 */ | ||
472 | { 0xFF, 0x8C }, /* 97 */ | ||
473 | { 0x00, 0x00 }, /* 98 */ | ||
474 | { 0x00, 0x00 }, /* 99 */ | ||
475 | { 0x00, 0x00 }, /* 9A */ | ||
476 | { 0x00, 0x00 }, /* 9B */ | ||
477 | { 0x00, 0x00 }, /* 9C */ | ||
478 | { 0x00, 0x00 }, /* 9D */ | ||
479 | { 0x00, 0x00 }, /* 9E */ | ||
480 | { 0x00, 0x00 }, /* 9F */ | ||
481 | { 0x00, 0x00 }, /* A0 */ | ||
482 | { 0x00, 0x00 }, /* A1 */ | ||
483 | { 0x00, 0x00 }, /* A2 */ | ||
484 | { 0x00, 0x00 }, /* A3 */ | ||
485 | { 0x00, 0x00 }, /* A4 */ | ||
486 | { 0x00, 0x00 }, /* A5 */ | ||
487 | { 0x00, 0x00 }, /* A6 */ | ||
488 | { 0x00, 0x00 }, /* A7 */ | ||
489 | { 0x00, 0x00 }, /* A8 */ | ||
490 | { 0x00, 0x00 }, /* A9 */ | ||
491 | { 0x00, 0x00 }, /* AA */ | ||
492 | { 0x00, 0x00 }, /* AB */ | ||
493 | { 0x00, 0x00 }, /* AC */ | ||
494 | { 0x00, 0x00 }, /* AD */ | ||
495 | { 0x00, 0x00 }, /* AE */ | ||
496 | { 0x00, 0x00 }, /* AF */ | ||
497 | { 0x00, 0x00 }, /* B0 */ | ||
498 | { 0x00, 0x00 }, /* B1 */ | ||
499 | { 0x00, 0x00 }, /* B2 */ | ||
500 | { 0x00, 0x00 }, /* B3 */ | ||
501 | { 0x00, 0x00 }, /* B4 */ | ||
502 | { 0x00, 0x00 }, /* B5 */ | ||
503 | { 0x00, 0x00 }, /* B6 */ | ||
504 | { 0x00, 0x00 }, /* B7 */ | ||
505 | { 0x00, 0x00 }, /* B8 */ | ||
506 | { 0x00, 0x00 }, /* B9 */ | ||
507 | { 0x00, 0x00 }, /* BA */ | ||
508 | { 0x00, 0x00 }, /* BB */ | ||
509 | { 0x00, 0x00 }, /* BC */ | ||
510 | { 0x00, 0x00 }, /* BD */ | ||
511 | { 0x00, 0x00 }, /* BE */ | ||
512 | { 0x00, 0x00 }, /* BF */ | ||
513 | { 0x00, 0x00 }, /* C0 */ | ||
514 | { 0x00, 0x00 }, /* C1 */ | ||
515 | { 0x00, 0x00 }, /* C2 */ | ||
516 | { 0x00, 0x00 }, /* C3 */ | ||
517 | { 0x00, 0x00 }, /* C4 */ | ||
518 | { 0x00, 0x00 }, /* C5 */ | ||
519 | { 0x00, 0x00 }, /* C6 */ | ||
520 | { 0x00, 0x00 }, /* C7 */ | ||
521 | { 0x00, 0x00 }, /* C8 */ | ||
522 | { 0x00, 0x00 }, /* C9 */ | ||
523 | { 0x00, 0x00 }, /* CA */ | ||
524 | { 0x00, 0x00 }, /* CB */ | ||
525 | { 0x00, 0x00 }, /* CC */ | ||
526 | { 0x00, 0x00 }, /* CD */ | ||
527 | { 0x00, 0x00 }, /* CE */ | ||
528 | { 0x00, 0x00 }, /* CF */ | ||
529 | { 0x00, 0x00 }, /* D0 */ | ||
530 | { 0x00, 0x00 }, /* D1 */ | ||
531 | { 0x00, 0x00 }, /* D2 */ | ||
532 | { 0x00, 0x00 }, /* D3 */ | ||
533 | { 0x00, 0x00 }, /* D4 */ | ||
534 | { 0x00, 0x00 }, /* D5 */ | ||
535 | { 0x00, 0x00 }, /* D6 */ | ||
536 | { 0x00, 0x00 }, /* D7 */ | ||
537 | { 0x00, 0x00 }, /* D8 */ | ||
538 | { 0x00, 0x00 }, /* D9 */ | ||
539 | { 0x00, 0x00 }, /* DA */ | ||
540 | { 0x00, 0x00 }, /* DB */ | ||
541 | { 0x00, 0x00 }, /* DC */ | ||
542 | { 0x00, 0x00 }, /* DD */ | ||
543 | { 0x00, 0x00 }, /* DE */ | ||
544 | { 0x00, 0x00 }, /* DF */ | ||
545 | { 0x00, 0x00 }, /* E0 */ | ||
546 | { 0x00, 0x00 }, /* E1 */ | ||
547 | { 0x00, 0x00 }, /* E2 */ | ||
548 | { 0x00, 0x00 }, /* E3 */ | ||
549 | { 0x00, 0x00 }, /* E4 */ | ||
550 | { 0x00, 0x00 }, /* E5 */ | ||
551 | { 0x00, 0x00 }, /* E6 */ | ||
552 | { 0x00, 0x00 }, /* E7 */ | ||
553 | { 0x00, 0x00 }, /* E8 */ | ||
554 | { 0x00, 0x00 }, /* E9 */ | ||
555 | { 0x00, 0x00 }, /* EA */ | ||
556 | { 0x00, 0x00 }, /* EB */ | ||
557 | { 0x00, 0x00 }, /* EC */ | ||
558 | { 0x00, 0x00 }, /* ED */ | ||
559 | { 0x00, 0x00 }, /* EE */ | ||
560 | { 0x00, 0x00 }, /* EF */ | ||
561 | { 0x00, 0x00 }, /* F0 */ | ||
562 | { 0x00, 0x00 }, /* F1 */ | ||
563 | { 0x00, 0x00 }, /* F2 */ | ||
564 | { 0x00, 0x00 }, /* F3 */ | ||
565 | { 0x00, 0x00 }, /* F4 */ | ||
566 | { 0x00, 0x00 }, /* F5 */ | ||
567 | { 0x00, 0x00 }, /* F6 */ | ||
568 | { 0x00, 0x00 }, /* F7 */ | ||
569 | { 0x00, 0x00 }, /* F8 */ | ||
570 | { 0x00, 0x00 }, /* F9 */ | ||
571 | { 0x00, 0x00 }, /* FA */ | ||
572 | { 0x00, 0x00 }, /* FB */ | ||
573 | { 0x00, 0x00 }, /* FC */ | ||
574 | { 0x00, 0x00 }, /* FD */ | ||
575 | { 0x00, 0x00 }, /* FE */ | ||
576 | { 0xFF, 0x00 }, /* FF */ | ||
577 | }; | ||
578 | |||
579 | static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg) | ||
580 | { | ||
581 | if (reg >= M98095_REG_CNT) | ||
582 | return 0; | ||
583 | return max98095_access[reg].readable != 0; | ||
584 | } | ||
585 | |||
586 | static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg) | ||
587 | { | ||
588 | if (reg > M98095_REG_MAX_CACHED) | ||
589 | return 1; | ||
590 | |||
591 | switch (reg) { | ||
592 | case M98095_000_HOST_DATA: | ||
593 | case M98095_001_HOST_INT_STS: | ||
594 | case M98095_002_HOST_RSP_STS: | ||
595 | case M98095_003_HOST_CMD_STS: | ||
596 | case M98095_004_CODEC_STS: | ||
597 | case M98095_005_DAI1_ALC_STS: | ||
598 | case M98095_006_DAI2_ALC_STS: | ||
599 | case M98095_007_JACK_AUTO_STS: | ||
600 | case M98095_008_JACK_MANUAL_STS: | ||
601 | case M98095_009_JACK_VBAT_STS: | ||
602 | case M98095_00A_ACC_ADC_STS: | ||
603 | case M98095_00B_MIC_NG_AGC_STS: | ||
604 | case M98095_00C_SPK_L_VOLT_STS: | ||
605 | case M98095_00D_SPK_R_VOLT_STS: | ||
606 | case M98095_00E_TEMP_SENSOR_STS: | ||
607 | return 1; | ||
608 | } | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * Filter coefficients are in a separate register segment | ||
615 | * and they share the address space of the normal registers. | ||
616 | * The coefficient registers do not need or share the cache. | ||
617 | */ | ||
618 | static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg, | ||
619 | unsigned int value) | ||
620 | { | ||
621 | u8 data[2]; | ||
622 | |||
623 | data[0] = reg; | ||
624 | data[1] = value; | ||
625 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
626 | return 0; | ||
627 | else | ||
628 | return -EIO; | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | * Load equalizer DSP coefficient configurations registers | ||
633 | */ | ||
634 | static void m98095_eq_band(struct snd_soc_codec *codec, unsigned int dai, | ||
635 | unsigned int band, u16 *coefs) | ||
636 | { | ||
637 | unsigned int eq_reg; | ||
638 | unsigned int i; | ||
639 | |||
640 | BUG_ON(band > 4); | ||
641 | BUG_ON(dai > 1); | ||
642 | |||
643 | /* Load the base register address */ | ||
644 | eq_reg = dai ? M98095_142_DAI2_EQ_BASE : M98095_110_DAI1_EQ_BASE; | ||
645 | |||
646 | /* Add the band address offset, note adjustment for word address */ | ||
647 | eq_reg += band * (M98095_COEFS_PER_BAND << 1); | ||
648 | |||
649 | /* Step through the registers and coefs */ | ||
650 | for (i = 0; i < M98095_COEFS_PER_BAND; i++) { | ||
651 | max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i])); | ||
652 | max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i])); | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /* | ||
657 | * Load biquad filter coefficient configurations registers | ||
658 | */ | ||
659 | static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, | ||
660 | unsigned int band, u16 *coefs) | ||
661 | { | ||
662 | unsigned int bq_reg; | ||
663 | unsigned int i; | ||
664 | |||
665 | BUG_ON(band > 1); | ||
666 | BUG_ON(dai > 1); | ||
667 | |||
668 | /* Load the base register address */ | ||
669 | bq_reg = dai ? M98095_17E_DAI2_BQ_BASE : M98095_174_DAI1_BQ_BASE; | ||
670 | |||
671 | /* Add the band address offset, note adjustment for word address */ | ||
672 | bq_reg += band * (M98095_COEFS_PER_BAND << 1); | ||
673 | |||
674 | /* Step through the registers and coefs */ | ||
675 | for (i = 0; i < M98095_COEFS_PER_BAND; i++) { | ||
676 | max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i])); | ||
677 | max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i])); | ||
678 | } | ||
679 | } | ||
680 | |||
681 | static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; | ||
682 | static const struct soc_enum max98095_dai1_filter_mode_enum[] = { | ||
683 | SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), | ||
684 | }; | ||
685 | static const struct soc_enum max98095_dai2_filter_mode_enum[] = { | ||
686 | SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), | ||
687 | }; | ||
688 | |||
689 | static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; | ||
690 | |||
691 | static const struct soc_enum max98095_extmic_enum = | ||
692 | SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); | ||
693 | |||
694 | static const struct snd_kcontrol_new max98095_extmic_mux = | ||
695 | SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); | ||
696 | |||
697 | static const char * const max98095_linein_text[] = { "INA", "INB" }; | ||
698 | |||
699 | static const struct soc_enum max98095_linein_enum = | ||
700 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); | ||
701 | |||
702 | static const struct snd_kcontrol_new max98095_linein_mux = | ||
703 | SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); | ||
704 | |||
705 | static const char * const max98095_line_mode_text[] = { | ||
706 | "Stereo", "Differential"}; | ||
707 | |||
708 | static const struct soc_enum max98095_linein_mode_enum = | ||
709 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); | ||
710 | |||
711 | static const struct soc_enum max98095_lineout_mode_enum = | ||
712 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); | ||
713 | |||
714 | static const char * const max98095_dai_fltr[] = { | ||
715 | "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", | ||
716 | "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; | ||
717 | static const struct soc_enum max98095_dai1_dac_filter_enum[] = { | ||
718 | SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), | ||
719 | }; | ||
720 | static const struct soc_enum max98095_dai2_dac_filter_enum[] = { | ||
721 | SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), | ||
722 | }; | ||
723 | static const struct soc_enum max98095_dai3_dac_filter_enum[] = { | ||
724 | SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), | ||
725 | }; | ||
726 | |||
727 | static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, | ||
728 | struct snd_ctl_elem_value *ucontrol) | ||
729 | { | ||
730 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
731 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
732 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
733 | |||
734 | max98095->mic1pre = sel; | ||
735 | snd_soc_update_bits(codec, M98095_05F_LVL_MIC1, M98095_MICPRE_MASK, | ||
736 | (1+sel)<<M98095_MICPRE_SHIFT); | ||
737 | |||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol, | ||
742 | struct snd_ctl_elem_value *ucontrol) | ||
743 | { | ||
744 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
745 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
746 | |||
747 | ucontrol->value.integer.value[0] = max98095->mic1pre; | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol, | ||
752 | struct snd_ctl_elem_value *ucontrol) | ||
753 | { | ||
754 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
755 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
756 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
757 | |||
758 | max98095->mic2pre = sel; | ||
759 | snd_soc_update_bits(codec, M98095_060_LVL_MIC2, M98095_MICPRE_MASK, | ||
760 | (1+sel)<<M98095_MICPRE_SHIFT); | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol, | ||
766 | struct snd_ctl_elem_value *ucontrol) | ||
767 | { | ||
768 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
769 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
770 | |||
771 | ucontrol->value.integer.value[0] = max98095->mic2pre; | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static const unsigned int max98095_micboost_tlv[] = { | ||
776 | TLV_DB_RANGE_HEAD(2), | ||
777 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | ||
778 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | ||
779 | }; | ||
780 | |||
781 | static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0); | ||
782 | static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0); | ||
783 | static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0); | ||
784 | |||
785 | static const unsigned int max98095_hp_tlv[] = { | ||
786 | TLV_DB_RANGE_HEAD(5), | ||
787 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | ||
788 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), | ||
789 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), | ||
790 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), | ||
791 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), | ||
792 | }; | ||
793 | |||
794 | static const unsigned int max98095_spk_tlv[] = { | ||
795 | TLV_DB_RANGE_HEAD(4), | ||
796 | 0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0), | ||
797 | 11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0), | ||
798 | 19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0), | ||
799 | 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0), | ||
800 | }; | ||
801 | |||
802 | static const unsigned int max98095_rcv_lout_tlv[] = { | ||
803 | TLV_DB_RANGE_HEAD(5), | ||
804 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), | ||
805 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), | ||
806 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), | ||
807 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), | ||
808 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), | ||
809 | }; | ||
810 | |||
811 | static const unsigned int max98095_lin_tlv[] = { | ||
812 | TLV_DB_RANGE_HEAD(3), | ||
813 | 0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0), | ||
814 | 3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0), | ||
815 | 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0), | ||
816 | }; | ||
817 | |||
818 | static const struct snd_kcontrol_new max98095_snd_controls[] = { | ||
819 | |||
820 | SOC_DOUBLE_R_TLV("Headphone Volume", M98095_064_LVL_HP_L, | ||
821 | M98095_065_LVL_HP_R, 0, 31, 0, max98095_hp_tlv), | ||
822 | |||
823 | SOC_DOUBLE_R_TLV("Speaker Volume", M98095_067_LVL_SPK_L, | ||
824 | M98095_068_LVL_SPK_R, 0, 39, 0, max98095_spk_tlv), | ||
825 | |||
826 | SOC_SINGLE_TLV("Receiver Volume", M98095_066_LVL_RCV, | ||
827 | 0, 31, 0, max98095_rcv_lout_tlv), | ||
828 | |||
829 | SOC_DOUBLE_R_TLV("Lineout Volume", M98095_062_LVL_LINEOUT1, | ||
830 | M98095_063_LVL_LINEOUT2, 0, 31, 0, max98095_rcv_lout_tlv), | ||
831 | |||
832 | SOC_DOUBLE_R("Headphone Switch", M98095_064_LVL_HP_L, | ||
833 | M98095_065_LVL_HP_R, 7, 1, 1), | ||
834 | |||
835 | SOC_DOUBLE_R("Speaker Switch", M98095_067_LVL_SPK_L, | ||
836 | M98095_068_LVL_SPK_R, 7, 1, 1), | ||
837 | |||
838 | SOC_SINGLE("Receiver Switch", M98095_066_LVL_RCV, 7, 1, 1), | ||
839 | |||
840 | SOC_DOUBLE_R("Lineout Switch", M98095_062_LVL_LINEOUT1, | ||
841 | M98095_063_LVL_LINEOUT2, 7, 1, 1), | ||
842 | |||
843 | SOC_SINGLE_TLV("MIC1 Volume", M98095_05F_LVL_MIC1, 0, 20, 1, | ||
844 | max98095_mic_tlv), | ||
845 | |||
846 | SOC_SINGLE_TLV("MIC2 Volume", M98095_060_LVL_MIC2, 0, 20, 1, | ||
847 | max98095_mic_tlv), | ||
848 | |||
849 | SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", | ||
850 | M98095_05F_LVL_MIC1, 5, 2, 0, | ||
851 | max98095_mic1pre_get, max98095_mic1pre_set, | ||
852 | max98095_micboost_tlv), | ||
853 | SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", | ||
854 | M98095_060_LVL_MIC2, 5, 2, 0, | ||
855 | max98095_mic2pre_get, max98095_mic2pre_set, | ||
856 | max98095_micboost_tlv), | ||
857 | |||
858 | SOC_SINGLE_TLV("Linein Volume", M98095_061_LVL_LINEIN, 0, 5, 1, | ||
859 | max98095_lin_tlv), | ||
860 | |||
861 | SOC_SINGLE_TLV("ADCL Volume", M98095_05D_LVL_ADC_L, 0, 15, 1, | ||
862 | max98095_adc_tlv), | ||
863 | SOC_SINGLE_TLV("ADCR Volume", M98095_05E_LVL_ADC_R, 0, 15, 1, | ||
864 | max98095_adc_tlv), | ||
865 | |||
866 | SOC_SINGLE_TLV("ADCL Boost Volume", M98095_05D_LVL_ADC_L, 4, 3, 0, | ||
867 | max98095_adcboost_tlv), | ||
868 | SOC_SINGLE_TLV("ADCR Boost Volume", M98095_05E_LVL_ADC_R, 4, 3, 0, | ||
869 | max98095_adcboost_tlv), | ||
870 | |||
871 | SOC_SINGLE("EQ1 Switch", M98095_088_CFG_LEVEL, 0, 1, 0), | ||
872 | SOC_SINGLE("EQ2 Switch", M98095_088_CFG_LEVEL, 1, 1, 0), | ||
873 | |||
874 | SOC_SINGLE("Biquad1 Switch", M98095_088_CFG_LEVEL, 2, 1, 0), | ||
875 | SOC_SINGLE("Biquad2 Switch", M98095_088_CFG_LEVEL, 3, 1, 0), | ||
876 | |||
877 | SOC_ENUM("DAI1 Filter Mode", max98095_dai1_filter_mode_enum), | ||
878 | SOC_ENUM("DAI2 Filter Mode", max98095_dai2_filter_mode_enum), | ||
879 | SOC_ENUM("DAI1 DAC Filter", max98095_dai1_dac_filter_enum), | ||
880 | SOC_ENUM("DAI2 DAC Filter", max98095_dai2_dac_filter_enum), | ||
881 | SOC_ENUM("DAI3 DAC Filter", max98095_dai3_dac_filter_enum), | ||
882 | |||
883 | SOC_ENUM("Linein Mode", max98095_linein_mode_enum), | ||
884 | SOC_ENUM("Lineout Mode", max98095_lineout_mode_enum), | ||
885 | }; | ||
886 | |||
887 | /* Left speaker mixer switch */ | ||
888 | static const struct snd_kcontrol_new max98095_left_speaker_mixer_controls[] = { | ||
889 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_050_MIX_SPK_LEFT, 0, 1, 0), | ||
890 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_050_MIX_SPK_LEFT, 6, 1, 0), | ||
891 | SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0), | ||
892 | SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0), | ||
893 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_050_MIX_SPK_LEFT, 4, 1, 0), | ||
894 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_050_MIX_SPK_LEFT, 5, 1, 0), | ||
895 | SOC_DAPM_SINGLE("IN1 Switch", M98095_050_MIX_SPK_LEFT, 1, 1, 0), | ||
896 | SOC_DAPM_SINGLE("IN2 Switch", M98095_050_MIX_SPK_LEFT, 2, 1, 0), | ||
897 | }; | ||
898 | |||
899 | /* Right speaker mixer switch */ | ||
900 | static const struct snd_kcontrol_new max98095_right_speaker_mixer_controls[] = { | ||
901 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 6, 1, 0), | ||
902 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 0, 1, 0), | ||
903 | SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0), | ||
904 | SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0), | ||
905 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_051_MIX_SPK_RIGHT, 5, 1, 0), | ||
906 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_051_MIX_SPK_RIGHT, 4, 1, 0), | ||
907 | SOC_DAPM_SINGLE("IN1 Switch", M98095_051_MIX_SPK_RIGHT, 1, 1, 0), | ||
908 | SOC_DAPM_SINGLE("IN2 Switch", M98095_051_MIX_SPK_RIGHT, 2, 1, 0), | ||
909 | }; | ||
910 | |||
911 | /* Left headphone mixer switch */ | ||
912 | static const struct snd_kcontrol_new max98095_left_hp_mixer_controls[] = { | ||
913 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04C_MIX_HP_LEFT, 0, 1, 0), | ||
914 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04C_MIX_HP_LEFT, 5, 1, 0), | ||
915 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_04C_MIX_HP_LEFT, 3, 1, 0), | ||
916 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_04C_MIX_HP_LEFT, 4, 1, 0), | ||
917 | SOC_DAPM_SINGLE("IN1 Switch", M98095_04C_MIX_HP_LEFT, 1, 1, 0), | ||
918 | SOC_DAPM_SINGLE("IN2 Switch", M98095_04C_MIX_HP_LEFT, 2, 1, 0), | ||
919 | }; | ||
920 | |||
921 | /* Right headphone mixer switch */ | ||
922 | static const struct snd_kcontrol_new max98095_right_hp_mixer_controls[] = { | ||
923 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 5, 1, 0), | ||
924 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 0, 1, 0), | ||
925 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_04D_MIX_HP_RIGHT, 3, 1, 0), | ||
926 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_04D_MIX_HP_RIGHT, 4, 1, 0), | ||
927 | SOC_DAPM_SINGLE("IN1 Switch", M98095_04D_MIX_HP_RIGHT, 1, 1, 0), | ||
928 | SOC_DAPM_SINGLE("IN2 Switch", M98095_04D_MIX_HP_RIGHT, 2, 1, 0), | ||
929 | }; | ||
930 | |||
931 | /* Receiver earpiece mixer switch */ | ||
932 | static const struct snd_kcontrol_new max98095_mono_rcv_mixer_controls[] = { | ||
933 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04F_MIX_RCV, 0, 1, 0), | ||
934 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04F_MIX_RCV, 5, 1, 0), | ||
935 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_04F_MIX_RCV, 3, 1, 0), | ||
936 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_04F_MIX_RCV, 4, 1, 0), | ||
937 | SOC_DAPM_SINGLE("IN1 Switch", M98095_04F_MIX_RCV, 1, 1, 0), | ||
938 | SOC_DAPM_SINGLE("IN2 Switch", M98095_04F_MIX_RCV, 2, 1, 0), | ||
939 | }; | ||
940 | |||
941 | /* Left lineout mixer switch */ | ||
942 | static const struct snd_kcontrol_new max98095_left_lineout_mixer_controls[] = { | ||
943 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_053_MIX_LINEOUT1, 5, 1, 0), | ||
944 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_053_MIX_LINEOUT1, 0, 1, 0), | ||
945 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_053_MIX_LINEOUT1, 3, 1, 0), | ||
946 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_053_MIX_LINEOUT1, 4, 1, 0), | ||
947 | SOC_DAPM_SINGLE("IN1 Switch", M98095_053_MIX_LINEOUT1, 1, 1, 0), | ||
948 | SOC_DAPM_SINGLE("IN2 Switch", M98095_053_MIX_LINEOUT1, 2, 1, 0), | ||
949 | }; | ||
950 | |||
951 | /* Right lineout mixer switch */ | ||
952 | static const struct snd_kcontrol_new max98095_right_lineout_mixer_controls[] = { | ||
953 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_054_MIX_LINEOUT2, 0, 1, 0), | ||
954 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_054_MIX_LINEOUT2, 5, 1, 0), | ||
955 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_054_MIX_LINEOUT2, 3, 1, 0), | ||
956 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_054_MIX_LINEOUT2, 4, 1, 0), | ||
957 | SOC_DAPM_SINGLE("IN1 Switch", M98095_054_MIX_LINEOUT2, 1, 1, 0), | ||
958 | SOC_DAPM_SINGLE("IN2 Switch", M98095_054_MIX_LINEOUT2, 2, 1, 0), | ||
959 | }; | ||
960 | |||
961 | /* Left ADC mixer switch */ | ||
962 | static const struct snd_kcontrol_new max98095_left_ADC_mixer_controls[] = { | ||
963 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_04A_MIX_ADC_LEFT, 7, 1, 0), | ||
964 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_04A_MIX_ADC_LEFT, 6, 1, 0), | ||
965 | SOC_DAPM_SINGLE("IN1 Switch", M98095_04A_MIX_ADC_LEFT, 3, 1, 0), | ||
966 | SOC_DAPM_SINGLE("IN2 Switch", M98095_04A_MIX_ADC_LEFT, 2, 1, 0), | ||
967 | }; | ||
968 | |||
969 | /* Right ADC mixer switch */ | ||
970 | static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { | ||
971 | SOC_DAPM_SINGLE("MIC1 Switch", M98095_04B_MIX_ADC_RIGHT, 7, 1, 0), | ||
972 | SOC_DAPM_SINGLE("MIC2 Switch", M98095_04B_MIX_ADC_RIGHT, 6, 1, 0), | ||
973 | SOC_DAPM_SINGLE("IN1 Switch", M98095_04B_MIX_ADC_RIGHT, 3, 1, 0), | ||
974 | SOC_DAPM_SINGLE("IN2 Switch", M98095_04B_MIX_ADC_RIGHT, 2, 1, 0), | ||
975 | }; | ||
976 | |||
977 | static int max98095_mic_event(struct snd_soc_dapm_widget *w, | ||
978 | struct snd_kcontrol *kcontrol, int event) | ||
979 | { | ||
980 | struct snd_soc_codec *codec = w->codec; | ||
981 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
982 | |||
983 | switch (event) { | ||
984 | case SND_SOC_DAPM_POST_PMU: | ||
985 | if (w->reg == M98095_05F_LVL_MIC1) { | ||
986 | snd_soc_update_bits(codec, w->reg, M98095_MICPRE_MASK, | ||
987 | (1+max98095->mic1pre)<<M98095_MICPRE_SHIFT); | ||
988 | } else { | ||
989 | snd_soc_update_bits(codec, w->reg, M98095_MICPRE_MASK, | ||
990 | (1+max98095->mic2pre)<<M98095_MICPRE_SHIFT); | ||
991 | } | ||
992 | break; | ||
993 | case SND_SOC_DAPM_POST_PMD: | ||
994 | snd_soc_update_bits(codec, w->reg, M98095_MICPRE_MASK, 0); | ||
995 | break; | ||
996 | default: | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | /* | ||
1004 | * The line inputs are stereo inputs with the left and right | ||
1005 | * channels sharing a common PGA power control signal. | ||
1006 | */ | ||
1007 | static int max98095_line_pga(struct snd_soc_dapm_widget *w, | ||
1008 | int event, u8 channel) | ||
1009 | { | ||
1010 | struct snd_soc_codec *codec = w->codec; | ||
1011 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1012 | u8 *state; | ||
1013 | |||
1014 | BUG_ON(!((channel == 1) || (channel == 2))); | ||
1015 | |||
1016 | state = &max98095->lin_state; | ||
1017 | |||
1018 | switch (event) { | ||
1019 | case SND_SOC_DAPM_POST_PMU: | ||
1020 | *state |= channel; | ||
1021 | snd_soc_update_bits(codec, w->reg, | ||
1022 | (1 << w->shift), (1 << w->shift)); | ||
1023 | break; | ||
1024 | case SND_SOC_DAPM_POST_PMD: | ||
1025 | *state &= ~channel; | ||
1026 | if (*state == 0) { | ||
1027 | snd_soc_update_bits(codec, w->reg, | ||
1028 | (1 << w->shift), 0); | ||
1029 | } | ||
1030 | break; | ||
1031 | default: | ||
1032 | return -EINVAL; | ||
1033 | } | ||
1034 | |||
1035 | return 0; | ||
1036 | } | ||
1037 | |||
1038 | static int max98095_pga_in1_event(struct snd_soc_dapm_widget *w, | ||
1039 | struct snd_kcontrol *k, int event) | ||
1040 | { | ||
1041 | return max98095_line_pga(w, event, 1); | ||
1042 | } | ||
1043 | |||
1044 | static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, | ||
1045 | struct snd_kcontrol *k, int event) | ||
1046 | { | ||
1047 | return max98095_line_pga(w, event, 2); | ||
1048 | } | ||
1049 | |||
1050 | /* | ||
1051 | * The stereo line out mixer outputs to two stereo line outs. | ||
1052 | * The 2nd pair has a separate set of enables. | ||
1053 | */ | ||
1054 | static int max98095_lineout_event(struct snd_soc_dapm_widget *w, | ||
1055 | struct snd_kcontrol *kcontrol, int event) | ||
1056 | { | ||
1057 | struct snd_soc_codec *codec = w->codec; | ||
1058 | |||
1059 | switch (event) { | ||
1060 | case SND_SOC_DAPM_POST_PMU: | ||
1061 | snd_soc_update_bits(codec, w->reg, | ||
1062 | (1 << (w->shift+2)), (1 << (w->shift+2))); | ||
1063 | break; | ||
1064 | case SND_SOC_DAPM_POST_PMD: | ||
1065 | snd_soc_update_bits(codec, w->reg, | ||
1066 | (1 << (w->shift+2)), 0); | ||
1067 | break; | ||
1068 | default: | ||
1069 | return -EINVAL; | ||
1070 | } | ||
1071 | |||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | static const struct snd_soc_dapm_widget max98095_dapm_widgets[] = { | ||
1076 | |||
1077 | SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98095_090_PWR_EN_IN, 0, 0), | ||
1078 | SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98095_090_PWR_EN_IN, 1, 0), | ||
1079 | |||
1080 | SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", | ||
1081 | M98095_091_PWR_EN_OUT, 0, 0), | ||
1082 | SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", | ||
1083 | M98095_091_PWR_EN_OUT, 1, 0), | ||
1084 | SND_SOC_DAPM_DAC("DACM2", "Aux Playback", | ||
1085 | M98095_091_PWR_EN_OUT, 2, 0), | ||
1086 | SND_SOC_DAPM_DAC("DACM3", "Voice Playback", | ||
1087 | M98095_091_PWR_EN_OUT, 2, 0), | ||
1088 | |||
1089 | SND_SOC_DAPM_PGA("HP Left Out", M98095_091_PWR_EN_OUT, | ||
1090 | 6, 0, NULL, 0), | ||
1091 | SND_SOC_DAPM_PGA("HP Right Out", M98095_091_PWR_EN_OUT, | ||
1092 | 7, 0, NULL, 0), | ||
1093 | |||
1094 | SND_SOC_DAPM_PGA("SPK Left Out", M98095_091_PWR_EN_OUT, | ||
1095 | 4, 0, NULL, 0), | ||
1096 | SND_SOC_DAPM_PGA("SPK Right Out", M98095_091_PWR_EN_OUT, | ||
1097 | 5, 0, NULL, 0), | ||
1098 | |||
1099 | SND_SOC_DAPM_PGA("RCV Mono Out", M98095_091_PWR_EN_OUT, | ||
1100 | 3, 0, NULL, 0), | ||
1101 | |||
1102 | SND_SOC_DAPM_PGA_E("LINE Left Out", M98095_092_PWR_EN_OUT, | ||
1103 | 0, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD), | ||
1104 | SND_SOC_DAPM_PGA_E("LINE Right Out", M98095_092_PWR_EN_OUT, | ||
1105 | 1, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD), | ||
1106 | |||
1107 | SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, | ||
1108 | &max98095_extmic_mux), | ||
1109 | |||
1110 | SND_SOC_DAPM_MUX("Linein Mux", SND_SOC_NOPM, 0, 0, | ||
1111 | &max98095_linein_mux), | ||
1112 | |||
1113 | SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
1114 | &max98095_left_hp_mixer_controls[0], | ||
1115 | ARRAY_SIZE(max98095_left_hp_mixer_controls)), | ||
1116 | |||
1117 | SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
1118 | &max98095_right_hp_mixer_controls[0], | ||
1119 | ARRAY_SIZE(max98095_right_hp_mixer_controls)), | ||
1120 | |||
1121 | SND_SOC_DAPM_MIXER("Left Speaker Mixer", SND_SOC_NOPM, 0, 0, | ||
1122 | &max98095_left_speaker_mixer_controls[0], | ||
1123 | ARRAY_SIZE(max98095_left_speaker_mixer_controls)), | ||
1124 | |||
1125 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", SND_SOC_NOPM, 0, 0, | ||
1126 | &max98095_right_speaker_mixer_controls[0], | ||
1127 | ARRAY_SIZE(max98095_right_speaker_mixer_controls)), | ||
1128 | |||
1129 | SND_SOC_DAPM_MIXER("Receiver Mixer", SND_SOC_NOPM, 0, 0, | ||
1130 | &max98095_mono_rcv_mixer_controls[0], | ||
1131 | ARRAY_SIZE(max98095_mono_rcv_mixer_controls)), | ||
1132 | |||
1133 | SND_SOC_DAPM_MIXER("Left Lineout Mixer", SND_SOC_NOPM, 0, 0, | ||
1134 | &max98095_left_lineout_mixer_controls[0], | ||
1135 | ARRAY_SIZE(max98095_left_lineout_mixer_controls)), | ||
1136 | |||
1137 | SND_SOC_DAPM_MIXER("Right Lineout Mixer", SND_SOC_NOPM, 0, 0, | ||
1138 | &max98095_right_lineout_mixer_controls[0], | ||
1139 | ARRAY_SIZE(max98095_right_lineout_mixer_controls)), | ||
1140 | |||
1141 | SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
1142 | &max98095_left_ADC_mixer_controls[0], | ||
1143 | ARRAY_SIZE(max98095_left_ADC_mixer_controls)), | ||
1144 | |||
1145 | SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
1146 | &max98095_right_ADC_mixer_controls[0], | ||
1147 | ARRAY_SIZE(max98095_right_ADC_mixer_controls)), | ||
1148 | |||
1149 | SND_SOC_DAPM_PGA_E("MIC1 Input", M98095_05F_LVL_MIC1, | ||
1150 | 5, 0, NULL, 0, max98095_mic_event, | ||
1151 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1152 | |||
1153 | SND_SOC_DAPM_PGA_E("MIC2 Input", M98095_060_LVL_MIC2, | ||
1154 | 5, 0, NULL, 0, max98095_mic_event, | ||
1155 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1156 | |||
1157 | SND_SOC_DAPM_PGA_E("IN1 Input", M98095_090_PWR_EN_IN, | ||
1158 | 7, 0, NULL, 0, max98095_pga_in1_event, | ||
1159 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1160 | |||
1161 | SND_SOC_DAPM_PGA_E("IN2 Input", M98095_090_PWR_EN_IN, | ||
1162 | 7, 0, NULL, 0, max98095_pga_in2_event, | ||
1163 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1164 | |||
1165 | SND_SOC_DAPM_MICBIAS("MICBIAS1", M98095_090_PWR_EN_IN, 2, 0), | ||
1166 | SND_SOC_DAPM_MICBIAS("MICBIAS2", M98095_090_PWR_EN_IN, 3, 0), | ||
1167 | |||
1168 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
1169 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
1170 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
1171 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
1172 | SND_SOC_DAPM_OUTPUT("RCV"), | ||
1173 | SND_SOC_DAPM_OUTPUT("OUT1"), | ||
1174 | SND_SOC_DAPM_OUTPUT("OUT2"), | ||
1175 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
1176 | SND_SOC_DAPM_OUTPUT("OUT4"), | ||
1177 | |||
1178 | SND_SOC_DAPM_INPUT("MIC1"), | ||
1179 | SND_SOC_DAPM_INPUT("MIC2"), | ||
1180 | SND_SOC_DAPM_INPUT("INA1"), | ||
1181 | SND_SOC_DAPM_INPUT("INA2"), | ||
1182 | SND_SOC_DAPM_INPUT("INB1"), | ||
1183 | SND_SOC_DAPM_INPUT("INB2"), | ||
1184 | }; | ||
1185 | |||
1186 | static const struct snd_soc_dapm_route max98095_audio_map[] = { | ||
1187 | /* Left headphone output mixer */ | ||
1188 | {"Left Headphone Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1189 | {"Left Headphone Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1190 | {"Left Headphone Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1191 | {"Left Headphone Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1192 | {"Left Headphone Mixer", "IN1 Switch", "IN1 Input"}, | ||
1193 | {"Left Headphone Mixer", "IN2 Switch", "IN2 Input"}, | ||
1194 | |||
1195 | /* Right headphone output mixer */ | ||
1196 | {"Right Headphone Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1197 | {"Right Headphone Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1198 | {"Right Headphone Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1199 | {"Right Headphone Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1200 | {"Right Headphone Mixer", "IN1 Switch", "IN1 Input"}, | ||
1201 | {"Right Headphone Mixer", "IN2 Switch", "IN2 Input"}, | ||
1202 | |||
1203 | /* Left speaker output mixer */ | ||
1204 | {"Left Speaker Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1205 | {"Left Speaker Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1206 | {"Left Speaker Mixer", "Mono DAC2 Switch", "DACM2"}, | ||
1207 | {"Left Speaker Mixer", "Mono DAC3 Switch", "DACM3"}, | ||
1208 | {"Left Speaker Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1209 | {"Left Speaker Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1210 | {"Left Speaker Mixer", "IN1 Switch", "IN1 Input"}, | ||
1211 | {"Left Speaker Mixer", "IN2 Switch", "IN2 Input"}, | ||
1212 | |||
1213 | /* Right speaker output mixer */ | ||
1214 | {"Right Speaker Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1215 | {"Right Speaker Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1216 | {"Right Speaker Mixer", "Mono DAC2 Switch", "DACM2"}, | ||
1217 | {"Right Speaker Mixer", "Mono DAC3 Switch", "DACM3"}, | ||
1218 | {"Right Speaker Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1219 | {"Right Speaker Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1220 | {"Right Speaker Mixer", "IN1 Switch", "IN1 Input"}, | ||
1221 | {"Right Speaker Mixer", "IN2 Switch", "IN2 Input"}, | ||
1222 | |||
1223 | /* Earpiece/Receiver output mixer */ | ||
1224 | {"Receiver Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1225 | {"Receiver Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1226 | {"Receiver Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1227 | {"Receiver Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1228 | {"Receiver Mixer", "IN1 Switch", "IN1 Input"}, | ||
1229 | {"Receiver Mixer", "IN2 Switch", "IN2 Input"}, | ||
1230 | |||
1231 | /* Left Lineout output mixer */ | ||
1232 | {"Left Lineout Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1233 | {"Left Lineout Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1234 | {"Left Lineout Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1235 | {"Left Lineout Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1236 | {"Left Lineout Mixer", "IN1 Switch", "IN1 Input"}, | ||
1237 | {"Left Lineout Mixer", "IN2 Switch", "IN2 Input"}, | ||
1238 | |||
1239 | /* Right lineout output mixer */ | ||
1240 | {"Right Lineout Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1241 | {"Right Lineout Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1242 | {"Right Lineout Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1243 | {"Right Lineout Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1244 | {"Right Lineout Mixer", "IN1 Switch", "IN1 Input"}, | ||
1245 | {"Right Lineout Mixer", "IN2 Switch", "IN2 Input"}, | ||
1246 | |||
1247 | {"HP Left Out", NULL, "Left Headphone Mixer"}, | ||
1248 | {"HP Right Out", NULL, "Right Headphone Mixer"}, | ||
1249 | {"SPK Left Out", NULL, "Left Speaker Mixer"}, | ||
1250 | {"SPK Right Out", NULL, "Right Speaker Mixer"}, | ||
1251 | {"RCV Mono Out", NULL, "Receiver Mixer"}, | ||
1252 | {"LINE Left Out", NULL, "Left Lineout Mixer"}, | ||
1253 | {"LINE Right Out", NULL, "Right Lineout Mixer"}, | ||
1254 | |||
1255 | {"HPL", NULL, "HP Left Out"}, | ||
1256 | {"HPR", NULL, "HP Right Out"}, | ||
1257 | {"SPKL", NULL, "SPK Left Out"}, | ||
1258 | {"SPKR", NULL, "SPK Right Out"}, | ||
1259 | {"RCV", NULL, "RCV Mono Out"}, | ||
1260 | {"OUT1", NULL, "LINE Left Out"}, | ||
1261 | {"OUT2", NULL, "LINE Right Out"}, | ||
1262 | {"OUT3", NULL, "LINE Left Out"}, | ||
1263 | {"OUT4", NULL, "LINE Right Out"}, | ||
1264 | |||
1265 | /* Left ADC input mixer */ | ||
1266 | {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1267 | {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1268 | {"Left ADC Mixer", "IN1 Switch", "IN1 Input"}, | ||
1269 | {"Left ADC Mixer", "IN2 Switch", "IN2 Input"}, | ||
1270 | |||
1271 | /* Right ADC input mixer */ | ||
1272 | {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1273 | {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1274 | {"Right ADC Mixer", "IN1 Switch", "IN1 Input"}, | ||
1275 | {"Right ADC Mixer", "IN2 Switch", "IN2 Input"}, | ||
1276 | |||
1277 | /* Inputs */ | ||
1278 | {"ADCL", NULL, "Left ADC Mixer"}, | ||
1279 | {"ADCR", NULL, "Right ADC Mixer"}, | ||
1280 | |||
1281 | {"IN1 Input", NULL, "INA1"}, | ||
1282 | {"IN2 Input", NULL, "INA2"}, | ||
1283 | |||
1284 | {"MIC1 Input", NULL, "MIC1"}, | ||
1285 | {"MIC2 Input", NULL, "MIC2"}, | ||
1286 | }; | ||
1287 | |||
1288 | static int max98095_add_widgets(struct snd_soc_codec *codec) | ||
1289 | { | ||
1290 | snd_soc_add_controls(codec, max98095_snd_controls, | ||
1291 | ARRAY_SIZE(max98095_snd_controls)); | ||
1292 | |||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | /* codec mclk clock divider coefficients */ | ||
1297 | static const struct { | ||
1298 | u32 rate; | ||
1299 | u8 sr; | ||
1300 | } rate_table[] = { | ||
1301 | {8000, 0x01}, | ||
1302 | {11025, 0x02}, | ||
1303 | {16000, 0x03}, | ||
1304 | {22050, 0x04}, | ||
1305 | {24000, 0x05}, | ||
1306 | {32000, 0x06}, | ||
1307 | {44100, 0x07}, | ||
1308 | {48000, 0x08}, | ||
1309 | {88200, 0x09}, | ||
1310 | {96000, 0x0A}, | ||
1311 | }; | ||
1312 | |||
1313 | static int rate_value(int rate, u8 *value) | ||
1314 | { | ||
1315 | int i; | ||
1316 | |||
1317 | for (i = 0; i < ARRAY_SIZE(rate_table); i++) { | ||
1318 | if (rate_table[i].rate >= rate) { | ||
1319 | *value = rate_table[i].sr; | ||
1320 | return 0; | ||
1321 | } | ||
1322 | } | ||
1323 | *value = rate_table[0].sr; | ||
1324 | return -EINVAL; | ||
1325 | } | ||
1326 | |||
1327 | static int max98095_dai1_hw_params(struct snd_pcm_substream *substream, | ||
1328 | struct snd_pcm_hw_params *params, | ||
1329 | struct snd_soc_dai *dai) | ||
1330 | { | ||
1331 | struct snd_soc_codec *codec = dai->codec; | ||
1332 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1333 | struct max98095_cdata *cdata; | ||
1334 | unsigned long long ni; | ||
1335 | unsigned int rate; | ||
1336 | u8 regval; | ||
1337 | |||
1338 | cdata = &max98095->dai[0]; | ||
1339 | |||
1340 | rate = params_rate(params); | ||
1341 | |||
1342 | switch (params_format(params)) { | ||
1343 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1344 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, | ||
1345 | M98095_DAI_WS, 0); | ||
1346 | break; | ||
1347 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1348 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, | ||
1349 | M98095_DAI_WS, M98095_DAI_WS); | ||
1350 | break; | ||
1351 | default: | ||
1352 | return -EINVAL; | ||
1353 | } | ||
1354 | |||
1355 | if (rate_value(rate, ®val)) | ||
1356 | return -EINVAL; | ||
1357 | |||
1358 | snd_soc_update_bits(codec, M98095_027_DAI1_CLKMODE, | ||
1359 | M98095_CLKMODE_MASK, regval); | ||
1360 | cdata->rate = rate; | ||
1361 | |||
1362 | /* Configure NI when operating as master */ | ||
1363 | if (snd_soc_read(codec, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { | ||
1364 | if (max98095->sysclk == 0) { | ||
1365 | dev_err(codec->dev, "Invalid system clock frequency\n"); | ||
1366 | return -EINVAL; | ||
1367 | } | ||
1368 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | ||
1369 | * (unsigned long long int)rate; | ||
1370 | do_div(ni, (unsigned long long int)max98095->sysclk); | ||
1371 | snd_soc_write(codec, M98095_028_DAI1_CLKCFG_HI, | ||
1372 | (ni >> 8) & 0x7F); | ||
1373 | snd_soc_write(codec, M98095_029_DAI1_CLKCFG_LO, | ||
1374 | ni & 0xFF); | ||
1375 | } | ||
1376 | |||
1377 | /* Update sample rate mode */ | ||
1378 | if (rate < 50000) | ||
1379 | snd_soc_update_bits(codec, M98095_02E_DAI1_FILTERS, | ||
1380 | M98095_DAI_DHF, 0); | ||
1381 | else | ||
1382 | snd_soc_update_bits(codec, M98095_02E_DAI1_FILTERS, | ||
1383 | M98095_DAI_DHF, M98095_DAI_DHF); | ||
1384 | |||
1385 | return 0; | ||
1386 | } | ||
1387 | |||
1388 | static int max98095_dai2_hw_params(struct snd_pcm_substream *substream, | ||
1389 | struct snd_pcm_hw_params *params, | ||
1390 | struct snd_soc_dai *dai) | ||
1391 | { | ||
1392 | struct snd_soc_codec *codec = dai->codec; | ||
1393 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1394 | struct max98095_cdata *cdata; | ||
1395 | unsigned long long ni; | ||
1396 | unsigned int rate; | ||
1397 | u8 regval; | ||
1398 | |||
1399 | cdata = &max98095->dai[1]; | ||
1400 | |||
1401 | rate = params_rate(params); | ||
1402 | |||
1403 | switch (params_format(params)) { | ||
1404 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1405 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, | ||
1406 | M98095_DAI_WS, 0); | ||
1407 | break; | ||
1408 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1409 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, | ||
1410 | M98095_DAI_WS, M98095_DAI_WS); | ||
1411 | break; | ||
1412 | default: | ||
1413 | return -EINVAL; | ||
1414 | } | ||
1415 | |||
1416 | if (rate_value(rate, ®val)) | ||
1417 | return -EINVAL; | ||
1418 | |||
1419 | snd_soc_update_bits(codec, M98095_031_DAI2_CLKMODE, | ||
1420 | M98095_CLKMODE_MASK, regval); | ||
1421 | cdata->rate = rate; | ||
1422 | |||
1423 | /* Configure NI when operating as master */ | ||
1424 | if (snd_soc_read(codec, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { | ||
1425 | if (max98095->sysclk == 0) { | ||
1426 | dev_err(codec->dev, "Invalid system clock frequency\n"); | ||
1427 | return -EINVAL; | ||
1428 | } | ||
1429 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | ||
1430 | * (unsigned long long int)rate; | ||
1431 | do_div(ni, (unsigned long long int)max98095->sysclk); | ||
1432 | snd_soc_write(codec, M98095_032_DAI2_CLKCFG_HI, | ||
1433 | (ni >> 8) & 0x7F); | ||
1434 | snd_soc_write(codec, M98095_033_DAI2_CLKCFG_LO, | ||
1435 | ni & 0xFF); | ||
1436 | } | ||
1437 | |||
1438 | /* Update sample rate mode */ | ||
1439 | if (rate < 50000) | ||
1440 | snd_soc_update_bits(codec, M98095_038_DAI2_FILTERS, | ||
1441 | M98095_DAI_DHF, 0); | ||
1442 | else | ||
1443 | snd_soc_update_bits(codec, M98095_038_DAI2_FILTERS, | ||
1444 | M98095_DAI_DHF, M98095_DAI_DHF); | ||
1445 | |||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | static int max98095_dai3_hw_params(struct snd_pcm_substream *substream, | ||
1450 | struct snd_pcm_hw_params *params, | ||
1451 | struct snd_soc_dai *dai) | ||
1452 | { | ||
1453 | struct snd_soc_codec *codec = dai->codec; | ||
1454 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1455 | struct max98095_cdata *cdata; | ||
1456 | unsigned long long ni; | ||
1457 | unsigned int rate; | ||
1458 | u8 regval; | ||
1459 | |||
1460 | cdata = &max98095->dai[2]; | ||
1461 | |||
1462 | rate = params_rate(params); | ||
1463 | |||
1464 | switch (params_format(params)) { | ||
1465 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1466 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, | ||
1467 | M98095_DAI_WS, 0); | ||
1468 | break; | ||
1469 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1470 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, | ||
1471 | M98095_DAI_WS, M98095_DAI_WS); | ||
1472 | break; | ||
1473 | default: | ||
1474 | return -EINVAL; | ||
1475 | } | ||
1476 | |||
1477 | if (rate_value(rate, ®val)) | ||
1478 | return -EINVAL; | ||
1479 | |||
1480 | snd_soc_update_bits(codec, M98095_03B_DAI3_CLKMODE, | ||
1481 | M98095_CLKMODE_MASK, regval); | ||
1482 | cdata->rate = rate; | ||
1483 | |||
1484 | /* Configure NI when operating as master */ | ||
1485 | if (snd_soc_read(codec, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { | ||
1486 | if (max98095->sysclk == 0) { | ||
1487 | dev_err(codec->dev, "Invalid system clock frequency\n"); | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | ||
1491 | * (unsigned long long int)rate; | ||
1492 | do_div(ni, (unsigned long long int)max98095->sysclk); | ||
1493 | snd_soc_write(codec, M98095_03C_DAI3_CLKCFG_HI, | ||
1494 | (ni >> 8) & 0x7F); | ||
1495 | snd_soc_write(codec, M98095_03D_DAI3_CLKCFG_LO, | ||
1496 | ni & 0xFF); | ||
1497 | } | ||
1498 | |||
1499 | /* Update sample rate mode */ | ||
1500 | if (rate < 50000) | ||
1501 | snd_soc_update_bits(codec, M98095_042_DAI3_FILTERS, | ||
1502 | M98095_DAI_DHF, 0); | ||
1503 | else | ||
1504 | snd_soc_update_bits(codec, M98095_042_DAI3_FILTERS, | ||
1505 | M98095_DAI_DHF, M98095_DAI_DHF); | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1510 | static int max98095_dai_set_sysclk(struct snd_soc_dai *dai, | ||
1511 | int clk_id, unsigned int freq, int dir) | ||
1512 | { | ||
1513 | struct snd_soc_codec *codec = dai->codec; | ||
1514 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1515 | |||
1516 | /* Requested clock frequency is already setup */ | ||
1517 | if (freq == max98095->sysclk) | ||
1518 | return 0; | ||
1519 | |||
1520 | max98095->sysclk = freq; /* remember current sysclk */ | ||
1521 | |||
1522 | /* Setup clocks for slave mode, and using the PLL | ||
1523 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | ||
1524 | * 0x02 (when master clk is 20MHz to 40MHz).. | ||
1525 | * 0x03 (when master clk is 40MHz to 60MHz).. | ||
1526 | */ | ||
1527 | if ((freq >= 10000000) && (freq < 20000000)) { | ||
1528 | snd_soc_write(codec, M98095_026_SYS_CLK, 0x10); | ||
1529 | } else if ((freq >= 20000000) && (freq < 40000000)) { | ||
1530 | snd_soc_write(codec, M98095_026_SYS_CLK, 0x20); | ||
1531 | } else if ((freq >= 40000000) && (freq < 60000000)) { | ||
1532 | snd_soc_write(codec, M98095_026_SYS_CLK, 0x30); | ||
1533 | } else { | ||
1534 | dev_err(codec->dev, "Invalid master clock frequency\n"); | ||
1535 | return -EINVAL; | ||
1536 | } | ||
1537 | |||
1538 | dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); | ||
1539 | |||
1540 | max98095->sysclk = freq; | ||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | static int max98095_dai1_set_fmt(struct snd_soc_dai *codec_dai, | ||
1545 | unsigned int fmt) | ||
1546 | { | ||
1547 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1548 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1549 | struct max98095_cdata *cdata; | ||
1550 | u8 regval = 0; | ||
1551 | |||
1552 | cdata = &max98095->dai[0]; | ||
1553 | |||
1554 | if (fmt != cdata->fmt) { | ||
1555 | cdata->fmt = fmt; | ||
1556 | |||
1557 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1558 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1559 | /* Slave mode PLL */ | ||
1560 | snd_soc_write(codec, M98095_028_DAI1_CLKCFG_HI, | ||
1561 | 0x80); | ||
1562 | snd_soc_write(codec, M98095_029_DAI1_CLKCFG_LO, | ||
1563 | 0x00); | ||
1564 | break; | ||
1565 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1566 | /* Set to master mode */ | ||
1567 | regval |= M98095_DAI_MAS; | ||
1568 | break; | ||
1569 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1570 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1571 | default: | ||
1572 | dev_err(codec->dev, "Clock mode unsupported"); | ||
1573 | return -EINVAL; | ||
1574 | } | ||
1575 | |||
1576 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1577 | case SND_SOC_DAIFMT_I2S: | ||
1578 | regval |= M98095_DAI_DLY; | ||
1579 | break; | ||
1580 | case SND_SOC_DAIFMT_LEFT_J: | ||
1581 | break; | ||
1582 | default: | ||
1583 | return -EINVAL; | ||
1584 | } | ||
1585 | |||
1586 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1587 | case SND_SOC_DAIFMT_NB_NF: | ||
1588 | break; | ||
1589 | case SND_SOC_DAIFMT_NB_IF: | ||
1590 | regval |= M98095_DAI_WCI; | ||
1591 | break; | ||
1592 | case SND_SOC_DAIFMT_IB_NF: | ||
1593 | regval |= M98095_DAI_BCI; | ||
1594 | break; | ||
1595 | case SND_SOC_DAIFMT_IB_IF: | ||
1596 | regval |= M98095_DAI_BCI|M98095_DAI_WCI; | ||
1597 | break; | ||
1598 | default: | ||
1599 | return -EINVAL; | ||
1600 | } | ||
1601 | |||
1602 | snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, | ||
1603 | M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | | ||
1604 | M98095_DAI_WCI, regval); | ||
1605 | |||
1606 | snd_soc_write(codec, M98095_02B_DAI1_CLOCK, M98095_DAI_BSEL64); | ||
1607 | } | ||
1608 | |||
1609 | return 0; | ||
1610 | } | ||
1611 | |||
1612 | static int max98095_dai2_set_fmt(struct snd_soc_dai *codec_dai, | ||
1613 | unsigned int fmt) | ||
1614 | { | ||
1615 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1616 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1617 | struct max98095_cdata *cdata; | ||
1618 | u8 regval = 0; | ||
1619 | |||
1620 | cdata = &max98095->dai[1]; | ||
1621 | |||
1622 | if (fmt != cdata->fmt) { | ||
1623 | cdata->fmt = fmt; | ||
1624 | |||
1625 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1626 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1627 | /* Slave mode PLL */ | ||
1628 | snd_soc_write(codec, M98095_032_DAI2_CLKCFG_HI, | ||
1629 | 0x80); | ||
1630 | snd_soc_write(codec, M98095_033_DAI2_CLKCFG_LO, | ||
1631 | 0x00); | ||
1632 | break; | ||
1633 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1634 | /* Set to master mode */ | ||
1635 | regval |= M98095_DAI_MAS; | ||
1636 | break; | ||
1637 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1638 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1639 | default: | ||
1640 | dev_err(codec->dev, "Clock mode unsupported"); | ||
1641 | return -EINVAL; | ||
1642 | } | ||
1643 | |||
1644 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1645 | case SND_SOC_DAIFMT_I2S: | ||
1646 | regval |= M98095_DAI_DLY; | ||
1647 | break; | ||
1648 | case SND_SOC_DAIFMT_LEFT_J: | ||
1649 | break; | ||
1650 | default: | ||
1651 | return -EINVAL; | ||
1652 | } | ||
1653 | |||
1654 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1655 | case SND_SOC_DAIFMT_NB_NF: | ||
1656 | break; | ||
1657 | case SND_SOC_DAIFMT_NB_IF: | ||
1658 | regval |= M98095_DAI_WCI; | ||
1659 | break; | ||
1660 | case SND_SOC_DAIFMT_IB_NF: | ||
1661 | regval |= M98095_DAI_BCI; | ||
1662 | break; | ||
1663 | case SND_SOC_DAIFMT_IB_IF: | ||
1664 | regval |= M98095_DAI_BCI|M98095_DAI_WCI; | ||
1665 | break; | ||
1666 | default: | ||
1667 | return -EINVAL; | ||
1668 | } | ||
1669 | |||
1670 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, | ||
1671 | M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | | ||
1672 | M98095_DAI_WCI, regval); | ||
1673 | |||
1674 | snd_soc_write(codec, M98095_035_DAI2_CLOCK, | ||
1675 | M98095_DAI_BSEL64); | ||
1676 | } | ||
1677 | |||
1678 | return 0; | ||
1679 | } | ||
1680 | |||
1681 | static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai, | ||
1682 | unsigned int fmt) | ||
1683 | { | ||
1684 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1685 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1686 | struct max98095_cdata *cdata; | ||
1687 | u8 regval = 0; | ||
1688 | |||
1689 | cdata = &max98095->dai[2]; | ||
1690 | |||
1691 | if (fmt != cdata->fmt) { | ||
1692 | cdata->fmt = fmt; | ||
1693 | |||
1694 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1695 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1696 | /* Slave mode PLL */ | ||
1697 | snd_soc_write(codec, M98095_03C_DAI3_CLKCFG_HI, | ||
1698 | 0x80); | ||
1699 | snd_soc_write(codec, M98095_03D_DAI3_CLKCFG_LO, | ||
1700 | 0x00); | ||
1701 | break; | ||
1702 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1703 | /* Set to master mode */ | ||
1704 | regval |= M98095_DAI_MAS; | ||
1705 | break; | ||
1706 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1707 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1708 | default: | ||
1709 | dev_err(codec->dev, "Clock mode unsupported"); | ||
1710 | return -EINVAL; | ||
1711 | } | ||
1712 | |||
1713 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1714 | case SND_SOC_DAIFMT_I2S: | ||
1715 | regval |= M98095_DAI_DLY; | ||
1716 | break; | ||
1717 | case SND_SOC_DAIFMT_LEFT_J: | ||
1718 | break; | ||
1719 | default: | ||
1720 | return -EINVAL; | ||
1721 | } | ||
1722 | |||
1723 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1724 | case SND_SOC_DAIFMT_NB_NF: | ||
1725 | break; | ||
1726 | case SND_SOC_DAIFMT_NB_IF: | ||
1727 | regval |= M98095_DAI_WCI; | ||
1728 | break; | ||
1729 | case SND_SOC_DAIFMT_IB_NF: | ||
1730 | regval |= M98095_DAI_BCI; | ||
1731 | break; | ||
1732 | case SND_SOC_DAIFMT_IB_IF: | ||
1733 | regval |= M98095_DAI_BCI|M98095_DAI_WCI; | ||
1734 | break; | ||
1735 | default: | ||
1736 | return -EINVAL; | ||
1737 | } | ||
1738 | |||
1739 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, | ||
1740 | M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | | ||
1741 | M98095_DAI_WCI, regval); | ||
1742 | |||
1743 | snd_soc_write(codec, M98095_03F_DAI3_CLOCK, | ||
1744 | M98095_DAI_BSEL64); | ||
1745 | } | ||
1746 | |||
1747 | return 0; | ||
1748 | } | ||
1749 | |||
1750 | static int max98095_set_bias_level(struct snd_soc_codec *codec, | ||
1751 | enum snd_soc_bias_level level) | ||
1752 | { | ||
1753 | int ret; | ||
1754 | |||
1755 | switch (level) { | ||
1756 | case SND_SOC_BIAS_ON: | ||
1757 | break; | ||
1758 | |||
1759 | case SND_SOC_BIAS_PREPARE: | ||
1760 | break; | ||
1761 | |||
1762 | case SND_SOC_BIAS_STANDBY: | ||
1763 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1764 | ret = snd_soc_cache_sync(codec); | ||
1765 | |||
1766 | if (ret != 0) { | ||
1767 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | ||
1768 | return ret; | ||
1769 | } | ||
1770 | } | ||
1771 | |||
1772 | snd_soc_update_bits(codec, M98095_090_PWR_EN_IN, | ||
1773 | M98095_MBEN, M98095_MBEN); | ||
1774 | break; | ||
1775 | |||
1776 | case SND_SOC_BIAS_OFF: | ||
1777 | snd_soc_update_bits(codec, M98095_090_PWR_EN_IN, | ||
1778 | M98095_MBEN, 0); | ||
1779 | codec->cache_sync = 1; | ||
1780 | break; | ||
1781 | } | ||
1782 | codec->dapm.bias_level = level; | ||
1783 | return 0; | ||
1784 | } | ||
1785 | |||
1786 | #define MAX98095_RATES SNDRV_PCM_RATE_8000_96000 | ||
1787 | #define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
1788 | |||
1789 | static struct snd_soc_dai_ops max98095_dai1_ops = { | ||
1790 | .set_sysclk = max98095_dai_set_sysclk, | ||
1791 | .set_fmt = max98095_dai1_set_fmt, | ||
1792 | .hw_params = max98095_dai1_hw_params, | ||
1793 | }; | ||
1794 | |||
1795 | static struct snd_soc_dai_ops max98095_dai2_ops = { | ||
1796 | .set_sysclk = max98095_dai_set_sysclk, | ||
1797 | .set_fmt = max98095_dai2_set_fmt, | ||
1798 | .hw_params = max98095_dai2_hw_params, | ||
1799 | }; | ||
1800 | |||
1801 | static struct snd_soc_dai_ops max98095_dai3_ops = { | ||
1802 | .set_sysclk = max98095_dai_set_sysclk, | ||
1803 | .set_fmt = max98095_dai3_set_fmt, | ||
1804 | .hw_params = max98095_dai3_hw_params, | ||
1805 | }; | ||
1806 | |||
1807 | static struct snd_soc_dai_driver max98095_dai[] = { | ||
1808 | { | ||
1809 | .name = "HiFi", | ||
1810 | .playback = { | ||
1811 | .stream_name = "HiFi Playback", | ||
1812 | .channels_min = 1, | ||
1813 | .channels_max = 2, | ||
1814 | .rates = MAX98095_RATES, | ||
1815 | .formats = MAX98095_FORMATS, | ||
1816 | }, | ||
1817 | .capture = { | ||
1818 | .stream_name = "HiFi Capture", | ||
1819 | .channels_min = 1, | ||
1820 | .channels_max = 2, | ||
1821 | .rates = MAX98095_RATES, | ||
1822 | .formats = MAX98095_FORMATS, | ||
1823 | }, | ||
1824 | .ops = &max98095_dai1_ops, | ||
1825 | }, | ||
1826 | { | ||
1827 | .name = "Aux", | ||
1828 | .playback = { | ||
1829 | .stream_name = "Aux Playback", | ||
1830 | .channels_min = 1, | ||
1831 | .channels_max = 1, | ||
1832 | .rates = MAX98095_RATES, | ||
1833 | .formats = MAX98095_FORMATS, | ||
1834 | }, | ||
1835 | .ops = &max98095_dai2_ops, | ||
1836 | }, | ||
1837 | { | ||
1838 | .name = "Voice", | ||
1839 | .playback = { | ||
1840 | .stream_name = "Voice Playback", | ||
1841 | .channels_min = 1, | ||
1842 | .channels_max = 1, | ||
1843 | .rates = MAX98095_RATES, | ||
1844 | .formats = MAX98095_FORMATS, | ||
1845 | }, | ||
1846 | .ops = &max98095_dai3_ops, | ||
1847 | } | ||
1848 | |||
1849 | }; | ||
1850 | |||
1851 | static int max98095_get_eq_channel(const char *name) | ||
1852 | { | ||
1853 | if (strcmp(name, "EQ1 Mode") == 0) | ||
1854 | return 0; | ||
1855 | if (strcmp(name, "EQ2 Mode") == 0) | ||
1856 | return 1; | ||
1857 | return -EINVAL; | ||
1858 | } | ||
1859 | |||
1860 | static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, | ||
1861 | struct snd_ctl_elem_value *ucontrol) | ||
1862 | { | ||
1863 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1864 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1865 | struct max98095_pdata *pdata = max98095->pdata; | ||
1866 | int channel = max98095_get_eq_channel(kcontrol->id.name); | ||
1867 | struct max98095_cdata *cdata; | ||
1868 | int sel = ucontrol->value.integer.value[0]; | ||
1869 | struct max98095_eq_cfg *coef_set; | ||
1870 | int fs, best, best_val, i; | ||
1871 | int regmask, regsave; | ||
1872 | |||
1873 | BUG_ON(channel > 1); | ||
1874 | |||
1875 | if (!pdata || !max98095->eq_textcnt) | ||
1876 | return 0; | ||
1877 | |||
1878 | if (sel >= pdata->eq_cfgcnt) | ||
1879 | return -EINVAL; | ||
1880 | |||
1881 | cdata = &max98095->dai[channel]; | ||
1882 | cdata->eq_sel = sel; | ||
1883 | fs = cdata->rate; | ||
1884 | |||
1885 | /* Find the selected configuration with nearest sample rate */ | ||
1886 | best = 0; | ||
1887 | best_val = INT_MAX; | ||
1888 | for (i = 0; i < pdata->eq_cfgcnt; i++) { | ||
1889 | if (strcmp(pdata->eq_cfg[i].name, max98095->eq_texts[sel]) == 0 && | ||
1890 | abs(pdata->eq_cfg[i].rate - fs) < best_val) { | ||
1891 | best = i; | ||
1892 | best_val = abs(pdata->eq_cfg[i].rate - fs); | ||
1893 | } | ||
1894 | } | ||
1895 | |||
1896 | dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | ||
1897 | pdata->eq_cfg[best].name, | ||
1898 | pdata->eq_cfg[best].rate, fs); | ||
1899 | |||
1900 | coef_set = &pdata->eq_cfg[best]; | ||
1901 | |||
1902 | regmask = (channel == 0) ? M98095_EQ1EN : M98095_EQ2EN; | ||
1903 | |||
1904 | /* Disable filter while configuring, and save current on/off state */ | ||
1905 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | ||
1906 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | ||
1907 | |||
1908 | mutex_lock(&codec->mutex); | ||
1909 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | ||
1910 | m98095_eq_band(codec, channel, 0, coef_set->band1); | ||
1911 | m98095_eq_band(codec, channel, 1, coef_set->band2); | ||
1912 | m98095_eq_band(codec, channel, 2, coef_set->band3); | ||
1913 | m98095_eq_band(codec, channel, 3, coef_set->band4); | ||
1914 | m98095_eq_band(codec, channel, 4, coef_set->band5); | ||
1915 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | ||
1916 | mutex_unlock(&codec->mutex); | ||
1917 | |||
1918 | /* Restore the original on/off state */ | ||
1919 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | ||
1920 | return 0; | ||
1921 | } | ||
1922 | |||
1923 | static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol, | ||
1924 | struct snd_ctl_elem_value *ucontrol) | ||
1925 | { | ||
1926 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1927 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1928 | int channel = max98095_get_eq_channel(kcontrol->id.name); | ||
1929 | struct max98095_cdata *cdata; | ||
1930 | |||
1931 | cdata = &max98095->dai[channel]; | ||
1932 | ucontrol->value.enumerated.item[0] = cdata->eq_sel; | ||
1933 | |||
1934 | return 0; | ||
1935 | } | ||
1936 | |||
1937 | static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) | ||
1938 | { | ||
1939 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
1940 | struct max98095_pdata *pdata = max98095->pdata; | ||
1941 | struct max98095_eq_cfg *cfg; | ||
1942 | unsigned int cfgcnt; | ||
1943 | int i, j; | ||
1944 | const char **t; | ||
1945 | int ret; | ||
1946 | |||
1947 | struct snd_kcontrol_new controls[] = { | ||
1948 | SOC_ENUM_EXT("EQ1 Mode", | ||
1949 | max98095->eq_enum, | ||
1950 | max98095_get_eq_enum, | ||
1951 | max98095_put_eq_enum), | ||
1952 | SOC_ENUM_EXT("EQ2 Mode", | ||
1953 | max98095->eq_enum, | ||
1954 | max98095_get_eq_enum, | ||
1955 | max98095_put_eq_enum), | ||
1956 | }; | ||
1957 | |||
1958 | cfg = pdata->eq_cfg; | ||
1959 | cfgcnt = pdata->eq_cfgcnt; | ||
1960 | |||
1961 | /* Setup an array of texts for the equalizer enum. | ||
1962 | * This is based on Mark Brown's equalizer driver code. | ||
1963 | */ | ||
1964 | max98095->eq_textcnt = 0; | ||
1965 | max98095->eq_texts = NULL; | ||
1966 | for (i = 0; i < cfgcnt; i++) { | ||
1967 | for (j = 0; j < max98095->eq_textcnt; j++) { | ||
1968 | if (strcmp(cfg[i].name, max98095->eq_texts[j]) == 0) | ||
1969 | break; | ||
1970 | } | ||
1971 | |||
1972 | if (j != max98095->eq_textcnt) | ||
1973 | continue; | ||
1974 | |||
1975 | /* Expand the array */ | ||
1976 | t = krealloc(max98095->eq_texts, | ||
1977 | sizeof(char *) * (max98095->eq_textcnt + 1), | ||
1978 | GFP_KERNEL); | ||
1979 | if (t == NULL) | ||
1980 | continue; | ||
1981 | |||
1982 | /* Store the new entry */ | ||
1983 | t[max98095->eq_textcnt] = cfg[i].name; | ||
1984 | max98095->eq_textcnt++; | ||
1985 | max98095->eq_texts = t; | ||
1986 | } | ||
1987 | |||
1988 | /* Now point the soc_enum to .texts array items */ | ||
1989 | max98095->eq_enum.texts = max98095->eq_texts; | ||
1990 | max98095->eq_enum.max = max98095->eq_textcnt; | ||
1991 | |||
1992 | ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | ||
1993 | if (ret != 0) | ||
1994 | dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); | ||
1995 | } | ||
1996 | |||
1997 | static int max98095_get_bq_channel(const char *name) | ||
1998 | { | ||
1999 | if (strcmp(name, "Biquad1 Mode") == 0) | ||
2000 | return 0; | ||
2001 | if (strcmp(name, "Biquad2 Mode") == 0) | ||
2002 | return 1; | ||
2003 | return -EINVAL; | ||
2004 | } | ||
2005 | |||
2006 | static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, | ||
2007 | struct snd_ctl_elem_value *ucontrol) | ||
2008 | { | ||
2009 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2010 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
2011 | struct max98095_pdata *pdata = max98095->pdata; | ||
2012 | int channel = max98095_get_bq_channel(kcontrol->id.name); | ||
2013 | struct max98095_cdata *cdata; | ||
2014 | int sel = ucontrol->value.integer.value[0]; | ||
2015 | struct max98095_biquad_cfg *coef_set; | ||
2016 | int fs, best, best_val, i; | ||
2017 | int regmask, regsave; | ||
2018 | |||
2019 | BUG_ON(channel > 1); | ||
2020 | |||
2021 | if (!pdata || !max98095->bq_textcnt) | ||
2022 | return 0; | ||
2023 | |||
2024 | if (sel >= pdata->bq_cfgcnt) | ||
2025 | return -EINVAL; | ||
2026 | |||
2027 | cdata = &max98095->dai[channel]; | ||
2028 | cdata->bq_sel = sel; | ||
2029 | fs = cdata->rate; | ||
2030 | |||
2031 | /* Find the selected configuration with nearest sample rate */ | ||
2032 | best = 0; | ||
2033 | best_val = INT_MAX; | ||
2034 | for (i = 0; i < pdata->bq_cfgcnt; i++) { | ||
2035 | if (strcmp(pdata->bq_cfg[i].name, max98095->bq_texts[sel]) == 0 && | ||
2036 | abs(pdata->bq_cfg[i].rate - fs) < best_val) { | ||
2037 | best = i; | ||
2038 | best_val = abs(pdata->bq_cfg[i].rate - fs); | ||
2039 | } | ||
2040 | } | ||
2041 | |||
2042 | dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | ||
2043 | pdata->bq_cfg[best].name, | ||
2044 | pdata->bq_cfg[best].rate, fs); | ||
2045 | |||
2046 | coef_set = &pdata->bq_cfg[best]; | ||
2047 | |||
2048 | regmask = (channel == 0) ? M98095_BQ1EN : M98095_BQ2EN; | ||
2049 | |||
2050 | /* Disable filter while configuring, and save current on/off state */ | ||
2051 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | ||
2052 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | ||
2053 | |||
2054 | mutex_lock(&codec->mutex); | ||
2055 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | ||
2056 | m98095_biquad_band(codec, channel, 0, coef_set->band1); | ||
2057 | m98095_biquad_band(codec, channel, 1, coef_set->band2); | ||
2058 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | ||
2059 | mutex_unlock(&codec->mutex); | ||
2060 | |||
2061 | /* Restore the original on/off state */ | ||
2062 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | ||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol, | ||
2067 | struct snd_ctl_elem_value *ucontrol) | ||
2068 | { | ||
2069 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2070 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
2071 | int channel = max98095_get_bq_channel(kcontrol->id.name); | ||
2072 | struct max98095_cdata *cdata; | ||
2073 | |||
2074 | cdata = &max98095->dai[channel]; | ||
2075 | ucontrol->value.enumerated.item[0] = cdata->bq_sel; | ||
2076 | |||
2077 | return 0; | ||
2078 | } | ||
2079 | |||
2080 | static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) | ||
2081 | { | ||
2082 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
2083 | struct max98095_pdata *pdata = max98095->pdata; | ||
2084 | struct max98095_biquad_cfg *cfg; | ||
2085 | unsigned int cfgcnt; | ||
2086 | int i, j; | ||
2087 | const char **t; | ||
2088 | int ret; | ||
2089 | |||
2090 | struct snd_kcontrol_new controls[] = { | ||
2091 | SOC_ENUM_EXT("Biquad1 Mode", | ||
2092 | max98095->bq_enum, | ||
2093 | max98095_get_bq_enum, | ||
2094 | max98095_put_bq_enum), | ||
2095 | SOC_ENUM_EXT("Biquad2 Mode", | ||
2096 | max98095->bq_enum, | ||
2097 | max98095_get_bq_enum, | ||
2098 | max98095_put_bq_enum), | ||
2099 | }; | ||
2100 | |||
2101 | cfg = pdata->bq_cfg; | ||
2102 | cfgcnt = pdata->bq_cfgcnt; | ||
2103 | |||
2104 | /* Setup an array of texts for the biquad enum. | ||
2105 | * This is based on Mark Brown's equalizer driver code. | ||
2106 | */ | ||
2107 | max98095->bq_textcnt = 0; | ||
2108 | max98095->bq_texts = NULL; | ||
2109 | for (i = 0; i < cfgcnt; i++) { | ||
2110 | for (j = 0; j < max98095->bq_textcnt; j++) { | ||
2111 | if (strcmp(cfg[i].name, max98095->bq_texts[j]) == 0) | ||
2112 | break; | ||
2113 | } | ||
2114 | |||
2115 | if (j != max98095->bq_textcnt) | ||
2116 | continue; | ||
2117 | |||
2118 | /* Expand the array */ | ||
2119 | t = krealloc(max98095->bq_texts, | ||
2120 | sizeof(char *) * (max98095->bq_textcnt + 1), | ||
2121 | GFP_KERNEL); | ||
2122 | if (t == NULL) | ||
2123 | continue; | ||
2124 | |||
2125 | /* Store the new entry */ | ||
2126 | t[max98095->bq_textcnt] = cfg[i].name; | ||
2127 | max98095->bq_textcnt++; | ||
2128 | max98095->bq_texts = t; | ||
2129 | } | ||
2130 | |||
2131 | /* Now point the soc_enum to .texts array items */ | ||
2132 | max98095->bq_enum.texts = max98095->bq_texts; | ||
2133 | max98095->bq_enum.max = max98095->bq_textcnt; | ||
2134 | |||
2135 | ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | ||
2136 | if (ret != 0) | ||
2137 | dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret); | ||
2138 | } | ||
2139 | |||
2140 | static void max98095_handle_pdata(struct snd_soc_codec *codec) | ||
2141 | { | ||
2142 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
2143 | struct max98095_pdata *pdata = max98095->pdata; | ||
2144 | u8 regval = 0; | ||
2145 | |||
2146 | if (!pdata) { | ||
2147 | dev_dbg(codec->dev, "No platform data\n"); | ||
2148 | return; | ||
2149 | } | ||
2150 | |||
2151 | /* Configure mic for analog/digital mic mode */ | ||
2152 | if (pdata->digmic_left_mode) | ||
2153 | regval |= M98095_DIGMIC_L; | ||
2154 | |||
2155 | if (pdata->digmic_right_mode) | ||
2156 | regval |= M98095_DIGMIC_R; | ||
2157 | |||
2158 | snd_soc_write(codec, M98095_087_CFG_MIC, regval); | ||
2159 | |||
2160 | /* Configure equalizers */ | ||
2161 | if (pdata->eq_cfgcnt) | ||
2162 | max98095_handle_eq_pdata(codec); | ||
2163 | |||
2164 | /* Configure bi-quad filters */ | ||
2165 | if (pdata->bq_cfgcnt) | ||
2166 | max98095_handle_bq_pdata(codec); | ||
2167 | } | ||
2168 | |||
2169 | #ifdef CONFIG_PM | ||
2170 | static int max98095_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
2171 | { | ||
2172 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2173 | |||
2174 | return 0; | ||
2175 | } | ||
2176 | |||
2177 | static int max98095_resume(struct snd_soc_codec *codec) | ||
2178 | { | ||
2179 | max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2180 | |||
2181 | return 0; | ||
2182 | } | ||
2183 | #else | ||
2184 | #define max98095_suspend NULL | ||
2185 | #define max98095_resume NULL | ||
2186 | #endif | ||
2187 | |||
2188 | static int max98095_reset(struct snd_soc_codec *codec) | ||
2189 | { | ||
2190 | int i, ret; | ||
2191 | |||
2192 | /* Gracefully reset the DSP core and the codec hardware | ||
2193 | * in a proper sequence */ | ||
2194 | ret = snd_soc_write(codec, M98095_00F_HOST_CFG, 0); | ||
2195 | if (ret < 0) { | ||
2196 | dev_err(codec->dev, "Failed to reset DSP: %d\n", ret); | ||
2197 | return ret; | ||
2198 | } | ||
2199 | |||
2200 | ret = snd_soc_write(codec, M98095_097_PWR_SYS, 0); | ||
2201 | if (ret < 0) { | ||
2202 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); | ||
2203 | return ret; | ||
2204 | } | ||
2205 | |||
2206 | /* Reset to hardware default for registers, as there is not | ||
2207 | * a soft reset hardware control register */ | ||
2208 | for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { | ||
2209 | ret = snd_soc_write(codec, i, max98095_reg_def[i]); | ||
2210 | if (ret < 0) { | ||
2211 | dev_err(codec->dev, "Failed to reset: %d\n", ret); | ||
2212 | return ret; | ||
2213 | } | ||
2214 | } | ||
2215 | |||
2216 | return ret; | ||
2217 | } | ||
2218 | |||
2219 | static int max98095_probe(struct snd_soc_codec *codec) | ||
2220 | { | ||
2221 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | ||
2222 | struct max98095_cdata *cdata; | ||
2223 | int ret = 0; | ||
2224 | |||
2225 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
2226 | if (ret != 0) { | ||
2227 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2228 | return ret; | ||
2229 | } | ||
2230 | |||
2231 | /* reset the codec, the DSP core, and disable all interrupts */ | ||
2232 | max98095_reset(codec); | ||
2233 | |||
2234 | /* initialize private data */ | ||
2235 | |||
2236 | max98095->sysclk = (unsigned)-1; | ||
2237 | max98095->eq_textcnt = 0; | ||
2238 | max98095->bq_textcnt = 0; | ||
2239 | |||
2240 | cdata = &max98095->dai[0]; | ||
2241 | cdata->rate = (unsigned)-1; | ||
2242 | cdata->fmt = (unsigned)-1; | ||
2243 | cdata->eq_sel = 0; | ||
2244 | cdata->bq_sel = 0; | ||
2245 | |||
2246 | cdata = &max98095->dai[1]; | ||
2247 | cdata->rate = (unsigned)-1; | ||
2248 | cdata->fmt = (unsigned)-1; | ||
2249 | cdata->eq_sel = 0; | ||
2250 | cdata->bq_sel = 0; | ||
2251 | |||
2252 | cdata = &max98095->dai[2]; | ||
2253 | cdata->rate = (unsigned)-1; | ||
2254 | cdata->fmt = (unsigned)-1; | ||
2255 | cdata->eq_sel = 0; | ||
2256 | cdata->bq_sel = 0; | ||
2257 | |||
2258 | max98095->lin_state = 0; | ||
2259 | max98095->mic1pre = 0; | ||
2260 | max98095->mic2pre = 0; | ||
2261 | |||
2262 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); | ||
2263 | if (ret < 0) { | ||
2264 | dev_err(codec->dev, "Failed to read device revision: %d\n", | ||
2265 | ret); | ||
2266 | goto err_access; | ||
2267 | } | ||
2268 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | ||
2269 | |||
2270 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); | ||
2271 | |||
2272 | /* initialize registers cache to hardware default */ | ||
2273 | max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2274 | |||
2275 | snd_soc_write(codec, M98095_048_MIX_DAC_LR, | ||
2276 | M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); | ||
2277 | |||
2278 | snd_soc_write(codec, M98095_049_MIX_DAC_M, | ||
2279 | M98095_DAI2M_TO_DACM|M98095_DAI3M_TO_DACM); | ||
2280 | |||
2281 | snd_soc_write(codec, M98095_092_PWR_EN_OUT, M98095_SPK_SPREADSPECTRUM); | ||
2282 | snd_soc_write(codec, M98095_045_CFG_DSP, M98095_DSPNORMAL); | ||
2283 | snd_soc_write(codec, M98095_04E_CFG_HP, M98095_HPNORMAL); | ||
2284 | |||
2285 | snd_soc_write(codec, M98095_02C_DAI1_IOCFG, | ||
2286 | M98095_S1NORMAL|M98095_SDATA); | ||
2287 | |||
2288 | snd_soc_write(codec, M98095_036_DAI2_IOCFG, | ||
2289 | M98095_S2NORMAL|M98095_SDATA); | ||
2290 | |||
2291 | snd_soc_write(codec, M98095_040_DAI3_IOCFG, | ||
2292 | M98095_S3NORMAL|M98095_SDATA); | ||
2293 | |||
2294 | max98095_handle_pdata(codec); | ||
2295 | |||
2296 | /* take the codec out of the shut down */ | ||
2297 | snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN, | ||
2298 | M98095_SHDNRUN); | ||
2299 | |||
2300 | max98095_add_widgets(codec); | ||
2301 | |||
2302 | err_access: | ||
2303 | return ret; | ||
2304 | } | ||
2305 | |||
2306 | static int max98095_remove(struct snd_soc_codec *codec) | ||
2307 | { | ||
2308 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2309 | |||
2310 | return 0; | ||
2311 | } | ||
2312 | |||
2313 | static struct snd_soc_codec_driver soc_codec_dev_max98095 = { | ||
2314 | .probe = max98095_probe, | ||
2315 | .remove = max98095_remove, | ||
2316 | .suspend = max98095_suspend, | ||
2317 | .resume = max98095_resume, | ||
2318 | .set_bias_level = max98095_set_bias_level, | ||
2319 | .reg_cache_size = ARRAY_SIZE(max98095_reg_def), | ||
2320 | .reg_word_size = sizeof(u8), | ||
2321 | .reg_cache_default = max98095_reg_def, | ||
2322 | .readable_register = max98095_readable, | ||
2323 | .volatile_register = max98095_volatile, | ||
2324 | .dapm_widgets = max98095_dapm_widgets, | ||
2325 | .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), | ||
2326 | .dapm_routes = max98095_audio_map, | ||
2327 | .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), | ||
2328 | }; | ||
2329 | |||
2330 | static int max98095_i2c_probe(struct i2c_client *i2c, | ||
2331 | const struct i2c_device_id *id) | ||
2332 | { | ||
2333 | struct max98095_priv *max98095; | ||
2334 | int ret; | ||
2335 | |||
2336 | max98095 = kzalloc(sizeof(struct max98095_priv), GFP_KERNEL); | ||
2337 | if (max98095 == NULL) | ||
2338 | return -ENOMEM; | ||
2339 | |||
2340 | max98095->devtype = id->driver_data; | ||
2341 | i2c_set_clientdata(i2c, max98095); | ||
2342 | max98095->control_data = i2c; | ||
2343 | max98095->pdata = i2c->dev.platform_data; | ||
2344 | |||
2345 | ret = snd_soc_register_codec(&i2c->dev, | ||
2346 | &soc_codec_dev_max98095, &max98095_dai[0], 3); | ||
2347 | if (ret < 0) | ||
2348 | kfree(max98095); | ||
2349 | return ret; | ||
2350 | } | ||
2351 | |||
2352 | static int __devexit max98095_i2c_remove(struct i2c_client *client) | ||
2353 | { | ||
2354 | snd_soc_unregister_codec(&client->dev); | ||
2355 | kfree(i2c_get_clientdata(client)); | ||
2356 | |||
2357 | return 0; | ||
2358 | } | ||
2359 | |||
2360 | static const struct i2c_device_id max98095_i2c_id[] = { | ||
2361 | { "max98095", MAX98095 }, | ||
2362 | { } | ||
2363 | }; | ||
2364 | MODULE_DEVICE_TABLE(i2c, max98095_i2c_id); | ||
2365 | |||
2366 | static struct i2c_driver max98095_i2c_driver = { | ||
2367 | .driver = { | ||
2368 | .name = "max98095", | ||
2369 | .owner = THIS_MODULE, | ||
2370 | }, | ||
2371 | .probe = max98095_i2c_probe, | ||
2372 | .remove = __devexit_p(max98095_i2c_remove), | ||
2373 | .id_table = max98095_i2c_id, | ||
2374 | }; | ||
2375 | |||
2376 | static int __init max98095_init(void) | ||
2377 | { | ||
2378 | int ret; | ||
2379 | |||
2380 | ret = i2c_add_driver(&max98095_i2c_driver); | ||
2381 | if (ret) | ||
2382 | pr_err("Failed to register max98095 I2C driver: %d\n", ret); | ||
2383 | |||
2384 | return ret; | ||
2385 | } | ||
2386 | module_init(max98095_init); | ||
2387 | |||
2388 | static void __exit max98095_exit(void) | ||
2389 | { | ||
2390 | i2c_del_driver(&max98095_i2c_driver); | ||
2391 | } | ||
2392 | module_exit(max98095_exit); | ||
2393 | |||
2394 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); | ||
2395 | MODULE_AUTHOR("Peter Hsiang"); | ||
2396 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/max98095.h b/sound/soc/codecs/max98095.h new file mode 100644 index 000000000000..891584a0eb03 --- /dev/null +++ b/sound/soc/codecs/max98095.h | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * max98095.h -- MAX98095 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Maxim Integrated Products | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _MAX98095_H | ||
12 | #define _MAX98095_H | ||
13 | |||
14 | /* | ||
15 | * MAX98095 Registers Definition | ||
16 | */ | ||
17 | |||
18 | #define M98095_000_HOST_DATA 0x00 | ||
19 | #define M98095_001_HOST_INT_STS 0x01 | ||
20 | #define M98095_002_HOST_RSP_STS 0x02 | ||
21 | #define M98095_003_HOST_CMD_STS 0x03 | ||
22 | #define M98095_004_CODEC_STS 0x04 | ||
23 | #define M98095_005_DAI1_ALC_STS 0x05 | ||
24 | #define M98095_006_DAI2_ALC_STS 0x06 | ||
25 | #define M98095_007_JACK_AUTO_STS 0x07 | ||
26 | #define M98095_008_JACK_MANUAL_STS 0x08 | ||
27 | #define M98095_009_JACK_VBAT_STS 0x09 | ||
28 | #define M98095_00A_ACC_ADC_STS 0x0A | ||
29 | #define M98095_00B_MIC_NG_AGC_STS 0x0B | ||
30 | #define M98095_00C_SPK_L_VOLT_STS 0x0C | ||
31 | #define M98095_00D_SPK_R_VOLT_STS 0x0D | ||
32 | #define M98095_00E_TEMP_SENSOR_STS 0x0E | ||
33 | #define M98095_00F_HOST_CFG 0x0F | ||
34 | #define M98095_010_HOST_INT_CFG 0x10 | ||
35 | #define M98095_011_HOST_INT_EN 0x11 | ||
36 | #define M98095_012_CODEC_INT_EN 0x12 | ||
37 | #define M98095_013_JACK_INT_EN 0x13 | ||
38 | #define M98095_014_JACK_INT_EN 0x14 | ||
39 | #define M98095_015_DEC 0x15 | ||
40 | #define M98095_016_RESERVED 0x16 | ||
41 | #define M98095_017_RESERVED 0x17 | ||
42 | #define M98095_018_KEYCODE3 0x18 | ||
43 | #define M98095_019_KEYCODE2 0x19 | ||
44 | #define M98095_01A_KEYCODE1 0x1A | ||
45 | #define M98095_01B_KEYCODE0 0x1B | ||
46 | #define M98095_01C_OEMCODE1 0x1C | ||
47 | #define M98095_01D_OEMCODE0 0x1D | ||
48 | #define M98095_01E_XCFG1 0x1E | ||
49 | #define M98095_01F_XCFG2 0x1F | ||
50 | #define M98095_020_XCFG3 0x20 | ||
51 | #define M98095_021_XCFG4 0x21 | ||
52 | #define M98095_022_XCFG5 0x22 | ||
53 | #define M98095_023_XCFG6 0x23 | ||
54 | #define M98095_024_XGPIO 0x24 | ||
55 | #define M98095_025_XCLKCFG 0x25 | ||
56 | #define M98095_026_SYS_CLK 0x26 | ||
57 | #define M98095_027_DAI1_CLKMODE 0x27 | ||
58 | #define M98095_028_DAI1_CLKCFG_HI 0x28 | ||
59 | #define M98095_029_DAI1_CLKCFG_LO 0x29 | ||
60 | #define M98095_02A_DAI1_FORMAT 0x2A | ||
61 | #define M98095_02B_DAI1_CLOCK 0x2B | ||
62 | #define M98095_02C_DAI1_IOCFG 0x2C | ||
63 | #define M98095_02D_DAI1_TDM 0x2D | ||
64 | #define M98095_02E_DAI1_FILTERS 0x2E | ||
65 | #define M98095_02F_DAI1_LVL1 0x2F | ||
66 | #define M98095_030_DAI1_LVL2 0x30 | ||
67 | #define M98095_031_DAI2_CLKMODE 0x31 | ||
68 | #define M98095_032_DAI2_CLKCFG_HI 0x32 | ||
69 | #define M98095_033_DAI2_CLKCFG_LO 0x33 | ||
70 | #define M98095_034_DAI2_FORMAT 0x34 | ||
71 | #define M98095_035_DAI2_CLOCK 0x35 | ||
72 | #define M98095_036_DAI2_IOCFG 0x36 | ||
73 | #define M98095_037_DAI2_TDM 0x37 | ||
74 | #define M98095_038_DAI2_FILTERS 0x38 | ||
75 | #define M98095_039_DAI2_LVL1 0x39 | ||
76 | #define M98095_03A_DAI2_LVL2 0x3A | ||
77 | #define M98095_03B_DAI3_CLKMODE 0x3B | ||
78 | #define M98095_03C_DAI3_CLKCFG_HI 0x3C | ||
79 | #define M98095_03D_DAI3_CLKCFG_LO 0x3D | ||
80 | #define M98095_03E_DAI3_FORMAT 0x3E | ||
81 | #define M98095_03F_DAI3_CLOCK 0x3F | ||
82 | #define M98095_040_DAI3_IOCFG 0x40 | ||
83 | #define M98095_041_DAI3_TDM 0x41 | ||
84 | #define M98095_042_DAI3_FILTERS 0x42 | ||
85 | #define M98095_043_DAI3_LVL1 0x43 | ||
86 | #define M98095_044_DAI3_LVL2 0x44 | ||
87 | #define M98095_045_CFG_DSP 0x45 | ||
88 | #define M98095_046_DAC_CTRL1 0x46 | ||
89 | #define M98095_047_DAC_CTRL2 0x47 | ||
90 | #define M98095_048_MIX_DAC_LR 0x48 | ||
91 | #define M98095_049_MIX_DAC_M 0x49 | ||
92 | #define M98095_04A_MIX_ADC_LEFT 0x4A | ||
93 | #define M98095_04B_MIX_ADC_RIGHT 0x4B | ||
94 | #define M98095_04C_MIX_HP_LEFT 0x4C | ||
95 | #define M98095_04D_MIX_HP_RIGHT 0x4D | ||
96 | #define M98095_04E_CFG_HP 0x4E | ||
97 | #define M98095_04F_MIX_RCV 0x4F | ||
98 | #define M98095_050_MIX_SPK_LEFT 0x50 | ||
99 | #define M98095_051_MIX_SPK_RIGHT 0x51 | ||
100 | #define M98095_052_MIX_SPK_CFG 0x52 | ||
101 | #define M98095_053_MIX_LINEOUT1 0x53 | ||
102 | #define M98095_054_MIX_LINEOUT2 0x54 | ||
103 | #define M98095_055_MIX_LINEOUT_CFG 0x55 | ||
104 | #define M98095_056_LVL_SIDETONE_DAI12 0x56 | ||
105 | #define M98095_057_LVL_SIDETONE_DAI3 0x57 | ||
106 | #define M98095_058_LVL_DAI1_PLAY 0x58 | ||
107 | #define M98095_059_LVL_DAI1_EQ 0x59 | ||
108 | #define M98095_05A_LVL_DAI2_PLAY 0x5A | ||
109 | #define M98095_05B_LVL_DAI2_EQ 0x5B | ||
110 | #define M98095_05C_LVL_DAI3_PLAY 0x5C | ||
111 | #define M98095_05D_LVL_ADC_L 0x5D | ||
112 | #define M98095_05E_LVL_ADC_R 0x5E | ||
113 | #define M98095_05F_LVL_MIC1 0x5F | ||
114 | #define M98095_060_LVL_MIC2 0x60 | ||
115 | #define M98095_061_LVL_LINEIN 0x61 | ||
116 | #define M98095_062_LVL_LINEOUT1 0x62 | ||
117 | #define M98095_063_LVL_LINEOUT2 0x63 | ||
118 | #define M98095_064_LVL_HP_L 0x64 | ||
119 | #define M98095_065_LVL_HP_R 0x65 | ||
120 | #define M98095_066_LVL_RCV 0x66 | ||
121 | #define M98095_067_LVL_SPK_L 0x67 | ||
122 | #define M98095_068_LVL_SPK_R 0x68 | ||
123 | #define M98095_069_MICAGC_CFG 0x69 | ||
124 | #define M98095_06A_MICAGC_THRESH 0x6A | ||
125 | #define M98095_06B_SPK_NOISEGATE 0x6B | ||
126 | #define M98095_06C_DAI1_ALC1_TIME 0x6C | ||
127 | #define M98095_06D_DAI1_ALC1_COMP 0x6D | ||
128 | #define M98095_06E_DAI1_ALC1_EXPN 0x6E | ||
129 | #define M98095_06F_DAI1_ALC1_GAIN 0x6F | ||
130 | #define M98095_070_DAI1_ALC2_TIME 0x70 | ||
131 | #define M98095_071_DAI1_ALC2_COMP 0x71 | ||
132 | #define M98095_072_DAI1_ALC2_EXPN 0x72 | ||
133 | #define M98095_073_DAI1_ALC2_GAIN 0x73 | ||
134 | #define M98095_074_DAI1_ALC3_TIME 0x74 | ||
135 | #define M98095_075_DAI1_ALC3_COMP 0x75 | ||
136 | #define M98095_076_DAI1_ALC3_EXPN 0x76 | ||
137 | #define M98095_077_DAI1_ALC3_GAIN 0x77 | ||
138 | #define M98095_078_DAI2_ALC1_TIME 0x78 | ||
139 | #define M98095_079_DAI2_ALC1_COMP 0x79 | ||
140 | #define M98095_07A_DAI2_ALC1_EXPN 0x7A | ||
141 | #define M98095_07B_DAI2_ALC1_GAIN 0x7B | ||
142 | #define M98095_07C_DAI2_ALC2_TIME 0x7C | ||
143 | #define M98095_07D_DAI2_ALC2_COMP 0x7D | ||
144 | #define M98095_07E_DAI2_ALC2_EXPN 0x7E | ||
145 | #define M98095_07F_DAI2_ALC2_GAIN 0x7F | ||
146 | #define M98095_080_DAI2_ALC3_TIME 0x80 | ||
147 | #define M98095_081_DAI2_ALC3_COMP 0x81 | ||
148 | #define M98095_082_DAI2_ALC3_EXPN 0x82 | ||
149 | #define M98095_083_DAI2_ALC3_GAIN 0x83 | ||
150 | #define M98095_084_HP_NOISE_GATE 0x84 | ||
151 | #define M98095_085_AUX_ADC 0x85 | ||
152 | #define M98095_086_CFG_LINE 0x86 | ||
153 | #define M98095_087_CFG_MIC 0x87 | ||
154 | #define M98095_088_CFG_LEVEL 0x88 | ||
155 | #define M98095_089_JACK_DET_AUTO 0x89 | ||
156 | #define M98095_08A_JACK_DET_MANUAL 0x8A | ||
157 | #define M98095_08B_JACK_KEYSCAN_DBC 0x8B | ||
158 | #define M98095_08C_JACK_KEYSCAN_DLY 0x8C | ||
159 | #define M98095_08D_JACK_KEY_THRESH 0x8D | ||
160 | #define M98095_08E_JACK_DC_SLEW 0x8E | ||
161 | #define M98095_08F_JACK_TEST_CFG 0x8F | ||
162 | #define M98095_090_PWR_EN_IN 0x90 | ||
163 | #define M98095_091_PWR_EN_OUT 0x91 | ||
164 | #define M98095_092_PWR_EN_OUT 0x92 | ||
165 | #define M98095_093_BIAS_CTRL 0x93 | ||
166 | #define M98095_094_PWR_DAC_21 0x94 | ||
167 | #define M98095_095_PWR_DAC_03 0x95 | ||
168 | #define M98095_096_PWR_DAC_CK 0x96 | ||
169 | #define M98095_097_PWR_SYS 0x97 | ||
170 | |||
171 | #define M98095_0FF_REV_ID 0xFF | ||
172 | |||
173 | #define M98095_REG_CNT (0xFF+1) | ||
174 | #define M98095_REG_MAX_CACHED 0X97 | ||
175 | |||
176 | /* MAX98095 Registers Bit Fields */ | ||
177 | |||
178 | /* M98095_00F_HOST_CFG */ | ||
179 | #define M98095_SEG (1<<0) | ||
180 | #define M98095_XTEN (1<<1) | ||
181 | #define M98095_MDLLEN (1<<2) | ||
182 | |||
183 | /* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ | ||
184 | #define M98095_CLKMODE_MASK 0xFF | ||
185 | |||
186 | /* M98095_02A_DAI1_FORMAT, M98095_034_DAI2_FORMAT, M98095_03E_DAI3_FORMAT */ | ||
187 | #define M98095_DAI_MAS (1<<7) | ||
188 | #define M98095_DAI_WCI (1<<6) | ||
189 | #define M98095_DAI_BCI (1<<5) | ||
190 | #define M98095_DAI_DLY (1<<4) | ||
191 | #define M98095_DAI_TDM (1<<2) | ||
192 | #define M98095_DAI_FSW (1<<1) | ||
193 | #define M98095_DAI_WS (1<<0) | ||
194 | |||
195 | /* M98095_02B_DAI1_CLOCK, M98095_035_DAI2_CLOCK, M98095_03F_DAI3_CLOCK */ | ||
196 | #define M98095_DAI_BSEL64 (1<<0) | ||
197 | #define M98095_DAI_DOSR_DIV2 (0<<5) | ||
198 | #define M98095_DAI_DOSR_DIV4 (1<<5) | ||
199 | |||
200 | /* M98095_02C_DAI1_IOCFG, M98095_036_DAI2_IOCFG, M98095_040_DAI3_IOCFG */ | ||
201 | #define M98095_S1NORMAL (1<<6) | ||
202 | #define M98095_S2NORMAL (2<<6) | ||
203 | #define M98095_S3NORMAL (3<<6) | ||
204 | #define M98095_SDATA (3<<0) | ||
205 | |||
206 | /* M98095_02E_DAI1_FILTERS, M98095_038_DAI2_FILTERS, M98095_042_DAI3_FILTERS */ | ||
207 | #define M98095_DAI_DHF (1<<3) | ||
208 | |||
209 | /* M98095_045_DSP_CFG */ | ||
210 | #define M98095_DSPNORMAL (5<<4) | ||
211 | |||
212 | /* M98095_048_MIX_DAC_LR */ | ||
213 | #define M98095_DAI1L_TO_DACR (1<<7) | ||
214 | #define M98095_DAI1R_TO_DACR (1<<6) | ||
215 | #define M98095_DAI2M_TO_DACR (1<<5) | ||
216 | #define M98095_DAI1L_TO_DACL (1<<3) | ||
217 | #define M98095_DAI1R_TO_DACL (1<<2) | ||
218 | #define M98095_DAI2M_TO_DACL (1<<1) | ||
219 | #define M98095_DAI3M_TO_DACL (1<<0) | ||
220 | |||
221 | /* M98095_049_MIX_DAC_M */ | ||
222 | #define M98095_DAI1L_TO_DACM (1<<3) | ||
223 | #define M98095_DAI1R_TO_DACM (1<<2) | ||
224 | #define M98095_DAI2M_TO_DACM (1<<1) | ||
225 | #define M98095_DAI3M_TO_DACM (1<<0) | ||
226 | |||
227 | /* M98095_04E_MIX_HP_CFG */ | ||
228 | #define M98095_HPNORMAL (3<<4) | ||
229 | |||
230 | /* M98095_05F_LVL_MIC1, M98095_060_LVL_MIC2 */ | ||
231 | #define M98095_MICPRE_MASK (3<<5) | ||
232 | #define M98095_MICPRE_SHIFT 5 | ||
233 | |||
234 | /* M98095_064_LVL_HP_L, M98095_065_LVL_HP_R */ | ||
235 | #define M98095_HP_MUTE (1<<7) | ||
236 | |||
237 | /* M98095_066_LVL_RCV */ | ||
238 | #define M98095_REC_MUTE (1<<7) | ||
239 | |||
240 | /* M98095_067_LVL_SPK_L, M98095_068_LVL_SPK_R */ | ||
241 | #define M98095_SP_MUTE (1<<7) | ||
242 | |||
243 | /* M98095_087_CFG_MIC */ | ||
244 | #define M98095_MICSEL_MASK (3<<0) | ||
245 | #define M98095_DIGMIC_L (1<<2) | ||
246 | #define M98095_DIGMIC_R (1<<3) | ||
247 | #define M98095_DIGMIC2L (1<<4) | ||
248 | #define M98095_DIGMIC2R (1<<5) | ||
249 | |||
250 | /* M98095_088_CFG_LEVEL */ | ||
251 | #define M98095_VSEN (1<<6) | ||
252 | #define M98095_ZDEN (1<<5) | ||
253 | #define M98095_BQ2EN (1<<3) | ||
254 | #define M98095_BQ1EN (1<<2) | ||
255 | #define M98095_EQ2EN (1<<1) | ||
256 | #define M98095_EQ1EN (1<<0) | ||
257 | |||
258 | /* M98095_090_PWR_EN_IN */ | ||
259 | #define M98095_INEN (1<<7) | ||
260 | #define M98095_MB2EN (1<<3) | ||
261 | #define M98095_MB1EN (1<<2) | ||
262 | #define M98095_MBEN (3<<2) | ||
263 | #define M98095_ADREN (1<<1) | ||
264 | #define M98095_ADLEN (1<<0) | ||
265 | |||
266 | /* M98095_091_PWR_EN_OUT */ | ||
267 | #define M98095_HPLEN (1<<7) | ||
268 | #define M98095_HPREN (1<<6) | ||
269 | #define M98095_SPLEN (1<<5) | ||
270 | #define M98095_SPREN (1<<4) | ||
271 | #define M98095_RECEN (1<<3) | ||
272 | #define M98095_DALEN (1<<1) | ||
273 | #define M98095_DAREN (1<<0) | ||
274 | |||
275 | /* M98095_092_PWR_EN_OUT */ | ||
276 | #define M98095_SPK_FIXEDSPECTRUM (0<<4) | ||
277 | #define M98095_SPK_SPREADSPECTRUM (1<<4) | ||
278 | |||
279 | /* M98095_097_PWR_SYS */ | ||
280 | #define M98095_SHDNRUN (1<<7) | ||
281 | #define M98095_PERFMODE (1<<3) | ||
282 | #define M98095_HPPLYBACK (1<<2) | ||
283 | #define M98095_PWRSV8K (1<<1) | ||
284 | #define M98095_PWRSV (1<<0) | ||
285 | |||
286 | #define M98095_COEFS_PER_BAND 5 | ||
287 | |||
288 | #define M98095_BYTE1(w) ((w >> 8) & 0xff) | ||
289 | #define M98095_BYTE0(w) (w & 0xff) | ||
290 | |||
291 | /* Equalizer filter coefficients */ | ||
292 | #define M98095_110_DAI1_EQ_BASE 0x10 | ||
293 | #define M98095_142_DAI2_EQ_BASE 0x42 | ||
294 | |||
295 | /* Biquad filter coefficients */ | ||
296 | #define M98095_174_DAI1_BQ_BASE 0x74 | ||
297 | #define M98095_17E_DAI2_BQ_BASE 0x7E | ||
298 | |||
299 | #endif | ||
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 4d9fb279e146..84ffdebb8a8b 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -827,8 +827,6 @@ EXPORT_SYMBOL_GPL(sn95031_jack_detection); | |||
827 | /* codec registration */ | 827 | /* codec registration */ |
828 | static int sn95031_codec_probe(struct snd_soc_codec *codec) | 828 | static int sn95031_codec_probe(struct snd_soc_codec *codec) |
829 | { | 829 | { |
830 | int ret; | ||
831 | |||
832 | pr_debug("codec_probe called\n"); | 830 | pr_debug("codec_probe called\n"); |
833 | 831 | ||
834 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 832 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
@@ -879,16 +877,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) | |||
879 | snd_soc_add_controls(codec, sn95031_snd_controls, | 877 | snd_soc_add_controls(codec, sn95031_snd_controls, |
880 | ARRAY_SIZE(sn95031_snd_controls)); | 878 | ARRAY_SIZE(sn95031_snd_controls)); |
881 | 879 | ||
882 | ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets, | 880 | return 0; |
883 | ARRAY_SIZE(sn95031_dapm_widgets)); | ||
884 | if (ret) | ||
885 | pr_err("soc_dapm_new_control failed %d", ret); | ||
886 | ret = snd_soc_dapm_add_routes(&codec->dapm, sn95031_audio_map, | ||
887 | ARRAY_SIZE(sn95031_audio_map)); | ||
888 | if (ret) | ||
889 | pr_err("soc_dapm_add_routes failed %d", ret); | ||
890 | |||
891 | return ret; | ||
892 | } | 881 | } |
893 | 882 | ||
894 | static int sn95031_codec_remove(struct snd_soc_codec *codec) | 883 | static int sn95031_codec_remove(struct snd_soc_codec *codec) |
@@ -905,6 +894,10 @@ struct snd_soc_codec_driver sn95031_codec = { | |||
905 | .read = sn95031_read, | 894 | .read = sn95031_read, |
906 | .write = sn95031_write, | 895 | .write = sn95031_write, |
907 | .set_bias_level = sn95031_set_vaud_bias, | 896 | .set_bias_level = sn95031_set_vaud_bias, |
897 | .dapm_widgets = sn95031_dapm_widgets, | ||
898 | .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), | ||
899 | .dapm_routes = sn95031_audio_map, | ||
900 | .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), | ||
908 | }; | 901 | }; |
909 | 902 | ||
910 | static int __devinit sn95031_device_probe(struct platform_device *pdev) | 903 | static int __devinit sn95031_device_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c index 4c32b54913ad..6a1a7e705cd7 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transciever.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | #define DRV_NAME "spdif-dit" |
25 | 25 | ||
26 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 |
27 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 27 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
@@ -56,7 +56,7 @@ static struct platform_driver spdif_dit_driver = { | |||
56 | .probe = spdif_dit_probe, | 56 | .probe = spdif_dit_probe, |
57 | .remove = spdif_dit_remove, | 57 | .remove = spdif_dit_remove, |
58 | .driver = { | 58 | .driver = { |
59 | .name = "spdif-dit", | 59 | .name = DRV_NAME, |
60 | .owner = THIS_MODULE, | 60 | .owner = THIS_MODULE, |
61 | }, | 61 | }, |
62 | }; | 62 | }; |
@@ -74,3 +74,7 @@ static void __exit dit_exit(void) | |||
74 | module_init(dit_modinit); | 74 | module_init(dit_modinit); |
75 | module_exit(dit_exit); | 75 | module_exit(dit_exit); |
76 | 76 | ||
77 | MODULE_AUTHOR("Steve Chen <schen@mvista.com>"); | ||
78 | MODULE_DESCRIPTION("SPDIF dummy codec driver"); | ||
79 | MODULE_LICENSE("GPL"); | ||
80 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 2727befd158e..84f4ad568556 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/pm.h> | 33 | #include <linux/pm.h> |
34 | #include <linux/i2c.h> | 34 | #include <linux/i2c.h> |
35 | #include <linux/spi/spi.h> | ||
35 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <sound/core.h> | 38 | #include <sound/core.h> |
@@ -39,18 +40,25 @@ | |||
39 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
40 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
41 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
43 | #include <sound/tlv.h> | ||
42 | 44 | ||
43 | #include "ssm2602.h" | 45 | #include "ssm2602.h" |
44 | 46 | ||
45 | #define SSM2602_VERSION "0.1" | 47 | #define SSM2602_VERSION "0.1" |
46 | 48 | ||
49 | enum ssm2602_type { | ||
50 | SSM2602, | ||
51 | SSM2604, | ||
52 | }; | ||
53 | |||
47 | /* codec private data */ | 54 | /* codec private data */ |
48 | struct ssm2602_priv { | 55 | struct ssm2602_priv { |
49 | unsigned int sysclk; | 56 | unsigned int sysclk; |
50 | enum snd_soc_control_type control_type; | 57 | enum snd_soc_control_type control_type; |
51 | void *control_data; | ||
52 | struct snd_pcm_substream *master_substream; | 58 | struct snd_pcm_substream *master_substream; |
53 | struct snd_pcm_substream *slave_substream; | 59 | struct snd_pcm_substream *slave_substream; |
60 | |||
61 | enum ssm2602_type type; | ||
54 | }; | 62 | }; |
55 | 63 | ||
56 | /* | 64 | /* |
@@ -60,60 +68,12 @@ struct ssm2602_priv { | |||
60 | * There is no point in caching the reset register | 68 | * There is no point in caching the reset register |
61 | */ | 69 | */ |
62 | static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { | 70 | static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { |
63 | 0x0017, 0x0017, 0x0079, 0x0079, | 71 | 0x0097, 0x0097, 0x0079, 0x0079, |
64 | 0x0000, 0x0000, 0x0000, 0x000a, | 72 | 0x000a, 0x0008, 0x009f, 0x000a, |
65 | 0x0000, 0x0000 | 73 | 0x0000, 0x0000 |
66 | }; | 74 | }; |
67 | 75 | ||
68 | /* | 76 | #define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0) |
69 | * read ssm2602 register cache | ||
70 | */ | ||
71 | static inline unsigned int ssm2602_read_reg_cache(struct snd_soc_codec *codec, | ||
72 | unsigned int reg) | ||
73 | { | ||
74 | u16 *cache = codec->reg_cache; | ||
75 | if (reg == SSM2602_RESET) | ||
76 | return 0; | ||
77 | if (reg >= SSM2602_CACHEREGNUM) | ||
78 | return -1; | ||
79 | return cache[reg]; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * write ssm2602 register cache | ||
84 | */ | ||
85 | static inline void ssm2602_write_reg_cache(struct snd_soc_codec *codec, | ||
86 | u16 reg, unsigned int value) | ||
87 | { | ||
88 | u16 *cache = codec->reg_cache; | ||
89 | if (reg >= SSM2602_CACHEREGNUM) | ||
90 | return; | ||
91 | cache[reg] = value; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * write to the ssm2602 register space | ||
96 | */ | ||
97 | static int ssm2602_write(struct snd_soc_codec *codec, unsigned int reg, | ||
98 | unsigned int value) | ||
99 | { | ||
100 | u8 data[2]; | ||
101 | |||
102 | /* data is | ||
103 | * D15..D9 ssm2602 register offset | ||
104 | * D8...D0 register data | ||
105 | */ | ||
106 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
107 | data[1] = value & 0x00ff; | ||
108 | |||
109 | ssm2602_write_reg_cache(codec, reg, value); | ||
110 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
111 | return 0; | ||
112 | else | ||
113 | return -EIO; | ||
114 | } | ||
115 | |||
116 | #define ssm2602_reset(c) ssm2602_write(c, SSM2602_RESET, 0) | ||
117 | 77 | ||
118 | /*Appending several "None"s just for OSS mixer use*/ | 78 | /*Appending several "None"s just for OSS mixer use*/ |
119 | static const char *ssm2602_input_select[] = { | 79 | static const char *ssm2602_input_select[] = { |
@@ -128,174 +88,187 @@ static const struct soc_enum ssm2602_enum[] = { | |||
128 | SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), | 88 | SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), |
129 | }; | 89 | }; |
130 | 90 | ||
131 | static const struct snd_kcontrol_new ssm2602_snd_controls[] = { | 91 | static const unsigned int ssm260x_outmix_tlv[] = { |
92 | TLV_DB_RANGE_HEAD(2), | ||
93 | 0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | ||
94 | 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0), | ||
95 | }; | ||
132 | 96 | ||
133 | SOC_DOUBLE_R("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V, | 97 | static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0); |
134 | 0, 127, 0), | 98 | static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0); |
135 | SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V, | ||
136 | 7, 1, 0), | ||
137 | 99 | ||
138 | SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0), | 100 | static const struct snd_kcontrol_new ssm260x_snd_controls[] = { |
101 | SOC_DOUBLE_R_TLV("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 45, 0, | ||
102 | ssm260x_inpga_tlv), | ||
139 | SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), | 103 | SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), |
140 | 104 | ||
141 | SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), | ||
142 | SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0), | ||
143 | SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), | ||
144 | |||
145 | SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), | ||
146 | |||
147 | SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1), | 105 | SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1), |
148 | SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0), | 106 | SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0), |
149 | 107 | ||
150 | SOC_ENUM("Capture Source", ssm2602_enum[0]), | ||
151 | |||
152 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), | 108 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), |
153 | }; | 109 | }; |
154 | 110 | ||
111 | static const struct snd_kcontrol_new ssm2602_snd_controls[] = { | ||
112 | SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V, | ||
113 | 0, 127, 0, ssm260x_outmix_tlv), | ||
114 | SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V, | ||
115 | 7, 1, 0), | ||
116 | SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1, | ||
117 | ssm260x_sidetone_tlv), | ||
118 | |||
119 | SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), | ||
120 | SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0), | ||
121 | SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), | ||
122 | }; | ||
123 | |||
155 | /* Output Mixer */ | 124 | /* Output Mixer */ |
156 | static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { | 125 | static const struct snd_kcontrol_new ssm260x_output_mixer_controls[] = { |
157 | SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), | 126 | SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), |
158 | SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0), | ||
159 | SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0), | 127 | SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0), |
128 | SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0), | ||
160 | }; | 129 | }; |
161 | 130 | ||
162 | /* Input mux */ | 131 | /* Input mux */ |
163 | static const struct snd_kcontrol_new ssm2602_input_mux_controls = | 132 | static const struct snd_kcontrol_new ssm2602_input_mux_controls = |
164 | SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]); | 133 | SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]); |
165 | 134 | ||
166 | static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = { | 135 | static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = { |
167 | SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1, | ||
168 | &ssm2602_output_mixer_controls[0], | ||
169 | ARRAY_SIZE(ssm2602_output_mixer_controls)), | ||
170 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1), | 136 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1), |
137 | SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1), | ||
138 | SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0), | ||
139 | |||
140 | SND_SOC_DAPM_SUPPLY("Digital Core Power", SSM2602_ACTIVE, 0, 0, NULL, 0), | ||
141 | |||
171 | SND_SOC_DAPM_OUTPUT("LOUT"), | 142 | SND_SOC_DAPM_OUTPUT("LOUT"), |
172 | SND_SOC_DAPM_OUTPUT("LHPOUT"), | ||
173 | SND_SOC_DAPM_OUTPUT("ROUT"), | 143 | SND_SOC_DAPM_OUTPUT("ROUT"), |
174 | SND_SOC_DAPM_OUTPUT("RHPOUT"), | 144 | SND_SOC_DAPM_INPUT("RLINEIN"), |
175 | SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1), | 145 | SND_SOC_DAPM_INPUT("LLINEIN"), |
146 | }; | ||
147 | |||
148 | static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = { | ||
149 | SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1, | ||
150 | ssm260x_output_mixer_controls, | ||
151 | ARRAY_SIZE(ssm260x_output_mixer_controls)), | ||
152 | |||
176 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls), | 153 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls), |
177 | SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0), | ||
178 | SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1), | 154 | SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1), |
155 | |||
156 | SND_SOC_DAPM_OUTPUT("LHPOUT"), | ||
157 | SND_SOC_DAPM_OUTPUT("RHPOUT"), | ||
179 | SND_SOC_DAPM_INPUT("MICIN"), | 158 | SND_SOC_DAPM_INPUT("MICIN"), |
180 | SND_SOC_DAPM_INPUT("RLINEIN"), | ||
181 | SND_SOC_DAPM_INPUT("LLINEIN"), | ||
182 | }; | 159 | }; |
183 | 160 | ||
184 | static const struct snd_soc_dapm_route audio_conn[] = { | 161 | static const struct snd_soc_dapm_widget ssm2604_dapm_widgets[] = { |
185 | /* output mixer */ | 162 | SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, |
163 | ssm260x_output_mixer_controls, | ||
164 | ARRAY_SIZE(ssm260x_output_mixer_controls) - 1), /* Last element is the mic */ | ||
165 | }; | ||
166 | |||
167 | static const struct snd_soc_dapm_route ssm260x_routes[] = { | ||
168 | {"DAC", NULL, "Digital Core Power"}, | ||
169 | {"ADC", NULL, "Digital Core Power"}, | ||
170 | |||
186 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, | 171 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, |
187 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, | 172 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, |
173 | |||
174 | {"ROUT", NULL, "Output Mixer"}, | ||
175 | {"LOUT", NULL, "Output Mixer"}, | ||
176 | |||
177 | {"Line Input", NULL, "LLINEIN"}, | ||
178 | {"Line Input", NULL, "RLINEIN"}, | ||
179 | }; | ||
180 | |||
181 | static const struct snd_soc_dapm_route ssm2602_routes[] = { | ||
188 | {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, | 182 | {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, |
189 | 183 | ||
190 | /* outputs */ | ||
191 | {"RHPOUT", NULL, "Output Mixer"}, | 184 | {"RHPOUT", NULL, "Output Mixer"}, |
192 | {"ROUT", NULL, "Output Mixer"}, | ||
193 | {"LHPOUT", NULL, "Output Mixer"}, | 185 | {"LHPOUT", NULL, "Output Mixer"}, |
194 | {"LOUT", NULL, "Output Mixer"}, | ||
195 | 186 | ||
196 | /* input mux */ | ||
197 | {"Input Mux", "Line", "Line Input"}, | 187 | {"Input Mux", "Line", "Line Input"}, |
198 | {"Input Mux", "Mic", "Mic Bias"}, | 188 | {"Input Mux", "Mic", "Mic Bias"}, |
199 | {"ADC", NULL, "Input Mux"}, | 189 | {"ADC", NULL, "Input Mux"}, |
200 | 190 | ||
201 | /* inputs */ | ||
202 | {"Line Input", NULL, "LLINEIN"}, | ||
203 | {"Line Input", NULL, "RLINEIN"}, | ||
204 | {"Mic Bias", NULL, "MICIN"}, | 191 | {"Mic Bias", NULL, "MICIN"}, |
205 | }; | 192 | }; |
206 | 193 | ||
207 | static int ssm2602_add_widgets(struct snd_soc_codec *codec) | 194 | static const struct snd_soc_dapm_route ssm2604_routes[] = { |
208 | { | 195 | {"ADC", NULL, "Line Input"}, |
209 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 196 | }; |
210 | |||
211 | snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets, | ||
212 | ARRAY_SIZE(ssm2602_dapm_widgets)); | ||
213 | snd_soc_dapm_add_routes(dapm, audio_conn, ARRAY_SIZE(audio_conn)); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | 197 | ||
218 | struct _coeff_div { | 198 | struct ssm2602_coeff { |
219 | u32 mclk; | 199 | u32 mclk; |
220 | u32 rate; | 200 | u32 rate; |
221 | u16 fs; | 201 | u8 srate; |
222 | u8 sr:4; | ||
223 | u8 bosr:1; | ||
224 | u8 usb:1; | ||
225 | }; | 202 | }; |
226 | 203 | ||
227 | /* codec mclk clock divider coefficients */ | 204 | #define SSM2602_COEFF_SRATE(sr, bosr, usb) (((sr) << 2) | ((bosr) << 1) | (usb)) |
228 | static const struct _coeff_div coeff_div[] = { | 205 | |
206 | /* codec mclk clock coefficients */ | ||
207 | static const struct ssm2602_coeff ssm2602_coeff_table[] = { | ||
229 | /* 48k */ | 208 | /* 48k */ |
230 | {12288000, 48000, 256, 0x0, 0x0, 0x0}, | 209 | {12288000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x0)}, |
231 | {18432000, 48000, 384, 0x0, 0x1, 0x0}, | 210 | {18432000, 48000, SSM2602_COEFF_SRATE(0x0, 0x1, 0x0)}, |
232 | {12000000, 48000, 250, 0x0, 0x0, 0x1}, | 211 | {12000000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x1)}, |
233 | 212 | ||
234 | /* 32k */ | 213 | /* 32k */ |
235 | {12288000, 32000, 384, 0x6, 0x0, 0x0}, | 214 | {12288000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x0)}, |
236 | {18432000, 32000, 576, 0x6, 0x1, 0x0}, | 215 | {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)}, |
237 | {12000000, 32000, 375, 0x6, 0x0, 0x1}, | 216 | {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)}, |
238 | 217 | ||
239 | /* 8k */ | 218 | /* 8k */ |
240 | {12288000, 8000, 1536, 0x3, 0x0, 0x0}, | 219 | {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)}, |
241 | {18432000, 8000, 2304, 0x3, 0x1, 0x0}, | 220 | {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)}, |
242 | {11289600, 8000, 1408, 0xb, 0x0, 0x0}, | 221 | {11289600, 8000, SSM2602_COEFF_SRATE(0xb, 0x0, 0x0)}, |
243 | {16934400, 8000, 2112, 0xb, 0x1, 0x0}, | 222 | {16934400, 8000, SSM2602_COEFF_SRATE(0xb, 0x1, 0x0)}, |
244 | {12000000, 8000, 1500, 0x3, 0x0, 0x1}, | 223 | {12000000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x1)}, |
245 | 224 | ||
246 | /* 96k */ | 225 | /* 96k */ |
247 | {12288000, 96000, 128, 0x7, 0x0, 0x0}, | 226 | {12288000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x0)}, |
248 | {18432000, 96000, 192, 0x7, 0x1, 0x0}, | 227 | {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, |
249 | {12000000, 96000, 125, 0x7, 0x0, 0x1}, | 228 | {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, |
250 | 229 | ||
251 | /* 44.1k */ | 230 | /* 44.1k */ |
252 | {11289600, 44100, 256, 0x8, 0x0, 0x0}, | 231 | {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, |
253 | {16934400, 44100, 384, 0x8, 0x1, 0x0}, | 232 | {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, |
254 | {12000000, 44100, 272, 0x8, 0x1, 0x1}, | 233 | {12000000, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x1)}, |
255 | 234 | ||
256 | /* 88.2k */ | 235 | /* 88.2k */ |
257 | {11289600, 88200, 128, 0xf, 0x0, 0x0}, | 236 | {11289600, 88200, SSM2602_COEFF_SRATE(0xf, 0x0, 0x0)}, |
258 | {16934400, 88200, 192, 0xf, 0x1, 0x0}, | 237 | {16934400, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x0)}, |
259 | {12000000, 88200, 136, 0xf, 0x1, 0x1}, | 238 | {12000000, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x1)}, |
260 | }; | 239 | }; |
261 | 240 | ||
262 | static inline int get_coeff(int mclk, int rate) | 241 | static inline int ssm2602_get_coeff(int mclk, int rate) |
263 | { | 242 | { |
264 | int i; | 243 | int i; |
265 | 244 | ||
266 | for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { | 245 | for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) { |
267 | if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) | 246 | if (ssm2602_coeff_table[i].rate == rate && |
268 | return i; | 247 | ssm2602_coeff_table[i].mclk == mclk) |
248 | return ssm2602_coeff_table[i].srate; | ||
269 | } | 249 | } |
270 | return i; | 250 | return -EINVAL; |
271 | } | 251 | } |
272 | 252 | ||
273 | static int ssm2602_hw_params(struct snd_pcm_substream *substream, | 253 | static int ssm2602_hw_params(struct snd_pcm_substream *substream, |
274 | struct snd_pcm_hw_params *params, | 254 | struct snd_pcm_hw_params *params, |
275 | struct snd_soc_dai *dai) | 255 | struct snd_soc_dai *dai) |
276 | { | 256 | { |
277 | u16 srate; | ||
278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 257 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
279 | struct snd_soc_codec *codec = rtd->codec; | 258 | struct snd_soc_codec *codec = rtd->codec; |
280 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 259 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
281 | struct i2c_client *i2c = codec->control_data; | 260 | u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3; |
282 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 261 | int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); |
283 | int i = get_coeff(ssm2602->sysclk, params_rate(params)); | ||
284 | 262 | ||
285 | if (substream == ssm2602->slave_substream) { | 263 | if (substream == ssm2602->slave_substream) { |
286 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | 264 | dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); |
287 | return 0; | 265 | return 0; |
288 | } | 266 | } |
289 | 267 | ||
290 | /*no match is found*/ | 268 | if (srate < 0) |
291 | if (i == ARRAY_SIZE(coeff_div)) | 269 | return srate; |
292 | return -EINVAL; | ||
293 | |||
294 | srate = (coeff_div[i].sr << 2) | | ||
295 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; | ||
296 | 270 | ||
297 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 271 | snd_soc_write(codec, SSM2602_SRATE, srate); |
298 | ssm2602_write(codec, SSM2602_SRATE, srate); | ||
299 | 272 | ||
300 | /* bit size */ | 273 | /* bit size */ |
301 | switch (params_format(params)) { | 274 | switch (params_format(params)) { |
@@ -311,8 +284,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
311 | iface |= 0x000c; | 284 | iface |= 0x000c; |
312 | break; | 285 | break; |
313 | } | 286 | } |
314 | ssm2602_write(codec, SSM2602_IFACE, iface); | 287 | snd_soc_write(codec, SSM2602_IFACE, iface); |
315 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); | ||
316 | return 0; | 288 | return 0; |
317 | } | 289 | } |
318 | 290 | ||
@@ -354,17 +326,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
354 | return 0; | 326 | return 0; |
355 | } | 327 | } |
356 | 328 | ||
357 | static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, | ||
358 | struct snd_soc_dai *dai) | ||
359 | { | ||
360 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
361 | struct snd_soc_codec *codec = rtd->codec; | ||
362 | /* set active */ | ||
363 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static void ssm2602_shutdown(struct snd_pcm_substream *substream, | 329 | static void ssm2602_shutdown(struct snd_pcm_substream *substream, |
369 | struct snd_soc_dai *dai) | 330 | struct snd_soc_dai *dai) |
370 | { | 331 | { |
@@ -372,25 +333,22 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, | |||
372 | struct snd_soc_codec *codec = rtd->codec; | 333 | struct snd_soc_codec *codec = rtd->codec; |
373 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 334 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
374 | 335 | ||
375 | /* deactivate */ | ||
376 | if (!codec->active) | ||
377 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | ||
378 | |||
379 | if (ssm2602->master_substream == substream) | 336 | if (ssm2602->master_substream == substream) |
380 | ssm2602->master_substream = ssm2602->slave_substream; | 337 | ssm2602->master_substream = ssm2602->slave_substream; |
381 | 338 | ||
382 | ssm2602->slave_substream = NULL; | 339 | ssm2602->slave_substream = NULL; |
383 | } | 340 | } |
384 | 341 | ||
342 | |||
385 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) | 343 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) |
386 | { | 344 | { |
387 | struct snd_soc_codec *codec = dai->codec; | 345 | struct snd_soc_codec *codec = dai->codec; |
388 | u16 mute_reg = ssm2602_read_reg_cache(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; | 346 | u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; |
389 | if (mute) | 347 | if (mute) |
390 | ssm2602_write(codec, SSM2602_APDIGI, | 348 | snd_soc_write(codec, SSM2602_APDIGI, |
391 | mute_reg | APDIGI_ENABLE_DAC_MUTE); | 349 | mute_reg | APDIGI_ENABLE_DAC_MUTE); |
392 | else | 350 | else |
393 | ssm2602_write(codec, SSM2602_APDIGI, mute_reg); | 351 | snd_soc_write(codec, SSM2602_APDIGI, mute_reg); |
394 | return 0; | 352 | return 0; |
395 | } | 353 | } |
396 | 354 | ||
@@ -466,30 +424,29 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
466 | } | 424 | } |
467 | 425 | ||
468 | /* set iface */ | 426 | /* set iface */ |
469 | ssm2602_write(codec, SSM2602_IFACE, iface); | 427 | snd_soc_write(codec, SSM2602_IFACE, iface); |
470 | return 0; | 428 | return 0; |
471 | } | 429 | } |
472 | 430 | ||
473 | static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | 431 | static int ssm2602_set_bias_level(struct snd_soc_codec *codec, |
474 | enum snd_soc_bias_level level) | 432 | enum snd_soc_bias_level level) |
475 | { | 433 | { |
476 | u16 reg = ssm2602_read_reg_cache(codec, SSM2602_PWR) & 0xff7f; | 434 | u16 reg = snd_soc_read(codec, SSM2602_PWR) & 0xff7f; |
477 | 435 | ||
478 | switch (level) { | 436 | switch (level) { |
479 | case SND_SOC_BIAS_ON: | 437 | case SND_SOC_BIAS_ON: |
480 | /* vref/mid, osc on, dac unmute */ | 438 | /* vref/mid, osc on, dac unmute */ |
481 | ssm2602_write(codec, SSM2602_PWR, reg); | 439 | snd_soc_write(codec, SSM2602_PWR, reg); |
482 | break; | 440 | break; |
483 | case SND_SOC_BIAS_PREPARE: | 441 | case SND_SOC_BIAS_PREPARE: |
484 | break; | 442 | break; |
485 | case SND_SOC_BIAS_STANDBY: | 443 | case SND_SOC_BIAS_STANDBY: |
486 | /* everything off except vref/vmid, */ | 444 | /* everything off except vref/vmid, */ |
487 | ssm2602_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); | 445 | snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); |
488 | break; | 446 | break; |
489 | case SND_SOC_BIAS_OFF: | 447 | case SND_SOC_BIAS_OFF: |
490 | /* everything off, dac mute, inactive */ | 448 | /* everything off, dac mute, inactive */ |
491 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 449 | snd_soc_write(codec, SSM2602_PWR, 0xffff); |
492 | ssm2602_write(codec, SSM2602_PWR, 0xffff); | ||
493 | break; | 450 | break; |
494 | 451 | ||
495 | } | 452 | } |
@@ -506,7 +463,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
506 | 463 | ||
507 | static struct snd_soc_dai_ops ssm2602_dai_ops = { | 464 | static struct snd_soc_dai_ops ssm2602_dai_ops = { |
508 | .startup = ssm2602_startup, | 465 | .startup = ssm2602_startup, |
509 | .prepare = ssm2602_pcm_prepare, | ||
510 | .hw_params = ssm2602_hw_params, | 466 | .hw_params = ssm2602_hw_params, |
511 | .shutdown = ssm2602_shutdown, | 467 | .shutdown = ssm2602_shutdown, |
512 | .digital_mute = ssm2602_mute, | 468 | .digital_mute = ssm2602_mute, |
@@ -539,50 +495,87 @@ static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state) | |||
539 | 495 | ||
540 | static int ssm2602_resume(struct snd_soc_codec *codec) | 496 | static int ssm2602_resume(struct snd_soc_codec *codec) |
541 | { | 497 | { |
542 | int i; | 498 | snd_soc_cache_sync(codec); |
543 | u8 data[2]; | 499 | |
544 | u16 *cache = codec->reg_cache; | ||
545 | |||
546 | /* Sync reg_cache with the hardware */ | ||
547 | for (i = 0; i < ARRAY_SIZE(ssm2602_reg); i++) { | ||
548 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | ||
549 | data[1] = cache[i] & 0x00ff; | ||
550 | codec->hw_write(codec->control_data, data, 2); | ||
551 | } | ||
552 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 500 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
501 | |||
553 | return 0; | 502 | return 0; |
554 | } | 503 | } |
555 | 504 | ||
556 | static int ssm2602_probe(struct snd_soc_codec *codec) | 505 | static int ssm2602_probe(struct snd_soc_codec *codec) |
557 | { | 506 | { |
507 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
508 | int ret, reg; | ||
509 | |||
510 | reg = snd_soc_read(codec, SSM2602_LOUT1V); | ||
511 | snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); | ||
512 | reg = snd_soc_read(codec, SSM2602_ROUT1V); | ||
513 | snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); | ||
514 | |||
515 | ret = snd_soc_add_controls(codec, ssm2602_snd_controls, | ||
516 | ARRAY_SIZE(ssm2602_snd_controls)); | ||
517 | if (ret) | ||
518 | return ret; | ||
519 | |||
520 | ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets, | ||
521 | ARRAY_SIZE(ssm2602_dapm_widgets)); | ||
522 | if (ret) | ||
523 | return ret; | ||
524 | |||
525 | return snd_soc_dapm_add_routes(dapm, ssm2602_routes, | ||
526 | ARRAY_SIZE(ssm2602_routes)); | ||
527 | } | ||
528 | |||
529 | static int ssm2604_probe(struct snd_soc_codec *codec) | ||
530 | { | ||
531 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
532 | int ret; | ||
533 | |||
534 | ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, | ||
535 | ARRAY_SIZE(ssm2604_dapm_widgets)); | ||
536 | if (ret) | ||
537 | return ret; | ||
538 | |||
539 | return snd_soc_dapm_add_routes(dapm, ssm2604_routes, | ||
540 | ARRAY_SIZE(ssm2604_routes)); | ||
541 | } | ||
542 | |||
543 | static int ssm260x_probe(struct snd_soc_codec *codec) | ||
544 | { | ||
558 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 545 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
559 | int ret = 0, reg; | 546 | int ret, reg; |
560 | 547 | ||
561 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); | 548 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); |
562 | 549 | ||
563 | codec->control_data = ssm2602->control_data; | 550 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type); |
551 | if (ret < 0) { | ||
552 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
553 | return ret; | ||
554 | } | ||
564 | 555 | ||
565 | ssm2602_reset(codec); | 556 | ret = ssm2602_reset(codec); |
557 | if (ret < 0) { | ||
558 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
559 | return ret; | ||
560 | } | ||
566 | 561 | ||
567 | /*power on device*/ | ||
568 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | ||
569 | /* set the update bits */ | 562 | /* set the update bits */ |
570 | reg = ssm2602_read_reg_cache(codec, SSM2602_LINVOL); | 563 | reg = snd_soc_read(codec, SSM2602_LINVOL); |
571 | ssm2602_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); | 564 | snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); |
572 | reg = ssm2602_read_reg_cache(codec, SSM2602_RINVOL); | 565 | reg = snd_soc_read(codec, SSM2602_RINVOL); |
573 | ssm2602_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); | 566 | snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); |
574 | reg = ssm2602_read_reg_cache(codec, SSM2602_LOUT1V); | ||
575 | ssm2602_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); | ||
576 | reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); | ||
577 | ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); | ||
578 | /*select Line in as default input*/ | 567 | /*select Line in as default input*/ |
579 | ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC | | 568 | snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | |
580 | APANA_ENABLE_MIC_BOOST); | 569 | APANA_ENABLE_MIC_BOOST); |
581 | ssm2602_write(codec, SSM2602_PWR, 0); | ||
582 | 570 | ||
583 | snd_soc_add_controls(codec, ssm2602_snd_controls, | 571 | switch (ssm2602->type) { |
584 | ARRAY_SIZE(ssm2602_snd_controls)); | 572 | case SSM2602: |
585 | ssm2602_add_widgets(codec); | 573 | ret = ssm2602_probe(codec); |
574 | break; | ||
575 | case SSM2604: | ||
576 | ret = ssm2604_probe(codec); | ||
577 | break; | ||
578 | } | ||
586 | 579 | ||
587 | return ret; | 580 | return ret; |
588 | } | 581 | } |
@@ -595,18 +588,61 @@ static int ssm2602_remove(struct snd_soc_codec *codec) | |||
595 | } | 588 | } |
596 | 589 | ||
597 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { | 590 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { |
598 | .probe = ssm2602_probe, | 591 | .probe = ssm260x_probe, |
599 | .remove = ssm2602_remove, | 592 | .remove = ssm2602_remove, |
600 | .suspend = ssm2602_suspend, | 593 | .suspend = ssm2602_suspend, |
601 | .resume = ssm2602_resume, | 594 | .resume = ssm2602_resume, |
602 | .read = ssm2602_read_reg_cache, | ||
603 | .write = ssm2602_write, | ||
604 | .set_bias_level = ssm2602_set_bias_level, | 595 | .set_bias_level = ssm2602_set_bias_level, |
605 | .reg_cache_size = sizeof(ssm2602_reg), | 596 | .reg_cache_size = ARRAY_SIZE(ssm2602_reg), |
606 | .reg_word_size = sizeof(u16), | 597 | .reg_word_size = sizeof(u16), |
607 | .reg_cache_default = ssm2602_reg, | 598 | .reg_cache_default = ssm2602_reg, |
599 | |||
600 | .controls = ssm260x_snd_controls, | ||
601 | .num_controls = ARRAY_SIZE(ssm260x_snd_controls), | ||
602 | .dapm_widgets = ssm260x_dapm_widgets, | ||
603 | .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), | ||
604 | .dapm_routes = ssm260x_routes, | ||
605 | .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), | ||
608 | }; | 606 | }; |
609 | 607 | ||
608 | #if defined(CONFIG_SPI_MASTER) | ||
609 | static int __devinit ssm2602_spi_probe(struct spi_device *spi) | ||
610 | { | ||
611 | struct ssm2602_priv *ssm2602; | ||
612 | int ret; | ||
613 | |||
614 | ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); | ||
615 | if (ssm2602 == NULL) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | spi_set_drvdata(spi, ssm2602); | ||
619 | ssm2602->control_type = SND_SOC_SPI; | ||
620 | ssm2602->type = SSM2602; | ||
621 | |||
622 | ret = snd_soc_register_codec(&spi->dev, | ||
623 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | ||
624 | if (ret < 0) | ||
625 | kfree(ssm2602); | ||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static int __devexit ssm2602_spi_remove(struct spi_device *spi) | ||
630 | { | ||
631 | snd_soc_unregister_codec(&spi->dev); | ||
632 | kfree(spi_get_drvdata(spi)); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static struct spi_driver ssm2602_spi_driver = { | ||
637 | .driver = { | ||
638 | .name = "ssm2602", | ||
639 | .owner = THIS_MODULE, | ||
640 | }, | ||
641 | .probe = ssm2602_spi_probe, | ||
642 | .remove = __devexit_p(ssm2602_spi_remove), | ||
643 | }; | ||
644 | #endif | ||
645 | |||
610 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 646 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
611 | /* | 647 | /* |
612 | * ssm2602 2 wire address is determined by GPIO5 | 648 | * ssm2602 2 wire address is determined by GPIO5 |
@@ -614,7 +650,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { | |||
614 | * low = 0x1a | 650 | * low = 0x1a |
615 | * high = 0x1b | 651 | * high = 0x1b |
616 | */ | 652 | */ |
617 | static int ssm2602_i2c_probe(struct i2c_client *i2c, | 653 | static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c, |
618 | const struct i2c_device_id *id) | 654 | const struct i2c_device_id *id) |
619 | { | 655 | { |
620 | struct ssm2602_priv *ssm2602; | 656 | struct ssm2602_priv *ssm2602; |
@@ -625,8 +661,8 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c, | |||
625 | return -ENOMEM; | 661 | return -ENOMEM; |
626 | 662 | ||
627 | i2c_set_clientdata(i2c, ssm2602); | 663 | i2c_set_clientdata(i2c, ssm2602); |
628 | ssm2602->control_data = i2c; | ||
629 | ssm2602->control_type = SND_SOC_I2C; | 664 | ssm2602->control_type = SND_SOC_I2C; |
665 | ssm2602->type = id->driver_data; | ||
630 | 666 | ||
631 | ret = snd_soc_register_codec(&i2c->dev, | 667 | ret = snd_soc_register_codec(&i2c->dev, |
632 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | 668 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); |
@@ -635,7 +671,7 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c, | |||
635 | return ret; | 671 | return ret; |
636 | } | 672 | } |
637 | 673 | ||
638 | static int ssm2602_i2c_remove(struct i2c_client *client) | 674 | static int __devexit ssm2602_i2c_remove(struct i2c_client *client) |
639 | { | 675 | { |
640 | snd_soc_unregister_codec(&client->dev); | 676 | snd_soc_unregister_codec(&client->dev); |
641 | kfree(i2c_get_clientdata(client)); | 677 | kfree(i2c_get_clientdata(client)); |
@@ -643,7 +679,9 @@ static int ssm2602_i2c_remove(struct i2c_client *client) | |||
643 | } | 679 | } |
644 | 680 | ||
645 | static const struct i2c_device_id ssm2602_i2c_id[] = { | 681 | static const struct i2c_device_id ssm2602_i2c_id[] = { |
646 | { "ssm2602", 0 }, | 682 | { "ssm2602", SSM2602 }, |
683 | { "ssm2603", SSM2602 }, | ||
684 | { "ssm2604", SSM2604 }, | ||
647 | { } | 685 | { } |
648 | }; | 686 | }; |
649 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | 687 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); |
@@ -651,11 +689,11 @@ MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | |||
651 | /* corgi i2c codec control layer */ | 689 | /* corgi i2c codec control layer */ |
652 | static struct i2c_driver ssm2602_i2c_driver = { | 690 | static struct i2c_driver ssm2602_i2c_driver = { |
653 | .driver = { | 691 | .driver = { |
654 | .name = "ssm2602-codec", | 692 | .name = "ssm2602", |
655 | .owner = THIS_MODULE, | 693 | .owner = THIS_MODULE, |
656 | }, | 694 | }, |
657 | .probe = ssm2602_i2c_probe, | 695 | .probe = ssm2602_i2c_probe, |
658 | .remove = ssm2602_i2c_remove, | 696 | .remove = __devexit_p(ssm2602_i2c_remove), |
659 | .id_table = ssm2602_i2c_id, | 697 | .id_table = ssm2602_i2c_id, |
660 | }; | 698 | }; |
661 | #endif | 699 | #endif |
@@ -664,25 +702,35 @@ static struct i2c_driver ssm2602_i2c_driver = { | |||
664 | static int __init ssm2602_modinit(void) | 702 | static int __init ssm2602_modinit(void) |
665 | { | 703 | { |
666 | int ret = 0; | 704 | int ret = 0; |
705 | |||
706 | #if defined(CONFIG_SPI_MASTER) | ||
707 | ret = spi_register_driver(&ssm2602_spi_driver); | ||
708 | if (ret) | ||
709 | return ret; | ||
710 | #endif | ||
711 | |||
667 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 712 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
668 | ret = i2c_add_driver(&ssm2602_i2c_driver); | 713 | ret = i2c_add_driver(&ssm2602_i2c_driver); |
669 | if (ret != 0) { | 714 | if (ret) |
670 | printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", | 715 | return ret; |
671 | ret); | ||
672 | } | ||
673 | #endif | 716 | #endif |
717 | |||
674 | return ret; | 718 | return ret; |
675 | } | 719 | } |
676 | module_init(ssm2602_modinit); | 720 | module_init(ssm2602_modinit); |
677 | 721 | ||
678 | static void __exit ssm2602_exit(void) | 722 | static void __exit ssm2602_exit(void) |
679 | { | 723 | { |
724 | #if defined(CONFIG_SPI_MASTER) | ||
725 | spi_unregister_driver(&ssm2602_spi_driver); | ||
726 | #endif | ||
727 | |||
680 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 728 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
681 | i2c_del_driver(&ssm2602_i2c_driver); | 729 | i2c_del_driver(&ssm2602_i2c_driver); |
682 | #endif | 730 | #endif |
683 | } | 731 | } |
684 | module_exit(ssm2602_exit); | 732 | module_exit(ssm2602_exit); |
685 | 733 | ||
686 | MODULE_DESCRIPTION("ASoC ssm2602 driver"); | 734 | MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); |
687 | MODULE_AUTHOR("Cliff Cai"); | 735 | MODULE_AUTHOR("Cliff Cai"); |
688 | MODULE_LICENSE("GPL"); | 736 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index 42a47d0f8e25..b98c69168036 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h | |||
@@ -117,11 +117,5 @@ | |||
117 | #define SSM2602_CACHEREGNUM 10 | 117 | #define SSM2602_CACHEREGNUM 10 |
118 | 118 | ||
119 | #define SSM2602_SYSCLK 0 | 119 | #define SSM2602_SYSCLK 0 |
120 | #define SSM2602_DAI 0 | ||
121 | |||
122 | struct ssm2602_setup_data { | ||
123 | int i2c_bus; | ||
124 | unsigned short i2c_address; | ||
125 | }; | ||
126 | 120 | ||
127 | #endif | 121 | #endif |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 54a30ef0ec8b..33bb52f3f683 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -212,7 +212,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { | |||
212 | SND_SOC_DAPM_INPUT("MICIN"), | 212 | SND_SOC_DAPM_INPUT("MICIN"), |
213 | }; | 213 | }; |
214 | 214 | ||
215 | static const struct snd_soc_dapm_route intercon[] = { | 215 | static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { |
216 | /* Output Mixer */ | 216 | /* Output Mixer */ |
217 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, | 217 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, |
218 | {"Output Mixer", "Playback Switch", "DAC"}, | 218 | {"Output Mixer", "Playback Switch", "DAC"}, |
@@ -388,18 +388,6 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, | |||
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
390 | 390 | ||
391 | static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) | ||
392 | { | ||
393 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
394 | |||
395 | snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, | ||
396 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); | ||
397 | /* set up audio path interconnects */ | ||
398 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | 391 | static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, |
404 | struct snd_pcm_hw_params *params, | 392 | struct snd_pcm_hw_params *params, |
405 | struct snd_soc_dai *dai) | 393 | struct snd_soc_dai *dai) |
@@ -676,7 +664,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec) | |||
676 | 664 | ||
677 | snd_soc_add_controls(codec, tlv320aic23_snd_controls, | 665 | snd_soc_add_controls(codec, tlv320aic23_snd_controls, |
678 | ARRAY_SIZE(tlv320aic23_snd_controls)); | 666 | ARRAY_SIZE(tlv320aic23_snd_controls)); |
679 | tlv320aic23_add_widgets(codec); | ||
680 | 667 | ||
681 | return 0; | 668 | return 0; |
682 | } | 669 | } |
@@ -698,6 +685,10 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | |||
698 | .read = tlv320aic23_read_reg_cache, | 685 | .read = tlv320aic23_read_reg_cache, |
699 | .write = tlv320aic23_write, | 686 | .write = tlv320aic23_write, |
700 | .set_bias_level = tlv320aic23_set_bias_level, | 687 | .set_bias_level = tlv320aic23_set_bias_level, |
688 | .dapm_widgets = tlv320aic23_dapm_widgets, | ||
689 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), | ||
690 | .dapm_routes = tlv320aic23_intercon, | ||
691 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), | ||
701 | }; | 692 | }; |
702 | 693 | ||
703 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 694 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 6c43c13f0430..c3d96fc8c267 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -157,7 +157,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, | |||
157 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | 157 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, |
158 | struct snd_ctl_elem_value *ucontrol) | 158 | struct snd_ctl_elem_value *ucontrol) |
159 | { | 159 | { |
160 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 160 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
161 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
161 | struct soc_mixer_control *mc = | 162 | struct soc_mixer_control *mc = |
162 | (struct soc_mixer_control *)kcontrol->private_value; | 163 | (struct soc_mixer_control *)kcontrol->private_value; |
163 | unsigned int reg = mc->reg; | 164 | unsigned int reg = mc->reg; |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 082e9d51963f..faa5e9fb1471 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver | 2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver |
3 | * | 3 | * |
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
5 | * | 5 | * |
6 | * Copyright: (C) 2009 Nokia Corporation | 6 | * Copyright: (C) 2009 Nokia Corporation |
7 | * | 7 | * |
@@ -587,6 +587,9 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { | |||
587 | SND_SOC_DAPM_SUPPLY("Right DAC Power", | 587 | SND_SOC_DAPM_SUPPLY("Right DAC Power", |
588 | DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0), | 588 | DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0), |
589 | 589 | ||
590 | SND_SOC_DAPM_SUPPLY("Codec Power", | ||
591 | DAC33_PWR_CTRL, 4, 0, NULL, 0), | ||
592 | |||
590 | SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event), | 593 | SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event), |
591 | SND_SOC_DAPM_POST("Post Playback", dac33_playback_event), | 594 | SND_SOC_DAPM_POST("Post Playback", dac33_playback_event), |
592 | }; | 595 | }; |
@@ -619,6 +622,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
619 | /* output */ | 622 | /* output */ |
620 | {"LEFT_LO", NULL, "Output Left Amplifier"}, | 623 | {"LEFT_LO", NULL, "Output Left Amplifier"}, |
621 | {"RIGHT_LO", NULL, "Output Right Amplifier"}, | 624 | {"RIGHT_LO", NULL, "Output Right Amplifier"}, |
625 | |||
626 | {"LEFT_LO", NULL, "Codec Power"}, | ||
627 | {"RIGHT_LO", NULL, "Codec Power"}, | ||
622 | }; | 628 | }; |
623 | 629 | ||
624 | static int dac33_add_widgets(struct snd_soc_codec *codec) | 630 | static int dac33_add_widgets(struct snd_soc_codec *codec) |
@@ -636,13 +642,10 @@ static int dac33_add_widgets(struct snd_soc_codec *codec) | |||
636 | static int dac33_set_bias_level(struct snd_soc_codec *codec, | 642 | static int dac33_set_bias_level(struct snd_soc_codec *codec, |
637 | enum snd_soc_bias_level level) | 643 | enum snd_soc_bias_level level) |
638 | { | 644 | { |
639 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | ||
640 | int ret; | 645 | int ret; |
641 | 646 | ||
642 | switch (level) { | 647 | switch (level) { |
643 | case SND_SOC_BIAS_ON: | 648 | case SND_SOC_BIAS_ON: |
644 | if (!dac33->substream) | ||
645 | dac33_soft_power(codec, 1); | ||
646 | break; | 649 | break; |
647 | case SND_SOC_BIAS_PREPARE: | 650 | case SND_SOC_BIAS_PREPARE: |
648 | break; | 651 | break; |
@@ -943,8 +946,8 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) | |||
943 | /* Write registers 0x08 and 0x09 (MSB, LSB) */ | 946 | /* Write registers 0x08 and 0x09 (MSB, LSB) */ |
944 | dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset); | 947 | dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset); |
945 | 948 | ||
946 | /* calib time: 128 is a nice number ;) */ | 949 | /* OSC calibration time */ |
947 | dac33_write(codec, DAC33_CALIB_TIME, 128); | 950 | dac33_write(codec, DAC33_CALIB_TIME, 96); |
948 | 951 | ||
949 | /* adjustment treshold & step */ | 952 | /* adjustment treshold & step */ |
950 | dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) | | 953 | dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) | |
@@ -1655,5 +1658,5 @@ module_exit(dac33_module_exit); | |||
1655 | 1658 | ||
1656 | 1659 | ||
1657 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); | 1660 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); |
1658 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>"); | 1661 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
1659 | MODULE_LICENSE("GPL"); | 1662 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h index 7c318b5da437..ed69670747bf 100644 --- a/sound/soc/codecs/tlv320dac33.h +++ b/sound/soc/codecs/tlv320dac33.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver | 2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver |
3 | * | 3 | * |
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
5 | * | 5 | * |
6 | * Copyright: (C) 2009 Nokia Corporation | 6 | * Copyright: (C) 2009 Nokia Corporation |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 1f1ac8110bef..239e0c461068 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) Nokia Corporation | 4 | * Copyright (C) Nokia Corporation |
5 | * | 5 | * |
6 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 6 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
@@ -495,7 +495,7 @@ static void __exit tpa6130a2_exit(void) | |||
495 | i2c_del_driver(&tpa6130a2_i2c_driver); | 495 | i2c_del_driver(&tpa6130a2_i2c_driver); |
496 | } | 496 | } |
497 | 497 | ||
498 | MODULE_AUTHOR("Peter Ujfalusi"); | 498 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
499 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); | 499 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); |
500 | MODULE_LICENSE("GPL"); | 500 | MODULE_LICENSE("GPL"); |
501 | 501 | ||
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 5df49c8756b2..417444020ba6 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) Nokia Corporation | 4 | * Copyright (C) Nokia Corporation |
5 | * | 5 | * |
6 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 6 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 255901c4460d..4c336636d4f5 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -960,9 +960,9 @@ static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0); | |||
960 | 960 | ||
961 | /* | 961 | /* |
962 | * AFMGAIN volume control: | 962 | * AFMGAIN volume control: |
963 | * from 18 to 24 dB in 6 dB steps | 963 | * from -18 to 24 dB in 6 dB steps |
964 | */ | 964 | */ |
965 | static DECLARE_TLV_DB_SCALE(afm_amp_tlv, 1800, 600, 0); | 965 | static DECLARE_TLV_DB_SCALE(afm_amp_tlv, -1800, 600, 0); |
966 | 966 | ||
967 | /* | 967 | /* |
968 | * HSGAIN volume control: | 968 | * HSGAIN volume control: |
@@ -1049,7 +1049,7 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { | |||
1049 | 1049 | ||
1050 | /* AFM gains */ | 1050 | /* AFM gains */ |
1051 | SOC_DOUBLE_TLV("Aux FM Volume", | 1051 | SOC_DOUBLE_TLV("Aux FM Volume", |
1052 | TWL6040_REG_LINEGAIN, 0, 4, 0xF, 0, afm_amp_tlv), | 1052 | TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv), |
1053 | 1053 | ||
1054 | /* Playback gains */ | 1054 | /* Playback gains */ |
1055 | SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume", | 1055 | SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume", |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 48ffd406a71d..a7b8f301bad3 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -601,9 +601,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = { | |||
601 | .reg_cache_step = 1, | 601 | .reg_cache_step = 1, |
602 | .read = uda134x_read_reg_cache, | 602 | .read = uda134x_read_reg_cache, |
603 | .write = uda134x_write, | 603 | .write = uda134x_write, |
604 | #ifdef POWER_OFF_ON_STANDBY | ||
605 | .set_bias_level = uda134x_set_bias_level, | 604 | .set_bias_level = uda134x_set_bias_level, |
606 | #endif | ||
607 | }; | 605 | }; |
608 | 606 | ||
609 | static int __devinit uda134x_codec_probe(struct platform_device *pdev) | 607 | static int __devinit uda134x_codec_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c new file mode 100644 index 000000000000..14d0716bf009 --- /dev/null +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Driver for the 1250-EV1 audio I/O module | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
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 | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/i2c.h> | ||
16 | |||
17 | #include <sound/soc.h> | ||
18 | #include <sound/soc-dapm.h> | ||
19 | |||
20 | static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = { | ||
21 | SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0), | ||
22 | SND_SOC_DAPM_DAC("DAC", "wm1250-ev1 Playback", SND_SOC_NOPM, 0, 0), | ||
23 | |||
24 | SND_SOC_DAPM_INPUT("WM1250 Input"), | ||
25 | SND_SOC_DAPM_INPUT("WM1250 Output"), | ||
26 | }; | ||
27 | |||
28 | static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = { | ||
29 | { "ADC", NULL, "WM1250 Input" }, | ||
30 | { "WM1250 Output", NULL, "DAC" }, | ||
31 | }; | ||
32 | |||
33 | static struct snd_soc_dai_driver wm1250_ev1_dai = { | ||
34 | .name = "wm1250-ev1", | ||
35 | .playback = { | ||
36 | .stream_name = "Playback", | ||
37 | .channels_min = 1, | ||
38 | .channels_max = 1, | ||
39 | .rates = SNDRV_PCM_RATE_8000, | ||
40 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
41 | }, | ||
42 | .capture = { | ||
43 | .stream_name = "Capture", | ||
44 | .channels_min = 1, | ||
45 | .channels_max = 1, | ||
46 | .rates = SNDRV_PCM_RATE_8000, | ||
47 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { | ||
52 | .dapm_widgets = wm1250_ev1_dapm_widgets, | ||
53 | .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), | ||
54 | .dapm_routes = wm1250_ev1_dapm_routes, | ||
55 | .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), | ||
56 | }; | ||
57 | |||
58 | static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, | ||
59 | const struct i2c_device_id *id) | ||
60 | { | ||
61 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, | ||
62 | &wm1250_ev1_dai, 1); | ||
63 | } | ||
64 | |||
65 | static int __devexit wm1250_ev1_remove(struct i2c_client *i2c) | ||
66 | { | ||
67 | snd_soc_unregister_codec(&i2c->dev); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static const struct i2c_device_id wm1250_ev1_i2c_id[] = { | ||
73 | { "wm1250-ev1", 0 }, | ||
74 | { } | ||
75 | }; | ||
76 | MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id); | ||
77 | |||
78 | static struct i2c_driver wm1250_ev1_i2c_driver = { | ||
79 | .driver = { | ||
80 | .name = "wm1250-ev1", | ||
81 | .owner = THIS_MODULE, | ||
82 | }, | ||
83 | .probe = wm1250_ev1_probe, | ||
84 | .remove = __devexit_p(wm1250_ev1_remove), | ||
85 | .id_table = wm1250_ev1_i2c_id, | ||
86 | }; | ||
87 | |||
88 | static int __init wm1250_ev1_modinit(void) | ||
89 | { | ||
90 | int ret = 0; | ||
91 | |||
92 | ret = i2c_add_driver(&wm1250_ev1_i2c_driver); | ||
93 | if (ret != 0) | ||
94 | pr_err("Failed to register WM1250-EV1 I2C driver: %d\n", ret); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | module_init(wm1250_ev1_modinit); | ||
99 | |||
100 | static void __exit wm1250_ev1_exit(void) | ||
101 | { | ||
102 | i2c_del_driver(&wm1250_ev1_i2c_driver); | ||
103 | } | ||
104 | module_exit(wm1250_ev1_exit); | ||
105 | |||
106 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
107 | MODULE_DESCRIPTION("WM1250-EV1 audio I/O module driver"); | ||
108 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 97c30382d3ff..a537e4af6ae7 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -77,7 +77,7 @@ SND_SOC_DAPM_OUTPUT("ROUT"), | |||
77 | SND_SOC_DAPM_OUTPUT("RHPOUT"), | 77 | SND_SOC_DAPM_OUTPUT("RHPOUT"), |
78 | }; | 78 | }; |
79 | 79 | ||
80 | static const struct snd_soc_dapm_route intercon[] = { | 80 | static const struct snd_soc_dapm_route wm8711_intercon[] = { |
81 | /* output mixer */ | 81 | /* output mixer */ |
82 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, | 82 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, |
83 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, | 83 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, |
@@ -89,17 +89,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
89 | {"LOUT", NULL, "Output Mixer"}, | 89 | {"LOUT", NULL, "Output Mixer"}, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static int wm8711_add_widgets(struct snd_soc_codec *codec) | ||
93 | { | ||
94 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
95 | |||
96 | snd_soc_dapm_new_controls(dapm, wm8711_dapm_widgets, | ||
97 | ARRAY_SIZE(wm8711_dapm_widgets)); | ||
98 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | struct _coeff_div { | 92 | struct _coeff_div { |
104 | u32 mclk; | 93 | u32 mclk; |
105 | u32 rate; | 94 | u32 rate; |
@@ -398,7 +387,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) | |||
398 | 387 | ||
399 | snd_soc_add_controls(codec, wm8711_snd_controls, | 388 | snd_soc_add_controls(codec, wm8711_snd_controls, |
400 | ARRAY_SIZE(wm8711_snd_controls)); | 389 | ARRAY_SIZE(wm8711_snd_controls)); |
401 | wm8711_add_widgets(codec); | ||
402 | 390 | ||
403 | return ret; | 391 | return ret; |
404 | 392 | ||
@@ -420,6 +408,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | |||
420 | .reg_cache_size = ARRAY_SIZE(wm8711_reg), | 408 | .reg_cache_size = ARRAY_SIZE(wm8711_reg), |
421 | .reg_word_size = sizeof(u16), | 409 | .reg_word_size = sizeof(u16), |
422 | .reg_cache_default = wm8711_reg, | 410 | .reg_cache_default = wm8711_reg, |
411 | .dapm_widgets = wm8711_dapm_widgets, | ||
412 | .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), | ||
413 | .dapm_routes = wm8711_intercon, | ||
414 | .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), | ||
423 | }; | 415 | }; |
424 | 416 | ||
425 | #if defined(CONFIG_SPI_MASTER) | 417 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 736b0352d0a7..86d4718d3a76 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -65,22 +65,11 @@ SND_SOC_DAPM_OUTPUT("VOUTL"), | |||
65 | SND_SOC_DAPM_OUTPUT("VOUTR"), | 65 | SND_SOC_DAPM_OUTPUT("VOUTR"), |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static const struct snd_soc_dapm_route intercon[] = { | 68 | static const struct snd_soc_dapm_route wm8728_intercon[] = { |
69 | {"VOUTL", NULL, "DAC"}, | 69 | {"VOUTL", NULL, "DAC"}, |
70 | {"VOUTR", NULL, "DAC"}, | 70 | {"VOUTR", NULL, "DAC"}, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static int wm8728_add_widgets(struct snd_soc_codec *codec) | ||
74 | { | ||
75 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
76 | |||
77 | snd_soc_dapm_new_controls(dapm, wm8728_dapm_widgets, | ||
78 | ARRAY_SIZE(wm8728_dapm_widgets)); | ||
79 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int wm8728_mute(struct snd_soc_dai *dai, int mute) | 73 | static int wm8728_mute(struct snd_soc_dai *dai, int mute) |
85 | { | 74 | { |
86 | struct snd_soc_codec *codec = dai->codec; | 75 | struct snd_soc_codec *codec = dai->codec; |
@@ -255,7 +244,6 @@ static int wm8728_probe(struct snd_soc_codec *codec) | |||
255 | 244 | ||
256 | snd_soc_add_controls(codec, wm8728_snd_controls, | 245 | snd_soc_add_controls(codec, wm8728_snd_controls, |
257 | ARRAY_SIZE(wm8728_snd_controls)); | 246 | ARRAY_SIZE(wm8728_snd_controls)); |
258 | wm8728_add_widgets(codec); | ||
259 | 247 | ||
260 | return ret; | 248 | return ret; |
261 | } | 249 | } |
@@ -275,6 +263,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | |||
275 | .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), | 263 | .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), |
276 | .reg_word_size = sizeof(u16), | 264 | .reg_word_size = sizeof(u16), |
277 | .reg_cache_default = wm8728_reg_defaults, | 265 | .reg_cache_default = wm8728_reg_defaults, |
266 | .dapm_widgets = wm8728_dapm_widgets, | ||
267 | .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), | ||
268 | .dapm_routes = wm8728_intercon, | ||
269 | .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), | ||
278 | }; | 270 | }; |
279 | 271 | ||
280 | #if defined(CONFIG_SPI_MASTER) | 272 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0a67c31b2663..6dec7cee2cb4 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -201,7 +201,7 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source, | |||
201 | return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; | 201 | return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; |
202 | } | 202 | } |
203 | 203 | ||
204 | static const struct snd_soc_dapm_route intercon[] = { | 204 | static const struct snd_soc_dapm_route wm8731_intercon[] = { |
205 | {"DAC", NULL, "OSC", wm8731_check_osc}, | 205 | {"DAC", NULL, "OSC", wm8731_check_osc}, |
206 | {"ADC", NULL, "OSC", wm8731_check_osc}, | 206 | {"ADC", NULL, "OSC", wm8731_check_osc}, |
207 | 207 | ||
@@ -227,17 +227,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
227 | {"Mic Bias", NULL, "MICIN"}, | 227 | {"Mic Bias", NULL, "MICIN"}, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static int wm8731_add_widgets(struct snd_soc_codec *codec) | ||
231 | { | ||
232 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
233 | |||
234 | snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets, | ||
235 | ARRAY_SIZE(wm8731_dapm_widgets)); | ||
236 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | struct _coeff_div { | 230 | struct _coeff_div { |
242 | u32 mclk; | 231 | u32 mclk; |
243 | u32 rate; | 232 | u32 rate; |
@@ -599,7 +588,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) | |||
599 | 588 | ||
600 | snd_soc_add_controls(codec, wm8731_snd_controls, | 589 | snd_soc_add_controls(codec, wm8731_snd_controls, |
601 | ARRAY_SIZE(wm8731_snd_controls)); | 590 | ARRAY_SIZE(wm8731_snd_controls)); |
602 | wm8731_add_widgets(codec); | ||
603 | 591 | ||
604 | /* Regulators will have been enabled by bias management */ | 592 | /* Regulators will have been enabled by bias management */ |
605 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 593 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
@@ -636,6 +624,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | |||
636 | .reg_cache_size = ARRAY_SIZE(wm8731_reg), | 624 | .reg_cache_size = ARRAY_SIZE(wm8731_reg), |
637 | .reg_word_size = sizeof(u16), | 625 | .reg_word_size = sizeof(u16), |
638 | .reg_cache_default = wm8731_reg, | 626 | .reg_cache_default = wm8731_reg, |
627 | .dapm_widgets = wm8731_dapm_widgets, | ||
628 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), | ||
629 | .dapm_routes = wm8731_intercon, | ||
630 | .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), | ||
639 | }; | 631 | }; |
640 | 632 | ||
641 | #if defined(CONFIG_SPI_MASTER) | 633 | #if defined(CONFIG_SPI_MASTER) |
@@ -667,7 +659,7 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi) | |||
667 | 659 | ||
668 | static struct spi_driver wm8731_spi_driver = { | 660 | static struct spi_driver wm8731_spi_driver = { |
669 | .driver = { | 661 | .driver = { |
670 | .name = "wm8731-codec", | 662 | .name = "wm8731", |
671 | .owner = THIS_MODULE, | 663 | .owner = THIS_MODULE, |
672 | }, | 664 | }, |
673 | .probe = wm8731_spi_probe, | 665 | .probe = wm8731_spi_probe, |
@@ -711,7 +703,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | |||
711 | 703 | ||
712 | static struct i2c_driver wm8731_i2c_driver = { | 704 | static struct i2c_driver wm8731_i2c_driver = { |
713 | .driver = { | 705 | .driver = { |
714 | .name = "wm8731-codec", | 706 | .name = "wm8731", |
715 | .owner = THIS_MODULE, | 707 | .owner = THIS_MODULE, |
716 | }, | 708 | }, |
717 | .probe = wm8731_i2c_probe, | 709 | .probe = wm8731_i2c_probe, |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f52b623bb692..43e3d760766f 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -382,7 +382,8 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
382 | static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | 382 | static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, |
383 | struct snd_ctl_elem_value *ucontrol) | 383 | struct snd_ctl_elem_value *ucontrol) |
384 | { | 384 | { |
385 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 385 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
386 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
386 | struct snd_soc_codec *codec = widget->codec; | 387 | struct snd_soc_codec *codec = widget->codec; |
387 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 388 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
388 | u16 reg; | 389 | u16 reg; |
@@ -634,6 +635,13 @@ static const struct soc_enum lsidetone_enum = | |||
634 | static const struct soc_enum rsidetone_enum = | 635 | static const struct soc_enum rsidetone_enum = |
635 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); | 636 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); |
636 | 637 | ||
638 | static const char *adcinput_text[] = { | ||
639 | "ADC", "DMIC" | ||
640 | }; | ||
641 | |||
642 | static const struct soc_enum adcinput_enum = | ||
643 | SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); | ||
644 | |||
637 | static const char *aif_text[] = { | 645 | static const char *aif_text[] = { |
638 | "Left", "Right" | 646 | "Left", "Right" |
639 | }; | 647 | }; |
@@ -692,7 +700,7 @@ SOC_ENUM("DRC Smoothing Threshold", drc_smoothing), | |||
692 | SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), | 700 | SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), |
693 | 701 | ||
694 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, | 702 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, |
695 | WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv), | 703 | WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), |
696 | SOC_ENUM("ADC Companding Mode", adc_companding), | 704 | SOC_ENUM("ADC Companding Mode", adc_companding), |
697 | SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), | 705 | SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), |
698 | 706 | ||
@@ -767,6 +775,9 @@ static const struct snd_kcontrol_new lsidetone_mux = | |||
767 | static const struct snd_kcontrol_new rsidetone_mux = | 775 | static const struct snd_kcontrol_new rsidetone_mux = |
768 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); | 776 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); |
769 | 777 | ||
778 | static const struct snd_kcontrol_new adcinput_mux = | ||
779 | SOC_DAPM_ENUM("ADC Input", adcinput_enum); | ||
780 | |||
770 | static const struct snd_kcontrol_new lcapture_mux = | 781 | static const struct snd_kcontrol_new lcapture_mux = |
771 | SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum); | 782 | SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum); |
772 | 783 | ||
@@ -817,6 +828,7 @@ SND_SOC_DAPM_INPUT("IN2L"), | |||
817 | SND_SOC_DAPM_INPUT("IN2R"), | 828 | SND_SOC_DAPM_INPUT("IN2R"), |
818 | SND_SOC_DAPM_INPUT("IN3L"), | 829 | SND_SOC_DAPM_INPUT("IN3L"), |
819 | SND_SOC_DAPM_INPUT("IN3R"), | 830 | SND_SOC_DAPM_INPUT("IN3R"), |
831 | SND_SOC_DAPM_INPUT("DMICDAT"), | ||
820 | 832 | ||
821 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | 833 | SND_SOC_DAPM_OUTPUT("HPOUTL"), |
822 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | 834 | SND_SOC_DAPM_OUTPUT("HPOUTR"), |
@@ -842,6 +854,9 @@ SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux), | |||
842 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), | 854 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), |
843 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), | 855 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), |
844 | 856 | ||
857 | SND_SOC_DAPM_MUX("Left ADC Input", SND_SOC_NOPM, 0, 0, &adcinput_mux), | ||
858 | SND_SOC_DAPM_MUX("Right ADC Input", SND_SOC_NOPM, 0, 0, &adcinput_mux), | ||
859 | |||
845 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0), | 860 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0), |
846 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0), | 861 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0), |
847 | 862 | ||
@@ -930,7 +945,7 @@ SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), | |||
930 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0), | 945 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0), |
931 | }; | 946 | }; |
932 | 947 | ||
933 | static const struct snd_soc_dapm_route intercon[] = { | 948 | static const struct snd_soc_dapm_route wm8903_intercon[] = { |
934 | 949 | ||
935 | { "CLK_DSP", NULL, "CLK_SYS" }, | 950 | { "CLK_DSP", NULL, "CLK_SYS" }, |
936 | { "Mic Bias", NULL, "CLK_SYS" }, | 951 | { "Mic Bias", NULL, "CLK_SYS" }, |
@@ -979,6 +994,11 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
979 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, | 994 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, |
980 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, | 995 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, |
981 | 996 | ||
997 | { "Left ADC Input", "ADC", "Left Input PGA" }, | ||
998 | { "Left ADC Input", "DMIC", "DMICDAT" }, | ||
999 | { "Right ADC Input", "ADC", "Right Input PGA" }, | ||
1000 | { "Right ADC Input", "DMIC", "DMICDAT" }, | ||
1001 | |||
982 | { "Left Capture Mux", "Left", "ADCL" }, | 1002 | { "Left Capture Mux", "Left", "ADCL" }, |
983 | { "Left Capture Mux", "Right", "ADCR" }, | 1003 | { "Left Capture Mux", "Right", "ADCR" }, |
984 | 1004 | ||
@@ -988,9 +1008,9 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
988 | { "AIFTXL", NULL, "Left Capture Mux" }, | 1008 | { "AIFTXL", NULL, "Left Capture Mux" }, |
989 | { "AIFTXR", NULL, "Right Capture Mux" }, | 1009 | { "AIFTXR", NULL, "Right Capture Mux" }, |
990 | 1010 | ||
991 | { "ADCL", NULL, "Left Input PGA" }, | 1011 | { "ADCL", NULL, "Left ADC Input" }, |
992 | { "ADCL", NULL, "CLK_DSP" }, | 1012 | { "ADCL", NULL, "CLK_DSP" }, |
993 | { "ADCR", NULL, "Right Input PGA" }, | 1013 | { "ADCR", NULL, "Right ADC Input" }, |
994 | { "ADCR", NULL, "CLK_DSP" }, | 1014 | { "ADCR", NULL, "CLK_DSP" }, |
995 | 1015 | ||
996 | { "Left Playback Mux", "Left", "AIFRXL" }, | 1016 | { "Left Playback Mux", "Left", "AIFRXL" }, |
@@ -1087,17 +1107,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1087 | { "Right Line Output PGA", NULL, "Charge Pump" }, | 1107 | { "Right Line Output PGA", NULL, "Charge Pump" }, |
1088 | }; | 1108 | }; |
1089 | 1109 | ||
1090 | static int wm8903_add_widgets(struct snd_soc_codec *codec) | ||
1091 | { | ||
1092 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1093 | |||
1094 | snd_soc_dapm_new_controls(dapm, wm8903_dapm_widgets, | ||
1095 | ARRAY_SIZE(wm8903_dapm_widgets)); | ||
1096 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 1110 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, |
1102 | enum snd_soc_bias_level level) | 1111 | enum snd_soc_bias_level level) |
1103 | { | 1112 | { |
@@ -2028,7 +2037,6 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
2028 | 2037 | ||
2029 | snd_soc_add_controls(codec, wm8903_snd_controls, | 2038 | snd_soc_add_controls(codec, wm8903_snd_controls, |
2030 | ARRAY_SIZE(wm8903_snd_controls)); | 2039 | ARRAY_SIZE(wm8903_snd_controls)); |
2031 | wm8903_add_widgets(codec); | ||
2032 | 2040 | ||
2033 | wm8903_init_gpio(codec); | 2041 | wm8903_init_gpio(codec); |
2034 | 2042 | ||
@@ -2054,6 +2062,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { | |||
2054 | .reg_cache_default = wm8903_reg_defaults, | 2062 | .reg_cache_default = wm8903_reg_defaults, |
2055 | .volatile_register = wm8903_volatile_register, | 2063 | .volatile_register = wm8903_volatile_register, |
2056 | .seq_notifier = wm8903_seq_notifier, | 2064 | .seq_notifier = wm8903_seq_notifier, |
2065 | .dapm_widgets = wm8903_dapm_widgets, | ||
2066 | .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), | ||
2067 | .dapm_routes = wm8903_intercon, | ||
2068 | .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), | ||
2057 | }; | 2069 | }; |
2058 | 2070 | ||
2059 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2071 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c new file mode 100644 index 000000000000..ccc9bd832794 --- /dev/null +++ b/sound/soc/codecs/wm8915.c | |||
@@ -0,0 +1,2931 @@ | |||
1 | /* | ||
2 | * wm8915.c - WM8915 audio codec interface | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/completion.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/gcd.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/jack.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/soc.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/tlv.h> | ||
33 | #include <trace/events/asoc.h> | ||
34 | |||
35 | #include <sound/wm8915.h> | ||
36 | #include "wm8915.h" | ||
37 | |||
38 | #define WM8915_AIFS 2 | ||
39 | |||
40 | #define HPOUT1L 1 | ||
41 | #define HPOUT1R 2 | ||
42 | #define HPOUT2L 4 | ||
43 | #define HPOUT2R 8 | ||
44 | |||
45 | #define WM8915_NUM_SUPPLIES 6 | ||
46 | static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { | ||
47 | "DCVDD", | ||
48 | "DBVDD", | ||
49 | "AVDD1", | ||
50 | "AVDD2", | ||
51 | "CPVDD", | ||
52 | "MICVDD", | ||
53 | }; | ||
54 | |||
55 | struct wm8915_priv { | ||
56 | struct snd_soc_codec *codec; | ||
57 | |||
58 | int ldo1ena; | ||
59 | |||
60 | int sysclk; | ||
61 | |||
62 | int fll_src; | ||
63 | int fll_fref; | ||
64 | int fll_fout; | ||
65 | |||
66 | struct completion fll_lock; | ||
67 | |||
68 | u16 dcs_pending; | ||
69 | struct completion dcs_done; | ||
70 | |||
71 | u16 hpout_ena; | ||
72 | u16 hpout_pending; | ||
73 | |||
74 | struct regulator_bulk_data supplies[WM8915_NUM_SUPPLIES]; | ||
75 | struct notifier_block disable_nb[WM8915_NUM_SUPPLIES]; | ||
76 | |||
77 | struct wm8915_pdata pdata; | ||
78 | |||
79 | int rx_rate[WM8915_AIFS]; | ||
80 | |||
81 | /* Platform dependant ReTune mobile configuration */ | ||
82 | int num_retune_mobile_texts; | ||
83 | const char **retune_mobile_texts; | ||
84 | int retune_mobile_cfg[2]; | ||
85 | struct soc_enum retune_mobile_enum; | ||
86 | |||
87 | struct snd_soc_jack *jack; | ||
88 | bool detecting; | ||
89 | bool jack_mic; | ||
90 | wm8915_polarity_fn polarity_cb; | ||
91 | |||
92 | #ifdef CONFIG_GPIOLIB | ||
93 | struct gpio_chip gpio_chip; | ||
94 | #endif | ||
95 | }; | ||
96 | |||
97 | /* We can't use the same notifier block for more than one supply and | ||
98 | * there's no way I can see to get from a callback to the caller | ||
99 | * except container_of(). | ||
100 | */ | ||
101 | #define WM8915_REGULATOR_EVENT(n) \ | ||
102 | static int wm8915_regulator_event_##n(struct notifier_block *nb, \ | ||
103 | unsigned long event, void *data) \ | ||
104 | { \ | ||
105 | struct wm8915_priv *wm8915 = container_of(nb, struct wm8915_priv, \ | ||
106 | disable_nb[n]); \ | ||
107 | if (event & REGULATOR_EVENT_DISABLE) { \ | ||
108 | wm8915->codec->cache_sync = 1; \ | ||
109 | } \ | ||
110 | return 0; \ | ||
111 | } | ||
112 | |||
113 | WM8915_REGULATOR_EVENT(0) | ||
114 | WM8915_REGULATOR_EVENT(1) | ||
115 | WM8915_REGULATOR_EVENT(2) | ||
116 | WM8915_REGULATOR_EVENT(3) | ||
117 | WM8915_REGULATOR_EVENT(4) | ||
118 | WM8915_REGULATOR_EVENT(5) | ||
119 | |||
120 | static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { | ||
121 | [WM8915_SOFTWARE_RESET] = 0x8915, | ||
122 | [WM8915_POWER_MANAGEMENT_7] = 0x10, | ||
123 | [WM8915_DAC1_HPOUT1_VOLUME] = 0x88, | ||
124 | [WM8915_DAC2_HPOUT2_VOLUME] = 0x88, | ||
125 | [WM8915_DAC1_LEFT_VOLUME] = 0x2c0, | ||
126 | [WM8915_DAC1_RIGHT_VOLUME] = 0x2c0, | ||
127 | [WM8915_DAC2_LEFT_VOLUME] = 0x2c0, | ||
128 | [WM8915_DAC2_RIGHT_VOLUME] = 0x2c0, | ||
129 | [WM8915_OUTPUT1_LEFT_VOLUME] = 0x80, | ||
130 | [WM8915_OUTPUT1_RIGHT_VOLUME] = 0x80, | ||
131 | [WM8915_OUTPUT2_LEFT_VOLUME] = 0x80, | ||
132 | [WM8915_OUTPUT2_RIGHT_VOLUME] = 0x80, | ||
133 | [WM8915_MICBIAS_1] = 0x39, | ||
134 | [WM8915_MICBIAS_2] = 0x39, | ||
135 | [WM8915_LDO_1] = 0x3, | ||
136 | [WM8915_LDO_2] = 0x13, | ||
137 | [WM8915_ACCESSORY_DETECT_MODE_1] = 0x4, | ||
138 | [WM8915_HEADPHONE_DETECT_1] = 0x20, | ||
139 | [WM8915_MIC_DETECT_1] = 0x7600, | ||
140 | [WM8915_MIC_DETECT_2] = 0xbf, | ||
141 | [WM8915_CHARGE_PUMP_1] = 0x1f25, | ||
142 | [WM8915_CHARGE_PUMP_2] = 0xab19, | ||
143 | [WM8915_DC_SERVO_5] = 0x2a2a, | ||
144 | [WM8915_CONTROL_INTERFACE_1] = 0x8004, | ||
145 | [WM8915_CLOCKING_1] = 0x10, | ||
146 | [WM8915_AIF_RATE] = 0x83, | ||
147 | [WM8915_FLL_CONTROL_4] = 0x5dc0, | ||
148 | [WM8915_FLL_CONTROL_5] = 0xc84, | ||
149 | [WM8915_FLL_EFS_2] = 0x2, | ||
150 | [WM8915_AIF1_TX_LRCLK_1] = 0x80, | ||
151 | [WM8915_AIF1_TX_LRCLK_2] = 0x8, | ||
152 | [WM8915_AIF1_RX_LRCLK_1] = 0x80, | ||
153 | [WM8915_AIF1TX_DATA_CONFIGURATION_1] = 0x1818, | ||
154 | [WM8915_AIF1RX_DATA_CONFIGURATION] = 0x1818, | ||
155 | [WM8915_AIF1TX_TEST] = 0x7, | ||
156 | [WM8915_AIF2_TX_LRCLK_1] = 0x80, | ||
157 | [WM8915_AIF2_TX_LRCLK_2] = 0x8, | ||
158 | [WM8915_AIF2_RX_LRCLK_1] = 0x80, | ||
159 | [WM8915_AIF2TX_DATA_CONFIGURATION_1] = 0x1818, | ||
160 | [WM8915_AIF2RX_DATA_CONFIGURATION] = 0x1818, | ||
161 | [WM8915_AIF2TX_TEST] = 0x1, | ||
162 | [WM8915_DSP1_TX_LEFT_VOLUME] = 0xc0, | ||
163 | [WM8915_DSP1_TX_RIGHT_VOLUME] = 0xc0, | ||
164 | [WM8915_DSP1_RX_LEFT_VOLUME] = 0xc0, | ||
165 | [WM8915_DSP1_RX_RIGHT_VOLUME] = 0xc0, | ||
166 | [WM8915_DSP1_TX_FILTERS] = 0x2000, | ||
167 | [WM8915_DSP1_RX_FILTERS_1] = 0x200, | ||
168 | [WM8915_DSP1_RX_FILTERS_2] = 0x10, | ||
169 | [WM8915_DSP1_DRC_1] = 0x98, | ||
170 | [WM8915_DSP1_DRC_2] = 0x845, | ||
171 | [WM8915_DSP1_RX_EQ_GAINS_1] = 0x6318, | ||
172 | [WM8915_DSP1_RX_EQ_GAINS_2] = 0x6300, | ||
173 | [WM8915_DSP1_RX_EQ_BAND_1_A] = 0xfca, | ||
174 | [WM8915_DSP1_RX_EQ_BAND_1_B] = 0x400, | ||
175 | [WM8915_DSP1_RX_EQ_BAND_1_PG] = 0xd8, | ||
176 | [WM8915_DSP1_RX_EQ_BAND_2_A] = 0x1eb5, | ||
177 | [WM8915_DSP1_RX_EQ_BAND_2_B] = 0xf145, | ||
178 | [WM8915_DSP1_RX_EQ_BAND_2_C] = 0xb75, | ||
179 | [WM8915_DSP1_RX_EQ_BAND_2_PG] = 0x1c5, | ||
180 | [WM8915_DSP1_RX_EQ_BAND_3_A] = 0x1c58, | ||
181 | [WM8915_DSP1_RX_EQ_BAND_3_B] = 0xf373, | ||
182 | [WM8915_DSP1_RX_EQ_BAND_3_C] = 0xa54, | ||
183 | [WM8915_DSP1_RX_EQ_BAND_3_PG] = 0x558, | ||
184 | [WM8915_DSP1_RX_EQ_BAND_4_A] = 0x168e, | ||
185 | [WM8915_DSP1_RX_EQ_BAND_4_B] = 0xf829, | ||
186 | [WM8915_DSP1_RX_EQ_BAND_4_C] = 0x7ad, | ||
187 | [WM8915_DSP1_RX_EQ_BAND_4_PG] = 0x1103, | ||
188 | [WM8915_DSP1_RX_EQ_BAND_5_A] = 0x564, | ||
189 | [WM8915_DSP1_RX_EQ_BAND_5_B] = 0x559, | ||
190 | [WM8915_DSP1_RX_EQ_BAND_5_PG] = 0x4000, | ||
191 | [WM8915_DSP2_TX_LEFT_VOLUME] = 0xc0, | ||
192 | [WM8915_DSP2_TX_RIGHT_VOLUME] = 0xc0, | ||
193 | [WM8915_DSP2_RX_LEFT_VOLUME] = 0xc0, | ||
194 | [WM8915_DSP2_RX_RIGHT_VOLUME] = 0xc0, | ||
195 | [WM8915_DSP2_TX_FILTERS] = 0x2000, | ||
196 | [WM8915_DSP2_RX_FILTERS_1] = 0x200, | ||
197 | [WM8915_DSP2_RX_FILTERS_2] = 0x10, | ||
198 | [WM8915_DSP2_DRC_1] = 0x98, | ||
199 | [WM8915_DSP2_DRC_2] = 0x845, | ||
200 | [WM8915_DSP2_RX_EQ_GAINS_1] = 0x6318, | ||
201 | [WM8915_DSP2_RX_EQ_GAINS_2] = 0x6300, | ||
202 | [WM8915_DSP2_RX_EQ_BAND_1_A] = 0xfca, | ||
203 | [WM8915_DSP2_RX_EQ_BAND_1_B] = 0x400, | ||
204 | [WM8915_DSP2_RX_EQ_BAND_1_PG] = 0xd8, | ||
205 | [WM8915_DSP2_RX_EQ_BAND_2_A] = 0x1eb5, | ||
206 | [WM8915_DSP2_RX_EQ_BAND_2_B] = 0xf145, | ||
207 | [WM8915_DSP2_RX_EQ_BAND_2_C] = 0xb75, | ||
208 | [WM8915_DSP2_RX_EQ_BAND_2_PG] = 0x1c5, | ||
209 | [WM8915_DSP2_RX_EQ_BAND_3_A] = 0x1c58, | ||
210 | [WM8915_DSP2_RX_EQ_BAND_3_B] = 0xf373, | ||
211 | [WM8915_DSP2_RX_EQ_BAND_3_C] = 0xa54, | ||
212 | [WM8915_DSP2_RX_EQ_BAND_3_PG] = 0x558, | ||
213 | [WM8915_DSP2_RX_EQ_BAND_4_A] = 0x168e, | ||
214 | [WM8915_DSP2_RX_EQ_BAND_4_B] = 0xf829, | ||
215 | [WM8915_DSP2_RX_EQ_BAND_4_C] = 0x7ad, | ||
216 | [WM8915_DSP2_RX_EQ_BAND_4_PG] = 0x1103, | ||
217 | [WM8915_DSP2_RX_EQ_BAND_5_A] = 0x564, | ||
218 | [WM8915_DSP2_RX_EQ_BAND_5_B] = 0x559, | ||
219 | [WM8915_DSP2_RX_EQ_BAND_5_PG] = 0x4000, | ||
220 | [WM8915_OVERSAMPLING] = 0xd, | ||
221 | [WM8915_SIDETONE] = 0x1040, | ||
222 | [WM8915_GPIO_1] = 0xa101, | ||
223 | [WM8915_GPIO_2] = 0xa101, | ||
224 | [WM8915_GPIO_3] = 0xa101, | ||
225 | [WM8915_GPIO_4] = 0xa101, | ||
226 | [WM8915_GPIO_5] = 0xa101, | ||
227 | [WM8915_PULL_CONTROL_2] = 0x140, | ||
228 | [WM8915_INTERRUPT_STATUS_1_MASK] = 0x1f, | ||
229 | [WM8915_INTERRUPT_STATUS_2_MASK] = 0x1ecf, | ||
230 | [WM8915_RIGHT_PDM_SPEAKER] = 0x1, | ||
231 | [WM8915_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69, | ||
232 | [WM8915_PDM_SPEAKER_VOLUME] = 0x66, | ||
233 | [WM8915_WRITE_SEQUENCER_0] = 0x1, | ||
234 | [WM8915_WRITE_SEQUENCER_1] = 0x1, | ||
235 | [WM8915_WRITE_SEQUENCER_3] = 0x6, | ||
236 | [WM8915_WRITE_SEQUENCER_4] = 0x40, | ||
237 | [WM8915_WRITE_SEQUENCER_5] = 0x1, | ||
238 | [WM8915_WRITE_SEQUENCER_6] = 0xf, | ||
239 | [WM8915_WRITE_SEQUENCER_7] = 0x6, | ||
240 | [WM8915_WRITE_SEQUENCER_8] = 0x1, | ||
241 | [WM8915_WRITE_SEQUENCER_9] = 0x3, | ||
242 | [WM8915_WRITE_SEQUENCER_10] = 0x104, | ||
243 | [WM8915_WRITE_SEQUENCER_12] = 0x60, | ||
244 | [WM8915_WRITE_SEQUENCER_13] = 0x11, | ||
245 | [WM8915_WRITE_SEQUENCER_14] = 0x401, | ||
246 | [WM8915_WRITE_SEQUENCER_16] = 0x50, | ||
247 | [WM8915_WRITE_SEQUENCER_17] = 0x3, | ||
248 | [WM8915_WRITE_SEQUENCER_18] = 0x100, | ||
249 | [WM8915_WRITE_SEQUENCER_20] = 0x51, | ||
250 | [WM8915_WRITE_SEQUENCER_21] = 0x3, | ||
251 | [WM8915_WRITE_SEQUENCER_22] = 0x104, | ||
252 | [WM8915_WRITE_SEQUENCER_23] = 0xa, | ||
253 | [WM8915_WRITE_SEQUENCER_24] = 0x60, | ||
254 | [WM8915_WRITE_SEQUENCER_25] = 0x3b, | ||
255 | [WM8915_WRITE_SEQUENCER_26] = 0x502, | ||
256 | [WM8915_WRITE_SEQUENCER_27] = 0x100, | ||
257 | [WM8915_WRITE_SEQUENCER_28] = 0x2fff, | ||
258 | [WM8915_WRITE_SEQUENCER_32] = 0x2fff, | ||
259 | [WM8915_WRITE_SEQUENCER_36] = 0x2fff, | ||
260 | [WM8915_WRITE_SEQUENCER_40] = 0x2fff, | ||
261 | [WM8915_WRITE_SEQUENCER_44] = 0x2fff, | ||
262 | [WM8915_WRITE_SEQUENCER_48] = 0x2fff, | ||
263 | [WM8915_WRITE_SEQUENCER_52] = 0x2fff, | ||
264 | [WM8915_WRITE_SEQUENCER_56] = 0x2fff, | ||
265 | [WM8915_WRITE_SEQUENCER_60] = 0x2fff, | ||
266 | [WM8915_WRITE_SEQUENCER_64] = 0x1, | ||
267 | [WM8915_WRITE_SEQUENCER_65] = 0x1, | ||
268 | [WM8915_WRITE_SEQUENCER_67] = 0x6, | ||
269 | [WM8915_WRITE_SEQUENCER_68] = 0x40, | ||
270 | [WM8915_WRITE_SEQUENCER_69] = 0x1, | ||
271 | [WM8915_WRITE_SEQUENCER_70] = 0xf, | ||
272 | [WM8915_WRITE_SEQUENCER_71] = 0x6, | ||
273 | [WM8915_WRITE_SEQUENCER_72] = 0x1, | ||
274 | [WM8915_WRITE_SEQUENCER_73] = 0x3, | ||
275 | [WM8915_WRITE_SEQUENCER_74] = 0x104, | ||
276 | [WM8915_WRITE_SEQUENCER_76] = 0x60, | ||
277 | [WM8915_WRITE_SEQUENCER_77] = 0x11, | ||
278 | [WM8915_WRITE_SEQUENCER_78] = 0x401, | ||
279 | [WM8915_WRITE_SEQUENCER_80] = 0x50, | ||
280 | [WM8915_WRITE_SEQUENCER_81] = 0x3, | ||
281 | [WM8915_WRITE_SEQUENCER_82] = 0x100, | ||
282 | [WM8915_WRITE_SEQUENCER_84] = 0x60, | ||
283 | [WM8915_WRITE_SEQUENCER_85] = 0x3b, | ||
284 | [WM8915_WRITE_SEQUENCER_86] = 0x502, | ||
285 | [WM8915_WRITE_SEQUENCER_87] = 0x100, | ||
286 | [WM8915_WRITE_SEQUENCER_88] = 0x2fff, | ||
287 | [WM8915_WRITE_SEQUENCER_92] = 0x2fff, | ||
288 | [WM8915_WRITE_SEQUENCER_96] = 0x2fff, | ||
289 | [WM8915_WRITE_SEQUENCER_100] = 0x2fff, | ||
290 | [WM8915_WRITE_SEQUENCER_104] = 0x2fff, | ||
291 | [WM8915_WRITE_SEQUENCER_108] = 0x2fff, | ||
292 | [WM8915_WRITE_SEQUENCER_112] = 0x2fff, | ||
293 | [WM8915_WRITE_SEQUENCER_116] = 0x2fff, | ||
294 | [WM8915_WRITE_SEQUENCER_120] = 0x2fff, | ||
295 | [WM8915_WRITE_SEQUENCER_124] = 0x2fff, | ||
296 | [WM8915_WRITE_SEQUENCER_128] = 0x1, | ||
297 | [WM8915_WRITE_SEQUENCER_129] = 0x1, | ||
298 | [WM8915_WRITE_SEQUENCER_131] = 0x6, | ||
299 | [WM8915_WRITE_SEQUENCER_132] = 0x40, | ||
300 | [WM8915_WRITE_SEQUENCER_133] = 0x1, | ||
301 | [WM8915_WRITE_SEQUENCER_134] = 0xf, | ||
302 | [WM8915_WRITE_SEQUENCER_135] = 0x6, | ||
303 | [WM8915_WRITE_SEQUENCER_136] = 0x1, | ||
304 | [WM8915_WRITE_SEQUENCER_137] = 0x3, | ||
305 | [WM8915_WRITE_SEQUENCER_138] = 0x106, | ||
306 | [WM8915_WRITE_SEQUENCER_140] = 0x61, | ||
307 | [WM8915_WRITE_SEQUENCER_141] = 0x11, | ||
308 | [WM8915_WRITE_SEQUENCER_142] = 0x401, | ||
309 | [WM8915_WRITE_SEQUENCER_144] = 0x50, | ||
310 | [WM8915_WRITE_SEQUENCER_145] = 0x3, | ||
311 | [WM8915_WRITE_SEQUENCER_146] = 0x102, | ||
312 | [WM8915_WRITE_SEQUENCER_148] = 0x51, | ||
313 | [WM8915_WRITE_SEQUENCER_149] = 0x3, | ||
314 | [WM8915_WRITE_SEQUENCER_150] = 0x106, | ||
315 | [WM8915_WRITE_SEQUENCER_151] = 0xa, | ||
316 | [WM8915_WRITE_SEQUENCER_152] = 0x61, | ||
317 | [WM8915_WRITE_SEQUENCER_153] = 0x3b, | ||
318 | [WM8915_WRITE_SEQUENCER_154] = 0x502, | ||
319 | [WM8915_WRITE_SEQUENCER_155] = 0x100, | ||
320 | [WM8915_WRITE_SEQUENCER_156] = 0x2fff, | ||
321 | [WM8915_WRITE_SEQUENCER_160] = 0x2fff, | ||
322 | [WM8915_WRITE_SEQUENCER_164] = 0x2fff, | ||
323 | [WM8915_WRITE_SEQUENCER_168] = 0x2fff, | ||
324 | [WM8915_WRITE_SEQUENCER_172] = 0x2fff, | ||
325 | [WM8915_WRITE_SEQUENCER_176] = 0x2fff, | ||
326 | [WM8915_WRITE_SEQUENCER_180] = 0x2fff, | ||
327 | [WM8915_WRITE_SEQUENCER_184] = 0x2fff, | ||
328 | [WM8915_WRITE_SEQUENCER_188] = 0x2fff, | ||
329 | [WM8915_WRITE_SEQUENCER_192] = 0x1, | ||
330 | [WM8915_WRITE_SEQUENCER_193] = 0x1, | ||
331 | [WM8915_WRITE_SEQUENCER_195] = 0x6, | ||
332 | [WM8915_WRITE_SEQUENCER_196] = 0x40, | ||
333 | [WM8915_WRITE_SEQUENCER_197] = 0x1, | ||
334 | [WM8915_WRITE_SEQUENCER_198] = 0xf, | ||
335 | [WM8915_WRITE_SEQUENCER_199] = 0x6, | ||
336 | [WM8915_WRITE_SEQUENCER_200] = 0x1, | ||
337 | [WM8915_WRITE_SEQUENCER_201] = 0x3, | ||
338 | [WM8915_WRITE_SEQUENCER_202] = 0x106, | ||
339 | [WM8915_WRITE_SEQUENCER_204] = 0x61, | ||
340 | [WM8915_WRITE_SEQUENCER_205] = 0x11, | ||
341 | [WM8915_WRITE_SEQUENCER_206] = 0x401, | ||
342 | [WM8915_WRITE_SEQUENCER_208] = 0x50, | ||
343 | [WM8915_WRITE_SEQUENCER_209] = 0x3, | ||
344 | [WM8915_WRITE_SEQUENCER_210] = 0x102, | ||
345 | [WM8915_WRITE_SEQUENCER_212] = 0x61, | ||
346 | [WM8915_WRITE_SEQUENCER_213] = 0x3b, | ||
347 | [WM8915_WRITE_SEQUENCER_214] = 0x502, | ||
348 | [WM8915_WRITE_SEQUENCER_215] = 0x100, | ||
349 | [WM8915_WRITE_SEQUENCER_216] = 0x2fff, | ||
350 | [WM8915_WRITE_SEQUENCER_220] = 0x2fff, | ||
351 | [WM8915_WRITE_SEQUENCER_224] = 0x2fff, | ||
352 | [WM8915_WRITE_SEQUENCER_228] = 0x2fff, | ||
353 | [WM8915_WRITE_SEQUENCER_232] = 0x2fff, | ||
354 | [WM8915_WRITE_SEQUENCER_236] = 0x2fff, | ||
355 | [WM8915_WRITE_SEQUENCER_240] = 0x2fff, | ||
356 | [WM8915_WRITE_SEQUENCER_244] = 0x2fff, | ||
357 | [WM8915_WRITE_SEQUENCER_248] = 0x2fff, | ||
358 | [WM8915_WRITE_SEQUENCER_252] = 0x2fff, | ||
359 | [WM8915_WRITE_SEQUENCER_256] = 0x60, | ||
360 | [WM8915_WRITE_SEQUENCER_258] = 0x601, | ||
361 | [WM8915_WRITE_SEQUENCER_260] = 0x50, | ||
362 | [WM8915_WRITE_SEQUENCER_262] = 0x100, | ||
363 | [WM8915_WRITE_SEQUENCER_264] = 0x1, | ||
364 | [WM8915_WRITE_SEQUENCER_266] = 0x104, | ||
365 | [WM8915_WRITE_SEQUENCER_267] = 0x100, | ||
366 | [WM8915_WRITE_SEQUENCER_268] = 0x2fff, | ||
367 | [WM8915_WRITE_SEQUENCER_272] = 0x2fff, | ||
368 | [WM8915_WRITE_SEQUENCER_276] = 0x2fff, | ||
369 | [WM8915_WRITE_SEQUENCER_280] = 0x2fff, | ||
370 | [WM8915_WRITE_SEQUENCER_284] = 0x2fff, | ||
371 | [WM8915_WRITE_SEQUENCER_288] = 0x2fff, | ||
372 | [WM8915_WRITE_SEQUENCER_292] = 0x2fff, | ||
373 | [WM8915_WRITE_SEQUENCER_296] = 0x2fff, | ||
374 | [WM8915_WRITE_SEQUENCER_300] = 0x2fff, | ||
375 | [WM8915_WRITE_SEQUENCER_304] = 0x2fff, | ||
376 | [WM8915_WRITE_SEQUENCER_308] = 0x2fff, | ||
377 | [WM8915_WRITE_SEQUENCER_312] = 0x2fff, | ||
378 | [WM8915_WRITE_SEQUENCER_316] = 0x2fff, | ||
379 | [WM8915_WRITE_SEQUENCER_320] = 0x61, | ||
380 | [WM8915_WRITE_SEQUENCER_322] = 0x601, | ||
381 | [WM8915_WRITE_SEQUENCER_324] = 0x50, | ||
382 | [WM8915_WRITE_SEQUENCER_326] = 0x102, | ||
383 | [WM8915_WRITE_SEQUENCER_328] = 0x1, | ||
384 | [WM8915_WRITE_SEQUENCER_330] = 0x106, | ||
385 | [WM8915_WRITE_SEQUENCER_331] = 0x100, | ||
386 | [WM8915_WRITE_SEQUENCER_332] = 0x2fff, | ||
387 | [WM8915_WRITE_SEQUENCER_336] = 0x2fff, | ||
388 | [WM8915_WRITE_SEQUENCER_340] = 0x2fff, | ||
389 | [WM8915_WRITE_SEQUENCER_344] = 0x2fff, | ||
390 | [WM8915_WRITE_SEQUENCER_348] = 0x2fff, | ||
391 | [WM8915_WRITE_SEQUENCER_352] = 0x2fff, | ||
392 | [WM8915_WRITE_SEQUENCER_356] = 0x2fff, | ||
393 | [WM8915_WRITE_SEQUENCER_360] = 0x2fff, | ||
394 | [WM8915_WRITE_SEQUENCER_364] = 0x2fff, | ||
395 | [WM8915_WRITE_SEQUENCER_368] = 0x2fff, | ||
396 | [WM8915_WRITE_SEQUENCER_372] = 0x2fff, | ||
397 | [WM8915_WRITE_SEQUENCER_376] = 0x2fff, | ||
398 | [WM8915_WRITE_SEQUENCER_380] = 0x2fff, | ||
399 | [WM8915_WRITE_SEQUENCER_384] = 0x60, | ||
400 | [WM8915_WRITE_SEQUENCER_386] = 0x601, | ||
401 | [WM8915_WRITE_SEQUENCER_388] = 0x61, | ||
402 | [WM8915_WRITE_SEQUENCER_390] = 0x601, | ||
403 | [WM8915_WRITE_SEQUENCER_392] = 0x50, | ||
404 | [WM8915_WRITE_SEQUENCER_394] = 0x300, | ||
405 | [WM8915_WRITE_SEQUENCER_396] = 0x1, | ||
406 | [WM8915_WRITE_SEQUENCER_398] = 0x304, | ||
407 | [WM8915_WRITE_SEQUENCER_400] = 0x40, | ||
408 | [WM8915_WRITE_SEQUENCER_402] = 0xf, | ||
409 | [WM8915_WRITE_SEQUENCER_404] = 0x1, | ||
410 | [WM8915_WRITE_SEQUENCER_407] = 0x100, | ||
411 | }; | ||
412 | |||
413 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); | ||
414 | static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 150, 0); | ||
415 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | ||
416 | static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0); | ||
417 | static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); | ||
418 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); | ||
419 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
420 | |||
421 | static const char *sidetone_hpf_text[] = { | ||
422 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" | ||
423 | }; | ||
424 | |||
425 | static const struct soc_enum sidetone_hpf = | ||
426 | SOC_ENUM_SINGLE(WM8915_SIDETONE, 7, 6, sidetone_hpf_text); | ||
427 | |||
428 | static const char *hpf_mode_text[] = { | ||
429 | "HiFi", "Custom", "Voice" | ||
430 | }; | ||
431 | |||
432 | static const struct soc_enum dsp1tx_hpf_mode = | ||
433 | SOC_ENUM_SINGLE(WM8915_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); | ||
434 | |||
435 | static const struct soc_enum dsp2tx_hpf_mode = | ||
436 | SOC_ENUM_SINGLE(WM8915_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); | ||
437 | |||
438 | static const char *hpf_cutoff_text[] = { | ||
439 | "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | ||
440 | }; | ||
441 | |||
442 | static const struct soc_enum dsp1tx_hpf_cutoff = | ||
443 | SOC_ENUM_SINGLE(WM8915_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); | ||
444 | |||
445 | static const struct soc_enum dsp2tx_hpf_cutoff = | ||
446 | SOC_ENUM_SINGLE(WM8915_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); | ||
447 | |||
448 | static void wm8915_set_retune_mobile(struct snd_soc_codec *codec, int block) | ||
449 | { | ||
450 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
451 | struct wm8915_pdata *pdata = &wm8915->pdata; | ||
452 | int base, best, best_val, save, i, cfg, iface; | ||
453 | |||
454 | if (!wm8915->num_retune_mobile_texts) | ||
455 | return; | ||
456 | |||
457 | switch (block) { | ||
458 | case 0: | ||
459 | base = WM8915_DSP1_RX_EQ_GAINS_1; | ||
460 | if (snd_soc_read(codec, WM8915_POWER_MANAGEMENT_8) & | ||
461 | WM8915_DSP1RX_SRC) | ||
462 | iface = 1; | ||
463 | else | ||
464 | iface = 0; | ||
465 | break; | ||
466 | case 1: | ||
467 | base = WM8915_DSP1_RX_EQ_GAINS_2; | ||
468 | if (snd_soc_read(codec, WM8915_POWER_MANAGEMENT_8) & | ||
469 | WM8915_DSP2RX_SRC) | ||
470 | iface = 1; | ||
471 | else | ||
472 | iface = 0; | ||
473 | break; | ||
474 | default: | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | /* Find the version of the currently selected configuration | ||
479 | * with the nearest sample rate. */ | ||
480 | cfg = wm8915->retune_mobile_cfg[block]; | ||
481 | best = 0; | ||
482 | best_val = INT_MAX; | ||
483 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
484 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
485 | wm8915->retune_mobile_texts[cfg]) == 0 && | ||
486 | abs(pdata->retune_mobile_cfgs[i].rate | ||
487 | - wm8915->rx_rate[iface]) < best_val) { | ||
488 | best = i; | ||
489 | best_val = abs(pdata->retune_mobile_cfgs[i].rate | ||
490 | - wm8915->rx_rate[iface]); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n", | ||
495 | block, | ||
496 | pdata->retune_mobile_cfgs[best].name, | ||
497 | pdata->retune_mobile_cfgs[best].rate, | ||
498 | wm8915->rx_rate[iface]); | ||
499 | |||
500 | /* The EQ will be disabled while reconfiguring it, remember the | ||
501 | * current configuration. | ||
502 | */ | ||
503 | save = snd_soc_read(codec, base); | ||
504 | save &= WM8915_DSP1RX_EQ_ENA; | ||
505 | |||
506 | for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++) | ||
507 | snd_soc_update_bits(codec, base + i, 0xffff, | ||
508 | pdata->retune_mobile_cfgs[best].regs[i]); | ||
509 | |||
510 | snd_soc_update_bits(codec, base, WM8915_DSP1RX_EQ_ENA, save); | ||
511 | } | ||
512 | |||
513 | /* Icky as hell but saves code duplication */ | ||
514 | static int wm8915_get_retune_mobile_block(const char *name) | ||
515 | { | ||
516 | if (strcmp(name, "DSP1 EQ Mode") == 0) | ||
517 | return 0; | ||
518 | if (strcmp(name, "DSP2 EQ Mode") == 0) | ||
519 | return 1; | ||
520 | return -EINVAL; | ||
521 | } | ||
522 | |||
523 | static int wm8915_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
524 | struct snd_ctl_elem_value *ucontrol) | ||
525 | { | ||
526 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
527 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
528 | struct wm8915_pdata *pdata = &wm8915->pdata; | ||
529 | int block = wm8915_get_retune_mobile_block(kcontrol->id.name); | ||
530 | int value = ucontrol->value.integer.value[0]; | ||
531 | |||
532 | if (block < 0) | ||
533 | return block; | ||
534 | |||
535 | if (value >= pdata->num_retune_mobile_cfgs) | ||
536 | return -EINVAL; | ||
537 | |||
538 | wm8915->retune_mobile_cfg[block] = value; | ||
539 | |||
540 | wm8915_set_retune_mobile(codec, block); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int wm8915_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
546 | struct snd_ctl_elem_value *ucontrol) | ||
547 | { | ||
548 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
549 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
550 | int block = wm8915_get_retune_mobile_block(kcontrol->id.name); | ||
551 | |||
552 | ucontrol->value.enumerated.item[0] = wm8915->retune_mobile_cfg[block]; | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static const struct snd_kcontrol_new wm8915_snd_controls[] = { | ||
558 | SOC_DOUBLE_R_TLV("Capture Volume", WM8915_LEFT_LINE_INPUT_VOLUME, | ||
559 | WM8915_RIGHT_LINE_INPUT_VOLUME, 0, 31, 0, inpga_tlv), | ||
560 | SOC_DOUBLE_R("Capture ZC Switch", WM8915_LEFT_LINE_INPUT_VOLUME, | ||
561 | WM8915_RIGHT_LINE_INPUT_VOLUME, 5, 1, 0), | ||
562 | |||
563 | SOC_DOUBLE_TLV("DAC1 Sidetone Volume", WM8915_DAC1_MIXER_VOLUMES, | ||
564 | 0, 5, 24, 0, sidetone_tlv), | ||
565 | SOC_DOUBLE_TLV("DAC2 Sidetone Volume", WM8915_DAC2_MIXER_VOLUMES, | ||
566 | 0, 5, 24, 0, sidetone_tlv), | ||
567 | SOC_SINGLE("Sidetone LPF Switch", WM8915_SIDETONE, 12, 1, 0), | ||
568 | SOC_ENUM("Sidetone HPF Cut-off", sidetone_hpf), | ||
569 | SOC_SINGLE("Sidetone HPF Switch", WM8915_SIDETONE, 6, 1, 0), | ||
570 | |||
571 | SOC_DOUBLE_R_TLV("DSP1 Capture Volume", WM8915_DSP1_TX_LEFT_VOLUME, | ||
572 | WM8915_DSP1_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
573 | SOC_DOUBLE_R_TLV("DSP2 Capture Volume", WM8915_DSP2_TX_LEFT_VOLUME, | ||
574 | WM8915_DSP2_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
575 | |||
576 | SOC_SINGLE("DSP1 Capture Notch Filter Switch", WM8915_DSP1_TX_FILTERS, | ||
577 | 13, 1, 0), | ||
578 | SOC_DOUBLE("DSP1 Capture HPF Switch", WM8915_DSP1_TX_FILTERS, 12, 11, 1, 0), | ||
579 | SOC_ENUM("DSP1 Capture HPF Mode", dsp1tx_hpf_mode), | ||
580 | SOC_ENUM("DSP1 Capture HPF Cutoff", dsp1tx_hpf_cutoff), | ||
581 | |||
582 | SOC_SINGLE("DSP2 Capture Notch Filter Switch", WM8915_DSP2_TX_FILTERS, | ||
583 | 13, 1, 0), | ||
584 | SOC_DOUBLE("DSP2 Capture HPF Switch", WM8915_DSP2_TX_FILTERS, 12, 11, 1, 0), | ||
585 | SOC_ENUM("DSP2 Capture HPF Mode", dsp2tx_hpf_mode), | ||
586 | SOC_ENUM("DSP2 Capture HPF Cutoff", dsp2tx_hpf_cutoff), | ||
587 | |||
588 | SOC_DOUBLE_R_TLV("DSP1 Playback Volume", WM8915_DSP1_RX_LEFT_VOLUME, | ||
589 | WM8915_DSP1_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv), | ||
590 | SOC_SINGLE("DSP1 Playback Switch", WM8915_DSP1_RX_FILTERS_1, 9, 1, 1), | ||
591 | |||
592 | SOC_DOUBLE_R_TLV("DSP2 Playback Volume", WM8915_DSP2_RX_LEFT_VOLUME, | ||
593 | WM8915_DSP2_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv), | ||
594 | SOC_SINGLE("DSP2 Playback Switch", WM8915_DSP2_RX_FILTERS_1, 9, 1, 1), | ||
595 | |||
596 | SOC_DOUBLE_R_TLV("DAC1 Volume", WM8915_DAC1_LEFT_VOLUME, | ||
597 | WM8915_DAC1_RIGHT_VOLUME, 1, 112, 0, digital_tlv), | ||
598 | SOC_DOUBLE_R("DAC1 Switch", WM8915_DAC1_LEFT_VOLUME, | ||
599 | WM8915_DAC1_RIGHT_VOLUME, 9, 1, 1), | ||
600 | |||
601 | SOC_DOUBLE_R_TLV("DAC2 Volume", WM8915_DAC2_LEFT_VOLUME, | ||
602 | WM8915_DAC2_RIGHT_VOLUME, 1, 112, 0, digital_tlv), | ||
603 | SOC_DOUBLE_R("DAC2 Switch", WM8915_DAC2_LEFT_VOLUME, | ||
604 | WM8915_DAC2_RIGHT_VOLUME, 9, 1, 1), | ||
605 | |||
606 | SOC_SINGLE("Speaker High Performance Switch", WM8915_OVERSAMPLING, 3, 1, 0), | ||
607 | SOC_SINGLE("DMIC High Performance Switch", WM8915_OVERSAMPLING, 2, 1, 0), | ||
608 | SOC_SINGLE("ADC High Performance Switch", WM8915_OVERSAMPLING, 1, 1, 0), | ||
609 | SOC_SINGLE("DAC High Performance Switch", WM8915_OVERSAMPLING, 0, 1, 0), | ||
610 | |||
611 | SOC_SINGLE("DAC Soft Mute Switch", WM8915_DAC_SOFTMUTE, 1, 1, 0), | ||
612 | SOC_SINGLE("DAC Slow Soft Mute Switch", WM8915_DAC_SOFTMUTE, 0, 1, 0), | ||
613 | |||
614 | SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8915_DAC1_HPOUT1_VOLUME, 0, 4, | ||
615 | 8, 0, out_digital_tlv), | ||
616 | SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8915_DAC2_HPOUT2_VOLUME, 0, 4, | ||
617 | 8, 0, out_digital_tlv), | ||
618 | |||
619 | SOC_DOUBLE_R_TLV("Output 1 Volume", WM8915_OUTPUT1_LEFT_VOLUME, | ||
620 | WM8915_OUTPUT1_RIGHT_VOLUME, 0, 12, 0, out_tlv), | ||
621 | SOC_DOUBLE_R("Output 1 ZC Switch", WM8915_OUTPUT1_LEFT_VOLUME, | ||
622 | WM8915_OUTPUT1_RIGHT_VOLUME, 7, 1, 0), | ||
623 | |||
624 | SOC_DOUBLE_R_TLV("Output 2 Volume", WM8915_OUTPUT2_LEFT_VOLUME, | ||
625 | WM8915_OUTPUT2_RIGHT_VOLUME, 0, 12, 0, out_tlv), | ||
626 | SOC_DOUBLE_R("Output 2 ZC Switch", WM8915_OUTPUT2_LEFT_VOLUME, | ||
627 | WM8915_OUTPUT2_RIGHT_VOLUME, 7, 1, 0), | ||
628 | |||
629 | SOC_DOUBLE_TLV("Speaker Volume", WM8915_PDM_SPEAKER_VOLUME, 0, 4, 8, 0, | ||
630 | spk_tlv), | ||
631 | SOC_DOUBLE_R("Speaker Switch", WM8915_LEFT_PDM_SPEAKER, | ||
632 | WM8915_RIGHT_PDM_SPEAKER, 3, 1, 1), | ||
633 | SOC_DOUBLE_R("Speaker ZC Switch", WM8915_LEFT_PDM_SPEAKER, | ||
634 | WM8915_RIGHT_PDM_SPEAKER, 2, 1, 0), | ||
635 | |||
636 | SOC_SINGLE("DSP1 EQ Switch", WM8915_DSP1_RX_EQ_GAINS_1, 0, 1, 0), | ||
637 | SOC_SINGLE("DSP2 EQ Switch", WM8915_DSP2_RX_EQ_GAINS_1, 0, 1, 0), | ||
638 | }; | ||
639 | |||
640 | static const struct snd_kcontrol_new wm8915_eq_controls[] = { | ||
641 | SOC_SINGLE_TLV("DSP1 EQ B1 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 11, 31, 0, | ||
642 | eq_tlv), | ||
643 | SOC_SINGLE_TLV("DSP1 EQ B2 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 6, 31, 0, | ||
644 | eq_tlv), | ||
645 | SOC_SINGLE_TLV("DSP1 EQ B3 Volume", WM8915_DSP1_RX_EQ_GAINS_1, 1, 31, 0, | ||
646 | eq_tlv), | ||
647 | SOC_SINGLE_TLV("DSP1 EQ B4 Volume", WM8915_DSP1_RX_EQ_GAINS_2, 11, 31, 0, | ||
648 | eq_tlv), | ||
649 | SOC_SINGLE_TLV("DSP1 EQ B5 Volume", WM8915_DSP1_RX_EQ_GAINS_2, 6, 31, 0, | ||
650 | eq_tlv), | ||
651 | |||
652 | SOC_SINGLE_TLV("DSP2 EQ B1 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 11, 31, 0, | ||
653 | eq_tlv), | ||
654 | SOC_SINGLE_TLV("DSP2 EQ B2 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 6, 31, 0, | ||
655 | eq_tlv), | ||
656 | SOC_SINGLE_TLV("DSP2 EQ B3 Volume", WM8915_DSP2_RX_EQ_GAINS_1, 1, 31, 0, | ||
657 | eq_tlv), | ||
658 | SOC_SINGLE_TLV("DSP2 EQ B4 Volume", WM8915_DSP2_RX_EQ_GAINS_2, 11, 31, 0, | ||
659 | eq_tlv), | ||
660 | SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8915_DSP2_RX_EQ_GAINS_2, 6, 31, 0, | ||
661 | eq_tlv), | ||
662 | }; | ||
663 | |||
664 | static int cp_event(struct snd_soc_dapm_widget *w, | ||
665 | struct snd_kcontrol *kcontrol, int event) | ||
666 | { | ||
667 | switch (event) { | ||
668 | case SND_SOC_DAPM_POST_PMU: | ||
669 | msleep(5); | ||
670 | break; | ||
671 | default: | ||
672 | BUG(); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int rmv_short_event(struct snd_soc_dapm_widget *w, | ||
680 | struct snd_kcontrol *kcontrol, int event) | ||
681 | { | ||
682 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(w->codec); | ||
683 | |||
684 | /* Record which outputs we enabled */ | ||
685 | switch (event) { | ||
686 | case SND_SOC_DAPM_PRE_PMD: | ||
687 | wm8915->hpout_pending &= ~w->shift; | ||
688 | break; | ||
689 | case SND_SOC_DAPM_PRE_PMU: | ||
690 | wm8915->hpout_pending |= w->shift; | ||
691 | break; | ||
692 | default: | ||
693 | BUG(); | ||
694 | return -EINVAL; | ||
695 | } | ||
696 | |||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | ||
701 | { | ||
702 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
703 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
704 | int i, ret; | ||
705 | unsigned long timeout = 200; | ||
706 | |||
707 | snd_soc_write(codec, WM8915_DC_SERVO_2, mask); | ||
708 | |||
709 | /* Use the interrupt if possible */ | ||
710 | do { | ||
711 | if (i2c->irq) { | ||
712 | timeout = wait_for_completion_timeout(&wm8915->dcs_done, | ||
713 | msecs_to_jiffies(200)); | ||
714 | if (timeout == 0) | ||
715 | dev_err(codec->dev, "DC servo timed out\n"); | ||
716 | |||
717 | } else { | ||
718 | msleep(1); | ||
719 | if (--i) { | ||
720 | timeout = 0; | ||
721 | break; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | ret = snd_soc_read(codec, WM8915_DC_SERVO_2); | ||
726 | dev_dbg(codec->dev, "DC servo state: %x\n", ret); | ||
727 | } while (ret & mask); | ||
728 | |||
729 | if (timeout == 0) | ||
730 | dev_err(codec->dev, "DC servo timed out for %x\n", mask); | ||
731 | else | ||
732 | dev_dbg(codec->dev, "DC servo complete for %x\n", mask); | ||
733 | } | ||
734 | |||
735 | static void wm8915_seq_notifier(struct snd_soc_dapm_context *dapm, | ||
736 | enum snd_soc_dapm_type event, int subseq) | ||
737 | { | ||
738 | struct snd_soc_codec *codec = container_of(dapm, | ||
739 | struct snd_soc_codec, dapm); | ||
740 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
741 | u16 val, mask; | ||
742 | |||
743 | /* Complete any pending DC servo starts */ | ||
744 | if (wm8915->dcs_pending) { | ||
745 | dev_dbg(codec->dev, "Starting DC servo for %x\n", | ||
746 | wm8915->dcs_pending); | ||
747 | |||
748 | /* Trigger a startup sequence */ | ||
749 | wait_for_dc_servo(codec, wm8915->dcs_pending | ||
750 | << WM8915_DCS_TRIG_STARTUP_0_SHIFT); | ||
751 | |||
752 | wm8915->dcs_pending = 0; | ||
753 | } | ||
754 | |||
755 | if (wm8915->hpout_pending != wm8915->hpout_ena) { | ||
756 | dev_dbg(codec->dev, "Applying RMV_SHORTs %x->%x\n", | ||
757 | wm8915->hpout_ena, wm8915->hpout_pending); | ||
758 | |||
759 | val = 0; | ||
760 | mask = 0; | ||
761 | if (wm8915->hpout_pending & HPOUT1L) { | ||
762 | val |= WM8915_HPOUT1L_RMV_SHORT; | ||
763 | mask |= WM8915_HPOUT1L_RMV_SHORT; | ||
764 | } else { | ||
765 | mask |= WM8915_HPOUT1L_RMV_SHORT | | ||
766 | WM8915_HPOUT1L_OUTP | | ||
767 | WM8915_HPOUT1L_DLY; | ||
768 | } | ||
769 | |||
770 | if (wm8915->hpout_pending & HPOUT1R) { | ||
771 | val |= WM8915_HPOUT1R_RMV_SHORT; | ||
772 | mask |= WM8915_HPOUT1R_RMV_SHORT; | ||
773 | } else { | ||
774 | mask |= WM8915_HPOUT1R_RMV_SHORT | | ||
775 | WM8915_HPOUT1R_OUTP | | ||
776 | WM8915_HPOUT1R_DLY; | ||
777 | } | ||
778 | |||
779 | snd_soc_update_bits(codec, WM8915_ANALOGUE_HP_1, mask, val); | ||
780 | |||
781 | val = 0; | ||
782 | mask = 0; | ||
783 | if (wm8915->hpout_pending & HPOUT2L) { | ||
784 | val |= WM8915_HPOUT2L_RMV_SHORT; | ||
785 | mask |= WM8915_HPOUT2L_RMV_SHORT; | ||
786 | } else { | ||
787 | mask |= WM8915_HPOUT2L_RMV_SHORT | | ||
788 | WM8915_HPOUT2L_OUTP | | ||
789 | WM8915_HPOUT2L_DLY; | ||
790 | } | ||
791 | |||
792 | if (wm8915->hpout_pending & HPOUT2R) { | ||
793 | val |= WM8915_HPOUT2R_RMV_SHORT; | ||
794 | mask |= WM8915_HPOUT2R_RMV_SHORT; | ||
795 | } else { | ||
796 | mask |= WM8915_HPOUT2R_RMV_SHORT | | ||
797 | WM8915_HPOUT2R_OUTP | | ||
798 | WM8915_HPOUT2R_DLY; | ||
799 | } | ||
800 | |||
801 | snd_soc_update_bits(codec, WM8915_ANALOGUE_HP_2, mask, val); | ||
802 | |||
803 | wm8915->hpout_ena = wm8915->hpout_pending; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | static int dcs_start(struct snd_soc_dapm_widget *w, | ||
808 | struct snd_kcontrol *kcontrol, int event) | ||
809 | { | ||
810 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(w->codec); | ||
811 | |||
812 | switch (event) { | ||
813 | case SND_SOC_DAPM_POST_PMU: | ||
814 | wm8915->dcs_pending |= 1 << w->shift; | ||
815 | break; | ||
816 | default: | ||
817 | BUG(); | ||
818 | return -EINVAL; | ||
819 | } | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | static const char *sidetone_text[] = { | ||
825 | "IN1", "IN2", | ||
826 | }; | ||
827 | |||
828 | static const struct soc_enum left_sidetone_enum = | ||
829 | SOC_ENUM_SINGLE(WM8915_SIDETONE, 0, 2, sidetone_text); | ||
830 | |||
831 | static const struct snd_kcontrol_new left_sidetone = | ||
832 | SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); | ||
833 | |||
834 | static const struct soc_enum right_sidetone_enum = | ||
835 | SOC_ENUM_SINGLE(WM8915_SIDETONE, 1, 2, sidetone_text); | ||
836 | |||
837 | static const struct snd_kcontrol_new right_sidetone = | ||
838 | SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); | ||
839 | |||
840 | static const char *spk_text[] = { | ||
841 | "DAC1L", "DAC1R", "DAC2L", "DAC2R" | ||
842 | }; | ||
843 | |||
844 | static const struct soc_enum spkl_enum = | ||
845 | SOC_ENUM_SINGLE(WM8915_LEFT_PDM_SPEAKER, 0, 4, spk_text); | ||
846 | |||
847 | static const struct snd_kcontrol_new spkl_mux = | ||
848 | SOC_DAPM_ENUM("SPKL", spkl_enum); | ||
849 | |||
850 | static const struct soc_enum spkr_enum = | ||
851 | SOC_ENUM_SINGLE(WM8915_RIGHT_PDM_SPEAKER, 0, 4, spk_text); | ||
852 | |||
853 | static const struct snd_kcontrol_new spkr_mux = | ||
854 | SOC_DAPM_ENUM("SPKR", spkr_enum); | ||
855 | |||
856 | static const char *dsp1rx_text[] = { | ||
857 | "AIF1", "AIF2" | ||
858 | }; | ||
859 | |||
860 | static const struct soc_enum dsp1rx_enum = | ||
861 | SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); | ||
862 | |||
863 | static const struct snd_kcontrol_new dsp1rx = | ||
864 | SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); | ||
865 | |||
866 | static const char *dsp2rx_text[] = { | ||
867 | "AIF2", "AIF1" | ||
868 | }; | ||
869 | |||
870 | static const struct soc_enum dsp2rx_enum = | ||
871 | SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); | ||
872 | |||
873 | static const struct snd_kcontrol_new dsp2rx = | ||
874 | SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); | ||
875 | |||
876 | static const char *aif2tx_text[] = { | ||
877 | "DSP2", "DSP1", "AIF1" | ||
878 | }; | ||
879 | |||
880 | static const struct soc_enum aif2tx_enum = | ||
881 | SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); | ||
882 | |||
883 | static const struct snd_kcontrol_new aif2tx = | ||
884 | SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); | ||
885 | |||
886 | static const char *inmux_text[] = { | ||
887 | "ADC", "DMIC1", "DMIC2" | ||
888 | }; | ||
889 | |||
890 | static const struct soc_enum in1_enum = | ||
891 | SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_7, 0, 3, inmux_text); | ||
892 | |||
893 | static const struct snd_kcontrol_new in1_mux = | ||
894 | SOC_DAPM_ENUM("IN1 Mux", in1_enum); | ||
895 | |||
896 | static const struct soc_enum in2_enum = | ||
897 | SOC_ENUM_SINGLE(WM8915_POWER_MANAGEMENT_7, 4, 3, inmux_text); | ||
898 | |||
899 | static const struct snd_kcontrol_new in2_mux = | ||
900 | SOC_DAPM_ENUM("IN2 Mux", in2_enum); | ||
901 | |||
902 | static const struct snd_kcontrol_new dac2r_mix[] = { | ||
903 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, | ||
904 | 5, 1, 0), | ||
905 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, | ||
906 | 4, 1, 0), | ||
907 | SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, 1, 1, 0), | ||
908 | SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC2_RIGHT_MIXER_ROUTING, 0, 1, 0), | ||
909 | }; | ||
910 | |||
911 | static const struct snd_kcontrol_new dac2l_mix[] = { | ||
912 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, | ||
913 | 5, 1, 0), | ||
914 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, | ||
915 | 4, 1, 0), | ||
916 | SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, 1, 1, 0), | ||
917 | SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC2_LEFT_MIXER_ROUTING, 0, 1, 0), | ||
918 | }; | ||
919 | |||
920 | static const struct snd_kcontrol_new dac1r_mix[] = { | ||
921 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, | ||
922 | 5, 1, 0), | ||
923 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, | ||
924 | 4, 1, 0), | ||
925 | SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, 1, 1, 0), | ||
926 | SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC1_RIGHT_MIXER_ROUTING, 0, 1, 0), | ||
927 | }; | ||
928 | |||
929 | static const struct snd_kcontrol_new dac1l_mix[] = { | ||
930 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, | ||
931 | 5, 1, 0), | ||
932 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, | ||
933 | 4, 1, 0), | ||
934 | SOC_DAPM_SINGLE("DSP2 Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, 1, 1, 0), | ||
935 | SOC_DAPM_SINGLE("DSP1 Switch", WM8915_DAC1_LEFT_MIXER_ROUTING, 0, 1, 0), | ||
936 | }; | ||
937 | |||
938 | static const struct snd_kcontrol_new dsp1txl[] = { | ||
939 | SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP1_TX_LEFT_MIXER_ROUTING, | ||
940 | 1, 1, 0), | ||
941 | SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP1_TX_LEFT_MIXER_ROUTING, | ||
942 | 0, 1, 0), | ||
943 | }; | ||
944 | |||
945 | static const struct snd_kcontrol_new dsp1txr[] = { | ||
946 | SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP1_TX_RIGHT_MIXER_ROUTING, | ||
947 | 1, 1, 0), | ||
948 | SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP1_TX_RIGHT_MIXER_ROUTING, | ||
949 | 0, 1, 0), | ||
950 | }; | ||
951 | |||
952 | static const struct snd_kcontrol_new dsp2txl[] = { | ||
953 | SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP2_TX_LEFT_MIXER_ROUTING, | ||
954 | 1, 1, 0), | ||
955 | SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP2_TX_LEFT_MIXER_ROUTING, | ||
956 | 0, 1, 0), | ||
957 | }; | ||
958 | |||
959 | static const struct snd_kcontrol_new dsp2txr[] = { | ||
960 | SOC_DAPM_SINGLE("IN1 Switch", WM8915_DSP2_TX_RIGHT_MIXER_ROUTING, | ||
961 | 1, 1, 0), | ||
962 | SOC_DAPM_SINGLE("DAC Switch", WM8915_DSP2_TX_RIGHT_MIXER_ROUTING, | ||
963 | 0, 1, 0), | ||
964 | }; | ||
965 | |||
966 | |||
967 | static const struct snd_soc_dapm_widget wm8915_dapm_widgets[] = { | ||
968 | SND_SOC_DAPM_INPUT("IN1LN"), | ||
969 | SND_SOC_DAPM_INPUT("IN1LP"), | ||
970 | SND_SOC_DAPM_INPUT("IN1RN"), | ||
971 | SND_SOC_DAPM_INPUT("IN1RP"), | ||
972 | |||
973 | SND_SOC_DAPM_INPUT("IN2LN"), | ||
974 | SND_SOC_DAPM_INPUT("IN2LP"), | ||
975 | SND_SOC_DAPM_INPUT("IN2RN"), | ||
976 | SND_SOC_DAPM_INPUT("IN2RP"), | ||
977 | |||
978 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | ||
979 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | ||
980 | |||
981 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8915_AIF_CLOCKING_1, 0, 0, NULL, 0), | ||
982 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8915_CLOCKING_1, 1, 0, NULL, 0), | ||
983 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8915_CLOCKING_1, 2, 0, NULL, 0), | ||
984 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8915_CHARGE_PUMP_1, 15, 0, cp_event, | ||
985 | SND_SOC_DAPM_POST_PMU), | ||
986 | |||
987 | SND_SOC_DAPM_SUPPLY("LDO2", WM8915_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | ||
988 | SND_SOC_DAPM_MICBIAS("MICB2", WM8915_POWER_MANAGEMENT_1, 9, 0), | ||
989 | SND_SOC_DAPM_MICBIAS("MICB1", WM8915_POWER_MANAGEMENT_1, 8, 0), | ||
990 | |||
991 | SND_SOC_DAPM_PGA("IN1L PGA", WM8915_POWER_MANAGEMENT_2, 5, 0, NULL, 0), | ||
992 | SND_SOC_DAPM_PGA("IN1R PGA", WM8915_POWER_MANAGEMENT_2, 4, 0, NULL, 0), | ||
993 | |||
994 | SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &in1_mux), | ||
995 | SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &in1_mux), | ||
996 | SND_SOC_DAPM_MUX("IN2L Mux", SND_SOC_NOPM, 0, 0, &in2_mux), | ||
997 | SND_SOC_DAPM_MUX("IN2R Mux", SND_SOC_NOPM, 0, 0, &in2_mux), | ||
998 | |||
999 | SND_SOC_DAPM_PGA("IN1L", WM8915_POWER_MANAGEMENT_7, 2, 0, NULL, 0), | ||
1000 | SND_SOC_DAPM_PGA("IN1R", WM8915_POWER_MANAGEMENT_7, 3, 0, NULL, 0), | ||
1001 | SND_SOC_DAPM_PGA("IN2L", WM8915_POWER_MANAGEMENT_7, 6, 0, NULL, 0), | ||
1002 | SND_SOC_DAPM_PGA("IN2R", WM8915_POWER_MANAGEMENT_7, 7, 0, NULL, 0), | ||
1003 | |||
1004 | SND_SOC_DAPM_SUPPLY("DMIC2", WM8915_POWER_MANAGEMENT_7, 9, 0, NULL, 0), | ||
1005 | SND_SOC_DAPM_SUPPLY("DMIC1", WM8915_POWER_MANAGEMENT_7, 8, 0, NULL, 0), | ||
1006 | |||
1007 | SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8915_POWER_MANAGEMENT_3, 5, 0), | ||
1008 | SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8915_POWER_MANAGEMENT_3, 4, 0), | ||
1009 | SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8915_POWER_MANAGEMENT_3, 3, 0), | ||
1010 | SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8915_POWER_MANAGEMENT_3, 2, 0), | ||
1011 | |||
1012 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8915_POWER_MANAGEMENT_3, 1, 0), | ||
1013 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8915_POWER_MANAGEMENT_3, 0, 0), | ||
1014 | |||
1015 | SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &left_sidetone), | ||
1016 | SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &right_sidetone), | ||
1017 | |||
1018 | SND_SOC_DAPM_AIF_IN("DSP2RXL", NULL, 0, WM8915_POWER_MANAGEMENT_3, 11, 0), | ||
1019 | SND_SOC_DAPM_AIF_IN("DSP2RXR", NULL, 1, WM8915_POWER_MANAGEMENT_3, 10, 0), | ||
1020 | SND_SOC_DAPM_AIF_IN("DSP1RXL", NULL, 0, WM8915_POWER_MANAGEMENT_3, 9, 0), | ||
1021 | SND_SOC_DAPM_AIF_IN("DSP1RXR", NULL, 1, WM8915_POWER_MANAGEMENT_3, 8, 0), | ||
1022 | |||
1023 | SND_SOC_DAPM_MIXER("DSP2TXL", WM8915_POWER_MANAGEMENT_5, 11, 0, | ||
1024 | dsp2txl, ARRAY_SIZE(dsp2txl)), | ||
1025 | SND_SOC_DAPM_MIXER("DSP2TXR", WM8915_POWER_MANAGEMENT_5, 10, 0, | ||
1026 | dsp2txr, ARRAY_SIZE(dsp2txr)), | ||
1027 | SND_SOC_DAPM_MIXER("DSP1TXL", WM8915_POWER_MANAGEMENT_5, 9, 0, | ||
1028 | dsp1txl, ARRAY_SIZE(dsp1txl)), | ||
1029 | SND_SOC_DAPM_MIXER("DSP1TXR", WM8915_POWER_MANAGEMENT_5, 8, 0, | ||
1030 | dsp1txr, ARRAY_SIZE(dsp1txr)), | ||
1031 | |||
1032 | SND_SOC_DAPM_MIXER("DAC2L Mixer", SND_SOC_NOPM, 0, 0, | ||
1033 | dac2l_mix, ARRAY_SIZE(dac2l_mix)), | ||
1034 | SND_SOC_DAPM_MIXER("DAC2R Mixer", SND_SOC_NOPM, 0, 0, | ||
1035 | dac2r_mix, ARRAY_SIZE(dac2r_mix)), | ||
1036 | SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0, | ||
1037 | dac1l_mix, ARRAY_SIZE(dac1l_mix)), | ||
1038 | SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0, | ||
1039 | dac1r_mix, ARRAY_SIZE(dac1r_mix)), | ||
1040 | |||
1041 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8915_POWER_MANAGEMENT_5, 3, 0), | ||
1042 | SND_SOC_DAPM_DAC("DAC2R", NULL, WM8915_POWER_MANAGEMENT_5, 2, 0), | ||
1043 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8915_POWER_MANAGEMENT_5, 1, 0), | ||
1044 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8915_POWER_MANAGEMENT_5, 0, 0), | ||
1045 | |||
1046 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1, | ||
1047 | WM8915_POWER_MANAGEMENT_4, 9, 0), | ||
1048 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2, | ||
1049 | WM8915_POWER_MANAGEMENT_4, 8, 0), | ||
1050 | |||
1051 | SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1, | ||
1052 | WM8915_POWER_MANAGEMENT_6, 9, 0), | ||
1053 | SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2, | ||
1054 | WM8915_POWER_MANAGEMENT_6, 8, 0), | ||
1055 | |||
1056 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, | ||
1057 | WM8915_POWER_MANAGEMENT_4, 5, 0), | ||
1058 | SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4, | ||
1059 | WM8915_POWER_MANAGEMENT_4, 4, 0), | ||
1060 | SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3, | ||
1061 | WM8915_POWER_MANAGEMENT_4, 3, 0), | ||
1062 | SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2, | ||
1063 | WM8915_POWER_MANAGEMENT_4, 2, 0), | ||
1064 | SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1, | ||
1065 | WM8915_POWER_MANAGEMENT_4, 1, 0), | ||
1066 | SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0, | ||
1067 | WM8915_POWER_MANAGEMENT_4, 0, 0), | ||
1068 | |||
1069 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5, | ||
1070 | WM8915_POWER_MANAGEMENT_6, 5, 0), | ||
1071 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4, | ||
1072 | WM8915_POWER_MANAGEMENT_6, 4, 0), | ||
1073 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3, | ||
1074 | WM8915_POWER_MANAGEMENT_6, 3, 0), | ||
1075 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2, | ||
1076 | WM8915_POWER_MANAGEMENT_6, 2, 0), | ||
1077 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1, | ||
1078 | WM8915_POWER_MANAGEMENT_6, 1, 0), | ||
1079 | SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0, | ||
1080 | WM8915_POWER_MANAGEMENT_6, 0, 0), | ||
1081 | |||
1082 | /* We route as stereo pairs so define some dummy widgets to squash | ||
1083 | * things down for now. RXA = 0,1, RXB = 2,3 and so on */ | ||
1084 | SND_SOC_DAPM_PGA("AIF1RXA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1085 | SND_SOC_DAPM_PGA("AIF1RXB", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1086 | SND_SOC_DAPM_PGA("AIF1RXC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1087 | SND_SOC_DAPM_PGA("AIF2RX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1088 | SND_SOC_DAPM_PGA("DSP2TX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1089 | |||
1090 | SND_SOC_DAPM_MUX("DSP1RX", SND_SOC_NOPM, 0, 0, &dsp1rx), | ||
1091 | SND_SOC_DAPM_MUX("DSP2RX", SND_SOC_NOPM, 0, 0, &dsp2rx), | ||
1092 | SND_SOC_DAPM_MUX("AIF2TX", SND_SOC_NOPM, 0, 0, &aif2tx), | ||
1093 | |||
1094 | SND_SOC_DAPM_MUX("SPKL", SND_SOC_NOPM, 0, 0, &spkl_mux), | ||
1095 | SND_SOC_DAPM_MUX("SPKR", SND_SOC_NOPM, 0, 0, &spkr_mux), | ||
1096 | SND_SOC_DAPM_PGA("SPKL PGA", WM8915_LEFT_PDM_SPEAKER, 4, 0, NULL, 0), | ||
1097 | SND_SOC_DAPM_PGA("SPKR PGA", WM8915_RIGHT_PDM_SPEAKER, 4, 0, NULL, 0), | ||
1098 | |||
1099 | SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8915_POWER_MANAGEMENT_1, 7, 0, NULL, 0), | ||
1100 | SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8915_ANALOGUE_HP_2, 5, 0, NULL, 0), | ||
1101 | SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8915_DC_SERVO_1, 2, 0, dcs_start, | ||
1102 | SND_SOC_DAPM_POST_PMU), | ||
1103 | SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8915_ANALOGUE_HP_2, 6, 0, NULL, 0), | ||
1104 | SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0, | ||
1105 | rmv_short_event, | ||
1106 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
1107 | |||
1108 | SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8915_POWER_MANAGEMENT_1, 6, 0,NULL, 0), | ||
1109 | SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8915_ANALOGUE_HP_2, 1, 0, NULL, 0), | ||
1110 | SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8915_DC_SERVO_1, 3, 0, dcs_start, | ||
1111 | SND_SOC_DAPM_POST_PMU), | ||
1112 | SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8915_ANALOGUE_HP_2, 2, 0, NULL, 0), | ||
1113 | SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0, | ||
1114 | rmv_short_event, | ||
1115 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
1116 | |||
1117 | SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8915_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | ||
1118 | SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8915_ANALOGUE_HP_1, 5, 0, NULL, 0), | ||
1119 | SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8915_DC_SERVO_1, 0, 0, dcs_start, | ||
1120 | SND_SOC_DAPM_POST_PMU), | ||
1121 | SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8915_ANALOGUE_HP_1, 6, 0, NULL, 0), | ||
1122 | SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0, | ||
1123 | rmv_short_event, | ||
1124 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
1125 | |||
1126 | SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8915_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | ||
1127 | SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8915_ANALOGUE_HP_1, 1, 0, NULL, 0), | ||
1128 | SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8915_DC_SERVO_1, 1, 0, dcs_start, | ||
1129 | SND_SOC_DAPM_POST_PMU), | ||
1130 | SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8915_ANALOGUE_HP_1, 2, 0, NULL, 0), | ||
1131 | SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0, | ||
1132 | rmv_short_event, | ||
1133 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
1134 | |||
1135 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | ||
1136 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | ||
1137 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | ||
1138 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | ||
1139 | SND_SOC_DAPM_OUTPUT("SPKDAT"), | ||
1140 | }; | ||
1141 | |||
1142 | static const struct snd_soc_dapm_route wm8915_dapm_routes[] = { | ||
1143 | { "AIFCLK", NULL, "SYSCLK" }, | ||
1144 | { "SYSDSPCLK", NULL, "SYSCLK" }, | ||
1145 | { "Charge Pump", NULL, "SYSCLK" }, | ||
1146 | |||
1147 | { "MICB1", NULL, "LDO2" }, | ||
1148 | { "MICB2", NULL, "LDO2" }, | ||
1149 | |||
1150 | { "IN1L PGA", NULL, "IN2LN" }, | ||
1151 | { "IN1L PGA", NULL, "IN2LP" }, | ||
1152 | { "IN1L PGA", NULL, "IN1LN" }, | ||
1153 | { "IN1L PGA", NULL, "IN1LP" }, | ||
1154 | |||
1155 | { "IN1R PGA", NULL, "IN2RN" }, | ||
1156 | { "IN1R PGA", NULL, "IN2RP" }, | ||
1157 | { "IN1R PGA", NULL, "IN1RN" }, | ||
1158 | { "IN1R PGA", NULL, "IN1RP" }, | ||
1159 | |||
1160 | { "ADCL", NULL, "IN1L PGA" }, | ||
1161 | |||
1162 | { "ADCR", NULL, "IN1R PGA" }, | ||
1163 | |||
1164 | { "DMIC1L", NULL, "DMIC1DAT" }, | ||
1165 | { "DMIC1R", NULL, "DMIC1DAT" }, | ||
1166 | { "DMIC2L", NULL, "DMIC2DAT" }, | ||
1167 | { "DMIC2R", NULL, "DMIC2DAT" }, | ||
1168 | |||
1169 | { "DMIC2L", NULL, "DMIC2" }, | ||
1170 | { "DMIC2R", NULL, "DMIC2" }, | ||
1171 | { "DMIC1L", NULL, "DMIC1" }, | ||
1172 | { "DMIC1R", NULL, "DMIC1" }, | ||
1173 | |||
1174 | { "IN1L Mux", "ADC", "ADCL" }, | ||
1175 | { "IN1L Mux", "DMIC1", "DMIC1L" }, | ||
1176 | { "IN1L Mux", "DMIC2", "DMIC2L" }, | ||
1177 | |||
1178 | { "IN1R Mux", "ADC", "ADCR" }, | ||
1179 | { "IN1R Mux", "DMIC1", "DMIC1R" }, | ||
1180 | { "IN1R Mux", "DMIC2", "DMIC2R" }, | ||
1181 | |||
1182 | { "IN2L Mux", "ADC", "ADCL" }, | ||
1183 | { "IN2L Mux", "DMIC1", "DMIC1L" }, | ||
1184 | { "IN2L Mux", "DMIC2", "DMIC2L" }, | ||
1185 | |||
1186 | { "IN2R Mux", "ADC", "ADCR" }, | ||
1187 | { "IN2R Mux", "DMIC1", "DMIC1R" }, | ||
1188 | { "IN2R Mux", "DMIC2", "DMIC2R" }, | ||
1189 | |||
1190 | { "Left Sidetone", "IN1", "IN1L Mux" }, | ||
1191 | { "Left Sidetone", "IN2", "IN2L Mux" }, | ||
1192 | |||
1193 | { "Right Sidetone", "IN1", "IN1R Mux" }, | ||
1194 | { "Right Sidetone", "IN2", "IN2R Mux" }, | ||
1195 | |||
1196 | { "DSP1TXL", "IN1 Switch", "IN1L Mux" }, | ||
1197 | { "DSP1TXR", "IN1 Switch", "IN1R Mux" }, | ||
1198 | |||
1199 | { "DSP2TXL", "IN1 Switch", "IN2L Mux" }, | ||
1200 | { "DSP2TXR", "IN1 Switch", "IN2R Mux" }, | ||
1201 | |||
1202 | { "AIF1TX0", NULL, "DSP1TXL" }, | ||
1203 | { "AIF1TX1", NULL, "DSP1TXR" }, | ||
1204 | { "AIF1TX2", NULL, "DSP2TXL" }, | ||
1205 | { "AIF1TX3", NULL, "DSP2TXR" }, | ||
1206 | { "AIF1TX4", NULL, "AIF2RX0" }, | ||
1207 | { "AIF1TX5", NULL, "AIF2RX1" }, | ||
1208 | |||
1209 | { "AIF1RX0", NULL, "AIFCLK" }, | ||
1210 | { "AIF1RX1", NULL, "AIFCLK" }, | ||
1211 | { "AIF1RX2", NULL, "AIFCLK" }, | ||
1212 | { "AIF1RX3", NULL, "AIFCLK" }, | ||
1213 | { "AIF1RX4", NULL, "AIFCLK" }, | ||
1214 | { "AIF1RX5", NULL, "AIFCLK" }, | ||
1215 | |||
1216 | { "AIF2RX0", NULL, "AIFCLK" }, | ||
1217 | { "AIF2RX1", NULL, "AIFCLK" }, | ||
1218 | |||
1219 | { "DSP1RXL", NULL, "SYSDSPCLK" }, | ||
1220 | { "DSP1RXR", NULL, "SYSDSPCLK" }, | ||
1221 | { "DSP2RXL", NULL, "SYSDSPCLK" }, | ||
1222 | { "DSP2RXR", NULL, "SYSDSPCLK" }, | ||
1223 | { "DSP1TXL", NULL, "SYSDSPCLK" }, | ||
1224 | { "DSP1TXR", NULL, "SYSDSPCLK" }, | ||
1225 | { "DSP2TXL", NULL, "SYSDSPCLK" }, | ||
1226 | { "DSP2TXR", NULL, "SYSDSPCLK" }, | ||
1227 | |||
1228 | { "AIF1RXA", NULL, "AIF1RX0" }, | ||
1229 | { "AIF1RXA", NULL, "AIF1RX1" }, | ||
1230 | { "AIF1RXB", NULL, "AIF1RX2" }, | ||
1231 | { "AIF1RXB", NULL, "AIF1RX3" }, | ||
1232 | { "AIF1RXC", NULL, "AIF1RX4" }, | ||
1233 | { "AIF1RXC", NULL, "AIF1RX5" }, | ||
1234 | |||
1235 | { "AIF2RX", NULL, "AIF2RX0" }, | ||
1236 | { "AIF2RX", NULL, "AIF2RX1" }, | ||
1237 | |||
1238 | { "AIF2TX", "DSP2", "DSP2TX" }, | ||
1239 | { "AIF2TX", "DSP1", "DSP1RX" }, | ||
1240 | { "AIF2TX", "AIF1", "AIF1RXC" }, | ||
1241 | |||
1242 | { "DSP1RXL", NULL, "DSP1RX" }, | ||
1243 | { "DSP1RXR", NULL, "DSP1RX" }, | ||
1244 | { "DSP2RXL", NULL, "DSP2RX" }, | ||
1245 | { "DSP2RXR", NULL, "DSP2RX" }, | ||
1246 | |||
1247 | { "DSP2TX", NULL, "DSP2TXL" }, | ||
1248 | { "DSP2TX", NULL, "DSP2TXR" }, | ||
1249 | |||
1250 | { "DSP1RX", "AIF1", "AIF1RXA" }, | ||
1251 | { "DSP1RX", "AIF2", "AIF2RX" }, | ||
1252 | |||
1253 | { "DSP2RX", "AIF1", "AIF1RXB" }, | ||
1254 | { "DSP2RX", "AIF2", "AIF2RX" }, | ||
1255 | |||
1256 | { "DAC2L Mixer", "DSP2 Switch", "DSP2RXL" }, | ||
1257 | { "DAC2L Mixer", "DSP1 Switch", "DSP1RXL" }, | ||
1258 | { "DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
1259 | { "DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
1260 | |||
1261 | { "DAC2R Mixer", "DSP2 Switch", "DSP2RXR" }, | ||
1262 | { "DAC2R Mixer", "DSP1 Switch", "DSP1RXR" }, | ||
1263 | { "DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
1264 | { "DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
1265 | |||
1266 | { "DAC1L Mixer", "DSP2 Switch", "DSP2RXL" }, | ||
1267 | { "DAC1L Mixer", "DSP1 Switch", "DSP1RXL" }, | ||
1268 | { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
1269 | { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
1270 | |||
1271 | { "DAC1R Mixer", "DSP2 Switch", "DSP2RXR" }, | ||
1272 | { "DAC1R Mixer", "DSP1 Switch", "DSP1RXR" }, | ||
1273 | { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
1274 | { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
1275 | |||
1276 | { "DAC1L", NULL, "DAC1L Mixer" }, | ||
1277 | { "DAC1R", NULL, "DAC1R Mixer" }, | ||
1278 | { "DAC2L", NULL, "DAC2L Mixer" }, | ||
1279 | { "DAC2R", NULL, "DAC2R Mixer" }, | ||
1280 | |||
1281 | { "HPOUT2L PGA", NULL, "Charge Pump" }, | ||
1282 | { "HPOUT2L PGA", NULL, "DAC2L" }, | ||
1283 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, | ||
1284 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, | ||
1285 | { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" }, | ||
1286 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, | ||
1287 | |||
1288 | { "HPOUT2R PGA", NULL, "Charge Pump" }, | ||
1289 | { "HPOUT2R PGA", NULL, "DAC2R" }, | ||
1290 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, | ||
1291 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, | ||
1292 | { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" }, | ||
1293 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, | ||
1294 | |||
1295 | { "HPOUT1L PGA", NULL, "Charge Pump" }, | ||
1296 | { "HPOUT1L PGA", NULL, "DAC1L" }, | ||
1297 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, | ||
1298 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, | ||
1299 | { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" }, | ||
1300 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, | ||
1301 | |||
1302 | { "HPOUT1R PGA", NULL, "Charge Pump" }, | ||
1303 | { "HPOUT1R PGA", NULL, "DAC1R" }, | ||
1304 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, | ||
1305 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, | ||
1306 | { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" }, | ||
1307 | { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" }, | ||
1308 | |||
1309 | { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" }, | ||
1310 | { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" }, | ||
1311 | { "HPOUT1L", NULL, "HPOUT1L_RMV_SHORT" }, | ||
1312 | { "HPOUT1R", NULL, "HPOUT1R_RMV_SHORT" }, | ||
1313 | |||
1314 | { "SPKL", "DAC1L", "DAC1L" }, | ||
1315 | { "SPKL", "DAC1R", "DAC1R" }, | ||
1316 | { "SPKL", "DAC2L", "DAC2L" }, | ||
1317 | { "SPKL", "DAC2R", "DAC2R" }, | ||
1318 | |||
1319 | { "SPKR", "DAC1L", "DAC1L" }, | ||
1320 | { "SPKR", "DAC1R", "DAC1R" }, | ||
1321 | { "SPKR", "DAC2L", "DAC2L" }, | ||
1322 | { "SPKR", "DAC2R", "DAC2R" }, | ||
1323 | |||
1324 | { "SPKL PGA", NULL, "SPKL" }, | ||
1325 | { "SPKR PGA", NULL, "SPKR" }, | ||
1326 | |||
1327 | { "SPKDAT", NULL, "SPKL PGA" }, | ||
1328 | { "SPKDAT", NULL, "SPKR PGA" }, | ||
1329 | }; | ||
1330 | |||
1331 | static int wm8915_readable_register(struct snd_soc_codec *codec, | ||
1332 | unsigned int reg) | ||
1333 | { | ||
1334 | /* Due to the sparseness of the register map the compiler | ||
1335 | * output from an explicit switch statement ends up being much | ||
1336 | * more efficient than a table. | ||
1337 | */ | ||
1338 | switch (reg) { | ||
1339 | case WM8915_SOFTWARE_RESET: | ||
1340 | case WM8915_POWER_MANAGEMENT_1: | ||
1341 | case WM8915_POWER_MANAGEMENT_2: | ||
1342 | case WM8915_POWER_MANAGEMENT_3: | ||
1343 | case WM8915_POWER_MANAGEMENT_4: | ||
1344 | case WM8915_POWER_MANAGEMENT_5: | ||
1345 | case WM8915_POWER_MANAGEMENT_6: | ||
1346 | case WM8915_POWER_MANAGEMENT_7: | ||
1347 | case WM8915_POWER_MANAGEMENT_8: | ||
1348 | case WM8915_LEFT_LINE_INPUT_VOLUME: | ||
1349 | case WM8915_RIGHT_LINE_INPUT_VOLUME: | ||
1350 | case WM8915_LINE_INPUT_CONTROL: | ||
1351 | case WM8915_DAC1_HPOUT1_VOLUME: | ||
1352 | case WM8915_DAC2_HPOUT2_VOLUME: | ||
1353 | case WM8915_DAC1_LEFT_VOLUME: | ||
1354 | case WM8915_DAC1_RIGHT_VOLUME: | ||
1355 | case WM8915_DAC2_LEFT_VOLUME: | ||
1356 | case WM8915_DAC2_RIGHT_VOLUME: | ||
1357 | case WM8915_OUTPUT1_LEFT_VOLUME: | ||
1358 | case WM8915_OUTPUT1_RIGHT_VOLUME: | ||
1359 | case WM8915_OUTPUT2_LEFT_VOLUME: | ||
1360 | case WM8915_OUTPUT2_RIGHT_VOLUME: | ||
1361 | case WM8915_MICBIAS_1: | ||
1362 | case WM8915_MICBIAS_2: | ||
1363 | case WM8915_LDO_1: | ||
1364 | case WM8915_LDO_2: | ||
1365 | case WM8915_ACCESSORY_DETECT_MODE_1: | ||
1366 | case WM8915_ACCESSORY_DETECT_MODE_2: | ||
1367 | case WM8915_HEADPHONE_DETECT_1: | ||
1368 | case WM8915_HEADPHONE_DETECT_2: | ||
1369 | case WM8915_MIC_DETECT_1: | ||
1370 | case WM8915_MIC_DETECT_2: | ||
1371 | case WM8915_MIC_DETECT_3: | ||
1372 | case WM8915_CHARGE_PUMP_1: | ||
1373 | case WM8915_CHARGE_PUMP_2: | ||
1374 | case WM8915_DC_SERVO_1: | ||
1375 | case WM8915_DC_SERVO_2: | ||
1376 | case WM8915_DC_SERVO_3: | ||
1377 | case WM8915_DC_SERVO_5: | ||
1378 | case WM8915_DC_SERVO_6: | ||
1379 | case WM8915_DC_SERVO_7: | ||
1380 | case WM8915_DC_SERVO_READBACK_0: | ||
1381 | case WM8915_ANALOGUE_HP_1: | ||
1382 | case WM8915_ANALOGUE_HP_2: | ||
1383 | case WM8915_CHIP_REVISION: | ||
1384 | case WM8915_CONTROL_INTERFACE_1: | ||
1385 | case WM8915_WRITE_SEQUENCER_CTRL_1: | ||
1386 | case WM8915_WRITE_SEQUENCER_CTRL_2: | ||
1387 | case WM8915_AIF_CLOCKING_1: | ||
1388 | case WM8915_AIF_CLOCKING_2: | ||
1389 | case WM8915_CLOCKING_1: | ||
1390 | case WM8915_CLOCKING_2: | ||
1391 | case WM8915_AIF_RATE: | ||
1392 | case WM8915_FLL_CONTROL_1: | ||
1393 | case WM8915_FLL_CONTROL_2: | ||
1394 | case WM8915_FLL_CONTROL_3: | ||
1395 | case WM8915_FLL_CONTROL_4: | ||
1396 | case WM8915_FLL_CONTROL_5: | ||
1397 | case WM8915_FLL_CONTROL_6: | ||
1398 | case WM8915_FLL_EFS_1: | ||
1399 | case WM8915_FLL_EFS_2: | ||
1400 | case WM8915_AIF1_CONTROL: | ||
1401 | case WM8915_AIF1_BCLK: | ||
1402 | case WM8915_AIF1_TX_LRCLK_1: | ||
1403 | case WM8915_AIF1_TX_LRCLK_2: | ||
1404 | case WM8915_AIF1_RX_LRCLK_1: | ||
1405 | case WM8915_AIF1_RX_LRCLK_2: | ||
1406 | case WM8915_AIF1TX_DATA_CONFIGURATION_1: | ||
1407 | case WM8915_AIF1TX_DATA_CONFIGURATION_2: | ||
1408 | case WM8915_AIF1RX_DATA_CONFIGURATION: | ||
1409 | case WM8915_AIF1TX_CHANNEL_0_CONFIGURATION: | ||
1410 | case WM8915_AIF1TX_CHANNEL_1_CONFIGURATION: | ||
1411 | case WM8915_AIF1TX_CHANNEL_2_CONFIGURATION: | ||
1412 | case WM8915_AIF1TX_CHANNEL_3_CONFIGURATION: | ||
1413 | case WM8915_AIF1TX_CHANNEL_4_CONFIGURATION: | ||
1414 | case WM8915_AIF1TX_CHANNEL_5_CONFIGURATION: | ||
1415 | case WM8915_AIF1RX_CHANNEL_0_CONFIGURATION: | ||
1416 | case WM8915_AIF1RX_CHANNEL_1_CONFIGURATION: | ||
1417 | case WM8915_AIF1RX_CHANNEL_2_CONFIGURATION: | ||
1418 | case WM8915_AIF1RX_CHANNEL_3_CONFIGURATION: | ||
1419 | case WM8915_AIF1RX_CHANNEL_4_CONFIGURATION: | ||
1420 | case WM8915_AIF1RX_CHANNEL_5_CONFIGURATION: | ||
1421 | case WM8915_AIF1RX_MONO_CONFIGURATION: | ||
1422 | case WM8915_AIF1TX_TEST: | ||
1423 | case WM8915_AIF2_CONTROL: | ||
1424 | case WM8915_AIF2_BCLK: | ||
1425 | case WM8915_AIF2_TX_LRCLK_1: | ||
1426 | case WM8915_AIF2_TX_LRCLK_2: | ||
1427 | case WM8915_AIF2_RX_LRCLK_1: | ||
1428 | case WM8915_AIF2_RX_LRCLK_2: | ||
1429 | case WM8915_AIF2TX_DATA_CONFIGURATION_1: | ||
1430 | case WM8915_AIF2TX_DATA_CONFIGURATION_2: | ||
1431 | case WM8915_AIF2RX_DATA_CONFIGURATION: | ||
1432 | case WM8915_AIF2TX_CHANNEL_0_CONFIGURATION: | ||
1433 | case WM8915_AIF2TX_CHANNEL_1_CONFIGURATION: | ||
1434 | case WM8915_AIF2RX_CHANNEL_0_CONFIGURATION: | ||
1435 | case WM8915_AIF2RX_CHANNEL_1_CONFIGURATION: | ||
1436 | case WM8915_AIF2RX_MONO_CONFIGURATION: | ||
1437 | case WM8915_AIF2TX_TEST: | ||
1438 | case WM8915_DSP1_TX_LEFT_VOLUME: | ||
1439 | case WM8915_DSP1_TX_RIGHT_VOLUME: | ||
1440 | case WM8915_DSP1_RX_LEFT_VOLUME: | ||
1441 | case WM8915_DSP1_RX_RIGHT_VOLUME: | ||
1442 | case WM8915_DSP1_TX_FILTERS: | ||
1443 | case WM8915_DSP1_RX_FILTERS_1: | ||
1444 | case WM8915_DSP1_RX_FILTERS_2: | ||
1445 | case WM8915_DSP1_DRC_1: | ||
1446 | case WM8915_DSP1_DRC_2: | ||
1447 | case WM8915_DSP1_DRC_3: | ||
1448 | case WM8915_DSP1_DRC_4: | ||
1449 | case WM8915_DSP1_DRC_5: | ||
1450 | case WM8915_DSP1_RX_EQ_GAINS_1: | ||
1451 | case WM8915_DSP1_RX_EQ_GAINS_2: | ||
1452 | case WM8915_DSP1_RX_EQ_BAND_1_A: | ||
1453 | case WM8915_DSP1_RX_EQ_BAND_1_B: | ||
1454 | case WM8915_DSP1_RX_EQ_BAND_1_PG: | ||
1455 | case WM8915_DSP1_RX_EQ_BAND_2_A: | ||
1456 | case WM8915_DSP1_RX_EQ_BAND_2_B: | ||
1457 | case WM8915_DSP1_RX_EQ_BAND_2_C: | ||
1458 | case WM8915_DSP1_RX_EQ_BAND_2_PG: | ||
1459 | case WM8915_DSP1_RX_EQ_BAND_3_A: | ||
1460 | case WM8915_DSP1_RX_EQ_BAND_3_B: | ||
1461 | case WM8915_DSP1_RX_EQ_BAND_3_C: | ||
1462 | case WM8915_DSP1_RX_EQ_BAND_3_PG: | ||
1463 | case WM8915_DSP1_RX_EQ_BAND_4_A: | ||
1464 | case WM8915_DSP1_RX_EQ_BAND_4_B: | ||
1465 | case WM8915_DSP1_RX_EQ_BAND_4_C: | ||
1466 | case WM8915_DSP1_RX_EQ_BAND_4_PG: | ||
1467 | case WM8915_DSP1_RX_EQ_BAND_5_A: | ||
1468 | case WM8915_DSP1_RX_EQ_BAND_5_B: | ||
1469 | case WM8915_DSP1_RX_EQ_BAND_5_PG: | ||
1470 | case WM8915_DSP2_TX_LEFT_VOLUME: | ||
1471 | case WM8915_DSP2_TX_RIGHT_VOLUME: | ||
1472 | case WM8915_DSP2_RX_LEFT_VOLUME: | ||
1473 | case WM8915_DSP2_RX_RIGHT_VOLUME: | ||
1474 | case WM8915_DSP2_TX_FILTERS: | ||
1475 | case WM8915_DSP2_RX_FILTERS_1: | ||
1476 | case WM8915_DSP2_RX_FILTERS_2: | ||
1477 | case WM8915_DSP2_DRC_1: | ||
1478 | case WM8915_DSP2_DRC_2: | ||
1479 | case WM8915_DSP2_DRC_3: | ||
1480 | case WM8915_DSP2_DRC_4: | ||
1481 | case WM8915_DSP2_DRC_5: | ||
1482 | case WM8915_DSP2_RX_EQ_GAINS_1: | ||
1483 | case WM8915_DSP2_RX_EQ_GAINS_2: | ||
1484 | case WM8915_DSP2_RX_EQ_BAND_1_A: | ||
1485 | case WM8915_DSP2_RX_EQ_BAND_1_B: | ||
1486 | case WM8915_DSP2_RX_EQ_BAND_1_PG: | ||
1487 | case WM8915_DSP2_RX_EQ_BAND_2_A: | ||
1488 | case WM8915_DSP2_RX_EQ_BAND_2_B: | ||
1489 | case WM8915_DSP2_RX_EQ_BAND_2_C: | ||
1490 | case WM8915_DSP2_RX_EQ_BAND_2_PG: | ||
1491 | case WM8915_DSP2_RX_EQ_BAND_3_A: | ||
1492 | case WM8915_DSP2_RX_EQ_BAND_3_B: | ||
1493 | case WM8915_DSP2_RX_EQ_BAND_3_C: | ||
1494 | case WM8915_DSP2_RX_EQ_BAND_3_PG: | ||
1495 | case WM8915_DSP2_RX_EQ_BAND_4_A: | ||
1496 | case WM8915_DSP2_RX_EQ_BAND_4_B: | ||
1497 | case WM8915_DSP2_RX_EQ_BAND_4_C: | ||
1498 | case WM8915_DSP2_RX_EQ_BAND_4_PG: | ||
1499 | case WM8915_DSP2_RX_EQ_BAND_5_A: | ||
1500 | case WM8915_DSP2_RX_EQ_BAND_5_B: | ||
1501 | case WM8915_DSP2_RX_EQ_BAND_5_PG: | ||
1502 | case WM8915_DAC1_MIXER_VOLUMES: | ||
1503 | case WM8915_DAC1_LEFT_MIXER_ROUTING: | ||
1504 | case WM8915_DAC1_RIGHT_MIXER_ROUTING: | ||
1505 | case WM8915_DAC2_MIXER_VOLUMES: | ||
1506 | case WM8915_DAC2_LEFT_MIXER_ROUTING: | ||
1507 | case WM8915_DAC2_RIGHT_MIXER_ROUTING: | ||
1508 | case WM8915_DSP1_TX_LEFT_MIXER_ROUTING: | ||
1509 | case WM8915_DSP1_TX_RIGHT_MIXER_ROUTING: | ||
1510 | case WM8915_DSP2_TX_LEFT_MIXER_ROUTING: | ||
1511 | case WM8915_DSP2_TX_RIGHT_MIXER_ROUTING: | ||
1512 | case WM8915_DSP_TX_MIXER_SELECT: | ||
1513 | case WM8915_DAC_SOFTMUTE: | ||
1514 | case WM8915_OVERSAMPLING: | ||
1515 | case WM8915_SIDETONE: | ||
1516 | case WM8915_GPIO_1: | ||
1517 | case WM8915_GPIO_2: | ||
1518 | case WM8915_GPIO_3: | ||
1519 | case WM8915_GPIO_4: | ||
1520 | case WM8915_GPIO_5: | ||
1521 | case WM8915_PULL_CONTROL_1: | ||
1522 | case WM8915_PULL_CONTROL_2: | ||
1523 | case WM8915_INTERRUPT_STATUS_1: | ||
1524 | case WM8915_INTERRUPT_STATUS_2: | ||
1525 | case WM8915_INTERRUPT_RAW_STATUS_2: | ||
1526 | case WM8915_INTERRUPT_STATUS_1_MASK: | ||
1527 | case WM8915_INTERRUPT_STATUS_2_MASK: | ||
1528 | case WM8915_INTERRUPT_CONTROL: | ||
1529 | case WM8915_LEFT_PDM_SPEAKER: | ||
1530 | case WM8915_RIGHT_PDM_SPEAKER: | ||
1531 | case WM8915_PDM_SPEAKER_MUTE_SEQUENCE: | ||
1532 | case WM8915_PDM_SPEAKER_VOLUME: | ||
1533 | return 1; | ||
1534 | default: | ||
1535 | return 0; | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | static int wm8915_volatile_register(struct snd_soc_codec *codec, | ||
1540 | unsigned int reg) | ||
1541 | { | ||
1542 | switch (reg) { | ||
1543 | case WM8915_SOFTWARE_RESET: | ||
1544 | case WM8915_CHIP_REVISION: | ||
1545 | case WM8915_LDO_1: | ||
1546 | case WM8915_LDO_2: | ||
1547 | case WM8915_INTERRUPT_STATUS_1: | ||
1548 | case WM8915_INTERRUPT_STATUS_2: | ||
1549 | case WM8915_INTERRUPT_RAW_STATUS_2: | ||
1550 | case WM8915_DC_SERVO_READBACK_0: | ||
1551 | case WM8915_DC_SERVO_2: | ||
1552 | case WM8915_DC_SERVO_6: | ||
1553 | case WM8915_DC_SERVO_7: | ||
1554 | case WM8915_FLL_CONTROL_6: | ||
1555 | case WM8915_MIC_DETECT_3: | ||
1556 | case WM8915_HEADPHONE_DETECT_1: | ||
1557 | case WM8915_HEADPHONE_DETECT_2: | ||
1558 | return 1; | ||
1559 | default: | ||
1560 | return 0; | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | static int wm8915_reset(struct snd_soc_codec *codec) | ||
1565 | { | ||
1566 | return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); | ||
1567 | } | ||
1568 | |||
1569 | static int wm8915_set_bias_level(struct snd_soc_codec *codec, | ||
1570 | enum snd_soc_bias_level level) | ||
1571 | { | ||
1572 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
1573 | int ret; | ||
1574 | |||
1575 | switch (level) { | ||
1576 | case SND_SOC_BIAS_ON: | ||
1577 | break; | ||
1578 | |||
1579 | case SND_SOC_BIAS_PREPARE: | ||
1580 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | ||
1581 | snd_soc_update_bits(codec, WM8915_POWER_MANAGEMENT_1, | ||
1582 | WM8915_BG_ENA, WM8915_BG_ENA); | ||
1583 | msleep(2); | ||
1584 | } | ||
1585 | break; | ||
1586 | |||
1587 | case SND_SOC_BIAS_STANDBY: | ||
1588 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1589 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8915->supplies), | ||
1590 | wm8915->supplies); | ||
1591 | if (ret != 0) { | ||
1592 | dev_err(codec->dev, | ||
1593 | "Failed to enable supplies: %d\n", | ||
1594 | ret); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | if (wm8915->pdata.ldo_ena >= 0) { | ||
1599 | gpio_set_value_cansleep(wm8915->pdata.ldo_ena, | ||
1600 | 1); | ||
1601 | msleep(5); | ||
1602 | } | ||
1603 | |||
1604 | codec->cache_only = false; | ||
1605 | snd_soc_cache_sync(codec); | ||
1606 | } | ||
1607 | |||
1608 | snd_soc_update_bits(codec, WM8915_POWER_MANAGEMENT_1, | ||
1609 | WM8915_BG_ENA, 0); | ||
1610 | break; | ||
1611 | |||
1612 | case SND_SOC_BIAS_OFF: | ||
1613 | codec->cache_only = true; | ||
1614 | if (wm8915->pdata.ldo_ena >= 0) | ||
1615 | gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0); | ||
1616 | regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies), | ||
1617 | wm8915->supplies); | ||
1618 | break; | ||
1619 | } | ||
1620 | |||
1621 | codec->dapm.bias_level = level; | ||
1622 | |||
1623 | return 0; | ||
1624 | } | ||
1625 | |||
1626 | static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
1627 | { | ||
1628 | struct snd_soc_codec *codec = dai->codec; | ||
1629 | int aifctrl = 0; | ||
1630 | int bclk = 0; | ||
1631 | int lrclk_tx = 0; | ||
1632 | int lrclk_rx = 0; | ||
1633 | int aifctrl_reg, bclk_reg, lrclk_tx_reg, lrclk_rx_reg; | ||
1634 | |||
1635 | switch (dai->id) { | ||
1636 | case 0: | ||
1637 | aifctrl_reg = WM8915_AIF1_CONTROL; | ||
1638 | bclk_reg = WM8915_AIF1_BCLK; | ||
1639 | lrclk_tx_reg = WM8915_AIF1_TX_LRCLK_2; | ||
1640 | lrclk_rx_reg = WM8915_AIF1_RX_LRCLK_2; | ||
1641 | break; | ||
1642 | case 1: | ||
1643 | aifctrl_reg = WM8915_AIF2_CONTROL; | ||
1644 | bclk_reg = WM8915_AIF2_BCLK; | ||
1645 | lrclk_tx_reg = WM8915_AIF2_TX_LRCLK_2; | ||
1646 | lrclk_rx_reg = WM8915_AIF2_RX_LRCLK_2; | ||
1647 | break; | ||
1648 | default: | ||
1649 | BUG(); | ||
1650 | return -EINVAL; | ||
1651 | } | ||
1652 | |||
1653 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1654 | case SND_SOC_DAIFMT_NB_NF: | ||
1655 | break; | ||
1656 | case SND_SOC_DAIFMT_IB_NF: | ||
1657 | bclk |= WM8915_AIF1_BCLK_INV; | ||
1658 | break; | ||
1659 | case SND_SOC_DAIFMT_NB_IF: | ||
1660 | lrclk_tx |= WM8915_AIF1TX_LRCLK_INV; | ||
1661 | lrclk_rx |= WM8915_AIF1RX_LRCLK_INV; | ||
1662 | break; | ||
1663 | case SND_SOC_DAIFMT_IB_IF: | ||
1664 | bclk |= WM8915_AIF1_BCLK_INV; | ||
1665 | lrclk_tx |= WM8915_AIF1TX_LRCLK_INV; | ||
1666 | lrclk_rx |= WM8915_AIF1RX_LRCLK_INV; | ||
1667 | break; | ||
1668 | } | ||
1669 | |||
1670 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1671 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1672 | break; | ||
1673 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1674 | lrclk_tx |= WM8915_AIF1TX_LRCLK_MSTR; | ||
1675 | lrclk_rx |= WM8915_AIF1RX_LRCLK_MSTR; | ||
1676 | break; | ||
1677 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1678 | bclk |= WM8915_AIF1_BCLK_MSTR; | ||
1679 | break; | ||
1680 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1681 | bclk |= WM8915_AIF1_BCLK_MSTR; | ||
1682 | lrclk_tx |= WM8915_AIF1TX_LRCLK_MSTR; | ||
1683 | lrclk_rx |= WM8915_AIF1RX_LRCLK_MSTR; | ||
1684 | break; | ||
1685 | default: | ||
1686 | return -EINVAL; | ||
1687 | } | ||
1688 | |||
1689 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1690 | case SND_SOC_DAIFMT_DSP_A: | ||
1691 | break; | ||
1692 | case SND_SOC_DAIFMT_DSP_B: | ||
1693 | aifctrl |= 1; | ||
1694 | break; | ||
1695 | case SND_SOC_DAIFMT_I2S: | ||
1696 | aifctrl |= 2; | ||
1697 | break; | ||
1698 | case SND_SOC_DAIFMT_LEFT_J: | ||
1699 | aifctrl |= 3; | ||
1700 | break; | ||
1701 | default: | ||
1702 | return -EINVAL; | ||
1703 | } | ||
1704 | |||
1705 | snd_soc_update_bits(codec, aifctrl_reg, WM8915_AIF1_FMT_MASK, aifctrl); | ||
1706 | snd_soc_update_bits(codec, bclk_reg, | ||
1707 | WM8915_AIF1_BCLK_INV | WM8915_AIF1_BCLK_MSTR, | ||
1708 | bclk); | ||
1709 | snd_soc_update_bits(codec, lrclk_tx_reg, | ||
1710 | WM8915_AIF1TX_LRCLK_INV | | ||
1711 | WM8915_AIF1TX_LRCLK_MSTR, | ||
1712 | lrclk_tx); | ||
1713 | snd_soc_update_bits(codec, lrclk_rx_reg, | ||
1714 | WM8915_AIF1RX_LRCLK_INV | | ||
1715 | WM8915_AIF1RX_LRCLK_MSTR, | ||
1716 | lrclk_rx); | ||
1717 | |||
1718 | return 0; | ||
1719 | } | ||
1720 | |||
1721 | static const int bclk_divs[] = { | ||
1722 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | ||
1723 | }; | ||
1724 | |||
1725 | static const int dsp_divs[] = { | ||
1726 | 48000, 32000, 16000, 8000 | ||
1727 | }; | ||
1728 | |||
1729 | static int wm8915_hw_params(struct snd_pcm_substream *substream, | ||
1730 | struct snd_pcm_hw_params *params, | ||
1731 | struct snd_soc_dai *dai) | ||
1732 | { | ||
1733 | struct snd_soc_codec *codec = dai->codec; | ||
1734 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
1735 | int bits, i, bclk_rate, best, cur_val; | ||
1736 | int aifdata = 0; | ||
1737 | int bclk = 0; | ||
1738 | int lrclk = 0; | ||
1739 | int dsp = 0; | ||
1740 | int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift; | ||
1741 | |||
1742 | if (!wm8915->sysclk) { | ||
1743 | dev_err(codec->dev, "SYSCLK not configured\n"); | ||
1744 | return -EINVAL; | ||
1745 | } | ||
1746 | |||
1747 | switch (dai->id) { | ||
1748 | case 0: | ||
1749 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || | ||
1750 | (snd_soc_read(codec, WM8915_GPIO_1)) & WM8915_GP1_FN_MASK) { | ||
1751 | aifdata_reg = WM8915_AIF1RX_DATA_CONFIGURATION; | ||
1752 | lrclk_reg = WM8915_AIF1_RX_LRCLK_1; | ||
1753 | } else { | ||
1754 | aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; | ||
1755 | lrclk_reg = WM8915_AIF1_TX_LRCLK_1; | ||
1756 | } | ||
1757 | bclk_reg = WM8915_AIF1_BCLK; | ||
1758 | dsp_shift = 0; | ||
1759 | break; | ||
1760 | case 1: | ||
1761 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || | ||
1762 | (snd_soc_read(codec, WM8915_GPIO_2)) & WM8915_GP2_FN_MASK) { | ||
1763 | aifdata_reg = WM8915_AIF2RX_DATA_CONFIGURATION; | ||
1764 | lrclk_reg = WM8915_AIF2_RX_LRCLK_1; | ||
1765 | } else { | ||
1766 | aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; | ||
1767 | lrclk_reg = WM8915_AIF2_TX_LRCLK_1; | ||
1768 | } | ||
1769 | bclk_reg = WM8915_AIF2_BCLK; | ||
1770 | dsp_shift = WM8915_DSP2_DIV_SHIFT; | ||
1771 | break; | ||
1772 | default: | ||
1773 | BUG(); | ||
1774 | return -EINVAL; | ||
1775 | } | ||
1776 | |||
1777 | bclk_rate = snd_soc_params_to_bclk(params); | ||
1778 | if (bclk_rate < 0) { | ||
1779 | dev_err(codec->dev, "Unsupported BCLK rate: %d\n", bclk_rate); | ||
1780 | return bclk_rate; | ||
1781 | } | ||
1782 | |||
1783 | /* Needs looking at for TDM */ | ||
1784 | bits = snd_pcm_format_width(params_format(params)); | ||
1785 | if (bits < 0) | ||
1786 | return bits; | ||
1787 | aifdata |= (bits << WM8915_AIF1TX_WL_SHIFT) | bits; | ||
1788 | |||
1789 | for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) { | ||
1790 | if (dsp_divs[i] == params_rate(params)) | ||
1791 | break; | ||
1792 | } | ||
1793 | if (i == ARRAY_SIZE(dsp_divs)) { | ||
1794 | dev_err(codec->dev, "Unsupported sample rate %dHz\n", | ||
1795 | params_rate(params)); | ||
1796 | return -EINVAL; | ||
1797 | } | ||
1798 | dsp |= i << dsp_shift; | ||
1799 | |||
1800 | /* Pick a divisor for BCLK as close as we can get to ideal */ | ||
1801 | best = 0; | ||
1802 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1803 | cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate; | ||
1804 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1805 | break; | ||
1806 | best = i; | ||
1807 | } | ||
1808 | bclk_rate = wm8915->sysclk / bclk_divs[best]; | ||
1809 | dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
1810 | bclk_divs[best], bclk_rate); | ||
1811 | bclk |= best; | ||
1812 | |||
1813 | lrclk = bclk_rate / params_rate(params); | ||
1814 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", | ||
1815 | lrclk, bclk_rate / lrclk); | ||
1816 | |||
1817 | snd_soc_update_bits(codec, aifdata_reg, | ||
1818 | WM8915_AIF1TX_WL_MASK | | ||
1819 | WM8915_AIF1TX_SLOT_LEN_MASK, | ||
1820 | aifdata); | ||
1821 | snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk); | ||
1822 | snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, | ||
1823 | lrclk); | ||
1824 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, | ||
1825 | WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); | ||
1826 | |||
1827 | wm8915->rx_rate[dai->id] = params_rate(params); | ||
1828 | |||
1829 | return 0; | ||
1830 | } | ||
1831 | |||
1832 | static int wm8915_set_sysclk(struct snd_soc_dai *dai, | ||
1833 | int clk_id, unsigned int freq, int dir) | ||
1834 | { | ||
1835 | struct snd_soc_codec *codec = dai->codec; | ||
1836 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
1837 | int lfclk = 0; | ||
1838 | int ratediv = 0; | ||
1839 | int src; | ||
1840 | int old; | ||
1841 | |||
1842 | /* Disable SYSCLK while we reconfigure */ | ||
1843 | old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1); | ||
1844 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | ||
1845 | WM8915_SYSCLK_ENA, 0); | ||
1846 | |||
1847 | switch (clk_id) { | ||
1848 | case WM8915_SYSCLK_MCLK1: | ||
1849 | wm8915->sysclk = freq; | ||
1850 | src = 0; | ||
1851 | break; | ||
1852 | case WM8915_SYSCLK_MCLK2: | ||
1853 | wm8915->sysclk = freq; | ||
1854 | src = 1; | ||
1855 | break; | ||
1856 | case WM8915_SYSCLK_FLL: | ||
1857 | wm8915->sysclk = freq; | ||
1858 | src = 2; | ||
1859 | break; | ||
1860 | default: | ||
1861 | dev_err(codec->dev, "Unsupported clock source %d\n", clk_id); | ||
1862 | return -EINVAL; | ||
1863 | } | ||
1864 | |||
1865 | switch (wm8915->sysclk) { | ||
1866 | case 6144000: | ||
1867 | snd_soc_update_bits(codec, WM8915_AIF_RATE, | ||
1868 | WM8915_SYSCLK_RATE, 0); | ||
1869 | break; | ||
1870 | case 24576000: | ||
1871 | ratediv = WM8915_SYSCLK_DIV; | ||
1872 | case 12288000: | ||
1873 | snd_soc_update_bits(codec, WM8915_AIF_RATE, | ||
1874 | WM8915_SYSCLK_RATE, WM8915_SYSCLK_RATE); | ||
1875 | break; | ||
1876 | case 32000: | ||
1877 | case 32768: | ||
1878 | lfclk = WM8915_LFCLK_ENA; | ||
1879 | break; | ||
1880 | default: | ||
1881 | dev_warn(codec->dev, "Unsupported clock rate %dHz\n", | ||
1882 | wm8915->sysclk); | ||
1883 | return -EINVAL; | ||
1884 | } | ||
1885 | |||
1886 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | ||
1887 | WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, | ||
1888 | src << WM8915_SYSCLK_SRC_SHIFT | ratediv); | ||
1889 | snd_soc_update_bits(codec, WM8915_CLOCKING_1, WM8915_LFCLK_ENA, lfclk); | ||
1890 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | ||
1891 | WM8915_SYSCLK_ENA, old); | ||
1892 | |||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1896 | struct _fll_div { | ||
1897 | u16 fll_fratio; | ||
1898 | u16 fll_outdiv; | ||
1899 | u16 fll_refclk_div; | ||
1900 | u16 fll_loop_gain; | ||
1901 | u16 fll_ref_freq; | ||
1902 | u16 n; | ||
1903 | u16 theta; | ||
1904 | u16 lambda; | ||
1905 | }; | ||
1906 | |||
1907 | static struct { | ||
1908 | unsigned int min; | ||
1909 | unsigned int max; | ||
1910 | u16 fll_fratio; | ||
1911 | int ratio; | ||
1912 | } fll_fratios[] = { | ||
1913 | { 0, 64000, 4, 16 }, | ||
1914 | { 64000, 128000, 3, 8 }, | ||
1915 | { 128000, 256000, 2, 4 }, | ||
1916 | { 256000, 1000000, 1, 2 }, | ||
1917 | { 1000000, 13500000, 0, 1 }, | ||
1918 | }; | ||
1919 | |||
1920 | static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | ||
1921 | unsigned int Fout) | ||
1922 | { | ||
1923 | unsigned int target; | ||
1924 | unsigned int div; | ||
1925 | unsigned int fratio, gcd_fll; | ||
1926 | int i; | ||
1927 | |||
1928 | /* Fref must be <=13.5MHz */ | ||
1929 | div = 1; | ||
1930 | fll_div->fll_refclk_div = 0; | ||
1931 | while ((Fref / div) > 13500000) { | ||
1932 | div *= 2; | ||
1933 | fll_div->fll_refclk_div++; | ||
1934 | |||
1935 | if (div > 8) { | ||
1936 | pr_err("Can't scale %dMHz input down to <=13.5MHz\n", | ||
1937 | Fref); | ||
1938 | return -EINVAL; | ||
1939 | } | ||
1940 | } | ||
1941 | |||
1942 | pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); | ||
1943 | |||
1944 | /* Apply the division for our remaining calculations */ | ||
1945 | Fref /= div; | ||
1946 | |||
1947 | if (Fref >= 3000000) | ||
1948 | fll_div->fll_loop_gain = 5; | ||
1949 | else | ||
1950 | fll_div->fll_loop_gain = 0; | ||
1951 | |||
1952 | if (Fref >= 48000) | ||
1953 | fll_div->fll_ref_freq = 0; | ||
1954 | else | ||
1955 | fll_div->fll_ref_freq = 1; | ||
1956 | |||
1957 | /* Fvco should be 90-100MHz; don't check the upper bound */ | ||
1958 | div = 2; | ||
1959 | while (Fout * div < 90000000) { | ||
1960 | div++; | ||
1961 | if (div > 64) { | ||
1962 | pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", | ||
1963 | Fout); | ||
1964 | return -EINVAL; | ||
1965 | } | ||
1966 | } | ||
1967 | target = Fout * div; | ||
1968 | fll_div->fll_outdiv = div - 1; | ||
1969 | |||
1970 | pr_debug("FLL Fvco=%dHz\n", target); | ||
1971 | |||
1972 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | ||
1973 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | ||
1974 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | ||
1975 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; | ||
1976 | fratio = fll_fratios[i].ratio; | ||
1977 | break; | ||
1978 | } | ||
1979 | } | ||
1980 | if (i == ARRAY_SIZE(fll_fratios)) { | ||
1981 | pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); | ||
1982 | return -EINVAL; | ||
1983 | } | ||
1984 | |||
1985 | fll_div->n = target / (fratio * Fref); | ||
1986 | |||
1987 | if (target % Fref == 0) { | ||
1988 | fll_div->theta = 0; | ||
1989 | fll_div->lambda = 0; | ||
1990 | } else { | ||
1991 | gcd_fll = gcd(target, fratio * Fref); | ||
1992 | |||
1993 | fll_div->theta = (target - (fll_div->n * fratio * Fref)) | ||
1994 | / gcd_fll; | ||
1995 | fll_div->lambda = (fratio * Fref) / gcd_fll; | ||
1996 | } | ||
1997 | |||
1998 | pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", | ||
1999 | fll_div->n, fll_div->theta, fll_div->lambda); | ||
2000 | pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", | ||
2001 | fll_div->fll_fratio, fll_div->fll_outdiv, | ||
2002 | fll_div->fll_refclk_div); | ||
2003 | |||
2004 | return 0; | ||
2005 | } | ||
2006 | |||
2007 | static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | ||
2008 | unsigned int Fref, unsigned int Fout) | ||
2009 | { | ||
2010 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2011 | struct _fll_div fll_div; | ||
2012 | unsigned long timeout; | ||
2013 | int ret, reg; | ||
2014 | |||
2015 | /* Any change? */ | ||
2016 | if (source == wm8915->fll_src && Fref == wm8915->fll_fref && | ||
2017 | Fout == wm8915->fll_fout) | ||
2018 | return 0; | ||
2019 | |||
2020 | if (Fout == 0) { | ||
2021 | dev_dbg(codec->dev, "FLL disabled\n"); | ||
2022 | |||
2023 | wm8915->fll_fref = 0; | ||
2024 | wm8915->fll_fout = 0; | ||
2025 | |||
2026 | snd_soc_update_bits(codec, WM8915_FLL_CONTROL_1, | ||
2027 | WM8915_FLL_ENA, 0); | ||
2028 | |||
2029 | return 0; | ||
2030 | } | ||
2031 | |||
2032 | ret = fll_factors(&fll_div, Fref, Fout); | ||
2033 | if (ret != 0) | ||
2034 | return ret; | ||
2035 | |||
2036 | switch (source) { | ||
2037 | case WM8915_FLL_MCLK1: | ||
2038 | reg = 0; | ||
2039 | break; | ||
2040 | case WM8915_FLL_MCLK2: | ||
2041 | reg = 1; | ||
2042 | case WM8915_FLL_DACLRCLK1: | ||
2043 | reg = 2; | ||
2044 | break; | ||
2045 | case WM8915_FLL_BCLK1: | ||
2046 | reg = 3; | ||
2047 | break; | ||
2048 | default: | ||
2049 | dev_err(codec->dev, "Unknown FLL source %d\n", ret); | ||
2050 | return -EINVAL; | ||
2051 | } | ||
2052 | |||
2053 | reg |= fll_div.fll_refclk_div << WM8915_FLL_REFCLK_DIV_SHIFT; | ||
2054 | reg |= fll_div.fll_ref_freq << WM8915_FLL_REF_FREQ_SHIFT; | ||
2055 | |||
2056 | snd_soc_update_bits(codec, WM8915_FLL_CONTROL_5, | ||
2057 | WM8915_FLL_REFCLK_DIV_MASK | WM8915_FLL_REF_FREQ | | ||
2058 | WM8915_FLL_REFCLK_SRC_MASK, reg); | ||
2059 | |||
2060 | reg = 0; | ||
2061 | if (fll_div.theta || fll_div.lambda) | ||
2062 | reg |= WM8915_FLL_EFS_ENA | (3 << WM8915_FLL_LFSR_SEL_SHIFT); | ||
2063 | else | ||
2064 | reg |= 1 << WM8915_FLL_LFSR_SEL_SHIFT; | ||
2065 | snd_soc_write(codec, WM8915_FLL_EFS_2, reg); | ||
2066 | |||
2067 | snd_soc_update_bits(codec, WM8915_FLL_CONTROL_2, | ||
2068 | WM8915_FLL_OUTDIV_MASK | | ||
2069 | WM8915_FLL_FRATIO_MASK, | ||
2070 | (fll_div.fll_outdiv << WM8915_FLL_OUTDIV_SHIFT) | | ||
2071 | (fll_div.fll_fratio)); | ||
2072 | |||
2073 | snd_soc_write(codec, WM8915_FLL_CONTROL_3, fll_div.theta); | ||
2074 | |||
2075 | snd_soc_update_bits(codec, WM8915_FLL_CONTROL_4, | ||
2076 | WM8915_FLL_N_MASK | WM8915_FLL_LOOP_GAIN_MASK, | ||
2077 | (fll_div.n << WM8915_FLL_N_SHIFT) | | ||
2078 | fll_div.fll_loop_gain); | ||
2079 | |||
2080 | snd_soc_write(codec, WM8915_FLL_EFS_1, fll_div.lambda); | ||
2081 | |||
2082 | snd_soc_update_bits(codec, WM8915_FLL_CONTROL_1, | ||
2083 | WM8915_FLL_ENA, WM8915_FLL_ENA); | ||
2084 | |||
2085 | /* The FLL supports live reconfiguration - kick that in case we were | ||
2086 | * already enabled. | ||
2087 | */ | ||
2088 | snd_soc_write(codec, WM8915_FLL_CONTROL_6, WM8915_FLL_SWITCH_CLK); | ||
2089 | |||
2090 | /* Wait for the FLL to lock, using the interrupt if possible */ | ||
2091 | if (Fref > 1000000) | ||
2092 | timeout = usecs_to_jiffies(300); | ||
2093 | else | ||
2094 | timeout = msecs_to_jiffies(2); | ||
2095 | |||
2096 | wait_for_completion_timeout(&wm8915->fll_lock, timeout); | ||
2097 | |||
2098 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | ||
2099 | |||
2100 | wm8915->fll_fref = Fref; | ||
2101 | wm8915->fll_fout = Fout; | ||
2102 | wm8915->fll_src = source; | ||
2103 | |||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | #ifdef CONFIG_GPIOLIB | ||
2108 | static inline struct wm8915_priv *gpio_to_wm8915(struct gpio_chip *chip) | ||
2109 | { | ||
2110 | return container_of(chip, struct wm8915_priv, gpio_chip); | ||
2111 | } | ||
2112 | |||
2113 | static void wm8915_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
2114 | { | ||
2115 | struct wm8915_priv *wm8915 = gpio_to_wm8915(chip); | ||
2116 | struct snd_soc_codec *codec = wm8915->codec; | ||
2117 | |||
2118 | snd_soc_update_bits(codec, WM8915_GPIO_1 + offset, | ||
2119 | WM8915_GP1_LVL, !!value << WM8915_GP1_LVL_SHIFT); | ||
2120 | } | ||
2121 | |||
2122 | static int wm8915_gpio_direction_out(struct gpio_chip *chip, | ||
2123 | unsigned offset, int value) | ||
2124 | { | ||
2125 | struct wm8915_priv *wm8915 = gpio_to_wm8915(chip); | ||
2126 | struct snd_soc_codec *codec = wm8915->codec; | ||
2127 | int val; | ||
2128 | |||
2129 | val = (1 << WM8915_GP1_FN_SHIFT) | (!!value << WM8915_GP1_LVL_SHIFT); | ||
2130 | |||
2131 | return snd_soc_update_bits(codec, WM8915_GPIO_1 + offset, | ||
2132 | WM8915_GP1_FN_MASK | WM8915_GP1_DIR | | ||
2133 | WM8915_GP1_LVL, val); | ||
2134 | } | ||
2135 | |||
2136 | static int wm8915_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
2137 | { | ||
2138 | struct wm8915_priv *wm8915 = gpio_to_wm8915(chip); | ||
2139 | struct snd_soc_codec *codec = wm8915->codec; | ||
2140 | int ret; | ||
2141 | |||
2142 | ret = snd_soc_read(codec, WM8915_GPIO_1 + offset); | ||
2143 | if (ret < 0) | ||
2144 | return ret; | ||
2145 | |||
2146 | return (ret & WM8915_GP1_LVL) != 0; | ||
2147 | } | ||
2148 | |||
2149 | static int wm8915_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
2150 | { | ||
2151 | struct wm8915_priv *wm8915 = gpio_to_wm8915(chip); | ||
2152 | struct snd_soc_codec *codec = wm8915->codec; | ||
2153 | |||
2154 | return snd_soc_update_bits(codec, WM8915_GPIO_1 + offset, | ||
2155 | WM8915_GP1_FN_MASK | WM8915_GP1_DIR, | ||
2156 | (1 << WM8915_GP1_FN_SHIFT) | | ||
2157 | (1 << WM8915_GP1_DIR_SHIFT)); | ||
2158 | } | ||
2159 | |||
2160 | static struct gpio_chip wm8915_template_chip = { | ||
2161 | .label = "wm8915", | ||
2162 | .owner = THIS_MODULE, | ||
2163 | .direction_output = wm8915_gpio_direction_out, | ||
2164 | .set = wm8915_gpio_set, | ||
2165 | .direction_input = wm8915_gpio_direction_in, | ||
2166 | .get = wm8915_gpio_get, | ||
2167 | .can_sleep = 1, | ||
2168 | }; | ||
2169 | |||
2170 | static void wm8915_init_gpio(struct snd_soc_codec *codec) | ||
2171 | { | ||
2172 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2173 | int ret; | ||
2174 | |||
2175 | wm8915->gpio_chip = wm8915_template_chip; | ||
2176 | wm8915->gpio_chip.ngpio = 5; | ||
2177 | wm8915->gpio_chip.dev = codec->dev; | ||
2178 | |||
2179 | if (wm8915->pdata.gpio_base) | ||
2180 | wm8915->gpio_chip.base = wm8915->pdata.gpio_base; | ||
2181 | else | ||
2182 | wm8915->gpio_chip.base = -1; | ||
2183 | |||
2184 | ret = gpiochip_add(&wm8915->gpio_chip); | ||
2185 | if (ret != 0) | ||
2186 | dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | ||
2187 | } | ||
2188 | |||
2189 | static void wm8915_free_gpio(struct snd_soc_codec *codec) | ||
2190 | { | ||
2191 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2192 | int ret; | ||
2193 | |||
2194 | ret = gpiochip_remove(&wm8915->gpio_chip); | ||
2195 | if (ret != 0) | ||
2196 | dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | ||
2197 | } | ||
2198 | #else | ||
2199 | static void wm8915_init_gpio(struct snd_soc_codec *codec) | ||
2200 | { | ||
2201 | } | ||
2202 | |||
2203 | static void wm8915_free_gpio(struct snd_soc_codec *codec) | ||
2204 | { | ||
2205 | } | ||
2206 | #endif | ||
2207 | |||
2208 | /** | ||
2209 | * wm8915_detect - Enable default WM8915 jack detection | ||
2210 | * | ||
2211 | * The WM8915 has advanced accessory detection support for headsets. | ||
2212 | * This function provides a default implementation which integrates | ||
2213 | * the majority of this functionality with minimal user configuration. | ||
2214 | * | ||
2215 | * This will detect headset, headphone and short circuit button and | ||
2216 | * will also detect inverted microphone ground connections and update | ||
2217 | * the polarity of the connections. | ||
2218 | */ | ||
2219 | int wm8915_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | ||
2220 | wm8915_polarity_fn polarity_cb) | ||
2221 | { | ||
2222 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2223 | |||
2224 | wm8915->jack = jack; | ||
2225 | wm8915->detecting = true; | ||
2226 | wm8915->polarity_cb = polarity_cb; | ||
2227 | |||
2228 | if (wm8915->polarity_cb) | ||
2229 | wm8915->polarity_cb(codec, 0); | ||
2230 | |||
2231 | /* Clear discarge to avoid noise during detection */ | ||
2232 | snd_soc_update_bits(codec, WM8915_MICBIAS_1, | ||
2233 | WM8915_MICB1_DISCH, 0); | ||
2234 | snd_soc_update_bits(codec, WM8915_MICBIAS_2, | ||
2235 | WM8915_MICB2_DISCH, 0); | ||
2236 | |||
2237 | /* LDO2 powers the microphones, SYSCLK clocks detection */ | ||
2238 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | ||
2239 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); | ||
2240 | |||
2241 | /* We start off just enabling microphone detection - even a | ||
2242 | * plain headphone will trigger detection. | ||
2243 | */ | ||
2244 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2245 | WM8915_MICD_ENA, WM8915_MICD_ENA); | ||
2246 | |||
2247 | /* Slowest detection rate, gives debounce for initial detection */ | ||
2248 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2249 | WM8915_MICD_RATE_MASK, | ||
2250 | WM8915_MICD_RATE_MASK); | ||
2251 | |||
2252 | /* Enable interrupts and we're off */ | ||
2253 | snd_soc_update_bits(codec, WM8915_INTERRUPT_STATUS_2_MASK, | ||
2254 | WM8915_IM_MICD_EINT, 0); | ||
2255 | |||
2256 | return 0; | ||
2257 | } | ||
2258 | EXPORT_SYMBOL_GPL(wm8915_detect); | ||
2259 | |||
2260 | static void wm8915_micd(struct snd_soc_codec *codec) | ||
2261 | { | ||
2262 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2263 | int val, reg; | ||
2264 | |||
2265 | val = snd_soc_read(codec, WM8915_MIC_DETECT_3); | ||
2266 | |||
2267 | dev_dbg(codec->dev, "Microphone event: %x\n", val); | ||
2268 | |||
2269 | if (!(val & WM8915_MICD_VALID)) { | ||
2270 | dev_warn(codec->dev, "Microphone detection state invalid\n"); | ||
2271 | return; | ||
2272 | } | ||
2273 | |||
2274 | /* No accessory, reset everything and report removal */ | ||
2275 | if (!(val & WM8915_MICD_STS)) { | ||
2276 | dev_dbg(codec->dev, "Jack removal detected\n"); | ||
2277 | wm8915->jack_mic = false; | ||
2278 | wm8915->detecting = true; | ||
2279 | snd_soc_jack_report(wm8915->jack, 0, | ||
2280 | SND_JACK_HEADSET | SND_JACK_BTN_0); | ||
2281 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2282 | WM8915_MICD_RATE_MASK, | ||
2283 | WM8915_MICD_RATE_MASK); | ||
2284 | return; | ||
2285 | } | ||
2286 | |||
2287 | /* If the measurement is very high we've got a microphone but | ||
2288 | * do a little debounce to account for mechanical issues. | ||
2289 | */ | ||
2290 | if (val & 0x400) { | ||
2291 | dev_dbg(codec->dev, "Microphone detected\n"); | ||
2292 | snd_soc_jack_report(wm8915->jack, SND_JACK_HEADSET, | ||
2293 | SND_JACK_HEADSET | SND_JACK_BTN_0); | ||
2294 | wm8915->jack_mic = true; | ||
2295 | wm8915->detecting = false; | ||
2296 | } | ||
2297 | |||
2298 | /* If we detected a lower impedence during initial startup | ||
2299 | * then we probably have the wrong polarity, flip it. Don't | ||
2300 | * do this for the lowest impedences to speed up detection of | ||
2301 | * plain headphones. | ||
2302 | */ | ||
2303 | if (wm8915->detecting && (val & 0x3f0)) { | ||
2304 | reg = snd_soc_read(codec, WM8915_ACCESSORY_DETECT_MODE_2); | ||
2305 | reg ^= WM8915_HPOUT1FB_SRC | WM8915_MICD_SRC | | ||
2306 | WM8915_MICD_BIAS_SRC; | ||
2307 | snd_soc_update_bits(codec, WM8915_ACCESSORY_DETECT_MODE_2, | ||
2308 | WM8915_HPOUT1FB_SRC | WM8915_MICD_SRC | | ||
2309 | WM8915_MICD_BIAS_SRC, reg); | ||
2310 | |||
2311 | if (wm8915->polarity_cb) | ||
2312 | wm8915->polarity_cb(codec, | ||
2313 | (reg & WM8915_MICD_SRC) != 0); | ||
2314 | |||
2315 | dev_dbg(codec->dev, "Set microphone polarity to %d\n", | ||
2316 | (reg & WM8915_MICD_SRC) != 0); | ||
2317 | |||
2318 | return; | ||
2319 | } | ||
2320 | |||
2321 | /* Don't distinguish between buttons, just report any low | ||
2322 | * impedence as BTN_0. | ||
2323 | */ | ||
2324 | if (val & 0x3fc) { | ||
2325 | if (wm8915->jack_mic) { | ||
2326 | dev_dbg(codec->dev, "Mic button detected\n"); | ||
2327 | snd_soc_jack_report(wm8915->jack, | ||
2328 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
2329 | SND_JACK_HEADSET | SND_JACK_BTN_0); | ||
2330 | } else { | ||
2331 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2332 | snd_soc_jack_report(wm8915->jack, | ||
2333 | SND_JACK_HEADPHONE, | ||
2334 | SND_JACK_HEADSET | | ||
2335 | SND_JACK_BTN_0); | ||
2336 | wm8915->detecting = false; | ||
2337 | } | ||
2338 | } | ||
2339 | |||
2340 | /* Increase poll rate to give better responsiveness for buttons */ | ||
2341 | if (!wm8915->detecting) | ||
2342 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2343 | WM8915_MICD_RATE_MASK, | ||
2344 | 5 << WM8915_MICD_RATE_SHIFT); | ||
2345 | } | ||
2346 | |||
2347 | static irqreturn_t wm8915_irq(int irq, void *data) | ||
2348 | { | ||
2349 | struct snd_soc_codec *codec = data; | ||
2350 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2351 | int irq_val; | ||
2352 | |||
2353 | irq_val = snd_soc_read(codec, WM8915_INTERRUPT_STATUS_2); | ||
2354 | if (irq_val < 0) { | ||
2355 | dev_err(codec->dev, "Failed to read IRQ status: %d\n", | ||
2356 | irq_val); | ||
2357 | return IRQ_NONE; | ||
2358 | } | ||
2359 | irq_val &= ~snd_soc_read(codec, WM8915_INTERRUPT_STATUS_2_MASK); | ||
2360 | |||
2361 | if (irq_val & (WM8915_DCS_DONE_01_EINT | WM8915_DCS_DONE_23_EINT)) { | ||
2362 | dev_dbg(codec->dev, "DC servo IRQ\n"); | ||
2363 | complete(&wm8915->dcs_done); | ||
2364 | } | ||
2365 | |||
2366 | if (irq_val & WM8915_FIFOS_ERR_EINT) | ||
2367 | dev_err(codec->dev, "Digital core FIFO error\n"); | ||
2368 | |||
2369 | if (irq_val & WM8915_FLL_LOCK_EINT) { | ||
2370 | dev_dbg(codec->dev, "FLL locked\n"); | ||
2371 | complete(&wm8915->fll_lock); | ||
2372 | } | ||
2373 | |||
2374 | if (irq_val & WM8915_MICD_EINT) | ||
2375 | wm8915_micd(codec); | ||
2376 | |||
2377 | if (irq_val) { | ||
2378 | snd_soc_write(codec, WM8915_INTERRUPT_STATUS_2, irq_val); | ||
2379 | |||
2380 | return IRQ_HANDLED; | ||
2381 | } else { | ||
2382 | return IRQ_NONE; | ||
2383 | } | ||
2384 | } | ||
2385 | |||
2386 | static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) | ||
2387 | { | ||
2388 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2389 | struct wm8915_pdata *pdata = &wm8915->pdata; | ||
2390 | |||
2391 | struct snd_kcontrol_new controls[] = { | ||
2392 | SOC_ENUM_EXT("DSP1 EQ Mode", | ||
2393 | wm8915->retune_mobile_enum, | ||
2394 | wm8915_get_retune_mobile_enum, | ||
2395 | wm8915_put_retune_mobile_enum), | ||
2396 | SOC_ENUM_EXT("DSP2 EQ Mode", | ||
2397 | wm8915->retune_mobile_enum, | ||
2398 | wm8915_get_retune_mobile_enum, | ||
2399 | wm8915_put_retune_mobile_enum), | ||
2400 | }; | ||
2401 | int ret, i, j; | ||
2402 | const char **t; | ||
2403 | |||
2404 | /* We need an array of texts for the enum API but the number | ||
2405 | * of texts is likely to be less than the number of | ||
2406 | * configurations due to the sample rate dependency of the | ||
2407 | * configurations. */ | ||
2408 | wm8915->num_retune_mobile_texts = 0; | ||
2409 | wm8915->retune_mobile_texts = NULL; | ||
2410 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
2411 | for (j = 0; j < wm8915->num_retune_mobile_texts; j++) { | ||
2412 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
2413 | wm8915->retune_mobile_texts[j]) == 0) | ||
2414 | break; | ||
2415 | } | ||
2416 | |||
2417 | if (j != wm8915->num_retune_mobile_texts) | ||
2418 | continue; | ||
2419 | |||
2420 | /* Expand the array... */ | ||
2421 | t = krealloc(wm8915->retune_mobile_texts, | ||
2422 | sizeof(char *) * | ||
2423 | (wm8915->num_retune_mobile_texts + 1), | ||
2424 | GFP_KERNEL); | ||
2425 | if (t == NULL) | ||
2426 | continue; | ||
2427 | |||
2428 | /* ...store the new entry... */ | ||
2429 | t[wm8915->num_retune_mobile_texts] = | ||
2430 | pdata->retune_mobile_cfgs[i].name; | ||
2431 | |||
2432 | /* ...and remember the new version. */ | ||
2433 | wm8915->num_retune_mobile_texts++; | ||
2434 | wm8915->retune_mobile_texts = t; | ||
2435 | } | ||
2436 | |||
2437 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | ||
2438 | wm8915->num_retune_mobile_texts); | ||
2439 | |||
2440 | wm8915->retune_mobile_enum.max = wm8915->num_retune_mobile_texts; | ||
2441 | wm8915->retune_mobile_enum.texts = wm8915->retune_mobile_texts; | ||
2442 | |||
2443 | ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | ||
2444 | if (ret != 0) | ||
2445 | dev_err(codec->dev, | ||
2446 | "Failed to add ReTune Mobile controls: %d\n", ret); | ||
2447 | } | ||
2448 | |||
2449 | static int wm8915_probe(struct snd_soc_codec *codec) | ||
2450 | { | ||
2451 | int ret; | ||
2452 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2453 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
2454 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2455 | int i, irq_flags; | ||
2456 | |||
2457 | wm8915->codec = codec; | ||
2458 | |||
2459 | init_completion(&wm8915->dcs_done); | ||
2460 | init_completion(&wm8915->fll_lock); | ||
2461 | |||
2462 | dapm->idle_bias_off = true; | ||
2463 | dapm->bias_level = SND_SOC_BIAS_OFF; | ||
2464 | |||
2465 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); | ||
2466 | if (ret != 0) { | ||
2467 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2468 | goto err; | ||
2469 | } | ||
2470 | |||
2471 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) | ||
2472 | wm8915->supplies[i].supply = wm8915_supply_names[i]; | ||
2473 | |||
2474 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8915->supplies), | ||
2475 | wm8915->supplies); | ||
2476 | if (ret != 0) { | ||
2477 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
2478 | goto err; | ||
2479 | } | ||
2480 | |||
2481 | wm8915->disable_nb[0].notifier_call = wm8915_regulator_event_0; | ||
2482 | wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; | ||
2483 | wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; | ||
2484 | wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; | ||
2485 | wm8915->disable_nb[4].notifier_call = wm8915_regulator_event_4; | ||
2486 | wm8915->disable_nb[5].notifier_call = wm8915_regulator_event_5; | ||
2487 | |||
2488 | /* This should really be moved into the regulator core */ | ||
2489 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { | ||
2490 | ret = regulator_register_notifier(wm8915->supplies[i].consumer, | ||
2491 | &wm8915->disable_nb[i]); | ||
2492 | if (ret != 0) { | ||
2493 | dev_err(codec->dev, | ||
2494 | "Failed to register regulator notifier: %d\n", | ||
2495 | ret); | ||
2496 | } | ||
2497 | } | ||
2498 | |||
2499 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8915->supplies), | ||
2500 | wm8915->supplies); | ||
2501 | if (ret != 0) { | ||
2502 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
2503 | goto err_get; | ||
2504 | } | ||
2505 | |||
2506 | if (wm8915->pdata.ldo_ena >= 0) { | ||
2507 | gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 1); | ||
2508 | msleep(5); | ||
2509 | } | ||
2510 | |||
2511 | ret = snd_soc_read(codec, WM8915_SOFTWARE_RESET); | ||
2512 | if (ret < 0) { | ||
2513 | dev_err(codec->dev, "Failed to read ID register: %d\n", ret); | ||
2514 | goto err_enable; | ||
2515 | } | ||
2516 | if (ret != 0x8915) { | ||
2517 | dev_err(codec->dev, "Device is not a WM8915, ID %x\n", ret); | ||
2518 | ret = -EINVAL; | ||
2519 | goto err_enable; | ||
2520 | } | ||
2521 | |||
2522 | ret = snd_soc_read(codec, WM8915_CHIP_REVISION); | ||
2523 | if (ret < 0) { | ||
2524 | dev_err(codec->dev, "Failed to read device revision: %d\n", | ||
2525 | ret); | ||
2526 | goto err_enable; | ||
2527 | } | ||
2528 | |||
2529 | dev_info(codec->dev, "revision %c\n", | ||
2530 | (ret & WM8915_CHIP_REV_MASK) + 'A'); | ||
2531 | |||
2532 | if (wm8915->pdata.ldo_ena >= 0) { | ||
2533 | gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0); | ||
2534 | } else { | ||
2535 | ret = wm8915_reset(codec); | ||
2536 | if (ret < 0) { | ||
2537 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
2538 | goto err_enable; | ||
2539 | } | ||
2540 | } | ||
2541 | |||
2542 | codec->cache_only = true; | ||
2543 | |||
2544 | /* Apply platform data settings */ | ||
2545 | snd_soc_update_bits(codec, WM8915_LINE_INPUT_CONTROL, | ||
2546 | WM8915_INL_MODE_MASK | WM8915_INR_MODE_MASK, | ||
2547 | wm8915->pdata.inl_mode << WM8915_INL_MODE_SHIFT | | ||
2548 | wm8915->pdata.inr_mode); | ||
2549 | |||
2550 | for (i = 0; i < ARRAY_SIZE(wm8915->pdata.gpio_default); i++) { | ||
2551 | if (!wm8915->pdata.gpio_default[i]) | ||
2552 | continue; | ||
2553 | |||
2554 | snd_soc_write(codec, WM8915_GPIO_1 + i, | ||
2555 | wm8915->pdata.gpio_default[i] & 0xffff); | ||
2556 | } | ||
2557 | |||
2558 | if (wm8915->pdata.spkmute_seq) | ||
2559 | snd_soc_update_bits(codec, WM8915_PDM_SPEAKER_MUTE_SEQUENCE, | ||
2560 | WM8915_SPK_MUTE_ENDIAN | | ||
2561 | WM8915_SPK_MUTE_SEQ1_MASK, | ||
2562 | wm8915->pdata.spkmute_seq); | ||
2563 | |||
2564 | snd_soc_update_bits(codec, WM8915_ACCESSORY_DETECT_MODE_2, | ||
2565 | WM8915_MICD_BIAS_SRC | WM8915_HPOUT1FB_SRC | | ||
2566 | WM8915_MICD_SRC, wm8915->pdata.micdet_def); | ||
2567 | |||
2568 | /* Latch volume update bits */ | ||
2569 | snd_soc_update_bits(codec, WM8915_LEFT_LINE_INPUT_VOLUME, | ||
2570 | WM8915_IN1_VU, WM8915_IN1_VU); | ||
2571 | snd_soc_update_bits(codec, WM8915_RIGHT_LINE_INPUT_VOLUME, | ||
2572 | WM8915_IN1_VU, WM8915_IN1_VU); | ||
2573 | |||
2574 | snd_soc_update_bits(codec, WM8915_DAC1_LEFT_VOLUME, | ||
2575 | WM8915_DAC1_VU, WM8915_DAC1_VU); | ||
2576 | snd_soc_update_bits(codec, WM8915_DAC1_RIGHT_VOLUME, | ||
2577 | WM8915_DAC1_VU, WM8915_DAC1_VU); | ||
2578 | snd_soc_update_bits(codec, WM8915_DAC2_LEFT_VOLUME, | ||
2579 | WM8915_DAC2_VU, WM8915_DAC2_VU); | ||
2580 | snd_soc_update_bits(codec, WM8915_DAC2_RIGHT_VOLUME, | ||
2581 | WM8915_DAC2_VU, WM8915_DAC2_VU); | ||
2582 | |||
2583 | snd_soc_update_bits(codec, WM8915_OUTPUT1_LEFT_VOLUME, | ||
2584 | WM8915_DAC1_VU, WM8915_DAC1_VU); | ||
2585 | snd_soc_update_bits(codec, WM8915_OUTPUT1_RIGHT_VOLUME, | ||
2586 | WM8915_DAC1_VU, WM8915_DAC1_VU); | ||
2587 | snd_soc_update_bits(codec, WM8915_OUTPUT2_LEFT_VOLUME, | ||
2588 | WM8915_DAC2_VU, WM8915_DAC2_VU); | ||
2589 | snd_soc_update_bits(codec, WM8915_OUTPUT2_RIGHT_VOLUME, | ||
2590 | WM8915_DAC2_VU, WM8915_DAC2_VU); | ||
2591 | |||
2592 | snd_soc_update_bits(codec, WM8915_DSP1_TX_LEFT_VOLUME, | ||
2593 | WM8915_DSP1TX_VU, WM8915_DSP1TX_VU); | ||
2594 | snd_soc_update_bits(codec, WM8915_DSP1_TX_RIGHT_VOLUME, | ||
2595 | WM8915_DSP1TX_VU, WM8915_DSP1TX_VU); | ||
2596 | snd_soc_update_bits(codec, WM8915_DSP2_TX_LEFT_VOLUME, | ||
2597 | WM8915_DSP2TX_VU, WM8915_DSP2TX_VU); | ||
2598 | snd_soc_update_bits(codec, WM8915_DSP2_TX_RIGHT_VOLUME, | ||
2599 | WM8915_DSP2TX_VU, WM8915_DSP2TX_VU); | ||
2600 | |||
2601 | snd_soc_update_bits(codec, WM8915_DSP1_RX_LEFT_VOLUME, | ||
2602 | WM8915_DSP1RX_VU, WM8915_DSP1RX_VU); | ||
2603 | snd_soc_update_bits(codec, WM8915_DSP1_RX_RIGHT_VOLUME, | ||
2604 | WM8915_DSP1RX_VU, WM8915_DSP1RX_VU); | ||
2605 | snd_soc_update_bits(codec, WM8915_DSP2_RX_LEFT_VOLUME, | ||
2606 | WM8915_DSP2RX_VU, WM8915_DSP2RX_VU); | ||
2607 | snd_soc_update_bits(codec, WM8915_DSP2_RX_RIGHT_VOLUME, | ||
2608 | WM8915_DSP2RX_VU, WM8915_DSP2RX_VU); | ||
2609 | |||
2610 | /* No support currently for the underclocked TDM modes and | ||
2611 | * pick a default TDM layout with each channel pair working with | ||
2612 | * slots 0 and 1. */ | ||
2613 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_0_CONFIGURATION, | ||
2614 | WM8915_AIF1RX_CHAN0_SLOTS_MASK | | ||
2615 | WM8915_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2616 | 1 << WM8915_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | ||
2617 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_1_CONFIGURATION, | ||
2618 | WM8915_AIF1RX_CHAN1_SLOTS_MASK | | ||
2619 | WM8915_AIF1RX_CHAN1_START_SLOT_MASK, | ||
2620 | 1 << WM8915_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | ||
2621 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_2_CONFIGURATION, | ||
2622 | WM8915_AIF1RX_CHAN2_SLOTS_MASK | | ||
2623 | WM8915_AIF1RX_CHAN2_START_SLOT_MASK, | ||
2624 | 1 << WM8915_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | ||
2625 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_3_CONFIGURATION, | ||
2626 | WM8915_AIF1RX_CHAN3_SLOTS_MASK | | ||
2627 | WM8915_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2628 | 1 << WM8915_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | ||
2629 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_4_CONFIGURATION, | ||
2630 | WM8915_AIF1RX_CHAN4_SLOTS_MASK | | ||
2631 | WM8915_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2632 | 1 << WM8915_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | ||
2633 | snd_soc_update_bits(codec, WM8915_AIF1RX_CHANNEL_5_CONFIGURATION, | ||
2634 | WM8915_AIF1RX_CHAN5_SLOTS_MASK | | ||
2635 | WM8915_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2636 | 1 << WM8915_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | ||
2637 | |||
2638 | snd_soc_update_bits(codec, WM8915_AIF2RX_CHANNEL_0_CONFIGURATION, | ||
2639 | WM8915_AIF2RX_CHAN0_SLOTS_MASK | | ||
2640 | WM8915_AIF2RX_CHAN0_START_SLOT_MASK, | ||
2641 | 1 << WM8915_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | ||
2642 | snd_soc_update_bits(codec, WM8915_AIF2RX_CHANNEL_1_CONFIGURATION, | ||
2643 | WM8915_AIF2RX_CHAN1_SLOTS_MASK | | ||
2644 | WM8915_AIF2RX_CHAN1_START_SLOT_MASK, | ||
2645 | 1 << WM8915_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | ||
2646 | |||
2647 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_0_CONFIGURATION, | ||
2648 | WM8915_AIF1TX_CHAN0_SLOTS_MASK | | ||
2649 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2650 | 1 << WM8915_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | ||
2651 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2652 | WM8915_AIF1TX_CHAN1_SLOTS_MASK | | ||
2653 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2654 | 1 << WM8915_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2655 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_2_CONFIGURATION, | ||
2656 | WM8915_AIF1TX_CHAN2_SLOTS_MASK | | ||
2657 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2658 | 1 << WM8915_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | ||
2659 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_3_CONFIGURATION, | ||
2660 | WM8915_AIF1TX_CHAN3_SLOTS_MASK | | ||
2661 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2662 | 1 << WM8915_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | ||
2663 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_4_CONFIGURATION, | ||
2664 | WM8915_AIF1TX_CHAN4_SLOTS_MASK | | ||
2665 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2666 | 1 << WM8915_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | ||
2667 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_5_CONFIGURATION, | ||
2668 | WM8915_AIF1TX_CHAN5_SLOTS_MASK | | ||
2669 | WM8915_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2670 | 1 << WM8915_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | ||
2671 | |||
2672 | snd_soc_update_bits(codec, WM8915_AIF2TX_CHANNEL_0_CONFIGURATION, | ||
2673 | WM8915_AIF2TX_CHAN0_SLOTS_MASK | | ||
2674 | WM8915_AIF2TX_CHAN0_START_SLOT_MASK, | ||
2675 | 1 << WM8915_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | ||
2676 | snd_soc_update_bits(codec, WM8915_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2677 | WM8915_AIF2TX_CHAN1_SLOTS_MASK | | ||
2678 | WM8915_AIF2TX_CHAN1_START_SLOT_MASK, | ||
2679 | 1 << WM8915_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2680 | |||
2681 | if (wm8915->pdata.num_retune_mobile_cfgs) | ||
2682 | wm8915_retune_mobile_pdata(codec); | ||
2683 | else | ||
2684 | snd_soc_add_controls(codec, wm8915_eq_controls, | ||
2685 | ARRAY_SIZE(wm8915_eq_controls)); | ||
2686 | |||
2687 | /* If the TX LRCLK pins are not in LRCLK mode configure the | ||
2688 | * AIFs to source their clocks from the RX LRCLKs. | ||
2689 | */ | ||
2690 | if ((snd_soc_read(codec, WM8915_GPIO_1))) | ||
2691 | snd_soc_update_bits(codec, WM8915_AIF1_TX_LRCLK_2, | ||
2692 | WM8915_AIF1TX_LRCLK_MODE, | ||
2693 | WM8915_AIF1TX_LRCLK_MODE); | ||
2694 | |||
2695 | if ((snd_soc_read(codec, WM8915_GPIO_2))) | ||
2696 | snd_soc_update_bits(codec, WM8915_AIF2_TX_LRCLK_2, | ||
2697 | WM8915_AIF2TX_LRCLK_MODE, | ||
2698 | WM8915_AIF2TX_LRCLK_MODE); | ||
2699 | |||
2700 | regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies), wm8915->supplies); | ||
2701 | |||
2702 | wm8915_init_gpio(codec); | ||
2703 | |||
2704 | if (i2c->irq) { | ||
2705 | if (wm8915->pdata.irq_flags) | ||
2706 | irq_flags = wm8915->pdata.irq_flags; | ||
2707 | else | ||
2708 | irq_flags = IRQF_TRIGGER_LOW; | ||
2709 | |||
2710 | irq_flags |= IRQF_ONESHOT; | ||
2711 | |||
2712 | ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, | ||
2713 | irq_flags, "wm8915", codec); | ||
2714 | if (ret == 0) { | ||
2715 | /* Unmask the interrupt */ | ||
2716 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, | ||
2717 | WM8915_IM_IRQ, 0); | ||
2718 | |||
2719 | /* Enable error reporting and DC servo status */ | ||
2720 | snd_soc_update_bits(codec, | ||
2721 | WM8915_INTERRUPT_STATUS_2_MASK, | ||
2722 | WM8915_IM_DCS_DONE_23_EINT | | ||
2723 | WM8915_IM_DCS_DONE_01_EINT | | ||
2724 | WM8915_IM_FLL_LOCK_EINT | | ||
2725 | WM8915_IM_FIFOS_ERR_EINT, | ||
2726 | 0); | ||
2727 | } else { | ||
2728 | dev_err(codec->dev, "Failed to request IRQ: %d\n", | ||
2729 | ret); | ||
2730 | } | ||
2731 | } | ||
2732 | |||
2733 | return 0; | ||
2734 | |||
2735 | err_enable: | ||
2736 | if (wm8915->pdata.ldo_ena >= 0) | ||
2737 | gpio_set_value_cansleep(wm8915->pdata.ldo_ena, 0); | ||
2738 | |||
2739 | regulator_bulk_disable(ARRAY_SIZE(wm8915->supplies), wm8915->supplies); | ||
2740 | err_get: | ||
2741 | regulator_bulk_free(ARRAY_SIZE(wm8915->supplies), wm8915->supplies); | ||
2742 | err: | ||
2743 | return ret; | ||
2744 | } | ||
2745 | |||
2746 | static int wm8915_remove(struct snd_soc_codec *codec) | ||
2747 | { | ||
2748 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
2749 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
2750 | int i; | ||
2751 | |||
2752 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, | ||
2753 | WM8915_IM_IRQ, WM8915_IM_IRQ); | ||
2754 | |||
2755 | if (i2c->irq) | ||
2756 | free_irq(i2c->irq, codec); | ||
2757 | |||
2758 | wm8915_free_gpio(codec); | ||
2759 | |||
2760 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) | ||
2761 | regulator_unregister_notifier(wm8915->supplies[i].consumer, | ||
2762 | &wm8915->disable_nb[i]); | ||
2763 | regulator_bulk_free(ARRAY_SIZE(wm8915->supplies), wm8915->supplies); | ||
2764 | |||
2765 | return 0; | ||
2766 | } | ||
2767 | |||
2768 | static struct snd_soc_codec_driver soc_codec_dev_wm8915 = { | ||
2769 | .probe = wm8915_probe, | ||
2770 | .remove = wm8915_remove, | ||
2771 | .set_bias_level = wm8915_set_bias_level, | ||
2772 | .seq_notifier = wm8915_seq_notifier, | ||
2773 | .reg_cache_size = WM8915_MAX_REGISTER + 1, | ||
2774 | .reg_word_size = sizeof(u16), | ||
2775 | .reg_cache_default = wm8915_reg, | ||
2776 | .volatile_register = wm8915_volatile_register, | ||
2777 | .readable_register = wm8915_readable_register, | ||
2778 | .compress_type = SND_SOC_RBTREE_COMPRESSION, | ||
2779 | .controls = wm8915_snd_controls, | ||
2780 | .num_controls = ARRAY_SIZE(wm8915_snd_controls), | ||
2781 | .dapm_widgets = wm8915_dapm_widgets, | ||
2782 | .num_dapm_widgets = ARRAY_SIZE(wm8915_dapm_widgets), | ||
2783 | .dapm_routes = wm8915_dapm_routes, | ||
2784 | .num_dapm_routes = ARRAY_SIZE(wm8915_dapm_routes), | ||
2785 | .set_pll = wm8915_set_fll, | ||
2786 | }; | ||
2787 | |||
2788 | #define WM8915_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | ||
2789 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) | ||
2790 | #define WM8915_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
2791 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
2792 | SNDRV_PCM_FMTBIT_S32_LE) | ||
2793 | |||
2794 | static struct snd_soc_dai_ops wm8915_dai_ops = { | ||
2795 | .set_fmt = wm8915_set_fmt, | ||
2796 | .hw_params = wm8915_hw_params, | ||
2797 | .set_sysclk = wm8915_set_sysclk, | ||
2798 | }; | ||
2799 | |||
2800 | static struct snd_soc_dai_driver wm8915_dai[] = { | ||
2801 | { | ||
2802 | .name = "wm8915-aif1", | ||
2803 | .playback = { | ||
2804 | .stream_name = "AIF1 Playback", | ||
2805 | .channels_min = 1, | ||
2806 | .channels_max = 6, | ||
2807 | .rates = WM8915_RATES, | ||
2808 | .formats = WM8915_FORMATS, | ||
2809 | }, | ||
2810 | .capture = { | ||
2811 | .stream_name = "AIF1 Capture", | ||
2812 | .channels_min = 1, | ||
2813 | .channels_max = 6, | ||
2814 | .rates = WM8915_RATES, | ||
2815 | .formats = WM8915_FORMATS, | ||
2816 | }, | ||
2817 | .ops = &wm8915_dai_ops, | ||
2818 | }, | ||
2819 | { | ||
2820 | .name = "wm8915-aif2", | ||
2821 | .playback = { | ||
2822 | .stream_name = "AIF2 Playback", | ||
2823 | .channels_min = 1, | ||
2824 | .channels_max = 2, | ||
2825 | .rates = WM8915_RATES, | ||
2826 | .formats = WM8915_FORMATS, | ||
2827 | }, | ||
2828 | .capture = { | ||
2829 | .stream_name = "AIF2 Capture", | ||
2830 | .channels_min = 1, | ||
2831 | .channels_max = 2, | ||
2832 | .rates = WM8915_RATES, | ||
2833 | .formats = WM8915_FORMATS, | ||
2834 | }, | ||
2835 | .ops = &wm8915_dai_ops, | ||
2836 | }, | ||
2837 | }; | ||
2838 | |||
2839 | static __devinit int wm8915_i2c_probe(struct i2c_client *i2c, | ||
2840 | const struct i2c_device_id *id) | ||
2841 | { | ||
2842 | struct wm8915_priv *wm8915; | ||
2843 | int ret; | ||
2844 | |||
2845 | wm8915 = kzalloc(sizeof(struct wm8915_priv), GFP_KERNEL); | ||
2846 | if (wm8915 == NULL) | ||
2847 | return -ENOMEM; | ||
2848 | |||
2849 | i2c_set_clientdata(i2c, wm8915); | ||
2850 | |||
2851 | if (dev_get_platdata(&i2c->dev)) | ||
2852 | memcpy(&wm8915->pdata, dev_get_platdata(&i2c->dev), | ||
2853 | sizeof(wm8915->pdata)); | ||
2854 | |||
2855 | if (wm8915->pdata.ldo_ena > 0) { | ||
2856 | ret = gpio_request_one(wm8915->pdata.ldo_ena, | ||
2857 | GPIOF_OUT_INIT_LOW, "WM8915 ENA"); | ||
2858 | if (ret < 0) { | ||
2859 | dev_err(&i2c->dev, "Failed to request GPIO %d: %d\n", | ||
2860 | wm8915->pdata.ldo_ena, ret); | ||
2861 | goto err; | ||
2862 | } | ||
2863 | } | ||
2864 | |||
2865 | ret = snd_soc_register_codec(&i2c->dev, | ||
2866 | &soc_codec_dev_wm8915, wm8915_dai, | ||
2867 | ARRAY_SIZE(wm8915_dai)); | ||
2868 | if (ret < 0) | ||
2869 | goto err_gpio; | ||
2870 | |||
2871 | return ret; | ||
2872 | |||
2873 | err_gpio: | ||
2874 | if (wm8915->pdata.ldo_ena > 0) | ||
2875 | gpio_free(wm8915->pdata.ldo_ena); | ||
2876 | err: | ||
2877 | kfree(wm8915); | ||
2878 | |||
2879 | return ret; | ||
2880 | } | ||
2881 | |||
2882 | static __devexit int wm8915_i2c_remove(struct i2c_client *client) | ||
2883 | { | ||
2884 | struct wm8915_priv *wm8915 = i2c_get_clientdata(client); | ||
2885 | |||
2886 | snd_soc_unregister_codec(&client->dev); | ||
2887 | if (wm8915->pdata.ldo_ena > 0) | ||
2888 | gpio_free(wm8915->pdata.ldo_ena); | ||
2889 | kfree(i2c_get_clientdata(client)); | ||
2890 | return 0; | ||
2891 | } | ||
2892 | |||
2893 | static const struct i2c_device_id wm8915_i2c_id[] = { | ||
2894 | { "wm8915", 0 }, | ||
2895 | { } | ||
2896 | }; | ||
2897 | MODULE_DEVICE_TABLE(i2c, wm8915_i2c_id); | ||
2898 | |||
2899 | static struct i2c_driver wm8915_i2c_driver = { | ||
2900 | .driver = { | ||
2901 | .name = "wm8915", | ||
2902 | .owner = THIS_MODULE, | ||
2903 | }, | ||
2904 | .probe = wm8915_i2c_probe, | ||
2905 | .remove = __devexit_p(wm8915_i2c_remove), | ||
2906 | .id_table = wm8915_i2c_id, | ||
2907 | }; | ||
2908 | |||
2909 | static int __init wm8915_modinit(void) | ||
2910 | { | ||
2911 | int ret; | ||
2912 | |||
2913 | ret = i2c_add_driver(&wm8915_i2c_driver); | ||
2914 | if (ret != 0) { | ||
2915 | printk(KERN_ERR "Failed to register WM8915 I2C driver: %d\n", | ||
2916 | ret); | ||
2917 | } | ||
2918 | |||
2919 | return ret; | ||
2920 | } | ||
2921 | module_init(wm8915_modinit); | ||
2922 | |||
2923 | static void __exit wm8915_exit(void) | ||
2924 | { | ||
2925 | i2c_del_driver(&wm8915_i2c_driver); | ||
2926 | } | ||
2927 | module_exit(wm8915_exit); | ||
2928 | |||
2929 | MODULE_DESCRIPTION("ASoC WM8915 driver"); | ||
2930 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
2931 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8915.h b/sound/soc/codecs/wm8915.h new file mode 100644 index 000000000000..200ffd7bf953 --- /dev/null +++ b/sound/soc/codecs/wm8915.h | |||
@@ -0,0 +1,3717 @@ | |||
1 | /* | ||
2 | * wm8915.h - WM8915 audio codec interface | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM8915_H | ||
14 | #define _WM8915_H | ||
15 | |||
16 | #define WM8915_SYSCLK_MCLK1 1 | ||
17 | #define WM8915_SYSCLK_MCLK2 2 | ||
18 | #define WM8915_SYSCLK_FLL 3 | ||
19 | |||
20 | #define WM8915_FLL_MCLK1 1 | ||
21 | #define WM8915_FLL_MCLK2 2 | ||
22 | #define WM8915_FLL_DACLRCLK1 3 | ||
23 | #define WM8915_FLL_BCLK1 4 | ||
24 | |||
25 | typedef void (*wm8915_polarity_fn)(struct snd_soc_codec *codec, int polarity); | ||
26 | |||
27 | int wm8915_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | ||
28 | wm8915_polarity_fn polarity_cb); | ||
29 | |||
30 | /* | ||
31 | * Register values. | ||
32 | */ | ||
33 | #define WM8915_SOFTWARE_RESET 0x00 | ||
34 | #define WM8915_POWER_MANAGEMENT_1 0x01 | ||
35 | #define WM8915_POWER_MANAGEMENT_2 0x02 | ||
36 | #define WM8915_POWER_MANAGEMENT_3 0x03 | ||
37 | #define WM8915_POWER_MANAGEMENT_4 0x04 | ||
38 | #define WM8915_POWER_MANAGEMENT_5 0x05 | ||
39 | #define WM8915_POWER_MANAGEMENT_6 0x06 | ||
40 | #define WM8915_POWER_MANAGEMENT_7 0x07 | ||
41 | #define WM8915_POWER_MANAGEMENT_8 0x08 | ||
42 | #define WM8915_LEFT_LINE_INPUT_VOLUME 0x10 | ||
43 | #define WM8915_RIGHT_LINE_INPUT_VOLUME 0x11 | ||
44 | #define WM8915_LINE_INPUT_CONTROL 0x12 | ||
45 | #define WM8915_DAC1_HPOUT1_VOLUME 0x15 | ||
46 | #define WM8915_DAC2_HPOUT2_VOLUME 0x16 | ||
47 | #define WM8915_DAC1_LEFT_VOLUME 0x18 | ||
48 | #define WM8915_DAC1_RIGHT_VOLUME 0x19 | ||
49 | #define WM8915_DAC2_LEFT_VOLUME 0x1A | ||
50 | #define WM8915_DAC2_RIGHT_VOLUME 0x1B | ||
51 | #define WM8915_OUTPUT1_LEFT_VOLUME 0x1C | ||
52 | #define WM8915_OUTPUT1_RIGHT_VOLUME 0x1D | ||
53 | #define WM8915_OUTPUT2_LEFT_VOLUME 0x1E | ||
54 | #define WM8915_OUTPUT2_RIGHT_VOLUME 0x1F | ||
55 | #define WM8915_MICBIAS_1 0x20 | ||
56 | #define WM8915_MICBIAS_2 0x21 | ||
57 | #define WM8915_LDO_1 0x28 | ||
58 | #define WM8915_LDO_2 0x29 | ||
59 | #define WM8915_ACCESSORY_DETECT_MODE_1 0x30 | ||
60 | #define WM8915_ACCESSORY_DETECT_MODE_2 0x31 | ||
61 | #define WM8915_HEADPHONE_DETECT_1 0x34 | ||
62 | #define WM8915_HEADPHONE_DETECT_2 0x35 | ||
63 | #define WM8915_MIC_DETECT_1 0x38 | ||
64 | #define WM8915_MIC_DETECT_2 0x39 | ||
65 | #define WM8915_MIC_DETECT_3 0x3A | ||
66 | #define WM8915_CHARGE_PUMP_1 0x40 | ||
67 | #define WM8915_CHARGE_PUMP_2 0x41 | ||
68 | #define WM8915_DC_SERVO_1 0x50 | ||
69 | #define WM8915_DC_SERVO_2 0x51 | ||
70 | #define WM8915_DC_SERVO_3 0x52 | ||
71 | #define WM8915_DC_SERVO_5 0x54 | ||
72 | #define WM8915_DC_SERVO_6 0x55 | ||
73 | #define WM8915_DC_SERVO_7 0x56 | ||
74 | #define WM8915_DC_SERVO_READBACK_0 0x57 | ||
75 | #define WM8915_ANALOGUE_HP_1 0x60 | ||
76 | #define WM8915_ANALOGUE_HP_2 0x61 | ||
77 | #define WM8915_CHIP_REVISION 0x100 | ||
78 | #define WM8915_CONTROL_INTERFACE_1 0x101 | ||
79 | #define WM8915_WRITE_SEQUENCER_CTRL_1 0x110 | ||
80 | #define WM8915_WRITE_SEQUENCER_CTRL_2 0x111 | ||
81 | #define WM8915_AIF_CLOCKING_1 0x200 | ||
82 | #define WM8915_AIF_CLOCKING_2 0x201 | ||
83 | #define WM8915_CLOCKING_1 0x208 | ||
84 | #define WM8915_CLOCKING_2 0x209 | ||
85 | #define WM8915_AIF_RATE 0x210 | ||
86 | #define WM8915_FLL_CONTROL_1 0x220 | ||
87 | #define WM8915_FLL_CONTROL_2 0x221 | ||
88 | #define WM8915_FLL_CONTROL_3 0x222 | ||
89 | #define WM8915_FLL_CONTROL_4 0x223 | ||
90 | #define WM8915_FLL_CONTROL_5 0x224 | ||
91 | #define WM8915_FLL_CONTROL_6 0x225 | ||
92 | #define WM8915_FLL_EFS_1 0x226 | ||
93 | #define WM8915_FLL_EFS_2 0x227 | ||
94 | #define WM8915_AIF1_CONTROL 0x300 | ||
95 | #define WM8915_AIF1_BCLK 0x301 | ||
96 | #define WM8915_AIF1_TX_LRCLK_1 0x302 | ||
97 | #define WM8915_AIF1_TX_LRCLK_2 0x303 | ||
98 | #define WM8915_AIF1_RX_LRCLK_1 0x304 | ||
99 | #define WM8915_AIF1_RX_LRCLK_2 0x305 | ||
100 | #define WM8915_AIF1TX_DATA_CONFIGURATION_1 0x306 | ||
101 | #define WM8915_AIF1TX_DATA_CONFIGURATION_2 0x307 | ||
102 | #define WM8915_AIF1RX_DATA_CONFIGURATION 0x308 | ||
103 | #define WM8915_AIF1TX_CHANNEL_0_CONFIGURATION 0x309 | ||
104 | #define WM8915_AIF1TX_CHANNEL_1_CONFIGURATION 0x30A | ||
105 | #define WM8915_AIF1TX_CHANNEL_2_CONFIGURATION 0x30B | ||
106 | #define WM8915_AIF1TX_CHANNEL_3_CONFIGURATION 0x30C | ||
107 | #define WM8915_AIF1TX_CHANNEL_4_CONFIGURATION 0x30D | ||
108 | #define WM8915_AIF1TX_CHANNEL_5_CONFIGURATION 0x30E | ||
109 | #define WM8915_AIF1RX_CHANNEL_0_CONFIGURATION 0x30F | ||
110 | #define WM8915_AIF1RX_CHANNEL_1_CONFIGURATION 0x310 | ||
111 | #define WM8915_AIF1RX_CHANNEL_2_CONFIGURATION 0x311 | ||
112 | #define WM8915_AIF1RX_CHANNEL_3_CONFIGURATION 0x312 | ||
113 | #define WM8915_AIF1RX_CHANNEL_4_CONFIGURATION 0x313 | ||
114 | #define WM8915_AIF1RX_CHANNEL_5_CONFIGURATION 0x314 | ||
115 | #define WM8915_AIF1RX_MONO_CONFIGURATION 0x315 | ||
116 | #define WM8915_AIF1TX_TEST 0x31A | ||
117 | #define WM8915_AIF2_CONTROL 0x320 | ||
118 | #define WM8915_AIF2_BCLK 0x321 | ||
119 | #define WM8915_AIF2_TX_LRCLK_1 0x322 | ||
120 | #define WM8915_AIF2_TX_LRCLK_2 0x323 | ||
121 | #define WM8915_AIF2_RX_LRCLK_1 0x324 | ||
122 | #define WM8915_AIF2_RX_LRCLK_2 0x325 | ||
123 | #define WM8915_AIF2TX_DATA_CONFIGURATION_1 0x326 | ||
124 | #define WM8915_AIF2TX_DATA_CONFIGURATION_2 0x327 | ||
125 | #define WM8915_AIF2RX_DATA_CONFIGURATION 0x328 | ||
126 | #define WM8915_AIF2TX_CHANNEL_0_CONFIGURATION 0x329 | ||
127 | #define WM8915_AIF2TX_CHANNEL_1_CONFIGURATION 0x32A | ||
128 | #define WM8915_AIF2RX_CHANNEL_0_CONFIGURATION 0x32B | ||
129 | #define WM8915_AIF2RX_CHANNEL_1_CONFIGURATION 0x32C | ||
130 | #define WM8915_AIF2RX_MONO_CONFIGURATION 0x32D | ||
131 | #define WM8915_AIF2TX_TEST 0x32F | ||
132 | #define WM8915_DSP1_TX_LEFT_VOLUME 0x400 | ||
133 | #define WM8915_DSP1_TX_RIGHT_VOLUME 0x401 | ||
134 | #define WM8915_DSP1_RX_LEFT_VOLUME 0x402 | ||
135 | #define WM8915_DSP1_RX_RIGHT_VOLUME 0x403 | ||
136 | #define WM8915_DSP1_TX_FILTERS 0x410 | ||
137 | #define WM8915_DSP1_RX_FILTERS_1 0x420 | ||
138 | #define WM8915_DSP1_RX_FILTERS_2 0x421 | ||
139 | #define WM8915_DSP1_DRC_1 0x440 | ||
140 | #define WM8915_DSP1_DRC_2 0x441 | ||
141 | #define WM8915_DSP1_DRC_3 0x442 | ||
142 | #define WM8915_DSP1_DRC_4 0x443 | ||
143 | #define WM8915_DSP1_DRC_5 0x444 | ||
144 | #define WM8915_DSP1_RX_EQ_GAINS_1 0x480 | ||
145 | #define WM8915_DSP1_RX_EQ_GAINS_2 0x481 | ||
146 | #define WM8915_DSP1_RX_EQ_BAND_1_A 0x482 | ||
147 | #define WM8915_DSP1_RX_EQ_BAND_1_B 0x483 | ||
148 | #define WM8915_DSP1_RX_EQ_BAND_1_PG 0x484 | ||
149 | #define WM8915_DSP1_RX_EQ_BAND_2_A 0x485 | ||
150 | #define WM8915_DSP1_RX_EQ_BAND_2_B 0x486 | ||
151 | #define WM8915_DSP1_RX_EQ_BAND_2_C 0x487 | ||
152 | #define WM8915_DSP1_RX_EQ_BAND_2_PG 0x488 | ||
153 | #define WM8915_DSP1_RX_EQ_BAND_3_A 0x489 | ||
154 | #define WM8915_DSP1_RX_EQ_BAND_3_B 0x48A | ||
155 | #define WM8915_DSP1_RX_EQ_BAND_3_C 0x48B | ||
156 | #define WM8915_DSP1_RX_EQ_BAND_3_PG 0x48C | ||
157 | #define WM8915_DSP1_RX_EQ_BAND_4_A 0x48D | ||
158 | #define WM8915_DSP1_RX_EQ_BAND_4_B 0x48E | ||
159 | #define WM8915_DSP1_RX_EQ_BAND_4_C 0x48F | ||
160 | #define WM8915_DSP1_RX_EQ_BAND_4_PG 0x490 | ||
161 | #define WM8915_DSP1_RX_EQ_BAND_5_A 0x491 | ||
162 | #define WM8915_DSP1_RX_EQ_BAND_5_B 0x492 | ||
163 | #define WM8915_DSP1_RX_EQ_BAND_5_PG 0x493 | ||
164 | #define WM8915_DSP2_TX_LEFT_VOLUME 0x500 | ||
165 | #define WM8915_DSP2_TX_RIGHT_VOLUME 0x501 | ||
166 | #define WM8915_DSP2_RX_LEFT_VOLUME 0x502 | ||
167 | #define WM8915_DSP2_RX_RIGHT_VOLUME 0x503 | ||
168 | #define WM8915_DSP2_TX_FILTERS 0x510 | ||
169 | #define WM8915_DSP2_RX_FILTERS_1 0x520 | ||
170 | #define WM8915_DSP2_RX_FILTERS_2 0x521 | ||
171 | #define WM8915_DSP2_DRC_1 0x540 | ||
172 | #define WM8915_DSP2_DRC_2 0x541 | ||
173 | #define WM8915_DSP2_DRC_3 0x542 | ||
174 | #define WM8915_DSP2_DRC_4 0x543 | ||
175 | #define WM8915_DSP2_DRC_5 0x544 | ||
176 | #define WM8915_DSP2_RX_EQ_GAINS_1 0x580 | ||
177 | #define WM8915_DSP2_RX_EQ_GAINS_2 0x581 | ||
178 | #define WM8915_DSP2_RX_EQ_BAND_1_A 0x582 | ||
179 | #define WM8915_DSP2_RX_EQ_BAND_1_B 0x583 | ||
180 | #define WM8915_DSP2_RX_EQ_BAND_1_PG 0x584 | ||
181 | #define WM8915_DSP2_RX_EQ_BAND_2_A 0x585 | ||
182 | #define WM8915_DSP2_RX_EQ_BAND_2_B 0x586 | ||
183 | #define WM8915_DSP2_RX_EQ_BAND_2_C 0x587 | ||
184 | #define WM8915_DSP2_RX_EQ_BAND_2_PG 0x588 | ||
185 | #define WM8915_DSP2_RX_EQ_BAND_3_A 0x589 | ||
186 | #define WM8915_DSP2_RX_EQ_BAND_3_B 0x58A | ||
187 | #define WM8915_DSP2_RX_EQ_BAND_3_C 0x58B | ||
188 | #define WM8915_DSP2_RX_EQ_BAND_3_PG 0x58C | ||
189 | #define WM8915_DSP2_RX_EQ_BAND_4_A 0x58D | ||
190 | #define WM8915_DSP2_RX_EQ_BAND_4_B 0x58E | ||
191 | #define WM8915_DSP2_RX_EQ_BAND_4_C 0x58F | ||
192 | #define WM8915_DSP2_RX_EQ_BAND_4_PG 0x590 | ||
193 | #define WM8915_DSP2_RX_EQ_BAND_5_A 0x591 | ||
194 | #define WM8915_DSP2_RX_EQ_BAND_5_B 0x592 | ||
195 | #define WM8915_DSP2_RX_EQ_BAND_5_PG 0x593 | ||
196 | #define WM8915_DAC1_MIXER_VOLUMES 0x600 | ||
197 | #define WM8915_DAC1_LEFT_MIXER_ROUTING 0x601 | ||
198 | #define WM8915_DAC1_RIGHT_MIXER_ROUTING 0x602 | ||
199 | #define WM8915_DAC2_MIXER_VOLUMES 0x603 | ||
200 | #define WM8915_DAC2_LEFT_MIXER_ROUTING 0x604 | ||
201 | #define WM8915_DAC2_RIGHT_MIXER_ROUTING 0x605 | ||
202 | #define WM8915_DSP1_TX_LEFT_MIXER_ROUTING 0x606 | ||
203 | #define WM8915_DSP1_TX_RIGHT_MIXER_ROUTING 0x607 | ||
204 | #define WM8915_DSP2_TX_LEFT_MIXER_ROUTING 0x608 | ||
205 | #define WM8915_DSP2_TX_RIGHT_MIXER_ROUTING 0x609 | ||
206 | #define WM8915_DSP_TX_MIXER_SELECT 0x60A | ||
207 | #define WM8915_DAC_SOFTMUTE 0x610 | ||
208 | #define WM8915_OVERSAMPLING 0x620 | ||
209 | #define WM8915_SIDETONE 0x621 | ||
210 | #define WM8915_GPIO_1 0x700 | ||
211 | #define WM8915_GPIO_2 0x701 | ||
212 | #define WM8915_GPIO_3 0x702 | ||
213 | #define WM8915_GPIO_4 0x703 | ||
214 | #define WM8915_GPIO_5 0x704 | ||
215 | #define WM8915_PULL_CONTROL_1 0x720 | ||
216 | #define WM8915_PULL_CONTROL_2 0x721 | ||
217 | #define WM8915_INTERRUPT_STATUS_1 0x730 | ||
218 | #define WM8915_INTERRUPT_STATUS_2 0x731 | ||
219 | #define WM8915_INTERRUPT_RAW_STATUS_2 0x732 | ||
220 | #define WM8915_INTERRUPT_STATUS_1_MASK 0x738 | ||
221 | #define WM8915_INTERRUPT_STATUS_2_MASK 0x739 | ||
222 | #define WM8915_INTERRUPT_CONTROL 0x740 | ||
223 | #define WM8915_LEFT_PDM_SPEAKER 0x800 | ||
224 | #define WM8915_RIGHT_PDM_SPEAKER 0x801 | ||
225 | #define WM8915_PDM_SPEAKER_MUTE_SEQUENCE 0x802 | ||
226 | #define WM8915_PDM_SPEAKER_VOLUME 0x803 | ||
227 | #define WM8915_WRITE_SEQUENCER_0 0x3000 | ||
228 | #define WM8915_WRITE_SEQUENCER_1 0x3001 | ||
229 | #define WM8915_WRITE_SEQUENCER_2 0x3002 | ||
230 | #define WM8915_WRITE_SEQUENCER_3 0x3003 | ||
231 | #define WM8915_WRITE_SEQUENCER_4 0x3004 | ||
232 | #define WM8915_WRITE_SEQUENCER_5 0x3005 | ||
233 | #define WM8915_WRITE_SEQUENCER_6 0x3006 | ||
234 | #define WM8915_WRITE_SEQUENCER_7 0x3007 | ||
235 | #define WM8915_WRITE_SEQUENCER_8 0x3008 | ||
236 | #define WM8915_WRITE_SEQUENCER_9 0x3009 | ||
237 | #define WM8915_WRITE_SEQUENCER_10 0x300A | ||
238 | #define WM8915_WRITE_SEQUENCER_11 0x300B | ||
239 | #define WM8915_WRITE_SEQUENCER_12 0x300C | ||
240 | #define WM8915_WRITE_SEQUENCER_13 0x300D | ||
241 | #define WM8915_WRITE_SEQUENCER_14 0x300E | ||
242 | #define WM8915_WRITE_SEQUENCER_15 0x300F | ||
243 | #define WM8915_WRITE_SEQUENCER_16 0x3010 | ||
244 | #define WM8915_WRITE_SEQUENCER_17 0x3011 | ||
245 | #define WM8915_WRITE_SEQUENCER_18 0x3012 | ||
246 | #define WM8915_WRITE_SEQUENCER_19 0x3013 | ||
247 | #define WM8915_WRITE_SEQUENCER_20 0x3014 | ||
248 | #define WM8915_WRITE_SEQUENCER_21 0x3015 | ||
249 | #define WM8915_WRITE_SEQUENCER_22 0x3016 | ||
250 | #define WM8915_WRITE_SEQUENCER_23 0x3017 | ||
251 | #define WM8915_WRITE_SEQUENCER_24 0x3018 | ||
252 | #define WM8915_WRITE_SEQUENCER_25 0x3019 | ||
253 | #define WM8915_WRITE_SEQUENCER_26 0x301A | ||
254 | #define WM8915_WRITE_SEQUENCER_27 0x301B | ||
255 | #define WM8915_WRITE_SEQUENCER_28 0x301C | ||
256 | #define WM8915_WRITE_SEQUENCER_29 0x301D | ||
257 | #define WM8915_WRITE_SEQUENCER_30 0x301E | ||
258 | #define WM8915_WRITE_SEQUENCER_31 0x301F | ||
259 | #define WM8915_WRITE_SEQUENCER_32 0x3020 | ||
260 | #define WM8915_WRITE_SEQUENCER_33 0x3021 | ||
261 | #define WM8915_WRITE_SEQUENCER_34 0x3022 | ||
262 | #define WM8915_WRITE_SEQUENCER_35 0x3023 | ||
263 | #define WM8915_WRITE_SEQUENCER_36 0x3024 | ||
264 | #define WM8915_WRITE_SEQUENCER_37 0x3025 | ||
265 | #define WM8915_WRITE_SEQUENCER_38 0x3026 | ||
266 | #define WM8915_WRITE_SEQUENCER_39 0x3027 | ||
267 | #define WM8915_WRITE_SEQUENCER_40 0x3028 | ||
268 | #define WM8915_WRITE_SEQUENCER_41 0x3029 | ||
269 | #define WM8915_WRITE_SEQUENCER_42 0x302A | ||
270 | #define WM8915_WRITE_SEQUENCER_43 0x302B | ||
271 | #define WM8915_WRITE_SEQUENCER_44 0x302C | ||
272 | #define WM8915_WRITE_SEQUENCER_45 0x302D | ||
273 | #define WM8915_WRITE_SEQUENCER_46 0x302E | ||
274 | #define WM8915_WRITE_SEQUENCER_47 0x302F | ||
275 | #define WM8915_WRITE_SEQUENCER_48 0x3030 | ||
276 | #define WM8915_WRITE_SEQUENCER_49 0x3031 | ||
277 | #define WM8915_WRITE_SEQUENCER_50 0x3032 | ||
278 | #define WM8915_WRITE_SEQUENCER_51 0x3033 | ||
279 | #define WM8915_WRITE_SEQUENCER_52 0x3034 | ||
280 | #define WM8915_WRITE_SEQUENCER_53 0x3035 | ||
281 | #define WM8915_WRITE_SEQUENCER_54 0x3036 | ||
282 | #define WM8915_WRITE_SEQUENCER_55 0x3037 | ||
283 | #define WM8915_WRITE_SEQUENCER_56 0x3038 | ||
284 | #define WM8915_WRITE_SEQUENCER_57 0x3039 | ||
285 | #define WM8915_WRITE_SEQUENCER_58 0x303A | ||
286 | #define WM8915_WRITE_SEQUENCER_59 0x303B | ||
287 | #define WM8915_WRITE_SEQUENCER_60 0x303C | ||
288 | #define WM8915_WRITE_SEQUENCER_61 0x303D | ||
289 | #define WM8915_WRITE_SEQUENCER_62 0x303E | ||
290 | #define WM8915_WRITE_SEQUENCER_63 0x303F | ||
291 | #define WM8915_WRITE_SEQUENCER_64 0x3040 | ||
292 | #define WM8915_WRITE_SEQUENCER_65 0x3041 | ||
293 | #define WM8915_WRITE_SEQUENCER_66 0x3042 | ||
294 | #define WM8915_WRITE_SEQUENCER_67 0x3043 | ||
295 | #define WM8915_WRITE_SEQUENCER_68 0x3044 | ||
296 | #define WM8915_WRITE_SEQUENCER_69 0x3045 | ||
297 | #define WM8915_WRITE_SEQUENCER_70 0x3046 | ||
298 | #define WM8915_WRITE_SEQUENCER_71 0x3047 | ||
299 | #define WM8915_WRITE_SEQUENCER_72 0x3048 | ||
300 | #define WM8915_WRITE_SEQUENCER_73 0x3049 | ||
301 | #define WM8915_WRITE_SEQUENCER_74 0x304A | ||
302 | #define WM8915_WRITE_SEQUENCER_75 0x304B | ||
303 | #define WM8915_WRITE_SEQUENCER_76 0x304C | ||
304 | #define WM8915_WRITE_SEQUENCER_77 0x304D | ||
305 | #define WM8915_WRITE_SEQUENCER_78 0x304E | ||
306 | #define WM8915_WRITE_SEQUENCER_79 0x304F | ||
307 | #define WM8915_WRITE_SEQUENCER_80 0x3050 | ||
308 | #define WM8915_WRITE_SEQUENCER_81 0x3051 | ||
309 | #define WM8915_WRITE_SEQUENCER_82 0x3052 | ||
310 | #define WM8915_WRITE_SEQUENCER_83 0x3053 | ||
311 | #define WM8915_WRITE_SEQUENCER_84 0x3054 | ||
312 | #define WM8915_WRITE_SEQUENCER_85 0x3055 | ||
313 | #define WM8915_WRITE_SEQUENCER_86 0x3056 | ||
314 | #define WM8915_WRITE_SEQUENCER_87 0x3057 | ||
315 | #define WM8915_WRITE_SEQUENCER_88 0x3058 | ||
316 | #define WM8915_WRITE_SEQUENCER_89 0x3059 | ||
317 | #define WM8915_WRITE_SEQUENCER_90 0x305A | ||
318 | #define WM8915_WRITE_SEQUENCER_91 0x305B | ||
319 | #define WM8915_WRITE_SEQUENCER_92 0x305C | ||
320 | #define WM8915_WRITE_SEQUENCER_93 0x305D | ||
321 | #define WM8915_WRITE_SEQUENCER_94 0x305E | ||
322 | #define WM8915_WRITE_SEQUENCER_95 0x305F | ||
323 | #define WM8915_WRITE_SEQUENCER_96 0x3060 | ||
324 | #define WM8915_WRITE_SEQUENCER_97 0x3061 | ||
325 | #define WM8915_WRITE_SEQUENCER_98 0x3062 | ||
326 | #define WM8915_WRITE_SEQUENCER_99 0x3063 | ||
327 | #define WM8915_WRITE_SEQUENCER_100 0x3064 | ||
328 | #define WM8915_WRITE_SEQUENCER_101 0x3065 | ||
329 | #define WM8915_WRITE_SEQUENCER_102 0x3066 | ||
330 | #define WM8915_WRITE_SEQUENCER_103 0x3067 | ||
331 | #define WM8915_WRITE_SEQUENCER_104 0x3068 | ||
332 | #define WM8915_WRITE_SEQUENCER_105 0x3069 | ||
333 | #define WM8915_WRITE_SEQUENCER_106 0x306A | ||
334 | #define WM8915_WRITE_SEQUENCER_107 0x306B | ||
335 | #define WM8915_WRITE_SEQUENCER_108 0x306C | ||
336 | #define WM8915_WRITE_SEQUENCER_109 0x306D | ||
337 | #define WM8915_WRITE_SEQUENCER_110 0x306E | ||
338 | #define WM8915_WRITE_SEQUENCER_111 0x306F | ||
339 | #define WM8915_WRITE_SEQUENCER_112 0x3070 | ||
340 | #define WM8915_WRITE_SEQUENCER_113 0x3071 | ||
341 | #define WM8915_WRITE_SEQUENCER_114 0x3072 | ||
342 | #define WM8915_WRITE_SEQUENCER_115 0x3073 | ||
343 | #define WM8915_WRITE_SEQUENCER_116 0x3074 | ||
344 | #define WM8915_WRITE_SEQUENCER_117 0x3075 | ||
345 | #define WM8915_WRITE_SEQUENCER_118 0x3076 | ||
346 | #define WM8915_WRITE_SEQUENCER_119 0x3077 | ||
347 | #define WM8915_WRITE_SEQUENCER_120 0x3078 | ||
348 | #define WM8915_WRITE_SEQUENCER_121 0x3079 | ||
349 | #define WM8915_WRITE_SEQUENCER_122 0x307A | ||
350 | #define WM8915_WRITE_SEQUENCER_123 0x307B | ||
351 | #define WM8915_WRITE_SEQUENCER_124 0x307C | ||
352 | #define WM8915_WRITE_SEQUENCER_125 0x307D | ||
353 | #define WM8915_WRITE_SEQUENCER_126 0x307E | ||
354 | #define WM8915_WRITE_SEQUENCER_127 0x307F | ||
355 | #define WM8915_WRITE_SEQUENCER_128 0x3080 | ||
356 | #define WM8915_WRITE_SEQUENCER_129 0x3081 | ||
357 | #define WM8915_WRITE_SEQUENCER_130 0x3082 | ||
358 | #define WM8915_WRITE_SEQUENCER_131 0x3083 | ||
359 | #define WM8915_WRITE_SEQUENCER_132 0x3084 | ||
360 | #define WM8915_WRITE_SEQUENCER_133 0x3085 | ||
361 | #define WM8915_WRITE_SEQUENCER_134 0x3086 | ||
362 | #define WM8915_WRITE_SEQUENCER_135 0x3087 | ||
363 | #define WM8915_WRITE_SEQUENCER_136 0x3088 | ||
364 | #define WM8915_WRITE_SEQUENCER_137 0x3089 | ||
365 | #define WM8915_WRITE_SEQUENCER_138 0x308A | ||
366 | #define WM8915_WRITE_SEQUENCER_139 0x308B | ||
367 | #define WM8915_WRITE_SEQUENCER_140 0x308C | ||
368 | #define WM8915_WRITE_SEQUENCER_141 0x308D | ||
369 | #define WM8915_WRITE_SEQUENCER_142 0x308E | ||
370 | #define WM8915_WRITE_SEQUENCER_143 0x308F | ||
371 | #define WM8915_WRITE_SEQUENCER_144 0x3090 | ||
372 | #define WM8915_WRITE_SEQUENCER_145 0x3091 | ||
373 | #define WM8915_WRITE_SEQUENCER_146 0x3092 | ||
374 | #define WM8915_WRITE_SEQUENCER_147 0x3093 | ||
375 | #define WM8915_WRITE_SEQUENCER_148 0x3094 | ||
376 | #define WM8915_WRITE_SEQUENCER_149 0x3095 | ||
377 | #define WM8915_WRITE_SEQUENCER_150 0x3096 | ||
378 | #define WM8915_WRITE_SEQUENCER_151 0x3097 | ||
379 | #define WM8915_WRITE_SEQUENCER_152 0x3098 | ||
380 | #define WM8915_WRITE_SEQUENCER_153 0x3099 | ||
381 | #define WM8915_WRITE_SEQUENCER_154 0x309A | ||
382 | #define WM8915_WRITE_SEQUENCER_155 0x309B | ||
383 | #define WM8915_WRITE_SEQUENCER_156 0x309C | ||
384 | #define WM8915_WRITE_SEQUENCER_157 0x309D | ||
385 | #define WM8915_WRITE_SEQUENCER_158 0x309E | ||
386 | #define WM8915_WRITE_SEQUENCER_159 0x309F | ||
387 | #define WM8915_WRITE_SEQUENCER_160 0x30A0 | ||
388 | #define WM8915_WRITE_SEQUENCER_161 0x30A1 | ||
389 | #define WM8915_WRITE_SEQUENCER_162 0x30A2 | ||
390 | #define WM8915_WRITE_SEQUENCER_163 0x30A3 | ||
391 | #define WM8915_WRITE_SEQUENCER_164 0x30A4 | ||
392 | #define WM8915_WRITE_SEQUENCER_165 0x30A5 | ||
393 | #define WM8915_WRITE_SEQUENCER_166 0x30A6 | ||
394 | #define WM8915_WRITE_SEQUENCER_167 0x30A7 | ||
395 | #define WM8915_WRITE_SEQUENCER_168 0x30A8 | ||
396 | #define WM8915_WRITE_SEQUENCER_169 0x30A9 | ||
397 | #define WM8915_WRITE_SEQUENCER_170 0x30AA | ||
398 | #define WM8915_WRITE_SEQUENCER_171 0x30AB | ||
399 | #define WM8915_WRITE_SEQUENCER_172 0x30AC | ||
400 | #define WM8915_WRITE_SEQUENCER_173 0x30AD | ||
401 | #define WM8915_WRITE_SEQUENCER_174 0x30AE | ||
402 | #define WM8915_WRITE_SEQUENCER_175 0x30AF | ||
403 | #define WM8915_WRITE_SEQUENCER_176 0x30B0 | ||
404 | #define WM8915_WRITE_SEQUENCER_177 0x30B1 | ||
405 | #define WM8915_WRITE_SEQUENCER_178 0x30B2 | ||
406 | #define WM8915_WRITE_SEQUENCER_179 0x30B3 | ||
407 | #define WM8915_WRITE_SEQUENCER_180 0x30B4 | ||
408 | #define WM8915_WRITE_SEQUENCER_181 0x30B5 | ||
409 | #define WM8915_WRITE_SEQUENCER_182 0x30B6 | ||
410 | #define WM8915_WRITE_SEQUENCER_183 0x30B7 | ||
411 | #define WM8915_WRITE_SEQUENCER_184 0x30B8 | ||
412 | #define WM8915_WRITE_SEQUENCER_185 0x30B9 | ||
413 | #define WM8915_WRITE_SEQUENCER_186 0x30BA | ||
414 | #define WM8915_WRITE_SEQUENCER_187 0x30BB | ||
415 | #define WM8915_WRITE_SEQUENCER_188 0x30BC | ||
416 | #define WM8915_WRITE_SEQUENCER_189 0x30BD | ||
417 | #define WM8915_WRITE_SEQUENCER_190 0x30BE | ||
418 | #define WM8915_WRITE_SEQUENCER_191 0x30BF | ||
419 | #define WM8915_WRITE_SEQUENCER_192 0x30C0 | ||
420 | #define WM8915_WRITE_SEQUENCER_193 0x30C1 | ||
421 | #define WM8915_WRITE_SEQUENCER_194 0x30C2 | ||
422 | #define WM8915_WRITE_SEQUENCER_195 0x30C3 | ||
423 | #define WM8915_WRITE_SEQUENCER_196 0x30C4 | ||
424 | #define WM8915_WRITE_SEQUENCER_197 0x30C5 | ||
425 | #define WM8915_WRITE_SEQUENCER_198 0x30C6 | ||
426 | #define WM8915_WRITE_SEQUENCER_199 0x30C7 | ||
427 | #define WM8915_WRITE_SEQUENCER_200 0x30C8 | ||
428 | #define WM8915_WRITE_SEQUENCER_201 0x30C9 | ||
429 | #define WM8915_WRITE_SEQUENCER_202 0x30CA | ||
430 | #define WM8915_WRITE_SEQUENCER_203 0x30CB | ||
431 | #define WM8915_WRITE_SEQUENCER_204 0x30CC | ||
432 | #define WM8915_WRITE_SEQUENCER_205 0x30CD | ||
433 | #define WM8915_WRITE_SEQUENCER_206 0x30CE | ||
434 | #define WM8915_WRITE_SEQUENCER_207 0x30CF | ||
435 | #define WM8915_WRITE_SEQUENCER_208 0x30D0 | ||
436 | #define WM8915_WRITE_SEQUENCER_209 0x30D1 | ||
437 | #define WM8915_WRITE_SEQUENCER_210 0x30D2 | ||
438 | #define WM8915_WRITE_SEQUENCER_211 0x30D3 | ||
439 | #define WM8915_WRITE_SEQUENCER_212 0x30D4 | ||
440 | #define WM8915_WRITE_SEQUENCER_213 0x30D5 | ||
441 | #define WM8915_WRITE_SEQUENCER_214 0x30D6 | ||
442 | #define WM8915_WRITE_SEQUENCER_215 0x30D7 | ||
443 | #define WM8915_WRITE_SEQUENCER_216 0x30D8 | ||
444 | #define WM8915_WRITE_SEQUENCER_217 0x30D9 | ||
445 | #define WM8915_WRITE_SEQUENCER_218 0x30DA | ||
446 | #define WM8915_WRITE_SEQUENCER_219 0x30DB | ||
447 | #define WM8915_WRITE_SEQUENCER_220 0x30DC | ||
448 | #define WM8915_WRITE_SEQUENCER_221 0x30DD | ||
449 | #define WM8915_WRITE_SEQUENCER_222 0x30DE | ||
450 | #define WM8915_WRITE_SEQUENCER_223 0x30DF | ||
451 | #define WM8915_WRITE_SEQUENCER_224 0x30E0 | ||
452 | #define WM8915_WRITE_SEQUENCER_225 0x30E1 | ||
453 | #define WM8915_WRITE_SEQUENCER_226 0x30E2 | ||
454 | #define WM8915_WRITE_SEQUENCER_227 0x30E3 | ||
455 | #define WM8915_WRITE_SEQUENCER_228 0x30E4 | ||
456 | #define WM8915_WRITE_SEQUENCER_229 0x30E5 | ||
457 | #define WM8915_WRITE_SEQUENCER_230 0x30E6 | ||
458 | #define WM8915_WRITE_SEQUENCER_231 0x30E7 | ||
459 | #define WM8915_WRITE_SEQUENCER_232 0x30E8 | ||
460 | #define WM8915_WRITE_SEQUENCER_233 0x30E9 | ||
461 | #define WM8915_WRITE_SEQUENCER_234 0x30EA | ||
462 | #define WM8915_WRITE_SEQUENCER_235 0x30EB | ||
463 | #define WM8915_WRITE_SEQUENCER_236 0x30EC | ||
464 | #define WM8915_WRITE_SEQUENCER_237 0x30ED | ||
465 | #define WM8915_WRITE_SEQUENCER_238 0x30EE | ||
466 | #define WM8915_WRITE_SEQUENCER_239 0x30EF | ||
467 | #define WM8915_WRITE_SEQUENCER_240 0x30F0 | ||
468 | #define WM8915_WRITE_SEQUENCER_241 0x30F1 | ||
469 | #define WM8915_WRITE_SEQUENCER_242 0x30F2 | ||
470 | #define WM8915_WRITE_SEQUENCER_243 0x30F3 | ||
471 | #define WM8915_WRITE_SEQUENCER_244 0x30F4 | ||
472 | #define WM8915_WRITE_SEQUENCER_245 0x30F5 | ||
473 | #define WM8915_WRITE_SEQUENCER_246 0x30F6 | ||
474 | #define WM8915_WRITE_SEQUENCER_247 0x30F7 | ||
475 | #define WM8915_WRITE_SEQUENCER_248 0x30F8 | ||
476 | #define WM8915_WRITE_SEQUENCER_249 0x30F9 | ||
477 | #define WM8915_WRITE_SEQUENCER_250 0x30FA | ||
478 | #define WM8915_WRITE_SEQUENCER_251 0x30FB | ||
479 | #define WM8915_WRITE_SEQUENCER_252 0x30FC | ||
480 | #define WM8915_WRITE_SEQUENCER_253 0x30FD | ||
481 | #define WM8915_WRITE_SEQUENCER_254 0x30FE | ||
482 | #define WM8915_WRITE_SEQUENCER_255 0x30FF | ||
483 | #define WM8915_WRITE_SEQUENCER_256 0x3100 | ||
484 | #define WM8915_WRITE_SEQUENCER_257 0x3101 | ||
485 | #define WM8915_WRITE_SEQUENCER_258 0x3102 | ||
486 | #define WM8915_WRITE_SEQUENCER_259 0x3103 | ||
487 | #define WM8915_WRITE_SEQUENCER_260 0x3104 | ||
488 | #define WM8915_WRITE_SEQUENCER_261 0x3105 | ||
489 | #define WM8915_WRITE_SEQUENCER_262 0x3106 | ||
490 | #define WM8915_WRITE_SEQUENCER_263 0x3107 | ||
491 | #define WM8915_WRITE_SEQUENCER_264 0x3108 | ||
492 | #define WM8915_WRITE_SEQUENCER_265 0x3109 | ||
493 | #define WM8915_WRITE_SEQUENCER_266 0x310A | ||
494 | #define WM8915_WRITE_SEQUENCER_267 0x310B | ||
495 | #define WM8915_WRITE_SEQUENCER_268 0x310C | ||
496 | #define WM8915_WRITE_SEQUENCER_269 0x310D | ||
497 | #define WM8915_WRITE_SEQUENCER_270 0x310E | ||
498 | #define WM8915_WRITE_SEQUENCER_271 0x310F | ||
499 | #define WM8915_WRITE_SEQUENCER_272 0x3110 | ||
500 | #define WM8915_WRITE_SEQUENCER_273 0x3111 | ||
501 | #define WM8915_WRITE_SEQUENCER_274 0x3112 | ||
502 | #define WM8915_WRITE_SEQUENCER_275 0x3113 | ||
503 | #define WM8915_WRITE_SEQUENCER_276 0x3114 | ||
504 | #define WM8915_WRITE_SEQUENCER_277 0x3115 | ||
505 | #define WM8915_WRITE_SEQUENCER_278 0x3116 | ||
506 | #define WM8915_WRITE_SEQUENCER_279 0x3117 | ||
507 | #define WM8915_WRITE_SEQUENCER_280 0x3118 | ||
508 | #define WM8915_WRITE_SEQUENCER_281 0x3119 | ||
509 | #define WM8915_WRITE_SEQUENCER_282 0x311A | ||
510 | #define WM8915_WRITE_SEQUENCER_283 0x311B | ||
511 | #define WM8915_WRITE_SEQUENCER_284 0x311C | ||
512 | #define WM8915_WRITE_SEQUENCER_285 0x311D | ||
513 | #define WM8915_WRITE_SEQUENCER_286 0x311E | ||
514 | #define WM8915_WRITE_SEQUENCER_287 0x311F | ||
515 | #define WM8915_WRITE_SEQUENCER_288 0x3120 | ||
516 | #define WM8915_WRITE_SEQUENCER_289 0x3121 | ||
517 | #define WM8915_WRITE_SEQUENCER_290 0x3122 | ||
518 | #define WM8915_WRITE_SEQUENCER_291 0x3123 | ||
519 | #define WM8915_WRITE_SEQUENCER_292 0x3124 | ||
520 | #define WM8915_WRITE_SEQUENCER_293 0x3125 | ||
521 | #define WM8915_WRITE_SEQUENCER_294 0x3126 | ||
522 | #define WM8915_WRITE_SEQUENCER_295 0x3127 | ||
523 | #define WM8915_WRITE_SEQUENCER_296 0x3128 | ||
524 | #define WM8915_WRITE_SEQUENCER_297 0x3129 | ||
525 | #define WM8915_WRITE_SEQUENCER_298 0x312A | ||
526 | #define WM8915_WRITE_SEQUENCER_299 0x312B | ||
527 | #define WM8915_WRITE_SEQUENCER_300 0x312C | ||
528 | #define WM8915_WRITE_SEQUENCER_301 0x312D | ||
529 | #define WM8915_WRITE_SEQUENCER_302 0x312E | ||
530 | #define WM8915_WRITE_SEQUENCER_303 0x312F | ||
531 | #define WM8915_WRITE_SEQUENCER_304 0x3130 | ||
532 | #define WM8915_WRITE_SEQUENCER_305 0x3131 | ||
533 | #define WM8915_WRITE_SEQUENCER_306 0x3132 | ||
534 | #define WM8915_WRITE_SEQUENCER_307 0x3133 | ||
535 | #define WM8915_WRITE_SEQUENCER_308 0x3134 | ||
536 | #define WM8915_WRITE_SEQUENCER_309 0x3135 | ||
537 | #define WM8915_WRITE_SEQUENCER_310 0x3136 | ||
538 | #define WM8915_WRITE_SEQUENCER_311 0x3137 | ||
539 | #define WM8915_WRITE_SEQUENCER_312 0x3138 | ||
540 | #define WM8915_WRITE_SEQUENCER_313 0x3139 | ||
541 | #define WM8915_WRITE_SEQUENCER_314 0x313A | ||
542 | #define WM8915_WRITE_SEQUENCER_315 0x313B | ||
543 | #define WM8915_WRITE_SEQUENCER_316 0x313C | ||
544 | #define WM8915_WRITE_SEQUENCER_317 0x313D | ||
545 | #define WM8915_WRITE_SEQUENCER_318 0x313E | ||
546 | #define WM8915_WRITE_SEQUENCER_319 0x313F | ||
547 | #define WM8915_WRITE_SEQUENCER_320 0x3140 | ||
548 | #define WM8915_WRITE_SEQUENCER_321 0x3141 | ||
549 | #define WM8915_WRITE_SEQUENCER_322 0x3142 | ||
550 | #define WM8915_WRITE_SEQUENCER_323 0x3143 | ||
551 | #define WM8915_WRITE_SEQUENCER_324 0x3144 | ||
552 | #define WM8915_WRITE_SEQUENCER_325 0x3145 | ||
553 | #define WM8915_WRITE_SEQUENCER_326 0x3146 | ||
554 | #define WM8915_WRITE_SEQUENCER_327 0x3147 | ||
555 | #define WM8915_WRITE_SEQUENCER_328 0x3148 | ||
556 | #define WM8915_WRITE_SEQUENCER_329 0x3149 | ||
557 | #define WM8915_WRITE_SEQUENCER_330 0x314A | ||
558 | #define WM8915_WRITE_SEQUENCER_331 0x314B | ||
559 | #define WM8915_WRITE_SEQUENCER_332 0x314C | ||
560 | #define WM8915_WRITE_SEQUENCER_333 0x314D | ||
561 | #define WM8915_WRITE_SEQUENCER_334 0x314E | ||
562 | #define WM8915_WRITE_SEQUENCER_335 0x314F | ||
563 | #define WM8915_WRITE_SEQUENCER_336 0x3150 | ||
564 | #define WM8915_WRITE_SEQUENCER_337 0x3151 | ||
565 | #define WM8915_WRITE_SEQUENCER_338 0x3152 | ||
566 | #define WM8915_WRITE_SEQUENCER_339 0x3153 | ||
567 | #define WM8915_WRITE_SEQUENCER_340 0x3154 | ||
568 | #define WM8915_WRITE_SEQUENCER_341 0x3155 | ||
569 | #define WM8915_WRITE_SEQUENCER_342 0x3156 | ||
570 | #define WM8915_WRITE_SEQUENCER_343 0x3157 | ||
571 | #define WM8915_WRITE_SEQUENCER_344 0x3158 | ||
572 | #define WM8915_WRITE_SEQUENCER_345 0x3159 | ||
573 | #define WM8915_WRITE_SEQUENCER_346 0x315A | ||
574 | #define WM8915_WRITE_SEQUENCER_347 0x315B | ||
575 | #define WM8915_WRITE_SEQUENCER_348 0x315C | ||
576 | #define WM8915_WRITE_SEQUENCER_349 0x315D | ||
577 | #define WM8915_WRITE_SEQUENCER_350 0x315E | ||
578 | #define WM8915_WRITE_SEQUENCER_351 0x315F | ||
579 | #define WM8915_WRITE_SEQUENCER_352 0x3160 | ||
580 | #define WM8915_WRITE_SEQUENCER_353 0x3161 | ||
581 | #define WM8915_WRITE_SEQUENCER_354 0x3162 | ||
582 | #define WM8915_WRITE_SEQUENCER_355 0x3163 | ||
583 | #define WM8915_WRITE_SEQUENCER_356 0x3164 | ||
584 | #define WM8915_WRITE_SEQUENCER_357 0x3165 | ||
585 | #define WM8915_WRITE_SEQUENCER_358 0x3166 | ||
586 | #define WM8915_WRITE_SEQUENCER_359 0x3167 | ||
587 | #define WM8915_WRITE_SEQUENCER_360 0x3168 | ||
588 | #define WM8915_WRITE_SEQUENCER_361 0x3169 | ||
589 | #define WM8915_WRITE_SEQUENCER_362 0x316A | ||
590 | #define WM8915_WRITE_SEQUENCER_363 0x316B | ||
591 | #define WM8915_WRITE_SEQUENCER_364 0x316C | ||
592 | #define WM8915_WRITE_SEQUENCER_365 0x316D | ||
593 | #define WM8915_WRITE_SEQUENCER_366 0x316E | ||
594 | #define WM8915_WRITE_SEQUENCER_367 0x316F | ||
595 | #define WM8915_WRITE_SEQUENCER_368 0x3170 | ||
596 | #define WM8915_WRITE_SEQUENCER_369 0x3171 | ||
597 | #define WM8915_WRITE_SEQUENCER_370 0x3172 | ||
598 | #define WM8915_WRITE_SEQUENCER_371 0x3173 | ||
599 | #define WM8915_WRITE_SEQUENCER_372 0x3174 | ||
600 | #define WM8915_WRITE_SEQUENCER_373 0x3175 | ||
601 | #define WM8915_WRITE_SEQUENCER_374 0x3176 | ||
602 | #define WM8915_WRITE_SEQUENCER_375 0x3177 | ||
603 | #define WM8915_WRITE_SEQUENCER_376 0x3178 | ||
604 | #define WM8915_WRITE_SEQUENCER_377 0x3179 | ||
605 | #define WM8915_WRITE_SEQUENCER_378 0x317A | ||
606 | #define WM8915_WRITE_SEQUENCER_379 0x317B | ||
607 | #define WM8915_WRITE_SEQUENCER_380 0x317C | ||
608 | #define WM8915_WRITE_SEQUENCER_381 0x317D | ||
609 | #define WM8915_WRITE_SEQUENCER_382 0x317E | ||
610 | #define WM8915_WRITE_SEQUENCER_383 0x317F | ||
611 | #define WM8915_WRITE_SEQUENCER_384 0x3180 | ||
612 | #define WM8915_WRITE_SEQUENCER_385 0x3181 | ||
613 | #define WM8915_WRITE_SEQUENCER_386 0x3182 | ||
614 | #define WM8915_WRITE_SEQUENCER_387 0x3183 | ||
615 | #define WM8915_WRITE_SEQUENCER_388 0x3184 | ||
616 | #define WM8915_WRITE_SEQUENCER_389 0x3185 | ||
617 | #define WM8915_WRITE_SEQUENCER_390 0x3186 | ||
618 | #define WM8915_WRITE_SEQUENCER_391 0x3187 | ||
619 | #define WM8915_WRITE_SEQUENCER_392 0x3188 | ||
620 | #define WM8915_WRITE_SEQUENCER_393 0x3189 | ||
621 | #define WM8915_WRITE_SEQUENCER_394 0x318A | ||
622 | #define WM8915_WRITE_SEQUENCER_395 0x318B | ||
623 | #define WM8915_WRITE_SEQUENCER_396 0x318C | ||
624 | #define WM8915_WRITE_SEQUENCER_397 0x318D | ||
625 | #define WM8915_WRITE_SEQUENCER_398 0x318E | ||
626 | #define WM8915_WRITE_SEQUENCER_399 0x318F | ||
627 | #define WM8915_WRITE_SEQUENCER_400 0x3190 | ||
628 | #define WM8915_WRITE_SEQUENCER_401 0x3191 | ||
629 | #define WM8915_WRITE_SEQUENCER_402 0x3192 | ||
630 | #define WM8915_WRITE_SEQUENCER_403 0x3193 | ||
631 | #define WM8915_WRITE_SEQUENCER_404 0x3194 | ||
632 | #define WM8915_WRITE_SEQUENCER_405 0x3195 | ||
633 | #define WM8915_WRITE_SEQUENCER_406 0x3196 | ||
634 | #define WM8915_WRITE_SEQUENCER_407 0x3197 | ||
635 | #define WM8915_WRITE_SEQUENCER_408 0x3198 | ||
636 | #define WM8915_WRITE_SEQUENCER_409 0x3199 | ||
637 | #define WM8915_WRITE_SEQUENCER_410 0x319A | ||
638 | #define WM8915_WRITE_SEQUENCER_411 0x319B | ||
639 | #define WM8915_WRITE_SEQUENCER_412 0x319C | ||
640 | #define WM8915_WRITE_SEQUENCER_413 0x319D | ||
641 | #define WM8915_WRITE_SEQUENCER_414 0x319E | ||
642 | #define WM8915_WRITE_SEQUENCER_415 0x319F | ||
643 | #define WM8915_WRITE_SEQUENCER_416 0x31A0 | ||
644 | #define WM8915_WRITE_SEQUENCER_417 0x31A1 | ||
645 | #define WM8915_WRITE_SEQUENCER_418 0x31A2 | ||
646 | #define WM8915_WRITE_SEQUENCER_419 0x31A3 | ||
647 | #define WM8915_WRITE_SEQUENCER_420 0x31A4 | ||
648 | #define WM8915_WRITE_SEQUENCER_421 0x31A5 | ||
649 | #define WM8915_WRITE_SEQUENCER_422 0x31A6 | ||
650 | #define WM8915_WRITE_SEQUENCER_423 0x31A7 | ||
651 | #define WM8915_WRITE_SEQUENCER_424 0x31A8 | ||
652 | #define WM8915_WRITE_SEQUENCER_425 0x31A9 | ||
653 | #define WM8915_WRITE_SEQUENCER_426 0x31AA | ||
654 | #define WM8915_WRITE_SEQUENCER_427 0x31AB | ||
655 | #define WM8915_WRITE_SEQUENCER_428 0x31AC | ||
656 | #define WM8915_WRITE_SEQUENCER_429 0x31AD | ||
657 | #define WM8915_WRITE_SEQUENCER_430 0x31AE | ||
658 | #define WM8915_WRITE_SEQUENCER_431 0x31AF | ||
659 | #define WM8915_WRITE_SEQUENCER_432 0x31B0 | ||
660 | #define WM8915_WRITE_SEQUENCER_433 0x31B1 | ||
661 | #define WM8915_WRITE_SEQUENCER_434 0x31B2 | ||
662 | #define WM8915_WRITE_SEQUENCER_435 0x31B3 | ||
663 | #define WM8915_WRITE_SEQUENCER_436 0x31B4 | ||
664 | #define WM8915_WRITE_SEQUENCER_437 0x31B5 | ||
665 | #define WM8915_WRITE_SEQUENCER_438 0x31B6 | ||
666 | #define WM8915_WRITE_SEQUENCER_439 0x31B7 | ||
667 | #define WM8915_WRITE_SEQUENCER_440 0x31B8 | ||
668 | #define WM8915_WRITE_SEQUENCER_441 0x31B9 | ||
669 | #define WM8915_WRITE_SEQUENCER_442 0x31BA | ||
670 | #define WM8915_WRITE_SEQUENCER_443 0x31BB | ||
671 | #define WM8915_WRITE_SEQUENCER_444 0x31BC | ||
672 | #define WM8915_WRITE_SEQUENCER_445 0x31BD | ||
673 | #define WM8915_WRITE_SEQUENCER_446 0x31BE | ||
674 | #define WM8915_WRITE_SEQUENCER_447 0x31BF | ||
675 | #define WM8915_WRITE_SEQUENCER_448 0x31C0 | ||
676 | #define WM8915_WRITE_SEQUENCER_449 0x31C1 | ||
677 | #define WM8915_WRITE_SEQUENCER_450 0x31C2 | ||
678 | #define WM8915_WRITE_SEQUENCER_451 0x31C3 | ||
679 | #define WM8915_WRITE_SEQUENCER_452 0x31C4 | ||
680 | #define WM8915_WRITE_SEQUENCER_453 0x31C5 | ||
681 | #define WM8915_WRITE_SEQUENCER_454 0x31C6 | ||
682 | #define WM8915_WRITE_SEQUENCER_455 0x31C7 | ||
683 | #define WM8915_WRITE_SEQUENCER_456 0x31C8 | ||
684 | #define WM8915_WRITE_SEQUENCER_457 0x31C9 | ||
685 | #define WM8915_WRITE_SEQUENCER_458 0x31CA | ||
686 | #define WM8915_WRITE_SEQUENCER_459 0x31CB | ||
687 | #define WM8915_WRITE_SEQUENCER_460 0x31CC | ||
688 | #define WM8915_WRITE_SEQUENCER_461 0x31CD | ||
689 | #define WM8915_WRITE_SEQUENCER_462 0x31CE | ||
690 | #define WM8915_WRITE_SEQUENCER_463 0x31CF | ||
691 | #define WM8915_WRITE_SEQUENCER_464 0x31D0 | ||
692 | #define WM8915_WRITE_SEQUENCER_465 0x31D1 | ||
693 | #define WM8915_WRITE_SEQUENCER_466 0x31D2 | ||
694 | #define WM8915_WRITE_SEQUENCER_467 0x31D3 | ||
695 | #define WM8915_WRITE_SEQUENCER_468 0x31D4 | ||
696 | #define WM8915_WRITE_SEQUENCER_469 0x31D5 | ||
697 | #define WM8915_WRITE_SEQUENCER_470 0x31D6 | ||
698 | #define WM8915_WRITE_SEQUENCER_471 0x31D7 | ||
699 | #define WM8915_WRITE_SEQUENCER_472 0x31D8 | ||
700 | #define WM8915_WRITE_SEQUENCER_473 0x31D9 | ||
701 | #define WM8915_WRITE_SEQUENCER_474 0x31DA | ||
702 | #define WM8915_WRITE_SEQUENCER_475 0x31DB | ||
703 | #define WM8915_WRITE_SEQUENCER_476 0x31DC | ||
704 | #define WM8915_WRITE_SEQUENCER_477 0x31DD | ||
705 | #define WM8915_WRITE_SEQUENCER_478 0x31DE | ||
706 | #define WM8915_WRITE_SEQUENCER_479 0x31DF | ||
707 | #define WM8915_WRITE_SEQUENCER_480 0x31E0 | ||
708 | #define WM8915_WRITE_SEQUENCER_481 0x31E1 | ||
709 | #define WM8915_WRITE_SEQUENCER_482 0x31E2 | ||
710 | #define WM8915_WRITE_SEQUENCER_483 0x31E3 | ||
711 | #define WM8915_WRITE_SEQUENCER_484 0x31E4 | ||
712 | #define WM8915_WRITE_SEQUENCER_485 0x31E5 | ||
713 | #define WM8915_WRITE_SEQUENCER_486 0x31E6 | ||
714 | #define WM8915_WRITE_SEQUENCER_487 0x31E7 | ||
715 | #define WM8915_WRITE_SEQUENCER_488 0x31E8 | ||
716 | #define WM8915_WRITE_SEQUENCER_489 0x31E9 | ||
717 | #define WM8915_WRITE_SEQUENCER_490 0x31EA | ||
718 | #define WM8915_WRITE_SEQUENCER_491 0x31EB | ||
719 | #define WM8915_WRITE_SEQUENCER_492 0x31EC | ||
720 | #define WM8915_WRITE_SEQUENCER_493 0x31ED | ||
721 | #define WM8915_WRITE_SEQUENCER_494 0x31EE | ||
722 | #define WM8915_WRITE_SEQUENCER_495 0x31EF | ||
723 | #define WM8915_WRITE_SEQUENCER_496 0x31F0 | ||
724 | #define WM8915_WRITE_SEQUENCER_497 0x31F1 | ||
725 | #define WM8915_WRITE_SEQUENCER_498 0x31F2 | ||
726 | #define WM8915_WRITE_SEQUENCER_499 0x31F3 | ||
727 | #define WM8915_WRITE_SEQUENCER_500 0x31F4 | ||
728 | #define WM8915_WRITE_SEQUENCER_501 0x31F5 | ||
729 | #define WM8915_WRITE_SEQUENCER_502 0x31F6 | ||
730 | #define WM8915_WRITE_SEQUENCER_503 0x31F7 | ||
731 | #define WM8915_WRITE_SEQUENCER_504 0x31F8 | ||
732 | #define WM8915_WRITE_SEQUENCER_505 0x31F9 | ||
733 | #define WM8915_WRITE_SEQUENCER_506 0x31FA | ||
734 | #define WM8915_WRITE_SEQUENCER_507 0x31FB | ||
735 | #define WM8915_WRITE_SEQUENCER_508 0x31FC | ||
736 | #define WM8915_WRITE_SEQUENCER_509 0x31FD | ||
737 | #define WM8915_WRITE_SEQUENCER_510 0x31FE | ||
738 | #define WM8915_WRITE_SEQUENCER_511 0x31FF | ||
739 | |||
740 | #define WM8915_REGISTER_COUNT 706 | ||
741 | #define WM8915_MAX_REGISTER 0x31FF | ||
742 | |||
743 | /* | ||
744 | * Field Definitions. | ||
745 | */ | ||
746 | |||
747 | /* | ||
748 | * R0 (0x00) - Software Reset | ||
749 | */ | ||
750 | #define WM8915_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ | ||
751 | #define WM8915_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ | ||
752 | #define WM8915_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ | ||
753 | |||
754 | /* | ||
755 | * R1 (0x01) - Power Management (1) | ||
756 | */ | ||
757 | #define WM8915_MICB2_ENA 0x0200 /* MICB2_ENA */ | ||
758 | #define WM8915_MICB2_ENA_MASK 0x0200 /* MICB2_ENA */ | ||
759 | #define WM8915_MICB2_ENA_SHIFT 9 /* MICB2_ENA */ | ||
760 | #define WM8915_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ | ||
761 | #define WM8915_MICB1_ENA 0x0100 /* MICB1_ENA */ | ||
762 | #define WM8915_MICB1_ENA_MASK 0x0100 /* MICB1_ENA */ | ||
763 | #define WM8915_MICB1_ENA_SHIFT 8 /* MICB1_ENA */ | ||
764 | #define WM8915_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ | ||
765 | #define WM8915_HPOUT2L_ENA 0x0080 /* HPOUT2L_ENA */ | ||
766 | #define WM8915_HPOUT2L_ENA_MASK 0x0080 /* HPOUT2L_ENA */ | ||
767 | #define WM8915_HPOUT2L_ENA_SHIFT 7 /* HPOUT2L_ENA */ | ||
768 | #define WM8915_HPOUT2L_ENA_WIDTH 1 /* HPOUT2L_ENA */ | ||
769 | #define WM8915_HPOUT2R_ENA 0x0040 /* HPOUT2R_ENA */ | ||
770 | #define WM8915_HPOUT2R_ENA_MASK 0x0040 /* HPOUT2R_ENA */ | ||
771 | #define WM8915_HPOUT2R_ENA_SHIFT 6 /* HPOUT2R_ENA */ | ||
772 | #define WM8915_HPOUT2R_ENA_WIDTH 1 /* HPOUT2R_ENA */ | ||
773 | #define WM8915_HPOUT1L_ENA 0x0020 /* HPOUT1L_ENA */ | ||
774 | #define WM8915_HPOUT1L_ENA_MASK 0x0020 /* HPOUT1L_ENA */ | ||
775 | #define WM8915_HPOUT1L_ENA_SHIFT 5 /* HPOUT1L_ENA */ | ||
776 | #define WM8915_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ | ||
777 | #define WM8915_HPOUT1R_ENA 0x0010 /* HPOUT1R_ENA */ | ||
778 | #define WM8915_HPOUT1R_ENA_MASK 0x0010 /* HPOUT1R_ENA */ | ||
779 | #define WM8915_HPOUT1R_ENA_SHIFT 4 /* HPOUT1R_ENA */ | ||
780 | #define WM8915_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ | ||
781 | #define WM8915_BG_ENA 0x0001 /* BG_ENA */ | ||
782 | #define WM8915_BG_ENA_MASK 0x0001 /* BG_ENA */ | ||
783 | #define WM8915_BG_ENA_SHIFT 0 /* BG_ENA */ | ||
784 | #define WM8915_BG_ENA_WIDTH 1 /* BG_ENA */ | ||
785 | |||
786 | /* | ||
787 | * R2 (0x02) - Power Management (2) | ||
788 | */ | ||
789 | #define WM8915_OPCLK_ENA 0x0800 /* OPCLK_ENA */ | ||
790 | #define WM8915_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ | ||
791 | #define WM8915_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ | ||
792 | #define WM8915_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ | ||
793 | #define WM8915_INL_ENA 0x0020 /* INL_ENA */ | ||
794 | #define WM8915_INL_ENA_MASK 0x0020 /* INL_ENA */ | ||
795 | #define WM8915_INL_ENA_SHIFT 5 /* INL_ENA */ | ||
796 | #define WM8915_INL_ENA_WIDTH 1 /* INL_ENA */ | ||
797 | #define WM8915_INR_ENA 0x0010 /* INR_ENA */ | ||
798 | #define WM8915_INR_ENA_MASK 0x0010 /* INR_ENA */ | ||
799 | #define WM8915_INR_ENA_SHIFT 4 /* INR_ENA */ | ||
800 | #define WM8915_INR_ENA_WIDTH 1 /* INR_ENA */ | ||
801 | #define WM8915_LDO2_ENA 0x0002 /* LDO2_ENA */ | ||
802 | #define WM8915_LDO2_ENA_MASK 0x0002 /* LDO2_ENA */ | ||
803 | #define WM8915_LDO2_ENA_SHIFT 1 /* LDO2_ENA */ | ||
804 | #define WM8915_LDO2_ENA_WIDTH 1 /* LDO2_ENA */ | ||
805 | |||
806 | /* | ||
807 | * R3 (0x03) - Power Management (3) | ||
808 | */ | ||
809 | #define WM8915_DSP2RXL_ENA 0x0800 /* DSP2RXL_ENA */ | ||
810 | #define WM8915_DSP2RXL_ENA_MASK 0x0800 /* DSP2RXL_ENA */ | ||
811 | #define WM8915_DSP2RXL_ENA_SHIFT 11 /* DSP2RXL_ENA */ | ||
812 | #define WM8915_DSP2RXL_ENA_WIDTH 1 /* DSP2RXL_ENA */ | ||
813 | #define WM8915_DSP2RXR_ENA 0x0400 /* DSP2RXR_ENA */ | ||
814 | #define WM8915_DSP2RXR_ENA_MASK 0x0400 /* DSP2RXR_ENA */ | ||
815 | #define WM8915_DSP2RXR_ENA_SHIFT 10 /* DSP2RXR_ENA */ | ||
816 | #define WM8915_DSP2RXR_ENA_WIDTH 1 /* DSP2RXR_ENA */ | ||
817 | #define WM8915_DSP1RXL_ENA 0x0200 /* DSP1RXL_ENA */ | ||
818 | #define WM8915_DSP1RXL_ENA_MASK 0x0200 /* DSP1RXL_ENA */ | ||
819 | #define WM8915_DSP1RXL_ENA_SHIFT 9 /* DSP1RXL_ENA */ | ||
820 | #define WM8915_DSP1RXL_ENA_WIDTH 1 /* DSP1RXL_ENA */ | ||
821 | #define WM8915_DSP1RXR_ENA 0x0100 /* DSP1RXR_ENA */ | ||
822 | #define WM8915_DSP1RXR_ENA_MASK 0x0100 /* DSP1RXR_ENA */ | ||
823 | #define WM8915_DSP1RXR_ENA_SHIFT 8 /* DSP1RXR_ENA */ | ||
824 | #define WM8915_DSP1RXR_ENA_WIDTH 1 /* DSP1RXR_ENA */ | ||
825 | #define WM8915_DMIC2L_ENA 0x0020 /* DMIC2L_ENA */ | ||
826 | #define WM8915_DMIC2L_ENA_MASK 0x0020 /* DMIC2L_ENA */ | ||
827 | #define WM8915_DMIC2L_ENA_SHIFT 5 /* DMIC2L_ENA */ | ||
828 | #define WM8915_DMIC2L_ENA_WIDTH 1 /* DMIC2L_ENA */ | ||
829 | #define WM8915_DMIC2R_ENA 0x0010 /* DMIC2R_ENA */ | ||
830 | #define WM8915_DMIC2R_ENA_MASK 0x0010 /* DMIC2R_ENA */ | ||
831 | #define WM8915_DMIC2R_ENA_SHIFT 4 /* DMIC2R_ENA */ | ||
832 | #define WM8915_DMIC2R_ENA_WIDTH 1 /* DMIC2R_ENA */ | ||
833 | #define WM8915_DMIC1L_ENA 0x0008 /* DMIC1L_ENA */ | ||
834 | #define WM8915_DMIC1L_ENA_MASK 0x0008 /* DMIC1L_ENA */ | ||
835 | #define WM8915_DMIC1L_ENA_SHIFT 3 /* DMIC1L_ENA */ | ||
836 | #define WM8915_DMIC1L_ENA_WIDTH 1 /* DMIC1L_ENA */ | ||
837 | #define WM8915_DMIC1R_ENA 0x0004 /* DMIC1R_ENA */ | ||
838 | #define WM8915_DMIC1R_ENA_MASK 0x0004 /* DMIC1R_ENA */ | ||
839 | #define WM8915_DMIC1R_ENA_SHIFT 2 /* DMIC1R_ENA */ | ||
840 | #define WM8915_DMIC1R_ENA_WIDTH 1 /* DMIC1R_ENA */ | ||
841 | #define WM8915_ADCL_ENA 0x0002 /* ADCL_ENA */ | ||
842 | #define WM8915_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ | ||
843 | #define WM8915_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ | ||
844 | #define WM8915_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ | ||
845 | #define WM8915_ADCR_ENA 0x0001 /* ADCR_ENA */ | ||
846 | #define WM8915_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ | ||
847 | #define WM8915_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ | ||
848 | #define WM8915_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ | ||
849 | |||
850 | /* | ||
851 | * R4 (0x04) - Power Management (4) | ||
852 | */ | ||
853 | #define WM8915_AIF2RX_CHAN1_ENA 0x0200 /* AIF2RX_CHAN1_ENA */ | ||
854 | #define WM8915_AIF2RX_CHAN1_ENA_MASK 0x0200 /* AIF2RX_CHAN1_ENA */ | ||
855 | #define WM8915_AIF2RX_CHAN1_ENA_SHIFT 9 /* AIF2RX_CHAN1_ENA */ | ||
856 | #define WM8915_AIF2RX_CHAN1_ENA_WIDTH 1 /* AIF2RX_CHAN1_ENA */ | ||
857 | #define WM8915_AIF2RX_CHAN0_ENA 0x0100 /* AIF2RX_CHAN0_ENA */ | ||
858 | #define WM8915_AIF2RX_CHAN0_ENA_MASK 0x0100 /* AIF2RX_CHAN0_ENA */ | ||
859 | #define WM8915_AIF2RX_CHAN0_ENA_SHIFT 8 /* AIF2RX_CHAN0_ENA */ | ||
860 | #define WM8915_AIF2RX_CHAN0_ENA_WIDTH 1 /* AIF2RX_CHAN0_ENA */ | ||
861 | #define WM8915_AIF1RX_CHAN5_ENA 0x0020 /* AIF1RX_CHAN5_ENA */ | ||
862 | #define WM8915_AIF1RX_CHAN5_ENA_MASK 0x0020 /* AIF1RX_CHAN5_ENA */ | ||
863 | #define WM8915_AIF1RX_CHAN5_ENA_SHIFT 5 /* AIF1RX_CHAN5_ENA */ | ||
864 | #define WM8915_AIF1RX_CHAN5_ENA_WIDTH 1 /* AIF1RX_CHAN5_ENA */ | ||
865 | #define WM8915_AIF1RX_CHAN4_ENA 0x0010 /* AIF1RX_CHAN4_ENA */ | ||
866 | #define WM8915_AIF1RX_CHAN4_ENA_MASK 0x0010 /* AIF1RX_CHAN4_ENA */ | ||
867 | #define WM8915_AIF1RX_CHAN4_ENA_SHIFT 4 /* AIF1RX_CHAN4_ENA */ | ||
868 | #define WM8915_AIF1RX_CHAN4_ENA_WIDTH 1 /* AIF1RX_CHAN4_ENA */ | ||
869 | #define WM8915_AIF1RX_CHAN3_ENA 0x0008 /* AIF1RX_CHAN3_ENA */ | ||
870 | #define WM8915_AIF1RX_CHAN3_ENA_MASK 0x0008 /* AIF1RX_CHAN3_ENA */ | ||
871 | #define WM8915_AIF1RX_CHAN3_ENA_SHIFT 3 /* AIF1RX_CHAN3_ENA */ | ||
872 | #define WM8915_AIF1RX_CHAN3_ENA_WIDTH 1 /* AIF1RX_CHAN3_ENA */ | ||
873 | #define WM8915_AIF1RX_CHAN2_ENA 0x0004 /* AIF1RX_CHAN2_ENA */ | ||
874 | #define WM8915_AIF1RX_CHAN2_ENA_MASK 0x0004 /* AIF1RX_CHAN2_ENA */ | ||
875 | #define WM8915_AIF1RX_CHAN2_ENA_SHIFT 2 /* AIF1RX_CHAN2_ENA */ | ||
876 | #define WM8915_AIF1RX_CHAN2_ENA_WIDTH 1 /* AIF1RX_CHAN2_ENA */ | ||
877 | #define WM8915_AIF1RX_CHAN1_ENA 0x0002 /* AIF1RX_CHAN1_ENA */ | ||
878 | #define WM8915_AIF1RX_CHAN1_ENA_MASK 0x0002 /* AIF1RX_CHAN1_ENA */ | ||
879 | #define WM8915_AIF1RX_CHAN1_ENA_SHIFT 1 /* AIF1RX_CHAN1_ENA */ | ||
880 | #define WM8915_AIF1RX_CHAN1_ENA_WIDTH 1 /* AIF1RX_CHAN1_ENA */ | ||
881 | #define WM8915_AIF1RX_CHAN0_ENA 0x0001 /* AIF1RX_CHAN0_ENA */ | ||
882 | #define WM8915_AIF1RX_CHAN0_ENA_MASK 0x0001 /* AIF1RX_CHAN0_ENA */ | ||
883 | #define WM8915_AIF1RX_CHAN0_ENA_SHIFT 0 /* AIF1RX_CHAN0_ENA */ | ||
884 | #define WM8915_AIF1RX_CHAN0_ENA_WIDTH 1 /* AIF1RX_CHAN0_ENA */ | ||
885 | |||
886 | /* | ||
887 | * R5 (0x05) - Power Management (5) | ||
888 | */ | ||
889 | #define WM8915_DSP2TXL_ENA 0x0800 /* DSP2TXL_ENA */ | ||
890 | #define WM8915_DSP2TXL_ENA_MASK 0x0800 /* DSP2TXL_ENA */ | ||
891 | #define WM8915_DSP2TXL_ENA_SHIFT 11 /* DSP2TXL_ENA */ | ||
892 | #define WM8915_DSP2TXL_ENA_WIDTH 1 /* DSP2TXL_ENA */ | ||
893 | #define WM8915_DSP2TXR_ENA 0x0400 /* DSP2TXR_ENA */ | ||
894 | #define WM8915_DSP2TXR_ENA_MASK 0x0400 /* DSP2TXR_ENA */ | ||
895 | #define WM8915_DSP2TXR_ENA_SHIFT 10 /* DSP2TXR_ENA */ | ||
896 | #define WM8915_DSP2TXR_ENA_WIDTH 1 /* DSP2TXR_ENA */ | ||
897 | #define WM8915_DSP1TXL_ENA 0x0200 /* DSP1TXL_ENA */ | ||
898 | #define WM8915_DSP1TXL_ENA_MASK 0x0200 /* DSP1TXL_ENA */ | ||
899 | #define WM8915_DSP1TXL_ENA_SHIFT 9 /* DSP1TXL_ENA */ | ||
900 | #define WM8915_DSP1TXL_ENA_WIDTH 1 /* DSP1TXL_ENA */ | ||
901 | #define WM8915_DSP1TXR_ENA 0x0100 /* DSP1TXR_ENA */ | ||
902 | #define WM8915_DSP1TXR_ENA_MASK 0x0100 /* DSP1TXR_ENA */ | ||
903 | #define WM8915_DSP1TXR_ENA_SHIFT 8 /* DSP1TXR_ENA */ | ||
904 | #define WM8915_DSP1TXR_ENA_WIDTH 1 /* DSP1TXR_ENA */ | ||
905 | #define WM8915_DAC2L_ENA 0x0008 /* DAC2L_ENA */ | ||
906 | #define WM8915_DAC2L_ENA_MASK 0x0008 /* DAC2L_ENA */ | ||
907 | #define WM8915_DAC2L_ENA_SHIFT 3 /* DAC2L_ENA */ | ||
908 | #define WM8915_DAC2L_ENA_WIDTH 1 /* DAC2L_ENA */ | ||
909 | #define WM8915_DAC2R_ENA 0x0004 /* DAC2R_ENA */ | ||
910 | #define WM8915_DAC2R_ENA_MASK 0x0004 /* DAC2R_ENA */ | ||
911 | #define WM8915_DAC2R_ENA_SHIFT 2 /* DAC2R_ENA */ | ||
912 | #define WM8915_DAC2R_ENA_WIDTH 1 /* DAC2R_ENA */ | ||
913 | #define WM8915_DAC1L_ENA 0x0002 /* DAC1L_ENA */ | ||
914 | #define WM8915_DAC1L_ENA_MASK 0x0002 /* DAC1L_ENA */ | ||
915 | #define WM8915_DAC1L_ENA_SHIFT 1 /* DAC1L_ENA */ | ||
916 | #define WM8915_DAC1L_ENA_WIDTH 1 /* DAC1L_ENA */ | ||
917 | #define WM8915_DAC1R_ENA 0x0001 /* DAC1R_ENA */ | ||
918 | #define WM8915_DAC1R_ENA_MASK 0x0001 /* DAC1R_ENA */ | ||
919 | #define WM8915_DAC1R_ENA_SHIFT 0 /* DAC1R_ENA */ | ||
920 | #define WM8915_DAC1R_ENA_WIDTH 1 /* DAC1R_ENA */ | ||
921 | |||
922 | /* | ||
923 | * R6 (0x06) - Power Management (6) | ||
924 | */ | ||
925 | #define WM8915_AIF2TX_CHAN1_ENA 0x0200 /* AIF2TX_CHAN1_ENA */ | ||
926 | #define WM8915_AIF2TX_CHAN1_ENA_MASK 0x0200 /* AIF2TX_CHAN1_ENA */ | ||
927 | #define WM8915_AIF2TX_CHAN1_ENA_SHIFT 9 /* AIF2TX_CHAN1_ENA */ | ||
928 | #define WM8915_AIF2TX_CHAN1_ENA_WIDTH 1 /* AIF2TX_CHAN1_ENA */ | ||
929 | #define WM8915_AIF2TX_CHAN0_ENA 0x0100 /* AIF2TX_CHAN0_ENA */ | ||
930 | #define WM8915_AIF2TX_CHAN0_ENA_MASK 0x0100 /* AIF2TX_CHAN0_ENA */ | ||
931 | #define WM8915_AIF2TX_CHAN0_ENA_SHIFT 8 /* AIF2TX_CHAN0_ENA */ | ||
932 | #define WM8915_AIF2TX_CHAN0_ENA_WIDTH 1 /* AIF2TX_CHAN0_ENA */ | ||
933 | #define WM8915_AIF1TX_CHAN5_ENA 0x0020 /* AIF1TX_CHAN5_ENA */ | ||
934 | #define WM8915_AIF1TX_CHAN5_ENA_MASK 0x0020 /* AIF1TX_CHAN5_ENA */ | ||
935 | #define WM8915_AIF1TX_CHAN5_ENA_SHIFT 5 /* AIF1TX_CHAN5_ENA */ | ||
936 | #define WM8915_AIF1TX_CHAN5_ENA_WIDTH 1 /* AIF1TX_CHAN5_ENA */ | ||
937 | #define WM8915_AIF1TX_CHAN4_ENA 0x0010 /* AIF1TX_CHAN4_ENA */ | ||
938 | #define WM8915_AIF1TX_CHAN4_ENA_MASK 0x0010 /* AIF1TX_CHAN4_ENA */ | ||
939 | #define WM8915_AIF1TX_CHAN4_ENA_SHIFT 4 /* AIF1TX_CHAN4_ENA */ | ||
940 | #define WM8915_AIF1TX_CHAN4_ENA_WIDTH 1 /* AIF1TX_CHAN4_ENA */ | ||
941 | #define WM8915_AIF1TX_CHAN3_ENA 0x0008 /* AIF1TX_CHAN3_ENA */ | ||
942 | #define WM8915_AIF1TX_CHAN3_ENA_MASK 0x0008 /* AIF1TX_CHAN3_ENA */ | ||
943 | #define WM8915_AIF1TX_CHAN3_ENA_SHIFT 3 /* AIF1TX_CHAN3_ENA */ | ||
944 | #define WM8915_AIF1TX_CHAN3_ENA_WIDTH 1 /* AIF1TX_CHAN3_ENA */ | ||
945 | #define WM8915_AIF1TX_CHAN2_ENA 0x0004 /* AIF1TX_CHAN2_ENA */ | ||
946 | #define WM8915_AIF1TX_CHAN2_ENA_MASK 0x0004 /* AIF1TX_CHAN2_ENA */ | ||
947 | #define WM8915_AIF1TX_CHAN2_ENA_SHIFT 2 /* AIF1TX_CHAN2_ENA */ | ||
948 | #define WM8915_AIF1TX_CHAN2_ENA_WIDTH 1 /* AIF1TX_CHAN2_ENA */ | ||
949 | #define WM8915_AIF1TX_CHAN1_ENA 0x0002 /* AIF1TX_CHAN1_ENA */ | ||
950 | #define WM8915_AIF1TX_CHAN1_ENA_MASK 0x0002 /* AIF1TX_CHAN1_ENA */ | ||
951 | #define WM8915_AIF1TX_CHAN1_ENA_SHIFT 1 /* AIF1TX_CHAN1_ENA */ | ||
952 | #define WM8915_AIF1TX_CHAN1_ENA_WIDTH 1 /* AIF1TX_CHAN1_ENA */ | ||
953 | #define WM8915_AIF1TX_CHAN0_ENA 0x0001 /* AIF1TX_CHAN0_ENA */ | ||
954 | #define WM8915_AIF1TX_CHAN0_ENA_MASK 0x0001 /* AIF1TX_CHAN0_ENA */ | ||
955 | #define WM8915_AIF1TX_CHAN0_ENA_SHIFT 0 /* AIF1TX_CHAN0_ENA */ | ||
956 | #define WM8915_AIF1TX_CHAN0_ENA_WIDTH 1 /* AIF1TX_CHAN0_ENA */ | ||
957 | |||
958 | /* | ||
959 | * R7 (0x07) - Power Management (7) | ||
960 | */ | ||
961 | #define WM8915_DMIC2_FN 0x0200 /* DMIC2_FN */ | ||
962 | #define WM8915_DMIC2_FN_MASK 0x0200 /* DMIC2_FN */ | ||
963 | #define WM8915_DMIC2_FN_SHIFT 9 /* DMIC2_FN */ | ||
964 | #define WM8915_DMIC2_FN_WIDTH 1 /* DMIC2_FN */ | ||
965 | #define WM8915_DMIC1_FN 0x0100 /* DMIC1_FN */ | ||
966 | #define WM8915_DMIC1_FN_MASK 0x0100 /* DMIC1_FN */ | ||
967 | #define WM8915_DMIC1_FN_SHIFT 8 /* DMIC1_FN */ | ||
968 | #define WM8915_DMIC1_FN_WIDTH 1 /* DMIC1_FN */ | ||
969 | #define WM8915_ADC_DMIC_DSP2R_ENA 0x0080 /* ADC_DMIC_DSP2R_ENA */ | ||
970 | #define WM8915_ADC_DMIC_DSP2R_ENA_MASK 0x0080 /* ADC_DMIC_DSP2R_ENA */ | ||
971 | #define WM8915_ADC_DMIC_DSP2R_ENA_SHIFT 7 /* ADC_DMIC_DSP2R_ENA */ | ||
972 | #define WM8915_ADC_DMIC_DSP2R_ENA_WIDTH 1 /* ADC_DMIC_DSP2R_ENA */ | ||
973 | #define WM8915_ADC_DMIC_DSP2L_ENA 0x0040 /* ADC_DMIC_DSP2L_ENA */ | ||
974 | #define WM8915_ADC_DMIC_DSP2L_ENA_MASK 0x0040 /* ADC_DMIC_DSP2L_ENA */ | ||
975 | #define WM8915_ADC_DMIC_DSP2L_ENA_SHIFT 6 /* ADC_DMIC_DSP2L_ENA */ | ||
976 | #define WM8915_ADC_DMIC_DSP2L_ENA_WIDTH 1 /* ADC_DMIC_DSP2L_ENA */ | ||
977 | #define WM8915_ADC_DMIC_SRC2_MASK 0x0030 /* ADC_DMIC_SRC2 - [5:4] */ | ||
978 | #define WM8915_ADC_DMIC_SRC2_SHIFT 4 /* ADC_DMIC_SRC2 - [5:4] */ | ||
979 | #define WM8915_ADC_DMIC_SRC2_WIDTH 2 /* ADC_DMIC_SRC2 - [5:4] */ | ||
980 | #define WM8915_ADC_DMIC_DSP1R_ENA 0x0008 /* ADC_DMIC_DSP1R_ENA */ | ||
981 | #define WM8915_ADC_DMIC_DSP1R_ENA_MASK 0x0008 /* ADC_DMIC_DSP1R_ENA */ | ||
982 | #define WM8915_ADC_DMIC_DSP1R_ENA_SHIFT 3 /* ADC_DMIC_DSP1R_ENA */ | ||
983 | #define WM8915_ADC_DMIC_DSP1R_ENA_WIDTH 1 /* ADC_DMIC_DSP1R_ENA */ | ||
984 | #define WM8915_ADC_DMIC_DSP1L_ENA 0x0004 /* ADC_DMIC_DSP1L_ENA */ | ||
985 | #define WM8915_ADC_DMIC_DSP1L_ENA_MASK 0x0004 /* ADC_DMIC_DSP1L_ENA */ | ||
986 | #define WM8915_ADC_DMIC_DSP1L_ENA_SHIFT 2 /* ADC_DMIC_DSP1L_ENA */ | ||
987 | #define WM8915_ADC_DMIC_DSP1L_ENA_WIDTH 1 /* ADC_DMIC_DSP1L_ENA */ | ||
988 | #define WM8915_ADC_DMIC_SRC1_MASK 0x0003 /* ADC_DMIC_SRC1 - [1:0] */ | ||
989 | #define WM8915_ADC_DMIC_SRC1_SHIFT 0 /* ADC_DMIC_SRC1 - [1:0] */ | ||
990 | #define WM8915_ADC_DMIC_SRC1_WIDTH 2 /* ADC_DMIC_SRC1 - [1:0] */ | ||
991 | |||
992 | /* | ||
993 | * R8 (0x08) - Power Management (8) | ||
994 | */ | ||
995 | #define WM8915_AIF2TX_SRC_MASK 0x00C0 /* AIF2TX_SRC - [7:6] */ | ||
996 | #define WM8915_AIF2TX_SRC_SHIFT 6 /* AIF2TX_SRC - [7:6] */ | ||
997 | #define WM8915_AIF2TX_SRC_WIDTH 2 /* AIF2TX_SRC - [7:6] */ | ||
998 | #define WM8915_DSP2RX_SRC 0x0010 /* DSP2RX_SRC */ | ||
999 | #define WM8915_DSP2RX_SRC_MASK 0x0010 /* DSP2RX_SRC */ | ||
1000 | #define WM8915_DSP2RX_SRC_SHIFT 4 /* DSP2RX_SRC */ | ||
1001 | #define WM8915_DSP2RX_SRC_WIDTH 1 /* DSP2RX_SRC */ | ||
1002 | #define WM8915_DSP1RX_SRC 0x0001 /* DSP1RX_SRC */ | ||
1003 | #define WM8915_DSP1RX_SRC_MASK 0x0001 /* DSP1RX_SRC */ | ||
1004 | #define WM8915_DSP1RX_SRC_SHIFT 0 /* DSP1RX_SRC */ | ||
1005 | #define WM8915_DSP1RX_SRC_WIDTH 1 /* DSP1RX_SRC */ | ||
1006 | |||
1007 | /* | ||
1008 | * R16 (0x10) - Left Line Input Volume | ||
1009 | */ | ||
1010 | #define WM8915_IN1_VU 0x0080 /* IN1_VU */ | ||
1011 | #define WM8915_IN1_VU_MASK 0x0080 /* IN1_VU */ | ||
1012 | #define WM8915_IN1_VU_SHIFT 7 /* IN1_VU */ | ||
1013 | #define WM8915_IN1_VU_WIDTH 1 /* IN1_VU */ | ||
1014 | #define WM8915_IN1L_ZC 0x0020 /* IN1L_ZC */ | ||
1015 | #define WM8915_IN1L_ZC_MASK 0x0020 /* IN1L_ZC */ | ||
1016 | #define WM8915_IN1L_ZC_SHIFT 5 /* IN1L_ZC */ | ||
1017 | #define WM8915_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ | ||
1018 | #define WM8915_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ | ||
1019 | #define WM8915_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ | ||
1020 | #define WM8915_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ | ||
1021 | |||
1022 | /* | ||
1023 | * R17 (0x11) - Right Line Input Volume | ||
1024 | */ | ||
1025 | #define WM8915_IN1_VU 0x0080 /* IN1_VU */ | ||
1026 | #define WM8915_IN1_VU_MASK 0x0080 /* IN1_VU */ | ||
1027 | #define WM8915_IN1_VU_SHIFT 7 /* IN1_VU */ | ||
1028 | #define WM8915_IN1_VU_WIDTH 1 /* IN1_VU */ | ||
1029 | #define WM8915_IN1R_ZC 0x0020 /* IN1R_ZC */ | ||
1030 | #define WM8915_IN1R_ZC_MASK 0x0020 /* IN1R_ZC */ | ||
1031 | #define WM8915_IN1R_ZC_SHIFT 5 /* IN1R_ZC */ | ||
1032 | #define WM8915_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ | ||
1033 | #define WM8915_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ | ||
1034 | #define WM8915_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ | ||
1035 | #define WM8915_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ | ||
1036 | |||
1037 | /* | ||
1038 | * R18 (0x12) - Line Input Control | ||
1039 | */ | ||
1040 | #define WM8915_INL_MODE_MASK 0x000C /* INL_MODE - [3:2] */ | ||
1041 | #define WM8915_INL_MODE_SHIFT 2 /* INL_MODE - [3:2] */ | ||
1042 | #define WM8915_INL_MODE_WIDTH 2 /* INL_MODE - [3:2] */ | ||
1043 | #define WM8915_INR_MODE_MASK 0x0003 /* INR_MODE - [1:0] */ | ||
1044 | #define WM8915_INR_MODE_SHIFT 0 /* INR_MODE - [1:0] */ | ||
1045 | #define WM8915_INR_MODE_WIDTH 2 /* INR_MODE - [1:0] */ | ||
1046 | |||
1047 | /* | ||
1048 | * R21 (0x15) - DAC1 HPOUT1 Volume | ||
1049 | */ | ||
1050 | #define WM8915_DAC1R_HPOUT1R_VOL_MASK 0x00F0 /* DAC1R_HPOUT1R_VOL - [7:4] */ | ||
1051 | #define WM8915_DAC1R_HPOUT1R_VOL_SHIFT 4 /* DAC1R_HPOUT1R_VOL - [7:4] */ | ||
1052 | #define WM8915_DAC1R_HPOUT1R_VOL_WIDTH 4 /* DAC1R_HPOUT1R_VOL - [7:4] */ | ||
1053 | #define WM8915_DAC1L_HPOUT1L_VOL_MASK 0x000F /* DAC1L_HPOUT1L_VOL - [3:0] */ | ||
1054 | #define WM8915_DAC1L_HPOUT1L_VOL_SHIFT 0 /* DAC1L_HPOUT1L_VOL - [3:0] */ | ||
1055 | #define WM8915_DAC1L_HPOUT1L_VOL_WIDTH 4 /* DAC1L_HPOUT1L_VOL - [3:0] */ | ||
1056 | |||
1057 | /* | ||
1058 | * R22 (0x16) - DAC2 HPOUT2 Volume | ||
1059 | */ | ||
1060 | #define WM8915_DAC2R_HPOUT2R_VOL_MASK 0x00F0 /* DAC2R_HPOUT2R_VOL - [7:4] */ | ||
1061 | #define WM8915_DAC2R_HPOUT2R_VOL_SHIFT 4 /* DAC2R_HPOUT2R_VOL - [7:4] */ | ||
1062 | #define WM8915_DAC2R_HPOUT2R_VOL_WIDTH 4 /* DAC2R_HPOUT2R_VOL - [7:4] */ | ||
1063 | #define WM8915_DAC2L_HPOUT2L_VOL_MASK 0x000F /* DAC2L_HPOUT2L_VOL - [3:0] */ | ||
1064 | #define WM8915_DAC2L_HPOUT2L_VOL_SHIFT 0 /* DAC2L_HPOUT2L_VOL - [3:0] */ | ||
1065 | #define WM8915_DAC2L_HPOUT2L_VOL_WIDTH 4 /* DAC2L_HPOUT2L_VOL - [3:0] */ | ||
1066 | |||
1067 | /* | ||
1068 | * R24 (0x18) - DAC1 Left Volume | ||
1069 | */ | ||
1070 | #define WM8915_DAC1L_MUTE 0x0200 /* DAC1L_MUTE */ | ||
1071 | #define WM8915_DAC1L_MUTE_MASK 0x0200 /* DAC1L_MUTE */ | ||
1072 | #define WM8915_DAC1L_MUTE_SHIFT 9 /* DAC1L_MUTE */ | ||
1073 | #define WM8915_DAC1L_MUTE_WIDTH 1 /* DAC1L_MUTE */ | ||
1074 | #define WM8915_DAC1_VU 0x0100 /* DAC1_VU */ | ||
1075 | #define WM8915_DAC1_VU_MASK 0x0100 /* DAC1_VU */ | ||
1076 | #define WM8915_DAC1_VU_SHIFT 8 /* DAC1_VU */ | ||
1077 | #define WM8915_DAC1_VU_WIDTH 1 /* DAC1_VU */ | ||
1078 | #define WM8915_DAC1L_VOL_MASK 0x00FF /* DAC1L_VOL - [7:0] */ | ||
1079 | #define WM8915_DAC1L_VOL_SHIFT 0 /* DAC1L_VOL - [7:0] */ | ||
1080 | #define WM8915_DAC1L_VOL_WIDTH 8 /* DAC1L_VOL - [7:0] */ | ||
1081 | |||
1082 | /* | ||
1083 | * R25 (0x19) - DAC1 Right Volume | ||
1084 | */ | ||
1085 | #define WM8915_DAC1R_MUTE 0x0200 /* DAC1R_MUTE */ | ||
1086 | #define WM8915_DAC1R_MUTE_MASK 0x0200 /* DAC1R_MUTE */ | ||
1087 | #define WM8915_DAC1R_MUTE_SHIFT 9 /* DAC1R_MUTE */ | ||
1088 | #define WM8915_DAC1R_MUTE_WIDTH 1 /* DAC1R_MUTE */ | ||
1089 | #define WM8915_DAC1_VU 0x0100 /* DAC1_VU */ | ||
1090 | #define WM8915_DAC1_VU_MASK 0x0100 /* DAC1_VU */ | ||
1091 | #define WM8915_DAC1_VU_SHIFT 8 /* DAC1_VU */ | ||
1092 | #define WM8915_DAC1_VU_WIDTH 1 /* DAC1_VU */ | ||
1093 | #define WM8915_DAC1R_VOL_MASK 0x00FF /* DAC1R_VOL - [7:0] */ | ||
1094 | #define WM8915_DAC1R_VOL_SHIFT 0 /* DAC1R_VOL - [7:0] */ | ||
1095 | #define WM8915_DAC1R_VOL_WIDTH 8 /* DAC1R_VOL - [7:0] */ | ||
1096 | |||
1097 | /* | ||
1098 | * R26 (0x1A) - DAC2 Left Volume | ||
1099 | */ | ||
1100 | #define WM8915_DAC2L_MUTE 0x0200 /* DAC2L_MUTE */ | ||
1101 | #define WM8915_DAC2L_MUTE_MASK 0x0200 /* DAC2L_MUTE */ | ||
1102 | #define WM8915_DAC2L_MUTE_SHIFT 9 /* DAC2L_MUTE */ | ||
1103 | #define WM8915_DAC2L_MUTE_WIDTH 1 /* DAC2L_MUTE */ | ||
1104 | #define WM8915_DAC2_VU 0x0100 /* DAC2_VU */ | ||
1105 | #define WM8915_DAC2_VU_MASK 0x0100 /* DAC2_VU */ | ||
1106 | #define WM8915_DAC2_VU_SHIFT 8 /* DAC2_VU */ | ||
1107 | #define WM8915_DAC2_VU_WIDTH 1 /* DAC2_VU */ | ||
1108 | #define WM8915_DAC2L_VOL_MASK 0x00FF /* DAC2L_VOL - [7:0] */ | ||
1109 | #define WM8915_DAC2L_VOL_SHIFT 0 /* DAC2L_VOL - [7:0] */ | ||
1110 | #define WM8915_DAC2L_VOL_WIDTH 8 /* DAC2L_VOL - [7:0] */ | ||
1111 | |||
1112 | /* | ||
1113 | * R27 (0x1B) - DAC2 Right Volume | ||
1114 | */ | ||
1115 | #define WM8915_DAC2R_MUTE 0x0200 /* DAC2R_MUTE */ | ||
1116 | #define WM8915_DAC2R_MUTE_MASK 0x0200 /* DAC2R_MUTE */ | ||
1117 | #define WM8915_DAC2R_MUTE_SHIFT 9 /* DAC2R_MUTE */ | ||
1118 | #define WM8915_DAC2R_MUTE_WIDTH 1 /* DAC2R_MUTE */ | ||
1119 | #define WM8915_DAC2_VU 0x0100 /* DAC2_VU */ | ||
1120 | #define WM8915_DAC2_VU_MASK 0x0100 /* DAC2_VU */ | ||
1121 | #define WM8915_DAC2_VU_SHIFT 8 /* DAC2_VU */ | ||
1122 | #define WM8915_DAC2_VU_WIDTH 1 /* DAC2_VU */ | ||
1123 | #define WM8915_DAC2R_VOL_MASK 0x00FF /* DAC2R_VOL - [7:0] */ | ||
1124 | #define WM8915_DAC2R_VOL_SHIFT 0 /* DAC2R_VOL - [7:0] */ | ||
1125 | #define WM8915_DAC2R_VOL_WIDTH 8 /* DAC2R_VOL - [7:0] */ | ||
1126 | |||
1127 | /* | ||
1128 | * R28 (0x1C) - Output1 Left Volume | ||
1129 | */ | ||
1130 | #define WM8915_DAC1_VU 0x0100 /* DAC1_VU */ | ||
1131 | #define WM8915_DAC1_VU_MASK 0x0100 /* DAC1_VU */ | ||
1132 | #define WM8915_DAC1_VU_SHIFT 8 /* DAC1_VU */ | ||
1133 | #define WM8915_DAC1_VU_WIDTH 1 /* DAC1_VU */ | ||
1134 | #define WM8915_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ | ||
1135 | #define WM8915_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ | ||
1136 | #define WM8915_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ | ||
1137 | #define WM8915_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ | ||
1138 | #define WM8915_HPOUT1L_VOL_MASK 0x000F /* HPOUT1L_VOL - [3:0] */ | ||
1139 | #define WM8915_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [3:0] */ | ||
1140 | #define WM8915_HPOUT1L_VOL_WIDTH 4 /* HPOUT1L_VOL - [3:0] */ | ||
1141 | |||
1142 | /* | ||
1143 | * R29 (0x1D) - Output1 Right Volume | ||
1144 | */ | ||
1145 | #define WM8915_DAC1_VU 0x0100 /* DAC1_VU */ | ||
1146 | #define WM8915_DAC1_VU_MASK 0x0100 /* DAC1_VU */ | ||
1147 | #define WM8915_DAC1_VU_SHIFT 8 /* DAC1_VU */ | ||
1148 | #define WM8915_DAC1_VU_WIDTH 1 /* DAC1_VU */ | ||
1149 | #define WM8915_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ | ||
1150 | #define WM8915_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ | ||
1151 | #define WM8915_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ | ||
1152 | #define WM8915_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ | ||
1153 | #define WM8915_HPOUT1R_VOL_MASK 0x000F /* HPOUT1R_VOL - [3:0] */ | ||
1154 | #define WM8915_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [3:0] */ | ||
1155 | #define WM8915_HPOUT1R_VOL_WIDTH 4 /* HPOUT1R_VOL - [3:0] */ | ||
1156 | |||
1157 | /* | ||
1158 | * R30 (0x1E) - Output2 Left Volume | ||
1159 | */ | ||
1160 | #define WM8915_DAC2_VU 0x0100 /* DAC2_VU */ | ||
1161 | #define WM8915_DAC2_VU_MASK 0x0100 /* DAC2_VU */ | ||
1162 | #define WM8915_DAC2_VU_SHIFT 8 /* DAC2_VU */ | ||
1163 | #define WM8915_DAC2_VU_WIDTH 1 /* DAC2_VU */ | ||
1164 | #define WM8915_HPOUT2L_ZC 0x0080 /* HPOUT2L_ZC */ | ||
1165 | #define WM8915_HPOUT2L_ZC_MASK 0x0080 /* HPOUT2L_ZC */ | ||
1166 | #define WM8915_HPOUT2L_ZC_SHIFT 7 /* HPOUT2L_ZC */ | ||
1167 | #define WM8915_HPOUT2L_ZC_WIDTH 1 /* HPOUT2L_ZC */ | ||
1168 | #define WM8915_HPOUT2L_VOL_MASK 0x000F /* HPOUT2L_VOL - [3:0] */ | ||
1169 | #define WM8915_HPOUT2L_VOL_SHIFT 0 /* HPOUT2L_VOL - [3:0] */ | ||
1170 | #define WM8915_HPOUT2L_VOL_WIDTH 4 /* HPOUT2L_VOL - [3:0] */ | ||
1171 | |||
1172 | /* | ||
1173 | * R31 (0x1F) - Output2 Right Volume | ||
1174 | */ | ||
1175 | #define WM8915_DAC2_VU 0x0100 /* DAC2_VU */ | ||
1176 | #define WM8915_DAC2_VU_MASK 0x0100 /* DAC2_VU */ | ||
1177 | #define WM8915_DAC2_VU_SHIFT 8 /* DAC2_VU */ | ||
1178 | #define WM8915_DAC2_VU_WIDTH 1 /* DAC2_VU */ | ||
1179 | #define WM8915_HPOUT2R_ZC 0x0080 /* HPOUT2R_ZC */ | ||
1180 | #define WM8915_HPOUT2R_ZC_MASK 0x0080 /* HPOUT2R_ZC */ | ||
1181 | #define WM8915_HPOUT2R_ZC_SHIFT 7 /* HPOUT2R_ZC */ | ||
1182 | #define WM8915_HPOUT2R_ZC_WIDTH 1 /* HPOUT2R_ZC */ | ||
1183 | #define WM8915_HPOUT2R_VOL_MASK 0x000F /* HPOUT2R_VOL - [3:0] */ | ||
1184 | #define WM8915_HPOUT2R_VOL_SHIFT 0 /* HPOUT2R_VOL - [3:0] */ | ||
1185 | #define WM8915_HPOUT2R_VOL_WIDTH 4 /* HPOUT2R_VOL - [3:0] */ | ||
1186 | |||
1187 | /* | ||
1188 | * R32 (0x20) - MICBIAS (1) | ||
1189 | */ | ||
1190 | #define WM8915_MICB1_RATE 0x0020 /* MICB1_RATE */ | ||
1191 | #define WM8915_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ | ||
1192 | #define WM8915_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ | ||
1193 | #define WM8915_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ | ||
1194 | #define WM8915_MICB1_MODE 0x0010 /* MICB1_MODE */ | ||
1195 | #define WM8915_MICB1_MODE_MASK 0x0010 /* MICB1_MODE */ | ||
1196 | #define WM8915_MICB1_MODE_SHIFT 4 /* MICB1_MODE */ | ||
1197 | #define WM8915_MICB1_MODE_WIDTH 1 /* MICB1_MODE */ | ||
1198 | #define WM8915_MICB1_LVL_MASK 0x000E /* MICB1_LVL - [3:1] */ | ||
1199 | #define WM8915_MICB1_LVL_SHIFT 1 /* MICB1_LVL - [3:1] */ | ||
1200 | #define WM8915_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [3:1] */ | ||
1201 | #define WM8915_MICB1_DISCH 0x0001 /* MICB1_DISCH */ | ||
1202 | #define WM8915_MICB1_DISCH_MASK 0x0001 /* MICB1_DISCH */ | ||
1203 | #define WM8915_MICB1_DISCH_SHIFT 0 /* MICB1_DISCH */ | ||
1204 | #define WM8915_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ | ||
1205 | |||
1206 | /* | ||
1207 | * R33 (0x21) - MICBIAS (2) | ||
1208 | */ | ||
1209 | #define WM8915_MICB2_RATE 0x0020 /* MICB2_RATE */ | ||
1210 | #define WM8915_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ | ||
1211 | #define WM8915_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ | ||
1212 | #define WM8915_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ | ||
1213 | #define WM8915_MICB2_MODE 0x0010 /* MICB2_MODE */ | ||
1214 | #define WM8915_MICB2_MODE_MASK 0x0010 /* MICB2_MODE */ | ||
1215 | #define WM8915_MICB2_MODE_SHIFT 4 /* MICB2_MODE */ | ||
1216 | #define WM8915_MICB2_MODE_WIDTH 1 /* MICB2_MODE */ | ||
1217 | #define WM8915_MICB2_LVL_MASK 0x000E /* MICB2_LVL - [3:1] */ | ||
1218 | #define WM8915_MICB2_LVL_SHIFT 1 /* MICB2_LVL - [3:1] */ | ||
1219 | #define WM8915_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [3:1] */ | ||
1220 | #define WM8915_MICB2_DISCH 0x0001 /* MICB2_DISCH */ | ||
1221 | #define WM8915_MICB2_DISCH_MASK 0x0001 /* MICB2_DISCH */ | ||
1222 | #define WM8915_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ | ||
1223 | #define WM8915_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ | ||
1224 | |||
1225 | /* | ||
1226 | * R40 (0x28) - LDO 1 | ||
1227 | */ | ||
1228 | #define WM8915_LDO1_MODE 0x0020 /* LDO1_MODE */ | ||
1229 | #define WM8915_LDO1_MODE_MASK 0x0020 /* LDO1_MODE */ | ||
1230 | #define WM8915_LDO1_MODE_SHIFT 5 /* LDO1_MODE */ | ||
1231 | #define WM8915_LDO1_MODE_WIDTH 1 /* LDO1_MODE */ | ||
1232 | #define WM8915_LDO1_VSEL_MASK 0x0006 /* LDO1_VSEL - [2:1] */ | ||
1233 | #define WM8915_LDO1_VSEL_SHIFT 1 /* LDO1_VSEL - [2:1] */ | ||
1234 | #define WM8915_LDO1_VSEL_WIDTH 2 /* LDO1_VSEL - [2:1] */ | ||
1235 | #define WM8915_LDO1_DISCH 0x0001 /* LDO1_DISCH */ | ||
1236 | #define WM8915_LDO1_DISCH_MASK 0x0001 /* LDO1_DISCH */ | ||
1237 | #define WM8915_LDO1_DISCH_SHIFT 0 /* LDO1_DISCH */ | ||
1238 | #define WM8915_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */ | ||
1239 | |||
1240 | /* | ||
1241 | * R41 (0x29) - LDO 2 | ||
1242 | */ | ||
1243 | #define WM8915_LDO2_MODE 0x0020 /* LDO2_MODE */ | ||
1244 | #define WM8915_LDO2_MODE_MASK 0x0020 /* LDO2_MODE */ | ||
1245 | #define WM8915_LDO2_MODE_SHIFT 5 /* LDO2_MODE */ | ||
1246 | #define WM8915_LDO2_MODE_WIDTH 1 /* LDO2_MODE */ | ||
1247 | #define WM8915_LDO2_VSEL_MASK 0x001E /* LDO2_VSEL - [4:1] */ | ||
1248 | #define WM8915_LDO2_VSEL_SHIFT 1 /* LDO2_VSEL - [4:1] */ | ||
1249 | #define WM8915_LDO2_VSEL_WIDTH 4 /* LDO2_VSEL - [4:1] */ | ||
1250 | #define WM8915_LDO2_DISCH 0x0001 /* LDO2_DISCH */ | ||
1251 | #define WM8915_LDO2_DISCH_MASK 0x0001 /* LDO2_DISCH */ | ||
1252 | #define WM8915_LDO2_DISCH_SHIFT 0 /* LDO2_DISCH */ | ||
1253 | #define WM8915_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ | ||
1254 | |||
1255 | /* | ||
1256 | * R48 (0x30) - Accessory Detect Mode 1 | ||
1257 | */ | ||
1258 | #define WM8915_JD_MODE_MASK 0x0003 /* JD_MODE - [1:0] */ | ||
1259 | #define WM8915_JD_MODE_SHIFT 0 /* JD_MODE - [1:0] */ | ||
1260 | #define WM8915_JD_MODE_WIDTH 2 /* JD_MODE - [1:0] */ | ||
1261 | |||
1262 | /* | ||
1263 | * R49 (0x31) - Accessory Detect Mode 2 | ||
1264 | */ | ||
1265 | #define WM8915_HPOUT1FB_SRC 0x0004 /* HPOUT1FB_SRC */ | ||
1266 | #define WM8915_HPOUT1FB_SRC_MASK 0x0004 /* HPOUT1FB_SRC */ | ||
1267 | #define WM8915_HPOUT1FB_SRC_SHIFT 2 /* HPOUT1FB_SRC */ | ||
1268 | #define WM8915_HPOUT1FB_SRC_WIDTH 1 /* HPOUT1FB_SRC */ | ||
1269 | #define WM8915_MICD_SRC 0x0002 /* MICD_SRC */ | ||
1270 | #define WM8915_MICD_SRC_MASK 0x0002 /* MICD_SRC */ | ||
1271 | #define WM8915_MICD_SRC_SHIFT 1 /* MICD_SRC */ | ||
1272 | #define WM8915_MICD_SRC_WIDTH 1 /* MICD_SRC */ | ||
1273 | #define WM8915_MICD_BIAS_SRC 0x0001 /* MICD_BIAS_SRC */ | ||
1274 | #define WM8915_MICD_BIAS_SRC_MASK 0x0001 /* MICD_BIAS_SRC */ | ||
1275 | #define WM8915_MICD_BIAS_SRC_SHIFT 0 /* MICD_BIAS_SRC */ | ||
1276 | #define WM8915_MICD_BIAS_SRC_WIDTH 1 /* MICD_BIAS_SRC */ | ||
1277 | |||
1278 | /* | ||
1279 | * R52 (0x34) - Headphone Detect 1 | ||
1280 | */ | ||
1281 | #define WM8915_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */ | ||
1282 | #define WM8915_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */ | ||
1283 | #define WM8915_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */ | ||
1284 | #define WM8915_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */ | ||
1285 | #define WM8915_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */ | ||
1286 | #define WM8915_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */ | ||
1287 | #define WM8915_HP_STEP_SIZE 0x0002 /* HP_STEP_SIZE */ | ||
1288 | #define WM8915_HP_STEP_SIZE_MASK 0x0002 /* HP_STEP_SIZE */ | ||
1289 | #define WM8915_HP_STEP_SIZE_SHIFT 1 /* HP_STEP_SIZE */ | ||
1290 | #define WM8915_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */ | ||
1291 | #define WM8915_HP_POLL 0x0001 /* HP_POLL */ | ||
1292 | #define WM8915_HP_POLL_MASK 0x0001 /* HP_POLL */ | ||
1293 | #define WM8915_HP_POLL_SHIFT 0 /* HP_POLL */ | ||
1294 | #define WM8915_HP_POLL_WIDTH 1 /* HP_POLL */ | ||
1295 | |||
1296 | /* | ||
1297 | * R53 (0x35) - Headphone Detect 2 | ||
1298 | */ | ||
1299 | #define WM8915_HP_DONE 0x0080 /* HP_DONE */ | ||
1300 | #define WM8915_HP_DONE_MASK 0x0080 /* HP_DONE */ | ||
1301 | #define WM8915_HP_DONE_SHIFT 7 /* HP_DONE */ | ||
1302 | #define WM8915_HP_DONE_WIDTH 1 /* HP_DONE */ | ||
1303 | #define WM8915_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ | ||
1304 | #define WM8915_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ | ||
1305 | #define WM8915_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ | ||
1306 | |||
1307 | /* | ||
1308 | * R56 (0x38) - Mic Detect 1 | ||
1309 | */ | ||
1310 | #define WM8915_MICD_BIAS_STARTTIME_MASK 0xF000 /* MICD_BIAS_STARTTIME - [15:12] */ | ||
1311 | #define WM8915_MICD_BIAS_STARTTIME_SHIFT 12 /* MICD_BIAS_STARTTIME - [15:12] */ | ||
1312 | #define WM8915_MICD_BIAS_STARTTIME_WIDTH 4 /* MICD_BIAS_STARTTIME - [15:12] */ | ||
1313 | #define WM8915_MICD_RATE_MASK 0x0F00 /* MICD_RATE - [11:8] */ | ||
1314 | #define WM8915_MICD_RATE_SHIFT 8 /* MICD_RATE - [11:8] */ | ||
1315 | #define WM8915_MICD_RATE_WIDTH 4 /* MICD_RATE - [11:8] */ | ||
1316 | #define WM8915_MICD_DBTIME 0x0002 /* MICD_DBTIME */ | ||
1317 | #define WM8915_MICD_DBTIME_MASK 0x0002 /* MICD_DBTIME */ | ||
1318 | #define WM8915_MICD_DBTIME_SHIFT 1 /* MICD_DBTIME */ | ||
1319 | #define WM8915_MICD_DBTIME_WIDTH 1 /* MICD_DBTIME */ | ||
1320 | #define WM8915_MICD_ENA 0x0001 /* MICD_ENA */ | ||
1321 | #define WM8915_MICD_ENA_MASK 0x0001 /* MICD_ENA */ | ||
1322 | #define WM8915_MICD_ENA_SHIFT 0 /* MICD_ENA */ | ||
1323 | #define WM8915_MICD_ENA_WIDTH 1 /* MICD_ENA */ | ||
1324 | |||
1325 | /* | ||
1326 | * R57 (0x39) - Mic Detect 2 | ||
1327 | */ | ||
1328 | #define WM8915_MICD_LVL_SEL_MASK 0x00FF /* MICD_LVL_SEL - [7:0] */ | ||
1329 | #define WM8915_MICD_LVL_SEL_SHIFT 0 /* MICD_LVL_SEL - [7:0] */ | ||
1330 | #define WM8915_MICD_LVL_SEL_WIDTH 8 /* MICD_LVL_SEL - [7:0] */ | ||
1331 | |||
1332 | /* | ||
1333 | * R58 (0x3A) - Mic Detect 3 | ||
1334 | */ | ||
1335 | #define WM8915_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */ | ||
1336 | #define WM8915_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */ | ||
1337 | #define WM8915_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */ | ||
1338 | #define WM8915_MICD_VALID 0x0002 /* MICD_VALID */ | ||
1339 | #define WM8915_MICD_VALID_MASK 0x0002 /* MICD_VALID */ | ||
1340 | #define WM8915_MICD_VALID_SHIFT 1 /* MICD_VALID */ | ||
1341 | #define WM8915_MICD_VALID_WIDTH 1 /* MICD_VALID */ | ||
1342 | #define WM8915_MICD_STS 0x0001 /* MICD_STS */ | ||
1343 | #define WM8915_MICD_STS_MASK 0x0001 /* MICD_STS */ | ||
1344 | #define WM8915_MICD_STS_SHIFT 0 /* MICD_STS */ | ||
1345 | #define WM8915_MICD_STS_WIDTH 1 /* MICD_STS */ | ||
1346 | |||
1347 | /* | ||
1348 | * R64 (0x40) - Charge Pump (1) | ||
1349 | */ | ||
1350 | #define WM8915_CP_ENA 0x8000 /* CP_ENA */ | ||
1351 | #define WM8915_CP_ENA_MASK 0x8000 /* CP_ENA */ | ||
1352 | #define WM8915_CP_ENA_SHIFT 15 /* CP_ENA */ | ||
1353 | #define WM8915_CP_ENA_WIDTH 1 /* CP_ENA */ | ||
1354 | |||
1355 | /* | ||
1356 | * R65 (0x41) - Charge Pump (2) | ||
1357 | */ | ||
1358 | #define WM8915_CP_DISCH 0x8000 /* CP_DISCH */ | ||
1359 | #define WM8915_CP_DISCH_MASK 0x8000 /* CP_DISCH */ | ||
1360 | #define WM8915_CP_DISCH_SHIFT 15 /* CP_DISCH */ | ||
1361 | #define WM8915_CP_DISCH_WIDTH 1 /* CP_DISCH */ | ||
1362 | |||
1363 | /* | ||
1364 | * R80 (0x50) - DC Servo (1) | ||
1365 | */ | ||
1366 | #define WM8915_DCS_ENA_CHAN_3 0x0008 /* DCS_ENA_CHAN_3 */ | ||
1367 | #define WM8915_DCS_ENA_CHAN_3_MASK 0x0008 /* DCS_ENA_CHAN_3 */ | ||
1368 | #define WM8915_DCS_ENA_CHAN_3_SHIFT 3 /* DCS_ENA_CHAN_3 */ | ||
1369 | #define WM8915_DCS_ENA_CHAN_3_WIDTH 1 /* DCS_ENA_CHAN_3 */ | ||
1370 | #define WM8915_DCS_ENA_CHAN_2 0x0004 /* DCS_ENA_CHAN_2 */ | ||
1371 | #define WM8915_DCS_ENA_CHAN_2_MASK 0x0004 /* DCS_ENA_CHAN_2 */ | ||
1372 | #define WM8915_DCS_ENA_CHAN_2_SHIFT 2 /* DCS_ENA_CHAN_2 */ | ||
1373 | #define WM8915_DCS_ENA_CHAN_2_WIDTH 1 /* DCS_ENA_CHAN_2 */ | ||
1374 | #define WM8915_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ | ||
1375 | #define WM8915_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ | ||
1376 | #define WM8915_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ | ||
1377 | #define WM8915_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ | ||
1378 | #define WM8915_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ | ||
1379 | #define WM8915_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ | ||
1380 | #define WM8915_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ | ||
1381 | #define WM8915_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ | ||
1382 | |||
1383 | /* | ||
1384 | * R81 (0x51) - DC Servo (2) | ||
1385 | */ | ||
1386 | #define WM8915_DCS_TRIG_SINGLE_3 0x8000 /* DCS_TRIG_SINGLE_3 */ | ||
1387 | #define WM8915_DCS_TRIG_SINGLE_3_MASK 0x8000 /* DCS_TRIG_SINGLE_3 */ | ||
1388 | #define WM8915_DCS_TRIG_SINGLE_3_SHIFT 15 /* DCS_TRIG_SINGLE_3 */ | ||
1389 | #define WM8915_DCS_TRIG_SINGLE_3_WIDTH 1 /* DCS_TRIG_SINGLE_3 */ | ||
1390 | #define WM8915_DCS_TRIG_SINGLE_2 0x4000 /* DCS_TRIG_SINGLE_2 */ | ||
1391 | #define WM8915_DCS_TRIG_SINGLE_2_MASK 0x4000 /* DCS_TRIG_SINGLE_2 */ | ||
1392 | #define WM8915_DCS_TRIG_SINGLE_2_SHIFT 14 /* DCS_TRIG_SINGLE_2 */ | ||
1393 | #define WM8915_DCS_TRIG_SINGLE_2_WIDTH 1 /* DCS_TRIG_SINGLE_2 */ | ||
1394 | #define WM8915_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ | ||
1395 | #define WM8915_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ | ||
1396 | #define WM8915_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ | ||
1397 | #define WM8915_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ | ||
1398 | #define WM8915_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ | ||
1399 | #define WM8915_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ | ||
1400 | #define WM8915_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ | ||
1401 | #define WM8915_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ | ||
1402 | #define WM8915_DCS_TRIG_SERIES_3 0x0800 /* DCS_TRIG_SERIES_3 */ | ||
1403 | #define WM8915_DCS_TRIG_SERIES_3_MASK 0x0800 /* DCS_TRIG_SERIES_3 */ | ||
1404 | #define WM8915_DCS_TRIG_SERIES_3_SHIFT 11 /* DCS_TRIG_SERIES_3 */ | ||
1405 | #define WM8915_DCS_TRIG_SERIES_3_WIDTH 1 /* DCS_TRIG_SERIES_3 */ | ||
1406 | #define WM8915_DCS_TRIG_SERIES_2 0x0400 /* DCS_TRIG_SERIES_2 */ | ||
1407 | #define WM8915_DCS_TRIG_SERIES_2_MASK 0x0400 /* DCS_TRIG_SERIES_2 */ | ||
1408 | #define WM8915_DCS_TRIG_SERIES_2_SHIFT 10 /* DCS_TRIG_SERIES_2 */ | ||
1409 | #define WM8915_DCS_TRIG_SERIES_2_WIDTH 1 /* DCS_TRIG_SERIES_2 */ | ||
1410 | #define WM8915_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ | ||
1411 | #define WM8915_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ | ||
1412 | #define WM8915_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ | ||
1413 | #define WM8915_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ | ||
1414 | #define WM8915_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ | ||
1415 | #define WM8915_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ | ||
1416 | #define WM8915_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ | ||
1417 | #define WM8915_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ | ||
1418 | #define WM8915_DCS_TRIG_STARTUP_3 0x0080 /* DCS_TRIG_STARTUP_3 */ | ||
1419 | #define WM8915_DCS_TRIG_STARTUP_3_MASK 0x0080 /* DCS_TRIG_STARTUP_3 */ | ||
1420 | #define WM8915_DCS_TRIG_STARTUP_3_SHIFT 7 /* DCS_TRIG_STARTUP_3 */ | ||
1421 | #define WM8915_DCS_TRIG_STARTUP_3_WIDTH 1 /* DCS_TRIG_STARTUP_3 */ | ||
1422 | #define WM8915_DCS_TRIG_STARTUP_2 0x0040 /* DCS_TRIG_STARTUP_2 */ | ||
1423 | #define WM8915_DCS_TRIG_STARTUP_2_MASK 0x0040 /* DCS_TRIG_STARTUP_2 */ | ||
1424 | #define WM8915_DCS_TRIG_STARTUP_2_SHIFT 6 /* DCS_TRIG_STARTUP_2 */ | ||
1425 | #define WM8915_DCS_TRIG_STARTUP_2_WIDTH 1 /* DCS_TRIG_STARTUP_2 */ | ||
1426 | #define WM8915_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ | ||
1427 | #define WM8915_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ | ||
1428 | #define WM8915_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ | ||
1429 | #define WM8915_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ | ||
1430 | #define WM8915_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ | ||
1431 | #define WM8915_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ | ||
1432 | #define WM8915_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ | ||
1433 | #define WM8915_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ | ||
1434 | #define WM8915_DCS_TRIG_DAC_WR_3 0x0008 /* DCS_TRIG_DAC_WR_3 */ | ||
1435 | #define WM8915_DCS_TRIG_DAC_WR_3_MASK 0x0008 /* DCS_TRIG_DAC_WR_3 */ | ||
1436 | #define WM8915_DCS_TRIG_DAC_WR_3_SHIFT 3 /* DCS_TRIG_DAC_WR_3 */ | ||
1437 | #define WM8915_DCS_TRIG_DAC_WR_3_WIDTH 1 /* DCS_TRIG_DAC_WR_3 */ | ||
1438 | #define WM8915_DCS_TRIG_DAC_WR_2 0x0004 /* DCS_TRIG_DAC_WR_2 */ | ||
1439 | #define WM8915_DCS_TRIG_DAC_WR_2_MASK 0x0004 /* DCS_TRIG_DAC_WR_2 */ | ||
1440 | #define WM8915_DCS_TRIG_DAC_WR_2_SHIFT 2 /* DCS_TRIG_DAC_WR_2 */ | ||
1441 | #define WM8915_DCS_TRIG_DAC_WR_2_WIDTH 1 /* DCS_TRIG_DAC_WR_2 */ | ||
1442 | #define WM8915_DCS_TRIG_DAC_WR_1 0x0002 /* DCS_TRIG_DAC_WR_1 */ | ||
1443 | #define WM8915_DCS_TRIG_DAC_WR_1_MASK 0x0002 /* DCS_TRIG_DAC_WR_1 */ | ||
1444 | #define WM8915_DCS_TRIG_DAC_WR_1_SHIFT 1 /* DCS_TRIG_DAC_WR_1 */ | ||
1445 | #define WM8915_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ | ||
1446 | #define WM8915_DCS_TRIG_DAC_WR_0 0x0001 /* DCS_TRIG_DAC_WR_0 */ | ||
1447 | #define WM8915_DCS_TRIG_DAC_WR_0_MASK 0x0001 /* DCS_TRIG_DAC_WR_0 */ | ||
1448 | #define WM8915_DCS_TRIG_DAC_WR_0_SHIFT 0 /* DCS_TRIG_DAC_WR_0 */ | ||
1449 | #define WM8915_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ | ||
1450 | |||
1451 | /* | ||
1452 | * R82 (0x52) - DC Servo (3) | ||
1453 | */ | ||
1454 | #define WM8915_DCS_TIMER_PERIOD_23_MASK 0x0F00 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
1455 | #define WM8915_DCS_TIMER_PERIOD_23_SHIFT 8 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
1456 | #define WM8915_DCS_TIMER_PERIOD_23_WIDTH 4 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
1457 | #define WM8915_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
1458 | #define WM8915_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
1459 | #define WM8915_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
1460 | |||
1461 | /* | ||
1462 | * R84 (0x54) - DC Servo (5) | ||
1463 | */ | ||
1464 | #define WM8915_DCS_SERIES_NO_23_MASK 0x7F00 /* DCS_SERIES_NO_23 - [14:8] */ | ||
1465 | #define WM8915_DCS_SERIES_NO_23_SHIFT 8 /* DCS_SERIES_NO_23 - [14:8] */ | ||
1466 | #define WM8915_DCS_SERIES_NO_23_WIDTH 7 /* DCS_SERIES_NO_23 - [14:8] */ | ||
1467 | #define WM8915_DCS_SERIES_NO_01_MASK 0x007F /* DCS_SERIES_NO_01 - [6:0] */ | ||
1468 | #define WM8915_DCS_SERIES_NO_01_SHIFT 0 /* DCS_SERIES_NO_01 - [6:0] */ | ||
1469 | #define WM8915_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [6:0] */ | ||
1470 | |||
1471 | /* | ||
1472 | * R85 (0x55) - DC Servo (6) | ||
1473 | */ | ||
1474 | #define WM8915_DCS_DAC_WR_VAL_3_MASK 0xFF00 /* DCS_DAC_WR_VAL_3 - [15:8] */ | ||
1475 | #define WM8915_DCS_DAC_WR_VAL_3_SHIFT 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ | ||
1476 | #define WM8915_DCS_DAC_WR_VAL_3_WIDTH 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ | ||
1477 | #define WM8915_DCS_DAC_WR_VAL_2_MASK 0x00FF /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
1478 | #define WM8915_DCS_DAC_WR_VAL_2_SHIFT 0 /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
1479 | #define WM8915_DCS_DAC_WR_VAL_2_WIDTH 8 /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
1480 | |||
1481 | /* | ||
1482 | * R86 (0x56) - DC Servo (7) | ||
1483 | */ | ||
1484 | #define WM8915_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ | ||
1485 | #define WM8915_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ | ||
1486 | #define WM8915_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ | ||
1487 | #define WM8915_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
1488 | #define WM8915_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
1489 | #define WM8915_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
1490 | |||
1491 | /* | ||
1492 | * R87 (0x57) - DC Servo Readback 0 | ||
1493 | */ | ||
1494 | #define WM8915_DCS_CAL_COMPLETE_MASK 0x0F00 /* DCS_CAL_COMPLETE - [11:8] */ | ||
1495 | #define WM8915_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [11:8] */ | ||
1496 | #define WM8915_DCS_CAL_COMPLETE_WIDTH 4 /* DCS_CAL_COMPLETE - [11:8] */ | ||
1497 | #define WM8915_DCS_DAC_WR_COMPLETE_MASK 0x00F0 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
1498 | #define WM8915_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
1499 | #define WM8915_DCS_DAC_WR_COMPLETE_WIDTH 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
1500 | #define WM8915_DCS_STARTUP_COMPLETE_MASK 0x000F /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
1501 | #define WM8915_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
1502 | #define WM8915_DCS_STARTUP_COMPLETE_WIDTH 4 /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
1503 | |||
1504 | /* | ||
1505 | * R96 (0x60) - Analogue HP (1) | ||
1506 | */ | ||
1507 | #define WM8915_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ | ||
1508 | #define WM8915_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ | ||
1509 | #define WM8915_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ | ||
1510 | #define WM8915_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ | ||
1511 | #define WM8915_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ | ||
1512 | #define WM8915_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ | ||
1513 | #define WM8915_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ | ||
1514 | #define WM8915_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ | ||
1515 | #define WM8915_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ | ||
1516 | #define WM8915_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ | ||
1517 | #define WM8915_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ | ||
1518 | #define WM8915_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ | ||
1519 | #define WM8915_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ | ||
1520 | #define WM8915_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ | ||
1521 | #define WM8915_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ | ||
1522 | #define WM8915_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ | ||
1523 | #define WM8915_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ | ||
1524 | #define WM8915_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ | ||
1525 | #define WM8915_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ | ||
1526 | #define WM8915_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ | ||
1527 | #define WM8915_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ | ||
1528 | #define WM8915_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ | ||
1529 | #define WM8915_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ | ||
1530 | #define WM8915_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ | ||
1531 | |||
1532 | /* | ||
1533 | * R97 (0x61) - Analogue HP (2) | ||
1534 | */ | ||
1535 | #define WM8915_HPOUT2L_RMV_SHORT 0x0080 /* HPOUT2L_RMV_SHORT */ | ||
1536 | #define WM8915_HPOUT2L_RMV_SHORT_MASK 0x0080 /* HPOUT2L_RMV_SHORT */ | ||
1537 | #define WM8915_HPOUT2L_RMV_SHORT_SHIFT 7 /* HPOUT2L_RMV_SHORT */ | ||
1538 | #define WM8915_HPOUT2L_RMV_SHORT_WIDTH 1 /* HPOUT2L_RMV_SHORT */ | ||
1539 | #define WM8915_HPOUT2L_OUTP 0x0040 /* HPOUT2L_OUTP */ | ||
1540 | #define WM8915_HPOUT2L_OUTP_MASK 0x0040 /* HPOUT2L_OUTP */ | ||
1541 | #define WM8915_HPOUT2L_OUTP_SHIFT 6 /* HPOUT2L_OUTP */ | ||
1542 | #define WM8915_HPOUT2L_OUTP_WIDTH 1 /* HPOUT2L_OUTP */ | ||
1543 | #define WM8915_HPOUT2L_DLY 0x0020 /* HPOUT2L_DLY */ | ||
1544 | #define WM8915_HPOUT2L_DLY_MASK 0x0020 /* HPOUT2L_DLY */ | ||
1545 | #define WM8915_HPOUT2L_DLY_SHIFT 5 /* HPOUT2L_DLY */ | ||
1546 | #define WM8915_HPOUT2L_DLY_WIDTH 1 /* HPOUT2L_DLY */ | ||
1547 | #define WM8915_HPOUT2R_RMV_SHORT 0x0008 /* HPOUT2R_RMV_SHORT */ | ||
1548 | #define WM8915_HPOUT2R_RMV_SHORT_MASK 0x0008 /* HPOUT2R_RMV_SHORT */ | ||
1549 | #define WM8915_HPOUT2R_RMV_SHORT_SHIFT 3 /* HPOUT2R_RMV_SHORT */ | ||
1550 | #define WM8915_HPOUT2R_RMV_SHORT_WIDTH 1 /* HPOUT2R_RMV_SHORT */ | ||
1551 | #define WM8915_HPOUT2R_OUTP 0x0004 /* HPOUT2R_OUTP */ | ||
1552 | #define WM8915_HPOUT2R_OUTP_MASK 0x0004 /* HPOUT2R_OUTP */ | ||
1553 | #define WM8915_HPOUT2R_OUTP_SHIFT 2 /* HPOUT2R_OUTP */ | ||
1554 | #define WM8915_HPOUT2R_OUTP_WIDTH 1 /* HPOUT2R_OUTP */ | ||
1555 | #define WM8915_HPOUT2R_DLY 0x0002 /* HPOUT2R_DLY */ | ||
1556 | #define WM8915_HPOUT2R_DLY_MASK 0x0002 /* HPOUT2R_DLY */ | ||
1557 | #define WM8915_HPOUT2R_DLY_SHIFT 1 /* HPOUT2R_DLY */ | ||
1558 | #define WM8915_HPOUT2R_DLY_WIDTH 1 /* HPOUT2R_DLY */ | ||
1559 | |||
1560 | /* | ||
1561 | * R256 (0x100) - Chip Revision | ||
1562 | */ | ||
1563 | #define WM8915_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */ | ||
1564 | #define WM8915_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */ | ||
1565 | #define WM8915_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */ | ||
1566 | |||
1567 | /* | ||
1568 | * R257 (0x101) - Control Interface (1) | ||
1569 | */ | ||
1570 | #define WM8915_AUTO_INC 0x0004 /* AUTO_INC */ | ||
1571 | #define WM8915_AUTO_INC_MASK 0x0004 /* AUTO_INC */ | ||
1572 | #define WM8915_AUTO_INC_SHIFT 2 /* AUTO_INC */ | ||
1573 | #define WM8915_AUTO_INC_WIDTH 1 /* AUTO_INC */ | ||
1574 | |||
1575 | /* | ||
1576 | * R272 (0x110) - Write Sequencer Ctrl (1) | ||
1577 | */ | ||
1578 | #define WM8915_WSEQ_ENA 0x8000 /* WSEQ_ENA */ | ||
1579 | #define WM8915_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */ | ||
1580 | #define WM8915_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */ | ||
1581 | #define WM8915_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ | ||
1582 | #define WM8915_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ | ||
1583 | #define WM8915_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ | ||
1584 | #define WM8915_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ | ||
1585 | #define WM8915_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ | ||
1586 | #define WM8915_WSEQ_START 0x0100 /* WSEQ_START */ | ||
1587 | #define WM8915_WSEQ_START_MASK 0x0100 /* WSEQ_START */ | ||
1588 | #define WM8915_WSEQ_START_SHIFT 8 /* WSEQ_START */ | ||
1589 | #define WM8915_WSEQ_START_WIDTH 1 /* WSEQ_START */ | ||
1590 | #define WM8915_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ | ||
1591 | #define WM8915_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ | ||
1592 | #define WM8915_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ | ||
1593 | |||
1594 | /* | ||
1595 | * R273 (0x111) - Write Sequencer Ctrl (2) | ||
1596 | */ | ||
1597 | #define WM8915_WSEQ_BUSY 0x0100 /* WSEQ_BUSY */ | ||
1598 | #define WM8915_WSEQ_BUSY_MASK 0x0100 /* WSEQ_BUSY */ | ||
1599 | #define WM8915_WSEQ_BUSY_SHIFT 8 /* WSEQ_BUSY */ | ||
1600 | #define WM8915_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ | ||
1601 | #define WM8915_WSEQ_CURRENT_INDEX_MASK 0x007F /* WSEQ_CURRENT_INDEX - [6:0] */ | ||
1602 | #define WM8915_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [6:0] */ | ||
1603 | #define WM8915_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [6:0] */ | ||
1604 | |||
1605 | /* | ||
1606 | * R512 (0x200) - AIF Clocking (1) | ||
1607 | */ | ||
1608 | #define WM8915_SYSCLK_SRC_MASK 0x0018 /* SYSCLK_SRC - [4:3] */ | ||
1609 | #define WM8915_SYSCLK_SRC_SHIFT 3 /* SYSCLK_SRC - [4:3] */ | ||
1610 | #define WM8915_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [4:3] */ | ||
1611 | #define WM8915_SYSCLK_INV 0x0004 /* SYSCLK_INV */ | ||
1612 | #define WM8915_SYSCLK_INV_MASK 0x0004 /* SYSCLK_INV */ | ||
1613 | #define WM8915_SYSCLK_INV_SHIFT 2 /* SYSCLK_INV */ | ||
1614 | #define WM8915_SYSCLK_INV_WIDTH 1 /* SYSCLK_INV */ | ||
1615 | #define WM8915_SYSCLK_DIV 0x0002 /* SYSCLK_DIV */ | ||
1616 | #define WM8915_SYSCLK_DIV_MASK 0x0002 /* SYSCLK_DIV */ | ||
1617 | #define WM8915_SYSCLK_DIV_SHIFT 1 /* SYSCLK_DIV */ | ||
1618 | #define WM8915_SYSCLK_DIV_WIDTH 1 /* SYSCLK_DIV */ | ||
1619 | #define WM8915_SYSCLK_ENA 0x0001 /* SYSCLK_ENA */ | ||
1620 | #define WM8915_SYSCLK_ENA_MASK 0x0001 /* SYSCLK_ENA */ | ||
1621 | #define WM8915_SYSCLK_ENA_SHIFT 0 /* SYSCLK_ENA */ | ||
1622 | #define WM8915_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ | ||
1623 | |||
1624 | /* | ||
1625 | * R513 (0x201) - AIF Clocking (2) | ||
1626 | */ | ||
1627 | #define WM8915_DSP2_DIV_MASK 0x0018 /* DSP2_DIV - [4:3] */ | ||
1628 | #define WM8915_DSP2_DIV_SHIFT 3 /* DSP2_DIV - [4:3] */ | ||
1629 | #define WM8915_DSP2_DIV_WIDTH 2 /* DSP2_DIV - [4:3] */ | ||
1630 | #define WM8915_DSP1_DIV_MASK 0x0003 /* DSP1_DIV - [1:0] */ | ||
1631 | #define WM8915_DSP1_DIV_SHIFT 0 /* DSP1_DIV - [1:0] */ | ||
1632 | #define WM8915_DSP1_DIV_WIDTH 2 /* DSP1_DIV - [1:0] */ | ||
1633 | |||
1634 | /* | ||
1635 | * R520 (0x208) - Clocking (1) | ||
1636 | */ | ||
1637 | #define WM8915_LFCLK_ENA 0x0020 /* LFCLK_ENA */ | ||
1638 | #define WM8915_LFCLK_ENA_MASK 0x0020 /* LFCLK_ENA */ | ||
1639 | #define WM8915_LFCLK_ENA_SHIFT 5 /* LFCLK_ENA */ | ||
1640 | #define WM8915_LFCLK_ENA_WIDTH 1 /* LFCLK_ENA */ | ||
1641 | #define WM8915_TOCLK_ENA 0x0010 /* TOCLK_ENA */ | ||
1642 | #define WM8915_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */ | ||
1643 | #define WM8915_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */ | ||
1644 | #define WM8915_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ | ||
1645 | #define WM8915_AIFCLK_ENA 0x0004 /* AIFCLK_ENA */ | ||
1646 | #define WM8915_AIFCLK_ENA_MASK 0x0004 /* AIFCLK_ENA */ | ||
1647 | #define WM8915_AIFCLK_ENA_SHIFT 2 /* AIFCLK_ENA */ | ||
1648 | #define WM8915_AIFCLK_ENA_WIDTH 1 /* AIFCLK_ENA */ | ||
1649 | #define WM8915_SYSDSPCLK_ENA 0x0002 /* SYSDSPCLK_ENA */ | ||
1650 | #define WM8915_SYSDSPCLK_ENA_MASK 0x0002 /* SYSDSPCLK_ENA */ | ||
1651 | #define WM8915_SYSDSPCLK_ENA_SHIFT 1 /* SYSDSPCLK_ENA */ | ||
1652 | #define WM8915_SYSDSPCLK_ENA_WIDTH 1 /* SYSDSPCLK_ENA */ | ||
1653 | |||
1654 | /* | ||
1655 | * R521 (0x209) - Clocking (2) | ||
1656 | */ | ||
1657 | #define WM8915_TOCLK_DIV_MASK 0x0700 /* TOCLK_DIV - [10:8] */ | ||
1658 | #define WM8915_TOCLK_DIV_SHIFT 8 /* TOCLK_DIV - [10:8] */ | ||
1659 | #define WM8915_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [10:8] */ | ||
1660 | #define WM8915_DBCLK_DIV_MASK 0x00F0 /* DBCLK_DIV - [7:4] */ | ||
1661 | #define WM8915_DBCLK_DIV_SHIFT 4 /* DBCLK_DIV - [7:4] */ | ||
1662 | #define WM8915_DBCLK_DIV_WIDTH 4 /* DBCLK_DIV - [7:4] */ | ||
1663 | #define WM8915_OPCLK_DIV_MASK 0x0007 /* OPCLK_DIV - [2:0] */ | ||
1664 | #define WM8915_OPCLK_DIV_SHIFT 0 /* OPCLK_DIV - [2:0] */ | ||
1665 | #define WM8915_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [2:0] */ | ||
1666 | |||
1667 | /* | ||
1668 | * R528 (0x210) - AIF Rate | ||
1669 | */ | ||
1670 | #define WM8915_SYSCLK_RATE 0x0001 /* SYSCLK_RATE */ | ||
1671 | #define WM8915_SYSCLK_RATE_MASK 0x0001 /* SYSCLK_RATE */ | ||
1672 | #define WM8915_SYSCLK_RATE_SHIFT 0 /* SYSCLK_RATE */ | ||
1673 | #define WM8915_SYSCLK_RATE_WIDTH 1 /* SYSCLK_RATE */ | ||
1674 | |||
1675 | /* | ||
1676 | * R544 (0x220) - FLL Control (1) | ||
1677 | */ | ||
1678 | #define WM8915_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ | ||
1679 | #define WM8915_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ | ||
1680 | #define WM8915_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ | ||
1681 | #define WM8915_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ | ||
1682 | #define WM8915_FLL_ENA 0x0001 /* FLL_ENA */ | ||
1683 | #define WM8915_FLL_ENA_MASK 0x0001 /* FLL_ENA */ | ||
1684 | #define WM8915_FLL_ENA_SHIFT 0 /* FLL_ENA */ | ||
1685 | #define WM8915_FLL_ENA_WIDTH 1 /* FLL_ENA */ | ||
1686 | |||
1687 | /* | ||
1688 | * R545 (0x221) - FLL Control (2) | ||
1689 | */ | ||
1690 | #define WM8915_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */ | ||
1691 | #define WM8915_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */ | ||
1692 | #define WM8915_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */ | ||
1693 | #define WM8915_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ | ||
1694 | #define WM8915_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ | ||
1695 | #define WM8915_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ | ||
1696 | |||
1697 | /* | ||
1698 | * R546 (0x222) - FLL Control (3) | ||
1699 | */ | ||
1700 | #define WM8915_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */ | ||
1701 | #define WM8915_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */ | ||
1702 | #define WM8915_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */ | ||
1703 | |||
1704 | /* | ||
1705 | * R547 (0x223) - FLL Control (4) | ||
1706 | */ | ||
1707 | #define WM8915_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ | ||
1708 | #define WM8915_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ | ||
1709 | #define WM8915_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ | ||
1710 | #define WM8915_FLL_LOOP_GAIN_MASK 0x000F /* FLL_LOOP_GAIN - [3:0] */ | ||
1711 | #define WM8915_FLL_LOOP_GAIN_SHIFT 0 /* FLL_LOOP_GAIN - [3:0] */ | ||
1712 | #define WM8915_FLL_LOOP_GAIN_WIDTH 4 /* FLL_LOOP_GAIN - [3:0] */ | ||
1713 | |||
1714 | /* | ||
1715 | * R548 (0x224) - FLL Control (5) | ||
1716 | */ | ||
1717 | #define WM8915_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */ | ||
1718 | #define WM8915_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */ | ||
1719 | #define WM8915_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */ | ||
1720 | #define WM8915_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */ | ||
1721 | #define WM8915_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */ | ||
1722 | #define WM8915_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */ | ||
1723 | #define WM8915_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ | ||
1724 | #define WM8915_FLL_REFCLK_DIV_MASK 0x0018 /* FLL_REFCLK_DIV - [4:3] */ | ||
1725 | #define WM8915_FLL_REFCLK_DIV_SHIFT 3 /* FLL_REFCLK_DIV - [4:3] */ | ||
1726 | #define WM8915_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [4:3] */ | ||
1727 | #define WM8915_FLL_REF_FREQ 0x0004 /* FLL_REF_FREQ */ | ||
1728 | #define WM8915_FLL_REF_FREQ_MASK 0x0004 /* FLL_REF_FREQ */ | ||
1729 | #define WM8915_FLL_REF_FREQ_SHIFT 2 /* FLL_REF_FREQ */ | ||
1730 | #define WM8915_FLL_REF_FREQ_WIDTH 1 /* FLL_REF_FREQ */ | ||
1731 | #define WM8915_FLL_REFCLK_SRC_MASK 0x0003 /* FLL_REFCLK_SRC - [1:0] */ | ||
1732 | #define WM8915_FLL_REFCLK_SRC_SHIFT 0 /* FLL_REFCLK_SRC - [1:0] */ | ||
1733 | #define WM8915_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [1:0] */ | ||
1734 | |||
1735 | /* | ||
1736 | * R549 (0x225) - FLL Control (6) | ||
1737 | */ | ||
1738 | #define WM8915_FLL_REFCLK_SRC_STS_MASK 0x000C /* FLL_REFCLK_SRC_STS - [3:2] */ | ||
1739 | #define WM8915_FLL_REFCLK_SRC_STS_SHIFT 2 /* FLL_REFCLK_SRC_STS - [3:2] */ | ||
1740 | #define WM8915_FLL_REFCLK_SRC_STS_WIDTH 2 /* FLL_REFCLK_SRC_STS - [3:2] */ | ||
1741 | #define WM8915_FLL_SWITCH_CLK 0x0001 /* FLL_SWITCH_CLK */ | ||
1742 | #define WM8915_FLL_SWITCH_CLK_MASK 0x0001 /* FLL_SWITCH_CLK */ | ||
1743 | #define WM8915_FLL_SWITCH_CLK_SHIFT 0 /* FLL_SWITCH_CLK */ | ||
1744 | #define WM8915_FLL_SWITCH_CLK_WIDTH 1 /* FLL_SWITCH_CLK */ | ||
1745 | |||
1746 | /* | ||
1747 | * R550 (0x226) - FLL EFS 1 | ||
1748 | */ | ||
1749 | #define WM8915_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */ | ||
1750 | #define WM8915_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */ | ||
1751 | #define WM8915_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */ | ||
1752 | |||
1753 | /* | ||
1754 | * R551 (0x227) - FLL EFS 2 | ||
1755 | */ | ||
1756 | #define WM8915_FLL_LFSR_SEL_MASK 0x0006 /* FLL_LFSR_SEL - [2:1] */ | ||
1757 | #define WM8915_FLL_LFSR_SEL_SHIFT 1 /* FLL_LFSR_SEL - [2:1] */ | ||
1758 | #define WM8915_FLL_LFSR_SEL_WIDTH 2 /* FLL_LFSR_SEL - [2:1] */ | ||
1759 | #define WM8915_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */ | ||
1760 | #define WM8915_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */ | ||
1761 | #define WM8915_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */ | ||
1762 | #define WM8915_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */ | ||
1763 | |||
1764 | /* | ||
1765 | * R768 (0x300) - AIF1 Control | ||
1766 | */ | ||
1767 | #define WM8915_AIF1_TRI 0x0004 /* AIF1_TRI */ | ||
1768 | #define WM8915_AIF1_TRI_MASK 0x0004 /* AIF1_TRI */ | ||
1769 | #define WM8915_AIF1_TRI_SHIFT 2 /* AIF1_TRI */ | ||
1770 | #define WM8915_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ | ||
1771 | #define WM8915_AIF1_FMT_MASK 0x0003 /* AIF1_FMT - [1:0] */ | ||
1772 | #define WM8915_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [1:0] */ | ||
1773 | #define WM8915_AIF1_FMT_WIDTH 2 /* AIF1_FMT - [1:0] */ | ||
1774 | |||
1775 | /* | ||
1776 | * R769 (0x301) - AIF1 BCLK | ||
1777 | */ | ||
1778 | #define WM8915_AIF1_BCLK_INV 0x0400 /* AIF1_BCLK_INV */ | ||
1779 | #define WM8915_AIF1_BCLK_INV_MASK 0x0400 /* AIF1_BCLK_INV */ | ||
1780 | #define WM8915_AIF1_BCLK_INV_SHIFT 10 /* AIF1_BCLK_INV */ | ||
1781 | #define WM8915_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ | ||
1782 | #define WM8915_AIF1_BCLK_FRC 0x0200 /* AIF1_BCLK_FRC */ | ||
1783 | #define WM8915_AIF1_BCLK_FRC_MASK 0x0200 /* AIF1_BCLK_FRC */ | ||
1784 | #define WM8915_AIF1_BCLK_FRC_SHIFT 9 /* AIF1_BCLK_FRC */ | ||
1785 | #define WM8915_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ | ||
1786 | #define WM8915_AIF1_BCLK_MSTR 0x0100 /* AIF1_BCLK_MSTR */ | ||
1787 | #define WM8915_AIF1_BCLK_MSTR_MASK 0x0100 /* AIF1_BCLK_MSTR */ | ||
1788 | #define WM8915_AIF1_BCLK_MSTR_SHIFT 8 /* AIF1_BCLK_MSTR */ | ||
1789 | #define WM8915_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ | ||
1790 | #define WM8915_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */ | ||
1791 | #define WM8915_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */ | ||
1792 | #define WM8915_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */ | ||
1793 | |||
1794 | /* | ||
1795 | * R770 (0x302) - AIF1 TX LRCLK(1) | ||
1796 | */ | ||
1797 | #define WM8915_AIF1TX_RATE_MASK 0x07FF /* AIF1TX_RATE - [10:0] */ | ||
1798 | #define WM8915_AIF1TX_RATE_SHIFT 0 /* AIF1TX_RATE - [10:0] */ | ||
1799 | #define WM8915_AIF1TX_RATE_WIDTH 11 /* AIF1TX_RATE - [10:0] */ | ||
1800 | |||
1801 | /* | ||
1802 | * R771 (0x303) - AIF1 TX LRCLK(2) | ||
1803 | */ | ||
1804 | #define WM8915_AIF1TX_LRCLK_MODE 0x0008 /* AIF1TX_LRCLK_MODE */ | ||
1805 | #define WM8915_AIF1TX_LRCLK_MODE_MASK 0x0008 /* AIF1TX_LRCLK_MODE */ | ||
1806 | #define WM8915_AIF1TX_LRCLK_MODE_SHIFT 3 /* AIF1TX_LRCLK_MODE */ | ||
1807 | #define WM8915_AIF1TX_LRCLK_MODE_WIDTH 1 /* AIF1TX_LRCLK_MODE */ | ||
1808 | #define WM8915_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ | ||
1809 | #define WM8915_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ | ||
1810 | #define WM8915_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ | ||
1811 | #define WM8915_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ | ||
1812 | #define WM8915_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ | ||
1813 | #define WM8915_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ | ||
1814 | #define WM8915_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ | ||
1815 | #define WM8915_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ | ||
1816 | #define WM8915_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ | ||
1817 | #define WM8915_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ | ||
1818 | #define WM8915_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ | ||
1819 | #define WM8915_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ | ||
1820 | |||
1821 | /* | ||
1822 | * R772 (0x304) - AIF1 RX LRCLK(1) | ||
1823 | */ | ||
1824 | #define WM8915_AIF1RX_RATE_MASK 0x07FF /* AIF1RX_RATE - [10:0] */ | ||
1825 | #define WM8915_AIF1RX_RATE_SHIFT 0 /* AIF1RX_RATE - [10:0] */ | ||
1826 | #define WM8915_AIF1RX_RATE_WIDTH 11 /* AIF1RX_RATE - [10:0] */ | ||
1827 | |||
1828 | /* | ||
1829 | * R773 (0x305) - AIF1 RX LRCLK(2) | ||
1830 | */ | ||
1831 | #define WM8915_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ | ||
1832 | #define WM8915_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ | ||
1833 | #define WM8915_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ | ||
1834 | #define WM8915_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ | ||
1835 | #define WM8915_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ | ||
1836 | #define WM8915_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ | ||
1837 | #define WM8915_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ | ||
1838 | #define WM8915_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ | ||
1839 | #define WM8915_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ | ||
1840 | #define WM8915_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ | ||
1841 | #define WM8915_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ | ||
1842 | #define WM8915_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ | ||
1843 | |||
1844 | /* | ||
1845 | * R774 (0x306) - AIF1TX Data Configuration (1) | ||
1846 | */ | ||
1847 | #define WM8915_AIF1TX_WL_MASK 0xFF00 /* AIF1TX_WL - [15:8] */ | ||
1848 | #define WM8915_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [15:8] */ | ||
1849 | #define WM8915_AIF1TX_WL_WIDTH 8 /* AIF1TX_WL - [15:8] */ | ||
1850 | #define WM8915_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ | ||
1851 | #define WM8915_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ | ||
1852 | #define WM8915_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ | ||
1853 | |||
1854 | /* | ||
1855 | * R775 (0x307) - AIF1TX Data Configuration (2) | ||
1856 | */ | ||
1857 | #define WM8915_AIF1TX_DAT_TRI 0x0001 /* AIF1TX_DAT_TRI */ | ||
1858 | #define WM8915_AIF1TX_DAT_TRI_MASK 0x0001 /* AIF1TX_DAT_TRI */ | ||
1859 | #define WM8915_AIF1TX_DAT_TRI_SHIFT 0 /* AIF1TX_DAT_TRI */ | ||
1860 | #define WM8915_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ | ||
1861 | |||
1862 | /* | ||
1863 | * R776 (0x308) - AIF1RX Data Configuration | ||
1864 | */ | ||
1865 | #define WM8915_AIF1RX_WL_MASK 0xFF00 /* AIF1RX_WL - [15:8] */ | ||
1866 | #define WM8915_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [15:8] */ | ||
1867 | #define WM8915_AIF1RX_WL_WIDTH 8 /* AIF1RX_WL - [15:8] */ | ||
1868 | #define WM8915_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ | ||
1869 | #define WM8915_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ | ||
1870 | #define WM8915_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ | ||
1871 | |||
1872 | /* | ||
1873 | * R777 (0x309) - AIF1TX Channel 0 Configuration | ||
1874 | */ | ||
1875 | #define WM8915_AIF1TX_CHAN0_DAT_INV 0x8000 /* AIF1TX_CHAN0_DAT_INV */ | ||
1876 | #define WM8915_AIF1TX_CHAN0_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN0_DAT_INV */ | ||
1877 | #define WM8915_AIF1TX_CHAN0_DAT_INV_SHIFT 15 /* AIF1TX_CHAN0_DAT_INV */ | ||
1878 | #define WM8915_AIF1TX_CHAN0_DAT_INV_WIDTH 1 /* AIF1TX_CHAN0_DAT_INV */ | ||
1879 | #define WM8915_AIF1TX_CHAN0_SPACING_MASK 0x7E00 /* AIF1TX_CHAN0_SPACING - [14:9] */ | ||
1880 | #define WM8915_AIF1TX_CHAN0_SPACING_SHIFT 9 /* AIF1TX_CHAN0_SPACING - [14:9] */ | ||
1881 | #define WM8915_AIF1TX_CHAN0_SPACING_WIDTH 6 /* AIF1TX_CHAN0_SPACING - [14:9] */ | ||
1882 | #define WM8915_AIF1TX_CHAN0_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN0_SLOTS - [8:6] */ | ||
1883 | #define WM8915_AIF1TX_CHAN0_SLOTS_SHIFT 6 /* AIF1TX_CHAN0_SLOTS - [8:6] */ | ||
1884 | #define WM8915_AIF1TX_CHAN0_SLOTS_WIDTH 3 /* AIF1TX_CHAN0_SLOTS - [8:6] */ | ||
1885 | #define WM8915_AIF1TX_CHAN0_START_SLOT_MASK 0x003F /* AIF1TX_CHAN0_START_SLOT - [5:0] */ | ||
1886 | #define WM8915_AIF1TX_CHAN0_START_SLOT_SHIFT 0 /* AIF1TX_CHAN0_START_SLOT - [5:0] */ | ||
1887 | #define WM8915_AIF1TX_CHAN0_START_SLOT_WIDTH 6 /* AIF1TX_CHAN0_START_SLOT - [5:0] */ | ||
1888 | |||
1889 | /* | ||
1890 | * R778 (0x30A) - AIF1TX Channel 1 Configuration | ||
1891 | */ | ||
1892 | #define WM8915_AIF1TX_CHAN1_DAT_INV 0x8000 /* AIF1TX_CHAN1_DAT_INV */ | ||
1893 | #define WM8915_AIF1TX_CHAN1_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN1_DAT_INV */ | ||
1894 | #define WM8915_AIF1TX_CHAN1_DAT_INV_SHIFT 15 /* AIF1TX_CHAN1_DAT_INV */ | ||
1895 | #define WM8915_AIF1TX_CHAN1_DAT_INV_WIDTH 1 /* AIF1TX_CHAN1_DAT_INV */ | ||
1896 | #define WM8915_AIF1TX_CHAN1_SPACING_MASK 0x7E00 /* AIF1TX_CHAN1_SPACING - [14:9] */ | ||
1897 | #define WM8915_AIF1TX_CHAN1_SPACING_SHIFT 9 /* AIF1TX_CHAN1_SPACING - [14:9] */ | ||
1898 | #define WM8915_AIF1TX_CHAN1_SPACING_WIDTH 6 /* AIF1TX_CHAN1_SPACING - [14:9] */ | ||
1899 | #define WM8915_AIF1TX_CHAN1_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN1_SLOTS - [8:6] */ | ||
1900 | #define WM8915_AIF1TX_CHAN1_SLOTS_SHIFT 6 /* AIF1TX_CHAN1_SLOTS - [8:6] */ | ||
1901 | #define WM8915_AIF1TX_CHAN1_SLOTS_WIDTH 3 /* AIF1TX_CHAN1_SLOTS - [8:6] */ | ||
1902 | #define WM8915_AIF1TX_CHAN1_START_SLOT_MASK 0x003F /* AIF1TX_CHAN1_START_SLOT - [5:0] */ | ||
1903 | #define WM8915_AIF1TX_CHAN1_START_SLOT_SHIFT 0 /* AIF1TX_CHAN1_START_SLOT - [5:0] */ | ||
1904 | #define WM8915_AIF1TX_CHAN1_START_SLOT_WIDTH 6 /* AIF1TX_CHAN1_START_SLOT - [5:0] */ | ||
1905 | |||
1906 | /* | ||
1907 | * R779 (0x30B) - AIF1TX Channel 2 Configuration | ||
1908 | */ | ||
1909 | #define WM8915_AIF1TX_CHAN2_DAT_INV 0x8000 /* AIF1TX_CHAN2_DAT_INV */ | ||
1910 | #define WM8915_AIF1TX_CHAN2_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN2_DAT_INV */ | ||
1911 | #define WM8915_AIF1TX_CHAN2_DAT_INV_SHIFT 15 /* AIF1TX_CHAN2_DAT_INV */ | ||
1912 | #define WM8915_AIF1TX_CHAN2_DAT_INV_WIDTH 1 /* AIF1TX_CHAN2_DAT_INV */ | ||
1913 | #define WM8915_AIF1TX_CHAN2_SPACING_MASK 0x7E00 /* AIF1TX_CHAN2_SPACING - [14:9] */ | ||
1914 | #define WM8915_AIF1TX_CHAN2_SPACING_SHIFT 9 /* AIF1TX_CHAN2_SPACING - [14:9] */ | ||
1915 | #define WM8915_AIF1TX_CHAN2_SPACING_WIDTH 6 /* AIF1TX_CHAN2_SPACING - [14:9] */ | ||
1916 | #define WM8915_AIF1TX_CHAN2_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN2_SLOTS - [8:6] */ | ||
1917 | #define WM8915_AIF1TX_CHAN2_SLOTS_SHIFT 6 /* AIF1TX_CHAN2_SLOTS - [8:6] */ | ||
1918 | #define WM8915_AIF1TX_CHAN2_SLOTS_WIDTH 3 /* AIF1TX_CHAN2_SLOTS - [8:6] */ | ||
1919 | #define WM8915_AIF1TX_CHAN2_START_SLOT_MASK 0x003F /* AIF1TX_CHAN2_START_SLOT - [5:0] */ | ||
1920 | #define WM8915_AIF1TX_CHAN2_START_SLOT_SHIFT 0 /* AIF1TX_CHAN2_START_SLOT - [5:0] */ | ||
1921 | #define WM8915_AIF1TX_CHAN2_START_SLOT_WIDTH 6 /* AIF1TX_CHAN2_START_SLOT - [5:0] */ | ||
1922 | |||
1923 | /* | ||
1924 | * R780 (0x30C) - AIF1TX Channel 3 Configuration | ||
1925 | */ | ||
1926 | #define WM8915_AIF1TX_CHAN3_DAT_INV 0x8000 /* AIF1TX_CHAN3_DAT_INV */ | ||
1927 | #define WM8915_AIF1TX_CHAN3_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN3_DAT_INV */ | ||
1928 | #define WM8915_AIF1TX_CHAN3_DAT_INV_SHIFT 15 /* AIF1TX_CHAN3_DAT_INV */ | ||
1929 | #define WM8915_AIF1TX_CHAN3_DAT_INV_WIDTH 1 /* AIF1TX_CHAN3_DAT_INV */ | ||
1930 | #define WM8915_AIF1TX_CHAN3_SPACING_MASK 0x7E00 /* AIF1TX_CHAN3_SPACING - [14:9] */ | ||
1931 | #define WM8915_AIF1TX_CHAN3_SPACING_SHIFT 9 /* AIF1TX_CHAN3_SPACING - [14:9] */ | ||
1932 | #define WM8915_AIF1TX_CHAN3_SPACING_WIDTH 6 /* AIF1TX_CHAN3_SPACING - [14:9] */ | ||
1933 | #define WM8915_AIF1TX_CHAN3_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN3_SLOTS - [8:6] */ | ||
1934 | #define WM8915_AIF1TX_CHAN3_SLOTS_SHIFT 6 /* AIF1TX_CHAN3_SLOTS - [8:6] */ | ||
1935 | #define WM8915_AIF1TX_CHAN3_SLOTS_WIDTH 3 /* AIF1TX_CHAN3_SLOTS - [8:6] */ | ||
1936 | #define WM8915_AIF1TX_CHAN3_START_SLOT_MASK 0x003F /* AIF1TX_CHAN3_START_SLOT - [5:0] */ | ||
1937 | #define WM8915_AIF1TX_CHAN3_START_SLOT_SHIFT 0 /* AIF1TX_CHAN3_START_SLOT - [5:0] */ | ||
1938 | #define WM8915_AIF1TX_CHAN3_START_SLOT_WIDTH 6 /* AIF1TX_CHAN3_START_SLOT - [5:0] */ | ||
1939 | |||
1940 | /* | ||
1941 | * R781 (0x30D) - AIF1TX Channel 4 Configuration | ||
1942 | */ | ||
1943 | #define WM8915_AIF1TX_CHAN4_DAT_INV 0x8000 /* AIF1TX_CHAN4_DAT_INV */ | ||
1944 | #define WM8915_AIF1TX_CHAN4_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN4_DAT_INV */ | ||
1945 | #define WM8915_AIF1TX_CHAN4_DAT_INV_SHIFT 15 /* AIF1TX_CHAN4_DAT_INV */ | ||
1946 | #define WM8915_AIF1TX_CHAN4_DAT_INV_WIDTH 1 /* AIF1TX_CHAN4_DAT_INV */ | ||
1947 | #define WM8915_AIF1TX_CHAN4_SPACING_MASK 0x7E00 /* AIF1TX_CHAN4_SPACING - [14:9] */ | ||
1948 | #define WM8915_AIF1TX_CHAN4_SPACING_SHIFT 9 /* AIF1TX_CHAN4_SPACING - [14:9] */ | ||
1949 | #define WM8915_AIF1TX_CHAN4_SPACING_WIDTH 6 /* AIF1TX_CHAN4_SPACING - [14:9] */ | ||
1950 | #define WM8915_AIF1TX_CHAN4_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN4_SLOTS - [8:6] */ | ||
1951 | #define WM8915_AIF1TX_CHAN4_SLOTS_SHIFT 6 /* AIF1TX_CHAN4_SLOTS - [8:6] */ | ||
1952 | #define WM8915_AIF1TX_CHAN4_SLOTS_WIDTH 3 /* AIF1TX_CHAN4_SLOTS - [8:6] */ | ||
1953 | #define WM8915_AIF1TX_CHAN4_START_SLOT_MASK 0x003F /* AIF1TX_CHAN4_START_SLOT - [5:0] */ | ||
1954 | #define WM8915_AIF1TX_CHAN4_START_SLOT_SHIFT 0 /* AIF1TX_CHAN4_START_SLOT - [5:0] */ | ||
1955 | #define WM8915_AIF1TX_CHAN4_START_SLOT_WIDTH 6 /* AIF1TX_CHAN4_START_SLOT - [5:0] */ | ||
1956 | |||
1957 | /* | ||
1958 | * R782 (0x30E) - AIF1TX Channel 5 Configuration | ||
1959 | */ | ||
1960 | #define WM8915_AIF1TX_CHAN5_DAT_INV 0x8000 /* AIF1TX_CHAN5_DAT_INV */ | ||
1961 | #define WM8915_AIF1TX_CHAN5_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN5_DAT_INV */ | ||
1962 | #define WM8915_AIF1TX_CHAN5_DAT_INV_SHIFT 15 /* AIF1TX_CHAN5_DAT_INV */ | ||
1963 | #define WM8915_AIF1TX_CHAN5_DAT_INV_WIDTH 1 /* AIF1TX_CHAN5_DAT_INV */ | ||
1964 | #define WM8915_AIF1TX_CHAN5_SPACING_MASK 0x7E00 /* AIF1TX_CHAN5_SPACING - [14:9] */ | ||
1965 | #define WM8915_AIF1TX_CHAN5_SPACING_SHIFT 9 /* AIF1TX_CHAN5_SPACING - [14:9] */ | ||
1966 | #define WM8915_AIF1TX_CHAN5_SPACING_WIDTH 6 /* AIF1TX_CHAN5_SPACING - [14:9] */ | ||
1967 | #define WM8915_AIF1TX_CHAN5_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN5_SLOTS - [8:6] */ | ||
1968 | #define WM8915_AIF1TX_CHAN5_SLOTS_SHIFT 6 /* AIF1TX_CHAN5_SLOTS - [8:6] */ | ||
1969 | #define WM8915_AIF1TX_CHAN5_SLOTS_WIDTH 3 /* AIF1TX_CHAN5_SLOTS - [8:6] */ | ||
1970 | #define WM8915_AIF1TX_CHAN5_START_SLOT_MASK 0x003F /* AIF1TX_CHAN5_START_SLOT - [5:0] */ | ||
1971 | #define WM8915_AIF1TX_CHAN5_START_SLOT_SHIFT 0 /* AIF1TX_CHAN5_START_SLOT - [5:0] */ | ||
1972 | #define WM8915_AIF1TX_CHAN5_START_SLOT_WIDTH 6 /* AIF1TX_CHAN5_START_SLOT - [5:0] */ | ||
1973 | |||
1974 | /* | ||
1975 | * R783 (0x30F) - AIF1RX Channel 0 Configuration | ||
1976 | */ | ||
1977 | #define WM8915_AIF1RX_CHAN0_DAT_INV 0x8000 /* AIF1RX_CHAN0_DAT_INV */ | ||
1978 | #define WM8915_AIF1RX_CHAN0_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN0_DAT_INV */ | ||
1979 | #define WM8915_AIF1RX_CHAN0_DAT_INV_SHIFT 15 /* AIF1RX_CHAN0_DAT_INV */ | ||
1980 | #define WM8915_AIF1RX_CHAN0_DAT_INV_WIDTH 1 /* AIF1RX_CHAN0_DAT_INV */ | ||
1981 | #define WM8915_AIF1RX_CHAN0_SPACING_MASK 0x7E00 /* AIF1RX_CHAN0_SPACING - [14:9] */ | ||
1982 | #define WM8915_AIF1RX_CHAN0_SPACING_SHIFT 9 /* AIF1RX_CHAN0_SPACING - [14:9] */ | ||
1983 | #define WM8915_AIF1RX_CHAN0_SPACING_WIDTH 6 /* AIF1RX_CHAN0_SPACING - [14:9] */ | ||
1984 | #define WM8915_AIF1RX_CHAN0_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN0_SLOTS - [8:6] */ | ||
1985 | #define WM8915_AIF1RX_CHAN0_SLOTS_SHIFT 6 /* AIF1RX_CHAN0_SLOTS - [8:6] */ | ||
1986 | #define WM8915_AIF1RX_CHAN0_SLOTS_WIDTH 3 /* AIF1RX_CHAN0_SLOTS - [8:6] */ | ||
1987 | #define WM8915_AIF1RX_CHAN0_START_SLOT_MASK 0x003F /* AIF1RX_CHAN0_START_SLOT - [5:0] */ | ||
1988 | #define WM8915_AIF1RX_CHAN0_START_SLOT_SHIFT 0 /* AIF1RX_CHAN0_START_SLOT - [5:0] */ | ||
1989 | #define WM8915_AIF1RX_CHAN0_START_SLOT_WIDTH 6 /* AIF1RX_CHAN0_START_SLOT - [5:0] */ | ||
1990 | |||
1991 | /* | ||
1992 | * R784 (0x310) - AIF1RX Channel 1 Configuration | ||
1993 | */ | ||
1994 | #define WM8915_AIF1RX_CHAN1_DAT_INV 0x8000 /* AIF1RX_CHAN1_DAT_INV */ | ||
1995 | #define WM8915_AIF1RX_CHAN1_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN1_DAT_INV */ | ||
1996 | #define WM8915_AIF1RX_CHAN1_DAT_INV_SHIFT 15 /* AIF1RX_CHAN1_DAT_INV */ | ||
1997 | #define WM8915_AIF1RX_CHAN1_DAT_INV_WIDTH 1 /* AIF1RX_CHAN1_DAT_INV */ | ||
1998 | #define WM8915_AIF1RX_CHAN1_SPACING_MASK 0x7E00 /* AIF1RX_CHAN1_SPACING - [14:9] */ | ||
1999 | #define WM8915_AIF1RX_CHAN1_SPACING_SHIFT 9 /* AIF1RX_CHAN1_SPACING - [14:9] */ | ||
2000 | #define WM8915_AIF1RX_CHAN1_SPACING_WIDTH 6 /* AIF1RX_CHAN1_SPACING - [14:9] */ | ||
2001 | #define WM8915_AIF1RX_CHAN1_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN1_SLOTS - [8:6] */ | ||
2002 | #define WM8915_AIF1RX_CHAN1_SLOTS_SHIFT 6 /* AIF1RX_CHAN1_SLOTS - [8:6] */ | ||
2003 | #define WM8915_AIF1RX_CHAN1_SLOTS_WIDTH 3 /* AIF1RX_CHAN1_SLOTS - [8:6] */ | ||
2004 | #define WM8915_AIF1RX_CHAN1_START_SLOT_MASK 0x003F /* AIF1RX_CHAN1_START_SLOT - [5:0] */ | ||
2005 | #define WM8915_AIF1RX_CHAN1_START_SLOT_SHIFT 0 /* AIF1RX_CHAN1_START_SLOT - [5:0] */ | ||
2006 | #define WM8915_AIF1RX_CHAN1_START_SLOT_WIDTH 6 /* AIF1RX_CHAN1_START_SLOT - [5:0] */ | ||
2007 | |||
2008 | /* | ||
2009 | * R785 (0x311) - AIF1RX Channel 2 Configuration | ||
2010 | */ | ||
2011 | #define WM8915_AIF1RX_CHAN2_DAT_INV 0x8000 /* AIF1RX_CHAN2_DAT_INV */ | ||
2012 | #define WM8915_AIF1RX_CHAN2_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN2_DAT_INV */ | ||
2013 | #define WM8915_AIF1RX_CHAN2_DAT_INV_SHIFT 15 /* AIF1RX_CHAN2_DAT_INV */ | ||
2014 | #define WM8915_AIF1RX_CHAN2_DAT_INV_WIDTH 1 /* AIF1RX_CHAN2_DAT_INV */ | ||
2015 | #define WM8915_AIF1RX_CHAN2_SPACING_MASK 0x7E00 /* AIF1RX_CHAN2_SPACING - [14:9] */ | ||
2016 | #define WM8915_AIF1RX_CHAN2_SPACING_SHIFT 9 /* AIF1RX_CHAN2_SPACING - [14:9] */ | ||
2017 | #define WM8915_AIF1RX_CHAN2_SPACING_WIDTH 6 /* AIF1RX_CHAN2_SPACING - [14:9] */ | ||
2018 | #define WM8915_AIF1RX_CHAN2_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN2_SLOTS - [8:6] */ | ||
2019 | #define WM8915_AIF1RX_CHAN2_SLOTS_SHIFT 6 /* AIF1RX_CHAN2_SLOTS - [8:6] */ | ||
2020 | #define WM8915_AIF1RX_CHAN2_SLOTS_WIDTH 3 /* AIF1RX_CHAN2_SLOTS - [8:6] */ | ||
2021 | #define WM8915_AIF1RX_CHAN2_START_SLOT_MASK 0x003F /* AIF1RX_CHAN2_START_SLOT - [5:0] */ | ||
2022 | #define WM8915_AIF1RX_CHAN2_START_SLOT_SHIFT 0 /* AIF1RX_CHAN2_START_SLOT - [5:0] */ | ||
2023 | #define WM8915_AIF1RX_CHAN2_START_SLOT_WIDTH 6 /* AIF1RX_CHAN2_START_SLOT - [5:0] */ | ||
2024 | |||
2025 | /* | ||
2026 | * R786 (0x312) - AIF1RX Channel 3 Configuration | ||
2027 | */ | ||
2028 | #define WM8915_AIF1RX_CHAN3_DAT_INV 0x8000 /* AIF1RX_CHAN3_DAT_INV */ | ||
2029 | #define WM8915_AIF1RX_CHAN3_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN3_DAT_INV */ | ||
2030 | #define WM8915_AIF1RX_CHAN3_DAT_INV_SHIFT 15 /* AIF1RX_CHAN3_DAT_INV */ | ||
2031 | #define WM8915_AIF1RX_CHAN3_DAT_INV_WIDTH 1 /* AIF1RX_CHAN3_DAT_INV */ | ||
2032 | #define WM8915_AIF1RX_CHAN3_SPACING_MASK 0x7E00 /* AIF1RX_CHAN3_SPACING - [14:9] */ | ||
2033 | #define WM8915_AIF1RX_CHAN3_SPACING_SHIFT 9 /* AIF1RX_CHAN3_SPACING - [14:9] */ | ||
2034 | #define WM8915_AIF1RX_CHAN3_SPACING_WIDTH 6 /* AIF1RX_CHAN3_SPACING - [14:9] */ | ||
2035 | #define WM8915_AIF1RX_CHAN3_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN3_SLOTS - [8:6] */ | ||
2036 | #define WM8915_AIF1RX_CHAN3_SLOTS_SHIFT 6 /* AIF1RX_CHAN3_SLOTS - [8:6] */ | ||
2037 | #define WM8915_AIF1RX_CHAN3_SLOTS_WIDTH 3 /* AIF1RX_CHAN3_SLOTS - [8:6] */ | ||
2038 | #define WM8915_AIF1RX_CHAN3_START_SLOT_MASK 0x003F /* AIF1RX_CHAN3_START_SLOT - [5:0] */ | ||
2039 | #define WM8915_AIF1RX_CHAN3_START_SLOT_SHIFT 0 /* AIF1RX_CHAN3_START_SLOT - [5:0] */ | ||
2040 | #define WM8915_AIF1RX_CHAN3_START_SLOT_WIDTH 6 /* AIF1RX_CHAN3_START_SLOT - [5:0] */ | ||
2041 | |||
2042 | /* | ||
2043 | * R787 (0x313) - AIF1RX Channel 4 Configuration | ||
2044 | */ | ||
2045 | #define WM8915_AIF1RX_CHAN4_DAT_INV 0x8000 /* AIF1RX_CHAN4_DAT_INV */ | ||
2046 | #define WM8915_AIF1RX_CHAN4_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN4_DAT_INV */ | ||
2047 | #define WM8915_AIF1RX_CHAN4_DAT_INV_SHIFT 15 /* AIF1RX_CHAN4_DAT_INV */ | ||
2048 | #define WM8915_AIF1RX_CHAN4_DAT_INV_WIDTH 1 /* AIF1RX_CHAN4_DAT_INV */ | ||
2049 | #define WM8915_AIF1RX_CHAN4_SPACING_MASK 0x7E00 /* AIF1RX_CHAN4_SPACING - [14:9] */ | ||
2050 | #define WM8915_AIF1RX_CHAN4_SPACING_SHIFT 9 /* AIF1RX_CHAN4_SPACING - [14:9] */ | ||
2051 | #define WM8915_AIF1RX_CHAN4_SPACING_WIDTH 6 /* AIF1RX_CHAN4_SPACING - [14:9] */ | ||
2052 | #define WM8915_AIF1RX_CHAN4_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN4_SLOTS - [8:6] */ | ||
2053 | #define WM8915_AIF1RX_CHAN4_SLOTS_SHIFT 6 /* AIF1RX_CHAN4_SLOTS - [8:6] */ | ||
2054 | #define WM8915_AIF1RX_CHAN4_SLOTS_WIDTH 3 /* AIF1RX_CHAN4_SLOTS - [8:6] */ | ||
2055 | #define WM8915_AIF1RX_CHAN4_START_SLOT_MASK 0x003F /* AIF1RX_CHAN4_START_SLOT - [5:0] */ | ||
2056 | #define WM8915_AIF1RX_CHAN4_START_SLOT_SHIFT 0 /* AIF1RX_CHAN4_START_SLOT - [5:0] */ | ||
2057 | #define WM8915_AIF1RX_CHAN4_START_SLOT_WIDTH 6 /* AIF1RX_CHAN4_START_SLOT - [5:0] */ | ||
2058 | |||
2059 | /* | ||
2060 | * R788 (0x314) - AIF1RX Channel 5 Configuration | ||
2061 | */ | ||
2062 | #define WM8915_AIF1RX_CHAN5_DAT_INV 0x8000 /* AIF1RX_CHAN5_DAT_INV */ | ||
2063 | #define WM8915_AIF1RX_CHAN5_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN5_DAT_INV */ | ||
2064 | #define WM8915_AIF1RX_CHAN5_DAT_INV_SHIFT 15 /* AIF1RX_CHAN5_DAT_INV */ | ||
2065 | #define WM8915_AIF1RX_CHAN5_DAT_INV_WIDTH 1 /* AIF1RX_CHAN5_DAT_INV */ | ||
2066 | #define WM8915_AIF1RX_CHAN5_SPACING_MASK 0x7E00 /* AIF1RX_CHAN5_SPACING - [14:9] */ | ||
2067 | #define WM8915_AIF1RX_CHAN5_SPACING_SHIFT 9 /* AIF1RX_CHAN5_SPACING - [14:9] */ | ||
2068 | #define WM8915_AIF1RX_CHAN5_SPACING_WIDTH 6 /* AIF1RX_CHAN5_SPACING - [14:9] */ | ||
2069 | #define WM8915_AIF1RX_CHAN5_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN5_SLOTS - [8:6] */ | ||
2070 | #define WM8915_AIF1RX_CHAN5_SLOTS_SHIFT 6 /* AIF1RX_CHAN5_SLOTS - [8:6] */ | ||
2071 | #define WM8915_AIF1RX_CHAN5_SLOTS_WIDTH 3 /* AIF1RX_CHAN5_SLOTS - [8:6] */ | ||
2072 | #define WM8915_AIF1RX_CHAN5_START_SLOT_MASK 0x003F /* AIF1RX_CHAN5_START_SLOT - [5:0] */ | ||
2073 | #define WM8915_AIF1RX_CHAN5_START_SLOT_SHIFT 0 /* AIF1RX_CHAN5_START_SLOT - [5:0] */ | ||
2074 | #define WM8915_AIF1RX_CHAN5_START_SLOT_WIDTH 6 /* AIF1RX_CHAN5_START_SLOT - [5:0] */ | ||
2075 | |||
2076 | /* | ||
2077 | * R789 (0x315) - AIF1RX Mono Configuration | ||
2078 | */ | ||
2079 | #define WM8915_AIF1RX_CHAN4_MONO_MODE 0x0004 /* AIF1RX_CHAN4_MONO_MODE */ | ||
2080 | #define WM8915_AIF1RX_CHAN4_MONO_MODE_MASK 0x0004 /* AIF1RX_CHAN4_MONO_MODE */ | ||
2081 | #define WM8915_AIF1RX_CHAN4_MONO_MODE_SHIFT 2 /* AIF1RX_CHAN4_MONO_MODE */ | ||
2082 | #define WM8915_AIF1RX_CHAN4_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN4_MONO_MODE */ | ||
2083 | #define WM8915_AIF1RX_CHAN2_MONO_MODE 0x0002 /* AIF1RX_CHAN2_MONO_MODE */ | ||
2084 | #define WM8915_AIF1RX_CHAN2_MONO_MODE_MASK 0x0002 /* AIF1RX_CHAN2_MONO_MODE */ | ||
2085 | #define WM8915_AIF1RX_CHAN2_MONO_MODE_SHIFT 1 /* AIF1RX_CHAN2_MONO_MODE */ | ||
2086 | #define WM8915_AIF1RX_CHAN2_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN2_MONO_MODE */ | ||
2087 | #define WM8915_AIF1RX_CHAN0_MONO_MODE 0x0001 /* AIF1RX_CHAN0_MONO_MODE */ | ||
2088 | #define WM8915_AIF1RX_CHAN0_MONO_MODE_MASK 0x0001 /* AIF1RX_CHAN0_MONO_MODE */ | ||
2089 | #define WM8915_AIF1RX_CHAN0_MONO_MODE_SHIFT 0 /* AIF1RX_CHAN0_MONO_MODE */ | ||
2090 | #define WM8915_AIF1RX_CHAN0_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN0_MONO_MODE */ | ||
2091 | |||
2092 | /* | ||
2093 | * R794 (0x31A) - AIF1TX Test | ||
2094 | */ | ||
2095 | #define WM8915_AIF1TX45_DITHER_ENA 0x0004 /* AIF1TX45_DITHER_ENA */ | ||
2096 | #define WM8915_AIF1TX45_DITHER_ENA_MASK 0x0004 /* AIF1TX45_DITHER_ENA */ | ||
2097 | #define WM8915_AIF1TX45_DITHER_ENA_SHIFT 2 /* AIF1TX45_DITHER_ENA */ | ||
2098 | #define WM8915_AIF1TX45_DITHER_ENA_WIDTH 1 /* AIF1TX45_DITHER_ENA */ | ||
2099 | #define WM8915_AIF1TX23_DITHER_ENA 0x0002 /* AIF1TX23_DITHER_ENA */ | ||
2100 | #define WM8915_AIF1TX23_DITHER_ENA_MASK 0x0002 /* AIF1TX23_DITHER_ENA */ | ||
2101 | #define WM8915_AIF1TX23_DITHER_ENA_SHIFT 1 /* AIF1TX23_DITHER_ENA */ | ||
2102 | #define WM8915_AIF1TX23_DITHER_ENA_WIDTH 1 /* AIF1TX23_DITHER_ENA */ | ||
2103 | #define WM8915_AIF1TX01_DITHER_ENA 0x0001 /* AIF1TX01_DITHER_ENA */ | ||
2104 | #define WM8915_AIF1TX01_DITHER_ENA_MASK 0x0001 /* AIF1TX01_DITHER_ENA */ | ||
2105 | #define WM8915_AIF1TX01_DITHER_ENA_SHIFT 0 /* AIF1TX01_DITHER_ENA */ | ||
2106 | #define WM8915_AIF1TX01_DITHER_ENA_WIDTH 1 /* AIF1TX01_DITHER_ENA */ | ||
2107 | |||
2108 | /* | ||
2109 | * R800 (0x320) - AIF2 Control | ||
2110 | */ | ||
2111 | #define WM8915_AIF2_TRI 0x0004 /* AIF2_TRI */ | ||
2112 | #define WM8915_AIF2_TRI_MASK 0x0004 /* AIF2_TRI */ | ||
2113 | #define WM8915_AIF2_TRI_SHIFT 2 /* AIF2_TRI */ | ||
2114 | #define WM8915_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ | ||
2115 | #define WM8915_AIF2_FMT_MASK 0x0003 /* AIF2_FMT - [1:0] */ | ||
2116 | #define WM8915_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [1:0] */ | ||
2117 | #define WM8915_AIF2_FMT_WIDTH 2 /* AIF2_FMT - [1:0] */ | ||
2118 | |||
2119 | /* | ||
2120 | * R801 (0x321) - AIF2 BCLK | ||
2121 | */ | ||
2122 | #define WM8915_AIF2_BCLK_INV 0x0400 /* AIF2_BCLK_INV */ | ||
2123 | #define WM8915_AIF2_BCLK_INV_MASK 0x0400 /* AIF2_BCLK_INV */ | ||
2124 | #define WM8915_AIF2_BCLK_INV_SHIFT 10 /* AIF2_BCLK_INV */ | ||
2125 | #define WM8915_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ | ||
2126 | #define WM8915_AIF2_BCLK_FRC 0x0200 /* AIF2_BCLK_FRC */ | ||
2127 | #define WM8915_AIF2_BCLK_FRC_MASK 0x0200 /* AIF2_BCLK_FRC */ | ||
2128 | #define WM8915_AIF2_BCLK_FRC_SHIFT 9 /* AIF2_BCLK_FRC */ | ||
2129 | #define WM8915_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */ | ||
2130 | #define WM8915_AIF2_BCLK_MSTR 0x0100 /* AIF2_BCLK_MSTR */ | ||
2131 | #define WM8915_AIF2_BCLK_MSTR_MASK 0x0100 /* AIF2_BCLK_MSTR */ | ||
2132 | #define WM8915_AIF2_BCLK_MSTR_SHIFT 8 /* AIF2_BCLK_MSTR */ | ||
2133 | #define WM8915_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */ | ||
2134 | #define WM8915_AIF2_BCLK_DIV_MASK 0x000F /* AIF2_BCLK_DIV - [3:0] */ | ||
2135 | #define WM8915_AIF2_BCLK_DIV_SHIFT 0 /* AIF2_BCLK_DIV - [3:0] */ | ||
2136 | #define WM8915_AIF2_BCLK_DIV_WIDTH 4 /* AIF2_BCLK_DIV - [3:0] */ | ||
2137 | |||
2138 | /* | ||
2139 | * R802 (0x322) - AIF2 TX LRCLK(1) | ||
2140 | */ | ||
2141 | #define WM8915_AIF2TX_RATE_MASK 0x07FF /* AIF2TX_RATE - [10:0] */ | ||
2142 | #define WM8915_AIF2TX_RATE_SHIFT 0 /* AIF2TX_RATE - [10:0] */ | ||
2143 | #define WM8915_AIF2TX_RATE_WIDTH 11 /* AIF2TX_RATE - [10:0] */ | ||
2144 | |||
2145 | /* | ||
2146 | * R803 (0x323) - AIF2 TX LRCLK(2) | ||
2147 | */ | ||
2148 | #define WM8915_AIF2TX_LRCLK_MODE 0x0008 /* AIF2TX_LRCLK_MODE */ | ||
2149 | #define WM8915_AIF2TX_LRCLK_MODE_MASK 0x0008 /* AIF2TX_LRCLK_MODE */ | ||
2150 | #define WM8915_AIF2TX_LRCLK_MODE_SHIFT 3 /* AIF2TX_LRCLK_MODE */ | ||
2151 | #define WM8915_AIF2TX_LRCLK_MODE_WIDTH 1 /* AIF2TX_LRCLK_MODE */ | ||
2152 | #define WM8915_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */ | ||
2153 | #define WM8915_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */ | ||
2154 | #define WM8915_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */ | ||
2155 | #define WM8915_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */ | ||
2156 | #define WM8915_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */ | ||
2157 | #define WM8915_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */ | ||
2158 | #define WM8915_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */ | ||
2159 | #define WM8915_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */ | ||
2160 | #define WM8915_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */ | ||
2161 | #define WM8915_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */ | ||
2162 | #define WM8915_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */ | ||
2163 | #define WM8915_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */ | ||
2164 | |||
2165 | /* | ||
2166 | * R804 (0x324) - AIF2 RX LRCLK(1) | ||
2167 | */ | ||
2168 | #define WM8915_AIF2RX_RATE_MASK 0x07FF /* AIF2RX_RATE - [10:0] */ | ||
2169 | #define WM8915_AIF2RX_RATE_SHIFT 0 /* AIF2RX_RATE - [10:0] */ | ||
2170 | #define WM8915_AIF2RX_RATE_WIDTH 11 /* AIF2RX_RATE - [10:0] */ | ||
2171 | |||
2172 | /* | ||
2173 | * R805 (0x325) - AIF2 RX LRCLK(2) | ||
2174 | */ | ||
2175 | #define WM8915_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */ | ||
2176 | #define WM8915_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */ | ||
2177 | #define WM8915_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */ | ||
2178 | #define WM8915_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */ | ||
2179 | #define WM8915_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */ | ||
2180 | #define WM8915_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */ | ||
2181 | #define WM8915_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */ | ||
2182 | #define WM8915_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */ | ||
2183 | #define WM8915_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */ | ||
2184 | #define WM8915_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */ | ||
2185 | #define WM8915_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */ | ||
2186 | #define WM8915_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */ | ||
2187 | |||
2188 | /* | ||
2189 | * R806 (0x326) - AIF2TX Data Configuration (1) | ||
2190 | */ | ||
2191 | #define WM8915_AIF2TX_WL_MASK 0xFF00 /* AIF2TX_WL - [15:8] */ | ||
2192 | #define WM8915_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [15:8] */ | ||
2193 | #define WM8915_AIF2TX_WL_WIDTH 8 /* AIF2TX_WL - [15:8] */ | ||
2194 | #define WM8915_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */ | ||
2195 | #define WM8915_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */ | ||
2196 | #define WM8915_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */ | ||
2197 | |||
2198 | /* | ||
2199 | * R807 (0x327) - AIF2TX Data Configuration (2) | ||
2200 | */ | ||
2201 | #define WM8915_AIF2TX_DAT_TRI 0x0001 /* AIF2TX_DAT_TRI */ | ||
2202 | #define WM8915_AIF2TX_DAT_TRI_MASK 0x0001 /* AIF2TX_DAT_TRI */ | ||
2203 | #define WM8915_AIF2TX_DAT_TRI_SHIFT 0 /* AIF2TX_DAT_TRI */ | ||
2204 | #define WM8915_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */ | ||
2205 | |||
2206 | /* | ||
2207 | * R808 (0x328) - AIF2RX Data Configuration | ||
2208 | */ | ||
2209 | #define WM8915_AIF2RX_WL_MASK 0xFF00 /* AIF2RX_WL - [15:8] */ | ||
2210 | #define WM8915_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [15:8] */ | ||
2211 | #define WM8915_AIF2RX_WL_WIDTH 8 /* AIF2RX_WL - [15:8] */ | ||
2212 | #define WM8915_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */ | ||
2213 | #define WM8915_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */ | ||
2214 | #define WM8915_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */ | ||
2215 | |||
2216 | /* | ||
2217 | * R809 (0x329) - AIF2TX Channel 0 Configuration | ||
2218 | */ | ||
2219 | #define WM8915_AIF2TX_CHAN0_DAT_INV 0x8000 /* AIF2TX_CHAN0_DAT_INV */ | ||
2220 | #define WM8915_AIF2TX_CHAN0_DAT_INV_MASK 0x8000 /* AIF2TX_CHAN0_DAT_INV */ | ||
2221 | #define WM8915_AIF2TX_CHAN0_DAT_INV_SHIFT 15 /* AIF2TX_CHAN0_DAT_INV */ | ||
2222 | #define WM8915_AIF2TX_CHAN0_DAT_INV_WIDTH 1 /* AIF2TX_CHAN0_DAT_INV */ | ||
2223 | #define WM8915_AIF2TX_CHAN0_SPACING_MASK 0x7E00 /* AIF2TX_CHAN0_SPACING - [14:9] */ | ||
2224 | #define WM8915_AIF2TX_CHAN0_SPACING_SHIFT 9 /* AIF2TX_CHAN0_SPACING - [14:9] */ | ||
2225 | #define WM8915_AIF2TX_CHAN0_SPACING_WIDTH 6 /* AIF2TX_CHAN0_SPACING - [14:9] */ | ||
2226 | #define WM8915_AIF2TX_CHAN0_SLOTS_MASK 0x01C0 /* AIF2TX_CHAN0_SLOTS - [8:6] */ | ||
2227 | #define WM8915_AIF2TX_CHAN0_SLOTS_SHIFT 6 /* AIF2TX_CHAN0_SLOTS - [8:6] */ | ||
2228 | #define WM8915_AIF2TX_CHAN0_SLOTS_WIDTH 3 /* AIF2TX_CHAN0_SLOTS - [8:6] */ | ||
2229 | #define WM8915_AIF2TX_CHAN0_START_SLOT_MASK 0x003F /* AIF2TX_CHAN0_START_SLOT - [5:0] */ | ||
2230 | #define WM8915_AIF2TX_CHAN0_START_SLOT_SHIFT 0 /* AIF2TX_CHAN0_START_SLOT - [5:0] */ | ||
2231 | #define WM8915_AIF2TX_CHAN0_START_SLOT_WIDTH 6 /* AIF2TX_CHAN0_START_SLOT - [5:0] */ | ||
2232 | |||
2233 | /* | ||
2234 | * R810 (0x32A) - AIF2TX Channel 1 Configuration | ||
2235 | */ | ||
2236 | #define WM8915_AIF2TX_CHAN1_DAT_INV 0x8000 /* AIF2TX_CHAN1_DAT_INV */ | ||
2237 | #define WM8915_AIF2TX_CHAN1_DAT_INV_MASK 0x8000 /* AIF2TX_CHAN1_DAT_INV */ | ||
2238 | #define WM8915_AIF2TX_CHAN1_DAT_INV_SHIFT 15 /* AIF2TX_CHAN1_DAT_INV */ | ||
2239 | #define WM8915_AIF2TX_CHAN1_DAT_INV_WIDTH 1 /* AIF2TX_CHAN1_DAT_INV */ | ||
2240 | #define WM8915_AIF2TX_CHAN1_SPACING_MASK 0x7E00 /* AIF2TX_CHAN1_SPACING - [14:9] */ | ||
2241 | #define WM8915_AIF2TX_CHAN1_SPACING_SHIFT 9 /* AIF2TX_CHAN1_SPACING - [14:9] */ | ||
2242 | #define WM8915_AIF2TX_CHAN1_SPACING_WIDTH 6 /* AIF2TX_CHAN1_SPACING - [14:9] */ | ||
2243 | #define WM8915_AIF2TX_CHAN1_SLOTS_MASK 0x01C0 /* AIF2TX_CHAN1_SLOTS - [8:6] */ | ||
2244 | #define WM8915_AIF2TX_CHAN1_SLOTS_SHIFT 6 /* AIF2TX_CHAN1_SLOTS - [8:6] */ | ||
2245 | #define WM8915_AIF2TX_CHAN1_SLOTS_WIDTH 3 /* AIF2TX_CHAN1_SLOTS - [8:6] */ | ||
2246 | #define WM8915_AIF2TX_CHAN1_START_SLOT_MASK 0x003F /* AIF2TX_CHAN1_START_SLOT - [5:0] */ | ||
2247 | #define WM8915_AIF2TX_CHAN1_START_SLOT_SHIFT 0 /* AIF2TX_CHAN1_START_SLOT - [5:0] */ | ||
2248 | #define WM8915_AIF2TX_CHAN1_START_SLOT_WIDTH 6 /* AIF2TX_CHAN1_START_SLOT - [5:0] */ | ||
2249 | |||
2250 | /* | ||
2251 | * R811 (0x32B) - AIF2RX Channel 0 Configuration | ||
2252 | */ | ||
2253 | #define WM8915_AIF2RX_CHAN0_DAT_INV 0x8000 /* AIF2RX_CHAN0_DAT_INV */ | ||
2254 | #define WM8915_AIF2RX_CHAN0_DAT_INV_MASK 0x8000 /* AIF2RX_CHAN0_DAT_INV */ | ||
2255 | #define WM8915_AIF2RX_CHAN0_DAT_INV_SHIFT 15 /* AIF2RX_CHAN0_DAT_INV */ | ||
2256 | #define WM8915_AIF2RX_CHAN0_DAT_INV_WIDTH 1 /* AIF2RX_CHAN0_DAT_INV */ | ||
2257 | #define WM8915_AIF2RX_CHAN0_SPACING_MASK 0x7E00 /* AIF2RX_CHAN0_SPACING - [14:9] */ | ||
2258 | #define WM8915_AIF2RX_CHAN0_SPACING_SHIFT 9 /* AIF2RX_CHAN0_SPACING - [14:9] */ | ||
2259 | #define WM8915_AIF2RX_CHAN0_SPACING_WIDTH 6 /* AIF2RX_CHAN0_SPACING - [14:9] */ | ||
2260 | #define WM8915_AIF2RX_CHAN0_SLOTS_MASK 0x01C0 /* AIF2RX_CHAN0_SLOTS - [8:6] */ | ||
2261 | #define WM8915_AIF2RX_CHAN0_SLOTS_SHIFT 6 /* AIF2RX_CHAN0_SLOTS - [8:6] */ | ||
2262 | #define WM8915_AIF2RX_CHAN0_SLOTS_WIDTH 3 /* AIF2RX_CHAN0_SLOTS - [8:6] */ | ||
2263 | #define WM8915_AIF2RX_CHAN0_START_SLOT_MASK 0x003F /* AIF2RX_CHAN0_START_SLOT - [5:0] */ | ||
2264 | #define WM8915_AIF2RX_CHAN0_START_SLOT_SHIFT 0 /* AIF2RX_CHAN0_START_SLOT - [5:0] */ | ||
2265 | #define WM8915_AIF2RX_CHAN0_START_SLOT_WIDTH 6 /* AIF2RX_CHAN0_START_SLOT - [5:0] */ | ||
2266 | |||
2267 | /* | ||
2268 | * R812 (0x32C) - AIF2RX Channel 1 Configuration | ||
2269 | */ | ||
2270 | #define WM8915_AIF2RX_CHAN1_DAT_INV 0x8000 /* AIF2RX_CHAN1_DAT_INV */ | ||
2271 | #define WM8915_AIF2RX_CHAN1_DAT_INV_MASK 0x8000 /* AIF2RX_CHAN1_DAT_INV */ | ||
2272 | #define WM8915_AIF2RX_CHAN1_DAT_INV_SHIFT 15 /* AIF2RX_CHAN1_DAT_INV */ | ||
2273 | #define WM8915_AIF2RX_CHAN1_DAT_INV_WIDTH 1 /* AIF2RX_CHAN1_DAT_INV */ | ||
2274 | #define WM8915_AIF2RX_CHAN1_SPACING_MASK 0x7E00 /* AIF2RX_CHAN1_SPACING - [14:9] */ | ||
2275 | #define WM8915_AIF2RX_CHAN1_SPACING_SHIFT 9 /* AIF2RX_CHAN1_SPACING - [14:9] */ | ||
2276 | #define WM8915_AIF2RX_CHAN1_SPACING_WIDTH 6 /* AIF2RX_CHAN1_SPACING - [14:9] */ | ||
2277 | #define WM8915_AIF2RX_CHAN1_SLOTS_MASK 0x01C0 /* AIF2RX_CHAN1_SLOTS - [8:6] */ | ||
2278 | #define WM8915_AIF2RX_CHAN1_SLOTS_SHIFT 6 /* AIF2RX_CHAN1_SLOTS - [8:6] */ | ||
2279 | #define WM8915_AIF2RX_CHAN1_SLOTS_WIDTH 3 /* AIF2RX_CHAN1_SLOTS - [8:6] */ | ||
2280 | #define WM8915_AIF2RX_CHAN1_START_SLOT_MASK 0x003F /* AIF2RX_CHAN1_START_SLOT - [5:0] */ | ||
2281 | #define WM8915_AIF2RX_CHAN1_START_SLOT_SHIFT 0 /* AIF2RX_CHAN1_START_SLOT - [5:0] */ | ||
2282 | #define WM8915_AIF2RX_CHAN1_START_SLOT_WIDTH 6 /* AIF2RX_CHAN1_START_SLOT - [5:0] */ | ||
2283 | |||
2284 | /* | ||
2285 | * R813 (0x32D) - AIF2RX Mono Configuration | ||
2286 | */ | ||
2287 | #define WM8915_AIF2RX_CHAN0_MONO_MODE 0x0001 /* AIF2RX_CHAN0_MONO_MODE */ | ||
2288 | #define WM8915_AIF2RX_CHAN0_MONO_MODE_MASK 0x0001 /* AIF2RX_CHAN0_MONO_MODE */ | ||
2289 | #define WM8915_AIF2RX_CHAN0_MONO_MODE_SHIFT 0 /* AIF2RX_CHAN0_MONO_MODE */ | ||
2290 | #define WM8915_AIF2RX_CHAN0_MONO_MODE_WIDTH 1 /* AIF2RX_CHAN0_MONO_MODE */ | ||
2291 | |||
2292 | /* | ||
2293 | * R815 (0x32F) - AIF2TX Test | ||
2294 | */ | ||
2295 | #define WM8915_AIF2TX_DITHER_ENA 0x0001 /* AIF2TX_DITHER_ENA */ | ||
2296 | #define WM8915_AIF2TX_DITHER_ENA_MASK 0x0001 /* AIF2TX_DITHER_ENA */ | ||
2297 | #define WM8915_AIF2TX_DITHER_ENA_SHIFT 0 /* AIF2TX_DITHER_ENA */ | ||
2298 | #define WM8915_AIF2TX_DITHER_ENA_WIDTH 1 /* AIF2TX_DITHER_ENA */ | ||
2299 | |||
2300 | /* | ||
2301 | * R1024 (0x400) - DSP1 TX Left Volume | ||
2302 | */ | ||
2303 | #define WM8915_DSP1TX_VU 0x0100 /* DSP1TX_VU */ | ||
2304 | #define WM8915_DSP1TX_VU_MASK 0x0100 /* DSP1TX_VU */ | ||
2305 | #define WM8915_DSP1TX_VU_SHIFT 8 /* DSP1TX_VU */ | ||
2306 | #define WM8915_DSP1TX_VU_WIDTH 1 /* DSP1TX_VU */ | ||
2307 | #define WM8915_DSP1TXL_VOL_MASK 0x00FF /* DSP1TXL_VOL - [7:0] */ | ||
2308 | #define WM8915_DSP1TXL_VOL_SHIFT 0 /* DSP1TXL_VOL - [7:0] */ | ||
2309 | #define WM8915_DSP1TXL_VOL_WIDTH 8 /* DSP1TXL_VOL - [7:0] */ | ||
2310 | |||
2311 | /* | ||
2312 | * R1025 (0x401) - DSP1 TX Right Volume | ||
2313 | */ | ||
2314 | #define WM8915_DSP1TX_VU 0x0100 /* DSP1TX_VU */ | ||
2315 | #define WM8915_DSP1TX_VU_MASK 0x0100 /* DSP1TX_VU */ | ||
2316 | #define WM8915_DSP1TX_VU_SHIFT 8 /* DSP1TX_VU */ | ||
2317 | #define WM8915_DSP1TX_VU_WIDTH 1 /* DSP1TX_VU */ | ||
2318 | #define WM8915_DSP1TXR_VOL_MASK 0x00FF /* DSP1TXR_VOL - [7:0] */ | ||
2319 | #define WM8915_DSP1TXR_VOL_SHIFT 0 /* DSP1TXR_VOL - [7:0] */ | ||
2320 | #define WM8915_DSP1TXR_VOL_WIDTH 8 /* DSP1TXR_VOL - [7:0] */ | ||
2321 | |||
2322 | /* | ||
2323 | * R1026 (0x402) - DSP1 RX Left Volume | ||
2324 | */ | ||
2325 | #define WM8915_DSP1RX_VU 0x0100 /* DSP1RX_VU */ | ||
2326 | #define WM8915_DSP1RX_VU_MASK 0x0100 /* DSP1RX_VU */ | ||
2327 | #define WM8915_DSP1RX_VU_SHIFT 8 /* DSP1RX_VU */ | ||
2328 | #define WM8915_DSP1RX_VU_WIDTH 1 /* DSP1RX_VU */ | ||
2329 | #define WM8915_DSP1RXL_VOL_MASK 0x00FF /* DSP1RXL_VOL - [7:0] */ | ||
2330 | #define WM8915_DSP1RXL_VOL_SHIFT 0 /* DSP1RXL_VOL - [7:0] */ | ||
2331 | #define WM8915_DSP1RXL_VOL_WIDTH 8 /* DSP1RXL_VOL - [7:0] */ | ||
2332 | |||
2333 | /* | ||
2334 | * R1027 (0x403) - DSP1 RX Right Volume | ||
2335 | */ | ||
2336 | #define WM8915_DSP1RX_VU 0x0100 /* DSP1RX_VU */ | ||
2337 | #define WM8915_DSP1RX_VU_MASK 0x0100 /* DSP1RX_VU */ | ||
2338 | #define WM8915_DSP1RX_VU_SHIFT 8 /* DSP1RX_VU */ | ||
2339 | #define WM8915_DSP1RX_VU_WIDTH 1 /* DSP1RX_VU */ | ||
2340 | #define WM8915_DSP1RXR_VOL_MASK 0x00FF /* DSP1RXR_VOL - [7:0] */ | ||
2341 | #define WM8915_DSP1RXR_VOL_SHIFT 0 /* DSP1RXR_VOL - [7:0] */ | ||
2342 | #define WM8915_DSP1RXR_VOL_WIDTH 8 /* DSP1RXR_VOL - [7:0] */ | ||
2343 | |||
2344 | /* | ||
2345 | * R1040 (0x410) - DSP1 TX Filters | ||
2346 | */ | ||
2347 | #define WM8915_DSP1TX_NF 0x2000 /* DSP1TX_NF */ | ||
2348 | #define WM8915_DSP1TX_NF_MASK 0x2000 /* DSP1TX_NF */ | ||
2349 | #define WM8915_DSP1TX_NF_SHIFT 13 /* DSP1TX_NF */ | ||
2350 | #define WM8915_DSP1TX_NF_WIDTH 1 /* DSP1TX_NF */ | ||
2351 | #define WM8915_DSP1TXL_HPF 0x1000 /* DSP1TXL_HPF */ | ||
2352 | #define WM8915_DSP1TXL_HPF_MASK 0x1000 /* DSP1TXL_HPF */ | ||
2353 | #define WM8915_DSP1TXL_HPF_SHIFT 12 /* DSP1TXL_HPF */ | ||
2354 | #define WM8915_DSP1TXL_HPF_WIDTH 1 /* DSP1TXL_HPF */ | ||
2355 | #define WM8915_DSP1TXR_HPF 0x0800 /* DSP1TXR_HPF */ | ||
2356 | #define WM8915_DSP1TXR_HPF_MASK 0x0800 /* DSP1TXR_HPF */ | ||
2357 | #define WM8915_DSP1TXR_HPF_SHIFT 11 /* DSP1TXR_HPF */ | ||
2358 | #define WM8915_DSP1TXR_HPF_WIDTH 1 /* DSP1TXR_HPF */ | ||
2359 | #define WM8915_DSP1TX_HPF_MODE_MASK 0x0018 /* DSP1TX_HPF_MODE - [4:3] */ | ||
2360 | #define WM8915_DSP1TX_HPF_MODE_SHIFT 3 /* DSP1TX_HPF_MODE - [4:3] */ | ||
2361 | #define WM8915_DSP1TX_HPF_MODE_WIDTH 2 /* DSP1TX_HPF_MODE - [4:3] */ | ||
2362 | #define WM8915_DSP1TX_HPF_CUT_MASK 0x0007 /* DSP1TX_HPF_CUT - [2:0] */ | ||
2363 | #define WM8915_DSP1TX_HPF_CUT_SHIFT 0 /* DSP1TX_HPF_CUT - [2:0] */ | ||
2364 | #define WM8915_DSP1TX_HPF_CUT_WIDTH 3 /* DSP1TX_HPF_CUT - [2:0] */ | ||
2365 | |||
2366 | /* | ||
2367 | * R1056 (0x420) - DSP1 RX Filters (1) | ||
2368 | */ | ||
2369 | #define WM8915_DSP1RX_MUTE 0x0200 /* DSP1RX_MUTE */ | ||
2370 | #define WM8915_DSP1RX_MUTE_MASK 0x0200 /* DSP1RX_MUTE */ | ||
2371 | #define WM8915_DSP1RX_MUTE_SHIFT 9 /* DSP1RX_MUTE */ | ||
2372 | #define WM8915_DSP1RX_MUTE_WIDTH 1 /* DSP1RX_MUTE */ | ||
2373 | #define WM8915_DSP1RX_MONO 0x0080 /* DSP1RX_MONO */ | ||
2374 | #define WM8915_DSP1RX_MONO_MASK 0x0080 /* DSP1RX_MONO */ | ||
2375 | #define WM8915_DSP1RX_MONO_SHIFT 7 /* DSP1RX_MONO */ | ||
2376 | #define WM8915_DSP1RX_MONO_WIDTH 1 /* DSP1RX_MONO */ | ||
2377 | #define WM8915_DSP1RX_MUTERATE 0x0020 /* DSP1RX_MUTERATE */ | ||
2378 | #define WM8915_DSP1RX_MUTERATE_MASK 0x0020 /* DSP1RX_MUTERATE */ | ||
2379 | #define WM8915_DSP1RX_MUTERATE_SHIFT 5 /* DSP1RX_MUTERATE */ | ||
2380 | #define WM8915_DSP1RX_MUTERATE_WIDTH 1 /* DSP1RX_MUTERATE */ | ||
2381 | #define WM8915_DSP1RX_UNMUTE_RAMP 0x0010 /* DSP1RX_UNMUTE_RAMP */ | ||
2382 | #define WM8915_DSP1RX_UNMUTE_RAMP_MASK 0x0010 /* DSP1RX_UNMUTE_RAMP */ | ||
2383 | #define WM8915_DSP1RX_UNMUTE_RAMP_SHIFT 4 /* DSP1RX_UNMUTE_RAMP */ | ||
2384 | #define WM8915_DSP1RX_UNMUTE_RAMP_WIDTH 1 /* DSP1RX_UNMUTE_RAMP */ | ||
2385 | |||
2386 | /* | ||
2387 | * R1057 (0x421) - DSP1 RX Filters (2) | ||
2388 | */ | ||
2389 | #define WM8915_DSP1RX_3D_GAIN_MASK 0x3E00 /* DSP1RX_3D_GAIN - [13:9] */ | ||
2390 | #define WM8915_DSP1RX_3D_GAIN_SHIFT 9 /* DSP1RX_3D_GAIN - [13:9] */ | ||
2391 | #define WM8915_DSP1RX_3D_GAIN_WIDTH 5 /* DSP1RX_3D_GAIN - [13:9] */ | ||
2392 | #define WM8915_DSP1RX_3D_ENA 0x0100 /* DSP1RX_3D_ENA */ | ||
2393 | #define WM8915_DSP1RX_3D_ENA_MASK 0x0100 /* DSP1RX_3D_ENA */ | ||
2394 | #define WM8915_DSP1RX_3D_ENA_SHIFT 8 /* DSP1RX_3D_ENA */ | ||
2395 | #define WM8915_DSP1RX_3D_ENA_WIDTH 1 /* DSP1RX_3D_ENA */ | ||
2396 | |||
2397 | /* | ||
2398 | * R1088 (0x440) - DSP1 DRC (1) | ||
2399 | */ | ||
2400 | #define WM8915_DSP1DRC_SIG_DET_RMS_MASK 0xF800 /* DSP1DRC_SIG_DET_RMS - [15:11] */ | ||
2401 | #define WM8915_DSP1DRC_SIG_DET_RMS_SHIFT 11 /* DSP1DRC_SIG_DET_RMS - [15:11] */ | ||
2402 | #define WM8915_DSP1DRC_SIG_DET_RMS_WIDTH 5 /* DSP1DRC_SIG_DET_RMS - [15:11] */ | ||
2403 | #define WM8915_DSP1DRC_SIG_DET_PK_MASK 0x0600 /* DSP1DRC_SIG_DET_PK - [10:9] */ | ||
2404 | #define WM8915_DSP1DRC_SIG_DET_PK_SHIFT 9 /* DSP1DRC_SIG_DET_PK - [10:9] */ | ||
2405 | #define WM8915_DSP1DRC_SIG_DET_PK_WIDTH 2 /* DSP1DRC_SIG_DET_PK - [10:9] */ | ||
2406 | #define WM8915_DSP1DRC_NG_ENA 0x0100 /* DSP1DRC_NG_ENA */ | ||
2407 | #define WM8915_DSP1DRC_NG_ENA_MASK 0x0100 /* DSP1DRC_NG_ENA */ | ||
2408 | #define WM8915_DSP1DRC_NG_ENA_SHIFT 8 /* DSP1DRC_NG_ENA */ | ||
2409 | #define WM8915_DSP1DRC_NG_ENA_WIDTH 1 /* DSP1DRC_NG_ENA */ | ||
2410 | #define WM8915_DSP1DRC_SIG_DET_MODE 0x0080 /* DSP1DRC_SIG_DET_MODE */ | ||
2411 | #define WM8915_DSP1DRC_SIG_DET_MODE_MASK 0x0080 /* DSP1DRC_SIG_DET_MODE */ | ||
2412 | #define WM8915_DSP1DRC_SIG_DET_MODE_SHIFT 7 /* DSP1DRC_SIG_DET_MODE */ | ||
2413 | #define WM8915_DSP1DRC_SIG_DET_MODE_WIDTH 1 /* DSP1DRC_SIG_DET_MODE */ | ||
2414 | #define WM8915_DSP1DRC_SIG_DET 0x0040 /* DSP1DRC_SIG_DET */ | ||
2415 | #define WM8915_DSP1DRC_SIG_DET_MASK 0x0040 /* DSP1DRC_SIG_DET */ | ||
2416 | #define WM8915_DSP1DRC_SIG_DET_SHIFT 6 /* DSP1DRC_SIG_DET */ | ||
2417 | #define WM8915_DSP1DRC_SIG_DET_WIDTH 1 /* DSP1DRC_SIG_DET */ | ||
2418 | #define WM8915_DSP1DRC_KNEE2_OP_ENA 0x0020 /* DSP1DRC_KNEE2_OP_ENA */ | ||
2419 | #define WM8915_DSP1DRC_KNEE2_OP_ENA_MASK 0x0020 /* DSP1DRC_KNEE2_OP_ENA */ | ||
2420 | #define WM8915_DSP1DRC_KNEE2_OP_ENA_SHIFT 5 /* DSP1DRC_KNEE2_OP_ENA */ | ||
2421 | #define WM8915_DSP1DRC_KNEE2_OP_ENA_WIDTH 1 /* DSP1DRC_KNEE2_OP_ENA */ | ||
2422 | #define WM8915_DSP1DRC_QR 0x0010 /* DSP1DRC_QR */ | ||
2423 | #define WM8915_DSP1DRC_QR_MASK 0x0010 /* DSP1DRC_QR */ | ||
2424 | #define WM8915_DSP1DRC_QR_SHIFT 4 /* DSP1DRC_QR */ | ||
2425 | #define WM8915_DSP1DRC_QR_WIDTH 1 /* DSP1DRC_QR */ | ||
2426 | #define WM8915_DSP1DRC_ANTICLIP 0x0008 /* DSP1DRC_ANTICLIP */ | ||
2427 | #define WM8915_DSP1DRC_ANTICLIP_MASK 0x0008 /* DSP1DRC_ANTICLIP */ | ||
2428 | #define WM8915_DSP1DRC_ANTICLIP_SHIFT 3 /* DSP1DRC_ANTICLIP */ | ||
2429 | #define WM8915_DSP1DRC_ANTICLIP_WIDTH 1 /* DSP1DRC_ANTICLIP */ | ||
2430 | #define WM8915_DSP1RX_DRC_ENA 0x0004 /* DSP1RX_DRC_ENA */ | ||
2431 | #define WM8915_DSP1RX_DRC_ENA_MASK 0x0004 /* DSP1RX_DRC_ENA */ | ||
2432 | #define WM8915_DSP1RX_DRC_ENA_SHIFT 2 /* DSP1RX_DRC_ENA */ | ||
2433 | #define WM8915_DSP1RX_DRC_ENA_WIDTH 1 /* DSP1RX_DRC_ENA */ | ||
2434 | #define WM8915_DSP1TXL_DRC_ENA 0x0002 /* DSP1TXL_DRC_ENA */ | ||
2435 | #define WM8915_DSP1TXL_DRC_ENA_MASK 0x0002 /* DSP1TXL_DRC_ENA */ | ||
2436 | #define WM8915_DSP1TXL_DRC_ENA_SHIFT 1 /* DSP1TXL_DRC_ENA */ | ||
2437 | #define WM8915_DSP1TXL_DRC_ENA_WIDTH 1 /* DSP1TXL_DRC_ENA */ | ||
2438 | #define WM8915_DSP1TXR_DRC_ENA 0x0001 /* DSP1TXR_DRC_ENA */ | ||
2439 | #define WM8915_DSP1TXR_DRC_ENA_MASK 0x0001 /* DSP1TXR_DRC_ENA */ | ||
2440 | #define WM8915_DSP1TXR_DRC_ENA_SHIFT 0 /* DSP1TXR_DRC_ENA */ | ||
2441 | #define WM8915_DSP1TXR_DRC_ENA_WIDTH 1 /* DSP1TXR_DRC_ENA */ | ||
2442 | |||
2443 | /* | ||
2444 | * R1089 (0x441) - DSP1 DRC (2) | ||
2445 | */ | ||
2446 | #define WM8915_DSP1DRC_ATK_MASK 0x1E00 /* DSP1DRC_ATK - [12:9] */ | ||
2447 | #define WM8915_DSP1DRC_ATK_SHIFT 9 /* DSP1DRC_ATK - [12:9] */ | ||
2448 | #define WM8915_DSP1DRC_ATK_WIDTH 4 /* DSP1DRC_ATK - [12:9] */ | ||
2449 | #define WM8915_DSP1DRC_DCY_MASK 0x01E0 /* DSP1DRC_DCY - [8:5] */ | ||
2450 | #define WM8915_DSP1DRC_DCY_SHIFT 5 /* DSP1DRC_DCY - [8:5] */ | ||
2451 | #define WM8915_DSP1DRC_DCY_WIDTH 4 /* DSP1DRC_DCY - [8:5] */ | ||
2452 | #define WM8915_DSP1DRC_MINGAIN_MASK 0x001C /* DSP1DRC_MINGAIN - [4:2] */ | ||
2453 | #define WM8915_DSP1DRC_MINGAIN_SHIFT 2 /* DSP1DRC_MINGAIN - [4:2] */ | ||
2454 | #define WM8915_DSP1DRC_MINGAIN_WIDTH 3 /* DSP1DRC_MINGAIN - [4:2] */ | ||
2455 | #define WM8915_DSP1DRC_MAXGAIN_MASK 0x0003 /* DSP1DRC_MAXGAIN - [1:0] */ | ||
2456 | #define WM8915_DSP1DRC_MAXGAIN_SHIFT 0 /* DSP1DRC_MAXGAIN - [1:0] */ | ||
2457 | #define WM8915_DSP1DRC_MAXGAIN_WIDTH 2 /* DSP1DRC_MAXGAIN - [1:0] */ | ||
2458 | |||
2459 | /* | ||
2460 | * R1090 (0x442) - DSP1 DRC (3) | ||
2461 | */ | ||
2462 | #define WM8915_DSP1DRC_NG_MINGAIN_MASK 0xF000 /* DSP1DRC_NG_MINGAIN - [15:12] */ | ||
2463 | #define WM8915_DSP1DRC_NG_MINGAIN_SHIFT 12 /* DSP1DRC_NG_MINGAIN - [15:12] */ | ||
2464 | #define WM8915_DSP1DRC_NG_MINGAIN_WIDTH 4 /* DSP1DRC_NG_MINGAIN - [15:12] */ | ||
2465 | #define WM8915_DSP1DRC_NG_EXP_MASK 0x0C00 /* DSP1DRC_NG_EXP - [11:10] */ | ||
2466 | #define WM8915_DSP1DRC_NG_EXP_SHIFT 10 /* DSP1DRC_NG_EXP - [11:10] */ | ||
2467 | #define WM8915_DSP1DRC_NG_EXP_WIDTH 2 /* DSP1DRC_NG_EXP - [11:10] */ | ||
2468 | #define WM8915_DSP1DRC_QR_THR_MASK 0x0300 /* DSP1DRC_QR_THR - [9:8] */ | ||
2469 | #define WM8915_DSP1DRC_QR_THR_SHIFT 8 /* DSP1DRC_QR_THR - [9:8] */ | ||
2470 | #define WM8915_DSP1DRC_QR_THR_WIDTH 2 /* DSP1DRC_QR_THR - [9:8] */ | ||
2471 | #define WM8915_DSP1DRC_QR_DCY_MASK 0x00C0 /* DSP1DRC_QR_DCY - [7:6] */ | ||
2472 | #define WM8915_DSP1DRC_QR_DCY_SHIFT 6 /* DSP1DRC_QR_DCY - [7:6] */ | ||
2473 | #define WM8915_DSP1DRC_QR_DCY_WIDTH 2 /* DSP1DRC_QR_DCY - [7:6] */ | ||
2474 | #define WM8915_DSP1DRC_HI_COMP_MASK 0x0038 /* DSP1DRC_HI_COMP - [5:3] */ | ||
2475 | #define WM8915_DSP1DRC_HI_COMP_SHIFT 3 /* DSP1DRC_HI_COMP - [5:3] */ | ||
2476 | #define WM8915_DSP1DRC_HI_COMP_WIDTH 3 /* DSP1DRC_HI_COMP - [5:3] */ | ||
2477 | #define WM8915_DSP1DRC_LO_COMP_MASK 0x0007 /* DSP1DRC_LO_COMP - [2:0] */ | ||
2478 | #define WM8915_DSP1DRC_LO_COMP_SHIFT 0 /* DSP1DRC_LO_COMP - [2:0] */ | ||
2479 | #define WM8915_DSP1DRC_LO_COMP_WIDTH 3 /* DSP1DRC_LO_COMP - [2:0] */ | ||
2480 | |||
2481 | /* | ||
2482 | * R1091 (0x443) - DSP1 DRC (4) | ||
2483 | */ | ||
2484 | #define WM8915_DSP1DRC_KNEE_IP_MASK 0x07E0 /* DSP1DRC_KNEE_IP - [10:5] */ | ||
2485 | #define WM8915_DSP1DRC_KNEE_IP_SHIFT 5 /* DSP1DRC_KNEE_IP - [10:5] */ | ||
2486 | #define WM8915_DSP1DRC_KNEE_IP_WIDTH 6 /* DSP1DRC_KNEE_IP - [10:5] */ | ||
2487 | #define WM8915_DSP1DRC_KNEE_OP_MASK 0x001F /* DSP1DRC_KNEE_OP - [4:0] */ | ||
2488 | #define WM8915_DSP1DRC_KNEE_OP_SHIFT 0 /* DSP1DRC_KNEE_OP - [4:0] */ | ||
2489 | #define WM8915_DSP1DRC_KNEE_OP_WIDTH 5 /* DSP1DRC_KNEE_OP - [4:0] */ | ||
2490 | |||
2491 | /* | ||
2492 | * R1092 (0x444) - DSP1 DRC (5) | ||
2493 | */ | ||
2494 | #define WM8915_DSP1DRC_KNEE2_IP_MASK 0x03E0 /* DSP1DRC_KNEE2_IP - [9:5] */ | ||
2495 | #define WM8915_DSP1DRC_KNEE2_IP_SHIFT 5 /* DSP1DRC_KNEE2_IP - [9:5] */ | ||
2496 | #define WM8915_DSP1DRC_KNEE2_IP_WIDTH 5 /* DSP1DRC_KNEE2_IP - [9:5] */ | ||
2497 | #define WM8915_DSP1DRC_KNEE2_OP_MASK 0x001F /* DSP1DRC_KNEE2_OP - [4:0] */ | ||
2498 | #define WM8915_DSP1DRC_KNEE2_OP_SHIFT 0 /* DSP1DRC_KNEE2_OP - [4:0] */ | ||
2499 | #define WM8915_DSP1DRC_KNEE2_OP_WIDTH 5 /* DSP1DRC_KNEE2_OP - [4:0] */ | ||
2500 | |||
2501 | /* | ||
2502 | * R1152 (0x480) - DSP1 RX EQ Gains (1) | ||
2503 | */ | ||
2504 | #define WM8915_DSP1RX_EQ_B1_GAIN_MASK 0xF800 /* DSP1RX_EQ_B1_GAIN - [15:11] */ | ||
2505 | #define WM8915_DSP1RX_EQ_B1_GAIN_SHIFT 11 /* DSP1RX_EQ_B1_GAIN - [15:11] */ | ||
2506 | #define WM8915_DSP1RX_EQ_B1_GAIN_WIDTH 5 /* DSP1RX_EQ_B1_GAIN - [15:11] */ | ||
2507 | #define WM8915_DSP1RX_EQ_B2_GAIN_MASK 0x07C0 /* DSP1RX_EQ_B2_GAIN - [10:6] */ | ||
2508 | #define WM8915_DSP1RX_EQ_B2_GAIN_SHIFT 6 /* DSP1RX_EQ_B2_GAIN - [10:6] */ | ||
2509 | #define WM8915_DSP1RX_EQ_B2_GAIN_WIDTH 5 /* DSP1RX_EQ_B2_GAIN - [10:6] */ | ||
2510 | #define WM8915_DSP1RX_EQ_B3_GAIN_MASK 0x003E /* DSP1RX_EQ_B3_GAIN - [5:1] */ | ||
2511 | #define WM8915_DSP1RX_EQ_B3_GAIN_SHIFT 1 /* DSP1RX_EQ_B3_GAIN - [5:1] */ | ||
2512 | #define WM8915_DSP1RX_EQ_B3_GAIN_WIDTH 5 /* DSP1RX_EQ_B3_GAIN - [5:1] */ | ||
2513 | #define WM8915_DSP1RX_EQ_ENA 0x0001 /* DSP1RX_EQ_ENA */ | ||
2514 | #define WM8915_DSP1RX_EQ_ENA_MASK 0x0001 /* DSP1RX_EQ_ENA */ | ||
2515 | #define WM8915_DSP1RX_EQ_ENA_SHIFT 0 /* DSP1RX_EQ_ENA */ | ||
2516 | #define WM8915_DSP1RX_EQ_ENA_WIDTH 1 /* DSP1RX_EQ_ENA */ | ||
2517 | |||
2518 | /* | ||
2519 | * R1153 (0x481) - DSP1 RX EQ Gains (2) | ||
2520 | */ | ||
2521 | #define WM8915_DSP1RX_EQ_B4_GAIN_MASK 0xF800 /* DSP1RX_EQ_B4_GAIN - [15:11] */ | ||
2522 | #define WM8915_DSP1RX_EQ_B4_GAIN_SHIFT 11 /* DSP1RX_EQ_B4_GAIN - [15:11] */ | ||
2523 | #define WM8915_DSP1RX_EQ_B4_GAIN_WIDTH 5 /* DSP1RX_EQ_B4_GAIN - [15:11] */ | ||
2524 | #define WM8915_DSP1RX_EQ_B5_GAIN_MASK 0x07C0 /* DSP1RX_EQ_B5_GAIN - [10:6] */ | ||
2525 | #define WM8915_DSP1RX_EQ_B5_GAIN_SHIFT 6 /* DSP1RX_EQ_B5_GAIN - [10:6] */ | ||
2526 | #define WM8915_DSP1RX_EQ_B5_GAIN_WIDTH 5 /* DSP1RX_EQ_B5_GAIN - [10:6] */ | ||
2527 | |||
2528 | /* | ||
2529 | * R1154 (0x482) - DSP1 RX EQ Band 1 A | ||
2530 | */ | ||
2531 | #define WM8915_DSP1RX_EQ_B1_A_MASK 0xFFFF /* DSP1RX_EQ_B1_A - [15:0] */ | ||
2532 | #define WM8915_DSP1RX_EQ_B1_A_SHIFT 0 /* DSP1RX_EQ_B1_A - [15:0] */ | ||
2533 | #define WM8915_DSP1RX_EQ_B1_A_WIDTH 16 /* DSP1RX_EQ_B1_A - [15:0] */ | ||
2534 | |||
2535 | /* | ||
2536 | * R1155 (0x483) - DSP1 RX EQ Band 1 B | ||
2537 | */ | ||
2538 | #define WM8915_DSP1RX_EQ_B1_B_MASK 0xFFFF /* DSP1RX_EQ_B1_B - [15:0] */ | ||
2539 | #define WM8915_DSP1RX_EQ_B1_B_SHIFT 0 /* DSP1RX_EQ_B1_B - [15:0] */ | ||
2540 | #define WM8915_DSP1RX_EQ_B1_B_WIDTH 16 /* DSP1RX_EQ_B1_B - [15:0] */ | ||
2541 | |||
2542 | /* | ||
2543 | * R1156 (0x484) - DSP1 RX EQ Band 1 PG | ||
2544 | */ | ||
2545 | #define WM8915_DSP1RX_EQ_B1_PG_MASK 0xFFFF /* DSP1RX_EQ_B1_PG - [15:0] */ | ||
2546 | #define WM8915_DSP1RX_EQ_B1_PG_SHIFT 0 /* DSP1RX_EQ_B1_PG - [15:0] */ | ||
2547 | #define WM8915_DSP1RX_EQ_B1_PG_WIDTH 16 /* DSP1RX_EQ_B1_PG - [15:0] */ | ||
2548 | |||
2549 | /* | ||
2550 | * R1157 (0x485) - DSP1 RX EQ Band 2 A | ||
2551 | */ | ||
2552 | #define WM8915_DSP1RX_EQ_B2_A_MASK 0xFFFF /* DSP1RX_EQ_B2_A - [15:0] */ | ||
2553 | #define WM8915_DSP1RX_EQ_B2_A_SHIFT 0 /* DSP1RX_EQ_B2_A - [15:0] */ | ||
2554 | #define WM8915_DSP1RX_EQ_B2_A_WIDTH 16 /* DSP1RX_EQ_B2_A - [15:0] */ | ||
2555 | |||
2556 | /* | ||
2557 | * R1158 (0x486) - DSP1 RX EQ Band 2 B | ||
2558 | */ | ||
2559 | #define WM8915_DSP1RX_EQ_B2_B_MASK 0xFFFF /* DSP1RX_EQ_B2_B - [15:0] */ | ||
2560 | #define WM8915_DSP1RX_EQ_B2_B_SHIFT 0 /* DSP1RX_EQ_B2_B - [15:0] */ | ||
2561 | #define WM8915_DSP1RX_EQ_B2_B_WIDTH 16 /* DSP1RX_EQ_B2_B - [15:0] */ | ||
2562 | |||
2563 | /* | ||
2564 | * R1159 (0x487) - DSP1 RX EQ Band 2 C | ||
2565 | */ | ||
2566 | #define WM8915_DSP1RX_EQ_B2_C_MASK 0xFFFF /* DSP1RX_EQ_B2_C - [15:0] */ | ||
2567 | #define WM8915_DSP1RX_EQ_B2_C_SHIFT 0 /* DSP1RX_EQ_B2_C - [15:0] */ | ||
2568 | #define WM8915_DSP1RX_EQ_B2_C_WIDTH 16 /* DSP1RX_EQ_B2_C - [15:0] */ | ||
2569 | |||
2570 | /* | ||
2571 | * R1160 (0x488) - DSP1 RX EQ Band 2 PG | ||
2572 | */ | ||
2573 | #define WM8915_DSP1RX_EQ_B2_PG_MASK 0xFFFF /* DSP1RX_EQ_B2_PG - [15:0] */ | ||
2574 | #define WM8915_DSP1RX_EQ_B2_PG_SHIFT 0 /* DSP1RX_EQ_B2_PG - [15:0] */ | ||
2575 | #define WM8915_DSP1RX_EQ_B2_PG_WIDTH 16 /* DSP1RX_EQ_B2_PG - [15:0] */ | ||
2576 | |||
2577 | /* | ||
2578 | * R1161 (0x489) - DSP1 RX EQ Band 3 A | ||
2579 | */ | ||
2580 | #define WM8915_DSP1RX_EQ_B3_A_MASK 0xFFFF /* DSP1RX_EQ_B3_A - [15:0] */ | ||
2581 | #define WM8915_DSP1RX_EQ_B3_A_SHIFT 0 /* DSP1RX_EQ_B3_A - [15:0] */ | ||
2582 | #define WM8915_DSP1RX_EQ_B3_A_WIDTH 16 /* DSP1RX_EQ_B3_A - [15:0] */ | ||
2583 | |||
2584 | /* | ||
2585 | * R1162 (0x48A) - DSP1 RX EQ Band 3 B | ||
2586 | */ | ||
2587 | #define WM8915_DSP1RX_EQ_B3_B_MASK 0xFFFF /* DSP1RX_EQ_B3_B - [15:0] */ | ||
2588 | #define WM8915_DSP1RX_EQ_B3_B_SHIFT 0 /* DSP1RX_EQ_B3_B - [15:0] */ | ||
2589 | #define WM8915_DSP1RX_EQ_B3_B_WIDTH 16 /* DSP1RX_EQ_B3_B - [15:0] */ | ||
2590 | |||
2591 | /* | ||
2592 | * R1163 (0x48B) - DSP1 RX EQ Band 3 C | ||
2593 | */ | ||
2594 | #define WM8915_DSP1RX_EQ_B3_C_MASK 0xFFFF /* DSP1RX_EQ_B3_C - [15:0] */ | ||
2595 | #define WM8915_DSP1RX_EQ_B3_C_SHIFT 0 /* DSP1RX_EQ_B3_C - [15:0] */ | ||
2596 | #define WM8915_DSP1RX_EQ_B3_C_WIDTH 16 /* DSP1RX_EQ_B3_C - [15:0] */ | ||
2597 | |||
2598 | /* | ||
2599 | * R1164 (0x48C) - DSP1 RX EQ Band 3 PG | ||
2600 | */ | ||
2601 | #define WM8915_DSP1RX_EQ_B3_PG_MASK 0xFFFF /* DSP1RX_EQ_B3_PG - [15:0] */ | ||
2602 | #define WM8915_DSP1RX_EQ_B3_PG_SHIFT 0 /* DSP1RX_EQ_B3_PG - [15:0] */ | ||
2603 | #define WM8915_DSP1RX_EQ_B3_PG_WIDTH 16 /* DSP1RX_EQ_B3_PG - [15:0] */ | ||
2604 | |||
2605 | /* | ||
2606 | * R1165 (0x48D) - DSP1 RX EQ Band 4 A | ||
2607 | */ | ||
2608 | #define WM8915_DSP1RX_EQ_B4_A_MASK 0xFFFF /* DSP1RX_EQ_B4_A - [15:0] */ | ||
2609 | #define WM8915_DSP1RX_EQ_B4_A_SHIFT 0 /* DSP1RX_EQ_B4_A - [15:0] */ | ||
2610 | #define WM8915_DSP1RX_EQ_B4_A_WIDTH 16 /* DSP1RX_EQ_B4_A - [15:0] */ | ||
2611 | |||
2612 | /* | ||
2613 | * R1166 (0x48E) - DSP1 RX EQ Band 4 B | ||
2614 | */ | ||
2615 | #define WM8915_DSP1RX_EQ_B4_B_MASK 0xFFFF /* DSP1RX_EQ_B4_B - [15:0] */ | ||
2616 | #define WM8915_DSP1RX_EQ_B4_B_SHIFT 0 /* DSP1RX_EQ_B4_B - [15:0] */ | ||
2617 | #define WM8915_DSP1RX_EQ_B4_B_WIDTH 16 /* DSP1RX_EQ_B4_B - [15:0] */ | ||
2618 | |||
2619 | /* | ||
2620 | * R1167 (0x48F) - DSP1 RX EQ Band 4 C | ||
2621 | */ | ||
2622 | #define WM8915_DSP1RX_EQ_B4_C_MASK 0xFFFF /* DSP1RX_EQ_B4_C - [15:0] */ | ||
2623 | #define WM8915_DSP1RX_EQ_B4_C_SHIFT 0 /* DSP1RX_EQ_B4_C - [15:0] */ | ||
2624 | #define WM8915_DSP1RX_EQ_B4_C_WIDTH 16 /* DSP1RX_EQ_B4_C - [15:0] */ | ||
2625 | |||
2626 | /* | ||
2627 | * R1168 (0x490) - DSP1 RX EQ Band 4 PG | ||
2628 | */ | ||
2629 | #define WM8915_DSP1RX_EQ_B4_PG_MASK 0xFFFF /* DSP1RX_EQ_B4_PG - [15:0] */ | ||
2630 | #define WM8915_DSP1RX_EQ_B4_PG_SHIFT 0 /* DSP1RX_EQ_B4_PG - [15:0] */ | ||
2631 | #define WM8915_DSP1RX_EQ_B4_PG_WIDTH 16 /* DSP1RX_EQ_B4_PG - [15:0] */ | ||
2632 | |||
2633 | /* | ||
2634 | * R1169 (0x491) - DSP1 RX EQ Band 5 A | ||
2635 | */ | ||
2636 | #define WM8915_DSP1RX_EQ_B5_A_MASK 0xFFFF /* DSP1RX_EQ_B5_A - [15:0] */ | ||
2637 | #define WM8915_DSP1RX_EQ_B5_A_SHIFT 0 /* DSP1RX_EQ_B5_A - [15:0] */ | ||
2638 | #define WM8915_DSP1RX_EQ_B5_A_WIDTH 16 /* DSP1RX_EQ_B5_A - [15:0] */ | ||
2639 | |||
2640 | /* | ||
2641 | * R1170 (0x492) - DSP1 RX EQ Band 5 B | ||
2642 | */ | ||
2643 | #define WM8915_DSP1RX_EQ_B5_B_MASK 0xFFFF /* DSP1RX_EQ_B5_B - [15:0] */ | ||
2644 | #define WM8915_DSP1RX_EQ_B5_B_SHIFT 0 /* DSP1RX_EQ_B5_B - [15:0] */ | ||
2645 | #define WM8915_DSP1RX_EQ_B5_B_WIDTH 16 /* DSP1RX_EQ_B5_B - [15:0] */ | ||
2646 | |||
2647 | /* | ||
2648 | * R1171 (0x493) - DSP1 RX EQ Band 5 PG | ||
2649 | */ | ||
2650 | #define WM8915_DSP1RX_EQ_B5_PG_MASK 0xFFFF /* DSP1RX_EQ_B5_PG - [15:0] */ | ||
2651 | #define WM8915_DSP1RX_EQ_B5_PG_SHIFT 0 /* DSP1RX_EQ_B5_PG - [15:0] */ | ||
2652 | #define WM8915_DSP1RX_EQ_B5_PG_WIDTH 16 /* DSP1RX_EQ_B5_PG - [15:0] */ | ||
2653 | |||
2654 | /* | ||
2655 | * R1280 (0x500) - DSP2 TX Left Volume | ||
2656 | */ | ||
2657 | #define WM8915_DSP2TX_VU 0x0100 /* DSP2TX_VU */ | ||
2658 | #define WM8915_DSP2TX_VU_MASK 0x0100 /* DSP2TX_VU */ | ||
2659 | #define WM8915_DSP2TX_VU_SHIFT 8 /* DSP2TX_VU */ | ||
2660 | #define WM8915_DSP2TX_VU_WIDTH 1 /* DSP2TX_VU */ | ||
2661 | #define WM8915_DSP2TXL_VOL_MASK 0x00FF /* DSP2TXL_VOL - [7:0] */ | ||
2662 | #define WM8915_DSP2TXL_VOL_SHIFT 0 /* DSP2TXL_VOL - [7:0] */ | ||
2663 | #define WM8915_DSP2TXL_VOL_WIDTH 8 /* DSP2TXL_VOL - [7:0] */ | ||
2664 | |||
2665 | /* | ||
2666 | * R1281 (0x501) - DSP2 TX Right Volume | ||
2667 | */ | ||
2668 | #define WM8915_DSP2TX_VU 0x0100 /* DSP2TX_VU */ | ||
2669 | #define WM8915_DSP2TX_VU_MASK 0x0100 /* DSP2TX_VU */ | ||
2670 | #define WM8915_DSP2TX_VU_SHIFT 8 /* DSP2TX_VU */ | ||
2671 | #define WM8915_DSP2TX_VU_WIDTH 1 /* DSP2TX_VU */ | ||
2672 | #define WM8915_DSP2TXR_VOL_MASK 0x00FF /* DSP2TXR_VOL - [7:0] */ | ||
2673 | #define WM8915_DSP2TXR_VOL_SHIFT 0 /* DSP2TXR_VOL - [7:0] */ | ||
2674 | #define WM8915_DSP2TXR_VOL_WIDTH 8 /* DSP2TXR_VOL - [7:0] */ | ||
2675 | |||
2676 | /* | ||
2677 | * R1282 (0x502) - DSP2 RX Left Volume | ||
2678 | */ | ||
2679 | #define WM8915_DSP2RX_VU 0x0100 /* DSP2RX_VU */ | ||
2680 | #define WM8915_DSP2RX_VU_MASK 0x0100 /* DSP2RX_VU */ | ||
2681 | #define WM8915_DSP2RX_VU_SHIFT 8 /* DSP2RX_VU */ | ||
2682 | #define WM8915_DSP2RX_VU_WIDTH 1 /* DSP2RX_VU */ | ||
2683 | #define WM8915_DSP2RXL_VOL_MASK 0x00FF /* DSP2RXL_VOL - [7:0] */ | ||
2684 | #define WM8915_DSP2RXL_VOL_SHIFT 0 /* DSP2RXL_VOL - [7:0] */ | ||
2685 | #define WM8915_DSP2RXL_VOL_WIDTH 8 /* DSP2RXL_VOL - [7:0] */ | ||
2686 | |||
2687 | /* | ||
2688 | * R1283 (0x503) - DSP2 RX Right Volume | ||
2689 | */ | ||
2690 | #define WM8915_DSP2RX_VU 0x0100 /* DSP2RX_VU */ | ||
2691 | #define WM8915_DSP2RX_VU_MASK 0x0100 /* DSP2RX_VU */ | ||
2692 | #define WM8915_DSP2RX_VU_SHIFT 8 /* DSP2RX_VU */ | ||
2693 | #define WM8915_DSP2RX_VU_WIDTH 1 /* DSP2RX_VU */ | ||
2694 | #define WM8915_DSP2RXR_VOL_MASK 0x00FF /* DSP2RXR_VOL - [7:0] */ | ||
2695 | #define WM8915_DSP2RXR_VOL_SHIFT 0 /* DSP2RXR_VOL - [7:0] */ | ||
2696 | #define WM8915_DSP2RXR_VOL_WIDTH 8 /* DSP2RXR_VOL - [7:0] */ | ||
2697 | |||
2698 | /* | ||
2699 | * R1296 (0x510) - DSP2 TX Filters | ||
2700 | */ | ||
2701 | #define WM8915_DSP2TX_NF 0x2000 /* DSP2TX_NF */ | ||
2702 | #define WM8915_DSP2TX_NF_MASK 0x2000 /* DSP2TX_NF */ | ||
2703 | #define WM8915_DSP2TX_NF_SHIFT 13 /* DSP2TX_NF */ | ||
2704 | #define WM8915_DSP2TX_NF_WIDTH 1 /* DSP2TX_NF */ | ||
2705 | #define WM8915_DSP2TXL_HPF 0x1000 /* DSP2TXL_HPF */ | ||
2706 | #define WM8915_DSP2TXL_HPF_MASK 0x1000 /* DSP2TXL_HPF */ | ||
2707 | #define WM8915_DSP2TXL_HPF_SHIFT 12 /* DSP2TXL_HPF */ | ||
2708 | #define WM8915_DSP2TXL_HPF_WIDTH 1 /* DSP2TXL_HPF */ | ||
2709 | #define WM8915_DSP2TXR_HPF 0x0800 /* DSP2TXR_HPF */ | ||
2710 | #define WM8915_DSP2TXR_HPF_MASK 0x0800 /* DSP2TXR_HPF */ | ||
2711 | #define WM8915_DSP2TXR_HPF_SHIFT 11 /* DSP2TXR_HPF */ | ||
2712 | #define WM8915_DSP2TXR_HPF_WIDTH 1 /* DSP2TXR_HPF */ | ||
2713 | #define WM8915_DSP2TX_HPF_MODE_MASK 0x0018 /* DSP2TX_HPF_MODE - [4:3] */ | ||
2714 | #define WM8915_DSP2TX_HPF_MODE_SHIFT 3 /* DSP2TX_HPF_MODE - [4:3] */ | ||
2715 | #define WM8915_DSP2TX_HPF_MODE_WIDTH 2 /* DSP2TX_HPF_MODE - [4:3] */ | ||
2716 | #define WM8915_DSP2TX_HPF_CUT_MASK 0x0007 /* DSP2TX_HPF_CUT - [2:0] */ | ||
2717 | #define WM8915_DSP2TX_HPF_CUT_SHIFT 0 /* DSP2TX_HPF_CUT - [2:0] */ | ||
2718 | #define WM8915_DSP2TX_HPF_CUT_WIDTH 3 /* DSP2TX_HPF_CUT - [2:0] */ | ||
2719 | |||
2720 | /* | ||
2721 | * R1312 (0x520) - DSP2 RX Filters (1) | ||
2722 | */ | ||
2723 | #define WM8915_DSP2RX_MUTE 0x0200 /* DSP2RX_MUTE */ | ||
2724 | #define WM8915_DSP2RX_MUTE_MASK 0x0200 /* DSP2RX_MUTE */ | ||
2725 | #define WM8915_DSP2RX_MUTE_SHIFT 9 /* DSP2RX_MUTE */ | ||
2726 | #define WM8915_DSP2RX_MUTE_WIDTH 1 /* DSP2RX_MUTE */ | ||
2727 | #define WM8915_DSP2RX_MONO 0x0080 /* DSP2RX_MONO */ | ||
2728 | #define WM8915_DSP2RX_MONO_MASK 0x0080 /* DSP2RX_MONO */ | ||
2729 | #define WM8915_DSP2RX_MONO_SHIFT 7 /* DSP2RX_MONO */ | ||
2730 | #define WM8915_DSP2RX_MONO_WIDTH 1 /* DSP2RX_MONO */ | ||
2731 | #define WM8915_DSP2RX_MUTERATE 0x0020 /* DSP2RX_MUTERATE */ | ||
2732 | #define WM8915_DSP2RX_MUTERATE_MASK 0x0020 /* DSP2RX_MUTERATE */ | ||
2733 | #define WM8915_DSP2RX_MUTERATE_SHIFT 5 /* DSP2RX_MUTERATE */ | ||
2734 | #define WM8915_DSP2RX_MUTERATE_WIDTH 1 /* DSP2RX_MUTERATE */ | ||
2735 | #define WM8915_DSP2RX_UNMUTE_RAMP 0x0010 /* DSP2RX_UNMUTE_RAMP */ | ||
2736 | #define WM8915_DSP2RX_UNMUTE_RAMP_MASK 0x0010 /* DSP2RX_UNMUTE_RAMP */ | ||
2737 | #define WM8915_DSP2RX_UNMUTE_RAMP_SHIFT 4 /* DSP2RX_UNMUTE_RAMP */ | ||
2738 | #define WM8915_DSP2RX_UNMUTE_RAMP_WIDTH 1 /* DSP2RX_UNMUTE_RAMP */ | ||
2739 | |||
2740 | /* | ||
2741 | * R1313 (0x521) - DSP2 RX Filters (2) | ||
2742 | */ | ||
2743 | #define WM8915_DSP2RX_3D_GAIN_MASK 0x3E00 /* DSP2RX_3D_GAIN - [13:9] */ | ||
2744 | #define WM8915_DSP2RX_3D_GAIN_SHIFT 9 /* DSP2RX_3D_GAIN - [13:9] */ | ||
2745 | #define WM8915_DSP2RX_3D_GAIN_WIDTH 5 /* DSP2RX_3D_GAIN - [13:9] */ | ||
2746 | #define WM8915_DSP2RX_3D_ENA 0x0100 /* DSP2RX_3D_ENA */ | ||
2747 | #define WM8915_DSP2RX_3D_ENA_MASK 0x0100 /* DSP2RX_3D_ENA */ | ||
2748 | #define WM8915_DSP2RX_3D_ENA_SHIFT 8 /* DSP2RX_3D_ENA */ | ||
2749 | #define WM8915_DSP2RX_3D_ENA_WIDTH 1 /* DSP2RX_3D_ENA */ | ||
2750 | |||
2751 | /* | ||
2752 | * R1344 (0x540) - DSP2 DRC (1) | ||
2753 | */ | ||
2754 | #define WM8915_DSP2DRC_SIG_DET_RMS_MASK 0xF800 /* DSP2DRC_SIG_DET_RMS - [15:11] */ | ||
2755 | #define WM8915_DSP2DRC_SIG_DET_RMS_SHIFT 11 /* DSP2DRC_SIG_DET_RMS - [15:11] */ | ||
2756 | #define WM8915_DSP2DRC_SIG_DET_RMS_WIDTH 5 /* DSP2DRC_SIG_DET_RMS - [15:11] */ | ||
2757 | #define WM8915_DSP2DRC_SIG_DET_PK_MASK 0x0600 /* DSP2DRC_SIG_DET_PK - [10:9] */ | ||
2758 | #define WM8915_DSP2DRC_SIG_DET_PK_SHIFT 9 /* DSP2DRC_SIG_DET_PK - [10:9] */ | ||
2759 | #define WM8915_DSP2DRC_SIG_DET_PK_WIDTH 2 /* DSP2DRC_SIG_DET_PK - [10:9] */ | ||
2760 | #define WM8915_DSP2DRC_NG_ENA 0x0100 /* DSP2DRC_NG_ENA */ | ||
2761 | #define WM8915_DSP2DRC_NG_ENA_MASK 0x0100 /* DSP2DRC_NG_ENA */ | ||
2762 | #define WM8915_DSP2DRC_NG_ENA_SHIFT 8 /* DSP2DRC_NG_ENA */ | ||
2763 | #define WM8915_DSP2DRC_NG_ENA_WIDTH 1 /* DSP2DRC_NG_ENA */ | ||
2764 | #define WM8915_DSP2DRC_SIG_DET_MODE 0x0080 /* DSP2DRC_SIG_DET_MODE */ | ||
2765 | #define WM8915_DSP2DRC_SIG_DET_MODE_MASK 0x0080 /* DSP2DRC_SIG_DET_MODE */ | ||
2766 | #define WM8915_DSP2DRC_SIG_DET_MODE_SHIFT 7 /* DSP2DRC_SIG_DET_MODE */ | ||
2767 | #define WM8915_DSP2DRC_SIG_DET_MODE_WIDTH 1 /* DSP2DRC_SIG_DET_MODE */ | ||
2768 | #define WM8915_DSP2DRC_SIG_DET 0x0040 /* DSP2DRC_SIG_DET */ | ||
2769 | #define WM8915_DSP2DRC_SIG_DET_MASK 0x0040 /* DSP2DRC_SIG_DET */ | ||
2770 | #define WM8915_DSP2DRC_SIG_DET_SHIFT 6 /* DSP2DRC_SIG_DET */ | ||
2771 | #define WM8915_DSP2DRC_SIG_DET_WIDTH 1 /* DSP2DRC_SIG_DET */ | ||
2772 | #define WM8915_DSP2DRC_KNEE2_OP_ENA 0x0020 /* DSP2DRC_KNEE2_OP_ENA */ | ||
2773 | #define WM8915_DSP2DRC_KNEE2_OP_ENA_MASK 0x0020 /* DSP2DRC_KNEE2_OP_ENA */ | ||
2774 | #define WM8915_DSP2DRC_KNEE2_OP_ENA_SHIFT 5 /* DSP2DRC_KNEE2_OP_ENA */ | ||
2775 | #define WM8915_DSP2DRC_KNEE2_OP_ENA_WIDTH 1 /* DSP2DRC_KNEE2_OP_ENA */ | ||
2776 | #define WM8915_DSP2DRC_QR 0x0010 /* DSP2DRC_QR */ | ||
2777 | #define WM8915_DSP2DRC_QR_MASK 0x0010 /* DSP2DRC_QR */ | ||
2778 | #define WM8915_DSP2DRC_QR_SHIFT 4 /* DSP2DRC_QR */ | ||
2779 | #define WM8915_DSP2DRC_QR_WIDTH 1 /* DSP2DRC_QR */ | ||
2780 | #define WM8915_DSP2DRC_ANTICLIP 0x0008 /* DSP2DRC_ANTICLIP */ | ||
2781 | #define WM8915_DSP2DRC_ANTICLIP_MASK 0x0008 /* DSP2DRC_ANTICLIP */ | ||
2782 | #define WM8915_DSP2DRC_ANTICLIP_SHIFT 3 /* DSP2DRC_ANTICLIP */ | ||
2783 | #define WM8915_DSP2DRC_ANTICLIP_WIDTH 1 /* DSP2DRC_ANTICLIP */ | ||
2784 | #define WM8915_DSP2RX_DRC_ENA 0x0004 /* DSP2RX_DRC_ENA */ | ||
2785 | #define WM8915_DSP2RX_DRC_ENA_MASK 0x0004 /* DSP2RX_DRC_ENA */ | ||
2786 | #define WM8915_DSP2RX_DRC_ENA_SHIFT 2 /* DSP2RX_DRC_ENA */ | ||
2787 | #define WM8915_DSP2RX_DRC_ENA_WIDTH 1 /* DSP2RX_DRC_ENA */ | ||
2788 | #define WM8915_DSP2TXL_DRC_ENA 0x0002 /* DSP2TXL_DRC_ENA */ | ||
2789 | #define WM8915_DSP2TXL_DRC_ENA_MASK 0x0002 /* DSP2TXL_DRC_ENA */ | ||
2790 | #define WM8915_DSP2TXL_DRC_ENA_SHIFT 1 /* DSP2TXL_DRC_ENA */ | ||
2791 | #define WM8915_DSP2TXL_DRC_ENA_WIDTH 1 /* DSP2TXL_DRC_ENA */ | ||
2792 | #define WM8915_DSP2TXR_DRC_ENA 0x0001 /* DSP2TXR_DRC_ENA */ | ||
2793 | #define WM8915_DSP2TXR_DRC_ENA_MASK 0x0001 /* DSP2TXR_DRC_ENA */ | ||
2794 | #define WM8915_DSP2TXR_DRC_ENA_SHIFT 0 /* DSP2TXR_DRC_ENA */ | ||
2795 | #define WM8915_DSP2TXR_DRC_ENA_WIDTH 1 /* DSP2TXR_DRC_ENA */ | ||
2796 | |||
2797 | /* | ||
2798 | * R1345 (0x541) - DSP2 DRC (2) | ||
2799 | */ | ||
2800 | #define WM8915_DSP2DRC_ATK_MASK 0x1E00 /* DSP2DRC_ATK - [12:9] */ | ||
2801 | #define WM8915_DSP2DRC_ATK_SHIFT 9 /* DSP2DRC_ATK - [12:9] */ | ||
2802 | #define WM8915_DSP2DRC_ATK_WIDTH 4 /* DSP2DRC_ATK - [12:9] */ | ||
2803 | #define WM8915_DSP2DRC_DCY_MASK 0x01E0 /* DSP2DRC_DCY - [8:5] */ | ||
2804 | #define WM8915_DSP2DRC_DCY_SHIFT 5 /* DSP2DRC_DCY - [8:5] */ | ||
2805 | #define WM8915_DSP2DRC_DCY_WIDTH 4 /* DSP2DRC_DCY - [8:5] */ | ||
2806 | #define WM8915_DSP2DRC_MINGAIN_MASK 0x001C /* DSP2DRC_MINGAIN - [4:2] */ | ||
2807 | #define WM8915_DSP2DRC_MINGAIN_SHIFT 2 /* DSP2DRC_MINGAIN - [4:2] */ | ||
2808 | #define WM8915_DSP2DRC_MINGAIN_WIDTH 3 /* DSP2DRC_MINGAIN - [4:2] */ | ||
2809 | #define WM8915_DSP2DRC_MAXGAIN_MASK 0x0003 /* DSP2DRC_MAXGAIN - [1:0] */ | ||
2810 | #define WM8915_DSP2DRC_MAXGAIN_SHIFT 0 /* DSP2DRC_MAXGAIN - [1:0] */ | ||
2811 | #define WM8915_DSP2DRC_MAXGAIN_WIDTH 2 /* DSP2DRC_MAXGAIN - [1:0] */ | ||
2812 | |||
2813 | /* | ||
2814 | * R1346 (0x542) - DSP2 DRC (3) | ||
2815 | */ | ||
2816 | #define WM8915_DSP2DRC_NG_MINGAIN_MASK 0xF000 /* DSP2DRC_NG_MINGAIN - [15:12] */ | ||
2817 | #define WM8915_DSP2DRC_NG_MINGAIN_SHIFT 12 /* DSP2DRC_NG_MINGAIN - [15:12] */ | ||
2818 | #define WM8915_DSP2DRC_NG_MINGAIN_WIDTH 4 /* DSP2DRC_NG_MINGAIN - [15:12] */ | ||
2819 | #define WM8915_DSP2DRC_NG_EXP_MASK 0x0C00 /* DSP2DRC_NG_EXP - [11:10] */ | ||
2820 | #define WM8915_DSP2DRC_NG_EXP_SHIFT 10 /* DSP2DRC_NG_EXP - [11:10] */ | ||
2821 | #define WM8915_DSP2DRC_NG_EXP_WIDTH 2 /* DSP2DRC_NG_EXP - [11:10] */ | ||
2822 | #define WM8915_DSP2DRC_QR_THR_MASK 0x0300 /* DSP2DRC_QR_THR - [9:8] */ | ||
2823 | #define WM8915_DSP2DRC_QR_THR_SHIFT 8 /* DSP2DRC_QR_THR - [9:8] */ | ||
2824 | #define WM8915_DSP2DRC_QR_THR_WIDTH 2 /* DSP2DRC_QR_THR - [9:8] */ | ||
2825 | #define WM8915_DSP2DRC_QR_DCY_MASK 0x00C0 /* DSP2DRC_QR_DCY - [7:6] */ | ||
2826 | #define WM8915_DSP2DRC_QR_DCY_SHIFT 6 /* DSP2DRC_QR_DCY - [7:6] */ | ||
2827 | #define WM8915_DSP2DRC_QR_DCY_WIDTH 2 /* DSP2DRC_QR_DCY - [7:6] */ | ||
2828 | #define WM8915_DSP2DRC_HI_COMP_MASK 0x0038 /* DSP2DRC_HI_COMP - [5:3] */ | ||
2829 | #define WM8915_DSP2DRC_HI_COMP_SHIFT 3 /* DSP2DRC_HI_COMP - [5:3] */ | ||
2830 | #define WM8915_DSP2DRC_HI_COMP_WIDTH 3 /* DSP2DRC_HI_COMP - [5:3] */ | ||
2831 | #define WM8915_DSP2DRC_LO_COMP_MASK 0x0007 /* DSP2DRC_LO_COMP - [2:0] */ | ||
2832 | #define WM8915_DSP2DRC_LO_COMP_SHIFT 0 /* DSP2DRC_LO_COMP - [2:0] */ | ||
2833 | #define WM8915_DSP2DRC_LO_COMP_WIDTH 3 /* DSP2DRC_LO_COMP - [2:0] */ | ||
2834 | |||
2835 | /* | ||
2836 | * R1347 (0x543) - DSP2 DRC (4) | ||
2837 | */ | ||
2838 | #define WM8915_DSP2DRC_KNEE_IP_MASK 0x07E0 /* DSP2DRC_KNEE_IP - [10:5] */ | ||
2839 | #define WM8915_DSP2DRC_KNEE_IP_SHIFT 5 /* DSP2DRC_KNEE_IP - [10:5] */ | ||
2840 | #define WM8915_DSP2DRC_KNEE_IP_WIDTH 6 /* DSP2DRC_KNEE_IP - [10:5] */ | ||
2841 | #define WM8915_DSP2DRC_KNEE_OP_MASK 0x001F /* DSP2DRC_KNEE_OP - [4:0] */ | ||
2842 | #define WM8915_DSP2DRC_KNEE_OP_SHIFT 0 /* DSP2DRC_KNEE_OP - [4:0] */ | ||
2843 | #define WM8915_DSP2DRC_KNEE_OP_WIDTH 5 /* DSP2DRC_KNEE_OP - [4:0] */ | ||
2844 | |||
2845 | /* | ||
2846 | * R1348 (0x544) - DSP2 DRC (5) | ||
2847 | */ | ||
2848 | #define WM8915_DSP2DRC_KNEE2_IP_MASK 0x03E0 /* DSP2DRC_KNEE2_IP - [9:5] */ | ||
2849 | #define WM8915_DSP2DRC_KNEE2_IP_SHIFT 5 /* DSP2DRC_KNEE2_IP - [9:5] */ | ||
2850 | #define WM8915_DSP2DRC_KNEE2_IP_WIDTH 5 /* DSP2DRC_KNEE2_IP - [9:5] */ | ||
2851 | #define WM8915_DSP2DRC_KNEE2_OP_MASK 0x001F /* DSP2DRC_KNEE2_OP - [4:0] */ | ||
2852 | #define WM8915_DSP2DRC_KNEE2_OP_SHIFT 0 /* DSP2DRC_KNEE2_OP - [4:0] */ | ||
2853 | #define WM8915_DSP2DRC_KNEE2_OP_WIDTH 5 /* DSP2DRC_KNEE2_OP - [4:0] */ | ||
2854 | |||
2855 | /* | ||
2856 | * R1408 (0x580) - DSP2 RX EQ Gains (1) | ||
2857 | */ | ||
2858 | #define WM8915_DSP2RX_EQ_B1_GAIN_MASK 0xF800 /* DSP2RX_EQ_B1_GAIN - [15:11] */ | ||
2859 | #define WM8915_DSP2RX_EQ_B1_GAIN_SHIFT 11 /* DSP2RX_EQ_B1_GAIN - [15:11] */ | ||
2860 | #define WM8915_DSP2RX_EQ_B1_GAIN_WIDTH 5 /* DSP2RX_EQ_B1_GAIN - [15:11] */ | ||
2861 | #define WM8915_DSP2RX_EQ_B2_GAIN_MASK 0x07C0 /* DSP2RX_EQ_B2_GAIN - [10:6] */ | ||
2862 | #define WM8915_DSP2RX_EQ_B2_GAIN_SHIFT 6 /* DSP2RX_EQ_B2_GAIN - [10:6] */ | ||
2863 | #define WM8915_DSP2RX_EQ_B2_GAIN_WIDTH 5 /* DSP2RX_EQ_B2_GAIN - [10:6] */ | ||
2864 | #define WM8915_DSP2RX_EQ_B3_GAIN_MASK 0x003E /* DSP2RX_EQ_B3_GAIN - [5:1] */ | ||
2865 | #define WM8915_DSP2RX_EQ_B3_GAIN_SHIFT 1 /* DSP2RX_EQ_B3_GAIN - [5:1] */ | ||
2866 | #define WM8915_DSP2RX_EQ_B3_GAIN_WIDTH 5 /* DSP2RX_EQ_B3_GAIN - [5:1] */ | ||
2867 | #define WM8915_DSP2RX_EQ_ENA 0x0001 /* DSP2RX_EQ_ENA */ | ||
2868 | #define WM8915_DSP2RX_EQ_ENA_MASK 0x0001 /* DSP2RX_EQ_ENA */ | ||
2869 | #define WM8915_DSP2RX_EQ_ENA_SHIFT 0 /* DSP2RX_EQ_ENA */ | ||
2870 | #define WM8915_DSP2RX_EQ_ENA_WIDTH 1 /* DSP2RX_EQ_ENA */ | ||
2871 | |||
2872 | /* | ||
2873 | * R1409 (0x581) - DSP2 RX EQ Gains (2) | ||
2874 | */ | ||
2875 | #define WM8915_DSP2RX_EQ_B4_GAIN_MASK 0xF800 /* DSP2RX_EQ_B4_GAIN - [15:11] */ | ||
2876 | #define WM8915_DSP2RX_EQ_B4_GAIN_SHIFT 11 /* DSP2RX_EQ_B4_GAIN - [15:11] */ | ||
2877 | #define WM8915_DSP2RX_EQ_B4_GAIN_WIDTH 5 /* DSP2RX_EQ_B4_GAIN - [15:11] */ | ||
2878 | #define WM8915_DSP2RX_EQ_B5_GAIN_MASK 0x07C0 /* DSP2RX_EQ_B5_GAIN - [10:6] */ | ||
2879 | #define WM8915_DSP2RX_EQ_B5_GAIN_SHIFT 6 /* DSP2RX_EQ_B5_GAIN - [10:6] */ | ||
2880 | #define WM8915_DSP2RX_EQ_B5_GAIN_WIDTH 5 /* DSP2RX_EQ_B5_GAIN - [10:6] */ | ||
2881 | |||
2882 | /* | ||
2883 | * R1410 (0x582) - DSP2 RX EQ Band 1 A | ||
2884 | */ | ||
2885 | #define WM8915_DSP2RX_EQ_B1_A_MASK 0xFFFF /* DSP2RX_EQ_B1_A - [15:0] */ | ||
2886 | #define WM8915_DSP2RX_EQ_B1_A_SHIFT 0 /* DSP2RX_EQ_B1_A - [15:0] */ | ||
2887 | #define WM8915_DSP2RX_EQ_B1_A_WIDTH 16 /* DSP2RX_EQ_B1_A - [15:0] */ | ||
2888 | |||
2889 | /* | ||
2890 | * R1411 (0x583) - DSP2 RX EQ Band 1 B | ||
2891 | */ | ||
2892 | #define WM8915_DSP2RX_EQ_B1_B_MASK 0xFFFF /* DSP2RX_EQ_B1_B - [15:0] */ | ||
2893 | #define WM8915_DSP2RX_EQ_B1_B_SHIFT 0 /* DSP2RX_EQ_B1_B - [15:0] */ | ||
2894 | #define WM8915_DSP2RX_EQ_B1_B_WIDTH 16 /* DSP2RX_EQ_B1_B - [15:0] */ | ||
2895 | |||
2896 | /* | ||
2897 | * R1412 (0x584) - DSP2 RX EQ Band 1 PG | ||
2898 | */ | ||
2899 | #define WM8915_DSP2RX_EQ_B1_PG_MASK 0xFFFF /* DSP2RX_EQ_B1_PG - [15:0] */ | ||
2900 | #define WM8915_DSP2RX_EQ_B1_PG_SHIFT 0 /* DSP2RX_EQ_B1_PG - [15:0] */ | ||
2901 | #define WM8915_DSP2RX_EQ_B1_PG_WIDTH 16 /* DSP2RX_EQ_B1_PG - [15:0] */ | ||
2902 | |||
2903 | /* | ||
2904 | * R1413 (0x585) - DSP2 RX EQ Band 2 A | ||
2905 | */ | ||
2906 | #define WM8915_DSP2RX_EQ_B2_A_MASK 0xFFFF /* DSP2RX_EQ_B2_A - [15:0] */ | ||
2907 | #define WM8915_DSP2RX_EQ_B2_A_SHIFT 0 /* DSP2RX_EQ_B2_A - [15:0] */ | ||
2908 | #define WM8915_DSP2RX_EQ_B2_A_WIDTH 16 /* DSP2RX_EQ_B2_A - [15:0] */ | ||
2909 | |||
2910 | /* | ||
2911 | * R1414 (0x586) - DSP2 RX EQ Band 2 B | ||
2912 | */ | ||
2913 | #define WM8915_DSP2RX_EQ_B2_B_MASK 0xFFFF /* DSP2RX_EQ_B2_B - [15:0] */ | ||
2914 | #define WM8915_DSP2RX_EQ_B2_B_SHIFT 0 /* DSP2RX_EQ_B2_B - [15:0] */ | ||
2915 | #define WM8915_DSP2RX_EQ_B2_B_WIDTH 16 /* DSP2RX_EQ_B2_B - [15:0] */ | ||
2916 | |||
2917 | /* | ||
2918 | * R1415 (0x587) - DSP2 RX EQ Band 2 C | ||
2919 | */ | ||
2920 | #define WM8915_DSP2RX_EQ_B2_C_MASK 0xFFFF /* DSP2RX_EQ_B2_C - [15:0] */ | ||
2921 | #define WM8915_DSP2RX_EQ_B2_C_SHIFT 0 /* DSP2RX_EQ_B2_C - [15:0] */ | ||
2922 | #define WM8915_DSP2RX_EQ_B2_C_WIDTH 16 /* DSP2RX_EQ_B2_C - [15:0] */ | ||
2923 | |||
2924 | /* | ||
2925 | * R1416 (0x588) - DSP2 RX EQ Band 2 PG | ||
2926 | */ | ||
2927 | #define WM8915_DSP2RX_EQ_B2_PG_MASK 0xFFFF /* DSP2RX_EQ_B2_PG - [15:0] */ | ||
2928 | #define WM8915_DSP2RX_EQ_B2_PG_SHIFT 0 /* DSP2RX_EQ_B2_PG - [15:0] */ | ||
2929 | #define WM8915_DSP2RX_EQ_B2_PG_WIDTH 16 /* DSP2RX_EQ_B2_PG - [15:0] */ | ||
2930 | |||
2931 | /* | ||
2932 | * R1417 (0x589) - DSP2 RX EQ Band 3 A | ||
2933 | */ | ||
2934 | #define WM8915_DSP2RX_EQ_B3_A_MASK 0xFFFF /* DSP2RX_EQ_B3_A - [15:0] */ | ||
2935 | #define WM8915_DSP2RX_EQ_B3_A_SHIFT 0 /* DSP2RX_EQ_B3_A - [15:0] */ | ||
2936 | #define WM8915_DSP2RX_EQ_B3_A_WIDTH 16 /* DSP2RX_EQ_B3_A - [15:0] */ | ||
2937 | |||
2938 | /* | ||
2939 | * R1418 (0x58A) - DSP2 RX EQ Band 3 B | ||
2940 | */ | ||
2941 | #define WM8915_DSP2RX_EQ_B3_B_MASK 0xFFFF /* DSP2RX_EQ_B3_B - [15:0] */ | ||
2942 | #define WM8915_DSP2RX_EQ_B3_B_SHIFT 0 /* DSP2RX_EQ_B3_B - [15:0] */ | ||
2943 | #define WM8915_DSP2RX_EQ_B3_B_WIDTH 16 /* DSP2RX_EQ_B3_B - [15:0] */ | ||
2944 | |||
2945 | /* | ||
2946 | * R1419 (0x58B) - DSP2 RX EQ Band 3 C | ||
2947 | */ | ||
2948 | #define WM8915_DSP2RX_EQ_B3_C_MASK 0xFFFF /* DSP2RX_EQ_B3_C - [15:0] */ | ||
2949 | #define WM8915_DSP2RX_EQ_B3_C_SHIFT 0 /* DSP2RX_EQ_B3_C - [15:0] */ | ||
2950 | #define WM8915_DSP2RX_EQ_B3_C_WIDTH 16 /* DSP2RX_EQ_B3_C - [15:0] */ | ||
2951 | |||
2952 | /* | ||
2953 | * R1420 (0x58C) - DSP2 RX EQ Band 3 PG | ||
2954 | */ | ||
2955 | #define WM8915_DSP2RX_EQ_B3_PG_MASK 0xFFFF /* DSP2RX_EQ_B3_PG - [15:0] */ | ||
2956 | #define WM8915_DSP2RX_EQ_B3_PG_SHIFT 0 /* DSP2RX_EQ_B3_PG - [15:0] */ | ||
2957 | #define WM8915_DSP2RX_EQ_B3_PG_WIDTH 16 /* DSP2RX_EQ_B3_PG - [15:0] */ | ||
2958 | |||
2959 | /* | ||
2960 | * R1421 (0x58D) - DSP2 RX EQ Band 4 A | ||
2961 | */ | ||
2962 | #define WM8915_DSP2RX_EQ_B4_A_MASK 0xFFFF /* DSP2RX_EQ_B4_A - [15:0] */ | ||
2963 | #define WM8915_DSP2RX_EQ_B4_A_SHIFT 0 /* DSP2RX_EQ_B4_A - [15:0] */ | ||
2964 | #define WM8915_DSP2RX_EQ_B4_A_WIDTH 16 /* DSP2RX_EQ_B4_A - [15:0] */ | ||
2965 | |||
2966 | /* | ||
2967 | * R1422 (0x58E) - DSP2 RX EQ Band 4 B | ||
2968 | */ | ||
2969 | #define WM8915_DSP2RX_EQ_B4_B_MASK 0xFFFF /* DSP2RX_EQ_B4_B - [15:0] */ | ||
2970 | #define WM8915_DSP2RX_EQ_B4_B_SHIFT 0 /* DSP2RX_EQ_B4_B - [15:0] */ | ||
2971 | #define WM8915_DSP2RX_EQ_B4_B_WIDTH 16 /* DSP2RX_EQ_B4_B - [15:0] */ | ||
2972 | |||
2973 | /* | ||
2974 | * R1423 (0x58F) - DSP2 RX EQ Band 4 C | ||
2975 | */ | ||
2976 | #define WM8915_DSP2RX_EQ_B4_C_MASK 0xFFFF /* DSP2RX_EQ_B4_C - [15:0] */ | ||
2977 | #define WM8915_DSP2RX_EQ_B4_C_SHIFT 0 /* DSP2RX_EQ_B4_C - [15:0] */ | ||
2978 | #define WM8915_DSP2RX_EQ_B4_C_WIDTH 16 /* DSP2RX_EQ_B4_C - [15:0] */ | ||
2979 | |||
2980 | /* | ||
2981 | * R1424 (0x590) - DSP2 RX EQ Band 4 PG | ||
2982 | */ | ||
2983 | #define WM8915_DSP2RX_EQ_B4_PG_MASK 0xFFFF /* DSP2RX_EQ_B4_PG - [15:0] */ | ||
2984 | #define WM8915_DSP2RX_EQ_B4_PG_SHIFT 0 /* DSP2RX_EQ_B4_PG - [15:0] */ | ||
2985 | #define WM8915_DSP2RX_EQ_B4_PG_WIDTH 16 /* DSP2RX_EQ_B4_PG - [15:0] */ | ||
2986 | |||
2987 | /* | ||
2988 | * R1425 (0x591) - DSP2 RX EQ Band 5 A | ||
2989 | */ | ||
2990 | #define WM8915_DSP2RX_EQ_B5_A_MASK 0xFFFF /* DSP2RX_EQ_B5_A - [15:0] */ | ||
2991 | #define WM8915_DSP2RX_EQ_B5_A_SHIFT 0 /* DSP2RX_EQ_B5_A - [15:0] */ | ||
2992 | #define WM8915_DSP2RX_EQ_B5_A_WIDTH 16 /* DSP2RX_EQ_B5_A - [15:0] */ | ||
2993 | |||
2994 | /* | ||
2995 | * R1426 (0x592) - DSP2 RX EQ Band 5 B | ||
2996 | */ | ||
2997 | #define WM8915_DSP2RX_EQ_B5_B_MASK 0xFFFF /* DSP2RX_EQ_B5_B - [15:0] */ | ||
2998 | #define WM8915_DSP2RX_EQ_B5_B_SHIFT 0 /* DSP2RX_EQ_B5_B - [15:0] */ | ||
2999 | #define WM8915_DSP2RX_EQ_B5_B_WIDTH 16 /* DSP2RX_EQ_B5_B - [15:0] */ | ||
3000 | |||
3001 | /* | ||
3002 | * R1427 (0x593) - DSP2 RX EQ Band 5 PG | ||
3003 | */ | ||
3004 | #define WM8915_DSP2RX_EQ_B5_PG_MASK 0xFFFF /* DSP2RX_EQ_B5_PG - [15:0] */ | ||
3005 | #define WM8915_DSP2RX_EQ_B5_PG_SHIFT 0 /* DSP2RX_EQ_B5_PG - [15:0] */ | ||
3006 | #define WM8915_DSP2RX_EQ_B5_PG_WIDTH 16 /* DSP2RX_EQ_B5_PG - [15:0] */ | ||
3007 | |||
3008 | /* | ||
3009 | * R1536 (0x600) - DAC1 Mixer Volumes | ||
3010 | */ | ||
3011 | #define WM8915_ADCR_DAC1_VOL_MASK 0x03E0 /* ADCR_DAC1_VOL - [9:5] */ | ||
3012 | #define WM8915_ADCR_DAC1_VOL_SHIFT 5 /* ADCR_DAC1_VOL - [9:5] */ | ||
3013 | #define WM8915_ADCR_DAC1_VOL_WIDTH 5 /* ADCR_DAC1_VOL - [9:5] */ | ||
3014 | #define WM8915_ADCL_DAC1_VOL_MASK 0x001F /* ADCL_DAC1_VOL - [4:0] */ | ||
3015 | #define WM8915_ADCL_DAC1_VOL_SHIFT 0 /* ADCL_DAC1_VOL - [4:0] */ | ||
3016 | #define WM8915_ADCL_DAC1_VOL_WIDTH 5 /* ADCL_DAC1_VOL - [4:0] */ | ||
3017 | |||
3018 | /* | ||
3019 | * R1537 (0x601) - DAC1 Left Mixer Routing | ||
3020 | */ | ||
3021 | #define WM8915_ADCR_TO_DAC1L 0x0020 /* ADCR_TO_DAC1L */ | ||
3022 | #define WM8915_ADCR_TO_DAC1L_MASK 0x0020 /* ADCR_TO_DAC1L */ | ||
3023 | #define WM8915_ADCR_TO_DAC1L_SHIFT 5 /* ADCR_TO_DAC1L */ | ||
3024 | #define WM8915_ADCR_TO_DAC1L_WIDTH 1 /* ADCR_TO_DAC1L */ | ||
3025 | #define WM8915_ADCL_TO_DAC1L 0x0010 /* ADCL_TO_DAC1L */ | ||
3026 | #define WM8915_ADCL_TO_DAC1L_MASK 0x0010 /* ADCL_TO_DAC1L */ | ||
3027 | #define WM8915_ADCL_TO_DAC1L_SHIFT 4 /* ADCL_TO_DAC1L */ | ||
3028 | #define WM8915_ADCL_TO_DAC1L_WIDTH 1 /* ADCL_TO_DAC1L */ | ||
3029 | #define WM8915_DSP2RXL_TO_DAC1L 0x0002 /* DSP2RXL_TO_DAC1L */ | ||
3030 | #define WM8915_DSP2RXL_TO_DAC1L_MASK 0x0002 /* DSP2RXL_TO_DAC1L */ | ||
3031 | #define WM8915_DSP2RXL_TO_DAC1L_SHIFT 1 /* DSP2RXL_TO_DAC1L */ | ||
3032 | #define WM8915_DSP2RXL_TO_DAC1L_WIDTH 1 /* DSP2RXL_TO_DAC1L */ | ||
3033 | #define WM8915_DSP1RXL_TO_DAC1L 0x0001 /* DSP1RXL_TO_DAC1L */ | ||
3034 | #define WM8915_DSP1RXL_TO_DAC1L_MASK 0x0001 /* DSP1RXL_TO_DAC1L */ | ||
3035 | #define WM8915_DSP1RXL_TO_DAC1L_SHIFT 0 /* DSP1RXL_TO_DAC1L */ | ||
3036 | #define WM8915_DSP1RXL_TO_DAC1L_WIDTH 1 /* DSP1RXL_TO_DAC1L */ | ||
3037 | |||
3038 | /* | ||
3039 | * R1538 (0x602) - DAC1 Right Mixer Routing | ||
3040 | */ | ||
3041 | #define WM8915_ADCR_TO_DAC1R 0x0020 /* ADCR_TO_DAC1R */ | ||
3042 | #define WM8915_ADCR_TO_DAC1R_MASK 0x0020 /* ADCR_TO_DAC1R */ | ||
3043 | #define WM8915_ADCR_TO_DAC1R_SHIFT 5 /* ADCR_TO_DAC1R */ | ||
3044 | #define WM8915_ADCR_TO_DAC1R_WIDTH 1 /* ADCR_TO_DAC1R */ | ||
3045 | #define WM8915_ADCL_TO_DAC1R 0x0010 /* ADCL_TO_DAC1R */ | ||
3046 | #define WM8915_ADCL_TO_DAC1R_MASK 0x0010 /* ADCL_TO_DAC1R */ | ||
3047 | #define WM8915_ADCL_TO_DAC1R_SHIFT 4 /* ADCL_TO_DAC1R */ | ||
3048 | #define WM8915_ADCL_TO_DAC1R_WIDTH 1 /* ADCL_TO_DAC1R */ | ||
3049 | #define WM8915_DSP2RXR_TO_DAC1R 0x0002 /* DSP2RXR_TO_DAC1R */ | ||
3050 | #define WM8915_DSP2RXR_TO_DAC1R_MASK 0x0002 /* DSP2RXR_TO_DAC1R */ | ||
3051 | #define WM8915_DSP2RXR_TO_DAC1R_SHIFT 1 /* DSP2RXR_TO_DAC1R */ | ||
3052 | #define WM8915_DSP2RXR_TO_DAC1R_WIDTH 1 /* DSP2RXR_TO_DAC1R */ | ||
3053 | #define WM8915_DSP1RXR_TO_DAC1R 0x0001 /* DSP1RXR_TO_DAC1R */ | ||
3054 | #define WM8915_DSP1RXR_TO_DAC1R_MASK 0x0001 /* DSP1RXR_TO_DAC1R */ | ||
3055 | #define WM8915_DSP1RXR_TO_DAC1R_SHIFT 0 /* DSP1RXR_TO_DAC1R */ | ||
3056 | #define WM8915_DSP1RXR_TO_DAC1R_WIDTH 1 /* DSP1RXR_TO_DAC1R */ | ||
3057 | |||
3058 | /* | ||
3059 | * R1539 (0x603) - DAC2 Mixer Volumes | ||
3060 | */ | ||
3061 | #define WM8915_ADCR_DAC2_VOL_MASK 0x03E0 /* ADCR_DAC2_VOL - [9:5] */ | ||
3062 | #define WM8915_ADCR_DAC2_VOL_SHIFT 5 /* ADCR_DAC2_VOL - [9:5] */ | ||
3063 | #define WM8915_ADCR_DAC2_VOL_WIDTH 5 /* ADCR_DAC2_VOL - [9:5] */ | ||
3064 | #define WM8915_ADCL_DAC2_VOL_MASK 0x001F /* ADCL_DAC2_VOL - [4:0] */ | ||
3065 | #define WM8915_ADCL_DAC2_VOL_SHIFT 0 /* ADCL_DAC2_VOL - [4:0] */ | ||
3066 | #define WM8915_ADCL_DAC2_VOL_WIDTH 5 /* ADCL_DAC2_VOL - [4:0] */ | ||
3067 | |||
3068 | /* | ||
3069 | * R1540 (0x604) - DAC2 Left Mixer Routing | ||
3070 | */ | ||
3071 | #define WM8915_ADCR_TO_DAC2L 0x0020 /* ADCR_TO_DAC2L */ | ||
3072 | #define WM8915_ADCR_TO_DAC2L_MASK 0x0020 /* ADCR_TO_DAC2L */ | ||
3073 | #define WM8915_ADCR_TO_DAC2L_SHIFT 5 /* ADCR_TO_DAC2L */ | ||
3074 | #define WM8915_ADCR_TO_DAC2L_WIDTH 1 /* ADCR_TO_DAC2L */ | ||
3075 | #define WM8915_ADCL_TO_DAC2L 0x0010 /* ADCL_TO_DAC2L */ | ||
3076 | #define WM8915_ADCL_TO_DAC2L_MASK 0x0010 /* ADCL_TO_DAC2L */ | ||
3077 | #define WM8915_ADCL_TO_DAC2L_SHIFT 4 /* ADCL_TO_DAC2L */ | ||
3078 | #define WM8915_ADCL_TO_DAC2L_WIDTH 1 /* ADCL_TO_DAC2L */ | ||
3079 | #define WM8915_DSP2RXL_TO_DAC2L 0x0002 /* DSP2RXL_TO_DAC2L */ | ||
3080 | #define WM8915_DSP2RXL_TO_DAC2L_MASK 0x0002 /* DSP2RXL_TO_DAC2L */ | ||
3081 | #define WM8915_DSP2RXL_TO_DAC2L_SHIFT 1 /* DSP2RXL_TO_DAC2L */ | ||
3082 | #define WM8915_DSP2RXL_TO_DAC2L_WIDTH 1 /* DSP2RXL_TO_DAC2L */ | ||
3083 | #define WM8915_DSP1RXL_TO_DAC2L 0x0001 /* DSP1RXL_TO_DAC2L */ | ||
3084 | #define WM8915_DSP1RXL_TO_DAC2L_MASK 0x0001 /* DSP1RXL_TO_DAC2L */ | ||
3085 | #define WM8915_DSP1RXL_TO_DAC2L_SHIFT 0 /* DSP1RXL_TO_DAC2L */ | ||
3086 | #define WM8915_DSP1RXL_TO_DAC2L_WIDTH 1 /* DSP1RXL_TO_DAC2L */ | ||
3087 | |||
3088 | /* | ||
3089 | * R1541 (0x605) - DAC2 Right Mixer Routing | ||
3090 | */ | ||
3091 | #define WM8915_ADCR_TO_DAC2R 0x0020 /* ADCR_TO_DAC2R */ | ||
3092 | #define WM8915_ADCR_TO_DAC2R_MASK 0x0020 /* ADCR_TO_DAC2R */ | ||
3093 | #define WM8915_ADCR_TO_DAC2R_SHIFT 5 /* ADCR_TO_DAC2R */ | ||
3094 | #define WM8915_ADCR_TO_DAC2R_WIDTH 1 /* ADCR_TO_DAC2R */ | ||
3095 | #define WM8915_ADCL_TO_DAC2R 0x0010 /* ADCL_TO_DAC2R */ | ||
3096 | #define WM8915_ADCL_TO_DAC2R_MASK 0x0010 /* ADCL_TO_DAC2R */ | ||
3097 | #define WM8915_ADCL_TO_DAC2R_SHIFT 4 /* ADCL_TO_DAC2R */ | ||
3098 | #define WM8915_ADCL_TO_DAC2R_WIDTH 1 /* ADCL_TO_DAC2R */ | ||
3099 | #define WM8915_DSP2RXR_TO_DAC2R 0x0002 /* DSP2RXR_TO_DAC2R */ | ||
3100 | #define WM8915_DSP2RXR_TO_DAC2R_MASK 0x0002 /* DSP2RXR_TO_DAC2R */ | ||
3101 | #define WM8915_DSP2RXR_TO_DAC2R_SHIFT 1 /* DSP2RXR_TO_DAC2R */ | ||
3102 | #define WM8915_DSP2RXR_TO_DAC2R_WIDTH 1 /* DSP2RXR_TO_DAC2R */ | ||
3103 | #define WM8915_DSP1RXR_TO_DAC2R 0x0001 /* DSP1RXR_TO_DAC2R */ | ||
3104 | #define WM8915_DSP1RXR_TO_DAC2R_MASK 0x0001 /* DSP1RXR_TO_DAC2R */ | ||
3105 | #define WM8915_DSP1RXR_TO_DAC2R_SHIFT 0 /* DSP1RXR_TO_DAC2R */ | ||
3106 | #define WM8915_DSP1RXR_TO_DAC2R_WIDTH 1 /* DSP1RXR_TO_DAC2R */ | ||
3107 | |||
3108 | /* | ||
3109 | * R1542 (0x606) - DSP1 TX Left Mixer Routing | ||
3110 | */ | ||
3111 | #define WM8915_ADC1L_TO_DSP1TXL 0x0002 /* ADC1L_TO_DSP1TXL */ | ||
3112 | #define WM8915_ADC1L_TO_DSP1TXL_MASK 0x0002 /* ADC1L_TO_DSP1TXL */ | ||
3113 | #define WM8915_ADC1L_TO_DSP1TXL_SHIFT 1 /* ADC1L_TO_DSP1TXL */ | ||
3114 | #define WM8915_ADC1L_TO_DSP1TXL_WIDTH 1 /* ADC1L_TO_DSP1TXL */ | ||
3115 | #define WM8915_DACL_TO_DSP1TXL 0x0001 /* DACL_TO_DSP1TXL */ | ||
3116 | #define WM8915_DACL_TO_DSP1TXL_MASK 0x0001 /* DACL_TO_DSP1TXL */ | ||
3117 | #define WM8915_DACL_TO_DSP1TXL_SHIFT 0 /* DACL_TO_DSP1TXL */ | ||
3118 | #define WM8915_DACL_TO_DSP1TXL_WIDTH 1 /* DACL_TO_DSP1TXL */ | ||
3119 | |||
3120 | /* | ||
3121 | * R1543 (0x607) - DSP1 TX Right Mixer Routing | ||
3122 | */ | ||
3123 | #define WM8915_ADC1R_TO_DSP1TXR 0x0002 /* ADC1R_TO_DSP1TXR */ | ||
3124 | #define WM8915_ADC1R_TO_DSP1TXR_MASK 0x0002 /* ADC1R_TO_DSP1TXR */ | ||
3125 | #define WM8915_ADC1R_TO_DSP1TXR_SHIFT 1 /* ADC1R_TO_DSP1TXR */ | ||
3126 | #define WM8915_ADC1R_TO_DSP1TXR_WIDTH 1 /* ADC1R_TO_DSP1TXR */ | ||
3127 | #define WM8915_DACR_TO_DSP1TXR 0x0001 /* DACR_TO_DSP1TXR */ | ||
3128 | #define WM8915_DACR_TO_DSP1TXR_MASK 0x0001 /* DACR_TO_DSP1TXR */ | ||
3129 | #define WM8915_DACR_TO_DSP1TXR_SHIFT 0 /* DACR_TO_DSP1TXR */ | ||
3130 | #define WM8915_DACR_TO_DSP1TXR_WIDTH 1 /* DACR_TO_DSP1TXR */ | ||
3131 | |||
3132 | /* | ||
3133 | * R1544 (0x608) - DSP2 TX Left Mixer Routing | ||
3134 | */ | ||
3135 | #define WM8915_ADC2L_TO_DSP2TXL 0x0002 /* ADC2L_TO_DSP2TXL */ | ||
3136 | #define WM8915_ADC2L_TO_DSP2TXL_MASK 0x0002 /* ADC2L_TO_DSP2TXL */ | ||
3137 | #define WM8915_ADC2L_TO_DSP2TXL_SHIFT 1 /* ADC2L_TO_DSP2TXL */ | ||
3138 | #define WM8915_ADC2L_TO_DSP2TXL_WIDTH 1 /* ADC2L_TO_DSP2TXL */ | ||
3139 | #define WM8915_DACL_TO_DSP2TXL 0x0001 /* DACL_TO_DSP2TXL */ | ||
3140 | #define WM8915_DACL_TO_DSP2TXL_MASK 0x0001 /* DACL_TO_DSP2TXL */ | ||
3141 | #define WM8915_DACL_TO_DSP2TXL_SHIFT 0 /* DACL_TO_DSP2TXL */ | ||
3142 | #define WM8915_DACL_TO_DSP2TXL_WIDTH 1 /* DACL_TO_DSP2TXL */ | ||
3143 | |||
3144 | /* | ||
3145 | * R1545 (0x609) - DSP2 TX Right Mixer Routing | ||
3146 | */ | ||
3147 | #define WM8915_ADC2R_TO_DSP2TXR 0x0002 /* ADC2R_TO_DSP2TXR */ | ||
3148 | #define WM8915_ADC2R_TO_DSP2TXR_MASK 0x0002 /* ADC2R_TO_DSP2TXR */ | ||
3149 | #define WM8915_ADC2R_TO_DSP2TXR_SHIFT 1 /* ADC2R_TO_DSP2TXR */ | ||
3150 | #define WM8915_ADC2R_TO_DSP2TXR_WIDTH 1 /* ADC2R_TO_DSP2TXR */ | ||
3151 | #define WM8915_DACR_TO_DSP2TXR 0x0001 /* DACR_TO_DSP2TXR */ | ||
3152 | #define WM8915_DACR_TO_DSP2TXR_MASK 0x0001 /* DACR_TO_DSP2TXR */ | ||
3153 | #define WM8915_DACR_TO_DSP2TXR_SHIFT 0 /* DACR_TO_DSP2TXR */ | ||
3154 | #define WM8915_DACR_TO_DSP2TXR_WIDTH 1 /* DACR_TO_DSP2TXR */ | ||
3155 | |||
3156 | /* | ||
3157 | * R1546 (0x60A) - DSP TX Mixer Select | ||
3158 | */ | ||
3159 | #define WM8915_DAC_TO_DSPTX_SRC 0x0001 /* DAC_TO_DSPTX_SRC */ | ||
3160 | #define WM8915_DAC_TO_DSPTX_SRC_MASK 0x0001 /* DAC_TO_DSPTX_SRC */ | ||
3161 | #define WM8915_DAC_TO_DSPTX_SRC_SHIFT 0 /* DAC_TO_DSPTX_SRC */ | ||
3162 | #define WM8915_DAC_TO_DSPTX_SRC_WIDTH 1 /* DAC_TO_DSPTX_SRC */ | ||
3163 | |||
3164 | /* | ||
3165 | * R1552 (0x610) - DAC Softmute | ||
3166 | */ | ||
3167 | #define WM8915_DAC_SOFTMUTEMODE 0x0002 /* DAC_SOFTMUTEMODE */ | ||
3168 | #define WM8915_DAC_SOFTMUTEMODE_MASK 0x0002 /* DAC_SOFTMUTEMODE */ | ||
3169 | #define WM8915_DAC_SOFTMUTEMODE_SHIFT 1 /* DAC_SOFTMUTEMODE */ | ||
3170 | #define WM8915_DAC_SOFTMUTEMODE_WIDTH 1 /* DAC_SOFTMUTEMODE */ | ||
3171 | #define WM8915_DAC_MUTERATE 0x0001 /* DAC_MUTERATE */ | ||
3172 | #define WM8915_DAC_MUTERATE_MASK 0x0001 /* DAC_MUTERATE */ | ||
3173 | #define WM8915_DAC_MUTERATE_SHIFT 0 /* DAC_MUTERATE */ | ||
3174 | #define WM8915_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ | ||
3175 | |||
3176 | /* | ||
3177 | * R1568 (0x620) - Oversampling | ||
3178 | */ | ||
3179 | #define WM8915_SPK_OSR128 0x0008 /* SPK_OSR128 */ | ||
3180 | #define WM8915_SPK_OSR128_MASK 0x0008 /* SPK_OSR128 */ | ||
3181 | #define WM8915_SPK_OSR128_SHIFT 3 /* SPK_OSR128 */ | ||
3182 | #define WM8915_SPK_OSR128_WIDTH 1 /* SPK_OSR128 */ | ||
3183 | #define WM8915_DMIC_OSR64 0x0004 /* DMIC_OSR64 */ | ||
3184 | #define WM8915_DMIC_OSR64_MASK 0x0004 /* DMIC_OSR64 */ | ||
3185 | #define WM8915_DMIC_OSR64_SHIFT 2 /* DMIC_OSR64 */ | ||
3186 | #define WM8915_DMIC_OSR64_WIDTH 1 /* DMIC_OSR64 */ | ||
3187 | #define WM8915_ADC_OSR128 0x0002 /* ADC_OSR128 */ | ||
3188 | #define WM8915_ADC_OSR128_MASK 0x0002 /* ADC_OSR128 */ | ||
3189 | #define WM8915_ADC_OSR128_SHIFT 1 /* ADC_OSR128 */ | ||
3190 | #define WM8915_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ | ||
3191 | #define WM8915_DAC_OSR128 0x0001 /* DAC_OSR128 */ | ||
3192 | #define WM8915_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ | ||
3193 | #define WM8915_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ | ||
3194 | #define WM8915_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ | ||
3195 | |||
3196 | /* | ||
3197 | * R1569 (0x621) - Sidetone | ||
3198 | */ | ||
3199 | #define WM8915_ST_LPF 0x1000 /* ST_LPF */ | ||
3200 | #define WM8915_ST_LPF_MASK 0x1000 /* ST_LPF */ | ||
3201 | #define WM8915_ST_LPF_SHIFT 12 /* ST_LPF */ | ||
3202 | #define WM8915_ST_LPF_WIDTH 1 /* ST_LPF */ | ||
3203 | #define WM8915_ST_HPF_CUT_MASK 0x0380 /* ST_HPF_CUT - [9:7] */ | ||
3204 | #define WM8915_ST_HPF_CUT_SHIFT 7 /* ST_HPF_CUT - [9:7] */ | ||
3205 | #define WM8915_ST_HPF_CUT_WIDTH 3 /* ST_HPF_CUT - [9:7] */ | ||
3206 | #define WM8915_ST_HPF 0x0040 /* ST_HPF */ | ||
3207 | #define WM8915_ST_HPF_MASK 0x0040 /* ST_HPF */ | ||
3208 | #define WM8915_ST_HPF_SHIFT 6 /* ST_HPF */ | ||
3209 | #define WM8915_ST_HPF_WIDTH 1 /* ST_HPF */ | ||
3210 | #define WM8915_STR_SEL 0x0002 /* STR_SEL */ | ||
3211 | #define WM8915_STR_SEL_MASK 0x0002 /* STR_SEL */ | ||
3212 | #define WM8915_STR_SEL_SHIFT 1 /* STR_SEL */ | ||
3213 | #define WM8915_STR_SEL_WIDTH 1 /* STR_SEL */ | ||
3214 | #define WM8915_STL_SEL 0x0001 /* STL_SEL */ | ||
3215 | #define WM8915_STL_SEL_MASK 0x0001 /* STL_SEL */ | ||
3216 | #define WM8915_STL_SEL_SHIFT 0 /* STL_SEL */ | ||
3217 | #define WM8915_STL_SEL_WIDTH 1 /* STL_SEL */ | ||
3218 | |||
3219 | /* | ||
3220 | * R1792 (0x700) - GPIO 1 | ||
3221 | */ | ||
3222 | #define WM8915_GP1_DIR 0x8000 /* GP1_DIR */ | ||
3223 | #define WM8915_GP1_DIR_MASK 0x8000 /* GP1_DIR */ | ||
3224 | #define WM8915_GP1_DIR_SHIFT 15 /* GP1_DIR */ | ||
3225 | #define WM8915_GP1_DIR_WIDTH 1 /* GP1_DIR */ | ||
3226 | #define WM8915_GP1_PU 0x4000 /* GP1_PU */ | ||
3227 | #define WM8915_GP1_PU_MASK 0x4000 /* GP1_PU */ | ||
3228 | #define WM8915_GP1_PU_SHIFT 14 /* GP1_PU */ | ||
3229 | #define WM8915_GP1_PU_WIDTH 1 /* GP1_PU */ | ||
3230 | #define WM8915_GP1_PD 0x2000 /* GP1_PD */ | ||
3231 | #define WM8915_GP1_PD_MASK 0x2000 /* GP1_PD */ | ||
3232 | #define WM8915_GP1_PD_SHIFT 13 /* GP1_PD */ | ||
3233 | #define WM8915_GP1_PD_WIDTH 1 /* GP1_PD */ | ||
3234 | #define WM8915_GP1_POL 0x0400 /* GP1_POL */ | ||
3235 | #define WM8915_GP1_POL_MASK 0x0400 /* GP1_POL */ | ||
3236 | #define WM8915_GP1_POL_SHIFT 10 /* GP1_POL */ | ||
3237 | #define WM8915_GP1_POL_WIDTH 1 /* GP1_POL */ | ||
3238 | #define WM8915_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ | ||
3239 | #define WM8915_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ | ||
3240 | #define WM8915_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ | ||
3241 | #define WM8915_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ | ||
3242 | #define WM8915_GP1_DB 0x0100 /* GP1_DB */ | ||
3243 | #define WM8915_GP1_DB_MASK 0x0100 /* GP1_DB */ | ||
3244 | #define WM8915_GP1_DB_SHIFT 8 /* GP1_DB */ | ||
3245 | #define WM8915_GP1_DB_WIDTH 1 /* GP1_DB */ | ||
3246 | #define WM8915_GP1_LVL 0x0040 /* GP1_LVL */ | ||
3247 | #define WM8915_GP1_LVL_MASK 0x0040 /* GP1_LVL */ | ||
3248 | #define WM8915_GP1_LVL_SHIFT 6 /* GP1_LVL */ | ||
3249 | #define WM8915_GP1_LVL_WIDTH 1 /* GP1_LVL */ | ||
3250 | #define WM8915_GP1_FN_MASK 0x000F /* GP1_FN - [3:0] */ | ||
3251 | #define WM8915_GP1_FN_SHIFT 0 /* GP1_FN - [3:0] */ | ||
3252 | #define WM8915_GP1_FN_WIDTH 4 /* GP1_FN - [3:0] */ | ||
3253 | |||
3254 | /* | ||
3255 | * R1793 (0x701) - GPIO 2 | ||
3256 | */ | ||
3257 | #define WM8915_GP2_DIR 0x8000 /* GP2_DIR */ | ||
3258 | #define WM8915_GP2_DIR_MASK 0x8000 /* GP2_DIR */ | ||
3259 | #define WM8915_GP2_DIR_SHIFT 15 /* GP2_DIR */ | ||
3260 | #define WM8915_GP2_DIR_WIDTH 1 /* GP2_DIR */ | ||
3261 | #define WM8915_GP2_PU 0x4000 /* GP2_PU */ | ||
3262 | #define WM8915_GP2_PU_MASK 0x4000 /* GP2_PU */ | ||
3263 | #define WM8915_GP2_PU_SHIFT 14 /* GP2_PU */ | ||
3264 | #define WM8915_GP2_PU_WIDTH 1 /* GP2_PU */ | ||
3265 | #define WM8915_GP2_PD 0x2000 /* GP2_PD */ | ||
3266 | #define WM8915_GP2_PD_MASK 0x2000 /* GP2_PD */ | ||
3267 | #define WM8915_GP2_PD_SHIFT 13 /* GP2_PD */ | ||
3268 | #define WM8915_GP2_PD_WIDTH 1 /* GP2_PD */ | ||
3269 | #define WM8915_GP2_POL 0x0400 /* GP2_POL */ | ||
3270 | #define WM8915_GP2_POL_MASK 0x0400 /* GP2_POL */ | ||
3271 | #define WM8915_GP2_POL_SHIFT 10 /* GP2_POL */ | ||
3272 | #define WM8915_GP2_POL_WIDTH 1 /* GP2_POL */ | ||
3273 | #define WM8915_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ | ||
3274 | #define WM8915_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ | ||
3275 | #define WM8915_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ | ||
3276 | #define WM8915_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ | ||
3277 | #define WM8915_GP2_DB 0x0100 /* GP2_DB */ | ||
3278 | #define WM8915_GP2_DB_MASK 0x0100 /* GP2_DB */ | ||
3279 | #define WM8915_GP2_DB_SHIFT 8 /* GP2_DB */ | ||
3280 | #define WM8915_GP2_DB_WIDTH 1 /* GP2_DB */ | ||
3281 | #define WM8915_GP2_LVL 0x0040 /* GP2_LVL */ | ||
3282 | #define WM8915_GP2_LVL_MASK 0x0040 /* GP2_LVL */ | ||
3283 | #define WM8915_GP2_LVL_SHIFT 6 /* GP2_LVL */ | ||
3284 | #define WM8915_GP2_LVL_WIDTH 1 /* GP2_LVL */ | ||
3285 | #define WM8915_GP2_FN_MASK 0x000F /* GP2_FN - [3:0] */ | ||
3286 | #define WM8915_GP2_FN_SHIFT 0 /* GP2_FN - [3:0] */ | ||
3287 | #define WM8915_GP2_FN_WIDTH 4 /* GP2_FN - [3:0] */ | ||
3288 | |||
3289 | /* | ||
3290 | * R1794 (0x702) - GPIO 3 | ||
3291 | */ | ||
3292 | #define WM8915_GP3_DIR 0x8000 /* GP3_DIR */ | ||
3293 | #define WM8915_GP3_DIR_MASK 0x8000 /* GP3_DIR */ | ||
3294 | #define WM8915_GP3_DIR_SHIFT 15 /* GP3_DIR */ | ||
3295 | #define WM8915_GP3_DIR_WIDTH 1 /* GP3_DIR */ | ||
3296 | #define WM8915_GP3_PU 0x4000 /* GP3_PU */ | ||
3297 | #define WM8915_GP3_PU_MASK 0x4000 /* GP3_PU */ | ||
3298 | #define WM8915_GP3_PU_SHIFT 14 /* GP3_PU */ | ||
3299 | #define WM8915_GP3_PU_WIDTH 1 /* GP3_PU */ | ||
3300 | #define WM8915_GP3_PD 0x2000 /* GP3_PD */ | ||
3301 | #define WM8915_GP3_PD_MASK 0x2000 /* GP3_PD */ | ||
3302 | #define WM8915_GP3_PD_SHIFT 13 /* GP3_PD */ | ||
3303 | #define WM8915_GP3_PD_WIDTH 1 /* GP3_PD */ | ||
3304 | #define WM8915_GP3_POL 0x0400 /* GP3_POL */ | ||
3305 | #define WM8915_GP3_POL_MASK 0x0400 /* GP3_POL */ | ||
3306 | #define WM8915_GP3_POL_SHIFT 10 /* GP3_POL */ | ||
3307 | #define WM8915_GP3_POL_WIDTH 1 /* GP3_POL */ | ||
3308 | #define WM8915_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ | ||
3309 | #define WM8915_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ | ||
3310 | #define WM8915_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ | ||
3311 | #define WM8915_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ | ||
3312 | #define WM8915_GP3_DB 0x0100 /* GP3_DB */ | ||
3313 | #define WM8915_GP3_DB_MASK 0x0100 /* GP3_DB */ | ||
3314 | #define WM8915_GP3_DB_SHIFT 8 /* GP3_DB */ | ||
3315 | #define WM8915_GP3_DB_WIDTH 1 /* GP3_DB */ | ||
3316 | #define WM8915_GP3_LVL 0x0040 /* GP3_LVL */ | ||
3317 | #define WM8915_GP3_LVL_MASK 0x0040 /* GP3_LVL */ | ||
3318 | #define WM8915_GP3_LVL_SHIFT 6 /* GP3_LVL */ | ||
3319 | #define WM8915_GP3_LVL_WIDTH 1 /* GP3_LVL */ | ||
3320 | #define WM8915_GP3_FN_MASK 0x000F /* GP3_FN - [3:0] */ | ||
3321 | #define WM8915_GP3_FN_SHIFT 0 /* GP3_FN - [3:0] */ | ||
3322 | #define WM8915_GP3_FN_WIDTH 4 /* GP3_FN - [3:0] */ | ||
3323 | |||
3324 | /* | ||
3325 | * R1795 (0x703) - GPIO 4 | ||
3326 | */ | ||
3327 | #define WM8915_GP4_DIR 0x8000 /* GP4_DIR */ | ||
3328 | #define WM8915_GP4_DIR_MASK 0x8000 /* GP4_DIR */ | ||
3329 | #define WM8915_GP4_DIR_SHIFT 15 /* GP4_DIR */ | ||
3330 | #define WM8915_GP4_DIR_WIDTH 1 /* GP4_DIR */ | ||
3331 | #define WM8915_GP4_PU 0x4000 /* GP4_PU */ | ||
3332 | #define WM8915_GP4_PU_MASK 0x4000 /* GP4_PU */ | ||
3333 | #define WM8915_GP4_PU_SHIFT 14 /* GP4_PU */ | ||
3334 | #define WM8915_GP4_PU_WIDTH 1 /* GP4_PU */ | ||
3335 | #define WM8915_GP4_PD 0x2000 /* GP4_PD */ | ||
3336 | #define WM8915_GP4_PD_MASK 0x2000 /* GP4_PD */ | ||
3337 | #define WM8915_GP4_PD_SHIFT 13 /* GP4_PD */ | ||
3338 | #define WM8915_GP4_PD_WIDTH 1 /* GP4_PD */ | ||
3339 | #define WM8915_GP4_POL 0x0400 /* GP4_POL */ | ||
3340 | #define WM8915_GP4_POL_MASK 0x0400 /* GP4_POL */ | ||
3341 | #define WM8915_GP4_POL_SHIFT 10 /* GP4_POL */ | ||
3342 | #define WM8915_GP4_POL_WIDTH 1 /* GP4_POL */ | ||
3343 | #define WM8915_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ | ||
3344 | #define WM8915_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ | ||
3345 | #define WM8915_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ | ||
3346 | #define WM8915_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ | ||
3347 | #define WM8915_GP4_DB 0x0100 /* GP4_DB */ | ||
3348 | #define WM8915_GP4_DB_MASK 0x0100 /* GP4_DB */ | ||
3349 | #define WM8915_GP4_DB_SHIFT 8 /* GP4_DB */ | ||
3350 | #define WM8915_GP4_DB_WIDTH 1 /* GP4_DB */ | ||
3351 | #define WM8915_GP4_LVL 0x0040 /* GP4_LVL */ | ||
3352 | #define WM8915_GP4_LVL_MASK 0x0040 /* GP4_LVL */ | ||
3353 | #define WM8915_GP4_LVL_SHIFT 6 /* GP4_LVL */ | ||
3354 | #define WM8915_GP4_LVL_WIDTH 1 /* GP4_LVL */ | ||
3355 | #define WM8915_GP4_FN_MASK 0x000F /* GP4_FN - [3:0] */ | ||
3356 | #define WM8915_GP4_FN_SHIFT 0 /* GP4_FN - [3:0] */ | ||
3357 | #define WM8915_GP4_FN_WIDTH 4 /* GP4_FN - [3:0] */ | ||
3358 | |||
3359 | /* | ||
3360 | * R1796 (0x704) - GPIO 5 | ||
3361 | */ | ||
3362 | #define WM8915_GP5_DIR 0x8000 /* GP5_DIR */ | ||
3363 | #define WM8915_GP5_DIR_MASK 0x8000 /* GP5_DIR */ | ||
3364 | #define WM8915_GP5_DIR_SHIFT 15 /* GP5_DIR */ | ||
3365 | #define WM8915_GP5_DIR_WIDTH 1 /* GP5_DIR */ | ||
3366 | #define WM8915_GP5_PU 0x4000 /* GP5_PU */ | ||
3367 | #define WM8915_GP5_PU_MASK 0x4000 /* GP5_PU */ | ||
3368 | #define WM8915_GP5_PU_SHIFT 14 /* GP5_PU */ | ||
3369 | #define WM8915_GP5_PU_WIDTH 1 /* GP5_PU */ | ||
3370 | #define WM8915_GP5_PD 0x2000 /* GP5_PD */ | ||
3371 | #define WM8915_GP5_PD_MASK 0x2000 /* GP5_PD */ | ||
3372 | #define WM8915_GP5_PD_SHIFT 13 /* GP5_PD */ | ||
3373 | #define WM8915_GP5_PD_WIDTH 1 /* GP5_PD */ | ||
3374 | #define WM8915_GP5_POL 0x0400 /* GP5_POL */ | ||
3375 | #define WM8915_GP5_POL_MASK 0x0400 /* GP5_POL */ | ||
3376 | #define WM8915_GP5_POL_SHIFT 10 /* GP5_POL */ | ||
3377 | #define WM8915_GP5_POL_WIDTH 1 /* GP5_POL */ | ||
3378 | #define WM8915_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ | ||
3379 | #define WM8915_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ | ||
3380 | #define WM8915_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ | ||
3381 | #define WM8915_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ | ||
3382 | #define WM8915_GP5_DB 0x0100 /* GP5_DB */ | ||
3383 | #define WM8915_GP5_DB_MASK 0x0100 /* GP5_DB */ | ||
3384 | #define WM8915_GP5_DB_SHIFT 8 /* GP5_DB */ | ||
3385 | #define WM8915_GP5_DB_WIDTH 1 /* GP5_DB */ | ||
3386 | #define WM8915_GP5_LVL 0x0040 /* GP5_LVL */ | ||
3387 | #define WM8915_GP5_LVL_MASK 0x0040 /* GP5_LVL */ | ||
3388 | #define WM8915_GP5_LVL_SHIFT 6 /* GP5_LVL */ | ||
3389 | #define WM8915_GP5_LVL_WIDTH 1 /* GP5_LVL */ | ||
3390 | #define WM8915_GP5_FN_MASK 0x000F /* GP5_FN - [3:0] */ | ||
3391 | #define WM8915_GP5_FN_SHIFT 0 /* GP5_FN - [3:0] */ | ||
3392 | #define WM8915_GP5_FN_WIDTH 4 /* GP5_FN - [3:0] */ | ||
3393 | |||
3394 | /* | ||
3395 | * R1824 (0x720) - Pull Control (1) | ||
3396 | */ | ||
3397 | #define WM8915_DMICDAT2_PD 0x1000 /* DMICDAT2_PD */ | ||
3398 | #define WM8915_DMICDAT2_PD_MASK 0x1000 /* DMICDAT2_PD */ | ||
3399 | #define WM8915_DMICDAT2_PD_SHIFT 12 /* DMICDAT2_PD */ | ||
3400 | #define WM8915_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ | ||
3401 | #define WM8915_DMICDAT1_PD 0x0400 /* DMICDAT1_PD */ | ||
3402 | #define WM8915_DMICDAT1_PD_MASK 0x0400 /* DMICDAT1_PD */ | ||
3403 | #define WM8915_DMICDAT1_PD_SHIFT 10 /* DMICDAT1_PD */ | ||
3404 | #define WM8915_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ | ||
3405 | #define WM8915_MCLK2_PU 0x0200 /* MCLK2_PU */ | ||
3406 | #define WM8915_MCLK2_PU_MASK 0x0200 /* MCLK2_PU */ | ||
3407 | #define WM8915_MCLK2_PU_SHIFT 9 /* MCLK2_PU */ | ||
3408 | #define WM8915_MCLK2_PU_WIDTH 1 /* MCLK2_PU */ | ||
3409 | #define WM8915_MCLK2_PD 0x0100 /* MCLK2_PD */ | ||
3410 | #define WM8915_MCLK2_PD_MASK 0x0100 /* MCLK2_PD */ | ||
3411 | #define WM8915_MCLK2_PD_SHIFT 8 /* MCLK2_PD */ | ||
3412 | #define WM8915_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ | ||
3413 | #define WM8915_MCLK1_PU 0x0080 /* MCLK1_PU */ | ||
3414 | #define WM8915_MCLK1_PU_MASK 0x0080 /* MCLK1_PU */ | ||
3415 | #define WM8915_MCLK1_PU_SHIFT 7 /* MCLK1_PU */ | ||
3416 | #define WM8915_MCLK1_PU_WIDTH 1 /* MCLK1_PU */ | ||
3417 | #define WM8915_MCLK1_PD 0x0040 /* MCLK1_PD */ | ||
3418 | #define WM8915_MCLK1_PD_MASK 0x0040 /* MCLK1_PD */ | ||
3419 | #define WM8915_MCLK1_PD_SHIFT 6 /* MCLK1_PD */ | ||
3420 | #define WM8915_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ | ||
3421 | #define WM8915_DACDAT1_PU 0x0020 /* DACDAT1_PU */ | ||
3422 | #define WM8915_DACDAT1_PU_MASK 0x0020 /* DACDAT1_PU */ | ||
3423 | #define WM8915_DACDAT1_PU_SHIFT 5 /* DACDAT1_PU */ | ||
3424 | #define WM8915_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */ | ||
3425 | #define WM8915_DACDAT1_PD 0x0010 /* DACDAT1_PD */ | ||
3426 | #define WM8915_DACDAT1_PD_MASK 0x0010 /* DACDAT1_PD */ | ||
3427 | #define WM8915_DACDAT1_PD_SHIFT 4 /* DACDAT1_PD */ | ||
3428 | #define WM8915_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */ | ||
3429 | #define WM8915_DACLRCLK1_PU 0x0008 /* DACLRCLK1_PU */ | ||
3430 | #define WM8915_DACLRCLK1_PU_MASK 0x0008 /* DACLRCLK1_PU */ | ||
3431 | #define WM8915_DACLRCLK1_PU_SHIFT 3 /* DACLRCLK1_PU */ | ||
3432 | #define WM8915_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */ | ||
3433 | #define WM8915_DACLRCLK1_PD 0x0004 /* DACLRCLK1_PD */ | ||
3434 | #define WM8915_DACLRCLK1_PD_MASK 0x0004 /* DACLRCLK1_PD */ | ||
3435 | #define WM8915_DACLRCLK1_PD_SHIFT 2 /* DACLRCLK1_PD */ | ||
3436 | #define WM8915_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */ | ||
3437 | #define WM8915_BCLK1_PU 0x0002 /* BCLK1_PU */ | ||
3438 | #define WM8915_BCLK1_PU_MASK 0x0002 /* BCLK1_PU */ | ||
3439 | #define WM8915_BCLK1_PU_SHIFT 1 /* BCLK1_PU */ | ||
3440 | #define WM8915_BCLK1_PU_WIDTH 1 /* BCLK1_PU */ | ||
3441 | #define WM8915_BCLK1_PD 0x0001 /* BCLK1_PD */ | ||
3442 | #define WM8915_BCLK1_PD_MASK 0x0001 /* BCLK1_PD */ | ||
3443 | #define WM8915_BCLK1_PD_SHIFT 0 /* BCLK1_PD */ | ||
3444 | #define WM8915_BCLK1_PD_WIDTH 1 /* BCLK1_PD */ | ||
3445 | |||
3446 | /* | ||
3447 | * R1825 (0x721) - Pull Control (2) | ||
3448 | */ | ||
3449 | #define WM8915_LDO1ENA_PD 0x0100 /* LDO1ENA_PD */ | ||
3450 | #define WM8915_LDO1ENA_PD_MASK 0x0100 /* LDO1ENA_PD */ | ||
3451 | #define WM8915_LDO1ENA_PD_SHIFT 8 /* LDO1ENA_PD */ | ||
3452 | #define WM8915_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ | ||
3453 | #define WM8915_ADDR_PD 0x0040 /* ADDR_PD */ | ||
3454 | #define WM8915_ADDR_PD_MASK 0x0040 /* ADDR_PD */ | ||
3455 | #define WM8915_ADDR_PD_SHIFT 6 /* ADDR_PD */ | ||
3456 | #define WM8915_ADDR_PD_WIDTH 1 /* ADDR_PD */ | ||
3457 | #define WM8915_DACDAT2_PU 0x0020 /* DACDAT2_PU */ | ||
3458 | #define WM8915_DACDAT2_PU_MASK 0x0020 /* DACDAT2_PU */ | ||
3459 | #define WM8915_DACDAT2_PU_SHIFT 5 /* DACDAT2_PU */ | ||
3460 | #define WM8915_DACDAT2_PU_WIDTH 1 /* DACDAT2_PU */ | ||
3461 | #define WM8915_DACDAT2_PD 0x0010 /* DACDAT2_PD */ | ||
3462 | #define WM8915_DACDAT2_PD_MASK 0x0010 /* DACDAT2_PD */ | ||
3463 | #define WM8915_DACDAT2_PD_SHIFT 4 /* DACDAT2_PD */ | ||
3464 | #define WM8915_DACDAT2_PD_WIDTH 1 /* DACDAT2_PD */ | ||
3465 | #define WM8915_DACLRCLK2_PU 0x0008 /* DACLRCLK2_PU */ | ||
3466 | #define WM8915_DACLRCLK2_PU_MASK 0x0008 /* DACLRCLK2_PU */ | ||
3467 | #define WM8915_DACLRCLK2_PU_SHIFT 3 /* DACLRCLK2_PU */ | ||
3468 | #define WM8915_DACLRCLK2_PU_WIDTH 1 /* DACLRCLK2_PU */ | ||
3469 | #define WM8915_DACLRCLK2_PD 0x0004 /* DACLRCLK2_PD */ | ||
3470 | #define WM8915_DACLRCLK2_PD_MASK 0x0004 /* DACLRCLK2_PD */ | ||
3471 | #define WM8915_DACLRCLK2_PD_SHIFT 2 /* DACLRCLK2_PD */ | ||
3472 | #define WM8915_DACLRCLK2_PD_WIDTH 1 /* DACLRCLK2_PD */ | ||
3473 | #define WM8915_BCLK2_PU 0x0002 /* BCLK2_PU */ | ||
3474 | #define WM8915_BCLK2_PU_MASK 0x0002 /* BCLK2_PU */ | ||
3475 | #define WM8915_BCLK2_PU_SHIFT 1 /* BCLK2_PU */ | ||
3476 | #define WM8915_BCLK2_PU_WIDTH 1 /* BCLK2_PU */ | ||
3477 | #define WM8915_BCLK2_PD 0x0001 /* BCLK2_PD */ | ||
3478 | #define WM8915_BCLK2_PD_MASK 0x0001 /* BCLK2_PD */ | ||
3479 | #define WM8915_BCLK2_PD_SHIFT 0 /* BCLK2_PD */ | ||
3480 | #define WM8915_BCLK2_PD_WIDTH 1 /* BCLK2_PD */ | ||
3481 | |||
3482 | /* | ||
3483 | * R1840 (0x730) - Interrupt Status 1 | ||
3484 | */ | ||
3485 | #define WM8915_GP5_EINT 0x0010 /* GP5_EINT */ | ||
3486 | #define WM8915_GP5_EINT_MASK 0x0010 /* GP5_EINT */ | ||
3487 | #define WM8915_GP5_EINT_SHIFT 4 /* GP5_EINT */ | ||
3488 | #define WM8915_GP5_EINT_WIDTH 1 /* GP5_EINT */ | ||
3489 | #define WM8915_GP4_EINT 0x0008 /* GP4_EINT */ | ||
3490 | #define WM8915_GP4_EINT_MASK 0x0008 /* GP4_EINT */ | ||
3491 | #define WM8915_GP4_EINT_SHIFT 3 /* GP4_EINT */ | ||
3492 | #define WM8915_GP4_EINT_WIDTH 1 /* GP4_EINT */ | ||
3493 | #define WM8915_GP3_EINT 0x0004 /* GP3_EINT */ | ||
3494 | #define WM8915_GP3_EINT_MASK 0x0004 /* GP3_EINT */ | ||
3495 | #define WM8915_GP3_EINT_SHIFT 2 /* GP3_EINT */ | ||
3496 | #define WM8915_GP3_EINT_WIDTH 1 /* GP3_EINT */ | ||
3497 | #define WM8915_GP2_EINT 0x0002 /* GP2_EINT */ | ||
3498 | #define WM8915_GP2_EINT_MASK 0x0002 /* GP2_EINT */ | ||
3499 | #define WM8915_GP2_EINT_SHIFT 1 /* GP2_EINT */ | ||
3500 | #define WM8915_GP2_EINT_WIDTH 1 /* GP2_EINT */ | ||
3501 | #define WM8915_GP1_EINT 0x0001 /* GP1_EINT */ | ||
3502 | #define WM8915_GP1_EINT_MASK 0x0001 /* GP1_EINT */ | ||
3503 | #define WM8915_GP1_EINT_SHIFT 0 /* GP1_EINT */ | ||
3504 | #define WM8915_GP1_EINT_WIDTH 1 /* GP1_EINT */ | ||
3505 | |||
3506 | /* | ||
3507 | * R1841 (0x731) - Interrupt Status 2 | ||
3508 | */ | ||
3509 | #define WM8915_DCS_DONE_23_EINT 0x1000 /* DCS_DONE_23_EINT */ | ||
3510 | #define WM8915_DCS_DONE_23_EINT_MASK 0x1000 /* DCS_DONE_23_EINT */ | ||
3511 | #define WM8915_DCS_DONE_23_EINT_SHIFT 12 /* DCS_DONE_23_EINT */ | ||
3512 | #define WM8915_DCS_DONE_23_EINT_WIDTH 1 /* DCS_DONE_23_EINT */ | ||
3513 | #define WM8915_DCS_DONE_01_EINT 0x0800 /* DCS_DONE_01_EINT */ | ||
3514 | #define WM8915_DCS_DONE_01_EINT_MASK 0x0800 /* DCS_DONE_01_EINT */ | ||
3515 | #define WM8915_DCS_DONE_01_EINT_SHIFT 11 /* DCS_DONE_01_EINT */ | ||
3516 | #define WM8915_DCS_DONE_01_EINT_WIDTH 1 /* DCS_DONE_01_EINT */ | ||
3517 | #define WM8915_WSEQ_DONE_EINT 0x0400 /* WSEQ_DONE_EINT */ | ||
3518 | #define WM8915_WSEQ_DONE_EINT_MASK 0x0400 /* WSEQ_DONE_EINT */ | ||
3519 | #define WM8915_WSEQ_DONE_EINT_SHIFT 10 /* WSEQ_DONE_EINT */ | ||
3520 | #define WM8915_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */ | ||
3521 | #define WM8915_FIFOS_ERR_EINT 0x0200 /* FIFOS_ERR_EINT */ | ||
3522 | #define WM8915_FIFOS_ERR_EINT_MASK 0x0200 /* FIFOS_ERR_EINT */ | ||
3523 | #define WM8915_FIFOS_ERR_EINT_SHIFT 9 /* FIFOS_ERR_EINT */ | ||
3524 | #define WM8915_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */ | ||
3525 | #define WM8915_DSP2DRC_SIG_DET_EINT 0x0080 /* DSP2DRC_SIG_DET_EINT */ | ||
3526 | #define WM8915_DSP2DRC_SIG_DET_EINT_MASK 0x0080 /* DSP2DRC_SIG_DET_EINT */ | ||
3527 | #define WM8915_DSP2DRC_SIG_DET_EINT_SHIFT 7 /* DSP2DRC_SIG_DET_EINT */ | ||
3528 | #define WM8915_DSP2DRC_SIG_DET_EINT_WIDTH 1 /* DSP2DRC_SIG_DET_EINT */ | ||
3529 | #define WM8915_DSP1DRC_SIG_DET_EINT 0x0040 /* DSP1DRC_SIG_DET_EINT */ | ||
3530 | #define WM8915_DSP1DRC_SIG_DET_EINT_MASK 0x0040 /* DSP1DRC_SIG_DET_EINT */ | ||
3531 | #define WM8915_DSP1DRC_SIG_DET_EINT_SHIFT 6 /* DSP1DRC_SIG_DET_EINT */ | ||
3532 | #define WM8915_DSP1DRC_SIG_DET_EINT_WIDTH 1 /* DSP1DRC_SIG_DET_EINT */ | ||
3533 | #define WM8915_FLL_SW_CLK_DONE_EINT 0x0008 /* FLL_SW_CLK_DONE_EINT */ | ||
3534 | #define WM8915_FLL_SW_CLK_DONE_EINT_MASK 0x0008 /* FLL_SW_CLK_DONE_EINT */ | ||
3535 | #define WM8915_FLL_SW_CLK_DONE_EINT_SHIFT 3 /* FLL_SW_CLK_DONE_EINT */ | ||
3536 | #define WM8915_FLL_SW_CLK_DONE_EINT_WIDTH 1 /* FLL_SW_CLK_DONE_EINT */ | ||
3537 | #define WM8915_FLL_LOCK_EINT 0x0004 /* FLL_LOCK_EINT */ | ||
3538 | #define WM8915_FLL_LOCK_EINT_MASK 0x0004 /* FLL_LOCK_EINT */ | ||
3539 | #define WM8915_FLL_LOCK_EINT_SHIFT 2 /* FLL_LOCK_EINT */ | ||
3540 | #define WM8915_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ | ||
3541 | #define WM8915_HP_DONE_EINT 0x0002 /* HP_DONE_EINT */ | ||
3542 | #define WM8915_HP_DONE_EINT_MASK 0x0002 /* HP_DONE_EINT */ | ||
3543 | #define WM8915_HP_DONE_EINT_SHIFT 1 /* HP_DONE_EINT */ | ||
3544 | #define WM8915_HP_DONE_EINT_WIDTH 1 /* HP_DONE_EINT */ | ||
3545 | #define WM8915_MICD_EINT 0x0001 /* MICD_EINT */ | ||
3546 | #define WM8915_MICD_EINT_MASK 0x0001 /* MICD_EINT */ | ||
3547 | #define WM8915_MICD_EINT_SHIFT 0 /* MICD_EINT */ | ||
3548 | #define WM8915_MICD_EINT_WIDTH 1 /* MICD_EINT */ | ||
3549 | |||
3550 | /* | ||
3551 | * R1842 (0x732) - Interrupt Raw Status 2 | ||
3552 | */ | ||
3553 | #define WM8915_DCS_DONE_23_STS 0x1000 /* DCS_DONE_23_STS */ | ||
3554 | #define WM8915_DCS_DONE_23_STS_MASK 0x1000 /* DCS_DONE_23_STS */ | ||
3555 | #define WM8915_DCS_DONE_23_STS_SHIFT 12 /* DCS_DONE_23_STS */ | ||
3556 | #define WM8915_DCS_DONE_23_STS_WIDTH 1 /* DCS_DONE_23_STS */ | ||
3557 | #define WM8915_DCS_DONE_01_STS 0x0800 /* DCS_DONE_01_STS */ | ||
3558 | #define WM8915_DCS_DONE_01_STS_MASK 0x0800 /* DCS_DONE_01_STS */ | ||
3559 | #define WM8915_DCS_DONE_01_STS_SHIFT 11 /* DCS_DONE_01_STS */ | ||
3560 | #define WM8915_DCS_DONE_01_STS_WIDTH 1 /* DCS_DONE_01_STS */ | ||
3561 | #define WM8915_WSEQ_DONE_STS 0x0400 /* WSEQ_DONE_STS */ | ||
3562 | #define WM8915_WSEQ_DONE_STS_MASK 0x0400 /* WSEQ_DONE_STS */ | ||
3563 | #define WM8915_WSEQ_DONE_STS_SHIFT 10 /* WSEQ_DONE_STS */ | ||
3564 | #define WM8915_WSEQ_DONE_STS_WIDTH 1 /* WSEQ_DONE_STS */ | ||
3565 | #define WM8915_FIFOS_ERR_STS 0x0200 /* FIFOS_ERR_STS */ | ||
3566 | #define WM8915_FIFOS_ERR_STS_MASK 0x0200 /* FIFOS_ERR_STS */ | ||
3567 | #define WM8915_FIFOS_ERR_STS_SHIFT 9 /* FIFOS_ERR_STS */ | ||
3568 | #define WM8915_FIFOS_ERR_STS_WIDTH 1 /* FIFOS_ERR_STS */ | ||
3569 | #define WM8915_DSP2DRC_SIG_DET_STS 0x0080 /* DSP2DRC_SIG_DET_STS */ | ||
3570 | #define WM8915_DSP2DRC_SIG_DET_STS_MASK 0x0080 /* DSP2DRC_SIG_DET_STS */ | ||
3571 | #define WM8915_DSP2DRC_SIG_DET_STS_SHIFT 7 /* DSP2DRC_SIG_DET_STS */ | ||
3572 | #define WM8915_DSP2DRC_SIG_DET_STS_WIDTH 1 /* DSP2DRC_SIG_DET_STS */ | ||
3573 | #define WM8915_DSP1DRC_SIG_DET_STS 0x0040 /* DSP1DRC_SIG_DET_STS */ | ||
3574 | #define WM8915_DSP1DRC_SIG_DET_STS_MASK 0x0040 /* DSP1DRC_SIG_DET_STS */ | ||
3575 | #define WM8915_DSP1DRC_SIG_DET_STS_SHIFT 6 /* DSP1DRC_SIG_DET_STS */ | ||
3576 | #define WM8915_DSP1DRC_SIG_DET_STS_WIDTH 1 /* DSP1DRC_SIG_DET_STS */ | ||
3577 | #define WM8915_FLL_LOCK_STS 0x0004 /* FLL_LOCK_STS */ | ||
3578 | #define WM8915_FLL_LOCK_STS_MASK 0x0004 /* FLL_LOCK_STS */ | ||
3579 | #define WM8915_FLL_LOCK_STS_SHIFT 2 /* FLL_LOCK_STS */ | ||
3580 | #define WM8915_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */ | ||
3581 | |||
3582 | /* | ||
3583 | * R1848 (0x738) - Interrupt Status 1 Mask | ||
3584 | */ | ||
3585 | #define WM8915_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ | ||
3586 | #define WM8915_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ | ||
3587 | #define WM8915_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ | ||
3588 | #define WM8915_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ | ||
3589 | #define WM8915_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ | ||
3590 | #define WM8915_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ | ||
3591 | #define WM8915_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ | ||
3592 | #define WM8915_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ | ||
3593 | #define WM8915_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ | ||
3594 | #define WM8915_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ | ||
3595 | #define WM8915_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ | ||
3596 | #define WM8915_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ | ||
3597 | #define WM8915_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ | ||
3598 | #define WM8915_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ | ||
3599 | #define WM8915_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ | ||
3600 | #define WM8915_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ | ||
3601 | #define WM8915_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ | ||
3602 | #define WM8915_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ | ||
3603 | #define WM8915_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ | ||
3604 | #define WM8915_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ | ||
3605 | |||
3606 | /* | ||
3607 | * R1849 (0x739) - Interrupt Status 2 Mask | ||
3608 | */ | ||
3609 | #define WM8915_IM_DCS_DONE_23_EINT 0x1000 /* IM_DCS_DONE_23_EINT */ | ||
3610 | #define WM8915_IM_DCS_DONE_23_EINT_MASK 0x1000 /* IM_DCS_DONE_23_EINT */ | ||
3611 | #define WM8915_IM_DCS_DONE_23_EINT_SHIFT 12 /* IM_DCS_DONE_23_EINT */ | ||
3612 | #define WM8915_IM_DCS_DONE_23_EINT_WIDTH 1 /* IM_DCS_DONE_23_EINT */ | ||
3613 | #define WM8915_IM_DCS_DONE_01_EINT 0x0800 /* IM_DCS_DONE_01_EINT */ | ||
3614 | #define WM8915_IM_DCS_DONE_01_EINT_MASK 0x0800 /* IM_DCS_DONE_01_EINT */ | ||
3615 | #define WM8915_IM_DCS_DONE_01_EINT_SHIFT 11 /* IM_DCS_DONE_01_EINT */ | ||
3616 | #define WM8915_IM_DCS_DONE_01_EINT_WIDTH 1 /* IM_DCS_DONE_01_EINT */ | ||
3617 | #define WM8915_IM_WSEQ_DONE_EINT 0x0400 /* IM_WSEQ_DONE_EINT */ | ||
3618 | #define WM8915_IM_WSEQ_DONE_EINT_MASK 0x0400 /* IM_WSEQ_DONE_EINT */ | ||
3619 | #define WM8915_IM_WSEQ_DONE_EINT_SHIFT 10 /* IM_WSEQ_DONE_EINT */ | ||
3620 | #define WM8915_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */ | ||
3621 | #define WM8915_IM_FIFOS_ERR_EINT 0x0200 /* IM_FIFOS_ERR_EINT */ | ||
3622 | #define WM8915_IM_FIFOS_ERR_EINT_MASK 0x0200 /* IM_FIFOS_ERR_EINT */ | ||
3623 | #define WM8915_IM_FIFOS_ERR_EINT_SHIFT 9 /* IM_FIFOS_ERR_EINT */ | ||
3624 | #define WM8915_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */ | ||
3625 | #define WM8915_IM_DSP2DRC_SIG_DET_EINT 0x0080 /* IM_DSP2DRC_SIG_DET_EINT */ | ||
3626 | #define WM8915_IM_DSP2DRC_SIG_DET_EINT_MASK 0x0080 /* IM_DSP2DRC_SIG_DET_EINT */ | ||
3627 | #define WM8915_IM_DSP2DRC_SIG_DET_EINT_SHIFT 7 /* IM_DSP2DRC_SIG_DET_EINT */ | ||
3628 | #define WM8915_IM_DSP2DRC_SIG_DET_EINT_WIDTH 1 /* IM_DSP2DRC_SIG_DET_EINT */ | ||
3629 | #define WM8915_IM_DSP1DRC_SIG_DET_EINT 0x0040 /* IM_DSP1DRC_SIG_DET_EINT */ | ||
3630 | #define WM8915_IM_DSP1DRC_SIG_DET_EINT_MASK 0x0040 /* IM_DSP1DRC_SIG_DET_EINT */ | ||
3631 | #define WM8915_IM_DSP1DRC_SIG_DET_EINT_SHIFT 6 /* IM_DSP1DRC_SIG_DET_EINT */ | ||
3632 | #define WM8915_IM_DSP1DRC_SIG_DET_EINT_WIDTH 1 /* IM_DSP1DRC_SIG_DET_EINT */ | ||
3633 | #define WM8915_IM_FLL_SW_CLK_DONE_EINT 0x0008 /* IM_FLL_SW_CLK_DONE_EINT */ | ||
3634 | #define WM8915_IM_FLL_SW_CLK_DONE_EINT_MASK 0x0008 /* IM_FLL_SW_CLK_DONE_EINT */ | ||
3635 | #define WM8915_IM_FLL_SW_CLK_DONE_EINT_SHIFT 3 /* IM_FLL_SW_CLK_DONE_EINT */ | ||
3636 | #define WM8915_IM_FLL_SW_CLK_DONE_EINT_WIDTH 1 /* IM_FLL_SW_CLK_DONE_EINT */ | ||
3637 | #define WM8915_IM_FLL_LOCK_EINT 0x0004 /* IM_FLL_LOCK_EINT */ | ||
3638 | #define WM8915_IM_FLL_LOCK_EINT_MASK 0x0004 /* IM_FLL_LOCK_EINT */ | ||
3639 | #define WM8915_IM_FLL_LOCK_EINT_SHIFT 2 /* IM_FLL_LOCK_EINT */ | ||
3640 | #define WM8915_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ | ||
3641 | #define WM8915_IM_HP_DONE_EINT 0x0002 /* IM_HP_DONE_EINT */ | ||
3642 | #define WM8915_IM_HP_DONE_EINT_MASK 0x0002 /* IM_HP_DONE_EINT */ | ||
3643 | #define WM8915_IM_HP_DONE_EINT_SHIFT 1 /* IM_HP_DONE_EINT */ | ||
3644 | #define WM8915_IM_HP_DONE_EINT_WIDTH 1 /* IM_HP_DONE_EINT */ | ||
3645 | #define WM8915_IM_MICD_EINT 0x0001 /* IM_MICD_EINT */ | ||
3646 | #define WM8915_IM_MICD_EINT_MASK 0x0001 /* IM_MICD_EINT */ | ||
3647 | #define WM8915_IM_MICD_EINT_SHIFT 0 /* IM_MICD_EINT */ | ||
3648 | #define WM8915_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */ | ||
3649 | |||
3650 | /* | ||
3651 | * R1856 (0x740) - Interrupt Control | ||
3652 | */ | ||
3653 | #define WM8915_IM_IRQ 0x0001 /* IM_IRQ */ | ||
3654 | #define WM8915_IM_IRQ_MASK 0x0001 /* IM_IRQ */ | ||
3655 | #define WM8915_IM_IRQ_SHIFT 0 /* IM_IRQ */ | ||
3656 | #define WM8915_IM_IRQ_WIDTH 1 /* IM_IRQ */ | ||
3657 | |||
3658 | /* | ||
3659 | * R2048 (0x800) - Left PDM Speaker | ||
3660 | */ | ||
3661 | #define WM8915_SPKL_ENA 0x0010 /* SPKL_ENA */ | ||
3662 | #define WM8915_SPKL_ENA_MASK 0x0010 /* SPKL_ENA */ | ||
3663 | #define WM8915_SPKL_ENA_SHIFT 4 /* SPKL_ENA */ | ||
3664 | #define WM8915_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ | ||
3665 | #define WM8915_SPKL_MUTE 0x0008 /* SPKL_MUTE */ | ||
3666 | #define WM8915_SPKL_MUTE_MASK 0x0008 /* SPKL_MUTE */ | ||
3667 | #define WM8915_SPKL_MUTE_SHIFT 3 /* SPKL_MUTE */ | ||
3668 | #define WM8915_SPKL_MUTE_WIDTH 1 /* SPKL_MUTE */ | ||
3669 | #define WM8915_SPKL_MUTE_ZC 0x0004 /* SPKL_MUTE_ZC */ | ||
3670 | #define WM8915_SPKL_MUTE_ZC_MASK 0x0004 /* SPKL_MUTE_ZC */ | ||
3671 | #define WM8915_SPKL_MUTE_ZC_SHIFT 2 /* SPKL_MUTE_ZC */ | ||
3672 | #define WM8915_SPKL_MUTE_ZC_WIDTH 1 /* SPKL_MUTE_ZC */ | ||
3673 | #define WM8915_SPKL_SRC_MASK 0x0003 /* SPKL_SRC - [1:0] */ | ||
3674 | #define WM8915_SPKL_SRC_SHIFT 0 /* SPKL_SRC - [1:0] */ | ||
3675 | #define WM8915_SPKL_SRC_WIDTH 2 /* SPKL_SRC - [1:0] */ | ||
3676 | |||
3677 | /* | ||
3678 | * R2049 (0x801) - Right PDM Speaker | ||
3679 | */ | ||
3680 | #define WM8915_SPKR_ENA 0x0010 /* SPKR_ENA */ | ||
3681 | #define WM8915_SPKR_ENA_MASK 0x0010 /* SPKR_ENA */ | ||
3682 | #define WM8915_SPKR_ENA_SHIFT 4 /* SPKR_ENA */ | ||
3683 | #define WM8915_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ | ||
3684 | #define WM8915_SPKR_MUTE 0x0008 /* SPKR_MUTE */ | ||
3685 | #define WM8915_SPKR_MUTE_MASK 0x0008 /* SPKR_MUTE */ | ||
3686 | #define WM8915_SPKR_MUTE_SHIFT 3 /* SPKR_MUTE */ | ||
3687 | #define WM8915_SPKR_MUTE_WIDTH 1 /* SPKR_MUTE */ | ||
3688 | #define WM8915_SPKR_MUTE_ZC 0x0004 /* SPKR_MUTE_ZC */ | ||
3689 | #define WM8915_SPKR_MUTE_ZC_MASK 0x0004 /* SPKR_MUTE_ZC */ | ||
3690 | #define WM8915_SPKR_MUTE_ZC_SHIFT 2 /* SPKR_MUTE_ZC */ | ||
3691 | #define WM8915_SPKR_MUTE_ZC_WIDTH 1 /* SPKR_MUTE_ZC */ | ||
3692 | #define WM8915_SPKR_SRC_MASK 0x0003 /* SPKR_SRC - [1:0] */ | ||
3693 | #define WM8915_SPKR_SRC_SHIFT 0 /* SPKR_SRC - [1:0] */ | ||
3694 | #define WM8915_SPKR_SRC_WIDTH 2 /* SPKR_SRC - [1:0] */ | ||
3695 | |||
3696 | /* | ||
3697 | * R2050 (0x802) - PDM Speaker Mute Sequence | ||
3698 | */ | ||
3699 | #define WM8915_SPK_MUTE_ENDIAN 0x0100 /* SPK_MUTE_ENDIAN */ | ||
3700 | #define WM8915_SPK_MUTE_ENDIAN_MASK 0x0100 /* SPK_MUTE_ENDIAN */ | ||
3701 | #define WM8915_SPK_MUTE_ENDIAN_SHIFT 8 /* SPK_MUTE_ENDIAN */ | ||
3702 | #define WM8915_SPK_MUTE_ENDIAN_WIDTH 1 /* SPK_MUTE_ENDIAN */ | ||
3703 | #define WM8915_SPK_MUTE_SEQ1_MASK 0x00FF /* SPK_MUTE_SEQ1 - [7:0] */ | ||
3704 | #define WM8915_SPK_MUTE_SEQ1_SHIFT 0 /* SPK_MUTE_SEQ1 - [7:0] */ | ||
3705 | #define WM8915_SPK_MUTE_SEQ1_WIDTH 8 /* SPK_MUTE_SEQ1 - [7:0] */ | ||
3706 | |||
3707 | /* | ||
3708 | * R2051 (0x803) - PDM Speaker Volume | ||
3709 | */ | ||
3710 | #define WM8915_SPKR_VOL_MASK 0x00F0 /* SPKR_VOL - [7:4] */ | ||
3711 | #define WM8915_SPKR_VOL_SHIFT 4 /* SPKR_VOL - [7:4] */ | ||
3712 | #define WM8915_SPKR_VOL_WIDTH 4 /* SPKR_VOL - [7:4] */ | ||
3713 | #define WM8915_SPKL_VOL_MASK 0x000F /* SPKL_VOL - [3:0] */ | ||
3714 | #define WM8915_SPKL_VOL_SHIFT 0 /* SPKL_VOL - [3:0] */ | ||
3715 | #define WM8915_SPKL_VOL_WIDTH 4 /* SPKL_VOL - [3:0] */ | ||
3716 | |||
3717 | #endif | ||
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c new file mode 100644 index 000000000000..0293763debe5 --- /dev/null +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -0,0 +1,1051 @@ | |||
1 | /* | ||
2 | * wm8958-dsp2.c -- WM8958 DSP2 support | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/slab.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/tlv.h> | ||
24 | #include <trace/events/asoc.h> | ||
25 | |||
26 | #include <linux/mfd/wm8994/core.h> | ||
27 | #include <linux/mfd/wm8994/registers.h> | ||
28 | #include <linux/mfd/wm8994/pdata.h> | ||
29 | #include <linux/mfd/wm8994/gpio.h> | ||
30 | |||
31 | #include "wm8994.h" | ||
32 | |||
33 | #define WM_FW_BLOCK_INFO 0xff | ||
34 | #define WM_FW_BLOCK_PM 0x00 | ||
35 | #define WM_FW_BLOCK_X 0x01 | ||
36 | #define WM_FW_BLOCK_Y 0x02 | ||
37 | #define WM_FW_BLOCK_Z 0x03 | ||
38 | #define WM_FW_BLOCK_I 0x06 | ||
39 | #define WM_FW_BLOCK_A 0x08 | ||
40 | #define WM_FW_BLOCK_C 0x0c | ||
41 | |||
42 | static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, | ||
43 | const struct firmware *fw, bool check) | ||
44 | { | ||
45 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
46 | u64 data64; | ||
47 | u32 data32; | ||
48 | const u8 *data; | ||
49 | char *str; | ||
50 | size_t block_len, len; | ||
51 | int ret = 0; | ||
52 | |||
53 | /* Suppress unneeded downloads */ | ||
54 | if (wm8994->cur_fw == fw) | ||
55 | return 0; | ||
56 | |||
57 | if (fw->size < 32) { | ||
58 | dev_err(codec->dev, "%s: firmware too short\n", name); | ||
59 | goto err; | ||
60 | } | ||
61 | |||
62 | if (memcmp(fw->data, "WMFW", 4) != 0) { | ||
63 | dev_err(codec->dev, "%s: firmware has bad file magic %08x\n", | ||
64 | name, data32); | ||
65 | goto err; | ||
66 | } | ||
67 | |||
68 | memcpy(&data32, fw->data + 4, sizeof(data32)); | ||
69 | len = be32_to_cpu(data32); | ||
70 | |||
71 | memcpy(&data32, fw->data + 8, sizeof(data32)); | ||
72 | data32 = be32_to_cpu(data32); | ||
73 | if ((data32 >> 24) & 0xff) { | ||
74 | dev_err(codec->dev, "%s: unsupported firmware version %d\n", | ||
75 | name, (data32 >> 24) & 0xff); | ||
76 | goto err; | ||
77 | } | ||
78 | if ((data32 & 0xffff) != 8958) { | ||
79 | dev_err(codec->dev, "%s: unsupported target device %d\n", | ||
80 | name, data32 & 0xffff); | ||
81 | goto err; | ||
82 | } | ||
83 | if (((data32 >> 16) & 0xff) != 0xc) { | ||
84 | dev_err(codec->dev, "%s: unsupported target core %d\n", | ||
85 | name, (data32 >> 16) & 0xff); | ||
86 | goto err; | ||
87 | } | ||
88 | |||
89 | if (check) { | ||
90 | memcpy(&data64, fw->data + 24, sizeof(u64)); | ||
91 | dev_info(codec->dev, "%s timestamp %llx\n", | ||
92 | name, be64_to_cpu(data64)); | ||
93 | } else { | ||
94 | snd_soc_write(codec, 0x102, 0x2); | ||
95 | snd_soc_write(codec, 0x900, 0x2); | ||
96 | } | ||
97 | |||
98 | data = fw->data + len; | ||
99 | len = fw->size - len; | ||
100 | while (len) { | ||
101 | if (len < 12) { | ||
102 | dev_err(codec->dev, "%s short data block of %zd\n", | ||
103 | name, len); | ||
104 | goto err; | ||
105 | } | ||
106 | |||
107 | memcpy(&data32, data + 4, sizeof(data32)); | ||
108 | block_len = be32_to_cpu(data32); | ||
109 | if (block_len + 8 > len) { | ||
110 | dev_err(codec->dev, "%zd byte block longer than file\n", | ||
111 | block_len); | ||
112 | goto err; | ||
113 | } | ||
114 | if (block_len == 0) { | ||
115 | dev_err(codec->dev, "Zero length block\n"); | ||
116 | goto err; | ||
117 | } | ||
118 | |||
119 | memcpy(&data32, data, sizeof(data32)); | ||
120 | data32 = be32_to_cpu(data32); | ||
121 | |||
122 | switch ((data32 >> 24) & 0xff) { | ||
123 | case WM_FW_BLOCK_INFO: | ||
124 | /* Informational text */ | ||
125 | if (!check) | ||
126 | break; | ||
127 | |||
128 | str = kzalloc(block_len + 1, GFP_KERNEL); | ||
129 | if (str) { | ||
130 | memcpy(str, data + 8, block_len); | ||
131 | dev_info(codec->dev, "%s: %s\n", name, str); | ||
132 | kfree(str); | ||
133 | } else { | ||
134 | dev_err(codec->dev, "Out of memory\n"); | ||
135 | } | ||
136 | break; | ||
137 | case WM_FW_BLOCK_PM: | ||
138 | case WM_FW_BLOCK_X: | ||
139 | case WM_FW_BLOCK_Y: | ||
140 | case WM_FW_BLOCK_Z: | ||
141 | case WM_FW_BLOCK_I: | ||
142 | case WM_FW_BLOCK_A: | ||
143 | case WM_FW_BLOCK_C: | ||
144 | dev_dbg(codec->dev, "%s: %zd bytes of %x@%x\n", name, | ||
145 | block_len, (data32 >> 24) & 0xff, | ||
146 | data32 & 0xffffff); | ||
147 | |||
148 | if (check) | ||
149 | break; | ||
150 | |||
151 | data32 &= 0xffffff; | ||
152 | |||
153 | wm8994_bulk_write(codec->control_data, | ||
154 | data32 & 0xffffff, | ||
155 | block_len / 2, | ||
156 | (void *)(data + 8)); | ||
157 | |||
158 | break; | ||
159 | default: | ||
160 | dev_warn(codec->dev, "%s: unknown block type %d\n", | ||
161 | name, (data32 >> 24) & 0xff); | ||
162 | break; | ||
163 | } | ||
164 | |||
165 | /* Round up to the next 32 bit word */ | ||
166 | block_len += block_len % 4; | ||
167 | |||
168 | data += block_len + 8; | ||
169 | len -= block_len + 8; | ||
170 | } | ||
171 | |||
172 | if (!check) { | ||
173 | dev_dbg(codec->dev, "%s: download done\n", name); | ||
174 | wm8994->cur_fw = fw; | ||
175 | } else { | ||
176 | dev_info(codec->dev, "%s: got firmware\n", name); | ||
177 | } | ||
178 | |||
179 | goto ok; | ||
180 | |||
181 | err: | ||
182 | ret = -EINVAL; | ||
183 | ok: | ||
184 | if (!check) { | ||
185 | snd_soc_write(codec, 0x900, 0x0); | ||
186 | snd_soc_write(codec, 0x102, 0x0); | ||
187 | } | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) | ||
193 | { | ||
194 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
195 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
196 | int i; | ||
197 | |||
198 | /* If the DSP is already running then noop */ | ||
199 | if (snd_soc_read(codec, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) | ||
200 | return; | ||
201 | |||
202 | /* If we have MBC firmware download it */ | ||
203 | if (wm8994->mbc) | ||
204 | wm8958_dsp2_fw(codec, "MBC", wm8994->mbc, false); | ||
205 | |||
206 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
207 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | ||
208 | |||
209 | /* If we've got user supplied MBC settings use them */ | ||
210 | if (pdata && pdata->num_mbc_cfgs) { | ||
211 | struct wm8958_mbc_cfg *cfg | ||
212 | = &pdata->mbc_cfgs[wm8994->mbc_cfg]; | ||
213 | |||
214 | for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) | ||
215 | snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1, | ||
216 | cfg->coeff_regs[i]); | ||
217 | |||
218 | for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++) | ||
219 | snd_soc_write(codec, | ||
220 | i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1, | ||
221 | cfg->cutoff_regs[i]); | ||
222 | } | ||
223 | |||
224 | /* Run the DSP */ | ||
225 | snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, | ||
226 | WM8958_DSP2_RUNR); | ||
227 | |||
228 | /* And we're off! */ | ||
229 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
230 | WM8958_MBC_ENA | | ||
231 | WM8958_MBC_SEL_MASK, | ||
232 | path << WM8958_MBC_SEL_SHIFT | | ||
233 | WM8958_MBC_ENA); | ||
234 | } | ||
235 | |||
236 | static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) | ||
237 | { | ||
238 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
239 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
240 | int i, ena; | ||
241 | |||
242 | if (wm8994->mbc_vss) | ||
243 | wm8958_dsp2_fw(codec, "MBC+VSS", wm8994->mbc_vss, false); | ||
244 | |||
245 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
246 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | ||
247 | |||
248 | /* If we've got user supplied settings use them */ | ||
249 | if (pdata && pdata->num_mbc_cfgs) { | ||
250 | struct wm8958_mbc_cfg *cfg | ||
251 | = &pdata->mbc_cfgs[wm8994->mbc_cfg]; | ||
252 | |||
253 | for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++) | ||
254 | snd_soc_write(codec, i + 0x2800, | ||
255 | cfg->combined_regs[i]); | ||
256 | } | ||
257 | |||
258 | if (pdata && pdata->num_vss_cfgs) { | ||
259 | struct wm8958_vss_cfg *cfg | ||
260 | = &pdata->vss_cfgs[wm8994->vss_cfg]; | ||
261 | |||
262 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | ||
263 | snd_soc_write(codec, i + 0x2600, cfg->regs[i]); | ||
264 | } | ||
265 | |||
266 | if (pdata && pdata->num_vss_hpf_cfgs) { | ||
267 | struct wm8958_vss_hpf_cfg *cfg | ||
268 | = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg]; | ||
269 | |||
270 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | ||
271 | snd_soc_write(codec, i + 0x2400, cfg->regs[i]); | ||
272 | } | ||
273 | |||
274 | /* Run the DSP */ | ||
275 | snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, | ||
276 | WM8958_DSP2_RUNR); | ||
277 | |||
278 | /* Enable the algorithms we've selected */ | ||
279 | ena = 0; | ||
280 | if (wm8994->mbc_ena[path]) | ||
281 | ena |= 0x8; | ||
282 | if (wm8994->hpf2_ena[path]) | ||
283 | ena |= 0x4; | ||
284 | if (wm8994->hpf1_ena[path]) | ||
285 | ena |= 0x2; | ||
286 | if (wm8994->vss_ena[path]) | ||
287 | ena |= 0x1; | ||
288 | |||
289 | snd_soc_write(codec, 0x2201, ena); | ||
290 | |||
291 | /* Switch the DSP into the data path */ | ||
292 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
293 | WM8958_MBC_SEL_MASK | WM8958_MBC_ENA, | ||
294 | path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA); | ||
295 | } | ||
296 | |||
297 | static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path) | ||
298 | { | ||
299 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
300 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
301 | int i; | ||
302 | |||
303 | wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false); | ||
304 | |||
305 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
306 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | ||
307 | |||
308 | /* If we've got user supplied settings use them */ | ||
309 | if (pdata && pdata->num_enh_eq_cfgs) { | ||
310 | struct wm8958_enh_eq_cfg *cfg | ||
311 | = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg]; | ||
312 | |||
313 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | ||
314 | snd_soc_write(codec, i + 0x2200, | ||
315 | cfg->regs[i]); | ||
316 | } | ||
317 | |||
318 | /* Run the DSP */ | ||
319 | snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, | ||
320 | WM8958_DSP2_RUNR); | ||
321 | |||
322 | /* Switch the DSP into the data path */ | ||
323 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
324 | WM8958_MBC_SEL_MASK | WM8958_MBC_ENA, | ||
325 | path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA); | ||
326 | } | ||
327 | |||
328 | static void wm8958_dsp_apply(struct snd_soc_codec *codec, int path, int start) | ||
329 | { | ||
330 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
331 | int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5); | ||
332 | int ena, reg, aif; | ||
333 | |||
334 | switch (path) { | ||
335 | case 0: | ||
336 | pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA); | ||
337 | aif = 0; | ||
338 | break; | ||
339 | case 1: | ||
340 | pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); | ||
341 | aif = 0; | ||
342 | break; | ||
343 | case 2: | ||
344 | pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA); | ||
345 | aif = 1; | ||
346 | break; | ||
347 | default: | ||
348 | BUG(); | ||
349 | return; | ||
350 | } | ||
351 | |||
352 | /* Do we have both an active AIF and an active algorithm? */ | ||
353 | ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] || | ||
354 | wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] || | ||
355 | wm8994->enh_eq_ena[path]; | ||
356 | if (!pwr_reg) | ||
357 | ena = 0; | ||
358 | |||
359 | reg = snd_soc_read(codec, WM8958_DSP2_PROGRAM); | ||
360 | |||
361 | dev_dbg(codec->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n", | ||
362 | path, wm8994->dsp_active, start, pwr_reg, reg); | ||
363 | |||
364 | if (start && ena) { | ||
365 | /* If the DSP is already running then noop */ | ||
366 | if (reg & WM8958_DSP2_ENA) | ||
367 | return; | ||
368 | |||
369 | /* If either AIFnCLK is not yet enabled postpone */ | ||
370 | if (!(snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | ||
371 | & WM8994_AIF1CLK_ENA_MASK) && | ||
372 | !(snd_soc_read(codec, WM8994_AIF2_CLOCKING_1) | ||
373 | & WM8994_AIF2CLK_ENA_MASK)) | ||
374 | return; | ||
375 | |||
376 | /* Switch the clock over to the appropriate AIF */ | ||
377 | snd_soc_update_bits(codec, WM8994_CLOCKING_1, | ||
378 | WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA, | ||
379 | aif << WM8958_DSP2CLK_SRC_SHIFT | | ||
380 | WM8958_DSP2CLK_ENA); | ||
381 | |||
382 | if (wm8994->enh_eq_ena[path]) | ||
383 | wm8958_dsp_start_enh_eq(codec, path); | ||
384 | else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] || | ||
385 | wm8994->hpf2_ena[path]) | ||
386 | wm8958_dsp_start_vss(codec, path); | ||
387 | else if (wm8994->mbc_ena[path]) | ||
388 | wm8958_dsp_start_mbc(codec, path); | ||
389 | |||
390 | wm8994->dsp_active = path; | ||
391 | |||
392 | dev_dbg(codec->dev, "DSP running in path %d\n", path); | ||
393 | } | ||
394 | |||
395 | if (!start && wm8994->dsp_active == path) { | ||
396 | /* If the DSP is already stopped then noop */ | ||
397 | if (!(reg & WM8958_DSP2_ENA)) | ||
398 | return; | ||
399 | |||
400 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
401 | WM8958_MBC_ENA, 0); | ||
402 | snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, | ||
403 | WM8958_DSP2_STOP); | ||
404 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
405 | WM8958_DSP2_ENA, 0); | ||
406 | snd_soc_update_bits(codec, WM8994_CLOCKING_1, | ||
407 | WM8958_DSP2CLK_ENA, 0); | ||
408 | |||
409 | wm8994->dsp_active = -1; | ||
410 | |||
411 | dev_dbg(codec->dev, "DSP stopped\n"); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | int wm8958_aif_ev(struct snd_soc_dapm_widget *w, | ||
416 | struct snd_kcontrol *kcontrol, int event) | ||
417 | { | ||
418 | struct snd_soc_codec *codec = w->codec; | ||
419 | int i; | ||
420 | |||
421 | switch (event) { | ||
422 | case SND_SOC_DAPM_POST_PMU: | ||
423 | case SND_SOC_DAPM_PRE_PMU: | ||
424 | for (i = 0; i < 3; i++) | ||
425 | wm8958_dsp_apply(codec, i, 1); | ||
426 | break; | ||
427 | case SND_SOC_DAPM_POST_PMD: | ||
428 | case SND_SOC_DAPM_PRE_PMD: | ||
429 | for (i = 0; i < 3; i++) | ||
430 | wm8958_dsp_apply(codec, i, 0); | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* Check if DSP2 is in use on another AIF */ | ||
438 | static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif) | ||
439 | { | ||
440 | int i; | ||
441 | |||
442 | for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) { | ||
443 | if (i == aif) | ||
444 | continue; | ||
445 | if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] || | ||
446 | wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i]) | ||
447 | return 1; | ||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, | ||
454 | struct snd_ctl_elem_value *ucontrol) | ||
455 | { | ||
456 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
457 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
458 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
459 | int value = ucontrol->value.integer.value[0]; | ||
460 | int reg; | ||
461 | |||
462 | /* Don't allow on the fly reconfiguration */ | ||
463 | reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
464 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | ||
465 | return -EBUSY; | ||
466 | |||
467 | if (value >= pdata->num_mbc_cfgs) | ||
468 | return -EINVAL; | ||
469 | |||
470 | wm8994->mbc_cfg = value; | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol, | ||
476 | struct snd_ctl_elem_value *ucontrol) | ||
477 | { | ||
478 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
479 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
480 | |||
481 | ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg; | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static int wm8958_mbc_info(struct snd_kcontrol *kcontrol, | ||
487 | struct snd_ctl_elem_info *uinfo) | ||
488 | { | ||
489 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
490 | uinfo->count = 1; | ||
491 | uinfo->value.integer.min = 0; | ||
492 | uinfo->value.integer.max = 1; | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int wm8958_mbc_get(struct snd_kcontrol *kcontrol, | ||
497 | struct snd_ctl_elem_value *ucontrol) | ||
498 | { | ||
499 | int mbc = kcontrol->private_value; | ||
500 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
501 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
502 | |||
503 | ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc]; | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int wm8958_mbc_put(struct snd_kcontrol *kcontrol, | ||
509 | struct snd_ctl_elem_value *ucontrol) | ||
510 | { | ||
511 | int mbc = kcontrol->private_value; | ||
512 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
513 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
514 | |||
515 | if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0]) | ||
516 | return 0; | ||
517 | |||
518 | if (ucontrol->value.integer.value[0] > 1) | ||
519 | return -EINVAL; | ||
520 | |||
521 | if (wm8958_dsp2_busy(wm8994, mbc)) { | ||
522 | dev_dbg(codec->dev, "DSP2 active on %d already\n", mbc); | ||
523 | return -EBUSY; | ||
524 | } | ||
525 | |||
526 | if (wm8994->enh_eq_ena[mbc]) | ||
527 | return -EBUSY; | ||
528 | |||
529 | wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0]; | ||
530 | |||
531 | wm8958_dsp_apply(codec, mbc, wm8994->mbc_ena[mbc]); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | #define WM8958_MBC_SWITCH(xname, xval) {\ | ||
537 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
538 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
539 | .info = wm8958_mbc_info, \ | ||
540 | .get = wm8958_mbc_get, .put = wm8958_mbc_put, \ | ||
541 | .private_value = xval } | ||
542 | |||
543 | static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, | ||
544 | struct snd_ctl_elem_value *ucontrol) | ||
545 | { | ||
546 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
547 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
548 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
549 | int value = ucontrol->value.integer.value[0]; | ||
550 | int reg; | ||
551 | |||
552 | /* Don't allow on the fly reconfiguration */ | ||
553 | reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
554 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | ||
555 | return -EBUSY; | ||
556 | |||
557 | if (value >= pdata->num_vss_cfgs) | ||
558 | return -EINVAL; | ||
559 | |||
560 | wm8994->vss_cfg = value; | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol, | ||
566 | struct snd_ctl_elem_value *ucontrol) | ||
567 | { | ||
568 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
569 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
570 | |||
571 | ucontrol->value.enumerated.item[0] = wm8994->vss_cfg; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, | ||
577 | struct snd_ctl_elem_value *ucontrol) | ||
578 | { | ||
579 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
580 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
581 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
582 | int value = ucontrol->value.integer.value[0]; | ||
583 | int reg; | ||
584 | |||
585 | /* Don't allow on the fly reconfiguration */ | ||
586 | reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
587 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | ||
588 | return -EBUSY; | ||
589 | |||
590 | if (value >= pdata->num_vss_hpf_cfgs) | ||
591 | return -EINVAL; | ||
592 | |||
593 | wm8994->vss_hpf_cfg = value; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol, | ||
599 | struct snd_ctl_elem_value *ucontrol) | ||
600 | { | ||
601 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
602 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
603 | |||
604 | ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg; | ||
605 | |||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static int wm8958_vss_info(struct snd_kcontrol *kcontrol, | ||
610 | struct snd_ctl_elem_info *uinfo) | ||
611 | { | ||
612 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
613 | uinfo->count = 1; | ||
614 | uinfo->value.integer.min = 0; | ||
615 | uinfo->value.integer.max = 1; | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static int wm8958_vss_get(struct snd_kcontrol *kcontrol, | ||
620 | struct snd_ctl_elem_value *ucontrol) | ||
621 | { | ||
622 | int vss = kcontrol->private_value; | ||
623 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
624 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
625 | |||
626 | ucontrol->value.integer.value[0] = wm8994->vss_ena[vss]; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int wm8958_vss_put(struct snd_kcontrol *kcontrol, | ||
632 | struct snd_ctl_elem_value *ucontrol) | ||
633 | { | ||
634 | int vss = kcontrol->private_value; | ||
635 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
636 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
637 | |||
638 | if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0]) | ||
639 | return 0; | ||
640 | |||
641 | if (ucontrol->value.integer.value[0] > 1) | ||
642 | return -EINVAL; | ||
643 | |||
644 | if (!wm8994->mbc_vss) | ||
645 | return -ENODEV; | ||
646 | |||
647 | if (wm8958_dsp2_busy(wm8994, vss)) { | ||
648 | dev_dbg(codec->dev, "DSP2 active on %d already\n", vss); | ||
649 | return -EBUSY; | ||
650 | } | ||
651 | |||
652 | if (wm8994->enh_eq_ena[vss]) | ||
653 | return -EBUSY; | ||
654 | |||
655 | wm8994->vss_ena[vss] = ucontrol->value.integer.value[0]; | ||
656 | |||
657 | wm8958_dsp_apply(codec, vss, wm8994->vss_ena[vss]); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | |||
663 | #define WM8958_VSS_SWITCH(xname, xval) {\ | ||
664 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
665 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
666 | .info = wm8958_vss_info, \ | ||
667 | .get = wm8958_vss_get, .put = wm8958_vss_put, \ | ||
668 | .private_value = xval } | ||
669 | |||
670 | static int wm8958_hpf_info(struct snd_kcontrol *kcontrol, | ||
671 | struct snd_ctl_elem_info *uinfo) | ||
672 | { | ||
673 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
674 | uinfo->count = 1; | ||
675 | uinfo->value.integer.min = 0; | ||
676 | uinfo->value.integer.max = 1; | ||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | static int wm8958_hpf_get(struct snd_kcontrol *kcontrol, | ||
681 | struct snd_ctl_elem_value *ucontrol) | ||
682 | { | ||
683 | int hpf = kcontrol->private_value; | ||
684 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
685 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
686 | |||
687 | if (hpf < 3) | ||
688 | ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3]; | ||
689 | else | ||
690 | ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3]; | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static int wm8958_hpf_put(struct snd_kcontrol *kcontrol, | ||
696 | struct snd_ctl_elem_value *ucontrol) | ||
697 | { | ||
698 | int hpf = kcontrol->private_value; | ||
699 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
700 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
701 | |||
702 | if (hpf < 3) { | ||
703 | if (wm8994->hpf1_ena[hpf % 3] == | ||
704 | ucontrol->value.integer.value[0]) | ||
705 | return 0; | ||
706 | } else { | ||
707 | if (wm8994->hpf2_ena[hpf % 3] == | ||
708 | ucontrol->value.integer.value[0]) | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | if (ucontrol->value.integer.value[0] > 1) | ||
713 | return -EINVAL; | ||
714 | |||
715 | if (!wm8994->mbc_vss) | ||
716 | return -ENODEV; | ||
717 | |||
718 | if (wm8958_dsp2_busy(wm8994, hpf % 3)) { | ||
719 | dev_dbg(codec->dev, "DSP2 active on %d already\n", hpf); | ||
720 | return -EBUSY; | ||
721 | } | ||
722 | |||
723 | if (wm8994->enh_eq_ena[hpf % 3]) | ||
724 | return -EBUSY; | ||
725 | |||
726 | if (hpf < 3) | ||
727 | wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0]; | ||
728 | else | ||
729 | wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0]; | ||
730 | |||
731 | wm8958_dsp_apply(codec, hpf % 3, ucontrol->value.integer.value[0]); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | #define WM8958_HPF_SWITCH(xname, xval) {\ | ||
737 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
738 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
739 | .info = wm8958_hpf_info, \ | ||
740 | .get = wm8958_hpf_get, .put = wm8958_hpf_put, \ | ||
741 | .private_value = xval } | ||
742 | |||
743 | static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, | ||
744 | struct snd_ctl_elem_value *ucontrol) | ||
745 | { | ||
746 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
747 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
748 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
749 | int value = ucontrol->value.integer.value[0]; | ||
750 | int reg; | ||
751 | |||
752 | /* Don't allow on the fly reconfiguration */ | ||
753 | reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
754 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | ||
755 | return -EBUSY; | ||
756 | |||
757 | if (value >= pdata->num_enh_eq_cfgs) | ||
758 | return -EINVAL; | ||
759 | |||
760 | wm8994->enh_eq_cfg = value; | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol, | ||
766 | struct snd_ctl_elem_value *ucontrol) | ||
767 | { | ||
768 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
769 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
770 | |||
771 | ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg; | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol, | ||
777 | struct snd_ctl_elem_info *uinfo) | ||
778 | { | ||
779 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
780 | uinfo->count = 1; | ||
781 | uinfo->value.integer.min = 0; | ||
782 | uinfo->value.integer.max = 1; | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol, | ||
787 | struct snd_ctl_elem_value *ucontrol) | ||
788 | { | ||
789 | int eq = kcontrol->private_value; | ||
790 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
791 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
792 | |||
793 | ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq]; | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol, | ||
799 | struct snd_ctl_elem_value *ucontrol) | ||
800 | { | ||
801 | int eq = kcontrol->private_value; | ||
802 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
803 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
804 | |||
805 | if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0]) | ||
806 | return 0; | ||
807 | |||
808 | if (ucontrol->value.integer.value[0] > 1) | ||
809 | return -EINVAL; | ||
810 | |||
811 | if (!wm8994->enh_eq) | ||
812 | return -ENODEV; | ||
813 | |||
814 | if (wm8958_dsp2_busy(wm8994, eq)) { | ||
815 | dev_dbg(codec->dev, "DSP2 active on %d already\n", eq); | ||
816 | return -EBUSY; | ||
817 | } | ||
818 | |||
819 | if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] || | ||
820 | wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq]) | ||
821 | return -EBUSY; | ||
822 | |||
823 | wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0]; | ||
824 | |||
825 | wm8958_dsp_apply(codec, eq, ucontrol->value.integer.value[0]); | ||
826 | |||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | #define WM8958_ENH_EQ_SWITCH(xname, xval) {\ | ||
831 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
832 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
833 | .info = wm8958_enh_eq_info, \ | ||
834 | .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \ | ||
835 | .private_value = xval } | ||
836 | |||
837 | static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = { | ||
838 | WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0), | ||
839 | WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1), | ||
840 | WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2), | ||
841 | }; | ||
842 | |||
843 | static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = { | ||
844 | WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0), | ||
845 | WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1), | ||
846 | WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2), | ||
847 | WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0), | ||
848 | WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1), | ||
849 | WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2), | ||
850 | WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3), | ||
851 | WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4), | ||
852 | WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5), | ||
853 | }; | ||
854 | |||
855 | static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = { | ||
856 | WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0), | ||
857 | WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1), | ||
858 | WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2), | ||
859 | }; | ||
860 | |||
861 | static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context) | ||
862 | { | ||
863 | struct snd_soc_codec *codec = context; | ||
864 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
865 | |||
866 | if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { | ||
867 | mutex_lock(&codec->mutex); | ||
868 | wm8994->enh_eq = fw; | ||
869 | mutex_unlock(&codec->mutex); | ||
870 | } | ||
871 | } | ||
872 | |||
873 | static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) | ||
874 | { | ||
875 | struct snd_soc_codec *codec = context; | ||
876 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
877 | |||
878 | if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { | ||
879 | mutex_lock(&codec->mutex); | ||
880 | wm8994->mbc_vss = fw; | ||
881 | mutex_unlock(&codec->mutex); | ||
882 | } | ||
883 | |||
884 | /* We can't have more than one request outstanding at once so | ||
885 | * we daisy chain. | ||
886 | */ | ||
887 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
888 | "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL, | ||
889 | codec, wm8958_enh_eq_loaded); | ||
890 | } | ||
891 | |||
892 | static void wm8958_mbc_loaded(const struct firmware *fw, void *context) | ||
893 | { | ||
894 | struct snd_soc_codec *codec = context; | ||
895 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
896 | |||
897 | if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0) | ||
898 | return; | ||
899 | |||
900 | mutex_lock(&codec->mutex); | ||
901 | wm8994->mbc = fw; | ||
902 | mutex_unlock(&codec->mutex); | ||
903 | |||
904 | /* We can't have more than one request outstanding at once so | ||
905 | * we daisy chain. | ||
906 | */ | ||
907 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
908 | "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL, | ||
909 | codec, wm8958_mbc_vss_loaded); | ||
910 | } | ||
911 | |||
912 | void wm8958_dsp2_init(struct snd_soc_codec *codec) | ||
913 | { | ||
914 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
915 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
916 | int ret, i; | ||
917 | |||
918 | wm8994->dsp_active = -1; | ||
919 | |||
920 | snd_soc_add_controls(codec, wm8958_mbc_snd_controls, | ||
921 | ARRAY_SIZE(wm8958_mbc_snd_controls)); | ||
922 | snd_soc_add_controls(codec, wm8958_vss_snd_controls, | ||
923 | ARRAY_SIZE(wm8958_vss_snd_controls)); | ||
924 | snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls, | ||
925 | ARRAY_SIZE(wm8958_enh_eq_snd_controls)); | ||
926 | |||
927 | |||
928 | /* We don't *require* firmware and don't want to delay boot */ | ||
929 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
930 | "wm8958_mbc.wfw", codec->dev, GFP_KERNEL, | ||
931 | codec, wm8958_mbc_loaded); | ||
932 | |||
933 | if (!pdata) | ||
934 | return; | ||
935 | |||
936 | if (pdata->num_mbc_cfgs) { | ||
937 | struct snd_kcontrol_new control[] = { | ||
938 | SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum, | ||
939 | wm8958_get_mbc_enum, wm8958_put_mbc_enum), | ||
940 | }; | ||
941 | |||
942 | /* We need an array of texts for the enum API */ | ||
943 | wm8994->mbc_texts = kmalloc(sizeof(char *) | ||
944 | * pdata->num_mbc_cfgs, GFP_KERNEL); | ||
945 | if (!wm8994->mbc_texts) { | ||
946 | dev_err(wm8994->codec->dev, | ||
947 | "Failed to allocate %d MBC config texts\n", | ||
948 | pdata->num_mbc_cfgs); | ||
949 | return; | ||
950 | } | ||
951 | |||
952 | for (i = 0; i < pdata->num_mbc_cfgs; i++) | ||
953 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; | ||
954 | |||
955 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | ||
956 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | ||
957 | |||
958 | ret = snd_soc_add_controls(wm8994->codec, control, 1); | ||
959 | if (ret != 0) | ||
960 | dev_err(wm8994->codec->dev, | ||
961 | "Failed to add MBC mode controls: %d\n", ret); | ||
962 | } | ||
963 | |||
964 | if (pdata->num_vss_cfgs) { | ||
965 | struct snd_kcontrol_new control[] = { | ||
966 | SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum, | ||
967 | wm8958_get_vss_enum, wm8958_put_vss_enum), | ||
968 | }; | ||
969 | |||
970 | /* We need an array of texts for the enum API */ | ||
971 | wm8994->vss_texts = kmalloc(sizeof(char *) | ||
972 | * pdata->num_vss_cfgs, GFP_KERNEL); | ||
973 | if (!wm8994->vss_texts) { | ||
974 | dev_err(wm8994->codec->dev, | ||
975 | "Failed to allocate %d VSS config texts\n", | ||
976 | pdata->num_vss_cfgs); | ||
977 | return; | ||
978 | } | ||
979 | |||
980 | for (i = 0; i < pdata->num_vss_cfgs; i++) | ||
981 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; | ||
982 | |||
983 | wm8994->vss_enum.max = pdata->num_vss_cfgs; | ||
984 | wm8994->vss_enum.texts = wm8994->vss_texts; | ||
985 | |||
986 | ret = snd_soc_add_controls(wm8994->codec, control, 1); | ||
987 | if (ret != 0) | ||
988 | dev_err(wm8994->codec->dev, | ||
989 | "Failed to add VSS mode controls: %d\n", ret); | ||
990 | } | ||
991 | |||
992 | if (pdata->num_vss_hpf_cfgs) { | ||
993 | struct snd_kcontrol_new control[] = { | ||
994 | SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum, | ||
995 | wm8958_get_vss_hpf_enum, | ||
996 | wm8958_put_vss_hpf_enum), | ||
997 | }; | ||
998 | |||
999 | /* We need an array of texts for the enum API */ | ||
1000 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | ||
1001 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | ||
1002 | if (!wm8994->vss_hpf_texts) { | ||
1003 | dev_err(wm8994->codec->dev, | ||
1004 | "Failed to allocate %d VSS HPF config texts\n", | ||
1005 | pdata->num_vss_hpf_cfgs); | ||
1006 | return; | ||
1007 | } | ||
1008 | |||
1009 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) | ||
1010 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; | ||
1011 | |||
1012 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; | ||
1013 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; | ||
1014 | |||
1015 | ret = snd_soc_add_controls(wm8994->codec, control, 1); | ||
1016 | if (ret != 0) | ||
1017 | dev_err(wm8994->codec->dev, | ||
1018 | "Failed to add VSS HPFmode controls: %d\n", | ||
1019 | ret); | ||
1020 | } | ||
1021 | |||
1022 | if (pdata->num_enh_eq_cfgs) { | ||
1023 | struct snd_kcontrol_new control[] = { | ||
1024 | SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum, | ||
1025 | wm8958_get_enh_eq_enum, | ||
1026 | wm8958_put_enh_eq_enum), | ||
1027 | }; | ||
1028 | |||
1029 | /* We need an array of texts for the enum API */ | ||
1030 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | ||
1031 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | ||
1032 | if (!wm8994->enh_eq_texts) { | ||
1033 | dev_err(wm8994->codec->dev, | ||
1034 | "Failed to allocate %d enhanced EQ config texts\n", | ||
1035 | pdata->num_enh_eq_cfgs); | ||
1036 | return; | ||
1037 | } | ||
1038 | |||
1039 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) | ||
1040 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; | ||
1041 | |||
1042 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; | ||
1043 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; | ||
1044 | |||
1045 | ret = snd_soc_add_controls(wm8994->codec, control, 1); | ||
1046 | if (ret != 0) | ||
1047 | dev_err(wm8994->codec->dev, | ||
1048 | "Failed to add enhanced EQ controls: %d\n", | ||
1049 | ret); | ||
1050 | } | ||
1051 | } | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 500011eb8b2b..f90ae427242b 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -58,6 +58,7 @@ struct wm8962_priv { | |||
58 | int bclk; /* Desired BCLK */ | 58 | int bclk; /* Desired BCLK */ |
59 | int lrclk; | 59 | int lrclk; |
60 | 60 | ||
61 | struct completion fll_lock; | ||
61 | int fll_src; | 62 | int fll_src; |
62 | int fll_fref; | 63 | int fll_fref; |
63 | int fll_fout; | 64 | int fll_fout; |
@@ -2038,6 +2039,13 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, | |||
2038 | return 0; | 2039 | return 0; |
2039 | } | 2040 | } |
2040 | 2041 | ||
2042 | static const char *cap_hpf_mode_text[] = { | ||
2043 | "Hi-fi", "Application" | ||
2044 | }; | ||
2045 | |||
2046 | static const struct soc_enum cap_hpf_mode = | ||
2047 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); | ||
2048 | |||
2041 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { | 2049 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { |
2042 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), | 2050 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), |
2043 | 2051 | ||
@@ -2063,6 +2071,9 @@ SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME, | |||
2063 | WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1), | 2071 | WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1), |
2064 | SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, | 2072 | SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, |
2065 | WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1), | 2073 | WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1), |
2074 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), | ||
2075 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), | ||
2076 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), | ||
2066 | 2077 | ||
2067 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, | 2078 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, |
2068 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), | 2079 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), |
@@ -2467,6 +2478,7 @@ SND_SOC_DAPM_INPUT("IN3R"), | |||
2467 | SND_SOC_DAPM_INPUT("IN4L"), | 2478 | SND_SOC_DAPM_INPUT("IN4L"), |
2468 | SND_SOC_DAPM_INPUT("IN4R"), | 2479 | SND_SOC_DAPM_INPUT("IN4R"), |
2469 | SND_SOC_DAPM_INPUT("Beep"), | 2480 | SND_SOC_DAPM_INPUT("Beep"), |
2481 | SND_SOC_DAPM_INPUT("DMICDAT"), | ||
2470 | 2482 | ||
2471 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0), | 2483 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0), |
2472 | 2484 | ||
@@ -2486,6 +2498,8 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, | |||
2486 | SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, | 2498 | SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, |
2487 | mixinr, ARRAY_SIZE(mixinr)), | 2499 | mixinr, ARRAY_SIZE(mixinr)), |
2488 | 2500 | ||
2501 | SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), | ||
2502 | |||
2489 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), | 2503 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), |
2490 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), | 2504 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), |
2491 | 2505 | ||
@@ -2563,13 +2577,17 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2563 | 2577 | ||
2564 | { "MICBIAS", NULL, "SYSCLK" }, | 2578 | { "MICBIAS", NULL, "SYSCLK" }, |
2565 | 2579 | ||
2580 | { "DMIC", NULL, "DMICDAT" }, | ||
2581 | |||
2566 | { "ADCL", NULL, "SYSCLK" }, | 2582 | { "ADCL", NULL, "SYSCLK" }, |
2567 | { "ADCL", NULL, "TOCLK" }, | 2583 | { "ADCL", NULL, "TOCLK" }, |
2568 | { "ADCL", NULL, "MIXINL" }, | 2584 | { "ADCL", NULL, "MIXINL" }, |
2585 | { "ADCL", NULL, "DMIC" }, | ||
2569 | 2586 | ||
2570 | { "ADCR", NULL, "SYSCLK" }, | 2587 | { "ADCR", NULL, "SYSCLK" }, |
2571 | { "ADCR", NULL, "TOCLK" }, | 2588 | { "ADCR", NULL, "TOCLK" }, |
2572 | { "ADCR", NULL, "MIXINR" }, | 2589 | { "ADCR", NULL, "MIXINR" }, |
2590 | { "ADCR", NULL, "DMIC" }, | ||
2573 | 2591 | ||
2574 | { "STL", "Left", "ADCL" }, | 2592 | { "STL", "Left", "ADCL" }, |
2575 | { "STL", "Right", "ADCR" }, | 2593 | { "STL", "Right", "ADCR" }, |
@@ -2990,7 +3008,6 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
2990 | case WM8962_SYSCLK_FLL: | 3008 | case WM8962_SYSCLK_FLL: |
2991 | wm8962->sysclk = WM8962_SYSCLK_FLL; | 3009 | wm8962->sysclk = WM8962_SYSCLK_FLL; |
2992 | src = 1 << WM8962_SYSCLK_SRC_SHIFT; | 3010 | src = 1 << WM8962_SYSCLK_SRC_SHIFT; |
2993 | WARN_ON(freq != wm8962->fll_fout); | ||
2994 | break; | 3011 | break; |
2995 | default: | 3012 | default: |
2996 | return -EINVAL; | 3013 | return -EINVAL; |
@@ -3172,12 +3189,12 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
3172 | return 0; | 3189 | return 0; |
3173 | } | 3190 | } |
3174 | 3191 | ||
3175 | static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | 3192 | static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
3176 | unsigned int Fref, unsigned int Fout) | 3193 | unsigned int Fref, unsigned int Fout) |
3177 | { | 3194 | { |
3178 | struct snd_soc_codec *codec = dai->codec; | ||
3179 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3195 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3180 | struct _fll_div fll_div; | 3196 | struct _fll_div fll_div; |
3197 | unsigned long timeout; | ||
3181 | int ret; | 3198 | int ret; |
3182 | int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA; | 3199 | int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA; |
3183 | 3200 | ||
@@ -3244,6 +3261,11 @@ static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | |||
3244 | 3261 | ||
3245 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 3262 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
3246 | 3263 | ||
3264 | /* This should be a massive overestimate */ | ||
3265 | timeout = msecs_to_jiffies(1); | ||
3266 | |||
3267 | wait_for_completion_timeout(&wm8962->fll_lock, timeout); | ||
3268 | |||
3247 | wm8962->fll_fref = Fref; | 3269 | wm8962->fll_fref = Fref; |
3248 | wm8962->fll_fout = Fout; | 3270 | wm8962->fll_fout = Fout; |
3249 | wm8962->fll_src = source; | 3271 | wm8962->fll_src = source; |
@@ -3274,7 +3296,6 @@ static struct snd_soc_dai_ops wm8962_dai_ops = { | |||
3274 | .hw_params = wm8962_hw_params, | 3296 | .hw_params = wm8962_hw_params, |
3275 | .set_sysclk = wm8962_set_dai_sysclk, | 3297 | .set_sysclk = wm8962_set_dai_sysclk, |
3276 | .set_fmt = wm8962_set_dai_fmt, | 3298 | .set_fmt = wm8962_set_dai_fmt, |
3277 | .set_pll = wm8962_set_fll, | ||
3278 | .digital_mute = wm8962_mute, | 3299 | .digital_mute = wm8962_mute, |
3279 | }; | 3300 | }; |
3280 | 3301 | ||
@@ -3340,6 +3361,11 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3340 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | 3361 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); |
3341 | active &= ~mask; | 3362 | active &= ~mask; |
3342 | 3363 | ||
3364 | if (active & WM8962_FLL_LOCK_EINT) { | ||
3365 | dev_dbg(codec->dev, "FLL locked\n"); | ||
3366 | complete(&wm8962->fll_lock); | ||
3367 | } | ||
3368 | |||
3343 | if (active & WM8962_FIFOS_ERR_EINT) | 3369 | if (active & WM8962_FIFOS_ERR_EINT) |
3344 | dev_err(codec->dev, "FIFO error\n"); | 3370 | dev_err(codec->dev, "FIFO error\n"); |
3345 | 3371 | ||
@@ -3709,9 +3735,11 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3709 | dev); | 3735 | dev); |
3710 | u16 *reg_cache = codec->reg_cache; | 3736 | u16 *reg_cache = codec->reg_cache; |
3711 | int i, trigger, irq_pol; | 3737 | int i, trigger, irq_pol; |
3738 | bool dmicclk, dmicdat; | ||
3712 | 3739 | ||
3713 | wm8962->codec = codec; | 3740 | wm8962->codec = codec; |
3714 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); | 3741 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); |
3742 | init_completion(&wm8962->fll_lock); | ||
3715 | 3743 | ||
3716 | codec->cache_sync = 1; | 3744 | codec->cache_sync = 1; |
3717 | codec->dapm.idle_bias_off = 1; | 3745 | codec->dapm.idle_bias_off = 1; |
@@ -3845,6 +3873,29 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3845 | 3873 | ||
3846 | wm8962_add_widgets(codec); | 3874 | wm8962_add_widgets(codec); |
3847 | 3875 | ||
3876 | /* Save boards having to disable DMIC when not in use */ | ||
3877 | dmicclk = false; | ||
3878 | dmicdat = false; | ||
3879 | for (i = 0; i < WM8962_MAX_GPIO; i++) { | ||
3880 | switch (snd_soc_read(codec, WM8962_GPIO_BASE + i) | ||
3881 | & WM8962_GP2_FN_MASK) { | ||
3882 | case WM8962_GPIO_FN_DMICCLK: | ||
3883 | dmicclk = true; | ||
3884 | break; | ||
3885 | case WM8962_GPIO_FN_DMICDAT: | ||
3886 | dmicdat = true; | ||
3887 | break; | ||
3888 | default: | ||
3889 | break; | ||
3890 | } | ||
3891 | } | ||
3892 | if (!dmicclk || !dmicdat) { | ||
3893 | dev_dbg(codec->dev, "DMIC not in use, disabling\n"); | ||
3894 | snd_soc_dapm_nc_pin(&codec->dapm, "DMICDAT"); | ||
3895 | } | ||
3896 | if (dmicclk != dmicdat) | ||
3897 | dev_warn(codec->dev, "DMIC GPIOs partially configured\n"); | ||
3898 | |||
3848 | wm8962_init_beep(codec); | 3899 | wm8962_init_beep(codec); |
3849 | wm8962_init_gpio(codec); | 3900 | wm8962_init_gpio(codec); |
3850 | 3901 | ||
@@ -3868,9 +3919,10 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3868 | i2c->irq, ret); | 3919 | i2c->irq, ret); |
3869 | /* Non-fatal */ | 3920 | /* Non-fatal */ |
3870 | } else { | 3921 | } else { |
3871 | /* Enable error reporting IRQs by default */ | 3922 | /* Enable some IRQs by default */ |
3872 | snd_soc_update_bits(codec, | 3923 | snd_soc_update_bits(codec, |
3873 | WM8962_INTERRUPT_STATUS_2_MASK, | 3924 | WM8962_INTERRUPT_STATUS_2_MASK, |
3925 | WM8962_FLL_LOCK_EINT | | ||
3874 | WM8962_TEMP_SHUT_EINT | | 3926 | WM8962_TEMP_SHUT_EINT | |
3875 | WM8962_FIFOS_ERR_EINT, 0); | 3927 | WM8962_FIFOS_ERR_EINT, 0); |
3876 | } | 3928 | } |
@@ -3918,6 +3970,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { | |||
3918 | .reg_cache_default = wm8962_reg, | 3970 | .reg_cache_default = wm8962_reg, |
3919 | .volatile_register = wm8962_volatile_register, | 3971 | .volatile_register = wm8962_volatile_register, |
3920 | .readable_register = wm8962_readable_register, | 3972 | .readable_register = wm8962_readable_register, |
3973 | .set_pll = wm8962_set_fll, | ||
3921 | }; | 3974 | }; |
3922 | 3975 | ||
3923 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 3976 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 056aef904347..9e5ff789b805 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -718,7 +718,8 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
718 | static int class_w_put(struct snd_kcontrol *kcontrol, | 718 | static int class_w_put(struct snd_kcontrol *kcontrol, |
719 | struct snd_ctl_elem_value *ucontrol) | 719 | struct snd_ctl_elem_value *ucontrol) |
720 | { | 720 | { |
721 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 721 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
722 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
722 | struct snd_soc_codec *codec = widget->codec; | 723 | struct snd_soc_codec *codec = widget->codec; |
723 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 724 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
724 | int ret; | 725 | int ret; |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 84e1bd1d2822..970a95c5360b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -38,12 +38,6 @@ | |||
38 | #include "wm8994.h" | 38 | #include "wm8994.h" |
39 | #include "wm_hubs.h" | 39 | #include "wm_hubs.h" |
40 | 40 | ||
41 | struct fll_config { | ||
42 | int src; | ||
43 | int in; | ||
44 | int out; | ||
45 | }; | ||
46 | |||
47 | #define WM8994_NUM_DRC 3 | 41 | #define WM8994_NUM_DRC 3 |
48 | #define WM8994_NUM_EQ 3 | 42 | #define WM8994_NUM_EQ 3 |
49 | 43 | ||
@@ -59,63 +53,11 @@ static int wm8994_retune_mobile_base[] = { | |||
59 | WM8994_AIF2_EQ_GAINS_1, | 53 | WM8994_AIF2_EQ_GAINS_1, |
60 | }; | 54 | }; |
61 | 55 | ||
62 | struct wm8994_micdet { | ||
63 | struct snd_soc_jack *jack; | ||
64 | int det; | ||
65 | int shrt; | ||
66 | }; | ||
67 | |||
68 | /* codec private data */ | ||
69 | struct wm8994_priv { | ||
70 | struct wm_hubs_data hubs; | ||
71 | enum snd_soc_control_type control_type; | ||
72 | void *control_data; | ||
73 | struct snd_soc_codec *codec; | ||
74 | int sysclk[2]; | ||
75 | int sysclk_rate[2]; | ||
76 | int mclk[2]; | ||
77 | int aifclk[2]; | ||
78 | struct fll_config fll[2], fll_suspend[2]; | ||
79 | |||
80 | int dac_rates[2]; | ||
81 | int lrclk_shared[2]; | ||
82 | |||
83 | int mbc_ena[3]; | ||
84 | |||
85 | /* Platform dependent DRC configuration */ | ||
86 | const char **drc_texts; | ||
87 | int drc_cfg[WM8994_NUM_DRC]; | ||
88 | struct soc_enum drc_enum; | ||
89 | |||
90 | /* Platform dependent ReTune mobile configuration */ | ||
91 | int num_retune_mobile_texts; | ||
92 | const char **retune_mobile_texts; | ||
93 | int retune_mobile_cfg[WM8994_NUM_EQ]; | ||
94 | struct soc_enum retune_mobile_enum; | ||
95 | |||
96 | /* Platform dependent MBC configuration */ | ||
97 | int mbc_cfg; | ||
98 | const char **mbc_texts; | ||
99 | struct soc_enum mbc_enum; | ||
100 | |||
101 | struct wm8994_micdet micdet[2]; | ||
102 | |||
103 | wm8958_micdet_cb jack_cb; | ||
104 | void *jack_cb_data; | ||
105 | int micdet_irq; | ||
106 | |||
107 | int revision; | ||
108 | struct wm8994_pdata *pdata; | ||
109 | |||
110 | unsigned int aif1clk_enable:1; | ||
111 | unsigned int aif2clk_enable:1; | ||
112 | |||
113 | unsigned int aif1clk_disable:1; | ||
114 | unsigned int aif2clk_disable:1; | ||
115 | }; | ||
116 | |||
117 | static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) | 56 | static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) |
118 | { | 57 | { |
58 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
59 | struct wm8994 *control = wm8994->control_data; | ||
60 | |||
119 | switch (reg) { | 61 | switch (reg) { |
120 | case WM8994_GPIO_1: | 62 | case WM8994_GPIO_1: |
121 | case WM8994_GPIO_2: | 63 | case WM8994_GPIO_2: |
@@ -132,6 +74,15 @@ static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) | |||
132 | case WM8994_INTERRUPT_STATUS_2: | 74 | case WM8994_INTERRUPT_STATUS_2: |
133 | case WM8994_INTERRUPT_RAW_STATUS_2: | 75 | case WM8994_INTERRUPT_RAW_STATUS_2: |
134 | return 1; | 76 | return 1; |
77 | |||
78 | case WM8958_DSP2_PROGRAM: | ||
79 | case WM8958_DSP2_CONFIG: | ||
80 | case WM8958_DSP2_EXECCONTROL: | ||
81 | if (control->type == WM8958) | ||
82 | return 1; | ||
83 | else | ||
84 | return 0; | ||
85 | |||
135 | default: | 86 | default: |
136 | break; | 87 | break; |
137 | } | 88 | } |
@@ -574,215 +525,6 @@ static const struct soc_enum dac_osr = | |||
574 | static const struct soc_enum adc_osr = | 525 | static const struct soc_enum adc_osr = |
575 | SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text); | 526 | SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text); |
576 | 527 | ||
577 | static void wm8958_mbc_apply(struct snd_soc_codec *codec, int mbc, int start) | ||
578 | { | ||
579 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
580 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
581 | int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5); | ||
582 | int ena, reg, aif, i; | ||
583 | |||
584 | switch (mbc) { | ||
585 | case 0: | ||
586 | pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA); | ||
587 | aif = 0; | ||
588 | break; | ||
589 | case 1: | ||
590 | pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); | ||
591 | aif = 0; | ||
592 | break; | ||
593 | case 2: | ||
594 | pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA); | ||
595 | aif = 1; | ||
596 | break; | ||
597 | default: | ||
598 | BUG(); | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | /* We can only enable the MBC if the AIF is enabled and we | ||
603 | * want it to be enabled. */ | ||
604 | ena = pwr_reg && wm8994->mbc_ena[mbc]; | ||
605 | |||
606 | reg = snd_soc_read(codec, WM8958_DSP2_PROGRAM); | ||
607 | |||
608 | dev_dbg(codec->dev, "MBC %d startup: %d, power: %x, DSP: %x\n", | ||
609 | mbc, start, pwr_reg, reg); | ||
610 | |||
611 | if (start && ena) { | ||
612 | /* If the DSP is already running then noop */ | ||
613 | if (reg & WM8958_DSP2_ENA) | ||
614 | return; | ||
615 | |||
616 | /* Switch the clock over to the appropriate AIF */ | ||
617 | snd_soc_update_bits(codec, WM8994_CLOCKING_1, | ||
618 | WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA, | ||
619 | aif << WM8958_DSP2CLK_SRC_SHIFT | | ||
620 | WM8958_DSP2CLK_ENA); | ||
621 | |||
622 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
623 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | ||
624 | |||
625 | /* If we've got user supplied MBC settings use them */ | ||
626 | if (pdata && pdata->num_mbc_cfgs) { | ||
627 | struct wm8958_mbc_cfg *cfg | ||
628 | = &pdata->mbc_cfgs[wm8994->mbc_cfg]; | ||
629 | |||
630 | for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) | ||
631 | snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1, | ||
632 | cfg->coeff_regs[i]); | ||
633 | |||
634 | for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++) | ||
635 | snd_soc_write(codec, | ||
636 | i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1, | ||
637 | cfg->cutoff_regs[i]); | ||
638 | } | ||
639 | |||
640 | /* Run the DSP */ | ||
641 | snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, | ||
642 | WM8958_DSP2_RUNR); | ||
643 | |||
644 | /* And we're off! */ | ||
645 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
646 | WM8958_MBC_ENA | WM8958_MBC_SEL_MASK, | ||
647 | mbc << WM8958_MBC_SEL_SHIFT | | ||
648 | WM8958_MBC_ENA); | ||
649 | } else { | ||
650 | /* If the DSP is already stopped then noop */ | ||
651 | if (!(reg & WM8958_DSP2_ENA)) | ||
652 | return; | ||
653 | |||
654 | snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, | ||
655 | WM8958_MBC_ENA, 0); | ||
656 | snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, | ||
657 | WM8958_DSP2_ENA, 0); | ||
658 | snd_soc_update_bits(codec, WM8994_CLOCKING_1, | ||
659 | WM8958_DSP2CLK_ENA, 0); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | static int wm8958_aif_ev(struct snd_soc_dapm_widget *w, | ||
664 | struct snd_kcontrol *kcontrol, int event) | ||
665 | { | ||
666 | struct snd_soc_codec *codec = w->codec; | ||
667 | int mbc; | ||
668 | |||
669 | switch (w->shift) { | ||
670 | case 13: | ||
671 | case 12: | ||
672 | mbc = 2; | ||
673 | break; | ||
674 | case 11: | ||
675 | case 10: | ||
676 | mbc = 1; | ||
677 | break; | ||
678 | case 9: | ||
679 | case 8: | ||
680 | mbc = 0; | ||
681 | break; | ||
682 | default: | ||
683 | BUG(); | ||
684 | return -EINVAL; | ||
685 | } | ||
686 | |||
687 | switch (event) { | ||
688 | case SND_SOC_DAPM_POST_PMU: | ||
689 | wm8958_mbc_apply(codec, mbc, 1); | ||
690 | break; | ||
691 | case SND_SOC_DAPM_POST_PMD: | ||
692 | wm8958_mbc_apply(codec, mbc, 0); | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, | ||
700 | struct snd_ctl_elem_value *ucontrol) | ||
701 | { | ||
702 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
703 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
704 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
705 | int value = ucontrol->value.integer.value[0]; | ||
706 | int reg; | ||
707 | |||
708 | /* Don't allow on the fly reconfiguration */ | ||
709 | reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
710 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | ||
711 | return -EBUSY; | ||
712 | |||
713 | if (value >= pdata->num_mbc_cfgs) | ||
714 | return -EINVAL; | ||
715 | |||
716 | wm8994->mbc_cfg = value; | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol, | ||
722 | struct snd_ctl_elem_value *ucontrol) | ||
723 | { | ||
724 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
725 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
726 | |||
727 | ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg; | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int wm8958_mbc_info(struct snd_kcontrol *kcontrol, | ||
733 | struct snd_ctl_elem_info *uinfo) | ||
734 | { | ||
735 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
736 | uinfo->count = 1; | ||
737 | uinfo->value.integer.min = 0; | ||
738 | uinfo->value.integer.max = 1; | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static int wm8958_mbc_get(struct snd_kcontrol *kcontrol, | ||
743 | struct snd_ctl_elem_value *ucontrol) | ||
744 | { | ||
745 | int mbc = kcontrol->private_value; | ||
746 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
747 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
748 | |||
749 | ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc]; | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int wm8958_mbc_put(struct snd_kcontrol *kcontrol, | ||
755 | struct snd_ctl_elem_value *ucontrol) | ||
756 | { | ||
757 | int mbc = kcontrol->private_value; | ||
758 | int i; | ||
759 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
760 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
761 | |||
762 | if (ucontrol->value.integer.value[0] > 1) | ||
763 | return -EINVAL; | ||
764 | |||
765 | for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) { | ||
766 | if (mbc != i && wm8994->mbc_ena[i]) { | ||
767 | dev_dbg(codec->dev, "MBC %d active already\n", mbc); | ||
768 | return -EBUSY; | ||
769 | } | ||
770 | } | ||
771 | |||
772 | wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0]; | ||
773 | |||
774 | wm8958_mbc_apply(codec, mbc, wm8994->mbc_ena[mbc]); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | #define WM8958_MBC_SWITCH(xname, xval) {\ | ||
780 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
781 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
782 | .info = wm8958_mbc_info, \ | ||
783 | .get = wm8958_mbc_get, .put = wm8958_mbc_put, \ | ||
784 | .private_value = xval } | ||
785 | |||
786 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { | 528 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { |
787 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, | 529 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, |
788 | WM8994_AIF1_ADC1_RIGHT_VOLUME, | 530 | WM8994_AIF1_ADC1_RIGHT_VOLUME, |
@@ -924,9 +666,6 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
924 | 666 | ||
925 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { | 667 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { |
926 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), | 668 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), |
927 | WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0), | ||
928 | WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1), | ||
929 | WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2), | ||
930 | }; | 669 | }; |
931 | 670 | ||
932 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 671 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
@@ -1032,6 +771,9 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w, | |||
1032 | break; | 771 | break; |
1033 | } | 772 | } |
1034 | 773 | ||
774 | /* We may also have postponed startup of DSP, handle that. */ | ||
775 | wm8958_aif_ev(w, kcontrol, event); | ||
776 | |||
1035 | return 0; | 777 | return 0; |
1036 | } | 778 | } |
1037 | 779 | ||
@@ -1135,7 +877,8 @@ static const char *hp_mux_text[] = { | |||
1135 | static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol, | 877 | static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol, |
1136 | struct snd_ctl_elem_value *ucontrol) | 878 | struct snd_ctl_elem_value *ucontrol) |
1137 | { | 879 | { |
1138 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | 880 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
881 | struct snd_soc_dapm_widget *w = wlist->widgets[0]; | ||
1139 | struct snd_soc_codec *codec = w->codec; | 882 | struct snd_soc_codec *codec = w->codec; |
1140 | int ret; | 883 | int ret; |
1141 | 884 | ||
@@ -1262,7 +1005,8 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | |||
1262 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, | 1005 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, |
1263 | struct snd_ctl_elem_value *ucontrol) | 1006 | struct snd_ctl_elem_value *ucontrol) |
1264 | { | 1007 | { |
1265 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | 1008 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1009 | struct snd_soc_dapm_widget *w = wlist->widgets[0]; | ||
1266 | struct snd_soc_codec *codec = w->codec; | 1010 | struct snd_soc_codec *codec = w->codec; |
1267 | int ret; | 1011 | int ret; |
1268 | 1012 | ||
@@ -2180,6 +1924,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2180 | WM8994_VMID_BUF_ENA | | 1924 | WM8994_VMID_BUF_ENA | |
2181 | WM8994_VMID_RAMP_MASK, 0); | 1925 | WM8994_VMID_RAMP_MASK, 0); |
2182 | 1926 | ||
1927 | wm8994->cur_fw = NULL; | ||
1928 | |||
2183 | pm_runtime_put(codec->dev); | 1929 | pm_runtime_put(codec->dev); |
2184 | } | 1930 | } |
2185 | break; | 1931 | break; |
@@ -2672,11 +2418,22 @@ static struct snd_soc_dai_driver wm8994_dai[] = { | |||
2672 | static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) | 2418 | static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) |
2673 | { | 2419 | { |
2674 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2420 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2421 | struct wm8994 *control = codec->control_data; | ||
2675 | int i, ret; | 2422 | int i, ret; |
2676 | 2423 | ||
2424 | switch (control->type) { | ||
2425 | case WM8994: | ||
2426 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); | ||
2427 | break; | ||
2428 | case WM8958: | ||
2429 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
2430 | WM8958_MICD_ENA, 0); | ||
2431 | break; | ||
2432 | } | ||
2433 | |||
2677 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 2434 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
2678 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | 2435 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
2679 | sizeof(struct fll_config)); | 2436 | sizeof(struct wm8994_fll_config)); |
2680 | ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); | 2437 | ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); |
2681 | if (ret < 0) | 2438 | if (ret < 0) |
2682 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", | 2439 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", |
@@ -2691,6 +2448,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) | |||
2691 | static int wm8994_resume(struct snd_soc_codec *codec) | 2448 | static int wm8994_resume(struct snd_soc_codec *codec) |
2692 | { | 2449 | { |
2693 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2450 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2451 | struct wm8994 *control = codec->control_data; | ||
2694 | int i, ret; | 2452 | int i, ret; |
2695 | unsigned int val, mask; | 2453 | unsigned int val, mask; |
2696 | 2454 | ||
@@ -2729,6 +2487,19 @@ static int wm8994_resume(struct snd_soc_codec *codec) | |||
2729 | i + 1, ret); | 2487 | i + 1, ret); |
2730 | } | 2488 | } |
2731 | 2489 | ||
2490 | switch (control->type) { | ||
2491 | case WM8994: | ||
2492 | if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) | ||
2493 | snd_soc_update_bits(codec, WM8994_MICBIAS, | ||
2494 | WM8994_MICD_ENA, WM8994_MICD_ENA); | ||
2495 | break; | ||
2496 | case WM8958: | ||
2497 | if (wm8994->jack_cb) | ||
2498 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
2499 | WM8958_MICD_ENA, WM8958_MICD_ENA); | ||
2500 | break; | ||
2501 | } | ||
2502 | |||
2732 | return 0; | 2503 | return 0; |
2733 | } | 2504 | } |
2734 | #else | 2505 | #else |
@@ -2862,34 +2633,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
2862 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | 2633 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", |
2863 | pdata->num_retune_mobile_cfgs); | 2634 | pdata->num_retune_mobile_cfgs); |
2864 | 2635 | ||
2865 | if (pdata->num_mbc_cfgs) { | ||
2866 | struct snd_kcontrol_new control[] = { | ||
2867 | SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum, | ||
2868 | wm8958_get_mbc_enum, wm8958_put_mbc_enum), | ||
2869 | }; | ||
2870 | |||
2871 | /* We need an array of texts for the enum API */ | ||
2872 | wm8994->mbc_texts = kmalloc(sizeof(char *) | ||
2873 | * pdata->num_mbc_cfgs, GFP_KERNEL); | ||
2874 | if (!wm8994->mbc_texts) { | ||
2875 | dev_err(wm8994->codec->dev, | ||
2876 | "Failed to allocate %d MBC config texts\n", | ||
2877 | pdata->num_mbc_cfgs); | ||
2878 | return; | ||
2879 | } | ||
2880 | |||
2881 | for (i = 0; i < pdata->num_mbc_cfgs; i++) | ||
2882 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; | ||
2883 | |||
2884 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | ||
2885 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | ||
2886 | |||
2887 | ret = snd_soc_add_controls(wm8994->codec, control, 1); | ||
2888 | if (ret != 0) | ||
2889 | dev_err(wm8994->codec->dev, | ||
2890 | "Failed to add MBC mode controls: %d\n", ret); | ||
2891 | } | ||
2892 | |||
2893 | if (pdata->num_retune_mobile_cfgs) | 2636 | if (pdata->num_retune_mobile_cfgs) |
2894 | wm8994_handle_retune_mobile_pdata(wm8994); | 2637 | wm8994_handle_retune_mobile_pdata(wm8994); |
2895 | else | 2638 | else |
@@ -3343,14 +3086,23 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3343 | case WM8958: | 3086 | case WM8958: |
3344 | snd_soc_add_controls(codec, wm8958_snd_controls, | 3087 | snd_soc_add_controls(codec, wm8958_snd_controls, |
3345 | ARRAY_SIZE(wm8958_snd_controls)); | 3088 | ARRAY_SIZE(wm8958_snd_controls)); |
3346 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, | ||
3347 | ARRAY_SIZE(wm8994_lateclk_widgets)); | ||
3348 | snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, | ||
3349 | ARRAY_SIZE(wm8994_adc_widgets)); | ||
3350 | snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, | ||
3351 | ARRAY_SIZE(wm8994_dac_widgets)); | ||
3352 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, | 3089 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, |
3353 | ARRAY_SIZE(wm8958_dapm_widgets)); | 3090 | ARRAY_SIZE(wm8958_dapm_widgets)); |
3091 | if (wm8994->revision < 1) { | ||
3092 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, | ||
3093 | ARRAY_SIZE(wm8994_lateclk_revd_widgets)); | ||
3094 | snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, | ||
3095 | ARRAY_SIZE(wm8994_adc_revd_widgets)); | ||
3096 | snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets, | ||
3097 | ARRAY_SIZE(wm8994_dac_revd_widgets)); | ||
3098 | } else { | ||
3099 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, | ||
3100 | ARRAY_SIZE(wm8994_lateclk_widgets)); | ||
3101 | snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, | ||
3102 | ARRAY_SIZE(wm8994_adc_widgets)); | ||
3103 | snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, | ||
3104 | ARRAY_SIZE(wm8994_dac_widgets)); | ||
3105 | } | ||
3354 | break; | 3106 | break; |
3355 | } | 3107 | } |
3356 | 3108 | ||
@@ -3374,10 +3126,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3374 | } | 3126 | } |
3375 | break; | 3127 | break; |
3376 | case WM8958: | 3128 | case WM8958: |
3377 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, | 3129 | if (wm8994->revision < 1) { |
3378 | ARRAY_SIZE(wm8994_lateclk_intercon)); | 3130 | snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, |
3379 | snd_soc_dapm_add_routes(dapm, wm8958_intercon, | 3131 | ARRAY_SIZE(wm8994_revd_intercon)); |
3380 | ARRAY_SIZE(wm8958_intercon)); | 3132 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, |
3133 | ARRAY_SIZE(wm8994_lateclk_revd_intercon)); | ||
3134 | } else { | ||
3135 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, | ||
3136 | ARRAY_SIZE(wm8994_lateclk_intercon)); | ||
3137 | snd_soc_dapm_add_routes(dapm, wm8958_intercon, | ||
3138 | ARRAY_SIZE(wm8958_intercon)); | ||
3139 | } | ||
3140 | |||
3141 | wm8958_dsp2_init(codec); | ||
3381 | break; | 3142 | break; |
3382 | } | 3143 | } |
3383 | 3144 | ||
@@ -3420,6 +3181,12 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3420 | free_irq(wm8994->micdet_irq, wm8994); | 3181 | free_irq(wm8994->micdet_irq, wm8994); |
3421 | break; | 3182 | break; |
3422 | } | 3183 | } |
3184 | if (wm8994->mbc) | ||
3185 | release_firmware(wm8994->mbc); | ||
3186 | if (wm8994->mbc_vss) | ||
3187 | release_firmware(wm8994->mbc_vss); | ||
3188 | if (wm8994->enh_eq) | ||
3189 | release_firmware(wm8994->enh_eq); | ||
3423 | kfree(wm8994->retune_mobile_texts); | 3190 | kfree(wm8994->retune_mobile_texts); |
3424 | kfree(wm8994->drc_texts); | 3191 | kfree(wm8994->drc_texts); |
3425 | kfree(wm8994); | 3192 | kfree(wm8994); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 999b8851226b..0a1db04b73bd 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -10,6 +10,9 @@ | |||
10 | #define _WM8994_H | 10 | #define _WM8994_H |
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | #include <linux/firmware.h> | ||
14 | |||
15 | #include "wm_hubs.h" | ||
13 | 16 | ||
14 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ | 17 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ |
15 | #define WM8994_SYSCLK_MCLK1 1 | 18 | #define WM8994_SYSCLK_MCLK1 1 |
@@ -45,4 +48,98 @@ struct wm8994_access_mask { | |||
45 | extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE]; | 48 | extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE]; |
46 | extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE]; | 49 | extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE]; |
47 | 50 | ||
51 | int wm8958_aif_ev(struct snd_soc_dapm_widget *w, | ||
52 | struct snd_kcontrol *kcontrol, int event); | ||
53 | |||
54 | void wm8958_dsp2_init(struct snd_soc_codec *codec); | ||
55 | |||
56 | struct wm8994_micdet { | ||
57 | struct snd_soc_jack *jack; | ||
58 | int det; | ||
59 | int shrt; | ||
60 | }; | ||
61 | |||
62 | /* codec private data */ | ||
63 | struct wm8994_fll_config { | ||
64 | int src; | ||
65 | int in; | ||
66 | int out; | ||
67 | }; | ||
68 | |||
69 | #define WM8994_NUM_DRC 3 | ||
70 | #define WM8994_NUM_EQ 3 | ||
71 | |||
72 | struct wm8994_priv { | ||
73 | struct wm_hubs_data hubs; | ||
74 | enum snd_soc_control_type control_type; | ||
75 | void *control_data; | ||
76 | struct snd_soc_codec *codec; | ||
77 | int sysclk[2]; | ||
78 | int sysclk_rate[2]; | ||
79 | int mclk[2]; | ||
80 | int aifclk[2]; | ||
81 | struct wm8994_fll_config fll[2], fll_suspend[2]; | ||
82 | |||
83 | int dac_rates[2]; | ||
84 | int lrclk_shared[2]; | ||
85 | |||
86 | int mbc_ena[3]; | ||
87 | int hpf1_ena[3]; | ||
88 | int hpf2_ena[3]; | ||
89 | int vss_ena[3]; | ||
90 | int enh_eq_ena[3]; | ||
91 | |||
92 | /* Platform dependant DRC configuration */ | ||
93 | const char **drc_texts; | ||
94 | int drc_cfg[WM8994_NUM_DRC]; | ||
95 | struct soc_enum drc_enum; | ||
96 | |||
97 | /* Platform dependant ReTune mobile configuration */ | ||
98 | int num_retune_mobile_texts; | ||
99 | const char **retune_mobile_texts; | ||
100 | int retune_mobile_cfg[WM8994_NUM_EQ]; | ||
101 | struct soc_enum retune_mobile_enum; | ||
102 | |||
103 | /* Platform dependant MBC configuration */ | ||
104 | int mbc_cfg; | ||
105 | const char **mbc_texts; | ||
106 | struct soc_enum mbc_enum; | ||
107 | |||
108 | /* Platform dependant VSS configuration */ | ||
109 | int vss_cfg; | ||
110 | const char **vss_texts; | ||
111 | struct soc_enum vss_enum; | ||
112 | |||
113 | /* Platform dependant VSS HPF configuration */ | ||
114 | int vss_hpf_cfg; | ||
115 | const char **vss_hpf_texts; | ||
116 | struct soc_enum vss_hpf_enum; | ||
117 | |||
118 | /* Platform dependant enhanced EQ configuration */ | ||
119 | int enh_eq_cfg; | ||
120 | const char **enh_eq_texts; | ||
121 | struct soc_enum enh_eq_enum; | ||
122 | |||
123 | struct wm8994_micdet micdet[2]; | ||
124 | |||
125 | wm8958_micdet_cb jack_cb; | ||
126 | void *jack_cb_data; | ||
127 | int micdet_irq; | ||
128 | |||
129 | int revision; | ||
130 | struct wm8994_pdata *pdata; | ||
131 | |||
132 | unsigned int aif1clk_enable:1; | ||
133 | unsigned int aif2clk_enable:1; | ||
134 | |||
135 | unsigned int aif1clk_disable:1; | ||
136 | unsigned int aif2clk_disable:1; | ||
137 | |||
138 | int dsp_active; | ||
139 | const struct firmware *cur_fw; | ||
140 | const struct firmware *mbc; | ||
141 | const struct firmware *mbc_vss; | ||
142 | const struct firmware *enh_eq; | ||
143 | }; | ||
144 | |||
48 | #endif | 145 | #endif |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 67eaaecbb42e..5ad873fda814 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -305,11 +305,11 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, | |||
305 | static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, | 305 | static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, |
306 | struct snd_ctl_elem_value *ucontrol) | 306 | struct snd_ctl_elem_value *ucontrol) |
307 | { | 307 | { |
308 | struct snd_soc_dapm_widget *w; | 308 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
309 | struct snd_soc_dapm_widget *w = wlist->widgets[0]; | ||
309 | struct snd_soc_codec *codec; | 310 | struct snd_soc_codec *codec; |
310 | int ret; | 311 | int ret; |
311 | 312 | ||
312 | w = snd_kcontrol_chip(kcontrol); | ||
313 | codec = w->codec; | 313 | codec = w->codec; |
314 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | 314 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); |
315 | wm8995_update_class_w(codec); | 315 | wm8995_update_class_w(codec); |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 47b357adabdd..646b58dda849 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -142,7 +142,7 @@ static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { | |||
142 | * constantly enabled, we use the mutes on those inputs to simulate such | 142 | * constantly enabled, we use the mutes on those inputs to simulate such |
143 | * controls. | 143 | * controls. |
144 | */ | 144 | */ |
145 | static const struct snd_soc_dapm_route audio_map[] = { | 145 | static const struct snd_soc_dapm_route wm9705_audio_map[] = { |
146 | /* HP mixer */ | 146 | /* HP mixer */ |
147 | {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, | 147 | {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, |
148 | {"HP Mixer", "CD Playback Switch", "CD PGA"}, | 148 | {"HP Mixer", "CD Playback Switch", "CD PGA"}, |
@@ -200,17 +200,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
200 | {"Right ADC", NULL, "ADC PGA"}, | 200 | {"Right ADC", NULL, "ADC PGA"}, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static int wm9705_add_widgets(struct snd_soc_codec *codec) | ||
204 | { | ||
205 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
206 | |||
207 | snd_soc_dapm_new_controls(dapm, wm9705_dapm_widgets, | ||
208 | ARRAY_SIZE(wm9705_dapm_widgets)); | ||
209 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* We use a register cache to enhance read performance. */ | 203 | /* We use a register cache to enhance read performance. */ |
215 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | 204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) |
216 | { | 205 | { |
@@ -364,7 +353,6 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) | |||
364 | 353 | ||
365 | snd_soc_add_controls(codec, wm9705_snd_ac97_controls, | 354 | snd_soc_add_controls(codec, wm9705_snd_ac97_controls, |
366 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | 355 | ARRAY_SIZE(wm9705_snd_ac97_controls)); |
367 | wm9705_add_widgets(codec); | ||
368 | 356 | ||
369 | return 0; | 357 | return 0; |
370 | 358 | ||
@@ -390,6 +378,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { | |||
390 | .reg_word_size = sizeof(u16), | 378 | .reg_word_size = sizeof(u16), |
391 | .reg_cache_step = 2, | 379 | .reg_cache_step = 2, |
392 | .reg_cache_default = wm9705_reg, | 380 | .reg_cache_default = wm9705_reg, |
381 | .dapm_widgets = wm9705_dapm_widgets, | ||
382 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), | ||
383 | .dapm_routes = wm9705_audio_map, | ||
384 | .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), | ||
393 | }; | 385 | }; |
394 | 386 | ||
395 | static __devinit int wm9705_probe(struct platform_device *pdev) | 387 | static __devinit int wm9705_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index bf5d4ef1a2a6..90117f8156e8 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -332,7 +332,7 @@ SND_SOC_DAPM_INPUT("MIC1"), | |||
332 | SND_SOC_DAPM_INPUT("MIC2"), | 332 | SND_SOC_DAPM_INPUT("MIC2"), |
333 | }; | 333 | }; |
334 | 334 | ||
335 | static const struct snd_soc_dapm_route audio_map[] = { | 335 | static const struct snd_soc_dapm_route wm9712_audio_map[] = { |
336 | /* virtual mixer - mixes left & right channels for spk and mono */ | 336 | /* virtual mixer - mixes left & right channels for spk and mono */ |
337 | {"AC97 Mixer", NULL, "Left DAC"}, | 337 | {"AC97 Mixer", NULL, "Left DAC"}, |
338 | {"AC97 Mixer", NULL, "Right DAC"}, | 338 | {"AC97 Mixer", NULL, "Right DAC"}, |
@@ -429,17 +429,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
429 | {"ROUT2", NULL, "Speaker PGA"}, | 429 | {"ROUT2", NULL, "Speaker PGA"}, |
430 | }; | 430 | }; |
431 | 431 | ||
432 | static int wm9712_add_widgets(struct snd_soc_codec *codec) | ||
433 | { | ||
434 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
435 | |||
436 | snd_soc_dapm_new_controls(dapm, wm9712_dapm_widgets, | ||
437 | ARRAY_SIZE(wm9712_dapm_widgets)); | ||
438 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 432 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
444 | unsigned int reg) | 433 | unsigned int reg) |
445 | { | 434 | { |
@@ -651,7 +640,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
651 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 640 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
652 | snd_soc_add_controls(codec, wm9712_snd_ac97_controls, | 641 | snd_soc_add_controls(codec, wm9712_snd_ac97_controls, |
653 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | 642 | ARRAY_SIZE(wm9712_snd_ac97_controls)); |
654 | wm9712_add_widgets(codec); | ||
655 | 643 | ||
656 | return 0; | 644 | return 0; |
657 | 645 | ||
@@ -678,6 +666,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
678 | .reg_word_size = sizeof(u16), | 666 | .reg_word_size = sizeof(u16), |
679 | .reg_cache_step = 2, | 667 | .reg_cache_step = 2, |
680 | .reg_cache_default = wm9712_reg, | 668 | .reg_cache_default = wm9712_reg, |
669 | .dapm_widgets = wm9712_dapm_widgets, | ||
670 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), | ||
671 | .dapm_routes = wm9712_audio_map, | ||
672 | .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), | ||
681 | }; | 673 | }; |
682 | 674 | ||
683 | static __devinit int wm9712_probe(struct platform_device *pdev) | 675 | static __devinit int wm9712_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 38ed98558718..7167cb6787db 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -487,7 +487,7 @@ SND_SOC_DAPM_INPUT("MIC2B"), | |||
487 | SND_SOC_DAPM_VMID("VMID"), | 487 | SND_SOC_DAPM_VMID("VMID"), |
488 | }; | 488 | }; |
489 | 489 | ||
490 | static const struct snd_soc_dapm_route audio_map[] = { | 490 | static const struct snd_soc_dapm_route wm9713_audio_map[] = { |
491 | /* left HP mixer */ | 491 | /* left HP mixer */ |
492 | {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"}, | 492 | {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"}, |
493 | {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, | 493 | {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, |
@@ -644,18 +644,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
644 | {"Capture Mono Mux", "Right", "Right Capture Source"}, | 644 | {"Capture Mono Mux", "Right", "Right Capture Source"}, |
645 | }; | 645 | }; |
646 | 646 | ||
647 | static int wm9713_add_widgets(struct snd_soc_codec *codec) | ||
648 | { | ||
649 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
650 | |||
651 | snd_soc_dapm_new_controls(dapm, wm9713_dapm_widgets, | ||
652 | ARRAY_SIZE(wm9713_dapm_widgets)); | ||
653 | |||
654 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 647 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
660 | unsigned int reg) | 648 | unsigned int reg) |
661 | { | 649 | { |
@@ -1231,7 +1219,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1231 | 1219 | ||
1232 | snd_soc_add_controls(codec, wm9713_snd_ac97_controls, | 1220 | snd_soc_add_controls(codec, wm9713_snd_ac97_controls, |
1233 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | 1221 | ARRAY_SIZE(wm9713_snd_ac97_controls)); |
1234 | wm9713_add_widgets(codec); | ||
1235 | 1222 | ||
1236 | return 0; | 1223 | return 0; |
1237 | 1224 | ||
@@ -1262,6 +1249,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1262 | .reg_word_size = sizeof(u16), | 1249 | .reg_word_size = sizeof(u16), |
1263 | .reg_cache_step = 2, | 1250 | .reg_cache_step = 2, |
1264 | .reg_cache_default = wm9713_reg, | 1251 | .reg_cache_default = wm9713_reg, |
1252 | .dapm_widgets = wm9713_dapm_widgets, | ||
1253 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), | ||
1254 | .dapm_routes = wm9713_audio_map, | ||
1255 | .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), | ||
1265 | }; | 1256 | }; |
1266 | 1257 | ||
1267 | static __devinit int wm9713_probe(struct platform_device *pdev) | 1258 | static __devinit int wm9713_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 4005e9af5d61..e55b298c14a0 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -787,17 +787,17 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
787 | static const struct snd_soc_dapm_route lineout1_diff_routes[] = { | 787 | static const struct snd_soc_dapm_route lineout1_diff_routes[] = { |
788 | { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, | 788 | { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, |
789 | { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, | 789 | { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, |
790 | { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" }, | 790 | { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" }, |
791 | 791 | ||
792 | { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, | 792 | { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, |
793 | { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, | 793 | { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, |
794 | }; | 794 | }; |
795 | 795 | ||
796 | static const struct snd_soc_dapm_route lineout1_se_routes[] = { | 796 | static const struct snd_soc_dapm_route lineout1_se_routes[] = { |
797 | { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" }, | 797 | { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, |
798 | { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" }, | 798 | { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, |
799 | 799 | ||
800 | { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" }, | 800 | { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, |
801 | 801 | ||
802 | { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, | 802 | { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, |
803 | { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, | 803 | { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, |
@@ -806,17 +806,17 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = { | |||
806 | static const struct snd_soc_dapm_route lineout2_diff_routes[] = { | 806 | static const struct snd_soc_dapm_route lineout2_diff_routes[] = { |
807 | { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, | 807 | { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, |
808 | { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, | 808 | { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, |
809 | { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" }, | 809 | { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" }, |
810 | 810 | ||
811 | { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, | 811 | { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, |
812 | { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, | 812 | { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, |
813 | }; | 813 | }; |
814 | 814 | ||
815 | static const struct snd_soc_dapm_route lineout2_se_routes[] = { | 815 | static const struct snd_soc_dapm_route lineout2_se_routes[] = { |
816 | { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" }, | 816 | { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, |
817 | { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" }, | 817 | { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, |
818 | 818 | ||
819 | { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" }, | 819 | { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, |
820 | 820 | ||
821 | { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, | 821 | { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, |
822 | { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, | 822 | { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, |
@@ -836,17 +836,21 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) | |||
836 | snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, | 836 | snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, |
837 | WM8993_IN2_VU, WM8993_IN2_VU); | 837 | WM8993_IN2_VU, WM8993_IN2_VU); |
838 | 838 | ||
839 | snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_LEFT, | ||
840 | WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); | ||
839 | snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, | 841 | snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, |
840 | WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); | 842 | WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); |
841 | 843 | ||
842 | snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, | 844 | snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, |
843 | WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC); | 845 | WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC, |
846 | WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC); | ||
844 | snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, | 847 | snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, |
845 | WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, | 848 | WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, |
846 | WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); | 849 | WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); |
847 | 850 | ||
848 | snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, | 851 | snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, |
849 | WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC); | 852 | WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU, |
853 | WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU); | ||
850 | snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, | 854 | snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, |
851 | WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, | 855 | WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, |
852 | WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); | 856 | WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index a5af834c8ef5..8566238db2a5 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -434,17 +434,21 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
434 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 434 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
435 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 435 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
436 | 436 | ||
437 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26)); | 437 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, |
438 | ACLKX | AHCLKX | AFSX); | ||
438 | break; | 439 | break; |
439 | case SND_SOC_DAIFMT_CBM_CFS: | 440 | case SND_SOC_DAIFMT_CBM_CFS: |
440 | /* codec is clock master and frame slave */ | 441 | /* codec is clock master and frame slave */ |
441 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); | 442 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); |
442 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); | 443 | mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); |
443 | 444 | ||
444 | mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 445 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
445 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 446 | mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
446 | 447 | ||
447 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26)); | 448 | mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, |
449 | ACLKX | ACLKR); | ||
450 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, | ||
451 | AFSX | AFSR); | ||
448 | break; | 452 | break; |
449 | case SND_SOC_DAIFMT_CBM_CFM: | 453 | case SND_SOC_DAIFMT_CBM_CFM: |
450 | /* codec is clock and frame master */ | 454 | /* codec is clock and frame master */ |
@@ -454,7 +458,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
454 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); | 458 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); |
455 | mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); | 459 | mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); |
456 | 460 | ||
457 | mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26)); | 461 | mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, |
462 | ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); | ||
458 | break; | 463 | break; |
459 | 464 | ||
460 | default: | 465 | default: |
@@ -644,7 +649,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | |||
644 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); | 649 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); |
645 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); | 650 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); |
646 | 651 | ||
647 | if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) | 652 | if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) |
648 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, | 653 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, |
649 | FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); | 654 | FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); |
650 | else | 655 | else |
@@ -660,7 +665,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | |||
660 | AHCLKRE); | 665 | AHCLKRE); |
661 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); | 666 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); |
662 | 667 | ||
663 | if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) | 668 | if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) |
664 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, | 669 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, |
665 | FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); | 670 | FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); |
666 | else | 671 | else |
@@ -904,6 +909,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
904 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 909 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
905 | dma_data->asp_chan_q = pdata->asp_chan_q; | 910 | dma_data->asp_chan_q = pdata->asp_chan_q; |
906 | dma_data->ram_chan_q = pdata->ram_chan_q; | 911 | dma_data->ram_chan_q = pdata->ram_chan_q; |
912 | dma_data->sram_size = pdata->sram_size_playback; | ||
907 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + | 913 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + |
908 | mem->start); | 914 | mem->start); |
909 | 915 | ||
@@ -920,6 +926,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
920 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 926 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; |
921 | dma_data->asp_chan_q = pdata->asp_chan_q; | 927 | dma_data->asp_chan_q = pdata->asp_chan_q; |
922 | dma_data->ram_chan_q = pdata->ram_chan_q; | 928 | dma_data->ram_chan_q = pdata->ram_chan_q; |
929 | dma_data->sram_size = pdata->sram_size_capture; | ||
923 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + | 930 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + |
924 | mem->start); | 931 | mem->start); |
925 | 932 | ||
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index ac2ded969253..5b13feca7537 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c | |||
@@ -667,12 +667,6 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
667 | if (res) | 667 | if (res) |
668 | ssi->dma_params_rx.dma = res->start; | 668 | ssi->dma_params_rx.dma = res->start; |
669 | 669 | ||
670 | if ((cpu_is_mx27() || cpu_is_mx21()) && | ||
671 | !(ssi->flags & IMX_SSI_USE_AC97) && | ||
672 | (ssi->flags & IMX_SSI_DMA)) { | ||
673 | ssi->flags |= IMX_SSI_DMA; | ||
674 | } | ||
675 | |||
676 | platform_set_drvdata(pdev, ssi); | 670 | platform_set_drvdata(pdev, ssi); |
677 | 671 | ||
678 | ret = snd_soc_register_dai(&pdev->dev, dai); | 672 | ret = snd_soc_register_dai(&pdev->dev, dai); |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 419bf4f5534a..cd22a54b2f14 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -133,7 +133,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, | |||
133 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 133 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
134 | uint32_t conf; | 134 | uint32_t conf; |
135 | 135 | ||
136 | if (!dai->active) | 136 | if (dai->active) |
137 | return; | 137 | return; |
138 | 138 | ||
139 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); | 139 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); |
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index 49723e3e7e38..c5fc339f68f1 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c | |||
@@ -27,11 +27,7 @@ | |||
27 | static int qi_lb60_spk_event(struct snd_soc_dapm_widget *widget, | 27 | static int qi_lb60_spk_event(struct snd_soc_dapm_widget *widget, |
28 | struct snd_kcontrol *ctrl, int event) | 28 | struct snd_kcontrol *ctrl, int event) |
29 | { | 29 | { |
30 | int on = 0; | 30 | int on = !SND_SOC_DAPM_EVENT_OFF(event); |
31 | if (event & SND_SOC_DAPM_POST_PMU) | ||
32 | on = 1; | ||
33 | else if (event & SND_SOC_DAPM_PRE_PMD) | ||
34 | on = 0; | ||
35 | 31 | ||
36 | gpio_set_value(QI_LB60_SND_GPIO, on); | 32 | gpio_set_value(QI_LB60_SND_GPIO, on); |
37 | gpio_set_value(QI_LB60_AMP_GPIO, on); | 33 | gpio_set_value(QI_LB60_AMP_GPIO, on); |
@@ -70,12 +66,6 @@ static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd) | |||
70 | return ret; | 66 | return ret; |
71 | } | 67 | } |
72 | 68 | ||
73 | snd_soc_dapm_new_controls(dapm, qi_lb60_widgets, | ||
74 | ARRAY_SIZE(qi_lb60_widgets)); | ||
75 | snd_soc_dapm_add_routes(dapm, qi_lb60_routes, | ||
76 | ARRAY_SIZE(qi_lb60_routes)); | ||
77 | snd_soc_dapm_sync(dapm); | ||
78 | |||
79 | return 0; | 69 | return 0; |
80 | } | 70 | } |
81 | 71 | ||
@@ -93,10 +83,20 @@ static struct snd_soc_card qi_lb60 = { | |||
93 | .name = "QI LB60", | 83 | .name = "QI LB60", |
94 | .dai_link = &qi_lb60_dai, | 84 | .dai_link = &qi_lb60_dai, |
95 | .num_links = 1, | 85 | .num_links = 1, |
86 | |||
87 | .dapm_widgets = qi_lb60_widgets, | ||
88 | .num_dapm_widgets = ARRAY_SIZE(qi_lb60_widgets), | ||
89 | .dapm_routes = qi_lb60_routes, | ||
90 | .num_dapm_routes = ARRAY_SIZE(qi_lb60_routes), | ||
96 | }; | 91 | }; |
97 | 92 | ||
98 | static struct platform_device *qi_lb60_snd_device; | 93 | static struct platform_device *qi_lb60_snd_device; |
99 | 94 | ||
95 | static const struct gpio qi_lb60_gpios[] = { | ||
96 | { QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" }, | ||
97 | { QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" }, | ||
98 | }; | ||
99 | |||
100 | static int __init qi_lb60_init(void) | 100 | static int __init qi_lb60_init(void) |
101 | { | 101 | { |
102 | int ret; | 102 | int ret; |
@@ -106,23 +106,12 @@ static int __init qi_lb60_init(void) | |||
106 | if (!qi_lb60_snd_device) | 106 | if (!qi_lb60_snd_device) |
107 | return -ENOMEM; | 107 | return -ENOMEM; |
108 | 108 | ||
109 | ret = gpio_request(QI_LB60_SND_GPIO, "SND"); | 109 | ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |
110 | if (ret) { | 110 | if (ret) { |
111 | pr_err("qi_lb60 snd: Failed to request SND GPIO(%d): %d\n", | 111 | pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret); |
112 | QI_LB60_SND_GPIO, ret); | ||
113 | goto err_device_put; | 112 | goto err_device_put; |
114 | } | 113 | } |
115 | 114 | ||
116 | ret = gpio_request(QI_LB60_AMP_GPIO, "AMP"); | ||
117 | if (ret) { | ||
118 | pr_err("qi_lb60 snd: Failed to request AMP GPIO(%d): %d\n", | ||
119 | QI_LB60_AMP_GPIO, ret); | ||
120 | goto err_gpio_free_snd; | ||
121 | } | ||
122 | |||
123 | gpio_direction_output(QI_LB60_SND_GPIO, 0); | ||
124 | gpio_direction_output(QI_LB60_AMP_GPIO, 0); | ||
125 | |||
126 | platform_set_drvdata(qi_lb60_snd_device, &qi_lb60); | 115 | platform_set_drvdata(qi_lb60_snd_device, &qi_lb60); |
127 | 116 | ||
128 | ret = platform_device_add(qi_lb60_snd_device); | 117 | ret = platform_device_add(qi_lb60_snd_device); |
@@ -135,10 +124,8 @@ static int __init qi_lb60_init(void) | |||
135 | 124 | ||
136 | err_unset_pdata: | 125 | err_unset_pdata: |
137 | platform_set_drvdata(qi_lb60_snd_device, NULL); | 126 | platform_set_drvdata(qi_lb60_snd_device, NULL); |
138 | /*err_gpio_free_amp:*/ | 127 | /*err_gpio_free_array:*/ |
139 | gpio_free(QI_LB60_AMP_GPIO); | 128 | gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |
140 | err_gpio_free_snd: | ||
141 | gpio_free(QI_LB60_SND_GPIO); | ||
142 | err_device_put: | 129 | err_device_put: |
143 | platform_device_put(qi_lb60_snd_device); | 130 | platform_device_put(qi_lb60_snd_device); |
144 | 131 | ||
@@ -148,9 +135,8 @@ module_init(qi_lb60_init); | |||
148 | 135 | ||
149 | static void __exit qi_lb60_exit(void) | 136 | static void __exit qi_lb60_exit(void) |
150 | { | 137 | { |
151 | gpio_free(QI_LB60_AMP_GPIO); | ||
152 | gpio_free(QI_LB60_SND_GPIO); | ||
153 | platform_device_unregister(qi_lb60_snd_device); | 138 | platform_device_unregister(qi_lb60_snd_device); |
139 | gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); | ||
154 | } | 140 | } |
155 | module_exit(qi_lb60_exit); | 141 | module_exit(qi_lb60_exit); |
156 | 142 | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d567c322a2fb..5a946b4115a2 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -249,10 +249,13 @@ static int sst_platform_open(struct snd_pcm_substream *substream) | |||
249 | return -ENOMEM; | 249 | return -ENOMEM; |
250 | } | 250 | } |
251 | stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID; | 251 | stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID; |
252 | stream->sstdrv_ops->module_name = SST_CARD_NAMES; | ||
252 | /* registering with SST driver to get access to SST APIs to use */ | 253 | /* registering with SST driver to get access to SST APIs to use */ |
253 | ret_val = register_sst_card(stream->sstdrv_ops); | 254 | ret_val = register_sst_card(stream->sstdrv_ops); |
254 | if (ret_val) { | 255 | if (ret_val) { |
255 | pr_err("sst: sst card registration failed\n"); | 256 | pr_err("sst: sst card registration failed\n"); |
257 | kfree(stream->sstdrv_ops); | ||
258 | kfree(stream); | ||
256 | return ret_val; | 259 | return ret_val; |
257 | } | 260 | } |
258 | runtime->private_data = stream; | 261 | runtime->private_data = stream; |
@@ -270,6 +273,7 @@ static int sst_platform_close(struct snd_pcm_substream *substream) | |||
270 | str_id = stream->stream_info.str_id; | 273 | str_id = stream->stream_info.str_id; |
271 | if (str_id) | 274 | if (str_id) |
272 | ret_val = stream->sstdrv_ops->pcm_control->close(str_id); | 275 | ret_val = stream->sstdrv_ops->pcm_control->close(str_id); |
276 | unregister_sst_card(stream->sstdrv_ops); | ||
273 | kfree(stream->sstdrv_ops); | 277 | kfree(stream->sstdrv_ops); |
274 | kfree(stream); | 278 | kfree(stream); |
275 | return ret_val; | 279 | return ret_val; |
@@ -376,6 +380,11 @@ static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, | |||
376 | return 0; | 380 | return 0; |
377 | } | 381 | } |
378 | 382 | ||
383 | static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) | ||
384 | { | ||
385 | return snd_pcm_lib_free_pages(substream); | ||
386 | } | ||
387 | |||
379 | static struct snd_pcm_ops sst_platform_ops = { | 388 | static struct snd_pcm_ops sst_platform_ops = { |
380 | .open = sst_platform_open, | 389 | .open = sst_platform_open, |
381 | .close = sst_platform_close, | 390 | .close = sst_platform_close, |
@@ -384,6 +393,7 @@ static struct snd_pcm_ops sst_platform_ops = { | |||
384 | .trigger = sst_platform_pcm_trigger, | 393 | .trigger = sst_platform_pcm_trigger, |
385 | .pointer = sst_platform_pcm_pointer, | 394 | .pointer = sst_platform_pcm_pointer, |
386 | .hw_params = sst_platform_pcm_hw_params, | 395 | .hw_params = sst_platform_pcm_hw_params, |
396 | .hw_free = sst_platform_pcm_hw_free, | ||
387 | }; | 397 | }; |
388 | 398 | ||
389 | static void sst_pcm_free(struct snd_pcm *pcm) | 399 | static void sst_pcm_free(struct snd_pcm *pcm) |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2175f09e57b6..07b772357244 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@nokia.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
@@ -146,7 +146,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
146 | * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) | 146 | * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) |
147 | * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) | 147 | * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) |
148 | */ | 148 | */ |
149 | if (cpu_is_omap343x() || cpu_is_omap44xx()) { | 149 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { |
150 | /* | 150 | /* |
151 | * Rule for the buffer size. We should not allow | 151 | * Rule for the buffer size. We should not allow |
152 | * smaller buffer than the FIFO size to avoid underruns | 152 | * smaller buffer than the FIFO size to avoid underruns |
@@ -258,7 +258,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
258 | default: | 258 | default: |
259 | return -EINVAL; | 259 | return -EINVAL; |
260 | } | 260 | } |
261 | if (cpu_is_omap343x()) { | 261 | if (cpu_is_omap34xx()) { |
262 | dma_data->set_threshold = omap_mcbsp_set_threshold; | 262 | dma_data->set_threshold = omap_mcbsp_set_threshold; |
263 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ | 263 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ |
264 | if (omap_mcbsp_get_dma_op_mode(bus_id) == | 264 | if (omap_mcbsp_get_dma_op_mode(bus_id) == |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 37dc7211ed3f..9a7dedd6f5a9 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@nokia.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 8caeb8d305c3..e6a6b991d05f 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@nokia.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
@@ -37,7 +37,8 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
37 | SNDRV_PCM_INFO_MMAP_VALID | | 37 | SNDRV_PCM_INFO_MMAP_VALID | |
38 | SNDRV_PCM_INFO_INTERLEAVED | | 38 | SNDRV_PCM_INFO_INTERLEAVED | |
39 | SNDRV_PCM_INFO_PAUSE | | 39 | SNDRV_PCM_INFO_PAUSE | |
40 | SNDRV_PCM_INFO_RESUME, | 40 | SNDRV_PCM_INFO_RESUME | |
41 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
41 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 42 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
42 | SNDRV_PCM_FMTBIT_S32_LE, | 43 | SNDRV_PCM_FMTBIT_S32_LE, |
43 | .period_bytes_min = 32, | 44 | .period_bytes_min = 32, |
@@ -195,7 +196,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
195 | if ((cpu_is_omap1510())) | 196 | if ((cpu_is_omap1510())) |
196 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | | 197 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | |
197 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); | 198 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); |
198 | else | 199 | else if (!substream->runtime->no_period_wakeup) |
199 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); | 200 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); |
200 | 201 | ||
201 | if (!(cpu_class_is_omap1())) { | 202 | if (!(cpu_class_is_omap1())) { |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index fea0515331fb..a0ed1dbb52d6 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@nokia.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index d0986220eff9..0aae998b6540 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 - 2009 Nokia Corporation | 4 | * Copyright (C) 2008 - 2009 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 6 | * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com> |
7 | * Eduardo Valentin <eduardo.valentin@nokia.com> | 7 | * Eduardo Valentin <eduardo.valentin@nokia.com> |
8 | * Jarkko Nikula <jhnikula@gmail.com> | 8 | * Jarkko Nikula <jhnikula@gmail.com> |
9 | * | 9 | * |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 580f48571303..33ebc46b45b5 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -155,6 +155,15 @@ config SND_SOC_RAUMFELD | |||
155 | help | 155 | help |
156 | Say Y if you want to add support for SoC audio on Raumfeld devices | 156 | Say Y if you want to add support for SoC audio on Raumfeld devices |
157 | 157 | ||
158 | config SND_PXA2XX_SOC_HX4700 | ||
159 | tristate "SoC Audio support for HP iPAQ hx4700" | ||
160 | depends on SND_PXA2XX_SOC && MACH_H4700 | ||
161 | select SND_PXA2XX_SOC_I2S | ||
162 | select SND_SOC_AK4641 | ||
163 | help | ||
164 | Say Y if you want to add support for SoC audio on the | ||
165 | HP iPAQ hx4700. | ||
166 | |||
158 | config SND_PXA2XX_SOC_MAGICIAN | 167 | config SND_PXA2XX_SOC_MAGICIAN |
159 | tristate "SoC Audio support for HTC Magician" | 168 | tristate "SoC Audio support for HTC Magician" |
160 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN | 169 | depends on SND_PXA2XX_SOC && MACH_MAGICIAN |
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 07660165ec8d..af357623be9d 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -22,6 +22,7 @@ snd-soc-palm27x-objs := palm27x.o | |||
22 | snd-soc-saarb-objs := saarb.o | 22 | snd-soc-saarb-objs := saarb.o |
23 | snd-soc-tavorevb3-objs := tavorevb3.o | 23 | snd-soc-tavorevb3-objs := tavorevb3.o |
24 | snd-soc-zylonite-objs := zylonite.o | 24 | snd-soc-zylonite-objs := zylonite.o |
25 | snd-soc-hx4700-objs := hx4700.o | ||
25 | snd-soc-magician-objs := magician.o | 26 | snd-soc-magician-objs := magician.o |
26 | snd-soc-mioa701-objs := mioa701_wm9713.o | 27 | snd-soc-mioa701-objs := mioa701_wm9713.o |
27 | snd-soc-z2-objs := z2.o | 28 | snd-soc-z2-objs := z2.o |
@@ -37,6 +38,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o | |||
37 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o | 38 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o |
38 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o | 39 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o |
39 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o | 40 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o |
41 | obj-$(CONFIG_SND_PXA2XX_SOC_HX4700) += snd-soc-hx4700.o | ||
40 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o | 42 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o |
41 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o | 43 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o |
42 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o | 44 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 9027da466cae..28757fb9df31 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -310,7 +310,7 @@ static struct snd_soc_dai_link corgi_dai = { | |||
310 | .cpu_dai_name = "pxa2xx-i2s", | 310 | .cpu_dai_name = "pxa2xx-i2s", |
311 | .codec_dai_name = "wm8731-hifi", | 311 | .codec_dai_name = "wm8731-hifi", |
312 | .platform_name = "pxa-pcm-audio", | 312 | .platform_name = "pxa-pcm-audio", |
313 | .codec_name = "wm8731-codec.0-001b", | 313 | .codec_name = "wm8731.0-001b", |
314 | .init = corgi_wm8731_init, | 314 | .init = corgi_wm8731_init, |
315 | .ops = &corgi_ops, | 315 | .ops = &corgi_ops, |
316 | }; | 316 | }; |
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c new file mode 100644 index 000000000000..65c124831a00 --- /dev/null +++ b/sound/soc/pxa/hx4700.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * SoC audio for HP iPAQ hx4700 | ||
3 | * | ||
4 | * Copyright (c) 2009 Philipp Zabel | ||
5 | * | ||
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 | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/gpio.h> | ||
19 | |||
20 | #include <sound/core.h> | ||
21 | #include <sound/jack.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | |||
26 | #include <mach/hx4700.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include "pxa2xx-i2s.h" | ||
29 | |||
30 | #include "../codecs/ak4641.h" | ||
31 | |||
32 | static struct snd_soc_jack hs_jack; | ||
33 | |||
34 | /* Headphones jack detection DAPM pin */ | ||
35 | static struct snd_soc_jack_pin hs_jack_pin[] = { | ||
36 | { | ||
37 | .pin = "Headphone Jack", | ||
38 | .mask = SND_JACK_HEADPHONE, | ||
39 | }, | ||
40 | { | ||
41 | .pin = "Speaker", | ||
42 | /* disable speaker when hp jack is inserted */ | ||
43 | .mask = SND_JACK_HEADPHONE, | ||
44 | .invert = 1, | ||
45 | }, | ||
46 | }; | ||
47 | |||
48 | /* Headphones jack detection GPIO */ | ||
49 | static struct snd_soc_jack_gpio hs_jack_gpio = { | ||
50 | .gpio = GPIO75_HX4700_EARPHONE_nDET, | ||
51 | .invert = true, | ||
52 | .name = "hp-gpio", | ||
53 | .report = SND_JACK_HEADPHONE, | ||
54 | .debounce_time = 200, | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * iPAQ hx4700 uses I2S for capture and playback. | ||
59 | */ | ||
60 | static int hx4700_hw_params(struct snd_pcm_substream *substream, | ||
61 | struct snd_pcm_hw_params *params) | ||
62 | { | ||
63 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
64 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
65 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
66 | int ret = 0; | ||
67 | |||
68 | /* set codec DAI configuration */ | ||
69 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
70 | SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | | ||
71 | SND_SOC_DAIFMT_CBS_CFS); | ||
72 | if (ret < 0) | ||
73 | return ret; | ||
74 | |||
75 | /* set cpu DAI configuration */ | ||
76 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
77 | SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | | ||
78 | SND_SOC_DAIFMT_CBS_CFS); | ||
79 | if (ret < 0) | ||
80 | return ret; | ||
81 | |||
82 | /* set the I2S system clock as output */ | ||
83 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, | ||
84 | SND_SOC_CLOCK_OUT); | ||
85 | if (ret < 0) | ||
86 | return ret; | ||
87 | |||
88 | /* inform codec driver about clock freq * | ||
89 | * (PXA I2S always uses divider 256) */ | ||
90 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 256 * params_rate(params), | ||
91 | SND_SOC_CLOCK_IN); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static struct snd_soc_ops hx4700_ops = { | ||
99 | .hw_params = hx4700_hw_params, | ||
100 | }; | ||
101 | |||
102 | static int hx4700_spk_power(struct snd_soc_dapm_widget *w, | ||
103 | struct snd_kcontrol *k, int event) | ||
104 | { | ||
105 | gpio_set_value(GPIO107_HX4700_SPK_nSD, !!SND_SOC_DAPM_EVENT_ON(event)); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int hx4700_hp_power(struct snd_soc_dapm_widget *w, | ||
110 | struct snd_kcontrol *k, int event) | ||
111 | { | ||
112 | gpio_set_value(GPIO92_HX4700_HP_DRIVER, !!SND_SOC_DAPM_EVENT_ON(event)); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | /* hx4700 machine dapm widgets */ | ||
117 | static const struct snd_soc_dapm_widget hx4700_dapm_widgets[] = { | ||
118 | SND_SOC_DAPM_HP("Headphone Jack", hx4700_hp_power), | ||
119 | SND_SOC_DAPM_SPK("Speaker", hx4700_spk_power), | ||
120 | SND_SOC_DAPM_MIC("Built-in Microphone", NULL), | ||
121 | }; | ||
122 | |||
123 | /* hx4700 machine audio_map */ | ||
124 | static const struct snd_soc_dapm_route hx4700_audio_map[] = { | ||
125 | |||
126 | /* Headphone connected to LOUT, ROUT */ | ||
127 | {"Headphone Jack", NULL, "LOUT"}, | ||
128 | {"Headphone Jack", NULL, "ROUT"}, | ||
129 | |||
130 | /* Speaker connected to MOUT2 */ | ||
131 | {"Speaker", NULL, "MOUT2"}, | ||
132 | |||
133 | /* Microphone connected to MICIN */ | ||
134 | {"MICIN", NULL, "Built-in Microphone"}, | ||
135 | {"AIN", NULL, "MICOUT"}, | ||
136 | }; | ||
137 | |||
138 | /* | ||
139 | * Logic for a ak4641 as connected on a HP iPAQ hx4700 | ||
140 | */ | ||
141 | static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) | ||
142 | { | ||
143 | struct snd_soc_codec *codec = rtd->codec; | ||
144 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
145 | int err; | ||
146 | |||
147 | /* NC codec pins */ | ||
148 | /* FIXME: is anything connected here? */ | ||
149 | snd_soc_dapm_nc_pin(dapm, "MOUT1"); | ||
150 | snd_soc_dapm_nc_pin(dapm, "MICEXT"); | ||
151 | snd_soc_dapm_nc_pin(dapm, "AUX"); | ||
152 | |||
153 | /* Jack detection API stuff */ | ||
154 | err = snd_soc_jack_new(codec, "Headphone Jack", | ||
155 | SND_JACK_HEADPHONE, &hs_jack); | ||
156 | if (err) | ||
157 | return err; | ||
158 | |||
159 | err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pin), | ||
160 | hs_jack_pin); | ||
161 | if (err) | ||
162 | return err; | ||
163 | |||
164 | err = snd_soc_jack_add_gpios(&hs_jack, 1, &hs_jack_gpio); | ||
165 | |||
166 | return err; | ||
167 | } | ||
168 | |||
169 | /* hx4700 digital audio interface glue - connects codec <--> CPU */ | ||
170 | static struct snd_soc_dai_link hx4700_dai = { | ||
171 | .name = "ak4641", | ||
172 | .stream_name = "AK4641", | ||
173 | .cpu_dai_name = "pxa2xx-i2s", | ||
174 | .codec_dai_name = "ak4641-hifi", | ||
175 | .platform_name = "pxa-pcm-audio", | ||
176 | .codec_name = "ak4641.0-0012", | ||
177 | .init = hx4700_ak4641_init, | ||
178 | .ops = &hx4700_ops, | ||
179 | }; | ||
180 | |||
181 | /* hx4700 audio machine driver */ | ||
182 | static struct snd_soc_card snd_soc_card_hx4700 = { | ||
183 | .name = "iPAQ hx4700", | ||
184 | .dai_link = &hx4700_dai, | ||
185 | .num_links = 1, | ||
186 | .dapm_widgets = hx4700_dapm_widgets, | ||
187 | .num_dapm_widgets = ARRAY_SIZE(hx4700_dapm_widgets), | ||
188 | .dapm_routes = hx4700_audio_map, | ||
189 | .num_dapm_routes = ARRAY_SIZE(hx4700_audio_map), | ||
190 | }; | ||
191 | |||
192 | static struct gpio hx4700_audio_gpios[] = { | ||
193 | { GPIO107_HX4700_SPK_nSD, GPIOF_OUT_INIT_HIGH, "SPK_POWER" }, | ||
194 | { GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" }, | ||
195 | }; | ||
196 | |||
197 | static int __devinit hx4700_audio_probe(struct platform_device *pdev) | ||
198 | { | ||
199 | int ret; | ||
200 | |||
201 | if (!machine_is_h4700()) | ||
202 | return -ENODEV; | ||
203 | |||
204 | ret = gpio_request_array(hx4700_audio_gpios, | ||
205 | ARRAY_SIZE(hx4700_audio_gpios)); | ||
206 | if (ret) | ||
207 | return ret; | ||
208 | |||
209 | snd_soc_card_hx4700.dev = &pdev->dev; | ||
210 | ret = snd_soc_register_card(&snd_soc_card_hx4700); | ||
211 | if (ret) | ||
212 | return ret; | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int __devexit hx4700_audio_remove(struct platform_device *pdev) | ||
218 | { | ||
219 | snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio); | ||
220 | snd_soc_unregister_card(&snd_soc_card_hx4700); | ||
221 | |||
222 | gpio_set_value(GPIO92_HX4700_HP_DRIVER, 0); | ||
223 | gpio_set_value(GPIO107_HX4700_SPK_nSD, 0); | ||
224 | |||
225 | gpio_free_array(hx4700_audio_gpios, ARRAY_SIZE(hx4700_audio_gpios)); | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static struct platform_driver hx4700_audio_driver = { | ||
230 | .driver = { | ||
231 | .name = "hx4700-audio", | ||
232 | .owner = THIS_MODULE, | ||
233 | .pm = &snd_soc_pm_ops, | ||
234 | }, | ||
235 | .probe = hx4700_audio_probe, | ||
236 | .remove = __devexit_p(hx4700_audio_remove), | ||
237 | }; | ||
238 | |||
239 | static int __init hx4700_modinit(void) | ||
240 | { | ||
241 | return platform_driver_register(&hx4700_audio_driver); | ||
242 | } | ||
243 | module_init(hx4700_modinit); | ||
244 | |||
245 | static void __exit hx4700_modexit(void) | ||
246 | { | ||
247 | platform_driver_unregister(&hx4700_audio_driver); | ||
248 | } | ||
249 | |||
250 | module_exit(hx4700_modexit); | ||
251 | |||
252 | MODULE_AUTHOR("Philipp Zabel"); | ||
253 | MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700"); | ||
254 | MODULE_LICENSE("GPL"); | ||
255 | MODULE_ALIAS("platform:hx4700-audio"); | ||
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index a7d4999f9b24..da3ae4316cf2 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -276,7 +276,7 @@ static struct snd_soc_dai_link poodle_dai = { | |||
276 | .cpu_dai_name = "pxa2xx-i2s", | 276 | .cpu_dai_name = "pxa2xx-i2s", |
277 | .codec_dai_name = "wm8731-hifi", | 277 | .codec_dai_name = "wm8731-hifi", |
278 | .platform_name = "pxa-pcm-audio", | 278 | .platform_name = "pxa-pcm-audio", |
279 | .codec_name = "wm8731-codec.0-001b", | 279 | .codec_name = "wm8731.0-001b", |
280 | .init = poodle_wm8731_init, | 280 | .init = poodle_wm8731_init, |
281 | .ops = &poodle_ops, | 281 | .ops = &poodle_ops, |
282 | }; | 282 | }; |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 8e1571350630..b253d864868a 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | static int spitz_jack_func; | 43 | static int spitz_jack_func; |
44 | static int spitz_spk_func; | 44 | static int spitz_spk_func; |
45 | static int spitz_mic_gpio; | ||
45 | 46 | ||
46 | static void spitz_ext_control(struct snd_soc_codec *codec) | 47 | static void spitz_ext_control(struct snd_soc_codec *codec) |
47 | { | 48 | { |
@@ -217,14 +218,7 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol, | |||
217 | static int spitz_mic_bias(struct snd_soc_dapm_widget *w, | 218 | static int spitz_mic_bias(struct snd_soc_dapm_widget *w, |
218 | struct snd_kcontrol *k, int event) | 219 | struct snd_kcontrol *k, int event) |
219 | { | 220 | { |
220 | if (machine_is_borzoi() || machine_is_spitz()) | 221 | gpio_set_value_cansleep(spitz_mic_gpio, SND_SOC_DAPM_EVENT_ON(event)); |
221 | gpio_set_value(SPITZ_GPIO_MIC_BIAS, | ||
222 | SND_SOC_DAPM_EVENT_ON(event)); | ||
223 | |||
224 | if (machine_is_akita()) | ||
225 | gpio_set_value(AKITA_GPIO_MIC_BIAS, | ||
226 | SND_SOC_DAPM_EVENT_ON(event)); | ||
227 | |||
228 | return 0; | 222 | return 0; |
229 | } | 223 | } |
230 | 224 | ||
@@ -339,22 +333,45 @@ static int __init spitz_init(void) | |||
339 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) | 333 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) |
340 | return -ENODEV; | 334 | return -ENODEV; |
341 | 335 | ||
336 | if (machine_is_borzoi() || machine_is_spitz()) | ||
337 | spitz_mic_gpio = SPITZ_GPIO_MIC_BIAS; | ||
338 | else | ||
339 | spitz_mic_gpio = AKITA_GPIO_MIC_BIAS; | ||
340 | |||
341 | ret = gpio_request(spitz_mic_gpio, "MIC GPIO"); | ||
342 | if (ret) | ||
343 | goto err1; | ||
344 | |||
345 | ret = gpio_direction_output(spitz_mic_gpio, 0); | ||
346 | if (ret) | ||
347 | goto err2; | ||
348 | |||
342 | spitz_snd_device = platform_device_alloc("soc-audio", -1); | 349 | spitz_snd_device = platform_device_alloc("soc-audio", -1); |
343 | if (!spitz_snd_device) | 350 | if (!spitz_snd_device) { |
344 | return -ENOMEM; | 351 | ret = -ENOMEM; |
352 | goto err2; | ||
353 | } | ||
345 | 354 | ||
346 | platform_set_drvdata(spitz_snd_device, &snd_soc_spitz); | 355 | platform_set_drvdata(spitz_snd_device, &snd_soc_spitz); |
347 | ret = platform_device_add(spitz_snd_device); | ||
348 | 356 | ||
357 | ret = platform_device_add(spitz_snd_device); | ||
349 | if (ret) | 358 | if (ret) |
350 | platform_device_put(spitz_snd_device); | 359 | goto err3; |
360 | |||
361 | return 0; | ||
351 | 362 | ||
363 | err3: | ||
364 | platform_device_put(spitz_snd_device); | ||
365 | err2: | ||
366 | gpio_free(spitz_mic_gpio); | ||
367 | err1: | ||
352 | return ret; | 368 | return ret; |
353 | } | 369 | } |
354 | 370 | ||
355 | static void __exit spitz_exit(void) | 371 | static void __exit spitz_exit(void) |
356 | { | 372 | { |
357 | platform_device_unregister(spitz_snd_device); | 373 | platform_device_unregister(spitz_snd_device); |
374 | gpio_free(spitz_mic_gpio); | ||
358 | } | 375 | } |
359 | 376 | ||
360 | module_init(spitz_init); | 377 | module_init(spitz_init); |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index a3fdfb631469..459566bfcd35 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -162,3 +162,18 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
162 | select SND_SAMSUNG_SPDIF | 162 | select SND_SAMSUNG_SPDIF |
163 | help | 163 | help |
164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. | 164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. |
165 | |||
166 | config SND_SOC_SMDK_WM8580_PCM | ||
167 | tristate "SoC PCM Audio support for WM8580 on SMDK" | ||
168 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | ||
169 | select SND_SOC_WM8580 | ||
170 | select SND_SAMSUNG_PCM | ||
171 | help | ||
172 | Say Y if you want to add support for SoC audio on the SMDK. | ||
173 | |||
174 | config SND_SOC_SPEYSIDE | ||
175 | tristate "Audio support for Wolfson Speyside" | ||
176 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | ||
177 | select SND_SAMSUNG_I2S | ||
178 | select SND_SOC_WM8915 | ||
179 | select SND_SOC_WM9081 | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 294dec05c26d..683843a2744f 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -34,6 +34,8 @@ snd-soc-smdk-wm9713-objs := smdk_wm9713.o | |||
34 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | 34 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o |
35 | snd-soc-goni-wm8994-objs := goni_wm8994.o | 35 | snd-soc-goni-wm8994-objs := goni_wm8994.o |
36 | snd-soc-smdk-spdif-objs := smdk_spdif.o | 36 | snd-soc-smdk-spdif-objs := smdk_spdif.o |
37 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o | ||
38 | snd-soc-speyside-objs := speyside.o | ||
37 | 39 | ||
38 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 40 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
39 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 41 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -51,3 +53,5 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o | |||
51 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | 53 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o |
52 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o | 54 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o |
53 | obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o | 55 | obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o |
56 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o | ||
57 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | ||
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c index f6b3a3ce5919..eb6d72ed55a7 100644 --- a/sound/soc/samsung/goni_wm8994.c +++ b/sound/soc/samsung/goni_wm8994.c | |||
@@ -236,18 +236,17 @@ static struct snd_soc_dai_link goni_dai[] = { | |||
236 | .name = "WM8994", | 236 | .name = "WM8994", |
237 | .stream_name = "WM8994 HiFi", | 237 | .stream_name = "WM8994 HiFi", |
238 | .cpu_dai_name = "samsung-i2s.0", | 238 | .cpu_dai_name = "samsung-i2s.0", |
239 | .codec_dai_name = "wm8994-hifi", | 239 | .codec_dai_name = "wm8994-aif1", |
240 | .platform_name = "samsung-audio", | 240 | .platform_name = "samsung-audio", |
241 | .codec_name = "wm8994-codec.0-0x1a", | 241 | .codec_name = "wm8994-codec.0-001a", |
242 | .init = goni_wm8994_init, | 242 | .init = goni_wm8994_init, |
243 | .ops = &goni_hifi_ops, | 243 | .ops = &goni_hifi_ops, |
244 | }, { | 244 | }, { |
245 | .name = "WM8994 Voice", | 245 | .name = "WM8994 Voice", |
246 | .stream_name = "Voice", | 246 | .stream_name = "Voice", |
247 | .cpu_dai_name = "goni-voice-dai", | 247 | .cpu_dai_name = "goni-voice-dai", |
248 | .codec_dai_name = "wm8994-voice", | 248 | .codec_dai_name = "wm8994-aif2", |
249 | .platform_name = "samsung-audio", | 249 | .codec_name = "wm8994-codec.0-001a", |
250 | .codec_name = "wm8994-codec.0-0x1a", | ||
251 | .ops = &goni_voice_ops, | 250 | .ops = &goni_voice_ops, |
252 | }, | 251 | }, |
253 | }; | 252 | }; |
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 452230975632..16152ed08648 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -432,7 +432,6 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
432 | { /* Voice via BT */ | 432 | { /* Voice via BT */ |
433 | .name = "Bluetooth", | 433 | .name = "Bluetooth", |
434 | .stream_name = "Voice", | 434 | .stream_name = "Voice", |
435 | .platform_name = "samsung-audio", | ||
436 | .cpu_dai_name = "dfbmcs320-pcm", | 435 | .cpu_dai_name = "dfbmcs320-pcm", |
437 | .codec_dai_name = "wm8753-voice", | 436 | .codec_dai_name = "wm8753-voice", |
438 | .codec_name = "wm8753-codec.0-001a", | 437 | .codec_name = "wm8753-codec.0-001a", |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c new file mode 100644 index 000000000000..0d12092df164 --- /dev/null +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * sound/soc/samsung/smdk_wm8580pcm.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co. Ltd | ||
5 | * | ||
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 | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | #include <sound/soc.h> | ||
12 | #include <sound/pcm_params.h> | ||
13 | #include <sound/pcm.h> | ||
14 | |||
15 | #include <asm/mach-types.h> | ||
16 | |||
17 | #include "../codecs/wm8580.h" | ||
18 | #include "dma.h" | ||
19 | #include "pcm.h" | ||
20 | |||
21 | /* | ||
22 | * Board Settings: | ||
23 | * o '1' means 'ON' | ||
24 | * o '0' means 'OFF' | ||
25 | * o 'X' means 'Don't care' | ||
26 | * | ||
27 | * SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-1111 | ||
28 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 | ||
29 | */ | ||
30 | |||
31 | #define SMDK_WM8580_EXT_OSC 12000000 | ||
32 | #define SMDK_WM8580_EXT_MCLK 4096000 | ||
33 | #define SMDK_WM8580_EXT_VOICE 2048000 | ||
34 | |||
35 | static unsigned long mclk_freq; | ||
36 | static unsigned long xtal_freq; | ||
37 | |||
38 | /* | ||
39 | * If MCLK clock directly gets from XTAL, we don't have to use PLL | ||
40 | * to make MCLK, but if XTAL clock source connects with other codec | ||
41 | * pin (like XTI), we should have to set codec's PLL to make MCLK. | ||
42 | * Because Samsung SoC does not support pcmcdclk output like I2S. | ||
43 | */ | ||
44 | |||
45 | static int smdk_wm8580_pcm_hw_params(struct snd_pcm_substream *substream, | ||
46 | struct snd_pcm_hw_params *params) | ||
47 | { | ||
48 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
49 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
51 | int rfs, ret; | ||
52 | |||
53 | switch (params_rate(params)) { | ||
54 | case 8000: | ||
55 | break; | ||
56 | default: | ||
57 | printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n", | ||
58 | __func__, __LINE__, params_rate(params)); | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | rfs = mclk_freq / params_rate(params) / 2; | ||
63 | |||
64 | /* Set the codec DAI configuration */ | ||
65 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | ||
66 | | SND_SOC_DAIFMT_IB_NF | ||
67 | | SND_SOC_DAIFMT_CBS_CFS); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
71 | /* Set the cpu DAI configuration */ | ||
72 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | ||
73 | | SND_SOC_DAIFMT_IB_NF | ||
74 | | SND_SOC_DAIFMT_CBS_CFS); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | |||
78 | if (mclk_freq == xtal_freq) { | ||
79 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK, | ||
80 | mclk_freq, SND_SOC_CLOCK_IN); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, | ||
85 | WM8580_CLKSRC_MCLK); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
88 | } else { | ||
89 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, | ||
90 | mclk_freq, SND_SOC_CLOCK_IN); | ||
91 | if (ret < 0) | ||
92 | return ret; | ||
93 | |||
94 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, | ||
95 | WM8580_CLKSRC_PLLA); | ||
96 | if (ret < 0) | ||
97 | return ret; | ||
98 | |||
99 | ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, | ||
100 | xtal_freq, mclk_freq); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | /* Set PCM source clock on CPU */ | ||
106 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX, | ||
107 | mclk_freq, SND_SOC_CLOCK_IN); | ||
108 | if (ret < 0) | ||
109 | return ret; | ||
110 | |||
111 | /* Set SCLK_DIV for making bclk */ | ||
112 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static struct snd_soc_ops smdk_wm8580_pcm_ops = { | ||
120 | .hw_params = smdk_wm8580_pcm_hw_params, | ||
121 | }; | ||
122 | |||
123 | static struct snd_soc_dai_link smdk_dai[] = { | ||
124 | { | ||
125 | .name = "WM8580 PAIF PCM RX", | ||
126 | .stream_name = "Playback", | ||
127 | .cpu_dai_name = "samsung-pcm.0", | ||
128 | .codec_dai_name = "wm8580-hifi-playback", | ||
129 | .platform_name = "samsung-audio", | ||
130 | .codec_name = "wm8580-codec.0-001b", | ||
131 | .ops = &smdk_wm8580_pcm_ops, | ||
132 | }, { | ||
133 | .name = "WM8580 PAIF PCM TX", | ||
134 | .stream_name = "Capture", | ||
135 | .cpu_dai_name = "samsung-pcm.0", | ||
136 | .codec_dai_name = "wm8580-hifi-capture", | ||
137 | .platform_name = "samsung-audio", | ||
138 | .codec_name = "wm8580-codec.0-001b", | ||
139 | .ops = &smdk_wm8580_pcm_ops, | ||
140 | }, | ||
141 | }; | ||
142 | |||
143 | static struct snd_soc_card smdk_pcm = { | ||
144 | .name = "SMDK-PCM", | ||
145 | .dai_link = smdk_dai, | ||
146 | .num_links = 2, | ||
147 | }; | ||
148 | |||
149 | /* | ||
150 | * After SMDKC110 Base Board's Rev is '0.1', 12MHz External OSC(X1) | ||
151 | * is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4), | ||
152 | * 2.0484Mhz, directly with MCLK both Codec and SoC. | ||
153 | */ | ||
154 | static int __devinit snd_smdk_probe(struct platform_device *pdev) | ||
155 | { | ||
156 | int ret = 0; | ||
157 | |||
158 | xtal_freq = SMDK_WM8580_EXT_OSC; | ||
159 | mclk_freq = SMDK_WM8580_EXT_MCLK; | ||
160 | |||
161 | if (machine_is_smdkc110() || machine_is_smdkv210()) | ||
162 | xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE; | ||
163 | |||
164 | smdk_pcm.dev = &pdev->dev; | ||
165 | ret = snd_soc_register_card(&smdk_pcm); | ||
166 | if (ret) { | ||
167 | dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int __devexit snd_smdk_remove(struct platform_device *pdev) | ||
175 | { | ||
176 | snd_soc_unregister_card(&smdk_pcm); | ||
177 | platform_set_drvdata(pdev, NULL); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static struct platform_driver snd_smdk_driver = { | ||
182 | .driver = { | ||
183 | .owner = THIS_MODULE, | ||
184 | .name = "samsung-smdk-pcm", | ||
185 | }, | ||
186 | .probe = snd_smdk_probe, | ||
187 | .remove = __devexit_p(snd_smdk_remove), | ||
188 | }; | ||
189 | |||
190 | static int __init smdk_audio_init(void) | ||
191 | { | ||
192 | return platform_driver_register(&snd_smdk_driver); | ||
193 | } | ||
194 | |||
195 | module_init(smdk_audio_init); | ||
196 | |||
197 | static void __exit smdk_audio_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&snd_smdk_driver); | ||
200 | } | ||
201 | |||
202 | module_exit(smdk_audio_exit); | ||
203 | |||
204 | MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>"); | ||
205 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM"); | ||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c new file mode 100644 index 000000000000..360a333cb7c0 --- /dev/null +++ b/sound/soc/samsung/speyside.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * Speyside audio support | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics | ||
5 | * | ||
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 | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | #include <sound/soc-dapm.h> | ||
14 | #include <sound/jack.h> | ||
15 | #include <linux/gpio.h> | ||
16 | |||
17 | #include "../codecs/wm8915.h" | ||
18 | #include "../codecs/wm9081.h" | ||
19 | |||
20 | #define WM8915_HPSEL_GPIO 214 | ||
21 | |||
22 | static int speyside_set_bias_level(struct snd_soc_card *card, | ||
23 | enum snd_soc_bias_level level) | ||
24 | { | ||
25 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
26 | int ret; | ||
27 | |||
28 | switch (level) { | ||
29 | case SND_SOC_BIAS_STANDBY: | ||
30 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK1, | ||
31 | 32768, SND_SOC_CLOCK_IN); | ||
32 | if (ret < 0) | ||
33 | return ret; | ||
34 | |||
35 | ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK1, | ||
36 | 0, 0, 0); | ||
37 | if (ret < 0) { | ||
38 | pr_err("Failed to stop FLL\n"); | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | default: | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int speyside_hw_params(struct snd_pcm_substream *substream, | ||
50 | struct snd_pcm_hw_params *params) | ||
51 | { | ||
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
53 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
54 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
55 | int ret; | ||
56 | |||
57 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ||
58 | | SND_SOC_DAIFMT_NB_NF | ||
59 | | SND_SOC_DAIFMT_CBM_CFM); | ||
60 | if (ret < 0) | ||
61 | return ret; | ||
62 | |||
63 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ||
64 | | SND_SOC_DAIFMT_NB_NF | ||
65 | | SND_SOC_DAIFMT_CBM_CFM); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | ret = snd_soc_dai_set_pll(codec_dai, 0, WM8915_FLL_MCLK1, | ||
70 | 32768, 256 * 48000); | ||
71 | if (ret < 0) | ||
72 | return ret; | ||
73 | |||
74 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_FLL, | ||
75 | 256 * 48000, SND_SOC_CLOCK_IN); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static struct snd_soc_ops speyside_ops = { | ||
83 | .hw_params = speyside_hw_params, | ||
84 | }; | ||
85 | |||
86 | static struct snd_soc_jack speyside_headset; | ||
87 | |||
88 | /* Headset jack detection DAPM pins */ | ||
89 | static struct snd_soc_jack_pin speyside_headset_pins[] = { | ||
90 | { | ||
91 | .pin = "Headset Mic", | ||
92 | .mask = SND_JACK_MICROPHONE, | ||
93 | }, | ||
94 | { | ||
95 | .pin = "Headphone", | ||
96 | .mask = SND_JACK_HEADPHONE, | ||
97 | }, | ||
98 | }; | ||
99 | |||
100 | /* Default the headphone selection to active high */ | ||
101 | static int speyside_jack_polarity; | ||
102 | |||
103 | static int speyside_get_micbias(struct snd_soc_dapm_widget *source, | ||
104 | struct snd_soc_dapm_widget *sink) | ||
105 | { | ||
106 | if (speyside_jack_polarity && (strcmp(source->name, "MICB1") == 0)) | ||
107 | return 1; | ||
108 | if (!speyside_jack_polarity && (strcmp(source->name, "MICB2") == 0)) | ||
109 | return 1; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void speyside_set_polarity(struct snd_soc_codec *codec, | ||
115 | int polarity) | ||
116 | { | ||
117 | speyside_jack_polarity = !polarity; | ||
118 | gpio_direction_output(WM8915_HPSEL_GPIO, speyside_jack_polarity); | ||
119 | |||
120 | /* Re-run DAPM to make sure we're using the correct mic bias */ | ||
121 | snd_soc_dapm_sync(&codec->dapm); | ||
122 | } | ||
123 | |||
124 | static int speyside_wm8915_init(struct snd_soc_pcm_runtime *rtd) | ||
125 | { | ||
126 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
127 | struct snd_soc_codec *codec = rtd->codec; | ||
128 | int ret; | ||
129 | |||
130 | ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK1, 32768, 0); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | ret = gpio_request(WM8915_HPSEL_GPIO, "HP_SEL"); | ||
135 | if (ret != 0) | ||
136 | pr_err("Failed to request HP_SEL GPIO: %d\n", ret); | ||
137 | gpio_direction_output(WM8915_HPSEL_GPIO, speyside_jack_polarity); | ||
138 | |||
139 | ret = snd_soc_jack_new(codec, "Headset", | ||
140 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
141 | &speyside_headset); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | |||
145 | ret = snd_soc_jack_add_pins(&speyside_headset, | ||
146 | ARRAY_SIZE(speyside_headset_pins), | ||
147 | speyside_headset_pins); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | |||
151 | wm8915_detect(codec, &speyside_headset, speyside_set_polarity); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int speyside_late_probe(struct snd_soc_card *card) | ||
157 | { | ||
158 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); | ||
159 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); | ||
160 | snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC"); | ||
161 | snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC"); | ||
162 | snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); | ||
163 | snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output"); | ||
164 | snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input"); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static struct snd_soc_dai_link speyside_dai[] = { | ||
170 | { | ||
171 | .name = "CPU", | ||
172 | .stream_name = "CPU", | ||
173 | .cpu_dai_name = "samsung-i2s.0", | ||
174 | .codec_dai_name = "wm8915-aif1", | ||
175 | .platform_name = "samsung-audio", | ||
176 | .codec_name = "wm8915.1-001a", | ||
177 | .init = speyside_wm8915_init, | ||
178 | .ops = &speyside_ops, | ||
179 | }, | ||
180 | { | ||
181 | .name = "Baseband", | ||
182 | .stream_name = "Baseband", | ||
183 | .cpu_dai_name = "wm8915-aif2", | ||
184 | .codec_dai_name = "wm1250-ev1", | ||
185 | .codec_name = "wm1250-ev1.1-0027", | ||
186 | .ops = &speyside_ops, | ||
187 | .ignore_suspend = 1, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm) | ||
192 | { | ||
193 | snd_soc_dapm_nc_pin(dapm, "LINEOUT"); | ||
194 | |||
195 | /* At any time the WM9081 is active it will have this clock */ | ||
196 | return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, | ||
197 | 48000 * 256, 0); | ||
198 | } | ||
199 | |||
200 | static struct snd_soc_aux_dev speyside_aux_dev[] = { | ||
201 | { | ||
202 | .name = "wm9081", | ||
203 | .codec_name = "wm9081.1-006c", | ||
204 | .init = speyside_wm9081_init, | ||
205 | }, | ||
206 | }; | ||
207 | |||
208 | static struct snd_soc_codec_conf speyside_codec_conf[] = { | ||
209 | { | ||
210 | .dev_name = "wm9081.1-006c", | ||
211 | .name_prefix = "Sub", | ||
212 | }, | ||
213 | }; | ||
214 | |||
215 | static const struct snd_kcontrol_new controls[] = { | ||
216 | SOC_DAPM_PIN_SWITCH("Main Speaker"), | ||
217 | SOC_DAPM_PIN_SWITCH("Main DMIC"), | ||
218 | SOC_DAPM_PIN_SWITCH("Main AMIC"), | ||
219 | SOC_DAPM_PIN_SWITCH("WM1250 Input"), | ||
220 | SOC_DAPM_PIN_SWITCH("WM1250 Output"), | ||
221 | }; | ||
222 | |||
223 | static struct snd_soc_dapm_widget widgets[] = { | ||
224 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
225 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
226 | |||
227 | SND_SOC_DAPM_SPK("Main Speaker", NULL), | ||
228 | |||
229 | SND_SOC_DAPM_MIC("Main AMIC", NULL), | ||
230 | SND_SOC_DAPM_MIC("Main DMIC", NULL), | ||
231 | }; | ||
232 | |||
233 | static struct snd_soc_dapm_route audio_paths[] = { | ||
234 | { "IN1RN", NULL, "MICB1" }, | ||
235 | { "IN1RP", NULL, "MICB1" }, | ||
236 | { "IN1RN", NULL, "MICB2" }, | ||
237 | { "IN1RP", NULL, "MICB2" }, | ||
238 | { "MICB1", NULL, "Headset Mic", speyside_get_micbias }, | ||
239 | { "MICB2", NULL, "Headset Mic", speyside_get_micbias }, | ||
240 | |||
241 | { "IN1LP", NULL, "MICB2" }, | ||
242 | { "IN1RN", NULL, "MICB1" }, | ||
243 | { "MICB2", NULL, "Main AMIC" }, | ||
244 | |||
245 | { "DMIC1DAT", NULL, "MICB1" }, | ||
246 | { "DMIC2DAT", NULL, "MICB1" }, | ||
247 | { "MICB1", NULL, "Main DMIC" }, | ||
248 | |||
249 | { "Headphone", NULL, "HPOUT1L" }, | ||
250 | { "Headphone", NULL, "HPOUT1R" }, | ||
251 | |||
252 | { "Sub IN1", NULL, "HPOUT2L" }, | ||
253 | { "Sub IN2", NULL, "HPOUT2R" }, | ||
254 | |||
255 | { "Main Speaker", NULL, "Sub SPKN" }, | ||
256 | { "Main Speaker", NULL, "Sub SPKP" }, | ||
257 | { "Main Speaker", NULL, "SPKDAT" }, | ||
258 | }; | ||
259 | |||
260 | static struct snd_soc_card speyside = { | ||
261 | .name = "Speyside", | ||
262 | .dai_link = speyside_dai, | ||
263 | .num_links = ARRAY_SIZE(speyside_dai), | ||
264 | .aux_dev = speyside_aux_dev, | ||
265 | .num_aux_devs = ARRAY_SIZE(speyside_aux_dev), | ||
266 | .codec_conf = speyside_codec_conf, | ||
267 | .num_configs = ARRAY_SIZE(speyside_codec_conf), | ||
268 | |||
269 | .set_bias_level = speyside_set_bias_level, | ||
270 | |||
271 | .controls = controls, | ||
272 | .num_controls = ARRAY_SIZE(controls), | ||
273 | .dapm_widgets = widgets, | ||
274 | .num_dapm_widgets = ARRAY_SIZE(widgets), | ||
275 | .dapm_routes = audio_paths, | ||
276 | .num_dapm_routes = ARRAY_SIZE(audio_paths), | ||
277 | |||
278 | .late_probe = speyside_late_probe, | ||
279 | }; | ||
280 | |||
281 | static __devinit int speyside_probe(struct platform_device *pdev) | ||
282 | { | ||
283 | struct snd_soc_card *card = &speyside; | ||
284 | int ret; | ||
285 | |||
286 | card->dev = &pdev->dev; | ||
287 | |||
288 | ret = snd_soc_register_card(card); | ||
289 | if (ret) { | ||
290 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
291 | ret); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int __devexit speyside_remove(struct platform_device *pdev) | ||
299 | { | ||
300 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
301 | |||
302 | snd_soc_unregister_card(card); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static struct platform_driver speyside_driver = { | ||
308 | .driver = { | ||
309 | .name = "speyside", | ||
310 | .owner = THIS_MODULE, | ||
311 | .pm = &snd_soc_pm_ops, | ||
312 | }, | ||
313 | .probe = speyside_probe, | ||
314 | .remove = __devexit_p(speyside_remove), | ||
315 | }; | ||
316 | |||
317 | static int __init speyside_audio_init(void) | ||
318 | { | ||
319 | return platform_driver_register(&speyside_driver); | ||
320 | } | ||
321 | module_init(speyside_audio_init); | ||
322 | |||
323 | static void __exit speyside_audio_exit(void) | ||
324 | { | ||
325 | platform_driver_unregister(&speyside_driver); | ||
326 | } | ||
327 | module_exit(speyside_audio_exit); | ||
328 | |||
329 | MODULE_DESCRIPTION("Speyside audio support"); | ||
330 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
331 | MODULE_LICENSE("GPL"); | ||
332 | MODULE_ALIAS("platform:speyside"); | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 23c0e83d4c19..4a9da6b5f4e1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -86,8 +86,8 @@ | |||
86 | #define SE (1 << 0) /* Fix the master clock */ | 86 | #define SE (1 << 0) /* Fix the master clock */ |
87 | 87 | ||
88 | /* CLK_RST */ | 88 | /* CLK_RST */ |
89 | #define B_CLK 0x00000010 | 89 | #define CRB (1 << 4) |
90 | #define A_CLK 0x00000001 | 90 | #define CRA (1 << 0) |
91 | 91 | ||
92 | /* IO SHIFT / MACRO */ | 92 | /* IO SHIFT / MACRO */ |
93 | #define BI_SHIFT 12 | 93 | #define BI_SHIFT 12 |
@@ -146,11 +146,20 @@ struct fsi_priv { | |||
146 | void __iomem *base; | 146 | void __iomem *base; |
147 | struct fsi_master *master; | 147 | struct fsi_master *master; |
148 | 148 | ||
149 | int chan_num; | ||
150 | struct fsi_stream playback; | 149 | struct fsi_stream playback; |
151 | struct fsi_stream capture; | 150 | struct fsi_stream capture; |
152 | 151 | ||
152 | int chan_num:16; | ||
153 | int clk_master:1; | ||
154 | |||
153 | long rate; | 155 | long rate; |
156 | |||
157 | /* for suspend/resume */ | ||
158 | u32 saved_do_fmt; | ||
159 | u32 saved_di_fmt; | ||
160 | u32 saved_ckg1; | ||
161 | u32 saved_ckg2; | ||
162 | u32 saved_out_sel; | ||
154 | }; | 163 | }; |
155 | 164 | ||
156 | struct fsi_core { | 165 | struct fsi_core { |
@@ -171,6 +180,14 @@ struct fsi_master { | |||
171 | struct fsi_core *core; | 180 | struct fsi_core *core; |
172 | struct sh_fsi_platform_info *info; | 181 | struct sh_fsi_platform_info *info; |
173 | spinlock_t lock; | 182 | spinlock_t lock; |
183 | |||
184 | /* for suspend/resume */ | ||
185 | u32 saved_a_mclk; | ||
186 | u32 saved_b_mclk; | ||
187 | u32 saved_iemsk; | ||
188 | u32 saved_imsk; | ||
189 | u32 saved_clk_rst; | ||
190 | u32 saved_soft_rst; | ||
174 | }; | 191 | }; |
175 | 192 | ||
176 | /* | 193 | /* |
@@ -244,6 +261,11 @@ static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) | |||
244 | return fsi->master; | 261 | return fsi->master; |
245 | } | 262 | } |
246 | 263 | ||
264 | static int fsi_is_clk_master(struct fsi_priv *fsi) | ||
265 | { | ||
266 | return fsi->clk_master; | ||
267 | } | ||
268 | |||
247 | static int fsi_is_port_a(struct fsi_priv *fsi) | 269 | static int fsi_is_port_a(struct fsi_priv *fsi) |
248 | { | 270 | { |
249 | return fsi->master->base == fsi->base; | 271 | return fsi->master->base == fsi->base; |
@@ -535,20 +557,45 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
535 | } | 557 | } |
536 | 558 | ||
537 | /* | 559 | /* |
538 | * ctrl function | 560 | * clock function |
539 | */ | 561 | */ |
562 | #define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) | ||
563 | #define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) | ||
564 | static void __fsi_module_clk_ctrl(struct fsi_master *master, | ||
565 | struct device *dev, | ||
566 | int enable) | ||
567 | { | ||
568 | pm_runtime_get_sync(dev); | ||
569 | |||
570 | if (enable) { | ||
571 | /* enable only SR */ | ||
572 | fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); | ||
573 | fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); | ||
574 | } else { | ||
575 | /* clear all registers */ | ||
576 | fsi_master_mask_set(master, SOFT_RST, FSISR, 0); | ||
577 | } | ||
540 | 578 | ||
541 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) | 579 | pm_runtime_put_sync(dev); |
580 | } | ||
581 | |||
582 | #define fsi_port_start(f) __fsi_port_clk_ctrl(f, 1) | ||
583 | #define fsi_port_stop(f) __fsi_port_clk_ctrl(f, 0) | ||
584 | static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) | ||
542 | { | 585 | { |
543 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); | ||
544 | struct fsi_master *master = fsi_get_master(fsi); | 586 | struct fsi_master *master = fsi_get_master(fsi); |
587 | u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; | ||
588 | u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; | ||
589 | int is_master = fsi_is_clk_master(fsi); | ||
545 | 590 | ||
546 | if (enable) | 591 | fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); |
547 | fsi_master_mask_set(master, CLK_RST, val, val); | 592 | if (is_master) |
548 | else | 593 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
549 | fsi_master_mask_set(master, CLK_RST, val, 0); | ||
550 | } | 594 | } |
551 | 595 | ||
596 | /* | ||
597 | * ctrl function | ||
598 | */ | ||
552 | static void fsi_fifo_init(struct fsi_priv *fsi, | 599 | static void fsi_fifo_init(struct fsi_priv *fsi, |
553 | int is_play, | 600 | int is_play, |
554 | struct snd_soc_dai *dai) | 601 | struct snd_soc_dai *dai) |
@@ -601,18 +648,6 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
601 | } | 648 | } |
602 | } | 649 | } |
603 | 650 | ||
604 | static void fsi_soft_all_reset(struct fsi_master *master) | ||
605 | { | ||
606 | /* port AB reset */ | ||
607 | fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); | ||
608 | mdelay(10); | ||
609 | |||
610 | /* soft reset */ | ||
611 | fsi_master_mask_set(master, SOFT_RST, FSISR, 0); | ||
612 | fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); | ||
613 | mdelay(10); | ||
614 | } | ||
615 | |||
616 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | 651 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) |
617 | { | 652 | { |
618 | struct snd_pcm_runtime *runtime; | 653 | struct snd_pcm_runtime *runtime; |
@@ -793,14 +828,13 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
793 | struct fsi_priv *fsi = fsi_get_priv(substream); | 828 | struct fsi_priv *fsi = fsi_get_priv(substream); |
794 | int is_play = fsi_is_play(substream); | 829 | int is_play = fsi_is_play(substream); |
795 | struct fsi_master *master = fsi_get_master(fsi); | 830 | struct fsi_master *master = fsi_get_master(fsi); |
796 | set_rate_func set_rate; | 831 | set_rate_func set_rate = fsi_get_info_set_rate(master); |
797 | 832 | ||
798 | fsi_irq_disable(fsi, is_play); | 833 | fsi_irq_disable(fsi, is_play); |
799 | fsi_clk_ctrl(fsi, 0); | ||
800 | 834 | ||
801 | set_rate = fsi_get_info_set_rate(master); | 835 | if (fsi_is_clk_master(fsi)) |
802 | if (set_rate && fsi->rate) | ||
803 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 836 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
837 | |||
804 | fsi->rate = 0; | 838 | fsi->rate = 0; |
805 | 839 | ||
806 | pm_runtime_put_sync(dai->dev); | 840 | pm_runtime_put_sync(dai->dev); |
@@ -821,8 +855,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
821 | frames_to_bytes(runtime, runtime->period_size)); | 855 | frames_to_bytes(runtime, runtime->period_size)); |
822 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); | 856 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); |
823 | fsi_irq_enable(fsi, is_play); | 857 | fsi_irq_enable(fsi, is_play); |
858 | fsi_port_start(fsi); | ||
824 | break; | 859 | break; |
825 | case SNDRV_PCM_TRIGGER_STOP: | 860 | case SNDRV_PCM_TRIGGER_STOP: |
861 | fsi_port_stop(fsi); | ||
826 | fsi_irq_disable(fsi, is_play); | 862 | fsi_irq_disable(fsi, is_play); |
827 | fsi_stream_pop(fsi, is_play); | 863 | fsi_stream_pop(fsi, is_play); |
828 | break; | 864 | break; |
@@ -876,6 +912,8 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | |||
876 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 912 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
877 | { | 913 | { |
878 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); | 914 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); |
915 | struct fsi_master *master = fsi_get_master(fsi); | ||
916 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
879 | u32 flags = fsi_get_info_flags(fsi); | 917 | u32 flags = fsi_get_info_flags(fsi); |
880 | u32 data = 0; | 918 | u32 data = 0; |
881 | int ret; | 919 | int ret; |
@@ -886,6 +924,7 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
886 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 924 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
887 | case SND_SOC_DAIFMT_CBM_CFM: | 925 | case SND_SOC_DAIFMT_CBM_CFM: |
888 | data = DIMD | DOMD; | 926 | data = DIMD | DOMD; |
927 | fsi->clk_master = 1; | ||
889 | break; | 928 | break; |
890 | case SND_SOC_DAIFMT_CBS_CFS: | 929 | case SND_SOC_DAIFMT_CBS_CFS: |
891 | break; | 930 | break; |
@@ -893,6 +932,13 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
893 | ret = -EINVAL; | 932 | ret = -EINVAL; |
894 | goto set_fmt_exit; | 933 | goto set_fmt_exit; |
895 | } | 934 | } |
935 | |||
936 | if (fsi_is_clk_master(fsi) && !set_rate) { | ||
937 | dev_err(dai->dev, "platform doesn't have set_rate\n"); | ||
938 | ret = -EINVAL; | ||
939 | goto set_fmt_exit; | ||
940 | } | ||
941 | |||
896 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | 942 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); |
897 | 943 | ||
898 | /* set format */ | 944 | /* set format */ |
@@ -919,13 +965,12 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
919 | { | 965 | { |
920 | struct fsi_priv *fsi = fsi_get_priv(substream); | 966 | struct fsi_priv *fsi = fsi_get_priv(substream); |
921 | struct fsi_master *master = fsi_get_master(fsi); | 967 | struct fsi_master *master = fsi_get_master(fsi); |
922 | set_rate_func set_rate; | 968 | set_rate_func set_rate = fsi_get_info_set_rate(master); |
923 | int fsi_ver = master->core->ver; | 969 | int fsi_ver = master->core->ver; |
924 | long rate = params_rate(params); | 970 | long rate = params_rate(params); |
925 | int ret; | 971 | int ret; |
926 | 972 | ||
927 | set_rate = fsi_get_info_set_rate(master); | 973 | if (!fsi_is_clk_master(fsi)) |
928 | if (!set_rate) | ||
929 | return 0; | 974 | return 0; |
930 | 975 | ||
931 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); | 976 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); |
@@ -987,7 +1032,6 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
987 | 1032 | ||
988 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | 1033 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); |
989 | udelay(10); | 1034 | udelay(10); |
990 | fsi_clk_ctrl(fsi, 1); | ||
991 | ret = 0; | 1035 | ret = 0; |
992 | } | 1036 | } |
993 | 1037 | ||
@@ -1202,9 +1246,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1202 | pm_runtime_enable(&pdev->dev); | 1246 | pm_runtime_enable(&pdev->dev); |
1203 | dev_set_drvdata(&pdev->dev, master); | 1247 | dev_set_drvdata(&pdev->dev, master); |
1204 | 1248 | ||
1205 | pm_runtime_get_sync(&pdev->dev); | 1249 | fsi_module_init(master, &pdev->dev); |
1206 | fsi_soft_all_reset(master); | ||
1207 | pm_runtime_put_sync(&pdev->dev); | ||
1208 | 1250 | ||
1209 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, | 1251 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, |
1210 | id_entry->name, master); | 1252 | id_entry->name, master); |
@@ -1248,6 +1290,8 @@ static int fsi_remove(struct platform_device *pdev) | |||
1248 | 1290 | ||
1249 | master = dev_get_drvdata(&pdev->dev); | 1291 | master = dev_get_drvdata(&pdev->dev); |
1250 | 1292 | ||
1293 | fsi_module_kill(master, &pdev->dev); | ||
1294 | |||
1251 | free_irq(master->irq, master); | 1295 | free_irq(master->irq, master); |
1252 | pm_runtime_disable(&pdev->dev); | 1296 | pm_runtime_disable(&pdev->dev); |
1253 | 1297 | ||
@@ -1260,6 +1304,82 @@ static int fsi_remove(struct platform_device *pdev) | |||
1260 | return 0; | 1304 | return 0; |
1261 | } | 1305 | } |
1262 | 1306 | ||
1307 | static void __fsi_suspend(struct fsi_priv *fsi, | ||
1308 | struct device *dev, | ||
1309 | set_rate_func set_rate) | ||
1310 | { | ||
1311 | fsi->saved_do_fmt = fsi_reg_read(fsi, DO_FMT); | ||
1312 | fsi->saved_di_fmt = fsi_reg_read(fsi, DI_FMT); | ||
1313 | fsi->saved_ckg1 = fsi_reg_read(fsi, CKG1); | ||
1314 | fsi->saved_ckg2 = fsi_reg_read(fsi, CKG2); | ||
1315 | fsi->saved_out_sel = fsi_reg_read(fsi, OUT_SEL); | ||
1316 | |||
1317 | if (fsi_is_clk_master(fsi)) | ||
1318 | set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 0); | ||
1319 | } | ||
1320 | |||
1321 | static void __fsi_resume(struct fsi_priv *fsi, | ||
1322 | struct device *dev, | ||
1323 | set_rate_func set_rate) | ||
1324 | { | ||
1325 | fsi_reg_write(fsi, DO_FMT, fsi->saved_do_fmt); | ||
1326 | fsi_reg_write(fsi, DI_FMT, fsi->saved_di_fmt); | ||
1327 | fsi_reg_write(fsi, CKG1, fsi->saved_ckg1); | ||
1328 | fsi_reg_write(fsi, CKG2, fsi->saved_ckg2); | ||
1329 | fsi_reg_write(fsi, OUT_SEL, fsi->saved_out_sel); | ||
1330 | |||
1331 | if (fsi_is_clk_master(fsi)) | ||
1332 | set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 1); | ||
1333 | } | ||
1334 | |||
1335 | static int fsi_suspend(struct device *dev) | ||
1336 | { | ||
1337 | struct fsi_master *master = dev_get_drvdata(dev); | ||
1338 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
1339 | |||
1340 | pm_runtime_get_sync(dev); | ||
1341 | |||
1342 | __fsi_suspend(&master->fsia, dev, set_rate); | ||
1343 | __fsi_suspend(&master->fsib, dev, set_rate); | ||
1344 | |||
1345 | master->saved_a_mclk = fsi_core_read(master, a_mclk); | ||
1346 | master->saved_b_mclk = fsi_core_read(master, b_mclk); | ||
1347 | master->saved_iemsk = fsi_core_read(master, iemsk); | ||
1348 | master->saved_imsk = fsi_core_read(master, imsk); | ||
1349 | master->saved_clk_rst = fsi_master_read(master, CLK_RST); | ||
1350 | master->saved_soft_rst = fsi_master_read(master, SOFT_RST); | ||
1351 | |||
1352 | fsi_module_kill(master, dev); | ||
1353 | |||
1354 | pm_runtime_put_sync(dev); | ||
1355 | |||
1356 | return 0; | ||
1357 | } | ||
1358 | |||
1359 | static int fsi_resume(struct device *dev) | ||
1360 | { | ||
1361 | struct fsi_master *master = dev_get_drvdata(dev); | ||
1362 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
1363 | |||
1364 | pm_runtime_get_sync(dev); | ||
1365 | |||
1366 | fsi_module_init(master, dev); | ||
1367 | |||
1368 | fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); | ||
1369 | fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); | ||
1370 | fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); | ||
1371 | fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); | ||
1372 | fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); | ||
1373 | fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); | ||
1374 | |||
1375 | __fsi_resume(&master->fsia, dev, set_rate); | ||
1376 | __fsi_resume(&master->fsib, dev, set_rate); | ||
1377 | |||
1378 | pm_runtime_put_sync(dev); | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1263 | static int fsi_runtime_nop(struct device *dev) | 1383 | static int fsi_runtime_nop(struct device *dev) |
1264 | { | 1384 | { |
1265 | /* Runtime PM callback shared between ->runtime_suspend() | 1385 | /* Runtime PM callback shared between ->runtime_suspend() |
@@ -1273,6 +1393,8 @@ static int fsi_runtime_nop(struct device *dev) | |||
1273 | } | 1393 | } |
1274 | 1394 | ||
1275 | static struct dev_pm_ops fsi_pm_ops = { | 1395 | static struct dev_pm_ops fsi_pm_ops = { |
1396 | .suspend = fsi_suspend, | ||
1397 | .resume = fsi_resume, | ||
1276 | .runtime_suspend = fsi_runtime_nop, | 1398 | .runtime_suspend = fsi_runtime_nop, |
1277 | .runtime_resume = fsi_runtime_nop, | 1399 | .runtime_resume = fsi_runtime_nop, |
1278 | }; | 1400 | }; |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 5d76da43b14c..06b7b81a1601 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -20,40 +20,28 @@ | |||
20 | 20 | ||
21 | #include <trace/events/asoc.h> | 21 | #include <trace/events/asoc.h> |
22 | 22 | ||
23 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | 23 | #ifdef CONFIG_SPI_MASTER |
24 | unsigned int reg) | 24 | static int do_spi_write(void *control, const char *data, int len) |
25 | { | 25 | { |
26 | struct spi_device *spi = control; | ||
26 | int ret; | 27 | int ret; |
27 | unsigned int val; | ||
28 | |||
29 | if (reg >= codec->driver->reg_cache_size || | ||
30 | snd_soc_codec_volatile_register(codec, reg) || | ||
31 | codec->cache_bypass) { | ||
32 | if (codec->cache_only) | ||
33 | return -1; | ||
34 | |||
35 | BUG_ON(!codec->hw_read); | ||
36 | return codec->hw_read(codec, reg); | ||
37 | } | ||
38 | 28 | ||
39 | ret = snd_soc_cache_read(codec, reg, &val); | 29 | ret = spi_write(spi, data, len); |
40 | if (ret < 0) | 30 | if (ret < 0) |
41 | return -1; | 31 | return ret; |
42 | return val; | 32 | |
33 | return len; | ||
43 | } | 34 | } |
35 | #endif | ||
44 | 36 | ||
45 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | 37 | static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, |
46 | unsigned int value) | 38 | unsigned int value, const void *data, int len) |
47 | { | 39 | { |
48 | u8 data[2]; | ||
49 | int ret; | 40 | int ret; |
50 | 41 | ||
51 | data[0] = (reg << 4) | ((value >> 8) & 0x000f); | ||
52 | data[1] = value & 0x00ff; | ||
53 | |||
54 | if (!snd_soc_codec_volatile_register(codec, reg) && | 42 | if (!snd_soc_codec_volatile_register(codec, reg) && |
55 | reg < codec->driver->reg_cache_size && | 43 | reg < codec->driver->reg_cache_size && |
56 | !codec->cache_bypass) { | 44 | !codec->cache_bypass) { |
57 | ret = snd_soc_cache_write(codec, reg, value); | 45 | ret = snd_soc_cache_write(codec, reg, value); |
58 | if (ret < 0) | 46 | if (ret < 0) |
59 | return -1; | 47 | return -1; |
@@ -64,8 +52,8 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | |||
64 | return 0; | 52 | return 0; |
65 | } | 53 | } |
66 | 54 | ||
67 | ret = codec->hw_write(codec->control_data, data, 2); | 55 | ret = codec->hw_write(codec->control_data, data, len); |
68 | if (ret == 2) | 56 | if (ret == len) |
69 | return 0; | 57 | return 0; |
70 | if (ret < 0) | 58 | if (ret < 0) |
71 | return ret; | 59 | return ret; |
@@ -73,50 +61,19 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | |||
73 | return -EIO; | 61 | return -EIO; |
74 | } | 62 | } |
75 | 63 | ||
76 | #if defined(CONFIG_SPI_MASTER) | 64 | static unsigned int do_hw_read(struct snd_soc_codec *codec, unsigned int reg) |
77 | static int snd_soc_4_12_spi_write(void *control_data, const char *data, | ||
78 | int len) | ||
79 | { | ||
80 | struct spi_device *spi = control_data; | ||
81 | struct spi_transfer t; | ||
82 | struct spi_message m; | ||
83 | u8 msg[2]; | ||
84 | |||
85 | if (len <= 0) | ||
86 | return 0; | ||
87 | |||
88 | msg[0] = data[1]; | ||
89 | msg[1] = data[0]; | ||
90 | |||
91 | spi_message_init(&m); | ||
92 | memset(&t, 0, sizeof t); | ||
93 | |||
94 | t.tx_buf = &msg[0]; | ||
95 | t.len = len; | ||
96 | |||
97 | spi_message_add_tail(&t, &m); | ||
98 | spi_sync(spi, &m); | ||
99 | |||
100 | return len; | ||
101 | } | ||
102 | #else | ||
103 | #define snd_soc_4_12_spi_write NULL | ||
104 | #endif | ||
105 | |||
106 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | ||
107 | unsigned int reg) | ||
108 | { | 65 | { |
109 | int ret; | 66 | int ret; |
110 | unsigned int val; | 67 | unsigned int val; |
111 | 68 | ||
112 | if (reg >= codec->driver->reg_cache_size || | 69 | if (reg >= codec->driver->reg_cache_size || |
113 | snd_soc_codec_volatile_register(codec, reg) || | 70 | snd_soc_codec_volatile_register(codec, reg) || |
114 | codec->cache_bypass) { | 71 | codec->cache_bypass) { |
115 | if (codec->cache_only) | 72 | if (codec->cache_only) |
116 | return -1; | 73 | return -1; |
117 | 74 | ||
118 | BUG_ON(!codec->hw_read); | 75 | BUG_ON(!codec->hw_read); |
119 | return codec->hw_read(codec, reg); | 76 | return codec->hw_read(codec, reg); |
120 | } | 77 | } |
121 | 78 | ||
122 | ret = snd_soc_cache_read(codec, reg, &val); | 79 | ret = snd_soc_cache_read(codec, reg, &val); |
@@ -125,259 +82,117 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | |||
125 | return val; | 82 | return val; |
126 | } | 83 | } |
127 | 84 | ||
128 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | 85 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, |
129 | unsigned int value) | 86 | unsigned int reg) |
130 | { | 87 | { |
131 | u8 data[2]; | 88 | return do_hw_read(codec, reg); |
132 | int ret; | ||
133 | |||
134 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
135 | data[1] = value & 0x00ff; | ||
136 | |||
137 | if (!snd_soc_codec_volatile_register(codec, reg) && | ||
138 | reg < codec->driver->reg_cache_size && | ||
139 | !codec->cache_bypass) { | ||
140 | ret = snd_soc_cache_write(codec, reg, value); | ||
141 | if (ret < 0) | ||
142 | return -1; | ||
143 | } | ||
144 | |||
145 | if (codec->cache_only) { | ||
146 | codec->cache_sync = 1; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | ret = codec->hw_write(codec->control_data, data, 2); | ||
151 | if (ret == 2) | ||
152 | return 0; | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | else | ||
156 | return -EIO; | ||
157 | } | 89 | } |
158 | 90 | ||
159 | #if defined(CONFIG_SPI_MASTER) | 91 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, |
160 | static int snd_soc_7_9_spi_write(void *control_data, const char *data, | 92 | unsigned int value) |
161 | int len) | ||
162 | { | 93 | { |
163 | struct spi_device *spi = control_data; | 94 | u16 data; |
164 | struct spi_transfer t; | ||
165 | struct spi_message m; | ||
166 | u8 msg[2]; | ||
167 | 95 | ||
168 | if (len <= 0) | 96 | data = cpu_to_be16((reg << 12) | (value & 0xffffff)); |
169 | return 0; | ||
170 | 97 | ||
171 | msg[0] = data[0]; | 98 | return do_hw_write(codec, reg, value, &data, 2); |
172 | msg[1] = data[1]; | 99 | } |
173 | 100 | ||
174 | spi_message_init(&m); | 101 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, |
175 | memset(&t, 0, sizeof t); | 102 | unsigned int reg) |
103 | { | ||
104 | return do_hw_read(codec, reg); | ||
105 | } | ||
176 | 106 | ||
177 | t.tx_buf = &msg[0]; | 107 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, |
178 | t.len = len; | 108 | unsigned int value) |
109 | { | ||
110 | u8 data[2]; | ||
179 | 111 | ||
180 | spi_message_add_tail(&t, &m); | 112 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); |
181 | spi_sync(spi, &m); | 113 | data[1] = value & 0x00ff; |
182 | 114 | ||
183 | return len; | 115 | return do_hw_write(codec, reg, value, data, 2); |
184 | } | 116 | } |
185 | #else | ||
186 | #define snd_soc_7_9_spi_write NULL | ||
187 | #endif | ||
188 | 117 | ||
189 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | 118 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, |
190 | unsigned int value) | 119 | unsigned int value) |
191 | { | 120 | { |
192 | u8 data[2]; | 121 | u8 data[2]; |
193 | int ret; | ||
194 | 122 | ||
195 | reg &= 0xff; | 123 | reg &= 0xff; |
196 | data[0] = reg; | 124 | data[0] = reg; |
197 | data[1] = value & 0xff; | 125 | data[1] = value & 0xff; |
198 | 126 | ||
199 | if (!snd_soc_codec_volatile_register(codec, reg) && | 127 | return do_hw_write(codec, reg, value, data, 2); |
200 | reg < codec->driver->reg_cache_size && | ||
201 | !codec->cache_bypass) { | ||
202 | ret = snd_soc_cache_write(codec, reg, value); | ||
203 | if (ret < 0) | ||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | if (codec->cache_only) { | ||
208 | codec->cache_sync = 1; | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
213 | return 0; | ||
214 | else | ||
215 | return -EIO; | ||
216 | } | 128 | } |
217 | 129 | ||
218 | static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, | 130 | static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, |
219 | unsigned int reg) | 131 | unsigned int reg) |
220 | { | 132 | { |
221 | int ret; | 133 | return do_hw_read(codec, reg); |
222 | unsigned int val; | ||
223 | |||
224 | reg &= 0xff; | ||
225 | if (reg >= codec->driver->reg_cache_size || | ||
226 | snd_soc_codec_volatile_register(codec, reg) || | ||
227 | codec->cache_bypass) { | ||
228 | if (codec->cache_only) | ||
229 | return -1; | ||
230 | |||
231 | BUG_ON(!codec->hw_read); | ||
232 | return codec->hw_read(codec, reg); | ||
233 | } | ||
234 | |||
235 | ret = snd_soc_cache_read(codec, reg, &val); | ||
236 | if (ret < 0) | ||
237 | return -1; | ||
238 | return val; | ||
239 | } | ||
240 | |||
241 | #if defined(CONFIG_SPI_MASTER) | ||
242 | static int snd_soc_8_8_spi_write(void *control_data, const char *data, | ||
243 | int len) | ||
244 | { | ||
245 | struct spi_device *spi = control_data; | ||
246 | struct spi_transfer t; | ||
247 | struct spi_message m; | ||
248 | u8 msg[2]; | ||
249 | |||
250 | if (len <= 0) | ||
251 | return 0; | ||
252 | |||
253 | msg[0] = data[0]; | ||
254 | msg[1] = data[1]; | ||
255 | |||
256 | spi_message_init(&m); | ||
257 | memset(&t, 0, sizeof t); | ||
258 | |||
259 | t.tx_buf = &msg[0]; | ||
260 | t.len = len; | ||
261 | |||
262 | spi_message_add_tail(&t, &m); | ||
263 | spi_sync(spi, &m); | ||
264 | |||
265 | return len; | ||
266 | } | 134 | } |
267 | #else | ||
268 | #define snd_soc_8_8_spi_write NULL | ||
269 | #endif | ||
270 | 135 | ||
271 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | 136 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, |
272 | unsigned int value) | 137 | unsigned int value) |
273 | { | 138 | { |
274 | u8 data[3]; | 139 | u8 data[3]; |
275 | int ret; | ||
276 | 140 | ||
277 | data[0] = reg; | 141 | data[0] = reg; |
278 | data[1] = (value >> 8) & 0xff; | 142 | data[1] = (value >> 8) & 0xff; |
279 | data[2] = value & 0xff; | 143 | data[2] = value & 0xff; |
280 | 144 | ||
281 | if (!snd_soc_codec_volatile_register(codec, reg) && | 145 | return do_hw_write(codec, reg, value, data, 3); |
282 | reg < codec->driver->reg_cache_size && | ||
283 | !codec->cache_bypass) { | ||
284 | ret = snd_soc_cache_write(codec, reg, value); | ||
285 | if (ret < 0) | ||
286 | return -1; | ||
287 | } | ||
288 | |||
289 | if (codec->cache_only) { | ||
290 | codec->cache_sync = 1; | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | if (codec->hw_write(codec->control_data, data, 3) == 3) | ||
295 | return 0; | ||
296 | else | ||
297 | return -EIO; | ||
298 | } | 146 | } |
299 | 147 | ||
300 | static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, | 148 | static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, |
301 | unsigned int reg) | 149 | unsigned int reg) |
302 | { | 150 | { |
303 | int ret; | 151 | return do_hw_read(codec, reg); |
304 | unsigned int val; | ||
305 | |||
306 | if (reg >= codec->driver->reg_cache_size || | ||
307 | snd_soc_codec_volatile_register(codec, reg) || | ||
308 | codec->cache_bypass) { | ||
309 | if (codec->cache_only) | ||
310 | return -1; | ||
311 | |||
312 | BUG_ON(!codec->hw_read); | ||
313 | return codec->hw_read(codec, reg); | ||
314 | } | ||
315 | |||
316 | ret = snd_soc_cache_read(codec, reg, &val); | ||
317 | if (ret < 0) | ||
318 | return -1; | ||
319 | return val; | ||
320 | } | ||
321 | |||
322 | #if defined(CONFIG_SPI_MASTER) | ||
323 | static int snd_soc_8_16_spi_write(void *control_data, const char *data, | ||
324 | int len) | ||
325 | { | ||
326 | struct spi_device *spi = control_data; | ||
327 | struct spi_transfer t; | ||
328 | struct spi_message m; | ||
329 | u8 msg[3]; | ||
330 | |||
331 | if (len <= 0) | ||
332 | return 0; | ||
333 | |||
334 | msg[0] = data[0]; | ||
335 | msg[1] = data[1]; | ||
336 | msg[2] = data[2]; | ||
337 | |||
338 | spi_message_init(&m); | ||
339 | memset(&t, 0, sizeof t); | ||
340 | |||
341 | t.tx_buf = &msg[0]; | ||
342 | t.len = len; | ||
343 | |||
344 | spi_message_add_tail(&t, &m); | ||
345 | spi_sync(spi, &m); | ||
346 | |||
347 | return len; | ||
348 | } | 152 | } |
349 | #else | ||
350 | #define snd_soc_8_16_spi_write NULL | ||
351 | #endif | ||
352 | 153 | ||
353 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | 154 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
354 | static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | 155 | static unsigned int do_i2c_read(struct snd_soc_codec *codec, |
355 | unsigned int r) | 156 | void *reg, int reglen, |
157 | void *data, int datalen) | ||
356 | { | 158 | { |
357 | struct i2c_msg xfer[2]; | 159 | struct i2c_msg xfer[2]; |
358 | u8 reg = r; | ||
359 | u8 data; | ||
360 | int ret; | 160 | int ret; |
361 | struct i2c_client *client = codec->control_data; | 161 | struct i2c_client *client = codec->control_data; |
362 | 162 | ||
363 | /* Write register */ | 163 | /* Write register */ |
364 | xfer[0].addr = client->addr; | 164 | xfer[0].addr = client->addr; |
365 | xfer[0].flags = 0; | 165 | xfer[0].flags = 0; |
366 | xfer[0].len = 1; | 166 | xfer[0].len = reglen; |
367 | xfer[0].buf = ® | 167 | xfer[0].buf = reg; |
368 | 168 | ||
369 | /* Read data */ | 169 | /* Read data */ |
370 | xfer[1].addr = client->addr; | 170 | xfer[1].addr = client->addr; |
371 | xfer[1].flags = I2C_M_RD; | 171 | xfer[1].flags = I2C_M_RD; |
372 | xfer[1].len = 1; | 172 | xfer[1].len = datalen; |
373 | xfer[1].buf = &data; | 173 | xfer[1].buf = data; |
374 | 174 | ||
375 | ret = i2c_transfer(client->adapter, xfer, 2); | 175 | ret = i2c_transfer(client->adapter, xfer, 2); |
376 | if (ret != 2) { | 176 | if (ret == 2) |
377 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
378 | return 0; | 177 | return 0; |
379 | } | 178 | else if (ret < 0) |
179 | return ret; | ||
180 | else | ||
181 | return -EIO; | ||
182 | } | ||
183 | #endif | ||
380 | 184 | ||
185 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
186 | static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | ||
187 | unsigned int r) | ||
188 | { | ||
189 | u8 reg = r; | ||
190 | u8 data; | ||
191 | int ret; | ||
192 | |||
193 | ret = do_i2c_read(codec, ®, 1, &data, 1); | ||
194 | if (ret < 0) | ||
195 | return 0; | ||
381 | return data; | 196 | return data; |
382 | } | 197 | } |
383 | #else | 198 | #else |
@@ -388,30 +203,13 @@ static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | |||
388 | static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | 203 | static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, |
389 | unsigned int r) | 204 | unsigned int r) |
390 | { | 205 | { |
391 | struct i2c_msg xfer[2]; | ||
392 | u8 reg = r; | 206 | u8 reg = r; |
393 | u16 data; | 207 | u16 data; |
394 | int ret; | 208 | int ret; |
395 | struct i2c_client *client = codec->control_data; | ||
396 | 209 | ||
397 | /* Write register */ | 210 | ret = do_i2c_read(codec, ®, 1, &data, 2); |
398 | xfer[0].addr = client->addr; | 211 | if (ret < 0) |
399 | xfer[0].flags = 0; | ||
400 | xfer[0].len = 1; | ||
401 | xfer[0].buf = ® | ||
402 | |||
403 | /* Read data */ | ||
404 | xfer[1].addr = client->addr; | ||
405 | xfer[1].flags = I2C_M_RD; | ||
406 | xfer[1].len = 2; | ||
407 | xfer[1].buf = (u8 *)&data; | ||
408 | |||
409 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
410 | if (ret != 2) { | ||
411 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
412 | return 0; | 212 | return 0; |
413 | } | ||
414 | |||
415 | return (data >> 8) | ((data & 0xff) << 8); | 213 | return (data >> 8) | ((data & 0xff) << 8); |
416 | } | 214 | } |
417 | #else | 215 | #else |
@@ -422,30 +220,13 @@ static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | |||
422 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | 220 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, |
423 | unsigned int r) | 221 | unsigned int r) |
424 | { | 222 | { |
425 | struct i2c_msg xfer[2]; | ||
426 | u16 reg = r; | 223 | u16 reg = r; |
427 | u8 data; | 224 | u8 data; |
428 | int ret; | 225 | int ret; |
429 | struct i2c_client *client = codec->control_data; | ||
430 | |||
431 | /* Write register */ | ||
432 | xfer[0].addr = client->addr; | ||
433 | xfer[0].flags = 0; | ||
434 | xfer[0].len = 2; | ||
435 | xfer[0].buf = (u8 *)® | ||
436 | |||
437 | /* Read data */ | ||
438 | xfer[1].addr = client->addr; | ||
439 | xfer[1].flags = I2C_M_RD; | ||
440 | xfer[1].len = 1; | ||
441 | xfer[1].buf = &data; | ||
442 | 226 | ||
443 | ret = i2c_transfer(client->adapter, xfer, 2); | 227 | ret = do_i2c_read(codec, ®, 2, &data, 1); |
444 | if (ret != 2) { | 228 | if (ret < 0) |
445 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
446 | return 0; | 229 | return 0; |
447 | } | ||
448 | |||
449 | return data; | 230 | return data; |
450 | } | 231 | } |
451 | #else | 232 | #else |
@@ -453,120 +234,34 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | |||
453 | #endif | 234 | #endif |
454 | 235 | ||
455 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | 236 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, |
456 | unsigned int reg) | 237 | unsigned int reg) |
457 | { | 238 | { |
458 | int ret; | 239 | return do_hw_read(codec, reg); |
459 | unsigned int val; | ||
460 | |||
461 | reg &= 0xff; | ||
462 | if (reg >= codec->driver->reg_cache_size || | ||
463 | snd_soc_codec_volatile_register(codec, reg) || | ||
464 | codec->cache_bypass) { | ||
465 | if (codec->cache_only) | ||
466 | return -1; | ||
467 | |||
468 | BUG_ON(!codec->hw_read); | ||
469 | return codec->hw_read(codec, reg); | ||
470 | } | ||
471 | |||
472 | ret = snd_soc_cache_read(codec, reg, &val); | ||
473 | if (ret < 0) | ||
474 | return -1; | ||
475 | return val; | ||
476 | } | 240 | } |
477 | 241 | ||
478 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | 242 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, |
479 | unsigned int value) | 243 | unsigned int value) |
480 | { | 244 | { |
481 | u8 data[3]; | 245 | u8 data[3]; |
482 | int ret; | ||
483 | 246 | ||
484 | data[0] = (reg >> 8) & 0xff; | 247 | data[0] = (reg >> 8) & 0xff; |
485 | data[1] = reg & 0xff; | 248 | data[1] = reg & 0xff; |
486 | data[2] = value; | 249 | data[2] = value; |
487 | 250 | ||
488 | reg &= 0xff; | 251 | return do_hw_write(codec, reg, value, data, 3); |
489 | if (!snd_soc_codec_volatile_register(codec, reg) && | ||
490 | reg < codec->driver->reg_cache_size && | ||
491 | !codec->cache_bypass) { | ||
492 | ret = snd_soc_cache_write(codec, reg, value); | ||
493 | if (ret < 0) | ||
494 | return -1; | ||
495 | } | ||
496 | |||
497 | if (codec->cache_only) { | ||
498 | codec->cache_sync = 1; | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | ret = codec->hw_write(codec->control_data, data, 3); | ||
503 | if (ret == 3) | ||
504 | return 0; | ||
505 | if (ret < 0) | ||
506 | return ret; | ||
507 | else | ||
508 | return -EIO; | ||
509 | } | ||
510 | |||
511 | #if defined(CONFIG_SPI_MASTER) | ||
512 | static int snd_soc_16_8_spi_write(void *control_data, const char *data, | ||
513 | int len) | ||
514 | { | ||
515 | struct spi_device *spi = control_data; | ||
516 | struct spi_transfer t; | ||
517 | struct spi_message m; | ||
518 | u8 msg[3]; | ||
519 | |||
520 | if (len <= 0) | ||
521 | return 0; | ||
522 | |||
523 | msg[0] = data[0]; | ||
524 | msg[1] = data[1]; | ||
525 | msg[2] = data[2]; | ||
526 | |||
527 | spi_message_init(&m); | ||
528 | memset(&t, 0, sizeof t); | ||
529 | |||
530 | t.tx_buf = &msg[0]; | ||
531 | t.len = len; | ||
532 | |||
533 | spi_message_add_tail(&t, &m); | ||
534 | spi_sync(spi, &m); | ||
535 | |||
536 | return len; | ||
537 | } | 252 | } |
538 | #else | ||
539 | #define snd_soc_16_8_spi_write NULL | ||
540 | #endif | ||
541 | 253 | ||
542 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | 254 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
543 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | 255 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, |
544 | unsigned int r) | 256 | unsigned int r) |
545 | { | 257 | { |
546 | struct i2c_msg xfer[2]; | ||
547 | u16 reg = cpu_to_be16(r); | 258 | u16 reg = cpu_to_be16(r); |
548 | u16 data; | 259 | u16 data; |
549 | int ret; | 260 | int ret; |
550 | struct i2c_client *client = codec->control_data; | ||
551 | |||
552 | /* Write register */ | ||
553 | xfer[0].addr = client->addr; | ||
554 | xfer[0].flags = 0; | ||
555 | xfer[0].len = 2; | ||
556 | xfer[0].buf = (u8 *)® | ||
557 | 261 | ||
558 | /* Read data */ | 262 | ret = do_i2c_read(codec, ®, 2, &data, 2); |
559 | xfer[1].addr = client->addr; | 263 | if (ret < 0) |
560 | xfer[1].flags = I2C_M_RD; | ||
561 | xfer[1].len = 2; | ||
562 | xfer[1].buf = (u8 *)&data; | ||
563 | |||
564 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
565 | if (ret != 2) { | ||
566 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
567 | return 0; | 264 | return 0; |
568 | } | ||
569 | |||
570 | return be16_to_cpu(data); | 265 | return be16_to_cpu(data); |
571 | } | 266 | } |
572 | #else | 267 | #else |
@@ -576,52 +271,59 @@ static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | |||
576 | static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | 271 | static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, |
577 | unsigned int reg) | 272 | unsigned int reg) |
578 | { | 273 | { |
579 | int ret; | 274 | return do_hw_read(codec, reg); |
580 | unsigned int val; | ||
581 | |||
582 | if (reg >= codec->driver->reg_cache_size || | ||
583 | snd_soc_codec_volatile_register(codec, reg) || | ||
584 | codec->cache_bypass) { | ||
585 | if (codec->cache_only) | ||
586 | return -1; | ||
587 | |||
588 | BUG_ON(!codec->hw_read); | ||
589 | return codec->hw_read(codec, reg); | ||
590 | } | ||
591 | |||
592 | ret = snd_soc_cache_read(codec, reg, &val); | ||
593 | if (ret < 0) | ||
594 | return -1; | ||
595 | |||
596 | return val; | ||
597 | } | 275 | } |
598 | 276 | ||
599 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | 277 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, |
600 | unsigned int value) | 278 | unsigned int value) |
601 | { | 279 | { |
602 | u8 data[4]; | 280 | u8 data[4]; |
603 | int ret; | ||
604 | 281 | ||
605 | data[0] = (reg >> 8) & 0xff; | 282 | data[0] = (reg >> 8) & 0xff; |
606 | data[1] = reg & 0xff; | 283 | data[1] = reg & 0xff; |
607 | data[2] = (value >> 8) & 0xff; | 284 | data[2] = (value >> 8) & 0xff; |
608 | data[3] = value & 0xff; | 285 | data[3] = value & 0xff; |
609 | 286 | ||
610 | if (!snd_soc_codec_volatile_register(codec, reg) && | 287 | return do_hw_write(codec, reg, value, data, 4); |
611 | reg < codec->driver->reg_cache_size && | 288 | } |
612 | !codec->cache_bypass) { | ||
613 | ret = snd_soc_cache_write(codec, reg, value); | ||
614 | if (ret < 0) | ||
615 | return -1; | ||
616 | } | ||
617 | 289 | ||
618 | if (codec->cache_only) { | 290 | /* Primitive bulk write support for soc-cache. The data pointed to by |
619 | codec->cache_sync = 1; | 291 | * `data' needs to already be in the form the hardware expects |
620 | return 0; | 292 | * including any leading register specific data. Any data written |
293 | * through this function will not go through the cache as it only | ||
294 | * handles writing to volatile or out of bounds registers. | ||
295 | */ | ||
296 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, | ||
297 | const void *data, size_t len) | ||
298 | { | ||
299 | int ret; | ||
300 | |||
301 | /* To ensure that we don't get out of sync with the cache, check | ||
302 | * whether the base register is volatile or if we've directly asked | ||
303 | * to bypass the cache. Out of bounds registers are considered | ||
304 | * volatile. | ||
305 | */ | ||
306 | if (!codec->cache_bypass | ||
307 | && !snd_soc_codec_volatile_register(codec, reg) | ||
308 | && reg < codec->driver->reg_cache_size) | ||
309 | return -EINVAL; | ||
310 | |||
311 | switch (codec->control_type) { | ||
312 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
313 | case SND_SOC_I2C: | ||
314 | ret = i2c_master_send(codec->control_data, data, len); | ||
315 | break; | ||
316 | #endif | ||
317 | #if defined(CONFIG_SPI_MASTER) | ||
318 | case SND_SOC_SPI: | ||
319 | ret = spi_write(codec->control_data, data, len); | ||
320 | break; | ||
321 | #endif | ||
322 | default: | ||
323 | BUG(); | ||
621 | } | 324 | } |
622 | 325 | ||
623 | ret = codec->hw_write(codec->control_data, data, 4); | 326 | if (ret == len) |
624 | if (ret == 4) | ||
625 | return 0; | 327 | return 0; |
626 | if (ret < 0) | 328 | if (ret < 0) |
627 | return ret; | 329 | return ret; |
@@ -629,79 +331,40 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | |||
629 | return -EIO; | 331 | return -EIO; |
630 | } | 332 | } |
631 | 333 | ||
632 | #if defined(CONFIG_SPI_MASTER) | ||
633 | static int snd_soc_16_16_spi_write(void *control_data, const char *data, | ||
634 | int len) | ||
635 | { | ||
636 | struct spi_device *spi = control_data; | ||
637 | struct spi_transfer t; | ||
638 | struct spi_message m; | ||
639 | u8 msg[4]; | ||
640 | |||
641 | if (len <= 0) | ||
642 | return 0; | ||
643 | |||
644 | msg[0] = data[0]; | ||
645 | msg[1] = data[1]; | ||
646 | msg[2] = data[2]; | ||
647 | msg[3] = data[3]; | ||
648 | |||
649 | spi_message_init(&m); | ||
650 | memset(&t, 0, sizeof t); | ||
651 | |||
652 | t.tx_buf = &msg[0]; | ||
653 | t.len = len; | ||
654 | |||
655 | spi_message_add_tail(&t, &m); | ||
656 | spi_sync(spi, &m); | ||
657 | |||
658 | return len; | ||
659 | } | ||
660 | #else | ||
661 | #define snd_soc_16_16_spi_write NULL | ||
662 | #endif | ||
663 | |||
664 | static struct { | 334 | static struct { |
665 | int addr_bits; | 335 | int addr_bits; |
666 | int data_bits; | 336 | int data_bits; |
667 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); | 337 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); |
668 | int (*spi_write)(void *, const char *, int); | ||
669 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | 338 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); |
670 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | 339 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); |
671 | } io_types[] = { | 340 | } io_types[] = { |
672 | { | 341 | { |
673 | .addr_bits = 4, .data_bits = 12, | 342 | .addr_bits = 4, .data_bits = 12, |
674 | .write = snd_soc_4_12_write, .read = snd_soc_4_12_read, | 343 | .write = snd_soc_4_12_write, .read = snd_soc_4_12_read, |
675 | .spi_write = snd_soc_4_12_spi_write, | ||
676 | }, | 344 | }, |
677 | { | 345 | { |
678 | .addr_bits = 7, .data_bits = 9, | 346 | .addr_bits = 7, .data_bits = 9, |
679 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, | 347 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, |
680 | .spi_write = snd_soc_7_9_spi_write, | ||
681 | }, | 348 | }, |
682 | { | 349 | { |
683 | .addr_bits = 8, .data_bits = 8, | 350 | .addr_bits = 8, .data_bits = 8, |
684 | .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, | 351 | .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, |
685 | .i2c_read = snd_soc_8_8_read_i2c, | 352 | .i2c_read = snd_soc_8_8_read_i2c, |
686 | .spi_write = snd_soc_8_8_spi_write, | ||
687 | }, | 353 | }, |
688 | { | 354 | { |
689 | .addr_bits = 8, .data_bits = 16, | 355 | .addr_bits = 8, .data_bits = 16, |
690 | .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, | 356 | .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, |
691 | .i2c_read = snd_soc_8_16_read_i2c, | 357 | .i2c_read = snd_soc_8_16_read_i2c, |
692 | .spi_write = snd_soc_8_16_spi_write, | ||
693 | }, | 358 | }, |
694 | { | 359 | { |
695 | .addr_bits = 16, .data_bits = 8, | 360 | .addr_bits = 16, .data_bits = 8, |
696 | .write = snd_soc_16_8_write, .read = snd_soc_16_8_read, | 361 | .write = snd_soc_16_8_write, .read = snd_soc_16_8_read, |
697 | .i2c_read = snd_soc_16_8_read_i2c, | 362 | .i2c_read = snd_soc_16_8_read_i2c, |
698 | .spi_write = snd_soc_16_8_spi_write, | ||
699 | }, | 363 | }, |
700 | { | 364 | { |
701 | .addr_bits = 16, .data_bits = 16, | 365 | .addr_bits = 16, .data_bits = 16, |
702 | .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, | 366 | .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, |
703 | .i2c_read = snd_soc_16_16_read_i2c, | 367 | .i2c_read = snd_soc_16_16_read_i2c, |
704 | .spi_write = snd_soc_16_16_spi_write, | ||
705 | }, | 368 | }, |
706 | }; | 369 | }; |
707 | 370 | ||
@@ -709,7 +372,6 @@ static struct { | |||
709 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | 372 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. |
710 | * | 373 | * |
711 | * @codec: CODEC to configure. | 374 | * @codec: CODEC to configure. |
712 | * @type: Type of cache. | ||
713 | * @addr_bits: Number of bits of register address data. | 375 | * @addr_bits: Number of bits of register address data. |
714 | * @data_bits: Number of bits of data per register. | 376 | * @data_bits: Number of bits of data per register. |
715 | * @control: Control bus used. | 377 | * @control: Control bus used. |
@@ -744,6 +406,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
744 | 406 | ||
745 | codec->write = io_types[i].write; | 407 | codec->write = io_types[i].write; |
746 | codec->read = io_types[i].read; | 408 | codec->read = io_types[i].read; |
409 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; | ||
747 | 410 | ||
748 | switch (control) { | 411 | switch (control) { |
749 | case SND_SOC_CUSTOM: | 412 | case SND_SOC_CUSTOM: |
@@ -762,8 +425,9 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
762 | break; | 425 | break; |
763 | 426 | ||
764 | case SND_SOC_SPI: | 427 | case SND_SOC_SPI: |
765 | if (io_types[i].spi_write) | 428 | #ifdef CONFIG_SPI_MASTER |
766 | codec->hw_write = io_types[i].spi_write; | 429 | codec->hw_write = do_spi_write; |
430 | #endif | ||
767 | 431 | ||
768 | codec->control_data = container_of(codec->dev, | 432 | codec->control_data = container_of(codec->dev, |
769 | struct spi_device, | 433 | struct spi_device, |
@@ -889,6 +553,8 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) | |||
889 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); | 553 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); |
890 | if (rbnode->value == rbnode->defval) | 554 | if (rbnode->value == rbnode->defval) |
891 | continue; | 555 | continue; |
556 | WARN_ON(codec->writable_register && | ||
557 | codec->writable_register(codec, rbnode->reg)); | ||
892 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); | 558 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); |
893 | if (ret) | 559 | if (ret) |
894 | return ret; | 560 | return ret; |
@@ -1149,6 +815,8 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) | |||
1149 | 815 | ||
1150 | lzo_blocks = codec->reg_cache; | 816 | lzo_blocks = codec->reg_cache; |
1151 | for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { | 817 | for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { |
818 | WARN_ON(codec->writable_register && | ||
819 | codec->writable_register(codec, i)); | ||
1152 | ret = snd_soc_cache_read(codec, i, &val); | 820 | ret = snd_soc_cache_read(codec, i, &val); |
1153 | if (ret) | 821 | if (ret) |
1154 | return ret; | 822 | return ret; |
@@ -1407,6 +1075,8 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | |||
1407 | 1075 | ||
1408 | codec_drv = codec->driver; | 1076 | codec_drv = codec->driver; |
1409 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { | 1077 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { |
1078 | WARN_ON(codec->writable_register && | ||
1079 | codec->writable_register(codec, i)); | ||
1410 | ret = snd_soc_cache_read(codec, i, &val); | 1080 | ret = snd_soc_cache_read(codec, i, &val); |
1411 | if (ret) | 1081 | if (ret) |
1412 | return ret; | 1082 | return ret; |
@@ -1523,7 +1193,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
1523 | codec->cache_ops->name, codec->name); | 1193 | codec->cache_ops->name, codec->name); |
1524 | return codec->cache_ops->init(codec); | 1194 | return codec->cache_ops->init(codec); |
1525 | } | 1195 | } |
1526 | return -EINVAL; | 1196 | return -ENOSYS; |
1527 | } | 1197 | } |
1528 | 1198 | ||
1529 | /* | 1199 | /* |
@@ -1538,7 +1208,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) | |||
1538 | codec->cache_ops->name, codec->name); | 1208 | codec->cache_ops->name, codec->name); |
1539 | return codec->cache_ops->exit(codec); | 1209 | return codec->cache_ops->exit(codec); |
1540 | } | 1210 | } |
1541 | return -EINVAL; | 1211 | return -ENOSYS; |
1542 | } | 1212 | } |
1543 | 1213 | ||
1544 | /** | 1214 | /** |
@@ -1562,7 +1232,7 @@ int snd_soc_cache_read(struct snd_soc_codec *codec, | |||
1562 | } | 1232 | } |
1563 | 1233 | ||
1564 | mutex_unlock(&codec->cache_rw_mutex); | 1234 | mutex_unlock(&codec->cache_rw_mutex); |
1565 | return -EINVAL; | 1235 | return -ENOSYS; |
1566 | } | 1236 | } |
1567 | EXPORT_SYMBOL_GPL(snd_soc_cache_read); | 1237 | EXPORT_SYMBOL_GPL(snd_soc_cache_read); |
1568 | 1238 | ||
@@ -1587,7 +1257,7 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, | |||
1587 | } | 1257 | } |
1588 | 1258 | ||
1589 | mutex_unlock(&codec->cache_rw_mutex); | 1259 | mutex_unlock(&codec->cache_rw_mutex); |
1590 | return -EINVAL; | 1260 | return -ENOSYS; |
1591 | } | 1261 | } |
1592 | EXPORT_SYMBOL_GPL(snd_soc_cache_write); | 1262 | EXPORT_SYMBOL_GPL(snd_soc_cache_write); |
1593 | 1263 | ||
@@ -1610,7 +1280,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec) | |||
1610 | } | 1280 | } |
1611 | 1281 | ||
1612 | if (!codec->cache_ops || !codec->cache_ops->sync) | 1282 | if (!codec->cache_ops || !codec->cache_ops->sync) |
1613 | return -EINVAL; | 1283 | return -ENOSYS; |
1614 | 1284 | ||
1615 | if (codec->cache_ops->name) | 1285 | if (codec->cache_ops->name) |
1616 | name = codec->cache_ops->name; | 1286 | name = codec->cache_ops->name; |
@@ -1677,3 +1347,17 @@ int snd_soc_default_readable_register(struct snd_soc_codec *codec, | |||
1677 | return codec->driver->reg_access_default[index].read; | 1347 | return codec->driver->reg_access_default[index].read; |
1678 | } | 1348 | } |
1679 | EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); | 1349 | EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); |
1350 | |||
1351 | int snd_soc_default_writable_register(struct snd_soc_codec *codec, | ||
1352 | unsigned int reg) | ||
1353 | { | ||
1354 | int index; | ||
1355 | |||
1356 | if (reg >= codec->driver->reg_cache_size) | ||
1357 | return 1; | ||
1358 | index = snd_soc_get_reg_access_index(codec, reg); | ||
1359 | if (index < 0) | ||
1360 | return 0; | ||
1361 | return codec->driver->reg_access_default[index].write; | ||
1362 | } | ||
1363 | EXPORT_SYMBOL_GPL(snd_soc_default_writable_register); | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d8562ce4de7a..bb7cd5812945 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -242,7 +242,7 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
242 | const char __user *user_buf, size_t count, loff_t *ppos) | 242 | const char __user *user_buf, size_t count, loff_t *ppos) |
243 | { | 243 | { |
244 | char buf[32]; | 244 | char buf[32]; |
245 | int buf_size; | 245 | size_t buf_size; |
246 | char *start = buf; | 246 | char *start = buf; |
247 | unsigned long reg, value; | 247 | unsigned long reg, value; |
248 | int step = 1; | 248 | int step = 1; |
@@ -302,13 +302,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
302 | printk(KERN_WARNING | 302 | printk(KERN_WARNING |
303 | "ASoC: Failed to create codec register debugfs file\n"); | 303 | "ASoC: Failed to create codec register debugfs file\n"); |
304 | 304 | ||
305 | codec->dapm.debugfs_dapm = debugfs_create_dir("dapm", | 305 | snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); |
306 | codec->debugfs_codec_root); | ||
307 | if (!codec->dapm.debugfs_dapm) | ||
308 | printk(KERN_WARNING | ||
309 | "Failed to create DAPM debugfs directory\n"); | ||
310 | |||
311 | snd_soc_dapm_debugfs_init(&codec->dapm); | ||
312 | } | 306 | } |
313 | 307 | ||
314 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 308 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) |
@@ -555,7 +549,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
555 | } | 549 | } |
556 | } | 550 | } |
557 | 551 | ||
558 | if (platform->driver->ops->open) { | 552 | if (platform->driver->ops && platform->driver->ops->open) { |
559 | ret = platform->driver->ops->open(substream); | 553 | ret = platform->driver->ops->open(substream); |
560 | if (ret < 0) { | 554 | if (ret < 0) { |
561 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); | 555 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); |
@@ -685,7 +679,7 @@ machine_err: | |||
685 | codec_dai->driver->ops->shutdown(substream, codec_dai); | 679 | codec_dai->driver->ops->shutdown(substream, codec_dai); |
686 | 680 | ||
687 | codec_dai_err: | 681 | codec_dai_err: |
688 | if (platform->driver->ops->close) | 682 | if (platform->driver->ops && platform->driver->ops->close) |
689 | platform->driver->ops->close(substream); | 683 | platform->driver->ops->close(substream); |
690 | 684 | ||
691 | platform_err: | 685 | platform_err: |
@@ -767,7 +761,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
767 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | 761 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) |
768 | rtd->dai_link->ops->shutdown(substream); | 762 | rtd->dai_link->ops->shutdown(substream); |
769 | 763 | ||
770 | if (platform->driver->ops->close) | 764 | if (platform->driver->ops && platform->driver->ops->close) |
771 | platform->driver->ops->close(substream); | 765 | platform->driver->ops->close(substream); |
772 | cpu_dai->runtime = NULL; | 766 | cpu_dai->runtime = NULL; |
773 | 767 | ||
@@ -810,7 +804,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
810 | } | 804 | } |
811 | } | 805 | } |
812 | 806 | ||
813 | if (platform->driver->ops->prepare) { | 807 | if (platform->driver->ops && platform->driver->ops->prepare) { |
814 | ret = platform->driver->ops->prepare(substream); | 808 | ret = platform->driver->ops->prepare(substream); |
815 | if (ret < 0) { | 809 | if (ret < 0) { |
816 | printk(KERN_ERR "asoc: platform prepare error\n"); | 810 | printk(KERN_ERR "asoc: platform prepare error\n"); |
@@ -899,7 +893,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
899 | } | 893 | } |
900 | } | 894 | } |
901 | 895 | ||
902 | if (platform->driver->ops->hw_params) { | 896 | if (platform->driver->ops && platform->driver->ops->hw_params) { |
903 | ret = platform->driver->ops->hw_params(substream, params); | 897 | ret = platform->driver->ops->hw_params(substream, params); |
904 | if (ret < 0) { | 898 | if (ret < 0) { |
905 | printk(KERN_ERR "asoc: platform %s hw params failed\n", | 899 | printk(KERN_ERR "asoc: platform %s hw params failed\n", |
@@ -952,7 +946,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
952 | rtd->dai_link->ops->hw_free(substream); | 946 | rtd->dai_link->ops->hw_free(substream); |
953 | 947 | ||
954 | /* free any DMA resources */ | 948 | /* free any DMA resources */ |
955 | if (platform->driver->ops->hw_free) | 949 | if (platform->driver->ops && platform->driver->ops->hw_free) |
956 | platform->driver->ops->hw_free(substream); | 950 | platform->driver->ops->hw_free(substream); |
957 | 951 | ||
958 | /* now free hw params for the DAIs */ | 952 | /* now free hw params for the DAIs */ |
@@ -980,7 +974,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
980 | return ret; | 974 | return ret; |
981 | } | 975 | } |
982 | 976 | ||
983 | if (platform->driver->ops->trigger) { | 977 | if (platform->driver->ops && platform->driver->ops->trigger) { |
984 | ret = platform->driver->ops->trigger(substream, cmd); | 978 | ret = platform->driver->ops->trigger(substream, cmd); |
985 | if (ret < 0) | 979 | if (ret < 0) |
986 | return ret; | 980 | return ret; |
@@ -1009,7 +1003,7 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
1009 | snd_pcm_uframes_t offset = 0; | 1003 | snd_pcm_uframes_t offset = 0; |
1010 | snd_pcm_sframes_t delay = 0; | 1004 | snd_pcm_sframes_t delay = 0; |
1011 | 1005 | ||
1012 | if (platform->driver->ops->pointer) | 1006 | if (platform->driver->ops && platform->driver->ops->pointer) |
1013 | offset = platform->driver->ops->pointer(substream); | 1007 | offset = platform->driver->ops->pointer(substream); |
1014 | 1008 | ||
1015 | if (cpu_dai->driver->ops->delay) | 1009 | if (cpu_dai->driver->ops->delay) |
@@ -1299,6 +1293,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
1299 | struct snd_soc_codec *codec; | 1293 | struct snd_soc_codec *codec; |
1300 | struct snd_soc_platform *platform; | 1294 | struct snd_soc_platform *platform; |
1301 | struct snd_soc_dai *codec_dai, *cpu_dai; | 1295 | struct snd_soc_dai *codec_dai, *cpu_dai; |
1296 | const char *platform_name; | ||
1302 | 1297 | ||
1303 | if (rtd->complete) | 1298 | if (rtd->complete) |
1304 | return 1; | 1299 | return 1; |
@@ -1351,13 +1346,18 @@ find_codec: | |||
1351 | dai_link->codec_name); | 1346 | dai_link->codec_name); |
1352 | 1347 | ||
1353 | find_platform: | 1348 | find_platform: |
1354 | /* do we already have the CODEC DAI for this link ? */ | 1349 | /* do we need a platform? */ |
1355 | if (rtd->platform) { | 1350 | if (rtd->platform) |
1356 | goto out; | 1351 | goto out; |
1357 | } | 1352 | |
1358 | /* no, then find CPU DAI from registered DAIs*/ | 1353 | /* if there's no platform we match on the empty platform */ |
1354 | platform_name = dai_link->platform_name; | ||
1355 | if (!platform_name) | ||
1356 | platform_name = "snd-soc-dummy"; | ||
1357 | |||
1358 | /* no, then find one from the set of registered platforms */ | ||
1359 | list_for_each_entry(platform, &platform_list, list) { | 1359 | list_for_each_entry(platform, &platform_list, list) { |
1360 | if (!strcmp(platform->name, dai_link->platform_name)) { | 1360 | if (!strcmp(platform->name, platform_name)) { |
1361 | rtd->platform = platform; | 1361 | rtd->platform = platform; |
1362 | goto out; | 1362 | goto out; |
1363 | } | 1363 | } |
@@ -1453,6 +1453,16 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1453 | } | 1453 | } |
1454 | } | 1454 | } |
1455 | 1455 | ||
1456 | static void soc_remove_dai_links(struct snd_soc_card *card) | ||
1457 | { | ||
1458 | int i; | ||
1459 | |||
1460 | for (i = 0; i < card->num_rtd; i++) | ||
1461 | soc_remove_dai_link(card, i); | ||
1462 | |||
1463 | card->num_rtd = 0; | ||
1464 | } | ||
1465 | |||
1456 | static void soc_set_name_prefix(struct snd_soc_card *card, | 1466 | static void soc_set_name_prefix(struct snd_soc_card *card, |
1457 | struct snd_soc_codec *codec) | 1467 | struct snd_soc_codec *codec) |
1458 | { | 1468 | { |
@@ -1483,6 +1493,12 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1483 | if (!try_module_get(codec->dev->driver->owner)) | 1493 | if (!try_module_get(codec->dev->driver->owner)) |
1484 | return -ENODEV; | 1494 | return -ENODEV; |
1485 | 1495 | ||
1496 | soc_init_codec_debugfs(codec); | ||
1497 | |||
1498 | if (driver->dapm_widgets) | ||
1499 | snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, | ||
1500 | driver->num_dapm_widgets); | ||
1501 | |||
1486 | if (driver->probe) { | 1502 | if (driver->probe) { |
1487 | ret = driver->probe(codec); | 1503 | ret = driver->probe(codec); |
1488 | if (ret < 0) { | 1504 | if (ret < 0) { |
@@ -1493,15 +1509,13 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1493 | } | 1509 | } |
1494 | } | 1510 | } |
1495 | 1511 | ||
1496 | if (driver->dapm_widgets) | 1512 | if (driver->controls) |
1497 | snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, | 1513 | snd_soc_add_controls(codec, driver->controls, |
1498 | driver->num_dapm_widgets); | 1514 | driver->num_controls); |
1499 | if (driver->dapm_routes) | 1515 | if (driver->dapm_routes) |
1500 | snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, | 1516 | snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, |
1501 | driver->num_dapm_routes); | 1517 | driver->num_dapm_routes); |
1502 | 1518 | ||
1503 | soc_init_codec_debugfs(codec); | ||
1504 | |||
1505 | /* mark codec as probed and add to card codec list */ | 1519 | /* mark codec as probed and add to card codec list */ |
1506 | codec->probed = 1; | 1520 | codec->probed = 1; |
1507 | list_add(&codec->card_list, &card->codec_dev_list); | 1521 | list_add(&codec->card_list, &card->codec_dev_list); |
@@ -1510,6 +1524,7 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1510 | return 0; | 1524 | return 0; |
1511 | 1525 | ||
1512 | err_probe: | 1526 | err_probe: |
1527 | soc_cleanup_codec_debugfs(codec); | ||
1513 | module_put(codec->dev->driver->owner); | 1528 | module_put(codec->dev->driver->owner); |
1514 | 1529 | ||
1515 | return ret; | 1530 | return ret; |
@@ -1860,11 +1875,19 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1860 | card->dapm.card = card; | 1875 | card->dapm.card = card; |
1861 | list_add(&card->dapm.list, &card->dapm_list); | 1876 | list_add(&card->dapm.list, &card->dapm_list); |
1862 | 1877 | ||
1878 | #ifdef CONFIG_DEBUG_FS | ||
1879 | snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); | ||
1880 | #endif | ||
1881 | |||
1863 | #ifdef CONFIG_PM_SLEEP | 1882 | #ifdef CONFIG_PM_SLEEP |
1864 | /* deferred resume work */ | 1883 | /* deferred resume work */ |
1865 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | 1884 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); |
1866 | #endif | 1885 | #endif |
1867 | 1886 | ||
1887 | if (card->dapm_widgets) | ||
1888 | snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, | ||
1889 | card->num_dapm_widgets); | ||
1890 | |||
1868 | /* initialise the sound card only once */ | 1891 | /* initialise the sound card only once */ |
1869 | if (card->probe) { | 1892 | if (card->probe) { |
1870 | ret = card->probe(card); | 1893 | ret = card->probe(card); |
@@ -1890,27 +1913,24 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1890 | } | 1913 | } |
1891 | } | 1914 | } |
1892 | 1915 | ||
1893 | if (card->dapm_widgets) | 1916 | /* We should have a non-codec control add function but we don't */ |
1894 | snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, | 1917 | if (card->controls) |
1895 | card->num_dapm_widgets); | 1918 | snd_soc_add_controls(list_first_entry(&card->codec_dev_list, |
1919 | struct snd_soc_codec, | ||
1920 | card_list), | ||
1921 | card->controls, | ||
1922 | card->num_controls); | ||
1923 | |||
1896 | if (card->dapm_routes) | 1924 | if (card->dapm_routes) |
1897 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, | 1925 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, |
1898 | card->num_dapm_routes); | 1926 | card->num_dapm_routes); |
1899 | 1927 | ||
1900 | #ifdef CONFIG_DEBUG_FS | ||
1901 | card->dapm.debugfs_dapm = debugfs_create_dir("dapm", | ||
1902 | card->debugfs_card_root); | ||
1903 | if (!card->dapm.debugfs_dapm) | ||
1904 | printk(KERN_WARNING | ||
1905 | "Failed to create card DAPM debugfs directory\n"); | ||
1906 | |||
1907 | snd_soc_dapm_debugfs_init(&card->dapm); | ||
1908 | #endif | ||
1909 | |||
1910 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1928 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
1911 | "%s", card->name); | ||
1912 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | ||
1913 | "%s", card->name); | 1929 | "%s", card->name); |
1930 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | ||
1931 | "%s", card->long_name ? card->long_name : card->name); | ||
1932 | snprintf(card->snd_card->driver, sizeof(card->snd_card->driver), | ||
1933 | "%s", card->driver_name ? card->driver_name : card->name); | ||
1914 | 1934 | ||
1915 | if (card->late_probe) { | 1935 | if (card->late_probe) { |
1916 | ret = card->late_probe(card); | 1936 | ret = card->late_probe(card); |
@@ -1949,8 +1969,7 @@ probe_aux_dev_err: | |||
1949 | soc_remove_aux_dev(card, i); | 1969 | soc_remove_aux_dev(card, i); |
1950 | 1970 | ||
1951 | probe_dai_err: | 1971 | probe_dai_err: |
1952 | for (i = 0; i < card->num_links; i++) | 1972 | soc_remove_dai_links(card); |
1953 | soc_remove_dai_link(card, i); | ||
1954 | 1973 | ||
1955 | card_probe_error: | 1974 | card_probe_error: |
1956 | if (card->remove) | 1975 | if (card->remove) |
@@ -2012,8 +2031,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
2012 | soc_remove_aux_dev(card, i); | 2031 | soc_remove_aux_dev(card, i); |
2013 | 2032 | ||
2014 | /* remove and free each DAI */ | 2033 | /* remove and free each DAI */ |
2015 | for (i = 0; i < card->num_rtd; i++) | 2034 | soc_remove_dai_links(card); |
2016 | soc_remove_dai_link(card, i); | ||
2017 | 2035 | ||
2018 | soc_cleanup_card_debugfs(card); | 2036 | soc_cleanup_card_debugfs(card); |
2019 | 2037 | ||
@@ -2021,6 +2039,8 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
2021 | if (card->remove) | 2039 | if (card->remove) |
2022 | card->remove(card); | 2040 | card->remove(card); |
2023 | 2041 | ||
2042 | snd_soc_dapm_free(&card->dapm); | ||
2043 | |||
2024 | kfree(card->rtd); | 2044 | kfree(card->rtd); |
2025 | snd_card_free(card->snd_card); | 2045 | snd_card_free(card->snd_card); |
2026 | return 0; | 2046 | return 0; |
@@ -2105,13 +2125,15 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2105 | 2125 | ||
2106 | rtd->pcm = pcm; | 2126 | rtd->pcm = pcm; |
2107 | pcm->private_data = rtd; | 2127 | pcm->private_data = rtd; |
2108 | soc_pcm_ops.mmap = platform->driver->ops->mmap; | 2128 | if (platform->driver->ops) { |
2109 | soc_pcm_ops.pointer = platform->driver->ops->pointer; | 2129 | soc_pcm_ops.mmap = platform->driver->ops->mmap; |
2110 | soc_pcm_ops.ioctl = platform->driver->ops->ioctl; | 2130 | soc_pcm_ops.pointer = platform->driver->ops->pointer; |
2111 | soc_pcm_ops.copy = platform->driver->ops->copy; | 2131 | soc_pcm_ops.ioctl = platform->driver->ops->ioctl; |
2112 | soc_pcm_ops.silence = platform->driver->ops->silence; | 2132 | soc_pcm_ops.copy = platform->driver->ops->copy; |
2113 | soc_pcm_ops.ack = platform->driver->ops->ack; | 2133 | soc_pcm_ops.silence = platform->driver->ops->silence; |
2114 | soc_pcm_ops.page = platform->driver->ops->page; | 2134 | soc_pcm_ops.ack = platform->driver->ops->ack; |
2135 | soc_pcm_ops.page = platform->driver->ops->page; | ||
2136 | } | ||
2115 | 2137 | ||
2116 | if (playback) | 2138 | if (playback) |
2117 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | 2139 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); |
@@ -2119,10 +2141,13 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2119 | if (capture) | 2141 | if (capture) |
2120 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | 2142 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); |
2121 | 2143 | ||
2122 | ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm); | 2144 | if (platform->driver->pcm_new) { |
2123 | if (ret < 0) { | 2145 | ret = platform->driver->pcm_new(rtd->card->snd_card, |
2124 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); | 2146 | codec_dai, pcm); |
2125 | return ret; | 2147 | if (ret < 0) { |
2148 | pr_err("asoc: platform pcm constructor failed\n"); | ||
2149 | return ret; | ||
2150 | } | ||
2126 | } | 2151 | } |
2127 | 2152 | ||
2128 | pcm->private_free = platform->driver->pcm_free; | 2153 | pcm->private_free = platform->driver->pcm_free; |
@@ -2150,6 +2175,42 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, | |||
2150 | EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); | 2175 | EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); |
2151 | 2176 | ||
2152 | /** | 2177 | /** |
2178 | * snd_soc_codec_readable_register: Report if a register is readable. | ||
2179 | * | ||
2180 | * @codec: CODEC to query. | ||
2181 | * @reg: Register to query. | ||
2182 | * | ||
2183 | * Boolean function indicating if a CODEC register is readable. | ||
2184 | */ | ||
2185 | int snd_soc_codec_readable_register(struct snd_soc_codec *codec, | ||
2186 | unsigned int reg) | ||
2187 | { | ||
2188 | if (codec->readable_register) | ||
2189 | return codec->readable_register(codec, reg); | ||
2190 | else | ||
2191 | return 0; | ||
2192 | } | ||
2193 | EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register); | ||
2194 | |||
2195 | /** | ||
2196 | * snd_soc_codec_writable_register: Report if a register is writable. | ||
2197 | * | ||
2198 | * @codec: CODEC to query. | ||
2199 | * @reg: Register to query. | ||
2200 | * | ||
2201 | * Boolean function indicating if a CODEC register is writable. | ||
2202 | */ | ||
2203 | int snd_soc_codec_writable_register(struct snd_soc_codec *codec, | ||
2204 | unsigned int reg) | ||
2205 | { | ||
2206 | if (codec->writable_register) | ||
2207 | return codec->writable_register(codec, reg); | ||
2208 | else | ||
2209 | return 0; | ||
2210 | } | ||
2211 | EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); | ||
2212 | |||
2213 | /** | ||
2153 | * snd_soc_new_ac97_codec - initailise AC97 device | 2214 | * snd_soc_new_ac97_codec - initailise AC97 device |
2154 | * @codec: audio codec | 2215 | * @codec: audio codec |
2155 | * @ops: AC97 bus operations | 2216 | * @ops: AC97 bus operations |
@@ -2231,6 +2292,13 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec, | |||
2231 | } | 2292 | } |
2232 | EXPORT_SYMBOL_GPL(snd_soc_write); | 2293 | EXPORT_SYMBOL_GPL(snd_soc_write); |
2233 | 2294 | ||
2295 | unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec, | ||
2296 | unsigned int reg, const void *data, size_t len) | ||
2297 | { | ||
2298 | return codec->bulk_write_raw(codec, reg, data, len); | ||
2299 | } | ||
2300 | EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw); | ||
2301 | |||
2234 | /** | 2302 | /** |
2235 | * snd_soc_update_bits - update codec register bits | 2303 | * snd_soc_update_bits - update codec register bits |
2236 | * @codec: audio codec | 2304 | * @codec: audio codec |
@@ -3291,6 +3359,8 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3291 | if (!card->name || !card->dev) | 3359 | if (!card->name || !card->dev) |
3292 | return -EINVAL; | 3360 | return -EINVAL; |
3293 | 3361 | ||
3362 | dev_set_drvdata(card->dev, card); | ||
3363 | |||
3294 | snd_soc_initialize_card_lists(card); | 3364 | snd_soc_initialize_card_lists(card); |
3295 | 3365 | ||
3296 | soc_init_card_debugfs(card); | 3366 | soc_init_card_debugfs(card); |
@@ -3412,7 +3482,7 @@ int snd_soc_register_dai(struct device *dev, | |||
3412 | 3482 | ||
3413 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); | 3483 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); |
3414 | if (dai == NULL) | 3484 | if (dai == NULL) |
3415 | return -ENOMEM; | 3485 | return -ENOMEM; |
3416 | 3486 | ||
3417 | /* create DAI component name */ | 3487 | /* create DAI component name */ |
3418 | dai->name = fmt_single_name(dev, &dai->id); | 3488 | dai->name = fmt_single_name(dev, &dai->id); |
@@ -3551,7 +3621,7 @@ int snd_soc_register_platform(struct device *dev, | |||
3551 | 3621 | ||
3552 | platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); | 3622 | platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); |
3553 | if (platform == NULL) | 3623 | if (platform == NULL) |
3554 | return -ENOMEM; | 3624 | return -ENOMEM; |
3555 | 3625 | ||
3556 | /* create platform component name */ | 3626 | /* create platform component name */ |
3557 | platform->name = fmt_single_name(dev, &platform->id); | 3627 | platform->name = fmt_single_name(dev, &platform->id); |
@@ -3669,6 +3739,7 @@ int snd_soc_register_codec(struct device *dev, | |||
3669 | codec->read = codec_drv->read; | 3739 | codec->read = codec_drv->read; |
3670 | codec->volatile_register = codec_drv->volatile_register; | 3740 | codec->volatile_register = codec_drv->volatile_register; |
3671 | codec->readable_register = codec_drv->readable_register; | 3741 | codec->readable_register = codec_drv->readable_register; |
3742 | codec->writable_register = codec_drv->writable_register; | ||
3672 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 3743 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
3673 | codec->dapm.dev = dev; | 3744 | codec->dapm.dev = dev; |
3674 | codec->dapm.codec = codec; | 3745 | codec->dapm.codec = codec; |
@@ -3703,6 +3774,8 @@ int snd_soc_register_codec(struct device *dev, | |||
3703 | codec->volatile_register = snd_soc_default_volatile_register; | 3774 | codec->volatile_register = snd_soc_default_volatile_register; |
3704 | if (!codec->readable_register) | 3775 | if (!codec->readable_register) |
3705 | codec->readable_register = snd_soc_default_readable_register; | 3776 | codec->readable_register = snd_soc_default_readable_register; |
3777 | if (!codec->writable_register) | ||
3778 | codec->writable_register = snd_soc_default_writable_register; | ||
3706 | } | 3779 | } |
3707 | 3780 | ||
3708 | for (i = 0; i < num_dai; i++) { | 3781 | for (i = 0; i < num_dai; i++) { |
@@ -3791,12 +3864,16 @@ static int __init snd_soc_init(void) | |||
3791 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); | 3864 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); |
3792 | #endif | 3865 | #endif |
3793 | 3866 | ||
3867 | snd_soc_util_init(); | ||
3868 | |||
3794 | return platform_driver_register(&soc_driver); | 3869 | return platform_driver_register(&soc_driver); |
3795 | } | 3870 | } |
3796 | module_init(snd_soc_init); | 3871 | module_init(snd_soc_init); |
3797 | 3872 | ||
3798 | static void __exit snd_soc_exit(void) | 3873 | static void __exit snd_soc_exit(void) |
3799 | { | 3874 | { |
3875 | snd_soc_util_exit(); | ||
3876 | |||
3800 | #ifdef CONFIG_DEBUG_FS | 3877 | #ifdef CONFIG_DEBUG_FS |
3801 | debugfs_remove_recursive(snd_soc_debugfs_root); | 3878 | debugfs_remove_recursive(snd_soc_debugfs_root); |
3802 | #endif | 3879 | #endif |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 81c4052c127c..456617e63789 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -187,7 +187,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
187 | case snd_soc_dapm_mixer_named_ctl: { | 187 | case snd_soc_dapm_mixer_named_ctl: { |
188 | int val; | 188 | int val; |
189 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 189 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
190 | w->kcontrols[i].private_value; | 190 | w->kcontrol_news[i].private_value; |
191 | unsigned int reg = mc->reg; | 191 | unsigned int reg = mc->reg; |
192 | unsigned int shift = mc->shift; | 192 | unsigned int shift = mc->shift; |
193 | int max = mc->max; | 193 | int max = mc->max; |
@@ -204,7 +204,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
204 | } | 204 | } |
205 | break; | 205 | break; |
206 | case snd_soc_dapm_mux: { | 206 | case snd_soc_dapm_mux: { |
207 | struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; | 207 | struct soc_enum *e = (struct soc_enum *) |
208 | w->kcontrol_news[i].private_value; | ||
208 | int val, item, bitmask; | 209 | int val, item, bitmask; |
209 | 210 | ||
210 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 211 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
@@ -220,7 +221,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
220 | } | 221 | } |
221 | break; | 222 | break; |
222 | case snd_soc_dapm_virt_mux: { | 223 | case snd_soc_dapm_virt_mux: { |
223 | struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; | 224 | struct soc_enum *e = (struct soc_enum *) |
225 | w->kcontrol_news[i].private_value; | ||
224 | 226 | ||
225 | p->connect = 0; | 227 | p->connect = 0; |
226 | /* since a virtual mux has no backing registers to | 228 | /* since a virtual mux has no backing registers to |
@@ -235,7 +237,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
235 | break; | 237 | break; |
236 | case snd_soc_dapm_value_mux: { | 238 | case snd_soc_dapm_value_mux: { |
237 | struct soc_enum *e = (struct soc_enum *) | 239 | struct soc_enum *e = (struct soc_enum *) |
238 | w->kcontrols[i].private_value; | 240 | w->kcontrol_news[i].private_value; |
239 | int val, item; | 241 | int val, item; |
240 | 242 | ||
241 | val = snd_soc_read(w->codec, e->reg); | 243 | val = snd_soc_read(w->codec, e->reg); |
@@ -310,11 +312,11 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | |||
310 | 312 | ||
311 | /* search for mixer kcontrol */ | 313 | /* search for mixer kcontrol */ |
312 | for (i = 0; i < dest->num_kcontrols; i++) { | 314 | for (i = 0; i < dest->num_kcontrols; i++) { |
313 | if (!strcmp(control_name, dest->kcontrols[i].name)) { | 315 | if (!strcmp(control_name, dest->kcontrol_news[i].name)) { |
314 | list_add(&path->list, &dapm->card->paths); | 316 | list_add(&path->list, &dapm->card->paths); |
315 | list_add(&path->list_sink, &dest->sources); | 317 | list_add(&path->list_sink, &dest->sources); |
316 | list_add(&path->list_source, &src->sinks); | 318 | list_add(&path->list_source, &src->sinks); |
317 | path->name = dest->kcontrols[i].name; | 319 | path->name = dest->kcontrol_news[i].name; |
318 | dapm_set_path_status(dest, path, i); | 320 | dapm_set_path_status(dest, path, i); |
319 | return 0; | 321 | return 0; |
320 | } | 322 | } |
@@ -322,43 +324,26 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | |||
322 | return -ENODEV; | 324 | return -ENODEV; |
323 | } | 325 | } |
324 | 326 | ||
325 | /* update dapm codec register bits */ | 327 | static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, |
326 | static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | 328 | const struct snd_kcontrol_new *kcontrol_new, |
329 | struct snd_kcontrol **kcontrol) | ||
327 | { | 330 | { |
328 | int change, power; | 331 | struct snd_soc_dapm_widget *w; |
329 | unsigned int old, new; | 332 | int i; |
330 | struct snd_soc_codec *codec = widget->codec; | ||
331 | struct snd_soc_dapm_context *dapm = widget->dapm; | ||
332 | struct snd_soc_card *card = dapm->card; | ||
333 | |||
334 | /* check for valid widgets */ | ||
335 | if (widget->reg < 0 || widget->id == snd_soc_dapm_input || | ||
336 | widget->id == snd_soc_dapm_output || | ||
337 | widget->id == snd_soc_dapm_hp || | ||
338 | widget->id == snd_soc_dapm_mic || | ||
339 | widget->id == snd_soc_dapm_line || | ||
340 | widget->id == snd_soc_dapm_spk) | ||
341 | return 0; | ||
342 | |||
343 | power = widget->power; | ||
344 | if (widget->invert) | ||
345 | power = (power ? 0:1); | ||
346 | 333 | ||
347 | old = snd_soc_read(codec, widget->reg); | 334 | *kcontrol = NULL; |
348 | new = (old & ~(0x1 << widget->shift)) | (power << widget->shift); | ||
349 | 335 | ||
350 | change = old != new; | 336 | list_for_each_entry(w, &dapm->card->widgets, list) { |
351 | if (change) { | 337 | for (i = 0; i < w->num_kcontrols; i++) { |
352 | pop_dbg(dapm->dev, card->pop_time, | 338 | if (&w->kcontrol_news[i] == kcontrol_new) { |
353 | "pop test %s : %s in %d ms\n", | 339 | if (w->kcontrols) |
354 | widget->name, widget->power ? "on" : "off", | 340 | *kcontrol = w->kcontrols[i]; |
355 | card->pop_time); | 341 | return 1; |
356 | pop_wait(card->pop_time); | 342 | } |
357 | snd_soc_write(codec, widget->reg, new); | 343 | } |
358 | } | 344 | } |
359 | dev_dbg(dapm->dev, "reg %x old %x new %x change %d\n", widget->reg, | 345 | |
360 | old, new, change); | 346 | return 0; |
361 | return change; | ||
362 | } | 347 | } |
363 | 348 | ||
364 | /* create new dapm mixer control */ | 349 | /* create new dapm mixer control */ |
@@ -370,6 +355,8 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
370 | struct snd_soc_dapm_path *path; | 355 | struct snd_soc_dapm_path *path; |
371 | struct snd_card *card = dapm->card->snd_card; | 356 | struct snd_card *card = dapm->card->snd_card; |
372 | const char *prefix; | 357 | const char *prefix; |
358 | struct snd_soc_dapm_widget_list *wlist; | ||
359 | size_t wlistsize; | ||
373 | 360 | ||
374 | if (dapm->codec) | 361 | if (dapm->codec) |
375 | prefix = dapm->codec->name_prefix; | 362 | prefix = dapm->codec->name_prefix; |
@@ -388,23 +375,37 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
388 | list_for_each_entry(path, &w->sources, list_sink) { | 375 | list_for_each_entry(path, &w->sources, list_sink) { |
389 | 376 | ||
390 | /* mixer/mux paths name must match control name */ | 377 | /* mixer/mux paths name must match control name */ |
391 | if (path->name != (char*)w->kcontrols[i].name) | 378 | if (path->name != (char *)w->kcontrol_news[i].name) |
392 | continue; | 379 | continue; |
393 | 380 | ||
381 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
382 | sizeof(struct snd_soc_dapm_widget *), | ||
383 | wlist = kzalloc(wlistsize, GFP_KERNEL); | ||
384 | if (wlist == NULL) { | ||
385 | dev_err(dapm->dev, | ||
386 | "asoc: can't allocate widget list for %s\n", | ||
387 | w->name); | ||
388 | return -ENOMEM; | ||
389 | } | ||
390 | wlist->num_widgets = 1; | ||
391 | wlist->widgets[0] = w; | ||
392 | |||
394 | /* add dapm control with long name. | 393 | /* add dapm control with long name. |
395 | * for dapm_mixer this is the concatenation of the | 394 | * for dapm_mixer this is the concatenation of the |
396 | * mixer and kcontrol name. | 395 | * mixer and kcontrol name. |
397 | * for dapm_mixer_named_ctl this is simply the | 396 | * for dapm_mixer_named_ctl this is simply the |
398 | * kcontrol name. | 397 | * kcontrol name. |
399 | */ | 398 | */ |
400 | name_len = strlen(w->kcontrols[i].name) + 1; | 399 | name_len = strlen(w->kcontrol_news[i].name) + 1; |
401 | if (w->id != snd_soc_dapm_mixer_named_ctl) | 400 | if (w->id != snd_soc_dapm_mixer_named_ctl) |
402 | name_len += 1 + strlen(w->name); | 401 | name_len += 1 + strlen(w->name); |
403 | 402 | ||
404 | path->long_name = kmalloc(name_len, GFP_KERNEL); | 403 | path->long_name = kmalloc(name_len, GFP_KERNEL); |
405 | 404 | ||
406 | if (path->long_name == NULL) | 405 | if (path->long_name == NULL) { |
406 | kfree(wlist); | ||
407 | return -ENOMEM; | 407 | return -ENOMEM; |
408 | } | ||
408 | 409 | ||
409 | switch (w->id) { | 410 | switch (w->id) { |
410 | default: | 411 | default: |
@@ -416,27 +417,30 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
416 | */ | 417 | */ |
417 | snprintf(path->long_name, name_len, "%s %s", | 418 | snprintf(path->long_name, name_len, "%s %s", |
418 | w->name + prefix_len, | 419 | w->name + prefix_len, |
419 | w->kcontrols[i].name); | 420 | w->kcontrol_news[i].name); |
420 | break; | 421 | break; |
421 | case snd_soc_dapm_mixer_named_ctl: | 422 | case snd_soc_dapm_mixer_named_ctl: |
422 | snprintf(path->long_name, name_len, "%s", | 423 | snprintf(path->long_name, name_len, "%s", |
423 | w->kcontrols[i].name); | 424 | w->kcontrol_news[i].name); |
424 | break; | 425 | break; |
425 | } | 426 | } |
426 | 427 | ||
427 | path->long_name[name_len - 1] = '\0'; | 428 | path->long_name[name_len - 1] = '\0'; |
428 | 429 | ||
429 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 430 | path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i], |
430 | path->long_name, prefix); | 431 | wlist, path->long_name, |
432 | prefix); | ||
431 | ret = snd_ctl_add(card, path->kcontrol); | 433 | ret = snd_ctl_add(card, path->kcontrol); |
432 | if (ret < 0) { | 434 | if (ret < 0) { |
433 | dev_err(dapm->dev, | 435 | dev_err(dapm->dev, |
434 | "asoc: failed to add dapm kcontrol %s: %d\n", | 436 | "asoc: failed to add dapm kcontrol %s: %d\n", |
435 | path->long_name, ret); | 437 | path->long_name, ret); |
438 | kfree(wlist); | ||
436 | kfree(path->long_name); | 439 | kfree(path->long_name); |
437 | path->long_name = NULL; | 440 | path->long_name = NULL; |
438 | return ret; | 441 | return ret; |
439 | } | 442 | } |
443 | w->kcontrols[i] = path->kcontrol; | ||
440 | } | 444 | } |
441 | } | 445 | } |
442 | return ret; | 446 | return ret; |
@@ -451,42 +455,80 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
451 | struct snd_card *card = dapm->card->snd_card; | 455 | struct snd_card *card = dapm->card->snd_card; |
452 | const char *prefix; | 456 | const char *prefix; |
453 | size_t prefix_len; | 457 | size_t prefix_len; |
454 | int ret = 0; | 458 | int ret; |
455 | 459 | struct snd_soc_dapm_widget_list *wlist; | |
456 | if (!w->num_kcontrols) { | 460 | int shared, wlistentries; |
457 | dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name); | 461 | size_t wlistsize; |
462 | char *name; | ||
463 | |||
464 | if (w->num_kcontrols != 1) { | ||
465 | dev_err(dapm->dev, | ||
466 | "asoc: mux %s has incorrect number of controls\n", | ||
467 | w->name); | ||
458 | return -EINVAL; | 468 | return -EINVAL; |
459 | } | 469 | } |
460 | 470 | ||
461 | if (dapm->codec) | 471 | shared = dapm_is_shared_kcontrol(dapm, &w->kcontrol_news[0], |
462 | prefix = dapm->codec->name_prefix; | 472 | &kcontrol); |
463 | else | 473 | if (kcontrol) { |
464 | prefix = NULL; | 474 | wlist = kcontrol->private_data; |
475 | wlistentries = wlist->num_widgets + 1; | ||
476 | } else { | ||
477 | wlist = NULL; | ||
478 | wlistentries = 1; | ||
479 | } | ||
480 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
481 | wlistentries * sizeof(struct snd_soc_dapm_widget *), | ||
482 | wlist = krealloc(wlist, wlistsize, GFP_KERNEL); | ||
483 | if (wlist == NULL) { | ||
484 | dev_err(dapm->dev, | ||
485 | "asoc: can't allocate widget list for %s\n", w->name); | ||
486 | return -ENOMEM; | ||
487 | } | ||
488 | wlist->num_widgets = wlistentries; | ||
489 | wlist->widgets[wlistentries - 1] = w; | ||
465 | 490 | ||
466 | if (prefix) | 491 | if (!kcontrol) { |
467 | prefix_len = strlen(prefix) + 1; | 492 | if (dapm->codec) |
468 | else | 493 | prefix = dapm->codec->name_prefix; |
469 | prefix_len = 0; | 494 | else |
495 | prefix = NULL; | ||
496 | |||
497 | if (shared) { | ||
498 | name = w->kcontrol_news[0].name; | ||
499 | prefix_len = 0; | ||
500 | } else { | ||
501 | name = w->name; | ||
502 | if (prefix) | ||
503 | prefix_len = strlen(prefix) + 1; | ||
504 | else | ||
505 | prefix_len = 0; | ||
506 | } | ||
470 | 507 | ||
471 | /* The control will get a prefix from the control creation | 508 | /* |
472 | * process but we're also using the same prefix for widgets so | 509 | * The control will get a prefix from the control creation |
473 | * cut the prefix off the front of the widget name. | 510 | * process but we're also using the same prefix for widgets so |
474 | */ | 511 | * cut the prefix off the front of the widget name. |
475 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name + prefix_len, | 512 | */ |
476 | prefix); | 513 | kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist, |
477 | ret = snd_ctl_add(card, kcontrol); | 514 | name + prefix_len, prefix); |
515 | ret = snd_ctl_add(card, kcontrol); | ||
516 | if (ret < 0) { | ||
517 | dev_err(dapm->dev, | ||
518 | "asoc: failed to add kcontrol %s\n", w->name); | ||
519 | kfree(wlist); | ||
520 | return ret; | ||
521 | } | ||
522 | } | ||
478 | 523 | ||
479 | if (ret < 0) | 524 | kcontrol->private_data = wlist; |
480 | goto err; | 525 | |
526 | w->kcontrols[0] = kcontrol; | ||
481 | 527 | ||
482 | list_for_each_entry(path, &w->sources, list_sink) | 528 | list_for_each_entry(path, &w->sources, list_sink) |
483 | path->kcontrol = kcontrol; | 529 | path->kcontrol = kcontrol; |
484 | 530 | ||
485 | return ret; | 531 | return 0; |
486 | |||
487 | err: | ||
488 | dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name); | ||
489 | return ret; | ||
490 | } | 532 | } |
491 | 533 | ||
492 | /* create new dapm volume control */ | 534 | /* create new dapm volume control */ |
@@ -644,57 +686,6 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, | |||
644 | } | 686 | } |
645 | EXPORT_SYMBOL_GPL(dapm_reg_event); | 687 | EXPORT_SYMBOL_GPL(dapm_reg_event); |
646 | 688 | ||
647 | /* Standard power change method, used to apply power changes to most | ||
648 | * widgets. | ||
649 | */ | ||
650 | static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w) | ||
651 | { | ||
652 | int ret; | ||
653 | |||
654 | /* call any power change event handlers */ | ||
655 | if (w->event) | ||
656 | dev_dbg(w->dapm->dev, "power %s event for %s flags %x\n", | ||
657 | w->power ? "on" : "off", | ||
658 | w->name, w->event_flags); | ||
659 | |||
660 | /* power up pre event */ | ||
661 | if (w->power && w->event && | ||
662 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | ||
663 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
664 | if (ret < 0) | ||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | /* power down pre event */ | ||
669 | if (!w->power && w->event && | ||
670 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
671 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
672 | if (ret < 0) | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | dapm_update_bits(w); | ||
677 | |||
678 | /* power up post event */ | ||
679 | if (w->power && w->event && | ||
680 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
681 | ret = w->event(w, | ||
682 | NULL, SND_SOC_DAPM_POST_PMU); | ||
683 | if (ret < 0) | ||
684 | return ret; | ||
685 | } | ||
686 | |||
687 | /* power down post event */ | ||
688 | if (!w->power && w->event && | ||
689 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
690 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
691 | if (ret < 0) | ||
692 | return ret; | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | /* Generic check to see if a widget should be powered. | 689 | /* Generic check to see if a widget should be powered. |
699 | */ | 690 | */ |
700 | static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) | 691 | static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) |
@@ -981,16 +972,6 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
981 | NULL, SND_SOC_DAPM_POST_PMD); | 972 | NULL, SND_SOC_DAPM_POST_PMD); |
982 | break; | 973 | break; |
983 | 974 | ||
984 | case snd_soc_dapm_input: | ||
985 | case snd_soc_dapm_output: | ||
986 | case snd_soc_dapm_hp: | ||
987 | case snd_soc_dapm_mic: | ||
988 | case snd_soc_dapm_line: | ||
989 | case snd_soc_dapm_spk: | ||
990 | /* No register support currently */ | ||
991 | ret = dapm_generic_apply_power(w); | ||
992 | break; | ||
993 | |||
994 | default: | 975 | default: |
995 | /* Queue it up for application */ | 976 | /* Queue it up for application */ |
996 | cur_sort = sort[w->id]; | 977 | cur_sort = sort[w->id]; |
@@ -1201,6 +1182,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1201 | } | 1182 | } |
1202 | } | 1183 | } |
1203 | 1184 | ||
1185 | /* Force all contexts in the card to the same bias state */ | ||
1186 | power = 0; | ||
1187 | list_for_each_entry(d, &card->dapm_list, list) | ||
1188 | if (d->dev_power) | ||
1189 | power = 1; | ||
1190 | list_for_each_entry(d, &card->dapm_list, list) | ||
1191 | d->dev_power = power; | ||
1192 | |||
1193 | |||
1204 | /* Run all the bias changes in parallel */ | 1194 | /* Run all the bias changes in parallel */ |
1205 | list_for_each_entry(d, &dapm->card->dapm_list, list) | 1195 | list_for_each_entry(d, &dapm->card->dapm_list, list) |
1206 | async_schedule_domain(dapm_pre_sequence_async, d, | 1196 | async_schedule_domain(dapm_pre_sequence_async, d, |
@@ -1304,31 +1294,104 @@ static const struct file_operations dapm_widget_power_fops = { | |||
1304 | .llseek = default_llseek, | 1294 | .llseek = default_llseek, |
1305 | }; | 1295 | }; |
1306 | 1296 | ||
1307 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) | 1297 | static int dapm_bias_open_file(struct inode *inode, struct file *file) |
1298 | { | ||
1299 | file->private_data = inode->i_private; | ||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf, | ||
1304 | size_t count, loff_t *ppos) | ||
1305 | { | ||
1306 | struct snd_soc_dapm_context *dapm = file->private_data; | ||
1307 | char *level; | ||
1308 | |||
1309 | switch (dapm->bias_level) { | ||
1310 | case SND_SOC_BIAS_ON: | ||
1311 | level = "On\n"; | ||
1312 | break; | ||
1313 | case SND_SOC_BIAS_PREPARE: | ||
1314 | level = "Prepare\n"; | ||
1315 | break; | ||
1316 | case SND_SOC_BIAS_STANDBY: | ||
1317 | level = "Standby\n"; | ||
1318 | break; | ||
1319 | case SND_SOC_BIAS_OFF: | ||
1320 | level = "Off\n"; | ||
1321 | break; | ||
1322 | default: | ||
1323 | BUG(); | ||
1324 | level = "Unknown\n"; | ||
1325 | break; | ||
1326 | } | ||
1327 | |||
1328 | return simple_read_from_buffer(user_buf, count, ppos, level, | ||
1329 | strlen(level)); | ||
1330 | } | ||
1331 | |||
1332 | static const struct file_operations dapm_bias_fops = { | ||
1333 | .open = dapm_bias_open_file, | ||
1334 | .read = dapm_bias_read_file, | ||
1335 | .llseek = default_llseek, | ||
1336 | }; | ||
1337 | |||
1338 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, | ||
1339 | struct dentry *parent) | ||
1308 | { | 1340 | { |
1309 | struct snd_soc_dapm_widget *w; | ||
1310 | struct dentry *d; | 1341 | struct dentry *d; |
1311 | 1342 | ||
1312 | if (!dapm->debugfs_dapm) | 1343 | dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); |
1344 | |||
1345 | if (!dapm->debugfs_dapm) { | ||
1346 | printk(KERN_WARNING | ||
1347 | "Failed to create DAPM debugfs directory\n"); | ||
1313 | return; | 1348 | return; |
1349 | } | ||
1314 | 1350 | ||
1315 | list_for_each_entry(w, &dapm->card->widgets, list) { | 1351 | d = debugfs_create_file("bias_level", 0444, |
1316 | if (!w->name || w->dapm != dapm) | 1352 | dapm->debugfs_dapm, dapm, |
1317 | continue; | 1353 | &dapm_bias_fops); |
1354 | if (!d) | ||
1355 | dev_warn(dapm->dev, | ||
1356 | "ASoC: Failed to create bias level debugfs file\n"); | ||
1357 | } | ||
1318 | 1358 | ||
1319 | d = debugfs_create_file(w->name, 0444, | 1359 | static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) |
1320 | dapm->debugfs_dapm, w, | 1360 | { |
1321 | &dapm_widget_power_fops); | 1361 | struct snd_soc_dapm_context *dapm = w->dapm; |
1322 | if (!d) | 1362 | struct dentry *d; |
1323 | dev_warn(w->dapm->dev, | 1363 | |
1324 | "ASoC: Failed to create %s debugfs file\n", | 1364 | if (!dapm->debugfs_dapm || !w->name) |
1325 | w->name); | 1365 | return; |
1326 | } | 1366 | |
1367 | d = debugfs_create_file(w->name, 0444, | ||
1368 | dapm->debugfs_dapm, w, | ||
1369 | &dapm_widget_power_fops); | ||
1370 | if (!d) | ||
1371 | dev_warn(w->dapm->dev, | ||
1372 | "ASoC: Failed to create %s debugfs file\n", | ||
1373 | w->name); | ||
1374 | } | ||
1375 | |||
1376 | static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | ||
1377 | { | ||
1378 | debugfs_remove_recursive(dapm->debugfs_dapm); | ||
1327 | } | 1379 | } |
1380 | |||
1328 | #else | 1381 | #else |
1329 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) | 1382 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, |
1383 | struct dentry *parent) | ||
1384 | { | ||
1385 | } | ||
1386 | |||
1387 | static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) | ||
1388 | { | ||
1389 | } | ||
1390 | |||
1391 | static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | ||
1330 | { | 1392 | { |
1331 | } | 1393 | } |
1394 | |||
1332 | #endif | 1395 | #endif |
1333 | 1396 | ||
1334 | /* test and update the power status of a mux widget */ | 1397 | /* test and update the power status of a mux widget */ |
@@ -1496,32 +1559,49 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | |||
1496 | kfree(p->long_name); | 1559 | kfree(p->long_name); |
1497 | kfree(p); | 1560 | kfree(p); |
1498 | } | 1561 | } |
1562 | kfree(w->kcontrols); | ||
1499 | kfree(w->name); | 1563 | kfree(w->name); |
1500 | kfree(w); | 1564 | kfree(w); |
1501 | } | 1565 | } |
1502 | } | 1566 | } |
1503 | 1567 | ||
1504 | static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | 1568 | static struct snd_soc_dapm_widget *dapm_find_widget( |
1505 | const char *pin, int status) | 1569 | struct snd_soc_dapm_context *dapm, const char *pin, |
1570 | bool search_other_contexts) | ||
1506 | { | 1571 | { |
1507 | struct snd_soc_dapm_widget *w; | 1572 | struct snd_soc_dapm_widget *w; |
1573 | struct snd_soc_dapm_widget *fallback = NULL; | ||
1508 | 1574 | ||
1509 | list_for_each_entry(w, &dapm->card->widgets, list) { | 1575 | list_for_each_entry(w, &dapm->card->widgets, list) { |
1510 | if (w->dapm != dapm) | ||
1511 | continue; | ||
1512 | if (!strcmp(w->name, pin)) { | 1576 | if (!strcmp(w->name, pin)) { |
1513 | dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n", | 1577 | if (w->dapm == dapm) |
1514 | pin, status); | 1578 | return w; |
1515 | w->connected = status; | 1579 | else |
1516 | /* Allow disabling of forced pins */ | 1580 | fallback = w; |
1517 | if (status == 0) | ||
1518 | w->force = 0; | ||
1519 | return 0; | ||
1520 | } | 1581 | } |
1521 | } | 1582 | } |
1522 | 1583 | ||
1523 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); | 1584 | if (search_other_contexts) |
1524 | return -EINVAL; | 1585 | return fallback; |
1586 | |||
1587 | return NULL; | ||
1588 | } | ||
1589 | |||
1590 | static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | ||
1591 | const char *pin, int status) | ||
1592 | { | ||
1593 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); | ||
1594 | |||
1595 | if (!w) { | ||
1596 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); | ||
1597 | return -EINVAL; | ||
1598 | } | ||
1599 | |||
1600 | w->connected = status; | ||
1601 | if (status == 0) | ||
1602 | w->force = 0; | ||
1603 | |||
1604 | return 0; | ||
1525 | } | 1605 | } |
1526 | 1606 | ||
1527 | /** | 1607 | /** |
@@ -1627,7 +1707,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
1627 | } | 1707 | } |
1628 | 1708 | ||
1629 | /* connect dynamic paths */ | 1709 | /* connect dynamic paths */ |
1630 | switch(wsink->id) { | 1710 | switch (wsink->id) { |
1631 | case snd_soc_dapm_adc: | 1711 | case snd_soc_dapm_adc: |
1632 | case snd_soc_dapm_dac: | 1712 | case snd_soc_dapm_dac: |
1633 | case snd_soc_dapm_pga: | 1713 | case snd_soc_dapm_pga: |
@@ -1650,7 +1730,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
1650 | case snd_soc_dapm_virt_mux: | 1730 | case snd_soc_dapm_virt_mux: |
1651 | case snd_soc_dapm_value_mux: | 1731 | case snd_soc_dapm_value_mux: |
1652 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, | 1732 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, |
1653 | &wsink->kcontrols[0]); | 1733 | &wsink->kcontrol_news[0]); |
1654 | if (ret != 0) | 1734 | if (ret != 0) |
1655 | goto err; | 1735 | goto err; |
1656 | break; | 1736 | break; |
@@ -1730,6 +1810,14 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
1730 | if (w->new) | 1810 | if (w->new) |
1731 | continue; | 1811 | continue; |
1732 | 1812 | ||
1813 | if (w->num_kcontrols) { | ||
1814 | w->kcontrols = kzalloc(w->num_kcontrols * | ||
1815 | sizeof(struct snd_kcontrol *), | ||
1816 | GFP_KERNEL); | ||
1817 | if (!w->kcontrols) | ||
1818 | return -ENOMEM; | ||
1819 | } | ||
1820 | |||
1733 | switch(w->id) { | 1821 | switch(w->id) { |
1734 | case snd_soc_dapm_switch: | 1822 | case snd_soc_dapm_switch: |
1735 | case snd_soc_dapm_mixer: | 1823 | case snd_soc_dapm_mixer: |
@@ -1785,6 +1873,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
1785 | } | 1873 | } |
1786 | 1874 | ||
1787 | w->new = 1; | 1875 | w->new = 1; |
1876 | |||
1877 | dapm_debugfs_add_widget(w); | ||
1788 | } | 1878 | } |
1789 | 1879 | ||
1790 | dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); | 1880 | dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); |
@@ -1804,7 +1894,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | |||
1804 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | 1894 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
1805 | struct snd_ctl_elem_value *ucontrol) | 1895 | struct snd_ctl_elem_value *ucontrol) |
1806 | { | 1896 | { |
1807 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1897 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1898 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1808 | struct soc_mixer_control *mc = | 1899 | struct soc_mixer_control *mc = |
1809 | (struct soc_mixer_control *)kcontrol->private_value; | 1900 | (struct soc_mixer_control *)kcontrol->private_value; |
1810 | unsigned int reg = mc->reg; | 1901 | unsigned int reg = mc->reg; |
@@ -1843,7 +1934,9 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | |||
1843 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 1934 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
1844 | struct snd_ctl_elem_value *ucontrol) | 1935 | struct snd_ctl_elem_value *ucontrol) |
1845 | { | 1936 | { |
1846 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1937 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1938 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1939 | struct snd_soc_codec *codec = widget->codec; | ||
1847 | struct soc_mixer_control *mc = | 1940 | struct soc_mixer_control *mc = |
1848 | (struct soc_mixer_control *)kcontrol->private_value; | 1941 | (struct soc_mixer_control *)kcontrol->private_value; |
1849 | unsigned int reg = mc->reg; | 1942 | unsigned int reg = mc->reg; |
@@ -1854,6 +1947,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1854 | unsigned int val; | 1947 | unsigned int val; |
1855 | int connect, change; | 1948 | int connect, change; |
1856 | struct snd_soc_dapm_update update; | 1949 | struct snd_soc_dapm_update update; |
1950 | int wi; | ||
1857 | 1951 | ||
1858 | val = (ucontrol->value.integer.value[0] & mask); | 1952 | val = (ucontrol->value.integer.value[0] & mask); |
1859 | 1953 | ||
@@ -1862,31 +1956,36 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1862 | mask = mask << shift; | 1956 | mask = mask << shift; |
1863 | val = val << shift; | 1957 | val = val << shift; |
1864 | 1958 | ||
1865 | mutex_lock(&widget->codec->mutex); | 1959 | if (val) |
1866 | widget->value = val; | 1960 | /* new connection */ |
1961 | connect = invert ? 0 : 1; | ||
1962 | else | ||
1963 | /* old connection must be powered down */ | ||
1964 | connect = invert ? 1 : 0; | ||
1965 | |||
1966 | mutex_lock(&codec->mutex); | ||
1867 | 1967 | ||
1868 | change = snd_soc_test_bits(widget->codec, reg, mask, val); | 1968 | change = snd_soc_test_bits(widget->codec, reg, mask, val); |
1869 | if (change) { | 1969 | if (change) { |
1870 | if (val) | 1970 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
1871 | /* new connection */ | 1971 | widget = wlist->widgets[wi]; |
1872 | connect = invert ? 0:1; | ||
1873 | else | ||
1874 | /* old connection must be powered down */ | ||
1875 | connect = invert ? 1:0; | ||
1876 | 1972 | ||
1877 | update.kcontrol = kcontrol; | 1973 | widget->value = val; |
1878 | update.widget = widget; | ||
1879 | update.reg = reg; | ||
1880 | update.mask = mask; | ||
1881 | update.val = val; | ||
1882 | widget->dapm->update = &update; | ||
1883 | 1974 | ||
1884 | dapm_mixer_update_power(widget, kcontrol, connect); | 1975 | update.kcontrol = kcontrol; |
1976 | update.widget = widget; | ||
1977 | update.reg = reg; | ||
1978 | update.mask = mask; | ||
1979 | update.val = val; | ||
1980 | widget->dapm->update = &update; | ||
1885 | 1981 | ||
1886 | widget->dapm->update = NULL; | 1982 | dapm_mixer_update_power(widget, kcontrol, connect); |
1983 | |||
1984 | widget->dapm->update = NULL; | ||
1985 | } | ||
1887 | } | 1986 | } |
1888 | 1987 | ||
1889 | mutex_unlock(&widget->codec->mutex); | 1988 | mutex_unlock(&codec->mutex); |
1890 | return 0; | 1989 | return 0; |
1891 | } | 1990 | } |
1892 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 1991 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
@@ -1903,7 +2002,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | |||
1903 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | 2002 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, |
1904 | struct snd_ctl_elem_value *ucontrol) | 2003 | struct snd_ctl_elem_value *ucontrol) |
1905 | { | 2004 | { |
1906 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2005 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2006 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1907 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2007 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1908 | unsigned int val, bitmask; | 2008 | unsigned int val, bitmask; |
1909 | 2009 | ||
@@ -1931,11 +2031,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | |||
1931 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 2031 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
1932 | struct snd_ctl_elem_value *ucontrol) | 2032 | struct snd_ctl_elem_value *ucontrol) |
1933 | { | 2033 | { |
1934 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2034 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2035 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2036 | struct snd_soc_codec *codec = widget->codec; | ||
1935 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2037 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1936 | unsigned int val, mux, change; | 2038 | unsigned int val, mux, change; |
1937 | unsigned int mask, bitmask; | 2039 | unsigned int mask, bitmask; |
1938 | struct snd_soc_dapm_update update; | 2040 | struct snd_soc_dapm_update update; |
2041 | int wi; | ||
1939 | 2042 | ||
1940 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 2043 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1941 | ; | 2044 | ; |
@@ -1951,22 +2054,29 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1951 | mask |= (bitmask - 1) << e->shift_r; | 2054 | mask |= (bitmask - 1) << e->shift_r; |
1952 | } | 2055 | } |
1953 | 2056 | ||
1954 | mutex_lock(&widget->codec->mutex); | 2057 | mutex_lock(&codec->mutex); |
1955 | widget->value = val; | 2058 | |
1956 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2059 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
2060 | if (change) { | ||
2061 | for (wi = 0; wi < wlist->num_widgets; wi++) { | ||
2062 | widget = wlist->widgets[wi]; | ||
1957 | 2063 | ||
1958 | update.kcontrol = kcontrol; | 2064 | widget->value = val; |
1959 | update.widget = widget; | ||
1960 | update.reg = e->reg; | ||
1961 | update.mask = mask; | ||
1962 | update.val = val; | ||
1963 | widget->dapm->update = &update; | ||
1964 | 2065 | ||
1965 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | 2066 | update.kcontrol = kcontrol; |
2067 | update.widget = widget; | ||
2068 | update.reg = e->reg; | ||
2069 | update.mask = mask; | ||
2070 | update.val = val; | ||
2071 | widget->dapm->update = &update; | ||
1966 | 2072 | ||
1967 | widget->dapm->update = NULL; | 2073 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1968 | 2074 | ||
1969 | mutex_unlock(&widget->codec->mutex); | 2075 | widget->dapm->update = NULL; |
2076 | } | ||
2077 | } | ||
2078 | |||
2079 | mutex_unlock(&codec->mutex); | ||
1970 | return change; | 2080 | return change; |
1971 | } | 2081 | } |
1972 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 2082 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
@@ -1981,7 +2091,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | |||
1981 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, | 2091 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, |
1982 | struct snd_ctl_elem_value *ucontrol) | 2092 | struct snd_ctl_elem_value *ucontrol) |
1983 | { | 2093 | { |
1984 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2094 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2095 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1985 | 2096 | ||
1986 | ucontrol->value.enumerated.item[0] = widget->value; | 2097 | ucontrol->value.enumerated.item[0] = widget->value; |
1987 | 2098 | ||
@@ -1999,22 +2110,33 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); | |||
1999 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | 2110 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, |
2000 | struct snd_ctl_elem_value *ucontrol) | 2111 | struct snd_ctl_elem_value *ucontrol) |
2001 | { | 2112 | { |
2002 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2113 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2114 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2115 | struct snd_soc_codec *codec = widget->codec; | ||
2003 | struct soc_enum *e = | 2116 | struct soc_enum *e = |
2004 | (struct soc_enum *)kcontrol->private_value; | 2117 | (struct soc_enum *)kcontrol->private_value; |
2005 | int change; | 2118 | int change; |
2006 | int ret = 0; | 2119 | int ret = 0; |
2120 | int wi; | ||
2007 | 2121 | ||
2008 | if (ucontrol->value.enumerated.item[0] >= e->max) | 2122 | if (ucontrol->value.enumerated.item[0] >= e->max) |
2009 | return -EINVAL; | 2123 | return -EINVAL; |
2010 | 2124 | ||
2011 | mutex_lock(&widget->codec->mutex); | 2125 | mutex_lock(&codec->mutex); |
2012 | 2126 | ||
2013 | change = widget->value != ucontrol->value.enumerated.item[0]; | 2127 | change = widget->value != ucontrol->value.enumerated.item[0]; |
2014 | widget->value = ucontrol->value.enumerated.item[0]; | 2128 | if (change) { |
2015 | dapm_mux_update_power(widget, kcontrol, change, widget->value, e); | 2129 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
2130 | widget = wlist->widgets[wi]; | ||
2016 | 2131 | ||
2017 | mutex_unlock(&widget->codec->mutex); | 2132 | widget->value = ucontrol->value.enumerated.item[0]; |
2133 | |||
2134 | dapm_mux_update_power(widget, kcontrol, change, | ||
2135 | widget->value, e); | ||
2136 | } | ||
2137 | } | ||
2138 | |||
2139 | mutex_unlock(&codec->mutex); | ||
2018 | return ret; | 2140 | return ret; |
2019 | } | 2141 | } |
2020 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | 2142 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); |
@@ -2035,7 +2157,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | |||
2035 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, | 2157 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, |
2036 | struct snd_ctl_elem_value *ucontrol) | 2158 | struct snd_ctl_elem_value *ucontrol) |
2037 | { | 2159 | { |
2038 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2160 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2161 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2039 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2162 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2040 | unsigned int reg_val, val, mux; | 2163 | unsigned int reg_val, val, mux; |
2041 | 2164 | ||
@@ -2075,11 +2198,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); | |||
2075 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | 2198 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, |
2076 | struct snd_ctl_elem_value *ucontrol) | 2199 | struct snd_ctl_elem_value *ucontrol) |
2077 | { | 2200 | { |
2078 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2201 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2202 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2203 | struct snd_soc_codec *codec = widget->codec; | ||
2079 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2204 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2080 | unsigned int val, mux, change; | 2205 | unsigned int val, mux, change; |
2081 | unsigned int mask; | 2206 | unsigned int mask; |
2082 | struct snd_soc_dapm_update update; | 2207 | struct snd_soc_dapm_update update; |
2208 | int wi; | ||
2083 | 2209 | ||
2084 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2210 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2085 | return -EINVAL; | 2211 | return -EINVAL; |
@@ -2093,22 +2219,29 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
2093 | mask |= e->mask << e->shift_r; | 2219 | mask |= e->mask << e->shift_r; |
2094 | } | 2220 | } |
2095 | 2221 | ||
2096 | mutex_lock(&widget->codec->mutex); | 2222 | mutex_lock(&codec->mutex); |
2097 | widget->value = val; | 2223 | |
2098 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2224 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
2225 | if (change) { | ||
2226 | for (wi = 0; wi < wlist->num_widgets; wi++) { | ||
2227 | widget = wlist->widgets[wi]; | ||
2099 | 2228 | ||
2100 | update.kcontrol = kcontrol; | 2229 | widget->value = val; |
2101 | update.widget = widget; | ||
2102 | update.reg = e->reg; | ||
2103 | update.mask = mask; | ||
2104 | update.val = val; | ||
2105 | widget->dapm->update = &update; | ||
2106 | 2230 | ||
2107 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | 2231 | update.kcontrol = kcontrol; |
2232 | update.widget = widget; | ||
2233 | update.reg = e->reg; | ||
2234 | update.mask = mask; | ||
2235 | update.val = val; | ||
2236 | widget->dapm->update = &update; | ||
2108 | 2237 | ||
2109 | widget->dapm->update = NULL; | 2238 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
2239 | |||
2240 | widget->dapm->update = NULL; | ||
2241 | } | ||
2242 | } | ||
2110 | 2243 | ||
2111 | mutex_unlock(&widget->codec->mutex); | 2244 | mutex_unlock(&codec->mutex); |
2112 | return change; | 2245 | return change; |
2113 | } | 2246 | } |
2114 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 2247 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
@@ -2346,22 +2479,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | |||
2346 | int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, | 2479 | int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, |
2347 | const char *pin) | 2480 | const char *pin) |
2348 | { | 2481 | { |
2349 | struct snd_soc_dapm_widget *w; | 2482 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); |
2350 | 2483 | ||
2351 | list_for_each_entry(w, &dapm->card->widgets, list) { | 2484 | if (!w) { |
2352 | if (w->dapm != dapm) | 2485 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
2353 | continue; | 2486 | return -EINVAL; |
2354 | if (!strcmp(w->name, pin)) { | ||
2355 | dev_dbg(w->dapm->dev, | ||
2356 | "dapm: force enable pin %s\n", pin); | ||
2357 | w->connected = 1; | ||
2358 | w->force = 1; | ||
2359 | return 0; | ||
2360 | } | ||
2361 | } | 2487 | } |
2362 | 2488 | ||
2363 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); | 2489 | dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin); |
2364 | return -EINVAL; | 2490 | w->connected = 1; |
2491 | w->force = 1; | ||
2492 | |||
2493 | return 0; | ||
2365 | } | 2494 | } |
2366 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); | 2495 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); |
2367 | 2496 | ||
@@ -2413,14 +2542,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | |||
2413 | int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, | 2542 | int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, |
2414 | const char *pin) | 2543 | const char *pin) |
2415 | { | 2544 | { |
2416 | struct snd_soc_dapm_widget *w; | 2545 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); |
2417 | 2546 | ||
2418 | list_for_each_entry(w, &dapm->card->widgets, list) { | 2547 | if (w) |
2419 | if (w->dapm != dapm) | 2548 | return w->connected; |
2420 | continue; | ||
2421 | if (!strcmp(w->name, pin)) | ||
2422 | return w->connected; | ||
2423 | } | ||
2424 | 2549 | ||
2425 | return 0; | 2550 | return 0; |
2426 | } | 2551 | } |
@@ -2440,19 +2565,16 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | |||
2440 | int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, | 2565 | int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, |
2441 | const char *pin) | 2566 | const char *pin) |
2442 | { | 2567 | { |
2443 | struct snd_soc_dapm_widget *w; | 2568 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false); |
2444 | 2569 | ||
2445 | list_for_each_entry(w, &dapm->card->widgets, list) { | 2570 | if (!w) { |
2446 | if (w->dapm != dapm) | 2571 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
2447 | continue; | 2572 | return -EINVAL; |
2448 | if (!strcmp(w->name, pin)) { | ||
2449 | w->ignore_suspend = 1; | ||
2450 | return 0; | ||
2451 | } | ||
2452 | } | 2573 | } |
2453 | 2574 | ||
2454 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); | 2575 | w->ignore_suspend = 1; |
2455 | return -EINVAL; | 2576 | |
2577 | return 0; | ||
2456 | } | 2578 | } |
2457 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 2579 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
2458 | 2580 | ||
@@ -2465,6 +2587,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | |||
2465 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) | 2587 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) |
2466 | { | 2588 | { |
2467 | snd_soc_dapm_sys_remove(dapm->dev); | 2589 | snd_soc_dapm_sys_remove(dapm->dev); |
2590 | dapm_debugfs_cleanup(dapm); | ||
2468 | dapm_free_widgets(dapm); | 2591 | dapm_free_widgets(dapm); |
2469 | list_del(&dapm->list); | 2592 | list_del(&dapm->list); |
2470 | } | 2593 | } |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fc017c0a7b5d..7c17b98d5846 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -325,7 +325,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
325 | gpio_handler, | 325 | gpio_handler, |
326 | IRQF_TRIGGER_RISING | | 326 | IRQF_TRIGGER_RISING | |
327 | IRQF_TRIGGER_FALLING, | 327 | IRQF_TRIGGER_FALLING, |
328 | jack->codec->dev->driver->name, | 328 | gpios[i].name, |
329 | &gpios[i]); | 329 | &gpios[i]); |
330 | if (ret) | 330 | if (ret) |
331 | goto err; | 331 | goto err; |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 3f45e6a439bf..ec921ec99c26 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * option) any later version. | 13 | * option) any later version. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/platform_device.h> | ||
16 | #include <sound/core.h> | 17 | #include <sound/core.h> |
17 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
18 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
@@ -55,3 +56,55 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) | |||
55 | return ret; | 56 | return ret; |
56 | } | 57 | } |
57 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); | 58 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); |
59 | |||
60 | static struct snd_soc_platform_driver dummy_platform; | ||
61 | |||
62 | static __devinit int snd_soc_dummy_probe(struct platform_device *pdev) | ||
63 | { | ||
64 | return snd_soc_register_platform(&pdev->dev, &dummy_platform); | ||
65 | } | ||
66 | |||
67 | static __devexit int snd_soc_dummy_remove(struct platform_device *pdev) | ||
68 | { | ||
69 | snd_soc_unregister_platform(&pdev->dev); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct platform_driver soc_dummy_driver = { | ||
75 | .driver = { | ||
76 | .name = "snd-soc-dummy", | ||
77 | .owner = THIS_MODULE, | ||
78 | }, | ||
79 | .probe = snd_soc_dummy_probe, | ||
80 | .remove = __devexit_p(snd_soc_dummy_remove), | ||
81 | }; | ||
82 | |||
83 | static struct platform_device *soc_dummy_dev; | ||
84 | |||
85 | int __init snd_soc_util_init(void) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | soc_dummy_dev = platform_device_alloc("snd-soc-dummy", -1); | ||
90 | if (!soc_dummy_dev) | ||
91 | return -ENOMEM; | ||
92 | |||
93 | ret = platform_device_add(soc_dummy_dev); | ||
94 | if (ret != 0) { | ||
95 | platform_device_put(soc_dummy_dev); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | ret = platform_driver_register(&soc_dummy_driver); | ||
100 | if (ret != 0) | ||
101 | platform_device_unregister(soc_dummy_dev); | ||
102 | |||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | void __exit snd_soc_util_exit(void) | ||
107 | { | ||
108 | platform_device_unregister(soc_dummy_dev); | ||
109 | platform_driver_unregister(&soc_dummy_driver); | ||
110 | } | ||
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 66b504f06c23..035d39a4beb4 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -1,26 +1,40 @@ | |||
1 | config SND_TEGRA_SOC | 1 | config SND_SOC_TEGRA |
2 | tristate "SoC Audio for the Tegra System-on-Chip" | 2 | tristate "SoC Audio for the Tegra System-on-Chip" |
3 | depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA | 3 | depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA |
4 | default m | ||
5 | help | 4 | help |
6 | Say Y or M here if you want support for SoC audio on Tegra. | 5 | Say Y or M here if you want support for SoC audio on Tegra. |
7 | 6 | ||
8 | config SND_TEGRA_SOC_I2S | 7 | config SND_SOC_TEGRA_I2S |
9 | tristate | 8 | tristate |
10 | depends on SND_TEGRA_SOC | 9 | depends on SND_SOC_TEGRA |
11 | default m | ||
12 | help | 10 | help |
13 | Say Y or M if you want to add support for codecs attached to the | 11 | Say Y or M if you want to add support for codecs attached to the |
14 | Tegra I2S interface. You will also need to select the individual | 12 | Tegra I2S interface. You will also need to select the individual |
15 | machine drivers to support below. | 13 | machine drivers to support below. |
16 | 14 | ||
17 | config SND_TEGRA_SOC_HARMONY | 15 | config MACH_HAS_SND_SOC_TEGRA_WM8903 |
18 | tristate "SoC Audio support for Tegra Harmony reference board" | 16 | bool |
19 | depends on SND_TEGRA_SOC && MACH_HARMONY && I2C | 17 | help |
20 | default m | 18 | Machines that use the SND_SOC_TEGRA_WM8903 driver should select |
21 | select SND_TEGRA_SOC_I2S | 19 | this config option, in order to allow the user to enable |
20 | SND_SOC_TEGRA_WM8903. | ||
21 | |||
22 | config SND_SOC_TEGRA_WM8903 | ||
23 | tristate "SoC Audio support for Tegra boards using a WM8903 codec" | ||
24 | depends on SND_SOC_TEGRA && I2C | ||
25 | depends on MACH_HAS_SND_SOC_TEGRA_WM8903 | ||
26 | select SND_SOC_TEGRA_I2S | ||
22 | select SND_SOC_WM8903 | 27 | select SND_SOC_WM8903 |
23 | help | 28 | help |
24 | Say Y or M here if you want to add support for SoC audio on the | 29 | Say Y or M here if you want to add support for SoC audio on Tegra |
25 | Tegra Harmony reference board. | 30 | boards using the WM8093 codec. Currently, the supported boards are |
31 | Harmony, Ventana, Seaboard, Kaen, and Aebl. | ||
26 | 32 | ||
33 | config SND_SOC_TEGRA_TRIMSLICE | ||
34 | tristate "SoC Audio support for TrimSlice board" | ||
35 | depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C | ||
36 | select SND_SOC_TEGRA_I2S | ||
37 | select SND_SOC_TLV320AIC23 | ||
38 | help | ||
39 | Say Y or M here if you want to add support for SoC audio on the | ||
40 | TrimSlice platform. | ||
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index fd183d3ab4f1..fa6574d92a31 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile | |||
@@ -4,12 +4,14 @@ snd-soc-tegra-pcm-objs := tegra_pcm.o | |||
4 | snd-soc-tegra-i2s-objs := tegra_i2s.o | 4 | snd-soc-tegra-i2s-objs := tegra_i2s.o |
5 | snd-soc-tegra-utils-objs += tegra_asoc_utils.o | 5 | snd-soc-tegra-utils-objs += tegra_asoc_utils.o |
6 | 6 | ||
7 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-utils.o | 7 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o |
8 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-das.o | 8 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o |
9 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-pcm.o | 9 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o |
10 | obj-$(CONFIG_SND_TEGRA_SOC_I2S) += snd-soc-tegra-i2s.o | 10 | obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o |
11 | 11 | ||
12 | # Tegra machine Support | 12 | # Tegra machine Support |
13 | snd-soc-tegra-harmony-objs := harmony.o | 13 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o |
14 | snd-soc-tegra-trimslice-objs := trimslice.o | ||
14 | 15 | ||
15 | obj-$(CONFIG_SND_TEGRA_SOC_HARMONY) += snd-soc-tegra-harmony.o | 16 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o |
17 | obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o | ||
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c deleted file mode 100644 index 556a57133925..000000000000 --- a/sound/soc/tegra/harmony.c +++ /dev/null | |||
@@ -1,394 +0,0 @@ | |||
1 | /* | ||
2 | * harmony.c - Harmony machine ASoC driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010-2011 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
10 | * | ||
11 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
12 | * Author: Graeme Gregory | ||
13 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/gpio.h> | ||
37 | |||
38 | #include <mach/harmony_audio.h> | ||
39 | |||
40 | #include <sound/core.h> | ||
41 | #include <sound/jack.h> | ||
42 | #include <sound/pcm.h> | ||
43 | #include <sound/pcm_params.h> | ||
44 | #include <sound/soc.h> | ||
45 | |||
46 | #include "../codecs/wm8903.h" | ||
47 | |||
48 | #include "tegra_das.h" | ||
49 | #include "tegra_i2s.h" | ||
50 | #include "tegra_pcm.h" | ||
51 | #include "tegra_asoc_utils.h" | ||
52 | |||
53 | #define DRV_NAME "tegra-snd-harmony" | ||
54 | |||
55 | #define GPIO_SPKR_EN BIT(0) | ||
56 | #define GPIO_INT_MIC_EN BIT(1) | ||
57 | #define GPIO_EXT_MIC_EN BIT(2) | ||
58 | |||
59 | struct tegra_harmony { | ||
60 | struct tegra_asoc_utils_data util_data; | ||
61 | struct harmony_audio_platform_data *pdata; | ||
62 | int gpio_requested; | ||
63 | }; | ||
64 | |||
65 | static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | ||
66 | struct snd_pcm_hw_params *params) | ||
67 | { | ||
68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
69 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
70 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
71 | struct snd_soc_codec *codec = rtd->codec; | ||
72 | struct snd_soc_card *card = codec->card; | ||
73 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
74 | int srate, mclk, mclk_change; | ||
75 | int err; | ||
76 | |||
77 | srate = params_rate(params); | ||
78 | switch (srate) { | ||
79 | case 64000: | ||
80 | case 88200: | ||
81 | case 96000: | ||
82 | mclk = 128 * srate; | ||
83 | break; | ||
84 | default: | ||
85 | mclk = 256 * srate; | ||
86 | break; | ||
87 | } | ||
88 | /* FIXME: Codec only requires >= 3MHz if OSR==0 */ | ||
89 | while (mclk < 6000000) | ||
90 | mclk *= 2; | ||
91 | |||
92 | err = tegra_asoc_utils_set_rate(&harmony->util_data, srate, mclk, | ||
93 | &mclk_change); | ||
94 | if (err < 0) { | ||
95 | dev_err(card->dev, "Can't configure clocks\n"); | ||
96 | return err; | ||
97 | } | ||
98 | |||
99 | err = snd_soc_dai_set_fmt(codec_dai, | ||
100 | SND_SOC_DAIFMT_I2S | | ||
101 | SND_SOC_DAIFMT_NB_NF | | ||
102 | SND_SOC_DAIFMT_CBS_CFS); | ||
103 | if (err < 0) { | ||
104 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
105 | return err; | ||
106 | } | ||
107 | |||
108 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
109 | SND_SOC_DAIFMT_I2S | | ||
110 | SND_SOC_DAIFMT_NB_NF | | ||
111 | SND_SOC_DAIFMT_CBS_CFS); | ||
112 | if (err < 0) { | ||
113 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
114 | return err; | ||
115 | } | ||
116 | |||
117 | if (mclk_change) { | ||
118 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
119 | SND_SOC_CLOCK_IN); | ||
120 | if (err < 0) { | ||
121 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
122 | return err; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static struct snd_soc_ops harmony_asoc_ops = { | ||
130 | .hw_params = harmony_asoc_hw_params, | ||
131 | }; | ||
132 | |||
133 | static struct snd_soc_jack harmony_hp_jack; | ||
134 | |||
135 | static struct snd_soc_jack_pin harmony_hp_jack_pins[] = { | ||
136 | { | ||
137 | .pin = "Headphone Jack", | ||
138 | .mask = SND_JACK_HEADPHONE, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct snd_soc_jack_gpio harmony_hp_jack_gpios[] = { | ||
143 | { | ||
144 | .name = "headphone detect", | ||
145 | .report = SND_JACK_HEADPHONE, | ||
146 | .debounce_time = 150, | ||
147 | .invert = 1, | ||
148 | } | ||
149 | }; | ||
150 | |||
151 | static struct snd_soc_jack harmony_mic_jack; | ||
152 | |||
153 | static struct snd_soc_jack_pin harmony_mic_jack_pins[] = { | ||
154 | { | ||
155 | .pin = "Mic Jack", | ||
156 | .mask = SND_JACK_MICROPHONE, | ||
157 | }, | ||
158 | }; | ||
159 | |||
160 | static int harmony_event_int_spk(struct snd_soc_dapm_widget *w, | ||
161 | struct snd_kcontrol *k, int event) | ||
162 | { | ||
163 | struct snd_soc_codec *codec = w->codec; | ||
164 | struct snd_soc_card *card = codec->card; | ||
165 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
166 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
167 | |||
168 | gpio_set_value_cansleep(pdata->gpio_spkr_en, | ||
169 | SND_SOC_DAPM_EVENT_ON(event)); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { | ||
175 | SND_SOC_DAPM_SPK("Int Spk", harmony_event_int_spk), | ||
176 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
177 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
178 | }; | ||
179 | |||
180 | static const struct snd_soc_dapm_route harmony_audio_map[] = { | ||
181 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
182 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
183 | {"Int Spk", NULL, "ROP"}, | ||
184 | {"Int Spk", NULL, "RON"}, | ||
185 | {"Int Spk", NULL, "LOP"}, | ||
186 | {"Int Spk", NULL, "LON"}, | ||
187 | {"Mic Bias", NULL, "Mic Jack"}, | ||
188 | {"IN1L", NULL, "Mic Bias"}, | ||
189 | }; | ||
190 | |||
191 | static const struct snd_kcontrol_new harmony_controls[] = { | ||
192 | SOC_DAPM_PIN_SWITCH("Int Spk"), | ||
193 | }; | ||
194 | |||
195 | static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
196 | { | ||
197 | struct snd_soc_codec *codec = rtd->codec; | ||
198 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
199 | struct snd_soc_card *card = codec->card; | ||
200 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
201 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
202 | int ret; | ||
203 | |||
204 | ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); | ||
205 | if (ret) { | ||
206 | dev_err(card->dev, "cannot get spkr_en gpio\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | harmony->gpio_requested |= GPIO_SPKR_EN; | ||
210 | |||
211 | gpio_direction_output(pdata->gpio_spkr_en, 0); | ||
212 | |||
213 | ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); | ||
214 | if (ret) { | ||
215 | dev_err(card->dev, "cannot get int_mic_en gpio\n"); | ||
216 | return ret; | ||
217 | } | ||
218 | harmony->gpio_requested |= GPIO_INT_MIC_EN; | ||
219 | |||
220 | /* Disable int mic; enable signal is active-high */ | ||
221 | gpio_direction_output(pdata->gpio_int_mic_en, 0); | ||
222 | |||
223 | ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); | ||
224 | if (ret) { | ||
225 | dev_err(card->dev, "cannot get ext_mic_en gpio\n"); | ||
226 | return ret; | ||
227 | } | ||
228 | harmony->gpio_requested |= GPIO_EXT_MIC_EN; | ||
229 | |||
230 | /* Enable ext mic; enable signal is active-low */ | ||
231 | gpio_direction_output(pdata->gpio_ext_mic_en, 0); | ||
232 | |||
233 | ret = snd_soc_add_controls(codec, harmony_controls, | ||
234 | ARRAY_SIZE(harmony_controls)); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | |||
238 | snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets, | ||
239 | ARRAY_SIZE(harmony_dapm_widgets)); | ||
240 | |||
241 | snd_soc_dapm_add_routes(dapm, harmony_audio_map, | ||
242 | ARRAY_SIZE(harmony_audio_map)); | ||
243 | |||
244 | harmony_hp_jack_gpios[0].gpio = pdata->gpio_hp_det; | ||
245 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, | ||
246 | &harmony_hp_jack); | ||
247 | snd_soc_jack_add_pins(&harmony_hp_jack, | ||
248 | ARRAY_SIZE(harmony_hp_jack_pins), | ||
249 | harmony_hp_jack_pins); | ||
250 | snd_soc_jack_add_gpios(&harmony_hp_jack, | ||
251 | ARRAY_SIZE(harmony_hp_jack_gpios), | ||
252 | harmony_hp_jack_gpios); | ||
253 | |||
254 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
255 | &harmony_mic_jack); | ||
256 | snd_soc_jack_add_pins(&harmony_mic_jack, | ||
257 | ARRAY_SIZE(harmony_mic_jack_pins), | ||
258 | harmony_mic_jack_pins); | ||
259 | wm8903_mic_detect(codec, &harmony_mic_jack, SND_JACK_MICROPHONE, 0); | ||
260 | |||
261 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); | ||
262 | |||
263 | snd_soc_dapm_nc_pin(dapm, "IN3L"); | ||
264 | snd_soc_dapm_nc_pin(dapm, "IN3R"); | ||
265 | snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); | ||
266 | snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); | ||
267 | |||
268 | snd_soc_dapm_sync(dapm); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static struct snd_soc_dai_link harmony_wm8903_dai = { | ||
274 | .name = "WM8903", | ||
275 | .stream_name = "WM8903 PCM", | ||
276 | .codec_name = "wm8903.0-001a", | ||
277 | .platform_name = "tegra-pcm-audio", | ||
278 | .cpu_dai_name = "tegra-i2s.0", | ||
279 | .codec_dai_name = "wm8903-hifi", | ||
280 | .init = harmony_asoc_init, | ||
281 | .ops = &harmony_asoc_ops, | ||
282 | }; | ||
283 | |||
284 | static struct snd_soc_card snd_soc_harmony = { | ||
285 | .name = "tegra-harmony", | ||
286 | .dai_link = &harmony_wm8903_dai, | ||
287 | .num_links = 1, | ||
288 | }; | ||
289 | |||
290 | static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev) | ||
291 | { | ||
292 | struct snd_soc_card *card = &snd_soc_harmony; | ||
293 | struct tegra_harmony *harmony; | ||
294 | struct harmony_audio_platform_data *pdata; | ||
295 | int ret; | ||
296 | |||
297 | if (!machine_is_harmony()) { | ||
298 | dev_err(&pdev->dev, "Not running on Tegra Harmony!\n"); | ||
299 | return -ENODEV; | ||
300 | } | ||
301 | |||
302 | pdata = pdev->dev.platform_data; | ||
303 | if (!pdata) { | ||
304 | dev_err(&pdev->dev, "no platform data supplied\n"); | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | |||
308 | harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL); | ||
309 | if (!harmony) { | ||
310 | dev_err(&pdev->dev, "Can't allocate tegra_harmony\n"); | ||
311 | return -ENOMEM; | ||
312 | } | ||
313 | |||
314 | harmony->pdata = pdata; | ||
315 | |||
316 | ret = tegra_asoc_utils_init(&harmony->util_data, &pdev->dev); | ||
317 | if (ret) | ||
318 | goto err_free_harmony; | ||
319 | |||
320 | card->dev = &pdev->dev; | ||
321 | platform_set_drvdata(pdev, card); | ||
322 | snd_soc_card_set_drvdata(card, harmony); | ||
323 | |||
324 | ret = snd_soc_register_card(card); | ||
325 | if (ret) { | ||
326 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
327 | ret); | ||
328 | goto err_clear_drvdata; | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | |||
333 | err_clear_drvdata: | ||
334 | snd_soc_card_set_drvdata(card, NULL); | ||
335 | platform_set_drvdata(pdev, NULL); | ||
336 | card->dev = NULL; | ||
337 | tegra_asoc_utils_fini(&harmony->util_data); | ||
338 | err_free_harmony: | ||
339 | kfree(harmony); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev) | ||
344 | { | ||
345 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
346 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
347 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
348 | |||
349 | snd_soc_unregister_card(card); | ||
350 | |||
351 | snd_soc_card_set_drvdata(card, NULL); | ||
352 | platform_set_drvdata(pdev, NULL); | ||
353 | card->dev = NULL; | ||
354 | |||
355 | tegra_asoc_utils_fini(&harmony->util_data); | ||
356 | |||
357 | if (harmony->gpio_requested & GPIO_EXT_MIC_EN) | ||
358 | gpio_free(pdata->gpio_ext_mic_en); | ||
359 | if (harmony->gpio_requested & GPIO_INT_MIC_EN) | ||
360 | gpio_free(pdata->gpio_int_mic_en); | ||
361 | if (harmony->gpio_requested & GPIO_SPKR_EN) | ||
362 | gpio_free(pdata->gpio_spkr_en); | ||
363 | |||
364 | kfree(harmony); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static struct platform_driver tegra_snd_harmony_driver = { | ||
370 | .driver = { | ||
371 | .name = DRV_NAME, | ||
372 | .owner = THIS_MODULE, | ||
373 | .pm = &snd_soc_pm_ops, | ||
374 | }, | ||
375 | .probe = tegra_snd_harmony_probe, | ||
376 | .remove = __devexit_p(tegra_snd_harmony_remove), | ||
377 | }; | ||
378 | |||
379 | static int __init snd_tegra_harmony_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&tegra_snd_harmony_driver); | ||
382 | } | ||
383 | module_init(snd_tegra_harmony_init); | ||
384 | |||
385 | static void __exit snd_tegra_harmony_exit(void) | ||
386 | { | ||
387 | platform_driver_unregister(&tegra_snd_harmony_driver); | ||
388 | } | ||
389 | module_exit(snd_tegra_harmony_exit); | ||
390 | |||
391 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
392 | MODULE_DESCRIPTION("Harmony machine ASoC driver"); | ||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 52f0a3f9ce40..dfa85cbb05c8 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c | |||
@@ -28,9 +28,10 @@ | |||
28 | #include "tegra_asoc_utils.h" | 28 | #include "tegra_asoc_utils.h" |
29 | 29 | ||
30 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | 30 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, |
31 | int mclk, int *mclk_change) | 31 | int mclk) |
32 | { | 32 | { |
33 | int new_baseclock; | 33 | int new_baseclock; |
34 | bool clk_change; | ||
34 | int err; | 35 | int err; |
35 | 36 | ||
36 | switch (srate) { | 37 | switch (srate) { |
@@ -52,10 +53,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | |||
52 | return -EINVAL; | 53 | return -EINVAL; |
53 | } | 54 | } |
54 | 55 | ||
55 | *mclk_change = ((new_baseclock != data->set_baseclock) || | 56 | clk_change = ((new_baseclock != data->set_baseclock) || |
56 | (mclk != data->set_mclk)); | 57 | (mclk != data->set_mclk)); |
57 | if (!*mclk_change) | 58 | if (!clk_change) |
58 | return 0; | 59 | return 0; |
59 | 60 | ||
60 | data->set_baseclock = 0; | 61 | data->set_baseclock = 0; |
61 | data->set_mclk = 0; | 62 | data->set_mclk = 0; |
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h index bbba7afdfc2c..4818195da25c 100644 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ b/sound/soc/tegra/tegra_asoc_utils.h | |||
@@ -36,7 +36,7 @@ struct tegra_asoc_utils_data { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | 38 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, |
39 | int mclk, int *mclk_change); | 39 | int mclk); |
40 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | 40 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, |
41 | struct device *dev); | 41 | struct device *dev); |
42 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); | 42 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); |
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 4f5e2c90b020..6b817e20548c 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c | |||
@@ -114,7 +114,7 @@ static void tegra_i2s_debug_remove(struct tegra_i2s *i2s) | |||
114 | debugfs_remove(i2s->debug); | 114 | debugfs_remove(i2s->debug); |
115 | } | 115 | } |
116 | #else | 116 | #else |
117 | static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s) | 117 | static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id) |
118 | { | 118 | { |
119 | } | 119 | } |
120 | 120 | ||
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c new file mode 100644 index 000000000000..0d6738a8b29a --- /dev/null +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -0,0 +1,475 @@ | |||
1 | /* | ||
2 | * tegra_wm8903.c - Tegra machine ASoC driver for boards using WM8903 codec. | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010-2011 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
10 | * | ||
11 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
12 | * Author: Graeme Gregory | ||
13 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/gpio.h> | ||
37 | |||
38 | #include <mach/tegra_wm8903_pdata.h> | ||
39 | |||
40 | #include <sound/core.h> | ||
41 | #include <sound/jack.h> | ||
42 | #include <sound/pcm.h> | ||
43 | #include <sound/pcm_params.h> | ||
44 | #include <sound/soc.h> | ||
45 | |||
46 | #include "../codecs/wm8903.h" | ||
47 | |||
48 | #include "tegra_das.h" | ||
49 | #include "tegra_i2s.h" | ||
50 | #include "tegra_pcm.h" | ||
51 | #include "tegra_asoc_utils.h" | ||
52 | |||
53 | #define DRV_NAME "tegra-snd-wm8903" | ||
54 | |||
55 | #define GPIO_SPKR_EN BIT(0) | ||
56 | #define GPIO_HP_MUTE BIT(1) | ||
57 | #define GPIO_INT_MIC_EN BIT(2) | ||
58 | #define GPIO_EXT_MIC_EN BIT(3) | ||
59 | |||
60 | struct tegra_wm8903 { | ||
61 | struct tegra_asoc_utils_data util_data; | ||
62 | struct tegra_wm8903_platform_data *pdata; | ||
63 | int gpio_requested; | ||
64 | }; | ||
65 | |||
66 | static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | ||
67 | struct snd_pcm_hw_params *params) | ||
68 | { | ||
69 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
70 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
71 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
72 | struct snd_soc_codec *codec = rtd->codec; | ||
73 | struct snd_soc_card *card = codec->card; | ||
74 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | ||
75 | int srate, mclk; | ||
76 | int err; | ||
77 | |||
78 | srate = params_rate(params); | ||
79 | switch (srate) { | ||
80 | case 64000: | ||
81 | case 88200: | ||
82 | case 96000: | ||
83 | mclk = 128 * srate; | ||
84 | break; | ||
85 | default: | ||
86 | mclk = 256 * srate; | ||
87 | break; | ||
88 | } | ||
89 | /* FIXME: Codec only requires >= 3MHz if OSR==0 */ | ||
90 | while (mclk < 6000000) | ||
91 | mclk *= 2; | ||
92 | |||
93 | err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); | ||
94 | if (err < 0) { | ||
95 | dev_err(card->dev, "Can't configure clocks\n"); | ||
96 | return err; | ||
97 | } | ||
98 | |||
99 | err = snd_soc_dai_set_fmt(codec_dai, | ||
100 | SND_SOC_DAIFMT_I2S | | ||
101 | SND_SOC_DAIFMT_NB_NF | | ||
102 | SND_SOC_DAIFMT_CBS_CFS); | ||
103 | if (err < 0) { | ||
104 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
105 | return err; | ||
106 | } | ||
107 | |||
108 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
109 | SND_SOC_DAIFMT_I2S | | ||
110 | SND_SOC_DAIFMT_NB_NF | | ||
111 | SND_SOC_DAIFMT_CBS_CFS); | ||
112 | if (err < 0) { | ||
113 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
114 | return err; | ||
115 | } | ||
116 | |||
117 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
118 | SND_SOC_CLOCK_IN); | ||
119 | if (err < 0) { | ||
120 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
121 | return err; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static struct snd_soc_ops tegra_wm8903_ops = { | ||
128 | .hw_params = tegra_wm8903_hw_params, | ||
129 | }; | ||
130 | |||
131 | static struct snd_soc_jack tegra_wm8903_hp_jack; | ||
132 | |||
133 | static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = { | ||
134 | { | ||
135 | .pin = "Headphone Jack", | ||
136 | .mask = SND_JACK_HEADPHONE, | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = { | ||
141 | .name = "headphone detect", | ||
142 | .report = SND_JACK_HEADPHONE, | ||
143 | .debounce_time = 150, | ||
144 | .invert = 1, | ||
145 | }; | ||
146 | |||
147 | static struct snd_soc_jack tegra_wm8903_mic_jack; | ||
148 | |||
149 | static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = { | ||
150 | { | ||
151 | .pin = "Mic Jack", | ||
152 | .mask = SND_JACK_MICROPHONE, | ||
153 | }, | ||
154 | }; | ||
155 | |||
156 | static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, | ||
157 | struct snd_kcontrol *k, int event) | ||
158 | { | ||
159 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
160 | struct snd_soc_card *card = dapm->card; | ||
161 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | ||
162 | struct tegra_wm8903_platform_data *pdata = machine->pdata; | ||
163 | |||
164 | if (!(machine->gpio_requested & GPIO_SPKR_EN)) | ||
165 | return 0; | ||
166 | |||
167 | gpio_set_value_cansleep(pdata->gpio_spkr_en, | ||
168 | SND_SOC_DAPM_EVENT_ON(event)); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, | ||
174 | struct snd_kcontrol *k, int event) | ||
175 | { | ||
176 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
177 | struct snd_soc_card *card = dapm->card; | ||
178 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | ||
179 | struct tegra_wm8903_platform_data *pdata = machine->pdata; | ||
180 | |||
181 | if (!(machine->gpio_requested & GPIO_HP_MUTE)) | ||
182 | return 0; | ||
183 | |||
184 | gpio_set_value_cansleep(pdata->gpio_hp_mute, | ||
185 | !SND_SOC_DAPM_EVENT_ON(event)); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = { | ||
191 | SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk), | ||
192 | SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp), | ||
193 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
194 | }; | ||
195 | |||
196 | static const struct snd_soc_dapm_route harmony_audio_map[] = { | ||
197 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
198 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
199 | {"Int Spk", NULL, "ROP"}, | ||
200 | {"Int Spk", NULL, "RON"}, | ||
201 | {"Int Spk", NULL, "LOP"}, | ||
202 | {"Int Spk", NULL, "LON"}, | ||
203 | {"Mic Bias", NULL, "Mic Jack"}, | ||
204 | {"IN1L", NULL, "Mic Bias"}, | ||
205 | }; | ||
206 | |||
207 | static const struct snd_soc_dapm_route seaboard_audio_map[] = { | ||
208 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
209 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
210 | {"Int Spk", NULL, "ROP"}, | ||
211 | {"Int Spk", NULL, "RON"}, | ||
212 | {"Int Spk", NULL, "LOP"}, | ||
213 | {"Int Spk", NULL, "LON"}, | ||
214 | {"Mic Bias", NULL, "Mic Jack"}, | ||
215 | {"IN1R", NULL, "Mic Bias"}, | ||
216 | }; | ||
217 | |||
218 | static const struct snd_soc_dapm_route kaen_audio_map[] = { | ||
219 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
220 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
221 | {"Int Spk", NULL, "ROP"}, | ||
222 | {"Int Spk", NULL, "RON"}, | ||
223 | {"Int Spk", NULL, "LOP"}, | ||
224 | {"Int Spk", NULL, "LON"}, | ||
225 | {"Mic Bias", NULL, "Mic Jack"}, | ||
226 | {"IN2R", NULL, "Mic Bias"}, | ||
227 | }; | ||
228 | |||
229 | static const struct snd_soc_dapm_route aebl_audio_map[] = { | ||
230 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
231 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
232 | {"Int Spk", NULL, "LINEOUTR"}, | ||
233 | {"Int Spk", NULL, "LINEOUTL"}, | ||
234 | {"Mic Bias", NULL, "Mic Jack"}, | ||
235 | {"IN1R", NULL, "Mic Bias"}, | ||
236 | }; | ||
237 | |||
238 | static const struct snd_kcontrol_new tegra_wm8903_controls[] = { | ||
239 | SOC_DAPM_PIN_SWITCH("Int Spk"), | ||
240 | }; | ||
241 | |||
242 | static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | ||
243 | { | ||
244 | struct snd_soc_codec *codec = rtd->codec; | ||
245 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
246 | struct snd_soc_card *card = codec->card; | ||
247 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | ||
248 | struct tegra_wm8903_platform_data *pdata = machine->pdata; | ||
249 | int ret; | ||
250 | |||
251 | if (gpio_is_valid(pdata->gpio_spkr_en)) { | ||
252 | ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); | ||
253 | if (ret) { | ||
254 | dev_err(card->dev, "cannot get spkr_en gpio\n"); | ||
255 | return ret; | ||
256 | } | ||
257 | machine->gpio_requested |= GPIO_SPKR_EN; | ||
258 | |||
259 | gpio_direction_output(pdata->gpio_spkr_en, 0); | ||
260 | } | ||
261 | |||
262 | if (gpio_is_valid(pdata->gpio_hp_mute)) { | ||
263 | ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); | ||
264 | if (ret) { | ||
265 | dev_err(card->dev, "cannot get hp_mute gpio\n"); | ||
266 | return ret; | ||
267 | } | ||
268 | machine->gpio_requested |= GPIO_HP_MUTE; | ||
269 | |||
270 | gpio_direction_output(pdata->gpio_hp_mute, 0); | ||
271 | } | ||
272 | |||
273 | if (gpio_is_valid(pdata->gpio_int_mic_en)) { | ||
274 | ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); | ||
275 | if (ret) { | ||
276 | dev_err(card->dev, "cannot get int_mic_en gpio\n"); | ||
277 | return ret; | ||
278 | } | ||
279 | machine->gpio_requested |= GPIO_INT_MIC_EN; | ||
280 | |||
281 | /* Disable int mic; enable signal is active-high */ | ||
282 | gpio_direction_output(pdata->gpio_int_mic_en, 0); | ||
283 | } | ||
284 | |||
285 | if (gpio_is_valid(pdata->gpio_ext_mic_en)) { | ||
286 | ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); | ||
287 | if (ret) { | ||
288 | dev_err(card->dev, "cannot get ext_mic_en gpio\n"); | ||
289 | return ret; | ||
290 | } | ||
291 | machine->gpio_requested |= GPIO_EXT_MIC_EN; | ||
292 | |||
293 | /* Enable ext mic; enable signal is active-low */ | ||
294 | gpio_direction_output(pdata->gpio_ext_mic_en, 0); | ||
295 | } | ||
296 | |||
297 | if (gpio_is_valid(pdata->gpio_hp_det)) { | ||
298 | tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; | ||
299 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, | ||
300 | &tegra_wm8903_hp_jack); | ||
301 | snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, | ||
302 | ARRAY_SIZE(tegra_wm8903_hp_jack_pins), | ||
303 | tegra_wm8903_hp_jack_pins); | ||
304 | snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, | ||
305 | 1, | ||
306 | &tegra_wm8903_hp_jack_gpio); | ||
307 | } | ||
308 | |||
309 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
310 | &tegra_wm8903_mic_jack); | ||
311 | snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, | ||
312 | ARRAY_SIZE(tegra_wm8903_mic_jack_pins), | ||
313 | tegra_wm8903_mic_jack_pins); | ||
314 | wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, | ||
315 | 0); | ||
316 | |||
317 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); | ||
318 | |||
319 | /* FIXME: Calculate automatically based on DAPM routes? */ | ||
320 | if (!machine_is_harmony() && !machine_is_ventana()) | ||
321 | snd_soc_dapm_nc_pin(dapm, "IN1L"); | ||
322 | if (!machine_is_seaboard() && !machine_is_aebl()) | ||
323 | snd_soc_dapm_nc_pin(dapm, "IN1R"); | ||
324 | snd_soc_dapm_nc_pin(dapm, "IN2L"); | ||
325 | if (!machine_is_kaen()) | ||
326 | snd_soc_dapm_nc_pin(dapm, "IN2R"); | ||
327 | snd_soc_dapm_nc_pin(dapm, "IN3L"); | ||
328 | snd_soc_dapm_nc_pin(dapm, "IN3R"); | ||
329 | |||
330 | if (machine_is_aebl()) { | ||
331 | snd_soc_dapm_nc_pin(dapm, "LON"); | ||
332 | snd_soc_dapm_nc_pin(dapm, "RON"); | ||
333 | snd_soc_dapm_nc_pin(dapm, "ROP"); | ||
334 | snd_soc_dapm_nc_pin(dapm, "LOP"); | ||
335 | } else { | ||
336 | snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); | ||
337 | snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); | ||
338 | } | ||
339 | |||
340 | snd_soc_dapm_sync(dapm); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct snd_soc_dai_link tegra_wm8903_dai = { | ||
346 | .name = "WM8903", | ||
347 | .stream_name = "WM8903 PCM", | ||
348 | .codec_name = "wm8903.0-001a", | ||
349 | .platform_name = "tegra-pcm-audio", | ||
350 | .cpu_dai_name = "tegra-i2s.0", | ||
351 | .codec_dai_name = "wm8903-hifi", | ||
352 | .init = tegra_wm8903_init, | ||
353 | .ops = &tegra_wm8903_ops, | ||
354 | }; | ||
355 | |||
356 | static struct snd_soc_card snd_soc_tegra_wm8903 = { | ||
357 | .name = "tegra-wm8903", | ||
358 | .dai_link = &tegra_wm8903_dai, | ||
359 | .num_links = 1, | ||
360 | |||
361 | .controls = tegra_wm8903_controls, | ||
362 | .num_controls = ARRAY_SIZE(tegra_wm8903_controls), | ||
363 | .dapm_widgets = tegra_wm8903_dapm_widgets, | ||
364 | .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets), | ||
365 | }; | ||
366 | |||
367 | static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | ||
368 | { | ||
369 | struct snd_soc_card *card = &snd_soc_tegra_wm8903; | ||
370 | struct tegra_wm8903 *machine; | ||
371 | struct tegra_wm8903_platform_data *pdata; | ||
372 | int ret; | ||
373 | |||
374 | pdata = pdev->dev.platform_data; | ||
375 | if (!pdata) { | ||
376 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
377 | return -EINVAL; | ||
378 | } | ||
379 | |||
380 | machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL); | ||
381 | if (!machine) { | ||
382 | dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n"); | ||
383 | return -ENOMEM; | ||
384 | } | ||
385 | |||
386 | machine->pdata = pdata; | ||
387 | |||
388 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | ||
389 | if (ret) | ||
390 | goto err_free_machine; | ||
391 | |||
392 | card->dev = &pdev->dev; | ||
393 | platform_set_drvdata(pdev, card); | ||
394 | snd_soc_card_set_drvdata(card, machine); | ||
395 | |||
396 | if (machine_is_harmony() || machine_is_ventana()) { | ||
397 | card->dapm_routes = harmony_audio_map; | ||
398 | card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); | ||
399 | } else if (machine_is_seaboard()) { | ||
400 | card->dapm_routes = seaboard_audio_map; | ||
401 | card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); | ||
402 | } else if (machine_is_kaen()) { | ||
403 | card->dapm_routes = kaen_audio_map; | ||
404 | card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); | ||
405 | } else { | ||
406 | card->dapm_routes = aebl_audio_map; | ||
407 | card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); | ||
408 | } | ||
409 | |||
410 | ret = snd_soc_register_card(card); | ||
411 | if (ret) { | ||
412 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
413 | ret); | ||
414 | goto err_fini_utils; | ||
415 | } | ||
416 | |||
417 | return 0; | ||
418 | |||
419 | err_fini_utils: | ||
420 | tegra_asoc_utils_fini(&machine->util_data); | ||
421 | err_free_machine: | ||
422 | kfree(machine); | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) | ||
427 | { | ||
428 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
429 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | ||
430 | struct tegra_wm8903_platform_data *pdata = machine->pdata; | ||
431 | |||
432 | snd_soc_unregister_card(card); | ||
433 | |||
434 | tegra_asoc_utils_fini(&machine->util_data); | ||
435 | |||
436 | if (machine->gpio_requested & GPIO_EXT_MIC_EN) | ||
437 | gpio_free(pdata->gpio_ext_mic_en); | ||
438 | if (machine->gpio_requested & GPIO_INT_MIC_EN) | ||
439 | gpio_free(pdata->gpio_int_mic_en); | ||
440 | if (machine->gpio_requested & GPIO_HP_MUTE) | ||
441 | gpio_free(pdata->gpio_hp_mute); | ||
442 | if (machine->gpio_requested & GPIO_SPKR_EN) | ||
443 | gpio_free(pdata->gpio_spkr_en); | ||
444 | |||
445 | kfree(machine); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static struct platform_driver tegra_wm8903_driver = { | ||
451 | .driver = { | ||
452 | .name = DRV_NAME, | ||
453 | .owner = THIS_MODULE, | ||
454 | .pm = &snd_soc_pm_ops, | ||
455 | }, | ||
456 | .probe = tegra_wm8903_driver_probe, | ||
457 | .remove = __devexit_p(tegra_wm8903_driver_remove), | ||
458 | }; | ||
459 | |||
460 | static int __init tegra_wm8903_modinit(void) | ||
461 | { | ||
462 | return platform_driver_register(&tegra_wm8903_driver); | ||
463 | } | ||
464 | module_init(tegra_wm8903_modinit); | ||
465 | |||
466 | static void __exit tegra_wm8903_modexit(void) | ||
467 | { | ||
468 | platform_driver_unregister(&tegra_wm8903_driver); | ||
469 | } | ||
470 | module_exit(tegra_wm8903_modexit); | ||
471 | |||
472 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
473 | MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver"); | ||
474 | MODULE_LICENSE("GPL"); | ||
475 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c new file mode 100644 index 000000000000..8fc07e9adf2e --- /dev/null +++ b/sound/soc/tegra/trimslice.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * trimslice.c - TrimSlice machine ASoC driver | ||
3 | * | ||
4 | * Copyright (C) 2011 - CompuLab, Ltd. | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * Author: Stephen Warren <swarren@nvidia.com> | ||
9 | * Copyright (C) 2010-2011 - NVIDIA, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/slab.h> | ||
32 | |||
33 | #include <sound/core.h> | ||
34 | #include <sound/jack.h> | ||
35 | #include <sound/pcm.h> | ||
36 | #include <sound/pcm_params.h> | ||
37 | #include <sound/soc.h> | ||
38 | |||
39 | #include "../codecs/tlv320aic23.h" | ||
40 | |||
41 | #include "tegra_das.h" | ||
42 | #include "tegra_i2s.h" | ||
43 | #include "tegra_pcm.h" | ||
44 | #include "tegra_asoc_utils.h" | ||
45 | |||
46 | #define DRV_NAME "tegra-snd-trimslice" | ||
47 | |||
48 | struct tegra_trimslice { | ||
49 | struct tegra_asoc_utils_data util_data; | ||
50 | }; | ||
51 | |||
52 | static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, | ||
53 | struct snd_pcm_hw_params *params) | ||
54 | { | ||
55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
56 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
57 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
58 | struct snd_soc_codec *codec = rtd->codec; | ||
59 | struct snd_soc_card *card = codec->card; | ||
60 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); | ||
61 | int srate, mclk; | ||
62 | int err; | ||
63 | |||
64 | srate = params_rate(params); | ||
65 | mclk = 128 * srate; | ||
66 | |||
67 | err = tegra_asoc_utils_set_rate(&trimslice->util_data, srate, mclk); | ||
68 | if (err < 0) { | ||
69 | dev_err(card->dev, "Can't configure clocks\n"); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | err = snd_soc_dai_set_fmt(codec_dai, | ||
74 | SND_SOC_DAIFMT_I2S | | ||
75 | SND_SOC_DAIFMT_NB_NF | | ||
76 | SND_SOC_DAIFMT_CBS_CFS); | ||
77 | if (err < 0) { | ||
78 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
79 | return err; | ||
80 | } | ||
81 | |||
82 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
83 | SND_SOC_DAIFMT_I2S | | ||
84 | SND_SOC_DAIFMT_NB_NF | | ||
85 | SND_SOC_DAIFMT_CBS_CFS); | ||
86 | if (err < 0) { | ||
87 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
88 | return err; | ||
89 | } | ||
90 | |||
91 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
92 | SND_SOC_CLOCK_IN); | ||
93 | if (err < 0) { | ||
94 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
95 | return err; | ||
96 | } | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static struct snd_soc_ops trimslice_asoc_ops = { | ||
102 | .hw_params = trimslice_asoc_hw_params, | ||
103 | }; | ||
104 | |||
105 | static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = { | ||
106 | SND_SOC_DAPM_HP("Line Out", NULL), | ||
107 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
108 | }; | ||
109 | |||
110 | static const struct snd_soc_dapm_route trimslice_audio_map[] = { | ||
111 | {"Line Out", NULL, "LOUT"}, | ||
112 | {"Line Out", NULL, "ROUT"}, | ||
113 | |||
114 | {"LLINEIN", NULL, "Line In"}, | ||
115 | {"RLINEIN", NULL, "Line In"}, | ||
116 | }; | ||
117 | |||
118 | static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
119 | { | ||
120 | struct snd_soc_codec *codec = rtd->codec; | ||
121 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
122 | |||
123 | snd_soc_dapm_nc_pin(dapm, "LHPOUT"); | ||
124 | snd_soc_dapm_nc_pin(dapm, "RHPOUT"); | ||
125 | snd_soc_dapm_nc_pin(dapm, "MICIN"); | ||
126 | |||
127 | snd_soc_dapm_sync(dapm); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { | ||
133 | .name = "TLV320AIC23", | ||
134 | .stream_name = "AIC23", | ||
135 | .codec_name = "tlv320aic23-codec.2-001a", | ||
136 | .platform_name = "tegra-pcm-audio", | ||
137 | .cpu_dai_name = "tegra-i2s.0", | ||
138 | .codec_dai_name = "tlv320aic23-hifi", | ||
139 | .init = trimslice_asoc_init, | ||
140 | .ops = &trimslice_asoc_ops, | ||
141 | }; | ||
142 | |||
143 | static struct snd_soc_card snd_soc_trimslice = { | ||
144 | .name = "tegra-trimslice", | ||
145 | .dai_link = &trimslice_tlv320aic23_dai, | ||
146 | .num_links = 1, | ||
147 | |||
148 | .dapm_widgets = trimslice_dapm_widgets, | ||
149 | .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets), | ||
150 | .dapm_routes = trimslice_audio_map, | ||
151 | .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map), | ||
152 | }; | ||
153 | |||
154 | static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) | ||
155 | { | ||
156 | struct snd_soc_card *card = &snd_soc_trimslice; | ||
157 | struct tegra_trimslice *trimslice; | ||
158 | int ret; | ||
159 | |||
160 | trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL); | ||
161 | if (!trimslice) { | ||
162 | dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n"); | ||
163 | return -ENOMEM; | ||
164 | } | ||
165 | |||
166 | ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); | ||
167 | if (ret) | ||
168 | goto err_free_trimslice; | ||
169 | |||
170 | card->dev = &pdev->dev; | ||
171 | platform_set_drvdata(pdev, card); | ||
172 | snd_soc_card_set_drvdata(card, trimslice); | ||
173 | |||
174 | ret = snd_soc_register_card(card); | ||
175 | if (ret) { | ||
176 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
177 | ret); | ||
178 | goto err_fini_utils; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | |||
183 | err_fini_utils: | ||
184 | tegra_asoc_utils_fini(&trimslice->util_data); | ||
185 | err_free_trimslice: | ||
186 | kfree(trimslice); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev) | ||
191 | { | ||
192 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
193 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); | ||
194 | |||
195 | snd_soc_unregister_card(card); | ||
196 | |||
197 | tegra_asoc_utils_fini(&trimslice->util_data); | ||
198 | |||
199 | kfree(trimslice); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static struct platform_driver tegra_snd_trimslice_driver = { | ||
205 | .driver = { | ||
206 | .name = DRV_NAME, | ||
207 | .owner = THIS_MODULE, | ||
208 | }, | ||
209 | .probe = tegra_snd_trimslice_probe, | ||
210 | .remove = __devexit_p(tegra_snd_trimslice_remove), | ||
211 | }; | ||
212 | |||
213 | static int __init snd_tegra_trimslice_init(void) | ||
214 | { | ||
215 | return platform_driver_register(&tegra_snd_trimslice_driver); | ||
216 | } | ||
217 | module_init(snd_tegra_trimslice_init); | ||
218 | |||
219 | static void __exit snd_tegra_trimslice_exit(void) | ||
220 | { | ||
221 | platform_driver_unregister(&tegra_snd_trimslice_driver); | ||
222 | } | ||
223 | module_exit(snd_tegra_trimslice_exit); | ||
224 | |||
225 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
226 | MODULE_DESCRIPTION("Trimslice machine ASoC driver"); | ||
227 | MODULE_LICENSE("GPL"); | ||
228 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index 248463511186..ac828eff1a63 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c | |||
@@ -65,6 +65,15 @@ init_data[] = { | |||
65 | { 0 } /* TERMINATING ENTRY */ | 65 | { 0 } /* TERMINATING ENTRY */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; | ||
69 | /* values to write to soundcard register for all samplerates */ | ||
70 | static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; | ||
71 | static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; | ||
72 | |||
73 | enum { | ||
74 | DIGITAL_THRU_ONLY_SAMPLERATE = 3 | ||
75 | }; | ||
76 | |||
68 | static void usb6fire_control_master_vol_update(struct control_runtime *rt) | 77 | static void usb6fire_control_master_vol_update(struct control_runtime *rt) |
69 | { | 78 | { |
70 | struct comm_runtime *comm_rt = rt->chip->comm; | 79 | struct comm_runtime *comm_rt = rt->chip->comm; |
@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt) | |||
95 | } | 104 | } |
96 | } | 105 | } |
97 | 106 | ||
107 | static int usb6fire_control_set_rate(struct control_runtime *rt, int rate) | ||
108 | { | ||
109 | int ret; | ||
110 | struct usb_device *device = rt->chip->dev; | ||
111 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
112 | |||
113 | if (rate < 0 || rate >= CONTROL_N_RATES) | ||
114 | return -EINVAL; | ||
115 | |||
116 | ret = usb_set_interface(device, 1, rates_altsetting[rate]); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | /* set soundcard clock */ | ||
121 | ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rate], | ||
122 | rates_6fire_vh[rate]); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int usb6fire_control_set_channels( | ||
130 | struct control_runtime *rt, int n_analog_out, | ||
131 | int n_analog_in, bool spdif_out, bool spdif_in) | ||
132 | { | ||
133 | int ret; | ||
134 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
135 | |||
136 | /* enable analog inputs and outputs | ||
137 | * (one bit per stereo-channel) */ | ||
138 | ret = comm_rt->write16(comm_rt, 0x02, 0x02, | ||
139 | (1 << (n_analog_out / 2)) - 1, | ||
140 | (1 << (n_analog_in / 2)) - 1); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | /* disable digital inputs and outputs */ | ||
145 | /* TODO: use spdif_x to enable/disable digital channels */ | ||
146 | ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int usb6fire_control_streaming_update(struct control_runtime *rt) | ||
154 | { | ||
155 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
156 | |||
157 | if (comm_rt) { | ||
158 | if (!rt->usb_streaming && rt->digital_thru_switch) | ||
159 | usb6fire_control_set_rate(rt, | ||
160 | DIGITAL_THRU_ONLY_SAMPLERATE); | ||
161 | return comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, | ||
162 | (rt->usb_streaming ? 0x01 : 0x00) | | ||
163 | (rt->digital_thru_switch ? 0x08 : 0x00)); | ||
164 | } | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | |||
98 | static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, | 168 | static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, |
99 | struct snd_ctl_elem_info *uinfo) | 169 | struct snd_ctl_elem_info *uinfo) |
100 | { | 170 | { |
@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol, | |||
195 | return 0; | 265 | return 0; |
196 | } | 266 | } |
197 | 267 | ||
268 | static int usb6fire_control_digital_thru_put(struct snd_kcontrol *kcontrol, | ||
269 | struct snd_ctl_elem_value *ucontrol) | ||
270 | { | ||
271 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
272 | int changed = 0; | ||
273 | |||
274 | if (rt->digital_thru_switch != ucontrol->value.integer.value[0]) { | ||
275 | rt->digital_thru_switch = ucontrol->value.integer.value[0]; | ||
276 | usb6fire_control_streaming_update(rt); | ||
277 | changed = 1; | ||
278 | } | ||
279 | return changed; | ||
280 | } | ||
281 | |||
282 | static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol, | ||
283 | struct snd_ctl_elem_value *ucontrol) | ||
284 | { | ||
285 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
286 | ucontrol->value.integer.value[0] = rt->digital_thru_switch; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
198 | static struct __devinitdata snd_kcontrol_new elements[] = { | 290 | static struct __devinitdata snd_kcontrol_new elements[] = { |
199 | { | 291 | { |
200 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 292 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = { | |||
223 | .get = usb6fire_control_opt_coax_get, | 315 | .get = usb6fire_control_opt_coax_get, |
224 | .put = usb6fire_control_opt_coax_put | 316 | .put = usb6fire_control_opt_coax_put |
225 | }, | 317 | }, |
318 | { | ||
319 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
320 | .name = "Digital Thru Playback Route", | ||
321 | .index = 0, | ||
322 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
323 | .info = snd_ctl_boolean_mono_info, | ||
324 | .get = usb6fire_control_digital_thru_get, | ||
325 | .put = usb6fire_control_digital_thru_put | ||
326 | }, | ||
226 | {} | 327 | {} |
227 | }; | 328 | }; |
228 | 329 | ||
@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) | |||
238 | return -ENOMEM; | 339 | return -ENOMEM; |
239 | 340 | ||
240 | rt->chip = chip; | 341 | rt->chip = chip; |
342 | rt->update_streaming = usb6fire_control_streaming_update; | ||
343 | rt->set_rate = usb6fire_control_set_rate; | ||
344 | rt->set_channels = usb6fire_control_set_channels; | ||
241 | 345 | ||
242 | i = 0; | 346 | i = 0; |
243 | while (init_data[i].type) { | 347 | while (init_data[i].type) { |
@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) | |||
249 | usb6fire_control_opt_coax_update(rt); | 353 | usb6fire_control_opt_coax_update(rt); |
250 | usb6fire_control_line_phono_update(rt); | 354 | usb6fire_control_line_phono_update(rt); |
251 | usb6fire_control_master_vol_update(rt); | 355 | usb6fire_control_master_vol_update(rt); |
356 | usb6fire_control_streaming_update(rt); | ||
252 | 357 | ||
253 | i = 0; | 358 | i = 0; |
254 | while (elements[i].name) { | 359 | while (elements[i].name) { |
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index b534c777ab02..8f5aeead2e3d 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h | |||
@@ -21,12 +21,29 @@ enum { | |||
21 | CONTROL_MAX_ELEMENTS = 32 | 21 | CONTROL_MAX_ELEMENTS = 32 |
22 | }; | 22 | }; |
23 | 23 | ||
24 | enum { | ||
25 | CONTROL_RATE_44KHZ, | ||
26 | CONTROL_RATE_48KHZ, | ||
27 | CONTROL_RATE_88KHZ, | ||
28 | CONTROL_RATE_96KHZ, | ||
29 | CONTROL_RATE_176KHZ, | ||
30 | CONTROL_RATE_192KHZ, | ||
31 | CONTROL_N_RATES | ||
32 | }; | ||
33 | |||
24 | struct control_runtime { | 34 | struct control_runtime { |
35 | int (*update_streaming)(struct control_runtime *rt); | ||
36 | int (*set_rate)(struct control_runtime *rt, int rate); | ||
37 | int (*set_channels)(struct control_runtime *rt, int n_analog_out, | ||
38 | int n_analog_in, bool spdif_out, bool spdif_in); | ||
39 | |||
25 | struct sfire_chip *chip; | 40 | struct sfire_chip *chip; |
26 | 41 | ||
27 | struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; | 42 | struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; |
28 | bool opt_coax_switch; | 43 | bool opt_coax_switch; |
29 | bool line_phono_switch; | 44 | bool line_phono_switch; |
45 | bool digital_thru_switch; | ||
46 | bool usb_streaming; | ||
30 | u8 master_vol; | 47 | u8 master_vol; |
31 | }; | 48 | }; |
32 | 49 | ||
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 86c1a3103760..d47beffedb0f 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c | |||
@@ -3,12 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Firmware loader | 4 | * Firmware loader |
5 | * | 5 | * |
6 | * Currently not working for all devices. To be able to use the device | ||
7 | * in linux, it is also possible to let the windows driver upload the firmware. | ||
8 | * For that, start the computer in windows and reboot. | ||
9 | * As long as the device is connected to the power supply, no firmware reload | ||
10 | * needs to be performed. | ||
11 | * | ||
12 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | 6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> |
13 | * Created: Jan 01, 2011 | 7 | * Created: Jan 01, 2011 |
14 | * Version: 0.3.0 | 8 | * Version: 0.3.0 |
@@ -21,6 +15,7 @@ | |||
21 | */ | 15 | */ |
22 | 16 | ||
23 | #include <linux/firmware.h> | 17 | #include <linux/firmware.h> |
18 | #include <linux/bitrev.h> | ||
24 | 19 | ||
25 | #include "firmware.h" | 20 | #include "firmware.h" |
26 | #include "chip.h" | 21 | #include "chip.h" |
@@ -33,32 +28,6 @@ enum { | |||
33 | FPGA_BUFSIZE = 512, FPGA_EP = 2 | 28 | FPGA_BUFSIZE = 512, FPGA_EP = 2 |
34 | }; | 29 | }; |
35 | 30 | ||
36 | static const u8 BIT_REVERSE_TABLE[256] = { | ||
37 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, | ||
38 | 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, | ||
39 | 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, | ||
40 | 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, | ||
41 | 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, | ||
42 | 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, | ||
43 | 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, | ||
44 | 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | ||
45 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, | ||
46 | 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, | ||
47 | 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, | ||
48 | 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, | ||
49 | 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, | ||
50 | 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, | ||
51 | 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, | ||
52 | 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | ||
53 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, | ||
54 | 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, | ||
55 | 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, | ||
56 | 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, | ||
57 | 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, | ||
58 | 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, | ||
59 | 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, | ||
60 | 0xbf, 0x7f, 0xff }; | ||
61 | |||
62 | /* | 31 | /* |
63 | * wMaxPacketSize of pcm endpoints. | 32 | * wMaxPacketSize of pcm endpoints. |
64 | * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c | 33 | * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c |
@@ -72,6 +41,10 @@ static const u8 ep_w_max_packet_size[] = { | |||
72 | 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ | 41 | 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ |
73 | }; | 42 | }; |
74 | 43 | ||
44 | static const u8 known_fw_versions[][4] = { | ||
45 | { 0x03, 0x01, 0x0b, 0x00 } | ||
46 | }; | ||
47 | |||
75 | struct ihex_record { | 48 | struct ihex_record { |
76 | u16 address; | 49 | u16 address; |
77 | u8 len; | 50 | u8 len; |
@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload( | |||
340 | 313 | ||
341 | while (c != end) { | 314 | while (c != end) { |
342 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) | 315 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) |
343 | buffer[i] = BIT_REVERSE_TABLE[(u8) *c]; | 316 | buffer[i] = byte_rev_table[(u8) *c]; |
344 | 317 | ||
345 | ret = usb6fire_fw_fpga_write(device, buffer, i); | 318 | ret = usb6fire_fw_fpga_write(device, buffer, i); |
346 | if (ret < 0) { | 319 | if (ret < 0) { |
@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload( | |||
363 | return 0; | 336 | return 0; |
364 | } | 337 | } |
365 | 338 | ||
339 | /* check, if the firmware version the devices has currently loaded | ||
340 | * is known by this driver. 'version' needs to have 4 bytes version | ||
341 | * info data. */ | ||
342 | static int usb6fire_fw_check(u8 *version) | ||
343 | { | ||
344 | int i; | ||
345 | |||
346 | for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++) | ||
347 | if (!memcmp(version, known_fw_versions + i, 4)) | ||
348 | return 0; | ||
349 | |||
350 | snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " | ||
351 | "%02x %02x %02x %02x. " | ||
352 | "please reconnect to power. if this failure " | ||
353 | "still happens, check your firmware installation.", | ||
354 | version[0], version[1], version[2], version[3]); | ||
355 | return -EINVAL; | ||
356 | } | ||
357 | |||
366 | int usb6fire_fw_init(struct usb_interface *intf) | 358 | int usb6fire_fw_init(struct usb_interface *intf) |
367 | { | 359 | { |
368 | int i; | 360 | int i; |
@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
378 | "firmware state.\n"); | 370 | "firmware state.\n"); |
379 | return ret; | 371 | return ret; |
380 | } | 372 | } |
381 | if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55 | 373 | if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) { |
382 | || buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7] | ||
383 | != 0x00) { | ||
384 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " | 374 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " |
385 | "received from device: "); | 375 | "received from device: "); |
386 | for (i = 0; i < 8; i++) | 376 | for (i = 0; i < 8; i++) |
@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
389 | return -EIO; | 379 | return -EIO; |
390 | } | 380 | } |
391 | /* do we need fpga loader ezusb firmware? */ | 381 | /* do we need fpga loader ezusb firmware? */ |
392 | if (buffer[3] == 0x01 && buffer[6] == 0x19) { | 382 | if (buffer[3] == 0x01) { |
393 | ret = usb6fire_fw_ezusb_upload(intf, | 383 | ret = usb6fire_fw_ezusb_upload(intf, |
394 | "6fire/dmx6firel2.ihx", 0, NULL, 0); | 384 | "6fire/dmx6firel2.ihx", 0, NULL, 0); |
395 | if (ret < 0) | 385 | if (ret < 0) |
@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
397 | return FW_NOT_READY; | 387 | return FW_NOT_READY; |
398 | } | 388 | } |
399 | /* do we need fpga firmware and application ezusb firmware? */ | 389 | /* do we need fpga firmware and application ezusb firmware? */ |
400 | else if (buffer[3] == 0x02 && buffer[6] == 0x0b) { | 390 | else if (buffer[3] == 0x02) { |
391 | ret = usb6fire_fw_check(buffer + 4); | ||
392 | if (ret < 0) | ||
393 | return ret; | ||
401 | ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); | 394 | ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); |
402 | if (ret < 0) | 395 | if (ret < 0) |
403 | return ret; | 396 | return ret; |
@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
410 | return FW_NOT_READY; | 403 | return FW_NOT_READY; |
411 | } | 404 | } |
412 | /* all fw loaded? */ | 405 | /* all fw loaded? */ |
413 | else if (buffer[3] == 0x03 && buffer[6] == 0x0b) | 406 | else if (buffer[3] == 0x03) |
414 | return 0; | 407 | return usb6fire_fw_check(buffer + 4); |
415 | /* unknown data? */ | 408 | /* unknown data? */ |
416 | else { | 409 | else { |
417 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " | 410 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " |
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index ba62c7468ba8..b137b25865cc 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c | |||
@@ -17,26 +17,23 @@ | |||
17 | #include "pcm.h" | 17 | #include "pcm.h" |
18 | #include "chip.h" | 18 | #include "chip.h" |
19 | #include "comm.h" | 19 | #include "comm.h" |
20 | #include "control.h" | ||
20 | 21 | ||
21 | enum { | 22 | enum { |
22 | OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 | 23 | OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 |
23 | }; | 24 | }; |
24 | 25 | ||
25 | /* keep next two synced with | 26 | /* keep next two synced with |
26 | * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */ | 27 | * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE |
28 | * and CONTROL_RATE_XXX in control.h */ | ||
27 | static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; | 29 | static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; |
28 | static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; | 30 | static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; |
29 | static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; | 31 | static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; |
30 | static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; | ||
31 | static const int rates_alsaid[] = { | 32 | static const int rates_alsaid[] = { |
32 | SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, | 33 | SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, |
33 | SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, | 34 | SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, |
34 | SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; | 35 | SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; |
35 | 36 | ||
36 | /* values to write to soundcard register for all samplerates */ | ||
37 | static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; | ||
38 | static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; | ||
39 | |||
40 | enum { /* settings for pcm */ | 37 | enum { /* settings for pcm */ |
41 | OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 | 38 | OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 |
42 | }; | 39 | }; |
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */ | |||
48 | STREAM_STOPPING | 45 | STREAM_STOPPING |
49 | }; | 46 | }; |
50 | 47 | ||
51 | enum { /* pcm sample rates (also index into RATES_XXX[]) */ | ||
52 | RATE_44KHZ, | ||
53 | RATE_48KHZ, | ||
54 | RATE_88KHZ, | ||
55 | RATE_96KHZ, | ||
56 | RATE_176KHZ, | ||
57 | RATE_192KHZ | ||
58 | }; | ||
59 | |||
60 | static const struct snd_pcm_hardware pcm_hw = { | 48 | static const struct snd_pcm_hardware pcm_hw = { |
61 | .info = SNDRV_PCM_INFO_MMAP | | 49 | .info = SNDRV_PCM_INFO_MMAP | |
62 | SNDRV_PCM_INFO_INTERLEAVED | | 50 | SNDRV_PCM_INFO_INTERLEAVED | |
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = { | |||
64 | SNDRV_PCM_INFO_MMAP_VALID | | 52 | SNDRV_PCM_INFO_MMAP_VALID | |
65 | SNDRV_PCM_INFO_BATCH, | 53 | SNDRV_PCM_INFO_BATCH, |
66 | 54 | ||
67 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 55 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, |
68 | 56 | ||
69 | .rates = SNDRV_PCM_RATE_44100 | | 57 | .rates = SNDRV_PCM_RATE_44100 | |
70 | SNDRV_PCM_RATE_48000 | | 58 | SNDRV_PCM_RATE_48000 | |
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = { | |||
87 | static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) | 75 | static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) |
88 | { | 76 | { |
89 | int ret; | 77 | int ret; |
90 | struct usb_device *device = rt->chip->dev; | 78 | struct control_runtime *ctrl_rt = rt->chip->control; |
91 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
92 | 79 | ||
93 | if (rt->rate >= ARRAY_SIZE(rates)) | 80 | ctrl_rt->usb_streaming = false; |
94 | return -EINVAL; | 81 | ret = ctrl_rt->update_streaming(ctrl_rt); |
95 | /* disable streaming */ | ||
96 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00); | ||
97 | if (ret < 0) { | 82 | if (ret < 0) { |
98 | snd_printk(KERN_ERR PREFIX "error stopping streaming while " | 83 | snd_printk(KERN_ERR PREFIX "error stopping streaming while " |
99 | "setting samplerate %d.\n", rates[rt->rate]); | 84 | "setting samplerate %d.\n", rates[rt->rate]); |
100 | return ret; | 85 | return ret; |
101 | } | 86 | } |
102 | 87 | ||
103 | ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]); | 88 | ret = ctrl_rt->set_rate(ctrl_rt, rt->rate); |
104 | if (ret < 0) { | ||
105 | snd_printk(KERN_ERR PREFIX "error setting interface " | ||
106 | "altsetting %d for samplerate %d.\n", | ||
107 | rates_altsetting[rt->rate], rates[rt->rate]); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | /* set soundcard clock */ | ||
112 | ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate], | ||
113 | rates_6fire_vh[rt->rate]); | ||
114 | if (ret < 0) { | 89 | if (ret < 0) { |
115 | snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", | 90 | snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", |
116 | rates[rt->rate]); | 91 | rates[rt->rate]); |
117 | return ret; | 92 | return ret; |
118 | } | 93 | } |
119 | 94 | ||
120 | /* enable analog inputs and outputs | 95 | ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS, |
121 | * (one bit per stereo-channel) */ | 96 | false, false); |
122 | ret = comm_rt->write16(comm_rt, 0x02, 0x02, | ||
123 | (1 << (OUT_N_CHANNELS / 2)) - 1, | ||
124 | (1 << (IN_N_CHANNELS / 2)) - 1); | ||
125 | if (ret < 0) { | 97 | if (ret < 0) { |
126 | snd_printk(KERN_ERR PREFIX "error initializing analog channels " | 98 | snd_printk(KERN_ERR PREFIX "error initializing channels " |
127 | "while setting samplerate %d.\n", | 99 | "while setting samplerate %d.\n", |
128 | rates[rt->rate]); | 100 | rates[rt->rate]); |
129 | return ret; | 101 | return ret; |
130 | } | 102 | } |
131 | /* disable digital inputs and outputs */ | ||
132 | ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00); | ||
133 | if (ret < 0) { | ||
134 | snd_printk(KERN_ERR PREFIX "error initializing digital " | ||
135 | "channels while setting samplerate %d.\n", | ||
136 | rates[rt->rate]); | ||
137 | return ret; | ||
138 | } | ||
139 | 103 | ||
140 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01); | 104 | ctrl_rt->usb_streaming = true; |
105 | ret = ctrl_rt->update_streaming(ctrl_rt); | ||
141 | if (ret < 0) { | 106 | if (ret < 0) { |
142 | snd_printk(KERN_ERR PREFIX "error starting streaming while " | 107 | snd_printk(KERN_ERR PREFIX "error starting streaming while " |
143 | "setting samplerate %d.\n", rates[rt->rate]); | 108 | "setting samplerate %d.\n", rates[rt->rate]); |
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream( | |||
168 | static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) | 133 | static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) |
169 | { | 134 | { |
170 | int i; | 135 | int i; |
136 | struct control_runtime *ctrl_rt = rt->chip->control; | ||
171 | 137 | ||
172 | if (rt->stream_state != STREAM_DISABLED) { | 138 | if (rt->stream_state != STREAM_DISABLED) { |
173 | for (i = 0; i < PCM_N_URBS; i++) { | 139 | for (i = 0; i < PCM_N_URBS; i++) { |
174 | usb_kill_urb(&rt->in_urbs[i].instance); | 140 | usb_kill_urb(&rt->in_urbs[i].instance); |
175 | usb_kill_urb(&rt->out_urbs[i].instance); | 141 | usb_kill_urb(&rt->out_urbs[i].instance); |
176 | } | 142 | } |
143 | ctrl_rt->usb_streaming = false; | ||
144 | ctrl_rt->update_streaming(ctrl_rt); | ||
177 | rt->stream_state = STREAM_DISABLED; | 145 | rt->stream_state = STREAM_DISABLED; |
178 | } | 146 | } |
179 | } | 147 | } |
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) | |||
228 | unsigned int total_length = 0; | 196 | unsigned int total_length = 0; |
229 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); | 197 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); |
230 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; | 198 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; |
231 | u32 *src = (u32 *) urb->buffer; | 199 | u32 *src = NULL; |
232 | u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off | 200 | u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off |
233 | * (alsa_rt->frame_bits >> 3)); | 201 | * (alsa_rt->frame_bits >> 3)); |
234 | u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | 202 | u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size |
@@ -244,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) | |||
244 | else | 212 | else |
245 | frame_count = 0; | 213 | frame_count = 0; |
246 | 214 | ||
247 | src = (u32 *) (urb->buffer + total_length); | 215 | if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) |
216 | src = (u32 *) (urb->buffer + total_length); | ||
217 | else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) | ||
218 | src = (u32 *) (urb->buffer - 1 + total_length); | ||
219 | else | ||
220 | return; | ||
248 | src++; /* skip leading 4 bytes of every packet */ | 221 | src++; /* skip leading 4 bytes of every packet */ |
249 | total_length += urb->packets[i].length; | 222 | total_length += urb->packets[i].length; |
250 | for (frame = 0; frame < frame_count; frame++) { | 223 | for (frame = 0; frame < frame_count; frame++) { |
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub, | |||
274 | * (alsa_rt->frame_bits >> 3)); | 247 | * (alsa_rt->frame_bits >> 3)); |
275 | u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | 248 | u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size |
276 | * (alsa_rt->frame_bits >> 3)); | 249 | * (alsa_rt->frame_bits >> 3)); |
277 | u32 *dest = (u32 *) urb->buffer; | 250 | u32 *dest; |
278 | int bytes_per_frame = alsa_rt->channels << 2; | 251 | int bytes_per_frame = alsa_rt->channels << 2; |
279 | 252 | ||
253 | if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) | ||
254 | dest = (u32 *) (urb->buffer - 1); | ||
255 | else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) | ||
256 | dest = (u32 *) (urb->buffer); | ||
257 | else { | ||
258 | snd_printk(KERN_ERR PREFIX "Unknown sample format."); | ||
259 | return; | ||
260 | } | ||
261 | |||
280 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { | 262 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { |
281 | /* at least 4 header bytes for valid packet. | 263 | /* at least 4 header bytes for valid packet. |
282 | * after that: 32 bits per sample for analog channels */ | 264 | * after that: 32 bits per sample for analog channels */ |
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) | |||
456 | /* all substreams closed? if so, stop streaming */ | 438 | /* all substreams closed? if so, stop streaming */ |
457 | if (!rt->playback.instance && !rt->capture.instance) { | 439 | if (!rt->playback.instance && !rt->capture.instance) { |
458 | usb6fire_pcm_stream_stop(rt); | 440 | usb6fire_pcm_stream_stop(rt); |
459 | rt->rate = -1; | 441 | rt->rate = ARRAY_SIZE(rates); |
460 | } | 442 | } |
461 | } | 443 | } |
462 | mutex_unlock(&rt->stream_mutex); | 444 | mutex_unlock(&rt->stream_mutex); |
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | |||
480 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | 462 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); |
481 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | 463 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); |
482 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | 464 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; |
483 | int i; | ||
484 | int ret; | 465 | int ret; |
485 | 466 | ||
486 | if (rt->panic) | 467 | if (rt->panic) |
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | |||
493 | sub->period_off = 0; | 474 | sub->period_off = 0; |
494 | 475 | ||
495 | if (rt->stream_state == STREAM_DISABLED) { | 476 | if (rt->stream_state == STREAM_DISABLED) { |
496 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 477 | for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++) |
497 | if (alsa_rt->rate == rates[i]) { | 478 | if (alsa_rt->rate == rates[rt->rate]) |
498 | rt->rate = i; | ||
499 | break; | 479 | break; |
500 | } | 480 | if (rt->rate == ARRAY_SIZE(rates)) { |
501 | if (i == ARRAY_SIZE(rates)) { | ||
502 | mutex_unlock(&rt->stream_mutex); | 481 | mutex_unlock(&rt->stream_mutex); |
503 | snd_printk("invalid rate %d in prepare.\n", | 482 | snd_printk("invalid rate %d in prepare.\n", |
504 | alsa_rt->rate); | 483 | alsa_rt->rate); |
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip) | |||
613 | 592 | ||
614 | rt->chip = chip; | 593 | rt->chip = chip; |
615 | rt->stream_state = STREAM_DISABLED; | 594 | rt->stream_state = STREAM_DISABLED; |
616 | rt->rate = -1; | 595 | rt->rate = ARRAY_SIZE(rates); |
617 | init_waitqueue_head(&rt->stream_wait_queue); | 596 | init_waitqueue_head(&rt->stream_wait_queue); |
618 | mutex_init(&rt->stream_mutex); | 597 | mutex_init(&rt->stream_mutex); |
619 | 598 | ||
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 97724d8fa9f6..8beb77563da2 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -100,19 +100,17 @@ config SND_USB_US122L | |||
100 | 100 | ||
101 | config SND_USB_6FIRE | 101 | config SND_USB_6FIRE |
102 | tristate "TerraTec DMX 6Fire USB" | 102 | tristate "TerraTec DMX 6Fire USB" |
103 | depends on EXPERIMENTAL | ||
104 | select FW_LOADER | 103 | select FW_LOADER |
104 | select BITREVERSE | ||
105 | select SND_RAWMIDI | 105 | select SND_RAWMIDI |
106 | select SND_PCM | 106 | select SND_PCM |
107 | help | 107 | help |
108 | Say Y here to include support for TerraTec 6fire DMX USB interface. | 108 | Say Y here to include support for TerraTec 6fire DMX USB interface. |
109 | 109 | ||
110 | You will need firmware files in order to be able to use the device | 110 | You will need firmware files in order to be able to use the device |
111 | after it has been coldstarted. This driver currently does not support | 111 | after it has been coldstarted. An install script for the firmware |
112 | firmware loading for all devices. If you own such a device, | 112 | and further help can be found at |
113 | you could start windows and let the windows driver upload | 113 | http://sixfireusb.sourceforge.net |
114 | the firmware. As long as you do not unplug your device from power, | ||
115 | it should be usable. | ||
116 | 114 | ||
117 | endif # SND_USB | 115 | endif # SND_USB |
118 | 116 | ||
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 7754a1034545..075195e8661a 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | |||
104 | int err; | 104 | int err; |
105 | unsigned char data; | 105 | unsigned char data; |
106 | struct usb_device *dev = chip->dev; | 106 | struct usb_device *dev = chip->dev; |
107 | struct uac_clock_source_descriptor *cs_desc = | ||
108 | snd_usb_find_clock_source(chip->ctrl_intf, source_id); | ||
109 | |||
110 | if (!cs_desc) | ||
111 | return 0; | ||
112 | |||
113 | /* If a clock source can't tell us whether it's valid, we assume it is */ | ||
114 | if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) | ||
115 | return 1; | ||
107 | 116 | ||
108 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | 117 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
109 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 118 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
@@ -114,7 +123,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | |||
114 | if (err < 0) { | 123 | if (err < 0) { |
115 | snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", | 124 | snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", |
116 | __func__, source_id); | 125 | __func__, source_id); |
117 | return err; | 126 | return 0; |
118 | } | 127 | } |
119 | 128 | ||
120 | return !!data; | 129 | return !!data; |
diff --git a/sound/usb/debug.h b/sound/usb/debug.h index 343ec2d9ee66..58030176f008 100644 --- a/sound/usb/debug.h +++ b/sound/usb/debug.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #ifdef HW_CONST_DEBUG | 8 | #ifdef HW_CONST_DEBUG |
9 | #define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 9 | #define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) |
10 | #else | 10 | #else |
11 | #define hwc_debug(fmt, args...) /**/ | 11 | #define hwc_debug(fmt, args...) do { } while(0) |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #endif /* __USBAUDIO_DEBUG_H */ | 14 | #endif /* __USBAUDIO_DEBUG_H */ |
diff --git a/sound/usb/format.c b/sound/usb/format.c index f079b5e2ab28..8d042dce0d16 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "helper.h" | 30 | #include "helper.h" |
31 | #include "debug.h" | 31 | #include "debug.h" |
32 | #include "clock.h" | 32 | #include "clock.h" |
33 | #include "format.h" | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * parse the audio format type I descriptor | 36 | * parse the audio format type I descriptor |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 6ec33b62e6cf..eab06edcc9b7 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1097 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1097 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1098 | " Switch" : " Volume"); | 1098 | " Switch" : " Volume"); |
1099 | if (control == UAC_FU_VOLUME) { | 1099 | if (control == UAC_FU_VOLUME) { |
1100 | kctl->tlv.c = mixer_vol_tlv; | ||
1101 | kctl->vd[0].access |= | ||
1102 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1103 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1104 | check_mapped_dB(map, cval); | 1100 | check_mapped_dB(map, cval); |
1101 | if (cval->dBmin < cval->dBmax) { | ||
1102 | kctl->tlv.c = mixer_vol_tlv; | ||
1103 | kctl->vd[0].access |= | ||
1104 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1105 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1106 | } | ||
1105 | } | 1107 | } |
1106 | break; | 1108 | break; |
1107 | 1109 | ||
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 73dcc8256bc0..9146cffa6ede 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -61,6 +61,7 @@ static const struct rc_config { | |||
61 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ | 61 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ |
62 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ | 62 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ |
63 | { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ | 63 | { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ |
64 | { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ | ||
64 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ | 65 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -188,6 +189,12 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
188 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 189 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
189 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 190 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
190 | !value, 0, NULL, 0, 100); | 191 | !value, 0, NULL, 0, 100); |
192 | /* USB X-Fi S51 Pro */ | ||
193 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) | ||
194 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
195 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
196 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
197 | !value, 0, NULL, 0, 100); | ||
191 | else | 198 | else |
192 | err = snd_usb_ctl_msg(mixer->chip->dev, | 199 | err = snd_usb_ctl_msg(mixer->chip->dev, |
193 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 200 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
234 | /* USB X-Fi S51 doesn't have a CMSS LED */ | 241 | /* USB X-Fi S51 doesn't have a CMSS LED */ |
235 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) | 242 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) |
236 | continue; | 243 | continue; |
244 | /* USB X-Fi S51 Pro doesn't have one either */ | ||
245 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0) | ||
246 | continue; | ||
237 | if (i > 1 && /* Live24ext has 2 LEDs only */ | 247 | if (i > 1 && /* Live24ext has 2 LEDs only */ |
238 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 248 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
239 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || | 249 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || |
250 | mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || | ||
240 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) | 251 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) |
241 | break; | 252 | break; |
242 | err = snd_ctl_add(mixer->chip->card, | 253 | err = snd_ctl_add(mixer->chip->card, |
@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
512 | case USB_ID(0x041e, 0x3020): | 523 | case USB_ID(0x041e, 0x3020): |
513 | case USB_ID(0x041e, 0x3040): | 524 | case USB_ID(0x041e, 0x3040): |
514 | case USB_ID(0x041e, 0x3042): | 525 | case USB_ID(0x041e, 0x3042): |
526 | case USB_ID(0x041e, 0x30df): | ||
515 | case USB_ID(0x041e, 0x3048): | 527 | case USB_ID(0x041e, 0x3048): |
516 | err = snd_audigy2nx_controls_create(mixer); | 528 | err = snd_audigy2nx_controls_create(mixer); |
517 | if (err < 0) | 529 | if (err < 0) |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index c66d3f64dcf8..78792a8900c3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1651 | } | 1651 | } |
1652 | } | 1652 | } |
1653 | }, | 1653 | }, |
1654 | { | ||
1655 | USB_DEVICE(0x0582, 0x0127), | ||
1656 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1657 | /* .vendor_name = "Roland", */ | ||
1658 | /* .product_name = "GR-55", */ | ||
1659 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1660 | .type = QUIRK_COMPOSITE, | ||
1661 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1662 | { | ||
1663 | .ifnum = 0, | ||
1664 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1665 | }, | ||
1666 | { | ||
1667 | .ifnum = 1, | ||
1668 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1669 | }, | ||
1670 | { | ||
1671 | .ifnum = 2, | ||
1672 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
1673 | }, | ||
1674 | { | ||
1675 | .ifnum = -1 | ||
1676 | } | ||
1677 | } | ||
1678 | } | ||
1679 | }, | ||
1654 | 1680 | ||
1655 | /* Guillemot devices */ | 1681 | /* Guillemot devices */ |
1656 | { | 1682 | { |
@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1953 | } | 1979 | } |
1954 | }, | 1980 | }, |
1955 | { | 1981 | { |
1956 | USB_DEVICE(0x0763, 0x2080), | 1982 | USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), |
1957 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1983 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1958 | /* .vendor_name = "M-Audio", */ | 1984 | /* .vendor_name = "M-Audio", */ |
1959 | /* .product_name = "Fast Track Ultra", */ | 1985 | /* .product_name = "Fast Track Ultra", */ |
@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2020 | } | 2046 | } |
2021 | }, | 2047 | }, |
2022 | { | 2048 | { |
2023 | USB_DEVICE(0x0763, 0x2081), | 2049 | USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081), |
2024 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 2050 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
2025 | /* .vendor_name = "M-Audio", */ | 2051 | /* .vendor_name = "M-Audio", */ |
2026 | /* .product_name = "Fast Track Ultra 8R", */ | 2052 | /* .product_name = "Fast Track Ultra 8R", */ |
@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2179 | } | 2205 | } |
2180 | }, | 2206 | }, |
2181 | 2207 | ||
2208 | /* KORG devices */ | ||
2209 | { | ||
2210 | USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200), | ||
2211 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2212 | .vendor_name = "KORG, Inc.", | ||
2213 | /* .product_name = "PANDORA PX5D", */ | ||
2214 | .ifnum = 3, | ||
2215 | .type = QUIRK_MIDI_STANDARD_INTERFACE, | ||
2216 | } | ||
2217 | }, | ||
2218 | |||
2182 | /* AKAI devices */ | 2219 | /* AKAI devices */ |
2183 | { | 2220 | { |
2184 | USB_DEVICE(0x09e8, 0x0062), | 2221 | USB_DEVICE(0x09e8, 0x0062), |
@@ -2332,6 +2369,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2332 | 2369 | ||
2333 | /* Native Instruments MK2 series */ | 2370 | /* Native Instruments MK2 series */ |
2334 | { | 2371 | { |
2372 | /* Komplete Audio 6 */ | ||
2373 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
2374 | .idVendor = 0x17cc, | ||
2375 | .idProduct = 0x1000, | ||
2376 | }, | ||
2377 | { | ||
2335 | /* Traktor Audio 6 */ | 2378 | /* Traktor Audio 6 */ |
2336 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 2379 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
2337 | .idVendor = 0x17cc, | 2380 | .idVendor = 0x17cc, |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 1b94ec3a3368..bd13d7257240 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
540 | /* Access Music VirusTI Desktop */ | 540 | /* Access Music VirusTI Desktop */ |
541 | return snd_usb_accessmusic_boot_quirk(dev); | 541 | return snd_usb_accessmusic_boot_quirk(dev); |
542 | 542 | ||
543 | case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */ | ||
543 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ | 544 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ |
544 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ | 545 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ |
545 | return snd_usb_nativeinstruments_boot_quirk(dev); | 546 | return snd_usb_nativeinstruments_boot_quirk(dev); |