diff options
Diffstat (limited to 'sound')
256 files changed, 16720 insertions, 7434 deletions
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 467836057ee5..a80d5ea87ccd 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, | |||
47 | /* We use the PCI APIs for now until the generic one gets fixed | 47 | /* We use the PCI APIs for now until the generic one gets fixed |
48 | * enough or until we get some macio-specific versions | 48 | * enough or until we get some macio-specific versions |
49 | */ | 49 | */ |
50 | r->space = dma_alloc_coherent( | 50 | r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, |
51 | &macio_get_pci_dev(i2sdev->macio)->dev, | 51 | r->size, &r->bus_addr, GFP_KERNEL); |
52 | r->size, | 52 | if (!r->space) |
53 | &r->bus_addr, | 53 | return -ENOMEM; |
54 | GFP_KERNEL); | ||
55 | 54 | ||
56 | if (!r->space) return -ENOMEM; | ||
57 | |||
58 | memset(r->space, 0, r->size); | ||
59 | r->cmds = (void*)DBDMA_ALIGN(r->space); | 55 | r->cmds = (void*)DBDMA_ALIGN(r->space); |
60 | r->bus_cmd_start = r->bus_addr + | 56 | r->bus_cmd_start = r->bus_addr + |
61 | (dma_addr_t)((char*)r->cmds - (char*)r->space); | 57 | (dma_addr_t)((char*)r->cmds - (char*)r->space); |
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 66de90ed30ca..39c3969ac1c7 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c | |||
@@ -152,9 +152,9 @@ static inline void pxa_ac97_cold_pxa27x(void) | |||
152 | gsr_bits = 0; | 152 | gsr_bits = 0; |
153 | 153 | ||
154 | /* PXA27x Developers Manual section 13.5.2.2.1 */ | 154 | /* PXA27x Developers Manual section 13.5.2.2.1 */ |
155 | clk_enable(ac97conf_clk); | 155 | clk_prepare_enable(ac97conf_clk); |
156 | udelay(5); | 156 | udelay(5); |
157 | clk_disable(ac97conf_clk); | 157 | clk_disable_unprepare(ac97conf_clk); |
158 | GCR = GCR_COLD_RST | GCR_WARM_RST; | 158 | GCR = GCR_COLD_RST | GCR_WARM_RST; |
159 | } | 159 | } |
160 | #endif | 160 | #endif |
@@ -299,14 +299,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) | |||
299 | int pxa2xx_ac97_hw_suspend(void) | 299 | int pxa2xx_ac97_hw_suspend(void) |
300 | { | 300 | { |
301 | GCR |= GCR_ACLINK_OFF; | 301 | GCR |= GCR_ACLINK_OFF; |
302 | clk_disable(ac97_clk); | 302 | clk_disable_unprepare(ac97_clk); |
303 | return 0; | 303 | return 0; |
304 | } | 304 | } |
305 | EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend); | 305 | EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend); |
306 | 306 | ||
307 | int pxa2xx_ac97_hw_resume(void) | 307 | int pxa2xx_ac97_hw_resume(void) |
308 | { | 308 | { |
309 | clk_enable(ac97_clk); | 309 | clk_prepare_enable(ac97_clk); |
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); | 312 | EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); |
@@ -368,7 +368,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) | |||
368 | goto err_clk; | 368 | goto err_clk; |
369 | } | 369 | } |
370 | 370 | ||
371 | ret = clk_enable(ac97_clk); | 371 | ret = clk_prepare_enable(ac97_clk); |
372 | if (ret) | 372 | if (ret) |
373 | goto err_clk2; | 373 | goto err_clk2; |
374 | 374 | ||
@@ -403,7 +403,7 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev) | |||
403 | clk_put(ac97conf_clk); | 403 | clk_put(ac97conf_clk); |
404 | ac97conf_clk = NULL; | 404 | ac97conf_clk = NULL; |
405 | } | 405 | } |
406 | clk_disable(ac97_clk); | 406 | clk_disable_unprepare(ac97_clk); |
407 | clk_put(ac97_clk); | 407 | clk_put(ac97_clk); |
408 | ac97_clk = NULL; | 408 | ac97_clk = NULL; |
409 | } | 409 | } |
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 7403f348ed14..89028fab64fd 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
@@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params) | |||
491 | { | 491 | { |
492 | /* first let's check the buffer parameter's */ | 492 | /* first let's check the buffer parameter's */ |
493 | if (params->buffer.fragment_size == 0 || | 493 | if (params->buffer.fragment_size == 0 || |
494 | params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) | 494 | params->buffer.fragments > INT_MAX / params->buffer.fragment_size) |
495 | return -EINVAL; | 495 | return -EINVAL; |
496 | 496 | ||
497 | /* now codec parameters */ | 497 | /* now codec parameters */ |
diff --git a/sound/core/control.c b/sound/core/control.c index f0b0e14497a5..b9611344ff9e 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg | |||
1406 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: | 1406 | case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: |
1407 | return snd_ctl_subscribe_events(ctl, ip); | 1407 | return snd_ctl_subscribe_events(ctl, ip); |
1408 | case SNDRV_CTL_IOCTL_TLV_READ: | 1408 | case SNDRV_CTL_IOCTL_TLV_READ: |
1409 | return snd_ctl_tlv_ioctl(ctl, argp, 0); | 1409 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ); |
1410 | case SNDRV_CTL_IOCTL_TLV_WRITE: | 1410 | case SNDRV_CTL_IOCTL_TLV_WRITE: |
1411 | return snd_ctl_tlv_ioctl(ctl, argp, 1); | 1411 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE); |
1412 | case SNDRV_CTL_IOCTL_TLV_COMMAND: | 1412 | case SNDRV_CTL_IOCTL_TLV_COMMAND: |
1413 | return snd_ctl_tlv_ioctl(ctl, argp, -1); | 1413 | return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD); |
1414 | case SNDRV_CTL_IOCTL_POWER: | 1414 | case SNDRV_CTL_IOCTL_POWER: |
1415 | return -ENOPROTOOPT; | 1415 | return -ENOPROTOOPT; |
1416 | case SNDRV_CTL_IOCTL_POWER_STATE: | 1416 | case SNDRV_CTL_IOCTL_POWER_STATE: |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index af49721ba0e3..102e8fd1d450 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -101,7 +101,9 @@ struct snd_pcm_sw_params32 { | |||
101 | u32 silence_threshold; | 101 | u32 silence_threshold; |
102 | u32 silence_size; | 102 | u32 silence_size; |
103 | u32 boundary; | 103 | u32 boundary; |
104 | unsigned char reserved[64]; | 104 | u32 proto; |
105 | u32 tstamp_type; | ||
106 | unsigned char reserved[56]; | ||
105 | }; | 107 | }; |
106 | 108 | ||
107 | /* recalcuate the boundary within 32bit */ | 109 | /* recalcuate the boundary within 32bit */ |
@@ -133,7 +135,9 @@ static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, | |||
133 | get_user(params.start_threshold, &src->start_threshold) || | 135 | get_user(params.start_threshold, &src->start_threshold) || |
134 | get_user(params.stop_threshold, &src->stop_threshold) || | 136 | get_user(params.stop_threshold, &src->stop_threshold) || |
135 | get_user(params.silence_threshold, &src->silence_threshold) || | 137 | get_user(params.silence_threshold, &src->silence_threshold) || |
136 | get_user(params.silence_size, &src->silence_size)) | 138 | get_user(params.silence_size, &src->silence_size) || |
139 | get_user(params.tstamp_type, &src->tstamp_type) || | ||
140 | get_user(params.proto, &src->proto)) | ||
137 | return -EFAULT; | 141 | return -EFAULT; |
138 | /* | 142 | /* |
139 | * Check silent_size parameter. Since we have 64bit boundary, | 143 | * Check silent_size parameter. Since we have 64bit boundary, |
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 76cbb9ec953a..6542c4083594 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c | |||
@@ -65,13 +65,15 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, | |||
65 | enum dma_slave_buswidth buswidth; | 65 | enum dma_slave_buswidth buswidth; |
66 | int bits; | 66 | int bits; |
67 | 67 | ||
68 | bits = snd_pcm_format_physical_width(params_format(params)); | 68 | bits = params_physical_width(params); |
69 | if (bits < 8 || bits > 64) | 69 | if (bits < 8 || bits > 64) |
70 | return -EINVAL; | 70 | return -EINVAL; |
71 | else if (bits == 8) | 71 | else if (bits == 8) |
72 | buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; | 72 | buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; |
73 | else if (bits == 16) | 73 | else if (bits == 16) |
74 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | 74 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; |
75 | else if (bits == 24) | ||
76 | buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; | ||
75 | else if (bits <= 32) | 77 | else if (bits <= 32) |
76 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | 78 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; |
77 | else | 79 | else |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index b653ab001fba..8cd2f930ad0b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -543,6 +543,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, | |||
543 | 543 | ||
544 | if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST) | 544 | if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST) |
545 | return -EINVAL; | 545 | return -EINVAL; |
546 | if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) && | ||
547 | params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST) | ||
548 | return -EINVAL; | ||
546 | if (params->avail_min == 0) | 549 | if (params->avail_min == 0) |
547 | return -EINVAL; | 550 | return -EINVAL; |
548 | if (params->silence_size >= runtime->boundary) { | 551 | if (params->silence_size >= runtime->boundary) { |
@@ -557,6 +560,8 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, | |||
557 | err = 0; | 560 | err = 0; |
558 | snd_pcm_stream_lock_irq(substream); | 561 | snd_pcm_stream_lock_irq(substream); |
559 | runtime->tstamp_mode = params->tstamp_mode; | 562 | runtime->tstamp_mode = params->tstamp_mode; |
563 | if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12)) | ||
564 | runtime->tstamp_type = params->tstamp_type; | ||
560 | runtime->period_step = params->period_step; | 565 | runtime->period_step = params->period_step; |
561 | runtime->control->avail_min = params->avail_min; | 566 | runtime->control->avail_min = params->avail_min; |
562 | runtime->start_threshold = params->start_threshold; | 567 | runtime->start_threshold = params->start_threshold; |
@@ -2540,9 +2545,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg) | |||
2540 | return -EFAULT; | 2545 | return -EFAULT; |
2541 | if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST) | 2546 | if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST) |
2542 | return -EINVAL; | 2547 | return -EINVAL; |
2543 | runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY; | 2548 | runtime->tstamp_type = arg; |
2544 | if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC) | ||
2545 | runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; | ||
2546 | return 0; | 2549 | return 0; |
2547 | } | 2550 | } |
2548 | 2551 | ||
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 1e206de0c2dd..ba8e4a64e13e 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, | |||
101 | len -= size; | 101 | len -= size; |
102 | } | 102 | } |
103 | return 0; | 103 | return 0; |
104 | } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) { | ||
105 | return func(private_data, event->data.ext.ptr, len); | ||
106 | } | 104 | } |
105 | if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) | ||
106 | return func(private_data, event->data.ext.ptr, len); | ||
107 | 107 | ||
108 | cell = (struct snd_seq_event_cell *)event->data.ext.ptr; | 108 | cell = (struct snd_seq_event_cell *)event->data.ext.ptr; |
109 | for (; len > 0 && cell; cell = cell->next) { | 109 | for (; len > 0 && cell; cell = cell->next) { |
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 775ef2efc296..46dff64908c8 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -83,8 +83,8 @@ config SND_BEBOB | |||
83 | * Edirol FA-66/FA-101 | 83 | * Edirol FA-66/FA-101 |
84 | * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 | 84 | * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 |
85 | * BridgeCo RDAudio1/Audio5 | 85 | * BridgeCo RDAudio1/Audio5 |
86 | * Mackie Onyx 1220/1620/1640 (Firewire I/O Card) | 86 | * Mackie Onyx 1220/1620/1640 (FireWire I/O Card) |
87 | * Mackie d.2 (Firewire Option) | 87 | * Mackie d.2 (FireWire Option) |
88 | * Stanton FinalScratch 2 (ScratchAmp) | 88 | * Stanton FinalScratch 2 (ScratchAmp) |
89 | * Tascam IF-FW/DM | 89 | * Tascam IF-FW/DM |
90 | * Behringer XENIX UFX 1204/1604 | 90 | * Behringer XENIX UFX 1204/1604 |
@@ -92,7 +92,7 @@ config SND_BEBOB | |||
92 | * Apogee Rosetta 200/400 (X-FireWire card) | 92 | * Apogee Rosetta 200/400 (X-FireWire card) |
93 | * Apogee DA/AD/DD-16X (X-FireWire card) | 93 | * Apogee DA/AD/DD-16X (X-FireWire card) |
94 | * Apogee Ensemble | 94 | * Apogee Ensemble |
95 | * ESI Quotafire610 | 95 | * ESI QuataFire 610 |
96 | * AcousticReality eARMasterOne | 96 | * AcousticReality eARMasterOne |
97 | * CME MatrixKFW | 97 | * CME MatrixKFW |
98 | * Phonic Helix Board 12 MkII/18 MkII/24 MkII | 98 | * Phonic Helix Board 12 MkII/18 MkII/24 MkII |
@@ -101,13 +101,13 @@ config SND_BEBOB | |||
101 | * ICON FireXon | 101 | * ICON FireXon |
102 | * PrismSound Orpheus/ADA-8XR | 102 | * PrismSound Orpheus/ADA-8XR |
103 | * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW | 103 | * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW |
104 | * Terratec EWS MIC2/EWS MIC4 | 104 | * TerraTec EWS MIC2/EWS MIC8 |
105 | * Terratec Aureon 7.1 Firewire | 105 | * TerraTec Aureon 7.1 FireWire |
106 | * Yamaha GO44/GO46 | 106 | * Yamaha GO44/GO46 |
107 | * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO | 107 | * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO |
108 | * M-Audio Firewire410/AudioPhile/Solo | 108 | * M-Audio FireWire410/AudioPhile/Solo |
109 | * M-Audio Ozonic/NRV10/ProfireLightBridge | 109 | * M-Audio Ozonic/NRV10/ProfireLightBridge |
110 | * M-Audio Firewire 1814/ProjectMix IO | 110 | * M-Audio FireWire 1814/ProjectMix IO |
111 | 111 | ||
112 | To compile this driver as a module, choose M here: the module | 112 | To compile this driver as a module, choose M here: the module |
113 | will be called snd-bebob. | 113 | will be called snd-bebob. |
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 6af50eb80ea7..70faa3a32526 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -379,11 +379,11 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
379 | struct special_params *params = bebob->maudio_special_quirk; | 379 | struct special_params *params = bebob->maudio_special_quirk; |
380 | int err, id; | 380 | int err, id; |
381 | 381 | ||
382 | mutex_lock(&bebob->mutex); | ||
383 | |||
384 | id = uval->value.enumerated.item[0]; | 382 | id = uval->value.enumerated.item[0]; |
385 | if (id >= ARRAY_SIZE(special_clk_labels)) | 383 | if (id >= ARRAY_SIZE(special_clk_labels)) |
386 | return 0; | 384 | return -EINVAL; |
385 | |||
386 | mutex_lock(&bebob->mutex); | ||
387 | 387 | ||
388 | err = avc_maudio_set_special_clk(bebob, id, | 388 | err = avc_maudio_set_special_clk(bebob, id, |
389 | params->dig_in_fmt, | 389 | params->dig_in_fmt, |
@@ -391,7 +391,10 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
391 | params->clk_lock); | 391 | params->clk_lock); |
392 | mutex_unlock(&bebob->mutex); | 392 | mutex_unlock(&bebob->mutex); |
393 | 393 | ||
394 | return err >= 0; | 394 | if (err >= 0) |
395 | err = 1; | ||
396 | |||
397 | return err; | ||
395 | } | 398 | } |
396 | static struct snd_kcontrol_new special_clk_ctl = { | 399 | static struct snd_kcontrol_new special_clk_ctl = { |
397 | .name = "Clock Source", | 400 | .name = "Clock Source", |
@@ -434,8 +437,8 @@ static struct snd_kcontrol_new special_sync_ctl = { | |||
434 | .get = special_sync_ctl_get, | 437 | .get = special_sync_ctl_get, |
435 | }; | 438 | }; |
436 | 439 | ||
437 | /* Digital interface control for special firmware */ | 440 | /* Digital input interface control for special firmware */ |
438 | static char *const special_dig_iface_labels[] = { | 441 | static char *const special_dig_in_iface_labels[] = { |
439 | "S/PDIF Optical", "S/PDIF Coaxial", "ADAT Optical" | 442 | "S/PDIF Optical", "S/PDIF Coaxial", "ADAT Optical" |
440 | }; | 443 | }; |
441 | static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, | 444 | static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, |
@@ -443,13 +446,13 @@ static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, | |||
443 | { | 446 | { |
444 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 447 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
445 | einf->count = 1; | 448 | einf->count = 1; |
446 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels); | 449 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_in_iface_labels); |
447 | 450 | ||
448 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | 451 | if (einf->value.enumerated.item >= einf->value.enumerated.items) |
449 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | 452 | einf->value.enumerated.item = einf->value.enumerated.items - 1; |
450 | 453 | ||
451 | strcpy(einf->value.enumerated.name, | 454 | strcpy(einf->value.enumerated.name, |
452 | special_dig_iface_labels[einf->value.enumerated.item]); | 455 | special_dig_in_iface_labels[einf->value.enumerated.item]); |
453 | 456 | ||
454 | return 0; | 457 | return 0; |
455 | } | 458 | } |
@@ -491,26 +494,36 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, | |||
491 | unsigned int id, dig_in_fmt, dig_in_iface; | 494 | unsigned int id, dig_in_fmt, dig_in_iface; |
492 | int err; | 495 | int err; |
493 | 496 | ||
494 | mutex_lock(&bebob->mutex); | ||
495 | |||
496 | id = uval->value.enumerated.item[0]; | 497 | id = uval->value.enumerated.item[0]; |
498 | if (id >= ARRAY_SIZE(special_dig_in_iface_labels)) | ||
499 | return -EINVAL; | ||
497 | 500 | ||
498 | /* decode user value */ | 501 | /* decode user value */ |
499 | dig_in_fmt = (id >> 1) & 0x01; | 502 | dig_in_fmt = (id >> 1) & 0x01; |
500 | dig_in_iface = id & 0x01; | 503 | dig_in_iface = id & 0x01; |
501 | 504 | ||
505 | mutex_lock(&bebob->mutex); | ||
506 | |||
502 | err = avc_maudio_set_special_clk(bebob, | 507 | err = avc_maudio_set_special_clk(bebob, |
503 | params->clk_src, | 508 | params->clk_src, |
504 | dig_in_fmt, | 509 | dig_in_fmt, |
505 | params->dig_out_fmt, | 510 | params->dig_out_fmt, |
506 | params->clk_lock); | 511 | params->clk_lock); |
507 | if ((err < 0) || (params->dig_in_fmt > 0)) /* ADAT */ | 512 | if (err < 0) |
513 | goto end; | ||
514 | |||
515 | /* For ADAT, optical interface is only available. */ | ||
516 | if (params->dig_in_fmt > 0) { | ||
517 | err = 1; | ||
508 | goto end; | 518 | goto end; |
519 | } | ||
509 | 520 | ||
521 | /* For S/PDIF, optical/coaxial interfaces are selectable. */ | ||
510 | err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); | 522 | err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); |
511 | if (err < 0) | 523 | if (err < 0) |
512 | dev_err(&bebob->unit->device, | 524 | dev_err(&bebob->unit->device, |
513 | "fail to set digital input interface: %d\n", err); | 525 | "fail to set digital input interface: %d\n", err); |
526 | err = 1; | ||
514 | end: | 527 | end: |
515 | special_stream_formation_set(bebob); | 528 | special_stream_formation_set(bebob); |
516 | mutex_unlock(&bebob->mutex); | 529 | mutex_unlock(&bebob->mutex); |
@@ -525,18 +538,22 @@ static struct snd_kcontrol_new special_dig_in_iface_ctl = { | |||
525 | .put = special_dig_in_iface_ctl_set | 538 | .put = special_dig_in_iface_ctl_set |
526 | }; | 539 | }; |
527 | 540 | ||
541 | /* Digital output interface control for special firmware */ | ||
542 | static char *const special_dig_out_iface_labels[] = { | ||
543 | "S/PDIF Optical and Coaxial", "ADAT Optical" | ||
544 | }; | ||
528 | static int special_dig_out_iface_ctl_info(struct snd_kcontrol *kctl, | 545 | static int special_dig_out_iface_ctl_info(struct snd_kcontrol *kctl, |
529 | struct snd_ctl_elem_info *einf) | 546 | struct snd_ctl_elem_info *einf) |
530 | { | 547 | { |
531 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 548 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
532 | einf->count = 1; | 549 | einf->count = 1; |
533 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels) - 1; | 550 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_out_iface_labels); |
534 | 551 | ||
535 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | 552 | if (einf->value.enumerated.item >= einf->value.enumerated.items) |
536 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | 553 | einf->value.enumerated.item = einf->value.enumerated.items - 1; |
537 | 554 | ||
538 | strcpy(einf->value.enumerated.name, | 555 | strcpy(einf->value.enumerated.name, |
539 | special_dig_iface_labels[einf->value.enumerated.item + 1]); | 556 | special_dig_out_iface_labels[einf->value.enumerated.item]); |
540 | 557 | ||
541 | return 0; | 558 | return 0; |
542 | } | 559 | } |
@@ -558,16 +575,20 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, | |||
558 | unsigned int id; | 575 | unsigned int id; |
559 | int err; | 576 | int err; |
560 | 577 | ||
561 | mutex_lock(&bebob->mutex); | ||
562 | |||
563 | id = uval->value.enumerated.item[0]; | 578 | id = uval->value.enumerated.item[0]; |
579 | if (id >= ARRAY_SIZE(special_dig_out_iface_labels)) | ||
580 | return -EINVAL; | ||
581 | |||
582 | mutex_lock(&bebob->mutex); | ||
564 | 583 | ||
565 | err = avc_maudio_set_special_clk(bebob, | 584 | err = avc_maudio_set_special_clk(bebob, |
566 | params->clk_src, | 585 | params->clk_src, |
567 | params->dig_in_fmt, | 586 | params->dig_in_fmt, |
568 | id, params->clk_lock); | 587 | id, params->clk_lock); |
569 | if (err >= 0) | 588 | if (err >= 0) { |
570 | special_stream_formation_set(bebob); | 589 | special_stream_formation_set(bebob); |
590 | err = 1; | ||
591 | } | ||
571 | 592 | ||
572 | mutex_unlock(&bebob->mutex); | 593 | mutex_unlock(&bebob->mutex); |
573 | return err; | 594 | return err; |
diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c index f29d4aaf56a1..0639dcb13f7d 100644 --- a/sound/firewire/fireworks/fireworks_proc.c +++ b/sound/firewire/fireworks/fireworks_proc.c | |||
@@ -64,7 +64,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
64 | hwinfo->phys_in_grp_count); | 64 | hwinfo->phys_in_grp_count); |
65 | for (i = 0; i < hwinfo->phys_in_grp_count; i++) { | 65 | for (i = 0; i < hwinfo->phys_in_grp_count; i++) { |
66 | snd_iprintf(buffer, | 66 | snd_iprintf(buffer, |
67 | "phys in grp[0x%d]: type 0x%d, count 0x%d\n", | 67 | "phys in grp[%d]: type 0x%X, count 0x%X\n", |
68 | i, hwinfo->phys_out_grps[i].type, | 68 | i, hwinfo->phys_out_grps[i].type, |
69 | hwinfo->phys_out_grps[i].count); | 69 | hwinfo->phys_out_grps[i].count); |
70 | } | 70 | } |
@@ -73,7 +73,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
73 | hwinfo->phys_out_grp_count); | 73 | hwinfo->phys_out_grp_count); |
74 | for (i = 0; i < hwinfo->phys_out_grp_count; i++) { | 74 | for (i = 0; i < hwinfo->phys_out_grp_count; i++) { |
75 | snd_iprintf(buffer, | 75 | snd_iprintf(buffer, |
76 | "phys out grps[0x%d]: type 0x%d, count 0x%d\n", | 76 | "phys out grps[%d]: type 0x%X, count 0x%X\n", |
77 | i, hwinfo->phys_out_grps[i].type, | 77 | i, hwinfo->phys_out_grps[i].type, |
78 | hwinfo->phys_out_grps[i].count); | 78 | hwinfo->phys_out_grps[i].count); |
79 | } | 79 | } |
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 3bbc3ec5be82..862735005b43 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c | |||
@@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) | |||
316 | case 0xf6: | 316 | case 0xf6: |
317 | /* printk( "tune_request\n"); */ | 317 | /* printk( "tune_request\n"); */ |
318 | devc->m_state = ST_INIT; | 318 | devc->m_state = ST_INIT; |
319 | break; | ||
319 | 320 | ||
320 | /* | 321 | /* |
321 | * Real time messages | 322 | * Real time messages |
@@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner) | |||
972 | devc->m_busy = 0; | 973 | devc->m_busy = 0; |
973 | devc->m_state = ST_INIT; | 974 | devc->m_state = ST_INIT; |
974 | devc->shared_irq = hw_config->always_detect; | 975 | devc->shared_irq = hw_config->always_detect; |
975 | devc->irq = hw_config->irq; | ||
976 | spin_lock_init(&devc->lock); | 976 | spin_lock_init(&devc->lock); |
977 | 977 | ||
978 | if (devc->irq < 0) | 978 | if (devc->irq < 0) |
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 4709e592e2cc..607cee4d545e 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c | |||
@@ -52,7 +52,7 @@ struct voice_info | |||
52 | int panning; /* 0xffff means not set */ | 52 | int panning; /* 0xffff means not set */ |
53 | }; | 53 | }; |
54 | 54 | ||
55 | typedef struct opl_devinfo | 55 | struct opl_devinfo |
56 | { | 56 | { |
57 | int base; | 57 | int base; |
58 | int left_io, right_io; | 58 | int left_io, right_io; |
@@ -73,7 +73,7 @@ typedef struct opl_devinfo | |||
73 | unsigned char cmask; | 73 | unsigned char cmask; |
74 | 74 | ||
75 | int is_opl4; | 75 | int is_opl4; |
76 | } opl_devinfo; | 76 | }; |
77 | 77 | ||
78 | static struct opl_devinfo *devc = NULL; | 78 | static struct opl_devinfo *devc = NULL; |
79 | 79 | ||
diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 145e36b2cfd0..ca0d6e9f49f5 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c | |||
@@ -123,25 +123,25 @@ static bool pss_mixer; | |||
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | 125 | ||
126 | typedef struct pss_mixerdata { | 126 | struct pss_mixerdata { |
127 | unsigned int volume_l; | 127 | unsigned int volume_l; |
128 | unsigned int volume_r; | 128 | unsigned int volume_r; |
129 | unsigned int bass; | 129 | unsigned int bass; |
130 | unsigned int treble; | 130 | unsigned int treble; |
131 | unsigned int synth; | 131 | unsigned int synth; |
132 | } pss_mixerdata; | 132 | }; |
133 | 133 | ||
134 | typedef struct pss_confdata { | 134 | struct pss_confdata { |
135 | int base; | 135 | int base; |
136 | int irq; | 136 | int irq; |
137 | int dma; | 137 | int dma; |
138 | int *osp; | 138 | int *osp; |
139 | pss_mixerdata mixer; | 139 | struct pss_mixerdata mixer; |
140 | int ad_mixer_dev; | 140 | int ad_mixer_dev; |
141 | } pss_confdata; | 141 | }; |
142 | 142 | ||
143 | static pss_confdata pss_data; | 143 | static struct pss_confdata pss_data; |
144 | static pss_confdata *devc = &pss_data; | 144 | static struct pss_confdata *devc = &pss_data; |
145 | static DEFINE_SPINLOCK(lock); | 145 | static DEFINE_SPINLOCK(lock); |
146 | 146 | ||
147 | static int pss_initialized; | 147 | static int pss_initialized; |
@@ -150,7 +150,7 @@ static int pss_cdrom_port = -1; /* Parameter for the PSS cdrom port */ | |||
150 | static bool pss_enable_joystick; /* Parameter for enabling the joystick */ | 150 | static bool pss_enable_joystick; /* Parameter for enabling the joystick */ |
151 | static coproc_operations pss_coproc_operations; | 151 | static coproc_operations pss_coproc_operations; |
152 | 152 | ||
153 | static void pss_write(pss_confdata *devc, int data) | 153 | static void pss_write(struct pss_confdata *devc, int data) |
154 | { | 154 | { |
155 | unsigned long i, limit; | 155 | unsigned long i, limit; |
156 | 156 | ||
@@ -206,7 +206,7 @@ static int __init probe_pss(struct address_info *hw_config) | |||
206 | return 1; | 206 | return 1; |
207 | } | 207 | } |
208 | 208 | ||
209 | static int set_irq(pss_confdata * devc, int dev, int irq) | 209 | static int set_irq(struct pss_confdata *devc, int dev, int irq) |
210 | { | 210 | { |
211 | static unsigned short irq_bits[16] = | 211 | static unsigned short irq_bits[16] = |
212 | { | 212 | { |
@@ -232,7 +232,7 @@ static int set_irq(pss_confdata * devc, int dev, int irq) | |||
232 | return 1; | 232 | return 1; |
233 | } | 233 | } |
234 | 234 | ||
235 | static void set_io_base(pss_confdata * devc, int dev, int base) | 235 | static void set_io_base(struct pss_confdata *devc, int dev, int base) |
236 | { | 236 | { |
237 | unsigned short tmp = inw(REG(dev)) & 0x003f; | 237 | unsigned short tmp = inw(REG(dev)) & 0x003f; |
238 | unsigned short bits = (base & 0x0ffc) << 4; | 238 | unsigned short bits = (base & 0x0ffc) << 4; |
@@ -240,7 +240,7 @@ static void set_io_base(pss_confdata * devc, int dev, int base) | |||
240 | outw(bits | tmp, REG(dev)); | 240 | outw(bits | tmp, REG(dev)); |
241 | } | 241 | } |
242 | 242 | ||
243 | static int set_dma(pss_confdata * devc, int dev, int dma) | 243 | static int set_dma(struct pss_confdata *devc, int dev, int dma) |
244 | { | 244 | { |
245 | static unsigned short dma_bits[8] = | 245 | static unsigned short dma_bits[8] = |
246 | { | 246 | { |
@@ -264,7 +264,7 @@ static int set_dma(pss_confdata * devc, int dev, int dma) | |||
264 | return 1; | 264 | return 1; |
265 | } | 265 | } |
266 | 266 | ||
267 | static int pss_reset_dsp(pss_confdata * devc) | 267 | static int pss_reset_dsp(struct pss_confdata *devc) |
268 | { | 268 | { |
269 | unsigned long i, limit = jiffies + HZ/10; | 269 | unsigned long i, limit = jiffies + HZ/10; |
270 | 270 | ||
@@ -275,7 +275,7 @@ static int pss_reset_dsp(pss_confdata * devc) | |||
275 | return 1; | 275 | return 1; |
276 | } | 276 | } |
277 | 277 | ||
278 | static int pss_put_dspword(pss_confdata * devc, unsigned short word) | 278 | static int pss_put_dspword(struct pss_confdata *devc, unsigned short word) |
279 | { | 279 | { |
280 | int i, val; | 280 | int i, val; |
281 | 281 | ||
@@ -291,7 +291,7 @@ static int pss_put_dspword(pss_confdata * devc, unsigned short word) | |||
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | static int pss_get_dspword(pss_confdata * devc, unsigned short *word) | 294 | static int pss_get_dspword(struct pss_confdata *devc, unsigned short *word) |
295 | { | 295 | { |
296 | int i, val; | 296 | int i, val; |
297 | 297 | ||
@@ -307,7 +307,8 @@ static int pss_get_dspword(pss_confdata * devc, unsigned short *word) | |||
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | 309 | ||
310 | static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) | 310 | static int pss_download_boot(struct pss_confdata *devc, unsigned char *block, |
311 | int size, int flags) | ||
311 | { | 312 | { |
312 | int i, val, count; | 313 | int i, val, count; |
313 | unsigned long limit; | 314 | unsigned long limit; |
@@ -397,7 +398,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size | |||
397 | } | 398 | } |
398 | 399 | ||
399 | /* Mixer */ | 400 | /* Mixer */ |
400 | static void set_master_volume(pss_confdata *devc, int left, int right) | 401 | static void set_master_volume(struct pss_confdata *devc, int left, int right) |
401 | { | 402 | { |
402 | static unsigned char log_scale[101] = { | 403 | static unsigned char log_scale[101] = { |
403 | 0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, | 404 | 0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, |
@@ -416,7 +417,7 @@ static void set_master_volume(pss_confdata *devc, int left, int right) | |||
416 | pss_write(devc, log_scale[right] | 0x0100); | 417 | pss_write(devc, log_scale[right] | 0x0100); |
417 | } | 418 | } |
418 | 419 | ||
419 | static void set_synth_volume(pss_confdata *devc, int volume) | 420 | static void set_synth_volume(struct pss_confdata *devc, int volume) |
420 | { | 421 | { |
421 | int vol = ((0x8000*volume)/100L); | 422 | int vol = ((0x8000*volume)/100L); |
422 | pss_write(devc, 0x0080); | 423 | pss_write(devc, 0x0080); |
@@ -425,21 +426,21 @@ static void set_synth_volume(pss_confdata *devc, int volume) | |||
425 | pss_write(devc, vol); | 426 | pss_write(devc, vol); |
426 | } | 427 | } |
427 | 428 | ||
428 | static void set_bass(pss_confdata *devc, int level) | 429 | static void set_bass(struct pss_confdata *devc, int level) |
429 | { | 430 | { |
430 | int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0; | 431 | int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0; |
431 | pss_write(devc, 0x0010); | 432 | pss_write(devc, 0x0010); |
432 | pss_write(devc, vol | 0x0200); | 433 | pss_write(devc, vol | 0x0200); |
433 | }; | 434 | }; |
434 | 435 | ||
435 | static void set_treble(pss_confdata *devc, int level) | 436 | static void set_treble(struct pss_confdata *devc, int level) |
436 | { | 437 | { |
437 | int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0; | 438 | int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0; |
438 | pss_write(devc, 0x0010); | 439 | pss_write(devc, 0x0010); |
439 | pss_write(devc, vol | 0x0300); | 440 | pss_write(devc, vol | 0x0300); |
440 | }; | 441 | }; |
441 | 442 | ||
442 | static void pss_mixer_reset(pss_confdata *devc) | 443 | static void pss_mixer_reset(struct pss_confdata *devc) |
443 | { | 444 | { |
444 | set_master_volume(devc, 33, 33); | 445 | set_master_volume(devc, 33, 33); |
445 | set_bass(devc, 50); | 446 | set_bass(devc, 50); |
@@ -499,7 +500,8 @@ static int ret_vol_stereo(int left, int right) | |||
499 | return ((right << 8) | left); | 500 | return ((right << 8) | left); |
500 | } | 501 | } |
501 | 502 | ||
502 | static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg) | 503 | static int call_ad_mixer(struct pss_confdata *devc, unsigned int cmd, |
504 | void __user *arg) | ||
503 | { | 505 | { |
504 | if (devc->ad_mixer_dev != NO_WSS_MIXER) | 506 | if (devc->ad_mixer_dev != NO_WSS_MIXER) |
505 | return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg); | 507 | return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg); |
@@ -509,7 +511,7 @@ static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg) | |||
509 | 511 | ||
510 | static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg) | 512 | static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg) |
511 | { | 513 | { |
512 | pss_confdata *devc = mixer_devs[dev]->devc; | 514 | struct pss_confdata *devc = mixer_devs[dev]->devc; |
513 | int cmdf = cmd & 0xff; | 515 | int cmdf = cmd & 0xff; |
514 | 516 | ||
515 | if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) && | 517 | if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) && |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 3a3a3a71088b..50dd0086cfb1 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -858,8 +858,8 @@ config SND_VIRTUOSO | |||
858 | select SND_JACK if INPUT=y || INPUT=SND | 858 | select SND_JACK if INPUT=y || INPUT=SND |
859 | help | 859 | help |
860 | Say Y here to include support for sound cards based on the | 860 | Say Y here to include support for sound cards based on the |
861 | Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, | 861 | Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX, |
862 | Essence ST (Deluxe), and Essence STX. | 862 | Essence ST (Deluxe), and Essence STX (II). |
863 | Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; | 863 | Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; |
864 | for the Xense, missing. | 864 | for the Xense, missing. |
865 | 865 | ||
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 9f10c9e0df5e..631aaa4046ad 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = { | |||
1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, | 1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, |
1755 | struct snd_ctl_elem_info *uinfo) | 1755 | struct snd_ctl_elem_info *uinfo) |
1756 | { | 1756 | { |
1757 | struct echoaudio *chip; | ||
1758 | |||
1759 | chip = snd_kcontrol_chip(kcontrol); | ||
1760 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1757 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1761 | uinfo->count = 96; | 1758 | uinfo->count = 96; |
1762 | uinfo->value.integer.min = ECHOGAIN_MINOUT; | 1759 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = { | |||
1798 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, | 1795 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, |
1799 | struct snd_ctl_elem_info *uinfo) | 1796 | struct snd_ctl_elem_info *uinfo) |
1800 | { | 1797 | { |
1801 | struct echoaudio *chip; | ||
1802 | |||
1803 | chip = snd_kcontrol_chip(kcontrol); | ||
1804 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1798 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1805 | uinfo->count = 6; | 1799 | uinfo->count = 6; |
1806 | uinfo->value.integer.min = 0; | 1800 | uinfo->value.integer.min = 0; |
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c new file mode 100644 index 000000000000..9c22f95838ef --- /dev/null +++ b/sound/pci/hda/dell_wmi_helper.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* Helper functions for Dell Mic Mute LED control; | ||
2 | * to be included from codec driver | ||
3 | */ | ||
4 | |||
5 | #if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS) | ||
6 | #include <linux/dell-led.h> | ||
7 | |||
8 | static int dell_led_value; | ||
9 | static int (*dell_led_set_func)(int, int); | ||
10 | static void (*dell_old_cap_hook)(struct hda_codec *, | ||
11 | struct snd_kcontrol *, | ||
12 | struct snd_ctl_elem_value *); | ||
13 | |||
14 | static void update_dell_wmi_micmute_led(struct hda_codec *codec, | ||
15 | struct snd_kcontrol *kcontrol, | ||
16 | struct snd_ctl_elem_value *ucontrol) | ||
17 | { | ||
18 | if (dell_old_cap_hook) | ||
19 | dell_old_cap_hook(codec, kcontrol, ucontrol); | ||
20 | |||
21 | if (!ucontrol || !dell_led_set_func) | ||
22 | return; | ||
23 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
24 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
25 | int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1; | ||
26 | if (val == dell_led_value) | ||
27 | return; | ||
28 | dell_led_value = val; | ||
29 | if (dell_led_set_func) | ||
30 | dell_led_set_func(DELL_LED_MICMUTE, dell_led_value); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | |||
35 | static void alc_fixup_dell_wmi(struct hda_codec *codec, | ||
36 | const struct hda_fixup *fix, int action) | ||
37 | { | ||
38 | struct alc_spec *spec = codec->spec; | ||
39 | bool removefunc = false; | ||
40 | |||
41 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
42 | if (!dell_led_set_func) | ||
43 | dell_led_set_func = symbol_request(dell_app_wmi_led_set); | ||
44 | if (!dell_led_set_func) { | ||
45 | codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n"); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | removefunc = true; | ||
50 | if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) { | ||
51 | dell_led_value = 0; | ||
52 | if (spec->gen.num_adc_nids > 1) | ||
53 | codec_dbg(codec, "Skipping micmute LED control due to several ADCs"); | ||
54 | else { | ||
55 | dell_old_cap_hook = spec->gen.cap_sync_hook; | ||
56 | spec->gen.cap_sync_hook = update_dell_wmi_micmute_led; | ||
57 | removefunc = false; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | } | ||
62 | |||
63 | if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
64 | symbol_put(dell_app_wmi_led_set); | ||
65 | dell_led_set_func = NULL; | ||
66 | dell_old_cap_hook = NULL; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | #else /* CONFIG_LEDS_DELL_NETBOOKS */ | ||
71 | static void alc_fixup_dell_wmi(struct hda_codec *codec, | ||
72 | const struct hda_fixup *fix, int action) | ||
73 | { | ||
74 | } | ||
75 | |||
76 | #endif /* CONFIG_LEDS_DELL_NETBOOKS */ | ||
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index dabe41975a9d..51dea49aadd4 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include "hda_local.h" | 17 | #include "hda_local.h" |
18 | #include "hda_auto_parser.h" | 18 | #include "hda_auto_parser.h" |
19 | 19 | ||
20 | #define SFX "hda_codec: " | ||
21 | |||
22 | /* | 20 | /* |
23 | * Helper for automatic pin configuration | 21 | * Helper for automatic pin configuration |
24 | */ | 22 | */ |
@@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec, | |||
856 | { | 854 | { |
857 | const struct snd_hda_pin_quirk *pq; | 855 | const struct snd_hda_pin_quirk *pq; |
858 | 856 | ||
859 | if (codec->fixup_forced) | 857 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
860 | return; | 858 | return; |
861 | 859 | ||
862 | for (pq = pin_quirk; pq->subvendor; pq++) { | 860 | for (pq = pin_quirk; pq->subvendor; pq++) { |
@@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
882 | const struct hda_fixup *fixlist) | 880 | const struct hda_fixup *fixlist) |
883 | { | 881 | { |
884 | const struct snd_pci_quirk *q; | 882 | const struct snd_pci_quirk *q; |
885 | int id = -1; | 883 | int id = HDA_FIXUP_ID_NOT_SET; |
886 | const char *name = NULL; | 884 | const char *name = NULL; |
887 | 885 | ||
886 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) | ||
887 | return; | ||
888 | |||
888 | /* when model=nofixup is given, don't pick up any fixups */ | 889 | /* when model=nofixup is given, don't pick up any fixups */ |
889 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { | 890 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { |
890 | codec->fixup_list = NULL; | 891 | codec->fixup_list = NULL; |
891 | codec->fixup_id = -1; | 892 | codec->fixup_name = NULL; |
892 | codec->fixup_forced = 1; | 893 | codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP; |
893 | return; | 894 | return; |
894 | } | 895 | } |
895 | 896 | ||
@@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
899 | codec->fixup_id = models->id; | 900 | codec->fixup_id = models->id; |
900 | codec->fixup_name = models->name; | 901 | codec->fixup_name = models->name; |
901 | codec->fixup_list = fixlist; | 902 | codec->fixup_list = fixlist; |
902 | codec->fixup_forced = 1; | ||
903 | return; | 903 | return; |
904 | } | 904 | } |
905 | models++; | 905 | models++; |
906 | } | 906 | } |
907 | } | 907 | } |
908 | if (id < 0 && quirk) { | 908 | if (quirk) { |
909 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 909 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
910 | if (q) { | 910 | if (q) { |
911 | id = q->value; | 911 | id = q->value; |
@@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
929 | } | 929 | } |
930 | } | 930 | } |
931 | 931 | ||
932 | codec->fixup_forced = 0; | ||
933 | codec->fixup_id = id; | 932 | codec->fixup_id = id; |
934 | if (id >= 0) { | 933 | if (id >= 0) { |
935 | codec->fixup_list = fixlist; | 934 | codec->fixup_list = fixlist; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4c20277a6835..ec6a7d0d1886 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1476 | 1476 | ||
1477 | INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); | 1477 | INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); |
1478 | codec->depop_delay = -1; | 1478 | codec->depop_delay = -1; |
1479 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
1479 | 1480 | ||
1480 | #ifdef CONFIG_PM | 1481 | #ifdef CONFIG_PM |
1481 | spin_lock_init(&codec->power_lock); | 1482 | spin_lock_init(&codec->power_lock); |
@@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2727 | return 0; | 2728 | return 0; |
2728 | } | 2729 | } |
2729 | 2730 | ||
2730 | typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | 2731 | typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *); |
2731 | 2732 | ||
2732 | /* apply the function to all matching slave ctls in the mixer list */ | 2733 | /* apply the function to all matching slave ctls in the mixer list */ |
2733 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | 2734 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, |
@@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2751 | name = tmpname; | 2752 | name = tmpname; |
2752 | } | 2753 | } |
2753 | if (!strcmp(sctl->id.name, name)) { | 2754 | if (!strcmp(sctl->id.name, name)) { |
2754 | err = func(data, sctl); | 2755 | err = func(codec, data, sctl); |
2755 | if (err) | 2756 | if (err) |
2756 | return err; | 2757 | return err; |
2757 | break; | 2758 | break; |
@@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2761 | return 0; | 2762 | return 0; |
2762 | } | 2763 | } |
2763 | 2764 | ||
2764 | static int check_slave_present(void *data, struct snd_kcontrol *sctl) | 2765 | static int check_slave_present(struct hda_codec *codec, |
2766 | void *data, struct snd_kcontrol *sctl) | ||
2765 | { | 2767 | { |
2766 | return 1; | 2768 | return 1; |
2767 | } | 2769 | } |
2768 | 2770 | ||
2769 | /* guess the value corresponding to 0dB */ | 2771 | /* guess the value corresponding to 0dB */ |
2770 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | 2772 | static int get_kctl_0dB_offset(struct hda_codec *codec, |
2773 | struct snd_kcontrol *kctl, int *step_to_check) | ||
2771 | { | 2774 | { |
2772 | int _tlv[4]; | 2775 | int _tlv[4]; |
2773 | const int *tlv = NULL; | 2776 | const int *tlv = NULL; |
@@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | |||
2788 | if (!step) | 2791 | if (!step) |
2789 | return -1; | 2792 | return -1; |
2790 | if (*step_to_check && *step_to_check != step) { | 2793 | if (*step_to_check && *step_to_check != step) { |
2791 | snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n", | 2794 | codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n", |
2792 | - *step_to_check, step); | 2795 | - *step_to_check, step); |
2793 | return -1; | 2796 | return -1; |
2794 | } | 2797 | } |
@@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | |||
2813 | } | 2816 | } |
2814 | 2817 | ||
2815 | /* initialize the slave volume with 0dB */ | 2818 | /* initialize the slave volume with 0dB */ |
2816 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | 2819 | static int init_slave_0dB(struct hda_codec *codec, |
2820 | void *data, struct snd_kcontrol *slave) | ||
2817 | { | 2821 | { |
2818 | int offset = get_kctl_0dB_offset(slave, data); | 2822 | int offset = get_kctl_0dB_offset(codec, slave, data); |
2819 | if (offset > 0) | 2823 | if (offset > 0) |
2820 | put_kctl_with_value(slave, offset); | 2824 | put_kctl_with_value(slave, offset); |
2821 | return 0; | 2825 | return 0; |
2822 | } | 2826 | } |
2823 | 2827 | ||
2824 | /* unmute the slave */ | 2828 | /* unmute the slave */ |
2825 | static int init_slave_unmute(void *data, struct snd_kcontrol *slave) | 2829 | static int init_slave_unmute(struct hda_codec *codec, |
2830 | void *data, struct snd_kcontrol *slave) | ||
2826 | { | 2831 | { |
2827 | return put_kctl_with_value(slave, 1); | 2832 | return put_kctl_with_value(slave, 1); |
2828 | } | 2833 | } |
2829 | 2834 | ||
2835 | static int add_slave(struct hda_codec *codec, | ||
2836 | void *data, struct snd_kcontrol *slave) | ||
2837 | { | ||
2838 | return snd_ctl_add_slave(data, slave); | ||
2839 | } | ||
2840 | |||
2830 | /** | 2841 | /** |
2831 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2842 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2832 | * @codec: HD-audio codec | 2843 | * @codec: HD-audio codec |
@@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2869 | if (err < 0) | 2880 | if (err < 0) |
2870 | return err; | 2881 | return err; |
2871 | 2882 | ||
2872 | err = map_slaves(codec, slaves, suffix, | 2883 | err = map_slaves(codec, slaves, suffix, add_slave, kctl); |
2873 | (map_slave_func_t)snd_ctl_add_slave, kctl); | ||
2874 | if (err < 0) | 2884 | if (err < 0) |
2875 | return err; | 2885 | return err; |
2876 | 2886 | ||
@@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4280 | 4290 | ||
4281 | /** | 4291 | /** |
4282 | * snd_hda_calc_stream_format - calculate format bitset | 4292 | * snd_hda_calc_stream_format - calculate format bitset |
4293 | * @codec: HD-audio codec | ||
4283 | * @rate: the sample rate | 4294 | * @rate: the sample rate |
4284 | * @channels: the number of channels | 4295 | * @channels: the number of channels |
4285 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) | 4296 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) |
@@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4289 | * | 4300 | * |
4290 | * Return zero if invalid. | 4301 | * Return zero if invalid. |
4291 | */ | 4302 | */ |
4292 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 4303 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
4304 | unsigned int rate, | ||
4293 | unsigned int channels, | 4305 | unsigned int channels, |
4294 | unsigned int format, | 4306 | unsigned int format, |
4295 | unsigned int maxbps, | 4307 | unsigned int maxbps, |
@@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4304 | break; | 4316 | break; |
4305 | } | 4317 | } |
4306 | if (!rate_bits[i].hz) { | 4318 | if (!rate_bits[i].hz) { |
4307 | snd_printdd("invalid rate %d\n", rate); | 4319 | codec_dbg(codec, "invalid rate %d\n", rate); |
4308 | return 0; | 4320 | return 0; |
4309 | } | 4321 | } |
4310 | 4322 | ||
4311 | if (channels == 0 || channels > 8) { | 4323 | if (channels == 0 || channels > 8) { |
4312 | snd_printdd("invalid channels %d\n", channels); | 4324 | codec_dbg(codec, "invalid channels %d\n", channels); |
4313 | return 0; | 4325 | return 0; |
4314 | } | 4326 | } |
4315 | val |= channels - 1; | 4327 | val |= channels - 1; |
@@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4332 | val |= AC_FMT_BITS_20; | 4344 | val |= AC_FMT_BITS_20; |
4333 | break; | 4345 | break; |
4334 | default: | 4346 | default: |
4335 | snd_printdd("invalid format width %d\n", | 4347 | codec_dbg(codec, "invalid format width %d\n", |
4336 | snd_pcm_format_width(format)); | 4348 | snd_pcm_format_width(format)); |
4337 | return 0; | 4349 | return 0; |
4338 | } | 4350 | } |
@@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl); | |||
5670 | * suffix is appended to the label. This label index number is stored | 5682 | * suffix is appended to the label. This label index number is stored |
5671 | * to type_idx when non-NULL pointer is given. | 5683 | * to type_idx when non-NULL pointer is given. |
5672 | */ | 5684 | */ |
5673 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 5685 | int snd_hda_add_imux_item(struct hda_codec *codec, |
5686 | struct hda_input_mux *imux, const char *label, | ||
5674 | int index, int *type_idx) | 5687 | int index, int *type_idx) |
5675 | { | 5688 | { |
5676 | int i, label_idx = 0; | 5689 | int i, label_idx = 0; |
5677 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | 5690 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { |
5678 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | 5691 | codec_err(codec, "hda_codec: Too many imux items!\n"); |
5679 | return -EINVAL; | 5692 | return -EINVAL; |
5680 | } | 5693 | } |
5681 | for (i = 0; i < imux->num_items; i++) { | 5694 | for (i = 0; i < imux->num_items; i++) { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 5825aa17d8e3..bbc5a1392c75 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -402,7 +402,6 @@ struct hda_codec { | |||
402 | 402 | ||
403 | /* fix-up list */ | 403 | /* fix-up list */ |
404 | int fixup_id; | 404 | int fixup_id; |
405 | unsigned int fixup_forced:1; /* fixup explicitly set by user */ | ||
406 | const struct hda_fixup *fixup_list; | 405 | const struct hda_fixup *fixup_list; |
407 | const char *fixup_name; | 406 | const char *fixup_name; |
408 | 407 | ||
@@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
538 | int do_now); | 537 | int do_now); |
539 | #define snd_hda_codec_cleanup_stream(codec, nid) \ | 538 | #define snd_hda_codec_cleanup_stream(codec, nid) \ |
540 | __snd_hda_codec_cleanup_stream(codec, nid, 0) | 539 | __snd_hda_codec_cleanup_stream(codec, nid, 0) |
541 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 540 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
541 | unsigned int rate, | ||
542 | unsigned int channels, | 542 | unsigned int channels, |
543 | unsigned int format, | 543 | unsigned int format, |
544 | unsigned int maxbps, | 544 | unsigned int maxbps, |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 480bbddbd801..8337645aa7a5 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/reboot.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
32 | #include "hda_priv.h" | 33 | #include "hda_priv.h" |
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
152 | upper_32_bits(azx_dev->bdl.addr)); | 153 | upper_32_bits(azx_dev->bdl.addr)); |
153 | 154 | ||
154 | /* enable the position buffer */ | 155 | /* enable the position buffer */ |
155 | if (chip->position_fix[0] != POS_FIX_LPIB || | 156 | if (chip->get_position[0] != azx_get_pos_lpib || |
156 | chip->position_fix[1] != POS_FIX_LPIB) { | 157 | chip->get_position[1] != azx_get_pos_lpib) { |
157 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 158 | if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE)) |
158 | azx_writel(chip, DPLBASE, | 159 | azx_writel(chip, DPLBASE, |
159 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 160 | (u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE); |
160 | } | 161 | } |
161 | 162 | ||
162 | /* set the interrupt enable bits in the descriptor control register */ | 163 | /* set the interrupt enable bits in the descriptor control register */ |
@@ -193,7 +194,8 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) | |||
193 | dsp_unlock(azx_dev); | 194 | dsp_unlock(azx_dev); |
194 | return azx_dev; | 195 | return azx_dev; |
195 | } | 196 | } |
196 | if (!res) | 197 | if (!res || |
198 | (chip->driver_caps & AZX_DCAPS_REVERSE_ASSIGN)) | ||
197 | res = azx_dev; | 199 | res = azx_dev; |
198 | } | 200 | } |
199 | dsp_unlock(azx_dev); | 201 | dsp_unlock(azx_dev); |
@@ -481,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
481 | } | 483 | } |
482 | 484 | ||
483 | azx_stream_reset(chip, azx_dev); | 485 | azx_stream_reset(chip, azx_dev); |
484 | format_val = snd_hda_calc_stream_format(runtime->rate, | 486 | format_val = snd_hda_calc_stream_format(apcm->codec, |
487 | runtime->rate, | ||
485 | runtime->channels, | 488 | runtime->channels, |
486 | runtime->format, | 489 | runtime->format, |
487 | hinfo->maxbps, | 490 | hinfo->maxbps, |
@@ -672,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
672 | return 0; | 675 | return 0; |
673 | } | 676 | } |
674 | 677 | ||
675 | /* get the current DMA position with correction on VIA chips */ | 678 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) |
676 | static unsigned int azx_via_get_position(struct azx *chip, | ||
677 | struct azx_dev *azx_dev) | ||
678 | { | 679 | { |
679 | unsigned int link_pos, mini_pos, bound_pos; | 680 | return azx_sd_readl(chip, azx_dev, SD_LPIB); |
680 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | 681 | } |
681 | unsigned int fifo_size; | 682 | EXPORT_SYMBOL_GPL(azx_get_pos_lpib); |
682 | |||
683 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
684 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
685 | /* Playback, no problem using link position */ | ||
686 | return link_pos; | ||
687 | } | ||
688 | |||
689 | /* Capture */ | ||
690 | /* For new chipset, | ||
691 | * use mod to get the DMA position just like old chipset | ||
692 | */ | ||
693 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
694 | mod_dma_pos %= azx_dev->period_bytes; | ||
695 | |||
696 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
697 | * Get from base address + offset. | ||
698 | */ | ||
699 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
700 | |||
701 | if (azx_dev->insufficient) { | ||
702 | /* Link position never gather than FIFO size */ | ||
703 | if (link_pos <= fifo_size) | ||
704 | return 0; | ||
705 | |||
706 | azx_dev->insufficient = 0; | ||
707 | } | ||
708 | |||
709 | if (link_pos <= fifo_size) | ||
710 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
711 | else | ||
712 | mini_pos = link_pos - fifo_size; | ||
713 | |||
714 | /* Find nearest previous boudary */ | ||
715 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
716 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
717 | if (mod_link_pos >= fifo_size) | ||
718 | bound_pos = link_pos - mod_link_pos; | ||
719 | else if (mod_dma_pos >= mod_mini_pos) | ||
720 | bound_pos = mini_pos - mod_mini_pos; | ||
721 | else { | ||
722 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
723 | if (bound_pos >= azx_dev->bufsize) | ||
724 | bound_pos = 0; | ||
725 | } | ||
726 | 683 | ||
727 | /* Calculate real DMA position we want */ | 684 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) |
728 | return bound_pos + mod_dma_pos; | 685 | { |
686 | return le32_to_cpu(*azx_dev->posbuf); | ||
729 | } | 687 | } |
688 | EXPORT_SYMBOL_GPL(azx_get_pos_posbuf); | ||
730 | 689 | ||
731 | unsigned int azx_get_position(struct azx *chip, | 690 | unsigned int azx_get_position(struct azx *chip, |
732 | struct azx_dev *azx_dev, | 691 | struct azx_dev *azx_dev) |
733 | bool with_check) | ||
734 | { | 692 | { |
735 | struct snd_pcm_substream *substream = azx_dev->substream; | 693 | struct snd_pcm_substream *substream = azx_dev->substream; |
736 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
737 | unsigned int pos; | 694 | unsigned int pos; |
738 | int stream = substream->stream; | 695 | int stream = substream->stream; |
739 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
740 | int delay = 0; | 696 | int delay = 0; |
741 | 697 | ||
742 | switch (chip->position_fix[stream]) { | 698 | if (chip->get_position[stream]) |
743 | case POS_FIX_LPIB: | 699 | pos = chip->get_position[stream](chip, azx_dev); |
744 | /* read LPIB */ | 700 | else /* use the position buffer as default */ |
745 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | 701 | pos = azx_get_pos_posbuf(chip, azx_dev); |
746 | break; | ||
747 | case POS_FIX_VIACOMBO: | ||
748 | pos = azx_via_get_position(chip, azx_dev); | ||
749 | break; | ||
750 | default: | ||
751 | /* use the position buffer */ | ||
752 | pos = le32_to_cpu(*azx_dev->posbuf); | ||
753 | if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { | ||
754 | if (!pos || pos == (u32)-1) { | ||
755 | dev_info(chip->card->dev, | ||
756 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
757 | chip->position_fix[stream] = POS_FIX_LPIB; | ||
758 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
759 | } else | ||
760 | chip->position_fix[stream] = POS_FIX_POSBUF; | ||
761 | } | ||
762 | break; | ||
763 | } | ||
764 | 702 | ||
765 | if (pos >= azx_dev->bufsize) | 703 | if (pos >= azx_dev->bufsize) |
766 | pos = 0; | 704 | pos = 0; |
767 | 705 | ||
768 | /* calculate runtime delay from LPIB */ | ||
769 | if (substream->runtime && | ||
770 | chip->position_fix[stream] == POS_FIX_POSBUF && | ||
771 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
772 | unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
773 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
774 | delay = pos - lpib_pos; | ||
775 | else | ||
776 | delay = lpib_pos - pos; | ||
777 | if (delay < 0) { | ||
778 | if (delay >= azx_dev->delay_negative_threshold) | ||
779 | delay = 0; | ||
780 | else | ||
781 | delay += azx_dev->bufsize; | ||
782 | } | ||
783 | if (delay >= azx_dev->period_bytes) { | ||
784 | dev_info(chip->card->dev, | ||
785 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
786 | delay, azx_dev->period_bytes); | ||
787 | delay = 0; | ||
788 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
789 | } | ||
790 | delay = bytes_to_frames(substream->runtime, delay); | ||
791 | } | ||
792 | |||
793 | if (substream->runtime) { | 706 | if (substream->runtime) { |
707 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
708 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
709 | |||
710 | if (chip->get_delay[stream]) | ||
711 | delay += chip->get_delay[stream](chip, azx_dev, pos); | ||
794 | if (hinfo->ops.get_delay) | 712 | if (hinfo->ops.get_delay) |
795 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, | 713 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, |
796 | substream); | 714 | substream); |
@@ -808,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
808 | struct azx *chip = apcm->chip; | 726 | struct azx *chip = apcm->chip; |
809 | struct azx_dev *azx_dev = get_azx_dev(substream); | 727 | struct azx_dev *azx_dev = get_azx_dev(substream); |
810 | return bytes_to_frames(substream->runtime, | 728 | return bytes_to_frames(substream->runtime, |
811 | azx_get_position(chip, azx_dev, false)); | 729 | azx_get_position(chip, azx_dev)); |
812 | } | 730 | } |
813 | 731 | ||
814 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, | 732 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, |
@@ -1058,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1058 | azx_writew(chip, CORBWP, 0); | 976 | azx_writew(chip, CORBWP, 0); |
1059 | 977 | ||
1060 | /* reset the corb hw read pointer */ | 978 | /* reset the corb hw read pointer */ |
1061 | azx_writew(chip, CORBRP, ICH6_CORBRP_RST); | 979 | azx_writew(chip, CORBRP, AZX_CORBRP_RST); |
1062 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { | 980 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { |
1063 | for (timeout = 1000; timeout > 0; timeout--) { | 981 | for (timeout = 1000; timeout > 0; timeout--) { |
1064 | if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST) | 982 | if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST) |
1065 | break; | 983 | break; |
1066 | udelay(1); | 984 | udelay(1); |
1067 | } | 985 | } |
@@ -1081,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1081 | } | 999 | } |
1082 | 1000 | ||
1083 | /* enable corb dma */ | 1001 | /* enable corb dma */ |
1084 | azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); | 1002 | azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN); |
1085 | 1003 | ||
1086 | /* RIRB set up */ | 1004 | /* RIRB set up */ |
1087 | chip->rirb.addr = chip->rb.addr + 2048; | 1005 | chip->rirb.addr = chip->rb.addr + 2048; |
@@ -1094,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1094 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | 1012 | /* set the rirb size to 256 entries (ULI requires explicitly) */ |
1095 | azx_writeb(chip, RIRBSIZE, 0x02); | 1013 | azx_writeb(chip, RIRBSIZE, 0x02); |
1096 | /* reset the rirb hw write pointer */ | 1014 | /* reset the rirb hw write pointer */ |
1097 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); | 1015 | azx_writew(chip, RIRBWP, AZX_RIRBWP_RST); |
1098 | /* set N=1, get RIRB response interrupt for new entry */ | 1016 | /* set N=1, get RIRB response interrupt for new entry */ |
1099 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | 1017 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) |
1100 | azx_writew(chip, RINTCNT, 0xc0); | 1018 | azx_writew(chip, RINTCNT, 0xc0); |
1101 | else | 1019 | else |
1102 | azx_writew(chip, RINTCNT, 1); | 1020 | azx_writew(chip, RINTCNT, 1); |
1103 | /* enable rirb dma and response irq */ | 1021 | /* enable rirb dma and response irq */ |
1104 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 1022 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); |
1105 | spin_unlock_irq(&chip->reg_lock); | 1023 | spin_unlock_irq(&chip->reg_lock); |
1106 | } | 1024 | } |
1107 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); | 1025 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); |
@@ -1145,7 +1063,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1145 | return -EIO; | 1063 | return -EIO; |
1146 | } | 1064 | } |
1147 | wp++; | 1065 | wp++; |
1148 | wp %= ICH6_MAX_CORB_ENTRIES; | 1066 | wp %= AZX_MAX_CORB_ENTRIES; |
1149 | 1067 | ||
1150 | rp = azx_readw(chip, CORBRP); | 1068 | rp = azx_readw(chip, CORBRP); |
1151 | if (wp == rp) { | 1069 | if (wp == rp) { |
@@ -1163,7 +1081,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1163 | return 0; | 1081 | return 0; |
1164 | } | 1082 | } |
1165 | 1083 | ||
1166 | #define ICH6_RIRB_EX_UNSOL_EV (1<<4) | 1084 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) |
1167 | 1085 | ||
1168 | /* retrieve RIRB entry - called from interrupt handler */ | 1086 | /* retrieve RIRB entry - called from interrupt handler */ |
1169 | static void azx_update_rirb(struct azx *chip) | 1087 | static void azx_update_rirb(struct azx *chip) |
@@ -1184,7 +1102,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1184 | 1102 | ||
1185 | while (chip->rirb.rp != wp) { | 1103 | while (chip->rirb.rp != wp) { |
1186 | chip->rirb.rp++; | 1104 | chip->rirb.rp++; |
1187 | chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; | 1105 | chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES; |
1188 | 1106 | ||
1189 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | 1107 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ |
1190 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); | 1108 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); |
@@ -1195,8 +1113,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1195 | res, res_ex, | 1113 | res, res_ex, |
1196 | chip->rirb.rp, wp); | 1114 | chip->rirb.rp, wp); |
1197 | snd_BUG(); | 1115 | snd_BUG(); |
1198 | } | 1116 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) |
1199 | else if (res_ex & ICH6_RIRB_EX_UNSOL_EV) | ||
1200 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); | 1117 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); |
1201 | else if (chip->rirb.cmds[addr]) { | 1118 | else if (chip->rirb.cmds[addr]) { |
1202 | chip->rirb.res[addr] = res; | 1119 | chip->rirb.res[addr] = res; |
@@ -1304,7 +1221,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1304 | /* release CORB/RIRB */ | 1221 | /* release CORB/RIRB */ |
1305 | azx_free_cmd_io(chip); | 1222 | azx_free_cmd_io(chip); |
1306 | /* disable unsolicited responses */ | 1223 | /* disable unsolicited responses */ |
1307 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); | 1224 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL); |
1308 | return -1; | 1225 | return -1; |
1309 | } | 1226 | } |
1310 | 1227 | ||
@@ -1325,7 +1242,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) | |||
1325 | 1242 | ||
1326 | while (timeout--) { | 1243 | while (timeout--) { |
1327 | /* check IRV busy bit */ | 1244 | /* check IRV busy bit */ |
1328 | if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { | 1245 | if (azx_readw(chip, IRS) & AZX_IRS_VALID) { |
1329 | /* reuse rirb.res as the response return value */ | 1246 | /* reuse rirb.res as the response return value */ |
1330 | chip->rirb.res[addr] = azx_readl(chip, IR); | 1247 | chip->rirb.res[addr] = azx_readl(chip, IR); |
1331 | return 0; | 1248 | return 0; |
@@ -1349,13 +1266,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) | |||
1349 | bus->rirb_error = 0; | 1266 | bus->rirb_error = 0; |
1350 | while (timeout--) { | 1267 | while (timeout--) { |
1351 | /* check ICB busy bit */ | 1268 | /* check ICB busy bit */ |
1352 | if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { | 1269 | if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { |
1353 | /* Clear IRV valid bit */ | 1270 | /* Clear IRV valid bit */ |
1354 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1271 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1355 | ICH6_IRS_VALID); | 1272 | AZX_IRS_VALID); |
1356 | azx_writel(chip, IC, val); | 1273 | azx_writel(chip, IC, val); |
1357 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1274 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1358 | ICH6_IRS_BUSY); | 1275 | AZX_IRS_BUSY); |
1359 | return azx_single_wait_for_response(chip, addr); | 1276 | return azx_single_wait_for_response(chip, addr); |
1360 | } | 1277 | } |
1361 | udelay(1); | 1278 | udelay(1); |
@@ -1584,10 +1501,10 @@ void azx_enter_link_reset(struct azx *chip) | |||
1584 | unsigned long timeout; | 1501 | unsigned long timeout; |
1585 | 1502 | ||
1586 | /* reset controller */ | 1503 | /* reset controller */ |
1587 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 1504 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET); |
1588 | 1505 | ||
1589 | timeout = jiffies + msecs_to_jiffies(100); | 1506 | timeout = jiffies + msecs_to_jiffies(100); |
1590 | while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && | 1507 | while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) && |
1591 | time_before(jiffies, timeout)) | 1508 | time_before(jiffies, timeout)) |
1592 | usleep_range(500, 1000); | 1509 | usleep_range(500, 1000); |
1593 | } | 1510 | } |
@@ -1598,7 +1515,7 @@ static void azx_exit_link_reset(struct azx *chip) | |||
1598 | { | 1515 | { |
1599 | unsigned long timeout; | 1516 | unsigned long timeout; |
1600 | 1517 | ||
1601 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 1518 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET); |
1602 | 1519 | ||
1603 | timeout = jiffies + msecs_to_jiffies(100); | 1520 | timeout = jiffies + msecs_to_jiffies(100); |
1604 | while (!azx_readb(chip, GCTL) && | 1521 | while (!azx_readb(chip, GCTL) && |
@@ -1639,7 +1556,7 @@ static int azx_reset(struct azx *chip, bool full_reset) | |||
1639 | /* Accept unsolicited responses */ | 1556 | /* Accept unsolicited responses */ |
1640 | if (!chip->single_cmd) | 1557 | if (!chip->single_cmd) |
1641 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | | 1558 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | |
1642 | ICH6_GCTL_UNSOL); | 1559 | AZX_GCTL_UNSOL); |
1643 | 1560 | ||
1644 | /* detect codecs */ | 1561 | /* detect codecs */ |
1645 | if (!chip->codec_mask) { | 1562 | if (!chip->codec_mask) { |
@@ -1656,7 +1573,7 @@ static void azx_int_enable(struct azx *chip) | |||
1656 | { | 1573 | { |
1657 | /* enable controller CIE and GIE */ | 1574 | /* enable controller CIE and GIE */ |
1658 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | | 1575 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | |
1659 | ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); | 1576 | AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); |
1660 | } | 1577 | } |
1661 | 1578 | ||
1662 | /* disable interrupts */ | 1579 | /* disable interrupts */ |
@@ -1677,7 +1594,7 @@ static void azx_int_disable(struct azx *chip) | |||
1677 | 1594 | ||
1678 | /* disable controller CIE and GIE */ | 1595 | /* disable controller CIE and GIE */ |
1679 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & | 1596 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & |
1680 | ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); | 1597 | ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN)); |
1681 | } | 1598 | } |
1682 | 1599 | ||
1683 | /* clear interrupts */ | 1600 | /* clear interrupts */ |
@@ -1698,7 +1615,7 @@ static void azx_int_clear(struct azx *chip) | |||
1698 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 1615 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
1699 | 1616 | ||
1700 | /* clear int status */ | 1617 | /* clear int status */ |
1701 | azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); | 1618 | azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); |
1702 | } | 1619 | } |
1703 | 1620 | ||
1704 | /* | 1621 | /* |
@@ -2030,5 +1947,30 @@ int azx_init_stream(struct azx *chip) | |||
2030 | } | 1947 | } |
2031 | EXPORT_SYMBOL_GPL(azx_init_stream); | 1948 | EXPORT_SYMBOL_GPL(azx_init_stream); |
2032 | 1949 | ||
1950 | /* | ||
1951 | * reboot notifier for hang-up problem at power-down | ||
1952 | */ | ||
1953 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
1954 | { | ||
1955 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
1956 | snd_hda_bus_reboot_notify(chip->bus); | ||
1957 | azx_stop_chip(chip); | ||
1958 | return NOTIFY_OK; | ||
1959 | } | ||
1960 | |||
1961 | void azx_notifier_register(struct azx *chip) | ||
1962 | { | ||
1963 | chip->reboot_notifier.notifier_call = azx_halt; | ||
1964 | register_reboot_notifier(&chip->reboot_notifier); | ||
1965 | } | ||
1966 | EXPORT_SYMBOL_GPL(azx_notifier_register); | ||
1967 | |||
1968 | void azx_notifier_unregister(struct azx *chip) | ||
1969 | { | ||
1970 | if (chip->reboot_notifier.notifier_call) | ||
1971 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
1972 | } | ||
1973 | EXPORT_SYMBOL_GPL(azx_notifier_unregister); | ||
1974 | |||
2033 | MODULE_LICENSE("GPL"); | 1975 | MODULE_LICENSE("GPL"); |
2034 | MODULE_DESCRIPTION("Common HDA driver funcitons"); | 1976 | MODULE_DESCRIPTION("Common HDA driver funcitons"); |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index baf0e77330af..c90d10fd4d8f 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream) | |||
25 | { | 25 | { |
26 | return substream->runtime->private_data; | 26 | return substream->runtime->private_data; |
27 | } | 27 | } |
28 | unsigned int azx_get_position(struct azx *chip, | 28 | unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev); |
29 | struct azx_dev *azx_dev, | 29 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev); |
30 | bool with_check); | 30 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); |
31 | 31 | ||
32 | /* Stream control. */ | 32 | /* Stream control. */ |
33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); | 33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); |
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip); | |||
50 | int azx_mixer_create(struct azx *chip); | 50 | int azx_mixer_create(struct azx *chip); |
51 | int azx_init_stream(struct azx *chip); | 51 | int azx_init_stream(struct azx *chip); |
52 | 52 | ||
53 | void azx_notifier_register(struct azx *chip); | ||
54 | void azx_notifier_unregister(struct azx *chip); | ||
55 | |||
53 | #endif /* __SOUND_HDA_CONTROLLER_H */ | 56 | #endif /* __SOUND_HDA_CONTROLLER_H */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 46690a7f48f6..e1cd34d9011d 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, | |||
167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ | 167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ |
168 | }) | 168 | }) |
169 | 169 | ||
170 | static void hdmi_update_short_audio_desc(struct cea_sad *a, | 170 | static void hdmi_update_short_audio_desc(struct hda_codec *codec, |
171 | struct cea_sad *a, | ||
171 | const unsigned char *buf) | 172 | const unsigned char *buf) |
172 | { | 173 | { |
173 | int i; | 174 | int i; |
@@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
188 | a->format = GRAB_BITS(buf, 0, 3, 4); | 189 | a->format = GRAB_BITS(buf, 0, 3, 4); |
189 | switch (a->format) { | 190 | switch (a->format) { |
190 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: | 191 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: |
191 | snd_printd(KERN_INFO | 192 | codec_info(codec, "HDMI: audio coding type 0 not expected\n"); |
192 | "HDMI: audio coding type 0 not expected\n"); | ||
193 | break; | 193 | break; |
194 | 194 | ||
195 | case AUDIO_CODING_TYPE_LPCM: | 195 | case AUDIO_CODING_TYPE_LPCM: |
@@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
233 | a->format = GRAB_BITS(buf, 2, 3, 5); | 233 | a->format = GRAB_BITS(buf, 2, 3, 5); |
234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || | 234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || |
235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { | 235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { |
236 | snd_printd(KERN_INFO | 236 | codec_info(codec, |
237 | "HDMI: audio coding xtype %d not expected\n", | 237 | "HDMI: audio coding xtype %d not expected\n", |
238 | a->format); | 238 | a->format); |
239 | a->format = 0; | 239 | a->format = 0; |
240 | } else | 240 | } else |
241 | a->format += AUDIO_CODING_TYPE_HE_AAC - | 241 | a->format += AUDIO_CODING_TYPE_HE_AAC - |
@@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
247 | /* | 247 | /* |
248 | * Be careful, ELD buf could be totally rubbish! | 248 | * Be careful, ELD buf could be totally rubbish! |
249 | */ | 249 | */ |
250 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 250 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
251 | const unsigned char *buf, int size) | 251 | const unsigned char *buf, int size) |
252 | { | 252 | { |
253 | int mnl; | 253 | int mnl; |
@@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); | 256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); |
257 | if (e->eld_ver != ELD_VER_CEA_861D && | 257 | if (e->eld_ver != ELD_VER_CEA_861D && |
258 | e->eld_ver != ELD_VER_PARTIAL) { | 258 | e->eld_ver != ELD_VER_PARTIAL) { |
259 | snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", | 259 | codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver); |
260 | e->eld_ver); | ||
261 | goto out_fail; | 260 | goto out_fail; |
262 | } | 261 | } |
263 | 262 | ||
@@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
280 | e->product_id = get_unaligned_le16(buf + 18); | 279 | e->product_id = get_unaligned_le16(buf + 18); |
281 | 280 | ||
282 | if (mnl > ELD_MAX_MNL) { | 281 | if (mnl > ELD_MAX_MNL) { |
283 | snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); | 282 | codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl); |
284 | goto out_fail; | 283 | goto out_fail; |
285 | } else if (ELD_FIXED_BYTES + mnl > size) { | 284 | } else if (ELD_FIXED_BYTES + mnl > size) { |
286 | snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); | 285 | codec_info(codec, "HDMI: out of range MNL %d\n", mnl); |
287 | goto out_fail; | 286 | goto out_fail; |
288 | } else | 287 | } else |
289 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); | 288 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); |
290 | 289 | ||
291 | for (i = 0; i < e->sad_count; i++) { | 290 | for (i = 0; i < e->sad_count; i++) { |
292 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { | 291 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { |
293 | snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); | 292 | codec_info(codec, "HDMI: out of range SAD %d\n", i); |
294 | goto out_fail; | 293 | goto out_fail; |
295 | } | 294 | } |
296 | hdmi_update_short_audio_desc(e->sad + i, | 295 | hdmi_update_short_audio_desc(codec, e->sad + i, |
297 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | 296 | buf + ELD_FIXED_BYTES + mnl + 3 * i); |
298 | } | 297 | } |
299 | 298 | ||
@@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) | |||
394 | 393 | ||
395 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 | 394 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 |
396 | 395 | ||
397 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 396 | static void hdmi_show_short_audio_desc(struct hda_codec *codec, |
397 | struct cea_sad *a) | ||
398 | { | 398 | { |
399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; | 399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; |
400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; | 400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; |
@@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) | |||
412 | else | 412 | else |
413 | buf2[0] = '\0'; | 413 | buf2[0] = '\0'; |
414 | 414 | ||
415 | _snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:" | 415 | codec_dbg(codec, |
416 | " channels = %d, rates =%s%s\n", | 416 | "HDMI: supports coding type %s: channels = %d, rates =%s%s\n", |
417 | cea_audio_coding_type_names[a->format], | 417 | cea_audio_coding_type_names[a->format], |
418 | a->channels, | 418 | a->channels, buf, buf2); |
419 | buf, | ||
420 | buf2); | ||
421 | } | 419 | } |
422 | 420 | ||
423 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | 421 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) |
@@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
432 | buf[j] = '\0'; /* necessary when j == 0 */ | 430 | buf[j] = '\0'; /* necessary when j == 0 */ |
433 | } | 431 | } |
434 | 432 | ||
435 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e) | 433 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e) |
436 | { | 434 | { |
437 | int i; | 435 | int i; |
438 | 436 | ||
439 | _snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n", | 437 | codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n", |
440 | e->monitor_name, | 438 | e->monitor_name, |
441 | eld_connection_type_names[e->conn_type]); | 439 | eld_connection_type_names[e->conn_type]); |
442 | 440 | ||
443 | if (e->spk_alloc) { | 441 | if (e->spk_alloc) { |
444 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 442 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
445 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); | 443 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); |
446 | _snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf); | 444 | codec_dbg(codec, "HDMI: available speakers:%s\n", buf); |
447 | } | 445 | } |
448 | 446 | ||
449 | for (i = 0; i < e->sad_count; i++) | 447 | for (i = 0; i < e->sad_count; i++) |
450 | hdmi_show_short_audio_desc(e->sad + i); | 448 | hdmi_show_short_audio_desc(codec, e->sad + i); |
451 | } | 449 | } |
452 | 450 | ||
453 | #ifdef CONFIG_PROC_FS | 451 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 589e47c5aeb3..b956449ddada 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -350,16 +350,16 @@ static void print_nid_path(struct hda_codec *codec, | |||
350 | const char *pfx, struct nid_path *path) | 350 | const char *pfx, struct nid_path *path) |
351 | { | 351 | { |
352 | char buf[40]; | 352 | char buf[40]; |
353 | char *pos = buf; | ||
353 | int i; | 354 | int i; |
354 | 355 | ||
356 | *pos = 0; | ||
357 | for (i = 0; i < path->depth; i++) | ||
358 | pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x", | ||
359 | pos != buf ? ":" : "", | ||
360 | path->path[i]); | ||
355 | 361 | ||
356 | buf[0] = 0; | 362 | codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf); |
357 | for (i = 0; i < path->depth; i++) { | ||
358 | char tmp[4]; | ||
359 | sprintf(tmp, ":%02x", path->path[i]); | ||
360 | strlcat(buf, tmp, sizeof(buf)); | ||
361 | } | ||
362 | codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf); | ||
363 | } | 363 | } |
364 | 364 | ||
365 | /* called recursively */ | 365 | /* called recursively */ |
@@ -1700,9 +1700,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1700 | #define DEBUG_BADNESS | 1700 | #define DEBUG_BADNESS |
1701 | 1701 | ||
1702 | #ifdef DEBUG_BADNESS | 1702 | #ifdef DEBUG_BADNESS |
1703 | #define debug_badness(fmt, args...) codec_dbg(codec, fmt, ##args) | 1703 | #define debug_badness(fmt, ...) \ |
1704 | codec_dbg(codec, fmt, ##__VA_ARGS__) | ||
1704 | #else | 1705 | #else |
1705 | #define debug_badness(...) | 1706 | #define debug_badness(fmt, ...) \ |
1707 | do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0) | ||
1706 | #endif | 1708 | #endif |
1707 | 1709 | ||
1708 | #ifdef DEBUG_BADNESS | 1710 | #ifdef DEBUG_BADNESS |
@@ -3054,7 +3056,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin, | |||
3054 | if (spec->hp_mic_pin == pin) | 3056 | if (spec->hp_mic_pin == pin) |
3055 | spec->hp_mic_mux_idx = imux->num_items; | 3057 | spec->hp_mic_mux_idx = imux->num_items; |
3056 | spec->imux_pins[imux->num_items] = pin; | 3058 | spec->imux_pins[imux->num_items] = pin; |
3057 | snd_hda_add_imux_item(imux, label, cfg_idx, NULL); | 3059 | snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL); |
3058 | imux_added = true; | 3060 | imux_added = true; |
3059 | if (spec->dyn_adc_switch) | 3061 | if (spec->dyn_adc_switch) |
3060 | spec->dyn_adc_idx[imux_idx] = c; | 3062 | spec->dyn_adc_idx[imux_idx] = c; |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index 8b4940ba33d6..d4d0375ac181 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c | |||
@@ -28,8 +28,8 @@ | |||
28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N | 28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N |
29 | * The values will be lost when the display power well is disabled. | 29 | * The values will be lost when the display power well is disabled. |
30 | */ | 30 | */ |
31 | #define ICH6_REG_EM4 0x100c | 31 | #define AZX_REG_EM4 0x100c |
32 | #define ICH6_REG_EM5 0x1010 | 32 | #define AZX_REG_EM5 0x1010 |
33 | 33 | ||
34 | static int (*get_power)(void); | 34 | static int (*get_power)(void); |
35 | static int (*put_power)(void); | 35 | static int (*put_power)(void); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b6b4e71a0b0b..5db1948699d8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/reboot.h> | ||
48 | #include <linux/io.h> | 47 | #include <linux/io.h> |
49 | #include <linux/pm_runtime.h> | 48 | #include <linux/pm_runtime.h> |
50 | #include <linux/clocksource.h> | 49 | #include <linux/clocksource.h> |
@@ -66,6 +65,52 @@ | |||
66 | #include "hda_priv.h" | 65 | #include "hda_priv.h" |
67 | #include "hda_i915.h" | 66 | #include "hda_i915.h" |
68 | 67 | ||
68 | /* position fix mode */ | ||
69 | enum { | ||
70 | POS_FIX_AUTO, | ||
71 | POS_FIX_LPIB, | ||
72 | POS_FIX_POSBUF, | ||
73 | POS_FIX_VIACOMBO, | ||
74 | POS_FIX_COMBO, | ||
75 | }; | ||
76 | |||
77 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
78 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
79 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
80 | |||
81 | /* Defines for Nvidia HDA support */ | ||
82 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
83 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
84 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
85 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
86 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
87 | |||
88 | /* Defines for Intel SCH HDA snoop control */ | ||
89 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
90 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
91 | |||
92 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
93 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
94 | /* Define VIA HD Audio Device ID*/ | ||
95 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
96 | |||
97 | /* max number of SDs */ | ||
98 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
99 | #define ICH6_NUM_CAPTURE 4 | ||
100 | #define ICH6_NUM_PLAYBACK 4 | ||
101 | |||
102 | /* ULI has 6 playback and 5 capture */ | ||
103 | #define ULI_NUM_CAPTURE 5 | ||
104 | #define ULI_NUM_PLAYBACK 6 | ||
105 | |||
106 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
107 | #define ATIHDMI_NUM_CAPTURE 0 | ||
108 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
109 | |||
110 | /* TERA has 4 playback and 3 capture */ | ||
111 | #define TERA_NUM_CAPTURE 3 | ||
112 | #define TERA_NUM_PLAYBACK 4 | ||
113 | |||
69 | 114 | ||
70 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 115 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
71 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 116 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -227,7 +272,7 @@ enum { | |||
227 | /* quirks for Intel PCH */ | 272 | /* quirks for Intel PCH */ |
228 | #define AZX_DCAPS_INTEL_PCH_NOPM \ | 273 | #define AZX_DCAPS_INTEL_PCH_NOPM \ |
229 | (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ | 274 | (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ |
230 | AZX_DCAPS_COUNT_LPIB_DELAY) | 275 | AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_REVERSE_ASSIGN) |
231 | 276 | ||
232 | #define AZX_DCAPS_INTEL_PCH \ | 277 | #define AZX_DCAPS_INTEL_PCH \ |
233 | (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) | 278 | (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) |
@@ -290,8 +335,28 @@ static char *driver_short_names[] = { | |||
290 | 335 | ||
291 | struct hda_intel { | 336 | struct hda_intel { |
292 | struct azx chip; | 337 | struct azx chip; |
293 | }; | ||
294 | 338 | ||
339 | /* for pending irqs */ | ||
340 | struct work_struct irq_pending_work; | ||
341 | |||
342 | /* sync probing */ | ||
343 | struct completion probe_wait; | ||
344 | struct work_struct probe_work; | ||
345 | |||
346 | /* card list (for power_save trigger) */ | ||
347 | struct list_head list; | ||
348 | |||
349 | /* extra flags */ | ||
350 | unsigned int irq_pending_warned:1; | ||
351 | |||
352 | /* VGA-switcheroo setup */ | ||
353 | unsigned int use_vga_switcheroo:1; | ||
354 | unsigned int vga_switcheroo_registered:1; | ||
355 | unsigned int init_failed:1; /* delayed init failed */ | ||
356 | |||
357 | /* secondary power domain for hdmi audio under vga device */ | ||
358 | struct dev_pm_domain hdmi_pm_domain; | ||
359 | }; | ||
295 | 360 | ||
296 | #ifdef CONFIG_X86 | 361 | #ifdef CONFIG_X86 |
297 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) | 362 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) |
@@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip) | |||
373 | */ | 438 | */ |
374 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { | 439 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { |
375 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); | 440 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); |
376 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | 441 | update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0); |
377 | } | 442 | } |
378 | 443 | ||
379 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, | 444 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, |
@@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip) | |||
421 | } | 486 | } |
422 | } | 487 | } |
423 | 488 | ||
489 | /* calculate runtime delay from LPIB */ | ||
490 | static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, | ||
491 | unsigned int pos) | ||
492 | { | ||
493 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
494 | int stream = substream->stream; | ||
495 | unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev); | ||
496 | int delay; | ||
497 | |||
498 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
499 | delay = pos - lpib_pos; | ||
500 | else | ||
501 | delay = lpib_pos - pos; | ||
502 | if (delay < 0) { | ||
503 | if (delay >= azx_dev->delay_negative_threshold) | ||
504 | delay = 0; | ||
505 | else | ||
506 | delay += azx_dev->bufsize; | ||
507 | } | ||
508 | |||
509 | if (delay >= azx_dev->period_bytes) { | ||
510 | dev_info(chip->card->dev, | ||
511 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
512 | delay, azx_dev->period_bytes); | ||
513 | delay = 0; | ||
514 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
515 | chip->get_delay[stream] = NULL; | ||
516 | } | ||
517 | |||
518 | return bytes_to_frames(substream->runtime, delay); | ||
519 | } | ||
520 | |||
424 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); | 521 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); |
425 | 522 | ||
426 | /* called from IRQ */ | 523 | /* called from IRQ */ |
427 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | 524 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) |
428 | { | 525 | { |
526 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
429 | int ok; | 527 | int ok; |
430 | 528 | ||
431 | ok = azx_position_ok(chip, azx_dev); | 529 | ok = azx_position_ok(chip, azx_dev); |
@@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
435 | } else if (ok == 0 && chip->bus && chip->bus->workq) { | 533 | } else if (ok == 0 && chip->bus && chip->bus->workq) { |
436 | /* bogus IRQ, process it later */ | 534 | /* bogus IRQ, process it later */ |
437 | azx_dev->irq_pending = 1; | 535 | azx_dev->irq_pending = 1; |
438 | queue_work(chip->bus->workq, &chip->irq_pending_work); | 536 | queue_work(chip->bus->workq, &hda->irq_pending_work); |
439 | } | 537 | } |
440 | return 0; | 538 | return 0; |
441 | } | 539 | } |
@@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
451 | */ | 549 | */ |
452 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | 550 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) |
453 | { | 551 | { |
552 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
553 | int stream = substream->stream; | ||
454 | u32 wallclk; | 554 | u32 wallclk; |
455 | unsigned int pos; | 555 | unsigned int pos; |
456 | 556 | ||
@@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
458 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) | 558 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) |
459 | return -1; /* bogus (too early) interrupt */ | 559 | return -1; /* bogus (too early) interrupt */ |
460 | 560 | ||
461 | pos = azx_get_position(chip, azx_dev, true); | 561 | if (chip->get_position[stream]) |
562 | pos = chip->get_position[stream](chip, azx_dev); | ||
563 | else { /* use the position buffer as default */ | ||
564 | pos = azx_get_pos_posbuf(chip, azx_dev); | ||
565 | if (!pos || pos == (u32)-1) { | ||
566 | dev_info(chip->card->dev, | ||
567 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
568 | chip->get_position[stream] = azx_get_pos_lpib; | ||
569 | pos = azx_get_pos_lpib(chip, azx_dev); | ||
570 | chip->get_delay[stream] = NULL; | ||
571 | } else { | ||
572 | chip->get_position[stream] = azx_get_pos_posbuf; | ||
573 | if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY) | ||
574 | chip->get_delay[stream] = azx_get_delay_from_lpib; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | if (pos >= azx_dev->bufsize) | ||
579 | pos = 0; | ||
462 | 580 | ||
463 | if (WARN_ONCE(!azx_dev->period_bytes, | 581 | if (WARN_ONCE(!azx_dev->period_bytes, |
464 | "hda-intel: zero azx_dev->period_bytes")) | 582 | "hda-intel: zero azx_dev->period_bytes")) |
@@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
476 | */ | 594 | */ |
477 | static void azx_irq_pending_work(struct work_struct *work) | 595 | static void azx_irq_pending_work(struct work_struct *work) |
478 | { | 596 | { |
479 | struct azx *chip = container_of(work, struct azx, irq_pending_work); | 597 | struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work); |
598 | struct azx *chip = &hda->chip; | ||
480 | int i, pending, ok; | 599 | int i, pending, ok; |
481 | 600 | ||
482 | if (!chip->irq_pending_warned) { | 601 | if (!hda->irq_pending_warned) { |
483 | dev_info(chip->card->dev, | 602 | dev_info(chip->card->dev, |
484 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", | 603 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", |
485 | chip->card->number); | 604 | chip->card->number); |
486 | chip->irq_pending_warned = 1; | 605 | hda->irq_pending_warned = 1; |
487 | } | 606 | } |
488 | 607 | ||
489 | for (;;) { | 608 | for (;;) { |
@@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
541 | return 0; | 660 | return 0; |
542 | } | 661 | } |
543 | 662 | ||
663 | /* get the current DMA position with correction on VIA chips */ | ||
664 | static unsigned int azx_via_get_position(struct azx *chip, | ||
665 | struct azx_dev *azx_dev) | ||
666 | { | ||
667 | unsigned int link_pos, mini_pos, bound_pos; | ||
668 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | ||
669 | unsigned int fifo_size; | ||
670 | |||
671 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
672 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
673 | /* Playback, no problem using link position */ | ||
674 | return link_pos; | ||
675 | } | ||
676 | |||
677 | /* Capture */ | ||
678 | /* For new chipset, | ||
679 | * use mod to get the DMA position just like old chipset | ||
680 | */ | ||
681 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
682 | mod_dma_pos %= azx_dev->period_bytes; | ||
683 | |||
684 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
685 | * Get from base address + offset. | ||
686 | */ | ||
687 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
688 | |||
689 | if (azx_dev->insufficient) { | ||
690 | /* Link position never gather than FIFO size */ | ||
691 | if (link_pos <= fifo_size) | ||
692 | return 0; | ||
693 | |||
694 | azx_dev->insufficient = 0; | ||
695 | } | ||
696 | |||
697 | if (link_pos <= fifo_size) | ||
698 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
699 | else | ||
700 | mini_pos = link_pos - fifo_size; | ||
701 | |||
702 | /* Find nearest previous boudary */ | ||
703 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
704 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
705 | if (mod_link_pos >= fifo_size) | ||
706 | bound_pos = link_pos - mod_link_pos; | ||
707 | else if (mod_dma_pos >= mod_mini_pos) | ||
708 | bound_pos = mini_pos - mod_mini_pos; | ||
709 | else { | ||
710 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
711 | if (bound_pos >= azx_dev->bufsize) | ||
712 | bound_pos = 0; | ||
713 | } | ||
714 | |||
715 | /* Calculate real DMA position we want */ | ||
716 | return bound_pos + mod_dma_pos; | ||
717 | } | ||
718 | |||
544 | #ifdef CONFIG_PM | 719 | #ifdef CONFIG_PM |
545 | static DEFINE_MUTEX(card_list_lock); | 720 | static DEFINE_MUTEX(card_list_lock); |
546 | static LIST_HEAD(card_list); | 721 | static LIST_HEAD(card_list); |
547 | 722 | ||
548 | static void azx_add_card_list(struct azx *chip) | 723 | static void azx_add_card_list(struct azx *chip) |
549 | { | 724 | { |
725 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
550 | mutex_lock(&card_list_lock); | 726 | mutex_lock(&card_list_lock); |
551 | list_add(&chip->list, &card_list); | 727 | list_add(&hda->list, &card_list); |
552 | mutex_unlock(&card_list_lock); | 728 | mutex_unlock(&card_list_lock); |
553 | } | 729 | } |
554 | 730 | ||
555 | static void azx_del_card_list(struct azx *chip) | 731 | static void azx_del_card_list(struct azx *chip) |
556 | { | 732 | { |
733 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
557 | mutex_lock(&card_list_lock); | 734 | mutex_lock(&card_list_lock); |
558 | list_del_init(&chip->list); | 735 | list_del_init(&hda->list); |
559 | mutex_unlock(&card_list_lock); | 736 | mutex_unlock(&card_list_lock); |
560 | } | 737 | } |
561 | 738 | ||
562 | /* trigger power-save check at writing parameter */ | 739 | /* trigger power-save check at writing parameter */ |
563 | static int param_set_xint(const char *val, const struct kernel_param *kp) | 740 | static int param_set_xint(const char *val, const struct kernel_param *kp) |
564 | { | 741 | { |
742 | struct hda_intel *hda; | ||
565 | struct azx *chip; | 743 | struct azx *chip; |
566 | struct hda_codec *c; | 744 | struct hda_codec *c; |
567 | int prev = power_save; | 745 | int prev = power_save; |
@@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
571 | return ret; | 749 | return ret; |
572 | 750 | ||
573 | mutex_lock(&card_list_lock); | 751 | mutex_lock(&card_list_lock); |
574 | list_for_each_entry(chip, &card_list, list) { | 752 | list_for_each_entry(hda, &card_list, list) { |
753 | chip = &hda->chip; | ||
575 | if (!chip->bus || chip->disabled) | 754 | if (!chip->bus || chip->disabled) |
576 | continue; | 755 | continue; |
577 | list_for_each_entry(c, &chip->bus->codec_list, list) | 756 | list_for_each_entry(c, &chip->bus->codec_list, list) |
@@ -593,10 +772,16 @@ static int azx_suspend(struct device *dev) | |||
593 | { | 772 | { |
594 | struct pci_dev *pci = to_pci_dev(dev); | 773 | struct pci_dev *pci = to_pci_dev(dev); |
595 | struct snd_card *card = dev_get_drvdata(dev); | 774 | struct snd_card *card = dev_get_drvdata(dev); |
596 | struct azx *chip = card->private_data; | 775 | struct azx *chip; |
776 | struct hda_intel *hda; | ||
597 | struct azx_pcm *p; | 777 | struct azx_pcm *p; |
598 | 778 | ||
599 | if (chip->disabled) | 779 | if (!card) |
780 | return 0; | ||
781 | |||
782 | chip = card->private_data; | ||
783 | hda = container_of(chip, struct hda_intel, chip); | ||
784 | if (chip->disabled || hda->init_failed) | ||
600 | return 0; | 785 | return 0; |
601 | 786 | ||
602 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 787 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -626,9 +811,15 @@ static int azx_resume(struct device *dev) | |||
626 | { | 811 | { |
627 | struct pci_dev *pci = to_pci_dev(dev); | 812 | struct pci_dev *pci = to_pci_dev(dev); |
628 | struct snd_card *card = dev_get_drvdata(dev); | 813 | struct snd_card *card = dev_get_drvdata(dev); |
629 | struct azx *chip = card->private_data; | 814 | struct azx *chip; |
815 | struct hda_intel *hda; | ||
630 | 816 | ||
631 | if (chip->disabled) | 817 | if (!card) |
818 | return 0; | ||
819 | |||
820 | chip = card->private_data; | ||
821 | hda = container_of(chip, struct hda_intel, chip); | ||
822 | if (chip->disabled || hda->init_failed) | ||
632 | return 0; | 823 | return 0; |
633 | 824 | ||
634 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 825 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
@@ -663,9 +854,15 @@ static int azx_resume(struct device *dev) | |||
663 | static int azx_runtime_suspend(struct device *dev) | 854 | static int azx_runtime_suspend(struct device *dev) |
664 | { | 855 | { |
665 | struct snd_card *card = dev_get_drvdata(dev); | 856 | struct snd_card *card = dev_get_drvdata(dev); |
666 | struct azx *chip = card->private_data; | 857 | struct azx *chip; |
858 | struct hda_intel *hda; | ||
667 | 859 | ||
668 | if (chip->disabled) | 860 | if (!card) |
861 | return 0; | ||
862 | |||
863 | chip = card->private_data; | ||
864 | hda = container_of(chip, struct hda_intel, chip); | ||
865 | if (chip->disabled || hda->init_failed) | ||
669 | return 0; | 866 | return 0; |
670 | 867 | ||
671 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) | 868 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) |
@@ -687,12 +884,18 @@ static int azx_runtime_suspend(struct device *dev) | |||
687 | static int azx_runtime_resume(struct device *dev) | 884 | static int azx_runtime_resume(struct device *dev) |
688 | { | 885 | { |
689 | struct snd_card *card = dev_get_drvdata(dev); | 886 | struct snd_card *card = dev_get_drvdata(dev); |
690 | struct azx *chip = card->private_data; | 887 | struct azx *chip; |
888 | struct hda_intel *hda; | ||
691 | struct hda_bus *bus; | 889 | struct hda_bus *bus; |
692 | struct hda_codec *codec; | 890 | struct hda_codec *codec; |
693 | int status; | 891 | int status; |
694 | 892 | ||
695 | if (chip->disabled) | 893 | if (!card) |
894 | return 0; | ||
895 | |||
896 | chip = card->private_data; | ||
897 | hda = container_of(chip, struct hda_intel, chip); | ||
898 | if (chip->disabled || hda->init_failed) | ||
696 | return 0; | 899 | return 0; |
697 | 900 | ||
698 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) | 901 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) |
@@ -727,9 +930,15 @@ static int azx_runtime_resume(struct device *dev) | |||
727 | static int azx_runtime_idle(struct device *dev) | 930 | static int azx_runtime_idle(struct device *dev) |
728 | { | 931 | { |
729 | struct snd_card *card = dev_get_drvdata(dev); | 932 | struct snd_card *card = dev_get_drvdata(dev); |
730 | struct azx *chip = card->private_data; | 933 | struct azx *chip; |
934 | struct hda_intel *hda; | ||
731 | 935 | ||
732 | if (chip->disabled) | 936 | if (!card) |
937 | return 0; | ||
938 | |||
939 | chip = card->private_data; | ||
940 | hda = container_of(chip, struct hda_intel, chip); | ||
941 | if (chip->disabled || hda->init_failed) | ||
733 | return 0; | 942 | return 0; |
734 | 943 | ||
735 | if (!power_save_controller || | 944 | if (!power_save_controller || |
@@ -753,29 +962,6 @@ static const struct dev_pm_ops azx_pm = { | |||
753 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
754 | 963 | ||
755 | 964 | ||
756 | /* | ||
757 | * reboot notifier for hang-up problem at power-down | ||
758 | */ | ||
759 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
760 | { | ||
761 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
762 | snd_hda_bus_reboot_notify(chip->bus); | ||
763 | azx_stop_chip(chip); | ||
764 | return NOTIFY_OK; | ||
765 | } | ||
766 | |||
767 | static void azx_notifier_register(struct azx *chip) | ||
768 | { | ||
769 | chip->reboot_notifier.notifier_call = azx_halt; | ||
770 | register_reboot_notifier(&chip->reboot_notifier); | ||
771 | } | ||
772 | |||
773 | static void azx_notifier_unregister(struct azx *chip) | ||
774 | { | ||
775 | if (chip->reboot_notifier.notifier_call) | ||
776 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
777 | } | ||
778 | |||
779 | static int azx_probe_continue(struct azx *chip); | 965 | static int azx_probe_continue(struct azx *chip); |
780 | 966 | ||
781 | #ifdef SUPPORT_VGA_SWITCHEROO | 967 | #ifdef SUPPORT_VGA_SWITCHEROO |
@@ -786,10 +972,11 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
786 | { | 972 | { |
787 | struct snd_card *card = pci_get_drvdata(pci); | 973 | struct snd_card *card = pci_get_drvdata(pci); |
788 | struct azx *chip = card->private_data; | 974 | struct azx *chip = card->private_data; |
975 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
789 | bool disabled; | 976 | bool disabled; |
790 | 977 | ||
791 | wait_for_completion(&chip->probe_wait); | 978 | wait_for_completion(&hda->probe_wait); |
792 | if (chip->init_failed) | 979 | if (hda->init_failed) |
793 | return; | 980 | return; |
794 | 981 | ||
795 | disabled = (state == VGA_SWITCHEROO_OFF); | 982 | disabled = (state == VGA_SWITCHEROO_OFF); |
@@ -803,7 +990,7 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
803 | "Start delayed initialization\n"); | 990 | "Start delayed initialization\n"); |
804 | if (azx_probe_continue(chip) < 0) { | 991 | if (azx_probe_continue(chip) < 0) { |
805 | dev_err(chip->card->dev, "initialization error\n"); | 992 | dev_err(chip->card->dev, "initialization error\n"); |
806 | chip->init_failed = true; | 993 | hda->init_failed = true; |
807 | } | 994 | } |
808 | } | 995 | } |
809 | } else { | 996 | } else { |
@@ -833,9 +1020,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
833 | { | 1020 | { |
834 | struct snd_card *card = pci_get_drvdata(pci); | 1021 | struct snd_card *card = pci_get_drvdata(pci); |
835 | struct azx *chip = card->private_data; | 1022 | struct azx *chip = card->private_data; |
1023 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
836 | 1024 | ||
837 | wait_for_completion(&chip->probe_wait); | 1025 | wait_for_completion(&hda->probe_wait); |
838 | if (chip->init_failed) | 1026 | if (hda->init_failed) |
839 | return false; | 1027 | return false; |
840 | if (chip->disabled || !chip->bus) | 1028 | if (chip->disabled || !chip->bus) |
841 | return true; | 1029 | return true; |
@@ -847,11 +1035,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
847 | 1035 | ||
848 | static void init_vga_switcheroo(struct azx *chip) | 1036 | static void init_vga_switcheroo(struct azx *chip) |
849 | { | 1037 | { |
1038 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
850 | struct pci_dev *p = get_bound_vga(chip->pci); | 1039 | struct pci_dev *p = get_bound_vga(chip->pci); |
851 | if (p) { | 1040 | if (p) { |
852 | dev_info(chip->card->dev, | 1041 | dev_info(chip->card->dev, |
853 | "Handle VGA-switcheroo audio client\n"); | 1042 | "Handle VGA-switcheroo audio client\n"); |
854 | chip->use_vga_switcheroo = 1; | 1043 | hda->use_vga_switcheroo = 1; |
855 | pci_dev_put(p); | 1044 | pci_dev_put(p); |
856 | } | 1045 | } |
857 | } | 1046 | } |
@@ -863,9 +1052,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { | |||
863 | 1052 | ||
864 | static int register_vga_switcheroo(struct azx *chip) | 1053 | static int register_vga_switcheroo(struct azx *chip) |
865 | { | 1054 | { |
1055 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
866 | int err; | 1056 | int err; |
867 | 1057 | ||
868 | if (!chip->use_vga_switcheroo) | 1058 | if (!hda->use_vga_switcheroo) |
869 | return 0; | 1059 | return 0; |
870 | /* FIXME: currently only handling DIS controller | 1060 | /* FIXME: currently only handling DIS controller |
871 | * is there any machine with two switchable HDMI audio controllers? | 1061 | * is there any machine with two switchable HDMI audio controllers? |
@@ -875,11 +1065,11 @@ static int register_vga_switcheroo(struct azx *chip) | |||
875 | chip->bus != NULL); | 1065 | chip->bus != NULL); |
876 | if (err < 0) | 1066 | if (err < 0) |
877 | return err; | 1067 | return err; |
878 | chip->vga_switcheroo_registered = 1; | 1068 | hda->vga_switcheroo_registered = 1; |
879 | 1069 | ||
880 | /* register as an optimus hdmi audio power domain */ | 1070 | /* register as an optimus hdmi audio power domain */ |
881 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, | 1071 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, |
882 | &chip->hdmi_pm_domain); | 1072 | &hda->hdmi_pm_domain); |
883 | return 0; | 1073 | return 0; |
884 | } | 1074 | } |
885 | #else | 1075 | #else |
@@ -895,7 +1085,6 @@ static int azx_free(struct azx *chip) | |||
895 | { | 1085 | { |
896 | struct pci_dev *pci = chip->pci; | 1086 | struct pci_dev *pci = chip->pci; |
897 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 1087 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
898 | |||
899 | int i; | 1088 | int i; |
900 | 1089 | ||
901 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) | 1090 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) |
@@ -906,13 +1095,13 @@ static int azx_free(struct azx *chip) | |||
906 | 1095 | ||
907 | azx_notifier_unregister(chip); | 1096 | azx_notifier_unregister(chip); |
908 | 1097 | ||
909 | chip->init_failed = 1; /* to be sure */ | 1098 | hda->init_failed = 1; /* to be sure */ |
910 | complete_all(&chip->probe_wait); | 1099 | complete_all(&hda->probe_wait); |
911 | 1100 | ||
912 | if (use_vga_switcheroo(chip)) { | 1101 | if (use_vga_switcheroo(hda)) { |
913 | if (chip->disabled && chip->bus) | 1102 | if (chip->disabled && chip->bus) |
914 | snd_hda_unlock_devices(chip->bus); | 1103 | snd_hda_unlock_devices(chip->bus); |
915 | if (chip->vga_switcheroo_registered) | 1104 | if (hda->vga_switcheroo_registered) |
916 | vga_switcheroo_unregister_client(chip->pci); | 1105 | vga_switcheroo_unregister_client(chip->pci); |
917 | } | 1106 | } |
918 | 1107 | ||
@@ -1048,6 +1237,30 @@ static int check_position_fix(struct azx *chip, int fix) | |||
1048 | return POS_FIX_AUTO; | 1237 | return POS_FIX_AUTO; |
1049 | } | 1238 | } |
1050 | 1239 | ||
1240 | static void assign_position_fix(struct azx *chip, int fix) | ||
1241 | { | ||
1242 | static azx_get_pos_callback_t callbacks[] = { | ||
1243 | [POS_FIX_AUTO] = NULL, | ||
1244 | [POS_FIX_LPIB] = azx_get_pos_lpib, | ||
1245 | [POS_FIX_POSBUF] = azx_get_pos_posbuf, | ||
1246 | [POS_FIX_VIACOMBO] = azx_via_get_position, | ||
1247 | [POS_FIX_COMBO] = azx_get_pos_lpib, | ||
1248 | }; | ||
1249 | |||
1250 | chip->get_position[0] = chip->get_position[1] = callbacks[fix]; | ||
1251 | |||
1252 | /* combo mode uses LPIB only for playback */ | ||
1253 | if (fix == POS_FIX_COMBO) | ||
1254 | chip->get_position[1] = NULL; | ||
1255 | |||
1256 | if (fix == POS_FIX_POSBUF && | ||
1257 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
1258 | chip->get_delay[0] = chip->get_delay[1] = | ||
1259 | azx_get_delay_from_lpib; | ||
1260 | } | ||
1261 | |||
1262 | } | ||
1263 | |||
1051 | /* | 1264 | /* |
1052 | * black-lists for probe_mask | 1265 | * black-lists for probe_mask |
1053 | */ | 1266 | */ |
@@ -1173,7 +1386,8 @@ static void azx_check_snoop_available(struct azx *chip) | |||
1173 | 1386 | ||
1174 | static void azx_probe_work(struct work_struct *work) | 1387 | static void azx_probe_work(struct work_struct *work) |
1175 | { | 1388 | { |
1176 | azx_probe_continue(container_of(work, struct azx, probe_work)); | 1389 | struct hda_intel *hda = container_of(work, struct hda_intel, probe_work); |
1390 | azx_probe_continue(&hda->chip); | ||
1177 | } | 1391 | } |
1178 | 1392 | ||
1179 | /* | 1393 | /* |
@@ -1216,19 +1430,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1216 | check_msi(chip); | 1430 | check_msi(chip); |
1217 | chip->dev_index = dev; | 1431 | chip->dev_index = dev; |
1218 | chip->jackpoll_ms = jackpoll_ms; | 1432 | chip->jackpoll_ms = jackpoll_ms; |
1219 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | ||
1220 | INIT_LIST_HEAD(&chip->pcm_list); | 1433 | INIT_LIST_HEAD(&chip->pcm_list); |
1221 | INIT_LIST_HEAD(&chip->list); | 1434 | INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work); |
1435 | INIT_LIST_HEAD(&hda->list); | ||
1222 | init_vga_switcheroo(chip); | 1436 | init_vga_switcheroo(chip); |
1223 | init_completion(&chip->probe_wait); | 1437 | init_completion(&hda->probe_wait); |
1224 | 1438 | ||
1225 | chip->position_fix[0] = chip->position_fix[1] = | 1439 | assign_position_fix(chip, check_position_fix(chip, position_fix[dev])); |
1226 | check_position_fix(chip, position_fix[dev]); | ||
1227 | /* combo mode uses LPIB for playback */ | ||
1228 | if (chip->position_fix[0] == POS_FIX_COMBO) { | ||
1229 | chip->position_fix[0] = POS_FIX_LPIB; | ||
1230 | chip->position_fix[1] = POS_FIX_AUTO; | ||
1231 | } | ||
1232 | 1440 | ||
1233 | check_probe_mask(chip, dev); | 1441 | check_probe_mask(chip, dev); |
1234 | 1442 | ||
@@ -1257,7 +1465,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1257 | } | 1465 | } |
1258 | 1466 | ||
1259 | /* continue probing in work context as may trigger request module */ | 1467 | /* continue probing in work context as may trigger request module */ |
1260 | INIT_WORK(&chip->probe_work, azx_probe_work); | 1468 | INIT_WORK(&hda->probe_work, azx_probe_work); |
1261 | 1469 | ||
1262 | *rchip = chip; | 1470 | *rchip = chip; |
1263 | 1471 | ||
@@ -1315,7 +1523,7 @@ static int azx_first_init(struct azx *chip) | |||
1315 | NULL); | 1523 | NULL); |
1316 | if (p_smbus) { | 1524 | if (p_smbus) { |
1317 | if (p_smbus->revision < 0x30) | 1525 | if (p_smbus->revision < 0x30) |
1318 | gcap &= ~ICH6_GCAP_64OK; | 1526 | gcap &= ~AZX_GCAP_64OK; |
1319 | pci_dev_put(p_smbus); | 1527 | pci_dev_put(p_smbus); |
1320 | } | 1528 | } |
1321 | } | 1529 | } |
@@ -1323,7 +1531,7 @@ static int azx_first_init(struct azx *chip) | |||
1323 | /* disable 64bit DMA address on some devices */ | 1531 | /* disable 64bit DMA address on some devices */ |
1324 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { | 1532 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { |
1325 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); | 1533 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); |
1326 | gcap &= ~ICH6_GCAP_64OK; | 1534 | gcap &= ~AZX_GCAP_64OK; |
1327 | } | 1535 | } |
1328 | 1536 | ||
1329 | /* disable buffer size rounding to 128-byte multiples if supported */ | 1537 | /* disable buffer size rounding to 128-byte multiples if supported */ |
@@ -1339,7 +1547,7 @@ static int azx_first_init(struct azx *chip) | |||
1339 | } | 1547 | } |
1340 | 1548 | ||
1341 | /* allow 64bit DMA address if supported by H/W */ | 1549 | /* allow 64bit DMA address if supported by H/W */ |
1342 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) | 1550 | if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) |
1343 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); | 1551 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); |
1344 | else { | 1552 | else { |
1345 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); | 1553 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); |
@@ -1583,6 +1791,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1583 | { | 1791 | { |
1584 | static int dev; | 1792 | static int dev; |
1585 | struct snd_card *card; | 1793 | struct snd_card *card; |
1794 | struct hda_intel *hda; | ||
1586 | struct azx *chip; | 1795 | struct azx *chip; |
1587 | bool schedule_probe; | 1796 | bool schedule_probe; |
1588 | int err; | 1797 | int err; |
@@ -1606,6 +1815,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1606 | if (err < 0) | 1815 | if (err < 0) |
1607 | goto out_free; | 1816 | goto out_free; |
1608 | card->private_data = chip; | 1817 | card->private_data = chip; |
1818 | hda = container_of(chip, struct hda_intel, chip); | ||
1609 | 1819 | ||
1610 | pci_set_drvdata(pci, card); | 1820 | pci_set_drvdata(pci, card); |
1611 | 1821 | ||
@@ -1642,11 +1852,11 @@ static int azx_probe(struct pci_dev *pci, | |||
1642 | #endif | 1852 | #endif |
1643 | 1853 | ||
1644 | if (schedule_probe) | 1854 | if (schedule_probe) |
1645 | schedule_work(&chip->probe_work); | 1855 | schedule_work(&hda->probe_work); |
1646 | 1856 | ||
1647 | dev++; | 1857 | dev++; |
1648 | if (chip->disabled) | 1858 | if (chip->disabled) |
1649 | complete_all(&chip->probe_wait); | 1859 | complete_all(&hda->probe_wait); |
1650 | return 0; | 1860 | return 0; |
1651 | 1861 | ||
1652 | out_free: | 1862 | out_free: |
@@ -1662,6 +1872,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { | |||
1662 | 1872 | ||
1663 | static int azx_probe_continue(struct azx *chip) | 1873 | static int azx_probe_continue(struct azx *chip) |
1664 | { | 1874 | { |
1875 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
1665 | struct pci_dev *pci = chip->pci; | 1876 | struct pci_dev *pci = chip->pci; |
1666 | int dev = chip->dev_index; | 1877 | int dev = chip->dev_index; |
1667 | int err; | 1878 | int err; |
@@ -1735,13 +1946,13 @@ static int azx_probe_continue(struct azx *chip) | |||
1735 | power_down_all_codecs(chip); | 1946 | power_down_all_codecs(chip); |
1736 | azx_notifier_register(chip); | 1947 | azx_notifier_register(chip); |
1737 | azx_add_card_list(chip); | 1948 | azx_add_card_list(chip); |
1738 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo) | 1949 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo) |
1739 | pm_runtime_put_noidle(&pci->dev); | 1950 | pm_runtime_put_noidle(&pci->dev); |
1740 | 1951 | ||
1741 | out_free: | 1952 | out_free: |
1742 | if (err < 0) | 1953 | if (err < 0) |
1743 | chip->init_failed = 1; | 1954 | hda->init_failed = 1; |
1744 | complete_all(&chip->probe_wait); | 1955 | complete_all(&hda->probe_wait); |
1745 | return err; | 1956 | return err; |
1746 | } | 1957 | } |
1747 | 1958 | ||
@@ -1806,6 +2017,9 @@ static const struct pci_device_id azx_ids[] = { | |||
1806 | /* BayTrail */ | 2017 | /* BayTrail */ |
1807 | { PCI_DEVICE(0x8086, 0x0f04), | 2018 | { PCI_DEVICE(0x8086, 0x0f04), |
1808 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 2019 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
2020 | /* Braswell */ | ||
2021 | { PCI_DEVICE(0x8086, 0x2284), | ||
2022 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | ||
1809 | /* ICH */ | 2023 | /* ICH */ |
1810 | { PCI_DEVICE(0x8086, 0x2668), | 2024 | { PCI_DEVICE(0x8086, 0x2668), |
1811 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | | 2025 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 4e2d4863daa1..364bb413e02a 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec, | |||
268 | const struct hda_input_mux *imux, | 268 | const struct hda_input_mux *imux, |
269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
270 | unsigned int *cur_val); | 270 | unsigned int *cur_val); |
271 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 271 | int snd_hda_add_imux_item(struct hda_codec *codec, |
272 | struct hda_input_mux *imux, const char *label, | ||
272 | int index, int *type_index_ret); | 273 | int index, int *type_index_ret); |
273 | 274 | ||
274 | /* | 275 | /* |
@@ -437,6 +438,8 @@ struct snd_hda_pin_quirk { | |||
437 | 438 | ||
438 | #endif | 439 | #endif |
439 | 440 | ||
441 | #define HDA_FIXUP_ID_NOT_SET -1 | ||
442 | #define HDA_FIXUP_ID_NO_FIXUP -2 | ||
440 | 443 | ||
441 | /* fixup types */ | 444 | /* fixup types */ |
442 | enum { | 445 | enum { |
@@ -773,9 +776,9 @@ struct hdmi_eld { | |||
773 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); | 776 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); |
774 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, | 777 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, |
775 | unsigned char *buf, int *eld_size); | 778 | unsigned char *buf, int *eld_size); |
776 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 779 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
777 | const unsigned char *buf, int size); | 780 | const unsigned char *buf, int size); |
778 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e); | 781 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e); |
779 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, | 782 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, |
780 | struct hda_pcm_stream *hinfo); | 783 | struct hda_pcm_stream *hinfo); |
781 | 784 | ||
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index 4a7cb01fa912..949cd437eeb2 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h | |||
@@ -22,107 +22,87 @@ | |||
22 | /* | 22 | /* |
23 | * registers | 23 | * registers |
24 | */ | 24 | */ |
25 | #define ICH6_REG_GCAP 0x00 | 25 | #define AZX_REG_GCAP 0x00 |
26 | #define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ | 26 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ |
27 | #define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | 27 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ |
28 | #define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | 28 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ |
29 | #define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ | 29 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ |
30 | #define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ | 30 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ |
31 | #define ICH6_REG_VMIN 0x02 | 31 | #define AZX_REG_VMIN 0x02 |
32 | #define ICH6_REG_VMAJ 0x03 | 32 | #define AZX_REG_VMAJ 0x03 |
33 | #define ICH6_REG_OUTPAY 0x04 | 33 | #define AZX_REG_OUTPAY 0x04 |
34 | #define ICH6_REG_INPAY 0x06 | 34 | #define AZX_REG_INPAY 0x06 |
35 | #define ICH6_REG_GCTL 0x08 | 35 | #define AZX_REG_GCTL 0x08 |
36 | #define ICH6_GCTL_RESET (1 << 0) /* controller reset */ | 36 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ |
37 | #define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ | 37 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ |
38 | #define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | 38 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ |
39 | #define ICH6_REG_WAKEEN 0x0c | 39 | #define AZX_REG_WAKEEN 0x0c |
40 | #define ICH6_REG_STATESTS 0x0e | 40 | #define AZX_REG_STATESTS 0x0e |
41 | #define ICH6_REG_GSTS 0x10 | 41 | #define AZX_REG_GSTS 0x10 |
42 | #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ | 42 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ |
43 | #define ICH6_REG_INTCTL 0x20 | 43 | #define AZX_REG_INTCTL 0x20 |
44 | #define ICH6_REG_INTSTS 0x24 | 44 | #define AZX_REG_INTSTS 0x24 |
45 | #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ | 45 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ |
46 | #define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | 46 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ |
47 | #define ICH6_REG_SSYNC 0x38 | 47 | #define AZX_REG_SSYNC 0x38 |
48 | #define ICH6_REG_CORBLBASE 0x40 | 48 | #define AZX_REG_CORBLBASE 0x40 |
49 | #define ICH6_REG_CORBUBASE 0x44 | 49 | #define AZX_REG_CORBUBASE 0x44 |
50 | #define ICH6_REG_CORBWP 0x48 | 50 | #define AZX_REG_CORBWP 0x48 |
51 | #define ICH6_REG_CORBRP 0x4a | 51 | #define AZX_REG_CORBRP 0x4a |
52 | #define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ | 52 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ |
53 | #define ICH6_REG_CORBCTL 0x4c | 53 | #define AZX_REG_CORBCTL 0x4c |
54 | #define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ | 54 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ |
55 | #define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | 55 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ |
56 | #define ICH6_REG_CORBSTS 0x4d | 56 | #define AZX_REG_CORBSTS 0x4d |
57 | #define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ | 57 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ |
58 | #define ICH6_REG_CORBSIZE 0x4e | 58 | #define AZX_REG_CORBSIZE 0x4e |
59 | 59 | ||
60 | #define ICH6_REG_RIRBLBASE 0x50 | 60 | #define AZX_REG_RIRBLBASE 0x50 |
61 | #define ICH6_REG_RIRBUBASE 0x54 | 61 | #define AZX_REG_RIRBUBASE 0x54 |
62 | #define ICH6_REG_RIRBWP 0x58 | 62 | #define AZX_REG_RIRBWP 0x58 |
63 | #define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ | 63 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ |
64 | #define ICH6_REG_RINTCNT 0x5a | 64 | #define AZX_REG_RINTCNT 0x5a |
65 | #define ICH6_REG_RIRBCTL 0x5c | 65 | #define AZX_REG_RIRBCTL 0x5c |
66 | #define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | 66 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ |
67 | #define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | 67 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ |
68 | #define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | 68 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ |
69 | #define ICH6_REG_RIRBSTS 0x5d | 69 | #define AZX_REG_RIRBSTS 0x5d |
70 | #define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ | 70 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ |
71 | #define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | 71 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ |
72 | #define ICH6_REG_RIRBSIZE 0x5e | 72 | #define AZX_REG_RIRBSIZE 0x5e |
73 | 73 | ||
74 | #define ICH6_REG_IC 0x60 | 74 | #define AZX_REG_IC 0x60 |
75 | #define ICH6_REG_IR 0x64 | 75 | #define AZX_REG_IR 0x64 |
76 | #define ICH6_REG_IRS 0x68 | 76 | #define AZX_REG_IRS 0x68 |
77 | #define ICH6_IRS_VALID (1<<1) | 77 | #define AZX_IRS_VALID (1<<1) |
78 | #define ICH6_IRS_BUSY (1<<0) | 78 | #define AZX_IRS_BUSY (1<<0) |
79 | 79 | ||
80 | #define ICH6_REG_DPLBASE 0x70 | 80 | #define AZX_REG_DPLBASE 0x70 |
81 | #define ICH6_REG_DPUBASE 0x74 | 81 | #define AZX_REG_DPUBASE 0x74 |
82 | #define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | 82 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ |
83 | 83 | ||
84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | 85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; |
86 | 86 | ||
87 | /* stream register offsets from stream base */ | 87 | /* stream register offsets from stream base */ |
88 | #define ICH6_REG_SD_CTL 0x00 | 88 | #define AZX_REG_SD_CTL 0x00 |
89 | #define ICH6_REG_SD_STS 0x03 | 89 | #define AZX_REG_SD_STS 0x03 |
90 | #define ICH6_REG_SD_LPIB 0x04 | 90 | #define AZX_REG_SD_LPIB 0x04 |
91 | #define ICH6_REG_SD_CBL 0x08 | 91 | #define AZX_REG_SD_CBL 0x08 |
92 | #define ICH6_REG_SD_LVI 0x0c | 92 | #define AZX_REG_SD_LVI 0x0c |
93 | #define ICH6_REG_SD_FIFOW 0x0e | 93 | #define AZX_REG_SD_FIFOW 0x0e |
94 | #define ICH6_REG_SD_FIFOSIZE 0x10 | 94 | #define AZX_REG_SD_FIFOSIZE 0x10 |
95 | #define ICH6_REG_SD_FORMAT 0x12 | 95 | #define AZX_REG_SD_FORMAT 0x12 |
96 | #define ICH6_REG_SD_BDLPL 0x18 | 96 | #define AZX_REG_SD_BDLPL 0x18 |
97 | #define ICH6_REG_SD_BDLPU 0x1c | 97 | #define AZX_REG_SD_BDLPU 0x1c |
98 | 98 | ||
99 | /* PCI space */ | 99 | /* PCI space */ |
100 | #define ICH6_PCIREG_TCSEL 0x44 | 100 | #define AZX_PCIREG_TCSEL 0x44 |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * other constants | 103 | * other constants |
104 | */ | 104 | */ |
105 | 105 | ||
106 | /* max number of SDs */ | ||
107 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
108 | #define ICH6_NUM_CAPTURE 4 | ||
109 | #define ICH6_NUM_PLAYBACK 4 | ||
110 | |||
111 | /* ULI has 6 playback and 5 capture */ | ||
112 | #define ULI_NUM_CAPTURE 5 | ||
113 | #define ULI_NUM_PLAYBACK 6 | ||
114 | |||
115 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
116 | #define ATIHDMI_NUM_CAPTURE 0 | ||
117 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
118 | |||
119 | /* TERA has 4 playback and 3 capture */ | ||
120 | #define TERA_NUM_CAPTURE 3 | ||
121 | #define TERA_NUM_PLAYBACK 4 | ||
122 | |||
123 | /* this number is statically defined for simplicity */ | ||
124 | #define MAX_AZX_DEV 16 | ||
125 | |||
126 | /* max number of fragments - we may use more if allocating more pages for BDL */ | 106 | /* max number of fragments - we may use more if allocating more pages for BDL */ |
127 | #define BDL_SIZE 4096 | 107 | #define BDL_SIZE 4096 |
128 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | 108 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) |
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
160 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | 140 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ |
161 | 141 | ||
162 | /* INTCTL and INTSTS */ | 142 | /* INTCTL and INTSTS */ |
163 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ | 143 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ |
164 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 144 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
165 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 145 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
166 | 146 | ||
167 | /* below are so far hardcoded - should read registers in future */ | 147 | /* below are so far hardcoded - should read registers in future */ |
168 | #define ICH6_MAX_CORB_ENTRIES 256 | 148 | #define AZX_MAX_CORB_ENTRIES 256 |
169 | #define ICH6_MAX_RIRB_ENTRIES 256 | 149 | #define AZX_MAX_RIRB_ENTRIES 256 |
170 | 150 | ||
171 | /* driver quirks (capabilities) */ | 151 | /* driver quirks (capabilities) */ |
172 | /* bits 0-7 are used for indicating driver type */ | 152 | /* bits 0-7 are used for indicating driver type */ |
@@ -186,40 +166,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
186 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ | 166 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
187 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | 167 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ |
188 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ | 168 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ |
169 | #define AZX_DCAPS_REVERSE_ASSIGN (1 << 24) /* Assign devices in reverse order */ | ||
189 | #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ | 170 | #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ |
190 | #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ | 171 | #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ |
191 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ | 172 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ |
192 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ | 173 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ |
193 | 174 | ||
194 | /* position fix mode */ | ||
195 | enum { | ||
196 | POS_FIX_AUTO, | ||
197 | POS_FIX_LPIB, | ||
198 | POS_FIX_POSBUF, | ||
199 | POS_FIX_VIACOMBO, | ||
200 | POS_FIX_COMBO, | ||
201 | }; | ||
202 | |||
203 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
204 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
205 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
206 | |||
207 | /* Defines for Nvidia HDA support */ | ||
208 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
209 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
210 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
211 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
212 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
213 | |||
214 | /* Defines for Intel SCH HDA snoop control */ | ||
215 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
216 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
217 | |||
218 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
219 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
220 | /* Define VIA HD Audio Device ID*/ | ||
221 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
222 | |||
223 | /* HD Audio class code */ | 175 | /* HD Audio class code */ |
224 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | 176 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 |
225 | 177 | ||
@@ -324,6 +276,9 @@ struct azx_pcm { | |||
324 | struct list_head list; | 276 | struct list_head list; |
325 | }; | 277 | }; |
326 | 278 | ||
279 | typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *); | ||
280 | typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); | ||
281 | |||
327 | struct azx { | 282 | struct azx { |
328 | struct snd_card *card; | 283 | struct snd_card *card; |
329 | struct pci_dev *pci; | 284 | struct pci_dev *pci; |
@@ -342,6 +297,10 @@ struct azx { | |||
342 | /* Register interaction. */ | 297 | /* Register interaction. */ |
343 | const struct hda_controller_ops *ops; | 298 | const struct hda_controller_ops *ops; |
344 | 299 | ||
300 | /* position adjustment callbacks */ | ||
301 | azx_get_pos_callback_t get_position[2]; | ||
302 | azx_get_delay_callback_t get_delay[2]; | ||
303 | |||
345 | /* pci resources */ | 304 | /* pci resources */ |
346 | unsigned long addr; | 305 | unsigned long addr; |
347 | void __iomem *remap_addr; | 306 | void __iomem *remap_addr; |
@@ -350,7 +309,6 @@ struct azx { | |||
350 | /* locks */ | 309 | /* locks */ |
351 | spinlock_t reg_lock; | 310 | spinlock_t reg_lock; |
352 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ | 311 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ |
353 | struct completion probe_wait; | ||
354 | 312 | ||
355 | /* streams (x num_streams) */ | 313 | /* streams (x num_streams) */ |
356 | struct azx_dev *azx_dev; | 314 | struct azx_dev *azx_dev; |
@@ -377,7 +335,6 @@ struct azx { | |||
377 | #endif | 335 | #endif |
378 | 336 | ||
379 | /* flags */ | 337 | /* flags */ |
380 | int position_fix[2]; /* for both playback/capture streams */ | ||
381 | const int *bdl_pos_adj; | 338 | const int *bdl_pos_adj; |
382 | int poll_count; | 339 | int poll_count; |
383 | unsigned int running:1; | 340 | unsigned int running:1; |
@@ -385,46 +342,23 @@ struct azx { | |||
385 | unsigned int single_cmd:1; | 342 | unsigned int single_cmd:1; |
386 | unsigned int polling_mode:1; | 343 | unsigned int polling_mode:1; |
387 | unsigned int msi:1; | 344 | unsigned int msi:1; |
388 | unsigned int irq_pending_warned:1; | ||
389 | unsigned int probing:1; /* codec probing phase */ | 345 | unsigned int probing:1; /* codec probing phase */ |
390 | unsigned int snoop:1; | 346 | unsigned int snoop:1; |
391 | unsigned int align_buffer_size:1; | 347 | unsigned int align_buffer_size:1; |
392 | unsigned int region_requested:1; | 348 | unsigned int region_requested:1; |
393 | |||
394 | /* VGA-switcheroo setup */ | ||
395 | unsigned int use_vga_switcheroo:1; | ||
396 | unsigned int vga_switcheroo_registered:1; | ||
397 | unsigned int init_failed:1; /* delayed init failed */ | ||
398 | unsigned int disabled:1; /* disabled by VGA-switcher */ | 349 | unsigned int disabled:1; /* disabled by VGA-switcher */ |
399 | 350 | ||
400 | /* for debugging */ | 351 | /* for debugging */ |
401 | unsigned int last_cmd[AZX_MAX_CODECS]; | 352 | unsigned int last_cmd[AZX_MAX_CODECS]; |
402 | 353 | ||
403 | /* for pending irqs */ | ||
404 | struct work_struct irq_pending_work; | ||
405 | |||
406 | struct work_struct probe_work; | ||
407 | |||
408 | /* reboot notifier (for mysterious hangup problem at power-down) */ | 354 | /* reboot notifier (for mysterious hangup problem at power-down) */ |
409 | struct notifier_block reboot_notifier; | 355 | struct notifier_block reboot_notifier; |
410 | 356 | ||
411 | /* card list (for power_save trigger) */ | ||
412 | struct list_head list; | ||
413 | |||
414 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 357 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
415 | struct azx_dev saved_azx_dev; | 358 | struct azx_dev saved_azx_dev; |
416 | #endif | 359 | #endif |
417 | |||
418 | /* secondary power domain for hdmi audio under vga device */ | ||
419 | struct dev_pm_domain hdmi_pm_domain; | ||
420 | }; | 360 | }; |
421 | 361 | ||
422 | #ifdef CONFIG_SND_VERBOSE_PRINTK | ||
423 | #define SFX /* nop */ | ||
424 | #else | ||
425 | #define SFX "hda-intel " | ||
426 | #endif | ||
427 | |||
428 | #ifdef CONFIG_X86 | 362 | #ifdef CONFIG_X86 |
429 | #define azx_snoop(chip) ((chip)->snoop) | 363 | #define azx_snoop(chip) ((chip)->snoop) |
430 | #else | 364 | #else |
@@ -436,29 +370,29 @@ struct azx { | |||
436 | */ | 370 | */ |
437 | 371 | ||
438 | #define azx_writel(chip, reg, value) \ | 372 | #define azx_writel(chip, reg, value) \ |
439 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg)) | 373 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)) |
440 | #define azx_readl(chip, reg) \ | 374 | #define azx_readl(chip, reg) \ |
441 | ((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg)) | 375 | ((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)) |
442 | #define azx_writew(chip, reg, value) \ | 376 | #define azx_writew(chip, reg, value) \ |
443 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg)) | 377 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)) |
444 | #define azx_readw(chip, reg) \ | 378 | #define azx_readw(chip, reg) \ |
445 | ((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg)) | 379 | ((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)) |
446 | #define azx_writeb(chip, reg, value) \ | 380 | #define azx_writeb(chip, reg, value) \ |
447 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg)) | 381 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)) |
448 | #define azx_readb(chip, reg) \ | 382 | #define azx_readb(chip, reg) \ |
449 | ((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg)) | 383 | ((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg)) |
450 | 384 | ||
451 | #define azx_sd_writel(chip, dev, reg, value) \ | 385 | #define azx_sd_writel(chip, dev, reg, value) \ |
452 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg)) | 386 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg)) |
453 | #define azx_sd_readl(chip, dev, reg) \ | 387 | #define azx_sd_readl(chip, dev, reg) \ |
454 | ((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg)) | 388 | ((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg)) |
455 | #define azx_sd_writew(chip, dev, reg, value) \ | 389 | #define azx_sd_writew(chip, dev, reg, value) \ |
456 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg)) | 390 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg)) |
457 | #define azx_sd_readw(chip, dev, reg) \ | 391 | #define azx_sd_readw(chip, dev, reg) \ |
458 | ((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg)) | 392 | ((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg)) |
459 | #define azx_sd_writeb(chip, dev, reg, value) \ | 393 | #define azx_sd_writeb(chip, dev, reg, value) \ |
460 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg)) | 394 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg)) |
461 | #define azx_sd_readb(chip, dev, reg) \ | 395 | #define azx_sd_readb(chip, dev, reg) \ |
462 | ((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg)) | 396 | ((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg)) |
463 | 397 | ||
464 | #endif /* __SOUND_HDA_PRIV_H */ | 398 | #endif /* __SOUND_HDA_PRIV_H */ |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index a366ba9293a8..227990bc02e3 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <linux/reboot.h> | ||
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <linux/time.h> | 33 | #include <linux/time.h> |
35 | 34 | ||
@@ -236,6 +235,7 @@ disable_hda: | |||
236 | return rc; | 235 | return rc; |
237 | } | 236 | } |
238 | 237 | ||
238 | #ifdef CONFIG_PM_SLEEP | ||
239 | static void hda_tegra_disable_clocks(struct hda_tegra *data) | 239 | static void hda_tegra_disable_clocks(struct hda_tegra *data) |
240 | { | 240 | { |
241 | clk_disable_unprepare(data->hda2hdmi_clk); | 241 | clk_disable_unprepare(data->hda2hdmi_clk); |
@@ -243,7 +243,6 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data) | |||
243 | clk_disable_unprepare(data->hda_clk); | 243 | clk_disable_unprepare(data->hda_clk); |
244 | } | 244 | } |
245 | 245 | ||
246 | #ifdef CONFIG_PM_SLEEP | ||
247 | /* | 246 | /* |
248 | * power management | 247 | * power management |
249 | */ | 248 | */ |
@@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev) | |||
272 | struct snd_card *card = dev_get_drvdata(dev); | 271 | struct snd_card *card = dev_get_drvdata(dev); |
273 | struct azx *chip = card->private_data; | 272 | struct azx *chip = card->private_data; |
274 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | 273 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); |
275 | int status; | ||
276 | 274 | ||
277 | hda_tegra_enable_clocks(hda); | 275 | hda_tegra_enable_clocks(hda); |
278 | 276 | ||
279 | /* Read STATESTS before controller reset */ | ||
280 | status = azx_readw(chip, STATESTS); | ||
281 | |||
282 | hda_tegra_init(hda); | 277 | hda_tegra_init(hda); |
283 | 278 | ||
284 | azx_init_chip(chip, 1); | 279 | azx_init_chip(chip, 1); |
@@ -295,30 +290,6 @@ static const struct dev_pm_ops hda_tegra_pm = { | |||
295 | }; | 290 | }; |
296 | 291 | ||
297 | /* | 292 | /* |
298 | * reboot notifier for hang-up problem at power-down | ||
299 | */ | ||
300 | static int hda_tegra_halt(struct notifier_block *nb, unsigned long event, | ||
301 | void *buf) | ||
302 | { | ||
303 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
304 | snd_hda_bus_reboot_notify(chip->bus); | ||
305 | azx_stop_chip(chip); | ||
306 | return NOTIFY_OK; | ||
307 | } | ||
308 | |||
309 | static void hda_tegra_notifier_register(struct azx *chip) | ||
310 | { | ||
311 | chip->reboot_notifier.notifier_call = hda_tegra_halt; | ||
312 | register_reboot_notifier(&chip->reboot_notifier); | ||
313 | } | ||
314 | |||
315 | static void hda_tegra_notifier_unregister(struct azx *chip) | ||
316 | { | ||
317 | if (chip->reboot_notifier.notifier_call) | ||
318 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * destructor | 293 | * destructor |
323 | */ | 294 | */ |
324 | static int hda_tegra_dev_free(struct snd_device *device) | 295 | static int hda_tegra_dev_free(struct snd_device *device) |
@@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device) | |||
326 | int i; | 297 | int i; |
327 | struct azx *chip = device->device_data; | 298 | struct azx *chip = device->device_data; |
328 | 299 | ||
329 | hda_tegra_notifier_unregister(chip); | 300 | azx_notifier_unregister(chip); |
330 | 301 | ||
331 | if (chip->initialized) { | 302 | if (chip->initialized) { |
332 | for (i = 0; i < chip->num_streams; i++) | 303 | for (i = 0; i < chip->num_streams; i++) |
@@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card, | |||
478 | chip->driver_type = driver_caps & 0xff; | 449 | chip->driver_type = driver_caps & 0xff; |
479 | chip->dev_index = 0; | 450 | chip->dev_index = 0; |
480 | INIT_LIST_HEAD(&chip->pcm_list); | 451 | INIT_LIST_HEAD(&chip->pcm_list); |
481 | INIT_LIST_HEAD(&chip->list); | ||
482 | 452 | ||
483 | chip->position_fix[0] = POS_FIX_AUTO; | ||
484 | chip->position_fix[1] = POS_FIX_AUTO; | ||
485 | chip->codec_probe_mask = -1; | 453 | chip->codec_probe_mask = -1; |
486 | 454 | ||
487 | chip->single_cmd = false; | 455 | chip->single_cmd = false; |
@@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
559 | 527 | ||
560 | chip->running = 1; | 528 | chip->running = 1; |
561 | power_down_all_codecs(chip); | 529 | power_down_all_codecs(chip); |
562 | hda_tegra_notifier_register(chip); | 530 | azx_notifier_register(chip); |
563 | 531 | ||
564 | return 0; | 532 | return 0; |
565 | 533 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 092f2bd030bd..4f3aba78f720 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -2046,14 +2046,14 @@ enum dma_state { | |||
2046 | DMA_STATE_RUN = 1 | 2046 | DMA_STATE_RUN = 1 |
2047 | }; | 2047 | }; |
2048 | 2048 | ||
2049 | static int dma_convert_to_hda_format( | 2049 | static int dma_convert_to_hda_format(struct hda_codec *codec, |
2050 | unsigned int sample_rate, | 2050 | unsigned int sample_rate, |
2051 | unsigned short channels, | 2051 | unsigned short channels, |
2052 | unsigned short *hda_format) | 2052 | unsigned short *hda_format) |
2053 | { | 2053 | { |
2054 | unsigned int format_val; | 2054 | unsigned int format_val; |
2055 | 2055 | ||
2056 | format_val = snd_hda_calc_stream_format( | 2056 | format_val = snd_hda_calc_stream_format(codec, |
2057 | sample_rate, | 2057 | sample_rate, |
2058 | channels, | 2058 | channels, |
2059 | SNDRV_PCM_FORMAT_S32_LE, | 2059 | SNDRV_PCM_FORMAT_S32_LE, |
@@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec, | |||
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | dma_engine->codec = codec; | 2454 | dma_engine->codec = codec; |
2455 | dma_convert_to_hda_format(sample_rate, channels, &hda_format); | 2455 | dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format); |
2456 | dma_engine->m_converter_format = hda_format; | 2456 | dma_engine->m_converter_format = hda_format; |
2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : | 2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : |
2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; | 2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 387f0b551889..3db724eaa53c 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -657,8 +657,10 @@ static void cs4208_fixup_mac(struct hda_codec *codec, | |||
657 | { | 657 | { |
658 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 658 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
659 | return; | 659 | return; |
660 | |||
661 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
660 | snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups); | 662 | snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups); |
661 | if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO) | 663 | if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET) |
662 | codec->fixup_id = CS4208_GPIO0; /* default fixup */ | 664 | codec->fixup_id = CS4208_GPIO0; /* default fixup */ |
663 | snd_hda_apply_fixup(codec, action); | 665 | snd_hda_apply_fixup(codec, action); |
664 | } | 666 | } |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 061ea5965dd5..ed3d133ffbb6 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -31,550 +31,11 @@ | |||
31 | #include "hda_jack.h" | 31 | #include "hda_jack.h" |
32 | #include "hda_generic.h" | 32 | #include "hda_generic.h" |
33 | 33 | ||
34 | #undef ENABLE_CMI_STATIC_QUIRKS | ||
35 | |||
36 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
37 | #define NUM_PINS 11 | ||
38 | |||
39 | |||
40 | /* board config type */ | ||
41 | enum { | ||
42 | CMI_MINIMAL, /* back 3-jack */ | ||
43 | CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */ | ||
44 | CMI_FULL, /* back 6-jack + front-panel 2-jack */ | ||
45 | CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ | ||
46 | CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ | ||
47 | CMI_AUTO, /* let driver guess it */ | ||
48 | CMI_MODELS | ||
49 | }; | ||
50 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
51 | |||
52 | struct cmi_spec { | 34 | struct cmi_spec { |
53 | struct hda_gen_spec gen; | 35 | struct hda_gen_spec gen; |
54 | |||
55 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
56 | /* below are only for static models */ | ||
57 | |||
58 | int board_config; | ||
59 | unsigned int no_line_in: 1; /* no line-in (5-jack) */ | ||
60 | unsigned int front_panel: 1; /* has front-panel 2-jack */ | ||
61 | |||
62 | /* playback */ | ||
63 | struct hda_multi_out multiout; | ||
64 | hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */ | ||
65 | int num_dacs; | ||
66 | |||
67 | /* capture */ | ||
68 | const hda_nid_t *adc_nids; | ||
69 | hda_nid_t dig_in_nid; | ||
70 | |||
71 | /* capture source */ | ||
72 | const struct hda_input_mux *input_mux; | ||
73 | unsigned int cur_mux[2]; | ||
74 | |||
75 | /* channel mode */ | ||
76 | int num_channel_modes; | ||
77 | const struct hda_channel_mode *channel_modes; | ||
78 | |||
79 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
80 | |||
81 | /* pin default configuration */ | ||
82 | hda_nid_t pin_nid[NUM_PINS]; | ||
83 | unsigned int def_conf[NUM_PINS]; | ||
84 | unsigned int pin_def_confs; | ||
85 | |||
86 | /* multichannel pins */ | ||
87 | struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ | ||
88 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
89 | }; | ||
90 | |||
91 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
92 | /* | ||
93 | * input MUX | ||
94 | */ | ||
95 | static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
96 | { | ||
97 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
98 | struct cmi_spec *spec = codec->spec; | ||
99 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
100 | } | ||
101 | |||
102 | static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
103 | { | ||
104 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
105 | struct cmi_spec *spec = codec->spec; | ||
106 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
107 | |||
108 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
113 | { | ||
114 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
115 | struct cmi_spec *spec = codec->spec; | ||
116 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
117 | |||
118 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
119 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * shared line-in, mic for surrounds | ||
124 | */ | ||
125 | |||
126 | /* 3-stack / 2 channel */ | ||
127 | static const struct hda_verb cmi9880_ch2_init[] = { | ||
128 | /* set line-in PIN for input */ | ||
129 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
130 | /* set mic PIN for input, also enable vref */ | ||
131 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
132 | /* route front PCM (DAC1) to HP */ | ||
133 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
134 | {} | ||
135 | }; | ||
136 | |||
137 | /* 3-stack / 6 channel */ | ||
138 | static const struct hda_verb cmi9880_ch6_init[] = { | ||
139 | /* set line-in PIN for output */ | ||
140 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
141 | /* set mic PIN for output */ | ||
142 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
143 | /* route front PCM (DAC1) to HP */ | ||
144 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
145 | {} | ||
146 | }; | ||
147 | |||
148 | /* 3-stack+front / 8 channel */ | ||
149 | static const struct hda_verb cmi9880_ch8_init[] = { | ||
150 | /* set line-in PIN for output */ | ||
151 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
152 | /* set mic PIN for output */ | ||
153 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
154 | /* route rear-surround PCM (DAC4) to HP */ | ||
155 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, | ||
156 | {} | ||
157 | }; | ||
158 | |||
159 | static const struct hda_channel_mode cmi9880_channel_modes[3] = { | ||
160 | { 2, cmi9880_ch2_init }, | ||
161 | { 6, cmi9880_ch6_init }, | ||
162 | { 8, cmi9880_ch8_init }, | ||
163 | }; | ||
164 | |||
165 | static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
166 | { | ||
167 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
168 | struct cmi_spec *spec = codec->spec; | ||
169 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes, | ||
170 | spec->num_channel_modes); | ||
171 | } | ||
172 | |||
173 | static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
174 | { | ||
175 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
176 | struct cmi_spec *spec = codec->spec; | ||
177 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes, | ||
178 | spec->num_channel_modes, spec->multiout.max_channels); | ||
179 | } | ||
180 | |||
181 | static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
182 | { | ||
183 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
184 | struct cmi_spec *spec = codec->spec; | ||
185 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes, | ||
186 | spec->num_channel_modes, &spec->multiout.max_channels); | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | */ | ||
191 | static const struct snd_kcontrol_new cmi9880_basic_mixer[] = { | ||
192 | /* CMI9880 has no playback volumes! */ | ||
193 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */ | ||
194 | HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT), | ||
195 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), | ||
196 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), | ||
197 | HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
198 | { | ||
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
200 | /* The multiple "Capture Source" controls confuse alsamixer | ||
201 | * So call somewhat different.. | ||
202 | */ | ||
203 | /* .name = "Capture Source", */ | ||
204 | .name = "Input Source", | ||
205 | .count = 2, | ||
206 | .info = cmi_mux_enum_info, | ||
207 | .get = cmi_mux_enum_get, | ||
208 | .put = cmi_mux_enum_put, | ||
209 | }, | ||
210 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), | ||
212 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), | ||
213 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), | ||
214 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT), | ||
215 | HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT), | ||
216 | { } /* end */ | ||
217 | }; | 36 | }; |
218 | 37 | ||
219 | /* | 38 | /* |
220 | * shared I/O pins | ||
221 | */ | ||
222 | static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = { | ||
223 | { | ||
224 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
225 | .name = "Channel Mode", | ||
226 | .info = cmi_ch_mode_info, | ||
227 | .get = cmi_ch_mode_get, | ||
228 | .put = cmi_ch_mode_put, | ||
229 | }, | ||
230 | { } /* end */ | ||
231 | }; | ||
232 | |||
233 | /* AUD-in selections: | ||
234 | * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20 | ||
235 | */ | ||
236 | static const struct hda_input_mux cmi9880_basic_mux = { | ||
237 | .num_items = 4, | ||
238 | .items = { | ||
239 | { "Front Mic", 0x5 }, | ||
240 | { "Rear Mic", 0x2 }, | ||
241 | { "Line", 0x1 }, | ||
242 | { "CD", 0x7 }, | ||
243 | } | ||
244 | }; | ||
245 | |||
246 | static const struct hda_input_mux cmi9880_no_line_mux = { | ||
247 | .num_items = 3, | ||
248 | .items = { | ||
249 | { "Front Mic", 0x5 }, | ||
250 | { "Rear Mic", 0x2 }, | ||
251 | { "CD", 0x7 }, | ||
252 | } | ||
253 | }; | ||
254 | |||
255 | /* front, rear, clfe, rear_surr */ | ||
256 | static const hda_nid_t cmi9880_dac_nids[4] = { | ||
257 | 0x03, 0x04, 0x05, 0x06 | ||
258 | }; | ||
259 | /* ADC0, ADC1 */ | ||
260 | static const hda_nid_t cmi9880_adc_nids[2] = { | ||
261 | 0x08, 0x09 | ||
262 | }; | ||
263 | |||
264 | #define CMI_DIG_OUT_NID 0x07 | ||
265 | #define CMI_DIG_IN_NID 0x0a | ||
266 | |||
267 | /* | ||
268 | */ | ||
269 | static const struct hda_verb cmi9880_basic_init[] = { | ||
270 | /* port-D for line out (rear panel) */ | ||
271 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
272 | /* port-E for HP out (front panel) */ | ||
273 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
274 | /* route front PCM to HP */ | ||
275 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
276 | /* port-A for surround (rear panel) */ | ||
277 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
278 | /* port-G for CLFE (rear panel) */ | ||
279 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
280 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
281 | /* port-H for side (rear panel) */ | ||
282 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
283 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
284 | /* port-C for line-in (rear panel) */ | ||
285 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
286 | /* port-B for mic-in (rear panel) with vref */ | ||
287 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
288 | /* port-F for mic-in (front panel) with vref */ | ||
289 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
290 | /* CD-in */ | ||
291 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
292 | /* route front mic to ADC1/2 */ | ||
293 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
294 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
295 | {} /* terminator */ | ||
296 | }; | ||
297 | |||
298 | static const struct hda_verb cmi9880_allout_init[] = { | ||
299 | /* port-D for line out (rear panel) */ | ||
300 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
301 | /* port-E for HP out (front panel) */ | ||
302 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
303 | /* route front PCM to HP */ | ||
304 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
305 | /* port-A for side (rear panel) */ | ||
306 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
307 | /* port-G for CLFE (rear panel) */ | ||
308 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
309 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
310 | /* port-H for side (rear panel) */ | ||
311 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
312 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
313 | /* port-C for surround (rear panel) */ | ||
314 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
315 | /* port-B for mic-in (rear panel) with vref */ | ||
316 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
317 | /* port-F for mic-in (front panel) with vref */ | ||
318 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
319 | /* CD-in */ | ||
320 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
321 | /* route front mic to ADC1/2 */ | ||
322 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
323 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
324 | {} /* terminator */ | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | */ | ||
329 | static int cmi9880_build_controls(struct hda_codec *codec) | ||
330 | { | ||
331 | struct cmi_spec *spec = codec->spec; | ||
332 | struct snd_kcontrol *kctl; | ||
333 | int i, err; | ||
334 | |||
335 | err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); | ||
336 | if (err < 0) | ||
337 | return err; | ||
338 | if (spec->channel_modes) { | ||
339 | err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | } | ||
343 | if (spec->multiout.dig_out_nid) { | ||
344 | err = snd_hda_create_spdif_out_ctls(codec, | ||
345 | spec->multiout.dig_out_nid, | ||
346 | spec->multiout.dig_out_nid); | ||
347 | if (err < 0) | ||
348 | return err; | ||
349 | err = snd_hda_create_spdif_share_sw(codec, | ||
350 | &spec->multiout); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | spec->multiout.share_spdif = 1; | ||
354 | } | ||
355 | if (spec->dig_in_nid) { | ||
356 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | ||
357 | if (err < 0) | ||
358 | return err; | ||
359 | } | ||
360 | |||
361 | /* assign Capture Source enums to NID */ | ||
362 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
363 | for (i = 0; kctl && i < kctl->count; i++) { | ||
364 | err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]); | ||
365 | if (err < 0) | ||
366 | return err; | ||
367 | } | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int cmi9880_init(struct hda_codec *codec) | ||
372 | { | ||
373 | struct cmi_spec *spec = codec->spec; | ||
374 | if (spec->board_config == CMI_ALLOUT) | ||
375 | snd_hda_sequence_write(codec, cmi9880_allout_init); | ||
376 | else | ||
377 | snd_hda_sequence_write(codec, cmi9880_basic_init); | ||
378 | if (spec->board_config == CMI_AUTO) | ||
379 | snd_hda_sequence_write(codec, spec->multi_init); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * Analog playback callbacks | ||
385 | */ | ||
386 | static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
387 | struct hda_codec *codec, | ||
388 | struct snd_pcm_substream *substream) | ||
389 | { | ||
390 | struct cmi_spec *spec = codec->spec; | ||
391 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
392 | hinfo); | ||
393 | } | ||
394 | |||
395 | static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
396 | struct hda_codec *codec, | ||
397 | unsigned int stream_tag, | ||
398 | unsigned int format, | ||
399 | struct snd_pcm_substream *substream) | ||
400 | { | ||
401 | struct cmi_spec *spec = codec->spec; | ||
402 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
403 | format, substream); | ||
404 | } | ||
405 | |||
406 | static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
407 | struct hda_codec *codec, | ||
408 | struct snd_pcm_substream *substream) | ||
409 | { | ||
410 | struct cmi_spec *spec = codec->spec; | ||
411 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Digital out | ||
416 | */ | ||
417 | static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
418 | struct hda_codec *codec, | ||
419 | struct snd_pcm_substream *substream) | ||
420 | { | ||
421 | struct cmi_spec *spec = codec->spec; | ||
422 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
423 | } | ||
424 | |||
425 | static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
426 | struct hda_codec *codec, | ||
427 | struct snd_pcm_substream *substream) | ||
428 | { | ||
429 | struct cmi_spec *spec = codec->spec; | ||
430 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
431 | } | ||
432 | |||
433 | static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
434 | struct hda_codec *codec, | ||
435 | unsigned int stream_tag, | ||
436 | unsigned int format, | ||
437 | struct snd_pcm_substream *substream) | ||
438 | { | ||
439 | struct cmi_spec *spec = codec->spec; | ||
440 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
441 | format, substream); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Analog capture | ||
446 | */ | ||
447 | static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
448 | struct hda_codec *codec, | ||
449 | unsigned int stream_tag, | ||
450 | unsigned int format, | ||
451 | struct snd_pcm_substream *substream) | ||
452 | { | ||
453 | struct cmi_spec *spec = codec->spec; | ||
454 | |||
455 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
456 | stream_tag, 0, format); | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
461 | struct hda_codec *codec, | ||
462 | struct snd_pcm_substream *substream) | ||
463 | { | ||
464 | struct cmi_spec *spec = codec->spec; | ||
465 | |||
466 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* | ||
472 | */ | ||
473 | static const struct hda_pcm_stream cmi9880_pcm_analog_playback = { | ||
474 | .substreams = 1, | ||
475 | .channels_min = 2, | ||
476 | .channels_max = 8, | ||
477 | .nid = 0x03, /* NID to query formats and rates */ | ||
478 | .ops = { | ||
479 | .open = cmi9880_playback_pcm_open, | ||
480 | .prepare = cmi9880_playback_pcm_prepare, | ||
481 | .cleanup = cmi9880_playback_pcm_cleanup | ||
482 | }, | ||
483 | }; | ||
484 | |||
485 | static const struct hda_pcm_stream cmi9880_pcm_analog_capture = { | ||
486 | .substreams = 2, | ||
487 | .channels_min = 2, | ||
488 | .channels_max = 2, | ||
489 | .nid = 0x08, /* NID to query formats and rates */ | ||
490 | .ops = { | ||
491 | .prepare = cmi9880_capture_pcm_prepare, | ||
492 | .cleanup = cmi9880_capture_pcm_cleanup | ||
493 | }, | ||
494 | }; | ||
495 | |||
496 | static const struct hda_pcm_stream cmi9880_pcm_digital_playback = { | ||
497 | .substreams = 1, | ||
498 | .channels_min = 2, | ||
499 | .channels_max = 2, | ||
500 | /* NID is set in cmi9880_build_pcms */ | ||
501 | .ops = { | ||
502 | .open = cmi9880_dig_playback_pcm_open, | ||
503 | .close = cmi9880_dig_playback_pcm_close, | ||
504 | .prepare = cmi9880_dig_playback_pcm_prepare | ||
505 | }, | ||
506 | }; | ||
507 | |||
508 | static const struct hda_pcm_stream cmi9880_pcm_digital_capture = { | ||
509 | .substreams = 1, | ||
510 | .channels_min = 2, | ||
511 | .channels_max = 2, | ||
512 | /* NID is set in cmi9880_build_pcms */ | ||
513 | }; | ||
514 | |||
515 | static int cmi9880_build_pcms(struct hda_codec *codec) | ||
516 | { | ||
517 | struct cmi_spec *spec = codec->spec; | ||
518 | struct hda_pcm *info = spec->pcm_rec; | ||
519 | |||
520 | codec->num_pcms = 1; | ||
521 | codec->pcm_info = info; | ||
522 | |||
523 | info->name = "CMI9880"; | ||
524 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback; | ||
525 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture; | ||
526 | |||
527 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | ||
528 | codec->num_pcms++; | ||
529 | info++; | ||
530 | info->name = "CMI9880 Digital"; | ||
531 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
532 | if (spec->multiout.dig_out_nid) { | ||
533 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; | ||
534 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
535 | } | ||
536 | if (spec->dig_in_nid) { | ||
537 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture; | ||
538 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static void cmi9880_free(struct hda_codec *codec) | ||
546 | { | ||
547 | kfree(codec->spec); | ||
548 | } | ||
549 | |||
550 | /* | ||
551 | */ | ||
552 | |||
553 | static const char * const cmi9880_models[CMI_MODELS] = { | ||
554 | [CMI_MINIMAL] = "minimal", | ||
555 | [CMI_MIN_FP] = "min_fp", | ||
556 | [CMI_FULL] = "full", | ||
557 | [CMI_FULL_DIG] = "full_dig", | ||
558 | [CMI_ALLOUT] = "allout", | ||
559 | [CMI_AUTO] = "auto", | ||
560 | }; | ||
561 | |||
562 | static const struct snd_pci_quirk cmi9880_cfg_tbl[] = { | ||
563 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG), | ||
564 | SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL), | ||
565 | SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG), | ||
566 | {} /* terminator */ | ||
567 | }; | ||
568 | |||
569 | static const struct hda_codec_ops cmi9880_patch_ops = { | ||
570 | .build_controls = cmi9880_build_controls, | ||
571 | .build_pcms = cmi9880_build_pcms, | ||
572 | .init = cmi9880_init, | ||
573 | .free = cmi9880_free, | ||
574 | }; | ||
575 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
576 | |||
577 | /* | ||
578 | * stuff for auto-parser | 39 | * stuff for auto-parser |
579 | */ | 40 | */ |
580 | static const struct hda_codec_ops cmi_auto_patch_ops = { | 41 | static const struct hda_codec_ops cmi_auto_patch_ops = { |
@@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = { | |||
585 | .unsol_event = snd_hda_jack_unsol_event, | 46 | .unsol_event = snd_hda_jack_unsol_event, |
586 | }; | 47 | }; |
587 | 48 | ||
588 | static int cmi_parse_auto_config(struct hda_codec *codec) | 49 | static int patch_cmi9880(struct hda_codec *codec) |
589 | { | 50 | { |
590 | struct cmi_spec *spec = codec->spec; | 51 | struct cmi_spec *spec; |
591 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | 52 | struct auto_pin_cfg *cfg; |
592 | int err; | 53 | int err; |
593 | 54 | ||
55 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
56 | if (spec == NULL) | ||
57 | return -ENOMEM; | ||
58 | |||
59 | codec->spec = spec; | ||
60 | cfg = &spec->gen.autocfg; | ||
594 | snd_hda_gen_spec_init(&spec->gen); | 61 | snd_hda_gen_spec_init(&spec->gen); |
595 | 62 | ||
596 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | 63 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); |
@@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec) | |||
608 | return err; | 75 | return err; |
609 | } | 76 | } |
610 | 77 | ||
611 | |||
612 | static int patch_cmi9880(struct hda_codec *codec) | ||
613 | { | ||
614 | struct cmi_spec *spec; | ||
615 | |||
616 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
617 | if (spec == NULL) | ||
618 | return -ENOMEM; | ||
619 | |||
620 | codec->spec = spec; | ||
621 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
622 | spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, | ||
623 | cmi9880_models, | ||
624 | cmi9880_cfg_tbl); | ||
625 | if (spec->board_config < 0) { | ||
626 | codec_dbg(codec, "%s: BIOS auto-probing.\n", | ||
627 | codec->chip_name); | ||
628 | spec->board_config = CMI_AUTO; /* try everything */ | ||
629 | } | ||
630 | |||
631 | if (spec->board_config == CMI_AUTO) | ||
632 | return cmi_parse_auto_config(codec); | ||
633 | |||
634 | /* copy default DAC NIDs */ | ||
635 | memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); | ||
636 | spec->num_dacs = 4; | ||
637 | |||
638 | switch (spec->board_config) { | ||
639 | case CMI_MINIMAL: | ||
640 | case CMI_MIN_FP: | ||
641 | spec->channel_modes = cmi9880_channel_modes; | ||
642 | if (spec->board_config == CMI_MINIMAL) | ||
643 | spec->num_channel_modes = 2; | ||
644 | else { | ||
645 | spec->front_panel = 1; | ||
646 | spec->num_channel_modes = 3; | ||
647 | } | ||
648 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | ||
649 | spec->input_mux = &cmi9880_basic_mux; | ||
650 | break; | ||
651 | case CMI_FULL: | ||
652 | case CMI_FULL_DIG: | ||
653 | spec->front_panel = 1; | ||
654 | spec->multiout.max_channels = 8; | ||
655 | spec->input_mux = &cmi9880_basic_mux; | ||
656 | if (spec->board_config == CMI_FULL_DIG) { | ||
657 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
658 | spec->dig_in_nid = CMI_DIG_IN_NID; | ||
659 | } | ||
660 | break; | ||
661 | case CMI_ALLOUT: | ||
662 | default: | ||
663 | spec->front_panel = 1; | ||
664 | spec->multiout.max_channels = 8; | ||
665 | spec->no_line_in = 1; | ||
666 | spec->input_mux = &cmi9880_no_line_mux; | ||
667 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
668 | break; | ||
669 | } | ||
670 | |||
671 | spec->multiout.num_dacs = spec->num_dacs; | ||
672 | spec->multiout.dac_nids = spec->dac_nids; | ||
673 | |||
674 | spec->adc_nids = cmi9880_adc_nids; | ||
675 | |||
676 | codec->patch_ops = cmi9880_patch_ops; | ||
677 | |||
678 | return 0; | ||
679 | #else | ||
680 | return cmi_parse_auto_config(codec); | ||
681 | #endif | ||
682 | } | ||
683 | |||
684 | /* | 78 | /* |
685 | * patch entries | 79 | * patch entries |
686 | */ | 80 | */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1dc7e974f3b1..7627a69ca6d7 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -34,27 +34,6 @@ | |||
34 | #include "hda_jack.h" | 34 | #include "hda_jack.h" |
35 | #include "hda_generic.h" | 35 | #include "hda_generic.h" |
36 | 36 | ||
37 | #undef ENABLE_CXT_STATIC_QUIRKS | ||
38 | |||
39 | #define CXT_PIN_DIR_IN 0x00 | ||
40 | #define CXT_PIN_DIR_OUT 0x01 | ||
41 | #define CXT_PIN_DIR_INOUT 0x02 | ||
42 | #define CXT_PIN_DIR_IN_NOMICBIAS 0x03 | ||
43 | #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
44 | |||
45 | #define CONEXANT_HP_EVENT 0x37 | ||
46 | #define CONEXANT_MIC_EVENT 0x38 | ||
47 | #define CONEXANT_LINE_EVENT 0x39 | ||
48 | |||
49 | /* Conexant 5051 specific */ | ||
50 | |||
51 | #define CXT5051_SPDIF_OUT 0x12 | ||
52 | #define CXT5051_PORTB_EVENT 0x38 | ||
53 | #define CXT5051_PORTC_EVENT 0x39 | ||
54 | |||
55 | #define AUTO_MIC_PORTB (1 << 1) | ||
56 | #define AUTO_MIC_PORTC (1 << 2) | ||
57 | |||
58 | struct conexant_spec { | 37 | struct conexant_spec { |
59 | struct hda_gen_spec gen; | 38 | struct hda_gen_spec gen; |
60 | 39 | ||
@@ -72,64 +51,6 @@ struct conexant_spec { | |||
72 | bool dc_enable; | 51 | bool dc_enable; |
73 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ | 52 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ |
74 | struct nid_path *dc_mode_path; | 53 | struct nid_path *dc_mode_path; |
75 | |||
76 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
77 | const struct snd_kcontrol_new *mixers[5]; | ||
78 | int num_mixers; | ||
79 | hda_nid_t vmaster_nid; | ||
80 | |||
81 | const struct hda_verb *init_verbs[5]; /* initialization verbs | ||
82 | * don't forget NULL | ||
83 | * termination! | ||
84 | */ | ||
85 | unsigned int num_init_verbs; | ||
86 | |||
87 | /* playback */ | ||
88 | struct hda_multi_out multiout; /* playback set-up | ||
89 | * max_channels, dacs must be set | ||
90 | * dig_out_nid and hp_nid are optional | ||
91 | */ | ||
92 | unsigned int cur_eapd; | ||
93 | unsigned int hp_present; | ||
94 | unsigned int line_present; | ||
95 | unsigned int auto_mic; | ||
96 | |||
97 | /* capture */ | ||
98 | unsigned int num_adc_nids; | ||
99 | const hda_nid_t *adc_nids; | ||
100 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | ||
101 | |||
102 | unsigned int cur_adc_idx; | ||
103 | hda_nid_t cur_adc; | ||
104 | unsigned int cur_adc_stream_tag; | ||
105 | unsigned int cur_adc_format; | ||
106 | |||
107 | const struct hda_pcm_stream *capture_stream; | ||
108 | |||
109 | /* capture source */ | ||
110 | const struct hda_input_mux *input_mux; | ||
111 | const hda_nid_t *capsrc_nids; | ||
112 | unsigned int cur_mux[3]; | ||
113 | |||
114 | /* channel model */ | ||
115 | const struct hda_channel_mode *channel_mode; | ||
116 | int num_channel_mode; | ||
117 | |||
118 | /* PCM information */ | ||
119 | struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ | ||
120 | |||
121 | unsigned int spdif_route; | ||
122 | |||
123 | unsigned int port_d_mode; | ||
124 | unsigned int dell_automute:1; | ||
125 | unsigned int dell_vostro:1; | ||
126 | unsigned int ideapad:1; | ||
127 | unsigned int thinkpad:1; | ||
128 | unsigned int hp_laptop:1; | ||
129 | unsigned int asus:1; | ||
130 | |||
131 | unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ | ||
132 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
133 | }; | 54 | }; |
134 | 55 | ||
135 | 56 | ||
@@ -173,2533 +94,6 @@ static int add_beep_ctls(struct hda_codec *codec) | |||
173 | #define add_beep_ctls(codec) 0 | 94 | #define add_beep_ctls(codec) 0 |
174 | #endif | 95 | #endif |
175 | 96 | ||
176 | |||
177 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
178 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
179 | struct hda_codec *codec, | ||
180 | struct snd_pcm_substream *substream) | ||
181 | { | ||
182 | struct conexant_spec *spec = codec->spec; | ||
183 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
184 | hinfo); | ||
185 | } | ||
186 | |||
187 | static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
188 | struct hda_codec *codec, | ||
189 | unsigned int stream_tag, | ||
190 | unsigned int format, | ||
191 | struct snd_pcm_substream *substream) | ||
192 | { | ||
193 | struct conexant_spec *spec = codec->spec; | ||
194 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, | ||
195 | stream_tag, | ||
196 | format, substream); | ||
197 | } | ||
198 | |||
199 | static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
200 | struct hda_codec *codec, | ||
201 | struct snd_pcm_substream *substream) | ||
202 | { | ||
203 | struct conexant_spec *spec = codec->spec; | ||
204 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Digital out | ||
209 | */ | ||
210 | static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
211 | struct hda_codec *codec, | ||
212 | struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | struct conexant_spec *spec = codec->spec; | ||
215 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
216 | } | ||
217 | |||
218 | static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
219 | struct hda_codec *codec, | ||
220 | struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct conexant_spec *spec = codec->spec; | ||
223 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
224 | } | ||
225 | |||
226 | static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
227 | struct hda_codec *codec, | ||
228 | unsigned int stream_tag, | ||
229 | unsigned int format, | ||
230 | struct snd_pcm_substream *substream) | ||
231 | { | ||
232 | struct conexant_spec *spec = codec->spec; | ||
233 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
234 | stream_tag, | ||
235 | format, substream); | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Analog capture | ||
240 | */ | ||
241 | static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
242 | struct hda_codec *codec, | ||
243 | unsigned int stream_tag, | ||
244 | unsigned int format, | ||
245 | struct snd_pcm_substream *substream) | ||
246 | { | ||
247 | struct conexant_spec *spec = codec->spec; | ||
248 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
249 | stream_tag, 0, format); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
254 | struct hda_codec *codec, | ||
255 | struct snd_pcm_substream *substream) | ||
256 | { | ||
257 | struct conexant_spec *spec = codec->spec; | ||
258 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | |||
263 | |||
264 | static const struct hda_pcm_stream conexant_pcm_analog_playback = { | ||
265 | .substreams = 1, | ||
266 | .channels_min = 2, | ||
267 | .channels_max = 2, | ||
268 | .nid = 0, /* fill later */ | ||
269 | .ops = { | ||
270 | .open = conexant_playback_pcm_open, | ||
271 | .prepare = conexant_playback_pcm_prepare, | ||
272 | .cleanup = conexant_playback_pcm_cleanup | ||
273 | }, | ||
274 | }; | ||
275 | |||
276 | static const struct hda_pcm_stream conexant_pcm_analog_capture = { | ||
277 | .substreams = 1, | ||
278 | .channels_min = 2, | ||
279 | .channels_max = 2, | ||
280 | .nid = 0, /* fill later */ | ||
281 | .ops = { | ||
282 | .prepare = conexant_capture_pcm_prepare, | ||
283 | .cleanup = conexant_capture_pcm_cleanup | ||
284 | }, | ||
285 | }; | ||
286 | |||
287 | |||
288 | static const struct hda_pcm_stream conexant_pcm_digital_playback = { | ||
289 | .substreams = 1, | ||
290 | .channels_min = 2, | ||
291 | .channels_max = 2, | ||
292 | .nid = 0, /* fill later */ | ||
293 | .ops = { | ||
294 | .open = conexant_dig_playback_pcm_open, | ||
295 | .close = conexant_dig_playback_pcm_close, | ||
296 | .prepare = conexant_dig_playback_pcm_prepare | ||
297 | }, | ||
298 | }; | ||
299 | |||
300 | static const struct hda_pcm_stream conexant_pcm_digital_capture = { | ||
301 | .substreams = 1, | ||
302 | .channels_min = 2, | ||
303 | .channels_max = 2, | ||
304 | /* NID is set in alc_build_pcms */ | ||
305 | }; | ||
306 | |||
307 | static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
308 | struct hda_codec *codec, | ||
309 | unsigned int stream_tag, | ||
310 | unsigned int format, | ||
311 | struct snd_pcm_substream *substream) | ||
312 | { | ||
313 | struct conexant_spec *spec = codec->spec; | ||
314 | spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
315 | spec->cur_adc_stream_tag = stream_tag; | ||
316 | spec->cur_adc_format = format; | ||
317 | snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
322 | struct hda_codec *codec, | ||
323 | struct snd_pcm_substream *substream) | ||
324 | { | ||
325 | struct conexant_spec *spec = codec->spec; | ||
326 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
327 | spec->cur_adc = 0; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static const struct hda_pcm_stream cx5051_pcm_analog_capture = { | ||
332 | .substreams = 1, | ||
333 | .channels_min = 2, | ||
334 | .channels_max = 2, | ||
335 | .nid = 0, /* fill later */ | ||
336 | .ops = { | ||
337 | .prepare = cx5051_capture_pcm_prepare, | ||
338 | .cleanup = cx5051_capture_pcm_cleanup | ||
339 | }, | ||
340 | }; | ||
341 | |||
342 | static int conexant_build_pcms(struct hda_codec *codec) | ||
343 | { | ||
344 | struct conexant_spec *spec = codec->spec; | ||
345 | struct hda_pcm *info = spec->pcm_rec; | ||
346 | |||
347 | codec->num_pcms = 1; | ||
348 | codec->pcm_info = info; | ||
349 | |||
350 | info->name = "CONEXANT Analog"; | ||
351 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; | ||
352 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
353 | spec->multiout.max_channels; | ||
354 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
355 | spec->multiout.dac_nids[0]; | ||
356 | if (spec->capture_stream) | ||
357 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; | ||
358 | else { | ||
359 | if (codec->vendor_id == 0x14f15051) | ||
360 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
361 | cx5051_pcm_analog_capture; | ||
362 | else { | ||
363 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
364 | conexant_pcm_analog_capture; | ||
365 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = | ||
366 | spec->num_adc_nids; | ||
367 | } | ||
368 | } | ||
369 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
370 | |||
371 | if (spec->multiout.dig_out_nid) { | ||
372 | info++; | ||
373 | codec->num_pcms++; | ||
374 | info->name = "Conexant Digital"; | ||
375 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
376 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
377 | conexant_pcm_digital_playback; | ||
378 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
379 | spec->multiout.dig_out_nid; | ||
380 | if (spec->dig_in_nid) { | ||
381 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
382 | conexant_pcm_digital_capture; | ||
383 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = | ||
384 | spec->dig_in_nid; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
392 | struct snd_ctl_elem_info *uinfo) | ||
393 | { | ||
394 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
395 | struct conexant_spec *spec = codec->spec; | ||
396 | |||
397 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
398 | } | ||
399 | |||
400 | static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
401 | struct snd_ctl_elem_value *ucontrol) | ||
402 | { | ||
403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
404 | struct conexant_spec *spec = codec->spec; | ||
405 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
406 | |||
407 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
412 | struct snd_ctl_elem_value *ucontrol) | ||
413 | { | ||
414 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
415 | struct conexant_spec *spec = codec->spec; | ||
416 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
417 | |||
418 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
419 | spec->capsrc_nids[adc_idx], | ||
420 | &spec->cur_mux[adc_idx]); | ||
421 | } | ||
422 | |||
423 | static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, | ||
424 | unsigned int power_state) | ||
425 | { | ||
426 | if (power_state == AC_PWRST_D3) | ||
427 | msleep(100); | ||
428 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
429 | power_state); | ||
430 | /* partial workaround for "azx_get_response timeout" */ | ||
431 | if (power_state == AC_PWRST_D0) | ||
432 | msleep(10); | ||
433 | snd_hda_codec_set_power_to_all(codec, fg, power_state); | ||
434 | } | ||
435 | |||
436 | static int conexant_init(struct hda_codec *codec) | ||
437 | { | ||
438 | struct conexant_spec *spec = codec->spec; | ||
439 | int i; | ||
440 | |||
441 | for (i = 0; i < spec->num_init_verbs; i++) | ||
442 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static void conexant_free(struct hda_codec *codec) | ||
447 | { | ||
448 | kfree(codec->spec); | ||
449 | } | ||
450 | |||
451 | static const struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
452 | { | ||
453 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
454 | .name = "Capture Source", | ||
455 | .info = conexant_mux_enum_info, | ||
456 | .get = conexant_mux_enum_get, | ||
457 | .put = conexant_mux_enum_put | ||
458 | }, | ||
459 | {} | ||
460 | }; | ||
461 | |||
462 | static const char * const slave_pfxs[] = { | ||
463 | "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE", | ||
464 | NULL | ||
465 | }; | ||
466 | |||
467 | static int conexant_build_controls(struct hda_codec *codec) | ||
468 | { | ||
469 | struct conexant_spec *spec = codec->spec; | ||
470 | unsigned int i; | ||
471 | int err; | ||
472 | |||
473 | for (i = 0; i < spec->num_mixers; i++) { | ||
474 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
475 | if (err < 0) | ||
476 | return err; | ||
477 | } | ||
478 | if (spec->multiout.dig_out_nid) { | ||
479 | err = snd_hda_create_spdif_out_ctls(codec, | ||
480 | spec->multiout.dig_out_nid, | ||
481 | spec->multiout.dig_out_nid); | ||
482 | if (err < 0) | ||
483 | return err; | ||
484 | err = snd_hda_create_spdif_share_sw(codec, | ||
485 | &spec->multiout); | ||
486 | if (err < 0) | ||
487 | return err; | ||
488 | spec->multiout.share_spdif = 1; | ||
489 | } | ||
490 | if (spec->dig_in_nid) { | ||
491 | err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); | ||
492 | if (err < 0) | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | /* if we have no master control, let's create it */ | ||
497 | if (spec->vmaster_nid && | ||
498 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
499 | unsigned int vmaster_tlv[4]; | ||
500 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
501 | HDA_OUTPUT, vmaster_tlv); | ||
502 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
503 | vmaster_tlv, slave_pfxs, | ||
504 | "Playback Volume"); | ||
505 | if (err < 0) | ||
506 | return err; | ||
507 | } | ||
508 | if (spec->vmaster_nid && | ||
509 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
510 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
511 | NULL, slave_pfxs, | ||
512 | "Playback Switch"); | ||
513 | if (err < 0) | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | if (spec->input_mux) { | ||
518 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | } | ||
522 | |||
523 | err = add_beep_ctls(codec); | ||
524 | if (err < 0) | ||
525 | return err; | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static const struct hda_codec_ops conexant_patch_ops = { | ||
531 | .build_controls = conexant_build_controls, | ||
532 | .build_pcms = conexant_build_pcms, | ||
533 | .init = conexant_init, | ||
534 | .free = conexant_free, | ||
535 | .set_power_state = conexant_set_power, | ||
536 | }; | ||
537 | |||
538 | static int patch_conexant_auto(struct hda_codec *codec); | ||
539 | /* | ||
540 | * EAPD control | ||
541 | * the private value = nid | (invert << 8) | ||
542 | */ | ||
543 | |||
544 | #define cxt_eapd_info snd_ctl_boolean_mono_info | ||
545 | |||
546 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, | ||
547 | struct snd_ctl_elem_value *ucontrol) | ||
548 | { | ||
549 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
550 | struct conexant_spec *spec = codec->spec; | ||
551 | int invert = (kcontrol->private_value >> 8) & 1; | ||
552 | if (invert) | ||
553 | ucontrol->value.integer.value[0] = !spec->cur_eapd; | ||
554 | else | ||
555 | ucontrol->value.integer.value[0] = spec->cur_eapd; | ||
556 | return 0; | ||
557 | |||
558 | } | ||
559 | |||
560 | static int cxt_eapd_put(struct snd_kcontrol *kcontrol, | ||
561 | struct snd_ctl_elem_value *ucontrol) | ||
562 | { | ||
563 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
564 | struct conexant_spec *spec = codec->spec; | ||
565 | int invert = (kcontrol->private_value >> 8) & 1; | ||
566 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
567 | unsigned int eapd; | ||
568 | |||
569 | eapd = !!ucontrol->value.integer.value[0]; | ||
570 | if (invert) | ||
571 | eapd = !eapd; | ||
572 | if (eapd == spec->cur_eapd) | ||
573 | return 0; | ||
574 | |||
575 | spec->cur_eapd = eapd; | ||
576 | snd_hda_codec_write_cache(codec, nid, | ||
577 | 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
578 | eapd ? 0x02 : 0x00); | ||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | /* controls for test mode */ | ||
583 | #ifdef CONFIG_SND_DEBUG | ||
584 | |||
585 | #define CXT_EAPD_SWITCH(xname, nid, mask) \ | ||
586 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
587 | .info = cxt_eapd_info, \ | ||
588 | .get = cxt_eapd_get, \ | ||
589 | .put = cxt_eapd_put, \ | ||
590 | .private_value = nid | (mask<<16) } | ||
591 | |||
592 | |||
593 | |||
594 | static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
595 | struct snd_ctl_elem_info *uinfo) | ||
596 | { | ||
597 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
598 | struct conexant_spec *spec = codec->spec; | ||
599 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
600 | spec->num_channel_mode); | ||
601 | } | ||
602 | |||
603 | static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
604 | struct snd_ctl_elem_value *ucontrol) | ||
605 | { | ||
606 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
607 | struct conexant_spec *spec = codec->spec; | ||
608 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
609 | spec->num_channel_mode, | ||
610 | spec->multiout.max_channels); | ||
611 | } | ||
612 | |||
613 | static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
614 | struct snd_ctl_elem_value *ucontrol) | ||
615 | { | ||
616 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
617 | struct conexant_spec *spec = codec->spec; | ||
618 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
619 | spec->num_channel_mode, | ||
620 | &spec->multiout.max_channels); | ||
621 | return err; | ||
622 | } | ||
623 | |||
624 | #define CXT_PIN_MODE(xname, nid, dir) \ | ||
625 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
626 | .info = conexant_ch_mode_info, \ | ||
627 | .get = conexant_ch_mode_get, \ | ||
628 | .put = conexant_ch_mode_put, \ | ||
629 | .private_value = nid | (dir<<16) } | ||
630 | |||
631 | #endif /* CONFIG_SND_DEBUG */ | ||
632 | |||
633 | /* Conexant 5045 specific */ | ||
634 | |||
635 | static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; | ||
636 | static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; | ||
637 | static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; | ||
638 | #define CXT5045_SPDIF_OUT 0x18 | ||
639 | |||
640 | static const struct hda_channel_mode cxt5045_modes[1] = { | ||
641 | { 2, NULL }, | ||
642 | }; | ||
643 | |||
644 | static const struct hda_input_mux cxt5045_capture_source = { | ||
645 | .num_items = 2, | ||
646 | .items = { | ||
647 | { "Internal Mic", 0x1 }, | ||
648 | { "Mic", 0x2 }, | ||
649 | } | ||
650 | }; | ||
651 | |||
652 | static const struct hda_input_mux cxt5045_capture_source_benq = { | ||
653 | .num_items = 4, | ||
654 | .items = { | ||
655 | { "Internal Mic", 0x1 }, | ||
656 | { "Mic", 0x2 }, | ||
657 | { "Line", 0x3 }, | ||
658 | { "Mixer", 0x0 }, | ||
659 | } | ||
660 | }; | ||
661 | |||
662 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
663 | static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
664 | struct snd_ctl_elem_value *ucontrol) | ||
665 | { | ||
666 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
667 | struct conexant_spec *spec = codec->spec; | ||
668 | unsigned int bits; | ||
669 | |||
670 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
671 | return 0; | ||
672 | |||
673 | /* toggle internal speakers mute depending of presence of | ||
674 | * the headphone jack | ||
675 | */ | ||
676 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
677 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
678 | HDA_AMP_MUTE, bits); | ||
679 | |||
680 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
681 | snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, | ||
682 | HDA_AMP_MUTE, bits); | ||
683 | return 1; | ||
684 | } | ||
685 | |||
686 | /* bind volumes of both NID 0x10 and 0x11 */ | ||
687 | static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = { | ||
688 | .ops = &snd_hda_bind_vol, | ||
689 | .values = { | ||
690 | HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), | ||
691 | HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), | ||
692 | 0 | ||
693 | }, | ||
694 | }; | ||
695 | |||
696 | /* toggle input of built-in and mic jack appropriately */ | ||
697 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
698 | { | ||
699 | static const struct hda_verb mic_jack_on[] = { | ||
700 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
701 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
702 | {} | ||
703 | }; | ||
704 | static const struct hda_verb mic_jack_off[] = { | ||
705 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
706 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
707 | {} | ||
708 | }; | ||
709 | unsigned int present; | ||
710 | |||
711 | present = snd_hda_jack_detect(codec, 0x12); | ||
712 | if (present) | ||
713 | snd_hda_sequence_write(codec, mic_jack_on); | ||
714 | else | ||
715 | snd_hda_sequence_write(codec, mic_jack_off); | ||
716 | } | ||
717 | |||
718 | |||
719 | /* mute internal speaker if HP is plugged */ | ||
720 | static void cxt5045_hp_automute(struct hda_codec *codec) | ||
721 | { | ||
722 | struct conexant_spec *spec = codec->spec; | ||
723 | unsigned int bits; | ||
724 | |||
725 | spec->hp_present = snd_hda_jack_detect(codec, 0x11); | ||
726 | |||
727 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
728 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
729 | HDA_AMP_MUTE, bits); | ||
730 | } | ||
731 | |||
732 | /* unsolicited event for HP jack sensing */ | ||
733 | static void cxt5045_hp_unsol_event(struct hda_codec *codec, | ||
734 | unsigned int res) | ||
735 | { | ||
736 | res >>= 26; | ||
737 | switch (res) { | ||
738 | case CONEXANT_HP_EVENT: | ||
739 | cxt5045_hp_automute(codec); | ||
740 | break; | ||
741 | case CONEXANT_MIC_EVENT: | ||
742 | cxt5045_hp_automic(codec); | ||
743 | break; | ||
744 | |||
745 | } | ||
746 | } | ||
747 | |||
748 | static const struct snd_kcontrol_new cxt5045_mixers[] = { | ||
749 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), | ||
750 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
751 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), | ||
752 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), | ||
753 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), | ||
754 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), | ||
755 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), | ||
756 | HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), | ||
757 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), | ||
758 | { | ||
759 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
760 | .name = "Master Playback Switch", | ||
761 | .info = cxt_eapd_info, | ||
762 | .get = cxt_eapd_get, | ||
763 | .put = cxt5045_hp_master_sw_put, | ||
764 | .private_value = 0x10, | ||
765 | }, | ||
766 | |||
767 | {} | ||
768 | }; | ||
769 | |||
770 | static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { | ||
771 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), | ||
772 | HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), | ||
773 | |||
774 | {} | ||
775 | }; | ||
776 | |||
777 | static const struct hda_verb cxt5045_init_verbs[] = { | ||
778 | /* Line in, Mic */ | ||
779 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
780 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
781 | /* HP, Amp */ | ||
782 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
783 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
784 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
785 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
786 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
787 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
788 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
789 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
790 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
791 | /* Record selector: Internal mic */ | ||
792 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
793 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
794 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
795 | /* SPDIF route: PCM */ | ||
796 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
797 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
798 | /* EAPD */ | ||
799 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | ||
800 | { } /* end */ | ||
801 | }; | ||
802 | |||
803 | static const struct hda_verb cxt5045_benq_init_verbs[] = { | ||
804 | /* Internal Mic, Mic */ | ||
805 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
806 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
807 | /* Line In,HP, Amp */ | ||
808 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
809 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
810 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
811 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
812 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
813 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
814 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
815 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
816 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
817 | /* Record selector: Internal mic */ | ||
818 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
819 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
820 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
821 | /* SPDIF route: PCM */ | ||
822 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
823 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
824 | /* EAPD */ | ||
825 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
826 | { } /* end */ | ||
827 | }; | ||
828 | |||
829 | static const struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
830 | /* pin sensing on HP jack */ | ||
831 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
832 | { } /* end */ | ||
833 | }; | ||
834 | |||
835 | static const struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
836 | /* pin sensing on HP jack */ | ||
837 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
838 | { } /* end */ | ||
839 | }; | ||
840 | |||
841 | #ifdef CONFIG_SND_DEBUG | ||
842 | /* Test configuration for debugging, modelled after the ALC260 test | ||
843 | * configuration. | ||
844 | */ | ||
845 | static const struct hda_input_mux cxt5045_test_capture_source = { | ||
846 | .num_items = 5, | ||
847 | .items = { | ||
848 | { "MIXER", 0x0 }, | ||
849 | { "MIC1 pin", 0x1 }, | ||
850 | { "LINE1 pin", 0x2 }, | ||
851 | { "HP-OUT pin", 0x3 }, | ||
852 | { "CD pin", 0x4 }, | ||
853 | }, | ||
854 | }; | ||
855 | |||
856 | static const struct snd_kcontrol_new cxt5045_test_mixer[] = { | ||
857 | |||
858 | /* Output controls */ | ||
859 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
860 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
861 | HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
862 | HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
863 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
864 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
865 | |||
866 | /* Modes for retasking pin widgets */ | ||
867 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | ||
868 | CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT), | ||
869 | |||
870 | /* EAPD Switch Control */ | ||
871 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | ||
872 | |||
873 | /* Loopback mixer controls */ | ||
874 | |||
875 | HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), | ||
876 | HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), | ||
877 | HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), | ||
878 | HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), | ||
879 | HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), | ||
880 | HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), | ||
881 | HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), | ||
882 | HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), | ||
883 | HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), | ||
884 | HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), | ||
885 | { | ||
886 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
887 | .name = "Input Source", | ||
888 | .info = conexant_mux_enum_info, | ||
889 | .get = conexant_mux_enum_get, | ||
890 | .put = conexant_mux_enum_put, | ||
891 | }, | ||
892 | /* Audio input controls */ | ||
893 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
894 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
895 | { } /* end */ | ||
896 | }; | ||
897 | |||
898 | static const struct hda_verb cxt5045_test_init_verbs[] = { | ||
899 | /* Set connections */ | ||
900 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
901 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
902 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
903 | /* Enable retasking pins as output, initially without power amp */ | ||
904 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
905 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
906 | |||
907 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
908 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
909 | * payload also sets the generation to 0, output to be in "consumer" | ||
910 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
911 | * control. | ||
912 | */ | ||
913 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
914 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
915 | |||
916 | /* Unmute retasking pin widget output buffers since the default | ||
917 | * state appears to be output. As the pin mode is changed by the | ||
918 | * user the pin mode control will take care of enabling the pin's | ||
919 | * input/output buffers as needed. | ||
920 | */ | ||
921 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
922 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
923 | |||
924 | /* Mute capture amp left and right */ | ||
925 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
926 | |||
927 | /* Set ADC connection select to match default mixer setting (mic1 | ||
928 | * pin) | ||
929 | */ | ||
930 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
931 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
932 | |||
933 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
934 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ | ||
935 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ | ||
936 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ | ||
937 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ | ||
938 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
939 | |||
940 | { } | ||
941 | }; | ||
942 | #endif | ||
943 | |||
944 | |||
945 | /* initialize jack-sensing, too */ | ||
946 | static int cxt5045_init(struct hda_codec *codec) | ||
947 | { | ||
948 | conexant_init(codec); | ||
949 | cxt5045_hp_automute(codec); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | |||
954 | enum { | ||
955 | CXT5045_LAPTOP_HPSENSE, | ||
956 | CXT5045_LAPTOP_MICSENSE, | ||
957 | CXT5045_LAPTOP_HPMICSENSE, | ||
958 | CXT5045_BENQ, | ||
959 | #ifdef CONFIG_SND_DEBUG | ||
960 | CXT5045_TEST, | ||
961 | #endif | ||
962 | CXT5045_AUTO, | ||
963 | CXT5045_MODELS | ||
964 | }; | ||
965 | |||
966 | static const char * const cxt5045_models[CXT5045_MODELS] = { | ||
967 | [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", | ||
968 | [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", | ||
969 | [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", | ||
970 | [CXT5045_BENQ] = "benq", | ||
971 | #ifdef CONFIG_SND_DEBUG | ||
972 | [CXT5045_TEST] = "test", | ||
973 | #endif | ||
974 | [CXT5045_AUTO] = "auto", | ||
975 | }; | ||
976 | |||
977 | static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { | ||
978 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | ||
979 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | ||
980 | SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), | ||
981 | SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", | ||
982 | CXT5045_LAPTOP_HPMICSENSE), | ||
983 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
984 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
985 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
986 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", | ||
987 | CXT5045_LAPTOP_HPMICSENSE), | ||
988 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | ||
989 | {} | ||
990 | }; | ||
991 | |||
992 | static int patch_cxt5045(struct hda_codec *codec) | ||
993 | { | ||
994 | struct conexant_spec *spec; | ||
995 | int board_config; | ||
996 | |||
997 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | ||
998 | cxt5045_models, | ||
999 | cxt5045_cfg_tbl); | ||
1000 | if (board_config < 0) | ||
1001 | board_config = CXT5045_AUTO; /* model=auto as default */ | ||
1002 | if (board_config == CXT5045_AUTO) | ||
1003 | return patch_conexant_auto(codec); | ||
1004 | |||
1005 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1006 | if (!spec) | ||
1007 | return -ENOMEM; | ||
1008 | codec->spec = spec; | ||
1009 | codec->single_adc_amp = 1; | ||
1010 | |||
1011 | spec->multiout.max_channels = 2; | ||
1012 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | ||
1013 | spec->multiout.dac_nids = cxt5045_dac_nids; | ||
1014 | spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT; | ||
1015 | spec->num_adc_nids = 1; | ||
1016 | spec->adc_nids = cxt5045_adc_nids; | ||
1017 | spec->capsrc_nids = cxt5045_capsrc_nids; | ||
1018 | spec->input_mux = &cxt5045_capture_source; | ||
1019 | spec->num_mixers = 1; | ||
1020 | spec->mixers[0] = cxt5045_mixers; | ||
1021 | spec->num_init_verbs = 1; | ||
1022 | spec->init_verbs[0] = cxt5045_init_verbs; | ||
1023 | spec->spdif_route = 0; | ||
1024 | spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes); | ||
1025 | spec->channel_mode = cxt5045_modes; | ||
1026 | |||
1027 | set_beep_amp(spec, 0x16, 0, 1); | ||
1028 | |||
1029 | codec->patch_ops = conexant_patch_ops; | ||
1030 | |||
1031 | switch (board_config) { | ||
1032 | case CXT5045_LAPTOP_HPSENSE: | ||
1033 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1034 | spec->input_mux = &cxt5045_capture_source; | ||
1035 | spec->num_init_verbs = 2; | ||
1036 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1037 | spec->mixers[0] = cxt5045_mixers; | ||
1038 | codec->patch_ops.init = cxt5045_init; | ||
1039 | break; | ||
1040 | case CXT5045_LAPTOP_MICSENSE: | ||
1041 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1042 | spec->input_mux = &cxt5045_capture_source; | ||
1043 | spec->num_init_verbs = 2; | ||
1044 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; | ||
1045 | spec->mixers[0] = cxt5045_mixers; | ||
1046 | codec->patch_ops.init = cxt5045_init; | ||
1047 | break; | ||
1048 | default: | ||
1049 | case CXT5045_LAPTOP_HPMICSENSE: | ||
1050 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1051 | spec->input_mux = &cxt5045_capture_source; | ||
1052 | spec->num_init_verbs = 3; | ||
1053 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1054 | spec->init_verbs[2] = cxt5045_mic_sense_init_verbs; | ||
1055 | spec->mixers[0] = cxt5045_mixers; | ||
1056 | codec->patch_ops.init = cxt5045_init; | ||
1057 | break; | ||
1058 | case CXT5045_BENQ: | ||
1059 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1060 | spec->input_mux = &cxt5045_capture_source_benq; | ||
1061 | spec->num_init_verbs = 1; | ||
1062 | spec->init_verbs[0] = cxt5045_benq_init_verbs; | ||
1063 | spec->mixers[0] = cxt5045_mixers; | ||
1064 | spec->mixers[1] = cxt5045_benq_mixers; | ||
1065 | spec->num_mixers = 2; | ||
1066 | codec->patch_ops.init = cxt5045_init; | ||
1067 | break; | ||
1068 | #ifdef CONFIG_SND_DEBUG | ||
1069 | case CXT5045_TEST: | ||
1070 | spec->input_mux = &cxt5045_test_capture_source; | ||
1071 | spec->mixers[0] = cxt5045_test_mixer; | ||
1072 | spec->init_verbs[0] = cxt5045_test_init_verbs; | ||
1073 | break; | ||
1074 | |||
1075 | #endif | ||
1076 | } | ||
1077 | |||
1078 | switch (codec->subsystem_id >> 16) { | ||
1079 | case 0x103c: | ||
1080 | case 0x1631: | ||
1081 | case 0x1734: | ||
1082 | case 0x17aa: | ||
1083 | /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have | ||
1084 | * really bad sound over 0dB on NID 0x17. Fix max PCM level to | ||
1085 | * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) | ||
1086 | */ | ||
1087 | snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, | ||
1088 | (0x14 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1089 | (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1090 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1091 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1092 | break; | ||
1093 | } | ||
1094 | |||
1095 | if (spec->beep_amp) | ||
1096 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | /* Conexant 5047 specific */ | ||
1103 | #define CXT5047_SPDIF_OUT 0x11 | ||
1104 | |||
1105 | static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ | ||
1106 | static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | ||
1107 | static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | ||
1108 | |||
1109 | static const struct hda_channel_mode cxt5047_modes[1] = { | ||
1110 | { 2, NULL }, | ||
1111 | }; | ||
1112 | |||
1113 | static const struct hda_input_mux cxt5047_toshiba_capture_source = { | ||
1114 | .num_items = 2, | ||
1115 | .items = { | ||
1116 | { "ExtMic", 0x2 }, | ||
1117 | { "Line-In", 0x1 }, | ||
1118 | } | ||
1119 | }; | ||
1120 | |||
1121 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1122 | static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1123 | struct snd_ctl_elem_value *ucontrol) | ||
1124 | { | ||
1125 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1126 | struct conexant_spec *spec = codec->spec; | ||
1127 | unsigned int bits; | ||
1128 | |||
1129 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1130 | return 0; | ||
1131 | |||
1132 | /* toggle internal speakers mute depending of presence of | ||
1133 | * the headphone jack | ||
1134 | */ | ||
1135 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
1136 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of | ||
1137 | * pin widgets unlike other codecs. In this case, we need to | ||
1138 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1139 | */ | ||
1140 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1141 | HDA_AMP_MUTE, bits); | ||
1142 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
1143 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | ||
1144 | HDA_AMP_MUTE, bits); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | /* mute internal speaker if HP is plugged */ | ||
1149 | static void cxt5047_hp_automute(struct hda_codec *codec) | ||
1150 | { | ||
1151 | struct conexant_spec *spec = codec->spec; | ||
1152 | unsigned int bits; | ||
1153 | |||
1154 | spec->hp_present = snd_hda_jack_detect(codec, 0x13); | ||
1155 | |||
1156 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
1157 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1158 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1159 | HDA_AMP_MUTE, bits); | ||
1160 | } | ||
1161 | |||
1162 | /* toggle input of built-in and mic jack appropriately */ | ||
1163 | static void cxt5047_hp_automic(struct hda_codec *codec) | ||
1164 | { | ||
1165 | static const struct hda_verb mic_jack_on[] = { | ||
1166 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1167 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1168 | {} | ||
1169 | }; | ||
1170 | static const struct hda_verb mic_jack_off[] = { | ||
1171 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1172 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1173 | {} | ||
1174 | }; | ||
1175 | unsigned int present; | ||
1176 | |||
1177 | present = snd_hda_jack_detect(codec, 0x15); | ||
1178 | if (present) | ||
1179 | snd_hda_sequence_write(codec, mic_jack_on); | ||
1180 | else | ||
1181 | snd_hda_sequence_write(codec, mic_jack_off); | ||
1182 | } | ||
1183 | |||
1184 | /* unsolicited event for HP jack sensing */ | ||
1185 | static void cxt5047_hp_unsol_event(struct hda_codec *codec, | ||
1186 | unsigned int res) | ||
1187 | { | ||
1188 | switch (res >> 26) { | ||
1189 | case CONEXANT_HP_EVENT: | ||
1190 | cxt5047_hp_automute(codec); | ||
1191 | break; | ||
1192 | case CONEXANT_MIC_EVENT: | ||
1193 | cxt5047_hp_automic(codec); | ||
1194 | break; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | static const struct snd_kcontrol_new cxt5047_base_mixers[] = { | ||
1199 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), | ||
1200 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), | ||
1201 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1202 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1203 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1204 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1205 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1206 | { | ||
1207 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1208 | .name = "Master Playback Switch", | ||
1209 | .info = cxt_eapd_info, | ||
1210 | .get = cxt_eapd_get, | ||
1211 | .put = cxt5047_hp_master_sw_put, | ||
1212 | .private_value = 0x13, | ||
1213 | }, | ||
1214 | |||
1215 | {} | ||
1216 | }; | ||
1217 | |||
1218 | static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { | ||
1219 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1220 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), | ||
1221 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1222 | {} | ||
1223 | }; | ||
1224 | |||
1225 | static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { | ||
1226 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1227 | { } /* end */ | ||
1228 | }; | ||
1229 | |||
1230 | static const struct hda_verb cxt5047_init_verbs[] = { | ||
1231 | /* Line in, Mic, Built-in Mic */ | ||
1232 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
1233 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1234 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1235 | /* HP, Speaker */ | ||
1236 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1237 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ | ||
1238 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ | ||
1239 | /* Record selector: Mic */ | ||
1240 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1241 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1242 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1243 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1244 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1245 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1246 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1247 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1248 | /* SPDIF route: PCM */ | ||
1249 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
1250 | /* Enable unsolicited events */ | ||
1251 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1252 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1253 | { } /* end */ | ||
1254 | }; | ||
1255 | |||
1256 | /* configuration for Toshiba Laptops */ | ||
1257 | static const struct hda_verb cxt5047_toshiba_init_verbs[] = { | ||
1258 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ | ||
1259 | {} | ||
1260 | }; | ||
1261 | |||
1262 | /* Test configuration for debugging, modelled after the ALC260 test | ||
1263 | * configuration. | ||
1264 | */ | ||
1265 | #ifdef CONFIG_SND_DEBUG | ||
1266 | static const struct hda_input_mux cxt5047_test_capture_source = { | ||
1267 | .num_items = 4, | ||
1268 | .items = { | ||
1269 | { "LINE1 pin", 0x0 }, | ||
1270 | { "MIC1 pin", 0x1 }, | ||
1271 | { "MIC2 pin", 0x2 }, | ||
1272 | { "CD pin", 0x3 }, | ||
1273 | }, | ||
1274 | }; | ||
1275 | |||
1276 | static const struct snd_kcontrol_new cxt5047_test_mixer[] = { | ||
1277 | |||
1278 | /* Output only controls */ | ||
1279 | HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), | ||
1280 | HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT), | ||
1281 | HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
1282 | HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
1283 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
1284 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
1285 | HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
1286 | HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
1287 | HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT), | ||
1288 | HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
1289 | HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1291 | |||
1292 | /* Modes for retasking pin widgets */ | ||
1293 | CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT), | ||
1294 | CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT), | ||
1295 | |||
1296 | /* EAPD Switch Control */ | ||
1297 | CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0), | ||
1298 | |||
1299 | /* Loopback mixer controls */ | ||
1300 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT), | ||
1301 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT), | ||
1302 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT), | ||
1303 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT), | ||
1304 | HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT), | ||
1305 | HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT), | ||
1306 | HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT), | ||
1307 | HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT), | ||
1308 | |||
1309 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT), | ||
1310 | HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT), | ||
1311 | HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT), | ||
1312 | HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT), | ||
1313 | HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT), | ||
1314 | HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT), | ||
1315 | HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT), | ||
1316 | HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT), | ||
1317 | { | ||
1318 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1319 | .name = "Input Source", | ||
1320 | .info = conexant_mux_enum_info, | ||
1321 | .get = conexant_mux_enum_get, | ||
1322 | .put = conexant_mux_enum_put, | ||
1323 | }, | ||
1324 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1325 | |||
1326 | { } /* end */ | ||
1327 | }; | ||
1328 | |||
1329 | static const struct hda_verb cxt5047_test_init_verbs[] = { | ||
1330 | /* Enable retasking pins as output, initially without power amp */ | ||
1331 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1332 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1333 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1334 | |||
1335 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
1336 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
1337 | * payload also sets the generation to 0, output to be in "consumer" | ||
1338 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
1339 | * control. | ||
1340 | */ | ||
1341 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
1342 | |||
1343 | /* Ensure mic1, mic2, line1 pin widgets take input from the | ||
1344 | * OUT1 sum bus when acting as an output. | ||
1345 | */ | ||
1346 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1347 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1348 | |||
1349 | /* Start with output sum widgets muted and their output gains at min */ | ||
1350 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1351 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1352 | |||
1353 | /* Unmute retasking pin widget output buffers since the default | ||
1354 | * state appears to be output. As the pin mode is changed by the | ||
1355 | * user the pin mode control will take care of enabling the pin's | ||
1356 | * input/output buffers as needed. | ||
1357 | */ | ||
1358 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1360 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1361 | |||
1362 | /* Mute capture amp left and right */ | ||
1363 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1364 | |||
1365 | /* Set ADC connection select to match default mixer setting (mic1 | ||
1366 | * pin) | ||
1367 | */ | ||
1368 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1369 | |||
1370 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
1371 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
1372 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
1373 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
1374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
1375 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
1376 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
1377 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
1378 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
1379 | |||
1380 | { } | ||
1381 | }; | ||
1382 | #endif | ||
1383 | |||
1384 | |||
1385 | /* initialize jack-sensing, too */ | ||
1386 | static int cxt5047_hp_init(struct hda_codec *codec) | ||
1387 | { | ||
1388 | conexant_init(codec); | ||
1389 | cxt5047_hp_automute(codec); | ||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | |||
1394 | enum { | ||
1395 | CXT5047_LAPTOP, /* Laptops w/o EAPD support */ | ||
1396 | CXT5047_LAPTOP_HP, /* Some HP laptops */ | ||
1397 | CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */ | ||
1398 | #ifdef CONFIG_SND_DEBUG | ||
1399 | CXT5047_TEST, | ||
1400 | #endif | ||
1401 | CXT5047_AUTO, | ||
1402 | CXT5047_MODELS | ||
1403 | }; | ||
1404 | |||
1405 | static const char * const cxt5047_models[CXT5047_MODELS] = { | ||
1406 | [CXT5047_LAPTOP] = "laptop", | ||
1407 | [CXT5047_LAPTOP_HP] = "laptop-hp", | ||
1408 | [CXT5047_LAPTOP_EAPD] = "laptop-eapd", | ||
1409 | #ifdef CONFIG_SND_DEBUG | ||
1410 | [CXT5047_TEST] = "test", | ||
1411 | #endif | ||
1412 | [CXT5047_AUTO] = "auto", | ||
1413 | }; | ||
1414 | |||
1415 | static const struct snd_pci_quirk cxt5047_cfg_tbl[] = { | ||
1416 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | ||
1417 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", | ||
1418 | CXT5047_LAPTOP), | ||
1419 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | ||
1420 | {} | ||
1421 | }; | ||
1422 | |||
1423 | static int patch_cxt5047(struct hda_codec *codec) | ||
1424 | { | ||
1425 | struct conexant_spec *spec; | ||
1426 | int board_config; | ||
1427 | |||
1428 | board_config = snd_hda_check_board_config(codec, CXT5047_MODELS, | ||
1429 | cxt5047_models, | ||
1430 | cxt5047_cfg_tbl); | ||
1431 | if (board_config < 0) | ||
1432 | board_config = CXT5047_AUTO; /* model=auto as default */ | ||
1433 | if (board_config == CXT5047_AUTO) | ||
1434 | return patch_conexant_auto(codec); | ||
1435 | |||
1436 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1437 | if (!spec) | ||
1438 | return -ENOMEM; | ||
1439 | codec->spec = spec; | ||
1440 | codec->pin_amp_workaround = 1; | ||
1441 | |||
1442 | spec->multiout.max_channels = 2; | ||
1443 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | ||
1444 | spec->multiout.dac_nids = cxt5047_dac_nids; | ||
1445 | spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT; | ||
1446 | spec->num_adc_nids = 1; | ||
1447 | spec->adc_nids = cxt5047_adc_nids; | ||
1448 | spec->capsrc_nids = cxt5047_capsrc_nids; | ||
1449 | spec->num_mixers = 1; | ||
1450 | spec->mixers[0] = cxt5047_base_mixers; | ||
1451 | spec->num_init_verbs = 1; | ||
1452 | spec->init_verbs[0] = cxt5047_init_verbs; | ||
1453 | spec->spdif_route = 0; | ||
1454 | spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes), | ||
1455 | spec->channel_mode = cxt5047_modes, | ||
1456 | |||
1457 | codec->patch_ops = conexant_patch_ops; | ||
1458 | |||
1459 | switch (board_config) { | ||
1460 | case CXT5047_LAPTOP: | ||
1461 | spec->num_mixers = 2; | ||
1462 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1463 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1464 | break; | ||
1465 | case CXT5047_LAPTOP_HP: | ||
1466 | spec->num_mixers = 2; | ||
1467 | spec->mixers[1] = cxt5047_hp_only_mixers; | ||
1468 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1469 | codec->patch_ops.init = cxt5047_hp_init; | ||
1470 | break; | ||
1471 | case CXT5047_LAPTOP_EAPD: | ||
1472 | spec->input_mux = &cxt5047_toshiba_capture_source; | ||
1473 | spec->num_mixers = 2; | ||
1474 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1475 | spec->num_init_verbs = 2; | ||
1476 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | ||
1477 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1478 | break; | ||
1479 | #ifdef CONFIG_SND_DEBUG | ||
1480 | case CXT5047_TEST: | ||
1481 | spec->input_mux = &cxt5047_test_capture_source; | ||
1482 | spec->mixers[0] = cxt5047_test_mixer; | ||
1483 | spec->init_verbs[0] = cxt5047_test_init_verbs; | ||
1484 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1485 | #endif | ||
1486 | } | ||
1487 | spec->vmaster_nid = 0x13; | ||
1488 | |||
1489 | switch (codec->subsystem_id >> 16) { | ||
1490 | case 0x103c: | ||
1491 | /* HP laptops have really bad sound over 0 dB on NID 0x10. | ||
1492 | * Fix max PCM level to 0 dB (originally it has 0x1e steps | ||
1493 | * with 0 dB offset 0x17) | ||
1494 | */ | ||
1495 | snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, | ||
1496 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1497 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1498 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1499 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1500 | break; | ||
1501 | } | ||
1502 | |||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1506 | /* Conexant 5051 specific */ | ||
1507 | static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; | ||
1508 | static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; | ||
1509 | |||
1510 | static const struct hda_channel_mode cxt5051_modes[1] = { | ||
1511 | { 2, NULL }, | ||
1512 | }; | ||
1513 | |||
1514 | static void cxt5051_update_speaker(struct hda_codec *codec) | ||
1515 | { | ||
1516 | struct conexant_spec *spec = codec->spec; | ||
1517 | unsigned int pinctl; | ||
1518 | /* headphone pin */ | ||
1519 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | ||
1520 | snd_hda_set_pin_ctl(codec, 0x16, pinctl); | ||
1521 | /* speaker pin */ | ||
1522 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1523 | snd_hda_set_pin_ctl(codec, 0x1a, pinctl); | ||
1524 | /* on ideapad there is an additional speaker (subwoofer) to mute */ | ||
1525 | if (spec->ideapad) | ||
1526 | snd_hda_set_pin_ctl(codec, 0x1b, pinctl); | ||
1527 | } | ||
1528 | |||
1529 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1530 | static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1531 | struct snd_ctl_elem_value *ucontrol) | ||
1532 | { | ||
1533 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1534 | |||
1535 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1536 | return 0; | ||
1537 | cxt5051_update_speaker(codec); | ||
1538 | return 1; | ||
1539 | } | ||
1540 | |||
1541 | /* toggle input of built-in and mic jack appropriately */ | ||
1542 | static void cxt5051_portb_automic(struct hda_codec *codec) | ||
1543 | { | ||
1544 | struct conexant_spec *spec = codec->spec; | ||
1545 | unsigned int present; | ||
1546 | |||
1547 | if (!(spec->auto_mic & AUTO_MIC_PORTB)) | ||
1548 | return; | ||
1549 | present = snd_hda_jack_detect(codec, 0x17); | ||
1550 | snd_hda_codec_write(codec, 0x14, 0, | ||
1551 | AC_VERB_SET_CONNECT_SEL, | ||
1552 | present ? 0x01 : 0x00); | ||
1553 | } | ||
1554 | |||
1555 | /* switch the current ADC according to the jack state */ | ||
1556 | static void cxt5051_portc_automic(struct hda_codec *codec) | ||
1557 | { | ||
1558 | struct conexant_spec *spec = codec->spec; | ||
1559 | unsigned int present; | ||
1560 | hda_nid_t new_adc; | ||
1561 | |||
1562 | if (!(spec->auto_mic & AUTO_MIC_PORTC)) | ||
1563 | return; | ||
1564 | present = snd_hda_jack_detect(codec, 0x18); | ||
1565 | if (present) | ||
1566 | spec->cur_adc_idx = 1; | ||
1567 | else | ||
1568 | spec->cur_adc_idx = 0; | ||
1569 | new_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
1570 | if (spec->cur_adc && spec->cur_adc != new_adc) { | ||
1571 | /* stream is running, let's swap the current ADC */ | ||
1572 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
1573 | spec->cur_adc = new_adc; | ||
1574 | snd_hda_codec_setup_stream(codec, new_adc, | ||
1575 | spec->cur_adc_stream_tag, 0, | ||
1576 | spec->cur_adc_format); | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | /* mute internal speaker if HP is plugged */ | ||
1581 | static void cxt5051_hp_automute(struct hda_codec *codec) | ||
1582 | { | ||
1583 | struct conexant_spec *spec = codec->spec; | ||
1584 | |||
1585 | spec->hp_present = snd_hda_jack_detect(codec, 0x16); | ||
1586 | cxt5051_update_speaker(codec); | ||
1587 | } | ||
1588 | |||
1589 | /* unsolicited event for HP jack sensing */ | ||
1590 | static void cxt5051_hp_unsol_event(struct hda_codec *codec, | ||
1591 | unsigned int res) | ||
1592 | { | ||
1593 | switch (res >> 26) { | ||
1594 | case CONEXANT_HP_EVENT: | ||
1595 | cxt5051_hp_automute(codec); | ||
1596 | break; | ||
1597 | case CXT5051_PORTB_EVENT: | ||
1598 | cxt5051_portb_automic(codec); | ||
1599 | break; | ||
1600 | case CXT5051_PORTC_EVENT: | ||
1601 | cxt5051_portc_automic(codec); | ||
1602 | break; | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | static const struct snd_kcontrol_new cxt5051_playback_mixers[] = { | ||
1607 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1608 | { | ||
1609 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1610 | .name = "Master Playback Switch", | ||
1611 | .info = cxt_eapd_info, | ||
1612 | .get = cxt_eapd_get, | ||
1613 | .put = cxt5051_hp_master_sw_put, | ||
1614 | .private_value = 0x1a, | ||
1615 | }, | ||
1616 | {} | ||
1617 | }; | ||
1618 | |||
1619 | static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { | ||
1620 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1621 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1622 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1623 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1624 | HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1625 | HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1626 | {} | ||
1627 | }; | ||
1628 | |||
1629 | static const struct snd_kcontrol_new cxt5051_hp_mixers[] = { | ||
1630 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1631 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1632 | HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1633 | HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1634 | {} | ||
1635 | }; | ||
1636 | |||
1637 | static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1638 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), | ||
1639 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), | ||
1640 | {} | ||
1641 | }; | ||
1642 | |||
1643 | static const struct snd_kcontrol_new cxt5051_f700_mixers[] = { | ||
1644 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), | ||
1645 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), | ||
1646 | {} | ||
1647 | }; | ||
1648 | |||
1649 | static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { | ||
1650 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1651 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1652 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1653 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1654 | {} | ||
1655 | }; | ||
1656 | |||
1657 | static const struct hda_verb cxt5051_init_verbs[] = { | ||
1658 | /* Line in, Mic */ | ||
1659 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1660 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1661 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1662 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1663 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1664 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1665 | /* SPK */ | ||
1666 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1667 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1668 | /* HP, Amp */ | ||
1669 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1670 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1671 | /* DAC1 */ | ||
1672 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1673 | /* Record selector: Internal mic */ | ||
1674 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1675 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1676 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1677 | /* SPDIF route: PCM */ | ||
1678 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1679 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1680 | /* EAPD */ | ||
1681 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1682 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1683 | { } /* end */ | ||
1684 | }; | ||
1685 | |||
1686 | static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1687 | /* Line in, Mic */ | ||
1688 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1689 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1690 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1691 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1692 | /* SPK */ | ||
1693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1694 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1695 | /* HP, Amp */ | ||
1696 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1697 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1698 | /* DAC1 */ | ||
1699 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1700 | /* Record selector: Internal mic */ | ||
1701 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1702 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1703 | /* SPDIF route: PCM */ | ||
1704 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1705 | /* EAPD */ | ||
1706 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1707 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1708 | { } /* end */ | ||
1709 | }; | ||
1710 | |||
1711 | static const struct hda_verb cxt5051_f700_init_verbs[] = { | ||
1712 | /* Line in, Mic */ | ||
1713 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1714 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1715 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1716 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1717 | /* SPK */ | ||
1718 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1719 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1720 | /* HP, Amp */ | ||
1721 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1722 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1723 | /* DAC1 */ | ||
1724 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1725 | /* Record selector: Internal mic */ | ||
1726 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1727 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1728 | /* SPDIF route: PCM */ | ||
1729 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1730 | /* EAPD */ | ||
1731 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1732 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1733 | { } /* end */ | ||
1734 | }; | ||
1735 | |||
1736 | static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | ||
1737 | unsigned int event) | ||
1738 | { | ||
1739 | snd_hda_codec_write(codec, nid, 0, | ||
1740 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1741 | AC_USRSP_EN | event); | ||
1742 | } | ||
1743 | |||
1744 | static const struct hda_verb cxt5051_ideapad_init_verbs[] = { | ||
1745 | /* Subwoofer */ | ||
1746 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1747 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1748 | { } /* end */ | ||
1749 | }; | ||
1750 | |||
1751 | /* initialize jack-sensing, too */ | ||
1752 | static int cxt5051_init(struct hda_codec *codec) | ||
1753 | { | ||
1754 | struct conexant_spec *spec = codec->spec; | ||
1755 | |||
1756 | conexant_init(codec); | ||
1757 | |||
1758 | if (spec->auto_mic & AUTO_MIC_PORTB) | ||
1759 | cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); | ||
1760 | if (spec->auto_mic & AUTO_MIC_PORTC) | ||
1761 | cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); | ||
1762 | |||
1763 | if (codec->patch_ops.unsol_event) { | ||
1764 | cxt5051_hp_automute(codec); | ||
1765 | cxt5051_portb_automic(codec); | ||
1766 | cxt5051_portc_automic(codec); | ||
1767 | } | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | |||
1772 | enum { | ||
1773 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | ||
1774 | CXT5051_HP, /* no docking */ | ||
1775 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1776 | CXT5051_F700, /* HP Compaq Presario F700 */ | ||
1777 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | ||
1778 | CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ | ||
1779 | CXT5051_AUTO, /* auto-parser */ | ||
1780 | CXT5051_MODELS | ||
1781 | }; | ||
1782 | |||
1783 | static const char *const cxt5051_models[CXT5051_MODELS] = { | ||
1784 | [CXT5051_LAPTOP] = "laptop", | ||
1785 | [CXT5051_HP] = "hp", | ||
1786 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1787 | [CXT5051_F700] = "hp-700", | ||
1788 | [CXT5051_TOSHIBA] = "toshiba", | ||
1789 | [CXT5051_IDEAPAD] = "ideapad", | ||
1790 | [CXT5051_AUTO] = "auto", | ||
1791 | }; | ||
1792 | |||
1793 | static const struct snd_pci_quirk cxt5051_cfg_tbl[] = { | ||
1794 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1795 | SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), | ||
1796 | SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), | ||
1797 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), | ||
1798 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
1799 | CXT5051_LAPTOP), | ||
1800 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | ||
1801 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), | ||
1802 | {} | ||
1803 | }; | ||
1804 | |||
1805 | static int patch_cxt5051(struct hda_codec *codec) | ||
1806 | { | ||
1807 | struct conexant_spec *spec; | ||
1808 | int board_config; | ||
1809 | |||
1810 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | ||
1811 | cxt5051_models, | ||
1812 | cxt5051_cfg_tbl); | ||
1813 | if (board_config < 0) | ||
1814 | board_config = CXT5051_AUTO; /* model=auto as default */ | ||
1815 | if (board_config == CXT5051_AUTO) | ||
1816 | return patch_conexant_auto(codec); | ||
1817 | |||
1818 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1819 | if (!spec) | ||
1820 | return -ENOMEM; | ||
1821 | codec->spec = spec; | ||
1822 | codec->pin_amp_workaround = 1; | ||
1823 | |||
1824 | codec->patch_ops = conexant_patch_ops; | ||
1825 | codec->patch_ops.init = cxt5051_init; | ||
1826 | |||
1827 | spec->multiout.max_channels = 2; | ||
1828 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids); | ||
1829 | spec->multiout.dac_nids = cxt5051_dac_nids; | ||
1830 | spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; | ||
1831 | spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ | ||
1832 | spec->adc_nids = cxt5051_adc_nids; | ||
1833 | spec->num_mixers = 2; | ||
1834 | spec->mixers[0] = cxt5051_capture_mixers; | ||
1835 | spec->mixers[1] = cxt5051_playback_mixers; | ||
1836 | spec->num_init_verbs = 1; | ||
1837 | spec->init_verbs[0] = cxt5051_init_verbs; | ||
1838 | spec->spdif_route = 0; | ||
1839 | spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes); | ||
1840 | spec->channel_mode = cxt5051_modes; | ||
1841 | spec->cur_adc = 0; | ||
1842 | spec->cur_adc_idx = 0; | ||
1843 | |||
1844 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
1845 | |||
1846 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1847 | |||
1848 | spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; | ||
1849 | switch (board_config) { | ||
1850 | case CXT5051_HP: | ||
1851 | spec->mixers[0] = cxt5051_hp_mixers; | ||
1852 | break; | ||
1853 | case CXT5051_HP_DV6736: | ||
1854 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; | ||
1855 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; | ||
1856 | spec->auto_mic = 0; | ||
1857 | break; | ||
1858 | case CXT5051_F700: | ||
1859 | spec->init_verbs[0] = cxt5051_f700_init_verbs; | ||
1860 | spec->mixers[0] = cxt5051_f700_mixers; | ||
1861 | spec->auto_mic = 0; | ||
1862 | break; | ||
1863 | case CXT5051_TOSHIBA: | ||
1864 | spec->mixers[0] = cxt5051_toshiba_mixers; | ||
1865 | spec->auto_mic = AUTO_MIC_PORTB; | ||
1866 | break; | ||
1867 | case CXT5051_IDEAPAD: | ||
1868 | spec->init_verbs[spec->num_init_verbs++] = | ||
1869 | cxt5051_ideapad_init_verbs; | ||
1870 | spec->ideapad = 1; | ||
1871 | break; | ||
1872 | } | ||
1873 | |||
1874 | if (spec->beep_amp) | ||
1875 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1876 | |||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | /* Conexant 5066 specific */ | ||
1881 | |||
1882 | static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; | ||
1883 | static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; | ||
1884 | static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; | ||
1885 | static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; | ||
1886 | |||
1887 | static const struct hda_channel_mode cxt5066_modes[1] = { | ||
1888 | { 2, NULL }, | ||
1889 | }; | ||
1890 | |||
1891 | #define HP_PRESENT_PORT_A (1 << 0) | ||
1892 | #define HP_PRESENT_PORT_D (1 << 1) | ||
1893 | #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) | ||
1894 | #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) | ||
1895 | |||
1896 | static void cxt5066_update_speaker(struct hda_codec *codec) | ||
1897 | { | ||
1898 | struct conexant_spec *spec = codec->spec; | ||
1899 | unsigned int pinctl; | ||
1900 | |||
1901 | codec_dbg(codec, | ||
1902 | "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", | ||
1903 | spec->hp_present, spec->cur_eapd); | ||
1904 | |||
1905 | /* Port A (HP) */ | ||
1906 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; | ||
1907 | snd_hda_set_pin_ctl(codec, 0x19, pinctl); | ||
1908 | |||
1909 | /* Port D (HP/LO) */ | ||
1910 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; | ||
1911 | if (spec->dell_automute || spec->thinkpad) { | ||
1912 | /* Mute if Port A is connected */ | ||
1913 | if (hp_port_a_present(spec)) | ||
1914 | pinctl = 0; | ||
1915 | } else { | ||
1916 | /* Thinkpad/Dell doesn't give pin-D status */ | ||
1917 | if (!hp_port_d_present(spec)) | ||
1918 | pinctl = 0; | ||
1919 | } | ||
1920 | snd_hda_set_pin_ctl(codec, 0x1c, pinctl); | ||
1921 | |||
1922 | /* CLASS_D AMP */ | ||
1923 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1924 | snd_hda_set_pin_ctl(codec, 0x1f, pinctl); | ||
1925 | } | ||
1926 | |||
1927 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1928 | static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1929 | struct snd_ctl_elem_value *ucontrol) | ||
1930 | { | ||
1931 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1932 | |||
1933 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1934 | return 0; | ||
1935 | |||
1936 | cxt5066_update_speaker(codec); | ||
1937 | return 1; | ||
1938 | } | ||
1939 | |||
1940 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1941 | static void cxt5066_vostro_automic(struct hda_codec *codec) | ||
1942 | { | ||
1943 | unsigned int present; | ||
1944 | |||
1945 | struct hda_verb ext_mic_present[] = { | ||
1946 | /* enable external mic, port B */ | ||
1947 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1948 | |||
1949 | /* switch to external mic input */ | ||
1950 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1951 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1952 | |||
1953 | /* disable internal digital mic */ | ||
1954 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1955 | {} | ||
1956 | }; | ||
1957 | static const struct hda_verb ext_mic_absent[] = { | ||
1958 | /* enable internal mic, port C */ | ||
1959 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1960 | |||
1961 | /* switch to internal mic input */ | ||
1962 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1963 | |||
1964 | /* disable external mic, port B */ | ||
1965 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1966 | {} | ||
1967 | }; | ||
1968 | |||
1969 | present = snd_hda_jack_detect(codec, 0x1a); | ||
1970 | if (present) { | ||
1971 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
1972 | snd_hda_sequence_write(codec, ext_mic_present); | ||
1973 | } else { | ||
1974 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
1975 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
1976 | } | ||
1977 | } | ||
1978 | |||
1979 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1980 | static void cxt5066_ideapad_automic(struct hda_codec *codec) | ||
1981 | { | ||
1982 | unsigned int present; | ||
1983 | |||
1984 | struct hda_verb ext_mic_present[] = { | ||
1985 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1986 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1987 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1988 | {} | ||
1989 | }; | ||
1990 | static const struct hda_verb ext_mic_absent[] = { | ||
1991 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1992 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1993 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1994 | {} | ||
1995 | }; | ||
1996 | |||
1997 | present = snd_hda_jack_detect(codec, 0x1b); | ||
1998 | if (present) { | ||
1999 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2000 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2001 | } else { | ||
2002 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2003 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2009 | static void cxt5066_asus_automic(struct hda_codec *codec) | ||
2010 | { | ||
2011 | unsigned int present; | ||
2012 | |||
2013 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2014 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2015 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2016 | present ? 1 : 0); | ||
2017 | } | ||
2018 | |||
2019 | |||
2020 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2021 | static void cxt5066_hp_laptop_automic(struct hda_codec *codec) | ||
2022 | { | ||
2023 | unsigned int present; | ||
2024 | |||
2025 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2026 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2027 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2028 | present ? 1 : 3); | ||
2029 | } | ||
2030 | |||
2031 | |||
2032 | /* toggle input of built-in digital mic and mic jack appropriately | ||
2033 | order is: external mic -> dock mic -> interal mic */ | ||
2034 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) | ||
2035 | { | ||
2036 | unsigned int ext_present, dock_present; | ||
2037 | |||
2038 | static const struct hda_verb ext_mic_present[] = { | ||
2039 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2040 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | ||
2041 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2042 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2043 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2044 | {} | ||
2045 | }; | ||
2046 | static const struct hda_verb dock_mic_present[] = { | ||
2047 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2048 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2049 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2050 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2051 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2052 | {} | ||
2053 | }; | ||
2054 | static const struct hda_verb ext_mic_absent[] = { | ||
2055 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
2056 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2057 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2058 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2059 | {} | ||
2060 | }; | ||
2061 | |||
2062 | ext_present = snd_hda_jack_detect(codec, 0x1b); | ||
2063 | dock_present = snd_hda_jack_detect(codec, 0x1a); | ||
2064 | if (ext_present) { | ||
2065 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2066 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2067 | } else if (dock_present) { | ||
2068 | codec_dbg(codec, "CXT5066: dock microphone detected\n"); | ||
2069 | snd_hda_sequence_write(codec, dock_mic_present); | ||
2070 | } else { | ||
2071 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2072 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2073 | } | ||
2074 | } | ||
2075 | |||
2076 | /* mute internal speaker if HP is plugged */ | ||
2077 | static void cxt5066_hp_automute(struct hda_codec *codec) | ||
2078 | { | ||
2079 | struct conexant_spec *spec = codec->spec; | ||
2080 | unsigned int portA, portD; | ||
2081 | |||
2082 | /* Port A */ | ||
2083 | portA = snd_hda_jack_detect(codec, 0x19); | ||
2084 | |||
2085 | /* Port D */ | ||
2086 | portD = snd_hda_jack_detect(codec, 0x1c); | ||
2087 | |||
2088 | spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; | ||
2089 | spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; | ||
2090 | codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n", | ||
2091 | portA, portD, spec->hp_present); | ||
2092 | cxt5066_update_speaker(codec); | ||
2093 | } | ||
2094 | |||
2095 | /* Dispatch the right mic autoswitch function */ | ||
2096 | static void cxt5066_automic(struct hda_codec *codec) | ||
2097 | { | ||
2098 | struct conexant_spec *spec = codec->spec; | ||
2099 | |||
2100 | if (spec->dell_vostro) | ||
2101 | cxt5066_vostro_automic(codec); | ||
2102 | else if (spec->ideapad) | ||
2103 | cxt5066_ideapad_automic(codec); | ||
2104 | else if (spec->thinkpad) | ||
2105 | cxt5066_thinkpad_automic(codec); | ||
2106 | else if (spec->hp_laptop) | ||
2107 | cxt5066_hp_laptop_automic(codec); | ||
2108 | else if (spec->asus) | ||
2109 | cxt5066_asus_automic(codec); | ||
2110 | } | ||
2111 | |||
2112 | /* unsolicited event for jack sensing */ | ||
2113 | static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) | ||
2114 | { | ||
2115 | codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26); | ||
2116 | switch (res >> 26) { | ||
2117 | case CONEXANT_HP_EVENT: | ||
2118 | cxt5066_hp_automute(codec); | ||
2119 | break; | ||
2120 | case CONEXANT_MIC_EVENT: | ||
2121 | cxt5066_automic(codec); | ||
2122 | break; | ||
2123 | } | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | ||
2128 | .num_items = 5, | ||
2129 | .items = { | ||
2130 | { "0dB", 0 }, | ||
2131 | { "10dB", 1 }, | ||
2132 | { "20dB", 2 }, | ||
2133 | { "30dB", 3 }, | ||
2134 | { "40dB", 4 }, | ||
2135 | }, | ||
2136 | }; | ||
2137 | |||
2138 | static void cxt5066_set_mic_boost(struct hda_codec *codec) | ||
2139 | { | ||
2140 | struct conexant_spec *spec = codec->spec; | ||
2141 | snd_hda_codec_write_cache(codec, 0x17, 0, | ||
2142 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2143 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | ||
2144 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | ||
2145 | if (spec->ideapad || spec->thinkpad) { | ||
2146 | /* adjust the internal mic as well...it is not through 0x17 */ | ||
2147 | snd_hda_codec_write_cache(codec, 0x23, 0, | ||
2148 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2149 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | | ||
2150 | cxt5066_analog_mic_boost. | ||
2151 | items[spec->mic_boost].index); | ||
2152 | } | ||
2153 | } | ||
2154 | |||
2155 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
2156 | struct snd_ctl_elem_info *uinfo) | ||
2157 | { | ||
2158 | return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo); | ||
2159 | } | ||
2160 | |||
2161 | static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
2162 | struct snd_ctl_elem_value *ucontrol) | ||
2163 | { | ||
2164 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2165 | struct conexant_spec *spec = codec->spec; | ||
2166 | ucontrol->value.enumerated.item[0] = spec->mic_boost; | ||
2167 | return 0; | ||
2168 | } | ||
2169 | |||
2170 | static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
2171 | struct snd_ctl_elem_value *ucontrol) | ||
2172 | { | ||
2173 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2174 | struct conexant_spec *spec = codec->spec; | ||
2175 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | ||
2176 | unsigned int idx; | ||
2177 | idx = ucontrol->value.enumerated.item[0]; | ||
2178 | if (idx >= imux->num_items) | ||
2179 | idx = imux->num_items - 1; | ||
2180 | |||
2181 | spec->mic_boost = idx; | ||
2182 | cxt5066_set_mic_boost(codec); | ||
2183 | return 1; | ||
2184 | } | ||
2185 | |||
2186 | static void conexant_check_dig_outs(struct hda_codec *codec, | ||
2187 | const hda_nid_t *dig_pins, | ||
2188 | int num_pins) | ||
2189 | { | ||
2190 | struct conexant_spec *spec = codec->spec; | ||
2191 | hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; | ||
2192 | int i; | ||
2193 | |||
2194 | for (i = 0; i < num_pins; i++, dig_pins++) { | ||
2195 | unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); | ||
2196 | if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) | ||
2197 | continue; | ||
2198 | if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) | ||
2199 | continue; | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2203 | static const struct hda_input_mux cxt5066_capture_source = { | ||
2204 | .num_items = 4, | ||
2205 | .items = { | ||
2206 | { "Mic B", 0 }, | ||
2207 | { "Mic C", 1 }, | ||
2208 | { "Mic E", 2 }, | ||
2209 | { "Mic F", 3 }, | ||
2210 | }, | ||
2211 | }; | ||
2212 | |||
2213 | static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = { | ||
2214 | .ops = &snd_hda_bind_vol, | ||
2215 | .values = { | ||
2216 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2217 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2218 | 0 | ||
2219 | }, | ||
2220 | }; | ||
2221 | |||
2222 | static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = { | ||
2223 | .ops = &snd_hda_bind_sw, | ||
2224 | .values = { | ||
2225 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2226 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2227 | 0 | ||
2228 | }, | ||
2229 | }; | ||
2230 | |||
2231 | static const struct snd_kcontrol_new cxt5066_mixer_master[] = { | ||
2232 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
2233 | {} | ||
2234 | }; | ||
2235 | |||
2236 | static const struct snd_kcontrol_new cxt5066_mixers[] = { | ||
2237 | { | ||
2238 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2239 | .name = "Master Playback Switch", | ||
2240 | .info = cxt_eapd_info, | ||
2241 | .get = cxt_eapd_get, | ||
2242 | .put = cxt5066_hp_master_sw_put, | ||
2243 | .private_value = 0x1d, | ||
2244 | }, | ||
2245 | |||
2246 | { | ||
2247 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2248 | .name = "Analog Mic Boost Capture Enum", | ||
2249 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2250 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2251 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2252 | }, | ||
2253 | |||
2254 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), | ||
2255 | HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others), | ||
2256 | {} | ||
2257 | }; | ||
2258 | |||
2259 | static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = { | ||
2260 | { | ||
2261 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2262 | .name = "Internal Mic Boost Capture Enum", | ||
2263 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2264 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2265 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2266 | .private_value = 0x23 | 0x100, | ||
2267 | }, | ||
2268 | {} | ||
2269 | }; | ||
2270 | |||
2271 | static const struct hda_verb cxt5066_init_verbs[] = { | ||
2272 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2273 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2274 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2275 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2276 | |||
2277 | /* Speakers */ | ||
2278 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2279 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2280 | |||
2281 | /* HP, Amp */ | ||
2282 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2283 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2284 | |||
2285 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2286 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2287 | |||
2288 | /* DAC1 */ | ||
2289 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2290 | |||
2291 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2292 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2293 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2294 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2295 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2296 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2297 | |||
2298 | /* no digital microphone support yet */ | ||
2299 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2300 | |||
2301 | /* Audio input selector */ | ||
2302 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2303 | |||
2304 | /* SPDIF route: PCM */ | ||
2305 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2306 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2307 | |||
2308 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2309 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2310 | |||
2311 | /* EAPD */ | ||
2312 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2313 | |||
2314 | /* not handling these yet */ | ||
2315 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2316 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2317 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2318 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2319 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2320 | {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2321 | {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2322 | {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2323 | { } /* end */ | ||
2324 | }; | ||
2325 | |||
2326 | static const struct hda_verb cxt5066_init_verbs_vostro[] = { | ||
2327 | /* Port A: headphones */ | ||
2328 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2329 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2330 | |||
2331 | /* Port B: external microphone */ | ||
2332 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2333 | |||
2334 | /* Port C: unused */ | ||
2335 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2336 | |||
2337 | /* Port D: unused */ | ||
2338 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2339 | |||
2340 | /* Port E: unused, but has primary EAPD */ | ||
2341 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2342 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2343 | |||
2344 | /* Port F: unused */ | ||
2345 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2346 | |||
2347 | /* Port G: internal speakers */ | ||
2348 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2349 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2350 | |||
2351 | /* DAC1 */ | ||
2352 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2353 | |||
2354 | /* DAC2: unused */ | ||
2355 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2356 | |||
2357 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2358 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2360 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2361 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2364 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2365 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2366 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2367 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2368 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2369 | |||
2370 | /* Digital microphone port */ | ||
2371 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2372 | |||
2373 | /* Audio input selectors */ | ||
2374 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2375 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
2376 | |||
2377 | /* Disable SPDIF */ | ||
2378 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2379 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2380 | |||
2381 | /* enable unsolicited events for Port A and B */ | ||
2382 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2383 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2384 | { } /* end */ | ||
2385 | }; | ||
2386 | |||
2387 | static const struct hda_verb cxt5066_init_verbs_ideapad[] = { | ||
2388 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2389 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2390 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2391 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2392 | |||
2393 | /* Speakers */ | ||
2394 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2395 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2396 | |||
2397 | /* HP, Amp */ | ||
2398 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2399 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2400 | |||
2401 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2402 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2403 | |||
2404 | /* DAC1 */ | ||
2405 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2406 | |||
2407 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2408 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2409 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2410 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2411 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2412 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2413 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2414 | |||
2415 | /* Audio input selector */ | ||
2416 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2417 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2418 | |||
2419 | /* SPDIF route: PCM */ | ||
2420 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2421 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2422 | |||
2423 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2424 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2425 | |||
2426 | /* internal microphone */ | ||
2427 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2428 | |||
2429 | /* EAPD */ | ||
2430 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2431 | |||
2432 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2433 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2434 | { } /* end */ | ||
2435 | }; | ||
2436 | |||
2437 | static const struct hda_verb cxt5066_init_verbs_thinkpad[] = { | ||
2438 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2439 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2440 | |||
2441 | /* Port G: internal speakers */ | ||
2442 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2443 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2444 | |||
2445 | /* Port A: HP, Amp */ | ||
2446 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2447 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2448 | |||
2449 | /* Port B: Mic Dock */ | ||
2450 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2451 | |||
2452 | /* Port C: Mic */ | ||
2453 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2454 | |||
2455 | /* Port D: HP Dock, Amp */ | ||
2456 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2457 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2458 | |||
2459 | /* DAC1 */ | ||
2460 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2461 | |||
2462 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2463 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2464 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2465 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2466 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2467 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2468 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2469 | |||
2470 | /* Audio input selector */ | ||
2471 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2472 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2473 | |||
2474 | /* SPDIF route: PCM */ | ||
2475 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2476 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2477 | |||
2478 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2479 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2480 | |||
2481 | /* internal microphone */ | ||
2482 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2483 | |||
2484 | /* EAPD */ | ||
2485 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2486 | |||
2487 | /* enable unsolicited events for Port A, B, C and D */ | ||
2488 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2489 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2490 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2491 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2492 | { } /* end */ | ||
2493 | }; | ||
2494 | |||
2495 | static const struct hda_verb cxt5066_init_verbs_portd_lo[] = { | ||
2496 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2497 | { } /* end */ | ||
2498 | }; | ||
2499 | |||
2500 | |||
2501 | static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { | ||
2502 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2503 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2504 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2505 | { } /* end */ | ||
2506 | }; | ||
2507 | |||
2508 | /* initialize jack-sensing, too */ | ||
2509 | static int cxt5066_init(struct hda_codec *codec) | ||
2510 | { | ||
2511 | codec_dbg(codec, "CXT5066: init\n"); | ||
2512 | conexant_init(codec); | ||
2513 | if (codec->patch_ops.unsol_event) { | ||
2514 | cxt5066_hp_automute(codec); | ||
2515 | cxt5066_automic(codec); | ||
2516 | } | ||
2517 | cxt5066_set_mic_boost(codec); | ||
2518 | return 0; | ||
2519 | } | ||
2520 | |||
2521 | enum { | ||
2522 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | ||
2523 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | ||
2524 | CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ | ||
2525 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | ||
2526 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | ||
2527 | CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ | ||
2528 | CXT5066_HP_LAPTOP, /* HP Laptop */ | ||
2529 | CXT5066_AUTO, /* BIOS auto-parser */ | ||
2530 | CXT5066_MODELS | ||
2531 | }; | ||
2532 | |||
2533 | static const char * const cxt5066_models[CXT5066_MODELS] = { | ||
2534 | [CXT5066_LAPTOP] = "laptop", | ||
2535 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | ||
2536 | [CXT5066_DELL_VOSTRO] = "dell-vostro", | ||
2537 | [CXT5066_IDEAPAD] = "ideapad", | ||
2538 | [CXT5066_THINKPAD] = "thinkpad", | ||
2539 | [CXT5066_ASUS] = "asus", | ||
2540 | [CXT5066_HP_LAPTOP] = "hp-laptop", | ||
2541 | [CXT5066_AUTO] = "auto", | ||
2542 | }; | ||
2543 | |||
2544 | static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | ||
2545 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), | ||
2546 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), | ||
2547 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), | ||
2548 | SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), | ||
2549 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | ||
2550 | SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), | ||
2551 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | ||
2552 | SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), | ||
2553 | SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), | ||
2554 | SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), | ||
2555 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), | ||
2556 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
2557 | CXT5066_LAPTOP), | ||
2558 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | ||
2559 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | ||
2560 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), | ||
2561 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | ||
2562 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | ||
2563 | {} | ||
2564 | }; | ||
2565 | |||
2566 | static int patch_cxt5066(struct hda_codec *codec) | ||
2567 | { | ||
2568 | struct conexant_spec *spec; | ||
2569 | int board_config; | ||
2570 | |||
2571 | board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, | ||
2572 | cxt5066_models, cxt5066_cfg_tbl); | ||
2573 | if (board_config < 0) | ||
2574 | board_config = CXT5066_AUTO; /* model=auto as default */ | ||
2575 | if (board_config == CXT5066_AUTO) | ||
2576 | return patch_conexant_auto(codec); | ||
2577 | |||
2578 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
2579 | if (!spec) | ||
2580 | return -ENOMEM; | ||
2581 | codec->spec = spec; | ||
2582 | |||
2583 | codec->patch_ops = conexant_patch_ops; | ||
2584 | codec->patch_ops.init = conexant_init; | ||
2585 | |||
2586 | spec->dell_automute = 0; | ||
2587 | spec->multiout.max_channels = 2; | ||
2588 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); | ||
2589 | spec->multiout.dac_nids = cxt5066_dac_nids; | ||
2590 | conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, | ||
2591 | ARRAY_SIZE(cxt5066_digout_pin_nids)); | ||
2592 | spec->num_adc_nids = 1; | ||
2593 | spec->adc_nids = cxt5066_adc_nids; | ||
2594 | spec->capsrc_nids = cxt5066_capsrc_nids; | ||
2595 | spec->input_mux = &cxt5066_capture_source; | ||
2596 | |||
2597 | spec->port_d_mode = PIN_HP; | ||
2598 | |||
2599 | spec->num_init_verbs = 1; | ||
2600 | spec->init_verbs[0] = cxt5066_init_verbs; | ||
2601 | spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes); | ||
2602 | spec->channel_mode = cxt5066_modes; | ||
2603 | spec->cur_adc = 0; | ||
2604 | spec->cur_adc_idx = 0; | ||
2605 | |||
2606 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
2607 | |||
2608 | switch (board_config) { | ||
2609 | default: | ||
2610 | case CXT5066_LAPTOP: | ||
2611 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2612 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2613 | break; | ||
2614 | case CXT5066_DELL_LAPTOP: | ||
2615 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2616 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2617 | |||
2618 | spec->port_d_mode = PIN_OUT; | ||
2619 | spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo; | ||
2620 | spec->num_init_verbs++; | ||
2621 | spec->dell_automute = 1; | ||
2622 | break; | ||
2623 | case CXT5066_ASUS: | ||
2624 | case CXT5066_HP_LAPTOP: | ||
2625 | codec->patch_ops.init = cxt5066_init; | ||
2626 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2627 | spec->init_verbs[spec->num_init_verbs] = | ||
2628 | cxt5066_init_verbs_hp_laptop; | ||
2629 | spec->num_init_verbs++; | ||
2630 | spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; | ||
2631 | spec->asus = board_config == CXT5066_ASUS; | ||
2632 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2633 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2634 | /* no S/PDIF out */ | ||
2635 | if (board_config == CXT5066_HP_LAPTOP) | ||
2636 | spec->multiout.dig_out_nid = 0; | ||
2637 | /* input source automatically selected */ | ||
2638 | spec->input_mux = NULL; | ||
2639 | spec->port_d_mode = 0; | ||
2640 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2641 | break; | ||
2642 | |||
2643 | case CXT5066_DELL_VOSTRO: | ||
2644 | codec->patch_ops.init = cxt5066_init; | ||
2645 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2646 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | ||
2647 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2648 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2649 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; | ||
2650 | spec->port_d_mode = 0; | ||
2651 | spec->dell_vostro = 1; | ||
2652 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2653 | |||
2654 | /* no S/PDIF out */ | ||
2655 | spec->multiout.dig_out_nid = 0; | ||
2656 | |||
2657 | /* input source automatically selected */ | ||
2658 | spec->input_mux = NULL; | ||
2659 | break; | ||
2660 | case CXT5066_IDEAPAD: | ||
2661 | codec->patch_ops.init = cxt5066_init; | ||
2662 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2663 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2664 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2665 | spec->init_verbs[0] = cxt5066_init_verbs_ideapad; | ||
2666 | spec->port_d_mode = 0; | ||
2667 | spec->ideapad = 1; | ||
2668 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2669 | |||
2670 | /* no S/PDIF out */ | ||
2671 | spec->multiout.dig_out_nid = 0; | ||
2672 | |||
2673 | /* input source automatically selected */ | ||
2674 | spec->input_mux = NULL; | ||
2675 | break; | ||
2676 | case CXT5066_THINKPAD: | ||
2677 | codec->patch_ops.init = cxt5066_init; | ||
2678 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2679 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2680 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2681 | spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; | ||
2682 | spec->thinkpad = 1; | ||
2683 | spec->port_d_mode = PIN_OUT; | ||
2684 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2685 | |||
2686 | /* no S/PDIF out */ | ||
2687 | spec->multiout.dig_out_nid = 0; | ||
2688 | |||
2689 | /* input source automatically selected */ | ||
2690 | spec->input_mux = NULL; | ||
2691 | break; | ||
2692 | } | ||
2693 | |||
2694 | if (spec->beep_amp) | ||
2695 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
2696 | |||
2697 | return 0; | ||
2698 | } | ||
2699 | |||
2700 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
2701 | |||
2702 | |||
2703 | /* | 97 | /* |
2704 | * Automatic parser for CX20641 & co | 98 | * Automatic parser for CX20641 & co |
2705 | */ | 99 | */ |
@@ -3487,35 +881,28 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3487 | return err; | 881 | return err; |
3488 | } | 882 | } |
3489 | 883 | ||
3490 | #ifndef ENABLE_CXT_STATIC_QUIRKS | ||
3491 | #define patch_cxt5045 patch_conexant_auto | ||
3492 | #define patch_cxt5047 patch_conexant_auto | ||
3493 | #define patch_cxt5051 patch_conexant_auto | ||
3494 | #define patch_cxt5066 patch_conexant_auto | ||
3495 | #endif | ||
3496 | |||
3497 | /* | 884 | /* |
3498 | */ | 885 | */ |
3499 | 886 | ||
3500 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { | 887 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { |
3501 | { .id = 0x14f15045, .name = "CX20549 (Venice)", | 888 | { .id = 0x14f15045, .name = "CX20549 (Venice)", |
3502 | .patch = patch_cxt5045 }, | 889 | .patch = patch_conexant_auto }, |
3503 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", | 890 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", |
3504 | .patch = patch_cxt5047 }, | 891 | .patch = patch_conexant_auto }, |
3505 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", | 892 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", |
3506 | .patch = patch_cxt5051 }, | 893 | .patch = patch_conexant_auto }, |
3507 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", | 894 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", |
3508 | .patch = patch_cxt5066 }, | 895 | .patch = patch_conexant_auto }, |
3509 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 896 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
3510 | .patch = patch_cxt5066 }, | 897 | .patch = patch_conexant_auto }, |
3511 | { .id = 0x14f15068, .name = "CX20584", | 898 | { .id = 0x14f15068, .name = "CX20584", |
3512 | .patch = patch_cxt5066 }, | 899 | .patch = patch_conexant_auto }, |
3513 | { .id = 0x14f15069, .name = "CX20585", | 900 | { .id = 0x14f15069, .name = "CX20585", |
3514 | .patch = patch_cxt5066 }, | 901 | .patch = patch_conexant_auto }, |
3515 | { .id = 0x14f1506c, .name = "CX20588", | 902 | { .id = 0x14f1506c, .name = "CX20588", |
3516 | .patch = patch_cxt5066 }, | 903 | .patch = patch_conexant_auto }, |
3517 | { .id = 0x14f1506e, .name = "CX20590", | 904 | { .id = 0x14f1506e, .name = "CX20590", |
3518 | .patch = patch_cxt5066 }, | 905 | .patch = patch_conexant_auto }, |
3519 | { .id = 0x14f15097, .name = "CX20631", | 906 | { .id = 0x14f15097, .name = "CX20631", |
3520 | .patch = patch_conexant_auto }, | 907 | .patch = patch_conexant_auto }, |
3521 | { .id = 0x14f15098, .name = "CX20632", | 908 | { .id = 0x14f15098, .name = "CX20632", |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 4fe876b65fda..36badba2dcec 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca) | |||
648 | * | 648 | * |
649 | * TODO: it could select the wrong CA from multiple candidates. | 649 | * TODO: it could select the wrong CA from multiple candidates. |
650 | */ | 650 | */ |
651 | static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | 651 | static int hdmi_channel_allocation(struct hda_codec *codec, |
652 | struct hdmi_eld *eld, int channels) | ||
652 | { | 653 | { |
653 | int i; | 654 | int i; |
654 | int ca = 0; | 655 | int ca = 0; |
@@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | |||
694 | } | 695 | } |
695 | 696 | ||
696 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); | 697 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); |
697 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 698 | codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
698 | ca, channels, buf); | 699 | ca, channels, buf); |
699 | 700 | ||
700 | return ca; | 701 | return ca; |
@@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1131 | if (!non_pcm && per_pin->chmap_set) | 1132 | if (!non_pcm && per_pin->chmap_set) |
1132 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 1133 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
1133 | else | 1134 | else |
1134 | ca = hdmi_channel_allocation(eld, channels); | 1135 | ca = hdmi_channel_allocation(codec, eld, channels); |
1135 | if (ca < 0) | 1136 | if (ca < 0) |
1136 | ca = 0; | 1137 | ca = 0; |
1137 | 1138 | ||
@@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1557 | eld->eld_valid = false; | 1558 | eld->eld_valid = false; |
1558 | else { | 1559 | else { |
1559 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); | 1560 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); |
1560 | if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer, | 1561 | if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, |
1561 | eld->eld_size) < 0) | 1562 | eld->eld_size) < 0) |
1562 | eld->eld_valid = false; | 1563 | eld->eld_valid = false; |
1563 | } | 1564 | } |
1564 | 1565 | ||
1565 | if (eld->eld_valid) { | 1566 | if (eld->eld_valid) { |
1566 | snd_hdmi_show_eld(&eld->info); | 1567 | snd_hdmi_show_eld(codec, &eld->info); |
1567 | update_eld = true; | 1568 | update_eld = true; |
1568 | } | 1569 | } |
1569 | else if (repoll) { | 1570 | else if (repoll) { |
@@ -3337,6 +3338,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3337 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, | 3338 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, |
3338 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, | 3339 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, |
3339 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 3340 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
3341 | { .id = 0x10de0070, .name = "GPU 70 HDMI/DP", .patch = patch_nvhdmi }, | ||
3340 | { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, | 3342 | { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, |
3341 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 3343 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
3342 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 3344 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
@@ -3354,6 +3356,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
3354 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, | 3356 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, |
3355 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | 3357 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
3356 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, | 3358 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, |
3359 | { .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, | ||
3357 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 3360 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
3358 | {} /* terminator */ | 3361 | {} /* terminator */ |
3359 | }; | 3362 | }; |
@@ -3394,6 +3397,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0044"); | |||
3394 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); | 3397 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); |
3395 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); | 3398 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); |
3396 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 3399 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
3400 | MODULE_ALIAS("snd-hda-codec-id:10de0070"); | ||
3397 | MODULE_ALIAS("snd-hda-codec-id:10de0071"); | 3401 | MODULE_ALIAS("snd-hda-codec-id:10de0071"); |
3398 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 3402 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
3399 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | 3403 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); |
@@ -3412,6 +3416,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862807"); | |||
3412 | MODULE_ALIAS("snd-hda-codec-id:80862808"); | 3416 | MODULE_ALIAS("snd-hda-codec-id:80862808"); |
3413 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | 3417 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
3414 | MODULE_ALIAS("snd-hda-codec-id:80862882"); | 3418 | MODULE_ALIAS("snd-hda-codec-id:80862882"); |
3419 | MODULE_ALIAS("snd-hda-codec-id:80862883"); | ||
3415 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 3420 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
3416 | 3421 | ||
3417 | MODULE_LICENSE("GPL"); | 3422 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b60824e90408..654c8f16d150 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -101,6 +101,7 @@ struct alc_spec { | |||
101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ | 101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ |
102 | int mute_led_polarity; | 102 | int mute_led_polarity; |
103 | hda_nid_t mute_led_nid; | 103 | hda_nid_t mute_led_nid; |
104 | hda_nid_t cap_mute_led_nid; | ||
104 | 105 | ||
105 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ | 106 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ |
106 | 107 | ||
@@ -3402,7 +3403,8 @@ static unsigned int led_power_filter(struct hda_codec *codec, | |||
3402 | { | 3403 | { |
3403 | struct alc_spec *spec = codec->spec; | 3404 | struct alc_spec *spec = codec->spec; |
3404 | 3405 | ||
3405 | if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid) | 3406 | if (power_state != AC_PWRST_D3 || nid == 0 || |
3407 | (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid)) | ||
3406 | return power_state; | 3408 | return power_state; |
3407 | 3409 | ||
3408 | /* Set pin ctl again, it might have just been set to 0 */ | 3410 | /* Set pin ctl again, it might have just been set to 0 */ |
@@ -3520,6 +3522,68 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, | |||
3520 | } | 3522 | } |
3521 | } | 3523 | } |
3522 | 3524 | ||
3525 | /* turn on/off mic-mute LED per capture hook */ | ||
3526 | static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec, | ||
3527 | struct snd_kcontrol *kcontrol, | ||
3528 | struct snd_ctl_elem_value *ucontrol) | ||
3529 | { | ||
3530 | struct alc_spec *spec = codec->spec; | ||
3531 | unsigned int pinval, enable, disable; | ||
3532 | |||
3533 | pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid); | ||
3534 | pinval &= ~AC_PINCTL_VREFEN; | ||
3535 | enable = pinval | AC_PINCTL_VREF_80; | ||
3536 | disable = pinval | AC_PINCTL_VREF_HIZ; | ||
3537 | |||
3538 | if (!ucontrol) | ||
3539 | return; | ||
3540 | |||
3541 | if (ucontrol->value.integer.value[0] || | ||
3542 | ucontrol->value.integer.value[1]) | ||
3543 | pinval = disable; | ||
3544 | else | ||
3545 | pinval = enable; | ||
3546 | |||
3547 | if (spec->cap_mute_led_nid) | ||
3548 | snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); | ||
3549 | } | ||
3550 | |||
3551 | static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, | ||
3552 | const struct hda_fixup *fix, int action) | ||
3553 | { | ||
3554 | struct alc_spec *spec = codec->spec; | ||
3555 | static const struct hda_verb gpio_init[] = { | ||
3556 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 }, | ||
3557 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 }, | ||
3558 | {} | ||
3559 | }; | ||
3560 | |||
3561 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3562 | spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook; | ||
3563 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3564 | spec->gpio_led = 0; | ||
3565 | spec->cap_mute_led_nid = 0x18; | ||
3566 | snd_hda_add_verbs(codec, gpio_init); | ||
3567 | codec->power_filter = led_power_filter; | ||
3568 | } | ||
3569 | } | ||
3570 | |||
3571 | static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, | ||
3572 | const struct hda_fixup *fix, int action) | ||
3573 | { | ||
3574 | struct alc_spec *spec = codec->spec; | ||
3575 | |||
3576 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3577 | spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; | ||
3578 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3579 | spec->mute_led_polarity = 0; | ||
3580 | spec->mute_led_nid = 0x1a; | ||
3581 | spec->cap_mute_led_nid = 0x18; | ||
3582 | spec->gen.vmaster_mute_enum = 1; | ||
3583 | codec->power_filter = led_power_filter; | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3523 | static void alc_headset_mode_unplugged(struct hda_codec *codec) | 3587 | static void alc_headset_mode_unplugged(struct hda_codec *codec) |
3524 | { | 3588 | { |
3525 | int val; | 3589 | int val; |
@@ -4231,6 +4295,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec, | |||
4231 | /* for hda_fixup_thinkpad_acpi() */ | 4295 | /* for hda_fixup_thinkpad_acpi() */ |
4232 | #include "thinkpad_helper.c" | 4296 | #include "thinkpad_helper.c" |
4233 | 4297 | ||
4298 | /* for dell wmi mic mute led */ | ||
4299 | #include "dell_wmi_helper.c" | ||
4300 | |||
4234 | enum { | 4301 | enum { |
4235 | ALC269_FIXUP_SONY_VAIO, | 4302 | ALC269_FIXUP_SONY_VAIO, |
4236 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 4303 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -4255,6 +4322,8 @@ enum { | |||
4255 | ALC269_FIXUP_HP_MUTE_LED_MIC1, | 4322 | ALC269_FIXUP_HP_MUTE_LED_MIC1, |
4256 | ALC269_FIXUP_HP_MUTE_LED_MIC2, | 4323 | ALC269_FIXUP_HP_MUTE_LED_MIC2, |
4257 | ALC269_FIXUP_HP_GPIO_LED, | 4324 | ALC269_FIXUP_HP_GPIO_LED, |
4325 | ALC269_FIXUP_HP_GPIO_MIC1_LED, | ||
4326 | ALC269_FIXUP_HP_LINE1_MIC1_LED, | ||
4258 | ALC269_FIXUP_INV_DMIC, | 4327 | ALC269_FIXUP_INV_DMIC, |
4259 | ALC269_FIXUP_LENOVO_DOCK, | 4328 | ALC269_FIXUP_LENOVO_DOCK, |
4260 | ALC269_FIXUP_NO_SHUTUP, | 4329 | ALC269_FIXUP_NO_SHUTUP, |
@@ -4292,6 +4361,8 @@ enum { | |||
4292 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, | 4361 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4293 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | 4362 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, |
4294 | ALC292_FIXUP_TPT440_DOCK, | 4363 | ALC292_FIXUP_TPT440_DOCK, |
4364 | ALC283_FIXUP_BXBT2807_MIC, | ||
4365 | ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, | ||
4295 | }; | 4366 | }; |
4296 | 4367 | ||
4297 | static const struct hda_fixup alc269_fixups[] = { | 4368 | static const struct hda_fixup alc269_fixups[] = { |
@@ -4447,6 +4518,14 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4447 | .type = HDA_FIXUP_FUNC, | 4518 | .type = HDA_FIXUP_FUNC, |
4448 | .v.func = alc269_fixup_hp_gpio_led, | 4519 | .v.func = alc269_fixup_hp_gpio_led, |
4449 | }, | 4520 | }, |
4521 | [ALC269_FIXUP_HP_GPIO_MIC1_LED] = { | ||
4522 | .type = HDA_FIXUP_FUNC, | ||
4523 | .v.func = alc269_fixup_hp_gpio_mic1_led, | ||
4524 | }, | ||
4525 | [ALC269_FIXUP_HP_LINE1_MIC1_LED] = { | ||
4526 | .type = HDA_FIXUP_FUNC, | ||
4527 | .v.func = alc269_fixup_hp_line1_mic1_led, | ||
4528 | }, | ||
4450 | [ALC269_FIXUP_INV_DMIC] = { | 4529 | [ALC269_FIXUP_INV_DMIC] = { |
4451 | .type = HDA_FIXUP_FUNC, | 4530 | .type = HDA_FIXUP_FUNC, |
4452 | .v.func = alc_fixup_inv_dmic_0x12, | 4531 | .v.func = alc_fixup_inv_dmic_0x12, |
@@ -4718,6 +4797,20 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4718 | .chained = true, | 4797 | .chained = true, |
4719 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST | 4798 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST |
4720 | }, | 4799 | }, |
4800 | [ALC283_FIXUP_BXBT2807_MIC] = { | ||
4801 | .type = HDA_FIXUP_PINS, | ||
4802 | .v.pins = (const struct hda_pintbl[]) { | ||
4803 | { 0x19, 0x04a110f0 }, | ||
4804 | { }, | ||
4805 | }, | ||
4806 | }, | ||
4807 | [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = { | ||
4808 | .type = HDA_FIXUP_FUNC, | ||
4809 | .v.func = alc_fixup_dell_wmi, | ||
4810 | .chained_before = true, | ||
4811 | .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE | ||
4812 | }, | ||
4813 | |||
4721 | }; | 4814 | }; |
4722 | 4815 | ||
4723 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4816 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -4727,7 +4820,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4727 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), | 4820 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), |
4728 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), | 4821 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), |
4729 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), | 4822 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), |
4730 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), | ||
4731 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | 4823 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), |
4732 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 4824 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
4733 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4825 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
@@ -4761,10 +4853,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4761 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4853 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4762 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4854 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4763 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4855 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4856 | SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | ||
4764 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4857 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4765 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4858 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4766 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4859 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4767 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4860 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4861 | SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | ||
4768 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), | 4862 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), |
4769 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4863 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4770 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4864 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
@@ -4782,6 +4876,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4782 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4876 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4783 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4877 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4784 | /* ALC282 */ | 4878 | /* ALC282 */ |
4879 | SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4880 | SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4785 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4881 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4786 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4882 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4787 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4883 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4790,6 +4886,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4790 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4886 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4791 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4887 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4792 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4888 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4889 | SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4890 | SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4891 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4892 | SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4893 | SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4894 | SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4895 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4896 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4897 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4898 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4899 | SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4900 | SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4901 | SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4902 | SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4793 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4903 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4794 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4904 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4795 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4905 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4814,13 +4924,43 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4814 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4924 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4815 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4925 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4816 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4926 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4927 | SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4928 | SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4929 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4930 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4931 | SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4817 | /* ALC290 */ | 4932 | /* ALC290 */ |
4933 | SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4934 | SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4935 | SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4936 | SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4937 | SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4938 | SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4939 | SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4940 | SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4941 | SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4942 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4943 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4944 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4945 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4946 | SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4947 | SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4948 | SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4949 | SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4950 | SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4951 | SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4952 | SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4953 | SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4818 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4954 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4819 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4955 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4820 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4956 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4821 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4957 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4822 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4958 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4823 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4959 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4960 | SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4961 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4962 | SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4963 | SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4824 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4964 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4825 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4965 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4826 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4966 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4843,7 +4983,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4843 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4983 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4844 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4984 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4845 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4985 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4846 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | ||
4847 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), | 4986 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
4848 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4987 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4849 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4988 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -4864,9 +5003,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4864 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 5003 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4865 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 5004 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4866 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), | 5005 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), |
4867 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
4868 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), | 5006 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), |
4869 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), | 5007 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), |
5008 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), | ||
4870 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 5009 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
4871 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 5010 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
4872 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), | 5011 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
@@ -4891,7 +5030,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4891 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5030 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4892 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 5031 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
4893 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 5032 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
4894 | SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI), | ||
4895 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ | 5033 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ |
4896 | 5034 | ||
4897 | #if 0 | 5035 | #if 0 |
@@ -4945,6 +5083,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4945 | {} | 5083 | {} |
4946 | }; | 5084 | }; |
4947 | 5085 | ||
5086 | static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = { | ||
5087 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), | ||
5088 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | ||
5089 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
5090 | SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI), | ||
5091 | {} | ||
5092 | }; | ||
5093 | |||
4948 | static const struct hda_model_fixup alc269_fixup_models[] = { | 5094 | static const struct hda_model_fixup alc269_fixup_models[] = { |
4949 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, | 5095 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, |
4950 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, | 5096 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, |
@@ -5040,6 +5186,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5040 | {0x1d, 0x40700001}, | 5186 | {0x1d, 0x40700001}, |
5041 | {0x1e, 0x411111f0}, | 5187 | {0x1e, 0x411111f0}, |
5042 | {0x21, 0x02211040}), | 5188 | {0x21, 0x02211040}), |
5189 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5190 | {0x12, 0x99a30130}, | ||
5191 | {0x14, 0x90170110}, | ||
5192 | {0x17, 0x40000000}, | ||
5193 | {0x18, 0x411111f0}, | ||
5194 | {0x19, 0x03a11020}, | ||
5195 | {0x1a, 0x411111f0}, | ||
5196 | {0x1b, 0x411111f0}, | ||
5197 | {0x1d, 0x40f41905}, | ||
5198 | {0x1e, 0x411111f0}, | ||
5199 | {0x21, 0x0321101f}), | ||
5043 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 5200 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
5044 | {0x12, 0x90a60130}, | 5201 | {0x12, 0x90a60130}, |
5045 | {0x14, 0x90170110}, | 5202 | {0x14, 0x90170110}, |
@@ -5162,6 +5319,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
5162 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 5319 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
5163 | alc269_fixup_tbl, alc269_fixups); | 5320 | alc269_fixup_tbl, alc269_fixups); |
5164 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); | 5321 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); |
5322 | snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl, | ||
5323 | alc269_fixups); | ||
5165 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 5324 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
5166 | 5325 | ||
5167 | alc_auto_parse_customize_define(codec); | 5326 | alc_auto_parse_customize_define(codec); |
@@ -5858,6 +6017,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
5858 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6017 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
5859 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6018 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5860 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6019 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
6020 | SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13), | ||
5861 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13), | 6021 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13), |
5862 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6022 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5863 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6023 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3744ea4e843d..ea823e1100da 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -84,6 +84,7 @@ enum { | |||
84 | STAC_DELL_EQ, | 84 | STAC_DELL_EQ, |
85 | STAC_ALIENWARE_M17X, | 85 | STAC_ALIENWARE_M17X, |
86 | STAC_92HD89XX_HP_FRONT_JACK, | 86 | STAC_92HD89XX_HP_FRONT_JACK, |
87 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, | ||
87 | STAC_92HD73XX_MODELS | 88 | STAC_92HD73XX_MODELS |
88 | }; | 89 | }; |
89 | 90 | ||
@@ -103,6 +104,7 @@ enum { | |||
103 | STAC_92HD83XXX_HP, | 104 | STAC_92HD83XXX_HP, |
104 | STAC_HP_ENVY_BASS, | 105 | STAC_HP_ENVY_BASS, |
105 | STAC_HP_BNB13_EQ, | 106 | STAC_HP_BNB13_EQ, |
107 | STAC_HP_ENVY_TS_BASS, | ||
106 | STAC_92HD83XXX_MODELS | 108 | STAC_92HD83XXX_MODELS |
107 | }; | 109 | }; |
108 | 110 | ||
@@ -1017,7 +1019,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec) | |||
1017 | for (i = 0; i < num_cons; i++) { | 1019 | for (i = 0; i < num_cons; i++) { |
1018 | if (snd_BUG_ON(!labels[i])) | 1020 | if (snd_BUG_ON(!labels[i])) |
1019 | return -EINVAL; | 1021 | return -EINVAL; |
1020 | snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL); | 1022 | snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL); |
1021 | } | 1023 | } |
1022 | 1024 | ||
1023 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); | 1025 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); |
@@ -1809,6 +1811,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { | |||
1809 | {} | 1811 | {} |
1810 | }; | 1812 | }; |
1811 | 1813 | ||
1814 | static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = { | ||
1815 | { 0x0e, 0x400000f0 }, | ||
1816 | {} | ||
1817 | }; | ||
1818 | |||
1812 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, | 1819 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, |
1813 | const struct hda_fixup *fix, int action) | 1820 | const struct hda_fixup *fix, int action) |
1814 | { | 1821 | { |
@@ -1931,6 +1938,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { | |||
1931 | [STAC_92HD89XX_HP_FRONT_JACK] = { | 1938 | [STAC_92HD89XX_HP_FRONT_JACK] = { |
1932 | .type = HDA_FIXUP_PINS, | 1939 | .type = HDA_FIXUP_PINS, |
1933 | .v.pins = stac92hd89xx_hp_front_jack_pin_configs, | 1940 | .v.pins = stac92hd89xx_hp_front_jack_pin_configs, |
1941 | }, | ||
1942 | [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { | ||
1943 | .type = HDA_FIXUP_PINS, | ||
1944 | .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, | ||
1934 | } | 1945 | } |
1935 | }; | 1946 | }; |
1936 | 1947 | ||
@@ -1991,6 +2002,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { | |||
1991 | "Alienware M17x", STAC_ALIENWARE_M17X), | 2002 | "Alienware M17x", STAC_ALIENWARE_M17X), |
1992 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, | 2003 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, |
1993 | "Alienware M17x R3", STAC_DELL_EQ), | 2004 | "Alienware M17x R3", STAC_DELL_EQ), |
2005 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, | ||
2006 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), | ||
1994 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, | 2007 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, |
1995 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), | 2008 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), |
1996 | {} /* terminator */ | 2009 | {} /* terminator */ |
@@ -2668,6 +2681,13 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = { | |||
2668 | .chained = true, | 2681 | .chained = true, |
2669 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, | 2682 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, |
2670 | }, | 2683 | }, |
2684 | [STAC_HP_ENVY_TS_BASS] = { | ||
2685 | .type = HDA_FIXUP_PINS, | ||
2686 | .v.pins = (const struct hda_pintbl[]) { | ||
2687 | { 0x10, 0x92170111 }, | ||
2688 | {} | ||
2689 | }, | ||
2690 | }, | ||
2671 | }; | 2691 | }; |
2672 | 2692 | ||
2673 | static const struct hda_model_fixup stac92hd83xxx_models[] = { | 2693 | static const struct hda_model_fixup stac92hd83xxx_models[] = { |
@@ -2684,6 +2704,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = { | |||
2684 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, | 2704 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, |
2685 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, | 2705 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, |
2686 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, | 2706 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, |
2707 | { .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" }, | ||
2687 | {} | 2708 | {} |
2688 | }; | 2709 | }; |
2689 | 2710 | ||
@@ -2739,6 +2760,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2739 | "HP bNB13", STAC_HP_BNB13_EQ), | 2760 | "HP bNB13", STAC_HP_BNB13_EQ), |
2740 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, | 2761 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, |
2741 | "HP bNB13", STAC_HP_BNB13_EQ), | 2762 | "HP bNB13", STAC_HP_BNB13_EQ), |
2763 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, | ||
2764 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), | ||
2742 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, | 2765 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, |
2743 | "HP bNB13", STAC_HP_BNB13_EQ), | 2766 | "HP bNB13", STAC_HP_BNB13_EQ), |
2744 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, | 2767 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, |
@@ -3438,9 +3461,11 @@ static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec, | |||
3438 | { | 3461 | { |
3439 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3462 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3440 | return; | 3463 | return; |
3464 | |||
3465 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
3441 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, | 3466 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, |
3442 | stac922x_fixups); | 3467 | stac922x_fixups); |
3443 | if (codec->fixup_id != STAC_INTEL_MAC_AUTO) | 3468 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
3444 | snd_hda_apply_fixup(codec, action); | 3469 | snd_hda_apply_fixup(codec, action); |
3445 | } | 3470 | } |
3446 | 3471 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index b209fc30b334..58f8f2ae758d 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -41,14 +41,17 @@ | |||
41 | #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x) | 41 | #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x) |
42 | 42 | ||
43 | #define ICE1712_REG_CONTROL 0x00 /* byte */ | 43 | #define ICE1712_REG_CONTROL 0x00 /* byte */ |
44 | #define ICE1712_RESET 0x80 /* reset whole chip */ | 44 | #define ICE1712_RESET 0x80 /* soft reset whole chip */ |
45 | #define ICE1712_SERR_LEVEL 0x04 /* SERR# level otherwise edge */ | 45 | #define ICE1712_SERR_ASSERT_DS_DMA 0x40 /* disabled SERR# assertion for the DS DMA Ch-C irq otherwise enabled */ |
46 | #define ICE1712_DOS_VOL 0x10 /* DOS WT/FM volume control */ | ||
47 | #define ICE1712_SERR_LEVEL 0x08 /* SERR# level otherwise edge */ | ||
48 | #define ICE1712_SERR_ASSERT_SB 0x02 /* disabled SERR# assertion for SB irq otherwise enabled */ | ||
46 | #define ICE1712_NATIVE 0x01 /* native mode otherwise SB */ | 49 | #define ICE1712_NATIVE 0x01 /* native mode otherwise SB */ |
47 | #define ICE1712_REG_IRQMASK 0x01 /* byte */ | 50 | #define ICE1712_REG_IRQMASK 0x01 /* byte */ |
48 | #define ICE1712_IRQ_MPU1 0x80 | 51 | #define ICE1712_IRQ_MPU1 0x80 /* MIDI irq mask */ |
49 | #define ICE1712_IRQ_TIMER 0x40 | 52 | #define ICE1712_IRQ_TIMER 0x40 /* Timer mask */ |
50 | #define ICE1712_IRQ_MPU2 0x20 | 53 | #define ICE1712_IRQ_MPU2 0x20 /* Secondary MIDI irq mask */ |
51 | #define ICE1712_IRQ_PROPCM 0x10 | 54 | #define ICE1712_IRQ_PROPCM 0x10 /* professional multi-track */ |
52 | #define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */ | 55 | #define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */ |
53 | #define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */ | 56 | #define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */ |
54 | #define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */ | 57 | #define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */ |
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 71f4bdcc4055..84f67450924e 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr, | |||
151 | { | 151 | { |
152 | u32 headptr, tailptr; | 152 | u32 headptr, tailptr; |
153 | u32 msg_frame_address; | 153 | u32 msg_frame_address; |
154 | int err, i; | 154 | int i; |
155 | 155 | ||
156 | if (snd_BUG_ON(msg->size % 4)) | 156 | if (snd_BUG_ON(msg->size % 4)) |
157 | return -EINVAL; | 157 | return -EINVAL; |
158 | 158 | ||
159 | err = 0; | ||
160 | |||
161 | /* get message frame address */ | 159 | /* get message frame address */ |
162 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); | 160 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); |
163 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); | 161 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 64b9fda5f04a..dbbbacfd535e 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { | |||
53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, | 53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, |
54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, | 54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, |
55 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, | 55 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, |
56 | { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, | ||
56 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | 57 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, |
57 | { } | 58 | { } |
58 | }; | 59 | }; |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index c8c7f2c9b355..e02605931669 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -100,8 +100,8 @@ | |||
100 | */ | 100 | */ |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * Xonar Essence ST (Deluxe)/STX | 103 | * Xonar Essence ST (Deluxe)/STX (II) |
104 | * ----------------------------- | 104 | * ---------------------------------- |
105 | * | 105 | * |
106 | * CMI8788: | 106 | * CMI8788: |
107 | * | 107 | * |
@@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip, | |||
1138 | chip->model.resume = xonar_stx_resume; | 1138 | chip->model.resume = xonar_stx_resume; |
1139 | chip->model.set_dac_params = set_pcm1796_params; | 1139 | chip->model.set_dac_params = set_pcm1796_params; |
1140 | break; | 1140 | break; |
1141 | case 0x85f4: | ||
1142 | chip->model = model_xonar_st; | ||
1143 | /* TODO: daughterboard support */ | ||
1144 | chip->model.shortname = "Xonar STX II"; | ||
1145 | chip->model.init = xonar_stx_init; | ||
1146 | chip->model.resume = xonar_stx_resume; | ||
1147 | chip->model.set_dac_params = set_pcm1796_params; | ||
1148 | break; | ||
1141 | default: | 1149 | default: |
1142 | return -EINVAL; | 1150 | return -EINVAL; |
1143 | } | 1151 | } |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index b4a8278241b1..f0315c3f7de4 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -941,7 +941,7 @@ setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval) | |||
941 | union cmdret rptr = CMDRET_ZERO; | 941 | union cmdret rptr = CMDRET_ZERO; |
942 | int i = 0; | 942 | int i = 0; |
943 | 943 | ||
944 | snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval); | 944 | snd_printdd("sent mixer %d: 0x%x 0x%x\n", num, rval, lval); |
945 | do { | 945 | do { |
946 | SEND_SDGV(cif, num, num, rval, lval); | 946 | SEND_SDGV(cif, num, num, rval, lval); |
947 | SEND_RDGV(cif, num, num, &rptr); | 947 | SEND_RDGV(cif, num, num, &rptr); |
@@ -1080,7 +1080,7 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval, | |||
1080 | return -EIO; | 1080 | return -EIO; |
1081 | *rval = rptr.retwords[0]; | 1081 | *rval = rptr.retwords[0]; |
1082 | *lval = rptr.retwords[1]; | 1082 | *lval = rptr.retwords[1]; |
1083 | snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval); | 1083 | snd_printdd("got mixer %d: 0x%x 0x%x\n", num, *rval, *lval); |
1084 | return 0; | 1084 | return 0; |
1085 | } | 1085 | } |
1086 | 1086 | ||
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 1272c18a2544..da875dced2ef 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi | |||
3880 | { | 3880 | { |
3881 | unsigned long flags; | 3881 | unsigned long flags; |
3882 | void (*private_free)(struct snd_trident_voice *); | 3882 | void (*private_free)(struct snd_trident_voice *); |
3883 | void *private_data; | ||
3884 | 3883 | ||
3885 | if (voice == NULL || !voice->use) | 3884 | if (voice == NULL || !voice->use) |
3886 | return; | 3885 | return; |
3887 | snd_trident_clear_voices(trident, voice->number, voice->number); | 3886 | snd_trident_clear_voices(trident, voice->number, voice->number); |
3888 | spin_lock_irqsave(&trident->voice_alloc, flags); | 3887 | spin_lock_irqsave(&trident->voice_alloc, flags); |
3889 | private_free = voice->private_free; | 3888 | private_free = voice->private_free; |
3890 | private_data = voice->private_data; | ||
3891 | voice->private_free = NULL; | 3889 | voice->private_free = NULL; |
3892 | voice->private_data = NULL; | 3890 | voice->private_data = NULL; |
3893 | if (voice->pcm) | 3891 | if (voice->pcm) |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 3102a579660b..04c474658e3c 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset) | |||
139 | static struct snd_util_memblk * | 139 | static struct snd_util_memblk * |
140 | search_empty(struct snd_util_memhdr *hdr, int size) | 140 | search_empty(struct snd_util_memhdr *hdr, int size) |
141 | { | 141 | { |
142 | struct snd_util_memblk *blk, *prev; | 142 | struct snd_util_memblk *blk; |
143 | int page, psize; | 143 | int page, psize; |
144 | struct list_head *p; | 144 | struct list_head *p; |
145 | 145 | ||
146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); | 146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); |
147 | prev = NULL; | ||
148 | page = 0; | 147 | page = 0; |
149 | list_for_each(p, &hdr->block) { | 148 | list_for_each(p, &hdr->block) { |
150 | blk = list_entry(p, struct snd_util_memblk, list); | 149 | blk = list_entry(p, struct snd_util_memblk, list); |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 0060b31cc3f3..0e9623368ab0 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig" | |||
47 | source "sound/soc/intel/Kconfig" | 47 | source "sound/soc/intel/Kconfig" |
48 | source "sound/soc/mxs/Kconfig" | 48 | source "sound/soc/mxs/Kconfig" |
49 | source "sound/soc/pxa/Kconfig" | 49 | source "sound/soc/pxa/Kconfig" |
50 | source "sound/soc/rockchip/Kconfig" | ||
50 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
51 | source "sound/soc/s6000/Kconfig" | 52 | source "sound/soc/s6000/Kconfig" |
52 | source "sound/soc/sh/Kconfig" | 53 | source "sound/soc/sh/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 5f1df02984f8..534714a1ca44 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/ | |||
24 | obj-$(CONFIG_SND_SOC) += omap/ | 24 | obj-$(CONFIG_SND_SOC) += omap/ |
25 | obj-$(CONFIG_SND_SOC) += kirkwood/ | 25 | obj-$(CONFIG_SND_SOC) += kirkwood/ |
26 | obj-$(CONFIG_SND_SOC) += pxa/ | 26 | obj-$(CONFIG_SND_SOC) += pxa/ |
27 | obj-$(CONFIG_SND_SOC) += rockchip/ | ||
27 | obj-$(CONFIG_SND_SOC) += samsung/ | 28 | obj-$(CONFIG_SND_SOC) += samsung/ |
28 | obj-$(CONFIG_SND_SOC) += s6000/ | 29 | obj-$(CONFIG_SND_SOC) += s6000/ |
29 | obj-$(CONFIG_SND_SOC) += sh/ | 30 | obj-$(CONFIG_SND_SOC) += sh/ |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index de433cfd044c..f403f399808a 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
347 | u32 tfmr, rfmr, tcmr, rcmr; | 347 | u32 tfmr, rfmr, tcmr, rcmr; |
348 | int start_event; | 348 | int start_event; |
349 | int ret; | 349 | int ret; |
350 | int fslen, fslen_ext; | ||
350 | 351 | ||
351 | /* | 352 | /* |
352 | * Currently, there is only one set of dma params for | 353 | * Currently, there is only one set of dma params for |
@@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
388 | } | 389 | } |
389 | 390 | ||
390 | /* | 391 | /* |
391 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
392 | * to the size of the Frame Mode Register FSLEN field. | ||
393 | */ | ||
394 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | ||
395 | && bits > 16) { | ||
396 | printk(KERN_WARNING | ||
397 | "atmel_ssc_dai: sample size %d " | ||
398 | "is too large for I2S\n", bits); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Compute SSC register settings. | 392 | * Compute SSC register settings. |
404 | */ | 393 | */ |
405 | switch (ssc_p->daifmt | 394 | switch (ssc_p->daifmt |
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
413 | * from the MCK divider, and the BCLK signal | 402 | * from the MCK divider, and the BCLK signal |
414 | * is output on the SSC TK line. | 403 | * is output on the SSC TK line. |
415 | */ | 404 | */ |
405 | |||
406 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | ||
407 | dev_err(dai->dev, | ||
408 | "sample size %d is too large for SSC device\n", | ||
409 | bits); | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | fslen_ext = (bits - 1) / 16; | ||
414 | fslen = (bits - 1) % 16; | ||
415 | |||
416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | 416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
417 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 417 | | SSC_BF(RCMR_STTDLY, START_DELAY) |
418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | 421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); |
422 | 422 | ||
423 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 423 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) |
424 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
424 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | 425 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
425 | | SSC_BF(RFMR_FSLEN, (bits - 1)) | 426 | | SSC_BF(RFMR_FSLEN, fslen) |
426 | | SSC_BF(RFMR_DATNB, (channels - 1)) | 427 | | SSC_BF(RFMR_DATNB, (channels - 1)) |
427 | | SSC_BIT(RFMR_MSBF) | 428 | | SSC_BIT(RFMR_MSBF) |
428 | | SSC_BF(RFMR_LOOP, 0) | 429 | | SSC_BF(RFMR_LOOP, 0) |
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
435 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | 436 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
436 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | 437 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); |
437 | 438 | ||
438 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 439 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) |
440 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
439 | | SSC_BF(TFMR_FSDEN, 0) | 441 | | SSC_BF(TFMR_FSDEN, 0) |
440 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | 442 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
441 | | SSC_BF(TFMR_FSLEN, (bits - 1)) | 443 | | SSC_BF(TFMR_FSLEN, fslen) |
442 | | SSC_BF(TFMR_DATNB, (channels - 1)) | 444 | | SSC_BF(TFMR_DATNB, (channels - 1)) |
443 | | SSC_BIT(TFMR_MSBF) | 445 | | SSC_BIT(TFMR_MSBF) |
444 | | SSC_BF(TFMR_DATDEF, 0) | 446 | | SSC_BF(TFMR_DATDEF, 0) |
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index b4e36901a40b..4052268ce462 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c | |||
@@ -18,10 +18,6 @@ | |||
18 | #include "../codecs/wm8904.h" | 18 | #include "../codecs/wm8904.h" |
19 | #include "atmel_ssc_dai.h" | 19 | #include "atmel_ssc_dai.h" |
20 | 20 | ||
21 | #define MCLK_RATE 32768 | ||
22 | |||
23 | static struct clk *mclk; | ||
24 | |||
25 | static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { | 21 | static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { |
26 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 22 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
27 | SND_SOC_DAPM_MIC("Mic", NULL), | 23 | SND_SOC_DAPM_MIC("Mic", NULL), |
@@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = { | |||
61 | .hw_params = atmel_asoc_wm8904_hw_params, | 57 | .hw_params = atmel_asoc_wm8904_hw_params, |
62 | }; | 58 | }; |
63 | 59 | ||
64 | static int atmel_set_bias_level(struct snd_soc_card *card, | ||
65 | struct snd_soc_dapm_context *dapm, | ||
66 | enum snd_soc_bias_level level) | ||
67 | { | ||
68 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
69 | switch (level) { | ||
70 | case SND_SOC_BIAS_PREPARE: | ||
71 | clk_prepare_enable(mclk); | ||
72 | break; | ||
73 | case SND_SOC_BIAS_OFF: | ||
74 | clk_disable_unprepare(mclk); | ||
75 | break; | ||
76 | default: | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | }; | ||
83 | |||
84 | static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { | 60 | static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { |
85 | .name = "WM8904", | 61 | .name = "WM8904", |
86 | .stream_name = "WM8904 PCM", | 62 | .stream_name = "WM8904 PCM", |
@@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { | |||
94 | static struct snd_soc_card atmel_asoc_wm8904_card = { | 70 | static struct snd_soc_card atmel_asoc_wm8904_card = { |
95 | .name = "atmel_asoc_wm8904", | 71 | .name = "atmel_asoc_wm8904", |
96 | .owner = THIS_MODULE, | 72 | .owner = THIS_MODULE, |
97 | .set_bias_level = atmel_set_bias_level, | ||
98 | .dai_link = &atmel_asoc_wm8904_dailink, | 73 | .dai_link = &atmel_asoc_wm8904_dailink, |
99 | .num_links = 1, | 74 | .num_links = 1, |
100 | .dapm_widgets = atmel_asoc_wm8904_dapm_widgets, | 75 | .dapm_widgets = atmel_asoc_wm8904_dapm_widgets, |
@@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev) | |||
153 | { | 128 | { |
154 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; | 129 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; |
155 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | 130 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; |
156 | struct clk *clk_src; | ||
157 | int id, ret; | 131 | int id, ret; |
158 | 132 | ||
159 | card->dev = &pdev->dev; | 133 | card->dev = &pdev->dev; |
@@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev) | |||
170 | return ret; | 144 | return ret; |
171 | } | 145 | } |
172 | 146 | ||
173 | mclk = clk_get(NULL, "pck0"); | ||
174 | if (IS_ERR(mclk)) { | ||
175 | dev_err(&pdev->dev, "failed to get pck0\n"); | ||
176 | ret = PTR_ERR(mclk); | ||
177 | goto err_set_audio; | ||
178 | } | ||
179 | |||
180 | clk_src = clk_get(NULL, "clk32k"); | ||
181 | if (IS_ERR(clk_src)) { | ||
182 | dev_err(&pdev->dev, "failed to get clk32k\n"); | ||
183 | ret = PTR_ERR(clk_src); | ||
184 | goto err_set_audio; | ||
185 | } | ||
186 | |||
187 | ret = clk_set_parent(mclk, clk_src); | ||
188 | clk_put(clk_src); | ||
189 | if (ret != 0) { | ||
190 | dev_err(&pdev->dev, "failed to set MCLK parent\n"); | ||
191 | goto err_set_audio; | ||
192 | } | ||
193 | |||
194 | dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE); | ||
195 | clk_set_rate(mclk, MCLK_RATE); | ||
196 | |||
197 | ret = snd_soc_register_card(card); | 147 | ret = snd_soc_register_card(card); |
198 | if (ret) { | 148 | if (ret) { |
199 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); | 149 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index a3881c4381c9..bcf591373a7a 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | |||
290 | unsigned int sample_size = runtime->sample_bits / 8; | 290 | unsigned int sample_size = runtime->sample_bits / 8; |
291 | void *buf = runtime->dma_area; | 291 | void *buf = runtime->dma_area; |
292 | struct bf5xx_i2s_pcm_data *dma_data; | 292 | struct bf5xx_i2s_pcm_data *dma_data; |
293 | unsigned int offset, size; | 293 | unsigned int offset, samples; |
294 | 294 | ||
295 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 295 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
296 | 296 | ||
297 | if (dma_data->tdm_mode) { | 297 | if (dma_data->tdm_mode) { |
298 | offset = pos * 8 * sample_size; | 298 | offset = pos * 8 * sample_size; |
299 | size = count * 8 * sample_size; | 299 | samples = count * 8; |
300 | } else { | 300 | } else { |
301 | offset = frames_to_bytes(runtime, pos); | 301 | offset = frames_to_bytes(runtime, pos); |
302 | size = frames_to_bytes(runtime, count); | 302 | samples = count * runtime->channels; |
303 | } | 303 | } |
304 | 304 | ||
305 | snd_pcm_format_set_silence(runtime->format, buf + offset, size); | 305 | snd_pcm_format_set_silence(runtime->format, buf + offset, samples); |
306 | 306 | ||
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 3c4b10ff48c1..922006dd0583 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -945,11 +945,11 @@ static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream, | |||
945 | unsigned char inf = 0, mask = 0; | 945 | unsigned char inf = 0, mask = 0; |
946 | 946 | ||
947 | /* bit size */ | 947 | /* bit size */ |
948 | switch (params_format(params)) { | 948 | switch (params_width(params)) { |
949 | case SNDRV_PCM_FORMAT_S16_LE: | 949 | case 16: |
950 | inf &= ~PCM_INF2_18WL; | 950 | inf &= ~PCM_INF2_18WL; |
951 | break; | 951 | break; |
952 | case SNDRV_PCM_FORMAT_S18_3LE: | 952 | case 18: |
953 | inf |= PCM_INF2_18WL; | 953 | inf |= PCM_INF2_18WL; |
954 | break; | 954 | break; |
955 | default: | 955 | default: |
@@ -1044,11 +1044,11 @@ static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1044 | unsigned char inf; | 1044 | unsigned char inf; |
1045 | 1045 | ||
1046 | /* bit size */ | 1046 | /* bit size */ |
1047 | switch (params_format(params)) { | 1047 | switch (params_width(params)) { |
1048 | case SNDRV_PCM_FORMAT_S16_LE: | 1048 | case 16: |
1049 | inf = 0; | 1049 | inf = 0; |
1050 | break; | 1050 | break; |
1051 | case SNDRV_PCM_FORMAT_S18_3LE: | 1051 | case 18: |
1052 | inf = PCM_INF2_18WL; | 1052 | inf = PCM_INF2_18WL; |
1053 | break; | 1053 | break; |
1054 | default: | 1054 | default: |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0b9571c858f8..8838838e25ed 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS | |||
47 | select SND_SOC_CS42L52 if I2C && INPUT | 47 | select SND_SOC_CS42L52 if I2C && INPUT |
48 | select SND_SOC_CS42L56 if I2C && INPUT | 48 | select SND_SOC_CS42L56 if I2C && INPUT |
49 | select SND_SOC_CS42L73 if I2C | 49 | select SND_SOC_CS42L73 if I2C |
50 | select SND_SOC_CS4265 if I2C | ||
50 | select SND_SOC_CS4270 if I2C | 51 | select SND_SOC_CS4270 if I2C |
51 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 52 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI |
52 | select SND_SOC_CS42XX8_I2C if I2C | 53 | select SND_SOC_CS42XX8_I2C if I2C |
@@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS | |||
74 | select SND_SOC_PCM3008 | 75 | select SND_SOC_PCM3008 |
75 | select SND_SOC_PCM512x_I2C if I2C | 76 | select SND_SOC_PCM512x_I2C if I2C |
76 | select SND_SOC_PCM512x_SPI if SPI_MASTER | 77 | select SND_SOC_PCM512x_SPI if SPI_MASTER |
78 | select SND_SOC_RT286 if I2C | ||
77 | select SND_SOC_RT5631 if I2C | 79 | select SND_SOC_RT5631 if I2C |
78 | select SND_SOC_RT5640 if I2C | 80 | select SND_SOC_RT5640 if I2C |
79 | select SND_SOC_RT5645 if I2C | 81 | select SND_SOC_RT5645 if I2C |
80 | select SND_SOC_RT5651 if I2C | 82 | select SND_SOC_RT5651 if I2C |
83 | select SND_SOC_RT5670 if I2C | ||
81 | select SND_SOC_RT5677 if I2C | 84 | select SND_SOC_RT5677 if I2C |
82 | select SND_SOC_SGTL5000 if I2C | 85 | select SND_SOC_SGTL5000 if I2C |
83 | select SND_SOC_SI476X if MFD_SI476X_CORE | 86 | select SND_SOC_SI476X if MFD_SI476X_CORE |
@@ -91,6 +94,7 @@ config SND_SOC_ALL_CODECS | |||
91 | select SND_SOC_STA350 if I2C | 94 | select SND_SOC_STA350 if I2C |
92 | select SND_SOC_STA529 if I2C | 95 | select SND_SOC_STA529 if I2C |
93 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 96 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
97 | select SND_SOC_TAS2552 if I2C | ||
94 | select SND_SOC_TAS5086 if I2C | 98 | select SND_SOC_TAS5086 if I2C |
95 | select SND_SOC_TLV320AIC23_I2C if I2C | 99 | select SND_SOC_TLV320AIC23_I2C if I2C |
96 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER | 100 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER |
@@ -338,6 +342,11 @@ config SND_SOC_CS42L73 | |||
338 | tristate "Cirrus Logic CS42L73 CODEC" | 342 | tristate "Cirrus Logic CS42L73 CODEC" |
339 | depends on I2C | 343 | depends on I2C |
340 | 344 | ||
345 | config SND_SOC_CS4265 | ||
346 | tristate "Cirrus Logic CS4265 CODEC" | ||
347 | depends on I2C | ||
348 | select REGMAP_I2C | ||
349 | |||
341 | # Cirrus Logic CS4270 Codec | 350 | # Cirrus Logic CS4270 Codec |
342 | config SND_SOC_CS4270 | 351 | config SND_SOC_CS4270 |
343 | tristate "Cirrus Logic CS4270 CODEC" | 352 | tristate "Cirrus Logic CS4270 CODEC" |
@@ -445,9 +454,16 @@ config SND_SOC_RL6231 | |||
445 | default y if SND_SOC_RT5640=y | 454 | default y if SND_SOC_RT5640=y |
446 | default y if SND_SOC_RT5645=y | 455 | default y if SND_SOC_RT5645=y |
447 | default y if SND_SOC_RT5651=y | 456 | default y if SND_SOC_RT5651=y |
457 | default y if SND_SOC_RT5670=y | ||
458 | default y if SND_SOC_RT5677=y | ||
448 | default m if SND_SOC_RT5640=m | 459 | default m if SND_SOC_RT5640=m |
449 | default m if SND_SOC_RT5645=m | 460 | default m if SND_SOC_RT5645=m |
450 | default m if SND_SOC_RT5651=m | 461 | default m if SND_SOC_RT5651=m |
462 | default m if SND_SOC_RT5670=m | ||
463 | default m if SND_SOC_RT5677=m | ||
464 | |||
465 | config SND_SOC_RT286 | ||
466 | tristate | ||
451 | 467 | ||
452 | config SND_SOC_RT5631 | 468 | config SND_SOC_RT5631 |
453 | tristate | 469 | tristate |
@@ -461,6 +477,9 @@ config SND_SOC_RT5645 | |||
461 | config SND_SOC_RT5651 | 477 | config SND_SOC_RT5651 |
462 | tristate | 478 | tristate |
463 | 479 | ||
480 | config SND_SOC_RT5670 | ||
481 | tristate | ||
482 | |||
464 | config SND_SOC_RT5677 | 483 | config SND_SOC_RT5677 |
465 | tristate | 484 | tristate |
466 | 485 | ||
@@ -521,6 +540,10 @@ config SND_SOC_STA529 | |||
521 | config SND_SOC_STAC9766 | 540 | config SND_SOC_STAC9766 |
522 | tristate | 541 | tristate |
523 | 542 | ||
543 | config SND_SOC_TAS2552 | ||
544 | tristate "Texas Instruments TAS2552 Mono Audio amplifier" | ||
545 | depends on I2C | ||
546 | |||
524 | config SND_SOC_TAS5086 | 547 | config SND_SOC_TAS5086 |
525 | tristate "Texas Instruments TAS5086 speaker amplifier" | 548 | tristate "Texas Instruments TAS5086 speaker amplifier" |
526 | depends on I2C | 549 | depends on I2C |
@@ -541,7 +564,9 @@ config SND_SOC_TLV320AIC26 | |||
541 | depends on SPI | 564 | depends on SPI |
542 | 565 | ||
543 | config SND_SOC_TLV320AIC31XX | 566 | config SND_SOC_TLV320AIC31XX |
544 | tristate | 567 | tristate "Texas Instruments TLV320AIC31xx CODECs" |
568 | depends on I2C | ||
569 | select REGMAP_I2C | ||
545 | 570 | ||
546 | config SND_SOC_TLV320AIC32X4 | 571 | config SND_SOC_TLV320AIC32X4 |
547 | tristate | 572 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1bd6e1cf6f82..20afe0f0c5be 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o | |||
37 | snd-soc-cs42l52-objs := cs42l52.o | 37 | snd-soc-cs42l52-objs := cs42l52.o |
38 | snd-soc-cs42l56-objs := cs42l56.o | 38 | snd-soc-cs42l56-objs := cs42l56.o |
39 | snd-soc-cs42l73-objs := cs42l73.o | 39 | snd-soc-cs42l73-objs := cs42l73.o |
40 | snd-soc-cs4265-objs := cs4265.o | ||
40 | snd-soc-cs4270-objs := cs4270.o | 41 | snd-soc-cs4270-objs := cs4270.o |
41 | snd-soc-cs4271-objs := cs4271.o | 42 | snd-soc-cs4271-objs := cs4271.o |
42 | snd-soc-cs42xx8-objs := cs42xx8.o | 43 | snd-soc-cs42xx8-objs := cs42xx8.o |
@@ -68,10 +69,12 @@ snd-soc-pcm512x-objs := pcm512x.o | |||
68 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o | 69 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o |
69 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o | 70 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o |
70 | snd-soc-rl6231-objs := rl6231.o | 71 | snd-soc-rl6231-objs := rl6231.o |
72 | snd-soc-rt286-objs := rt286.o | ||
71 | snd-soc-rt5631-objs := rt5631.o | 73 | snd-soc-rt5631-objs := rt5631.o |
72 | snd-soc-rt5640-objs := rt5640.o | 74 | snd-soc-rt5640-objs := rt5640.o |
73 | snd-soc-rt5645-objs := rt5645.o | 75 | snd-soc-rt5645-objs := rt5645.o |
74 | snd-soc-rt5651-objs := rt5651.o | 76 | snd-soc-rt5651-objs := rt5651.o |
77 | snd-soc-rt5670-objs := rt5670.o | ||
75 | snd-soc-rt5677-objs := rt5677.o | 78 | snd-soc-rt5677-objs := rt5677.o |
76 | snd-soc-sgtl5000-objs := sgtl5000.o | 79 | snd-soc-sgtl5000-objs := sgtl5000.o |
77 | snd-soc-alc5623-objs := alc5623.o | 80 | snd-soc-alc5623-objs := alc5623.o |
@@ -162,6 +165,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o | |||
162 | # Amp | 165 | # Amp |
163 | snd-soc-max9877-objs := max9877.o | 166 | snd-soc-max9877-objs := max9877.o |
164 | snd-soc-tpa6130a2-objs := tpa6130a2.o | 167 | snd-soc-tpa6130a2-objs := tpa6130a2.o |
168 | snd-soc-tas2552-objs := tas2552.o | ||
165 | 169 | ||
166 | obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o | 170 | obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o |
167 | obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o | 171 | obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o |
@@ -204,6 +208,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o | |||
204 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o | 208 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
205 | obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o | 209 | obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o |
206 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o | 210 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o |
211 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o | ||
207 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 212 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
208 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 213 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
209 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | 214 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o |
@@ -235,10 +240,12 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o | |||
235 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o | 240 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o |
236 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | 241 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o |
237 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o | 242 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o |
243 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o | ||
238 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 244 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
239 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 245 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
240 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | 246 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o |
241 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o | 247 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o |
248 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o | ||
242 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o | 249 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o |
243 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 250 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
244 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 251 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
@@ -255,6 +262,7 @@ obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | |||
255 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o | 262 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o |
256 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 263 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
257 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 264 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
265 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o | ||
258 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 266 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
259 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 267 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
260 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o | 268 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 8d9ba4ba4bfe..e889e1b84192 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
89 | int ret; | 89 | int ret; |
90 | 90 | ||
91 | /* add codec as bus device for standard ac97 */ | 91 | /* add codec as bus device for standard ac97 */ |
92 | ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL, | 92 | ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops, |
93 | &ac97_bus); | 93 | NULL, &ac97_bus); |
94 | if (ret < 0) | 94 | if (ret < 0) |
95 | return ret; | 95 | return ret; |
96 | 96 | ||
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d71c59cf7bdd..370b742117ef 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg, | |||
230 | 230 | ||
231 | *value = 0; | 231 | *value = 0; |
232 | 232 | ||
233 | for (i = 0; i < size; i++) | 233 | for (i = 0; i < size; i++) { |
234 | *value |= recv_buf[i] << (i * 8); | 234 | *value <<= 8; |
235 | *value |= recv_buf[i]; | ||
236 | } | ||
235 | 237 | ||
236 | return 0; | 238 | return 0; |
237 | } | 239 | } |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 2961fae9670a..0b659704e60c 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -359,14 +359,14 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, | |||
359 | if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) | 359 | if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) |
360 | return 0; | 360 | return 0; |
361 | 361 | ||
362 | switch (params_format(params)) { | 362 | switch (params_width(params)) { |
363 | case SNDRV_PCM_FORMAT_S16_LE: | 363 | case 16: |
364 | val = ADAU17X1_SERIAL_PORT1_DELAY16; | 364 | val = ADAU17X1_SERIAL_PORT1_DELAY16; |
365 | break; | 365 | break; |
366 | case SNDRV_PCM_FORMAT_S24_LE: | 366 | case 24: |
367 | val = ADAU17X1_SERIAL_PORT1_DELAY8; | 367 | val = ADAU17X1_SERIAL_PORT1_DELAY8; |
368 | break; | 368 | break; |
369 | case SNDRV_PCM_FORMAT_S32_LE: | 369 | case 32: |
370 | val = ADAU17X1_SERIAL_PORT1_DELAY0; | 370 | val = ADAU17X1_SERIAL_PORT1_DELAY0; |
371 | break; | 371 | break; |
372 | default: | 372 | default: |
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index fd55da7cb9d4..70ab35744aba 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c | |||
@@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap, | |||
968 | if (adau1977->dvdd_reg) | 968 | if (adau1977->dvdd_reg) |
969 | power_off_mask = ~0; | 969 | power_off_mask = ~0; |
970 | else | 970 | else |
971 | power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; | 971 | power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN; |
972 | 972 | ||
973 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, | 973 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, |
974 | power_off_mask, 0x00); | 974 | power_off_mask, 0x00); |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3ba4c0f11418..041712592e29 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = { | |||
547 | .extended_frequencies = 1, | 547 | .extended_frequencies = 1, |
548 | }; | 548 | }; |
549 | 549 | ||
550 | static struct of_device_id ak4642_of_match[]; | 550 | static const struct of_device_id ak4642_of_match[]; |
551 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 551 | static int ak4642_i2c_probe(struct i2c_client *i2c, |
552 | const struct i2c_device_id *id) | 552 | const struct i2c_device_id *id) |
553 | { | 553 | { |
@@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client) | |||
593 | return 0; | 593 | return 0; |
594 | } | 594 | } |
595 | 595 | ||
596 | static struct of_device_id ak4642_of_match[] = { | 596 | static const struct of_device_id ak4642_of_match[] = { |
597 | { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata}, | 597 | { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata}, |
598 | { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata}, | 598 | { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata}, |
599 | { .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata}, | 599 | { .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata}, |
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index 72e953b2cb41..8107a1cac876 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c | |||
@@ -14,12 +14,18 @@ | |||
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_gpio.h> | 15 | #include <linux/of_gpio.h> |
16 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
17 | #include <linux/regulator/consumer.h> | ||
17 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
18 | #include <sound/pcm.h> | 19 | #include <sound/pcm.h> |
19 | #include <sound/initval.h> | 20 | #include <sound/initval.h> |
20 | 21 | ||
22 | static const char * const supply_names[] = { | ||
23 | "va", "vd" | ||
24 | }; | ||
25 | |||
21 | struct ak5386_priv { | 26 | struct ak5386_priv { |
22 | int reset_gpio; | 27 | int reset_gpio; |
28 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
23 | }; | 29 | }; |
24 | 30 | ||
25 | static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = { | 31 | static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = { |
@@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = { | |||
32 | { "Capture", NULL, "AINR" }, | 38 | { "Capture", NULL, "AINR" }, |
33 | }; | 39 | }; |
34 | 40 | ||
41 | static int ak5386_soc_probe(struct snd_soc_codec *codec) | ||
42 | { | ||
43 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
44 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
45 | } | ||
46 | |||
47 | static int ak5386_soc_remove(struct snd_soc_codec *codec) | ||
48 | { | ||
49 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
50 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | #ifdef CONFIG_PM | ||
55 | static int ak5386_soc_suspend(struct snd_soc_codec *codec) | ||
56 | { | ||
57 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
58 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int ak5386_soc_resume(struct snd_soc_codec *codec) | ||
63 | { | ||
64 | struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
65 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
66 | } | ||
67 | #else | ||
68 | #define ak5386_soc_suspend NULL | ||
69 | #define ak5386_soc_resume NULL | ||
70 | #endif /* CONFIG_PM */ | ||
71 | |||
35 | static struct snd_soc_codec_driver soc_codec_ak5386 = { | 72 | static struct snd_soc_codec_driver soc_codec_ak5386 = { |
73 | .probe = ak5386_soc_probe, | ||
74 | .remove = ak5386_soc_remove, | ||
75 | .suspend = ak5386_soc_suspend, | ||
76 | .resume = ak5386_soc_resume, | ||
36 | .dapm_widgets = ak5386_dapm_widgets, | 77 | .dapm_widgets = ak5386_dapm_widgets, |
37 | .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), | 78 | .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), |
38 | .dapm_routes = ak5386_dapm_routes, | 79 | .dapm_routes = ak5386_dapm_routes, |
@@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev) | |||
122 | { | 163 | { |
123 | struct device *dev = &pdev->dev; | 164 | struct device *dev = &pdev->dev; |
124 | struct ak5386_priv *priv; | 165 | struct ak5386_priv *priv; |
166 | int ret, i; | ||
125 | 167 | ||
126 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 168 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
127 | if (!priv) | 169 | if (!priv) |
@@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev) | |||
130 | priv->reset_gpio = -EINVAL; | 172 | priv->reset_gpio = -EINVAL; |
131 | dev_set_drvdata(dev, priv); | 173 | dev_set_drvdata(dev, priv); |
132 | 174 | ||
175 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
176 | priv->supplies[i].supply = supply_names[i]; | ||
177 | |||
178 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies), | ||
179 | priv->supplies); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | |||
133 | if (of_match_device(of_match_ptr(ak5386_dt_ids), dev)) | 183 | if (of_match_device(of_match_ptr(ak5386_dt_ids), dev)) |
134 | priv->reset_gpio = of_get_named_gpio(dev->of_node, | 184 | priv->reset_gpio = of_get_named_gpio(dev->of_node, |
135 | "reset-gpio", 0); | 185 | "reset-gpio", 0); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 29e198f57d4c..2f2e91ac690f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec) | |||
243 | } | 243 | } |
244 | EXPORT_SYMBOL_GPL(arizona_init_spk); | 244 | EXPORT_SYMBOL_GPL(arizona_init_spk); |
245 | 245 | ||
246 | static const struct snd_soc_dapm_route arizona_mono_routes[] = { | ||
247 | { "OUT1R", NULL, "OUT1L" }, | ||
248 | { "OUT2R", NULL, "OUT2L" }, | ||
249 | { "OUT3R", NULL, "OUT3L" }, | ||
250 | { "OUT4R", NULL, "OUT4L" }, | ||
251 | { "OUT5R", NULL, "OUT5L" }, | ||
252 | { "OUT6R", NULL, "OUT6L" }, | ||
253 | }; | ||
254 | |||
255 | int arizona_init_mono(struct snd_soc_codec *codec) | ||
256 | { | ||
257 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
258 | struct arizona *arizona = priv->arizona; | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) { | ||
262 | if (arizona->pdata.out_mono[i]) | ||
263 | snd_soc_dapm_add_routes(&codec->dapm, | ||
264 | &arizona_mono_routes[i], 1); | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | EXPORT_SYMBOL_GPL(arizona_init_mono); | ||
270 | |||
246 | int arizona_init_gpio(struct snd_soc_codec *codec) | 271 | int arizona_init_gpio(struct snd_soc_codec *codec) |
247 | { | 272 | { |
248 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 273 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
@@ -1127,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream, | |||
1127 | constraint); | 1152 | constraint); |
1128 | } | 1153 | } |
1129 | 1154 | ||
1155 | static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, | ||
1156 | unsigned int rate) | ||
1157 | { | ||
1158 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1159 | struct arizona *arizona = priv->arizona; | ||
1160 | struct reg_default dac_comp[] = { | ||
1161 | { 0x80, 0x3 }, | ||
1162 | { ARIZONA_DAC_COMP_1, 0 }, | ||
1163 | { ARIZONA_DAC_COMP_2, 0 }, | ||
1164 | { 0x80, 0x0 }, | ||
1165 | }; | ||
1166 | |||
1167 | mutex_lock(&codec->mutex); | ||
1168 | |||
1169 | dac_comp[1].def = arizona->dac_comp_coeff; | ||
1170 | if (rate >= 176400) | ||
1171 | dac_comp[2].def = arizona->dac_comp_enabled; | ||
1172 | |||
1173 | mutex_unlock(&codec->mutex); | ||
1174 | |||
1175 | regmap_multi_reg_write(arizona->regmap, | ||
1176 | dac_comp, | ||
1177 | ARRAY_SIZE(dac_comp)); | ||
1178 | } | ||
1179 | |||
1130 | static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | 1180 | static int arizona_hw_params_rate(struct snd_pcm_substream *substream, |
1131 | struct snd_pcm_hw_params *params, | 1181 | struct snd_pcm_hw_params *params, |
1132 | struct snd_soc_dai *dai) | 1182 | struct snd_soc_dai *dai) |
@@ -1153,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1153 | 1203 | ||
1154 | switch (dai_priv->clk) { | 1204 | switch (dai_priv->clk) { |
1155 | case ARIZONA_CLK_SYSCLK: | 1205 | case ARIZONA_CLK_SYSCLK: |
1206 | switch (priv->arizona->type) { | ||
1207 | case WM5102: | ||
1208 | arizona_wm5102_set_dac_comp(codec, | ||
1209 | params_rate(params)); | ||
1210 | break; | ||
1211 | default: | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1156 | snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, | 1215 | snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, |
1157 | ARIZONA_SAMPLE_RATE_1_MASK, sr_val); | 1216 | ARIZONA_SAMPLE_RATE_1_MASK, sr_val); |
1158 | if (base) | 1217 | if (base) |
@@ -1175,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, | |||
1175 | return 0; | 1234 | return 0; |
1176 | } | 1235 | } |
1177 | 1236 | ||
1237 | static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec, | ||
1238 | int base, int bclk, int lrclk, int frame) | ||
1239 | { | ||
1240 | int val; | ||
1241 | |||
1242 | val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL); | ||
1243 | if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK)) | ||
1244 | return true; | ||
1245 | |||
1246 | val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE); | ||
1247 | if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK)) | ||
1248 | return true; | ||
1249 | |||
1250 | val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1); | ||
1251 | if (frame != (val & (ARIZONA_AIF1TX_WL_MASK | | ||
1252 | ARIZONA_AIF1TX_SLOT_LEN_MASK))) | ||
1253 | return true; | ||
1254 | |||
1255 | return false; | ||
1256 | } | ||
1257 | |||
1178 | static int arizona_hw_params(struct snd_pcm_substream *substream, | 1258 | static int arizona_hw_params(struct snd_pcm_substream *substream, |
1179 | struct snd_pcm_hw_params *params, | 1259 | struct snd_pcm_hw_params *params, |
1180 | struct snd_soc_dai *dai) | 1260 | struct snd_soc_dai *dai) |
@@ -1185,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1185 | int base = dai->driver->base; | 1265 | int base = dai->driver->base; |
1186 | const int *rates; | 1266 | const int *rates; |
1187 | int i, ret, val; | 1267 | int i, ret, val; |
1268 | int channels = params_channels(params); | ||
1188 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; | 1269 | int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; |
1270 | int tdm_width = arizona->tdm_width[dai->id - 1]; | ||
1271 | int tdm_slots = arizona->tdm_slots[dai->id - 1]; | ||
1189 | int bclk, lrclk, wl, frame, bclk_target; | 1272 | int bclk, lrclk, wl, frame, bclk_target; |
1273 | bool reconfig; | ||
1274 | unsigned int aif_tx_state, aif_rx_state; | ||
1190 | 1275 | ||
1191 | if (params_rate(params) % 8000) | 1276 | if (params_rate(params) % 8000) |
1192 | rates = &arizona_44k1_bclk_rates[0]; | 1277 | rates = &arizona_44k1_bclk_rates[0]; |
1193 | else | 1278 | else |
1194 | rates = &arizona_48k_bclk_rates[0]; | 1279 | rates = &arizona_48k_bclk_rates[0]; |
1195 | 1280 | ||
1196 | bclk_target = snd_soc_params_to_bclk(params); | 1281 | if (tdm_slots) { |
1197 | if (chan_limit && chan_limit < params_channels(params)) { | 1282 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", |
1283 | tdm_slots, tdm_width); | ||
1284 | bclk_target = tdm_slots * tdm_width * params_rate(params); | ||
1285 | channels = tdm_slots; | ||
1286 | } else { | ||
1287 | bclk_target = snd_soc_params_to_bclk(params); | ||
1288 | } | ||
1289 | |||
1290 | if (chan_limit && chan_limit < channels) { | ||
1198 | arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); | 1291 | arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); |
1199 | bclk_target /= params_channels(params); | 1292 | bclk_target /= channels; |
1200 | bclk_target *= chan_limit; | 1293 | bclk_target *= chan_limit; |
1201 | } | 1294 | } |
1202 | 1295 | ||
1203 | /* Force stereo for I2S mode */ | 1296 | /* Force multiple of 2 channels for I2S mode */ |
1204 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); | 1297 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); |
1205 | if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) { | 1298 | if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) { |
1206 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); | 1299 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); |
1207 | bclk_target *= 2; | 1300 | bclk_target /= channels; |
1301 | bclk_target *= channels + 1; | ||
1208 | } | 1302 | } |
1209 | 1303 | ||
1210 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { | 1304 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { |
@@ -1228,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1228 | wl = snd_pcm_format_width(params_format(params)); | 1322 | wl = snd_pcm_format_width(params_format(params)); |
1229 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; | 1323 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; |
1230 | 1324 | ||
1325 | reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame); | ||
1326 | |||
1327 | if (reconfig) { | ||
1328 | /* Save AIF TX/RX state */ | ||
1329 | aif_tx_state = snd_soc_read(codec, | ||
1330 | base + ARIZONA_AIF_TX_ENABLES); | ||
1331 | aif_rx_state = snd_soc_read(codec, | ||
1332 | base + ARIZONA_AIF_RX_ENABLES); | ||
1333 | /* Disable AIF TX/RX before reconfiguring it */ | ||
1334 | regmap_update_bits_async(arizona->regmap, | ||
1335 | base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0); | ||
1336 | regmap_update_bits(arizona->regmap, | ||
1337 | base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0); | ||
1338 | } | ||
1339 | |||
1231 | ret = arizona_hw_params_rate(substream, params, dai); | 1340 | ret = arizona_hw_params_rate(substream, params, dai); |
1232 | if (ret != 0) | 1341 | if (ret != 0) |
1233 | return ret; | 1342 | goto restore_aif; |
1234 | 1343 | ||
1235 | regmap_update_bits_async(arizona->regmap, | 1344 | if (reconfig) { |
1236 | base + ARIZONA_AIF_BCLK_CTRL, | 1345 | regmap_update_bits_async(arizona->regmap, |
1237 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); | 1346 | base + ARIZONA_AIF_BCLK_CTRL, |
1238 | regmap_update_bits_async(arizona->regmap, | 1347 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); |
1239 | base + ARIZONA_AIF_TX_BCLK_RATE, | 1348 | regmap_update_bits_async(arizona->regmap, |
1240 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); | 1349 | base + ARIZONA_AIF_TX_BCLK_RATE, |
1241 | regmap_update_bits_async(arizona->regmap, | 1350 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); |
1242 | base + ARIZONA_AIF_RX_BCLK_RATE, | 1351 | regmap_update_bits_async(arizona->regmap, |
1243 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); | 1352 | base + ARIZONA_AIF_RX_BCLK_RATE, |
1244 | regmap_update_bits_async(arizona->regmap, | 1353 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); |
1245 | base + ARIZONA_AIF_FRAME_CTRL_1, | 1354 | regmap_update_bits_async(arizona->regmap, |
1246 | ARIZONA_AIF1TX_WL_MASK | | 1355 | base + ARIZONA_AIF_FRAME_CTRL_1, |
1247 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | 1356 | ARIZONA_AIF1TX_WL_MASK | |
1248 | regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2, | 1357 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); |
1249 | ARIZONA_AIF1RX_WL_MASK | | 1358 | regmap_update_bits(arizona->regmap, |
1250 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | 1359 | base + ARIZONA_AIF_FRAME_CTRL_2, |
1360 | ARIZONA_AIF1RX_WL_MASK | | ||
1361 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | ||
1362 | } | ||
1251 | 1363 | ||
1252 | return 0; | 1364 | restore_aif: |
1365 | if (reconfig) { | ||
1366 | /* Restore AIF TX/RX state */ | ||
1367 | regmap_update_bits_async(arizona->regmap, | ||
1368 | base + ARIZONA_AIF_TX_ENABLES, | ||
1369 | 0xff, aif_tx_state); | ||
1370 | regmap_update_bits(arizona->regmap, | ||
1371 | base + ARIZONA_AIF_RX_ENABLES, | ||
1372 | 0xff, aif_rx_state); | ||
1373 | } | ||
1374 | return ret; | ||
1253 | } | 1375 | } |
1254 | 1376 | ||
1255 | static const char *arizona_dai_clk_str(int clk_id) | 1377 | static const char *arizona_dai_clk_str(int clk_id) |
@@ -1324,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
1324 | ARIZONA_AIF1_TRI, reg); | 1446 | ARIZONA_AIF1_TRI, reg); |
1325 | } | 1447 | } |
1326 | 1448 | ||
1449 | static void arizona_set_channels_to_mask(struct snd_soc_dai *dai, | ||
1450 | unsigned int base, | ||
1451 | int channels, unsigned int mask) | ||
1452 | { | ||
1453 | struct snd_soc_codec *codec = dai->codec; | ||
1454 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1455 | struct arizona *arizona = priv->arizona; | ||
1456 | int slot, i; | ||
1457 | |||
1458 | for (i = 0; i < channels; ++i) { | ||
1459 | slot = ffs(mask) - 1; | ||
1460 | if (slot < 0) | ||
1461 | return; | ||
1462 | |||
1463 | regmap_write(arizona->regmap, base + i, slot); | ||
1464 | |||
1465 | mask &= ~(1 << slot); | ||
1466 | } | ||
1467 | |||
1468 | if (mask) | ||
1469 | arizona_aif_warn(dai, "Too many channels in TDM mask\n"); | ||
1470 | } | ||
1471 | |||
1472 | static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
1473 | unsigned int rx_mask, int slots, int slot_width) | ||
1474 | { | ||
1475 | struct snd_soc_codec *codec = dai->codec; | ||
1476 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1477 | struct arizona *arizona = priv->arizona; | ||
1478 | int base = dai->driver->base; | ||
1479 | int rx_max_chan = dai->driver->playback.channels_max; | ||
1480 | int tx_max_chan = dai->driver->capture.channels_max; | ||
1481 | |||
1482 | /* Only support TDM for the physical AIFs */ | ||
1483 | if (dai->id > ARIZONA_MAX_AIF) | ||
1484 | return -ENOTSUPP; | ||
1485 | |||
1486 | if (slots == 0) { | ||
1487 | tx_mask = (1 << tx_max_chan) - 1; | ||
1488 | rx_mask = (1 << rx_max_chan) - 1; | ||
1489 | } | ||
1490 | |||
1491 | arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3, | ||
1492 | tx_max_chan, tx_mask); | ||
1493 | arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11, | ||
1494 | rx_max_chan, rx_mask); | ||
1495 | |||
1496 | arizona->tdm_width[dai->id - 1] = slot_width; | ||
1497 | arizona->tdm_slots[dai->id - 1] = slots; | ||
1498 | |||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1327 | const struct snd_soc_dai_ops arizona_dai_ops = { | 1502 | const struct snd_soc_dai_ops arizona_dai_ops = { |
1328 | .startup = arizona_startup, | 1503 | .startup = arizona_startup, |
1329 | .set_fmt = arizona_set_fmt, | 1504 | .set_fmt = arizona_set_fmt, |
1505 | .set_tdm_slot = arizona_set_tdm_slot, | ||
1330 | .hw_params = arizona_hw_params, | 1506 | .hw_params = arizona_hw_params, |
1331 | .set_sysclk = arizona_dai_set_sysclk, | 1507 | .set_sysclk = arizona_dai_set_sysclk, |
1332 | .set_tristate = arizona_set_tristate, | 1508 | .set_tristate = arizona_set_tristate, |
@@ -1400,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll, | |||
1400 | { | 1576 | { |
1401 | unsigned int Fvco_min; | 1577 | unsigned int Fvco_min; |
1402 | 1578 | ||
1579 | if (fll->fout && Fout != fll->fout) { | ||
1580 | arizona_fll_err(fll, | ||
1581 | "Can't change output on active FLL\n"); | ||
1582 | return -EINVAL; | ||
1583 | } | ||
1584 | |||
1403 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { | 1585 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { |
1404 | arizona_fll_err(fll, | 1586 | arizona_fll_err(fll, |
1405 | "Can't scale %dMHz in to <=13.5MHz\n", | 1587 | "Can't scale %dMHz in to <=13.5MHz\n", |
@@ -1478,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll, | |||
1478 | while (div <= ARIZONA_FLL_MAX_REFDIV) { | 1660 | while (div <= ARIZONA_FLL_MAX_REFDIV) { |
1479 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; | 1661 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; |
1480 | ratio++) { | 1662 | ratio++) { |
1663 | if ((ARIZONA_FLL_VCO_CORNER / 2) / | ||
1664 | (fll->vco_mult * ratio) < Fref) | ||
1665 | break; | ||
1666 | |||
1481 | if (target % (ratio * Fref)) { | 1667 | if (target % (ratio * Fref)) { |
1482 | cfg->refdiv = refdiv; | 1668 | cfg->refdiv = refdiv; |
1483 | cfg->fratio = ratio - 1; | 1669 | cfg->fratio = ratio - 1; |
@@ -1485,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll, | |||
1485 | } | 1671 | } |
1486 | } | 1672 | } |
1487 | 1673 | ||
1488 | for (ratio = init_ratio - 1; ratio >= 0; ratio--) { | 1674 | for (ratio = init_ratio - 1; ratio > 0; ratio--) { |
1489 | if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < | ||
1490 | Fref) | ||
1491 | break; | ||
1492 | |||
1493 | if (target % (ratio * Fref)) { | 1675 | if (target % (ratio * Fref)) { |
1494 | cfg->refdiv = refdiv; | 1676 | cfg->refdiv = refdiv; |
1495 | cfg->fratio = ratio - 1; | 1677 | cfg->fratio = ratio - 1; |
@@ -1616,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1616 | ARIZONA_FLL1_CTRL_UPD | cfg->n); | 1798 | ARIZONA_FLL1_CTRL_UPD | cfg->n); |
1617 | } | 1799 | } |
1618 | 1800 | ||
1619 | static bool arizona_is_enabled_fll(struct arizona_fll *fll) | 1801 | static int arizona_is_enabled_fll(struct arizona_fll *fll) |
1620 | { | 1802 | { |
1621 | struct arizona *arizona = fll->arizona; | 1803 | struct arizona *arizona = fll->arizona; |
1622 | unsigned int reg; | 1804 | unsigned int reg; |
@@ -1632,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) | |||
1632 | return reg & ARIZONA_FLL1_ENA; | 1814 | return reg & ARIZONA_FLL1_ENA; |
1633 | } | 1815 | } |
1634 | 1816 | ||
1635 | static void arizona_enable_fll(struct arizona_fll *fll) | 1817 | static int arizona_enable_fll(struct arizona_fll *fll) |
1636 | { | 1818 | { |
1637 | struct arizona *arizona = fll->arizona; | 1819 | struct arizona *arizona = fll->arizona; |
1638 | int ret; | 1820 | int ret; |
1639 | bool use_sync = false; | 1821 | bool use_sync = false; |
1822 | int already_enabled = arizona_is_enabled_fll(fll); | ||
1640 | struct arizona_fll_cfg cfg; | 1823 | struct arizona_fll_cfg cfg; |
1641 | 1824 | ||
1825 | if (already_enabled < 0) | ||
1826 | return already_enabled; | ||
1827 | |||
1828 | if (already_enabled) { | ||
1829 | /* Facilitate smooth refclk across the transition */ | ||
1830 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7, | ||
1831 | ARIZONA_FLL1_GAIN_MASK, 0); | ||
1832 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, | ||
1833 | ARIZONA_FLL1_FREERUN, | ||
1834 | ARIZONA_FLL1_FREERUN); | ||
1835 | } | ||
1836 | |||
1642 | /* | 1837 | /* |
1643 | * If we have both REFCLK and SYNCCLK then enable both, | 1838 | * If we have both REFCLK and SYNCCLK then enable both, |
1644 | * otherwise apply the SYNCCLK settings to REFCLK. | 1839 | * otherwise apply the SYNCCLK settings to REFCLK. |
@@ -1666,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll) | |||
1666 | ARIZONA_FLL1_SYNC_ENA, 0); | 1861 | ARIZONA_FLL1_SYNC_ENA, 0); |
1667 | } else { | 1862 | } else { |
1668 | arizona_fll_err(fll, "No clocks provided\n"); | 1863 | arizona_fll_err(fll, "No clocks provided\n"); |
1669 | return; | 1864 | return -EINVAL; |
1670 | } | 1865 | } |
1671 | 1866 | ||
1672 | /* | 1867 | /* |
@@ -1681,25 +1876,29 @@ static void arizona_enable_fll(struct arizona_fll *fll) | |||
1681 | ARIZONA_FLL1_SYNC_BW, | 1876 | ARIZONA_FLL1_SYNC_BW, |
1682 | ARIZONA_FLL1_SYNC_BW); | 1877 | ARIZONA_FLL1_SYNC_BW); |
1683 | 1878 | ||
1684 | if (!arizona_is_enabled_fll(fll)) | 1879 | if (!already_enabled) |
1685 | pm_runtime_get(arizona->dev); | 1880 | pm_runtime_get(arizona->dev); |
1686 | 1881 | ||
1687 | /* Clear any pending completions */ | 1882 | /* Clear any pending completions */ |
1688 | try_wait_for_completion(&fll->ok); | 1883 | try_wait_for_completion(&fll->ok); |
1689 | 1884 | ||
1690 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | 1885 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
1691 | ARIZONA_FLL1_FREERUN, 0); | ||
1692 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1693 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | 1886 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); |
1694 | if (use_sync) | 1887 | if (use_sync) |
1695 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, | 1888 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
1696 | ARIZONA_FLL1_SYNC_ENA, | 1889 | ARIZONA_FLL1_SYNC_ENA, |
1697 | ARIZONA_FLL1_SYNC_ENA); | 1890 | ARIZONA_FLL1_SYNC_ENA); |
1698 | 1891 | ||
1892 | if (already_enabled) | ||
1893 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1894 | ARIZONA_FLL1_FREERUN, 0); | ||
1895 | |||
1699 | ret = wait_for_completion_timeout(&fll->ok, | 1896 | ret = wait_for_completion_timeout(&fll->ok, |
1700 | msecs_to_jiffies(250)); | 1897 | msecs_to_jiffies(250)); |
1701 | if (ret == 0) | 1898 | if (ret == 0) |
1702 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | 1899 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); |
1900 | |||
1901 | return 0; | ||
1703 | } | 1902 | } |
1704 | 1903 | ||
1705 | static void arizona_disable_fll(struct arizona_fll *fll) | 1904 | static void arizona_disable_fll(struct arizona_fll *fll) |
@@ -1713,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1713 | ARIZONA_FLL1_ENA, 0, &change); | 1912 | ARIZONA_FLL1_ENA, 0, &change); |
1714 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | 1913 | regmap_update_bits(arizona->regmap, fll->base + 0x11, |
1715 | ARIZONA_FLL1_SYNC_ENA, 0); | 1914 | ARIZONA_FLL1_SYNC_ENA, 0); |
1915 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | ||
1916 | ARIZONA_FLL1_FREERUN, 0); | ||
1716 | 1917 | ||
1717 | if (change) | 1918 | if (change) |
1718 | pm_runtime_put_autosuspend(arizona->dev); | 1919 | pm_runtime_put_autosuspend(arizona->dev); |
@@ -1721,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1721 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | 1922 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, |
1722 | unsigned int Fref, unsigned int Fout) | 1923 | unsigned int Fref, unsigned int Fout) |
1723 | { | 1924 | { |
1724 | int ret; | 1925 | int ret = 0; |
1725 | 1926 | ||
1726 | if (fll->ref_src == source && fll->ref_freq == Fref) | 1927 | if (fll->ref_src == source && fll->ref_freq == Fref) |
1727 | return 0; | 1928 | return 0; |
@@ -1736,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | |||
1736 | fll->ref_freq = Fref; | 1937 | fll->ref_freq = Fref; |
1737 | 1938 | ||
1738 | if (fll->fout && Fref > 0) { | 1939 | if (fll->fout && Fref > 0) { |
1739 | arizona_enable_fll(fll); | 1940 | ret = arizona_enable_fll(fll); |
1740 | } | 1941 | } |
1741 | 1942 | ||
1742 | return 0; | 1943 | return ret; |
1743 | } | 1944 | } |
1744 | EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); | 1945 | EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); |
1745 | 1946 | ||
1746 | int arizona_set_fll(struct arizona_fll *fll, int source, | 1947 | int arizona_set_fll(struct arizona_fll *fll, int source, |
1747 | unsigned int Fref, unsigned int Fout) | 1948 | unsigned int Fref, unsigned int Fout) |
1748 | { | 1949 | { |
1749 | int ret; | 1950 | int ret = 0; |
1750 | 1951 | ||
1751 | if (fll->sync_src == source && | 1952 | if (fll->sync_src == source && |
1752 | fll->sync_freq == Fref && fll->fout == Fout) | 1953 | fll->sync_freq == Fref && fll->fout == Fout) |
@@ -1768,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1768 | fll->sync_freq = Fref; | 1969 | fll->sync_freq = Fref; |
1769 | fll->fout = Fout; | 1970 | fll->fout = Fout; |
1770 | 1971 | ||
1771 | if (Fout) { | 1972 | if (Fout) |
1772 | arizona_enable_fll(fll); | 1973 | ret = arizona_enable_fll(fll); |
1773 | } else { | 1974 | else |
1774 | arizona_disable_fll(fll); | 1975 | arizona_disable_fll(fll); |
1775 | } | ||
1776 | 1976 | ||
1777 | return 0; | 1977 | return ret; |
1778 | } | 1978 | } |
1779 | EXPORT_SYMBOL_GPL(arizona_set_fll); | 1979 | EXPORT_SYMBOL_GPL(arizona_set_fll); |
1780 | 1980 | ||
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 05ae17f5bca3..942cfb197b6d 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source, | |||
249 | 249 | ||
250 | extern int arizona_init_spk(struct snd_soc_codec *codec); | 250 | extern int arizona_init_spk(struct snd_soc_codec *codec); |
251 | extern int arizona_init_gpio(struct snd_soc_codec *codec); | 251 | extern int arizona_init_gpio(struct snd_soc_codec *codec); |
252 | extern int arizona_init_mono(struct snd_soc_codec *codec); | ||
252 | 253 | ||
253 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); | 254 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); |
254 | 255 | ||
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c new file mode 100644 index 000000000000..a20b30ca52c0 --- /dev/null +++ b/sound/soc/codecs/cs4265.c | |||
@@ -0,0 +1,682 @@ | |||
1 | /* | ||
2 | * cs4265.c -- CS4265 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Author: Paul Handrigan <paul.handrigan@cirrus.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 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/gpio/consumer.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/soc-dapm.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include "cs4265.h" | ||
33 | |||
34 | struct cs4265_private { | ||
35 | struct device *dev; | ||
36 | struct regmap *regmap; | ||
37 | struct gpio_desc *reset_gpio; | ||
38 | u8 format; | ||
39 | u32 sysclk; | ||
40 | }; | ||
41 | |||
42 | static const struct reg_default cs4265_reg_defaults[] = { | ||
43 | { CS4265_PWRCTL, 0x0F }, | ||
44 | { CS4265_DAC_CTL, 0x08 }, | ||
45 | { CS4265_ADC_CTL, 0x00 }, | ||
46 | { CS4265_MCLK_FREQ, 0x00 }, | ||
47 | { CS4265_SIG_SEL, 0x40 }, | ||
48 | { CS4265_CHB_PGA_CTL, 0x00 }, | ||
49 | { CS4265_CHA_PGA_CTL, 0x00 }, | ||
50 | { CS4265_ADC_CTL2, 0x19 }, | ||
51 | { CS4265_DAC_CHA_VOL, 0x00 }, | ||
52 | { CS4265_DAC_CHB_VOL, 0x00 }, | ||
53 | { CS4265_DAC_CTL2, 0xC0 }, | ||
54 | { CS4265_SPDIF_CTL1, 0x00 }, | ||
55 | { CS4265_SPDIF_CTL2, 0x00 }, | ||
56 | { CS4265_INT_MASK, 0x00 }, | ||
57 | { CS4265_STATUS_MODE_MSB, 0x00 }, | ||
58 | { CS4265_STATUS_MODE_LSB, 0x00 }, | ||
59 | }; | ||
60 | |||
61 | static bool cs4265_readable_register(struct device *dev, unsigned int reg) | ||
62 | { | ||
63 | switch (reg) { | ||
64 | case CS4265_PWRCTL: | ||
65 | case CS4265_DAC_CTL: | ||
66 | case CS4265_ADC_CTL: | ||
67 | case CS4265_MCLK_FREQ: | ||
68 | case CS4265_SIG_SEL: | ||
69 | case CS4265_CHB_PGA_CTL: | ||
70 | case CS4265_CHA_PGA_CTL: | ||
71 | case CS4265_ADC_CTL2: | ||
72 | case CS4265_DAC_CHA_VOL: | ||
73 | case CS4265_DAC_CHB_VOL: | ||
74 | case CS4265_DAC_CTL2: | ||
75 | case CS4265_SPDIF_CTL1: | ||
76 | case CS4265_SPDIF_CTL2: | ||
77 | case CS4265_INT_MASK: | ||
78 | case CS4265_STATUS_MODE_MSB: | ||
79 | case CS4265_STATUS_MODE_LSB: | ||
80 | return true; | ||
81 | default: | ||
82 | return false; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static bool cs4265_volatile_register(struct device *dev, unsigned int reg) | ||
87 | { | ||
88 | switch (reg) { | ||
89 | case CS4265_INT_STATUS: | ||
90 | return true; | ||
91 | default: | ||
92 | return false; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0); | ||
97 | |||
98 | static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0); | ||
99 | |||
100 | static const char * const digital_input_mux_text[] = { | ||
101 | "SDIN1", "SDIN2" | ||
102 | }; | ||
103 | |||
104 | static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7, | ||
105 | digital_input_mux_text); | ||
106 | |||
107 | static const struct snd_kcontrol_new digital_input_mux = | ||
108 | SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum); | ||
109 | |||
110 | static const char * const mic_linein_text[] = { | ||
111 | "MIC", "LINEIN" | ||
112 | }; | ||
113 | |||
114 | static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0, | ||
115 | mic_linein_text); | ||
116 | |||
117 | static const char * const cam_mode_text[] = { | ||
118 | "One Byte", "Two Byte" | ||
119 | }; | ||
120 | |||
121 | static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5, | ||
122 | cam_mode_text); | ||
123 | |||
124 | static const char * const cam_mono_stereo_text[] = { | ||
125 | "Stereo", "Mono" | ||
126 | }; | ||
127 | |||
128 | static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2, | ||
129 | cam_mono_stereo_text); | ||
130 | |||
131 | static const char * const mono_select_text[] = { | ||
132 | "Channel A", "Channel B" | ||
133 | }; | ||
134 | |||
135 | static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0, | ||
136 | mono_select_text); | ||
137 | |||
138 | static const struct snd_kcontrol_new mic_linein_mux = | ||
139 | SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum); | ||
140 | |||
141 | static const struct snd_kcontrol_new loopback_ctl = | ||
142 | SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0); | ||
143 | |||
144 | static const struct snd_kcontrol_new spdif_switch = | ||
145 | SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0); | ||
146 | |||
147 | static const struct snd_kcontrol_new dac_switch = | ||
148 | SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0); | ||
149 | |||
150 | static const struct snd_kcontrol_new cs4265_snd_controls[] = { | ||
151 | |||
152 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL, | ||
153 | CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv), | ||
154 | SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL, | ||
155 | CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv), | ||
156 | SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1, | ||
157 | 1, 0), | ||
158 | SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5, | ||
159 | 1, 0), | ||
160 | SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6, | ||
161 | 1, 0), | ||
162 | SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7, | ||
163 | 1, 0), | ||
164 | SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1, | ||
165 | 1, 0), | ||
166 | SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3, | ||
167 | 1, 1), | ||
168 | SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7, | ||
169 | 1, 0), | ||
170 | SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1, | ||
171 | 6, 1, 0), | ||
172 | SOC_ENUM("C Data Access", cam_mode_enum), | ||
173 | SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, | ||
174 | 3, 1, 0), | ||
175 | SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), | ||
176 | SOC_SINGLE("MMTLR Data Switch", 0, | ||
177 | 1, 1, 0), | ||
178 | SOC_ENUM("Mono Channel Select", spdif_mono_select_enum), | ||
179 | SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24), | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = { | ||
183 | |||
184 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
185 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
186 | SND_SOC_DAPM_INPUT("MICL"), | ||
187 | SND_SOC_DAPM_INPUT("MICR"), | ||
188 | |||
189 | SND_SOC_DAPM_AIF_OUT("DOUT", NULL, 0, | ||
190 | SND_SOC_NOPM, 0, 0), | ||
191 | SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL, 0, | ||
192 | SND_SOC_NOPM, 0, 0), | ||
193 | |||
194 | SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux), | ||
195 | |||
196 | SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1), | ||
197 | SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3, | ||
198 | 1, NULL, 0), | ||
199 | |||
200 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, | ||
201 | 0, 0, &digital_input_mux), | ||
202 | |||
203 | SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
204 | SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
205 | SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
206 | |||
207 | SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0, | ||
208 | &loopback_ctl), | ||
209 | SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0, | ||
210 | &spdif_switch), | ||
211 | SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1, | ||
212 | &dac_switch), | ||
213 | |||
214 | SND_SOC_DAPM_AIF_IN("DIN1", NULL, 0, | ||
215 | SND_SOC_NOPM, 0, 0), | ||
216 | SND_SOC_DAPM_AIF_IN("DIN2", NULL, 0, | ||
217 | SND_SOC_NOPM, 0, 0), | ||
218 | SND_SOC_DAPM_AIF_IN("TXIN", NULL, 0, | ||
219 | CS4265_SPDIF_CTL2, 5, 1), | ||
220 | |||
221 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | ||
222 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | ||
223 | |||
224 | }; | ||
225 | |||
226 | static const struct snd_soc_dapm_route cs4265_audio_map[] = { | ||
227 | |||
228 | {"DIN1", NULL, "DAI1 Playback"}, | ||
229 | {"DIN2", NULL, "DAI2 Playback"}, | ||
230 | {"SDIN1 Input Mixer", NULL, "DIN1"}, | ||
231 | {"SDIN2 Input Mixer", NULL, "DIN2"}, | ||
232 | {"Input Mux", "SDIN1", "SDIN1 Input Mixer"}, | ||
233 | {"Input Mux", "SDIN2", "SDIN2 Input Mixer"}, | ||
234 | {"DAC", "Switch", "Input Mux"}, | ||
235 | {"SPDIF", "Switch", "Input Mux"}, | ||
236 | {"LINEOUTL", NULL, "DAC"}, | ||
237 | {"LINEOUTR", NULL, "DAC"}, | ||
238 | {"SPDIFOUT", NULL, "SPDIF"}, | ||
239 | |||
240 | {"ADC Mux", "LINEIN", "LINEINL"}, | ||
241 | {"ADC Mux", "LINEIN", "LINEINR"}, | ||
242 | {"ADC Mux", "MIC", "MICL"}, | ||
243 | {"ADC Mux", "MIC", "MICR"}, | ||
244 | {"ADC", NULL, "ADC Mux"}, | ||
245 | {"DOUT", NULL, "ADC"}, | ||
246 | {"DAI1 Capture", NULL, "DOUT"}, | ||
247 | {"DAI2 Capture", NULL, "DOUT"}, | ||
248 | |||
249 | /* Loopback */ | ||
250 | {"Loopback", "Switch", "ADC"}, | ||
251 | {"DAC", NULL, "Loopback"}, | ||
252 | }; | ||
253 | |||
254 | struct cs4265_clk_para { | ||
255 | u32 mclk; | ||
256 | u32 rate; | ||
257 | u8 fm_mode; /* values 1, 2, or 4 */ | ||
258 | u8 mclkdiv; | ||
259 | }; | ||
260 | |||
261 | static const struct cs4265_clk_para clk_map_table[] = { | ||
262 | /*32k*/ | ||
263 | {8192000, 32000, 0, 0}, | ||
264 | {12288000, 32000, 0, 1}, | ||
265 | {16384000, 32000, 0, 2}, | ||
266 | {24576000, 32000, 0, 3}, | ||
267 | {32768000, 32000, 0, 4}, | ||
268 | |||
269 | /*44.1k*/ | ||
270 | {11289600, 44100, 0, 0}, | ||
271 | {16934400, 44100, 0, 1}, | ||
272 | {22579200, 44100, 0, 2}, | ||
273 | {33868000, 44100, 0, 3}, | ||
274 | {45158400, 44100, 0, 4}, | ||
275 | |||
276 | /*48k*/ | ||
277 | {12288000, 48000, 0, 0}, | ||
278 | {18432000, 48000, 0, 1}, | ||
279 | {24576000, 48000, 0, 2}, | ||
280 | {36864000, 48000, 0, 3}, | ||
281 | {49152000, 48000, 0, 4}, | ||
282 | |||
283 | /*64k*/ | ||
284 | {8192000, 64000, 1, 0}, | ||
285 | {1228800, 64000, 1, 1}, | ||
286 | {1693440, 64000, 1, 2}, | ||
287 | {2457600, 64000, 1, 3}, | ||
288 | {3276800, 64000, 1, 4}, | ||
289 | |||
290 | /* 88.2k */ | ||
291 | {11289600, 88200, 1, 0}, | ||
292 | {16934400, 88200, 1, 1}, | ||
293 | {22579200, 88200, 1, 2}, | ||
294 | {33868000, 88200, 1, 3}, | ||
295 | {45158400, 88200, 1, 4}, | ||
296 | |||
297 | /* 96k */ | ||
298 | {12288000, 96000, 1, 0}, | ||
299 | {18432000, 96000, 1, 1}, | ||
300 | {24576000, 96000, 1, 2}, | ||
301 | {36864000, 96000, 1, 3}, | ||
302 | {49152000, 96000, 1, 4}, | ||
303 | |||
304 | /* 128k */ | ||
305 | {8192000, 128000, 2, 0}, | ||
306 | {12288000, 128000, 2, 1}, | ||
307 | {16934400, 128000, 2, 2}, | ||
308 | {24576000, 128000, 2, 3}, | ||
309 | {32768000, 128000, 2, 4}, | ||
310 | |||
311 | /* 176.4k */ | ||
312 | {11289600, 176400, 2, 0}, | ||
313 | {16934400, 176400, 2, 1}, | ||
314 | {22579200, 176400, 2, 2}, | ||
315 | {33868000, 176400, 2, 3}, | ||
316 | {49152000, 176400, 2, 4}, | ||
317 | |||
318 | /* 192k */ | ||
319 | {12288000, 192000, 2, 0}, | ||
320 | {18432000, 192000, 2, 1}, | ||
321 | {24576000, 192000, 2, 2}, | ||
322 | {36864000, 192000, 2, 3}, | ||
323 | {49152000, 192000, 2, 4}, | ||
324 | }; | ||
325 | |||
326 | static int cs4265_get_clk_index(int mclk, int rate) | ||
327 | { | ||
328 | int i; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { | ||
331 | if (clk_map_table[i].rate == rate && | ||
332 | clk_map_table[i].mclk == mclk) | ||
333 | return i; | ||
334 | } | ||
335 | return -EINVAL; | ||
336 | } | ||
337 | |||
338 | static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id, | ||
339 | unsigned int freq, int dir) | ||
340 | { | ||
341 | struct snd_soc_codec *codec = codec_dai->codec; | ||
342 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
343 | int i; | ||
344 | |||
345 | if (clk_id != 0) { | ||
346 | dev_err(codec->dev, "Invalid clk_id %d\n", clk_id); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { | ||
350 | if (clk_map_table[i].mclk == freq) { | ||
351 | cs4265->sysclk = freq; | ||
352 | return 0; | ||
353 | } | ||
354 | } | ||
355 | cs4265->sysclk = 0; | ||
356 | dev_err(codec->dev, "Invalid freq parameter %d\n", freq); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | |||
360 | static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
361 | { | ||
362 | struct snd_soc_codec *codec = codec_dai->codec; | ||
363 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
364 | u8 iface = 0; | ||
365 | |||
366 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
367 | case SND_SOC_DAIFMT_CBM_CFM: | ||
368 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
369 | CS4265_ADC_MASTER, | ||
370 | CS4265_ADC_MASTER); | ||
371 | break; | ||
372 | case SND_SOC_DAIFMT_CBS_CFS: | ||
373 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
374 | CS4265_ADC_MASTER, | ||
375 | 0); | ||
376 | break; | ||
377 | default: | ||
378 | return -EINVAL; | ||
379 | } | ||
380 | |||
381 | /* interface format */ | ||
382 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
383 | case SND_SOC_DAIFMT_I2S: | ||
384 | iface |= SND_SOC_DAIFMT_I2S; | ||
385 | break; | ||
386 | case SND_SOC_DAIFMT_RIGHT_J: | ||
387 | iface |= SND_SOC_DAIFMT_RIGHT_J; | ||
388 | break; | ||
389 | case SND_SOC_DAIFMT_LEFT_J: | ||
390 | iface |= SND_SOC_DAIFMT_LEFT_J; | ||
391 | break; | ||
392 | default: | ||
393 | return -EINVAL; | ||
394 | } | ||
395 | |||
396 | cs4265->format = iface; | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute) | ||
401 | { | ||
402 | struct snd_soc_codec *codec = dai->codec; | ||
403 | |||
404 | if (mute) { | ||
405 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
406 | CS4265_DAC_CTL_MUTE, | ||
407 | CS4265_DAC_CTL_MUTE); | ||
408 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
409 | CS4265_SPDIF_CTL2_MUTE, | ||
410 | CS4265_SPDIF_CTL2_MUTE); | ||
411 | } else { | ||
412 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
413 | CS4265_DAC_CTL_MUTE, | ||
414 | 0); | ||
415 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
416 | CS4265_SPDIF_CTL2_MUTE, | ||
417 | 0); | ||
418 | } | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream, | ||
423 | struct snd_pcm_hw_params *params, | ||
424 | struct snd_soc_dai *dai) | ||
425 | { | ||
426 | struct snd_soc_codec *codec = dai->codec; | ||
427 | struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec); | ||
428 | int index; | ||
429 | |||
430 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && | ||
431 | ((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) | ||
432 | == SND_SOC_DAIFMT_RIGHT_J)) | ||
433 | return -EINVAL; | ||
434 | |||
435 | index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params)); | ||
436 | if (index >= 0) { | ||
437 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
438 | CS4265_ADC_FM, clk_map_table[index].fm_mode); | ||
439 | snd_soc_update_bits(codec, CS4265_MCLK_FREQ, | ||
440 | CS4265_MCLK_FREQ_MASK, | ||
441 | clk_map_table[index].mclkdiv); | ||
442 | |||
443 | } else { | ||
444 | dev_err(codec->dev, "can't get correct mclk\n"); | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
449 | case SND_SOC_DAIFMT_I2S: | ||
450 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
451 | CS4265_DAC_CTL_DIF, (1 << 4)); | ||
452 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
453 | CS4265_ADC_DIF, (1 << 4)); | ||
454 | snd_soc_update_bits(codec, CS4265_SPDIF_CTL2, | ||
455 | CS4265_SPDIF_CTL2_DIF, (1 << 6)); | ||
456 | break; | ||
457 | case SND_SOC_DAIFMT_RIGHT_J: | ||
458 | if (params_width(params) == 16) { | ||
459 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
460 | CS4265_DAC_CTL_DIF, (1 << 5)); | ||
461 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
462 | CS4265_SPDIF_CTL2_DIF, (1 << 7)); | ||
463 | } else { | ||
464 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
465 | CS4265_DAC_CTL_DIF, (3 << 5)); | ||
466 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
467 | CS4265_SPDIF_CTL2_DIF, (1 << 7)); | ||
468 | } | ||
469 | break; | ||
470 | case SND_SOC_DAIFMT_LEFT_J: | ||
471 | snd_soc_update_bits(codec, CS4265_DAC_CTL, | ||
472 | CS4265_DAC_CTL_DIF, 0); | ||
473 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
474 | CS4265_ADC_DIF, 0); | ||
475 | snd_soc_update_bits(codec, CS4265_ADC_CTL, | ||
476 | CS4265_SPDIF_CTL2_DIF, (1 << 6)); | ||
477 | |||
478 | break; | ||
479 | default: | ||
480 | return -EINVAL; | ||
481 | } | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int cs4265_set_bias_level(struct snd_soc_codec *codec, | ||
486 | enum snd_soc_bias_level level) | ||
487 | { | ||
488 | switch (level) { | ||
489 | case SND_SOC_BIAS_ON: | ||
490 | break; | ||
491 | case SND_SOC_BIAS_PREPARE: | ||
492 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
493 | CS4265_PWRCTL_PDN, 0); | ||
494 | break; | ||
495 | case SND_SOC_BIAS_STANDBY: | ||
496 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
497 | CS4265_PWRCTL_PDN, | ||
498 | CS4265_PWRCTL_PDN); | ||
499 | break; | ||
500 | case SND_SOC_BIAS_OFF: | ||
501 | snd_soc_update_bits(codec, CS4265_PWRCTL, | ||
502 | CS4265_PWRCTL_PDN, | ||
503 | CS4265_PWRCTL_PDN); | ||
504 | break; | ||
505 | } | ||
506 | codec->dapm.bias_level = level; | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | #define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
511 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ | ||
512 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ | ||
513 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | ||
514 | |||
515 | #define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
516 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) | ||
517 | |||
518 | static const struct snd_soc_dai_ops cs4265_ops = { | ||
519 | .hw_params = cs4265_pcm_hw_params, | ||
520 | .digital_mute = cs4265_digital_mute, | ||
521 | .set_fmt = cs4265_set_fmt, | ||
522 | .set_sysclk = cs4265_set_sysclk, | ||
523 | }; | ||
524 | |||
525 | static struct snd_soc_dai_driver cs4265_dai[] = { | ||
526 | { | ||
527 | .name = "cs4265-dai1", | ||
528 | .playback = { | ||
529 | .stream_name = "DAI1 Playback", | ||
530 | .channels_min = 1, | ||
531 | .channels_max = 2, | ||
532 | .rates = CS4265_RATES, | ||
533 | .formats = CS4265_FORMATS, | ||
534 | }, | ||
535 | .capture = { | ||
536 | .stream_name = "DAI1 Capture", | ||
537 | .channels_min = 1, | ||
538 | .channels_max = 2, | ||
539 | .rates = CS4265_RATES, | ||
540 | .formats = CS4265_FORMATS, | ||
541 | }, | ||
542 | .ops = &cs4265_ops, | ||
543 | }, | ||
544 | { | ||
545 | .name = "cs4265-dai2", | ||
546 | .playback = { | ||
547 | .stream_name = "DAI2 Playback", | ||
548 | .channels_min = 1, | ||
549 | .channels_max = 2, | ||
550 | .rates = CS4265_RATES, | ||
551 | .formats = CS4265_FORMATS, | ||
552 | }, | ||
553 | .capture = { | ||
554 | .stream_name = "DAI2 Capture", | ||
555 | .channels_min = 1, | ||
556 | .channels_max = 2, | ||
557 | .rates = CS4265_RATES, | ||
558 | .formats = CS4265_FORMATS, | ||
559 | }, | ||
560 | .ops = &cs4265_ops, | ||
561 | }, | ||
562 | }; | ||
563 | |||
564 | static const struct snd_soc_codec_driver soc_codec_cs4265 = { | ||
565 | .set_bias_level = cs4265_set_bias_level, | ||
566 | |||
567 | .dapm_widgets = cs4265_dapm_widgets, | ||
568 | .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), | ||
569 | .dapm_routes = cs4265_audio_map, | ||
570 | .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), | ||
571 | |||
572 | .controls = cs4265_snd_controls, | ||
573 | .num_controls = ARRAY_SIZE(cs4265_snd_controls), | ||
574 | }; | ||
575 | |||
576 | static const struct regmap_config cs4265_regmap = { | ||
577 | .reg_bits = 8, | ||
578 | .val_bits = 8, | ||
579 | |||
580 | .max_register = CS4265_MAX_REGISTER, | ||
581 | .reg_defaults = cs4265_reg_defaults, | ||
582 | .num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults), | ||
583 | .readable_reg = cs4265_readable_register, | ||
584 | .volatile_reg = cs4265_volatile_register, | ||
585 | .cache_type = REGCACHE_RBTREE, | ||
586 | }; | ||
587 | |||
588 | static int cs4265_i2c_probe(struct i2c_client *i2c_client, | ||
589 | const struct i2c_device_id *id) | ||
590 | { | ||
591 | struct cs4265_private *cs4265; | ||
592 | int ret = 0; | ||
593 | unsigned int devid = 0; | ||
594 | unsigned int reg; | ||
595 | |||
596 | cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private), | ||
597 | GFP_KERNEL); | ||
598 | if (cs4265 == NULL) | ||
599 | return -ENOMEM; | ||
600 | cs4265->dev = &i2c_client->dev; | ||
601 | |||
602 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); | ||
603 | if (IS_ERR(cs4265->regmap)) { | ||
604 | ret = PTR_ERR(cs4265->regmap); | ||
605 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | ||
606 | return ret; | ||
607 | } | ||
608 | |||
609 | cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev, | ||
610 | "reset-gpios"); | ||
611 | if (IS_ERR(cs4265->reset_gpio)) { | ||
612 | ret = PTR_ERR(cs4265->reset_gpio); | ||
613 | if (ret != -ENOENT && ret != -ENOSYS) | ||
614 | return ret; | ||
615 | |||
616 | cs4265->reset_gpio = NULL; | ||
617 | } else { | ||
618 | ret = gpiod_direction_output(cs4265->reset_gpio, 0); | ||
619 | if (ret) | ||
620 | return ret; | ||
621 | mdelay(1); | ||
622 | gpiod_set_value_cansleep(cs4265->reset_gpio, 1); | ||
623 | |||
624 | } | ||
625 | |||
626 | i2c_set_clientdata(i2c_client, cs4265); | ||
627 | |||
628 | ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, ®); | ||
629 | devid = reg & CS4265_CHIP_ID_MASK; | ||
630 | if (devid != CS4265_CHIP_ID_VAL) { | ||
631 | ret = -ENODEV; | ||
632 | dev_err(&i2c_client->dev, | ||
633 | "CS4265 Device ID (%X). Expected %X\n", | ||
634 | devid, CS4265_CHIP_ID); | ||
635 | return ret; | ||
636 | } | ||
637 | dev_info(&i2c_client->dev, | ||
638 | "CS4265 Version %x\n", | ||
639 | reg & CS4265_REV_ID_MASK); | ||
640 | |||
641 | regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F); | ||
642 | |||
643 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
644 | &soc_codec_cs4265, cs4265_dai, | ||
645 | ARRAY_SIZE(cs4265_dai)); | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static int cs4265_i2c_remove(struct i2c_client *client) | ||
650 | { | ||
651 | snd_soc_unregister_codec(&client->dev); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | static const struct of_device_id cs4265_of_match[] = { | ||
656 | { .compatible = "cirrus,cs4265", }, | ||
657 | { } | ||
658 | }; | ||
659 | MODULE_DEVICE_TABLE(of, cs4265_of_match); | ||
660 | |||
661 | static const struct i2c_device_id cs4265_id[] = { | ||
662 | { "cs4265", 0 }, | ||
663 | { } | ||
664 | }; | ||
665 | MODULE_DEVICE_TABLE(i2c, cs4265_id); | ||
666 | |||
667 | static struct i2c_driver cs4265_i2c_driver = { | ||
668 | .driver = { | ||
669 | .name = "cs4265", | ||
670 | .owner = THIS_MODULE, | ||
671 | .of_match_table = cs4265_of_match, | ||
672 | }, | ||
673 | .id_table = cs4265_id, | ||
674 | .probe = cs4265_i2c_probe, | ||
675 | .remove = cs4265_i2c_remove, | ||
676 | }; | ||
677 | |||
678 | module_i2c_driver(cs4265_i2c_driver); | ||
679 | |||
680 | MODULE_DESCRIPTION("ASoC CS4265 driver"); | ||
681 | MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>"); | ||
682 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4265.h b/sound/soc/codecs/cs4265.h new file mode 100644 index 000000000000..0a80a8dcec67 --- /dev/null +++ b/sound/soc/codecs/cs4265.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * cs4265.h -- CS4265 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Author: Paul Handrigan <paul.handrigan@cirrus.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 | |||
14 | #ifndef __CS4265_H__ | ||
15 | #define __CS4265_H__ | ||
16 | |||
17 | #define CS4265_CHIP_ID 0x1 | ||
18 | #define CS4265_CHIP_ID_VAL 0xD0 | ||
19 | #define CS4265_CHIP_ID_MASK 0xF0 | ||
20 | #define CS4265_REV_ID_MASK 0x0F | ||
21 | |||
22 | #define CS4265_PWRCTL 0x02 | ||
23 | #define CS4265_PWRCTL_PDN 1 | ||
24 | |||
25 | #define CS4265_DAC_CTL 0x3 | ||
26 | #define CS4265_DAC_CTL_MUTE (1 << 2) | ||
27 | #define CS4265_DAC_CTL_DIF (3 << 4) | ||
28 | |||
29 | #define CS4265_ADC_CTL 0x4 | ||
30 | #define CS4265_ADC_MASTER 1 | ||
31 | #define CS4265_ADC_DIF (1 << 4) | ||
32 | #define CS4265_ADC_FM (3 << 6) | ||
33 | |||
34 | #define CS4265_MCLK_FREQ 0x5 | ||
35 | #define CS4265_MCLK_FREQ_MASK (7 << 4) | ||
36 | |||
37 | #define CS4265_SIG_SEL 0x6 | ||
38 | #define CS4265_SIG_SEL_LOOP (1 << 1) | ||
39 | |||
40 | #define CS4265_CHB_PGA_CTL 0x7 | ||
41 | #define CS4265_CHA_PGA_CTL 0x8 | ||
42 | |||
43 | #define CS4265_ADC_CTL2 0x9 | ||
44 | |||
45 | #define CS4265_DAC_CHA_VOL 0xA | ||
46 | #define CS4265_DAC_CHB_VOL 0xB | ||
47 | |||
48 | #define CS4265_DAC_CTL2 0xC | ||
49 | |||
50 | #define CS4265_INT_STATUS 0xD | ||
51 | #define CS4265_INT_MASK 0xE | ||
52 | #define CS4265_STATUS_MODE_MSB 0xF | ||
53 | #define CS4265_STATUS_MODE_LSB 0x10 | ||
54 | |||
55 | #define CS4265_SPDIF_CTL1 0x11 | ||
56 | |||
57 | #define CS4265_SPDIF_CTL2 0x12 | ||
58 | #define CS4265_SPDIF_CTL2_MUTE (1 << 4) | ||
59 | #define CS4265_SPDIF_CTL2_DIF (3 << 6) | ||
60 | |||
61 | #define CS4265_C_DATA_BUFF 0x13 | ||
62 | #define CS4265_MAX_REGISTER 0x2A | ||
63 | |||
64 | #endif | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 9947a9583679..e6d4ff9fd992 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
664 | 664 | ||
665 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), | 665 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), |
666 | GFP_KERNEL); | 666 | GFP_KERNEL); |
667 | if (!cs4270) { | 667 | if (!cs4270) |
668 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
669 | return -ENOMEM; | 668 | return -ENOMEM; |
670 | } | ||
671 | 669 | ||
672 | /* get the power supply regulators */ | 670 | /* get the power supply regulators */ |
673 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | 671 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 071fc77f2f06..969167d8b71e 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -399,15 +399,15 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
399 | CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv), | 399 | CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv), |
400 | 400 | ||
401 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL, | 401 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL, |
402 | CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv), | 402 | CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv), |
403 | 403 | ||
404 | SOC_ENUM("Headphone Analog Gain", hp_gain_enum), | 404 | SOC_ENUM("Headphone Analog Gain", hp_gain_enum), |
405 | 405 | ||
406 | SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL, | 406 | SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL, |
407 | CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv), | 407 | CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv), |
408 | 408 | ||
409 | SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, | 409 | SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, |
410 | CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv), | 410 | CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv), |
411 | 411 | ||
412 | SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), | 412 | SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), |
413 | 413 | ||
@@ -417,10 +417,10 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
417 | SOC_ENUM("MIC Bias Level", mic_bias_level_enum), | 417 | SOC_ENUM("MIC Bias Level", mic_bias_level_enum), |
418 | 418 | ||
419 | SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL, | 419 | SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL, |
420 | CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv), | 420 | CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv), |
421 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", | 421 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", |
422 | CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, | 422 | CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, |
423 | 6, 0x7f, 0x19, ipd_tlv), | 423 | 0, 0x19, 0x7F, ipd_tlv), |
424 | 424 | ||
425 | SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), | 425 | SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), |
426 | 426 | ||
@@ -428,11 +428,11 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
428 | CS42L52_ADCB_MIXER_VOL, 7, 1, 1), | 428 | CS42L52_ADCB_MIXER_VOL, 7, 1, 1), |
429 | 429 | ||
430 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL, | 430 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL, |
431 | CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv), | 431 | CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv), |
432 | 432 | ||
433 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", | 433 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", |
434 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, | 434 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, |
435 | 0, 0x7f, 0x19, mix_tlv), | 435 | 0, 0x19, 0x7f, mix_tlv), |
436 | SOC_DOUBLE_R("PCM Mixer Switch", | 436 | SOC_DOUBLE_R("PCM Mixer Switch", |
437 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1), | 437 | CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1), |
438 | 438 | ||
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index fdc4bd27b0df..c766a5a9ce80 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -318,24 +318,32 @@ static const struct soc_enum adca_swap_enum = | |||
318 | ARRAY_SIZE(left_swap_text), | 318 | ARRAY_SIZE(left_swap_text), |
319 | left_swap_text, | 319 | left_swap_text, |
320 | swap_values); | 320 | swap_values); |
321 | static const struct snd_kcontrol_new adca_swap_mux = | ||
322 | SOC_DAPM_ENUM("Route", adca_swap_enum); | ||
321 | 323 | ||
322 | static const struct soc_enum pcma_swap_enum = | 324 | static const struct soc_enum pcma_swap_enum = |
323 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3, | 325 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3, |
324 | ARRAY_SIZE(left_swap_text), | 326 | ARRAY_SIZE(left_swap_text), |
325 | left_swap_text, | 327 | left_swap_text, |
326 | swap_values); | 328 | swap_values); |
329 | static const struct snd_kcontrol_new pcma_swap_mux = | ||
330 | SOC_DAPM_ENUM("Route", pcma_swap_enum); | ||
327 | 331 | ||
328 | static const struct soc_enum adcb_swap_enum = | 332 | static const struct soc_enum adcb_swap_enum = |
329 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3, | 333 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3, |
330 | ARRAY_SIZE(right_swap_text), | 334 | ARRAY_SIZE(right_swap_text), |
331 | right_swap_text, | 335 | right_swap_text, |
332 | swap_values); | 336 | swap_values); |
337 | static const struct snd_kcontrol_new adcb_swap_mux = | ||
338 | SOC_DAPM_ENUM("Route", adcb_swap_enum); | ||
333 | 339 | ||
334 | static const struct soc_enum pcmb_swap_enum = | 340 | static const struct soc_enum pcmb_swap_enum = |
335 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3, | 341 | SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3, |
336 | ARRAY_SIZE(right_swap_text), | 342 | ARRAY_SIZE(right_swap_text), |
337 | right_swap_text, | 343 | right_swap_text, |
338 | swap_values); | 344 | swap_values); |
345 | static const struct snd_kcontrol_new pcmb_swap_mux = | ||
346 | SOC_DAPM_ENUM("Route", pcmb_swap_enum); | ||
339 | 347 | ||
340 | static const struct snd_kcontrol_new hpa_switch = | 348 | static const struct snd_kcontrol_new hpa_switch = |
341 | SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1); | 349 | SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1); |
@@ -421,15 +429,15 @@ static const struct soc_enum ng_delay_enum = | |||
421 | static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | 429 | static const struct snd_kcontrol_new cs42l56_snd_controls[] = { |
422 | 430 | ||
423 | SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME, | 431 | SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME, |
424 | CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xfd, adv_tlv), | 432 | CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv), |
425 | SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1), | 433 | SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1), |
426 | 434 | ||
427 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME, | 435 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME, |
428 | CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv), | 436 | CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), |
429 | SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1), | 437 | SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1), |
430 | 438 | ||
431 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME, | 439 | SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME, |
432 | CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0xa9, hl_tlv), | 440 | CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), |
433 | SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1), | 441 | SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1), |
434 | 442 | ||
435 | SOC_SINGLE_TLV("Analog Advisory Volume", | 443 | SOC_SINGLE_TLV("Analog Advisory Volume", |
@@ -438,16 +446,16 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | |||
438 | CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), | 446 | CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), |
439 | 447 | ||
440 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME, | 448 | SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME, |
441 | CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0xfd, pga_tlv), | 449 | CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv), |
442 | SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR, | 450 | SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR, |
443 | CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv), | 451 | CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv), |
444 | SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1), | 452 | SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1), |
445 | SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), | 453 | SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), |
446 | 454 | ||
447 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, | 455 | SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, |
448 | CS42L56_HPA_VOLUME, 0, 0x44, 0x55, hl_tlv), | 456 | CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv), |
449 | SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, | 457 | SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, |
450 | CS42L56_LOA_VOLUME, 0, 0x44, 0x55, hl_tlv), | 458 | CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv), |
451 | 459 | ||
452 | SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, | 460 | SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, |
453 | 0, 0x00, 1, tone_tlv), | 461 | 0, 0x00, 1, tone_tlv), |
@@ -467,11 +475,6 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { | |||
467 | SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1), | 475 | SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1), |
468 | SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1), | 476 | SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1), |
469 | 477 | ||
470 | SOC_ENUM("PCMA Swap", pcma_swap_enum), | ||
471 | SOC_ENUM("PCMB Swap", pcmb_swap_enum), | ||
472 | SOC_ENUM("ADCA Swap", adca_swap_enum), | ||
473 | SOC_ENUM("ADCB Swap", adcb_swap_enum), | ||
474 | |||
475 | SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1), | 478 | SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1), |
476 | SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1), | 479 | SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1), |
477 | SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum), | 480 | SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum), |
@@ -570,6 +573,16 @@ static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = { | |||
570 | SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1), | 573 | SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1), |
571 | SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1), | 574 | SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1), |
572 | 575 | ||
576 | SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0, | ||
577 | &adca_swap_mux), | ||
578 | SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0, | ||
579 | &adcb_swap_mux), | ||
580 | |||
581 | SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0, | ||
582 | &pcma_swap_mux), | ||
583 | SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0, | ||
584 | &pcmb_swap_mux), | ||
585 | |||
573 | SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0), | 586 | SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0), |
574 | SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0), | 587 | SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0), |
575 | 588 | ||
@@ -607,8 +620,19 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = { | |||
607 | {"Digital Output Mux", NULL, "ADCA"}, | 620 | {"Digital Output Mux", NULL, "ADCA"}, |
608 | {"Digital Output Mux", NULL, "ADCB"}, | 621 | {"Digital Output Mux", NULL, "ADCB"}, |
609 | 622 | ||
610 | {"ADCB", NULL, "ADCB Mux"}, | 623 | {"ADCB", NULL, "ADCB Swap Mux"}, |
611 | {"ADCA", NULL, "ADCA Mux"}, | 624 | {"ADCA", NULL, "ADCA Swap Mux"}, |
625 | |||
626 | {"ADCA Swap Mux", NULL, "ADCA"}, | ||
627 | {"ADCB Swap Mux", NULL, "ADCB"}, | ||
628 | |||
629 | {"DACA", "Left", "ADCA Swap Mux"}, | ||
630 | {"DACA", "LR 2", "ADCA Swap Mux"}, | ||
631 | {"DACA", "Right", "ADCA Swap Mux"}, | ||
632 | |||
633 | {"DACB", "Left", "ADCB Swap Mux"}, | ||
634 | {"DACB", "LR 2", "ADCB Swap Mux"}, | ||
635 | {"DACB", "Right", "ADCB Swap Mux"}, | ||
612 | 636 | ||
613 | {"ADCA Mux", NULL, "AIN3A"}, | 637 | {"ADCA Mux", NULL, "AIN3A"}, |
614 | {"ADCA Mux", NULL, "AIN2A"}, | 638 | {"ADCA Mux", NULL, "AIN2A"}, |
@@ -633,30 +657,32 @@ static const struct snd_soc_dapm_route cs42l56_audio_map[] = { | |||
633 | {"PGAB Input Mux", NULL, "AIN2B"}, | 657 | {"PGAB Input Mux", NULL, "AIN2B"}, |
634 | {"PGAB Input Mux", NULL, "AIN3B"}, | 658 | {"PGAB Input Mux", NULL, "AIN3B"}, |
635 | 659 | ||
636 | {"LOB", NULL, "Lineout Right"}, | 660 | {"LOB", "Switch", "LINEOUTB Input Mux"}, |
637 | {"LOA", NULL, "Lineout Left"}, | 661 | {"LOA", "Switch", "LINEOUTA Input Mux"}, |
638 | |||
639 | {"Lineout Right", "Switch", "LINEOUTB Input Mux"}, | ||
640 | {"Lineout Left", "Switch", "LINEOUTA Input Mux"}, | ||
641 | 662 | ||
642 | {"LINEOUTA Input Mux", "PGAA", "PGAA"}, | 663 | {"LINEOUTA Input Mux", "PGAA", "PGAA"}, |
643 | {"LINEOUTB Input Mux", "PGAB", "PGAB"}, | 664 | {"LINEOUTB Input Mux", "PGAB", "PGAB"}, |
644 | {"LINEOUTA Input Mux", "DACA", "DACA"}, | 665 | {"LINEOUTA Input Mux", "DACA", "DACA"}, |
645 | {"LINEOUTB Input Mux", "DACB", "DACB"}, | 666 | {"LINEOUTB Input Mux", "DACB", "DACB"}, |
646 | 667 | ||
647 | {"HPA", NULL, "Headphone Left"}, | 668 | {"HPA", "Switch", "HPB Input Mux"}, |
648 | {"HPB", NULL, "Headphone Right"}, | 669 | {"HPB", "Switch", "HPA Input Mux"}, |
649 | |||
650 | {"Headphone Right", "Switch", "HPB Input Mux"}, | ||
651 | {"Headphone Left", "Switch", "HPA Input Mux"}, | ||
652 | 670 | ||
653 | {"HPA Input Mux", "PGAA", "PGAA"}, | 671 | {"HPA Input Mux", "PGAA", "PGAA"}, |
654 | {"HPB Input Mux", "PGAB", "PGAB"}, | 672 | {"HPB Input Mux", "PGAB", "PGAB"}, |
655 | {"HPA Input Mux", "DACA", "DACA"}, | 673 | {"HPA Input Mux", "DACA", "DACA"}, |
656 | {"HPB Input Mux", "DACB", "DACB"}, | 674 | {"HPB Input Mux", "DACB", "DACB"}, |
657 | 675 | ||
658 | {"DACB", NULL, "HiFi Playback"}, | 676 | {"DACA", NULL, "PCMA Swap Mux"}, |
659 | {"DACA", NULL, "HiFi Playback"}, | 677 | {"DACB", NULL, "PCMB Swap Mux"}, |
678 | |||
679 | {"PCMB Swap Mux", "Left", "HiFi Playback"}, | ||
680 | {"PCMB Swap Mux", "LR 2", "HiFi Playback"}, | ||
681 | {"PCMB Swap Mux", "Right", "HiFi Playback"}, | ||
682 | |||
683 | {"PCMA Swap Mux", "Left", "HiFi Playback"}, | ||
684 | {"PCMA Swap Mux", "LR 2", "HiFi Playback"}, | ||
685 | {"PCMA Swap Mux", "Right", "HiFi Playback"}, | ||
660 | 686 | ||
661 | }; | 687 | }; |
662 | 688 | ||
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index ae3717992d56..0e7b9eb2ba61 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -401,7 +401,7 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = { | |||
401 | CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv), | 401 | CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv), |
402 | 402 | ||
403 | SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL, | 403 | SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL, |
404 | CS42L73_MICBPREPGABVOL, 5, 0x34, | 404 | CS42L73_MICBPREPGABVOL, 0, 0x34, |
405 | 0x24, micpga_tlv), | 405 | 0x24, micpga_tlv), |
406 | 406 | ||
407 | SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL, | 407 | SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL, |
@@ -1408,10 +1408,8 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1408 | 1408 | ||
1409 | cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private), | 1409 | cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private), |
1410 | GFP_KERNEL); | 1410 | GFP_KERNEL); |
1411 | if (!cs42l73) { | 1411 | if (!cs42l73) |
1412 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
1413 | return -ENOMEM; | 1412 | return -ENOMEM; |
1414 | } | ||
1415 | 1413 | ||
1416 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); | 1414 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); |
1417 | if (IS_ERR(cs42l73->regmap)) { | 1415 | if (IS_ERR(cs42l73->regmap)) { |
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index a25bc6061a30..02b1520ae0bc 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -219,6 +219,9 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
219 | case SND_SOC_DAIFMT_RIGHT_J: | 219 | case SND_SOC_DAIFMT_RIGHT_J: |
220 | val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; | 220 | val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; |
221 | break; | 221 | break; |
222 | case SND_SOC_DAIFMT_DSP_A: | ||
223 | val = CS42XX8_INTF_DAC_DIF_TDM | CS42XX8_INTF_ADC_DIF_TDM; | ||
224 | break; | ||
222 | default: | 225 | default: |
223 | dev_err(codec->dev, "unsupported dai format\n"); | 226 | dev_err(codec->dev, "unsupported dai format\n"); |
224 | return -EINVAL; | 227 | return -EINVAL; |
@@ -422,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = { | |||
422 | }; | 425 | }; |
423 | EXPORT_SYMBOL_GPL(cs42888_data); | 426 | EXPORT_SYMBOL_GPL(cs42888_data); |
424 | 427 | ||
425 | const struct of_device_id cs42xx8_of_match[] = { | 428 | static const struct of_device_id cs42xx8_of_match[] = { |
426 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, | 429 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, |
427 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, | 430 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, |
428 | { /* sentinel */ } | 431 | { /* sentinel */ } |
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h index da0b94aee419..b2c10e537ef6 100644 --- a/sound/soc/codecs/cs42xx8.h +++ b/sound/soc/codecs/cs42xx8.h | |||
@@ -128,8 +128,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap); | |||
128 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) | 128 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) |
129 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) | 129 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) |
130 | #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) | 130 | #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) |
131 | #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) | 131 | #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (5 << CS42XX8_INTF_DAC_DIF_SHIFT) |
132 | #define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) | 132 | #define CS42XX8_INTF_DAC_DIF_TDM (6 << CS42XX8_INTF_DAC_DIF_SHIFT) |
133 | #define CS42XX8_INTF_ADC_DIF_SHIFT 0 | 133 | #define CS42XX8_INTF_ADC_DIF_SHIFT 0 |
134 | #define CS42XX8_INTF_ADC_DIF_WIDTH 3 | 134 | #define CS42XX8_INTF_ADC_DIF_WIDTH 3 |
135 | #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) | 135 | #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) |
@@ -138,8 +138,8 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap); | |||
138 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) | 138 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) |
139 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) | 139 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) |
140 | #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) | 140 | #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) |
141 | #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) | 141 | #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (5 << CS42XX8_INTF_ADC_DIF_SHIFT) |
142 | #define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) | 142 | #define CS42XX8_INTF_ADC_DIF_TDM (6 << CS42XX8_INTF_ADC_DIF_SHIFT) |
143 | 143 | ||
144 | /* ADC Control & DAC De-Emphasis (Address 05h) */ | 144 | /* ADC Control & DAC De-Emphasis (Address 05h) */ |
145 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 | 145 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index d5fd00a64748..8f95b0300f1a 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty) | |||
253 | /* Prevent the codec driver from further accessing the modem */ | 253 | /* Prevent the codec driver from further accessing the modem */ |
254 | codec->hw_write = NULL; | 254 | codec->hw_write = NULL; |
255 | cx20442->control_data = NULL; | 255 | cx20442->control_data = NULL; |
256 | codec->card->pop_time = 0; | 256 | codec->component.card->pop_time = 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* Line discipline .hangup() */ | 259 | /* Line discipline .hangup() */ |
@@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty, | |||
281 | /* Set up codec driver access to modem controls */ | 281 | /* Set up codec driver access to modem controls */ |
282 | cx20442->control_data = tty; | 282 | cx20442->control_data = tty; |
283 | codec->hw_write = (hw_write_t)tty->ops->write; | 283 | codec->hw_write = (hw_write_t)tty->ops->write; |
284 | codec->card->pop_time = 1; | 284 | codec->component.card->pop_time = 1; |
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
@@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec) | |||
372 | 372 | ||
373 | snd_soc_codec_set_drvdata(codec, cx20442); | 373 | snd_soc_codec_set_drvdata(codec, cx20442); |
374 | codec->hw_write = NULL; | 374 | codec->hw_write = NULL; |
375 | codec->card->pop_time = 0; | 375 | codec->component.card->pop_time = 0; |
376 | 376 | ||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
@@ -383,8 +383,8 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) | |||
383 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); | 383 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); |
384 | 384 | ||
385 | if (cx20442->control_data) { | 385 | if (cx20442->control_data) { |
386 | struct tty_struct *tty = cx20442->control_data; | 386 | struct tty_struct *tty = cx20442->control_data; |
387 | tty_hangup(tty); | 387 | tty_hangup(tty); |
388 | } | 388 | } |
389 | 389 | ||
390 | if (!IS_ERR(cx20442->por)) { | 390 | if (!IS_ERR(cx20442->por)) { |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 9134982807b5..2cd3e5427441 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -1299,12 +1299,12 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, | |||
1299 | 1299 | ||
1300 | rate = params_rate(params); | 1300 | rate = params_rate(params); |
1301 | 1301 | ||
1302 | switch (params_format(params)) { | 1302 | switch (params_width(params)) { |
1303 | case SNDRV_PCM_FORMAT_S16_LE: | 1303 | case 16: |
1304 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | 1304 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, |
1305 | M98088_DAI_WS, 0); | 1305 | M98088_DAI_WS, 0); |
1306 | break; | 1306 | break; |
1307 | case SNDRV_PCM_FORMAT_S24_LE: | 1307 | case 24: |
1308 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | 1308 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, |
1309 | M98088_DAI_WS, M98088_DAI_WS); | 1309 | M98088_DAI_WS, M98088_DAI_WS); |
1310 | break; | 1310 | break; |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index f5fccc7a8e89..4a063fa88526 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -26,10 +26,6 @@ | |||
26 | #include <sound/max98090.h> | 26 | #include <sound/max98090.h> |
27 | #include "max98090.h" | 27 | #include "max98090.h" |
28 | 28 | ||
29 | #define DEBUG | ||
30 | #define EXTMIC_METHOD | ||
31 | #define EXTMIC_METHOD_TEST | ||
32 | |||
33 | /* Allows for sparsely populated register maps */ | 29 | /* Allows for sparsely populated register maps */ |
34 | static struct reg_default max98090_reg[] = { | 30 | static struct reg_default max98090_reg[] = { |
35 | { 0x00, 0x00 }, /* 00 Software Reset */ | 31 | { 0x00, 0x00 }, /* 00 Software Reset */ |
@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, | |||
820 | else | 816 | else |
821 | val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; | 817 | val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; |
822 | 818 | ||
823 | |||
824 | if (val >= 1) { | 819 | if (val >= 1) { |
825 | if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { | 820 | if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { |
826 | max98090->pa1en = val - 1; /* Update for volatile */ | 821 | max98090->pa1en = val - 1; /* Update for volatile */ |
@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux = | |||
1140 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); | 1135 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); |
1141 | 1136 | ||
1142 | static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | 1137 | static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { |
1143 | |||
1144 | SND_SOC_DAPM_INPUT("MIC1"), | 1138 | SND_SOC_DAPM_INPUT("MIC1"), |
1145 | SND_SOC_DAPM_INPUT("MIC2"), | 1139 | SND_SOC_DAPM_INPUT("MIC2"), |
1146 | SND_SOC_DAPM_INPUT("DMICL"), | 1140 | SND_SOC_DAPM_INPUT("DMICL"), |
@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | |||
1304 | }; | 1298 | }; |
1305 | 1299 | ||
1306 | static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { | 1300 | static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { |
1307 | |||
1308 | SND_SOC_DAPM_INPUT("DMIC3"), | 1301 | SND_SOC_DAPM_INPUT("DMIC3"), |
1309 | SND_SOC_DAPM_INPUT("DMIC4"), | 1302 | SND_SOC_DAPM_INPUT("DMIC4"), |
1310 | 1303 | ||
@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { | |||
1315 | }; | 1308 | }; |
1316 | 1309 | ||
1317 | static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | 1310 | static const struct snd_soc_dapm_route max98090_dapm_routes[] = { |
1318 | |||
1319 | {"MIC1 Input", NULL, "MIC1"}, | 1311 | {"MIC1 Input", NULL, "MIC1"}, |
1320 | {"MIC2 Input", NULL, "MIC2"}, | 1312 | {"MIC2 Input", NULL, "MIC2"}, |
1321 | 1313 | ||
@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1493 | {"SPKR", NULL, "SPK Right Out"}, | 1485 | {"SPKR", NULL, "SPK Right Out"}, |
1494 | {"RCVL", NULL, "RCV Left Out"}, | 1486 | {"RCVL", NULL, "RCV Left Out"}, |
1495 | {"RCVR", NULL, "RCV Right Out"}, | 1487 | {"RCVR", NULL, "RCV Right Out"}, |
1496 | |||
1497 | }; | 1488 | }; |
1498 | 1489 | ||
1499 | static const struct snd_soc_dapm_route max98091_dapm_routes[] = { | 1490 | static const struct snd_soc_dapm_route max98091_dapm_routes[] = { |
1500 | |||
1501 | /* DMIC inputs */ | 1491 | /* DMIC inputs */ |
1502 | {"DMIC3", NULL, "DMIC3_ENA"}, | 1492 | {"DMIC3", NULL, "DMIC3_ENA"}, |
1503 | {"DMIC4", NULL, "DMIC4_ENA"}, | 1493 | {"DMIC4", NULL, "DMIC4_ENA"}, |
1504 | {"DMIC3", NULL, "AHPF"}, | 1494 | {"DMIC3", NULL, "AHPF"}, |
1505 | {"DMIC4", NULL, "AHPF"}, | 1495 | {"DMIC4", NULL, "AHPF"}, |
1506 | |||
1507 | }; | 1496 | }; |
1508 | 1497 | ||
1509 | static int max98090_add_widgets(struct snd_soc_codec *codec) | 1498 | static int max98090_add_widgets(struct snd_soc_codec *codec) |
@@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec) | |||
1531 | 1520 | ||
1532 | snd_soc_dapm_add_routes(dapm, max98091_dapm_routes, | 1521 | snd_soc_dapm_add_routes(dapm, max98091_dapm_routes, |
1533 | ARRAY_SIZE(max98091_dapm_routes)); | 1522 | ARRAY_SIZE(max98091_dapm_routes)); |
1534 | |||
1535 | } | 1523 | } |
1536 | 1524 | ||
1537 | return 0; | 1525 | return 0; |
@@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = { | |||
2212 | } | 2200 | } |
2213 | }; | 2201 | }; |
2214 | 2202 | ||
2215 | static void max98090_handle_pdata(struct snd_soc_codec *codec) | ||
2216 | { | ||
2217 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | ||
2218 | struct max98090_pdata *pdata = max98090->pdata; | ||
2219 | |||
2220 | if (!pdata) { | ||
2221 | dev_err(codec->dev, "No platform data\n"); | ||
2222 | return; | ||
2223 | } | ||
2224 | |||
2225 | } | ||
2226 | |||
2227 | static int max98090_probe(struct snd_soc_codec *codec) | 2203 | static int max98090_probe(struct snd_soc_codec *codec) |
2228 | { | 2204 | { |
2229 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 2205 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
2230 | struct max98090_cdata *cdata; | 2206 | struct max98090_cdata *cdata; |
2207 | enum max98090_type devtype; | ||
2231 | int ret = 0; | 2208 | int ret = 0; |
2232 | 2209 | ||
2233 | dev_dbg(codec->dev, "max98090_probe\n"); | 2210 | dev_dbg(codec->dev, "max98090_probe\n"); |
@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2263 | } | 2240 | } |
2264 | 2241 | ||
2265 | if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { | 2242 | if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { |
2266 | max98090->devtype = MAX98090; | 2243 | devtype = MAX98090; |
2267 | dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); | 2244 | dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); |
2268 | } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { | 2245 | } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { |
2269 | max98090->devtype = MAX98091; | 2246 | devtype = MAX98091; |
2270 | dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); | 2247 | dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); |
2271 | } else { | 2248 | } else { |
2272 | max98090->devtype = MAX98090; | 2249 | devtype = MAX98090; |
2273 | dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); | 2250 | dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); |
2274 | } | 2251 | } |
2275 | 2252 | ||
2253 | if (max98090->devtype != devtype) { | ||
2254 | dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n"); | ||
2255 | max98090->devtype = devtype; | ||
2256 | } | ||
2257 | |||
2276 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; | 2258 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; |
2277 | 2259 | ||
2278 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); | 2260 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); |
@@ -2284,7 +2266,7 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2284 | /* Register for interrupts */ | 2266 | /* Register for interrupts */ |
2285 | dev_dbg(codec->dev, "irq = %d\n", max98090->irq); | 2267 | dev_dbg(codec->dev, "irq = %d\n", max98090->irq); |
2286 | 2268 | ||
2287 | ret = request_threaded_irq(max98090->irq, NULL, | 2269 | ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, |
2288 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 2270 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
2289 | "max98090_interrupt", codec); | 2271 | "max98090_interrupt", codec); |
2290 | if (ret < 0) { | 2272 | if (ret < 0) { |
@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2317 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, | 2299 | snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, |
2318 | M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); | 2300 | M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); |
2319 | 2301 | ||
2320 | max98090_handle_pdata(codec); | ||
2321 | |||
2322 | max98090_add_widgets(codec); | 2302 | max98090_add_widgets(codec); |
2323 | 2303 | ||
2324 | err_access: | 2304 | err_access: |
@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev) | |||
2428 | } | 2408 | } |
2429 | #endif | 2409 | #endif |
2430 | 2410 | ||
2431 | #ifdef CONFIG_PM | 2411 | #ifdef CONFIG_PM_SLEEP |
2432 | static int max98090_resume(struct device *dev) | 2412 | static int max98090_resume(struct device *dev) |
2433 | { | 2413 | { |
2434 | struct max98090_priv *max98090 = dev_get_drvdata(dev); | 2414 | struct max98090_priv *max98090 = dev_get_drvdata(dev); |
@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = { | |||
2460 | 2440 | ||
2461 | static const struct i2c_device_id max98090_i2c_id[] = { | 2441 | static const struct i2c_device_id max98090_i2c_id[] = { |
2462 | { "max98090", MAX98090 }, | 2442 | { "max98090", MAX98090 }, |
2443 | { "max98091", MAX98091 }, | ||
2463 | { } | 2444 | { } |
2464 | }; | 2445 | }; |
2465 | MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); | 2446 | MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); |
2466 | 2447 | ||
2467 | static const struct of_device_id max98090_of_match[] = { | 2448 | static const struct of_device_id max98090_of_match[] = { |
2468 | { .compatible = "maxim,max98090", }, | 2449 | { .compatible = "maxim,max98090", }, |
2450 | { .compatible = "maxim,max98091", }, | ||
2469 | { } | 2451 | { } |
2470 | }; | 2452 | }; |
2471 | MODULE_DEVICE_TABLE(of, max98090_of_match); | 2453 | MODULE_DEVICE_TABLE(of, max98090_of_match); |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 89ec00424880..0ee6797d5083 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -1280,12 +1280,12 @@ static int max98095_dai2_hw_params(struct snd_pcm_substream *substream, | |||
1280 | 1280 | ||
1281 | rate = params_rate(params); | 1281 | rate = params_rate(params); |
1282 | 1282 | ||
1283 | switch (params_format(params)) { | 1283 | switch (params_width(params)) { |
1284 | case SNDRV_PCM_FORMAT_S16_LE: | 1284 | case 16: |
1285 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, | 1285 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, |
1286 | M98095_DAI_WS, 0); | 1286 | M98095_DAI_WS, 0); |
1287 | break; | 1287 | break; |
1288 | case SNDRV_PCM_FORMAT_S24_LE: | 1288 | case 24: |
1289 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, | 1289 | snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, |
1290 | M98095_DAI_WS, M98095_DAI_WS); | 1290 | M98095_DAI_WS, M98095_DAI_WS); |
1291 | break; | 1291 | break; |
@@ -1341,12 +1341,12 @@ static int max98095_dai3_hw_params(struct snd_pcm_substream *substream, | |||
1341 | 1341 | ||
1342 | rate = params_rate(params); | 1342 | rate = params_rate(params); |
1343 | 1343 | ||
1344 | switch (params_format(params)) { | 1344 | switch (params_width(params)) { |
1345 | case SNDRV_PCM_FORMAT_S16_LE: | 1345 | case 16: |
1346 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, | 1346 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, |
1347 | M98095_DAI_WS, 0); | 1347 | M98095_DAI_WS, 0); |
1348 | break; | 1348 | break; |
1349 | case SNDRV_PCM_FORMAT_S24_LE: | 1349 | case 24: |
1350 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, | 1350 | snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, |
1351 | M98095_DAI_WS, M98095_DAI_WS); | 1351 | M98095_DAI_WS, M98095_DAI_WS); |
1352 | break; | 1352 | break; |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 9965277b595a..388f90a597fa 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
766 | 766 | ||
767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); | 767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); |
768 | if (ret) | 768 | if (ret) |
769 | return ret; | 769 | goto out; |
770 | 770 | ||
771 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); | 771 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); |
772 | if (ret) | 772 | if (ret) |
773 | return ret; | 773 | goto out; |
774 | } | 774 | } |
775 | 775 | ||
776 | dev_set_drvdata(&pdev->dev, priv); | 776 | dev_set_drvdata(&pdev->dev, priv); |
@@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
783 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, | 783 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, |
784 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); | 784 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); |
785 | 785 | ||
786 | out: | ||
787 | of_node_put(np); | ||
786 | return ret; | 788 | return ret; |
787 | } | 789 | } |
788 | 790 | ||
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 3a80ba4452df..57b0c94a710b 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define PCM1792A_DAC_VOL_LEFT 0x10 | 36 | #define PCM1792A_DAC_VOL_LEFT 0x10 |
37 | #define PCM1792A_DAC_VOL_RIGHT 0x11 | 37 | #define PCM1792A_DAC_VOL_RIGHT 0x11 |
38 | #define PCM1792A_FMT_CONTROL 0x12 | 38 | #define PCM1792A_FMT_CONTROL 0x12 |
39 | #define PCM1792A_MODE_CONTROL 0x13 | ||
39 | #define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL | 40 | #define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL |
40 | 41 | ||
41 | #define PCM1792A_FMT_MASK 0x70 | 42 | #define PCM1792A_FMT_MASK 0x70 |
@@ -164,6 +165,8 @@ static const struct snd_kcontrol_new pcm1792a_controls[] = { | |||
164 | SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT, | 165 | SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT, |
165 | PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0, | 166 | PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0, |
166 | pcm1792a_dac_tlv), | 167 | pcm1792a_dac_tlv), |
168 | SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0), | ||
169 | SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0), | ||
167 | }; | 170 | }; |
168 | 171 | ||
169 | static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = { | 172 | static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = { |
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h index 7a83d1fc102a..51d5470fee16 100644 --- a/sound/soc/codecs/pcm1792a.h +++ b/sound/soc/codecs/pcm1792a.h | |||
@@ -18,7 +18,8 @@ | |||
18 | #define __PCM1792A_H__ | 18 | #define __PCM1792A_H__ |
19 | 19 | ||
20 | #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ | 20 | #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ |
21 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) | 21 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ |
22 | SNDRV_PCM_RATE_192000) | ||
22 | 23 | ||
23 | #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ | 24 | #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
24 | SNDRV_PCM_FMTBIT_S16_LE) | 25 | SNDRV_PCM_FMTBIT_S16_LE) |
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 7b82fbe0d14c..56650d6c2f53 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c | |||
@@ -11,25 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 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/gpio.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_gpio.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/spi/spi.h> | ||
25 | #include <linux/acpi.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/tlv.h> | ||
33 | 14 | ||
34 | #include "rl6231.h" | 15 | #include "rl6231.h" |
35 | 16 | ||
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c new file mode 100644 index 000000000000..e4f6102efc1a --- /dev/null +++ b/sound/soc/codecs/rt286.c | |||
@@ -0,0 +1,1222 @@ | |||
1 | /* | ||
2 | * rt286.c -- RT286 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2013 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.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 <linux/spi/spi.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <sound/rt286.h> | ||
31 | #include <sound/hda_verbs.h> | ||
32 | |||
33 | #include "rt286.h" | ||
34 | |||
35 | #define RT286_VENDOR_ID 0x10ec0286 | ||
36 | |||
37 | struct rt286_priv { | ||
38 | struct regmap *regmap; | ||
39 | struct rt286_platform_data pdata; | ||
40 | struct i2c_client *i2c; | ||
41 | struct snd_soc_jack *jack; | ||
42 | struct delayed_work jack_detect_work; | ||
43 | int sys_clk; | ||
44 | struct reg_default *index_cache; | ||
45 | }; | ||
46 | |||
47 | static struct reg_default rt286_index_def[] = { | ||
48 | { 0x01, 0xaaaa }, | ||
49 | { 0x02, 0x8aaa }, | ||
50 | { 0x03, 0x0002 }, | ||
51 | { 0x04, 0xaf01 }, | ||
52 | { 0x08, 0x000d }, | ||
53 | { 0x09, 0xd810 }, | ||
54 | { 0x0a, 0x0060 }, | ||
55 | { 0x0b, 0x0000 }, | ||
56 | { 0x0d, 0x2800 }, | ||
57 | { 0x0f, 0x0000 }, | ||
58 | { 0x19, 0x0a17 }, | ||
59 | { 0x20, 0x0020 }, | ||
60 | { 0x33, 0x0208 }, | ||
61 | { 0x49, 0x0004 }, | ||
62 | { 0x4f, 0x50e9 }, | ||
63 | { 0x50, 0x2c00 }, | ||
64 | { 0x63, 0x2902 }, | ||
65 | { 0x67, 0x1111 }, | ||
66 | { 0x68, 0x1016 }, | ||
67 | { 0x69, 0x273f }, | ||
68 | }; | ||
69 | #define INDEX_CACHE_SIZE ARRAY_SIZE(rt286_index_def) | ||
70 | |||
71 | static const struct reg_default rt286_reg[] = { | ||
72 | { 0x00170500, 0x00000400 }, | ||
73 | { 0x00220000, 0x00000031 }, | ||
74 | { 0x00239000, 0x0000007f }, | ||
75 | { 0x0023a000, 0x0000007f }, | ||
76 | { 0x00270500, 0x00000400 }, | ||
77 | { 0x00370500, 0x00000400 }, | ||
78 | { 0x00870500, 0x00000400 }, | ||
79 | { 0x00920000, 0x00000031 }, | ||
80 | { 0x00935000, 0x000000c3 }, | ||
81 | { 0x00936000, 0x000000c3 }, | ||
82 | { 0x00970500, 0x00000400 }, | ||
83 | { 0x00b37000, 0x00000097 }, | ||
84 | { 0x00b37200, 0x00000097 }, | ||
85 | { 0x00b37300, 0x00000097 }, | ||
86 | { 0x00c37000, 0x00000000 }, | ||
87 | { 0x00c37100, 0x00000080 }, | ||
88 | { 0x01270500, 0x00000400 }, | ||
89 | { 0x01370500, 0x00000400 }, | ||
90 | { 0x01371f00, 0x411111f0 }, | ||
91 | { 0x01439000, 0x00000080 }, | ||
92 | { 0x0143a000, 0x00000080 }, | ||
93 | { 0x01470700, 0x00000000 }, | ||
94 | { 0x01470500, 0x00000400 }, | ||
95 | { 0x01470c00, 0x00000000 }, | ||
96 | { 0x01470100, 0x00000000 }, | ||
97 | { 0x01837000, 0x00000000 }, | ||
98 | { 0x01870500, 0x00000400 }, | ||
99 | { 0x02050000, 0x00000000 }, | ||
100 | { 0x02139000, 0x00000080 }, | ||
101 | { 0x0213a000, 0x00000080 }, | ||
102 | { 0x02170100, 0x00000000 }, | ||
103 | { 0x02170500, 0x00000400 }, | ||
104 | { 0x02170700, 0x00000000 }, | ||
105 | { 0x02270100, 0x00000000 }, | ||
106 | { 0x02370100, 0x00000000 }, | ||
107 | { 0x02040000, 0x00004002 }, | ||
108 | { 0x01870700, 0x00000020 }, | ||
109 | { 0x00830000, 0x000000c3 }, | ||
110 | { 0x00930000, 0x000000c3 }, | ||
111 | { 0x01270700, 0x00000000 }, | ||
112 | }; | ||
113 | |||
114 | static bool rt286_volatile_register(struct device *dev, unsigned int reg) | ||
115 | { | ||
116 | switch (reg) { | ||
117 | case 0 ... 0xff: | ||
118 | case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
119 | case RT286_GET_HP_SENSE: | ||
120 | case RT286_GET_MIC1_SENSE: | ||
121 | case RT286_PROC_COEF: | ||
122 | return true; | ||
123 | default: | ||
124 | return false; | ||
125 | } | ||
126 | |||
127 | |||
128 | } | ||
129 | |||
130 | static bool rt286_readable_register(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case 0 ... 0xff: | ||
134 | case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
135 | case RT286_GET_HP_SENSE: | ||
136 | case RT286_GET_MIC1_SENSE: | ||
137 | case RT286_SET_AUDIO_POWER: | ||
138 | case RT286_SET_HPO_POWER: | ||
139 | case RT286_SET_SPK_POWER: | ||
140 | case RT286_SET_DMIC1_POWER: | ||
141 | case RT286_SPK_MUX: | ||
142 | case RT286_HPO_MUX: | ||
143 | case RT286_ADC0_MUX: | ||
144 | case RT286_ADC1_MUX: | ||
145 | case RT286_SET_MIC1: | ||
146 | case RT286_SET_PIN_HPO: | ||
147 | case RT286_SET_PIN_SPK: | ||
148 | case RT286_SET_PIN_DMIC1: | ||
149 | case RT286_SPK_EAPD: | ||
150 | case RT286_SET_AMP_GAIN_HPO: | ||
151 | case RT286_SET_DMIC2_DEFAULT: | ||
152 | case RT286_DACL_GAIN: | ||
153 | case RT286_DACR_GAIN: | ||
154 | case RT286_ADCL_GAIN: | ||
155 | case RT286_ADCR_GAIN: | ||
156 | case RT286_MIC_GAIN: | ||
157 | case RT286_SPOL_GAIN: | ||
158 | case RT286_SPOR_GAIN: | ||
159 | case RT286_HPOL_GAIN: | ||
160 | case RT286_HPOR_GAIN: | ||
161 | case RT286_F_DAC_SWITCH: | ||
162 | case RT286_F_RECMIX_SWITCH: | ||
163 | case RT286_REC_MIC_SWITCH: | ||
164 | case RT286_REC_I2S_SWITCH: | ||
165 | case RT286_REC_LINE_SWITCH: | ||
166 | case RT286_REC_BEEP_SWITCH: | ||
167 | case RT286_DAC_FORMAT: | ||
168 | case RT286_ADC_FORMAT: | ||
169 | case RT286_COEF_INDEX: | ||
170 | case RT286_PROC_COEF: | ||
171 | case RT286_SET_AMP_GAIN_ADC_IN1: | ||
172 | case RT286_SET_AMP_GAIN_ADC_IN2: | ||
173 | case RT286_SET_POWER(RT286_DAC_OUT1): | ||
174 | case RT286_SET_POWER(RT286_DAC_OUT2): | ||
175 | case RT286_SET_POWER(RT286_ADC_IN1): | ||
176 | case RT286_SET_POWER(RT286_ADC_IN2): | ||
177 | case RT286_SET_POWER(RT286_DMIC2): | ||
178 | case RT286_SET_POWER(RT286_MIC1): | ||
179 | return true; | ||
180 | default: | ||
181 | return false; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) | ||
186 | { | ||
187 | struct i2c_client *client = context; | ||
188 | struct rt286_priv *rt286 = i2c_get_clientdata(client); | ||
189 | u8 data[4]; | ||
190 | int ret, i; | ||
191 | |||
192 | /*handle index registers*/ | ||
193 | if (reg <= 0xff) { | ||
194 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
195 | reg = RT286_PROC_COEF; | ||
196 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
197 | if (reg == rt286->index_cache[i].reg) { | ||
198 | rt286->index_cache[i].def = value; | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | } | ||
203 | } | ||
204 | |||
205 | data[0] = (reg >> 24) & 0xff; | ||
206 | data[1] = (reg >> 16) & 0xff; | ||
207 | /* | ||
208 | * 4 bit VID: reg should be 0 | ||
209 | * 12 bit VID: value should be 0 | ||
210 | * So we use an OR operator to handle it rather than use if condition. | ||
211 | */ | ||
212 | data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); | ||
213 | data[3] = value & 0xff; | ||
214 | |||
215 | ret = i2c_master_send(client, data, 4); | ||
216 | |||
217 | if (ret == 4) | ||
218 | return 0; | ||
219 | else | ||
220 | pr_err("ret=%d\n", ret); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | else | ||
224 | return -EIO; | ||
225 | } | ||
226 | |||
227 | static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | ||
228 | { | ||
229 | struct i2c_client *client = context; | ||
230 | struct i2c_msg xfer[2]; | ||
231 | int ret; | ||
232 | __be32 be_reg; | ||
233 | unsigned int index, vid, buf = 0x0; | ||
234 | |||
235 | /*handle index registers*/ | ||
236 | if (reg <= 0xff) { | ||
237 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | ||
238 | reg = RT286_PROC_COEF; | ||
239 | } | ||
240 | |||
241 | reg = reg | 0x80000; | ||
242 | vid = (reg >> 8) & 0xfff; | ||
243 | |||
244 | if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { | ||
245 | index = (reg >> 8) & 0xf; | ||
246 | reg = (reg & ~0xf0f) | index; | ||
247 | } | ||
248 | be_reg = cpu_to_be32(reg); | ||
249 | |||
250 | /* Write register */ | ||
251 | xfer[0].addr = client->addr; | ||
252 | xfer[0].flags = 0; | ||
253 | xfer[0].len = 4; | ||
254 | xfer[0].buf = (u8 *)&be_reg; | ||
255 | |||
256 | /* Read data */ | ||
257 | xfer[1].addr = client->addr; | ||
258 | xfer[1].flags = I2C_M_RD; | ||
259 | xfer[1].len = 4; | ||
260 | xfer[1].buf = (u8 *)&buf; | ||
261 | |||
262 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
263 | if (ret < 0) | ||
264 | return ret; | ||
265 | else if (ret != 2) | ||
266 | return -EIO; | ||
267 | |||
268 | *value = be32_to_cpu(buf); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static void rt286_index_sync(struct snd_soc_codec *codec) | ||
274 | { | ||
275 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
276 | int i; | ||
277 | |||
278 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
279 | snd_soc_write(codec, rt286->index_cache[i].reg, | ||
280 | rt286->index_cache[i].def); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static int rt286_support_power_controls[] = { | ||
285 | RT286_DAC_OUT1, | ||
286 | RT286_DAC_OUT2, | ||
287 | RT286_ADC_IN1, | ||
288 | RT286_ADC_IN2, | ||
289 | RT286_MIC1, | ||
290 | RT286_DMIC1, | ||
291 | RT286_DMIC2, | ||
292 | RT286_SPK_OUT, | ||
293 | RT286_HP_OUT, | ||
294 | }; | ||
295 | #define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls) | ||
296 | |||
297 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | ||
298 | { | ||
299 | unsigned int val, buf; | ||
300 | int i; | ||
301 | |||
302 | *hp = false; | ||
303 | *mic = false; | ||
304 | |||
305 | if (rt286->pdata.cbj_en) { | ||
306 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | ||
307 | *hp = buf & 0x80000000; | ||
308 | if (*hp) { | ||
309 | /* power on HV,VERF */ | ||
310 | regmap_update_bits(rt286->regmap, | ||
311 | RT286_POWER_CTRL1, 0x1001, 0x0); | ||
312 | /* power LDO1 */ | ||
313 | regmap_update_bits(rt286->regmap, | ||
314 | RT286_POWER_CTRL2, 0x4, 0x4); | ||
315 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | ||
316 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
317 | |||
318 | msleep(200); | ||
319 | i = 40; | ||
320 | while (((val & 0x0800) == 0) && (i > 0)) { | ||
321 | regmap_read(rt286->regmap, | ||
322 | RT286_CBJ_CTRL2, &val); | ||
323 | i--; | ||
324 | msleep(20); | ||
325 | } | ||
326 | |||
327 | if (0x0400 == (val & 0x0700)) { | ||
328 | *mic = false; | ||
329 | |||
330 | regmap_write(rt286->regmap, | ||
331 | RT286_SET_MIC1, 0x20); | ||
332 | /* power off HV,VERF */ | ||
333 | regmap_update_bits(rt286->regmap, | ||
334 | RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
335 | regmap_update_bits(rt286->regmap, | ||
336 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
337 | regmap_update_bits(rt286->regmap, | ||
338 | RT286_CBJ_CTRL1, 0x0030, 0x0000); | ||
339 | regmap_update_bits(rt286->regmap, | ||
340 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
341 | } else if ((0x0200 == (val & 0x0700)) || | ||
342 | (0x0100 == (val & 0x0700))) { | ||
343 | *mic = true; | ||
344 | regmap_update_bits(rt286->regmap, | ||
345 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
346 | regmap_update_bits(rt286->regmap, | ||
347 | RT286_CBJ_CTRL1, 0x0030, 0x0020); | ||
348 | regmap_update_bits(rt286->regmap, | ||
349 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
350 | } else { | ||
351 | *mic = false; | ||
352 | } | ||
353 | |||
354 | regmap_update_bits(rt286->regmap, | ||
355 | RT286_MISC_CTRL1, | ||
356 | 0x0060, 0x0000); | ||
357 | } else { | ||
358 | regmap_update_bits(rt286->regmap, | ||
359 | RT286_MISC_CTRL1, | ||
360 | 0x0060, 0x0020); | ||
361 | regmap_update_bits(rt286->regmap, | ||
362 | RT286_A_BIAS_CTRL3, | ||
363 | 0xc000, 0x8000); | ||
364 | regmap_update_bits(rt286->regmap, | ||
365 | RT286_CBJ_CTRL1, | ||
366 | 0x0030, 0x0020); | ||
367 | regmap_update_bits(rt286->regmap, | ||
368 | RT286_A_BIAS_CTRL2, | ||
369 | 0xc000, 0x8000); | ||
370 | |||
371 | *mic = false; | ||
372 | } | ||
373 | } else { | ||
374 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | ||
375 | *hp = buf & 0x80000000; | ||
376 | regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf); | ||
377 | *mic = buf & 0x80000000; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void rt286_jack_detect_work(struct work_struct *work) | ||
384 | { | ||
385 | struct rt286_priv *rt286 = | ||
386 | container_of(work, struct rt286_priv, jack_detect_work.work); | ||
387 | int status = 0; | ||
388 | bool hp = false; | ||
389 | bool mic = false; | ||
390 | |||
391 | rt286_jack_detect(rt286, &hp, &mic); | ||
392 | |||
393 | if (hp == true) | ||
394 | status |= SND_JACK_HEADPHONE; | ||
395 | |||
396 | if (mic == true) | ||
397 | status |= SND_JACK_MICROPHONE; | ||
398 | |||
399 | snd_soc_jack_report(rt286->jack, status, | ||
400 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
401 | } | ||
402 | |||
403 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | ||
404 | { | ||
405 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
406 | |||
407 | rt286->jack = jack; | ||
408 | |||
409 | /* Send an initial empty report */ | ||
410 | snd_soc_jack_report(rt286->jack, 0, | ||
411 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | EXPORT_SYMBOL_GPL(rt286_mic_detect); | ||
416 | |||
417 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | ||
418 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | ||
419 | |||
420 | static const struct snd_kcontrol_new rt286_snd_controls[] = { | ||
421 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, | ||
422 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
423 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, | ||
424 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
425 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, | ||
426 | 0, 0x3, 0, mic_vol_tlv), | ||
427 | SOC_DOUBLE_R("Speaker Playback Switch", RT286_SPOL_GAIN, | ||
428 | RT286_SPOR_GAIN, RT286_MUTE_SFT, 1, 1), | ||
429 | }; | ||
430 | |||
431 | /* Digital Mixer */ | ||
432 | static const struct snd_kcontrol_new rt286_front_mix[] = { | ||
433 | SOC_DAPM_SINGLE("DAC Switch", RT286_F_DAC_SWITCH, | ||
434 | RT286_MUTE_SFT, 1, 1), | ||
435 | SOC_DAPM_SINGLE("RECMIX Switch", RT286_F_RECMIX_SWITCH, | ||
436 | RT286_MUTE_SFT, 1, 1), | ||
437 | }; | ||
438 | |||
439 | /* Analog Input Mixer */ | ||
440 | static const struct snd_kcontrol_new rt286_rec_mix[] = { | ||
441 | SOC_DAPM_SINGLE("Mic1 Switch", RT286_REC_MIC_SWITCH, | ||
442 | RT286_MUTE_SFT, 1, 1), | ||
443 | SOC_DAPM_SINGLE("I2S Switch", RT286_REC_I2S_SWITCH, | ||
444 | RT286_MUTE_SFT, 1, 1), | ||
445 | SOC_DAPM_SINGLE("Line1 Switch", RT286_REC_LINE_SWITCH, | ||
446 | RT286_MUTE_SFT, 1, 1), | ||
447 | SOC_DAPM_SINGLE("Beep Switch", RT286_REC_BEEP_SWITCH, | ||
448 | RT286_MUTE_SFT, 1, 1), | ||
449 | }; | ||
450 | |||
451 | static const struct snd_kcontrol_new spo_enable_control = | ||
452 | SOC_DAPM_SINGLE("Switch", RT286_SET_PIN_SPK, | ||
453 | RT286_SET_PIN_SFT, 1, 0); | ||
454 | |||
455 | static const struct snd_kcontrol_new hpol_enable_control = | ||
456 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOL_GAIN, | ||
457 | RT286_MUTE_SFT, 1, 1); | ||
458 | |||
459 | static const struct snd_kcontrol_new hpor_enable_control = | ||
460 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOR_GAIN, | ||
461 | RT286_MUTE_SFT, 1, 1); | ||
462 | |||
463 | /* ADC0 source */ | ||
464 | static const char * const rt286_adc_src[] = { | ||
465 | "Mic", "RECMIX", "Dmic" | ||
466 | }; | ||
467 | |||
468 | static const int rt286_adc_values[] = { | ||
469 | 0, 4, 5, | ||
470 | }; | ||
471 | |||
472 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
473 | rt286_adc0_enum, RT286_ADC0_MUX, RT286_ADC_SEL_SFT, | ||
474 | RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); | ||
475 | |||
476 | static const struct snd_kcontrol_new rt286_adc0_mux = | ||
477 | SOC_DAPM_ENUM("ADC 0 source", rt286_adc0_enum); | ||
478 | |||
479 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
480 | rt286_adc1_enum, RT286_ADC1_MUX, RT286_ADC_SEL_SFT, | ||
481 | RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); | ||
482 | |||
483 | static const struct snd_kcontrol_new rt286_adc1_mux = | ||
484 | SOC_DAPM_ENUM("ADC 1 source", rt286_adc1_enum); | ||
485 | |||
486 | static const char * const rt286_dac_src[] = { | ||
487 | "Front", "Surround" | ||
488 | }; | ||
489 | /* HP-OUT source */ | ||
490 | static SOC_ENUM_SINGLE_DECL(rt286_hpo_enum, RT286_HPO_MUX, | ||
491 | 0, rt286_dac_src); | ||
492 | |||
493 | static const struct snd_kcontrol_new rt286_hpo_mux = | ||
494 | SOC_DAPM_ENUM("HPO source", rt286_hpo_enum); | ||
495 | |||
496 | /* SPK-OUT source */ | ||
497 | static SOC_ENUM_SINGLE_DECL(rt286_spo_enum, RT286_SPK_MUX, | ||
498 | 0, rt286_dac_src); | ||
499 | |||
500 | static const struct snd_kcontrol_new rt286_spo_mux = | ||
501 | SOC_DAPM_ENUM("SPO source", rt286_spo_enum); | ||
502 | |||
503 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, | ||
504 | struct snd_kcontrol *kcontrol, int event) | ||
505 | { | ||
506 | struct snd_soc_codec *codec = w->codec; | ||
507 | |||
508 | switch (event) { | ||
509 | case SND_SOC_DAPM_POST_PMU: | ||
510 | snd_soc_write(codec, | ||
511 | RT286_SPK_EAPD, RT286_SET_EAPD_HIGH); | ||
512 | break; | ||
513 | case SND_SOC_DAPM_PRE_PMD: | ||
514 | snd_soc_write(codec, | ||
515 | RT286_SPK_EAPD, RT286_SET_EAPD_LOW); | ||
516 | break; | ||
517 | |||
518 | default: | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | ||
526 | struct snd_kcontrol *kcontrol, int event) | ||
527 | { | ||
528 | struct snd_soc_codec *codec = w->codec; | ||
529 | |||
530 | switch (event) { | ||
531 | case SND_SOC_DAPM_POST_PMU: | ||
532 | snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0x20); | ||
533 | break; | ||
534 | case SND_SOC_DAPM_PRE_PMD: | ||
535 | snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0); | ||
536 | break; | ||
537 | default: | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int rt286_adc_event(struct snd_soc_dapm_widget *w, | ||
545 | struct snd_kcontrol *kcontrol, int event) | ||
546 | { | ||
547 | struct snd_soc_codec *codec = w->codec; | ||
548 | unsigned int nid; | ||
549 | |||
550 | nid = (w->reg >> 20) & 0xff; | ||
551 | |||
552 | switch (event) { | ||
553 | case SND_SOC_DAPM_POST_PMU: | ||
554 | snd_soc_update_bits(codec, | ||
555 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
556 | 0x7080, 0x7000); | ||
557 | break; | ||
558 | case SND_SOC_DAPM_PRE_PMD: | ||
559 | snd_soc_update_bits(codec, | ||
560 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
561 | 0x7080, 0x7080); | ||
562 | break; | ||
563 | default: | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | ||
571 | /* Input Lines */ | ||
572 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | ||
573 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | ||
574 | SND_SOC_DAPM_INPUT("MIC1"), | ||
575 | SND_SOC_DAPM_INPUT("LINE1"), | ||
576 | SND_SOC_DAPM_INPUT("Beep"), | ||
577 | |||
578 | /* DMIC */ | ||
579 | SND_SOC_DAPM_PGA_E("DMIC1", RT286_SET_POWER(RT286_DMIC1), 0, 1, | ||
580 | NULL, 0, rt286_set_dmic1_event, | ||
581 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
582 | SND_SOC_DAPM_PGA("DMIC2", RT286_SET_POWER(RT286_DMIC2), 0, 1, | ||
583 | NULL, 0), | ||
584 | SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, | ||
585 | 0, 0, NULL, 0), | ||
586 | |||
587 | /* REC Mixer */ | ||
588 | SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, | ||
589 | rt286_rec_mix, ARRAY_SIZE(rt286_rec_mix)), | ||
590 | |||
591 | /* ADCs */ | ||
592 | SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
593 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
594 | |||
595 | /* ADC Mux */ | ||
596 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, | ||
597 | &rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
598 | SND_SOC_DAPM_POST_PMU), | ||
599 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, | ||
600 | &rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
601 | SND_SOC_DAPM_POST_PMU), | ||
602 | |||
603 | /* Audio Interface */ | ||
604 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
605 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
606 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
607 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
608 | |||
609 | /* Output Side */ | ||
610 | /* DACs */ | ||
611 | SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
612 | SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
613 | |||
614 | /* Output Mux */ | ||
615 | SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt286_spo_mux), | ||
616 | SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt286_hpo_mux), | ||
617 | |||
618 | SND_SOC_DAPM_SUPPLY("HP Power", RT286_SET_PIN_HPO, | ||
619 | RT286_SET_PIN_SFT, 0, NULL, 0), | ||
620 | |||
621 | /* Output Mixer */ | ||
622 | SND_SOC_DAPM_MIXER("Front", RT286_SET_POWER(RT286_DAC_OUT1), 0, 1, | ||
623 | rt286_front_mix, ARRAY_SIZE(rt286_front_mix)), | ||
624 | SND_SOC_DAPM_PGA("Surround", RT286_SET_POWER(RT286_DAC_OUT2), 0, 1, | ||
625 | NULL, 0), | ||
626 | |||
627 | /* Output Pga */ | ||
628 | SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, | ||
629 | &spo_enable_control, rt286_spk_event, | ||
630 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
631 | SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, | ||
632 | &hpol_enable_control), | ||
633 | SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, | ||
634 | &hpor_enable_control), | ||
635 | |||
636 | /* Output Lines */ | ||
637 | SND_SOC_DAPM_OUTPUT("SPOL"), | ||
638 | SND_SOC_DAPM_OUTPUT("SPOR"), | ||
639 | SND_SOC_DAPM_OUTPUT("HPO Pin"), | ||
640 | SND_SOC_DAPM_OUTPUT("SPDIF"), | ||
641 | }; | ||
642 | |||
643 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { | ||
644 | {"DMIC1", NULL, "DMIC1 Pin"}, | ||
645 | {"DMIC2", NULL, "DMIC2 Pin"}, | ||
646 | {"DMIC1", NULL, "DMIC Receiver"}, | ||
647 | {"DMIC2", NULL, "DMIC Receiver"}, | ||
648 | |||
649 | {"RECMIX", "Beep Switch", "Beep"}, | ||
650 | {"RECMIX", "Line1 Switch", "LINE1"}, | ||
651 | {"RECMIX", "Mic1 Switch", "MIC1"}, | ||
652 | |||
653 | {"ADC 0 Mux", "Dmic", "DMIC1"}, | ||
654 | {"ADC 0 Mux", "RECMIX", "RECMIX"}, | ||
655 | {"ADC 0 Mux", "Mic", "MIC1"}, | ||
656 | {"ADC 1 Mux", "Dmic", "DMIC2"}, | ||
657 | {"ADC 1 Mux", "RECMIX", "RECMIX"}, | ||
658 | {"ADC 1 Mux", "Mic", "MIC1"}, | ||
659 | |||
660 | {"ADC 0", NULL, "ADC 0 Mux"}, | ||
661 | {"ADC 1", NULL, "ADC 1 Mux"}, | ||
662 | |||
663 | {"AIF1TX", NULL, "ADC 0"}, | ||
664 | {"AIF2TX", NULL, "ADC 1"}, | ||
665 | |||
666 | {"DAC 0", NULL, "AIF1RX"}, | ||
667 | {"DAC 1", NULL, "AIF2RX"}, | ||
668 | |||
669 | {"Front", "DAC Switch", "DAC 0"}, | ||
670 | {"Front", "RECMIX Switch", "RECMIX"}, | ||
671 | |||
672 | {"Surround", NULL, "DAC 1"}, | ||
673 | |||
674 | {"SPK Mux", "Front", "Front"}, | ||
675 | {"SPK Mux", "Surround", "Surround"}, | ||
676 | |||
677 | {"HPO Mux", "Front", "Front"}, | ||
678 | {"HPO Mux", "Surround", "Surround"}, | ||
679 | |||
680 | {"SPO", "Switch", "SPK Mux"}, | ||
681 | {"HPO L", "Switch", "HPO Mux"}, | ||
682 | {"HPO R", "Switch", "HPO Mux"}, | ||
683 | {"HPO L", NULL, "HP Power"}, | ||
684 | {"HPO R", NULL, "HP Power"}, | ||
685 | |||
686 | {"SPOL", NULL, "SPO"}, | ||
687 | {"SPOR", NULL, "SPO"}, | ||
688 | {"HPO Pin", NULL, "HPO L"}, | ||
689 | {"HPO Pin", NULL, "HPO R"}, | ||
690 | }; | ||
691 | |||
692 | static int rt286_hw_params(struct snd_pcm_substream *substream, | ||
693 | struct snd_pcm_hw_params *params, | ||
694 | struct snd_soc_dai *dai) | ||
695 | { | ||
696 | struct snd_soc_codec *codec = dai->codec; | ||
697 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
698 | unsigned int val = 0; | ||
699 | int d_len_code; | ||
700 | |||
701 | switch (params_rate(params)) { | ||
702 | /* bit 14 0:48K 1:44.1K */ | ||
703 | case 44100: | ||
704 | val |= 0x4000; | ||
705 | break; | ||
706 | case 48000: | ||
707 | break; | ||
708 | default: | ||
709 | dev_err(codec->dev, "Unsupported sample rate %d\n", | ||
710 | params_rate(params)); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | switch (rt286->sys_clk) { | ||
714 | case 12288000: | ||
715 | case 24576000: | ||
716 | if (params_rate(params) != 48000) { | ||
717 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
718 | params_rate(params), rt286->sys_clk); | ||
719 | return -EINVAL; | ||
720 | } | ||
721 | break; | ||
722 | case 11289600: | ||
723 | case 22579200: | ||
724 | if (params_rate(params) != 44100) { | ||
725 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
726 | params_rate(params), rt286->sys_clk); | ||
727 | return -EINVAL; | ||
728 | } | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | if (params_channels(params) <= 16) { | ||
733 | /* bit 3:0 Number of Channel */ | ||
734 | val |= (params_channels(params) - 1); | ||
735 | } else { | ||
736 | dev_err(codec->dev, "Unsupported channels %d\n", | ||
737 | params_channels(params)); | ||
738 | return -EINVAL; | ||
739 | } | ||
740 | |||
741 | d_len_code = 0; | ||
742 | switch (params_width(params)) { | ||
743 | /* bit 6:4 Bits per Sample */ | ||
744 | case 16: | ||
745 | d_len_code = 0; | ||
746 | val |= (0x1 << 4); | ||
747 | break; | ||
748 | case 32: | ||
749 | d_len_code = 2; | ||
750 | val |= (0x4 << 4); | ||
751 | break; | ||
752 | case 20: | ||
753 | d_len_code = 1; | ||
754 | val |= (0x2 << 4); | ||
755 | break; | ||
756 | case 24: | ||
757 | d_len_code = 2; | ||
758 | val |= (0x3 << 4); | ||
759 | break; | ||
760 | case 8: | ||
761 | d_len_code = 3; | ||
762 | break; | ||
763 | default: | ||
764 | return -EINVAL; | ||
765 | } | ||
766 | |||
767 | snd_soc_update_bits(codec, | ||
768 | RT286_I2S_CTRL1, 0x0018, d_len_code << 3); | ||
769 | dev_dbg(codec->dev, "format val = 0x%x\n", val); | ||
770 | |||
771 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
772 | snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x407f, val); | ||
773 | else | ||
774 | snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x407f, val); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
780 | { | ||
781 | struct snd_soc_codec *codec = dai->codec; | ||
782 | |||
783 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
784 | case SND_SOC_DAIFMT_CBM_CFM: | ||
785 | snd_soc_update_bits(codec, | ||
786 | RT286_I2S_CTRL1, 0x800, 0x800); | ||
787 | break; | ||
788 | case SND_SOC_DAIFMT_CBS_CFS: | ||
789 | snd_soc_update_bits(codec, | ||
790 | RT286_I2S_CTRL1, 0x800, 0x0); | ||
791 | break; | ||
792 | default: | ||
793 | return -EINVAL; | ||
794 | } | ||
795 | |||
796 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
797 | case SND_SOC_DAIFMT_I2S: | ||
798 | snd_soc_update_bits(codec, | ||
799 | RT286_I2S_CTRL1, 0x300, 0x0); | ||
800 | break; | ||
801 | case SND_SOC_DAIFMT_LEFT_J: | ||
802 | snd_soc_update_bits(codec, | ||
803 | RT286_I2S_CTRL1, 0x300, 0x1 << 8); | ||
804 | break; | ||
805 | case SND_SOC_DAIFMT_DSP_A: | ||
806 | snd_soc_update_bits(codec, | ||
807 | RT286_I2S_CTRL1, 0x300, 0x2 << 8); | ||
808 | break; | ||
809 | case SND_SOC_DAIFMT_DSP_B: | ||
810 | snd_soc_update_bits(codec, | ||
811 | RT286_I2S_CTRL1, 0x300, 0x3 << 8); | ||
812 | break; | ||
813 | default: | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | /* bit 15 Stream Type 0:PCM 1:Non-PCM */ | ||
817 | snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x8000, 0); | ||
818 | snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x8000, 0); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static int rt286_set_dai_sysclk(struct snd_soc_dai *dai, | ||
824 | int clk_id, unsigned int freq, int dir) | ||
825 | { | ||
826 | struct snd_soc_codec *codec = dai->codec; | ||
827 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
828 | |||
829 | dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq); | ||
830 | |||
831 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
832 | snd_soc_update_bits(codec, | ||
833 | RT286_I2S_CTRL2, 0x0100, 0x0); | ||
834 | snd_soc_update_bits(codec, | ||
835 | RT286_PLL_CTRL1, 0x20, 0x20); | ||
836 | } else { | ||
837 | snd_soc_update_bits(codec, | ||
838 | RT286_I2S_CTRL2, 0x0100, 0x0100); | ||
839 | snd_soc_update_bits(codec, | ||
840 | RT286_PLL_CTRL, 0x4, 0x4); | ||
841 | snd_soc_update_bits(codec, | ||
842 | RT286_PLL_CTRL1, 0x20, 0x0); | ||
843 | } | ||
844 | |||
845 | switch (freq) { | ||
846 | case 19200000: | ||
847 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
848 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | snd_soc_update_bits(codec, | ||
852 | RT286_I2S_CTRL2, 0x40, 0x40); | ||
853 | break; | ||
854 | case 24000000: | ||
855 | if (RT286_SCLK_S_MCLK == clk_id) { | ||
856 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | snd_soc_update_bits(codec, | ||
860 | RT286_I2S_CTRL2, 0x40, 0x0); | ||
861 | break; | ||
862 | case 12288000: | ||
863 | case 11289600: | ||
864 | snd_soc_update_bits(codec, | ||
865 | RT286_I2S_CTRL2, 0x8, 0x0); | ||
866 | snd_soc_update_bits(codec, | ||
867 | RT286_CLK_DIV, 0xfc1e, 0x0004); | ||
868 | break; | ||
869 | case 24576000: | ||
870 | case 22579200: | ||
871 | snd_soc_update_bits(codec, | ||
872 | RT286_I2S_CTRL2, 0x8, 0x8); | ||
873 | snd_soc_update_bits(codec, | ||
874 | RT286_CLK_DIV, 0xfc1e, 0x5406); | ||
875 | break; | ||
876 | default: | ||
877 | dev_err(codec->dev, "Unsupported system clock\n"); | ||
878 | return -EINVAL; | ||
879 | } | ||
880 | |||
881 | rt286->sys_clk = freq; | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int rt286_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
887 | { | ||
888 | struct snd_soc_codec *codec = dai->codec; | ||
889 | |||
890 | dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio); | ||
891 | if (50 == ratio) | ||
892 | snd_soc_update_bits(codec, | ||
893 | RT286_I2S_CTRL1, 0x1000, 0x1000); | ||
894 | else | ||
895 | snd_soc_update_bits(codec, | ||
896 | RT286_I2S_CTRL1, 0x1000, 0x0); | ||
897 | |||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | static int rt286_set_bias_level(struct snd_soc_codec *codec, | ||
903 | enum snd_soc_bias_level level) | ||
904 | { | ||
905 | switch (level) { | ||
906 | case SND_SOC_BIAS_PREPARE: | ||
907 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | ||
908 | snd_soc_write(codec, | ||
909 | RT286_SET_AUDIO_POWER, AC_PWRST_D0); | ||
910 | snd_soc_update_bits(codec, | ||
911 | RT286_DC_GAIN, 0x200, 0x200); | ||
912 | } | ||
913 | break; | ||
914 | |||
915 | case SND_SOC_BIAS_ON: | ||
916 | mdelay(10); | ||
917 | break; | ||
918 | |||
919 | case SND_SOC_BIAS_STANDBY: | ||
920 | snd_soc_write(codec, | ||
921 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); | ||
922 | snd_soc_update_bits(codec, | ||
923 | RT286_DC_GAIN, 0x200, 0x0); | ||
924 | break; | ||
925 | |||
926 | default: | ||
927 | break; | ||
928 | } | ||
929 | codec->dapm.bias_level = level; | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static irqreturn_t rt286_irq(int irq, void *data) | ||
935 | { | ||
936 | struct rt286_priv *rt286 = data; | ||
937 | bool hp = false; | ||
938 | bool mic = false; | ||
939 | int status = 0; | ||
940 | |||
941 | rt286_jack_detect(rt286, &hp, &mic); | ||
942 | |||
943 | /* Clear IRQ */ | ||
944 | regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1); | ||
945 | |||
946 | if (hp == true) | ||
947 | status |= SND_JACK_HEADPHONE; | ||
948 | |||
949 | if (mic == true) | ||
950 | status |= SND_JACK_MICROPHONE; | ||
951 | |||
952 | snd_soc_jack_report(rt286->jack, status, | ||
953 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
954 | |||
955 | pm_wakeup_event(&rt286->i2c->dev, 300); | ||
956 | |||
957 | return IRQ_HANDLED; | ||
958 | } | ||
959 | |||
960 | static int rt286_probe(struct snd_soc_codec *codec) | ||
961 | { | ||
962 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
963 | |||
964 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
965 | |||
966 | if (rt286->i2c->irq) { | ||
967 | regmap_update_bits(rt286->regmap, | ||
968 | RT286_IRQ_CTRL, 0x2, 0x2); | ||
969 | |||
970 | INIT_DELAYED_WORK(&rt286->jack_detect_work, | ||
971 | rt286_jack_detect_work); | ||
972 | schedule_delayed_work(&rt286->jack_detect_work, | ||
973 | msecs_to_jiffies(1250)); | ||
974 | } | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int rt286_remove(struct snd_soc_codec *codec) | ||
980 | { | ||
981 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
982 | |||
983 | cancel_delayed_work_sync(&rt286->jack_detect_work); | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | #ifdef CONFIG_PM | ||
989 | static int rt286_suspend(struct snd_soc_codec *codec) | ||
990 | { | ||
991 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
992 | |||
993 | regcache_cache_only(rt286->regmap, true); | ||
994 | regcache_mark_dirty(rt286->regmap); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static int rt286_resume(struct snd_soc_codec *codec) | ||
1000 | { | ||
1001 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
1002 | |||
1003 | regcache_cache_only(rt286->regmap, false); | ||
1004 | rt286_index_sync(codec); | ||
1005 | regcache_sync(rt286->regmap); | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | #else | ||
1010 | #define rt286_suspend NULL | ||
1011 | #define rt286_resume NULL | ||
1012 | #endif | ||
1013 | |||
1014 | #define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
1015 | #define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1016 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
1017 | |||
1018 | static const struct snd_soc_dai_ops rt286_aif_dai_ops = { | ||
1019 | .hw_params = rt286_hw_params, | ||
1020 | .set_fmt = rt286_set_dai_fmt, | ||
1021 | .set_sysclk = rt286_set_dai_sysclk, | ||
1022 | .set_bclk_ratio = rt286_set_bclk_ratio, | ||
1023 | }; | ||
1024 | |||
1025 | static struct snd_soc_dai_driver rt286_dai[] = { | ||
1026 | { | ||
1027 | .name = "rt286-aif1", | ||
1028 | .id = RT286_AIF1, | ||
1029 | .playback = { | ||
1030 | .stream_name = "AIF1 Playback", | ||
1031 | .channels_min = 1, | ||
1032 | .channels_max = 2, | ||
1033 | .rates = RT286_STEREO_RATES, | ||
1034 | .formats = RT286_FORMATS, | ||
1035 | }, | ||
1036 | .capture = { | ||
1037 | .stream_name = "AIF1 Capture", | ||
1038 | .channels_min = 1, | ||
1039 | .channels_max = 2, | ||
1040 | .rates = RT286_STEREO_RATES, | ||
1041 | .formats = RT286_FORMATS, | ||
1042 | }, | ||
1043 | .ops = &rt286_aif_dai_ops, | ||
1044 | .symmetric_rates = 1, | ||
1045 | }, | ||
1046 | { | ||
1047 | .name = "rt286-aif2", | ||
1048 | .id = RT286_AIF2, | ||
1049 | .playback = { | ||
1050 | .stream_name = "AIF2 Playback", | ||
1051 | .channels_min = 1, | ||
1052 | .channels_max = 2, | ||
1053 | .rates = RT286_STEREO_RATES, | ||
1054 | .formats = RT286_FORMATS, | ||
1055 | }, | ||
1056 | .capture = { | ||
1057 | .stream_name = "AIF2 Capture", | ||
1058 | .channels_min = 1, | ||
1059 | .channels_max = 2, | ||
1060 | .rates = RT286_STEREO_RATES, | ||
1061 | .formats = RT286_FORMATS, | ||
1062 | }, | ||
1063 | .ops = &rt286_aif_dai_ops, | ||
1064 | .symmetric_rates = 1, | ||
1065 | }, | ||
1066 | |||
1067 | }; | ||
1068 | |||
1069 | static struct snd_soc_codec_driver soc_codec_dev_rt286 = { | ||
1070 | .probe = rt286_probe, | ||
1071 | .remove = rt286_remove, | ||
1072 | .suspend = rt286_suspend, | ||
1073 | .resume = rt286_resume, | ||
1074 | .set_bias_level = rt286_set_bias_level, | ||
1075 | .idle_bias_off = true, | ||
1076 | .controls = rt286_snd_controls, | ||
1077 | .num_controls = ARRAY_SIZE(rt286_snd_controls), | ||
1078 | .dapm_widgets = rt286_dapm_widgets, | ||
1079 | .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), | ||
1080 | .dapm_routes = rt286_dapm_routes, | ||
1081 | .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), | ||
1082 | }; | ||
1083 | |||
1084 | static const struct regmap_config rt286_regmap = { | ||
1085 | .reg_bits = 32, | ||
1086 | .val_bits = 32, | ||
1087 | .max_register = 0x02370100, | ||
1088 | .volatile_reg = rt286_volatile_register, | ||
1089 | .readable_reg = rt286_readable_register, | ||
1090 | .reg_write = rt286_hw_write, | ||
1091 | .reg_read = rt286_hw_read, | ||
1092 | .cache_type = REGCACHE_RBTREE, | ||
1093 | .reg_defaults = rt286_reg, | ||
1094 | .num_reg_defaults = ARRAY_SIZE(rt286_reg), | ||
1095 | }; | ||
1096 | |||
1097 | static const struct i2c_device_id rt286_i2c_id[] = { | ||
1098 | {"rt286", 0}, | ||
1099 | {} | ||
1100 | }; | ||
1101 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); | ||
1102 | |||
1103 | static const struct acpi_device_id rt286_acpi_match[] = { | ||
1104 | { "INT343A", 0 }, | ||
1105 | {}, | ||
1106 | }; | ||
1107 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); | ||
1108 | |||
1109 | static int rt286_i2c_probe(struct i2c_client *i2c, | ||
1110 | const struct i2c_device_id *id) | ||
1111 | { | ||
1112 | struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
1113 | struct rt286_priv *rt286; | ||
1114 | int i, ret; | ||
1115 | |||
1116 | rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), | ||
1117 | GFP_KERNEL); | ||
1118 | if (NULL == rt286) | ||
1119 | return -ENOMEM; | ||
1120 | |||
1121 | rt286->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt286_regmap); | ||
1122 | if (IS_ERR(rt286->regmap)) { | ||
1123 | ret = PTR_ERR(rt286->regmap); | ||
1124 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1125 | ret); | ||
1126 | return ret; | ||
1127 | } | ||
1128 | |||
1129 | regmap_read(rt286->regmap, | ||
1130 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | ||
1131 | if (ret != RT286_VENDOR_ID) { | ||
1132 | dev_err(&i2c->dev, | ||
1133 | "Device with ID register %x is not rt286\n", ret); | ||
1134 | return -ENODEV; | ||
1135 | } | ||
1136 | |||
1137 | rt286->index_cache = rt286_index_def; | ||
1138 | rt286->i2c = i2c; | ||
1139 | i2c_set_clientdata(i2c, rt286); | ||
1140 | |||
1141 | if (pdata) | ||
1142 | rt286->pdata = *pdata; | ||
1143 | |||
1144 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | ||
1145 | |||
1146 | for (i = 0; i < RT286_POWER_REG_LEN; i++) | ||
1147 | regmap_write(rt286->regmap, | ||
1148 | RT286_SET_POWER(rt286_support_power_controls[i]), | ||
1149 | AC_PWRST_D1); | ||
1150 | |||
1151 | if (!rt286->pdata.cbj_en) { | ||
1152 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); | ||
1153 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); | ||
1154 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); | ||
1155 | regmap_update_bits(rt286->regmap, | ||
1156 | RT286_CBJ_CTRL1, 0xf000, 0xb000); | ||
1157 | } else { | ||
1158 | regmap_update_bits(rt286->regmap, | ||
1159 | RT286_CBJ_CTRL1, 0xf000, 0x5000); | ||
1160 | } | ||
1161 | |||
1162 | mdelay(10); | ||
1163 | |||
1164 | if (!rt286->pdata.gpio2_en) | ||
1165 | regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000); | ||
1166 | else | ||
1167 | regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0); | ||
1168 | |||
1169 | mdelay(10); | ||
1170 | |||
1171 | /*Power down LDO2*/ | ||
1172 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0); | ||
1173 | |||
1174 | /*Set depop parameter*/ | ||
1175 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); | ||
1176 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | ||
1177 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | ||
1178 | |||
1179 | if (rt286->i2c->irq) { | ||
1180 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, | ||
1181 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); | ||
1182 | if (ret != 0) { | ||
1183 | dev_err(&i2c->dev, | ||
1184 | "Failed to reguest IRQ: %d\n", ret); | ||
1185 | return ret; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt286, | ||
1190 | rt286_dai, ARRAY_SIZE(rt286_dai)); | ||
1191 | |||
1192 | return ret; | ||
1193 | } | ||
1194 | |||
1195 | static int rt286_i2c_remove(struct i2c_client *i2c) | ||
1196 | { | ||
1197 | struct rt286_priv *rt286 = i2c_get_clientdata(i2c); | ||
1198 | |||
1199 | if (i2c->irq) | ||
1200 | free_irq(i2c->irq, rt286); | ||
1201 | snd_soc_unregister_codec(&i2c->dev); | ||
1202 | |||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | |||
1207 | static struct i2c_driver rt286_i2c_driver = { | ||
1208 | .driver = { | ||
1209 | .name = "rt286", | ||
1210 | .owner = THIS_MODULE, | ||
1211 | .acpi_match_table = ACPI_PTR(rt286_acpi_match), | ||
1212 | }, | ||
1213 | .probe = rt286_i2c_probe, | ||
1214 | .remove = rt286_i2c_remove, | ||
1215 | .id_table = rt286_i2c_id, | ||
1216 | }; | ||
1217 | |||
1218 | module_i2c_driver(rt286_i2c_driver); | ||
1219 | |||
1220 | MODULE_DESCRIPTION("ASoC RT286 driver"); | ||
1221 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
1222 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h new file mode 100644 index 000000000000..b539b7320a79 --- /dev/null +++ b/sound/soc/codecs/rt286.h | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * rt286.h -- RT286 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT286_H__ | ||
13 | #define __RT286_H__ | ||
14 | |||
15 | #define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) | ||
16 | |||
17 | #define RT286_AUDIO_FUNCTION_GROUP 0x01 | ||
18 | #define RT286_DAC_OUT1 0x02 | ||
19 | #define RT286_DAC_OUT2 0x03 | ||
20 | #define RT286_ADC_IN1 0x09 | ||
21 | #define RT286_ADC_IN2 0x08 | ||
22 | #define RT286_MIXER_IN 0x0b | ||
23 | #define RT286_MIXER_OUT1 0x0c | ||
24 | #define RT286_MIXER_OUT2 0x0d | ||
25 | #define RT286_DMIC1 0x12 | ||
26 | #define RT286_DMIC2 0x13 | ||
27 | #define RT286_SPK_OUT 0x14 | ||
28 | #define RT286_MIC1 0x18 | ||
29 | #define RT286_LINE1 0x1a | ||
30 | #define RT286_BEEP 0x1d | ||
31 | #define RT286_SPDIF 0x1e | ||
32 | #define RT286_VENDOR_REGISTERS 0x20 | ||
33 | #define RT286_HP_OUT 0x21 | ||
34 | #define RT286_MIXER_IN1 0x22 | ||
35 | #define RT286_MIXER_IN2 0x23 | ||
36 | |||
37 | #define RT286_SET_PIN_SFT 6 | ||
38 | #define RT286_SET_PIN_ENABLE 0x40 | ||
39 | #define RT286_SET_PIN_DISABLE 0 | ||
40 | #define RT286_SET_EAPD_HIGH 0x2 | ||
41 | #define RT286_SET_EAPD_LOW 0 | ||
42 | |||
43 | #define RT286_MUTE_SFT 7 | ||
44 | |||
45 | /* Verb commands */ | ||
46 | #define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM) | ||
47 | #define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0) | ||
48 | #define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP) | ||
49 | #define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT) | ||
50 | #define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT) | ||
51 | #define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1) | ||
52 | #define RT286_SPK_MUX\ | ||
53 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0) | ||
54 | #define RT286_HPO_MUX\ | ||
55 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0) | ||
56 | #define RT286_ADC0_MUX\ | ||
57 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0) | ||
58 | #define RT286_ADC1_MUX\ | ||
59 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0) | ||
60 | #define RT286_SET_MIC1\ | ||
61 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0) | ||
62 | #define RT286_SET_PIN_HPO\ | ||
63 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0) | ||
64 | #define RT286_SET_PIN_SPK\ | ||
65 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0) | ||
66 | #define RT286_SET_PIN_DMIC1\ | ||
67 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0) | ||
68 | #define RT286_SPK_EAPD\ | ||
69 | VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0) | ||
70 | #define RT286_SET_AMP_GAIN_HPO\ | ||
71 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0) | ||
72 | #define RT286_SET_AMP_GAIN_ADC_IN1\ | ||
73 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0) | ||
74 | #define RT286_SET_AMP_GAIN_ADC_IN2\ | ||
75 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0) | ||
76 | #define RT286_GET_HP_SENSE\ | ||
77 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0) | ||
78 | #define RT286_GET_MIC1_SENSE\ | ||
79 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0) | ||
80 | #define RT286_SET_DMIC2_DEFAULT\ | ||
81 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0) | ||
82 | #define RT286_DACL_GAIN\ | ||
83 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000) | ||
84 | #define RT286_DACR_GAIN\ | ||
85 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000) | ||
86 | #define RT286_ADCL_GAIN\ | ||
87 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000) | ||
88 | #define RT286_ADCR_GAIN\ | ||
89 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000) | ||
90 | #define RT286_MIC_GAIN\ | ||
91 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000) | ||
92 | #define RT286_SPOL_GAIN\ | ||
93 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000) | ||
94 | #define RT286_SPOR_GAIN\ | ||
95 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000) | ||
96 | #define RT286_HPOL_GAIN\ | ||
97 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000) | ||
98 | #define RT286_HPOR_GAIN\ | ||
99 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000) | ||
100 | #define RT286_F_DAC_SWITCH\ | ||
101 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000) | ||
102 | #define RT286_F_RECMIX_SWITCH\ | ||
103 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100) | ||
104 | #define RT286_REC_MIC_SWITCH\ | ||
105 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000) | ||
106 | #define RT286_REC_I2S_SWITCH\ | ||
107 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100) | ||
108 | #define RT286_REC_LINE_SWITCH\ | ||
109 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200) | ||
110 | #define RT286_REC_BEEP_SWITCH\ | ||
111 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300) | ||
112 | #define RT286_DAC_FORMAT\ | ||
113 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0) | ||
114 | #define RT286_ADC_FORMAT\ | ||
115 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0) | ||
116 | #define RT286_COEF_INDEX\ | ||
117 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0) | ||
118 | #define RT286_PROC_COEF\ | ||
119 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0) | ||
120 | |||
121 | /* Index registers */ | ||
122 | #define RT286_A_BIAS_CTRL1 0x01 | ||
123 | #define RT286_A_BIAS_CTRL2 0x02 | ||
124 | #define RT286_POWER_CTRL1 0x03 | ||
125 | #define RT286_A_BIAS_CTRL3 0x04 | ||
126 | #define RT286_POWER_CTRL2 0x08 | ||
127 | #define RT286_I2S_CTRL1 0x09 | ||
128 | #define RT286_I2S_CTRL2 0x0a | ||
129 | #define RT286_CLK_DIV 0x0b | ||
130 | #define RT286_DC_GAIN 0x0d | ||
131 | #define RT286_POWER_CTRL3 0x0f | ||
132 | #define RT286_MIC1_DET_CTRL 0x19 | ||
133 | #define RT286_MISC_CTRL1 0x20 | ||
134 | #define RT286_IRQ_CTRL 0x33 | ||
135 | #define RT286_PLL_CTRL1 0x49 | ||
136 | #define RT286_CBJ_CTRL1 0x4f | ||
137 | #define RT286_CBJ_CTRL2 0x50 | ||
138 | #define RT286_PLL_CTRL 0x63 | ||
139 | #define RT286_DEPOP_CTRL1 0x66 | ||
140 | #define RT286_DEPOP_CTRL2 0x67 | ||
141 | #define RT286_DEPOP_CTRL3 0x68 | ||
142 | #define RT286_DEPOP_CTRL4 0x69 | ||
143 | |||
144 | /* SPDIF (0x06) */ | ||
145 | #define RT286_SPDIF_SEL_SFT 0 | ||
146 | #define RT286_SPDIF_SEL_PCM0 0 | ||
147 | #define RT286_SPDIF_SEL_PCM1 1 | ||
148 | #define RT286_SPDIF_SEL_SPOUT 2 | ||
149 | #define RT286_SPDIF_SEL_PP 3 | ||
150 | |||
151 | /* RECMIX (0x0b) */ | ||
152 | #define RT286_M_REC_BEEP_SFT 0 | ||
153 | #define RT286_M_REC_LINE1_SFT 1 | ||
154 | #define RT286_M_REC_MIC1_SFT 2 | ||
155 | #define RT286_M_REC_I2S_SFT 3 | ||
156 | |||
157 | /* Front (0x0c) */ | ||
158 | #define RT286_M_FRONT_DAC_SFT 0 | ||
159 | #define RT286_M_FRONT_REC_SFT 1 | ||
160 | |||
161 | /* SPK-OUT (0x14) */ | ||
162 | #define RT286_M_SPK_MUX_SFT 14 | ||
163 | #define RT286_SPK_SEL_MASK 0x1 | ||
164 | #define RT286_SPK_SEL_SFT 0 | ||
165 | #define RT286_SPK_SEL_F 0 | ||
166 | #define RT286_SPK_SEL_S 1 | ||
167 | |||
168 | /* HP-OUT (0x21) */ | ||
169 | #define RT286_M_HP_MUX_SFT 14 | ||
170 | #define RT286_HP_SEL_MASK 0x1 | ||
171 | #define RT286_HP_SEL_SFT 0 | ||
172 | #define RT286_HP_SEL_F 0 | ||
173 | #define RT286_HP_SEL_S 1 | ||
174 | |||
175 | /* ADC (0x22) (0x23) */ | ||
176 | #define RT286_ADC_SEL_MASK 0x7 | ||
177 | #define RT286_ADC_SEL_SFT 0 | ||
178 | #define RT286_ADC_SEL_SURR 0 | ||
179 | #define RT286_ADC_SEL_FRONT 1 | ||
180 | #define RT286_ADC_SEL_DMIC 2 | ||
181 | #define RT286_ADC_SEL_BEEP 4 | ||
182 | #define RT286_ADC_SEL_LINE1 5 | ||
183 | #define RT286_ADC_SEL_I2S 6 | ||
184 | #define RT286_ADC_SEL_MIC1 7 | ||
185 | |||
186 | #define RT286_SCLK_S_MCLK 0 | ||
187 | #define RT286_SCLK_S_PLL 1 | ||
188 | |||
189 | enum { | ||
190 | RT286_AIF1, | ||
191 | RT286_AIF2, | ||
192 | RT286_AIFS, | ||
193 | }; | ||
194 | |||
195 | int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); | ||
196 | |||
197 | #endif /* __RT286_H__ */ | ||
198 | |||
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 30e234708579..1ba27db660a6 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -1370,16 +1370,16 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, | |||
1370 | return coeff; | 1370 | return coeff; |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | switch (params_format(params)) { | 1373 | switch (params_width(params)) { |
1374 | case SNDRV_PCM_FORMAT_S16_LE: | 1374 | case 16: |
1375 | break; | 1375 | break; |
1376 | case SNDRV_PCM_FORMAT_S20_3LE: | 1376 | case 20: |
1377 | iface |= RT5631_SDP_I2S_DL_20; | 1377 | iface |= RT5631_SDP_I2S_DL_20; |
1378 | break; | 1378 | break; |
1379 | case SNDRV_PCM_FORMAT_S24_LE: | 1379 | case 24: |
1380 | iface |= RT5631_SDP_I2S_DL_24; | 1380 | iface |= RT5631_SDP_I2S_DL_24; |
1381 | break; | 1381 | break; |
1382 | case SNDRV_PCM_FORMAT_S8: | 1382 | case 8: |
1383 | iface |= RT5631_SDP_I2S_DL_8; | 1383 | iface |= RT5631_SDP_I2S_DL_8; |
1384 | break; | 1384 | break; |
1385 | default: | 1385 | default: |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index de80e89b5fd8..6bc6efdec550 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -2215,14 +2215,8 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2215 | 2215 | ||
2216 | rt5640->hp_mute = 1; | 2216 | rt5640->hp_mute = 1; |
2217 | 2217 | ||
2218 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, | 2218 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, |
2219 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); | 2219 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); |
2220 | if (ret < 0) | ||
2221 | goto err; | ||
2222 | |||
2223 | return 0; | ||
2224 | err: | ||
2225 | return ret; | ||
2226 | } | 2220 | } |
2227 | 2221 | ||
2228 | static int rt5640_i2c_remove(struct i2c_client *i2c) | 2222 | static int rt5640_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 02147be2b302..a7762d0a623e 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -2345,14 +2345,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2345 | 2345 | ||
2346 | } | 2346 | } |
2347 | 2347 | ||
2348 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 2348 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2350 | if (ret < 0) | ||
2351 | goto err; | ||
2352 | |||
2353 | return 0; | ||
2354 | err: | ||
2355 | return ret; | ||
2356 | } | 2350 | } |
2357 | 2351 | ||
2358 | static int rt5645_i2c_remove(struct i2c_client *i2c) | 2352 | static int rt5645_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index ea4b1c652a26..bb0a3ab5416c 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -1366,16 +1366,16 @@ static int rt5651_hw_params(struct snd_pcm_substream *substream, | |||
1366 | dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", | 1366 | dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", |
1367 | bclk_ms, pre_div, dai->id); | 1367 | bclk_ms, pre_div, dai->id); |
1368 | 1368 | ||
1369 | switch (params_format(params)) { | 1369 | switch (params_width(params)) { |
1370 | case SNDRV_PCM_FORMAT_S16_LE: | 1370 | case 16: |
1371 | break; | 1371 | break; |
1372 | case SNDRV_PCM_FORMAT_S20_3LE: | 1372 | case 20: |
1373 | val_len |= RT5651_I2S_DL_20; | 1373 | val_len |= RT5651_I2S_DL_20; |
1374 | break; | 1374 | break; |
1375 | case SNDRV_PCM_FORMAT_S24_LE: | 1375 | case 24: |
1376 | val_len |= RT5651_I2S_DL_24; | 1376 | val_len |= RT5651_I2S_DL_24; |
1377 | break; | 1377 | break; |
1378 | case SNDRV_PCM_FORMAT_S8: | 1378 | case 8: |
1379 | val_len |= RT5651_I2S_DL_8; | 1379 | val_len |= RT5651_I2S_DL_8; |
1380 | break; | 1380 | break; |
1381 | default: | 1381 | default: |
diff --git a/sound/soc/codecs/rt5670-dsp.h b/sound/soc/codecs/rt5670-dsp.h new file mode 100644 index 000000000000..a34d0cdb8198 --- /dev/null +++ b/sound/soc/codecs/rt5670-dsp.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * rt5670-dsp.h -- RT5670 ALSA SoC DSP driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Microelectronics | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT5670_DSP_H__ | ||
13 | #define __RT5670_DSP_H__ | ||
14 | |||
15 | #define RT5670_DSP_CTRL1 0xe0 | ||
16 | #define RT5670_DSP_CTRL2 0xe1 | ||
17 | #define RT5670_DSP_CTRL3 0xe2 | ||
18 | #define RT5670_DSP_CTRL4 0xe3 | ||
19 | #define RT5670_DSP_CTRL5 0xe4 | ||
20 | |||
21 | /* DSP Control 1 (0xe0) */ | ||
22 | #define RT5670_DSP_CMD_MASK (0xff << 8) | ||
23 | #define RT5670_DSP_CMD_PE (0x0d << 8) /* Patch Entry */ | ||
24 | #define RT5670_DSP_CMD_MW (0x3b << 8) /* Memory Write */ | ||
25 | #define RT5670_DSP_CMD_MR (0x37 << 8) /* Memory Read */ | ||
26 | #define RT5670_DSP_CMD_RR (0x60 << 8) /* Register Read */ | ||
27 | #define RT5670_DSP_CMD_RW (0x68 << 8) /* Register Write */ | ||
28 | #define RT5670_DSP_REG_DATHI (0x26 << 8) /* High Data Addr */ | ||
29 | #define RT5670_DSP_REG_DATLO (0x25 << 8) /* Low Data Addr */ | ||
30 | #define RT5670_DSP_CLK_MASK (0x3 << 6) | ||
31 | #define RT5670_DSP_CLK_SFT 6 | ||
32 | #define RT5670_DSP_CLK_768K (0x0 << 6) | ||
33 | #define RT5670_DSP_CLK_384K (0x1 << 6) | ||
34 | #define RT5670_DSP_CLK_192K (0x2 << 6) | ||
35 | #define RT5670_DSP_CLK_96K (0x3 << 6) | ||
36 | #define RT5670_DSP_BUSY_MASK (0x1 << 5) | ||
37 | #define RT5670_DSP_RW_MASK (0x1 << 4) | ||
38 | #define RT5670_DSP_DL_MASK (0x3 << 2) | ||
39 | #define RT5670_DSP_DL_0 (0x0 << 2) | ||
40 | #define RT5670_DSP_DL_1 (0x1 << 2) | ||
41 | #define RT5670_DSP_DL_2 (0x2 << 2) | ||
42 | #define RT5670_DSP_DL_3 (0x3 << 2) | ||
43 | #define RT5670_DSP_I2C_AL_16 (0x1 << 1) | ||
44 | #define RT5670_DSP_CMD_EN (0x1) | ||
45 | |||
46 | struct rt5670_dsp_param { | ||
47 | u16 cmd_fmt; | ||
48 | u16 addr; | ||
49 | u16 data; | ||
50 | u8 cmd; | ||
51 | }; | ||
52 | |||
53 | #endif /* __RT5670_DSP_H__ */ | ||
54 | |||
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c new file mode 100644 index 000000000000..ba9d9b4d4857 --- /dev/null +++ b/sound/soc/codecs/rt5670.c | |||
@@ -0,0 +1,2657 @@ | |||
1 | /* | ||
2 | * rt5670.c -- RT5670 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.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 <linux/spi/spi.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/jack.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/rt5670.h> | ||
29 | |||
30 | #include "rl6231.h" | ||
31 | #include "rt5670.h" | ||
32 | #include "rt5670-dsp.h" | ||
33 | |||
34 | #define RT5670_DEVICE_ID 0x6271 | ||
35 | |||
36 | #define RT5670_PR_RANGE_BASE (0xff + 1) | ||
37 | #define RT5670_PR_SPACING 0x100 | ||
38 | |||
39 | #define RT5670_PR_BASE (RT5670_PR_RANGE_BASE + (0 * RT5670_PR_SPACING)) | ||
40 | |||
41 | static const struct regmap_range_cfg rt5670_ranges[] = { | ||
42 | { .name = "PR", .range_min = RT5670_PR_BASE, | ||
43 | .range_max = RT5670_PR_BASE + 0xf8, | ||
44 | .selector_reg = RT5670_PRIV_INDEX, | ||
45 | .selector_mask = 0xff, | ||
46 | .selector_shift = 0x0, | ||
47 | .window_start = RT5670_PRIV_DATA, | ||
48 | .window_len = 0x1, }, | ||
49 | }; | ||
50 | |||
51 | static struct reg_default init_list[] = { | ||
52 | { RT5670_PR_BASE + 0x14, 0x9a8a }, | ||
53 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, | ||
54 | { RT5670_PR_BASE + 0x3d, 0x3640 }, | ||
55 | }; | ||
56 | #define RT5670_INIT_REG_LEN ARRAY_SIZE(init_list) | ||
57 | |||
58 | static const struct reg_default rt5670_reg[] = { | ||
59 | { 0x00, 0x0000 }, | ||
60 | { 0x02, 0x8888 }, | ||
61 | { 0x03, 0x8888 }, | ||
62 | { 0x0a, 0x0001 }, | ||
63 | { 0x0b, 0x0827 }, | ||
64 | { 0x0c, 0x0000 }, | ||
65 | { 0x0d, 0x0008 }, | ||
66 | { 0x0e, 0x0000 }, | ||
67 | { 0x0f, 0x0808 }, | ||
68 | { 0x19, 0xafaf }, | ||
69 | { 0x1a, 0xafaf }, | ||
70 | { 0x1b, 0x0011 }, | ||
71 | { 0x1c, 0x2f2f }, | ||
72 | { 0x1d, 0x2f2f }, | ||
73 | { 0x1e, 0x0000 }, | ||
74 | { 0x1f, 0x2f2f }, | ||
75 | { 0x20, 0x0000 }, | ||
76 | { 0x26, 0x7860 }, | ||
77 | { 0x27, 0x7860 }, | ||
78 | { 0x28, 0x7871 }, | ||
79 | { 0x29, 0x8080 }, | ||
80 | { 0x2a, 0x5656 }, | ||
81 | { 0x2b, 0x5454 }, | ||
82 | { 0x2c, 0xaaa0 }, | ||
83 | { 0x2d, 0x0000 }, | ||
84 | { 0x2e, 0x2f2f }, | ||
85 | { 0x2f, 0x1002 }, | ||
86 | { 0x30, 0x0000 }, | ||
87 | { 0x31, 0x5f00 }, | ||
88 | { 0x32, 0x0000 }, | ||
89 | { 0x33, 0x0000 }, | ||
90 | { 0x34, 0x0000 }, | ||
91 | { 0x35, 0x0000 }, | ||
92 | { 0x36, 0x0000 }, | ||
93 | { 0x37, 0x0000 }, | ||
94 | { 0x38, 0x0000 }, | ||
95 | { 0x3b, 0x0000 }, | ||
96 | { 0x3c, 0x007f }, | ||
97 | { 0x3d, 0x0000 }, | ||
98 | { 0x3e, 0x007f }, | ||
99 | { 0x45, 0xe00f }, | ||
100 | { 0x4c, 0x5380 }, | ||
101 | { 0x4f, 0x0073 }, | ||
102 | { 0x52, 0x00d3 }, | ||
103 | { 0x53, 0xf0f0 }, | ||
104 | { 0x61, 0x0000 }, | ||
105 | { 0x62, 0x0001 }, | ||
106 | { 0x63, 0x00c3 }, | ||
107 | { 0x64, 0x0000 }, | ||
108 | { 0x65, 0x0000 }, | ||
109 | { 0x66, 0x0000 }, | ||
110 | { 0x6f, 0x8000 }, | ||
111 | { 0x70, 0x8000 }, | ||
112 | { 0x71, 0x8000 }, | ||
113 | { 0x72, 0x8000 }, | ||
114 | { 0x73, 0x1110 }, | ||
115 | { 0x74, 0x0e00 }, | ||
116 | { 0x75, 0x1505 }, | ||
117 | { 0x76, 0x0015 }, | ||
118 | { 0x77, 0x0c00 }, | ||
119 | { 0x78, 0x4000 }, | ||
120 | { 0x79, 0x0123 }, | ||
121 | { 0x7f, 0x1100 }, | ||
122 | { 0x80, 0x0000 }, | ||
123 | { 0x81, 0x0000 }, | ||
124 | { 0x82, 0x0000 }, | ||
125 | { 0x83, 0x0000 }, | ||
126 | { 0x84, 0x0000 }, | ||
127 | { 0x85, 0x0000 }, | ||
128 | { 0x86, 0x0008 }, | ||
129 | { 0x87, 0x0000 }, | ||
130 | { 0x88, 0x0000 }, | ||
131 | { 0x89, 0x0000 }, | ||
132 | { 0x8a, 0x0000 }, | ||
133 | { 0x8b, 0x0000 }, | ||
134 | { 0x8c, 0x0007 }, | ||
135 | { 0x8d, 0x0000 }, | ||
136 | { 0x8e, 0x0004 }, | ||
137 | { 0x8f, 0x1100 }, | ||
138 | { 0x90, 0x0646 }, | ||
139 | { 0x91, 0x0c06 }, | ||
140 | { 0x93, 0x0000 }, | ||
141 | { 0x94, 0x0000 }, | ||
142 | { 0x95, 0x0000 }, | ||
143 | { 0x97, 0x0000 }, | ||
144 | { 0x98, 0x0000 }, | ||
145 | { 0x99, 0x0000 }, | ||
146 | { 0x9a, 0x2184 }, | ||
147 | { 0x9b, 0x010a }, | ||
148 | { 0x9c, 0x0aea }, | ||
149 | { 0x9d, 0x000c }, | ||
150 | { 0x9e, 0x0400 }, | ||
151 | { 0xae, 0x7000 }, | ||
152 | { 0xaf, 0x0000 }, | ||
153 | { 0xb0, 0x6000 }, | ||
154 | { 0xb1, 0x0000 }, | ||
155 | { 0xb2, 0x0000 }, | ||
156 | { 0xb3, 0x001f }, | ||
157 | { 0xb4, 0x2206 }, | ||
158 | { 0xb5, 0x1f00 }, | ||
159 | { 0xb6, 0x0000 }, | ||
160 | { 0xb7, 0x0000 }, | ||
161 | { 0xbb, 0x0000 }, | ||
162 | { 0xbc, 0x0000 }, | ||
163 | { 0xbd, 0x0000 }, | ||
164 | { 0xbe, 0x0000 }, | ||
165 | { 0xbf, 0x0000 }, | ||
166 | { 0xc0, 0x0000 }, | ||
167 | { 0xc1, 0x0000 }, | ||
168 | { 0xc2, 0x0000 }, | ||
169 | { 0xcd, 0x0000 }, | ||
170 | { 0xce, 0x0000 }, | ||
171 | { 0xcf, 0x1813 }, | ||
172 | { 0xd0, 0x0690 }, | ||
173 | { 0xd1, 0x1c17 }, | ||
174 | { 0xd3, 0xb320 }, | ||
175 | { 0xd4, 0x0000 }, | ||
176 | { 0xd6, 0x0400 }, | ||
177 | { 0xd9, 0x0809 }, | ||
178 | { 0xda, 0x0000 }, | ||
179 | { 0xdb, 0x0001 }, | ||
180 | { 0xdc, 0x0049 }, | ||
181 | { 0xdd, 0x0009 }, | ||
182 | { 0xe6, 0x8000 }, | ||
183 | { 0xe7, 0x0000 }, | ||
184 | { 0xec, 0xb300 }, | ||
185 | { 0xed, 0x0000 }, | ||
186 | { 0xee, 0xb300 }, | ||
187 | { 0xef, 0x0000 }, | ||
188 | { 0xf8, 0x0000 }, | ||
189 | { 0xf9, 0x0000 }, | ||
190 | { 0xfa, 0x8010 }, | ||
191 | { 0xfb, 0x0033 }, | ||
192 | { 0xfc, 0x0080 }, | ||
193 | }; | ||
194 | |||
195 | static bool rt5670_volatile_register(struct device *dev, unsigned int reg) | ||
196 | { | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) { | ||
200 | if ((reg >= rt5670_ranges[i].window_start && | ||
201 | reg <= rt5670_ranges[i].window_start + | ||
202 | rt5670_ranges[i].window_len) || | ||
203 | (reg >= rt5670_ranges[i].range_min && | ||
204 | reg <= rt5670_ranges[i].range_max)) { | ||
205 | return true; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | switch (reg) { | ||
210 | case RT5670_RESET: | ||
211 | case RT5670_PDM_DATA_CTRL1: | ||
212 | case RT5670_PDM1_DATA_CTRL4: | ||
213 | case RT5670_PDM2_DATA_CTRL4: | ||
214 | case RT5670_PRIV_DATA: | ||
215 | case RT5670_ASRC_5: | ||
216 | case RT5670_CJ_CTRL1: | ||
217 | case RT5670_CJ_CTRL2: | ||
218 | case RT5670_CJ_CTRL3: | ||
219 | case RT5670_A_JD_CTRL1: | ||
220 | case RT5670_A_JD_CTRL2: | ||
221 | case RT5670_VAD_CTRL5: | ||
222 | case RT5670_ADC_EQ_CTRL1: | ||
223 | case RT5670_EQ_CTRL1: | ||
224 | case RT5670_ALC_CTRL_1: | ||
225 | case RT5670_IRQ_CTRL1: | ||
226 | case RT5670_IRQ_CTRL2: | ||
227 | case RT5670_INT_IRQ_ST: | ||
228 | case RT5670_IL_CMD: | ||
229 | case RT5670_DSP_CTRL1: | ||
230 | case RT5670_DSP_CTRL2: | ||
231 | case RT5670_DSP_CTRL3: | ||
232 | case RT5670_DSP_CTRL4: | ||
233 | case RT5670_DSP_CTRL5: | ||
234 | case RT5670_VENDOR_ID: | ||
235 | case RT5670_VENDOR_ID1: | ||
236 | case RT5670_VENDOR_ID2: | ||
237 | return true; | ||
238 | default: | ||
239 | return false; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static bool rt5670_readable_register(struct device *dev, unsigned int reg) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; i < ARRAY_SIZE(rt5670_ranges); i++) { | ||
248 | if ((reg >= rt5670_ranges[i].window_start && | ||
249 | reg <= rt5670_ranges[i].window_start + | ||
250 | rt5670_ranges[i].window_len) || | ||
251 | (reg >= rt5670_ranges[i].range_min && | ||
252 | reg <= rt5670_ranges[i].range_max)) { | ||
253 | return true; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | switch (reg) { | ||
258 | case RT5670_RESET: | ||
259 | case RT5670_HP_VOL: | ||
260 | case RT5670_LOUT1: | ||
261 | case RT5670_CJ_CTRL1: | ||
262 | case RT5670_CJ_CTRL2: | ||
263 | case RT5670_CJ_CTRL3: | ||
264 | case RT5670_IN2: | ||
265 | case RT5670_INL1_INR1_VOL: | ||
266 | case RT5670_DAC1_DIG_VOL: | ||
267 | case RT5670_DAC2_DIG_VOL: | ||
268 | case RT5670_DAC_CTRL: | ||
269 | case RT5670_STO1_ADC_DIG_VOL: | ||
270 | case RT5670_MONO_ADC_DIG_VOL: | ||
271 | case RT5670_STO2_ADC_DIG_VOL: | ||
272 | case RT5670_ADC_BST_VOL1: | ||
273 | case RT5670_ADC_BST_VOL2: | ||
274 | case RT5670_STO2_ADC_MIXER: | ||
275 | case RT5670_STO1_ADC_MIXER: | ||
276 | case RT5670_MONO_ADC_MIXER: | ||
277 | case RT5670_AD_DA_MIXER: | ||
278 | case RT5670_STO_DAC_MIXER: | ||
279 | case RT5670_DD_MIXER: | ||
280 | case RT5670_DIG_MIXER: | ||
281 | case RT5670_DSP_PATH1: | ||
282 | case RT5670_DSP_PATH2: | ||
283 | case RT5670_DIG_INF1_DATA: | ||
284 | case RT5670_DIG_INF2_DATA: | ||
285 | case RT5670_PDM_OUT_CTRL: | ||
286 | case RT5670_PDM_DATA_CTRL1: | ||
287 | case RT5670_PDM1_DATA_CTRL2: | ||
288 | case RT5670_PDM1_DATA_CTRL3: | ||
289 | case RT5670_PDM1_DATA_CTRL4: | ||
290 | case RT5670_PDM2_DATA_CTRL2: | ||
291 | case RT5670_PDM2_DATA_CTRL3: | ||
292 | case RT5670_PDM2_DATA_CTRL4: | ||
293 | case RT5670_REC_L1_MIXER: | ||
294 | case RT5670_REC_L2_MIXER: | ||
295 | case RT5670_REC_R1_MIXER: | ||
296 | case RT5670_REC_R2_MIXER: | ||
297 | case RT5670_HPO_MIXER: | ||
298 | case RT5670_MONO_MIXER: | ||
299 | case RT5670_OUT_L1_MIXER: | ||
300 | case RT5670_OUT_R1_MIXER: | ||
301 | case RT5670_LOUT_MIXER: | ||
302 | case RT5670_PWR_DIG1: | ||
303 | case RT5670_PWR_DIG2: | ||
304 | case RT5670_PWR_ANLG1: | ||
305 | case RT5670_PWR_ANLG2: | ||
306 | case RT5670_PWR_MIXER: | ||
307 | case RT5670_PWR_VOL: | ||
308 | case RT5670_PRIV_INDEX: | ||
309 | case RT5670_PRIV_DATA: | ||
310 | case RT5670_I2S4_SDP: | ||
311 | case RT5670_I2S1_SDP: | ||
312 | case RT5670_I2S2_SDP: | ||
313 | case RT5670_I2S3_SDP: | ||
314 | case RT5670_ADDA_CLK1: | ||
315 | case RT5670_ADDA_CLK2: | ||
316 | case RT5670_DMIC_CTRL1: | ||
317 | case RT5670_DMIC_CTRL2: | ||
318 | case RT5670_TDM_CTRL_1: | ||
319 | case RT5670_TDM_CTRL_2: | ||
320 | case RT5670_TDM_CTRL_3: | ||
321 | case RT5670_DSP_CLK: | ||
322 | case RT5670_GLB_CLK: | ||
323 | case RT5670_PLL_CTRL1: | ||
324 | case RT5670_PLL_CTRL2: | ||
325 | case RT5670_ASRC_1: | ||
326 | case RT5670_ASRC_2: | ||
327 | case RT5670_ASRC_3: | ||
328 | case RT5670_ASRC_4: | ||
329 | case RT5670_ASRC_5: | ||
330 | case RT5670_ASRC_7: | ||
331 | case RT5670_ASRC_8: | ||
332 | case RT5670_ASRC_9: | ||
333 | case RT5670_ASRC_10: | ||
334 | case RT5670_ASRC_11: | ||
335 | case RT5670_ASRC_12: | ||
336 | case RT5670_ASRC_13: | ||
337 | case RT5670_ASRC_14: | ||
338 | case RT5670_DEPOP_M1: | ||
339 | case RT5670_DEPOP_M2: | ||
340 | case RT5670_DEPOP_M3: | ||
341 | case RT5670_CHARGE_PUMP: | ||
342 | case RT5670_MICBIAS: | ||
343 | case RT5670_A_JD_CTRL1: | ||
344 | case RT5670_A_JD_CTRL2: | ||
345 | case RT5670_VAD_CTRL1: | ||
346 | case RT5670_VAD_CTRL2: | ||
347 | case RT5670_VAD_CTRL3: | ||
348 | case RT5670_VAD_CTRL4: | ||
349 | case RT5670_VAD_CTRL5: | ||
350 | case RT5670_ADC_EQ_CTRL1: | ||
351 | case RT5670_ADC_EQ_CTRL2: | ||
352 | case RT5670_EQ_CTRL1: | ||
353 | case RT5670_EQ_CTRL2: | ||
354 | case RT5670_ALC_DRC_CTRL1: | ||
355 | case RT5670_ALC_DRC_CTRL2: | ||
356 | case RT5670_ALC_CTRL_1: | ||
357 | case RT5670_ALC_CTRL_2: | ||
358 | case RT5670_ALC_CTRL_3: | ||
359 | case RT5670_JD_CTRL: | ||
360 | case RT5670_IRQ_CTRL1: | ||
361 | case RT5670_IRQ_CTRL2: | ||
362 | case RT5670_INT_IRQ_ST: | ||
363 | case RT5670_GPIO_CTRL1: | ||
364 | case RT5670_GPIO_CTRL2: | ||
365 | case RT5670_GPIO_CTRL3: | ||
366 | case RT5670_SCRABBLE_FUN: | ||
367 | case RT5670_SCRABBLE_CTRL: | ||
368 | case RT5670_BASE_BACK: | ||
369 | case RT5670_MP3_PLUS1: | ||
370 | case RT5670_MP3_PLUS2: | ||
371 | case RT5670_ADJ_HPF1: | ||
372 | case RT5670_ADJ_HPF2: | ||
373 | case RT5670_HP_CALIB_AMP_DET: | ||
374 | case RT5670_SV_ZCD1: | ||
375 | case RT5670_SV_ZCD2: | ||
376 | case RT5670_IL_CMD: | ||
377 | case RT5670_IL_CMD2: | ||
378 | case RT5670_IL_CMD3: | ||
379 | case RT5670_DRC_HL_CTRL1: | ||
380 | case RT5670_DRC_HL_CTRL2: | ||
381 | case RT5670_ADC_MONO_HP_CTRL1: | ||
382 | case RT5670_ADC_MONO_HP_CTRL2: | ||
383 | case RT5670_ADC_STO2_HP_CTRL1: | ||
384 | case RT5670_ADC_STO2_HP_CTRL2: | ||
385 | case RT5670_JD_CTRL3: | ||
386 | case RT5670_JD_CTRL4: | ||
387 | case RT5670_DIG_MISC: | ||
388 | case RT5670_DSP_CTRL1: | ||
389 | case RT5670_DSP_CTRL2: | ||
390 | case RT5670_DSP_CTRL3: | ||
391 | case RT5670_DSP_CTRL4: | ||
392 | case RT5670_DSP_CTRL5: | ||
393 | case RT5670_GEN_CTRL2: | ||
394 | case RT5670_GEN_CTRL3: | ||
395 | case RT5670_VENDOR_ID: | ||
396 | case RT5670_VENDOR_ID1: | ||
397 | case RT5670_VENDOR_ID2: | ||
398 | return true; | ||
399 | default: | ||
400 | return false; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | ||
405 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | ||
406 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | ||
407 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | ||
408 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | ||
409 | |||
410 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | ||
411 | static unsigned int bst_tlv[] = { | ||
412 | TLV_DB_RANGE_HEAD(7), | ||
413 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
414 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | ||
415 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | ||
416 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | ||
417 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | ||
418 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | ||
419 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | ||
420 | }; | ||
421 | |||
422 | /* Interface data select */ | ||
423 | static const char * const rt5670_data_select[] = { | ||
424 | "Normal", "Swap", "left copy to right", "right copy to left" | ||
425 | }; | ||
426 | |||
427 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA, | ||
428 | RT5670_IF2_DAC_SEL_SFT, rt5670_data_select); | ||
429 | |||
430 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA, | ||
431 | RT5670_IF2_ADC_SEL_SFT, rt5670_data_select); | ||
432 | |||
433 | static const struct snd_kcontrol_new rt5670_snd_controls[] = { | ||
434 | /* Headphone Output Volume */ | ||
435 | SOC_DOUBLE("HP Playback Switch", RT5670_HP_VOL, | ||
436 | RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), | ||
437 | SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL, | ||
438 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
439 | 39, 0, out_vol_tlv), | ||
440 | /* OUTPUT Control */ | ||
441 | SOC_DOUBLE("OUT Channel Switch", RT5670_LOUT1, | ||
442 | RT5670_VOL_L_SFT, RT5670_VOL_R_SFT, 1, 1), | ||
443 | SOC_DOUBLE_TLV("OUT Playback Volume", RT5670_LOUT1, | ||
444 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv), | ||
445 | /* DAC Digital Volume */ | ||
446 | SOC_DOUBLE("DAC2 Playback Switch", RT5670_DAC_CTRL, | ||
447 | RT5670_M_DAC_L2_VOL_SFT, RT5670_M_DAC_R2_VOL_SFT, 1, 1), | ||
448 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5670_DAC1_DIG_VOL, | ||
449 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
450 | 175, 0, dac_vol_tlv), | ||
451 | SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5670_DAC2_DIG_VOL, | ||
452 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
453 | 175, 0, dac_vol_tlv), | ||
454 | /* IN1/IN2 Control */ | ||
455 | SOC_SINGLE_TLV("IN1 Boost Volume", RT5670_CJ_CTRL1, | ||
456 | RT5670_BST_SFT1, 8, 0, bst_tlv), | ||
457 | SOC_SINGLE_TLV("IN2 Boost Volume", RT5670_IN2, | ||
458 | RT5670_BST_SFT1, 8, 0, bst_tlv), | ||
459 | /* INL/INR Volume Control */ | ||
460 | SOC_DOUBLE_TLV("IN Capture Volume", RT5670_INL1_INR1_VOL, | ||
461 | RT5670_INL_VOL_SFT, RT5670_INR_VOL_SFT, | ||
462 | 31, 1, in_vol_tlv), | ||
463 | /* ADC Digital Volume Control */ | ||
464 | SOC_DOUBLE("ADC Capture Switch", RT5670_STO1_ADC_DIG_VOL, | ||
465 | RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), | ||
466 | SOC_DOUBLE_TLV("ADC Capture Volume", RT5670_STO1_ADC_DIG_VOL, | ||
467 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
468 | 127, 0, adc_vol_tlv), | ||
469 | |||
470 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5670_MONO_ADC_DIG_VOL, | ||
471 | RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, | ||
472 | 127, 0, adc_vol_tlv), | ||
473 | |||
474 | /* ADC Boost Volume Control */ | ||
475 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1, | ||
476 | RT5670_STO1_ADC_L_BST_SFT, RT5670_STO1_ADC_R_BST_SFT, | ||
477 | 3, 0, adc_bst_tlv), | ||
478 | |||
479 | SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5670_ADC_BST_VOL1, | ||
480 | RT5670_STO2_ADC_L_BST_SFT, RT5670_STO2_ADC_R_BST_SFT, | ||
481 | 3, 0, adc_bst_tlv), | ||
482 | |||
483 | SOC_ENUM("ADC IF2 Data Switch", rt5670_if2_adc_enum), | ||
484 | SOC_ENUM("DAC IF2 Data Switch", rt5670_if2_dac_enum), | ||
485 | }; | ||
486 | |||
487 | /** | ||
488 | * set_dmic_clk - Set parameter of dmic. | ||
489 | * | ||
490 | * @w: DAPM widget. | ||
491 | * @kcontrol: The kcontrol of this widget. | ||
492 | * @event: Event id. | ||
493 | * | ||
494 | * Choose dmic clock between 1MHz and 3MHz. | ||
495 | * It is better for clock to approximate 3MHz. | ||
496 | */ | ||
497 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | ||
498 | struct snd_kcontrol *kcontrol, int event) | ||
499 | { | ||
500 | struct snd_soc_codec *codec = w->codec; | ||
501 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
502 | int idx = -EINVAL; | ||
503 | |||
504 | idx = rl6231_calc_dmic_clk(rt5670->sysclk); | ||
505 | |||
506 | if (idx < 0) | ||
507 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | ||
508 | else | ||
509 | snd_soc_update_bits(codec, RT5670_DMIC_CTRL1, | ||
510 | RT5670_DMIC_CLK_MASK, idx << RT5670_DMIC_CLK_SFT); | ||
511 | return idx; | ||
512 | } | ||
513 | |||
514 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | ||
515 | struct snd_soc_dapm_widget *sink) | ||
516 | { | ||
517 | unsigned int val; | ||
518 | |||
519 | val = snd_soc_read(source->codec, RT5670_GLB_CLK); | ||
520 | val &= RT5670_SCLK_SRC_MASK; | ||
521 | if (val == RT5670_SCLK_SRC_PLL1) | ||
522 | return 1; | ||
523 | else | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | ||
528 | struct snd_soc_dapm_widget *sink) | ||
529 | { | ||
530 | unsigned int reg, shift, val; | ||
531 | |||
532 | switch (source->shift) { | ||
533 | case 0: | ||
534 | reg = RT5670_ASRC_3; | ||
535 | shift = 0; | ||
536 | break; | ||
537 | case 1: | ||
538 | reg = RT5670_ASRC_3; | ||
539 | shift = 4; | ||
540 | break; | ||
541 | case 2: | ||
542 | reg = RT5670_ASRC_5; | ||
543 | shift = 12; | ||
544 | break; | ||
545 | case 3: | ||
546 | reg = RT5670_ASRC_2; | ||
547 | shift = 0; | ||
548 | break; | ||
549 | case 8: | ||
550 | reg = RT5670_ASRC_2; | ||
551 | shift = 4; | ||
552 | break; | ||
553 | case 9: | ||
554 | reg = RT5670_ASRC_2; | ||
555 | shift = 8; | ||
556 | break; | ||
557 | case 10: | ||
558 | reg = RT5670_ASRC_2; | ||
559 | shift = 12; | ||
560 | break; | ||
561 | default: | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; | ||
566 | switch (val) { | ||
567 | case 1: | ||
568 | case 2: | ||
569 | case 3: | ||
570 | case 4: | ||
571 | return 1; | ||
572 | default: | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | } | ||
577 | |||
578 | /* Digital Mixer */ | ||
579 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | ||
580 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | ||
581 | RT5670_M_ADC_L1_SFT, 1, 1), | ||
582 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER, | ||
583 | RT5670_M_ADC_L2_SFT, 1, 1), | ||
584 | }; | ||
585 | |||
586 | static const struct snd_kcontrol_new rt5670_sto1_adc_r_mix[] = { | ||
587 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | ||
588 | RT5670_M_ADC_R1_SFT, 1, 1), | ||
589 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO1_ADC_MIXER, | ||
590 | RT5670_M_ADC_R2_SFT, 1, 1), | ||
591 | }; | ||
592 | |||
593 | static const struct snd_kcontrol_new rt5670_sto2_adc_l_mix[] = { | ||
594 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER, | ||
595 | RT5670_M_ADC_L1_SFT, 1, 1), | ||
596 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER, | ||
597 | RT5670_M_ADC_L2_SFT, 1, 1), | ||
598 | }; | ||
599 | |||
600 | static const struct snd_kcontrol_new rt5670_sto2_adc_r_mix[] = { | ||
601 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO2_ADC_MIXER, | ||
602 | RT5670_M_ADC_R1_SFT, 1, 1), | ||
603 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_STO2_ADC_MIXER, | ||
604 | RT5670_M_ADC_R2_SFT, 1, 1), | ||
605 | }; | ||
606 | |||
607 | static const struct snd_kcontrol_new rt5670_mono_adc_l_mix[] = { | ||
608 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER, | ||
609 | RT5670_M_MONO_ADC_L1_SFT, 1, 1), | ||
610 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER, | ||
611 | RT5670_M_MONO_ADC_L2_SFT, 1, 1), | ||
612 | }; | ||
613 | |||
614 | static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] = { | ||
615 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_MONO_ADC_MIXER, | ||
616 | RT5670_M_MONO_ADC_R1_SFT, 1, 1), | ||
617 | SOC_DAPM_SINGLE("ADC2 Switch", RT5670_MONO_ADC_MIXER, | ||
618 | RT5670_M_MONO_ADC_R2_SFT, 1, 1), | ||
619 | }; | ||
620 | |||
621 | static const struct snd_kcontrol_new rt5670_dac_l_mix[] = { | ||
622 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, | ||
623 | RT5670_M_ADCMIX_L_SFT, 1, 1), | ||
624 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, | ||
625 | RT5670_M_DAC1_L_SFT, 1, 1), | ||
626 | }; | ||
627 | |||
628 | static const struct snd_kcontrol_new rt5670_dac_r_mix[] = { | ||
629 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, | ||
630 | RT5670_M_ADCMIX_R_SFT, 1, 1), | ||
631 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, | ||
632 | RT5670_M_DAC1_R_SFT, 1, 1), | ||
633 | }; | ||
634 | |||
635 | static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] = { | ||
636 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER, | ||
637 | RT5670_M_DAC_L1_SFT, 1, 1), | ||
638 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_STO_DAC_MIXER, | ||
639 | RT5670_M_DAC_L2_SFT, 1, 1), | ||
640 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER, | ||
641 | RT5670_M_DAC_R1_STO_L_SFT, 1, 1), | ||
642 | }; | ||
643 | |||
644 | static const struct snd_kcontrol_new rt5670_sto_dac_r_mix[] = { | ||
645 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_STO_DAC_MIXER, | ||
646 | RT5670_M_DAC_R1_SFT, 1, 1), | ||
647 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_STO_DAC_MIXER, | ||
648 | RT5670_M_DAC_R2_SFT, 1, 1), | ||
649 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_STO_DAC_MIXER, | ||
650 | RT5670_M_DAC_L1_STO_R_SFT, 1, 1), | ||
651 | }; | ||
652 | |||
653 | static const struct snd_kcontrol_new rt5670_mono_dac_l_mix[] = { | ||
654 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_DD_MIXER, | ||
655 | RT5670_M_DAC_L1_MONO_L_SFT, 1, 1), | ||
656 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER, | ||
657 | RT5670_M_DAC_L2_MONO_L_SFT, 1, 1), | ||
658 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER, | ||
659 | RT5670_M_DAC_R2_MONO_L_SFT, 1, 1), | ||
660 | }; | ||
661 | |||
662 | static const struct snd_kcontrol_new rt5670_mono_dac_r_mix[] = { | ||
663 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_DD_MIXER, | ||
664 | RT5670_M_DAC_R1_MONO_R_SFT, 1, 1), | ||
665 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DD_MIXER, | ||
666 | RT5670_M_DAC_R2_MONO_R_SFT, 1, 1), | ||
667 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DD_MIXER, | ||
668 | RT5670_M_DAC_L2_MONO_R_SFT, 1, 1), | ||
669 | }; | ||
670 | |||
671 | static const struct snd_kcontrol_new rt5670_dig_l_mix[] = { | ||
672 | SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5670_DIG_MIXER, | ||
673 | RT5670_M_STO_L_DAC_L_SFT, 1, 1), | ||
674 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER, | ||
675 | RT5670_M_DAC_L2_DAC_L_SFT, 1, 1), | ||
676 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER, | ||
677 | RT5670_M_DAC_R2_DAC_L_SFT, 1, 1), | ||
678 | }; | ||
679 | |||
680 | static const struct snd_kcontrol_new rt5670_dig_r_mix[] = { | ||
681 | SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5670_DIG_MIXER, | ||
682 | RT5670_M_STO_R_DAC_R_SFT, 1, 1), | ||
683 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_DIG_MIXER, | ||
684 | RT5670_M_DAC_R2_DAC_R_SFT, 1, 1), | ||
685 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_DIG_MIXER, | ||
686 | RT5670_M_DAC_L2_DAC_R_SFT, 1, 1), | ||
687 | }; | ||
688 | |||
689 | /* Analog Input Mixer */ | ||
690 | static const struct snd_kcontrol_new rt5670_rec_l_mix[] = { | ||
691 | SOC_DAPM_SINGLE("INL Switch", RT5670_REC_L2_MIXER, | ||
692 | RT5670_M_IN_L_RM_L_SFT, 1, 1), | ||
693 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_L2_MIXER, | ||
694 | RT5670_M_BST2_RM_L_SFT, 1, 1), | ||
695 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_L2_MIXER, | ||
696 | RT5670_M_BST1_RM_L_SFT, 1, 1), | ||
697 | }; | ||
698 | |||
699 | static const struct snd_kcontrol_new rt5670_rec_r_mix[] = { | ||
700 | SOC_DAPM_SINGLE("INR Switch", RT5670_REC_R2_MIXER, | ||
701 | RT5670_M_IN_R_RM_R_SFT, 1, 1), | ||
702 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_REC_R2_MIXER, | ||
703 | RT5670_M_BST2_RM_R_SFT, 1, 1), | ||
704 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_REC_R2_MIXER, | ||
705 | RT5670_M_BST1_RM_R_SFT, 1, 1), | ||
706 | }; | ||
707 | |||
708 | static const struct snd_kcontrol_new rt5670_out_l_mix[] = { | ||
709 | SOC_DAPM_SINGLE("BST1 Switch", RT5670_OUT_L1_MIXER, | ||
710 | RT5670_M_BST1_OM_L_SFT, 1, 1), | ||
711 | SOC_DAPM_SINGLE("INL Switch", RT5670_OUT_L1_MIXER, | ||
712 | RT5670_M_IN_L_OM_L_SFT, 1, 1), | ||
713 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5670_OUT_L1_MIXER, | ||
714 | RT5670_M_DAC_L2_OM_L_SFT, 1, 1), | ||
715 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_OUT_L1_MIXER, | ||
716 | RT5670_M_DAC_L1_OM_L_SFT, 1, 1), | ||
717 | }; | ||
718 | |||
719 | static const struct snd_kcontrol_new rt5670_out_r_mix[] = { | ||
720 | SOC_DAPM_SINGLE("BST2 Switch", RT5670_OUT_R1_MIXER, | ||
721 | RT5670_M_BST2_OM_R_SFT, 1, 1), | ||
722 | SOC_DAPM_SINGLE("INR Switch", RT5670_OUT_R1_MIXER, | ||
723 | RT5670_M_IN_R_OM_R_SFT, 1, 1), | ||
724 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5670_OUT_R1_MIXER, | ||
725 | RT5670_M_DAC_R2_OM_R_SFT, 1, 1), | ||
726 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_OUT_R1_MIXER, | ||
727 | RT5670_M_DAC_R1_OM_R_SFT, 1, 1), | ||
728 | }; | ||
729 | |||
730 | static const struct snd_kcontrol_new rt5670_hpo_mix[] = { | ||
731 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
732 | RT5670_M_DAC1_HM_SFT, 1, 1), | ||
733 | SOC_DAPM_SINGLE("HPVOL Switch", RT5670_HPO_MIXER, | ||
734 | RT5670_M_HPVOL_HM_SFT, 1, 1), | ||
735 | }; | ||
736 | |||
737 | static const struct snd_kcontrol_new rt5670_hpvoll_mix[] = { | ||
738 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
739 | RT5670_M_DACL1_HML_SFT, 1, 1), | ||
740 | SOC_DAPM_SINGLE("INL Switch", RT5670_HPO_MIXER, | ||
741 | RT5670_M_INL1_HML_SFT, 1, 1), | ||
742 | }; | ||
743 | |||
744 | static const struct snd_kcontrol_new rt5670_hpvolr_mix[] = { | ||
745 | SOC_DAPM_SINGLE("DAC1 Switch", RT5670_HPO_MIXER, | ||
746 | RT5670_M_DACR1_HMR_SFT, 1, 1), | ||
747 | SOC_DAPM_SINGLE("INR Switch", RT5670_HPO_MIXER, | ||
748 | RT5670_M_INR1_HMR_SFT, 1, 1), | ||
749 | }; | ||
750 | |||
751 | static const struct snd_kcontrol_new rt5670_lout_mix[] = { | ||
752 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_LOUT_MIXER, | ||
753 | RT5670_M_DAC_L1_LM_SFT, 1, 1), | ||
754 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_LOUT_MIXER, | ||
755 | RT5670_M_DAC_R1_LM_SFT, 1, 1), | ||
756 | SOC_DAPM_SINGLE("OUTMIX L Switch", RT5670_LOUT_MIXER, | ||
757 | RT5670_M_OV_L_LM_SFT, 1, 1), | ||
758 | SOC_DAPM_SINGLE("OUTMIX R Switch", RT5670_LOUT_MIXER, | ||
759 | RT5670_M_OV_R_LM_SFT, 1, 1), | ||
760 | }; | ||
761 | |||
762 | static const struct snd_kcontrol_new rt5670_hpl_mix[] = { | ||
763 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_HPO_MIXER, | ||
764 | RT5670_M_DACL1_HML_SFT, 1, 1), | ||
765 | SOC_DAPM_SINGLE("INL1 Switch", RT5670_HPO_MIXER, | ||
766 | RT5670_M_INL1_HML_SFT, 1, 1), | ||
767 | }; | ||
768 | |||
769 | static const struct snd_kcontrol_new rt5670_hpr_mix[] = { | ||
770 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_HPO_MIXER, | ||
771 | RT5670_M_DACR1_HMR_SFT, 1, 1), | ||
772 | SOC_DAPM_SINGLE("INR1 Switch", RT5670_HPO_MIXER, | ||
773 | RT5670_M_INR1_HMR_SFT, 1, 1), | ||
774 | }; | ||
775 | |||
776 | static const struct snd_kcontrol_new lout_l_enable_control = | ||
777 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1, | ||
778 | RT5670_L_MUTE_SFT, 1, 1); | ||
779 | |||
780 | static const struct snd_kcontrol_new lout_r_enable_control = | ||
781 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1, | ||
782 | RT5670_R_MUTE_SFT, 1, 1); | ||
783 | |||
784 | /* DAC1 L/R source */ /* MX-29 [9:8] [11:10] */ | ||
785 | static const char * const rt5670_dac1_src[] = { | ||
786 | "IF1 DAC", "IF2 DAC" | ||
787 | }; | ||
788 | |||
789 | static SOC_ENUM_SINGLE_DECL(rt5670_dac1l_enum, RT5670_AD_DA_MIXER, | ||
790 | RT5670_DAC1_L_SEL_SFT, rt5670_dac1_src); | ||
791 | |||
792 | static const struct snd_kcontrol_new rt5670_dac1l_mux = | ||
793 | SOC_DAPM_ENUM("DAC1 L source", rt5670_dac1l_enum); | ||
794 | |||
795 | static SOC_ENUM_SINGLE_DECL(rt5670_dac1r_enum, RT5670_AD_DA_MIXER, | ||
796 | RT5670_DAC1_R_SEL_SFT, rt5670_dac1_src); | ||
797 | |||
798 | static const struct snd_kcontrol_new rt5670_dac1r_mux = | ||
799 | SOC_DAPM_ENUM("DAC1 R source", rt5670_dac1r_enum); | ||
800 | |||
801 | /*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */ | ||
802 | /* TODO Use SOC_VALUE_ENUM_SINGLE_DECL */ | ||
803 | static const char * const rt5670_dac12_src[] = { | ||
804 | "IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC", | ||
805 | "Bass", "VAD_ADC", "IF4 DAC" | ||
806 | }; | ||
807 | |||
808 | static SOC_ENUM_SINGLE_DECL(rt5670_dac2l_enum, RT5670_DAC_CTRL, | ||
809 | RT5670_DAC2_L_SEL_SFT, rt5670_dac12_src); | ||
810 | |||
811 | static const struct snd_kcontrol_new rt5670_dac_l2_mux = | ||
812 | SOC_DAPM_ENUM("DAC2 L source", rt5670_dac2l_enum); | ||
813 | |||
814 | static const char * const rt5670_dacr2_src[] = { | ||
815 | "IF1 DAC", "IF2 DAC", "IF3 DAC", "TxDC DAC", "TxDP ADC", "IF4 DAC" | ||
816 | }; | ||
817 | |||
818 | static SOC_ENUM_SINGLE_DECL(rt5670_dac2r_enum, RT5670_DAC_CTRL, | ||
819 | RT5670_DAC2_R_SEL_SFT, rt5670_dacr2_src); | ||
820 | |||
821 | static const struct snd_kcontrol_new rt5670_dac_r2_mux = | ||
822 | SOC_DAPM_ENUM("DAC2 R source", rt5670_dac2r_enum); | ||
823 | |||
824 | /*RxDP source*/ /* MX-2D [15:13] */ | ||
825 | static const char * const rt5670_rxdp_src[] = { | ||
826 | "IF2 DAC", "IF1 DAC", "STO1 ADC Mixer", "STO2 ADC Mixer", | ||
827 | "Mono ADC Mixer L", "Mono ADC Mixer R", "DAC1" | ||
828 | }; | ||
829 | |||
830 | static SOC_ENUM_SINGLE_DECL(rt5670_rxdp_enum, RT5670_DSP_PATH1, | ||
831 | RT5670_RXDP_SEL_SFT, rt5670_rxdp_src); | ||
832 | |||
833 | static const struct snd_kcontrol_new rt5670_rxdp_mux = | ||
834 | SOC_DAPM_ENUM("DAC2 L source", rt5670_rxdp_enum); | ||
835 | |||
836 | /* MX-2D [1] [0] */ | ||
837 | static const char * const rt5670_dsp_bypass_src[] = { | ||
838 | "DSP", "Bypass" | ||
839 | }; | ||
840 | |||
841 | static SOC_ENUM_SINGLE_DECL(rt5670_dsp_ul_enum, RT5670_DSP_PATH1, | ||
842 | RT5670_DSP_UL_SFT, rt5670_dsp_bypass_src); | ||
843 | |||
844 | static const struct snd_kcontrol_new rt5670_dsp_ul_mux = | ||
845 | SOC_DAPM_ENUM("DSP UL source", rt5670_dsp_ul_enum); | ||
846 | |||
847 | static SOC_ENUM_SINGLE_DECL(rt5670_dsp_dl_enum, RT5670_DSP_PATH1, | ||
848 | RT5670_DSP_DL_SFT, rt5670_dsp_bypass_src); | ||
849 | |||
850 | static const struct snd_kcontrol_new rt5670_dsp_dl_mux = | ||
851 | SOC_DAPM_ENUM("DSP DL source", rt5670_dsp_dl_enum); | ||
852 | |||
853 | /* Stereo2 ADC source */ | ||
854 | /* MX-26 [15] */ | ||
855 | static const char * const rt5670_stereo2_adc_lr_src[] = { | ||
856 | "L", "LR" | ||
857 | }; | ||
858 | |||
859 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_lr_enum, RT5670_STO2_ADC_MIXER, | ||
860 | RT5670_STO2_ADC_SRC_SFT, rt5670_stereo2_adc_lr_src); | ||
861 | |||
862 | static const struct snd_kcontrol_new rt5670_sto2_adc_lr_mux = | ||
863 | SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5670_stereo2_adc_lr_enum); | ||
864 | |||
865 | /* Stereo1 ADC source */ | ||
866 | /* MX-27 MX-26 [12] */ | ||
867 | static const char * const rt5670_stereo_adc1_src[] = { | ||
868 | "DAC MIX", "ADC" | ||
869 | }; | ||
870 | |||
871 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER, | ||
872 | RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); | ||
873 | |||
874 | static const struct snd_kcontrol_new rt5670_sto_adc_l1_mux = | ||
875 | SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5670_stereo1_adc1_enum); | ||
876 | |||
877 | static const struct snd_kcontrol_new rt5670_sto_adc_r1_mux = | ||
878 | SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5670_stereo1_adc1_enum); | ||
879 | |||
880 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER, | ||
881 | RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); | ||
882 | |||
883 | static const struct snd_kcontrol_new rt5670_sto2_adc_l1_mux = | ||
884 | SOC_DAPM_ENUM("Stereo2 ADC L1 source", rt5670_stereo2_adc1_enum); | ||
885 | |||
886 | static const struct snd_kcontrol_new rt5670_sto2_adc_r1_mux = | ||
887 | SOC_DAPM_ENUM("Stereo2 ADC R1 source", rt5670_stereo2_adc1_enum); | ||
888 | |||
889 | /* MX-27 MX-26 [11] */ | ||
890 | static const char * const rt5670_stereo_adc2_src[] = { | ||
891 | "DAC MIX", "DMIC" | ||
892 | }; | ||
893 | |||
894 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER, | ||
895 | RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); | ||
896 | |||
897 | static const struct snd_kcontrol_new rt5670_sto_adc_l2_mux = | ||
898 | SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5670_stereo1_adc2_enum); | ||
899 | |||
900 | static const struct snd_kcontrol_new rt5670_sto_adc_r2_mux = | ||
901 | SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5670_stereo1_adc2_enum); | ||
902 | |||
903 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER, | ||
904 | RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); | ||
905 | |||
906 | static const struct snd_kcontrol_new rt5670_sto2_adc_l2_mux = | ||
907 | SOC_DAPM_ENUM("Stereo2 ADC L2 source", rt5670_stereo2_adc2_enum); | ||
908 | |||
909 | static const struct snd_kcontrol_new rt5670_sto2_adc_r2_mux = | ||
910 | SOC_DAPM_ENUM("Stereo2 ADC R2 source", rt5670_stereo2_adc2_enum); | ||
911 | |||
912 | /* MX-27 MX26 [10] */ | ||
913 | static const char * const rt5670_stereo_adc_src[] = { | ||
914 | "ADC1L ADC2R", "ADC3" | ||
915 | }; | ||
916 | |||
917 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc_enum, RT5670_STO1_ADC_MIXER, | ||
918 | RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src); | ||
919 | |||
920 | static const struct snd_kcontrol_new rt5670_sto_adc_mux = | ||
921 | SOC_DAPM_ENUM("Stereo1 ADC source", rt5670_stereo1_adc_enum); | ||
922 | |||
923 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_enum, RT5670_STO2_ADC_MIXER, | ||
924 | RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src); | ||
925 | |||
926 | static const struct snd_kcontrol_new rt5670_sto2_adc_mux = | ||
927 | SOC_DAPM_ENUM("Stereo2 ADC source", rt5670_stereo2_adc_enum); | ||
928 | |||
929 | /* MX-27 MX-26 [9:8] */ | ||
930 | static const char * const rt5670_stereo_dmic_src[] = { | ||
931 | "DMIC1", "DMIC2", "DMIC3" | ||
932 | }; | ||
933 | |||
934 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_dmic_enum, RT5670_STO1_ADC_MIXER, | ||
935 | RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src); | ||
936 | |||
937 | static const struct snd_kcontrol_new rt5670_sto1_dmic_mux = | ||
938 | SOC_DAPM_ENUM("Stereo1 DMIC source", rt5670_stereo1_dmic_enum); | ||
939 | |||
940 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_dmic_enum, RT5670_STO2_ADC_MIXER, | ||
941 | RT5670_DMIC_SRC_SFT, rt5670_stereo_dmic_src); | ||
942 | |||
943 | static const struct snd_kcontrol_new rt5670_sto2_dmic_mux = | ||
944 | SOC_DAPM_ENUM("Stereo2 DMIC source", rt5670_stereo2_dmic_enum); | ||
945 | |||
946 | /* MX-27 [0] */ | ||
947 | static const char * const rt5670_stereo_dmic3_src[] = { | ||
948 | "DMIC3", "PDM ADC" | ||
949 | }; | ||
950 | |||
951 | static SOC_ENUM_SINGLE_DECL(rt5670_stereo_dmic3_enum, RT5670_STO1_ADC_MIXER, | ||
952 | RT5670_DMIC3_SRC_SFT, rt5670_stereo_dmic3_src); | ||
953 | |||
954 | static const struct snd_kcontrol_new rt5670_sto_dmic3_mux = | ||
955 | SOC_DAPM_ENUM("Stereo DMIC3 source", rt5670_stereo_dmic3_enum); | ||
956 | |||
957 | /* Mono ADC source */ | ||
958 | /* MX-28 [12] */ | ||
959 | static const char * const rt5670_mono_adc_l1_src[] = { | ||
960 | "Mono DAC MIXL", "ADC1" | ||
961 | }; | ||
962 | |||
963 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l1_enum, RT5670_MONO_ADC_MIXER, | ||
964 | RT5670_MONO_ADC_L1_SRC_SFT, rt5670_mono_adc_l1_src); | ||
965 | |||
966 | static const struct snd_kcontrol_new rt5670_mono_adc_l1_mux = | ||
967 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5670_mono_adc_l1_enum); | ||
968 | /* MX-28 [11] */ | ||
969 | static const char * const rt5670_mono_adc_l2_src[] = { | ||
970 | "Mono DAC MIXL", "DMIC" | ||
971 | }; | ||
972 | |||
973 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_l2_enum, RT5670_MONO_ADC_MIXER, | ||
974 | RT5670_MONO_ADC_L2_SRC_SFT, rt5670_mono_adc_l2_src); | ||
975 | |||
976 | static const struct snd_kcontrol_new rt5670_mono_adc_l2_mux = | ||
977 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5670_mono_adc_l2_enum); | ||
978 | |||
979 | /* MX-28 [9:8] */ | ||
980 | static const char * const rt5670_mono_dmic_src[] = { | ||
981 | "DMIC1", "DMIC2", "DMIC3" | ||
982 | }; | ||
983 | |||
984 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_l_enum, RT5670_MONO_ADC_MIXER, | ||
985 | RT5670_MONO_DMIC_L_SRC_SFT, rt5670_mono_dmic_src); | ||
986 | |||
987 | static const struct snd_kcontrol_new rt5670_mono_dmic_l_mux = | ||
988 | SOC_DAPM_ENUM("Mono DMIC left source", rt5670_mono_dmic_l_enum); | ||
989 | /* MX-28 [1:0] */ | ||
990 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_dmic_r_enum, RT5670_MONO_ADC_MIXER, | ||
991 | RT5670_MONO_DMIC_R_SRC_SFT, rt5670_mono_dmic_src); | ||
992 | |||
993 | static const struct snd_kcontrol_new rt5670_mono_dmic_r_mux = | ||
994 | SOC_DAPM_ENUM("Mono DMIC Right source", rt5670_mono_dmic_r_enum); | ||
995 | /* MX-28 [4] */ | ||
996 | static const char * const rt5670_mono_adc_r1_src[] = { | ||
997 | "Mono DAC MIXR", "ADC2" | ||
998 | }; | ||
999 | |||
1000 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r1_enum, RT5670_MONO_ADC_MIXER, | ||
1001 | RT5670_MONO_ADC_R1_SRC_SFT, rt5670_mono_adc_r1_src); | ||
1002 | |||
1003 | static const struct snd_kcontrol_new rt5670_mono_adc_r1_mux = | ||
1004 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5670_mono_adc_r1_enum); | ||
1005 | /* MX-28 [3] */ | ||
1006 | static const char * const rt5670_mono_adc_r2_src[] = { | ||
1007 | "Mono DAC MIXR", "DMIC" | ||
1008 | }; | ||
1009 | |||
1010 | static SOC_ENUM_SINGLE_DECL(rt5670_mono_adc_r2_enum, RT5670_MONO_ADC_MIXER, | ||
1011 | RT5670_MONO_ADC_R2_SRC_SFT, rt5670_mono_adc_r2_src); | ||
1012 | |||
1013 | static const struct snd_kcontrol_new rt5670_mono_adc_r2_mux = | ||
1014 | SOC_DAPM_ENUM("Mono ADC2 right source", rt5670_mono_adc_r2_enum); | ||
1015 | |||
1016 | /* MX-2D [3:2] */ | ||
1017 | static const char * const rt5670_txdp_slot_src[] = { | ||
1018 | "Slot 0-1", "Slot 2-3", "Slot 4-5", "Slot 6-7" | ||
1019 | }; | ||
1020 | |||
1021 | static SOC_ENUM_SINGLE_DECL(rt5670_txdp_slot_enum, RT5670_DSP_PATH1, | ||
1022 | RT5670_TXDP_SLOT_SEL_SFT, rt5670_txdp_slot_src); | ||
1023 | |||
1024 | static const struct snd_kcontrol_new rt5670_txdp_slot_mux = | ||
1025 | SOC_DAPM_ENUM("TxDP Slot source", rt5670_txdp_slot_enum); | ||
1026 | |||
1027 | /* MX-2F [15] */ | ||
1028 | static const char * const rt5670_if1_adc2_in_src[] = { | ||
1029 | "IF_ADC2", "VAD_ADC" | ||
1030 | }; | ||
1031 | |||
1032 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in_enum, RT5670_DIG_INF1_DATA, | ||
1033 | RT5670_IF1_ADC2_IN_SFT, rt5670_if1_adc2_in_src); | ||
1034 | |||
1035 | static const struct snd_kcontrol_new rt5670_if1_adc2_in_mux = | ||
1036 | SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5670_if1_adc2_in_enum); | ||
1037 | |||
1038 | /* MX-2F [14:12] */ | ||
1039 | static const char * const rt5670_if2_adc_in_src[] = { | ||
1040 | "IF_ADC1", "IF_ADC2", "IF_ADC3", "TxDC_DAC", "TxDP_ADC", "VAD_ADC" | ||
1041 | }; | ||
1042 | |||
1043 | static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_in_enum, RT5670_DIG_INF1_DATA, | ||
1044 | RT5670_IF2_ADC_IN_SFT, rt5670_if2_adc_in_src); | ||
1045 | |||
1046 | static const struct snd_kcontrol_new rt5670_if2_adc_in_mux = | ||
1047 | SOC_DAPM_ENUM("IF2 ADC IN source", rt5670_if2_adc_in_enum); | ||
1048 | |||
1049 | /* MX-30 [5:4] */ | ||
1050 | static const char * const rt5670_if4_adc_in_src[] = { | ||
1051 | "IF_ADC1", "IF_ADC2", "IF_ADC3" | ||
1052 | }; | ||
1053 | |||
1054 | static SOC_ENUM_SINGLE_DECL(rt5670_if4_adc_in_enum, RT5670_DIG_INF2_DATA, | ||
1055 | RT5670_IF4_ADC_IN_SFT, rt5670_if4_adc_in_src); | ||
1056 | |||
1057 | static const struct snd_kcontrol_new rt5670_if4_adc_in_mux = | ||
1058 | SOC_DAPM_ENUM("IF4 ADC IN source", rt5670_if4_adc_in_enum); | ||
1059 | |||
1060 | /* MX-31 [15] [13] [11] [9] */ | ||
1061 | static const char * const rt5670_pdm_src[] = { | ||
1062 | "Mono DAC", "Stereo DAC" | ||
1063 | }; | ||
1064 | |||
1065 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_l_enum, RT5670_PDM_OUT_CTRL, | ||
1066 | RT5670_PDM1_L_SFT, rt5670_pdm_src); | ||
1067 | |||
1068 | static const struct snd_kcontrol_new rt5670_pdm1_l_mux = | ||
1069 | SOC_DAPM_ENUM("PDM1 L source", rt5670_pdm1_l_enum); | ||
1070 | |||
1071 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm1_r_enum, RT5670_PDM_OUT_CTRL, | ||
1072 | RT5670_PDM1_R_SFT, rt5670_pdm_src); | ||
1073 | |||
1074 | static const struct snd_kcontrol_new rt5670_pdm1_r_mux = | ||
1075 | SOC_DAPM_ENUM("PDM1 R source", rt5670_pdm1_r_enum); | ||
1076 | |||
1077 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_l_enum, RT5670_PDM_OUT_CTRL, | ||
1078 | RT5670_PDM2_L_SFT, rt5670_pdm_src); | ||
1079 | |||
1080 | static const struct snd_kcontrol_new rt5670_pdm2_l_mux = | ||
1081 | SOC_DAPM_ENUM("PDM2 L source", rt5670_pdm2_l_enum); | ||
1082 | |||
1083 | static SOC_ENUM_SINGLE_DECL(rt5670_pdm2_r_enum, RT5670_PDM_OUT_CTRL, | ||
1084 | RT5670_PDM2_R_SFT, rt5670_pdm_src); | ||
1085 | |||
1086 | static const struct snd_kcontrol_new rt5670_pdm2_r_mux = | ||
1087 | SOC_DAPM_ENUM("PDM2 R source", rt5670_pdm2_r_enum); | ||
1088 | |||
1089 | /* MX-FA [12] */ | ||
1090 | static const char * const rt5670_if1_adc1_in1_src[] = { | ||
1091 | "IF_ADC1", "IF1_ADC3" | ||
1092 | }; | ||
1093 | |||
1094 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in1_enum, RT5670_DIG_MISC, | ||
1095 | RT5670_IF1_ADC1_IN1_SFT, rt5670_if1_adc1_in1_src); | ||
1096 | |||
1097 | static const struct snd_kcontrol_new rt5670_if1_adc1_in1_mux = | ||
1098 | SOC_DAPM_ENUM("IF1 ADC1 IN1 source", rt5670_if1_adc1_in1_enum); | ||
1099 | |||
1100 | /* MX-FA [11] */ | ||
1101 | static const char * const rt5670_if1_adc1_in2_src[] = { | ||
1102 | "IF1_ADC1_IN1", "IF1_ADC4" | ||
1103 | }; | ||
1104 | |||
1105 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc1_in2_enum, RT5670_DIG_MISC, | ||
1106 | RT5670_IF1_ADC1_IN2_SFT, rt5670_if1_adc1_in2_src); | ||
1107 | |||
1108 | static const struct snd_kcontrol_new rt5670_if1_adc1_in2_mux = | ||
1109 | SOC_DAPM_ENUM("IF1 ADC1 IN2 source", rt5670_if1_adc1_in2_enum); | ||
1110 | |||
1111 | /* MX-FA [10] */ | ||
1112 | static const char * const rt5670_if1_adc2_in1_src[] = { | ||
1113 | "IF1_ADC2_IN", "IF1_ADC4" | ||
1114 | }; | ||
1115 | |||
1116 | static SOC_ENUM_SINGLE_DECL(rt5670_if1_adc2_in1_enum, RT5670_DIG_MISC, | ||
1117 | RT5670_IF1_ADC2_IN1_SFT, rt5670_if1_adc2_in1_src); | ||
1118 | |||
1119 | static const struct snd_kcontrol_new rt5670_if1_adc2_in1_mux = | ||
1120 | SOC_DAPM_ENUM("IF1 ADC2 IN1 source", rt5670_if1_adc2_in1_enum); | ||
1121 | |||
1122 | /* MX-9D [9:8] */ | ||
1123 | static const char * const rt5670_vad_adc_src[] = { | ||
1124 | "Sto1 ADC L", "Mono ADC L", "Mono ADC R", "Sto2 ADC L" | ||
1125 | }; | ||
1126 | |||
1127 | static SOC_ENUM_SINGLE_DECL(rt5670_vad_adc_enum, RT5670_VAD_CTRL4, | ||
1128 | RT5670_VAD_SEL_SFT, rt5670_vad_adc_src); | ||
1129 | |||
1130 | static const struct snd_kcontrol_new rt5670_vad_adc_mux = | ||
1131 | SOC_DAPM_ENUM("VAD ADC source", rt5670_vad_adc_enum); | ||
1132 | |||
1133 | static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, | ||
1134 | struct snd_kcontrol *kcontrol, int event) | ||
1135 | { | ||
1136 | struct snd_soc_codec *codec = w->codec; | ||
1137 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
1138 | |||
1139 | switch (event) { | ||
1140 | case SND_SOC_DAPM_POST_PMU: | ||
1141 | regmap_update_bits(rt5670->regmap, RT5670_CHARGE_PUMP, | ||
1142 | RT5670_PM_HP_MASK, RT5670_PM_HP_HV); | ||
1143 | regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2, | ||
1144 | 0x0400, 0x0400); | ||
1145 | /* headphone amp power on */ | ||
1146 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
1147 | RT5670_PWR_HA | RT5670_PWR_FV1 | | ||
1148 | RT5670_PWR_FV2, RT5670_PWR_HA | | ||
1149 | RT5670_PWR_FV1 | RT5670_PWR_FV2); | ||
1150 | /* depop parameters */ | ||
1151 | regmap_write(rt5670->regmap, RT5670_DEPOP_M2, 0x3100); | ||
1152 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8009); | ||
1153 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1154 | RT5670_HP_DCC_INT1, 0x9f00); | ||
1155 | mdelay(20); | ||
1156 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1157 | break; | ||
1158 | case SND_SOC_DAPM_PRE_PMD: | ||
1159 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x0004); | ||
1160 | msleep(30); | ||
1161 | break; | ||
1162 | default: | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | static int rt5670_hp_event(struct snd_soc_dapm_widget *w, | ||
1170 | struct snd_kcontrol *kcontrol, int event) | ||
1171 | { | ||
1172 | struct snd_soc_codec *codec = w->codec; | ||
1173 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
1174 | |||
1175 | switch (event) { | ||
1176 | case SND_SOC_DAPM_POST_PMU: | ||
1177 | /* headphone unmute sequence */ | ||
1178 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1179 | RT5670_MAMP_INT_REG2, 0xb400); | ||
1180 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772); | ||
1181 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x805d); | ||
1182 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d); | ||
1183 | regmap_update_bits(rt5670->regmap, RT5670_GEN_CTRL2, | ||
1184 | 0x0300, 0x0300); | ||
1185 | regmap_update_bits(rt5670->regmap, RT5670_HP_VOL, | ||
1186 | RT5670_L_MUTE | RT5670_R_MUTE, 0); | ||
1187 | msleep(80); | ||
1188 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1189 | break; | ||
1190 | |||
1191 | case SND_SOC_DAPM_PRE_PMD: | ||
1192 | /* headphone mute sequence */ | ||
1193 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1194 | RT5670_MAMP_INT_REG2, 0xb400); | ||
1195 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0772); | ||
1196 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x803d); | ||
1197 | mdelay(10); | ||
1198 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x831d); | ||
1199 | mdelay(10); | ||
1200 | regmap_update_bits(rt5670->regmap, RT5670_HP_VOL, | ||
1201 | RT5670_L_MUTE | RT5670_R_MUTE, | ||
1202 | RT5670_L_MUTE | RT5670_R_MUTE); | ||
1203 | msleep(20); | ||
1204 | regmap_update_bits(rt5670->regmap, | ||
1205 | RT5670_GEN_CTRL2, 0x0300, 0x0); | ||
1206 | regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019); | ||
1207 | regmap_write(rt5670->regmap, RT5670_DEPOP_M3, 0x0707); | ||
1208 | regmap_write(rt5670->regmap, RT5670_PR_BASE + | ||
1209 | RT5670_MAMP_INT_REG2, 0xfc00); | ||
1210 | break; | ||
1211 | |||
1212 | default: | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, | ||
1220 | struct snd_kcontrol *kcontrol, int event) | ||
1221 | { | ||
1222 | struct snd_soc_codec *codec = w->codec; | ||
1223 | |||
1224 | switch (event) { | ||
1225 | case SND_SOC_DAPM_POST_PMU: | ||
1226 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1227 | RT5670_PWR_BST1_P, RT5670_PWR_BST1_P); | ||
1228 | break; | ||
1229 | |||
1230 | case SND_SOC_DAPM_PRE_PMD: | ||
1231 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1232 | RT5670_PWR_BST1_P, 0); | ||
1233 | break; | ||
1234 | |||
1235 | default: | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int rt5670_bst2_event(struct snd_soc_dapm_widget *w, | ||
1243 | struct snd_kcontrol *kcontrol, int event) | ||
1244 | { | ||
1245 | struct snd_soc_codec *codec = w->codec; | ||
1246 | |||
1247 | switch (event) { | ||
1248 | case SND_SOC_DAPM_POST_PMU: | ||
1249 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1250 | RT5670_PWR_BST2_P, RT5670_PWR_BST2_P); | ||
1251 | break; | ||
1252 | |||
1253 | case SND_SOC_DAPM_PRE_PMD: | ||
1254 | snd_soc_update_bits(codec, RT5670_PWR_ANLG2, | ||
1255 | RT5670_PWR_BST2_P, 0); | ||
1256 | break; | ||
1257 | |||
1258 | default: | ||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { | ||
1266 | SND_SOC_DAPM_SUPPLY("PLL1", RT5670_PWR_ANLG2, | ||
1267 | RT5670_PWR_PLL_BIT, 0, NULL, 0), | ||
1268 | SND_SOC_DAPM_SUPPLY("I2S DSP", RT5670_PWR_DIG2, | ||
1269 | RT5670_PWR_I2S_DSP_BIT, 0, NULL, 0), | ||
1270 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5670_PWR_VOL, | ||
1271 | RT5670_PWR_MIC_DET_BIT, 0, NULL, 0), | ||
1272 | |||
1273 | /* ASRC */ | ||
1274 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5670_ASRC_1, | ||
1275 | 11, 0, NULL, 0), | ||
1276 | SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5670_ASRC_1, | ||
1277 | 12, 0, NULL, 0), | ||
1278 | SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5670_ASRC_1, | ||
1279 | 10, 0, NULL, 0), | ||
1280 | SND_SOC_DAPM_SUPPLY_S("DAC MONO L ASRC", 1, RT5670_ASRC_1, | ||
1281 | 9, 0, NULL, 0), | ||
1282 | SND_SOC_DAPM_SUPPLY_S("DAC MONO R ASRC", 1, RT5670_ASRC_1, | ||
1283 | 8, 0, NULL, 0), | ||
1284 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5670_ASRC_1, | ||
1285 | 3, 0, NULL, 0), | ||
1286 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5670_ASRC_1, | ||
1287 | 2, 0, NULL, 0), | ||
1288 | SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5670_ASRC_1, | ||
1289 | 1, 0, NULL, 0), | ||
1290 | SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5670_ASRC_1, | ||
1291 | 0, 0, NULL, 0), | ||
1292 | |||
1293 | /* Input Side */ | ||
1294 | /* micbias */ | ||
1295 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5670_PWR_ANLG2, | ||
1296 | RT5670_PWR_MB1_BIT, 0, NULL, 0), | ||
1297 | |||
1298 | /* Input Lines */ | ||
1299 | SND_SOC_DAPM_INPUT("DMIC L1"), | ||
1300 | SND_SOC_DAPM_INPUT("DMIC R1"), | ||
1301 | SND_SOC_DAPM_INPUT("DMIC L2"), | ||
1302 | SND_SOC_DAPM_INPUT("DMIC R2"), | ||
1303 | SND_SOC_DAPM_INPUT("DMIC L3"), | ||
1304 | SND_SOC_DAPM_INPUT("DMIC R3"), | ||
1305 | |||
1306 | SND_SOC_DAPM_INPUT("IN1P"), | ||
1307 | SND_SOC_DAPM_INPUT("IN1N"), | ||
1308 | SND_SOC_DAPM_INPUT("IN2P"), | ||
1309 | SND_SOC_DAPM_INPUT("IN2N"), | ||
1310 | |||
1311 | SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1312 | SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1313 | SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1314 | |||
1315 | SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, | ||
1316 | set_dmic_clk, SND_SOC_DAPM_PRE_PMU), | ||
1317 | SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5670_DMIC_CTRL1, | ||
1318 | RT5670_DMIC_1_EN_SFT, 0, NULL, 0), | ||
1319 | SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5670_DMIC_CTRL1, | ||
1320 | RT5670_DMIC_2_EN_SFT, 0, NULL, 0), | ||
1321 | SND_SOC_DAPM_SUPPLY("DMIC3 Power", RT5670_DMIC_CTRL1, | ||
1322 | RT5670_DMIC_3_EN_SFT, 0, NULL, 0), | ||
1323 | /* Boost */ | ||
1324 | SND_SOC_DAPM_PGA_E("BST1", RT5670_PWR_ANLG2, RT5670_PWR_BST1_BIT, | ||
1325 | 0, NULL, 0, rt5670_bst1_event, | ||
1326 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1327 | SND_SOC_DAPM_PGA_E("BST2", RT5670_PWR_ANLG2, RT5670_PWR_BST2_BIT, | ||
1328 | 0, NULL, 0, rt5670_bst2_event, | ||
1329 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1330 | /* Input Volume */ | ||
1331 | SND_SOC_DAPM_PGA("INL VOL", RT5670_PWR_VOL, | ||
1332 | RT5670_PWR_IN_L_BIT, 0, NULL, 0), | ||
1333 | SND_SOC_DAPM_PGA("INR VOL", RT5670_PWR_VOL, | ||
1334 | RT5670_PWR_IN_R_BIT, 0, NULL, 0), | ||
1335 | |||
1336 | /* REC Mixer */ | ||
1337 | SND_SOC_DAPM_MIXER("RECMIXL", RT5670_PWR_MIXER, RT5670_PWR_RM_L_BIT, 0, | ||
1338 | rt5670_rec_l_mix, ARRAY_SIZE(rt5670_rec_l_mix)), | ||
1339 | SND_SOC_DAPM_MIXER("RECMIXR", RT5670_PWR_MIXER, RT5670_PWR_RM_R_BIT, 0, | ||
1340 | rt5670_rec_r_mix, ARRAY_SIZE(rt5670_rec_r_mix)), | ||
1341 | /* ADCs */ | ||
1342 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
1343 | SND_SOC_DAPM_ADC("ADC 2", NULL, SND_SOC_NOPM, 0, 0), | ||
1344 | |||
1345 | SND_SOC_DAPM_PGA("ADC 1_2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1346 | |||
1347 | SND_SOC_DAPM_SUPPLY("ADC 1 power", RT5670_PWR_DIG1, | ||
1348 | RT5670_PWR_ADC_L_BIT, 0, NULL, 0), | ||
1349 | SND_SOC_DAPM_SUPPLY("ADC 2 power", RT5670_PWR_DIG1, | ||
1350 | RT5670_PWR_ADC_R_BIT, 0, NULL, 0), | ||
1351 | SND_SOC_DAPM_SUPPLY("ADC clock", RT5670_PR_BASE + | ||
1352 | RT5670_CHOP_DAC_ADC, 12, 0, NULL, 0), | ||
1353 | /* ADC Mux */ | ||
1354 | SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, | ||
1355 | &rt5670_sto1_dmic_mux), | ||
1356 | SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1357 | &rt5670_sto_adc_l2_mux), | ||
1358 | SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1359 | &rt5670_sto_adc_r2_mux), | ||
1360 | SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1361 | &rt5670_sto_adc_l1_mux), | ||
1362 | SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1363 | &rt5670_sto_adc_r1_mux), | ||
1364 | SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, | ||
1365 | &rt5670_sto2_dmic_mux), | ||
1366 | SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1367 | &rt5670_sto2_adc_l2_mux), | ||
1368 | SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1369 | &rt5670_sto2_adc_r2_mux), | ||
1370 | SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1371 | &rt5670_sto2_adc_l1_mux), | ||
1372 | SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1373 | &rt5670_sto2_adc_r1_mux), | ||
1374 | SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0, | ||
1375 | &rt5670_sto2_adc_lr_mux), | ||
1376 | SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0, | ||
1377 | &rt5670_mono_dmic_l_mux), | ||
1378 | SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0, | ||
1379 | &rt5670_mono_dmic_r_mux), | ||
1380 | SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1381 | &rt5670_mono_adc_l2_mux), | ||
1382 | SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1383 | &rt5670_mono_adc_l1_mux), | ||
1384 | SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1385 | &rt5670_mono_adc_r1_mux), | ||
1386 | SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1387 | &rt5670_mono_adc_r2_mux), | ||
1388 | /* ADC Mixer */ | ||
1389 | SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5670_PWR_DIG2, | ||
1390 | RT5670_PWR_ADC_S1F_BIT, 0, NULL, 0), | ||
1391 | SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5670_PWR_DIG2, | ||
1392 | RT5670_PWR_ADC_S2F_BIT, 0, NULL, 0), | ||
1393 | SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", RT5670_STO1_ADC_DIG_VOL, | ||
1394 | RT5670_L_MUTE_SFT, 1, rt5670_sto1_adc_l_mix, | ||
1395 | ARRAY_SIZE(rt5670_sto1_adc_l_mix)), | ||
1396 | SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", RT5670_STO1_ADC_DIG_VOL, | ||
1397 | RT5670_R_MUTE_SFT, 1, rt5670_sto1_adc_r_mix, | ||
1398 | ARRAY_SIZE(rt5670_sto1_adc_r_mix)), | ||
1399 | SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, | ||
1400 | rt5670_sto2_adc_l_mix, | ||
1401 | ARRAY_SIZE(rt5670_sto2_adc_l_mix)), | ||
1402 | SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, | ||
1403 | rt5670_sto2_adc_r_mix, | ||
1404 | ARRAY_SIZE(rt5670_sto2_adc_r_mix)), | ||
1405 | SND_SOC_DAPM_SUPPLY("ADC Mono Left Filter", RT5670_PWR_DIG2, | ||
1406 | RT5670_PWR_ADC_MF_L_BIT, 0, NULL, 0), | ||
1407 | SND_SOC_DAPM_MIXER("Mono ADC MIXL", RT5670_MONO_ADC_DIG_VOL, | ||
1408 | RT5670_L_MUTE_SFT, 1, rt5670_mono_adc_l_mix, | ||
1409 | ARRAY_SIZE(rt5670_mono_adc_l_mix)), | ||
1410 | SND_SOC_DAPM_SUPPLY("ADC Mono Right Filter", RT5670_PWR_DIG2, | ||
1411 | RT5670_PWR_ADC_MF_R_BIT, 0, NULL, 0), | ||
1412 | SND_SOC_DAPM_MIXER("Mono ADC MIXR", RT5670_MONO_ADC_DIG_VOL, | ||
1413 | RT5670_R_MUTE_SFT, 1, rt5670_mono_adc_r_mix, | ||
1414 | ARRAY_SIZE(rt5670_mono_adc_r_mix)), | ||
1415 | |||
1416 | /* ADC PGA */ | ||
1417 | SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1418 | SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1419 | SND_SOC_DAPM_PGA("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1420 | SND_SOC_DAPM_PGA("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1421 | SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1422 | SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1423 | SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1424 | SND_SOC_DAPM_PGA("Mono ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1425 | SND_SOC_DAPM_PGA("VAD_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1426 | SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1427 | SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1428 | SND_SOC_DAPM_PGA("IF_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1429 | SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1430 | SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1431 | SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1432 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1433 | |||
1434 | /* DSP */ | ||
1435 | SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1436 | SND_SOC_DAPM_PGA("TxDP_ADC_L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1437 | SND_SOC_DAPM_PGA("TxDP_ADC_R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1438 | SND_SOC_DAPM_PGA("TxDC_DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1439 | |||
1440 | SND_SOC_DAPM_MUX("TDM Data Mux", SND_SOC_NOPM, 0, 0, | ||
1441 | &rt5670_txdp_slot_mux), | ||
1442 | |||
1443 | SND_SOC_DAPM_MUX("DSP UL Mux", SND_SOC_NOPM, 0, 0, | ||
1444 | &rt5670_dsp_ul_mux), | ||
1445 | SND_SOC_DAPM_MUX("DSP DL Mux", SND_SOC_NOPM, 0, 0, | ||
1446 | &rt5670_dsp_dl_mux), | ||
1447 | |||
1448 | SND_SOC_DAPM_MUX("RxDP Mux", SND_SOC_NOPM, 0, 0, | ||
1449 | &rt5670_rxdp_mux), | ||
1450 | |||
1451 | /* IF2 Mux */ | ||
1452 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, 0, 0, | ||
1453 | &rt5670_if2_adc_in_mux), | ||
1454 | |||
1455 | /* Digital Interface */ | ||
1456 | SND_SOC_DAPM_SUPPLY("I2S1", RT5670_PWR_DIG1, | ||
1457 | RT5670_PWR_I2S1_BIT, 0, NULL, 0), | ||
1458 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1459 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1460 | SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1461 | SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1462 | SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1463 | SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1464 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1465 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1466 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1467 | SND_SOC_DAPM_SUPPLY("I2S2", RT5670_PWR_DIG1, | ||
1468 | RT5670_PWR_I2S2_BIT, 0, NULL, 0), | ||
1469 | SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1470 | SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1471 | SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1472 | SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1473 | SND_SOC_DAPM_PGA("IF2 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1474 | SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1475 | |||
1476 | /* Digital Interface Select */ | ||
1477 | SND_SOC_DAPM_MUX("IF1 ADC1 IN1 Mux", SND_SOC_NOPM, 0, 0, | ||
1478 | &rt5670_if1_adc1_in1_mux), | ||
1479 | SND_SOC_DAPM_MUX("IF1 ADC1 IN2 Mux", SND_SOC_NOPM, 0, 0, | ||
1480 | &rt5670_if1_adc1_in2_mux), | ||
1481 | SND_SOC_DAPM_MUX("IF1 ADC2 IN Mux", SND_SOC_NOPM, 0, 0, | ||
1482 | &rt5670_if1_adc2_in_mux), | ||
1483 | SND_SOC_DAPM_MUX("IF1 ADC2 IN1 Mux", SND_SOC_NOPM, 0, 0, | ||
1484 | &rt5670_if1_adc2_in1_mux), | ||
1485 | SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0, | ||
1486 | &rt5670_vad_adc_mux), | ||
1487 | |||
1488 | /* Audio Interface */ | ||
1489 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1490 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
1491 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1492 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, | ||
1493 | RT5670_GPIO_CTRL1, RT5670_I2S2_PIN_SFT, 1), | ||
1494 | |||
1495 | /* Audio DSP */ | ||
1496 | SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1497 | |||
1498 | /* Output Side */ | ||
1499 | /* DAC mixer before sound effect */ | ||
1500 | SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, | ||
1501 | rt5670_dac_l_mix, ARRAY_SIZE(rt5670_dac_l_mix)), | ||
1502 | SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, | ||
1503 | rt5670_dac_r_mix, ARRAY_SIZE(rt5670_dac_r_mix)), | ||
1504 | SND_SOC_DAPM_PGA("DAC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1505 | |||
1506 | /* DAC2 channel Mux */ | ||
1507 | SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1508 | &rt5670_dac_l2_mux), | ||
1509 | SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1510 | &rt5670_dac_r2_mux), | ||
1511 | SND_SOC_DAPM_PGA("DAC L2 Volume", RT5670_PWR_DIG1, | ||
1512 | RT5670_PWR_DAC_L2_BIT, 0, NULL, 0), | ||
1513 | SND_SOC_DAPM_PGA("DAC R2 Volume", RT5670_PWR_DIG1, | ||
1514 | RT5670_PWR_DAC_R2_BIT, 0, NULL, 0), | ||
1515 | |||
1516 | SND_SOC_DAPM_MUX("DAC1 L Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1l_mux), | ||
1517 | SND_SOC_DAPM_MUX("DAC1 R Mux", SND_SOC_NOPM, 0, 0, &rt5670_dac1r_mux), | ||
1518 | |||
1519 | /* DAC Mixer */ | ||
1520 | SND_SOC_DAPM_SUPPLY("DAC Stereo1 Filter", RT5670_PWR_DIG2, | ||
1521 | RT5670_PWR_DAC_S1F_BIT, 0, NULL, 0), | ||
1522 | SND_SOC_DAPM_SUPPLY("DAC Mono Left Filter", RT5670_PWR_DIG2, | ||
1523 | RT5670_PWR_DAC_MF_L_BIT, 0, NULL, 0), | ||
1524 | SND_SOC_DAPM_SUPPLY("DAC Mono Right Filter", RT5670_PWR_DIG2, | ||
1525 | RT5670_PWR_DAC_MF_R_BIT, 0, NULL, 0), | ||
1526 | SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1527 | rt5670_sto_dac_l_mix, | ||
1528 | ARRAY_SIZE(rt5670_sto_dac_l_mix)), | ||
1529 | SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1530 | rt5670_sto_dac_r_mix, | ||
1531 | ARRAY_SIZE(rt5670_sto_dac_r_mix)), | ||
1532 | SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1533 | rt5670_mono_dac_l_mix, | ||
1534 | ARRAY_SIZE(rt5670_mono_dac_l_mix)), | ||
1535 | SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1536 | rt5670_mono_dac_r_mix, | ||
1537 | ARRAY_SIZE(rt5670_mono_dac_r_mix)), | ||
1538 | SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1539 | rt5670_dig_l_mix, | ||
1540 | ARRAY_SIZE(rt5670_dig_l_mix)), | ||
1541 | SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1542 | rt5670_dig_r_mix, | ||
1543 | ARRAY_SIZE(rt5670_dig_r_mix)), | ||
1544 | |||
1545 | /* DACs */ | ||
1546 | SND_SOC_DAPM_SUPPLY("DAC L1 Power", RT5670_PWR_DIG1, | ||
1547 | RT5670_PWR_DAC_L1_BIT, 0, NULL, 0), | ||
1548 | SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5670_PWR_DIG1, | ||
1549 | RT5670_PWR_DAC_R1_BIT, 0, NULL, 0), | ||
1550 | SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0), | ||
1551 | SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0), | ||
1552 | SND_SOC_DAPM_DAC("DAC L2", NULL, RT5670_PWR_DIG1, | ||
1553 | RT5670_PWR_DAC_L2_BIT, 0), | ||
1554 | |||
1555 | SND_SOC_DAPM_DAC("DAC R2", NULL, RT5670_PWR_DIG1, | ||
1556 | RT5670_PWR_DAC_R2_BIT, 0), | ||
1557 | /* OUT Mixer */ | ||
1558 | |||
1559 | SND_SOC_DAPM_MIXER("OUT MIXL", RT5670_PWR_MIXER, RT5670_PWR_OM_L_BIT, | ||
1560 | 0, rt5670_out_l_mix, ARRAY_SIZE(rt5670_out_l_mix)), | ||
1561 | SND_SOC_DAPM_MIXER("OUT MIXR", RT5670_PWR_MIXER, RT5670_PWR_OM_R_BIT, | ||
1562 | 0, rt5670_out_r_mix, ARRAY_SIZE(rt5670_out_r_mix)), | ||
1563 | /* Ouput Volume */ | ||
1564 | SND_SOC_DAPM_MIXER("HPOVOL MIXL", RT5670_PWR_VOL, | ||
1565 | RT5670_PWR_HV_L_BIT, 0, | ||
1566 | rt5670_hpvoll_mix, ARRAY_SIZE(rt5670_hpvoll_mix)), | ||
1567 | SND_SOC_DAPM_MIXER("HPOVOL MIXR", RT5670_PWR_VOL, | ||
1568 | RT5670_PWR_HV_R_BIT, 0, | ||
1569 | rt5670_hpvolr_mix, ARRAY_SIZE(rt5670_hpvolr_mix)), | ||
1570 | SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1571 | SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1572 | SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1573 | |||
1574 | /* HPO/LOUT/Mono Mixer */ | ||
1575 | SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, | ||
1576 | rt5670_hpo_mix, ARRAY_SIZE(rt5670_hpo_mix)), | ||
1577 | SND_SOC_DAPM_MIXER("LOUT MIX", RT5670_PWR_ANLG1, RT5670_PWR_LM_BIT, | ||
1578 | 0, rt5670_lout_mix, ARRAY_SIZE(rt5670_lout_mix)), | ||
1579 | SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, 0, 0, | ||
1580 | rt5670_hp_power_event, SND_SOC_DAPM_POST_PMU | | ||
1581 | SND_SOC_DAPM_PRE_PMD), | ||
1582 | SND_SOC_DAPM_SUPPLY("HP L Amp", RT5670_PWR_ANLG1, | ||
1583 | RT5670_PWR_HP_L_BIT, 0, NULL, 0), | ||
1584 | SND_SOC_DAPM_SUPPLY("HP R Amp", RT5670_PWR_ANLG1, | ||
1585 | RT5670_PWR_HP_R_BIT, 0, NULL, 0), | ||
1586 | SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, | ||
1587 | rt5670_hp_event, SND_SOC_DAPM_PRE_PMD | | ||
1588 | SND_SOC_DAPM_POST_PMU), | ||
1589 | SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0, | ||
1590 | &lout_l_enable_control), | ||
1591 | SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0, | ||
1592 | &lout_r_enable_control), | ||
1593 | SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1594 | |||
1595 | /* PDM */ | ||
1596 | SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5670_PWR_DIG2, | ||
1597 | RT5670_PWR_PDM1_BIT, 0, NULL, 0), | ||
1598 | SND_SOC_DAPM_SUPPLY("PDM2 Power", RT5670_PWR_DIG2, | ||
1599 | RT5670_PWR_PDM2_BIT, 0, NULL, 0), | ||
1600 | |||
1601 | SND_SOC_DAPM_MUX("PDM1 L Mux", RT5670_PDM_OUT_CTRL, | ||
1602 | RT5670_M_PDM1_L_SFT, 1, &rt5670_pdm1_l_mux), | ||
1603 | SND_SOC_DAPM_MUX("PDM1 R Mux", RT5670_PDM_OUT_CTRL, | ||
1604 | RT5670_M_PDM1_R_SFT, 1, &rt5670_pdm1_r_mux), | ||
1605 | SND_SOC_DAPM_MUX("PDM2 L Mux", RT5670_PDM_OUT_CTRL, | ||
1606 | RT5670_M_PDM2_L_SFT, 1, &rt5670_pdm2_l_mux), | ||
1607 | SND_SOC_DAPM_MUX("PDM2 R Mux", RT5670_PDM_OUT_CTRL, | ||
1608 | RT5670_M_PDM2_R_SFT, 1, &rt5670_pdm2_r_mux), | ||
1609 | |||
1610 | /* Output Lines */ | ||
1611 | SND_SOC_DAPM_OUTPUT("HPOL"), | ||
1612 | SND_SOC_DAPM_OUTPUT("HPOR"), | ||
1613 | SND_SOC_DAPM_OUTPUT("LOUTL"), | ||
1614 | SND_SOC_DAPM_OUTPUT("LOUTR"), | ||
1615 | SND_SOC_DAPM_OUTPUT("PDM1L"), | ||
1616 | SND_SOC_DAPM_OUTPUT("PDM1R"), | ||
1617 | SND_SOC_DAPM_OUTPUT("PDM2L"), | ||
1618 | SND_SOC_DAPM_OUTPUT("PDM2R"), | ||
1619 | }; | ||
1620 | |||
1621 | static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | ||
1622 | { "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | ||
1623 | { "ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | ||
1624 | { "ADC Mono Left Filter", NULL, "ADC MONO L ASRC", is_using_asrc }, | ||
1625 | { "ADC Mono Right Filter", NULL, "ADC MONO R ASRC", is_using_asrc }, | ||
1626 | { "DAC Mono Left Filter", NULL, "DAC MONO L ASRC", is_using_asrc }, | ||
1627 | { "DAC Mono Right Filter", NULL, "DAC MONO R ASRC", is_using_asrc }, | ||
1628 | { "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc }, | ||
1629 | |||
1630 | { "I2S1", NULL, "I2S1 ASRC" }, | ||
1631 | { "I2S2", NULL, "I2S2 ASRC" }, | ||
1632 | |||
1633 | { "DMIC1", NULL, "DMIC L1" }, | ||
1634 | { "DMIC1", NULL, "DMIC R1" }, | ||
1635 | { "DMIC2", NULL, "DMIC L2" }, | ||
1636 | { "DMIC2", NULL, "DMIC R2" }, | ||
1637 | { "DMIC3", NULL, "DMIC L3" }, | ||
1638 | { "DMIC3", NULL, "DMIC R3" }, | ||
1639 | |||
1640 | { "BST1", NULL, "IN1P" }, | ||
1641 | { "BST1", NULL, "IN1N" }, | ||
1642 | { "BST1", NULL, "Mic Det Power" }, | ||
1643 | { "BST2", NULL, "IN2P" }, | ||
1644 | { "BST2", NULL, "IN2N" }, | ||
1645 | |||
1646 | { "INL VOL", NULL, "IN2P" }, | ||
1647 | { "INR VOL", NULL, "IN2N" }, | ||
1648 | |||
1649 | { "RECMIXL", "INL Switch", "INL VOL" }, | ||
1650 | { "RECMIXL", "BST2 Switch", "BST2" }, | ||
1651 | { "RECMIXL", "BST1 Switch", "BST1" }, | ||
1652 | |||
1653 | { "RECMIXR", "INR Switch", "INR VOL" }, | ||
1654 | { "RECMIXR", "BST2 Switch", "BST2" }, | ||
1655 | { "RECMIXR", "BST1 Switch", "BST1" }, | ||
1656 | |||
1657 | { "ADC 1", NULL, "RECMIXL" }, | ||
1658 | { "ADC 1", NULL, "ADC 1 power" }, | ||
1659 | { "ADC 1", NULL, "ADC clock" }, | ||
1660 | { "ADC 2", NULL, "RECMIXR" }, | ||
1661 | { "ADC 2", NULL, "ADC 2 power" }, | ||
1662 | { "ADC 2", NULL, "ADC clock" }, | ||
1663 | |||
1664 | { "DMIC L1", NULL, "DMIC CLK" }, | ||
1665 | { "DMIC L1", NULL, "DMIC1 Power" }, | ||
1666 | { "DMIC R1", NULL, "DMIC CLK" }, | ||
1667 | { "DMIC R1", NULL, "DMIC1 Power" }, | ||
1668 | { "DMIC L2", NULL, "DMIC CLK" }, | ||
1669 | { "DMIC L2", NULL, "DMIC2 Power" }, | ||
1670 | { "DMIC R2", NULL, "DMIC CLK" }, | ||
1671 | { "DMIC R2", NULL, "DMIC2 Power" }, | ||
1672 | { "DMIC L3", NULL, "DMIC CLK" }, | ||
1673 | { "DMIC L3", NULL, "DMIC3 Power" }, | ||
1674 | { "DMIC R3", NULL, "DMIC CLK" }, | ||
1675 | { "DMIC R3", NULL, "DMIC3 Power" }, | ||
1676 | |||
1677 | { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, | ||
1678 | { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, | ||
1679 | { "Stereo1 DMIC Mux", "DMIC3", "DMIC3" }, | ||
1680 | |||
1681 | { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, | ||
1682 | { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, | ||
1683 | { "Stereo2 DMIC Mux", "DMIC3", "DMIC3" }, | ||
1684 | |||
1685 | { "Mono DMIC L Mux", "DMIC1", "DMIC L1" }, | ||
1686 | { "Mono DMIC L Mux", "DMIC2", "DMIC L2" }, | ||
1687 | { "Mono DMIC L Mux", "DMIC3", "DMIC L3" }, | ||
1688 | |||
1689 | { "Mono DMIC R Mux", "DMIC1", "DMIC R1" }, | ||
1690 | { "Mono DMIC R Mux", "DMIC2", "DMIC R2" }, | ||
1691 | { "Mono DMIC R Mux", "DMIC3", "DMIC R3" }, | ||
1692 | |||
1693 | { "ADC 1_2", NULL, "ADC 1" }, | ||
1694 | { "ADC 1_2", NULL, "ADC 2" }, | ||
1695 | |||
1696 | { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" }, | ||
1697 | { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, | ||
1698 | { "Stereo1 ADC L1 Mux", "ADC", "ADC 1_2" }, | ||
1699 | { "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" }, | ||
1700 | |||
1701 | { "Stereo1 ADC R1 Mux", "ADC", "ADC 1_2" }, | ||
1702 | { "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" }, | ||
1703 | { "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC Mux" }, | ||
1704 | { "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" }, | ||
1705 | |||
1706 | { "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" }, | ||
1707 | { "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" }, | ||
1708 | { "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" }, | ||
1709 | { "Mono ADC L1 Mux", "ADC1", "ADC 1" }, | ||
1710 | |||
1711 | { "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" }, | ||
1712 | { "Mono ADC R1 Mux", "ADC2", "ADC 2" }, | ||
1713 | { "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" }, | ||
1714 | { "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" }, | ||
1715 | |||
1716 | { "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" }, | ||
1717 | { "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" }, | ||
1718 | { "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" }, | ||
1719 | { "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" }, | ||
1720 | |||
1721 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, | ||
1722 | { "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" }, | ||
1723 | { "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1724 | |||
1725 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, | ||
1726 | { "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" }, | ||
1727 | { "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1728 | |||
1729 | { "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" }, | ||
1730 | { "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" }, | ||
1731 | { "Mono ADC MIXL", NULL, "ADC Mono Left Filter" }, | ||
1732 | { "ADC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1733 | |||
1734 | { "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" }, | ||
1735 | { "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" }, | ||
1736 | { "Mono ADC MIXR", NULL, "ADC Mono Right Filter" }, | ||
1737 | { "ADC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1738 | |||
1739 | { "Stereo2 ADC L2 Mux", "DMIC", "Stereo2 DMIC Mux" }, | ||
1740 | { "Stereo2 ADC L2 Mux", "DAC MIX", "DAC MIXL" }, | ||
1741 | { "Stereo2 ADC L1 Mux", "ADC", "ADC 1_2" }, | ||
1742 | { "Stereo2 ADC L1 Mux", "DAC MIX", "DAC MIXL" }, | ||
1743 | |||
1744 | { "Stereo2 ADC R1 Mux", "ADC", "ADC 1_2" }, | ||
1745 | { "Stereo2 ADC R1 Mux", "DAC MIX", "DAC MIXR" }, | ||
1746 | { "Stereo2 ADC R2 Mux", "DMIC", "Stereo2 DMIC Mux" }, | ||
1747 | { "Stereo2 ADC R2 Mux", "DAC MIX", "DAC MIXR" }, | ||
1748 | |||
1749 | { "Sto2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux" }, | ||
1750 | { "Sto2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux" }, | ||
1751 | { "Sto2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux" }, | ||
1752 | { "Sto2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux" }, | ||
1753 | |||
1754 | { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXL" }, | ||
1755 | { "Sto2 ADC LR MIX", NULL, "Sto2 ADC MIXR" }, | ||
1756 | |||
1757 | { "Stereo2 ADC LR Mux", "L", "Sto2 ADC MIXL" }, | ||
1758 | { "Stereo2 ADC LR Mux", "LR", "Sto2 ADC LR MIX" }, | ||
1759 | |||
1760 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, | ||
1761 | { "Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter" }, | ||
1762 | { "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1763 | |||
1764 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, | ||
1765 | { "Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter" }, | ||
1766 | { "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1767 | |||
1768 | { "VAD ADC Mux", "Sto1 ADC L", "Stereo1 ADC MIXL" }, | ||
1769 | { "VAD ADC Mux", "Mono ADC L", "Mono ADC MIXL" }, | ||
1770 | { "VAD ADC Mux", "Mono ADC R", "Mono ADC MIXR" }, | ||
1771 | { "VAD ADC Mux", "Sto2 ADC L", "Sto2 ADC MIXL" }, | ||
1772 | |||
1773 | { "VAD_ADC", NULL, "VAD ADC Mux" }, | ||
1774 | |||
1775 | { "IF_ADC1", NULL, "Stereo1 ADC MIXL" }, | ||
1776 | { "IF_ADC1", NULL, "Stereo1 ADC MIXR" }, | ||
1777 | { "IF_ADC2", NULL, "Mono ADC MIXL" }, | ||
1778 | { "IF_ADC2", NULL, "Mono ADC MIXR" }, | ||
1779 | { "IF_ADC3", NULL, "Stereo2 ADC MIXL" }, | ||
1780 | { "IF_ADC3", NULL, "Stereo2 ADC MIXR" }, | ||
1781 | |||
1782 | { "IF1 ADC1 IN1 Mux", "IF_ADC1", "IF_ADC1" }, | ||
1783 | { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" }, | ||
1784 | |||
1785 | { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" }, | ||
1786 | { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" }, | ||
1787 | |||
1788 | { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" }, | ||
1789 | { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" }, | ||
1790 | |||
1791 | { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" }, | ||
1792 | { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" }, | ||
1793 | |||
1794 | { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" }, | ||
1795 | { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" }, | ||
1796 | |||
1797 | { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, | ||
1798 | { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, | ||
1799 | { "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXL" }, | ||
1800 | { "Stereo2 ADC MIX", NULL, "Sto2 ADC MIXR" }, | ||
1801 | { "Mono ADC MIX", NULL, "Mono ADC MIXL" }, | ||
1802 | { "Mono ADC MIX", NULL, "Mono ADC MIXR" }, | ||
1803 | |||
1804 | { "RxDP Mux", "IF2 DAC", "IF2 DAC" }, | ||
1805 | { "RxDP Mux", "IF1 DAC", "IF1 DAC2" }, | ||
1806 | { "RxDP Mux", "STO1 ADC Mixer", "Stereo1 ADC MIX" }, | ||
1807 | { "RxDP Mux", "STO2 ADC Mixer", "Stereo2 ADC MIX" }, | ||
1808 | { "RxDP Mux", "Mono ADC Mixer L", "Mono ADC MIXL" }, | ||
1809 | { "RxDP Mux", "Mono ADC Mixer R", "Mono ADC MIXR" }, | ||
1810 | { "RxDP Mux", "DAC1", "DAC MIX" }, | ||
1811 | |||
1812 | { "TDM Data Mux", "Slot 0-1", "Stereo1 ADC MIX" }, | ||
1813 | { "TDM Data Mux", "Slot 2-3", "Mono ADC MIX" }, | ||
1814 | { "TDM Data Mux", "Slot 4-5", "Stereo2 ADC MIX" }, | ||
1815 | { "TDM Data Mux", "Slot 6-7", "IF2 DAC" }, | ||
1816 | |||
1817 | { "DSP UL Mux", "Bypass", "TDM Data Mux" }, | ||
1818 | { "DSP UL Mux", NULL, "I2S DSP" }, | ||
1819 | { "DSP DL Mux", "Bypass", "RxDP Mux" }, | ||
1820 | { "DSP DL Mux", NULL, "I2S DSP" }, | ||
1821 | |||
1822 | { "TxDP_ADC_L", NULL, "DSP UL Mux" }, | ||
1823 | { "TxDP_ADC_R", NULL, "DSP UL Mux" }, | ||
1824 | { "TxDC_DAC", NULL, "DSP DL Mux" }, | ||
1825 | |||
1826 | { "TxDP_ADC", NULL, "TxDP_ADC_L" }, | ||
1827 | { "TxDP_ADC", NULL, "TxDP_ADC_R" }, | ||
1828 | |||
1829 | { "IF1 ADC", NULL, "I2S1" }, | ||
1830 | { "IF1 ADC", NULL, "IF1_ADC1" }, | ||
1831 | { "IF1 ADC", NULL, "IF1_ADC2" }, | ||
1832 | { "IF1 ADC", NULL, "IF_ADC3" }, | ||
1833 | { "IF1 ADC", NULL, "TxDP_ADC" }, | ||
1834 | |||
1835 | { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" }, | ||
1836 | { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, | ||
1837 | { "IF2 ADC Mux", "IF_ADC3", "IF_ADC3" }, | ||
1838 | { "IF2 ADC Mux", "TxDC_DAC", "TxDC_DAC" }, | ||
1839 | { "IF2 ADC Mux", "TxDP_ADC", "TxDP_ADC" }, | ||
1840 | { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, | ||
1841 | |||
1842 | { "IF2 ADC L", NULL, "IF2 ADC Mux" }, | ||
1843 | { "IF2 ADC R", NULL, "IF2 ADC Mux" }, | ||
1844 | |||
1845 | { "IF2 ADC", NULL, "I2S2" }, | ||
1846 | { "IF2 ADC", NULL, "IF2 ADC L" }, | ||
1847 | { "IF2 ADC", NULL, "IF2 ADC R" }, | ||
1848 | |||
1849 | { "AIF1TX", NULL, "IF1 ADC" }, | ||
1850 | { "AIF2TX", NULL, "IF2 ADC" }, | ||
1851 | |||
1852 | { "IF1 DAC1", NULL, "AIF1RX" }, | ||
1853 | { "IF1 DAC2", NULL, "AIF1RX" }, | ||
1854 | { "IF2 DAC", NULL, "AIF2RX" }, | ||
1855 | |||
1856 | { "IF1 DAC1", NULL, "I2S1" }, | ||
1857 | { "IF1 DAC2", NULL, "I2S1" }, | ||
1858 | { "IF2 DAC", NULL, "I2S2" }, | ||
1859 | |||
1860 | { "IF1 DAC2 L", NULL, "IF1 DAC2" }, | ||
1861 | { "IF1 DAC2 R", NULL, "IF1 DAC2" }, | ||
1862 | { "IF1 DAC1 L", NULL, "IF1 DAC1" }, | ||
1863 | { "IF1 DAC1 R", NULL, "IF1 DAC1" }, | ||
1864 | { "IF2 DAC L", NULL, "IF2 DAC" }, | ||
1865 | { "IF2 DAC R", NULL, "IF2 DAC" }, | ||
1866 | |||
1867 | { "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" }, | ||
1868 | { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" }, | ||
1869 | |||
1870 | { "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" }, | ||
1871 | { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, | ||
1872 | |||
1873 | { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, | ||
1874 | { "DAC1 MIXL", "DAC1 Switch", "DAC1 L Mux" }, | ||
1875 | { "DAC1 MIXL", NULL, "DAC Stereo1 Filter" }, | ||
1876 | { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" }, | ||
1877 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, | ||
1878 | { "DAC1 MIXR", NULL, "DAC Stereo1 Filter" }, | ||
1879 | |||
1880 | { "DAC MIX", NULL, "DAC1 MIXL" }, | ||
1881 | { "DAC MIX", NULL, "DAC1 MIXR" }, | ||
1882 | |||
1883 | { "Audio DSP", NULL, "DAC1 MIXL" }, | ||
1884 | { "Audio DSP", NULL, "DAC1 MIXR" }, | ||
1885 | |||
1886 | { "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" }, | ||
1887 | { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" }, | ||
1888 | { "DAC L2 Mux", "TxDC DAC", "TxDC_DAC" }, | ||
1889 | { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, | ||
1890 | { "DAC L2 Volume", NULL, "DAC L2 Mux" }, | ||
1891 | { "DAC L2 Volume", NULL, "DAC Mono Left Filter" }, | ||
1892 | |||
1893 | { "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" }, | ||
1894 | { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" }, | ||
1895 | { "DAC R2 Mux", "TxDC DAC", "TxDC_DAC" }, | ||
1896 | { "DAC R2 Mux", "TxDP ADC", "TxDP_ADC" }, | ||
1897 | { "DAC R2 Volume", NULL, "DAC R2 Mux" }, | ||
1898 | { "DAC R2 Volume", NULL, "DAC Mono Right Filter" }, | ||
1899 | |||
1900 | { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1901 | { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1902 | { "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1903 | { "Stereo DAC MIXL", NULL, "DAC Stereo1 Filter" }, | ||
1904 | { "Stereo DAC MIXL", NULL, "DAC L1 Power" }, | ||
1905 | { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1906 | { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1907 | { "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1908 | { "Stereo DAC MIXR", NULL, "DAC Stereo1 Filter" }, | ||
1909 | { "Stereo DAC MIXR", NULL, "DAC R1 Power" }, | ||
1910 | |||
1911 | { "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, | ||
1912 | { "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1913 | { "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1914 | { "Mono DAC MIXL", NULL, "DAC Mono Left Filter" }, | ||
1915 | { "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, | ||
1916 | { "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1917 | { "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1918 | { "Mono DAC MIXR", NULL, "DAC Mono Right Filter" }, | ||
1919 | |||
1920 | { "DAC MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, | ||
1921 | { "DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1922 | { "DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1923 | { "DAC MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, | ||
1924 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | ||
1925 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | ||
1926 | |||
1927 | { "DAC L1", NULL, "DAC L1 Power" }, | ||
1928 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
1929 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1930 | { "DAC R1", NULL, "DAC R1 Power" }, | ||
1931 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
1932 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1933 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
1934 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1935 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
1936 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1937 | |||
1938 | { "OUT MIXL", "BST1 Switch", "BST1" }, | ||
1939 | { "OUT MIXL", "INL Switch", "INL VOL" }, | ||
1940 | { "OUT MIXL", "DAC L2 Switch", "DAC L2" }, | ||
1941 | { "OUT MIXL", "DAC L1 Switch", "DAC L1" }, | ||
1942 | |||
1943 | { "OUT MIXR", "BST2 Switch", "BST2" }, | ||
1944 | { "OUT MIXR", "INR Switch", "INR VOL" }, | ||
1945 | { "OUT MIXR", "DAC R2 Switch", "DAC R2" }, | ||
1946 | { "OUT MIXR", "DAC R1 Switch", "DAC R1" }, | ||
1947 | |||
1948 | { "HPOVOL MIXL", "DAC1 Switch", "DAC L1" }, | ||
1949 | { "HPOVOL MIXL", "INL Switch", "INL VOL" }, | ||
1950 | { "HPOVOL MIXR", "DAC1 Switch", "DAC R1" }, | ||
1951 | { "HPOVOL MIXR", "INR Switch", "INR VOL" }, | ||
1952 | |||
1953 | { "DAC 2", NULL, "DAC L2" }, | ||
1954 | { "DAC 2", NULL, "DAC R2" }, | ||
1955 | { "DAC 1", NULL, "DAC L1" }, | ||
1956 | { "DAC 1", NULL, "DAC R1" }, | ||
1957 | { "HPOVOL", NULL, "HPOVOL MIXL" }, | ||
1958 | { "HPOVOL", NULL, "HPOVOL MIXR" }, | ||
1959 | { "HPO MIX", "DAC1 Switch", "DAC 1" }, | ||
1960 | { "HPO MIX", "HPVOL Switch", "HPOVOL" }, | ||
1961 | |||
1962 | { "LOUT MIX", "DAC L1 Switch", "DAC L1" }, | ||
1963 | { "LOUT MIX", "DAC R1 Switch", "DAC R1" }, | ||
1964 | { "LOUT MIX", "OUTMIX L Switch", "OUT MIXL" }, | ||
1965 | { "LOUT MIX", "OUTMIX R Switch", "OUT MIXR" }, | ||
1966 | |||
1967 | { "PDM1 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
1968 | { "PDM1 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
1969 | { "PDM1 L Mux", NULL, "PDM1 Power" }, | ||
1970 | { "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
1971 | { "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
1972 | { "PDM1 R Mux", NULL, "PDM1 Power" }, | ||
1973 | { "PDM2 L Mux", "Stereo DAC", "Stereo DAC MIXL" }, | ||
1974 | { "PDM2 L Mux", "Mono DAC", "Mono DAC MIXL" }, | ||
1975 | { "PDM2 L Mux", NULL, "PDM2 Power" }, | ||
1976 | { "PDM2 R Mux", "Stereo DAC", "Stereo DAC MIXR" }, | ||
1977 | { "PDM2 R Mux", "Mono DAC", "Mono DAC MIXR" }, | ||
1978 | { "PDM2 R Mux", NULL, "PDM2 Power" }, | ||
1979 | |||
1980 | { "HP Amp", NULL, "HPO MIX" }, | ||
1981 | { "HP Amp", NULL, "Mic Det Power" }, | ||
1982 | { "HPOL", NULL, "HP Amp" }, | ||
1983 | { "HPOL", NULL, "HP L Amp" }, | ||
1984 | { "HPOL", NULL, "Improve HP Amp Drv" }, | ||
1985 | { "HPOR", NULL, "HP Amp" }, | ||
1986 | { "HPOR", NULL, "HP R Amp" }, | ||
1987 | { "HPOR", NULL, "Improve HP Amp Drv" }, | ||
1988 | |||
1989 | { "LOUT Amp", NULL, "LOUT MIX" }, | ||
1990 | { "LOUT L Playback", "Switch", "LOUT Amp" }, | ||
1991 | { "LOUT R Playback", "Switch", "LOUT Amp" }, | ||
1992 | { "LOUTL", NULL, "LOUT L Playback" }, | ||
1993 | { "LOUTR", NULL, "LOUT R Playback" }, | ||
1994 | { "LOUTL", NULL, "Improve HP Amp Drv" }, | ||
1995 | { "LOUTR", NULL, "Improve HP Amp Drv" }, | ||
1996 | |||
1997 | { "PDM1L", NULL, "PDM1 L Mux" }, | ||
1998 | { "PDM1R", NULL, "PDM1 R Mux" }, | ||
1999 | { "PDM2L", NULL, "PDM2 L Mux" }, | ||
2000 | { "PDM2R", NULL, "PDM2 R Mux" }, | ||
2001 | }; | ||
2002 | |||
2003 | static int rt5670_hw_params(struct snd_pcm_substream *substream, | ||
2004 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
2005 | { | ||
2006 | struct snd_soc_codec *codec = dai->codec; | ||
2007 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2008 | unsigned int val_len = 0, val_clk, mask_clk; | ||
2009 | int pre_div, bclk_ms, frame_size; | ||
2010 | |||
2011 | rt5670->lrck[dai->id] = params_rate(params); | ||
2012 | pre_div = rl6231_get_clk_info(rt5670->sysclk, rt5670->lrck[dai->id]); | ||
2013 | if (pre_div < 0) { | ||
2014 | dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", | ||
2015 | rt5670->lrck[dai->id], dai->id); | ||
2016 | return -EINVAL; | ||
2017 | } | ||
2018 | frame_size = snd_soc_params_to_frame_size(params); | ||
2019 | if (frame_size < 0) { | ||
2020 | dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); | ||
2021 | return -EINVAL; | ||
2022 | } | ||
2023 | bclk_ms = frame_size > 32; | ||
2024 | rt5670->bclk[dai->id] = rt5670->lrck[dai->id] * (32 << bclk_ms); | ||
2025 | |||
2026 | dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", | ||
2027 | rt5670->bclk[dai->id], rt5670->lrck[dai->id]); | ||
2028 | dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", | ||
2029 | bclk_ms, pre_div, dai->id); | ||
2030 | |||
2031 | switch (params_width(params)) { | ||
2032 | case 16: | ||
2033 | break; | ||
2034 | case 20: | ||
2035 | val_len |= RT5670_I2S_DL_20; | ||
2036 | break; | ||
2037 | case 24: | ||
2038 | val_len |= RT5670_I2S_DL_24; | ||
2039 | break; | ||
2040 | case 8: | ||
2041 | val_len |= RT5670_I2S_DL_8; | ||
2042 | break; | ||
2043 | default: | ||
2044 | return -EINVAL; | ||
2045 | } | ||
2046 | |||
2047 | switch (dai->id) { | ||
2048 | case RT5670_AIF1: | ||
2049 | mask_clk = RT5670_I2S_BCLK_MS1_MASK | RT5670_I2S_PD1_MASK; | ||
2050 | val_clk = bclk_ms << RT5670_I2S_BCLK_MS1_SFT | | ||
2051 | pre_div << RT5670_I2S_PD1_SFT; | ||
2052 | snd_soc_update_bits(codec, RT5670_I2S1_SDP, | ||
2053 | RT5670_I2S_DL_MASK, val_len); | ||
2054 | snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk); | ||
2055 | break; | ||
2056 | case RT5670_AIF2: | ||
2057 | mask_clk = RT5670_I2S_BCLK_MS2_MASK | RT5670_I2S_PD2_MASK; | ||
2058 | val_clk = bclk_ms << RT5670_I2S_BCLK_MS2_SFT | | ||
2059 | pre_div << RT5670_I2S_PD2_SFT; | ||
2060 | snd_soc_update_bits(codec, RT5670_I2S2_SDP, | ||
2061 | RT5670_I2S_DL_MASK, val_len); | ||
2062 | snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk); | ||
2063 | break; | ||
2064 | default: | ||
2065 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2066 | return -EINVAL; | ||
2067 | } | ||
2068 | |||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2072 | static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
2073 | { | ||
2074 | struct snd_soc_codec *codec = dai->codec; | ||
2075 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2076 | unsigned int reg_val = 0; | ||
2077 | |||
2078 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
2079 | case SND_SOC_DAIFMT_CBM_CFM: | ||
2080 | rt5670->master[dai->id] = 1; | ||
2081 | break; | ||
2082 | case SND_SOC_DAIFMT_CBS_CFS: | ||
2083 | reg_val |= RT5670_I2S_MS_S; | ||
2084 | rt5670->master[dai->id] = 0; | ||
2085 | break; | ||
2086 | default: | ||
2087 | return -EINVAL; | ||
2088 | } | ||
2089 | |||
2090 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
2091 | case SND_SOC_DAIFMT_NB_NF: | ||
2092 | break; | ||
2093 | case SND_SOC_DAIFMT_IB_NF: | ||
2094 | reg_val |= RT5670_I2S_BP_INV; | ||
2095 | break; | ||
2096 | default: | ||
2097 | return -EINVAL; | ||
2098 | } | ||
2099 | |||
2100 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
2101 | case SND_SOC_DAIFMT_I2S: | ||
2102 | break; | ||
2103 | case SND_SOC_DAIFMT_LEFT_J: | ||
2104 | reg_val |= RT5670_I2S_DF_LEFT; | ||
2105 | break; | ||
2106 | case SND_SOC_DAIFMT_DSP_A: | ||
2107 | reg_val |= RT5670_I2S_DF_PCM_A; | ||
2108 | break; | ||
2109 | case SND_SOC_DAIFMT_DSP_B: | ||
2110 | reg_val |= RT5670_I2S_DF_PCM_B; | ||
2111 | break; | ||
2112 | default: | ||
2113 | return -EINVAL; | ||
2114 | } | ||
2115 | |||
2116 | switch (dai->id) { | ||
2117 | case RT5670_AIF1: | ||
2118 | snd_soc_update_bits(codec, RT5670_I2S1_SDP, | ||
2119 | RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK | | ||
2120 | RT5670_I2S_DF_MASK, reg_val); | ||
2121 | break; | ||
2122 | case RT5670_AIF2: | ||
2123 | snd_soc_update_bits(codec, RT5670_I2S2_SDP, | ||
2124 | RT5670_I2S_MS_MASK | RT5670_I2S_BP_MASK | | ||
2125 | RT5670_I2S_DF_MASK, reg_val); | ||
2126 | break; | ||
2127 | default: | ||
2128 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2129 | return -EINVAL; | ||
2130 | } | ||
2131 | return 0; | ||
2132 | } | ||
2133 | |||
2134 | static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | ||
2135 | int clk_id, unsigned int freq, int dir) | ||
2136 | { | ||
2137 | struct snd_soc_codec *codec = dai->codec; | ||
2138 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2139 | unsigned int reg_val = 0; | ||
2140 | |||
2141 | if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) | ||
2142 | return 0; | ||
2143 | |||
2144 | switch (clk_id) { | ||
2145 | case RT5670_SCLK_S_MCLK: | ||
2146 | reg_val |= RT5670_SCLK_SRC_MCLK; | ||
2147 | break; | ||
2148 | case RT5670_SCLK_S_PLL1: | ||
2149 | reg_val |= RT5670_SCLK_SRC_PLL1; | ||
2150 | break; | ||
2151 | case RT5670_SCLK_S_RCCLK: | ||
2152 | reg_val |= RT5670_SCLK_SRC_RCCLK; | ||
2153 | break; | ||
2154 | default: | ||
2155 | dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); | ||
2156 | return -EINVAL; | ||
2157 | } | ||
2158 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2159 | RT5670_SCLK_SRC_MASK, reg_val); | ||
2160 | rt5670->sysclk = freq; | ||
2161 | rt5670->sysclk_src = clk_id; | ||
2162 | |||
2163 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); | ||
2164 | |||
2165 | return 0; | ||
2166 | } | ||
2167 | |||
2168 | static int rt5670_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
2169 | unsigned int freq_in, unsigned int freq_out) | ||
2170 | { | ||
2171 | struct snd_soc_codec *codec = dai->codec; | ||
2172 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2173 | struct rl6231_pll_code pll_code; | ||
2174 | int ret; | ||
2175 | |||
2176 | if (source == rt5670->pll_src && freq_in == rt5670->pll_in && | ||
2177 | freq_out == rt5670->pll_out) | ||
2178 | return 0; | ||
2179 | |||
2180 | if (!freq_in || !freq_out) { | ||
2181 | dev_dbg(codec->dev, "PLL disabled\n"); | ||
2182 | |||
2183 | rt5670->pll_in = 0; | ||
2184 | rt5670->pll_out = 0; | ||
2185 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2186 | RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_MCLK); | ||
2187 | return 0; | ||
2188 | } | ||
2189 | |||
2190 | switch (source) { | ||
2191 | case RT5670_PLL1_S_MCLK: | ||
2192 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2193 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_MCLK); | ||
2194 | break; | ||
2195 | case RT5670_PLL1_S_BCLK1: | ||
2196 | case RT5670_PLL1_S_BCLK2: | ||
2197 | case RT5670_PLL1_S_BCLK3: | ||
2198 | case RT5670_PLL1_S_BCLK4: | ||
2199 | switch (dai->id) { | ||
2200 | case RT5670_AIF1: | ||
2201 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2202 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK1); | ||
2203 | break; | ||
2204 | case RT5670_AIF2: | ||
2205 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | ||
2206 | RT5670_PLL1_SRC_MASK, RT5670_PLL1_SRC_BCLK2); | ||
2207 | break; | ||
2208 | default: | ||
2209 | dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); | ||
2210 | return -EINVAL; | ||
2211 | } | ||
2212 | break; | ||
2213 | default: | ||
2214 | dev_err(codec->dev, "Unknown PLL source %d\n", source); | ||
2215 | return -EINVAL; | ||
2216 | } | ||
2217 | |||
2218 | ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); | ||
2219 | if (ret < 0) { | ||
2220 | dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); | ||
2221 | return ret; | ||
2222 | } | ||
2223 | |||
2224 | dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", | ||
2225 | pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), | ||
2226 | pll_code.n_code, pll_code.k_code); | ||
2227 | |||
2228 | snd_soc_write(codec, RT5670_PLL_CTRL1, | ||
2229 | pll_code.n_code << RT5670_PLL_N_SFT | pll_code.k_code); | ||
2230 | snd_soc_write(codec, RT5670_PLL_CTRL2, | ||
2231 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT | | ||
2232 | pll_code.m_bp << RT5670_PLL_M_BP_SFT); | ||
2233 | |||
2234 | rt5670->pll_in = freq_in; | ||
2235 | rt5670->pll_out = freq_out; | ||
2236 | rt5670->pll_src = source; | ||
2237 | |||
2238 | return 0; | ||
2239 | } | ||
2240 | |||
2241 | static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
2242 | unsigned int rx_mask, int slots, int slot_width) | ||
2243 | { | ||
2244 | struct snd_soc_codec *codec = dai->codec; | ||
2245 | unsigned int val = 0; | ||
2246 | |||
2247 | if (rx_mask || tx_mask) | ||
2248 | val |= (1 << 14); | ||
2249 | |||
2250 | switch (slots) { | ||
2251 | case 4: | ||
2252 | val |= (1 << 12); | ||
2253 | break; | ||
2254 | case 6: | ||
2255 | val |= (2 << 12); | ||
2256 | break; | ||
2257 | case 8: | ||
2258 | val |= (3 << 12); | ||
2259 | break; | ||
2260 | case 2: | ||
2261 | break; | ||
2262 | default: | ||
2263 | return -EINVAL; | ||
2264 | } | ||
2265 | |||
2266 | switch (slot_width) { | ||
2267 | case 20: | ||
2268 | val |= (1 << 10); | ||
2269 | break; | ||
2270 | case 24: | ||
2271 | val |= (2 << 10); | ||
2272 | break; | ||
2273 | case 32: | ||
2274 | val |= (3 << 10); | ||
2275 | break; | ||
2276 | case 16: | ||
2277 | break; | ||
2278 | default: | ||
2279 | return -EINVAL; | ||
2280 | } | ||
2281 | |||
2282 | snd_soc_update_bits(codec, RT5670_TDM_CTRL_1, 0x7c00, val); | ||
2283 | |||
2284 | return 0; | ||
2285 | } | ||
2286 | |||
2287 | static int rt5670_set_bias_level(struct snd_soc_codec *codec, | ||
2288 | enum snd_soc_bias_level level) | ||
2289 | { | ||
2290 | switch (level) { | ||
2291 | case SND_SOC_BIAS_PREPARE: | ||
2292 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | ||
2293 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2294 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2295 | RT5670_PWR_BG | RT5670_PWR_VREF2, | ||
2296 | RT5670_PWR_VREF1 | RT5670_PWR_MB | | ||
2297 | RT5670_PWR_BG | RT5670_PWR_VREF2); | ||
2298 | mdelay(10); | ||
2299 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2300 | RT5670_PWR_FV1 | RT5670_PWR_FV2, | ||
2301 | RT5670_PWR_FV1 | RT5670_PWR_FV2); | ||
2302 | snd_soc_update_bits(codec, RT5670_CHARGE_PUMP, | ||
2303 | RT5670_OSW_L_MASK | RT5670_OSW_R_MASK, | ||
2304 | RT5670_OSW_L_DIS | RT5670_OSW_R_DIS); | ||
2305 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1); | ||
2306 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2307 | RT5670_LDO_SEL_MASK, 0x3); | ||
2308 | } | ||
2309 | break; | ||
2310 | case SND_SOC_BIAS_STANDBY: | ||
2311 | snd_soc_write(codec, RT5670_PWR_DIG1, 0x0000); | ||
2312 | snd_soc_write(codec, RT5670_PWR_DIG2, 0x0001); | ||
2313 | snd_soc_write(codec, RT5670_PWR_VOL, 0x0000); | ||
2314 | snd_soc_write(codec, RT5670_PWR_MIXER, 0x0001); | ||
2315 | snd_soc_write(codec, RT5670_PWR_ANLG1, 0x2800); | ||
2316 | snd_soc_write(codec, RT5670_PWR_ANLG2, 0x0004); | ||
2317 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x0); | ||
2318 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | ||
2319 | RT5670_LDO_SEL_MASK, 0x1); | ||
2320 | break; | ||
2321 | |||
2322 | default: | ||
2323 | break; | ||
2324 | } | ||
2325 | codec->dapm.bias_level = level; | ||
2326 | |||
2327 | return 0; | ||
2328 | } | ||
2329 | |||
2330 | static int rt5670_probe(struct snd_soc_codec *codec) | ||
2331 | { | ||
2332 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2333 | |||
2334 | rt5670->codec = codec; | ||
2335 | |||
2336 | return 0; | ||
2337 | } | ||
2338 | |||
2339 | static int rt5670_remove(struct snd_soc_codec *codec) | ||
2340 | { | ||
2341 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2342 | |||
2343 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2344 | return 0; | ||
2345 | } | ||
2346 | |||
2347 | #ifdef CONFIG_PM | ||
2348 | static int rt5670_suspend(struct snd_soc_codec *codec) | ||
2349 | { | ||
2350 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2351 | |||
2352 | regcache_cache_only(rt5670->regmap, true); | ||
2353 | regcache_mark_dirty(rt5670->regmap); | ||
2354 | return 0; | ||
2355 | } | ||
2356 | |||
2357 | static int rt5670_resume(struct snd_soc_codec *codec) | ||
2358 | { | ||
2359 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
2360 | |||
2361 | regcache_cache_only(rt5670->regmap, false); | ||
2362 | regcache_sync(rt5670->regmap); | ||
2363 | |||
2364 | return 0; | ||
2365 | } | ||
2366 | #else | ||
2367 | #define rt5670_suspend NULL | ||
2368 | #define rt5670_resume NULL | ||
2369 | #endif | ||
2370 | |||
2371 | #define RT5670_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | ||
2372 | #define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
2373 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
2374 | |||
2375 | static struct snd_soc_dai_ops rt5670_aif_dai_ops = { | ||
2376 | .hw_params = rt5670_hw_params, | ||
2377 | .set_fmt = rt5670_set_dai_fmt, | ||
2378 | .set_sysclk = rt5670_set_dai_sysclk, | ||
2379 | .set_tdm_slot = rt5670_set_tdm_slot, | ||
2380 | .set_pll = rt5670_set_dai_pll, | ||
2381 | }; | ||
2382 | |||
2383 | static struct snd_soc_dai_driver rt5670_dai[] = { | ||
2384 | { | ||
2385 | .name = "rt5670-aif1", | ||
2386 | .id = RT5670_AIF1, | ||
2387 | .playback = { | ||
2388 | .stream_name = "AIF1 Playback", | ||
2389 | .channels_min = 1, | ||
2390 | .channels_max = 2, | ||
2391 | .rates = RT5670_STEREO_RATES, | ||
2392 | .formats = RT5670_FORMATS, | ||
2393 | }, | ||
2394 | .capture = { | ||
2395 | .stream_name = "AIF1 Capture", | ||
2396 | .channels_min = 1, | ||
2397 | .channels_max = 2, | ||
2398 | .rates = RT5670_STEREO_RATES, | ||
2399 | .formats = RT5670_FORMATS, | ||
2400 | }, | ||
2401 | .ops = &rt5670_aif_dai_ops, | ||
2402 | }, | ||
2403 | { | ||
2404 | .name = "rt5670-aif2", | ||
2405 | .id = RT5670_AIF2, | ||
2406 | .playback = { | ||
2407 | .stream_name = "AIF2 Playback", | ||
2408 | .channels_min = 1, | ||
2409 | .channels_max = 2, | ||
2410 | .rates = RT5670_STEREO_RATES, | ||
2411 | .formats = RT5670_FORMATS, | ||
2412 | }, | ||
2413 | .capture = { | ||
2414 | .stream_name = "AIF2 Capture", | ||
2415 | .channels_min = 1, | ||
2416 | .channels_max = 2, | ||
2417 | .rates = RT5670_STEREO_RATES, | ||
2418 | .formats = RT5670_FORMATS, | ||
2419 | }, | ||
2420 | .ops = &rt5670_aif_dai_ops, | ||
2421 | }, | ||
2422 | }; | ||
2423 | |||
2424 | static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { | ||
2425 | .probe = rt5670_probe, | ||
2426 | .remove = rt5670_remove, | ||
2427 | .suspend = rt5670_suspend, | ||
2428 | .resume = rt5670_resume, | ||
2429 | .set_bias_level = rt5670_set_bias_level, | ||
2430 | .idle_bias_off = true, | ||
2431 | .controls = rt5670_snd_controls, | ||
2432 | .num_controls = ARRAY_SIZE(rt5670_snd_controls), | ||
2433 | .dapm_widgets = rt5670_dapm_widgets, | ||
2434 | .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), | ||
2435 | .dapm_routes = rt5670_dapm_routes, | ||
2436 | .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), | ||
2437 | }; | ||
2438 | |||
2439 | static const struct regmap_config rt5670_regmap = { | ||
2440 | .reg_bits = 8, | ||
2441 | .val_bits = 16, | ||
2442 | .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * | ||
2443 | RT5670_PR_SPACING), | ||
2444 | .volatile_reg = rt5670_volatile_register, | ||
2445 | .readable_reg = rt5670_readable_register, | ||
2446 | .cache_type = REGCACHE_RBTREE, | ||
2447 | .reg_defaults = rt5670_reg, | ||
2448 | .num_reg_defaults = ARRAY_SIZE(rt5670_reg), | ||
2449 | .ranges = rt5670_ranges, | ||
2450 | .num_ranges = ARRAY_SIZE(rt5670_ranges), | ||
2451 | }; | ||
2452 | |||
2453 | static const struct i2c_device_id rt5670_i2c_id[] = { | ||
2454 | { "rt5670", 0 }, | ||
2455 | { } | ||
2456 | }; | ||
2457 | MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | ||
2458 | |||
2459 | static int rt5670_i2c_probe(struct i2c_client *i2c, | ||
2460 | const struct i2c_device_id *id) | ||
2461 | { | ||
2462 | struct rt5670_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
2463 | struct rt5670_priv *rt5670; | ||
2464 | int ret; | ||
2465 | unsigned int val; | ||
2466 | |||
2467 | rt5670 = devm_kzalloc(&i2c->dev, | ||
2468 | sizeof(struct rt5670_priv), | ||
2469 | GFP_KERNEL); | ||
2470 | if (NULL == rt5670) | ||
2471 | return -ENOMEM; | ||
2472 | |||
2473 | i2c_set_clientdata(i2c, rt5670); | ||
2474 | |||
2475 | if (pdata) | ||
2476 | rt5670->pdata = *pdata; | ||
2477 | |||
2478 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); | ||
2479 | if (IS_ERR(rt5670->regmap)) { | ||
2480 | ret = PTR_ERR(rt5670->regmap); | ||
2481 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
2482 | ret); | ||
2483 | return ret; | ||
2484 | } | ||
2485 | |||
2486 | regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val); | ||
2487 | if (val != RT5670_DEVICE_ID) { | ||
2488 | dev_err(&i2c->dev, | ||
2489 | "Device with ID register %x is not rt5670/72\n", val); | ||
2490 | return -ENODEV; | ||
2491 | } | ||
2492 | |||
2493 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2494 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
2495 | RT5670_PWR_HP_L | RT5670_PWR_HP_R | | ||
2496 | RT5670_PWR_VREF2, RT5670_PWR_VREF2); | ||
2497 | msleep(100); | ||
2498 | |||
2499 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | ||
2500 | |||
2501 | ret = regmap_register_patch(rt5670->regmap, init_list, | ||
2502 | ARRAY_SIZE(init_list)); | ||
2503 | if (ret != 0) | ||
2504 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | ||
2505 | |||
2506 | if (rt5670->pdata.in2_diff) | ||
2507 | regmap_update_bits(rt5670->regmap, RT5670_IN2, | ||
2508 | RT5670_IN_DF2, RT5670_IN_DF2); | ||
2509 | |||
2510 | if (i2c->irq) { | ||
2511 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2512 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); | ||
2513 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, | ||
2514 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); | ||
2515 | |||
2516 | } | ||
2517 | |||
2518 | if (rt5670->pdata.jd_mode) { | ||
2519 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | ||
2520 | RT5670_PWR_MB, RT5670_PWR_MB); | ||
2521 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2, | ||
2522 | RT5670_PWR_JD1, RT5670_PWR_JD1); | ||
2523 | regmap_update_bits(rt5670->regmap, RT5670_IRQ_CTRL1, | ||
2524 | RT5670_JD1_1_EN_MASK, RT5670_JD1_1_EN); | ||
2525 | regmap_update_bits(rt5670->regmap, RT5670_JD_CTRL3, | ||
2526 | RT5670_JD_TRI_CBJ_SEL_MASK | | ||
2527 | RT5670_JD_TRI_HPO_SEL_MASK, | ||
2528 | RT5670_JD_CBJ_JD1_1 | RT5670_JD_HPO_JD1_1); | ||
2529 | switch (rt5670->pdata.jd_mode) { | ||
2530 | case 1: | ||
2531 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2532 | RT5670_JD1_MODE_MASK, | ||
2533 | RT5670_JD1_MODE_0); | ||
2534 | break; | ||
2535 | case 2: | ||
2536 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2537 | RT5670_JD1_MODE_MASK, | ||
2538 | RT5670_JD1_MODE_1); | ||
2539 | break; | ||
2540 | case 3: | ||
2541 | regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, | ||
2542 | RT5670_JD1_MODE_MASK, | ||
2543 | RT5670_JD1_MODE_2); | ||
2544 | break; | ||
2545 | default: | ||
2546 | break; | ||
2547 | } | ||
2548 | } | ||
2549 | |||
2550 | if (rt5670->pdata.dmic_en) { | ||
2551 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2552 | RT5670_GP2_PIN_MASK, | ||
2553 | RT5670_GP2_PIN_DMIC1_SCL); | ||
2554 | |||
2555 | switch (rt5670->pdata.dmic1_data_pin) { | ||
2556 | case RT5670_DMIC_DATA_IN2P: | ||
2557 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2558 | RT5670_DMIC_1_DP_MASK, | ||
2559 | RT5670_DMIC_1_DP_IN2P); | ||
2560 | break; | ||
2561 | |||
2562 | case RT5670_DMIC_DATA_GPIO6: | ||
2563 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2564 | RT5670_DMIC_1_DP_MASK, | ||
2565 | RT5670_DMIC_1_DP_GPIO6); | ||
2566 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2567 | RT5670_GP6_PIN_MASK, | ||
2568 | RT5670_GP6_PIN_DMIC1_SDA); | ||
2569 | break; | ||
2570 | |||
2571 | case RT5670_DMIC_DATA_GPIO7: | ||
2572 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2573 | RT5670_DMIC_1_DP_MASK, | ||
2574 | RT5670_DMIC_1_DP_GPIO7); | ||
2575 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2576 | RT5670_GP7_PIN_MASK, | ||
2577 | RT5670_GP7_PIN_DMIC1_SDA); | ||
2578 | break; | ||
2579 | |||
2580 | default: | ||
2581 | break; | ||
2582 | } | ||
2583 | |||
2584 | switch (rt5670->pdata.dmic2_data_pin) { | ||
2585 | case RT5670_DMIC_DATA_IN3N: | ||
2586 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2587 | RT5670_DMIC_2_DP_MASK, | ||
2588 | RT5670_DMIC_2_DP_IN3N); | ||
2589 | break; | ||
2590 | |||
2591 | case RT5670_DMIC_DATA_GPIO8: | ||
2592 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, | ||
2593 | RT5670_DMIC_2_DP_MASK, | ||
2594 | RT5670_DMIC_2_DP_GPIO8); | ||
2595 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2596 | RT5670_GP8_PIN_MASK, | ||
2597 | RT5670_GP8_PIN_DMIC2_SDA); | ||
2598 | break; | ||
2599 | |||
2600 | default: | ||
2601 | break; | ||
2602 | } | ||
2603 | |||
2604 | switch (rt5670->pdata.dmic3_data_pin) { | ||
2605 | case RT5670_DMIC_DATA_GPIO5: | ||
2606 | regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL2, | ||
2607 | RT5670_DMIC_3_DP_MASK, | ||
2608 | RT5670_DMIC_3_DP_GPIO5); | ||
2609 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | ||
2610 | RT5670_GP5_PIN_MASK, | ||
2611 | RT5670_GP5_PIN_DMIC3_SDA); | ||
2612 | break; | ||
2613 | |||
2614 | case RT5670_DMIC_DATA_GPIO9: | ||
2615 | case RT5670_DMIC_DATA_GPIO10: | ||
2616 | dev_err(&i2c->dev, | ||
2617 | "Always use GPIO5 as DMIC3 data pin\n"); | ||
2618 | break; | ||
2619 | |||
2620 | default: | ||
2621 | break; | ||
2622 | } | ||
2623 | |||
2624 | } | ||
2625 | |||
2626 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670, | ||
2627 | rt5670_dai, ARRAY_SIZE(rt5670_dai)); | ||
2628 | if (ret < 0) | ||
2629 | goto err; | ||
2630 | |||
2631 | return 0; | ||
2632 | err: | ||
2633 | return ret; | ||
2634 | } | ||
2635 | |||
2636 | static int rt5670_i2c_remove(struct i2c_client *i2c) | ||
2637 | { | ||
2638 | snd_soc_unregister_codec(&i2c->dev); | ||
2639 | |||
2640 | return 0; | ||
2641 | } | ||
2642 | |||
2643 | static struct i2c_driver rt5670_i2c_driver = { | ||
2644 | .driver = { | ||
2645 | .name = "rt5670", | ||
2646 | .owner = THIS_MODULE, | ||
2647 | }, | ||
2648 | .probe = rt5670_i2c_probe, | ||
2649 | .remove = rt5670_i2c_remove, | ||
2650 | .id_table = rt5670_i2c_id, | ||
2651 | }; | ||
2652 | |||
2653 | module_i2c_driver(rt5670_i2c_driver); | ||
2654 | |||
2655 | MODULE_DESCRIPTION("ASoC RT5670 driver"); | ||
2656 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
2657 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h new file mode 100644 index 000000000000..a0b5c855b492 --- /dev/null +++ b/sound/soc/codecs/rt5670.h | |||
@@ -0,0 +1,2000 @@ | |||
1 | /* | ||
2 | * rt5670.h -- RT5670 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 Realtek Microelectronics | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT5670_H__ | ||
13 | #define __RT5670_H__ | ||
14 | |||
15 | #include <sound/rt5670.h> | ||
16 | |||
17 | /* Info */ | ||
18 | #define RT5670_RESET 0x00 | ||
19 | #define RT5670_VENDOR_ID 0xfd | ||
20 | #define RT5670_VENDOR_ID1 0xfe | ||
21 | #define RT5670_VENDOR_ID2 0xff | ||
22 | /* I/O - Output */ | ||
23 | #define RT5670_HP_VOL 0x02 | ||
24 | #define RT5670_LOUT1 0x03 | ||
25 | /* I/O - Input */ | ||
26 | #define RT5670_CJ_CTRL1 0x0a | ||
27 | #define RT5670_CJ_CTRL2 0x0b | ||
28 | #define RT5670_CJ_CTRL3 0x0c | ||
29 | #define RT5670_IN2 0x0e | ||
30 | #define RT5670_INL1_INR1_VOL 0x0f | ||
31 | /* I/O - ADC/DAC/DMIC */ | ||
32 | #define RT5670_DAC1_DIG_VOL 0x19 | ||
33 | #define RT5670_DAC2_DIG_VOL 0x1a | ||
34 | #define RT5670_DAC_CTRL 0x1b | ||
35 | #define RT5670_STO1_ADC_DIG_VOL 0x1c | ||
36 | #define RT5670_MONO_ADC_DIG_VOL 0x1d | ||
37 | #define RT5670_ADC_BST_VOL1 0x1e | ||
38 | #define RT5670_STO2_ADC_DIG_VOL 0x1f | ||
39 | /* Mixer - D-D */ | ||
40 | #define RT5670_ADC_BST_VOL2 0x20 | ||
41 | #define RT5670_STO2_ADC_MIXER 0x26 | ||
42 | #define RT5670_STO1_ADC_MIXER 0x27 | ||
43 | #define RT5670_MONO_ADC_MIXER 0x28 | ||
44 | #define RT5670_AD_DA_MIXER 0x29 | ||
45 | #define RT5670_STO_DAC_MIXER 0x2a | ||
46 | #define RT5670_DD_MIXER 0x2b | ||
47 | #define RT5670_DIG_MIXER 0x2c | ||
48 | #define RT5670_DSP_PATH1 0x2d | ||
49 | #define RT5670_DSP_PATH2 0x2e | ||
50 | #define RT5670_DIG_INF1_DATA 0x2f | ||
51 | #define RT5670_DIG_INF2_DATA 0x30 | ||
52 | /* Mixer - PDM */ | ||
53 | #define RT5670_PDM_OUT_CTRL 0x31 | ||
54 | #define RT5670_PDM_DATA_CTRL1 0x32 | ||
55 | #define RT5670_PDM1_DATA_CTRL2 0x33 | ||
56 | #define RT5670_PDM1_DATA_CTRL3 0x34 | ||
57 | #define RT5670_PDM1_DATA_CTRL4 0x35 | ||
58 | #define RT5670_PDM2_DATA_CTRL2 0x36 | ||
59 | #define RT5670_PDM2_DATA_CTRL3 0x37 | ||
60 | #define RT5670_PDM2_DATA_CTRL4 0x38 | ||
61 | /* Mixer - ADC */ | ||
62 | #define RT5670_REC_L1_MIXER 0x3b | ||
63 | #define RT5670_REC_L2_MIXER 0x3c | ||
64 | #define RT5670_REC_R1_MIXER 0x3d | ||
65 | #define RT5670_REC_R2_MIXER 0x3e | ||
66 | /* Mixer - DAC */ | ||
67 | #define RT5670_HPO_MIXER 0x45 | ||
68 | #define RT5670_MONO_MIXER 0x4c | ||
69 | #define RT5670_OUT_L1_MIXER 0x4f | ||
70 | #define RT5670_OUT_R1_MIXER 0x52 | ||
71 | #define RT5670_LOUT_MIXER 0x53 | ||
72 | /* Power */ | ||
73 | #define RT5670_PWR_DIG1 0x61 | ||
74 | #define RT5670_PWR_DIG2 0x62 | ||
75 | #define RT5670_PWR_ANLG1 0x63 | ||
76 | #define RT5670_PWR_ANLG2 0x64 | ||
77 | #define RT5670_PWR_MIXER 0x65 | ||
78 | #define RT5670_PWR_VOL 0x66 | ||
79 | /* Private Register Control */ | ||
80 | #define RT5670_PRIV_INDEX 0x6a | ||
81 | #define RT5670_PRIV_DATA 0x6c | ||
82 | /* Format - ADC/DAC */ | ||
83 | #define RT5670_I2S4_SDP 0x6f | ||
84 | #define RT5670_I2S1_SDP 0x70 | ||
85 | #define RT5670_I2S2_SDP 0x71 | ||
86 | #define RT5670_I2S3_SDP 0x72 | ||
87 | #define RT5670_ADDA_CLK1 0x73 | ||
88 | #define RT5670_ADDA_CLK2 0x74 | ||
89 | #define RT5670_DMIC_CTRL1 0x75 | ||
90 | #define RT5670_DMIC_CTRL2 0x76 | ||
91 | /* Format - TDM Control */ | ||
92 | #define RT5670_TDM_CTRL_1 0x77 | ||
93 | #define RT5670_TDM_CTRL_2 0x78 | ||
94 | #define RT5670_TDM_CTRL_3 0x79 | ||
95 | |||
96 | /* Function - Analog */ | ||
97 | #define RT5670_DSP_CLK 0x7f | ||
98 | #define RT5670_GLB_CLK 0x80 | ||
99 | #define RT5670_PLL_CTRL1 0x81 | ||
100 | #define RT5670_PLL_CTRL2 0x82 | ||
101 | #define RT5670_ASRC_1 0x83 | ||
102 | #define RT5670_ASRC_2 0x84 | ||
103 | #define RT5670_ASRC_3 0x85 | ||
104 | #define RT5670_ASRC_4 0x86 | ||
105 | #define RT5670_ASRC_5 0x87 | ||
106 | #define RT5670_ASRC_7 0x89 | ||
107 | #define RT5670_ASRC_8 0x8a | ||
108 | #define RT5670_ASRC_9 0x8b | ||
109 | #define RT5670_ASRC_10 0x8c | ||
110 | #define RT5670_ASRC_11 0x8d | ||
111 | #define RT5670_DEPOP_M1 0x8e | ||
112 | #define RT5670_DEPOP_M2 0x8f | ||
113 | #define RT5670_DEPOP_M3 0x90 | ||
114 | #define RT5670_CHARGE_PUMP 0x91 | ||
115 | #define RT5670_MICBIAS 0x93 | ||
116 | #define RT5670_A_JD_CTRL1 0x94 | ||
117 | #define RT5670_A_JD_CTRL2 0x95 | ||
118 | #define RT5670_ASRC_12 0x97 | ||
119 | #define RT5670_ASRC_13 0x98 | ||
120 | #define RT5670_ASRC_14 0x99 | ||
121 | #define RT5670_VAD_CTRL1 0x9a | ||
122 | #define RT5670_VAD_CTRL2 0x9b | ||
123 | #define RT5670_VAD_CTRL3 0x9c | ||
124 | #define RT5670_VAD_CTRL4 0x9d | ||
125 | #define RT5670_VAD_CTRL5 0x9e | ||
126 | /* Function - Digital */ | ||
127 | #define RT5670_ADC_EQ_CTRL1 0xae | ||
128 | #define RT5670_ADC_EQ_CTRL2 0xaf | ||
129 | #define RT5670_EQ_CTRL1 0xb0 | ||
130 | #define RT5670_EQ_CTRL2 0xb1 | ||
131 | #define RT5670_ALC_DRC_CTRL1 0xb2 | ||
132 | #define RT5670_ALC_DRC_CTRL2 0xb3 | ||
133 | #define RT5670_ALC_CTRL_1 0xb4 | ||
134 | #define RT5670_ALC_CTRL_2 0xb5 | ||
135 | #define RT5670_ALC_CTRL_3 0xb6 | ||
136 | #define RT5670_ALC_CTRL_4 0xb7 | ||
137 | #define RT5670_JD_CTRL 0xbb | ||
138 | #define RT5670_IRQ_CTRL1 0xbd | ||
139 | #define RT5670_IRQ_CTRL2 0xbe | ||
140 | #define RT5670_INT_IRQ_ST 0xbf | ||
141 | #define RT5670_GPIO_CTRL1 0xc0 | ||
142 | #define RT5670_GPIO_CTRL2 0xc1 | ||
143 | #define RT5670_GPIO_CTRL3 0xc2 | ||
144 | #define RT5670_SCRABBLE_FUN 0xcd | ||
145 | #define RT5670_SCRABBLE_CTRL 0xce | ||
146 | #define RT5670_BASE_BACK 0xcf | ||
147 | #define RT5670_MP3_PLUS1 0xd0 | ||
148 | #define RT5670_MP3_PLUS2 0xd1 | ||
149 | #define RT5670_ADJ_HPF1 0xd3 | ||
150 | #define RT5670_ADJ_HPF2 0xd4 | ||
151 | #define RT5670_HP_CALIB_AMP_DET 0xd6 | ||
152 | #define RT5670_SV_ZCD1 0xd9 | ||
153 | #define RT5670_SV_ZCD2 0xda | ||
154 | #define RT5670_IL_CMD 0xdb | ||
155 | #define RT5670_IL_CMD2 0xdc | ||
156 | #define RT5670_IL_CMD3 0xdd | ||
157 | #define RT5670_DRC_HL_CTRL1 0xe6 | ||
158 | #define RT5670_DRC_HL_CTRL2 0xe7 | ||
159 | #define RT5670_ADC_MONO_HP_CTRL1 0xec | ||
160 | #define RT5670_ADC_MONO_HP_CTRL2 0xed | ||
161 | #define RT5670_ADC_STO2_HP_CTRL1 0xee | ||
162 | #define RT5670_ADC_STO2_HP_CTRL2 0xef | ||
163 | #define RT5670_JD_CTRL3 0xf8 | ||
164 | #define RT5670_JD_CTRL4 0xf9 | ||
165 | /* General Control */ | ||
166 | #define RT5670_DIG_MISC 0xfa | ||
167 | #define RT5670_GEN_CTRL2 0xfb | ||
168 | #define RT5670_GEN_CTRL3 0xfc | ||
169 | |||
170 | |||
171 | /* Index of Codec Private Register definition */ | ||
172 | #define RT5670_DIG_VOL 0x00 | ||
173 | #define RT5670_PR_ALC_CTRL_1 0x01 | ||
174 | #define RT5670_PR_ALC_CTRL_2 0x02 | ||
175 | #define RT5670_PR_ALC_CTRL_3 0x03 | ||
176 | #define RT5670_PR_ALC_CTRL_4 0x04 | ||
177 | #define RT5670_PR_ALC_CTRL_5 0x05 | ||
178 | #define RT5670_PR_ALC_CTRL_6 0x06 | ||
179 | #define RT5670_BIAS_CUR1 0x12 | ||
180 | #define RT5670_BIAS_CUR3 0x14 | ||
181 | #define RT5670_CLSD_INT_REG1 0x1c | ||
182 | #define RT5670_MAMP_INT_REG2 0x37 | ||
183 | #define RT5670_CHOP_DAC_ADC 0x3d | ||
184 | #define RT5670_MIXER_INT_REG 0x3f | ||
185 | #define RT5670_3D_SPK 0x63 | ||
186 | #define RT5670_WND_1 0x6c | ||
187 | #define RT5670_WND_2 0x6d | ||
188 | #define RT5670_WND_3 0x6e | ||
189 | #define RT5670_WND_4 0x6f | ||
190 | #define RT5670_WND_5 0x70 | ||
191 | #define RT5670_WND_8 0x73 | ||
192 | #define RT5670_DIP_SPK_INF 0x75 | ||
193 | #define RT5670_HP_DCC_INT1 0x77 | ||
194 | #define RT5670_EQ_BW_LOP 0xa0 | ||
195 | #define RT5670_EQ_GN_LOP 0xa1 | ||
196 | #define RT5670_EQ_FC_BP1 0xa2 | ||
197 | #define RT5670_EQ_BW_BP1 0xa3 | ||
198 | #define RT5670_EQ_GN_BP1 0xa4 | ||
199 | #define RT5670_EQ_FC_BP2 0xa5 | ||
200 | #define RT5670_EQ_BW_BP2 0xa6 | ||
201 | #define RT5670_EQ_GN_BP2 0xa7 | ||
202 | #define RT5670_EQ_FC_BP3 0xa8 | ||
203 | #define RT5670_EQ_BW_BP3 0xa9 | ||
204 | #define RT5670_EQ_GN_BP3 0xaa | ||
205 | #define RT5670_EQ_FC_BP4 0xab | ||
206 | #define RT5670_EQ_BW_BP4 0xac | ||
207 | #define RT5670_EQ_GN_BP4 0xad | ||
208 | #define RT5670_EQ_FC_HIP1 0xae | ||
209 | #define RT5670_EQ_GN_HIP1 0xaf | ||
210 | #define RT5670_EQ_FC_HIP2 0xb0 | ||
211 | #define RT5670_EQ_BW_HIP2 0xb1 | ||
212 | #define RT5670_EQ_GN_HIP2 0xb2 | ||
213 | #define RT5670_EQ_PRE_VOL 0xb3 | ||
214 | #define RT5670_EQ_PST_VOL 0xb4 | ||
215 | |||
216 | |||
217 | /* global definition */ | ||
218 | #define RT5670_L_MUTE (0x1 << 15) | ||
219 | #define RT5670_L_MUTE_SFT 15 | ||
220 | #define RT5670_VOL_L_MUTE (0x1 << 14) | ||
221 | #define RT5670_VOL_L_SFT 14 | ||
222 | #define RT5670_R_MUTE (0x1 << 7) | ||
223 | #define RT5670_R_MUTE_SFT 7 | ||
224 | #define RT5670_VOL_R_MUTE (0x1 << 6) | ||
225 | #define RT5670_VOL_R_SFT 6 | ||
226 | #define RT5670_L_VOL_MASK (0x3f << 8) | ||
227 | #define RT5670_L_VOL_SFT 8 | ||
228 | #define RT5670_R_VOL_MASK (0x3f) | ||
229 | #define RT5670_R_VOL_SFT 0 | ||
230 | |||
231 | /* Combo Jack Control 1 (0x0a) */ | ||
232 | #define RT5670_CBJ_BST1_MASK (0xf << 12) | ||
233 | #define RT5670_CBJ_BST1_SFT (12) | ||
234 | #define RT5670_CBJ_JD_HP_EN (0x1 << 9) | ||
235 | #define RT5670_CBJ_JD_MIC_EN (0x1 << 8) | ||
236 | #define RT5670_CBJ_BST1_EN (0x1 << 2) | ||
237 | |||
238 | /* Combo Jack Control 1 (0x0b) */ | ||
239 | #define RT5670_CBJ_MN_JD (0x1 << 12) | ||
240 | #define RT5670_CAPLESS_EN (0x1 << 11) | ||
241 | #define RT5670_CBJ_DET_MODE (0x1 << 7) | ||
242 | |||
243 | /* IN2 Control (0x0e) */ | ||
244 | #define RT5670_BST_MASK1 (0xf<<12) | ||
245 | #define RT5670_BST_SFT1 12 | ||
246 | #define RT5670_BST_MASK2 (0xf<<8) | ||
247 | #define RT5670_BST_SFT2 8 | ||
248 | #define RT5670_IN_DF1 (0x1 << 7) | ||
249 | #define RT5670_IN_SFT1 7 | ||
250 | #define RT5670_IN_DF2 (0x1 << 6) | ||
251 | #define RT5670_IN_SFT2 6 | ||
252 | |||
253 | /* INL and INR Volume Control (0x0f) */ | ||
254 | #define RT5670_INL_SEL_MASK (0x1 << 15) | ||
255 | #define RT5670_INL_SEL_SFT 15 | ||
256 | #define RT5670_INL_SEL_IN4P (0x0 << 15) | ||
257 | #define RT5670_INL_SEL_MONOP (0x1 << 15) | ||
258 | #define RT5670_INL_VOL_MASK (0x1f << 8) | ||
259 | #define RT5670_INL_VOL_SFT 8 | ||
260 | #define RT5670_INR_SEL_MASK (0x1 << 7) | ||
261 | #define RT5670_INR_SEL_SFT 7 | ||
262 | #define RT5670_INR_SEL_IN4N (0x0 << 7) | ||
263 | #define RT5670_INR_SEL_MONON (0x1 << 7) | ||
264 | #define RT5670_INR_VOL_MASK (0x1f) | ||
265 | #define RT5670_INR_VOL_SFT 0 | ||
266 | |||
267 | /* Sidetone Control (0x18) */ | ||
268 | #define RT5670_ST_SEL_MASK (0x7 << 9) | ||
269 | #define RT5670_ST_SEL_SFT 9 | ||
270 | #define RT5670_M_ST_DACR2 (0x1 << 8) | ||
271 | #define RT5670_M_ST_DACR2_SFT 8 | ||
272 | #define RT5670_M_ST_DACL2 (0x1 << 7) | ||
273 | #define RT5670_M_ST_DACL2_SFT 7 | ||
274 | #define RT5670_ST_EN (0x1 << 6) | ||
275 | #define RT5670_ST_EN_SFT 6 | ||
276 | |||
277 | /* DAC1 Digital Volume (0x19) */ | ||
278 | #define RT5670_DAC_L1_VOL_MASK (0xff << 8) | ||
279 | #define RT5670_DAC_L1_VOL_SFT 8 | ||
280 | #define RT5670_DAC_R1_VOL_MASK (0xff) | ||
281 | #define RT5670_DAC_R1_VOL_SFT 0 | ||
282 | |||
283 | /* DAC2 Digital Volume (0x1a) */ | ||
284 | #define RT5670_DAC_L2_VOL_MASK (0xff << 8) | ||
285 | #define RT5670_DAC_L2_VOL_SFT 8 | ||
286 | #define RT5670_DAC_R2_VOL_MASK (0xff) | ||
287 | #define RT5670_DAC_R2_VOL_SFT 0 | ||
288 | |||
289 | /* DAC2 Control (0x1b) */ | ||
290 | #define RT5670_M_DAC_L2_VOL (0x1 << 13) | ||
291 | #define RT5670_M_DAC_L2_VOL_SFT 13 | ||
292 | #define RT5670_M_DAC_R2_VOL (0x1 << 12) | ||
293 | #define RT5670_M_DAC_R2_VOL_SFT 12 | ||
294 | #define RT5670_DAC2_L_SEL_MASK (0x7 << 4) | ||
295 | #define RT5670_DAC2_L_SEL_SFT 4 | ||
296 | #define RT5670_DAC2_R_SEL_MASK (0x7 << 0) | ||
297 | #define RT5670_DAC2_R_SEL_SFT 0 | ||
298 | |||
299 | /* ADC Digital Volume Control (0x1c) */ | ||
300 | #define RT5670_ADC_L_VOL_MASK (0x7f << 8) | ||
301 | #define RT5670_ADC_L_VOL_SFT 8 | ||
302 | #define RT5670_ADC_R_VOL_MASK (0x7f) | ||
303 | #define RT5670_ADC_R_VOL_SFT 0 | ||
304 | |||
305 | /* Mono ADC Digital Volume Control (0x1d) */ | ||
306 | #define RT5670_MONO_ADC_L_VOL_MASK (0x7f << 8) | ||
307 | #define RT5670_MONO_ADC_L_VOL_SFT 8 | ||
308 | #define RT5670_MONO_ADC_R_VOL_MASK (0x7f) | ||
309 | #define RT5670_MONO_ADC_R_VOL_SFT 0 | ||
310 | |||
311 | /* ADC Boost Volume Control (0x1e) */ | ||
312 | #define RT5670_STO1_ADC_L_BST_MASK (0x3 << 14) | ||
313 | #define RT5670_STO1_ADC_L_BST_SFT 14 | ||
314 | #define RT5670_STO1_ADC_R_BST_MASK (0x3 << 12) | ||
315 | #define RT5670_STO1_ADC_R_BST_SFT 12 | ||
316 | #define RT5670_STO1_ADC_COMP_MASK (0x3 << 10) | ||
317 | #define RT5670_STO1_ADC_COMP_SFT 10 | ||
318 | #define RT5670_STO2_ADC_L_BST_MASK (0x3 << 8) | ||
319 | #define RT5670_STO2_ADC_L_BST_SFT 8 | ||
320 | #define RT5670_STO2_ADC_R_BST_MASK (0x3 << 6) | ||
321 | #define RT5670_STO2_ADC_R_BST_SFT 6 | ||
322 | #define RT5670_STO2_ADC_COMP_MASK (0x3 << 4) | ||
323 | #define RT5670_STO2_ADC_COMP_SFT 4 | ||
324 | |||
325 | /* Stereo2 ADC Mixer Control (0x26) */ | ||
326 | #define RT5670_STO2_ADC_SRC_MASK (0x1 << 15) | ||
327 | #define RT5670_STO2_ADC_SRC_SFT 15 | ||
328 | |||
329 | /* Stereo ADC Mixer Control (0x26 0x27) */ | ||
330 | #define RT5670_M_ADC_L1 (0x1 << 14) | ||
331 | #define RT5670_M_ADC_L1_SFT 14 | ||
332 | #define RT5670_M_ADC_L2 (0x1 << 13) | ||
333 | #define RT5670_M_ADC_L2_SFT 13 | ||
334 | #define RT5670_ADC_1_SRC_MASK (0x1 << 12) | ||
335 | #define RT5670_ADC_1_SRC_SFT 12 | ||
336 | #define RT5670_ADC_1_SRC_ADC (0x1 << 12) | ||
337 | #define RT5670_ADC_1_SRC_DACMIX (0x0 << 12) | ||
338 | #define RT5670_ADC_2_SRC_MASK (0x1 << 11) | ||
339 | #define RT5670_ADC_2_SRC_SFT 11 | ||
340 | #define RT5670_ADC_SRC_MASK (0x1 << 10) | ||
341 | #define RT5670_ADC_SRC_SFT 10 | ||
342 | #define RT5670_DMIC_SRC_MASK (0x3 << 8) | ||
343 | #define RT5670_DMIC_SRC_SFT 8 | ||
344 | #define RT5670_M_ADC_R1 (0x1 << 6) | ||
345 | #define RT5670_M_ADC_R1_SFT 6 | ||
346 | #define RT5670_M_ADC_R2 (0x1 << 5) | ||
347 | #define RT5670_M_ADC_R2_SFT 5 | ||
348 | #define RT5670_DMIC3_SRC_MASK (0x1 << 1) | ||
349 | #define RT5670_DMIC3_SRC_SFT 0 | ||
350 | |||
351 | /* Mono ADC Mixer Control (0x28) */ | ||
352 | #define RT5670_M_MONO_ADC_L1 (0x1 << 14) | ||
353 | #define RT5670_M_MONO_ADC_L1_SFT 14 | ||
354 | #define RT5670_M_MONO_ADC_L2 (0x1 << 13) | ||
355 | #define RT5670_M_MONO_ADC_L2_SFT 13 | ||
356 | #define RT5670_MONO_ADC_L1_SRC_MASK (0x1 << 12) | ||
357 | #define RT5670_MONO_ADC_L1_SRC_SFT 12 | ||
358 | #define RT5670_MONO_ADC_L1_SRC_DACMIXL (0x0 << 12) | ||
359 | #define RT5670_MONO_ADC_L1_SRC_ADCL (0x1 << 12) | ||
360 | #define RT5670_MONO_ADC_L2_SRC_MASK (0x1 << 11) | ||
361 | #define RT5670_MONO_ADC_L2_SRC_SFT 11 | ||
362 | #define RT5670_MONO_ADC_L_SRC_MASK (0x1 << 10) | ||
363 | #define RT5670_MONO_ADC_L_SRC_SFT 10 | ||
364 | #define RT5670_MONO_DMIC_L_SRC_MASK (0x3 << 8) | ||
365 | #define RT5670_MONO_DMIC_L_SRC_SFT 8 | ||
366 | #define RT5670_M_MONO_ADC_R1 (0x1 << 6) | ||
367 | #define RT5670_M_MONO_ADC_R1_SFT 6 | ||
368 | #define RT5670_M_MONO_ADC_R2 (0x1 << 5) | ||
369 | #define RT5670_M_MONO_ADC_R2_SFT 5 | ||
370 | #define RT5670_MONO_ADC_R1_SRC_MASK (0x1 << 4) | ||
371 | #define RT5670_MONO_ADC_R1_SRC_SFT 4 | ||
372 | #define RT5670_MONO_ADC_R1_SRC_ADCR (0x1 << 4) | ||
373 | #define RT5670_MONO_ADC_R1_SRC_DACMIXR (0x0 << 4) | ||
374 | #define RT5670_MONO_ADC_R2_SRC_MASK (0x1 << 3) | ||
375 | #define RT5670_MONO_ADC_R2_SRC_SFT 3 | ||
376 | #define RT5670_MONO_DMIC_R_SRC_MASK (0x3) | ||
377 | #define RT5670_MONO_DMIC_R_SRC_SFT 0 | ||
378 | |||
379 | /* ADC Mixer to DAC Mixer Control (0x29) */ | ||
380 | #define RT5670_M_ADCMIX_L (0x1 << 15) | ||
381 | #define RT5670_M_ADCMIX_L_SFT 15 | ||
382 | #define RT5670_M_DAC1_L (0x1 << 14) | ||
383 | #define RT5670_M_DAC1_L_SFT 14 | ||
384 | #define RT5670_DAC1_R_SEL_MASK (0x3 << 10) | ||
385 | #define RT5670_DAC1_R_SEL_SFT 10 | ||
386 | #define RT5670_DAC1_R_SEL_IF1 (0x0 << 10) | ||
387 | #define RT5670_DAC1_R_SEL_IF2 (0x1 << 10) | ||
388 | #define RT5670_DAC1_R_SEL_IF3 (0x2 << 10) | ||
389 | #define RT5670_DAC1_R_SEL_IF4 (0x3 << 10) | ||
390 | #define RT5670_DAC1_L_SEL_MASK (0x3 << 8) | ||
391 | #define RT5670_DAC1_L_SEL_SFT 8 | ||
392 | #define RT5670_DAC1_L_SEL_IF1 (0x0 << 8) | ||
393 | #define RT5670_DAC1_L_SEL_IF2 (0x1 << 8) | ||
394 | #define RT5670_DAC1_L_SEL_IF3 (0x2 << 8) | ||
395 | #define RT5670_DAC1_L_SEL_IF4 (0x3 << 8) | ||
396 | #define RT5670_M_ADCMIX_R (0x1 << 7) | ||
397 | #define RT5670_M_ADCMIX_R_SFT 7 | ||
398 | #define RT5670_M_DAC1_R (0x1 << 6) | ||
399 | #define RT5670_M_DAC1_R_SFT 6 | ||
400 | |||
401 | /* Stereo DAC Mixer Control (0x2a) */ | ||
402 | #define RT5670_M_DAC_L1 (0x1 << 14) | ||
403 | #define RT5670_M_DAC_L1_SFT 14 | ||
404 | #define RT5670_DAC_L1_STO_L_VOL_MASK (0x1 << 13) | ||
405 | #define RT5670_DAC_L1_STO_L_VOL_SFT 13 | ||
406 | #define RT5670_M_DAC_L2 (0x1 << 12) | ||
407 | #define RT5670_M_DAC_L2_SFT 12 | ||
408 | #define RT5670_DAC_L2_STO_L_VOL_MASK (0x1 << 11) | ||
409 | #define RT5670_DAC_L2_STO_L_VOL_SFT 11 | ||
410 | #define RT5670_M_DAC_R1_STO_L (0x1 << 9) | ||
411 | #define RT5670_M_DAC_R1_STO_L_SFT 9 | ||
412 | #define RT5670_DAC_R1_STO_L_VOL_MASK (0x1 << 8) | ||
413 | #define RT5670_DAC_R1_STO_L_VOL_SFT 8 | ||
414 | #define RT5670_M_DAC_R1 (0x1 << 6) | ||
415 | #define RT5670_M_DAC_R1_SFT 6 | ||
416 | #define RT5670_DAC_R1_STO_R_VOL_MASK (0x1 << 5) | ||
417 | #define RT5670_DAC_R1_STO_R_VOL_SFT 5 | ||
418 | #define RT5670_M_DAC_R2 (0x1 << 4) | ||
419 | #define RT5670_M_DAC_R2_SFT 4 | ||
420 | #define RT5670_DAC_R2_STO_R_VOL_MASK (0x1 << 3) | ||
421 | #define RT5670_DAC_R2_STO_R_VOL_SFT 3 | ||
422 | #define RT5670_M_DAC_L1_STO_R (0x1 << 1) | ||
423 | #define RT5670_M_DAC_L1_STO_R_SFT 1 | ||
424 | #define RT5670_DAC_L1_STO_R_VOL_MASK (0x1) | ||
425 | #define RT5670_DAC_L1_STO_R_VOL_SFT 0 | ||
426 | |||
427 | /* Mono DAC Mixer Control (0x2b) */ | ||
428 | #define RT5670_M_DAC_L1_MONO_L (0x1 << 14) | ||
429 | #define RT5670_M_DAC_L1_MONO_L_SFT 14 | ||
430 | #define RT5670_DAC_L1_MONO_L_VOL_MASK (0x1 << 13) | ||
431 | #define RT5670_DAC_L1_MONO_L_VOL_SFT 13 | ||
432 | #define RT5670_M_DAC_L2_MONO_L (0x1 << 12) | ||
433 | #define RT5670_M_DAC_L2_MONO_L_SFT 12 | ||
434 | #define RT5670_DAC_L2_MONO_L_VOL_MASK (0x1 << 11) | ||
435 | #define RT5670_DAC_L2_MONO_L_VOL_SFT 11 | ||
436 | #define RT5670_M_DAC_R2_MONO_L (0x1 << 10) | ||
437 | #define RT5670_M_DAC_R2_MONO_L_SFT 10 | ||
438 | #define RT5670_DAC_R2_MONO_L_VOL_MASK (0x1 << 9) | ||
439 | #define RT5670_DAC_R2_MONO_L_VOL_SFT 9 | ||
440 | #define RT5670_M_DAC_R1_MONO_R (0x1 << 6) | ||
441 | #define RT5670_M_DAC_R1_MONO_R_SFT 6 | ||
442 | #define RT5670_DAC_R1_MONO_R_VOL_MASK (0x1 << 5) | ||
443 | #define RT5670_DAC_R1_MONO_R_VOL_SFT 5 | ||
444 | #define RT5670_M_DAC_R2_MONO_R (0x1 << 4) | ||
445 | #define RT5670_M_DAC_R2_MONO_R_SFT 4 | ||
446 | #define RT5670_DAC_R2_MONO_R_VOL_MASK (0x1 << 3) | ||
447 | #define RT5670_DAC_R2_MONO_R_VOL_SFT 3 | ||
448 | #define RT5670_M_DAC_L2_MONO_R (0x1 << 2) | ||
449 | #define RT5670_M_DAC_L2_MONO_R_SFT 2 | ||
450 | #define RT5670_DAC_L2_MONO_R_VOL_MASK (0x1 << 1) | ||
451 | #define RT5670_DAC_L2_MONO_R_VOL_SFT 1 | ||
452 | |||
453 | /* Digital Mixer Control (0x2c) */ | ||
454 | #define RT5670_M_STO_L_DAC_L (0x1 << 15) | ||
455 | #define RT5670_M_STO_L_DAC_L_SFT 15 | ||
456 | #define RT5670_STO_L_DAC_L_VOL_MASK (0x1 << 14) | ||
457 | #define RT5670_STO_L_DAC_L_VOL_SFT 14 | ||
458 | #define RT5670_M_DAC_L2_DAC_L (0x1 << 13) | ||
459 | #define RT5670_M_DAC_L2_DAC_L_SFT 13 | ||
460 | #define RT5670_DAC_L2_DAC_L_VOL_MASK (0x1 << 12) | ||
461 | #define RT5670_DAC_L2_DAC_L_VOL_SFT 12 | ||
462 | #define RT5670_M_STO_R_DAC_R (0x1 << 11) | ||
463 | #define RT5670_M_STO_R_DAC_R_SFT 11 | ||
464 | #define RT5670_STO_R_DAC_R_VOL_MASK (0x1 << 10) | ||
465 | #define RT5670_STO_R_DAC_R_VOL_SFT 10 | ||
466 | #define RT5670_M_DAC_R2_DAC_R (0x1 << 9) | ||
467 | #define RT5670_M_DAC_R2_DAC_R_SFT 9 | ||
468 | #define RT5670_DAC_R2_DAC_R_VOL_MASK (0x1 << 8) | ||
469 | #define RT5670_DAC_R2_DAC_R_VOL_SFT 8 | ||
470 | #define RT5670_M_DAC_R2_DAC_L (0x1 << 7) | ||
471 | #define RT5670_M_DAC_R2_DAC_L_SFT 7 | ||
472 | #define RT5670_DAC_R2_DAC_L_VOL_MASK (0x1 << 6) | ||
473 | #define RT5670_DAC_R2_DAC_L_VOL_SFT 6 | ||
474 | #define RT5670_M_DAC_L2_DAC_R (0x1 << 5) | ||
475 | #define RT5670_M_DAC_L2_DAC_R_SFT 5 | ||
476 | #define RT5670_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) | ||
477 | #define RT5670_DAC_L2_DAC_R_VOL_SFT 4 | ||
478 | |||
479 | /* DSP Path Control 1 (0x2d) */ | ||
480 | #define RT5670_RXDP_SEL_MASK (0x7 << 13) | ||
481 | #define RT5670_RXDP_SEL_SFT 13 | ||
482 | #define RT5670_RXDP_SRC_MASK (0x3 << 11) | ||
483 | #define RT5670_RXDP_SRC_SFT 11 | ||
484 | #define RT5670_RXDP_SRC_NOR (0x0 << 11) | ||
485 | #define RT5670_RXDP_SRC_DIV2 (0x1 << 11) | ||
486 | #define RT5670_RXDP_SRC_DIV3 (0x2 << 11) | ||
487 | #define RT5670_TXDP_SRC_MASK (0x3 << 4) | ||
488 | #define RT5670_TXDP_SRC_SFT 4 | ||
489 | #define RT5670_TXDP_SRC_NOR (0x0 << 4) | ||
490 | #define RT5670_TXDP_SRC_DIV2 (0x1 << 4) | ||
491 | #define RT5670_TXDP_SRC_DIV3 (0x2 << 4) | ||
492 | #define RT5670_TXDP_SLOT_SEL_MASK (0x3 << 2) | ||
493 | #define RT5670_TXDP_SLOT_SEL_SFT 2 | ||
494 | #define RT5670_DSP_UL_SEL (0x1 << 1) | ||
495 | #define RT5670_DSP_UL_SFT 1 | ||
496 | #define RT5670_DSP_DL_SEL 0x1 | ||
497 | #define RT5670_DSP_DL_SFT 0 | ||
498 | |||
499 | /* DSP Path Control 2 (0x2e) */ | ||
500 | #define RT5670_TXDP_L_VOL_MASK (0x7f << 8) | ||
501 | #define RT5670_TXDP_L_VOL_SFT 8 | ||
502 | #define RT5670_TXDP_R_VOL_MASK (0x7f) | ||
503 | #define RT5670_TXDP_R_VOL_SFT 0 | ||
504 | |||
505 | /* Digital Interface Data Control (0x2f) */ | ||
506 | #define RT5670_IF1_ADC2_IN_SEL (0x1 << 15) | ||
507 | #define RT5670_IF1_ADC2_IN_SFT 15 | ||
508 | #define RT5670_IF2_ADC_IN_MASK (0x7 << 12) | ||
509 | #define RT5670_IF2_ADC_IN_SFT 12 | ||
510 | #define RT5670_IF2_DAC_SEL_MASK (0x3 << 10) | ||
511 | #define RT5670_IF2_DAC_SEL_SFT 10 | ||
512 | #define RT5670_IF2_ADC_SEL_MASK (0x3 << 8) | ||
513 | #define RT5670_IF2_ADC_SEL_SFT 8 | ||
514 | |||
515 | /* Digital Interface Data Control (0x30) */ | ||
516 | #define RT5670_IF4_ADC_IN_MASK (0x3 << 4) | ||
517 | #define RT5670_IF4_ADC_IN_SFT 4 | ||
518 | |||
519 | /* PDM Output Control (0x31) */ | ||
520 | #define RT5670_PDM1_L_MASK (0x1 << 15) | ||
521 | #define RT5670_PDM1_L_SFT 15 | ||
522 | #define RT5670_M_PDM1_L (0x1 << 14) | ||
523 | #define RT5670_M_PDM1_L_SFT 14 | ||
524 | #define RT5670_PDM1_R_MASK (0x1 << 13) | ||
525 | #define RT5670_PDM1_R_SFT 13 | ||
526 | #define RT5670_M_PDM1_R (0x1 << 12) | ||
527 | #define RT5670_M_PDM1_R_SFT 12 | ||
528 | #define RT5670_PDM2_L_MASK (0x1 << 11) | ||
529 | #define RT5670_PDM2_L_SFT 11 | ||
530 | #define RT5670_M_PDM2_L (0x1 << 10) | ||
531 | #define RT5670_M_PDM2_L_SFT 10 | ||
532 | #define RT5670_PDM2_R_MASK (0x1 << 9) | ||
533 | #define RT5670_PDM2_R_SFT 9 | ||
534 | #define RT5670_M_PDM2_R (0x1 << 8) | ||
535 | #define RT5670_M_PDM2_R_SFT 8 | ||
536 | #define RT5670_PDM2_BUSY (0x1 << 7) | ||
537 | #define RT5670_PDM1_BUSY (0x1 << 6) | ||
538 | #define RT5670_PDM_PATTERN (0x1 << 5) | ||
539 | #define RT5670_PDM_GAIN (0x1 << 4) | ||
540 | #define RT5670_PDM_DIV_MASK (0x3) | ||
541 | |||
542 | /* REC Left Mixer Control 1 (0x3b) */ | ||
543 | #define RT5670_G_HP_L_RM_L_MASK (0x7 << 13) | ||
544 | #define RT5670_G_HP_L_RM_L_SFT 13 | ||
545 | #define RT5670_G_IN_L_RM_L_MASK (0x7 << 10) | ||
546 | #define RT5670_G_IN_L_RM_L_SFT 10 | ||
547 | #define RT5670_G_BST4_RM_L_MASK (0x7 << 7) | ||
548 | #define RT5670_G_BST4_RM_L_SFT 7 | ||
549 | #define RT5670_G_BST3_RM_L_MASK (0x7 << 4) | ||
550 | #define RT5670_G_BST3_RM_L_SFT 4 | ||
551 | #define RT5670_G_BST2_RM_L_MASK (0x7 << 1) | ||
552 | #define RT5670_G_BST2_RM_L_SFT 1 | ||
553 | |||
554 | /* REC Left Mixer Control 2 (0x3c) */ | ||
555 | #define RT5670_G_BST1_RM_L_MASK (0x7 << 13) | ||
556 | #define RT5670_G_BST1_RM_L_SFT 13 | ||
557 | #define RT5670_M_IN_L_RM_L (0x1 << 5) | ||
558 | #define RT5670_M_IN_L_RM_L_SFT 5 | ||
559 | #define RT5670_M_BST2_RM_L (0x1 << 3) | ||
560 | #define RT5670_M_BST2_RM_L_SFT 3 | ||
561 | #define RT5670_M_BST1_RM_L (0x1 << 1) | ||
562 | #define RT5670_M_BST1_RM_L_SFT 1 | ||
563 | |||
564 | /* REC Right Mixer Control 1 (0x3d) */ | ||
565 | #define RT5670_G_HP_R_RM_R_MASK (0x7 << 13) | ||
566 | #define RT5670_G_HP_R_RM_R_SFT 13 | ||
567 | #define RT5670_G_IN_R_RM_R_MASK (0x7 << 10) | ||
568 | #define RT5670_G_IN_R_RM_R_SFT 10 | ||
569 | #define RT5670_G_BST4_RM_R_MASK (0x7 << 7) | ||
570 | #define RT5670_G_BST4_RM_R_SFT 7 | ||
571 | #define RT5670_G_BST3_RM_R_MASK (0x7 << 4) | ||
572 | #define RT5670_G_BST3_RM_R_SFT 4 | ||
573 | #define RT5670_G_BST2_RM_R_MASK (0x7 << 1) | ||
574 | #define RT5670_G_BST2_RM_R_SFT 1 | ||
575 | |||
576 | /* REC Right Mixer Control 2 (0x3e) */ | ||
577 | #define RT5670_G_BST1_RM_R_MASK (0x7 << 13) | ||
578 | #define RT5670_G_BST1_RM_R_SFT 13 | ||
579 | #define RT5670_M_IN_R_RM_R (0x1 << 5) | ||
580 | #define RT5670_M_IN_R_RM_R_SFT 5 | ||
581 | #define RT5670_M_BST2_RM_R (0x1 << 3) | ||
582 | #define RT5670_M_BST2_RM_R_SFT 3 | ||
583 | #define RT5670_M_BST1_RM_R (0x1 << 1) | ||
584 | #define RT5670_M_BST1_RM_R_SFT 1 | ||
585 | |||
586 | /* HPMIX Control (0x45) */ | ||
587 | #define RT5670_M_DAC2_HM (0x1 << 15) | ||
588 | #define RT5670_M_DAC2_HM_SFT 15 | ||
589 | #define RT5670_M_HPVOL_HM (0x1 << 14) | ||
590 | #define RT5670_M_HPVOL_HM_SFT 14 | ||
591 | #define RT5670_M_DAC1_HM (0x1 << 13) | ||
592 | #define RT5670_M_DAC1_HM_SFT 13 | ||
593 | #define RT5670_G_HPOMIX_MASK (0x1 << 12) | ||
594 | #define RT5670_G_HPOMIX_SFT 12 | ||
595 | #define RT5670_M_INR1_HMR (0x1 << 3) | ||
596 | #define RT5670_M_INR1_HMR_SFT 3 | ||
597 | #define RT5670_M_DACR1_HMR (0x1 << 2) | ||
598 | #define RT5670_M_DACR1_HMR_SFT 2 | ||
599 | #define RT5670_M_INL1_HML (0x1 << 1) | ||
600 | #define RT5670_M_INL1_HML_SFT 1 | ||
601 | #define RT5670_M_DACL1_HML (0x1) | ||
602 | #define RT5670_M_DACL1_HML_SFT 0 | ||
603 | |||
604 | /* Mono Output Mixer Control (0x4c) */ | ||
605 | #define RT5670_M_DAC_R2_MA (0x1 << 15) | ||
606 | #define RT5670_M_DAC_R2_MA_SFT 15 | ||
607 | #define RT5670_M_DAC_L2_MA (0x1 << 14) | ||
608 | #define RT5670_M_DAC_L2_MA_SFT 14 | ||
609 | #define RT5670_M_OV_R_MM (0x1 << 13) | ||
610 | #define RT5670_M_OV_R_MM_SFT 13 | ||
611 | #define RT5670_M_OV_L_MM (0x1 << 12) | ||
612 | #define RT5670_M_OV_L_MM_SFT 12 | ||
613 | #define RT5670_G_MONOMIX_MASK (0x1 << 10) | ||
614 | #define RT5670_G_MONOMIX_SFT 10 | ||
615 | #define RT5670_M_DAC_R2_MM (0x1 << 9) | ||
616 | #define RT5670_M_DAC_R2_MM_SFT 9 | ||
617 | #define RT5670_M_DAC_L2_MM (0x1 << 8) | ||
618 | #define RT5670_M_DAC_L2_MM_SFT 8 | ||
619 | #define RT5670_M_BST4_MM (0x1 << 7) | ||
620 | #define RT5670_M_BST4_MM_SFT 7 | ||
621 | |||
622 | /* Output Left Mixer Control 1 (0x4d) */ | ||
623 | #define RT5670_G_BST3_OM_L_MASK (0x7 << 13) | ||
624 | #define RT5670_G_BST3_OM_L_SFT 13 | ||
625 | #define RT5670_G_BST2_OM_L_MASK (0x7 << 10) | ||
626 | #define RT5670_G_BST2_OM_L_SFT 10 | ||
627 | #define RT5670_G_BST1_OM_L_MASK (0x7 << 7) | ||
628 | #define RT5670_G_BST1_OM_L_SFT 7 | ||
629 | #define RT5670_G_IN_L_OM_L_MASK (0x7 << 4) | ||
630 | #define RT5670_G_IN_L_OM_L_SFT 4 | ||
631 | #define RT5670_G_RM_L_OM_L_MASK (0x7 << 1) | ||
632 | #define RT5670_G_RM_L_OM_L_SFT 1 | ||
633 | |||
634 | /* Output Left Mixer Control 2 (0x4e) */ | ||
635 | #define RT5670_G_DAC_R2_OM_L_MASK (0x7 << 13) | ||
636 | #define RT5670_G_DAC_R2_OM_L_SFT 13 | ||
637 | #define RT5670_G_DAC_L2_OM_L_MASK (0x7 << 10) | ||
638 | #define RT5670_G_DAC_L2_OM_L_SFT 10 | ||
639 | #define RT5670_G_DAC_L1_OM_L_MASK (0x7 << 7) | ||
640 | #define RT5670_G_DAC_L1_OM_L_SFT 7 | ||
641 | |||
642 | /* Output Left Mixer Control 3 (0x4f) */ | ||
643 | #define RT5670_M_BST1_OM_L (0x1 << 5) | ||
644 | #define RT5670_M_BST1_OM_L_SFT 5 | ||
645 | #define RT5670_M_IN_L_OM_L (0x1 << 4) | ||
646 | #define RT5670_M_IN_L_OM_L_SFT 4 | ||
647 | #define RT5670_M_DAC_L2_OM_L (0x1 << 1) | ||
648 | #define RT5670_M_DAC_L2_OM_L_SFT 1 | ||
649 | #define RT5670_M_DAC_L1_OM_L (0x1) | ||
650 | #define RT5670_M_DAC_L1_OM_L_SFT 0 | ||
651 | |||
652 | /* Output Right Mixer Control 1 (0x50) */ | ||
653 | #define RT5670_G_BST4_OM_R_MASK (0x7 << 13) | ||
654 | #define RT5670_G_BST4_OM_R_SFT 13 | ||
655 | #define RT5670_G_BST2_OM_R_MASK (0x7 << 10) | ||
656 | #define RT5670_G_BST2_OM_R_SFT 10 | ||
657 | #define RT5670_G_BST1_OM_R_MASK (0x7 << 7) | ||
658 | #define RT5670_G_BST1_OM_R_SFT 7 | ||
659 | #define RT5670_G_IN_R_OM_R_MASK (0x7 << 4) | ||
660 | #define RT5670_G_IN_R_OM_R_SFT 4 | ||
661 | #define RT5670_G_RM_R_OM_R_MASK (0x7 << 1) | ||
662 | #define RT5670_G_RM_R_OM_R_SFT 1 | ||
663 | |||
664 | /* Output Right Mixer Control 2 (0x51) */ | ||
665 | #define RT5670_G_DAC_L2_OM_R_MASK (0x7 << 13) | ||
666 | #define RT5670_G_DAC_L2_OM_R_SFT 13 | ||
667 | #define RT5670_G_DAC_R2_OM_R_MASK (0x7 << 10) | ||
668 | #define RT5670_G_DAC_R2_OM_R_SFT 10 | ||
669 | #define RT5670_G_DAC_R1_OM_R_MASK (0x7 << 7) | ||
670 | #define RT5670_G_DAC_R1_OM_R_SFT 7 | ||
671 | |||
672 | /* Output Right Mixer Control 3 (0x52) */ | ||
673 | #define RT5670_M_BST2_OM_R (0x1 << 6) | ||
674 | #define RT5670_M_BST2_OM_R_SFT 6 | ||
675 | #define RT5670_M_IN_R_OM_R (0x1 << 4) | ||
676 | #define RT5670_M_IN_R_OM_R_SFT 4 | ||
677 | #define RT5670_M_DAC_R2_OM_R (0x1 << 1) | ||
678 | #define RT5670_M_DAC_R2_OM_R_SFT 1 | ||
679 | #define RT5670_M_DAC_R1_OM_R (0x1) | ||
680 | #define RT5670_M_DAC_R1_OM_R_SFT 0 | ||
681 | |||
682 | /* LOUT Mixer Control (0x53) */ | ||
683 | #define RT5670_M_DAC_L1_LM (0x1 << 15) | ||
684 | #define RT5670_M_DAC_L1_LM_SFT 15 | ||
685 | #define RT5670_M_DAC_R1_LM (0x1 << 14) | ||
686 | #define RT5670_M_DAC_R1_LM_SFT 14 | ||
687 | #define RT5670_M_OV_L_LM (0x1 << 13) | ||
688 | #define RT5670_M_OV_L_LM_SFT 13 | ||
689 | #define RT5670_M_OV_R_LM (0x1 << 12) | ||
690 | #define RT5670_M_OV_R_LM_SFT 12 | ||
691 | #define RT5670_G_LOUTMIX_MASK (0x1 << 11) | ||
692 | #define RT5670_G_LOUTMIX_SFT 11 | ||
693 | |||
694 | /* Power Management for Digital 1 (0x61) */ | ||
695 | #define RT5670_PWR_I2S1 (0x1 << 15) | ||
696 | #define RT5670_PWR_I2S1_BIT 15 | ||
697 | #define RT5670_PWR_I2S2 (0x1 << 14) | ||
698 | #define RT5670_PWR_I2S2_BIT 14 | ||
699 | #define RT5670_PWR_DAC_L1 (0x1 << 12) | ||
700 | #define RT5670_PWR_DAC_L1_BIT 12 | ||
701 | #define RT5670_PWR_DAC_R1 (0x1 << 11) | ||
702 | #define RT5670_PWR_DAC_R1_BIT 11 | ||
703 | #define RT5670_PWR_DAC_L2 (0x1 << 7) | ||
704 | #define RT5670_PWR_DAC_L2_BIT 7 | ||
705 | #define RT5670_PWR_DAC_R2 (0x1 << 6) | ||
706 | #define RT5670_PWR_DAC_R2_BIT 6 | ||
707 | #define RT5670_PWR_ADC_L (0x1 << 2) | ||
708 | #define RT5670_PWR_ADC_L_BIT 2 | ||
709 | #define RT5670_PWR_ADC_R (0x1 << 1) | ||
710 | #define RT5670_PWR_ADC_R_BIT 1 | ||
711 | #define RT5670_PWR_CLS_D (0x1) | ||
712 | #define RT5670_PWR_CLS_D_BIT 0 | ||
713 | |||
714 | /* Power Management for Digital 2 (0x62) */ | ||
715 | #define RT5670_PWR_ADC_S1F (0x1 << 15) | ||
716 | #define RT5670_PWR_ADC_S1F_BIT 15 | ||
717 | #define RT5670_PWR_ADC_MF_L (0x1 << 14) | ||
718 | #define RT5670_PWR_ADC_MF_L_BIT 14 | ||
719 | #define RT5670_PWR_ADC_MF_R (0x1 << 13) | ||
720 | #define RT5670_PWR_ADC_MF_R_BIT 13 | ||
721 | #define RT5670_PWR_I2S_DSP (0x1 << 12) | ||
722 | #define RT5670_PWR_I2S_DSP_BIT 12 | ||
723 | #define RT5670_PWR_DAC_S1F (0x1 << 11) | ||
724 | #define RT5670_PWR_DAC_S1F_BIT 11 | ||
725 | #define RT5670_PWR_DAC_MF_L (0x1 << 10) | ||
726 | #define RT5670_PWR_DAC_MF_L_BIT 10 | ||
727 | #define RT5670_PWR_DAC_MF_R (0x1 << 9) | ||
728 | #define RT5670_PWR_DAC_MF_R_BIT 9 | ||
729 | #define RT5670_PWR_ADC_S2F (0x1 << 8) | ||
730 | #define RT5670_PWR_ADC_S2F_BIT 8 | ||
731 | #define RT5670_PWR_PDM1 (0x1 << 7) | ||
732 | #define RT5670_PWR_PDM1_BIT 7 | ||
733 | #define RT5670_PWR_PDM2 (0x1 << 6) | ||
734 | #define RT5670_PWR_PDM2_BIT 6 | ||
735 | |||
736 | /* Power Management for Analog 1 (0x63) */ | ||
737 | #define RT5670_PWR_VREF1 (0x1 << 15) | ||
738 | #define RT5670_PWR_VREF1_BIT 15 | ||
739 | #define RT5670_PWR_FV1 (0x1 << 14) | ||
740 | #define RT5670_PWR_FV1_BIT 14 | ||
741 | #define RT5670_PWR_MB (0x1 << 13) | ||
742 | #define RT5670_PWR_MB_BIT 13 | ||
743 | #define RT5670_PWR_LM (0x1 << 12) | ||
744 | #define RT5670_PWR_LM_BIT 12 | ||
745 | #define RT5670_PWR_BG (0x1 << 11) | ||
746 | #define RT5670_PWR_BG_BIT 11 | ||
747 | #define RT5670_PWR_HP_L (0x1 << 7) | ||
748 | #define RT5670_PWR_HP_L_BIT 7 | ||
749 | #define RT5670_PWR_HP_R (0x1 << 6) | ||
750 | #define RT5670_PWR_HP_R_BIT 6 | ||
751 | #define RT5670_PWR_HA (0x1 << 5) | ||
752 | #define RT5670_PWR_HA_BIT 5 | ||
753 | #define RT5670_PWR_VREF2 (0x1 << 4) | ||
754 | #define RT5670_PWR_VREF2_BIT 4 | ||
755 | #define RT5670_PWR_FV2 (0x1 << 3) | ||
756 | #define RT5670_PWR_FV2_BIT 3 | ||
757 | #define RT5670_LDO_SEL_MASK (0x3) | ||
758 | #define RT5670_LDO_SEL_SFT 0 | ||
759 | |||
760 | /* Power Management for Analog 2 (0x64) */ | ||
761 | #define RT5670_PWR_BST1 (0x1 << 15) | ||
762 | #define RT5670_PWR_BST1_BIT 15 | ||
763 | #define RT5670_PWR_BST2 (0x1 << 13) | ||
764 | #define RT5670_PWR_BST2_BIT 13 | ||
765 | #define RT5670_PWR_MB1 (0x1 << 11) | ||
766 | #define RT5670_PWR_MB1_BIT 11 | ||
767 | #define RT5670_PWR_MB2 (0x1 << 10) | ||
768 | #define RT5670_PWR_MB2_BIT 10 | ||
769 | #define RT5670_PWR_PLL (0x1 << 9) | ||
770 | #define RT5670_PWR_PLL_BIT 9 | ||
771 | #define RT5670_PWR_BST1_P (0x1 << 6) | ||
772 | #define RT5670_PWR_BST1_P_BIT 6 | ||
773 | #define RT5670_PWR_BST2_P (0x1 << 4) | ||
774 | #define RT5670_PWR_BST2_P_BIT 4 | ||
775 | #define RT5670_PWR_JD1 (0x1 << 2) | ||
776 | #define RT5670_PWR_JD1_BIT 2 | ||
777 | #define RT5670_PWR_JD (0x1 << 1) | ||
778 | #define RT5670_PWR_JD_BIT 1 | ||
779 | |||
780 | /* Power Management for Mixer (0x65) */ | ||
781 | #define RT5670_PWR_OM_L (0x1 << 15) | ||
782 | #define RT5670_PWR_OM_L_BIT 15 | ||
783 | #define RT5670_PWR_OM_R (0x1 << 14) | ||
784 | #define RT5670_PWR_OM_R_BIT 14 | ||
785 | #define RT5670_PWR_RM_L (0x1 << 11) | ||
786 | #define RT5670_PWR_RM_L_BIT 11 | ||
787 | #define RT5670_PWR_RM_R (0x1 << 10) | ||
788 | #define RT5670_PWR_RM_R_BIT 10 | ||
789 | |||
790 | /* Power Management for Volume (0x66) */ | ||
791 | #define RT5670_PWR_HV_L (0x1 << 11) | ||
792 | #define RT5670_PWR_HV_L_BIT 11 | ||
793 | #define RT5670_PWR_HV_R (0x1 << 10) | ||
794 | #define RT5670_PWR_HV_R_BIT 10 | ||
795 | #define RT5670_PWR_IN_L (0x1 << 9) | ||
796 | #define RT5670_PWR_IN_L_BIT 9 | ||
797 | #define RT5670_PWR_IN_R (0x1 << 8) | ||
798 | #define RT5670_PWR_IN_R_BIT 8 | ||
799 | #define RT5670_PWR_MIC_DET (0x1 << 5) | ||
800 | #define RT5670_PWR_MIC_DET_BIT 5 | ||
801 | |||
802 | /* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71 0x72) */ | ||
803 | #define RT5670_I2S_MS_MASK (0x1 << 15) | ||
804 | #define RT5670_I2S_MS_SFT 15 | ||
805 | #define RT5670_I2S_MS_M (0x0 << 15) | ||
806 | #define RT5670_I2S_MS_S (0x1 << 15) | ||
807 | #define RT5670_I2S_IF_MASK (0x7 << 12) | ||
808 | #define RT5670_I2S_IF_SFT 12 | ||
809 | #define RT5670_I2S_O_CP_MASK (0x3 << 10) | ||
810 | #define RT5670_I2S_O_CP_SFT 10 | ||
811 | #define RT5670_I2S_O_CP_OFF (0x0 << 10) | ||
812 | #define RT5670_I2S_O_CP_U_LAW (0x1 << 10) | ||
813 | #define RT5670_I2S_O_CP_A_LAW (0x2 << 10) | ||
814 | #define RT5670_I2S_I_CP_MASK (0x3 << 8) | ||
815 | #define RT5670_I2S_I_CP_SFT 8 | ||
816 | #define RT5670_I2S_I_CP_OFF (0x0 << 8) | ||
817 | #define RT5670_I2S_I_CP_U_LAW (0x1 << 8) | ||
818 | #define RT5670_I2S_I_CP_A_LAW (0x2 << 8) | ||
819 | #define RT5670_I2S_BP_MASK (0x1 << 7) | ||
820 | #define RT5670_I2S_BP_SFT 7 | ||
821 | #define RT5670_I2S_BP_NOR (0x0 << 7) | ||
822 | #define RT5670_I2S_BP_INV (0x1 << 7) | ||
823 | #define RT5670_I2S_DL_MASK (0x3 << 2) | ||
824 | #define RT5670_I2S_DL_SFT 2 | ||
825 | #define RT5670_I2S_DL_16 (0x0 << 2) | ||
826 | #define RT5670_I2S_DL_20 (0x1 << 2) | ||
827 | #define RT5670_I2S_DL_24 (0x2 << 2) | ||
828 | #define RT5670_I2S_DL_8 (0x3 << 2) | ||
829 | #define RT5670_I2S_DF_MASK (0x3) | ||
830 | #define RT5670_I2S_DF_SFT 0 | ||
831 | #define RT5670_I2S_DF_I2S (0x0) | ||
832 | #define RT5670_I2S_DF_LEFT (0x1) | ||
833 | #define RT5670_I2S_DF_PCM_A (0x2) | ||
834 | #define RT5670_I2S_DF_PCM_B (0x3) | ||
835 | |||
836 | /* I2S2 Audio Serial Data Port Control (0x71) */ | ||
837 | #define RT5670_I2S2_SDI_MASK (0x1 << 6) | ||
838 | #define RT5670_I2S2_SDI_SFT 6 | ||
839 | #define RT5670_I2S2_SDI_I2S1 (0x0 << 6) | ||
840 | #define RT5670_I2S2_SDI_I2S2 (0x1 << 6) | ||
841 | |||
842 | /* ADC/DAC Clock Control 1 (0x73) */ | ||
843 | #define RT5670_I2S_BCLK_MS1_MASK (0x1 << 15) | ||
844 | #define RT5670_I2S_BCLK_MS1_SFT 15 | ||
845 | #define RT5670_I2S_BCLK_MS1_32 (0x0 << 15) | ||
846 | #define RT5670_I2S_BCLK_MS1_64 (0x1 << 15) | ||
847 | #define RT5670_I2S_PD1_MASK (0x7 << 12) | ||
848 | #define RT5670_I2S_PD1_SFT 12 | ||
849 | #define RT5670_I2S_PD1_1 (0x0 << 12) | ||
850 | #define RT5670_I2S_PD1_2 (0x1 << 12) | ||
851 | #define RT5670_I2S_PD1_3 (0x2 << 12) | ||
852 | #define RT5670_I2S_PD1_4 (0x3 << 12) | ||
853 | #define RT5670_I2S_PD1_6 (0x4 << 12) | ||
854 | #define RT5670_I2S_PD1_8 (0x5 << 12) | ||
855 | #define RT5670_I2S_PD1_12 (0x6 << 12) | ||
856 | #define RT5670_I2S_PD1_16 (0x7 << 12) | ||
857 | #define RT5670_I2S_BCLK_MS2_MASK (0x1 << 11) | ||
858 | #define RT5670_I2S_BCLK_MS2_SFT 11 | ||
859 | #define RT5670_I2S_BCLK_MS2_32 (0x0 << 11) | ||
860 | #define RT5670_I2S_BCLK_MS2_64 (0x1 << 11) | ||
861 | #define RT5670_I2S_PD2_MASK (0x7 << 8) | ||
862 | #define RT5670_I2S_PD2_SFT 8 | ||
863 | #define RT5670_I2S_PD2_1 (0x0 << 8) | ||
864 | #define RT5670_I2S_PD2_2 (0x1 << 8) | ||
865 | #define RT5670_I2S_PD2_3 (0x2 << 8) | ||
866 | #define RT5670_I2S_PD2_4 (0x3 << 8) | ||
867 | #define RT5670_I2S_PD2_6 (0x4 << 8) | ||
868 | #define RT5670_I2S_PD2_8 (0x5 << 8) | ||
869 | #define RT5670_I2S_PD2_12 (0x6 << 8) | ||
870 | #define RT5670_I2S_PD2_16 (0x7 << 8) | ||
871 | #define RT5670_I2S_BCLK_MS3_MASK (0x1 << 7) | ||
872 | #define RT5670_I2S_BCLK_MS3_SFT 7 | ||
873 | #define RT5670_I2S_BCLK_MS3_32 (0x0 << 7) | ||
874 | #define RT5670_I2S_BCLK_MS3_64 (0x1 << 7) | ||
875 | #define RT5670_I2S_PD3_MASK (0x7 << 4) | ||
876 | #define RT5670_I2S_PD3_SFT 4 | ||
877 | #define RT5670_I2S_PD3_1 (0x0 << 4) | ||
878 | #define RT5670_I2S_PD3_2 (0x1 << 4) | ||
879 | #define RT5670_I2S_PD3_3 (0x2 << 4) | ||
880 | #define RT5670_I2S_PD3_4 (0x3 << 4) | ||
881 | #define RT5670_I2S_PD3_6 (0x4 << 4) | ||
882 | #define RT5670_I2S_PD3_8 (0x5 << 4) | ||
883 | #define RT5670_I2S_PD3_12 (0x6 << 4) | ||
884 | #define RT5670_I2S_PD3_16 (0x7 << 4) | ||
885 | #define RT5670_DAC_OSR_MASK (0x3 << 2) | ||
886 | #define RT5670_DAC_OSR_SFT 2 | ||
887 | #define RT5670_DAC_OSR_128 (0x0 << 2) | ||
888 | #define RT5670_DAC_OSR_64 (0x1 << 2) | ||
889 | #define RT5670_DAC_OSR_32 (0x2 << 2) | ||
890 | #define RT5670_DAC_OSR_16 (0x3 << 2) | ||
891 | #define RT5670_ADC_OSR_MASK (0x3) | ||
892 | #define RT5670_ADC_OSR_SFT 0 | ||
893 | #define RT5670_ADC_OSR_128 (0x0) | ||
894 | #define RT5670_ADC_OSR_64 (0x1) | ||
895 | #define RT5670_ADC_OSR_32 (0x2) | ||
896 | #define RT5670_ADC_OSR_16 (0x3) | ||
897 | |||
898 | /* ADC/DAC Clock Control 2 (0x74) */ | ||
899 | #define RT5670_DAC_L_OSR_MASK (0x3 << 14) | ||
900 | #define RT5670_DAC_L_OSR_SFT 14 | ||
901 | #define RT5670_DAC_L_OSR_128 (0x0 << 14) | ||
902 | #define RT5670_DAC_L_OSR_64 (0x1 << 14) | ||
903 | #define RT5670_DAC_L_OSR_32 (0x2 << 14) | ||
904 | #define RT5670_DAC_L_OSR_16 (0x3 << 14) | ||
905 | #define RT5670_ADC_R_OSR_MASK (0x3 << 12) | ||
906 | #define RT5670_ADC_R_OSR_SFT 12 | ||
907 | #define RT5670_ADC_R_OSR_128 (0x0 << 12) | ||
908 | #define RT5670_ADC_R_OSR_64 (0x1 << 12) | ||
909 | #define RT5670_ADC_R_OSR_32 (0x2 << 12) | ||
910 | #define RT5670_ADC_R_OSR_16 (0x3 << 12) | ||
911 | #define RT5670_DAHPF_EN (0x1 << 11) | ||
912 | #define RT5670_DAHPF_EN_SFT 11 | ||
913 | #define RT5670_ADHPF_EN (0x1 << 10) | ||
914 | #define RT5670_ADHPF_EN_SFT 10 | ||
915 | |||
916 | /* Digital Microphone Control (0x75) */ | ||
917 | #define RT5670_DMIC_1_EN_MASK (0x1 << 15) | ||
918 | #define RT5670_DMIC_1_EN_SFT 15 | ||
919 | #define RT5670_DMIC_1_DIS (0x0 << 15) | ||
920 | #define RT5670_DMIC_1_EN (0x1 << 15) | ||
921 | #define RT5670_DMIC_2_EN_MASK (0x1 << 14) | ||
922 | #define RT5670_DMIC_2_EN_SFT 14 | ||
923 | #define RT5670_DMIC_2_DIS (0x0 << 14) | ||
924 | #define RT5670_DMIC_2_EN (0x1 << 14) | ||
925 | #define RT5670_DMIC_1L_LH_MASK (0x1 << 13) | ||
926 | #define RT5670_DMIC_1L_LH_SFT 13 | ||
927 | #define RT5670_DMIC_1L_LH_FALLING (0x0 << 13) | ||
928 | #define RT5670_DMIC_1L_LH_RISING (0x1 << 13) | ||
929 | #define RT5670_DMIC_1R_LH_MASK (0x1 << 12) | ||
930 | #define RT5670_DMIC_1R_LH_SFT 12 | ||
931 | #define RT5670_DMIC_1R_LH_FALLING (0x0 << 12) | ||
932 | #define RT5670_DMIC_1R_LH_RISING (0x1 << 12) | ||
933 | #define RT5670_DMIC_2_DP_MASK (0x1 << 10) | ||
934 | #define RT5670_DMIC_2_DP_SFT 10 | ||
935 | #define RT5670_DMIC_2_DP_GPIO8 (0x0 << 10) | ||
936 | #define RT5670_DMIC_2_DP_IN3N (0x1 << 10) | ||
937 | #define RT5670_DMIC_2L_LH_MASK (0x1 << 9) | ||
938 | #define RT5670_DMIC_2L_LH_SFT 9 | ||
939 | #define RT5670_DMIC_2L_LH_FALLING (0x0 << 9) | ||
940 | #define RT5670_DMIC_2L_LH_RISING (0x1 << 9) | ||
941 | #define RT5670_DMIC_2R_LH_MASK (0x1 << 8) | ||
942 | #define RT5670_DMIC_2R_LH_SFT 8 | ||
943 | #define RT5670_DMIC_2R_LH_FALLING (0x0 << 8) | ||
944 | #define RT5670_DMIC_2R_LH_RISING (0x1 << 8) | ||
945 | #define RT5670_DMIC_CLK_MASK (0x7 << 5) | ||
946 | #define RT5670_DMIC_CLK_SFT 5 | ||
947 | #define RT5670_DMIC_3_EN_MASK (0x1 << 4) | ||
948 | #define RT5670_DMIC_3_EN_SFT 4 | ||
949 | #define RT5670_DMIC_3_DIS (0x0 << 4) | ||
950 | #define RT5670_DMIC_3_EN (0x1 << 4) | ||
951 | #define RT5670_DMIC_1_DP_MASK (0x3 << 0) | ||
952 | #define RT5670_DMIC_1_DP_SFT 0 | ||
953 | #define RT5670_DMIC_1_DP_GPIO6 (0x0 << 0) | ||
954 | #define RT5670_DMIC_1_DP_IN2P (0x1 << 0) | ||
955 | #define RT5670_DMIC_1_DP_GPIO7 (0x2 << 0) | ||
956 | |||
957 | /* Digital Microphone Control2 (0x76) */ | ||
958 | #define RT5670_DMIC_3_DP_MASK (0x3 << 6) | ||
959 | #define RT5670_DMIC_3_DP_SFT 6 | ||
960 | #define RT5670_DMIC_3_DP_GPIO9 (0x0 << 6) | ||
961 | #define RT5670_DMIC_3_DP_GPIO10 (0x1 << 6) | ||
962 | #define RT5670_DMIC_3_DP_GPIO5 (0x2 << 6) | ||
963 | |||
964 | /* Global Clock Control (0x80) */ | ||
965 | #define RT5670_SCLK_SRC_MASK (0x3 << 14) | ||
966 | #define RT5670_SCLK_SRC_SFT 14 | ||
967 | #define RT5670_SCLK_SRC_MCLK (0x0 << 14) | ||
968 | #define RT5670_SCLK_SRC_PLL1 (0x1 << 14) | ||
969 | #define RT5670_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */ | ||
970 | #define RT5670_PLL1_SRC_MASK (0x3 << 12) | ||
971 | #define RT5670_PLL1_SRC_SFT 12 | ||
972 | #define RT5670_PLL1_SRC_MCLK (0x0 << 12) | ||
973 | #define RT5670_PLL1_SRC_BCLK1 (0x1 << 12) | ||
974 | #define RT5670_PLL1_SRC_BCLK2 (0x2 << 12) | ||
975 | #define RT5670_PLL1_SRC_BCLK3 (0x3 << 12) | ||
976 | #define RT5670_PLL1_PD_MASK (0x1 << 3) | ||
977 | #define RT5670_PLL1_PD_SFT 3 | ||
978 | #define RT5670_PLL1_PD_1 (0x0 << 3) | ||
979 | #define RT5670_PLL1_PD_2 (0x1 << 3) | ||
980 | |||
981 | #define RT5670_PLL_INP_MAX 40000000 | ||
982 | #define RT5670_PLL_INP_MIN 256000 | ||
983 | /* PLL M/N/K Code Control 1 (0x81) */ | ||
984 | #define RT5670_PLL_N_MAX 0x1ff | ||
985 | #define RT5670_PLL_N_MASK (RT5670_PLL_N_MAX << 7) | ||
986 | #define RT5670_PLL_N_SFT 7 | ||
987 | #define RT5670_PLL_K_MAX 0x1f | ||
988 | #define RT5670_PLL_K_MASK (RT5670_PLL_K_MAX) | ||
989 | #define RT5670_PLL_K_SFT 0 | ||
990 | |||
991 | /* PLL M/N/K Code Control 2 (0x82) */ | ||
992 | #define RT5670_PLL_M_MAX 0xf | ||
993 | #define RT5670_PLL_M_MASK (RT5670_PLL_M_MAX << 12) | ||
994 | #define RT5670_PLL_M_SFT 12 | ||
995 | #define RT5670_PLL_M_BP (0x1 << 11) | ||
996 | #define RT5670_PLL_M_BP_SFT 11 | ||
997 | |||
998 | /* ASRC Control 1 (0x83) */ | ||
999 | #define RT5670_STO_T_MASK (0x1 << 15) | ||
1000 | #define RT5670_STO_T_SFT 15 | ||
1001 | #define RT5670_STO_T_SCLK (0x0 << 15) | ||
1002 | #define RT5670_STO_T_LRCK1 (0x1 << 15) | ||
1003 | #define RT5670_M1_T_MASK (0x1 << 14) | ||
1004 | #define RT5670_M1_T_SFT 14 | ||
1005 | #define RT5670_M1_T_I2S2 (0x0 << 14) | ||
1006 | #define RT5670_M1_T_I2S2_D3 (0x1 << 14) | ||
1007 | #define RT5670_I2S2_F_MASK (0x1 << 12) | ||
1008 | #define RT5670_I2S2_F_SFT 12 | ||
1009 | #define RT5670_I2S2_F_I2S2_D2 (0x0 << 12) | ||
1010 | #define RT5670_I2S2_F_I2S1_TCLK (0x1 << 12) | ||
1011 | #define RT5670_DMIC_1_M_MASK (0x1 << 9) | ||
1012 | #define RT5670_DMIC_1_M_SFT 9 | ||
1013 | #define RT5670_DMIC_1_M_NOR (0x0 << 9) | ||
1014 | #define RT5670_DMIC_1_M_ASYN (0x1 << 9) | ||
1015 | #define RT5670_DMIC_2_M_MASK (0x1 << 8) | ||
1016 | #define RT5670_DMIC_2_M_SFT 8 | ||
1017 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) | ||
1018 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) | ||
1019 | |||
1020 | /* ASRC Control 2 (0x84) */ | ||
1021 | #define RT5670_MDA_L_M_MASK (0x1 << 15) | ||
1022 | #define RT5670_MDA_L_M_SFT 15 | ||
1023 | #define RT5670_MDA_L_M_NOR (0x0 << 15) | ||
1024 | #define RT5670_MDA_L_M_ASYN (0x1 << 15) | ||
1025 | #define RT5670_MDA_R_M_MASK (0x1 << 14) | ||
1026 | #define RT5670_MDA_R_M_SFT 14 | ||
1027 | #define RT5670_MDA_R_M_NOR (0x0 << 14) | ||
1028 | #define RT5670_MDA_R_M_ASYN (0x1 << 14) | ||
1029 | #define RT5670_MAD_L_M_MASK (0x1 << 13) | ||
1030 | #define RT5670_MAD_L_M_SFT 13 | ||
1031 | #define RT5670_MAD_L_M_NOR (0x0 << 13) | ||
1032 | #define RT5670_MAD_L_M_ASYN (0x1 << 13) | ||
1033 | #define RT5670_MAD_R_M_MASK (0x1 << 12) | ||
1034 | #define RT5670_MAD_R_M_SFT 12 | ||
1035 | #define RT5670_MAD_R_M_NOR (0x0 << 12) | ||
1036 | #define RT5670_MAD_R_M_ASYN (0x1 << 12) | ||
1037 | #define RT5670_ADC_M_MASK (0x1 << 11) | ||
1038 | #define RT5670_ADC_M_SFT 11 | ||
1039 | #define RT5670_ADC_M_NOR (0x0 << 11) | ||
1040 | #define RT5670_ADC_M_ASYN (0x1 << 11) | ||
1041 | #define RT5670_STO_DAC_M_MASK (0x1 << 5) | ||
1042 | #define RT5670_STO_DAC_M_SFT 5 | ||
1043 | #define RT5670_STO_DAC_M_NOR (0x0 << 5) | ||
1044 | #define RT5670_STO_DAC_M_ASYN (0x1 << 5) | ||
1045 | #define RT5670_I2S1_R_D_MASK (0x1 << 4) | ||
1046 | #define RT5670_I2S1_R_D_SFT 4 | ||
1047 | #define RT5670_I2S1_R_D_DIS (0x0 << 4) | ||
1048 | #define RT5670_I2S1_R_D_EN (0x1 << 4) | ||
1049 | #define RT5670_I2S2_R_D_MASK (0x1 << 3) | ||
1050 | #define RT5670_I2S2_R_D_SFT 3 | ||
1051 | #define RT5670_I2S2_R_D_DIS (0x0 << 3) | ||
1052 | #define RT5670_I2S2_R_D_EN (0x1 << 3) | ||
1053 | #define RT5670_PRE_SCLK_MASK (0x3) | ||
1054 | #define RT5670_PRE_SCLK_SFT 0 | ||
1055 | #define RT5670_PRE_SCLK_512 (0x0) | ||
1056 | #define RT5670_PRE_SCLK_1024 (0x1) | ||
1057 | #define RT5670_PRE_SCLK_2048 (0x2) | ||
1058 | |||
1059 | /* ASRC Control 3 (0x85) */ | ||
1060 | #define RT5670_I2S1_RATE_MASK (0xf << 12) | ||
1061 | #define RT5670_I2S1_RATE_SFT 12 | ||
1062 | #define RT5670_I2S2_RATE_MASK (0xf << 8) | ||
1063 | #define RT5670_I2S2_RATE_SFT 8 | ||
1064 | |||
1065 | /* ASRC Control 4 (0x89) */ | ||
1066 | #define RT5670_I2S1_PD_MASK (0x7 << 12) | ||
1067 | #define RT5670_I2S1_PD_SFT 12 | ||
1068 | #define RT5670_I2S2_PD_MASK (0x7 << 8) | ||
1069 | #define RT5670_I2S2_PD_SFT 8 | ||
1070 | |||
1071 | /* HPOUT Over Current Detection (0x8b) */ | ||
1072 | #define RT5670_HP_OVCD_MASK (0x1 << 10) | ||
1073 | #define RT5670_HP_OVCD_SFT 10 | ||
1074 | #define RT5670_HP_OVCD_DIS (0x0 << 10) | ||
1075 | #define RT5670_HP_OVCD_EN (0x1 << 10) | ||
1076 | #define RT5670_HP_OC_TH_MASK (0x3 << 8) | ||
1077 | #define RT5670_HP_OC_TH_SFT 8 | ||
1078 | #define RT5670_HP_OC_TH_90 (0x0 << 8) | ||
1079 | #define RT5670_HP_OC_TH_105 (0x1 << 8) | ||
1080 | #define RT5670_HP_OC_TH_120 (0x2 << 8) | ||
1081 | #define RT5670_HP_OC_TH_135 (0x3 << 8) | ||
1082 | |||
1083 | /* Class D Over Current Control (0x8c) */ | ||
1084 | #define RT5670_CLSD_OC_MASK (0x1 << 9) | ||
1085 | #define RT5670_CLSD_OC_SFT 9 | ||
1086 | #define RT5670_CLSD_OC_PU (0x0 << 9) | ||
1087 | #define RT5670_CLSD_OC_PD (0x1 << 9) | ||
1088 | #define RT5670_AUTO_PD_MASK (0x1 << 8) | ||
1089 | #define RT5670_AUTO_PD_SFT 8 | ||
1090 | #define RT5670_AUTO_PD_DIS (0x0 << 8) | ||
1091 | #define RT5670_AUTO_PD_EN (0x1 << 8) | ||
1092 | #define RT5670_CLSD_OC_TH_MASK (0x3f) | ||
1093 | #define RT5670_CLSD_OC_TH_SFT 0 | ||
1094 | |||
1095 | /* Class D Output Control (0x8d) */ | ||
1096 | #define RT5670_CLSD_RATIO_MASK (0xf << 12) | ||
1097 | #define RT5670_CLSD_RATIO_SFT 12 | ||
1098 | #define RT5670_CLSD_OM_MASK (0x1 << 11) | ||
1099 | #define RT5670_CLSD_OM_SFT 11 | ||
1100 | #define RT5670_CLSD_OM_MONO (0x0 << 11) | ||
1101 | #define RT5670_CLSD_OM_STO (0x1 << 11) | ||
1102 | #define RT5670_CLSD_SCH_MASK (0x1 << 10) | ||
1103 | #define RT5670_CLSD_SCH_SFT 10 | ||
1104 | #define RT5670_CLSD_SCH_L (0x0 << 10) | ||
1105 | #define RT5670_CLSD_SCH_S (0x1 << 10) | ||
1106 | |||
1107 | /* Depop Mode Control 1 (0x8e) */ | ||
1108 | #define RT5670_SMT_TRIG_MASK (0x1 << 15) | ||
1109 | #define RT5670_SMT_TRIG_SFT 15 | ||
1110 | #define RT5670_SMT_TRIG_DIS (0x0 << 15) | ||
1111 | #define RT5670_SMT_TRIG_EN (0x1 << 15) | ||
1112 | #define RT5670_HP_L_SMT_MASK (0x1 << 9) | ||
1113 | #define RT5670_HP_L_SMT_SFT 9 | ||
1114 | #define RT5670_HP_L_SMT_DIS (0x0 << 9) | ||
1115 | #define RT5670_HP_L_SMT_EN (0x1 << 9) | ||
1116 | #define RT5670_HP_R_SMT_MASK (0x1 << 8) | ||
1117 | #define RT5670_HP_R_SMT_SFT 8 | ||
1118 | #define RT5670_HP_R_SMT_DIS (0x0 << 8) | ||
1119 | #define RT5670_HP_R_SMT_EN (0x1 << 8) | ||
1120 | #define RT5670_HP_CD_PD_MASK (0x1 << 7) | ||
1121 | #define RT5670_HP_CD_PD_SFT 7 | ||
1122 | #define RT5670_HP_CD_PD_DIS (0x0 << 7) | ||
1123 | #define RT5670_HP_CD_PD_EN (0x1 << 7) | ||
1124 | #define RT5670_RSTN_MASK (0x1 << 6) | ||
1125 | #define RT5670_RSTN_SFT 6 | ||
1126 | #define RT5670_RSTN_DIS (0x0 << 6) | ||
1127 | #define RT5670_RSTN_EN (0x1 << 6) | ||
1128 | #define RT5670_RSTP_MASK (0x1 << 5) | ||
1129 | #define RT5670_RSTP_SFT 5 | ||
1130 | #define RT5670_RSTP_DIS (0x0 << 5) | ||
1131 | #define RT5670_RSTP_EN (0x1 << 5) | ||
1132 | #define RT5670_HP_CO_MASK (0x1 << 4) | ||
1133 | #define RT5670_HP_CO_SFT 4 | ||
1134 | #define RT5670_HP_CO_DIS (0x0 << 4) | ||
1135 | #define RT5670_HP_CO_EN (0x1 << 4) | ||
1136 | #define RT5670_HP_CP_MASK (0x1 << 3) | ||
1137 | #define RT5670_HP_CP_SFT 3 | ||
1138 | #define RT5670_HP_CP_PD (0x0 << 3) | ||
1139 | #define RT5670_HP_CP_PU (0x1 << 3) | ||
1140 | #define RT5670_HP_SG_MASK (0x1 << 2) | ||
1141 | #define RT5670_HP_SG_SFT 2 | ||
1142 | #define RT5670_HP_SG_DIS (0x0 << 2) | ||
1143 | #define RT5670_HP_SG_EN (0x1 << 2) | ||
1144 | #define RT5670_HP_DP_MASK (0x1 << 1) | ||
1145 | #define RT5670_HP_DP_SFT 1 | ||
1146 | #define RT5670_HP_DP_PD (0x0 << 1) | ||
1147 | #define RT5670_HP_DP_PU (0x1 << 1) | ||
1148 | #define RT5670_HP_CB_MASK (0x1) | ||
1149 | #define RT5670_HP_CB_SFT 0 | ||
1150 | #define RT5670_HP_CB_PD (0x0) | ||
1151 | #define RT5670_HP_CB_PU (0x1) | ||
1152 | |||
1153 | /* Depop Mode Control 2 (0x8f) */ | ||
1154 | #define RT5670_DEPOP_MASK (0x1 << 13) | ||
1155 | #define RT5670_DEPOP_SFT 13 | ||
1156 | #define RT5670_DEPOP_AUTO (0x0 << 13) | ||
1157 | #define RT5670_DEPOP_MAN (0x1 << 13) | ||
1158 | #define RT5670_RAMP_MASK (0x1 << 12) | ||
1159 | #define RT5670_RAMP_SFT 12 | ||
1160 | #define RT5670_RAMP_DIS (0x0 << 12) | ||
1161 | #define RT5670_RAMP_EN (0x1 << 12) | ||
1162 | #define RT5670_BPS_MASK (0x1 << 11) | ||
1163 | #define RT5670_BPS_SFT 11 | ||
1164 | #define RT5670_BPS_DIS (0x0 << 11) | ||
1165 | #define RT5670_BPS_EN (0x1 << 11) | ||
1166 | #define RT5670_FAST_UPDN_MASK (0x1 << 10) | ||
1167 | #define RT5670_FAST_UPDN_SFT 10 | ||
1168 | #define RT5670_FAST_UPDN_DIS (0x0 << 10) | ||
1169 | #define RT5670_FAST_UPDN_EN (0x1 << 10) | ||
1170 | #define RT5670_MRES_MASK (0x3 << 8) | ||
1171 | #define RT5670_MRES_SFT 8 | ||
1172 | #define RT5670_MRES_15MO (0x0 << 8) | ||
1173 | #define RT5670_MRES_25MO (0x1 << 8) | ||
1174 | #define RT5670_MRES_35MO (0x2 << 8) | ||
1175 | #define RT5670_MRES_45MO (0x3 << 8) | ||
1176 | #define RT5670_VLO_MASK (0x1 << 7) | ||
1177 | #define RT5670_VLO_SFT 7 | ||
1178 | #define RT5670_VLO_3V (0x0 << 7) | ||
1179 | #define RT5670_VLO_32V (0x1 << 7) | ||
1180 | #define RT5670_DIG_DP_MASK (0x1 << 6) | ||
1181 | #define RT5670_DIG_DP_SFT 6 | ||
1182 | #define RT5670_DIG_DP_DIS (0x0 << 6) | ||
1183 | #define RT5670_DIG_DP_EN (0x1 << 6) | ||
1184 | #define RT5670_DP_TH_MASK (0x3 << 4) | ||
1185 | #define RT5670_DP_TH_SFT 4 | ||
1186 | |||
1187 | /* Depop Mode Control 3 (0x90) */ | ||
1188 | #define RT5670_CP_SYS_MASK (0x7 << 12) | ||
1189 | #define RT5670_CP_SYS_SFT 12 | ||
1190 | #define RT5670_CP_FQ1_MASK (0x7 << 8) | ||
1191 | #define RT5670_CP_FQ1_SFT 8 | ||
1192 | #define RT5670_CP_FQ2_MASK (0x7 << 4) | ||
1193 | #define RT5670_CP_FQ2_SFT 4 | ||
1194 | #define RT5670_CP_FQ3_MASK (0x7) | ||
1195 | #define RT5670_CP_FQ3_SFT 0 | ||
1196 | #define RT5670_CP_FQ_1_5_KHZ 0 | ||
1197 | #define RT5670_CP_FQ_3_KHZ 1 | ||
1198 | #define RT5670_CP_FQ_6_KHZ 2 | ||
1199 | #define RT5670_CP_FQ_12_KHZ 3 | ||
1200 | #define RT5670_CP_FQ_24_KHZ 4 | ||
1201 | #define RT5670_CP_FQ_48_KHZ 5 | ||
1202 | #define RT5670_CP_FQ_96_KHZ 6 | ||
1203 | #define RT5670_CP_FQ_192_KHZ 7 | ||
1204 | |||
1205 | /* HPOUT charge pump (0x91) */ | ||
1206 | #define RT5670_OSW_L_MASK (0x1 << 11) | ||
1207 | #define RT5670_OSW_L_SFT 11 | ||
1208 | #define RT5670_OSW_L_DIS (0x0 << 11) | ||
1209 | #define RT5670_OSW_L_EN (0x1 << 11) | ||
1210 | #define RT5670_OSW_R_MASK (0x1 << 10) | ||
1211 | #define RT5670_OSW_R_SFT 10 | ||
1212 | #define RT5670_OSW_R_DIS (0x0 << 10) | ||
1213 | #define RT5670_OSW_R_EN (0x1 << 10) | ||
1214 | #define RT5670_PM_HP_MASK (0x3 << 8) | ||
1215 | #define RT5670_PM_HP_SFT 8 | ||
1216 | #define RT5670_PM_HP_LV (0x0 << 8) | ||
1217 | #define RT5670_PM_HP_MV (0x1 << 8) | ||
1218 | #define RT5670_PM_HP_HV (0x2 << 8) | ||
1219 | #define RT5670_IB_HP_MASK (0x3 << 6) | ||
1220 | #define RT5670_IB_HP_SFT 6 | ||
1221 | #define RT5670_IB_HP_125IL (0x0 << 6) | ||
1222 | #define RT5670_IB_HP_25IL (0x1 << 6) | ||
1223 | #define RT5670_IB_HP_5IL (0x2 << 6) | ||
1224 | #define RT5670_IB_HP_1IL (0x3 << 6) | ||
1225 | |||
1226 | /* PV detection and SPK gain control (0x92) */ | ||
1227 | #define RT5670_PVDD_DET_MASK (0x1 << 15) | ||
1228 | #define RT5670_PVDD_DET_SFT 15 | ||
1229 | #define RT5670_PVDD_DET_DIS (0x0 << 15) | ||
1230 | #define RT5670_PVDD_DET_EN (0x1 << 15) | ||
1231 | #define RT5670_SPK_AG_MASK (0x1 << 14) | ||
1232 | #define RT5670_SPK_AG_SFT 14 | ||
1233 | #define RT5670_SPK_AG_DIS (0x0 << 14) | ||
1234 | #define RT5670_SPK_AG_EN (0x1 << 14) | ||
1235 | |||
1236 | /* Micbias Control (0x93) */ | ||
1237 | #define RT5670_MIC1_BS_MASK (0x1 << 15) | ||
1238 | #define RT5670_MIC1_BS_SFT 15 | ||
1239 | #define RT5670_MIC1_BS_9AV (0x0 << 15) | ||
1240 | #define RT5670_MIC1_BS_75AV (0x1 << 15) | ||
1241 | #define RT5670_MIC2_BS_MASK (0x1 << 14) | ||
1242 | #define RT5670_MIC2_BS_SFT 14 | ||
1243 | #define RT5670_MIC2_BS_9AV (0x0 << 14) | ||
1244 | #define RT5670_MIC2_BS_75AV (0x1 << 14) | ||
1245 | #define RT5670_MIC1_CLK_MASK (0x1 << 13) | ||
1246 | #define RT5670_MIC1_CLK_SFT 13 | ||
1247 | #define RT5670_MIC1_CLK_DIS (0x0 << 13) | ||
1248 | #define RT5670_MIC1_CLK_EN (0x1 << 13) | ||
1249 | #define RT5670_MIC2_CLK_MASK (0x1 << 12) | ||
1250 | #define RT5670_MIC2_CLK_SFT 12 | ||
1251 | #define RT5670_MIC2_CLK_DIS (0x0 << 12) | ||
1252 | #define RT5670_MIC2_CLK_EN (0x1 << 12) | ||
1253 | #define RT5670_MIC1_OVCD_MASK (0x1 << 11) | ||
1254 | #define RT5670_MIC1_OVCD_SFT 11 | ||
1255 | #define RT5670_MIC1_OVCD_DIS (0x0 << 11) | ||
1256 | #define RT5670_MIC1_OVCD_EN (0x1 << 11) | ||
1257 | #define RT5670_MIC1_OVTH_MASK (0x3 << 9) | ||
1258 | #define RT5670_MIC1_OVTH_SFT 9 | ||
1259 | #define RT5670_MIC1_OVTH_600UA (0x0 << 9) | ||
1260 | #define RT5670_MIC1_OVTH_1500UA (0x1 << 9) | ||
1261 | #define RT5670_MIC1_OVTH_2000UA (0x2 << 9) | ||
1262 | #define RT5670_MIC2_OVCD_MASK (0x1 << 8) | ||
1263 | #define RT5670_MIC2_OVCD_SFT 8 | ||
1264 | #define RT5670_MIC2_OVCD_DIS (0x0 << 8) | ||
1265 | #define RT5670_MIC2_OVCD_EN (0x1 << 8) | ||
1266 | #define RT5670_MIC2_OVTH_MASK (0x3 << 6) | ||
1267 | #define RT5670_MIC2_OVTH_SFT 6 | ||
1268 | #define RT5670_MIC2_OVTH_600UA (0x0 << 6) | ||
1269 | #define RT5670_MIC2_OVTH_1500UA (0x1 << 6) | ||
1270 | #define RT5670_MIC2_OVTH_2000UA (0x2 << 6) | ||
1271 | #define RT5670_PWR_MB_MASK (0x1 << 5) | ||
1272 | #define RT5670_PWR_MB_SFT 5 | ||
1273 | #define RT5670_PWR_MB_PD (0x0 << 5) | ||
1274 | #define RT5670_PWR_MB_PU (0x1 << 5) | ||
1275 | #define RT5670_PWR_CLK25M_MASK (0x1 << 4) | ||
1276 | #define RT5670_PWR_CLK25M_SFT 4 | ||
1277 | #define RT5670_PWR_CLK25M_PD (0x0 << 4) | ||
1278 | #define RT5670_PWR_CLK25M_PU (0x1 << 4) | ||
1279 | |||
1280 | /* Analog JD Control 1 (0x94) */ | ||
1281 | #define RT5670_JD1_MODE_MASK (0x3 << 0) | ||
1282 | #define RT5670_JD1_MODE_0 (0x0 << 0) | ||
1283 | #define RT5670_JD1_MODE_1 (0x1 << 0) | ||
1284 | #define RT5670_JD1_MODE_2 (0x2 << 0) | ||
1285 | |||
1286 | /* VAD Control 4 (0x9d) */ | ||
1287 | #define RT5670_VAD_SEL_MASK (0x3 << 8) | ||
1288 | #define RT5670_VAD_SEL_SFT 8 | ||
1289 | |||
1290 | /* EQ Control 1 (0xb0) */ | ||
1291 | #define RT5670_EQ_SRC_MASK (0x1 << 15) | ||
1292 | #define RT5670_EQ_SRC_SFT 15 | ||
1293 | #define RT5670_EQ_SRC_DAC (0x0 << 15) | ||
1294 | #define RT5670_EQ_SRC_ADC (0x1 << 15) | ||
1295 | #define RT5670_EQ_UPD (0x1 << 14) | ||
1296 | #define RT5670_EQ_UPD_BIT 14 | ||
1297 | #define RT5670_EQ_CD_MASK (0x1 << 13) | ||
1298 | #define RT5670_EQ_CD_SFT 13 | ||
1299 | #define RT5670_EQ_CD_DIS (0x0 << 13) | ||
1300 | #define RT5670_EQ_CD_EN (0x1 << 13) | ||
1301 | #define RT5670_EQ_DITH_MASK (0x3 << 8) | ||
1302 | #define RT5670_EQ_DITH_SFT 8 | ||
1303 | #define RT5670_EQ_DITH_NOR (0x0 << 8) | ||
1304 | #define RT5670_EQ_DITH_LSB (0x1 << 8) | ||
1305 | #define RT5670_EQ_DITH_LSB_1 (0x2 << 8) | ||
1306 | #define RT5670_EQ_DITH_LSB_2 (0x3 << 8) | ||
1307 | |||
1308 | /* EQ Control 2 (0xb1) */ | ||
1309 | #define RT5670_EQ_HPF1_M_MASK (0x1 << 8) | ||
1310 | #define RT5670_EQ_HPF1_M_SFT 8 | ||
1311 | #define RT5670_EQ_HPF1_M_HI (0x0 << 8) | ||
1312 | #define RT5670_EQ_HPF1_M_1ST (0x1 << 8) | ||
1313 | #define RT5670_EQ_LPF1_M_MASK (0x1 << 7) | ||
1314 | #define RT5670_EQ_LPF1_M_SFT 7 | ||
1315 | #define RT5670_EQ_LPF1_M_LO (0x0 << 7) | ||
1316 | #define RT5670_EQ_LPF1_M_1ST (0x1 << 7) | ||
1317 | #define RT5670_EQ_HPF2_MASK (0x1 << 6) | ||
1318 | #define RT5670_EQ_HPF2_SFT 6 | ||
1319 | #define RT5670_EQ_HPF2_DIS (0x0 << 6) | ||
1320 | #define RT5670_EQ_HPF2_EN (0x1 << 6) | ||
1321 | #define RT5670_EQ_HPF1_MASK (0x1 << 5) | ||
1322 | #define RT5670_EQ_HPF1_SFT 5 | ||
1323 | #define RT5670_EQ_HPF1_DIS (0x0 << 5) | ||
1324 | #define RT5670_EQ_HPF1_EN (0x1 << 5) | ||
1325 | #define RT5670_EQ_BPF4_MASK (0x1 << 4) | ||
1326 | #define RT5670_EQ_BPF4_SFT 4 | ||
1327 | #define RT5670_EQ_BPF4_DIS (0x0 << 4) | ||
1328 | #define RT5670_EQ_BPF4_EN (0x1 << 4) | ||
1329 | #define RT5670_EQ_BPF3_MASK (0x1 << 3) | ||
1330 | #define RT5670_EQ_BPF3_SFT 3 | ||
1331 | #define RT5670_EQ_BPF3_DIS (0x0 << 3) | ||
1332 | #define RT5670_EQ_BPF3_EN (0x1 << 3) | ||
1333 | #define RT5670_EQ_BPF2_MASK (0x1 << 2) | ||
1334 | #define RT5670_EQ_BPF2_SFT 2 | ||
1335 | #define RT5670_EQ_BPF2_DIS (0x0 << 2) | ||
1336 | #define RT5670_EQ_BPF2_EN (0x1 << 2) | ||
1337 | #define RT5670_EQ_BPF1_MASK (0x1 << 1) | ||
1338 | #define RT5670_EQ_BPF1_SFT 1 | ||
1339 | #define RT5670_EQ_BPF1_DIS (0x0 << 1) | ||
1340 | #define RT5670_EQ_BPF1_EN (0x1 << 1) | ||
1341 | #define RT5670_EQ_LPF_MASK (0x1) | ||
1342 | #define RT5670_EQ_LPF_SFT 0 | ||
1343 | #define RT5670_EQ_LPF_DIS (0x0) | ||
1344 | #define RT5670_EQ_LPF_EN (0x1) | ||
1345 | #define RT5670_EQ_CTRL_MASK (0x7f) | ||
1346 | |||
1347 | /* Memory Test (0xb2) */ | ||
1348 | #define RT5670_MT_MASK (0x1 << 15) | ||
1349 | #define RT5670_MT_SFT 15 | ||
1350 | #define RT5670_MT_DIS (0x0 << 15) | ||
1351 | #define RT5670_MT_EN (0x1 << 15) | ||
1352 | |||
1353 | /* DRC/AGC Control 1 (0xb4) */ | ||
1354 | #define RT5670_DRC_AGC_P_MASK (0x1 << 15) | ||
1355 | #define RT5670_DRC_AGC_P_SFT 15 | ||
1356 | #define RT5670_DRC_AGC_P_DAC (0x0 << 15) | ||
1357 | #define RT5670_DRC_AGC_P_ADC (0x1 << 15) | ||
1358 | #define RT5670_DRC_AGC_MASK (0x1 << 14) | ||
1359 | #define RT5670_DRC_AGC_SFT 14 | ||
1360 | #define RT5670_DRC_AGC_DIS (0x0 << 14) | ||
1361 | #define RT5670_DRC_AGC_EN (0x1 << 14) | ||
1362 | #define RT5670_DRC_AGC_UPD (0x1 << 13) | ||
1363 | #define RT5670_DRC_AGC_UPD_BIT 13 | ||
1364 | #define RT5670_DRC_AGC_AR_MASK (0x1f << 8) | ||
1365 | #define RT5670_DRC_AGC_AR_SFT 8 | ||
1366 | #define RT5670_DRC_AGC_R_MASK (0x7 << 5) | ||
1367 | #define RT5670_DRC_AGC_R_SFT 5 | ||
1368 | #define RT5670_DRC_AGC_R_48K (0x1 << 5) | ||
1369 | #define RT5670_DRC_AGC_R_96K (0x2 << 5) | ||
1370 | #define RT5670_DRC_AGC_R_192K (0x3 << 5) | ||
1371 | #define RT5670_DRC_AGC_R_441K (0x5 << 5) | ||
1372 | #define RT5670_DRC_AGC_R_882K (0x6 << 5) | ||
1373 | #define RT5670_DRC_AGC_R_1764K (0x7 << 5) | ||
1374 | #define RT5670_DRC_AGC_RC_MASK (0x1f) | ||
1375 | #define RT5670_DRC_AGC_RC_SFT 0 | ||
1376 | |||
1377 | /* DRC/AGC Control 2 (0xb5) */ | ||
1378 | #define RT5670_DRC_AGC_POB_MASK (0x3f << 8) | ||
1379 | #define RT5670_DRC_AGC_POB_SFT 8 | ||
1380 | #define RT5670_DRC_AGC_CP_MASK (0x1 << 7) | ||
1381 | #define RT5670_DRC_AGC_CP_SFT 7 | ||
1382 | #define RT5670_DRC_AGC_CP_DIS (0x0 << 7) | ||
1383 | #define RT5670_DRC_AGC_CP_EN (0x1 << 7) | ||
1384 | #define RT5670_DRC_AGC_CPR_MASK (0x3 << 5) | ||
1385 | #define RT5670_DRC_AGC_CPR_SFT 5 | ||
1386 | #define RT5670_DRC_AGC_CPR_1_1 (0x0 << 5) | ||
1387 | #define RT5670_DRC_AGC_CPR_1_2 (0x1 << 5) | ||
1388 | #define RT5670_DRC_AGC_CPR_1_3 (0x2 << 5) | ||
1389 | #define RT5670_DRC_AGC_CPR_1_4 (0x3 << 5) | ||
1390 | #define RT5670_DRC_AGC_PRB_MASK (0x1f) | ||
1391 | #define RT5670_DRC_AGC_PRB_SFT 0 | ||
1392 | |||
1393 | /* DRC/AGC Control 3 (0xb6) */ | ||
1394 | #define RT5670_DRC_AGC_NGB_MASK (0xf << 12) | ||
1395 | #define RT5670_DRC_AGC_NGB_SFT 12 | ||
1396 | #define RT5670_DRC_AGC_TAR_MASK (0x1f << 7) | ||
1397 | #define RT5670_DRC_AGC_TAR_SFT 7 | ||
1398 | #define RT5670_DRC_AGC_NG_MASK (0x1 << 6) | ||
1399 | #define RT5670_DRC_AGC_NG_SFT 6 | ||
1400 | #define RT5670_DRC_AGC_NG_DIS (0x0 << 6) | ||
1401 | #define RT5670_DRC_AGC_NG_EN (0x1 << 6) | ||
1402 | #define RT5670_DRC_AGC_NGH_MASK (0x1 << 5) | ||
1403 | #define RT5670_DRC_AGC_NGH_SFT 5 | ||
1404 | #define RT5670_DRC_AGC_NGH_DIS (0x0 << 5) | ||
1405 | #define RT5670_DRC_AGC_NGH_EN (0x1 << 5) | ||
1406 | #define RT5670_DRC_AGC_NGT_MASK (0x1f) | ||
1407 | #define RT5670_DRC_AGC_NGT_SFT 0 | ||
1408 | |||
1409 | /* Jack Detect Control (0xbb) */ | ||
1410 | #define RT5670_JD_MASK (0x7 << 13) | ||
1411 | #define RT5670_JD_SFT 13 | ||
1412 | #define RT5670_JD_DIS (0x0 << 13) | ||
1413 | #define RT5670_JD_GPIO1 (0x1 << 13) | ||
1414 | #define RT5670_JD_JD1_IN4P (0x2 << 13) | ||
1415 | #define RT5670_JD_JD2_IN4N (0x3 << 13) | ||
1416 | #define RT5670_JD_GPIO2 (0x4 << 13) | ||
1417 | #define RT5670_JD_GPIO3 (0x5 << 13) | ||
1418 | #define RT5670_JD_GPIO4 (0x6 << 13) | ||
1419 | #define RT5670_JD_HP_MASK (0x1 << 11) | ||
1420 | #define RT5670_JD_HP_SFT 11 | ||
1421 | #define RT5670_JD_HP_DIS (0x0 << 11) | ||
1422 | #define RT5670_JD_HP_EN (0x1 << 11) | ||
1423 | #define RT5670_JD_HP_TRG_MASK (0x1 << 10) | ||
1424 | #define RT5670_JD_HP_TRG_SFT 10 | ||
1425 | #define RT5670_JD_HP_TRG_LO (0x0 << 10) | ||
1426 | #define RT5670_JD_HP_TRG_HI (0x1 << 10) | ||
1427 | #define RT5670_JD_SPL_MASK (0x1 << 9) | ||
1428 | #define RT5670_JD_SPL_SFT 9 | ||
1429 | #define RT5670_JD_SPL_DIS (0x0 << 9) | ||
1430 | #define RT5670_JD_SPL_EN (0x1 << 9) | ||
1431 | #define RT5670_JD_SPL_TRG_MASK (0x1 << 8) | ||
1432 | #define RT5670_JD_SPL_TRG_SFT 8 | ||
1433 | #define RT5670_JD_SPL_TRG_LO (0x0 << 8) | ||
1434 | #define RT5670_JD_SPL_TRG_HI (0x1 << 8) | ||
1435 | #define RT5670_JD_SPR_MASK (0x1 << 7) | ||
1436 | #define RT5670_JD_SPR_SFT 7 | ||
1437 | #define RT5670_JD_SPR_DIS (0x0 << 7) | ||
1438 | #define RT5670_JD_SPR_EN (0x1 << 7) | ||
1439 | #define RT5670_JD_SPR_TRG_MASK (0x1 << 6) | ||
1440 | #define RT5670_JD_SPR_TRG_SFT 6 | ||
1441 | #define RT5670_JD_SPR_TRG_LO (0x0 << 6) | ||
1442 | #define RT5670_JD_SPR_TRG_HI (0x1 << 6) | ||
1443 | #define RT5670_JD_MO_MASK (0x1 << 5) | ||
1444 | #define RT5670_JD_MO_SFT 5 | ||
1445 | #define RT5670_JD_MO_DIS (0x0 << 5) | ||
1446 | #define RT5670_JD_MO_EN (0x1 << 5) | ||
1447 | #define RT5670_JD_MO_TRG_MASK (0x1 << 4) | ||
1448 | #define RT5670_JD_MO_TRG_SFT 4 | ||
1449 | #define RT5670_JD_MO_TRG_LO (0x0 << 4) | ||
1450 | #define RT5670_JD_MO_TRG_HI (0x1 << 4) | ||
1451 | #define RT5670_JD_LO_MASK (0x1 << 3) | ||
1452 | #define RT5670_JD_LO_SFT 3 | ||
1453 | #define RT5670_JD_LO_DIS (0x0 << 3) | ||
1454 | #define RT5670_JD_LO_EN (0x1 << 3) | ||
1455 | #define RT5670_JD_LO_TRG_MASK (0x1 << 2) | ||
1456 | #define RT5670_JD_LO_TRG_SFT 2 | ||
1457 | #define RT5670_JD_LO_TRG_LO (0x0 << 2) | ||
1458 | #define RT5670_JD_LO_TRG_HI (0x1 << 2) | ||
1459 | #define RT5670_JD1_IN4P_MASK (0x1 << 1) | ||
1460 | #define RT5670_JD1_IN4P_SFT 1 | ||
1461 | #define RT5670_JD1_IN4P_DIS (0x0 << 1) | ||
1462 | #define RT5670_JD1_IN4P_EN (0x1 << 1) | ||
1463 | #define RT5670_JD2_IN4N_MASK (0x1) | ||
1464 | #define RT5670_JD2_IN4N_SFT 0 | ||
1465 | #define RT5670_JD2_IN4N_DIS (0x0) | ||
1466 | #define RT5670_JD2_IN4N_EN (0x1) | ||
1467 | |||
1468 | /* IRQ Control 1 (0xbd) */ | ||
1469 | #define RT5670_IRQ_JD_MASK (0x1 << 15) | ||
1470 | #define RT5670_IRQ_JD_SFT 15 | ||
1471 | #define RT5670_IRQ_JD_BP (0x0 << 15) | ||
1472 | #define RT5670_IRQ_JD_NOR (0x1 << 15) | ||
1473 | #define RT5670_IRQ_OT_MASK (0x1 << 14) | ||
1474 | #define RT5670_IRQ_OT_SFT 14 | ||
1475 | #define RT5670_IRQ_OT_BP (0x0 << 14) | ||
1476 | #define RT5670_IRQ_OT_NOR (0x1 << 14) | ||
1477 | #define RT5670_JD_STKY_MASK (0x1 << 13) | ||
1478 | #define RT5670_JD_STKY_SFT 13 | ||
1479 | #define RT5670_JD_STKY_DIS (0x0 << 13) | ||
1480 | #define RT5670_JD_STKY_EN (0x1 << 13) | ||
1481 | #define RT5670_OT_STKY_MASK (0x1 << 12) | ||
1482 | #define RT5670_OT_STKY_SFT 12 | ||
1483 | #define RT5670_OT_STKY_DIS (0x0 << 12) | ||
1484 | #define RT5670_OT_STKY_EN (0x1 << 12) | ||
1485 | #define RT5670_JD_P_MASK (0x1 << 11) | ||
1486 | #define RT5670_JD_P_SFT 11 | ||
1487 | #define RT5670_JD_P_NOR (0x0 << 11) | ||
1488 | #define RT5670_JD_P_INV (0x1 << 11) | ||
1489 | #define RT5670_OT_P_MASK (0x1 << 10) | ||
1490 | #define RT5670_OT_P_SFT 10 | ||
1491 | #define RT5670_OT_P_NOR (0x0 << 10) | ||
1492 | #define RT5670_OT_P_INV (0x1 << 10) | ||
1493 | #define RT5670_JD1_1_EN_MASK (0x1 << 9) | ||
1494 | #define RT5670_JD1_1_EN_SFT 9 | ||
1495 | #define RT5670_JD1_1_DIS (0x0 << 9) | ||
1496 | #define RT5670_JD1_1_EN (0x1 << 9) | ||
1497 | |||
1498 | /* IRQ Control 2 (0xbe) */ | ||
1499 | #define RT5670_IRQ_MB1_OC_MASK (0x1 << 15) | ||
1500 | #define RT5670_IRQ_MB1_OC_SFT 15 | ||
1501 | #define RT5670_IRQ_MB1_OC_BP (0x0 << 15) | ||
1502 | #define RT5670_IRQ_MB1_OC_NOR (0x1 << 15) | ||
1503 | #define RT5670_IRQ_MB2_OC_MASK (0x1 << 14) | ||
1504 | #define RT5670_IRQ_MB2_OC_SFT 14 | ||
1505 | #define RT5670_IRQ_MB2_OC_BP (0x0 << 14) | ||
1506 | #define RT5670_IRQ_MB2_OC_NOR (0x1 << 14) | ||
1507 | #define RT5670_MB1_OC_STKY_MASK (0x1 << 11) | ||
1508 | #define RT5670_MB1_OC_STKY_SFT 11 | ||
1509 | #define RT5670_MB1_OC_STKY_DIS (0x0 << 11) | ||
1510 | #define RT5670_MB1_OC_STKY_EN (0x1 << 11) | ||
1511 | #define RT5670_MB2_OC_STKY_MASK (0x1 << 10) | ||
1512 | #define RT5670_MB2_OC_STKY_SFT 10 | ||
1513 | #define RT5670_MB2_OC_STKY_DIS (0x0 << 10) | ||
1514 | #define RT5670_MB2_OC_STKY_EN (0x1 << 10) | ||
1515 | #define RT5670_MB1_OC_P_MASK (0x1 << 7) | ||
1516 | #define RT5670_MB1_OC_P_SFT 7 | ||
1517 | #define RT5670_MB1_OC_P_NOR (0x0 << 7) | ||
1518 | #define RT5670_MB1_OC_P_INV (0x1 << 7) | ||
1519 | #define RT5670_MB2_OC_P_MASK (0x1 << 6) | ||
1520 | #define RT5670_MB2_OC_P_SFT 6 | ||
1521 | #define RT5670_MB2_OC_P_NOR (0x0 << 6) | ||
1522 | #define RT5670_MB2_OC_P_INV (0x1 << 6) | ||
1523 | #define RT5670_MB1_OC_CLR (0x1 << 3) | ||
1524 | #define RT5670_MB1_OC_CLR_SFT 3 | ||
1525 | #define RT5670_MB2_OC_CLR (0x1 << 2) | ||
1526 | #define RT5670_MB2_OC_CLR_SFT 2 | ||
1527 | |||
1528 | /* GPIO Control 1 (0xc0) */ | ||
1529 | #define RT5670_GP1_PIN_MASK (0x1 << 15) | ||
1530 | #define RT5670_GP1_PIN_SFT 15 | ||
1531 | #define RT5670_GP1_PIN_GPIO1 (0x0 << 15) | ||
1532 | #define RT5670_GP1_PIN_IRQ (0x1 << 15) | ||
1533 | #define RT5670_GP2_PIN_MASK (0x1 << 14) | ||
1534 | #define RT5670_GP2_PIN_SFT 14 | ||
1535 | #define RT5670_GP2_PIN_GPIO2 (0x0 << 14) | ||
1536 | #define RT5670_GP2_PIN_DMIC1_SCL (0x1 << 14) | ||
1537 | #define RT5670_GP3_PIN_MASK (0x3 << 12) | ||
1538 | #define RT5670_GP3_PIN_SFT 12 | ||
1539 | #define RT5670_GP3_PIN_GPIO3 (0x0 << 12) | ||
1540 | #define RT5670_GP3_PIN_DMIC1_SDA (0x1 << 12) | ||
1541 | #define RT5670_GP3_PIN_IRQ (0x2 << 12) | ||
1542 | #define RT5670_GP4_PIN_MASK (0x1 << 11) | ||
1543 | #define RT5670_GP4_PIN_SFT 11 | ||
1544 | #define RT5670_GP4_PIN_GPIO4 (0x0 << 11) | ||
1545 | #define RT5670_GP4_PIN_DMIC2_SDA (0x1 << 11) | ||
1546 | #define RT5670_DP_SIG_MASK (0x1 << 10) | ||
1547 | #define RT5670_DP_SIG_SFT 10 | ||
1548 | #define RT5670_DP_SIG_TEST (0x0 << 10) | ||
1549 | #define RT5670_DP_SIG_AP (0x1 << 10) | ||
1550 | #define RT5670_GPIO_M_MASK (0x1 << 9) | ||
1551 | #define RT5670_GPIO_M_SFT 9 | ||
1552 | #define RT5670_GPIO_M_FLT (0x0 << 9) | ||
1553 | #define RT5670_GPIO_M_PH (0x1 << 9) | ||
1554 | #define RT5670_I2S2_PIN_MASK (0x1 << 8) | ||
1555 | #define RT5670_I2S2_PIN_SFT 8 | ||
1556 | #define RT5670_I2S2_PIN_I2S (0x0 << 8) | ||
1557 | #define RT5670_I2S2_PIN_GPIO (0x1 << 8) | ||
1558 | #define RT5670_GP5_PIN_MASK (0x1 << 7) | ||
1559 | #define RT5670_GP5_PIN_SFT 7 | ||
1560 | #define RT5670_GP5_PIN_GPIO5 (0x0 << 7) | ||
1561 | #define RT5670_GP5_PIN_DMIC3_SDA (0x1 << 7) | ||
1562 | #define RT5670_GP6_PIN_MASK (0x1 << 6) | ||
1563 | #define RT5670_GP6_PIN_SFT 6 | ||
1564 | #define RT5670_GP6_PIN_GPIO6 (0x0 << 6) | ||
1565 | #define RT5670_GP6_PIN_DMIC1_SDA (0x1 << 6) | ||
1566 | #define RT5670_GP7_PIN_MASK (0x3 << 4) | ||
1567 | #define RT5670_GP7_PIN_SFT 4 | ||
1568 | #define RT5670_GP7_PIN_GPIO7 (0x0 << 4) | ||
1569 | #define RT5670_GP7_PIN_DMIC1_SDA (0x1 << 4) | ||
1570 | #define RT5670_GP7_PIN_PDM_SCL2 (0x2 << 4) | ||
1571 | #define RT5670_GP8_PIN_MASK (0x1 << 3) | ||
1572 | #define RT5670_GP8_PIN_SFT 3 | ||
1573 | #define RT5670_GP8_PIN_GPIO8 (0x0 << 3) | ||
1574 | #define RT5670_GP8_PIN_DMIC2_SDA (0x1 << 3) | ||
1575 | #define RT5670_GP9_PIN_MASK (0x1 << 2) | ||
1576 | #define RT5670_GP9_PIN_SFT 2 | ||
1577 | #define RT5670_GP9_PIN_GPIO9 (0x0 << 2) | ||
1578 | #define RT5670_GP9_PIN_DMIC3_SDA (0x1 << 2) | ||
1579 | #define RT5670_GP10_PIN_MASK (0x3) | ||
1580 | #define RT5670_GP10_PIN_SFT 0 | ||
1581 | #define RT5670_GP10_PIN_GPIO9 (0x0) | ||
1582 | #define RT5670_GP10_PIN_DMIC3_SDA (0x1) | ||
1583 | #define RT5670_GP10_PIN_PDM_ADT2 (0x2) | ||
1584 | |||
1585 | /* GPIO Control 2 (0xc1) */ | ||
1586 | #define RT5670_GP4_PF_MASK (0x1 << 11) | ||
1587 | #define RT5670_GP4_PF_SFT 11 | ||
1588 | #define RT5670_GP4_PF_IN (0x0 << 11) | ||
1589 | #define RT5670_GP4_PF_OUT (0x1 << 11) | ||
1590 | #define RT5670_GP4_OUT_MASK (0x1 << 10) | ||
1591 | #define RT5670_GP4_OUT_SFT 10 | ||
1592 | #define RT5670_GP4_OUT_LO (0x0 << 10) | ||
1593 | #define RT5670_GP4_OUT_HI (0x1 << 10) | ||
1594 | #define RT5670_GP4_P_MASK (0x1 << 9) | ||
1595 | #define RT5670_GP4_P_SFT 9 | ||
1596 | #define RT5670_GP4_P_NOR (0x0 << 9) | ||
1597 | #define RT5670_GP4_P_INV (0x1 << 9) | ||
1598 | #define RT5670_GP3_PF_MASK (0x1 << 8) | ||
1599 | #define RT5670_GP3_PF_SFT 8 | ||
1600 | #define RT5670_GP3_PF_IN (0x0 << 8) | ||
1601 | #define RT5670_GP3_PF_OUT (0x1 << 8) | ||
1602 | #define RT5670_GP3_OUT_MASK (0x1 << 7) | ||
1603 | #define RT5670_GP3_OUT_SFT 7 | ||
1604 | #define RT5670_GP3_OUT_LO (0x0 << 7) | ||
1605 | #define RT5670_GP3_OUT_HI (0x1 << 7) | ||
1606 | #define RT5670_GP3_P_MASK (0x1 << 6) | ||
1607 | #define RT5670_GP3_P_SFT 6 | ||
1608 | #define RT5670_GP3_P_NOR (0x0 << 6) | ||
1609 | #define RT5670_GP3_P_INV (0x1 << 6) | ||
1610 | #define RT5670_GP2_PF_MASK (0x1 << 5) | ||
1611 | #define RT5670_GP2_PF_SFT 5 | ||
1612 | #define RT5670_GP2_PF_IN (0x0 << 5) | ||
1613 | #define RT5670_GP2_PF_OUT (0x1 << 5) | ||
1614 | #define RT5670_GP2_OUT_MASK (0x1 << 4) | ||
1615 | #define RT5670_GP2_OUT_SFT 4 | ||
1616 | #define RT5670_GP2_OUT_LO (0x0 << 4) | ||
1617 | #define RT5670_GP2_OUT_HI (0x1 << 4) | ||
1618 | #define RT5670_GP2_P_MASK (0x1 << 3) | ||
1619 | #define RT5670_GP2_P_SFT 3 | ||
1620 | #define RT5670_GP2_P_NOR (0x0 << 3) | ||
1621 | #define RT5670_GP2_P_INV (0x1 << 3) | ||
1622 | #define RT5670_GP1_PF_MASK (0x1 << 2) | ||
1623 | #define RT5670_GP1_PF_SFT 2 | ||
1624 | #define RT5670_GP1_PF_IN (0x0 << 2) | ||
1625 | #define RT5670_GP1_PF_OUT (0x1 << 2) | ||
1626 | #define RT5670_GP1_OUT_MASK (0x1 << 1) | ||
1627 | #define RT5670_GP1_OUT_SFT 1 | ||
1628 | #define RT5670_GP1_OUT_LO (0x0 << 1) | ||
1629 | #define RT5670_GP1_OUT_HI (0x1 << 1) | ||
1630 | #define RT5670_GP1_P_MASK (0x1) | ||
1631 | #define RT5670_GP1_P_SFT 0 | ||
1632 | #define RT5670_GP1_P_NOR (0x0) | ||
1633 | #define RT5670_GP1_P_INV (0x1) | ||
1634 | |||
1635 | /* Scramble Function (0xcd) */ | ||
1636 | #define RT5670_SCB_KEY_MASK (0xff) | ||
1637 | #define RT5670_SCB_KEY_SFT 0 | ||
1638 | |||
1639 | /* Scramble Control (0xce) */ | ||
1640 | #define RT5670_SCB_SWAP_MASK (0x1 << 15) | ||
1641 | #define RT5670_SCB_SWAP_SFT 15 | ||
1642 | #define RT5670_SCB_SWAP_DIS (0x0 << 15) | ||
1643 | #define RT5670_SCB_SWAP_EN (0x1 << 15) | ||
1644 | #define RT5670_SCB_MASK (0x1 << 14) | ||
1645 | #define RT5670_SCB_SFT 14 | ||
1646 | #define RT5670_SCB_DIS (0x0 << 14) | ||
1647 | #define RT5670_SCB_EN (0x1 << 14) | ||
1648 | |||
1649 | /* Baseback Control (0xcf) */ | ||
1650 | #define RT5670_BB_MASK (0x1 << 15) | ||
1651 | #define RT5670_BB_SFT 15 | ||
1652 | #define RT5670_BB_DIS (0x0 << 15) | ||
1653 | #define RT5670_BB_EN (0x1 << 15) | ||
1654 | #define RT5670_BB_CT_MASK (0x7 << 12) | ||
1655 | #define RT5670_BB_CT_SFT 12 | ||
1656 | #define RT5670_BB_CT_A (0x0 << 12) | ||
1657 | #define RT5670_BB_CT_B (0x1 << 12) | ||
1658 | #define RT5670_BB_CT_C (0x2 << 12) | ||
1659 | #define RT5670_BB_CT_D (0x3 << 12) | ||
1660 | #define RT5670_M_BB_L_MASK (0x1 << 9) | ||
1661 | #define RT5670_M_BB_L_SFT 9 | ||
1662 | #define RT5670_M_BB_R_MASK (0x1 << 8) | ||
1663 | #define RT5670_M_BB_R_SFT 8 | ||
1664 | #define RT5670_M_BB_HPF_L_MASK (0x1 << 7) | ||
1665 | #define RT5670_M_BB_HPF_L_SFT 7 | ||
1666 | #define RT5670_M_BB_HPF_R_MASK (0x1 << 6) | ||
1667 | #define RT5670_M_BB_HPF_R_SFT 6 | ||
1668 | #define RT5670_G_BB_BST_MASK (0x3f) | ||
1669 | #define RT5670_G_BB_BST_SFT 0 | ||
1670 | |||
1671 | /* MP3 Plus Control 1 (0xd0) */ | ||
1672 | #define RT5670_M_MP3_L_MASK (0x1 << 15) | ||
1673 | #define RT5670_M_MP3_L_SFT 15 | ||
1674 | #define RT5670_M_MP3_R_MASK (0x1 << 14) | ||
1675 | #define RT5670_M_MP3_R_SFT 14 | ||
1676 | #define RT5670_M_MP3_MASK (0x1 << 13) | ||
1677 | #define RT5670_M_MP3_SFT 13 | ||
1678 | #define RT5670_M_MP3_DIS (0x0 << 13) | ||
1679 | #define RT5670_M_MP3_EN (0x1 << 13) | ||
1680 | #define RT5670_EG_MP3_MASK (0x1f << 8) | ||
1681 | #define RT5670_EG_MP3_SFT 8 | ||
1682 | #define RT5670_MP3_HLP_MASK (0x1 << 7) | ||
1683 | #define RT5670_MP3_HLP_SFT 7 | ||
1684 | #define RT5670_MP3_HLP_DIS (0x0 << 7) | ||
1685 | #define RT5670_MP3_HLP_EN (0x1 << 7) | ||
1686 | #define RT5670_M_MP3_ORG_L_MASK (0x1 << 6) | ||
1687 | #define RT5670_M_MP3_ORG_L_SFT 6 | ||
1688 | #define RT5670_M_MP3_ORG_R_MASK (0x1 << 5) | ||
1689 | #define RT5670_M_MP3_ORG_R_SFT 5 | ||
1690 | |||
1691 | /* MP3 Plus Control 2 (0xd1) */ | ||
1692 | #define RT5670_MP3_WT_MASK (0x1 << 13) | ||
1693 | #define RT5670_MP3_WT_SFT 13 | ||
1694 | #define RT5670_MP3_WT_1_4 (0x0 << 13) | ||
1695 | #define RT5670_MP3_WT_1_2 (0x1 << 13) | ||
1696 | #define RT5670_OG_MP3_MASK (0x1f << 8) | ||
1697 | #define RT5670_OG_MP3_SFT 8 | ||
1698 | #define RT5670_HG_MP3_MASK (0x3f) | ||
1699 | #define RT5670_HG_MP3_SFT 0 | ||
1700 | |||
1701 | /* 3D HP Control 1 (0xd2) */ | ||
1702 | #define RT5670_3D_CF_MASK (0x1 << 15) | ||
1703 | #define RT5670_3D_CF_SFT 15 | ||
1704 | #define RT5670_3D_CF_DIS (0x0 << 15) | ||
1705 | #define RT5670_3D_CF_EN (0x1 << 15) | ||
1706 | #define RT5670_3D_HP_MASK (0x1 << 14) | ||
1707 | #define RT5670_3D_HP_SFT 14 | ||
1708 | #define RT5670_3D_HP_DIS (0x0 << 14) | ||
1709 | #define RT5670_3D_HP_EN (0x1 << 14) | ||
1710 | #define RT5670_3D_BT_MASK (0x1 << 13) | ||
1711 | #define RT5670_3D_BT_SFT 13 | ||
1712 | #define RT5670_3D_BT_DIS (0x0 << 13) | ||
1713 | #define RT5670_3D_BT_EN (0x1 << 13) | ||
1714 | #define RT5670_3D_1F_MIX_MASK (0x3 << 11) | ||
1715 | #define RT5670_3D_1F_MIX_SFT 11 | ||
1716 | #define RT5670_3D_HP_M_MASK (0x1 << 10) | ||
1717 | #define RT5670_3D_HP_M_SFT 10 | ||
1718 | #define RT5670_3D_HP_M_SUR (0x0 << 10) | ||
1719 | #define RT5670_3D_HP_M_FRO (0x1 << 10) | ||
1720 | #define RT5670_M_3D_HRTF_MASK (0x1 << 9) | ||
1721 | #define RT5670_M_3D_HRTF_SFT 9 | ||
1722 | #define RT5670_M_3D_D2H_MASK (0x1 << 8) | ||
1723 | #define RT5670_M_3D_D2H_SFT 8 | ||
1724 | #define RT5670_M_3D_D2R_MASK (0x1 << 7) | ||
1725 | #define RT5670_M_3D_D2R_SFT 7 | ||
1726 | #define RT5670_M_3D_REVB_MASK (0x1 << 6) | ||
1727 | #define RT5670_M_3D_REVB_SFT 6 | ||
1728 | |||
1729 | /* Adjustable high pass filter control 1 (0xd3) */ | ||
1730 | #define RT5670_2ND_HPF_MASK (0x1 << 15) | ||
1731 | #define RT5670_2ND_HPF_SFT 15 | ||
1732 | #define RT5670_2ND_HPF_DIS (0x0 << 15) | ||
1733 | #define RT5670_2ND_HPF_EN (0x1 << 15) | ||
1734 | #define RT5670_HPF_CF_L_MASK (0x7 << 12) | ||
1735 | #define RT5670_HPF_CF_L_SFT 12 | ||
1736 | #define RT5670_1ST_HPF_MASK (0x1 << 11) | ||
1737 | #define RT5670_1ST_HPF_SFT 11 | ||
1738 | #define RT5670_1ST_HPF_DIS (0x0 << 11) | ||
1739 | #define RT5670_1ST_HPF_EN (0x1 << 11) | ||
1740 | #define RT5670_HPF_CF_R_MASK (0x7 << 8) | ||
1741 | #define RT5670_HPF_CF_R_SFT 8 | ||
1742 | #define RT5670_ZD_T_MASK (0x3 << 6) | ||
1743 | #define RT5670_ZD_T_SFT 6 | ||
1744 | #define RT5670_ZD_F_MASK (0x3 << 4) | ||
1745 | #define RT5670_ZD_F_SFT 4 | ||
1746 | #define RT5670_ZD_F_IM (0x0 << 4) | ||
1747 | #define RT5670_ZD_F_ZC_IM (0x1 << 4) | ||
1748 | #define RT5670_ZD_F_ZC_IOD (0x2 << 4) | ||
1749 | #define RT5670_ZD_F_UN (0x3 << 4) | ||
1750 | |||
1751 | /* HP calibration control and Amp detection (0xd6) */ | ||
1752 | #define RT5670_SI_DAC_MASK (0x1 << 11) | ||
1753 | #define RT5670_SI_DAC_SFT 11 | ||
1754 | #define RT5670_SI_DAC_AUTO (0x0 << 11) | ||
1755 | #define RT5670_SI_DAC_TEST (0x1 << 11) | ||
1756 | #define RT5670_DC_CAL_M_MASK (0x1 << 10) | ||
1757 | #define RT5670_DC_CAL_M_SFT 10 | ||
1758 | #define RT5670_DC_CAL_M_CAL (0x0 << 10) | ||
1759 | #define RT5670_DC_CAL_M_NOR (0x1 << 10) | ||
1760 | #define RT5670_DC_CAL_MASK (0x1 << 9) | ||
1761 | #define RT5670_DC_CAL_SFT 9 | ||
1762 | #define RT5670_DC_CAL_DIS (0x0 << 9) | ||
1763 | #define RT5670_DC_CAL_EN (0x1 << 9) | ||
1764 | #define RT5670_HPD_RCV_MASK (0x7 << 6) | ||
1765 | #define RT5670_HPD_RCV_SFT 6 | ||
1766 | #define RT5670_HPD_PS_MASK (0x1 << 5) | ||
1767 | #define RT5670_HPD_PS_SFT 5 | ||
1768 | #define RT5670_HPD_PS_DIS (0x0 << 5) | ||
1769 | #define RT5670_HPD_PS_EN (0x1 << 5) | ||
1770 | #define RT5670_CAL_M_MASK (0x1 << 4) | ||
1771 | #define RT5670_CAL_M_SFT 4 | ||
1772 | #define RT5670_CAL_M_DEP (0x0 << 4) | ||
1773 | #define RT5670_CAL_M_CAL (0x1 << 4) | ||
1774 | #define RT5670_CAL_MASK (0x1 << 3) | ||
1775 | #define RT5670_CAL_SFT 3 | ||
1776 | #define RT5670_CAL_DIS (0x0 << 3) | ||
1777 | #define RT5670_CAL_EN (0x1 << 3) | ||
1778 | #define RT5670_CAL_TEST_MASK (0x1 << 2) | ||
1779 | #define RT5670_CAL_TEST_SFT 2 | ||
1780 | #define RT5670_CAL_TEST_DIS (0x0 << 2) | ||
1781 | #define RT5670_CAL_TEST_EN (0x1 << 2) | ||
1782 | #define RT5670_CAL_P_MASK (0x3) | ||
1783 | #define RT5670_CAL_P_SFT 0 | ||
1784 | #define RT5670_CAL_P_NONE (0x0) | ||
1785 | #define RT5670_CAL_P_CAL (0x1) | ||
1786 | #define RT5670_CAL_P_DAC_CAL (0x2) | ||
1787 | |||
1788 | /* Soft volume and zero cross control 1 (0xd9) */ | ||
1789 | #define RT5670_SV_MASK (0x1 << 15) | ||
1790 | #define RT5670_SV_SFT 15 | ||
1791 | #define RT5670_SV_DIS (0x0 << 15) | ||
1792 | #define RT5670_SV_EN (0x1 << 15) | ||
1793 | #define RT5670_SPO_SV_MASK (0x1 << 14) | ||
1794 | #define RT5670_SPO_SV_SFT 14 | ||
1795 | #define RT5670_SPO_SV_DIS (0x0 << 14) | ||
1796 | #define RT5670_SPO_SV_EN (0x1 << 14) | ||
1797 | #define RT5670_OUT_SV_MASK (0x1 << 13) | ||
1798 | #define RT5670_OUT_SV_SFT 13 | ||
1799 | #define RT5670_OUT_SV_DIS (0x0 << 13) | ||
1800 | #define RT5670_OUT_SV_EN (0x1 << 13) | ||
1801 | #define RT5670_HP_SV_MASK (0x1 << 12) | ||
1802 | #define RT5670_HP_SV_SFT 12 | ||
1803 | #define RT5670_HP_SV_DIS (0x0 << 12) | ||
1804 | #define RT5670_HP_SV_EN (0x1 << 12) | ||
1805 | #define RT5670_ZCD_DIG_MASK (0x1 << 11) | ||
1806 | #define RT5670_ZCD_DIG_SFT 11 | ||
1807 | #define RT5670_ZCD_DIG_DIS (0x0 << 11) | ||
1808 | #define RT5670_ZCD_DIG_EN (0x1 << 11) | ||
1809 | #define RT5670_ZCD_MASK (0x1 << 10) | ||
1810 | #define RT5670_ZCD_SFT 10 | ||
1811 | #define RT5670_ZCD_PD (0x0 << 10) | ||
1812 | #define RT5670_ZCD_PU (0x1 << 10) | ||
1813 | #define RT5670_M_ZCD_MASK (0x3f << 4) | ||
1814 | #define RT5670_M_ZCD_SFT 4 | ||
1815 | #define RT5670_M_ZCD_RM_L (0x1 << 9) | ||
1816 | #define RT5670_M_ZCD_RM_R (0x1 << 8) | ||
1817 | #define RT5670_M_ZCD_SM_L (0x1 << 7) | ||
1818 | #define RT5670_M_ZCD_SM_R (0x1 << 6) | ||
1819 | #define RT5670_M_ZCD_OM_L (0x1 << 5) | ||
1820 | #define RT5670_M_ZCD_OM_R (0x1 << 4) | ||
1821 | #define RT5670_SV_DLY_MASK (0xf) | ||
1822 | #define RT5670_SV_DLY_SFT 0 | ||
1823 | |||
1824 | /* Soft volume and zero cross control 2 (0xda) */ | ||
1825 | #define RT5670_ZCD_HP_MASK (0x1 << 15) | ||
1826 | #define RT5670_ZCD_HP_SFT 15 | ||
1827 | #define RT5670_ZCD_HP_DIS (0x0 << 15) | ||
1828 | #define RT5670_ZCD_HP_EN (0x1 << 15) | ||
1829 | |||
1830 | |||
1831 | /* Codec Private Register definition */ | ||
1832 | /* 3D Speaker Control (0x63) */ | ||
1833 | #define RT5670_3D_SPK_MASK (0x1 << 15) | ||
1834 | #define RT5670_3D_SPK_SFT 15 | ||
1835 | #define RT5670_3D_SPK_DIS (0x0 << 15) | ||
1836 | #define RT5670_3D_SPK_EN (0x1 << 15) | ||
1837 | #define RT5670_3D_SPK_M_MASK (0x3 << 13) | ||
1838 | #define RT5670_3D_SPK_M_SFT 13 | ||
1839 | #define RT5670_3D_SPK_CG_MASK (0x1f << 8) | ||
1840 | #define RT5670_3D_SPK_CG_SFT 8 | ||
1841 | #define RT5670_3D_SPK_SG_MASK (0x1f) | ||
1842 | #define RT5670_3D_SPK_SG_SFT 0 | ||
1843 | |||
1844 | /* Wind Noise Detection Control 1 (0x6c) */ | ||
1845 | #define RT5670_WND_MASK (0x1 << 15) | ||
1846 | #define RT5670_WND_SFT 15 | ||
1847 | #define RT5670_WND_DIS (0x0 << 15) | ||
1848 | #define RT5670_WND_EN (0x1 << 15) | ||
1849 | |||
1850 | /* Wind Noise Detection Control 2 (0x6d) */ | ||
1851 | #define RT5670_WND_FC_NW_MASK (0x3f << 10) | ||
1852 | #define RT5670_WND_FC_NW_SFT 10 | ||
1853 | #define RT5670_WND_FC_WK_MASK (0x3f << 4) | ||
1854 | #define RT5670_WND_FC_WK_SFT 4 | ||
1855 | |||
1856 | /* Wind Noise Detection Control 3 (0x6e) */ | ||
1857 | #define RT5670_HPF_FC_MASK (0x3f << 6) | ||
1858 | #define RT5670_HPF_FC_SFT 6 | ||
1859 | #define RT5670_WND_FC_ST_MASK (0x3f) | ||
1860 | #define RT5670_WND_FC_ST_SFT 0 | ||
1861 | |||
1862 | /* Wind Noise Detection Control 4 (0x6f) */ | ||
1863 | #define RT5670_WND_TH_LO_MASK (0x3ff) | ||
1864 | #define RT5670_WND_TH_LO_SFT 0 | ||
1865 | |||
1866 | /* Wind Noise Detection Control 5 (0x70) */ | ||
1867 | #define RT5670_WND_TH_HI_MASK (0x3ff) | ||
1868 | #define RT5670_WND_TH_HI_SFT 0 | ||
1869 | |||
1870 | /* Wind Noise Detection Control 8 (0x73) */ | ||
1871 | #define RT5670_WND_WIND_MASK (0x1 << 13) /* Read-Only */ | ||
1872 | #define RT5670_WND_WIND_SFT 13 | ||
1873 | #define RT5670_WND_STRONG_MASK (0x1 << 12) /* Read-Only */ | ||
1874 | #define RT5670_WND_STRONG_SFT 12 | ||
1875 | enum { | ||
1876 | RT5670_NO_WIND, | ||
1877 | RT5670_BREEZE, | ||
1878 | RT5670_STORM, | ||
1879 | }; | ||
1880 | |||
1881 | /* Dipole Speaker Interface (0x75) */ | ||
1882 | #define RT5670_DP_ATT_MASK (0x3 << 14) | ||
1883 | #define RT5670_DP_ATT_SFT 14 | ||
1884 | #define RT5670_DP_SPK_MASK (0x1 << 10) | ||
1885 | #define RT5670_DP_SPK_SFT 10 | ||
1886 | #define RT5670_DP_SPK_DIS (0x0 << 10) | ||
1887 | #define RT5670_DP_SPK_EN (0x1 << 10) | ||
1888 | |||
1889 | /* EQ Pre Volume Control (0xb3) */ | ||
1890 | #define RT5670_EQ_PRE_VOL_MASK (0xffff) | ||
1891 | #define RT5670_EQ_PRE_VOL_SFT 0 | ||
1892 | |||
1893 | /* EQ Post Volume Control (0xb4) */ | ||
1894 | #define RT5670_EQ_PST_VOL_MASK (0xffff) | ||
1895 | #define RT5670_EQ_PST_VOL_SFT 0 | ||
1896 | |||
1897 | /* Jack Detect Control 3 (0xf8) */ | ||
1898 | #define RT5670_CMP_MIC_IN_DET_MASK (0x7 << 12) | ||
1899 | #define RT5670_JD_CBJ_EN (0x1 << 7) | ||
1900 | #define RT5670_JD_CBJ_POL (0x1 << 6) | ||
1901 | #define RT5670_JD_TRI_CBJ_SEL_MASK (0x7 << 3) | ||
1902 | #define RT5670_JD_TRI_CBJ_SEL_SFT (3) | ||
1903 | #define RT5670_JD_CBJ_GPIO_JD1 (0x0 << 3) | ||
1904 | #define RT5670_JD_CBJ_JD1_1 (0x1 << 3) | ||
1905 | #define RT5670_JD_CBJ_JD1_2 (0x2 << 3) | ||
1906 | #define RT5670_JD_CBJ_JD2 (0x3 << 3) | ||
1907 | #define RT5670_JD_CBJ_JD3 (0x4 << 3) | ||
1908 | #define RT5670_JD_CBJ_GPIO_JD2 (0x5 << 3) | ||
1909 | #define RT5670_JD_CBJ_MX0B_12 (0x6 << 3) | ||
1910 | #define RT5670_JD_TRI_HPO_SEL_MASK (0x7 << 3) | ||
1911 | #define RT5670_JD_TRI_HPO_SEL_SFT (0) | ||
1912 | #define RT5670_JD_HPO_GPIO_JD1 (0x0) | ||
1913 | #define RT5670_JD_HPO_JD1_1 (0x1) | ||
1914 | #define RT5670_JD_HPO_JD1_2 (0x2) | ||
1915 | #define RT5670_JD_HPO_JD2 (0x3) | ||
1916 | #define RT5670_JD_HPO_JD3 (0x4) | ||
1917 | #define RT5670_JD_HPO_GPIO_JD2 (0x5) | ||
1918 | #define RT5670_JD_HPO_MX0B_12 (0x6) | ||
1919 | |||
1920 | /* Digital Misc Control (0xfa) */ | ||
1921 | #define RT5670_RST_DSP (0x1 << 13) | ||
1922 | #define RT5670_IF1_ADC1_IN1_SEL (0x1 << 12) | ||
1923 | #define RT5670_IF1_ADC1_IN1_SFT 12 | ||
1924 | #define RT5670_IF1_ADC1_IN2_SEL (0x1 << 11) | ||
1925 | #define RT5670_IF1_ADC1_IN2_SFT 11 | ||
1926 | #define RT5670_IF1_ADC2_IN1_SEL (0x1 << 10) | ||
1927 | #define RT5670_IF1_ADC2_IN1_SFT 10 | ||
1928 | |||
1929 | /* General Control2 (0xfb) */ | ||
1930 | #define RT5670_RXDC_SRC_MASK (0x1 << 7) | ||
1931 | #define RT5670_RXDC_SRC_STO (0x0 << 7) | ||
1932 | #define RT5670_RXDC_SRC_MONO (0x1 << 7) | ||
1933 | #define RT5670_RXDC_SRC_SFT (7) | ||
1934 | #define RT5670_RXDP2_SEL_MASK (0x1 << 3) | ||
1935 | #define RT5670_RXDP2_SEL_IF2 (0x0 << 3) | ||
1936 | #define RT5670_RXDP2_SEL_ADC (0x1 << 3) | ||
1937 | #define RT5670_RXDP2_SEL_SFT (3) | ||
1938 | |||
1939 | /* System Clock Source */ | ||
1940 | enum { | ||
1941 | RT5670_SCLK_S_MCLK, | ||
1942 | RT5670_SCLK_S_PLL1, | ||
1943 | RT5670_SCLK_S_RCCLK, | ||
1944 | }; | ||
1945 | |||
1946 | /* PLL1 Source */ | ||
1947 | enum { | ||
1948 | RT5670_PLL1_S_MCLK, | ||
1949 | RT5670_PLL1_S_BCLK1, | ||
1950 | RT5670_PLL1_S_BCLK2, | ||
1951 | RT5670_PLL1_S_BCLK3, | ||
1952 | RT5670_PLL1_S_BCLK4, | ||
1953 | }; | ||
1954 | |||
1955 | enum { | ||
1956 | RT5670_AIF1, | ||
1957 | RT5670_AIF2, | ||
1958 | RT5670_AIF3, | ||
1959 | RT5670_AIF4, | ||
1960 | RT5670_AIFS, | ||
1961 | }; | ||
1962 | |||
1963 | enum { | ||
1964 | RT5670_DMIC_DATA_GPIO6, | ||
1965 | RT5670_DMIC_DATA_IN2P, | ||
1966 | RT5670_DMIC_DATA_GPIO7, | ||
1967 | }; | ||
1968 | |||
1969 | enum { | ||
1970 | RT5670_DMIC_DATA_GPIO8, | ||
1971 | RT5670_DMIC_DATA_IN3N, | ||
1972 | }; | ||
1973 | |||
1974 | enum { | ||
1975 | RT5670_DMIC_DATA_GPIO9, | ||
1976 | RT5670_DMIC_DATA_GPIO10, | ||
1977 | RT5670_DMIC_DATA_GPIO5, | ||
1978 | }; | ||
1979 | |||
1980 | struct rt5670_priv { | ||
1981 | struct snd_soc_codec *codec; | ||
1982 | struct rt5670_platform_data pdata; | ||
1983 | struct regmap *regmap; | ||
1984 | |||
1985 | int sysclk; | ||
1986 | int sysclk_src; | ||
1987 | int lrck[RT5670_AIFS]; | ||
1988 | int bclk[RT5670_AIFS]; | ||
1989 | int master[RT5670_AIFS]; | ||
1990 | |||
1991 | int pll_src; | ||
1992 | int pll_in; | ||
1993 | int pll_out; | ||
1994 | |||
1995 | int dsp_sw; /* expected parameter setting */ | ||
1996 | int dsp_rate; | ||
1997 | int jack_type; | ||
1998 | }; | ||
1999 | |||
2000 | #endif /* __RT5670_H__ */ | ||
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 833231e27340..67f14556462f 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
28 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
29 | 29 | ||
30 | #include "rl6231.h" | ||
30 | #include "rt5677.h" | 31 | #include "rt5677.h" |
31 | 32 | ||
32 | #define RT5677_DEVICE_ID 0x6327 | 33 | #define RT5677_DEVICE_ID 0x6327 |
@@ -604,19 +605,19 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
604 | adc_vol_tlv), | 605 | adc_vol_tlv), |
605 | 606 | ||
606 | /* ADC Boost Volume Control */ | 607 | /* ADC Boost Volume Control */ |
607 | SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5677_STO1_2_ADC_BST, | 608 | SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST, |
608 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, | 609 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, |
609 | adc_bst_tlv), | 610 | adc_bst_tlv), |
610 | SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5677_STO1_2_ADC_BST, | 611 | SOC_DOUBLE_TLV("STO2 ADC Boost Volume", RT5677_STO1_2_ADC_BST, |
611 | RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0, | 612 | RT5677_STO2_ADC_L_BST_SFT, RT5677_STO2_ADC_R_BST_SFT, 3, 0, |
612 | adc_bst_tlv), | 613 | adc_bst_tlv), |
613 | SOC_DOUBLE_TLV("STO3 ADC Boost Gain", RT5677_STO3_4_ADC_BST, | 614 | SOC_DOUBLE_TLV("STO3 ADC Boost Volume", RT5677_STO3_4_ADC_BST, |
614 | RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0, | 615 | RT5677_STO3_ADC_L_BST_SFT, RT5677_STO3_ADC_R_BST_SFT, 3, 0, |
615 | adc_bst_tlv), | 616 | adc_bst_tlv), |
616 | SOC_DOUBLE_TLV("STO4 ADC Boost Gain", RT5677_STO3_4_ADC_BST, | 617 | SOC_DOUBLE_TLV("STO4 ADC Boost Volume", RT5677_STO3_4_ADC_BST, |
617 | RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0, | 618 | RT5677_STO4_ADC_L_BST_SFT, RT5677_STO4_ADC_R_BST_SFT, 3, 0, |
618 | adc_bst_tlv), | 619 | adc_bst_tlv), |
619 | SOC_DOUBLE_TLV("Mono ADC Boost Gain", RT5677_ADC_BST_CTRL2, | 620 | SOC_DOUBLE_TLV("Mono ADC Boost Volume", RT5677_ADC_BST_CTRL2, |
620 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, | 621 | RT5677_MONO_ADC_L_BST_SFT, RT5677_MONO_ADC_R_BST_SFT, 3, 0, |
621 | adc_bst_tlv), | 622 | adc_bst_tlv), |
622 | }; | 623 | }; |
@@ -636,21 +637,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
636 | { | 637 | { |
637 | struct snd_soc_codec *codec = w->codec; | 638 | struct snd_soc_codec *codec = w->codec; |
638 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 639 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
639 | int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL, i; | 640 | int idx = rl6231_calc_dmic_clk(rt5677->sysclk); |
640 | int rate, red, bound, temp; | ||
641 | |||
642 | rate = rt5677->sysclk; | ||
643 | red = 3000000 * 12; | ||
644 | for (i = 0; i < ARRAY_SIZE(div); i++) { | ||
645 | bound = div[i] * 3000000; | ||
646 | if (rate > bound) | ||
647 | continue; | ||
648 | temp = bound - rate; | ||
649 | if (temp < red) { | ||
650 | red = temp; | ||
651 | idx = i; | ||
652 | } | ||
653 | } | ||
654 | 641 | ||
655 | if (idx < 0) | 642 | if (idx < 0) |
656 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 643 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
@@ -951,7 +938,7 @@ static const struct snd_kcontrol_new rt5677_ob_7_mix[] = { | |||
951 | 938 | ||
952 | 939 | ||
953 | /* Mux */ | 940 | /* Mux */ |
954 | /* DAC1 L/R source */ /* MX-29 [10:8] */ | 941 | /* DAC1 L/R Source */ /* MX-29 [10:8] */ |
955 | static const char * const rt5677_dac1_src[] = { | 942 | static const char * const rt5677_dac1_src[] = { |
956 | "IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01", | 943 | "IF1 DAC 01", "IF2 DAC 01", "IF3 DAC LR", "IF4 DAC LR", "SLB DAC 01", |
957 | "OB 01" | 944 | "OB 01" |
@@ -962,9 +949,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
962 | RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src); | 949 | RT5677_DAC1_L_SEL_SFT, rt5677_dac1_src); |
963 | 950 | ||
964 | static const struct snd_kcontrol_new rt5677_dac1_mux = | 951 | static const struct snd_kcontrol_new rt5677_dac1_mux = |
965 | SOC_DAPM_ENUM("DAC1 source", rt5677_dac1_enum); | 952 | SOC_DAPM_ENUM("DAC1 Source", rt5677_dac1_enum); |
966 | 953 | ||
967 | /* ADDA1 L/R source */ /* MX-29 [1:0] */ | 954 | /* ADDA1 L/R Source */ /* MX-29 [1:0] */ |
968 | static const char * const rt5677_adda1_src[] = { | 955 | static const char * const rt5677_adda1_src[] = { |
969 | "STO1 ADC MIX", "STO2 ADC MIX", "OB 67", | 956 | "STO1 ADC MIX", "STO2 ADC MIX", "OB 67", |
970 | }; | 957 | }; |
@@ -974,10 +961,10 @@ static SOC_ENUM_SINGLE_DECL( | |||
974 | RT5677_ADDA1_SEL_SFT, rt5677_adda1_src); | 961 | RT5677_ADDA1_SEL_SFT, rt5677_adda1_src); |
975 | 962 | ||
976 | static const struct snd_kcontrol_new rt5677_adda1_mux = | 963 | static const struct snd_kcontrol_new rt5677_adda1_mux = |
977 | SOC_DAPM_ENUM("ADDA1 source", rt5677_adda1_enum); | 964 | SOC_DAPM_ENUM("ADDA1 Source", rt5677_adda1_enum); |
978 | 965 | ||
979 | 966 | ||
980 | /*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */ | 967 | /*DAC2 L/R Source*/ /* MX-1B [6:4] [2:0] */ |
981 | static const char * const rt5677_dac2l_src[] = { | 968 | static const char * const rt5677_dac2l_src[] = { |
982 | "IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2", | 969 | "IF1 DAC 2", "IF2 DAC 2", "IF3 DAC L", "IF4 DAC L", "SLB DAC 2", |
983 | "OB 2", | 970 | "OB 2", |
@@ -988,7 +975,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
988 | RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src); | 975 | RT5677_SEL_DAC2_L_SRC_SFT, rt5677_dac2l_src); |
989 | 976 | ||
990 | static const struct snd_kcontrol_new rt5677_dac2_l_mux = | 977 | static const struct snd_kcontrol_new rt5677_dac2_l_mux = |
991 | SOC_DAPM_ENUM("DAC2 L source", rt5677_dac2l_enum); | 978 | SOC_DAPM_ENUM("DAC2 L Source", rt5677_dac2l_enum); |
992 | 979 | ||
993 | static const char * const rt5677_dac2r_src[] = { | 980 | static const char * const rt5677_dac2r_src[] = { |
994 | "IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3", | 981 | "IF1 DAC 3", "IF2 DAC 3", "IF3 DAC R", "IF4 DAC R", "SLB DAC 3", |
@@ -1000,9 +987,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1000 | RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src); | 987 | RT5677_SEL_DAC2_R_SRC_SFT, rt5677_dac2r_src); |
1001 | 988 | ||
1002 | static const struct snd_kcontrol_new rt5677_dac2_r_mux = | 989 | static const struct snd_kcontrol_new rt5677_dac2_r_mux = |
1003 | SOC_DAPM_ENUM("DAC2 R source", rt5677_dac2r_enum); | 990 | SOC_DAPM_ENUM("DAC2 R Source", rt5677_dac2r_enum); |
1004 | 991 | ||
1005 | /*DAC3 L/R source*/ /* MX-16 [6:4] [2:0] */ | 992 | /*DAC3 L/R Source*/ /* MX-16 [6:4] [2:0] */ |
1006 | static const char * const rt5677_dac3l_src[] = { | 993 | static const char * const rt5677_dac3l_src[] = { |
1007 | "IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L", | 994 | "IF1 DAC 4", "IF2 DAC 4", "IF3 DAC L", "IF4 DAC L", |
1008 | "SLB DAC 4", "OB 4" | 995 | "SLB DAC 4", "OB 4" |
@@ -1013,7 +1000,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1013 | RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src); | 1000 | RT5677_SEL_DAC3_L_SRC_SFT, rt5677_dac3l_src); |
1014 | 1001 | ||
1015 | static const struct snd_kcontrol_new rt5677_dac3_l_mux = | 1002 | static const struct snd_kcontrol_new rt5677_dac3_l_mux = |
1016 | SOC_DAPM_ENUM("DAC3 L source", rt5677_dac3l_enum); | 1003 | SOC_DAPM_ENUM("DAC3 L Source", rt5677_dac3l_enum); |
1017 | 1004 | ||
1018 | static const char * const rt5677_dac3r_src[] = { | 1005 | static const char * const rt5677_dac3r_src[] = { |
1019 | "IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R", | 1006 | "IF1 DAC 5", "IF2 DAC 5", "IF3 DAC R", "IF4 DAC R", |
@@ -1025,9 +1012,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1025 | RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src); | 1012 | RT5677_SEL_DAC3_R_SRC_SFT, rt5677_dac3r_src); |
1026 | 1013 | ||
1027 | static const struct snd_kcontrol_new rt5677_dac3_r_mux = | 1014 | static const struct snd_kcontrol_new rt5677_dac3_r_mux = |
1028 | SOC_DAPM_ENUM("DAC3 R source", rt5677_dac3r_enum); | 1015 | SOC_DAPM_ENUM("DAC3 R Source", rt5677_dac3r_enum); |
1029 | 1016 | ||
1030 | /*DAC4 L/R source*/ /* MX-16 [14:12] [10:8] */ | 1017 | /*DAC4 L/R Source*/ /* MX-16 [14:12] [10:8] */ |
1031 | static const char * const rt5677_dac4l_src[] = { | 1018 | static const char * const rt5677_dac4l_src[] = { |
1032 | "IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L", | 1019 | "IF1 DAC 6", "IF2 DAC 6", "IF3 DAC L", "IF4 DAC L", |
1033 | "SLB DAC 6", "OB 6" | 1020 | "SLB DAC 6", "OB 6" |
@@ -1038,7 +1025,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1038 | RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src); | 1025 | RT5677_SEL_DAC4_L_SRC_SFT, rt5677_dac4l_src); |
1039 | 1026 | ||
1040 | static const struct snd_kcontrol_new rt5677_dac4_l_mux = | 1027 | static const struct snd_kcontrol_new rt5677_dac4_l_mux = |
1041 | SOC_DAPM_ENUM("DAC4 L source", rt5677_dac4l_enum); | 1028 | SOC_DAPM_ENUM("DAC4 L Source", rt5677_dac4l_enum); |
1042 | 1029 | ||
1043 | static const char * const rt5677_dac4r_src[] = { | 1030 | static const char * const rt5677_dac4r_src[] = { |
1044 | "IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R", | 1031 | "IF1 DAC 7", "IF2 DAC 7", "IF3 DAC R", "IF4 DAC R", |
@@ -1050,7 +1037,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1050 | RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src); | 1037 | RT5677_SEL_DAC4_R_SRC_SFT, rt5677_dac4r_src); |
1051 | 1038 | ||
1052 | static const struct snd_kcontrol_new rt5677_dac4_r_mux = | 1039 | static const struct snd_kcontrol_new rt5677_dac4_r_mux = |
1053 | SOC_DAPM_ENUM("DAC4 R source", rt5677_dac4r_enum); | 1040 | SOC_DAPM_ENUM("DAC4 R Source", rt5677_dac4r_enum); |
1054 | 1041 | ||
1055 | /* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */ | 1042 | /* In/OutBound Source Pass SRC */ /* MX-A5 [3] [4] [0] [1] [2] */ |
1056 | static const char * const rt5677_iob_bypass_src[] = { | 1043 | static const char * const rt5677_iob_bypass_src[] = { |
@@ -1062,35 +1049,35 @@ static SOC_ENUM_SINGLE_DECL( | |||
1062 | RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src); | 1049 | RT5677_SEL_SRC_OB01_SFT, rt5677_iob_bypass_src); |
1063 | 1050 | ||
1064 | static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux = | 1051 | static const struct snd_kcontrol_new rt5677_ob01_bypass_src_mux = |
1065 | SOC_DAPM_ENUM("OB01 Bypass source", rt5677_ob01_bypass_src_enum); | 1052 | SOC_DAPM_ENUM("OB01 Bypass Source", rt5677_ob01_bypass_src_enum); |
1066 | 1053 | ||
1067 | static SOC_ENUM_SINGLE_DECL( | 1054 | static SOC_ENUM_SINGLE_DECL( |
1068 | rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1055 | rt5677_ob23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1069 | RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src); | 1056 | RT5677_SEL_SRC_OB23_SFT, rt5677_iob_bypass_src); |
1070 | 1057 | ||
1071 | static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux = | 1058 | static const struct snd_kcontrol_new rt5677_ob23_bypass_src_mux = |
1072 | SOC_DAPM_ENUM("OB23 Bypass source", rt5677_ob23_bypass_src_enum); | 1059 | SOC_DAPM_ENUM("OB23 Bypass Source", rt5677_ob23_bypass_src_enum); |
1073 | 1060 | ||
1074 | static SOC_ENUM_SINGLE_DECL( | 1061 | static SOC_ENUM_SINGLE_DECL( |
1075 | rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1062 | rt5677_ib01_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1076 | RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src); | 1063 | RT5677_SEL_SRC_IB01_SFT, rt5677_iob_bypass_src); |
1077 | 1064 | ||
1078 | static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux = | 1065 | static const struct snd_kcontrol_new rt5677_ib01_bypass_src_mux = |
1079 | SOC_DAPM_ENUM("IB01 Bypass source", rt5677_ib01_bypass_src_enum); | 1066 | SOC_DAPM_ENUM("IB01 Bypass Source", rt5677_ib01_bypass_src_enum); |
1080 | 1067 | ||
1081 | static SOC_ENUM_SINGLE_DECL( | 1068 | static SOC_ENUM_SINGLE_DECL( |
1082 | rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1069 | rt5677_ib23_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1083 | RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src); | 1070 | RT5677_SEL_SRC_IB23_SFT, rt5677_iob_bypass_src); |
1084 | 1071 | ||
1085 | static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux = | 1072 | static const struct snd_kcontrol_new rt5677_ib23_bypass_src_mux = |
1086 | SOC_DAPM_ENUM("IB23 Bypass source", rt5677_ib23_bypass_src_enum); | 1073 | SOC_DAPM_ENUM("IB23 Bypass Source", rt5677_ib23_bypass_src_enum); |
1087 | 1074 | ||
1088 | static SOC_ENUM_SINGLE_DECL( | 1075 | static SOC_ENUM_SINGLE_DECL( |
1089 | rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, | 1076 | rt5677_ib45_bypass_src_enum, RT5677_DSP_IN_OUTB_CTRL, |
1090 | RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src); | 1077 | RT5677_SEL_SRC_IB45_SFT, rt5677_iob_bypass_src); |
1091 | 1078 | ||
1092 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = | 1079 | static const struct snd_kcontrol_new rt5677_ib45_bypass_src_mux = |
1093 | SOC_DAPM_ENUM("IB45 Bypass source", rt5677_ib45_bypass_src_enum); | 1080 | SOC_DAPM_ENUM("IB45 Bypass Source", rt5677_ib45_bypass_src_enum); |
1094 | 1081 | ||
1095 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ | 1082 | /* Stereo ADC Source 2 */ /* MX-27 MX26 MX25 [11:10] */ |
1096 | static const char * const rt5677_stereo_adc2_src[] = { | 1083 | static const char * const rt5677_stereo_adc2_src[] = { |
@@ -1102,21 +1089,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1102 | RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src); | 1089 | RT5677_SEL_STO1_ADC2_SFT, rt5677_stereo_adc2_src); |
1103 | 1090 | ||
1104 | static const struct snd_kcontrol_new rt5677_sto1_adc2_mux = | 1091 | static const struct snd_kcontrol_new rt5677_sto1_adc2_mux = |
1105 | SOC_DAPM_ENUM("Stereo1 ADC2 source", rt5677_stereo1_adc2_enum); | 1092 | SOC_DAPM_ENUM("Stereo1 ADC2 Source", rt5677_stereo1_adc2_enum); |
1106 | 1093 | ||
1107 | static SOC_ENUM_SINGLE_DECL( | 1094 | static SOC_ENUM_SINGLE_DECL( |
1108 | rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER, | 1095 | rt5677_stereo2_adc2_enum, RT5677_STO2_ADC_MIXER, |
1109 | RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src); | 1096 | RT5677_SEL_STO2_ADC2_SFT, rt5677_stereo_adc2_src); |
1110 | 1097 | ||
1111 | static const struct snd_kcontrol_new rt5677_sto2_adc2_mux = | 1098 | static const struct snd_kcontrol_new rt5677_sto2_adc2_mux = |
1112 | SOC_DAPM_ENUM("Stereo2 ADC2 source", rt5677_stereo2_adc2_enum); | 1099 | SOC_DAPM_ENUM("Stereo2 ADC2 Source", rt5677_stereo2_adc2_enum); |
1113 | 1100 | ||
1114 | static SOC_ENUM_SINGLE_DECL( | 1101 | static SOC_ENUM_SINGLE_DECL( |
1115 | rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER, | 1102 | rt5677_stereo3_adc2_enum, RT5677_STO3_ADC_MIXER, |
1116 | RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src); | 1103 | RT5677_SEL_STO3_ADC2_SFT, rt5677_stereo_adc2_src); |
1117 | 1104 | ||
1118 | static const struct snd_kcontrol_new rt5677_sto3_adc2_mux = | 1105 | static const struct snd_kcontrol_new rt5677_sto3_adc2_mux = |
1119 | SOC_DAPM_ENUM("Stereo3 ADC2 source", rt5677_stereo3_adc2_enum); | 1106 | SOC_DAPM_ENUM("Stereo3 ADC2 Source", rt5677_stereo3_adc2_enum); |
1120 | 1107 | ||
1121 | /* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */ | 1108 | /* DMIC Source */ /* MX-28 [9:8][1:0] MX-27 MX-26 MX-25 MX-24 [9:8] */ |
1122 | static const char * const rt5677_dmic_src[] = { | 1109 | static const char * const rt5677_dmic_src[] = { |
@@ -1128,44 +1115,44 @@ static SOC_ENUM_SINGLE_DECL( | |||
1128 | RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src); | 1115 | RT5677_SEL_MONO_DMIC_L_SFT, rt5677_dmic_src); |
1129 | 1116 | ||
1130 | static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux = | 1117 | static const struct snd_kcontrol_new rt5677_mono_dmic_l_mux = |
1131 | SOC_DAPM_ENUM("Mono DMIC L source", rt5677_mono_dmic_l_enum); | 1118 | SOC_DAPM_ENUM("Mono DMIC L Source", rt5677_mono_dmic_l_enum); |
1132 | 1119 | ||
1133 | static SOC_ENUM_SINGLE_DECL( | 1120 | static SOC_ENUM_SINGLE_DECL( |
1134 | rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER, | 1121 | rt5677_mono_dmic_r_enum, RT5677_MONO_ADC_MIXER, |
1135 | RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src); | 1122 | RT5677_SEL_MONO_DMIC_R_SFT, rt5677_dmic_src); |
1136 | 1123 | ||
1137 | static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux = | 1124 | static const struct snd_kcontrol_new rt5677_mono_dmic_r_mux = |
1138 | SOC_DAPM_ENUM("Mono DMIC R source", rt5677_mono_dmic_r_enum); | 1125 | SOC_DAPM_ENUM("Mono DMIC R Source", rt5677_mono_dmic_r_enum); |
1139 | 1126 | ||
1140 | static SOC_ENUM_SINGLE_DECL( | 1127 | static SOC_ENUM_SINGLE_DECL( |
1141 | rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER, | 1128 | rt5677_stereo1_dmic_enum, RT5677_STO1_ADC_MIXER, |
1142 | RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src); | 1129 | RT5677_SEL_STO1_DMIC_SFT, rt5677_dmic_src); |
1143 | 1130 | ||
1144 | static const struct snd_kcontrol_new rt5677_sto1_dmic_mux = | 1131 | static const struct snd_kcontrol_new rt5677_sto1_dmic_mux = |
1145 | SOC_DAPM_ENUM("Stereo1 DMIC source", rt5677_stereo1_dmic_enum); | 1132 | SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5677_stereo1_dmic_enum); |
1146 | 1133 | ||
1147 | static SOC_ENUM_SINGLE_DECL( | 1134 | static SOC_ENUM_SINGLE_DECL( |
1148 | rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER, | 1135 | rt5677_stereo2_dmic_enum, RT5677_STO2_ADC_MIXER, |
1149 | RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src); | 1136 | RT5677_SEL_STO2_DMIC_SFT, rt5677_dmic_src); |
1150 | 1137 | ||
1151 | static const struct snd_kcontrol_new rt5677_sto2_dmic_mux = | 1138 | static const struct snd_kcontrol_new rt5677_sto2_dmic_mux = |
1152 | SOC_DAPM_ENUM("Stereo2 DMIC source", rt5677_stereo2_dmic_enum); | 1139 | SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5677_stereo2_dmic_enum); |
1153 | 1140 | ||
1154 | static SOC_ENUM_SINGLE_DECL( | 1141 | static SOC_ENUM_SINGLE_DECL( |
1155 | rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER, | 1142 | rt5677_stereo3_dmic_enum, RT5677_STO3_ADC_MIXER, |
1156 | RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src); | 1143 | RT5677_SEL_STO3_DMIC_SFT, rt5677_dmic_src); |
1157 | 1144 | ||
1158 | static const struct snd_kcontrol_new rt5677_sto3_dmic_mux = | 1145 | static const struct snd_kcontrol_new rt5677_sto3_dmic_mux = |
1159 | SOC_DAPM_ENUM("Stereo3 DMIC source", rt5677_stereo3_dmic_enum); | 1146 | SOC_DAPM_ENUM("Stereo3 DMIC Source", rt5677_stereo3_dmic_enum); |
1160 | 1147 | ||
1161 | static SOC_ENUM_SINGLE_DECL( | 1148 | static SOC_ENUM_SINGLE_DECL( |
1162 | rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER, | 1149 | rt5677_stereo4_dmic_enum, RT5677_STO4_ADC_MIXER, |
1163 | RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src); | 1150 | RT5677_SEL_STO4_DMIC_SFT, rt5677_dmic_src); |
1164 | 1151 | ||
1165 | static const struct snd_kcontrol_new rt5677_sto4_dmic_mux = | 1152 | static const struct snd_kcontrol_new rt5677_sto4_dmic_mux = |
1166 | SOC_DAPM_ENUM("Stereo4 DMIC source", rt5677_stereo4_dmic_enum); | 1153 | SOC_DAPM_ENUM("Stereo4 DMIC Source", rt5677_stereo4_dmic_enum); |
1167 | 1154 | ||
1168 | /* Stereo2 ADC source */ /* MX-26 [0] */ | 1155 | /* Stereo2 ADC Source */ /* MX-26 [0] */ |
1169 | static const char * const rt5677_stereo2_adc_lr_src[] = { | 1156 | static const char * const rt5677_stereo2_adc_lr_src[] = { |
1170 | "L", "LR" | 1157 | "L", "LR" |
1171 | }; | 1158 | }; |
@@ -1175,7 +1162,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1175 | RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src); | 1162 | RT5677_SEL_STO2_LR_MIX_SFT, rt5677_stereo2_adc_lr_src); |
1176 | 1163 | ||
1177 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = | 1164 | static const struct snd_kcontrol_new rt5677_sto2_adc_lr_mux = |
1178 | SOC_DAPM_ENUM("Stereo2 ADC LR source", rt5677_stereo2_adc_lr_enum); | 1165 | SOC_DAPM_ENUM("Stereo2 ADC LR Source", rt5677_stereo2_adc_lr_enum); |
1179 | 1166 | ||
1180 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ | 1167 | /* Stereo1 ADC Source 1 */ /* MX-27 MX26 MX25 [13:12] */ |
1181 | static const char * const rt5677_stereo_adc1_src[] = { | 1168 | static const char * const rt5677_stereo_adc1_src[] = { |
@@ -1187,23 +1174,23 @@ static SOC_ENUM_SINGLE_DECL( | |||
1187 | RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src); | 1174 | RT5677_SEL_STO1_ADC1_SFT, rt5677_stereo_adc1_src); |
1188 | 1175 | ||
1189 | static const struct snd_kcontrol_new rt5677_sto1_adc1_mux = | 1176 | static const struct snd_kcontrol_new rt5677_sto1_adc1_mux = |
1190 | SOC_DAPM_ENUM("Stereo1 ADC1 source", rt5677_stereo1_adc1_enum); | 1177 | SOC_DAPM_ENUM("Stereo1 ADC1 Source", rt5677_stereo1_adc1_enum); |
1191 | 1178 | ||
1192 | static SOC_ENUM_SINGLE_DECL( | 1179 | static SOC_ENUM_SINGLE_DECL( |
1193 | rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER, | 1180 | rt5677_stereo2_adc1_enum, RT5677_STO2_ADC_MIXER, |
1194 | RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src); | 1181 | RT5677_SEL_STO2_ADC1_SFT, rt5677_stereo_adc1_src); |
1195 | 1182 | ||
1196 | static const struct snd_kcontrol_new rt5677_sto2_adc1_mux = | 1183 | static const struct snd_kcontrol_new rt5677_sto2_adc1_mux = |
1197 | SOC_DAPM_ENUM("Stereo2 ADC1 source", rt5677_stereo2_adc1_enum); | 1184 | SOC_DAPM_ENUM("Stereo2 ADC1 Source", rt5677_stereo2_adc1_enum); |
1198 | 1185 | ||
1199 | static SOC_ENUM_SINGLE_DECL( | 1186 | static SOC_ENUM_SINGLE_DECL( |
1200 | rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER, | 1187 | rt5677_stereo3_adc1_enum, RT5677_STO3_ADC_MIXER, |
1201 | RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src); | 1188 | RT5677_SEL_STO3_ADC1_SFT, rt5677_stereo_adc1_src); |
1202 | 1189 | ||
1203 | static const struct snd_kcontrol_new rt5677_sto3_adc1_mux = | 1190 | static const struct snd_kcontrol_new rt5677_sto3_adc1_mux = |
1204 | SOC_DAPM_ENUM("Stereo3 ADC1 source", rt5677_stereo3_adc1_enum); | 1191 | SOC_DAPM_ENUM("Stereo3 ADC1 Source", rt5677_stereo3_adc1_enum); |
1205 | 1192 | ||
1206 | /* Mono ADC Left source 2 */ /* MX-28 [11:10] */ | 1193 | /* Mono ADC Left Source 2 */ /* MX-28 [11:10] */ |
1207 | static const char * const rt5677_mono_adc2_l_src[] = { | 1194 | static const char * const rt5677_mono_adc2_l_src[] = { |
1208 | "DD MIX1L", "DMIC", "MONO DAC MIXL" | 1195 | "DD MIX1L", "DMIC", "MONO DAC MIXL" |
1209 | }; | 1196 | }; |
@@ -1213,9 +1200,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1213 | RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src); | 1200 | RT5677_SEL_MONO_ADC_L2_SFT, rt5677_mono_adc2_l_src); |
1214 | 1201 | ||
1215 | static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux = | 1202 | static const struct snd_kcontrol_new rt5677_mono_adc2_l_mux = |
1216 | SOC_DAPM_ENUM("Mono ADC2 L source", rt5677_mono_adc2_l_enum); | 1203 | SOC_DAPM_ENUM("Mono ADC2 L Source", rt5677_mono_adc2_l_enum); |
1217 | 1204 | ||
1218 | /* Mono ADC Left source 1 */ /* MX-28 [13:12] */ | 1205 | /* Mono ADC Left Source 1 */ /* MX-28 [13:12] */ |
1219 | static const char * const rt5677_mono_adc1_l_src[] = { | 1206 | static const char * const rt5677_mono_adc1_l_src[] = { |
1220 | "DD MIX1L", "ADC1", "MONO DAC MIXL" | 1207 | "DD MIX1L", "ADC1", "MONO DAC MIXL" |
1221 | }; | 1208 | }; |
@@ -1225,9 +1212,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1225 | RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src); | 1212 | RT5677_SEL_MONO_ADC_L1_SFT, rt5677_mono_adc1_l_src); |
1226 | 1213 | ||
1227 | static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux = | 1214 | static const struct snd_kcontrol_new rt5677_mono_adc1_l_mux = |
1228 | SOC_DAPM_ENUM("Mono ADC1 L source", rt5677_mono_adc1_l_enum); | 1215 | SOC_DAPM_ENUM("Mono ADC1 L Source", rt5677_mono_adc1_l_enum); |
1229 | 1216 | ||
1230 | /* Mono ADC Right source 2 */ /* MX-28 [3:2] */ | 1217 | /* Mono ADC Right Source 2 */ /* MX-28 [3:2] */ |
1231 | static const char * const rt5677_mono_adc2_r_src[] = { | 1218 | static const char * const rt5677_mono_adc2_r_src[] = { |
1232 | "DD MIX1R", "DMIC", "MONO DAC MIXR" | 1219 | "DD MIX1R", "DMIC", "MONO DAC MIXR" |
1233 | }; | 1220 | }; |
@@ -1237,9 +1224,9 @@ static SOC_ENUM_SINGLE_DECL( | |||
1237 | RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src); | 1224 | RT5677_SEL_MONO_ADC_R2_SFT, rt5677_mono_adc2_r_src); |
1238 | 1225 | ||
1239 | static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux = | 1226 | static const struct snd_kcontrol_new rt5677_mono_adc2_r_mux = |
1240 | SOC_DAPM_ENUM("Mono ADC2 R source", rt5677_mono_adc2_r_enum); | 1227 | SOC_DAPM_ENUM("Mono ADC2 R Source", rt5677_mono_adc2_r_enum); |
1241 | 1228 | ||
1242 | /* Mono ADC Right source 1 */ /* MX-28 [5:4] */ | 1229 | /* Mono ADC Right Source 1 */ /* MX-28 [5:4] */ |
1243 | static const char * const rt5677_mono_adc1_r_src[] = { | 1230 | static const char * const rt5677_mono_adc1_r_src[] = { |
1244 | "DD MIX1R", "ADC2", "MONO DAC MIXR" | 1231 | "DD MIX1R", "ADC2", "MONO DAC MIXR" |
1245 | }; | 1232 | }; |
@@ -1249,7 +1236,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1249 | RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src); | 1236 | RT5677_SEL_MONO_ADC_R1_SFT, rt5677_mono_adc1_r_src); |
1250 | 1237 | ||
1251 | static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux = | 1238 | static const struct snd_kcontrol_new rt5677_mono_adc1_r_mux = |
1252 | SOC_DAPM_ENUM("Mono ADC1 R source", rt5677_mono_adc1_r_enum); | 1239 | SOC_DAPM_ENUM("Mono ADC1 R Source", rt5677_mono_adc1_r_enum); |
1253 | 1240 | ||
1254 | /* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */ | 1241 | /* Stereo4 ADC Source 2 */ /* MX-24 [11:10] */ |
1255 | static const char * const rt5677_stereo4_adc2_src[] = { | 1242 | static const char * const rt5677_stereo4_adc2_src[] = { |
@@ -1261,7 +1248,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1261 | RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src); | 1248 | RT5677_SEL_STO4_ADC2_SFT, rt5677_stereo4_adc2_src); |
1262 | 1249 | ||
1263 | static const struct snd_kcontrol_new rt5677_sto4_adc2_mux = | 1250 | static const struct snd_kcontrol_new rt5677_sto4_adc2_mux = |
1264 | SOC_DAPM_ENUM("Stereo4 ADC2 source", rt5677_stereo4_adc2_enum); | 1251 | SOC_DAPM_ENUM("Stereo4 ADC2 Source", rt5677_stereo4_adc2_enum); |
1265 | 1252 | ||
1266 | 1253 | ||
1267 | /* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */ | 1254 | /* Stereo4 ADC Source 1 */ /* MX-24 [13:12] */ |
@@ -1274,7 +1261,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1274 | RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src); | 1261 | RT5677_SEL_STO4_ADC1_SFT, rt5677_stereo4_adc1_src); |
1275 | 1262 | ||
1276 | static const struct snd_kcontrol_new rt5677_sto4_adc1_mux = | 1263 | static const struct snd_kcontrol_new rt5677_sto4_adc1_mux = |
1277 | SOC_DAPM_ENUM("Stereo4 ADC1 source", rt5677_stereo4_adc1_enum); | 1264 | SOC_DAPM_ENUM("Stereo4 ADC1 Source", rt5677_stereo4_adc1_enum); |
1278 | 1265 | ||
1279 | /* InBound0/1 Source */ /* MX-A3 [14:12] */ | 1266 | /* InBound0/1 Source */ /* MX-A3 [14:12] */ |
1280 | static const char * const rt5677_inbound01_src[] = { | 1267 | static const char * const rt5677_inbound01_src[] = { |
@@ -1416,7 +1403,7 @@ static SOC_ENUM_SINGLE_DECL( | |||
1416 | static const struct snd_kcontrol_new rt5677_dac3_mux = | 1403 | static const struct snd_kcontrol_new rt5677_dac3_mux = |
1417 | SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum); | 1404 | SOC_DAPM_ENUM("Analog DAC3 Source", rt5677_dac3_enum); |
1418 | 1405 | ||
1419 | /* PDM channel source */ /* MX-31 [13:12][9:8][5:4][1:0] */ | 1406 | /* PDM channel Source */ /* MX-31 [13:12][9:8][5:4][1:0] */ |
1420 | static const char * const rt5677_pdm_src[] = { | 1407 | static const char * const rt5677_pdm_src[] = { |
1421 | "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2" | 1408 | "STO1 DAC MIX", "MONO DAC MIX", "DD MIX1", "DD MIX2" |
1422 | }; | 1409 | }; |
@@ -1426,28 +1413,28 @@ static SOC_ENUM_SINGLE_DECL( | |||
1426 | RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src); | 1413 | RT5677_SEL_PDM1_L_SFT, rt5677_pdm_src); |
1427 | 1414 | ||
1428 | static const struct snd_kcontrol_new rt5677_pdm1_l_mux = | 1415 | static const struct snd_kcontrol_new rt5677_pdm1_l_mux = |
1429 | SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_l_enum); | 1416 | SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_l_enum); |
1430 | 1417 | ||
1431 | static SOC_ENUM_SINGLE_DECL( | 1418 | static SOC_ENUM_SINGLE_DECL( |
1432 | rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL, | 1419 | rt5677_pdm2_l_enum, RT5677_PDM_OUT_CTRL, |
1433 | RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src); | 1420 | RT5677_SEL_PDM2_L_SFT, rt5677_pdm_src); |
1434 | 1421 | ||
1435 | static const struct snd_kcontrol_new rt5677_pdm2_l_mux = | 1422 | static const struct snd_kcontrol_new rt5677_pdm2_l_mux = |
1436 | SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_l_enum); | 1423 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_l_enum); |
1437 | 1424 | ||
1438 | static SOC_ENUM_SINGLE_DECL( | 1425 | static SOC_ENUM_SINGLE_DECL( |
1439 | rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL, | 1426 | rt5677_pdm1_r_enum, RT5677_PDM_OUT_CTRL, |
1440 | RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src); | 1427 | RT5677_SEL_PDM1_R_SFT, rt5677_pdm_src); |
1441 | 1428 | ||
1442 | static const struct snd_kcontrol_new rt5677_pdm1_r_mux = | 1429 | static const struct snd_kcontrol_new rt5677_pdm1_r_mux = |
1443 | SOC_DAPM_ENUM("PDM1 source", rt5677_pdm1_r_enum); | 1430 | SOC_DAPM_ENUM("PDM1 Source", rt5677_pdm1_r_enum); |
1444 | 1431 | ||
1445 | static SOC_ENUM_SINGLE_DECL( | 1432 | static SOC_ENUM_SINGLE_DECL( |
1446 | rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL, | 1433 | rt5677_pdm2_r_enum, RT5677_PDM_OUT_CTRL, |
1447 | RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src); | 1434 | RT5677_SEL_PDM2_R_SFT, rt5677_pdm_src); |
1448 | 1435 | ||
1449 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = | 1436 | static const struct snd_kcontrol_new rt5677_pdm2_r_mux = |
1450 | SOC_DAPM_ENUM("PDM2 source", rt5677_pdm2_r_enum); | 1437 | SOC_DAPM_ENUM("PDM2 Source", rt5677_pdm2_r_enum); |
1451 | 1438 | ||
1452 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/ | 1439 | /* TDM IF1/2 SLB ADC1 Data Selection */ /* MX-3C MX-41 [5:4] MX-08 [1:0]*/ |
1453 | static const char * const rt5677_if12_adc1_src[] = { | 1440 | static const char * const rt5677_if12_adc1_src[] = { |
@@ -1459,21 +1446,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1459 | RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src); | 1446 | RT5677_IF1_ADC1_SFT, rt5677_if12_adc1_src); |
1460 | 1447 | ||
1461 | static const struct snd_kcontrol_new rt5677_if1_adc1_mux = | 1448 | static const struct snd_kcontrol_new rt5677_if1_adc1_mux = |
1462 | SOC_DAPM_ENUM("IF1 ADC1 source", rt5677_if1_adc1_enum); | 1449 | SOC_DAPM_ENUM("IF1 ADC1 Source", rt5677_if1_adc1_enum); |
1463 | 1450 | ||
1464 | static SOC_ENUM_SINGLE_DECL( | 1451 | static SOC_ENUM_SINGLE_DECL( |
1465 | rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2, | 1452 | rt5677_if2_adc1_enum, RT5677_TDM2_CTRL2, |
1466 | RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src); | 1453 | RT5677_IF2_ADC1_SFT, rt5677_if12_adc1_src); |
1467 | 1454 | ||
1468 | static const struct snd_kcontrol_new rt5677_if2_adc1_mux = | 1455 | static const struct snd_kcontrol_new rt5677_if2_adc1_mux = |
1469 | SOC_DAPM_ENUM("IF2 ADC1 source", rt5677_if2_adc1_enum); | 1456 | SOC_DAPM_ENUM("IF2 ADC1 Source", rt5677_if2_adc1_enum); |
1470 | 1457 | ||
1471 | static SOC_ENUM_SINGLE_DECL( | 1458 | static SOC_ENUM_SINGLE_DECL( |
1472 | rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX, | 1459 | rt5677_slb_adc1_enum, RT5677_SLIMBUS_RX, |
1473 | RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src); | 1460 | RT5677_SLB_ADC1_SFT, rt5677_if12_adc1_src); |
1474 | 1461 | ||
1475 | static const struct snd_kcontrol_new rt5677_slb_adc1_mux = | 1462 | static const struct snd_kcontrol_new rt5677_slb_adc1_mux = |
1476 | SOC_DAPM_ENUM("SLB ADC1 source", rt5677_slb_adc1_enum); | 1463 | SOC_DAPM_ENUM("SLB ADC1 Source", rt5677_slb_adc1_enum); |
1477 | 1464 | ||
1478 | /* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */ | 1465 | /* TDM IF1/2 SLB ADC2 Data Selection */ /* MX-3C MX-41 [7:6] MX-08 [3:2] */ |
1479 | static const char * const rt5677_if12_adc2_src[] = { | 1466 | static const char * const rt5677_if12_adc2_src[] = { |
@@ -1485,21 +1472,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1485 | RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src); | 1472 | RT5677_IF1_ADC2_SFT, rt5677_if12_adc2_src); |
1486 | 1473 | ||
1487 | static const struct snd_kcontrol_new rt5677_if1_adc2_mux = | 1474 | static const struct snd_kcontrol_new rt5677_if1_adc2_mux = |
1488 | SOC_DAPM_ENUM("IF1 ADC2 source", rt5677_if1_adc2_enum); | 1475 | SOC_DAPM_ENUM("IF1 ADC2 Source", rt5677_if1_adc2_enum); |
1489 | 1476 | ||
1490 | static SOC_ENUM_SINGLE_DECL( | 1477 | static SOC_ENUM_SINGLE_DECL( |
1491 | rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2, | 1478 | rt5677_if2_adc2_enum, RT5677_TDM2_CTRL2, |
1492 | RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src); | 1479 | RT5677_IF2_ADC2_SFT, rt5677_if12_adc2_src); |
1493 | 1480 | ||
1494 | static const struct snd_kcontrol_new rt5677_if2_adc2_mux = | 1481 | static const struct snd_kcontrol_new rt5677_if2_adc2_mux = |
1495 | SOC_DAPM_ENUM("IF2 ADC2 source", rt5677_if2_adc2_enum); | 1482 | SOC_DAPM_ENUM("IF2 ADC2 Source", rt5677_if2_adc2_enum); |
1496 | 1483 | ||
1497 | static SOC_ENUM_SINGLE_DECL( | 1484 | static SOC_ENUM_SINGLE_DECL( |
1498 | rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX, | 1485 | rt5677_slb_adc2_enum, RT5677_SLIMBUS_RX, |
1499 | RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src); | 1486 | RT5677_SLB_ADC2_SFT, rt5677_if12_adc2_src); |
1500 | 1487 | ||
1501 | static const struct snd_kcontrol_new rt5677_slb_adc2_mux = | 1488 | static const struct snd_kcontrol_new rt5677_slb_adc2_mux = |
1502 | SOC_DAPM_ENUM("SLB ADC2 source", rt5677_slb_adc2_enum); | 1489 | SOC_DAPM_ENUM("SLB ADC2 Source", rt5677_slb_adc2_enum); |
1503 | 1490 | ||
1504 | /* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */ | 1491 | /* TDM IF1/2 SLB ADC3 Data Selection */ /* MX-3C MX-41 [9:8] MX-08 [5:4] */ |
1505 | static const char * const rt5677_if12_adc3_src[] = { | 1492 | static const char * const rt5677_if12_adc3_src[] = { |
@@ -1511,21 +1498,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1511 | RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src); | 1498 | RT5677_IF1_ADC3_SFT, rt5677_if12_adc3_src); |
1512 | 1499 | ||
1513 | static const struct snd_kcontrol_new rt5677_if1_adc3_mux = | 1500 | static const struct snd_kcontrol_new rt5677_if1_adc3_mux = |
1514 | SOC_DAPM_ENUM("IF1 ADC3 source", rt5677_if1_adc3_enum); | 1501 | SOC_DAPM_ENUM("IF1 ADC3 Source", rt5677_if1_adc3_enum); |
1515 | 1502 | ||
1516 | static SOC_ENUM_SINGLE_DECL( | 1503 | static SOC_ENUM_SINGLE_DECL( |
1517 | rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2, | 1504 | rt5677_if2_adc3_enum, RT5677_TDM2_CTRL2, |
1518 | RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src); | 1505 | RT5677_IF2_ADC3_SFT, rt5677_if12_adc3_src); |
1519 | 1506 | ||
1520 | static const struct snd_kcontrol_new rt5677_if2_adc3_mux = | 1507 | static const struct snd_kcontrol_new rt5677_if2_adc3_mux = |
1521 | SOC_DAPM_ENUM("IF2 ADC3 source", rt5677_if2_adc3_enum); | 1508 | SOC_DAPM_ENUM("IF2 ADC3 Source", rt5677_if2_adc3_enum); |
1522 | 1509 | ||
1523 | static SOC_ENUM_SINGLE_DECL( | 1510 | static SOC_ENUM_SINGLE_DECL( |
1524 | rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX, | 1511 | rt5677_slb_adc3_enum, RT5677_SLIMBUS_RX, |
1525 | RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src); | 1512 | RT5677_SLB_ADC3_SFT, rt5677_if12_adc3_src); |
1526 | 1513 | ||
1527 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = | 1514 | static const struct snd_kcontrol_new rt5677_slb_adc3_mux = |
1528 | SOC_DAPM_ENUM("SLB ADC3 source", rt5677_slb_adc3_enum); | 1515 | SOC_DAPM_ENUM("SLB ADC3 Source", rt5677_slb_adc3_enum); |
1529 | 1516 | ||
1530 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ | 1517 | /* TDM IF1/2 SLB ADC4 Data Selection */ /* MX-3C MX-41 [11:10] MX-08 [7:6] */ |
1531 | static const char * const rt5677_if12_adc4_src[] = { | 1518 | static const char * const rt5677_if12_adc4_src[] = { |
@@ -1537,21 +1524,21 @@ static SOC_ENUM_SINGLE_DECL( | |||
1537 | RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src); | 1524 | RT5677_IF1_ADC4_SFT, rt5677_if12_adc4_src); |
1538 | 1525 | ||
1539 | static const struct snd_kcontrol_new rt5677_if1_adc4_mux = | 1526 | static const struct snd_kcontrol_new rt5677_if1_adc4_mux = |
1540 | SOC_DAPM_ENUM("IF1 ADC4 source", rt5677_if1_adc4_enum); | 1527 | SOC_DAPM_ENUM("IF1 ADC4 Source", rt5677_if1_adc4_enum); |
1541 | 1528 | ||
1542 | static SOC_ENUM_SINGLE_DECL( | 1529 | static SOC_ENUM_SINGLE_DECL( |
1543 | rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2, | 1530 | rt5677_if2_adc4_enum, RT5677_TDM2_CTRL2, |
1544 | RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src); | 1531 | RT5677_IF2_ADC4_SFT, rt5677_if12_adc4_src); |
1545 | 1532 | ||
1546 | static const struct snd_kcontrol_new rt5677_if2_adc4_mux = | 1533 | static const struct snd_kcontrol_new rt5677_if2_adc4_mux = |
1547 | SOC_DAPM_ENUM("IF2 ADC4 source", rt5677_if2_adc4_enum); | 1534 | SOC_DAPM_ENUM("IF2 ADC4 Source", rt5677_if2_adc4_enum); |
1548 | 1535 | ||
1549 | static SOC_ENUM_SINGLE_DECL( | 1536 | static SOC_ENUM_SINGLE_DECL( |
1550 | rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX, | 1537 | rt5677_slb_adc4_enum, RT5677_SLIMBUS_RX, |
1551 | RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src); | 1538 | RT5677_SLB_ADC4_SFT, rt5677_if12_adc4_src); |
1552 | 1539 | ||
1553 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = | 1540 | static const struct snd_kcontrol_new rt5677_slb_adc4_mux = |
1554 | SOC_DAPM_ENUM("SLB ADC4 source", rt5677_slb_adc4_enum); | 1541 | SOC_DAPM_ENUM("SLB ADC4 Source", rt5677_slb_adc4_enum); |
1555 | 1542 | ||
1556 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/ | 1543 | /* Interface3/4 ADC Data Input */ /* MX-2F [3:0] MX-30 [7:4]*/ |
1557 | static const char * const rt5677_if34_adc_src[] = { | 1544 | static const char * const rt5677_if34_adc_src[] = { |
@@ -1564,14 +1551,14 @@ static SOC_ENUM_SINGLE_DECL( | |||
1564 | RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src); | 1551 | RT5677_IF3_ADC_IN_SFT, rt5677_if34_adc_src); |
1565 | 1552 | ||
1566 | static const struct snd_kcontrol_new rt5677_if3_adc_mux = | 1553 | static const struct snd_kcontrol_new rt5677_if3_adc_mux = |
1567 | SOC_DAPM_ENUM("IF3 ADC source", rt5677_if3_adc_enum); | 1554 | SOC_DAPM_ENUM("IF3 ADC Source", rt5677_if3_adc_enum); |
1568 | 1555 | ||
1569 | static SOC_ENUM_SINGLE_DECL( | 1556 | static SOC_ENUM_SINGLE_DECL( |
1570 | rt5677_if4_adc_enum, RT5677_IF4_DATA, | 1557 | rt5677_if4_adc_enum, RT5677_IF4_DATA, |
1571 | RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src); | 1558 | RT5677_IF4_ADC_IN_SFT, rt5677_if34_adc_src); |
1572 | 1559 | ||
1573 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = | 1560 | static const struct snd_kcontrol_new rt5677_if4_adc_mux = |
1574 | SOC_DAPM_ENUM("IF4 ADC source", rt5677_if4_adc_enum); | 1561 | SOC_DAPM_ENUM("IF4 ADC Source", rt5677_if4_adc_enum); |
1575 | 1562 | ||
1576 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, | 1563 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, |
1577 | struct snd_kcontrol *kcontrol, int event) | 1564 | struct snd_kcontrol *kcontrol, int event) |
@@ -1670,6 +1657,13 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, | |||
1670 | RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 | | 1657 | RT5677_PWR_CLK_MB, RT5677_PWR_CLK_MB1 | |
1671 | RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB); | 1658 | RT5677_PWR_PP_MB1 | RT5677_PWR_CLK_MB); |
1672 | break; | 1659 | break; |
1660 | |||
1661 | case SND_SOC_DAPM_PRE_PMD: | ||
1662 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, | ||
1663 | RT5677_PWR_CLK_MB1 | RT5677_PWR_PP_MB1 | | ||
1664 | RT5677_PWR_CLK_MB, 0); | ||
1665 | break; | ||
1666 | |||
1673 | default: | 1667 | default: |
1674 | return 0; | 1668 | return 0; |
1675 | } | 1669 | } |
@@ -1685,8 +1679,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1685 | 1679 | ||
1686 | /* Input Side */ | 1680 | /* Input Side */ |
1687 | /* micbias */ | 1681 | /* micbias */ |
1688 | SND_SOC_DAPM_SUPPLY("micbias1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, | 1682 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, |
1689 | 0, rt5677_set_micbias1_event, SND_SOC_DAPM_POST_PMU), | 1683 | 0, rt5677_set_micbias1_event, SND_SOC_DAPM_PRE_PMD | |
1684 | SND_SOC_DAPM_POST_PMU), | ||
1690 | 1685 | ||
1691 | /* Input Lines */ | 1686 | /* Input Lines */ |
1692 | SND_SOC_DAPM_INPUT("DMIC L1"), | 1687 | SND_SOC_DAPM_INPUT("DMIC L1"), |
@@ -2798,21 +2793,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2798 | { "PDM2R", NULL, "PDM2 R Mux" }, | 2793 | { "PDM2R", NULL, "PDM2 R Mux" }, |
2799 | }; | 2794 | }; |
2800 | 2795 | ||
2801 | static int get_clk_info(int sclk, int rate) | ||
2802 | { | ||
2803 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
2804 | |||
2805 | if (sclk <= 0 || rate <= 0) | ||
2806 | return -EINVAL; | ||
2807 | |||
2808 | rate = rate << 8; | ||
2809 | for (i = 0; i < ARRAY_SIZE(pd); i++) | ||
2810 | if (sclk == rate * pd[i]) | ||
2811 | return i; | ||
2812 | |||
2813 | return -EINVAL; | ||
2814 | } | ||
2815 | |||
2816 | static int rt5677_hw_params(struct snd_pcm_substream *substream, | 2796 | static int rt5677_hw_params(struct snd_pcm_substream *substream, |
2817 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2797 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2818 | { | 2798 | { |
@@ -2822,7 +2802,7 @@ static int rt5677_hw_params(struct snd_pcm_substream *substream, | |||
2822 | int pre_div, bclk_ms, frame_size; | 2802 | int pre_div, bclk_ms, frame_size; |
2823 | 2803 | ||
2824 | rt5677->lrck[dai->id] = params_rate(params); | 2804 | rt5677->lrck[dai->id] = params_rate(params); |
2825 | pre_div = get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); | 2805 | pre_div = rl6231_get_clk_info(rt5677->sysclk, rt5677->lrck[dai->id]); |
2826 | if (pre_div < 0) { | 2806 | if (pre_div < 0) { |
2827 | dev_err(codec->dev, "Unsupported clock setting\n"); | 2807 | dev_err(codec->dev, "Unsupported clock setting\n"); |
2828 | return -EINVAL; | 2808 | return -EINVAL; |
@@ -3016,62 +2996,12 @@ static int rt5677_set_dai_sysclk(struct snd_soc_dai *dai, | |||
3016 | * Returns 0 for success or negative error code. | 2996 | * Returns 0 for success or negative error code. |
3017 | */ | 2997 | */ |
3018 | static int rt5677_pll_calc(const unsigned int freq_in, | 2998 | static int rt5677_pll_calc(const unsigned int freq_in, |
3019 | const unsigned int freq_out, struct rt5677_pll_code *pll_code) | 2999 | const unsigned int freq_out, struct rl6231_pll_code *pll_code) |
3020 | { | 3000 | { |
3021 | int max_n = RT5677_PLL_N_MAX, max_m = RT5677_PLL_M_MAX; | 3001 | if (RT5677_PLL_INP_MIN > freq_in) |
3022 | int k, red, n_t, pll_out, in_t; | ||
3023 | int n = 0, m = 0, m_t = 0; | ||
3024 | int out_t, red_t = abs(freq_out - freq_in); | ||
3025 | bool m_bp = false, k_bp = false; | ||
3026 | |||
3027 | if (RT5677_PLL_INP_MAX < freq_in || RT5677_PLL_INP_MIN > freq_in) | ||
3028 | return -EINVAL; | 3002 | return -EINVAL; |
3029 | 3003 | ||
3030 | k = 100000000 / freq_out - 2; | 3004 | return rl6231_pll_calc(freq_in, freq_out, pll_code); |
3031 | if (k > RT5677_PLL_K_MAX) | ||
3032 | k = RT5677_PLL_K_MAX; | ||
3033 | for (n_t = 0; n_t <= max_n; n_t++) { | ||
3034 | in_t = freq_in / (k + 2); | ||
3035 | pll_out = freq_out / (n_t + 2); | ||
3036 | if (in_t < 0) | ||
3037 | continue; | ||
3038 | if (in_t == pll_out) { | ||
3039 | m_bp = true; | ||
3040 | n = n_t; | ||
3041 | goto code_find; | ||
3042 | } | ||
3043 | red = abs(in_t - pll_out); | ||
3044 | if (red < red_t) { | ||
3045 | m_bp = true; | ||
3046 | n = n_t; | ||
3047 | m = m_t; | ||
3048 | if (red == 0) | ||
3049 | goto code_find; | ||
3050 | red_t = red; | ||
3051 | } | ||
3052 | for (m_t = 0; m_t <= max_m; m_t++) { | ||
3053 | out_t = in_t / (m_t + 2); | ||
3054 | red = abs(out_t - pll_out); | ||
3055 | if (red < red_t) { | ||
3056 | m_bp = false; | ||
3057 | n = n_t; | ||
3058 | m = m_t; | ||
3059 | if (red == 0) | ||
3060 | goto code_find; | ||
3061 | red_t = red; | ||
3062 | } | ||
3063 | } | ||
3064 | } | ||
3065 | pr_debug("Only get approximation about PLL\n"); | ||
3066 | |||
3067 | code_find: | ||
3068 | |||
3069 | pll_code->m_bp = m_bp; | ||
3070 | pll_code->k_bp = k_bp; | ||
3071 | pll_code->m_code = m; | ||
3072 | pll_code->n_code = n; | ||
3073 | pll_code->k_code = k; | ||
3074 | return 0; | ||
3075 | } | 3005 | } |
3076 | 3006 | ||
3077 | static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | 3007 | static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, |
@@ -3079,7 +3009,7 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
3079 | { | 3009 | { |
3080 | struct snd_soc_codec *codec = dai->codec; | 3010 | struct snd_soc_codec *codec = dai->codec; |
3081 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 3011 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3082 | struct rt5677_pll_code pll_code; | 3012 | struct rl6231_pll_code pll_code; |
3083 | int ret; | 3013 | int ret; |
3084 | 3014 | ||
3085 | if (source == rt5677->pll_src && freq_in == rt5677->pll_in && | 3015 | if (source == rt5677->pll_src && freq_in == rt5677->pll_in && |
@@ -3137,15 +3067,12 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
3137 | return ret; | 3067 | return ret; |
3138 | } | 3068 | } |
3139 | 3069 | ||
3140 | dev_dbg(codec->dev, "m_bypass=%d k_bypass=%d m=%d n=%d k=%d\n", | 3070 | dev_dbg(codec->dev, "m_bypass=%d m=%d n=%d k=%d\n", |
3141 | pll_code.m_bp, pll_code.k_bp, | 3071 | pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), |
3142 | (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code, | 3072 | pll_code.n_code, pll_code.k_code); |
3143 | (pll_code.k_bp ? 0 : pll_code.k_code)); | ||
3144 | 3073 | ||
3145 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1, | 3074 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1, |
3146 | pll_code.n_code << RT5677_PLL_N_SFT | | 3075 | pll_code.n_code << RT5677_PLL_N_SFT | pll_code.k_code); |
3147 | pll_code.k_bp << RT5677_PLL_K_BP_SFT | | ||
3148 | (pll_code.k_bp ? 0 : pll_code.k_code)); | ||
3149 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2, | 3076 | regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2, |
3150 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | | 3077 | (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | |
3151 | pll_code.m_bp << RT5677_PLL_M_BP_SFT); | 3078 | pll_code.m_bp << RT5677_PLL_M_BP_SFT); |
@@ -3197,7 +3124,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3197 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); | 3124 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); |
3198 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); | 3125 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); |
3199 | regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); | 3126 | regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); |
3200 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0000); | 3127 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022); |
3201 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); | 3128 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); |
3202 | regmap_update_bits(rt5677->regmap, | 3129 | regmap_update_bits(rt5677->regmap, |
3203 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); | 3130 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); |
@@ -3454,14 +3381,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3454 | regmap_update_bits(rt5677->regmap, RT5677_IN1, | 3381 | regmap_update_bits(rt5677->regmap, RT5677_IN1, |
3455 | RT5677_IN_DF2, RT5677_IN_DF2); | 3382 | RT5677_IN_DF2, RT5677_IN_DF2); |
3456 | 3383 | ||
3457 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, | 3384 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, |
3458 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); | 3385 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); |
3459 | if (ret < 0) | ||
3460 | goto err; | ||
3461 | |||
3462 | return 0; | ||
3463 | err: | ||
3464 | return ret; | ||
3465 | } | 3386 | } |
3466 | 3387 | ||
3467 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 3388 | static int rt5677_i2c_remove(struct i2c_client *i2c) |
@@ -3480,18 +3401,7 @@ static struct i2c_driver rt5677_i2c_driver = { | |||
3480 | .remove = rt5677_i2c_remove, | 3401 | .remove = rt5677_i2c_remove, |
3481 | .id_table = rt5677_i2c_id, | 3402 | .id_table = rt5677_i2c_id, |
3482 | }; | 3403 | }; |
3483 | 3404 | module_i2c_driver(rt5677_i2c_driver); | |
3484 | static int __init rt5677_modinit(void) | ||
3485 | { | ||
3486 | return i2c_add_driver(&rt5677_i2c_driver); | ||
3487 | } | ||
3488 | module_init(rt5677_modinit); | ||
3489 | |||
3490 | static void __exit rt5677_modexit(void) | ||
3491 | { | ||
3492 | i2c_del_driver(&rt5677_i2c_driver); | ||
3493 | } | ||
3494 | module_exit(rt5677_modexit); | ||
3495 | 3405 | ||
3496 | MODULE_DESCRIPTION("ASoC RT5677 driver"); | 3406 | MODULE_DESCRIPTION("ASoC RT5677 driver"); |
3497 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | 3407 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index af4e9c797408..863393e62096 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -1393,13 +1393,6 @@ | |||
1393 | #define RT5677_DSP_IB_9_L (0x1 << 1) | 1393 | #define RT5677_DSP_IB_9_L (0x1 << 1) |
1394 | #define RT5677_DSP_IB_9_L_SFT 1 | 1394 | #define RT5677_DSP_IB_9_L_SFT 1 |
1395 | 1395 | ||
1396 | /* Debug String Length */ | ||
1397 | #define RT5677_REG_DISP_LEN 23 | ||
1398 | |||
1399 | #define RT5677_NO_JACK BIT(0) | ||
1400 | #define RT5677_HEADSET_DET BIT(1) | ||
1401 | #define RT5677_HEADPHO_DET BIT(2) | ||
1402 | |||
1403 | /* System Clock Source */ | 1396 | /* System Clock Source */ |
1404 | enum { | 1397 | enum { |
1405 | RT5677_SCLK_S_MCLK, | 1398 | RT5677_SCLK_S_MCLK, |
@@ -1425,14 +1418,6 @@ enum { | |||
1425 | RT5677_AIFS, | 1418 | RT5677_AIFS, |
1426 | }; | 1419 | }; |
1427 | 1420 | ||
1428 | struct rt5677_pll_code { | ||
1429 | bool m_bp; /* Indicates bypass m code or not. */ | ||
1430 | bool k_bp; /* Indicates bypass k code or not. */ | ||
1431 | int m_code; | ||
1432 | int n_code; | ||
1433 | int k_code; | ||
1434 | }; | ||
1435 | |||
1436 | struct rt5677_priv { | 1421 | struct rt5677_priv { |
1437 | struct snd_soc_codec *codec; | 1422 | struct snd_soc_codec *codec; |
1438 | struct rt5677_platform_data pdata; | 1423 | struct rt5677_platform_data pdata; |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3d39f0b5b4a8..e997d271728d 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -724,25 +724,25 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream, | |||
724 | return ret; | 724 | return ret; |
725 | 725 | ||
726 | /* set i2s data format */ | 726 | /* set i2s data format */ |
727 | switch (params_format(params)) { | 727 | switch (params_width(params)) { |
728 | case SNDRV_PCM_FORMAT_S16_LE: | 728 | case 16: |
729 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) | 729 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) |
730 | return -EINVAL; | 730 | return -EINVAL; |
731 | i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT; | 731 | i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT; |
732 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS << | 732 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS << |
733 | SGTL5000_I2S_SCLKFREQ_SHIFT; | 733 | SGTL5000_I2S_SCLKFREQ_SHIFT; |
734 | break; | 734 | break; |
735 | case SNDRV_PCM_FORMAT_S20_3LE: | 735 | case 20: |
736 | i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT; | 736 | i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT; |
737 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << | 737 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << |
738 | SGTL5000_I2S_SCLKFREQ_SHIFT; | 738 | SGTL5000_I2S_SCLKFREQ_SHIFT; |
739 | break; | 739 | break; |
740 | case SNDRV_PCM_FORMAT_S24_LE: | 740 | case 24: |
741 | i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT; | 741 | i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT; |
742 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << | 742 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << |
743 | SGTL5000_I2S_SCLKFREQ_SHIFT; | 743 | SGTL5000_I2S_SCLKFREQ_SHIFT; |
744 | break; | 744 | break; |
745 | case SNDRV_PCM_FORMAT_S32_LE: | 745 | case 32: |
746 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) | 746 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) |
747 | return -EINVAL; | 747 | return -EINVAL; |
748 | i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT; | 748 | i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT; |
@@ -843,10 +843,8 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, | |||
843 | 843 | ||
844 | ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); | 844 | ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); |
845 | 845 | ||
846 | if (!ldo) { | 846 | if (!ldo) |
847 | dev_err(codec->dev, "failed to allocate ldo_regulator\n"); | ||
848 | return -ENOMEM; | 847 | return -ENOMEM; |
849 | } | ||
850 | 848 | ||
851 | ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); | 849 | ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); |
852 | if (!ldo->desc.name) { | 850 | if (!ldo->desc.name) { |
@@ -1277,7 +1275,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1277 | return ret; | 1275 | return ret; |
1278 | } | 1276 | } |
1279 | 1277 | ||
1280 | ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | 1278 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), |
1281 | sgtl5000->supplies); | 1279 | sgtl5000->supplies); |
1282 | if (ret) | 1280 | if (ret) |
1283 | goto err_ldo_remove; | 1281 | goto err_ldo_remove; |
@@ -1285,13 +1283,16 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1285 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | 1283 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), |
1286 | sgtl5000->supplies); | 1284 | sgtl5000->supplies); |
1287 | if (ret) | 1285 | if (ret) |
1288 | goto err_ldo_remove; | 1286 | goto err_regulator_free; |
1289 | 1287 | ||
1290 | /* wait for all power rails bring up */ | 1288 | /* wait for all power rails bring up */ |
1291 | udelay(10); | 1289 | udelay(10); |
1292 | 1290 | ||
1293 | return 0; | 1291 | return 0; |
1294 | 1292 | ||
1293 | err_regulator_free: | ||
1294 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1295 | sgtl5000->supplies); | ||
1295 | err_ldo_remove: | 1296 | err_ldo_remove: |
1296 | if (!external_vddd) | 1297 | if (!external_vddd) |
1297 | ldo_regulator_remove(codec); | 1298 | ldo_regulator_remove(codec); |
@@ -1361,6 +1362,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1361 | err: | 1362 | err: |
1362 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1363 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1363 | sgtl5000->supplies); | 1364 | sgtl5000->supplies); |
1365 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1366 | sgtl5000->supplies); | ||
1364 | ldo_regulator_remove(codec); | 1367 | ldo_regulator_remove(codec); |
1365 | 1368 | ||
1366 | return ret; | 1369 | return ret; |
@@ -1374,6 +1377,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) | |||
1374 | 1377 | ||
1375 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1378 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1376 | sgtl5000->supplies); | 1379 | sgtl5000->supplies); |
1380 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1381 | sgtl5000->supplies); | ||
1377 | ldo_regulator_remove(codec); | 1382 | ldo_regulator_remove(codec); |
1378 | 1383 | ||
1379 | return 0; | 1384 | return 0; |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index f26befb0c297..cdf882fa7716 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
@@ -167,17 +167,17 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream, | |||
167 | return -EINVAL; | 167 | return -EINVAL; |
168 | } | 168 | } |
169 | 169 | ||
170 | switch (params_format(params)) { | 170 | switch (params_width(params)) { |
171 | case SNDRV_PCM_FORMAT_S8: | 171 | case 8: |
172 | width = SI476X_PCM_FORMAT_S8; | 172 | width = SI476X_PCM_FORMAT_S8; |
173 | break; | 173 | break; |
174 | case SNDRV_PCM_FORMAT_S16_LE: | 174 | case 16: |
175 | width = SI476X_PCM_FORMAT_S16_LE; | 175 | width = SI476X_PCM_FORMAT_S16_LE; |
176 | break; | 176 | break; |
177 | case SNDRV_PCM_FORMAT_S20_3LE: | 177 | case 20: |
178 | width = SI476X_PCM_FORMAT_S20_3LE; | 178 | width = SI476X_PCM_FORMAT_S20_3LE; |
179 | break; | 179 | break; |
180 | case SNDRV_PCM_FORMAT_S24_LE: | 180 | case 24: |
181 | width = SI476X_PCM_FORMAT_S24_LE; | 181 | width = SI476X_PCM_FORMAT_S24_LE; |
182 | break; | 182 | break; |
183 | default: | 183 | default: |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index d90cb0fafcb2..06ba4923fd5a 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -471,8 +471,8 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev) | |||
471 | 471 | ||
472 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 472 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
473 | base = devm_ioremap_resource(&pdev->dev, mem_res); | 473 | base = devm_ioremap_resource(&pdev->dev, mem_res); |
474 | if (base == NULL) | 474 | if (IS_ERR(base)) |
475 | return -ENOMEM; | 475 | return PTR_ERR(base); |
476 | 476 | ||
477 | sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, | 477 | sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
478 | &sirf_audio_codec_regmap_config); | 478 | &sirf_audio_codec_regmap_config); |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 42dff26b3a2a..cf8fa40662f0 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -661,12 +661,12 @@ static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, | |||
661 | { | 661 | { |
662 | unsigned int format, rate; | 662 | unsigned int format, rate; |
663 | 663 | ||
664 | switch (params_format(params)) { | 664 | switch (params_width(params)) { |
665 | case SNDRV_PCM_FORMAT_S16_LE: | 665 | case 16: |
666 | format = BIT(4)|BIT(5); | 666 | format = BIT(4)|BIT(5); |
667 | break; | 667 | break; |
668 | 668 | ||
669 | case SNDRV_PCM_FORMAT_S24_LE: | 669 | case 24: |
670 | format = 0; | 670 | format = 0; |
671 | break; | 671 | break; |
672 | default: | 672 | default: |
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index a078aa31052a..e0df537dd4b7 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #define DRV_NAME "spdif-dit" | 25 | #define DRV_NAME "spdif-dit" |
26 | 26 | ||
27 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 | 27 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 |
28 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 28 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
29 | SNDRV_PCM_FMTBIT_S20_3LE | \ | 29 | SNDRV_PCM_FMTBIT_S20_3LE | \ |
30 | SNDRV_PCM_FMTBIT_S24_LE) | 30 | SNDRV_PCM_FMTBIT_S24_LE) |
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 56adb3e2def9..e8680bea5f86 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -361,11 +361,11 @@ static int ssm2518_hw_params(struct snd_pcm_substream *substream, | |||
361 | return -EINVAL; | 361 | return -EINVAL; |
362 | 362 | ||
363 | if (ssm2518->right_j) { | 363 | if (ssm2518->right_j) { |
364 | switch (params_format(params)) { | 364 | switch (params_width(params)) { |
365 | case SNDRV_PCM_FORMAT_S16_LE: | 365 | case 16: |
366 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT; | 366 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT; |
367 | break; | 367 | break; |
368 | case SNDRV_PCM_FORMAT_S24_LE: | 368 | case 24: |
369 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT; | 369 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT; |
370 | break; | 370 | break; |
371 | default: | 371 | default: |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 97b0454eb346..484b3bbe8624 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -275,17 +275,17 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
275 | regmap_write(ssm2602->regmap, SSM2602_SRATE, srate); | 275 | regmap_write(ssm2602->regmap, SSM2602_SRATE, srate); |
276 | 276 | ||
277 | /* bit size */ | 277 | /* bit size */ |
278 | switch (params_format(params)) { | 278 | switch (params_width(params)) { |
279 | case SNDRV_PCM_FORMAT_S16_LE: | 279 | case 16: |
280 | iface = 0x0; | 280 | iface = 0x0; |
281 | break; | 281 | break; |
282 | case SNDRV_PCM_FORMAT_S20_3LE: | 282 | case 20: |
283 | iface = 0x4; | 283 | iface = 0x4; |
284 | break; | 284 | break; |
285 | case SNDRV_PCM_FORMAT_S24_LE: | 285 | case 24: |
286 | iface = 0x8; | 286 | iface = 0x8; |
287 | break; | 287 | break; |
288 | case SNDRV_PCM_FORMAT_S32_LE: | 288 | case 32: |
289 | iface = 0xc; | 289 | iface = 0xc; |
290 | break; | 290 | break; |
291 | default: | 291 | default: |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 0579d187135b..48740855566d 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -678,15 +678,11 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
678 | 678 | ||
679 | confb = snd_soc_read(codec, STA32X_CONFB); | 679 | confb = snd_soc_read(codec, STA32X_CONFB); |
680 | confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); | 680 | confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); |
681 | switch (params_format(params)) { | 681 | switch (params_width(params)) { |
682 | case SNDRV_PCM_FORMAT_S24_LE: | 682 | case 24: |
683 | case SNDRV_PCM_FORMAT_S24_BE: | ||
684 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
685 | case SNDRV_PCM_FORMAT_S24_3BE: | ||
686 | pr_debug("24bit\n"); | 683 | pr_debug("24bit\n"); |
687 | /* fall through */ | 684 | /* fall through */ |
688 | case SNDRV_PCM_FORMAT_S32_LE: | 685 | case 32: |
689 | case SNDRV_PCM_FORMAT_S32_BE: | ||
690 | pr_debug("24bit or 32bit\n"); | 686 | pr_debug("24bit or 32bit\n"); |
691 | switch (sta32x->format) { | 687 | switch (sta32x->format) { |
692 | case SND_SOC_DAIFMT_I2S: | 688 | case SND_SOC_DAIFMT_I2S: |
@@ -701,8 +697,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
701 | } | 697 | } |
702 | 698 | ||
703 | break; | 699 | break; |
704 | case SNDRV_PCM_FORMAT_S20_3LE: | 700 | case 20: |
705 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
706 | pr_debug("20bit\n"); | 701 | pr_debug("20bit\n"); |
707 | switch (sta32x->format) { | 702 | switch (sta32x->format) { |
708 | case SND_SOC_DAIFMT_I2S: | 703 | case SND_SOC_DAIFMT_I2S: |
@@ -717,8 +712,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
717 | } | 712 | } |
718 | 713 | ||
719 | break; | 714 | break; |
720 | case SNDRV_PCM_FORMAT_S18_3LE: | 715 | case 18: |
721 | case SNDRV_PCM_FORMAT_S18_3BE: | ||
722 | pr_debug("18bit\n"); | 716 | pr_debug("18bit\n"); |
723 | switch (sta32x->format) { | 717 | switch (sta32x->format) { |
724 | case SND_SOC_DAIFMT_I2S: | 718 | case SND_SOC_DAIFMT_I2S: |
@@ -733,8 +727,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
733 | } | 727 | } |
734 | 728 | ||
735 | break; | 729 | break; |
736 | case SNDRV_PCM_FORMAT_S16_LE: | 730 | case 16: |
737 | case SNDRV_PCM_FORMAT_S16_BE: | ||
738 | pr_debug("16bit\n"); | 731 | pr_debug("16bit\n"); |
739 | switch (sta32x->format) { | 732 | switch (sta32x->format) { |
740 | case SND_SOC_DAIFMT_I2S: | 733 | case SND_SOC_DAIFMT_I2S: |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index a40c4b0196a3..9aa1323fb2ab 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -197,16 +197,16 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, | |||
197 | int pdata, play_freq_val, record_freq_val; | 197 | int pdata, play_freq_val, record_freq_val; |
198 | int bclk_to_fs_ratio; | 198 | int bclk_to_fs_ratio; |
199 | 199 | ||
200 | switch (params_format(params)) { | 200 | switch (params_width(params)) { |
201 | case SNDRV_PCM_FORMAT_S16_LE: | 201 | case 16: |
202 | pdata = 1; | 202 | pdata = 1; |
203 | bclk_to_fs_ratio = 0; | 203 | bclk_to_fs_ratio = 0; |
204 | break; | 204 | break; |
205 | case SNDRV_PCM_FORMAT_S24_LE: | 205 | case 24: |
206 | pdata = 2; | 206 | pdata = 2; |
207 | bclk_to_fs_ratio = 1; | 207 | bclk_to_fs_ratio = 1; |
208 | break; | 208 | break; |
209 | case SNDRV_PCM_FORMAT_S32_LE: | 209 | case 32: |
210 | pdata = 3; | 210 | pdata = 3; |
211 | bclk_to_fs_ratio = 2; | 211 | bclk_to_fs_ratio = 2; |
212 | break; | 212 | break; |
@@ -380,10 +380,8 @@ static int sta529_i2c_probe(struct i2c_client *i2c, | |||
380 | return -EINVAL; | 380 | return -EINVAL; |
381 | 381 | ||
382 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); | 382 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); |
383 | if (sta529 == NULL) { | 383 | if (!sta529) |
384 | dev_err(&i2c->dev, "Can not allocate memory\n"); | ||
385 | return -ENOMEM; | 384 | return -ENOMEM; |
386 | } | ||
387 | 385 | ||
388 | sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); | 386 | sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); |
389 | if (IS_ERR(sta529->regmap)) { | 387 | if (IS_ERR(sta529->regmap)) { |
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c new file mode 100644 index 000000000000..23b32960ff1d --- /dev/null +++ b/sound/soc/codecs/tas2552.c | |||
@@ -0,0 +1,544 @@ | |||
1 | /* | ||
2 | * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * Author: Dan Murphy <dmurphy@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/of_gpio.h> | ||
24 | #include <linux/pm_runtime.h> | ||
25 | #include <linux/regmap.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #include <linux/gpio/consumer.h> | ||
29 | #include <linux/regulator/consumer.h> | ||
30 | |||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/tlv.h> | ||
36 | #include <sound/tas2552-plat.h> | ||
37 | |||
38 | #include "tas2552.h" | ||
39 | |||
40 | static struct reg_default tas2552_reg_defs[] = { | ||
41 | {TAS2552_CFG_1, 0x22}, | ||
42 | {TAS2552_CFG_3, 0x80}, | ||
43 | {TAS2552_DOUT, 0x00}, | ||
44 | {TAS2552_OUTPUT_DATA, 0xc0}, | ||
45 | {TAS2552_PDM_CFG, 0x01}, | ||
46 | {TAS2552_PGA_GAIN, 0x00}, | ||
47 | {TAS2552_BOOST_PT_CTRL, 0x0f}, | ||
48 | {TAS2552_RESERVED_0D, 0x00}, | ||
49 | {TAS2552_LIMIT_RATE_HYS, 0x08}, | ||
50 | {TAS2552_CFG_2, 0xef}, | ||
51 | {TAS2552_SER_CTRL_1, 0x00}, | ||
52 | {TAS2552_SER_CTRL_2, 0x00}, | ||
53 | {TAS2552_PLL_CTRL_1, 0x10}, | ||
54 | {TAS2552_PLL_CTRL_2, 0x00}, | ||
55 | {TAS2552_PLL_CTRL_3, 0x00}, | ||
56 | {TAS2552_BTIP, 0x8f}, | ||
57 | {TAS2552_BTS_CTRL, 0x80}, | ||
58 | {TAS2552_LIMIT_RELEASE, 0x04}, | ||
59 | {TAS2552_LIMIT_INT_COUNT, 0x00}, | ||
60 | {TAS2552_EDGE_RATE_CTRL, 0x40}, | ||
61 | {TAS2552_VBAT_DATA, 0x00}, | ||
62 | }; | ||
63 | |||
64 | #define TAS2552_NUM_SUPPLIES 3 | ||
65 | static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = { | ||
66 | "vbat", /* vbat voltage */ | ||
67 | "iovdd", /* I/O Voltage */ | ||
68 | "avdd", /* Analog DAC Voltage */ | ||
69 | }; | ||
70 | |||
71 | struct tas2552_data { | ||
72 | struct snd_soc_codec *codec; | ||
73 | struct regmap *regmap; | ||
74 | struct i2c_client *tas2552_client; | ||
75 | struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES]; | ||
76 | struct gpio_desc *enable_gpio; | ||
77 | unsigned char regs[TAS2552_VBAT_DATA]; | ||
78 | unsigned int mclk; | ||
79 | }; | ||
80 | |||
81 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | ||
82 | { | ||
83 | u8 cfg1_reg; | ||
84 | |||
85 | if (sw_shutdown) | ||
86 | cfg1_reg = 0; | ||
87 | else | ||
88 | cfg1_reg = TAS2552_SWS_MASK; | ||
89 | |||
90 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, | ||
91 | TAS2552_SWS_MASK, cfg1_reg); | ||
92 | } | ||
93 | |||
94 | static int tas2552_hw_params(struct snd_pcm_substream *substream, | ||
95 | struct snd_pcm_hw_params *params, | ||
96 | struct snd_soc_dai *dai) | ||
97 | { | ||
98 | struct snd_soc_codec *codec = dai->codec; | ||
99 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | ||
100 | int sample_rate, pll_clk; | ||
101 | int d; | ||
102 | u8 p, j; | ||
103 | |||
104 | /* Turn on Class D amplifier */ | ||
105 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN_MASK, | ||
106 | TAS2552_CLASSD_EN); | ||
107 | |||
108 | if (!tas2552->mclk) | ||
109 | return -EINVAL; | ||
110 | |||
111 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); | ||
112 | |||
113 | if (tas2552->mclk == TAS2552_245MHZ_CLK || | ||
114 | tas2552->mclk == TAS2552_225MHZ_CLK) { | ||
115 | /* By pass the PLL configuration */ | ||
116 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2, | ||
117 | TAS2552_PLL_BYPASS_MASK, | ||
118 | TAS2552_PLL_BYPASS); | ||
119 | } else { | ||
120 | /* Fill in the PLL control registers for J & D | ||
121 | * PLL_CLK = (.5 * freq * J.D) / 2^p | ||
122 | * Need to fill in J and D here based on incoming freq | ||
123 | */ | ||
124 | p = snd_soc_read(codec, TAS2552_PLL_CTRL_1); | ||
125 | p = (p >> 7); | ||
126 | sample_rate = params_rate(params); | ||
127 | |||
128 | if (sample_rate == 48000) | ||
129 | pll_clk = TAS2552_245MHZ_CLK; | ||
130 | else if (sample_rate == 44100) | ||
131 | pll_clk = TAS2552_225MHZ_CLK; | ||
132 | else { | ||
133 | dev_vdbg(codec->dev, "Substream sample rate is not found %i\n", | ||
134 | params_rate(params)); | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | j = (pll_clk * 2 * (1 << p)) / tas2552->mclk; | ||
139 | d = (pll_clk * 2 * (1 << p)) % tas2552->mclk; | ||
140 | |||
141 | snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1, | ||
142 | TAS2552_PLL_J_MASK, j); | ||
143 | snd_soc_write(codec, TAS2552_PLL_CTRL_2, | ||
144 | (d >> 7) & TAS2552_PLL_D_UPPER_MASK); | ||
145 | snd_soc_write(codec, TAS2552_PLL_CTRL_3, | ||
146 | d & TAS2552_PLL_D_LOWER_MASK); | ||
147 | |||
148 | } | ||
149 | |||
150 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, | ||
151 | TAS2552_PLL_ENABLE); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
157 | { | ||
158 | struct snd_soc_codec *codec = dai->codec; | ||
159 | u8 serial_format; | ||
160 | u8 serial_control_mask; | ||
161 | |||
162 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
163 | case SND_SOC_DAIFMT_CBS_CFS: | ||
164 | serial_format = 0x00; | ||
165 | break; | ||
166 | case SND_SOC_DAIFMT_CBS_CFM: | ||
167 | serial_format = TAS2552_WORD_CLK_MASK; | ||
168 | break; | ||
169 | case SND_SOC_DAIFMT_CBM_CFS: | ||
170 | serial_format = TAS2552_BIT_CLK_MASK; | ||
171 | break; | ||
172 | case SND_SOC_DAIFMT_CBM_CFM: | ||
173 | serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK); | ||
174 | break; | ||
175 | default: | ||
176 | dev_vdbg(codec->dev, "DAI Format master is not found\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK; | ||
181 | |||
182 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
183 | case SND_SOC_DAIFMT_I2S: | ||
184 | serial_format &= TAS2552_DAIFMT_I2S_MASK; | ||
185 | break; | ||
186 | case SND_SOC_DAIFMT_DSP_A: | ||
187 | serial_format |= TAS2552_DAIFMT_DSP; | ||
188 | break; | ||
189 | case SND_SOC_DAIFMT_RIGHT_J: | ||
190 | serial_format |= TAS2552_DAIFMT_RIGHT_J; | ||
191 | break; | ||
192 | case SND_SOC_DAIFMT_LEFT_J: | ||
193 | serial_format |= TAS2552_DAIFMT_LEFT_J; | ||
194 | break; | ||
195 | default: | ||
196 | dev_vdbg(codec->dev, "DAI Format is not found\n"); | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | if (fmt & SND_SOC_DAIFMT_FORMAT_MASK) | ||
201 | serial_control_mask |= TAS2552_DATA_FORMAT_MASK; | ||
202 | |||
203 | snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask, | ||
204 | serial_format); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
210 | unsigned int freq, int dir) | ||
211 | { | ||
212 | struct snd_soc_codec *codec = dai->codec; | ||
213 | struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); | ||
214 | |||
215 | tas2552->mclk = freq; | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int tas2552_mute(struct snd_soc_dai *dai, int mute) | ||
221 | { | ||
222 | u8 cfg1_reg; | ||
223 | struct snd_soc_codec *codec = dai->codec; | ||
224 | |||
225 | if (mute) | ||
226 | cfg1_reg = TAS2552_MUTE_MASK; | ||
227 | else | ||
228 | cfg1_reg = ~TAS2552_MUTE_MASK; | ||
229 | |||
230 | snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | #ifdef CONFIG_PM_RUNTIME | ||
236 | static int tas2552_runtime_suspend(struct device *dev) | ||
237 | { | ||
238 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); | ||
239 | |||
240 | tas2552_sw_shutdown(tas2552, 0); | ||
241 | |||
242 | regcache_cache_only(tas2552->regmap, true); | ||
243 | regcache_mark_dirty(tas2552->regmap); | ||
244 | |||
245 | if (tas2552->enable_gpio) | ||
246 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int tas2552_runtime_resume(struct device *dev) | ||
252 | { | ||
253 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); | ||
254 | |||
255 | if (tas2552->enable_gpio) | ||
256 | gpiod_set_value(tas2552->enable_gpio, 1); | ||
257 | |||
258 | tas2552_sw_shutdown(tas2552, 1); | ||
259 | |||
260 | regcache_cache_only(tas2552->regmap, false); | ||
261 | regcache_sync(tas2552->regmap); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | #endif | ||
266 | |||
267 | static const struct dev_pm_ops tas2552_pm = { | ||
268 | SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume, | ||
269 | NULL) | ||
270 | }; | ||
271 | |||
272 | static void tas2552_shutdown(struct snd_pcm_substream *substream, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | struct snd_soc_codec *codec = dai->codec; | ||
276 | |||
277 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); | ||
278 | } | ||
279 | |||
280 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { | ||
281 | .hw_params = tas2552_hw_params, | ||
282 | .set_sysclk = tas2552_set_dai_sysclk, | ||
283 | .set_fmt = tas2552_set_dai_fmt, | ||
284 | .shutdown = tas2552_shutdown, | ||
285 | .digital_mute = tas2552_mute, | ||
286 | }; | ||
287 | |||
288 | /* Formats supported by TAS2552 driver. */ | ||
289 | #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
290 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
291 | |||
292 | /* TAS2552 dai structure. */ | ||
293 | static struct snd_soc_dai_driver tas2552_dai[] = { | ||
294 | { | ||
295 | .name = "tas2552-amplifier", | ||
296 | .playback = { | ||
297 | .stream_name = "Speaker", | ||
298 | .channels_min = 2, | ||
299 | .channels_max = 2, | ||
300 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
301 | .formats = TAS2552_FORMATS, | ||
302 | }, | ||
303 | .ops = &tas2552_speaker_dai_ops, | ||
304 | }, | ||
305 | }; | ||
306 | |||
307 | /* | ||
308 | * DAC digital volumes. From -7 to 24 dB in 1 dB steps | ||
309 | */ | ||
310 | static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); | ||
311 | |||
312 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { | ||
313 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", | ||
314 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), | ||
315 | }; | ||
316 | |||
317 | static const struct reg_default tas2552_init_regs[] = { | ||
318 | { TAS2552_RESERVED_0D, 0xc0 }, | ||
319 | }; | ||
320 | |||
321 | static int tas2552_codec_probe(struct snd_soc_codec *codec) | ||
322 | { | ||
323 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
324 | int ret; | ||
325 | |||
326 | tas2552->codec = codec; | ||
327 | |||
328 | ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies), | ||
329 | tas2552->supplies); | ||
330 | |||
331 | if (ret != 0) { | ||
332 | dev_err(codec->dev, "Failed to enable supplies: %d\n", | ||
333 | ret); | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | if (tas2552->enable_gpio) | ||
338 | gpiod_set_value(tas2552->enable_gpio, 1); | ||
339 | |||
340 | ret = pm_runtime_get_sync(codec->dev); | ||
341 | if (ret < 0) { | ||
342 | dev_err(codec->dev, "Enabling device failed: %d\n", | ||
343 | ret); | ||
344 | goto probe_fail; | ||
345 | } | ||
346 | |||
347 | snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK | | ||
348 | TAS2552_PLL_SRC_BCLK); | ||
349 | snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | | ||
350 | TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ); | ||
351 | snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I); | ||
352 | snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8); | ||
353 | snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL); | ||
354 | snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 | | ||
355 | TAS2552_APT_THRESH_2_1_7); | ||
356 | |||
357 | ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs, | ||
358 | ARRAY_SIZE(tas2552_init_regs)); | ||
359 | if (ret != 0) { | ||
360 | dev_err(codec->dev, "Failed to write init registers: %d\n", | ||
361 | ret); | ||
362 | goto patch_fail; | ||
363 | } | ||
364 | |||
365 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN | | ||
366 | TAS2552_BOOST_EN | TAS2552_APT_EN | | ||
367 | TAS2552_LIM_EN); | ||
368 | return 0; | ||
369 | |||
370 | patch_fail: | ||
371 | pm_runtime_put(codec->dev); | ||
372 | probe_fail: | ||
373 | if (tas2552->enable_gpio) | ||
374 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
375 | |||
376 | regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), | ||
377 | tas2552->supplies); | ||
378 | return -EIO; | ||
379 | } | ||
380 | |||
381 | static int tas2552_codec_remove(struct snd_soc_codec *codec) | ||
382 | { | ||
383 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
384 | |||
385 | pm_runtime_put(codec->dev); | ||
386 | |||
387 | if (tas2552->enable_gpio) | ||
388 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
389 | |||
390 | return 0; | ||
391 | }; | ||
392 | |||
393 | #ifdef CONFIG_PM | ||
394 | static int tas2552_suspend(struct snd_soc_codec *codec) | ||
395 | { | ||
396 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
397 | int ret; | ||
398 | |||
399 | ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), | ||
400 | tas2552->supplies); | ||
401 | |||
402 | if (ret != 0) | ||
403 | dev_err(codec->dev, "Failed to disable supplies: %d\n", | ||
404 | ret); | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int tas2552_resume(struct snd_soc_codec *codec) | ||
409 | { | ||
410 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | ||
411 | int ret; | ||
412 | |||
413 | ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies), | ||
414 | tas2552->supplies); | ||
415 | |||
416 | if (ret != 0) { | ||
417 | dev_err(codec->dev, "Failed to enable supplies: %d\n", | ||
418 | ret); | ||
419 | } | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | #else | ||
424 | #define tas2552_suspend NULL | ||
425 | #define tas2552_resume NULL | ||
426 | #endif | ||
427 | |||
428 | static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { | ||
429 | .probe = tas2552_codec_probe, | ||
430 | .remove = tas2552_codec_remove, | ||
431 | .suspend = tas2552_suspend, | ||
432 | .resume = tas2552_resume, | ||
433 | .controls = tas2552_snd_controls, | ||
434 | .num_controls = ARRAY_SIZE(tas2552_snd_controls), | ||
435 | }; | ||
436 | |||
437 | static const struct regmap_config tas2552_regmap_config = { | ||
438 | .reg_bits = 8, | ||
439 | .val_bits = 8, | ||
440 | |||
441 | .max_register = TAS2552_MAX_REG, | ||
442 | .reg_defaults = tas2552_reg_defs, | ||
443 | .num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs), | ||
444 | .cache_type = REGCACHE_RBTREE, | ||
445 | }; | ||
446 | |||
447 | static int tas2552_probe(struct i2c_client *client, | ||
448 | const struct i2c_device_id *id) | ||
449 | { | ||
450 | struct device *dev; | ||
451 | struct tas2552_data *data; | ||
452 | int ret; | ||
453 | int i; | ||
454 | |||
455 | dev = &client->dev; | ||
456 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); | ||
457 | if (data == NULL) | ||
458 | return -ENOMEM; | ||
459 | |||
460 | data->enable_gpio = devm_gpiod_get(dev, "enable"); | ||
461 | if (IS_ERR(data->enable_gpio)) { | ||
462 | ret = PTR_ERR(data->enable_gpio); | ||
463 | if (ret != -ENOENT && ret != -ENOSYS) | ||
464 | return ret; | ||
465 | |||
466 | data->enable_gpio = NULL; | ||
467 | } else { | ||
468 | gpiod_direction_output(data->enable_gpio, 0); | ||
469 | } | ||
470 | |||
471 | data->tas2552_client = client; | ||
472 | data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config); | ||
473 | if (IS_ERR(data->regmap)) { | ||
474 | ret = PTR_ERR(data->regmap); | ||
475 | dev_err(&client->dev, "Failed to allocate register map: %d\n", | ||
476 | ret); | ||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | ||
481 | data->supplies[i].supply = tas2552_supply_names[i]; | ||
482 | |||
483 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), | ||
484 | data->supplies); | ||
485 | if (ret != 0) { | ||
486 | dev_err(dev, "Failed to request supplies: %d\n", ret); | ||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | pm_runtime_set_active(&client->dev); | ||
491 | pm_runtime_set_autosuspend_delay(&client->dev, 1000); | ||
492 | pm_runtime_use_autosuspend(&client->dev); | ||
493 | pm_runtime_enable(&client->dev); | ||
494 | pm_runtime_mark_last_busy(&client->dev); | ||
495 | pm_runtime_put_sync_autosuspend(&client->dev); | ||
496 | |||
497 | dev_set_drvdata(&client->dev, data); | ||
498 | |||
499 | ret = snd_soc_register_codec(&client->dev, | ||
500 | &soc_codec_dev_tas2552, | ||
501 | tas2552_dai, ARRAY_SIZE(tas2552_dai)); | ||
502 | if (ret < 0) | ||
503 | dev_err(&client->dev, "Failed to register codec: %d\n", ret); | ||
504 | |||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static int tas2552_i2c_remove(struct i2c_client *client) | ||
509 | { | ||
510 | snd_soc_unregister_codec(&client->dev); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static const struct i2c_device_id tas2552_id[] = { | ||
515 | { "tas2552", 0 }, | ||
516 | { } | ||
517 | }; | ||
518 | MODULE_DEVICE_TABLE(i2c, tas2552_id); | ||
519 | |||
520 | #if IS_ENABLED(CONFIG_OF) | ||
521 | static const struct of_device_id tas2552_of_match[] = { | ||
522 | { .compatible = "ti,tas2552", }, | ||
523 | {}, | ||
524 | }; | ||
525 | MODULE_DEVICE_TABLE(of, tas2552_of_match); | ||
526 | #endif | ||
527 | |||
528 | static struct i2c_driver tas2552_i2c_driver = { | ||
529 | .driver = { | ||
530 | .name = "tas2552", | ||
531 | .owner = THIS_MODULE, | ||
532 | .of_match_table = of_match_ptr(tas2552_of_match), | ||
533 | .pm = &tas2552_pm, | ||
534 | }, | ||
535 | .probe = tas2552_probe, | ||
536 | .remove = tas2552_i2c_remove, | ||
537 | .id_table = tas2552_id, | ||
538 | }; | ||
539 | |||
540 | module_i2c_driver(tas2552_i2c_driver); | ||
541 | |||
542 | MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>"); | ||
543 | MODULE_DESCRIPTION("TAS2552 Audio amplifier driver"); | ||
544 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h new file mode 100644 index 000000000000..6cea8f31bf88 --- /dev/null +++ b/sound/soc/codecs/tas2552.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * tas2552.h - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * Author: Dan Murphy <dmurphy@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #ifndef __TAS2552_H__ | ||
19 | #define __TAS2552_H__ | ||
20 | |||
21 | /* Register Address Map */ | ||
22 | #define TAS2552_DEVICE_STATUS 0x00 | ||
23 | #define TAS2552_CFG_1 0x01 | ||
24 | #define TAS2552_CFG_2 0x02 | ||
25 | #define TAS2552_CFG_3 0x03 | ||
26 | #define TAS2552_DOUT 0x04 | ||
27 | #define TAS2552_SER_CTRL_1 0x05 | ||
28 | #define TAS2552_SER_CTRL_2 0x06 | ||
29 | #define TAS2552_OUTPUT_DATA 0x07 | ||
30 | #define TAS2552_PLL_CTRL_1 0x08 | ||
31 | #define TAS2552_PLL_CTRL_2 0x09 | ||
32 | #define TAS2552_PLL_CTRL_3 0x0a | ||
33 | #define TAS2552_BTIP 0x0b | ||
34 | #define TAS2552_BTS_CTRL 0x0c | ||
35 | #define TAS2552_RESERVED_0D 0x0d | ||
36 | #define TAS2552_LIMIT_RATE_HYS 0x0e | ||
37 | #define TAS2552_LIMIT_RELEASE 0x0f | ||
38 | #define TAS2552_LIMIT_INT_COUNT 0x10 | ||
39 | #define TAS2552_PDM_CFG 0x11 | ||
40 | #define TAS2552_PGA_GAIN 0x12 | ||
41 | #define TAS2552_EDGE_RATE_CTRL 0x13 | ||
42 | #define TAS2552_BOOST_PT_CTRL 0x14 | ||
43 | #define TAS2552_VER_NUM 0x16 | ||
44 | #define TAS2552_VBAT_DATA 0x19 | ||
45 | #define TAS2552_MAX_REG 0x20 | ||
46 | |||
47 | /* CFG1 Register Masks */ | ||
48 | #define TAS2552_MUTE_MASK (1 << 2) | ||
49 | #define TAS2552_SWS_MASK (1 << 1) | ||
50 | #define TAS2552_WCLK_MASK 0x07 | ||
51 | #define TAS2552_CLASSD_EN_MASK (1 << 7) | ||
52 | |||
53 | /* CFG2 Register Masks */ | ||
54 | #define TAS2552_CLASSD_EN (1 << 7) | ||
55 | #define TAS2552_BOOST_EN (1 << 6) | ||
56 | #define TAS2552_APT_EN (1 << 5) | ||
57 | #define TAS2552_PLL_ENABLE (1 << 3) | ||
58 | #define TAS2552_LIM_EN (1 << 2) | ||
59 | #define TAS2552_IVSENSE_EN (1 << 1) | ||
60 | |||
61 | /* CFG3 Register Masks */ | ||
62 | #define TAS2552_WORD_CLK_MASK (1 << 7) | ||
63 | #define TAS2552_BIT_CLK_MASK (1 << 6) | ||
64 | #define TAS2552_DATA_FORMAT_MASK (0x11 << 2) | ||
65 | |||
66 | #define TAS2552_DAIFMT_I2S_MASK 0xf3 | ||
67 | #define TAS2552_DAIFMT_DSP (1 << 3) | ||
68 | #define TAS2552_DAIFMT_RIGHT_J (1 << 4) | ||
69 | #define TAS2552_DAIFMT_LEFT_J (0x11 << 3) | ||
70 | |||
71 | #define TAS2552_PLL_SRC_MCLK 0x00 | ||
72 | #define TAS2552_PLL_SRC_BCLK (1 << 3) | ||
73 | #define TAS2552_PLL_SRC_IVCLKIN (1 << 4) | ||
74 | #define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3) | ||
75 | |||
76 | #define TAS2552_DIN_SRC_SEL_MUTED 0x00 | ||
77 | #define TAS2552_DIN_SRC_SEL_LEFT (1 << 4) | ||
78 | #define TAS2552_DIN_SRC_SEL_RIGHT (1 << 5) | ||
79 | #define TAS2552_DIN_SRC_SEL_AVG_L_R (0x11 << 4) | ||
80 | |||
81 | #define TAS2552_PDM_IN_SEL (1 << 5) | ||
82 | #define TAS2552_I2S_OUT_SEL (1 << 6) | ||
83 | #define TAS2552_ANALOG_IN_SEL (1 << 7) | ||
84 | |||
85 | /* CFG3 WCLK Dividers */ | ||
86 | #define TAS2552_8KHZ 0x00 | ||
87 | #define TAS2552_11_12KHZ (1 << 1) | ||
88 | #define TAS2552_16KHZ (1 << 2) | ||
89 | #define TAS2552_22_24KHZ (1 << 3) | ||
90 | #define TAS2552_32KHZ (1 << 4) | ||
91 | #define TAS2552_44_48KHZ (1 << 5) | ||
92 | #define TAS2552_88_96KHZ (1 << 6) | ||
93 | #define TAS2552_176_192KHZ (1 << 7) | ||
94 | |||
95 | /* OUTPUT_DATA register */ | ||
96 | #define TAS2552_PDM_DATA_I 0x00 | ||
97 | #define TAS2552_PDM_DATA_V (1 << 6) | ||
98 | #define TAS2552_PDM_DATA_I_V (1 << 7) | ||
99 | #define TAS2552_PDM_DATA_V_I (0x11 << 6) | ||
100 | |||
101 | /* PDM CFG Register */ | ||
102 | #define TAS2552_PDM_DATA_ES_RISE 0x4 | ||
103 | |||
104 | #define TAS2552_PDM_PLL_CLK_SEL 0x00 | ||
105 | #define TAS2552_PDM_IV_CLK_SEL (1 << 1) | ||
106 | #define TAS2552_PDM_BCLK_SEL (1 << 2) | ||
107 | #define TAS2552_PDM_MCLK_SEL (1 << 3) | ||
108 | |||
109 | /* Boost pass-through register */ | ||
110 | #define TAS2552_APT_DELAY_50 0x00 | ||
111 | #define TAS2552_APT_DELAY_75 (1 << 1) | ||
112 | #define TAS2552_APT_DELAY_125 (1 << 2) | ||
113 | #define TAS2552_APT_DELAY_200 (1 << 3) | ||
114 | |||
115 | #define TAS2552_APT_THRESH_2_5 0x00 | ||
116 | #define TAS2552_APT_THRESH_1_7 (1 << 3) | ||
117 | #define TAS2552_APT_THRESH_1_4_1_1 (1 << 4) | ||
118 | #define TAS2552_APT_THRESH_2_1_7 (0x11 << 2) | ||
119 | |||
120 | /* PLL Control Register */ | ||
121 | #define TAS2552_245MHZ_CLK 24576000 | ||
122 | #define TAS2552_225MHZ_CLK 22579200 | ||
123 | #define TAS2552_PLL_J_MASK 0x7f | ||
124 | #define TAS2552_PLL_D_UPPER_MASK 0x3f | ||
125 | #define TAS2552_PLL_D_LOWER_MASK 0xff | ||
126 | #define TAS2552_PLL_BYPASS_MASK 0x80 | ||
127 | #define TAS2552_PLL_BYPASS 0x80 | ||
128 | |||
129 | #endif | ||
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d48491a4a19d..249ef5c4c762 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/gpio.h> | 36 | #include <linux/gpio.h> |
37 | #include <linux/i2c.h> | 37 | #include <linux/i2c.h> |
38 | #include <linux/regmap.h> | 38 | #include <linux/regmap.h> |
39 | #include <linux/regulator/consumer.h> | ||
39 | #include <linux/spi/spi.h> | 40 | #include <linux/spi/spi.h> |
40 | #include <linux/of.h> | 41 | #include <linux/of.h> |
41 | #include <linux/of_device.h> | 42 | #include <linux/of_device.h> |
@@ -240,6 +241,10 @@ static int tas5086_reg_read(void *context, unsigned int reg, | |||
240 | return 0; | 241 | return 0; |
241 | } | 242 | } |
242 | 243 | ||
244 | static const char * const supply_names[] = { | ||
245 | "dvdd", "avdd" | ||
246 | }; | ||
247 | |||
243 | struct tas5086_private { | 248 | struct tas5086_private { |
244 | struct regmap *regmap; | 249 | struct regmap *regmap; |
245 | unsigned int mclk, sclk; | 250 | unsigned int mclk, sclk; |
@@ -251,6 +256,7 @@ struct tas5086_private { | |||
251 | int rate; | 256 | int rate; |
252 | /* GPIO driving Reset pin, if any */ | 257 | /* GPIO driving Reset pin, if any */ |
253 | int gpio_nreset; | 258 | int gpio_nreset; |
259 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
254 | }; | 260 | }; |
255 | 261 | ||
256 | static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; | 262 | static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; |
@@ -419,14 +425,14 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream, | |||
419 | } | 425 | } |
420 | 426 | ||
421 | /* ... then add the offset for the sample bit depth. */ | 427 | /* ... then add the offset for the sample bit depth. */ |
422 | switch (params_format(params)) { | 428 | switch (params_width(params)) { |
423 | case SNDRV_PCM_FORMAT_S16_LE: | 429 | case 16: |
424 | val += 0; | 430 | val += 0; |
425 | break; | 431 | break; |
426 | case SNDRV_PCM_FORMAT_S20_3LE: | 432 | case 20: |
427 | val += 1; | 433 | val += 1; |
428 | break; | 434 | break; |
429 | case SNDRV_PCM_FORMAT_S24_3LE: | 435 | case 24: |
430 | val += 2; | 436 | val += 2; |
431 | break; | 437 | break; |
432 | default: | 438 | default: |
@@ -773,6 +779,8 @@ static int tas5086_soc_suspend(struct snd_soc_codec *codec) | |||
773 | if (ret < 0) | 779 | if (ret < 0) |
774 | return ret; | 780 | return ret; |
775 | 781 | ||
782 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
783 | |||
776 | return 0; | 784 | return 0; |
777 | } | 785 | } |
778 | 786 | ||
@@ -781,6 +789,10 @@ static int tas5086_soc_resume(struct snd_soc_codec *codec) | |||
781 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 789 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
782 | int ret; | 790 | int ret; |
783 | 791 | ||
792 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
793 | if (ret < 0) | ||
794 | return ret; | ||
795 | |||
784 | tas5086_reset(priv); | 796 | tas5086_reset(priv); |
785 | regcache_mark_dirty(priv->regmap); | 797 | regcache_mark_dirty(priv->regmap); |
786 | 798 | ||
@@ -812,6 +824,12 @@ static int tas5086_probe(struct snd_soc_codec *codec) | |||
812 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 824 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
813 | int i, ret; | 825 | int i, ret; |
814 | 826 | ||
827 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
828 | if (ret < 0) { | ||
829 | dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); | ||
830 | return ret; | ||
831 | } | ||
832 | |||
815 | priv->pwm_start_mid_z = 0; | 833 | priv->pwm_start_mid_z = 0; |
816 | priv->charge_period = 1300000; /* hardware default is 1300 ms */ | 834 | priv->charge_period = 1300000; /* hardware default is 1300 ms */ |
817 | 835 | ||
@@ -832,16 +850,22 @@ static int tas5086_probe(struct snd_soc_codec *codec) | |||
832 | } | 850 | } |
833 | } | 851 | } |
834 | 852 | ||
853 | tas5086_reset(priv); | ||
835 | ret = tas5086_init(codec->dev, priv); | 854 | ret = tas5086_init(codec->dev, priv); |
836 | if (ret < 0) | 855 | if (ret < 0) |
837 | return ret; | 856 | goto exit_disable_regulators; |
838 | 857 | ||
839 | /* set master volume to 0 dB */ | 858 | /* set master volume to 0 dB */ |
840 | ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30); | 859 | ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30); |
841 | if (ret < 0) | 860 | if (ret < 0) |
842 | return ret; | 861 | goto exit_disable_regulators; |
843 | 862 | ||
844 | return 0; | 863 | return 0; |
864 | |||
865 | exit_disable_regulators: | ||
866 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
867 | |||
868 | return ret; | ||
845 | } | 869 | } |
846 | 870 | ||
847 | static int tas5086_remove(struct snd_soc_codec *codec) | 871 | static int tas5086_remove(struct snd_soc_codec *codec) |
@@ -852,6 +876,8 @@ static int tas5086_remove(struct snd_soc_codec *codec) | |||
852 | /* Set codec to the reset state */ | 876 | /* Set codec to the reset state */ |
853 | gpio_set_value(priv->gpio_nreset, 0); | 877 | gpio_set_value(priv->gpio_nreset, 0); |
854 | 878 | ||
879 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
880 | |||
855 | return 0; | 881 | return 0; |
856 | }; | 882 | }; |
857 | 883 | ||
@@ -900,6 +926,16 @@ static int tas5086_i2c_probe(struct i2c_client *i2c, | |||
900 | if (!priv) | 926 | if (!priv) |
901 | return -ENOMEM; | 927 | return -ENOMEM; |
902 | 928 | ||
929 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
930 | priv->supplies[i].supply = supply_names[i]; | ||
931 | |||
932 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies), | ||
933 | priv->supplies); | ||
934 | if (ret < 0) { | ||
935 | dev_err(dev, "Failed to get regulators: %d\n", ret); | ||
936 | return ret; | ||
937 | } | ||
938 | |||
903 | priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); | 939 | priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); |
904 | if (IS_ERR(priv->regmap)) { | 940 | if (IS_ERR(priv->regmap)) { |
905 | ret = PTR_ERR(priv->regmap); | 941 | ret = PTR_ERR(priv->regmap); |
@@ -919,21 +955,34 @@ static int tas5086_i2c_probe(struct i2c_client *i2c, | |||
919 | gpio_nreset = -EINVAL; | 955 | gpio_nreset = -EINVAL; |
920 | 956 | ||
921 | priv->gpio_nreset = gpio_nreset; | 957 | priv->gpio_nreset = gpio_nreset; |
958 | |||
959 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
960 | if (ret < 0) { | ||
961 | dev_err(dev, "Failed to enable regulators: %d\n", ret); | ||
962 | return ret; | ||
963 | } | ||
964 | |||
922 | tas5086_reset(priv); | 965 | tas5086_reset(priv); |
923 | 966 | ||
924 | /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ | 967 | /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ |
925 | ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); | 968 | ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); |
926 | if (ret < 0) | 969 | if (ret == 0 && i != 0x3) { |
927 | return ret; | ||
928 | |||
929 | if (i != 0x3) { | ||
930 | dev_err(dev, | 970 | dev_err(dev, |
931 | "Failed to identify TAS5086 codec (got %02x)\n", i); | 971 | "Failed to identify TAS5086 codec (got %02x)\n", i); |
932 | return -ENODEV; | 972 | ret = -ENODEV; |
933 | } | 973 | } |
934 | 974 | ||
935 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, | 975 | /* |
936 | &tas5086_dai, 1); | 976 | * The chip has been identified, so we can turn off the power |
977 | * again until the dai link is set up. | ||
978 | */ | ||
979 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
980 | |||
981 | if (ret == 0) | ||
982 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, | ||
983 | &tas5086_dai, 1); | ||
984 | |||
985 | return ret; | ||
937 | } | 986 | } |
938 | 987 | ||
939 | static int tas5086_i2c_remove(struct i2c_client *i2c) | 988 | static int tas5086_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 686b8b85b956..d67167920c2f 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -364,16 +364,16 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | |||
364 | 364 | ||
365 | iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); | 365 | iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); |
366 | 366 | ||
367 | switch (params_format(params)) { | 367 | switch (params_width(params)) { |
368 | case SNDRV_PCM_FORMAT_S16_LE: | 368 | case 16: |
369 | break; | 369 | break; |
370 | case SNDRV_PCM_FORMAT_S20_3LE: | 370 | case 20: |
371 | iface_reg |= (0x01 << 2); | 371 | iface_reg |= (0x01 << 2); |
372 | break; | 372 | break; |
373 | case SNDRV_PCM_FORMAT_S24_LE: | 373 | case 24: |
374 | iface_reg |= (0x02 << 2); | 374 | iface_reg |= (0x02 << 2); |
375 | break; | 375 | break; |
376 | case SNDRV_PCM_FORMAT_S32_LE: | 376 | case 32: |
377 | iface_reg |= (0x03 << 2); | 377 | iface_reg |= (0x03 << 2); |
378 | break; | 378 | break; |
379 | } | 379 | } |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 43069de3d56a..620ab9ea1ef0 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -71,8 +71,8 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
71 | 71 | ||
72 | dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n", | 72 | dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n", |
73 | substream, params); | 73 | substream, params); |
74 | dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params), | 74 | dev_dbg(&aic26->spi->dev, "rate=%i width=%d\n", params_rate(params), |
75 | params_format(params)); | 75 | params_width(params)); |
76 | 76 | ||
77 | switch (params_rate(params)) { | 77 | switch (params_rate(params)) { |
78 | case 8000: fsref = 48000; divisor = AIC26_DIV_6; break; | 78 | case 8000: fsref = 48000; divisor = AIC26_DIV_6; break; |
@@ -89,11 +89,11 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /* select data word length */ | 91 | /* select data word length */ |
92 | switch (params_format(params)) { | 92 | switch (params_width(params)) { |
93 | case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break; | 93 | case 8: wlen = AIC26_WLEN_16; break; |
94 | case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break; | 94 | case 16: wlen = AIC26_WLEN_16; break; |
95 | case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break; | 95 | case 24: wlen = AIC26_WLEN_24; break; |
96 | case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break; | 96 | case 32: wlen = AIC26_WLEN_32; break; |
97 | default: | 97 | default: |
98 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; | 98 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; |
99 | } | 99 | } |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 23419109ecac..0f64c7890eed 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -249,17 +249,16 @@ static const char * const mic_select_text[] = { | |||
249 | "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" | 249 | "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static const | 252 | static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, |
253 | SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); | 253 | mic_select_text); |
254 | static const | 254 | static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, |
255 | SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); | 255 | mic_select_text); |
256 | static const | 256 | static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, |
257 | SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); | 257 | mic_select_text); |
258 | 258 | ||
259 | static const | 259 | static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); |
260 | SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); | 260 | static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, |
261 | static const | 261 | mic_select_text); |
262 | SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); | ||
263 | 262 | ||
264 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); | 263 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); |
265 | static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); | 264 | static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); |
@@ -329,6 +328,7 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, | |||
329 | unsigned int bits; | 328 | unsigned int bits; |
330 | int counter = count; | 329 | int counter = count; |
331 | int ret = regmap_read(aic31xx->regmap, reg, &bits); | 330 | int ret = regmap_read(aic31xx->regmap, reg, &bits); |
331 | |||
332 | while ((bits & mask) != wbits && counter && !ret) { | 332 | while ((bits & mask) != wbits && counter && !ret) { |
333 | usleep_range(sleep, sleep * 2); | 333 | usleep_range(sleep, sleep * 2); |
334 | ret = regmap_read(aic31xx->regmap, reg, &bits); | 334 | ret = regmap_read(aic31xx->regmap, reg, &bits); |
@@ -435,6 +435,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
435 | { | 435 | { |
436 | struct snd_soc_codec *codec = w->codec; | 436 | struct snd_soc_codec *codec = w->codec; |
437 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 437 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
438 | |||
438 | switch (event) { | 439 | switch (event) { |
439 | case SND_SOC_DAPM_POST_PMU: | 440 | case SND_SOC_DAPM_POST_PMU: |
440 | /* change mic bias voltage to user defined */ | 441 | /* change mic bias voltage to user defined */ |
@@ -759,8 +760,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, | |||
759 | struct snd_soc_codec *codec = dai->codec; | 760 | struct snd_soc_codec *codec = dai->codec; |
760 | u8 data = 0; | 761 | u8 data = 0; |
761 | 762 | ||
762 | dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", | 763 | dev_dbg(codec->dev, "## %s: width %d rate %d\n", |
763 | __func__, params_format(params), params_width(params), | 764 | __func__, params_width(params), |
764 | params_rate(params)); | 765 | params_rate(params)); |
765 | 766 | ||
766 | switch (params_width(params)) { | 767 | switch (params_width(params)) { |
@@ -779,8 +780,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, | |||
779 | AIC31XX_IFACE1_DATALEN_SHIFT); | 780 | AIC31XX_IFACE1_DATALEN_SHIFT); |
780 | break; | 781 | break; |
781 | default: | 782 | default: |
782 | dev_err(codec->dev, "%s: Unsupported format %d\n", | 783 | dev_err(codec->dev, "%s: Unsupported width %d\n", |
783 | __func__, params_format(params)); | 784 | __func__, params_width(params)); |
784 | return -EINVAL; | 785 | return -EINVAL; |
785 | } | 786 | } |
786 | 787 | ||
@@ -1178,7 +1179,7 @@ static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) | |||
1178 | } | 1179 | } |
1179 | #endif /* CONFIG_OF */ | 1180 | #endif /* CONFIG_OF */ |
1180 | 1181 | ||
1181 | static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | 1182 | static int aic31xx_device_init(struct aic31xx_priv *aic31xx) |
1182 | { | 1183 | { |
1183 | int ret, i; | 1184 | int ret, i; |
1184 | 1185 | ||
@@ -1197,7 +1198,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | |||
1197 | "aic31xx-reset-pin"); | 1198 | "aic31xx-reset-pin"); |
1198 | if (ret < 0) { | 1199 | if (ret < 0) { |
1199 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); | 1200 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); |
1200 | return; | 1201 | return ret; |
1201 | } | 1202 | } |
1202 | } | 1203 | } |
1203 | 1204 | ||
@@ -1210,6 +1211,7 @@ static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | |||
1210 | if (ret != 0) | 1211 | if (ret != 0) |
1211 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); | 1212 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); |
1212 | 1213 | ||
1214 | return ret; | ||
1213 | } | 1215 | } |
1214 | 1216 | ||
1215 | static int aic31xx_i2c_probe(struct i2c_client *i2c, | 1217 | static int aic31xx_i2c_probe(struct i2c_client *i2c, |
@@ -1239,7 +1241,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1239 | 1241 | ||
1240 | aic31xx->pdata.codec_type = id->driver_data; | 1242 | aic31xx->pdata.codec_type = id->driver_data; |
1241 | 1243 | ||
1242 | aic31xx_device_init(aic31xx); | 1244 | ret = aic31xx_device_init(aic31xx); |
1245 | if (ret) | ||
1246 | return ret; | ||
1243 | 1247 | ||
1244 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, | 1248 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, |
1245 | aic31xx_dai_driver, | 1249 | aic31xx_dai_driver, |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1d9b117345a3..6ea662db2410 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -450,16 +450,16 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, | |||
450 | 450 | ||
451 | data = snd_soc_read(codec, AIC32X4_IFACE1); | 451 | data = snd_soc_read(codec, AIC32X4_IFACE1); |
452 | data = data & ~(3 << 4); | 452 | data = data & ~(3 << 4); |
453 | switch (params_format(params)) { | 453 | switch (params_width(params)) { |
454 | case SNDRV_PCM_FORMAT_S16_LE: | 454 | case 16: |
455 | break; | 455 | break; |
456 | case SNDRV_PCM_FORMAT_S20_3LE: | 456 | case 20: |
457 | data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT); | 457 | data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT); |
458 | break; | 458 | break; |
459 | case SNDRV_PCM_FORMAT_S24_LE: | 459 | case 24: |
460 | data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT); | 460 | data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT); |
461 | break; | 461 | break; |
462 | case SNDRV_PCM_FORMAT_S32_LE: | 462 | case 32: |
463 | data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT); | 463 | data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT); |
464 | break; | 464 | break; |
465 | } | 465 | } |
@@ -626,32 +626,33 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
626 | snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | | 626 | snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | |
627 | AIC32X4_MICBIAS_2075V); | 627 | AIC32X4_MICBIAS_2075V); |
628 | } | 628 | } |
629 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { | 629 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) |
630 | snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); | 630 | snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); |
631 | } | ||
632 | 631 | ||
633 | tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? | 632 | tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? |
634 | AIC32X4_LDOCTLEN : 0; | 633 | AIC32X4_LDOCTLEN : 0; |
635 | snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); | 634 | snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); |
636 | 635 | ||
637 | tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); | 636 | tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); |
638 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { | 637 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) |
639 | tmp_reg |= AIC32X4_LDOIN_18_36; | 638 | tmp_reg |= AIC32X4_LDOIN_18_36; |
640 | } | 639 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) |
641 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) { | ||
642 | tmp_reg |= AIC32X4_LDOIN2HP; | 640 | tmp_reg |= AIC32X4_LDOIN2HP; |
643 | } | ||
644 | snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); | 641 | snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); |
645 | 642 | ||
646 | /* Mic PGA routing */ | 643 | /* Mic PGA routing */ |
647 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) | 644 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) |
648 | snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); | 645 | snd_soc_write(codec, AIC32X4_LMICPGANIN, |
646 | AIC32X4_LMICPGANIN_IN2R_10K); | ||
649 | else | 647 | else |
650 | snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_CM1L_10K); | 648 | snd_soc_write(codec, AIC32X4_LMICPGANIN, |
649 | AIC32X4_LMICPGANIN_CM1L_10K); | ||
651 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) | 650 | if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) |
652 | snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); | 651 | snd_soc_write(codec, AIC32X4_RMICPGANIN, |
652 | AIC32X4_RMICPGANIN_IN1L_10K); | ||
653 | else | 653 | else |
654 | snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_CM1R_10K); | 654 | snd_soc_write(codec, AIC32X4_RMICPGANIN, |
655 | AIC32X4_RMICPGANIN_CM1R_10K); | ||
655 | 656 | ||
656 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 657 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
657 | 658 | ||
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e12fafbb1e09..64f179ee9834 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -873,16 +873,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
873 | 873 | ||
874 | /* select data word length */ | 874 | /* select data word length */ |
875 | data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); | 875 | data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); |
876 | switch (params_format(params)) { | 876 | switch (params_width(params)) { |
877 | case SNDRV_PCM_FORMAT_S16_LE: | 877 | case 16: |
878 | break; | 878 | break; |
879 | case SNDRV_PCM_FORMAT_S20_3LE: | 879 | case 20: |
880 | data |= (0x01 << 4); | 880 | data |= (0x01 << 4); |
881 | break; | 881 | break; |
882 | case SNDRV_PCM_FORMAT_S24_LE: | 882 | case 24: |
883 | data |= (0x02 << 4); | 883 | data |= (0x02 << 4); |
884 | break; | 884 | break; |
885 | case SNDRV_PCM_FORMAT_S32_LE: | 885 | case 32: |
886 | data |= (0x03 << 4); | 886 | data |= (0x03 << 4); |
887 | break; | 887 | break; |
888 | } | 888 | } |
@@ -1194,7 +1194,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, | |||
1194 | 1194 | ||
1195 | #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 | 1195 | #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 |
1196 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1196 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1197 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | 1197 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
1198 | SNDRV_PCM_FMTBIT_S32_LE) | ||
1198 | 1199 | ||
1199 | static const struct snd_soc_dai_ops aic3x_dai_ops = { | 1200 | static const struct snd_soc_dai_ops aic3x_dai_ops = { |
1200 | .hw_params = aic3x_hw_params, | 1201 | .hw_params = aic3x_hw_params, |
@@ -1477,10 +1478,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1477 | u32 value; | 1478 | u32 value; |
1478 | 1479 | ||
1479 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1480 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
1480 | if (aic3x == NULL) { | 1481 | if (!aic3x) |
1481 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1482 | return -ENOMEM; | 1482 | return -ENOMEM; |
1483 | } | ||
1484 | 1483 | ||
1485 | aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); | 1484 | aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); |
1486 | if (IS_ERR(aic3x->regmap)) { | 1485 | if (IS_ERR(aic3x->regmap)) { |
@@ -1498,10 +1497,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1498 | } else if (np) { | 1497 | } else if (np) { |
1499 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | 1498 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), |
1500 | GFP_KERNEL); | 1499 | GFP_KERNEL); |
1501 | if (ai3x_setup == NULL) { | 1500 | if (!ai3x_setup) |
1502 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1503 | return -ENOMEM; | 1501 | return -ENOMEM; |
1504 | } | ||
1505 | 1502 | ||
1506 | ret = of_get_named_gpio(np, "gpio-reset", 0); | 1503 | ret = of_get_named_gpio(np, "gpio-reset", 0); |
1507 | if (ret >= 0) | 1504 | if (ret >= 0) |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index df3a7506c023..e21ed934bdbf 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -832,18 +832,18 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, | |||
832 | return -EINVAL; | 832 | return -EINVAL; |
833 | } | 833 | } |
834 | 834 | ||
835 | switch (params_format(params)) { | 835 | switch (params_width(params)) { |
836 | case SNDRV_PCM_FORMAT_S16_LE: | 836 | case 16: |
837 | dac33->fifo_size = DAC33_FIFO_SIZE_16BIT; | 837 | dac33->fifo_size = DAC33_FIFO_SIZE_16BIT; |
838 | dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32); | 838 | dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32); |
839 | break; | 839 | break; |
840 | case SNDRV_PCM_FORMAT_S32_LE: | 840 | case 32: |
841 | dac33->fifo_size = DAC33_FIFO_SIZE_24BIT; | 841 | dac33->fifo_size = DAC33_FIFO_SIZE_24BIT; |
842 | dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64); | 842 | dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64); |
843 | break; | 843 | break; |
844 | default: | 844 | default: |
845 | dev_err(codec->dev, "unsupported format %d\n", | 845 | dev_err(codec->dev, "unsupported width %d\n", |
846 | params_format(params)); | 846 | params_width(params)); |
847 | return -EINVAL; | 847 | return -EINVAL; |
848 | } | 848 | } |
849 | 849 | ||
@@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) | |||
1404 | if (dac33->irq >= 0) { | 1404 | if (dac33->irq >= 0) { |
1405 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | 1405 | ret = request_irq(dac33->irq, dac33_interrupt_handler, |
1406 | IRQF_TRIGGER_RISING, | 1406 | IRQF_TRIGGER_RISING, |
1407 | codec->name, codec); | 1407 | codec->component.name, codec); |
1408 | if (ret < 0) { | 1408 | if (ret < 0) { |
1409 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | 1409 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", |
1410 | dac33->irq, ret); | 1410 | dac33->irq, ret); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 8fc5a647453b..6fac9e034c48 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -381,10 +381,8 @@ static int tpa6130a2_probe(struct i2c_client *client, | |||
381 | dev = &client->dev; | 381 | dev = &client->dev; |
382 | 382 | ||
383 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); | 383 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); |
384 | if (data == NULL) { | 384 | if (!data) |
385 | dev_err(dev, "Can not allocate memory\n"); | ||
386 | return -ENOMEM; | 385 | return -ENOMEM; |
387 | } | ||
388 | 386 | ||
389 | if (pdata) { | 387 | if (pdata) { |
390 | data->power_gpio = pdata->power_gpio; | 388 | data->power_gpio = pdata->power_gpio; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 69e12a311ba2..b6b0cb399599 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -344,17 +344,16 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
344 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) | 344 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) |
345 | { | 345 | { |
346 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 346 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
347 | int status = -1; | ||
348 | 347 | ||
349 | if (enable) { | 348 | if (enable) { |
350 | twl4030->apll_enabled++; | 349 | twl4030->apll_enabled++; |
351 | if (twl4030->apll_enabled == 1) | 350 | if (twl4030->apll_enabled == 1) |
352 | status = twl4030_audio_enable_resource( | 351 | twl4030_audio_enable_resource( |
353 | TWL4030_AUDIO_RES_APLL); | 352 | TWL4030_AUDIO_RES_APLL); |
354 | } else { | 353 | } else { |
355 | twl4030->apll_enabled--; | 354 | twl4030->apll_enabled--; |
356 | if (!twl4030->apll_enabled) | 355 | if (!twl4030->apll_enabled) |
357 | status = twl4030_audio_disable_resource( | 356 | twl4030_audio_disable_resource( |
358 | TWL4030_AUDIO_RES_APLL); | 357 | TWL4030_AUDIO_RES_APLL); |
359 | } | 358 | } |
360 | } | 359 | } |
@@ -1764,16 +1763,16 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1764 | old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF); | 1763 | old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
1765 | format = old_format; | 1764 | format = old_format; |
1766 | format &= ~TWL4030_DATA_WIDTH; | 1765 | format &= ~TWL4030_DATA_WIDTH; |
1767 | switch (params_format(params)) { | 1766 | switch (params_width(params)) { |
1768 | case SNDRV_PCM_FORMAT_S16_LE: | 1767 | case 16: |
1769 | format |= TWL4030_DATA_WIDTH_16S_16W; | 1768 | format |= TWL4030_DATA_WIDTH_16S_16W; |
1770 | break; | 1769 | break; |
1771 | case SNDRV_PCM_FORMAT_S32_LE: | 1770 | case 32: |
1772 | format |= TWL4030_DATA_WIDTH_32S_24W; | 1771 | format |= TWL4030_DATA_WIDTH_32S_24W; |
1773 | break; | 1772 | break; |
1774 | default: | 1773 | default: |
1775 | dev_err(codec->dev, "%s: unknown format %d\n", __func__, | 1774 | dev_err(codec->dev, "%s: unsupported bits/sample %d\n", |
1776 | params_format(params)); | 1775 | __func__, params_width(params)); |
1777 | return -EINVAL; | 1776 | return -EINVAL; |
1778 | } | 1777 | } |
1779 | 1778 | ||
@@ -2162,10 +2161,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
2162 | 2161 | ||
2163 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), | 2162 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), |
2164 | GFP_KERNEL); | 2163 | GFP_KERNEL); |
2165 | if (twl4030 == NULL) { | 2164 | if (!twl4030) |
2166 | dev_err(codec->dev, "Can not allocate memory\n"); | ||
2167 | return -ENOMEM; | 2165 | return -ENOMEM; |
2168 | } | ||
2169 | snd_soc_codec_set_drvdata(codec, twl4030); | 2166 | snd_soc_codec_set_drvdata(codec, twl4030); |
2170 | /* Set the defaults, and power up the codec */ | 2167 | /* Set the defaults, and power up the codec */ |
2171 | twl4030->sysclk = twl4030_audio_get_mclk() / 1000; | 2168 | twl4030->sysclk = twl4030_audio_get_mclk() / 1000; |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index edf27acc1d77..32b2f78aa62c 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -243,14 +243,14 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
243 | case SND_SOC_DAIFMT_I2S: | 243 | case SND_SOC_DAIFMT_I2S: |
244 | break; | 244 | break; |
245 | case SND_SOC_DAIFMT_RIGHT_J: | 245 | case SND_SOC_DAIFMT_RIGHT_J: |
246 | switch (params_format(params)) { | 246 | switch (params_width(params)) { |
247 | case SNDRV_PCM_FORMAT_S16_LE: | 247 | case 16: |
248 | hw_params |= (1<<1); | 248 | hw_params |= (1<<1); |
249 | break; | 249 | break; |
250 | case SNDRV_PCM_FORMAT_S18_3LE: | 250 | case 18: |
251 | hw_params |= (1<<2); | 251 | hw_params |= (1<<2); |
252 | break; | 252 | break; |
253 | case SNDRV_PCM_FORMAT_S20_3LE: | 253 | case 20: |
254 | hw_params |= ((1<<2) | (1<<1)); | 254 | hw_params |= ((1<<2) | (1<<1)); |
255 | break; | 255 | break; |
256 | default: | 256 | default: |
@@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = { | |||
479 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | 479 | static int uda134x_soc_probe(struct snd_soc_codec *codec) |
480 | { | 480 | { |
481 | struct uda134x_priv *uda134x; | 481 | struct uda134x_priv *uda134x; |
482 | struct uda134x_platform_data *pd = codec->card->dev->platform_data; | 482 | struct uda134x_platform_data *pd = codec->component.card->dev->platform_data; |
483 | const struct snd_soc_dapm_widget *widgets; | 483 | const struct snd_soc_dapm_widget *widgets; |
484 | unsigned num_widgets; | 484 | unsigned num_widgets; |
485 | 485 | ||
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 4ead0dc02b87..f3d4e88d0b7b 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -341,8 +341,9 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream, | |||
341 | struct wl1273_core *core = wl1273->core; | 341 | struct wl1273_core *core = wl1273->core; |
342 | unsigned int rate, width, r; | 342 | unsigned int rate, width, r; |
343 | 343 | ||
344 | if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) { | 344 | if (params_width(params) != 16) { |
345 | pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n"); | 345 | dev_err(dai->dev, "%d bits/sample not supported\n", |
346 | params_width(params)); | ||
346 | return -EINVAL; | 347 | return -EINVAL; |
347 | } | 348 | } |
348 | 349 | ||
@@ -461,10 +462,8 @@ static int wl1273_probe(struct snd_soc_codec *codec) | |||
461 | } | 462 | } |
462 | 463 | ||
463 | wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); | 464 | wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); |
464 | if (wl1273 == NULL) { | 465 | if (!wl1273) |
465 | dev_err(codec->dev, "Cannot allocate memory.\n"); | ||
466 | return -ENOMEM; | 466 | return -ENOMEM; |
467 | } | ||
468 | 467 | ||
469 | wl1273->mode = WL1273_MODE_BT; | 468 | wl1273->mode = WL1273_MODE_BT; |
470 | wl1273->core = *core; | 469 | wl1273->core = *core; |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 71ce3159a62e..f37989ec7cba 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -144,7 +144,7 @@ static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { | |||
144 | 144 | ||
145 | static const char *wm0010_state_to_str(enum wm0010_state state) | 145 | static const char *wm0010_state_to_str(enum wm0010_state state) |
146 | { | 146 | { |
147 | const char *state_to_str[] = { | 147 | static const char * const state_to_str[] = { |
148 | "Power off", | 148 | "Power off", |
149 | "Out of reset", | 149 | "Out of reset", |
150 | "Boot ROM", | 150 | "Boot ROM", |
@@ -413,7 +413,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
413 | 413 | ||
414 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | 414 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); |
415 | if (!xfer) { | 415 | if (!xfer) { |
416 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
417 | ret = -ENOMEM; | 416 | ret = -ENOMEM; |
418 | goto abort; | 417 | goto abort; |
419 | } | 418 | } |
@@ -423,8 +422,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
423 | 422 | ||
424 | out = kzalloc(len, GFP_KERNEL | GFP_DMA); | 423 | out = kzalloc(len, GFP_KERNEL | GFP_DMA); |
425 | if (!out) { | 424 | if (!out) { |
426 | dev_err(codec->dev, | ||
427 | "Failed to allocate RX buffer\n"); | ||
428 | ret = -ENOMEM; | 425 | ret = -ENOMEM; |
429 | goto abort1; | 426 | goto abort1; |
430 | } | 427 | } |
@@ -432,8 +429,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) | |||
432 | 429 | ||
433 | img = kzalloc(len, GFP_KERNEL | GFP_DMA); | 430 | img = kzalloc(len, GFP_KERNEL | GFP_DMA); |
434 | if (!img) { | 431 | if (!img) { |
435 | dev_err(codec->dev, | ||
436 | "Failed to allocate image buffer\n"); | ||
437 | ret = -ENOMEM; | 432 | ret = -ENOMEM; |
438 | goto abort1; | 433 | goto abort1; |
439 | } | 434 | } |
@@ -526,14 +521,12 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec) | |||
526 | /* Copy to local buffer first as vmalloc causes problems for dma */ | 521 | /* Copy to local buffer first as vmalloc causes problems for dma */ |
527 | img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); | 522 | img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); |
528 | if (!img) { | 523 | if (!img) { |
529 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
530 | ret = -ENOMEM; | 524 | ret = -ENOMEM; |
531 | goto abort2; | 525 | goto abort2; |
532 | } | 526 | } |
533 | 527 | ||
534 | out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); | 528 | out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); |
535 | if (!out) { | 529 | if (!out) { |
536 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
537 | ret = -ENOMEM; | 530 | ret = -ENOMEM; |
538 | goto abort1; | 531 | goto abort1; |
539 | } | 532 | } |
@@ -679,11 +672,8 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
679 | } | 672 | } |
680 | 673 | ||
681 | img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); | 674 | img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); |
682 | if (!img_swap) { | 675 | if (!img_swap) |
683 | dev_err(codec->dev, | ||
684 | "Failed to allocate image buffer\n"); | ||
685 | goto abort; | 676 | goto abort; |
686 | } | ||
687 | 677 | ||
688 | /* We need to re-order for 0010 */ | 678 | /* We need to re-order for 0010 */ |
689 | byte_swap_64((u64 *)&pll_rec, img_swap, len); | 679 | byte_swap_64((u64 *)&pll_rec, img_swap, len); |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 6e6b93d4696e..8011f75fb6cb 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -164,7 +164,6 @@ static int wm1250_ev1_pdata(struct i2c_client *i2c) | |||
164 | 164 | ||
165 | wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL); | 165 | wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL); |
166 | if (!wm1250) { | 166 | if (!wm1250) { |
167 | dev_err(&i2c->dev, "Unable to allocate private data\n"); | ||
168 | ret = -ENOMEM; | 167 | ret = -ENOMEM; |
169 | goto err; | 168 | goto err; |
170 | } | 169 | } |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a4c352cc3464..34ef65c52a7d 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -826,10 +826,8 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
826 | 826 | ||
827 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), | 827 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), |
828 | GFP_KERNEL); | 828 | GFP_KERNEL); |
829 | if (wm2000 == NULL) { | 829 | if (!wm2000) |
830 | dev_err(&i2c->dev, "Unable to allocate private data\n"); | ||
831 | return -ENOMEM; | 830 | return -ENOMEM; |
832 | } | ||
833 | 831 | ||
834 | mutex_init(&wm2000->lock); | 832 | mutex_init(&wm2000->lock); |
835 | 833 | ||
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 91a9ea2a2056..7bb0d36d4c54 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -735,8 +735,7 @@ WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE), | |||
735 | static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, | 735 | static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, |
736 | enum snd_soc_dapm_type event, int subseq) | 736 | enum snd_soc_dapm_type event, int subseq) |
737 | { | 737 | { |
738 | struct snd_soc_codec *codec = container_of(dapm, | 738 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
739 | struct snd_soc_codec, dapm); | ||
740 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 739 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
741 | u16 val, expect, i; | 740 | u16 val, expect, i; |
742 | 741 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 289b64d89abd..f60234962527 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -612,6 +612,62 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
612 | return 0; | 612 | return 0; |
613 | } | 613 | } |
614 | 614 | ||
615 | static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | ||
616 | struct snd_ctl_elem_value *ucontrol) | ||
617 | { | ||
618 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
620 | uint16_t data; | ||
621 | |||
622 | mutex_lock(&codec->mutex); | ||
623 | data = cpu_to_be16(arizona->dac_comp_coeff); | ||
624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); | ||
625 | mutex_unlock(&codec->mutex); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol, | ||
631 | struct snd_ctl_elem_value *ucontrol) | ||
632 | { | ||
633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
635 | |||
636 | mutex_lock(&codec->mutex); | ||
637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, | ||
638 | sizeof(arizona->dac_comp_coeff)); | ||
639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); | ||
640 | mutex_unlock(&codec->mutex); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, | ||
646 | struct snd_ctl_elem_value *ucontrol) | ||
647 | { | ||
648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
650 | |||
651 | mutex_lock(&codec->mutex); | ||
652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; | ||
653 | mutex_unlock(&codec->mutex); | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol, | ||
659 | struct snd_ctl_elem_value *ucontrol) | ||
660 | { | ||
661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
663 | |||
664 | mutex_lock(&codec->mutex); | ||
665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; | ||
666 | mutex_unlock(&codec->mutex); | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | |||
615 | static const char *wm5102_osr_text[] = { | 671 | static const char *wm5102_osr_text[] = { |
616 | "Low power", "Normal", "High performance", | 672 | "Low power", "Normal", "High performance", |
617 | }; | 673 | }; |
@@ -843,6 +899,12 @@ SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL, | |||
843 | ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), | 899 | ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), |
844 | SOC_ENUM("Noise Gate Hold", arizona_ng_hold), | 900 | SOC_ENUM("Noise Gate Hold", arizona_ng_hold), |
845 | 901 | ||
902 | SND_SOC_BYTES_EXT("Output Compensation Coefficient", 2, | ||
903 | wm5102_out_comp_coeff_get, wm5102_out_comp_coeff_put), | ||
904 | |||
905 | SOC_SINGLE_EXT("Output Compensation Switch", 0, 0, 1, 0, | ||
906 | wm5102_out_comp_switch_get, wm5102_out_comp_switch_put), | ||
907 | |||
846 | WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L), | 908 | WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L), |
847 | WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R), | 909 | WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R), |
848 | WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L), | 910 | WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L), |
@@ -1653,6 +1715,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1653 | }, | 1715 | }, |
1654 | .ops = &arizona_dai_ops, | 1716 | .ops = &arizona_dai_ops, |
1655 | .symmetric_rates = 1, | 1717 | .symmetric_rates = 1, |
1718 | .symmetric_samplebits = 1, | ||
1656 | }, | 1719 | }, |
1657 | { | 1720 | { |
1658 | .name = "wm5102-aif2", | 1721 | .name = "wm5102-aif2", |
@@ -1674,6 +1737,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1674 | }, | 1737 | }, |
1675 | .ops = &arizona_dai_ops, | 1738 | .ops = &arizona_dai_ops, |
1676 | .symmetric_rates = 1, | 1739 | .symmetric_rates = 1, |
1740 | .symmetric_samplebits = 1, | ||
1677 | }, | 1741 | }, |
1678 | { | 1742 | { |
1679 | .name = "wm5102-aif3", | 1743 | .name = "wm5102-aif3", |
@@ -1695,6 +1759,7 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1695 | }, | 1759 | }, |
1696 | .ops = &arizona_dai_ops, | 1760 | .ops = &arizona_dai_ops, |
1697 | .symmetric_rates = 1, | 1761 | .symmetric_rates = 1, |
1762 | .symmetric_samplebits = 1, | ||
1698 | }, | 1763 | }, |
1699 | { | 1764 | { |
1700 | .name = "wm5102-slim1", | 1765 | .name = "wm5102-slim1", |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2e5fcb559e90..2f2ec26d831c 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -1485,6 +1485,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1485 | }, | 1485 | }, |
1486 | .ops = &arizona_dai_ops, | 1486 | .ops = &arizona_dai_ops, |
1487 | .symmetric_rates = 1, | 1487 | .symmetric_rates = 1, |
1488 | .symmetric_samplebits = 1, | ||
1488 | }, | 1489 | }, |
1489 | { | 1490 | { |
1490 | .name = "wm5110-aif2", | 1491 | .name = "wm5110-aif2", |
@@ -1506,6 +1507,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1506 | }, | 1507 | }, |
1507 | .ops = &arizona_dai_ops, | 1508 | .ops = &arizona_dai_ops, |
1508 | .symmetric_rates = 1, | 1509 | .symmetric_rates = 1, |
1510 | .symmetric_samplebits = 1, | ||
1509 | }, | 1511 | }, |
1510 | { | 1512 | { |
1511 | .name = "wm5110-aif3", | 1513 | .name = "wm5110-aif3", |
@@ -1527,6 +1529,7 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
1527 | }, | 1529 | }, |
1528 | .ops = &arizona_dai_ops, | 1530 | .ops = &arizona_dai_ops, |
1529 | .symmetric_rates = 1, | 1531 | .symmetric_rates = 1, |
1532 | .symmetric_samplebits = 1, | ||
1530 | }, | 1533 | }, |
1531 | { | 1534 | { |
1532 | .name = "wm5110-slim1", | 1535 | .name = "wm5110-slim1", |
@@ -1596,6 +1599,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1596 | 1599 | ||
1597 | arizona_init_spk(codec); | 1600 | arizona_init_spk(codec); |
1598 | arizona_init_gpio(codec); | 1601 | arizona_init_gpio(codec); |
1602 | arizona_init_mono(codec); | ||
1599 | 1603 | ||
1600 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); | 1604 | ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); |
1601 | if (ret != 0) | 1605 | if (ret != 0) |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 392285edb595..3dfdcc4197fa 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -918,16 +918,16 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, | |||
918 | ~WM8350_AIF_WL_MASK; | 918 | ~WM8350_AIF_WL_MASK; |
919 | 919 | ||
920 | /* bit size */ | 920 | /* bit size */ |
921 | switch (params_format(params)) { | 921 | switch (params_width(params)) { |
922 | case SNDRV_PCM_FORMAT_S16_LE: | 922 | case 16: |
923 | break; | 923 | break; |
924 | case SNDRV_PCM_FORMAT_S20_3LE: | 924 | case 20: |
925 | iface |= 0x1 << 10; | 925 | iface |= 0x1 << 10; |
926 | break; | 926 | break; |
927 | case SNDRV_PCM_FORMAT_S24_LE: | 927 | case 24: |
928 | iface |= 0x2 << 10; | 928 | iface |= 0x2 << 10; |
929 | break; | 929 | break; |
930 | case SNDRV_PCM_FORMAT_S32_LE: | 930 | case 32: |
931 | iface |= 0x3 << 10; | 931 | iface |= 0x3 << 10; |
932 | break; | 932 | break; |
933 | } | 933 | } |
@@ -1341,21 +1341,18 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | |||
1341 | { | 1341 | { |
1342 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | 1342 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); |
1343 | struct wm8350 *wm8350 = priv->wm8350; | 1343 | struct wm8350 *wm8350 = priv->wm8350; |
1344 | int irq; | ||
1345 | int ena; | 1344 | int ena; |
1346 | 1345 | ||
1347 | switch (which) { | 1346 | switch (which) { |
1348 | case WM8350_JDL: | 1347 | case WM8350_JDL: |
1349 | priv->hpl.jack = jack; | 1348 | priv->hpl.jack = jack; |
1350 | priv->hpl.report = report; | 1349 | priv->hpl.report = report; |
1351 | irq = WM8350_IRQ_CODEC_JCK_DET_L; | ||
1352 | ena = WM8350_JDL_ENA; | 1350 | ena = WM8350_JDL_ENA; |
1353 | break; | 1351 | break; |
1354 | 1352 | ||
1355 | case WM8350_JDR: | 1353 | case WM8350_JDR: |
1356 | priv->hpr.jack = jack; | 1354 | priv->hpr.jack = jack; |
1357 | priv->hpr.report = report; | 1355 | priv->hpr.report = report; |
1358 | irq = WM8350_IRQ_CODEC_JCK_DET_R; | ||
1359 | ena = WM8350_JDR_ENA; | 1356 | ena = WM8350_JDR_ENA; |
1360 | break; | 1357 | break; |
1361 | 1358 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 06e913d3fea1..72471bef2e9a 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1095,16 +1095,16 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, | |||
1095 | 1095 | ||
1096 | audio1 &= ~WM8400_AIF_WL_MASK; | 1096 | audio1 &= ~WM8400_AIF_WL_MASK; |
1097 | /* bit size */ | 1097 | /* bit size */ |
1098 | switch (params_format(params)) { | 1098 | switch (params_width(params)) { |
1099 | case SNDRV_PCM_FORMAT_S16_LE: | 1099 | case 16: |
1100 | break; | 1100 | break; |
1101 | case SNDRV_PCM_FORMAT_S20_3LE: | 1101 | case 20: |
1102 | audio1 |= WM8400_AIF_WL_20BITS; | 1102 | audio1 |= WM8400_AIF_WL_20BITS; |
1103 | break; | 1103 | break; |
1104 | case SNDRV_PCM_FORMAT_S24_LE: | 1104 | case 24: |
1105 | audio1 |= WM8400_AIF_WL_24BITS; | 1105 | audio1 |= WM8400_AIF_WL_24BITS; |
1106 | break; | 1106 | break; |
1107 | case SNDRV_PCM_FORMAT_S32_LE: | 1107 | case 32: |
1108 | audio1 |= WM8400_AIF_WL_32BITS; | 1108 | audio1 |= WM8400_AIF_WL_32BITS; |
1109 | break; | 1109 | break; |
1110 | } | 1110 | } |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 1c1e328feeb8..e11127f9069e 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -449,16 +449,16 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | |||
449 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; | 449 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; |
450 | 450 | ||
451 | /* bit size */ | 451 | /* bit size */ |
452 | switch (params_format(params)) { | 452 | switch (params_width(params)) { |
453 | case SNDRV_PCM_FORMAT_S16_LE: | 453 | case 16: |
454 | break; | 454 | break; |
455 | case SNDRV_PCM_FORMAT_S20_3LE: | 455 | case 20: |
456 | iface |= 0x0020; | 456 | iface |= 0x0020; |
457 | break; | 457 | break; |
458 | case SNDRV_PCM_FORMAT_S24_LE: | 458 | case 24: |
459 | iface |= 0x0040; | 459 | iface |= 0x0040; |
460 | break; | 460 | break; |
461 | case SNDRV_PCM_FORMAT_S32_LE: | 461 | case 32: |
462 | iface |= 0x0060; | 462 | iface |= 0x0060; |
463 | break; | 463 | break; |
464 | } | 464 | } |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 601ee8178af1..ec1f5740dbd0 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -163,16 +163,16 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, | |||
163 | aifctrl2 |= lrclk_ratios[i].value; | 163 | aifctrl2 |= lrclk_ratios[i].value; |
164 | 164 | ||
165 | aifctrl1 &= ~WM8523_WL_MASK; | 165 | aifctrl1 &= ~WM8523_WL_MASK; |
166 | switch (params_format(params)) { | 166 | switch (params_width(params)) { |
167 | case SNDRV_PCM_FORMAT_S16_LE: | 167 | case 16: |
168 | break; | 168 | break; |
169 | case SNDRV_PCM_FORMAT_S20_3LE: | 169 | case 20: |
170 | aifctrl1 |= 0x8; | 170 | aifctrl1 |= 0x8; |
171 | break; | 171 | break; |
172 | case SNDRV_PCM_FORMAT_S24_LE: | 172 | case 24: |
173 | aifctrl1 |= 0x10; | 173 | aifctrl1 |= 0x10; |
174 | break; | 174 | break; |
175 | case SNDRV_PCM_FORMAT_S32_LE: | 175 | case 32: |
176 | aifctrl1 |= 0x18; | 176 | aifctrl1 |= 0x18; |
177 | break; | 177 | break; |
178 | } | 178 | } |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7665ff6aea6d..911605ee25b0 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -511,19 +511,19 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
511 | int i, ratio, osr; | 511 | int i, ratio, osr; |
512 | 512 | ||
513 | /* bit size */ | 513 | /* bit size */ |
514 | switch (params_format(params)) { | 514 | switch (params_width(params)) { |
515 | case SNDRV_PCM_FORMAT_S16_LE: | 515 | case 16: |
516 | paifa |= 0x8; | 516 | paifa |= 0x8; |
517 | break; | 517 | break; |
518 | case SNDRV_PCM_FORMAT_S20_3LE: | 518 | case 20: |
519 | paifa |= 0x0; | 519 | paifa |= 0x0; |
520 | paifb |= WM8580_AIF_LENGTH_20; | 520 | paifb |= WM8580_AIF_LENGTH_20; |
521 | break; | 521 | break; |
522 | case SNDRV_PCM_FORMAT_S24_LE: | 522 | case 24: |
523 | paifa |= 0x0; | 523 | paifa |= 0x0; |
524 | paifb |= WM8580_AIF_LENGTH_24; | 524 | paifb |= WM8580_AIF_LENGTH_24; |
525 | break; | 525 | break; |
526 | case SNDRV_PCM_FORMAT_S32_LE: | 526 | case 32: |
527 | paifa |= 0x0; | 527 | paifa |= 0x0; |
528 | paifb |= WM8580_AIF_LENGTH_32; | 528 | paifb |= WM8580_AIF_LENGTH_32; |
529 | break; | 529 | break; |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index b0fbcb377baf..32187e739b4f 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -169,13 +169,13 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, | |||
169 | snd_soc_write(codec, WM8711_SRATE, srate); | 169 | snd_soc_write(codec, WM8711_SRATE, srate); |
170 | 170 | ||
171 | /* bit size */ | 171 | /* bit size */ |
172 | switch (params_format(params)) { | 172 | switch (params_width(params)) { |
173 | case SNDRV_PCM_FORMAT_S16_LE: | 173 | case 16: |
174 | break; | 174 | break; |
175 | case SNDRV_PCM_FORMAT_S20_3LE: | 175 | case 20: |
176 | iface |= 0x0004; | 176 | iface |= 0x0004; |
177 | break; | 177 | break; |
178 | case SNDRV_PCM_FORMAT_S24_LE: | 178 | case 24: |
179 | iface |= 0x0008; | 179 | iface |= 0x0008; |
180 | break; | 180 | break; |
181 | } | 181 | } |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index bac7fc28fe71..38ff826f589a 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -94,13 +94,13 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, | |||
94 | 94 | ||
95 | dac &= ~0x18; | 95 | dac &= ~0x18; |
96 | 96 | ||
97 | switch (params_format(params)) { | 97 | switch (params_width(params)) { |
98 | case SNDRV_PCM_FORMAT_S16_LE: | 98 | case 16: |
99 | break; | 99 | break; |
100 | case SNDRV_PCM_FORMAT_S20_3LE: | 100 | case 20: |
101 | dac |= 0x10; | 101 | dac |= 0x10; |
102 | break; | 102 | break; |
103 | case SNDRV_PCM_FORMAT_S24_LE: | 103 | case 24: |
104 | dac |= 0x08; | 104 | dac |= 0x08; |
105 | break; | 105 | break; |
106 | default: | 106 | default: |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 5ada61611324..eebb3280bfad 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -348,13 +348,13 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
348 | snd_soc_write(codec, WM8731_SRATE, srate); | 348 | snd_soc_write(codec, WM8731_SRATE, srate); |
349 | 349 | ||
350 | /* bit size */ | 350 | /* bit size */ |
351 | switch (params_format(params)) { | 351 | switch (params_width(params)) { |
352 | case SNDRV_PCM_FORMAT_S16_LE: | 352 | case 16: |
353 | break; | 353 | break; |
354 | case SNDRV_PCM_FORMAT_S20_3LE: | 354 | case 20: |
355 | iface |= 0x0004; | 355 | iface |= 0x0004; |
356 | break; | 356 | break; |
357 | case SNDRV_PCM_FORMAT_S24_LE: | 357 | case 24: |
358 | iface |= 0x0008; | 358 | iface |= 0x0008; |
359 | break; | 359 | break; |
360 | } | 360 | } |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index b27f26cdc049..744a422ecb05 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -367,16 +367,16 @@ static int wm8737_hw_params(struct snd_pcm_substream *substream, | |||
367 | 367 | ||
368 | clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT); | 368 | clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT); |
369 | 369 | ||
370 | switch (params_format(params)) { | 370 | switch (params_width(params)) { |
371 | case SNDRV_PCM_FORMAT_S16_LE: | 371 | case 16: |
372 | break; | 372 | break; |
373 | case SNDRV_PCM_FORMAT_S20_3LE: | 373 | case 20: |
374 | af |= 0x8; | 374 | af |= 0x8; |
375 | break; | 375 | break; |
376 | case SNDRV_PCM_FORMAT_S24_LE: | 376 | case 24: |
377 | af |= 0x10; | 377 | af |= 0x10; |
378 | break; | 378 | break; |
379 | case SNDRV_PCM_FORMAT_S32_LE: | 379 | case 32: |
380 | af |= 0x18; | 380 | af |= 0x18; |
381 | break; | 381 | break; |
382 | default: | 382 | default: |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b33542a04607..a237f1627f61 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -241,26 +241,26 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, | |||
241 | } | 241 | } |
242 | 242 | ||
243 | /* bit size */ | 243 | /* bit size */ |
244 | switch (params_format(params)) { | 244 | switch (params_width(params)) { |
245 | case SNDRV_PCM_FORMAT_S16_LE: | 245 | case 16: |
246 | break; | 246 | break; |
247 | case SNDRV_PCM_FORMAT_S20_3LE: | 247 | case 20: |
248 | iface |= 0x0001; | 248 | iface |= 0x0001; |
249 | break; | 249 | break; |
250 | case SNDRV_PCM_FORMAT_S24_LE: | 250 | case 24: |
251 | iface |= 0x0002; | 251 | iface |= 0x0002; |
252 | break; | 252 | break; |
253 | case SNDRV_PCM_FORMAT_S32_LE: | 253 | case 32: |
254 | iface |= 0x0003; | 254 | iface |= 0x0003; |
255 | break; | 255 | break; |
256 | default: | 256 | default: |
257 | dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d", | 257 | dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d", |
258 | params_format(params)); | 258 | params_width(params)); |
259 | return -EINVAL; | 259 | return -EINVAL; |
260 | } | 260 | } |
261 | 261 | ||
262 | dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", | 262 | dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", |
263 | params_format(params)); | 263 | params_width(params)); |
264 | 264 | ||
265 | snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); | 265 | snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); |
266 | return 0; | 266 | return 0; |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 33990b63d214..67653a2db223 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -586,16 +586,16 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, | |||
586 | int coeff = get_coeff(wm8750->sysclk, params_rate(params)); | 586 | int coeff = get_coeff(wm8750->sysclk, params_rate(params)); |
587 | 587 | ||
588 | /* bit size */ | 588 | /* bit size */ |
589 | switch (params_format(params)) { | 589 | switch (params_width(params)) { |
590 | case SNDRV_PCM_FORMAT_S16_LE: | 590 | case 16: |
591 | break; | 591 | break; |
592 | case SNDRV_PCM_FORMAT_S20_3LE: | 592 | case 20: |
593 | iface |= 0x0004; | 593 | iface |= 0x0004; |
594 | break; | 594 | break; |
595 | case SNDRV_PCM_FORMAT_S24_LE: | 595 | case 24: |
596 | iface |= 0x0008; | 596 | iface |= 0x0008; |
597 | break; | 597 | break; |
598 | case SNDRV_PCM_FORMAT_S32_LE: | 598 | case 32: |
599 | iface |= 0x000c; | 599 | iface |= 0x000c; |
600 | break; | 600 | break; |
601 | } | 601 | } |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 53e57b4049a8..e54e097f4fcb 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -937,16 +937,16 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | |||
937 | u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f; | 937 | u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f; |
938 | 938 | ||
939 | /* bit size */ | 939 | /* bit size */ |
940 | switch (params_format(params)) { | 940 | switch (params_width(params)) { |
941 | case SNDRV_PCM_FORMAT_S16_LE: | 941 | case 16: |
942 | break; | 942 | break; |
943 | case SNDRV_PCM_FORMAT_S20_3LE: | 943 | case 20: |
944 | voice |= 0x0004; | 944 | voice |= 0x0004; |
945 | break; | 945 | break; |
946 | case SNDRV_PCM_FORMAT_S24_LE: | 946 | case 24: |
947 | voice |= 0x0008; | 947 | voice |= 0x0008; |
948 | break; | 948 | break; |
949 | case SNDRV_PCM_FORMAT_S32_LE: | 949 | case 32: |
950 | voice |= 0x000c; | 950 | voice |= 0x000c; |
951 | break; | 951 | break; |
952 | } | 952 | } |
@@ -1176,16 +1176,16 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1176 | coeff_div[coeff].usb); | 1176 | coeff_div[coeff].usb); |
1177 | 1177 | ||
1178 | /* bit size */ | 1178 | /* bit size */ |
1179 | switch (params_format(params)) { | 1179 | switch (params_width(params)) { |
1180 | case SNDRV_PCM_FORMAT_S16_LE: | 1180 | case 16: |
1181 | break; | 1181 | break; |
1182 | case SNDRV_PCM_FORMAT_S20_3LE: | 1182 | case 20: |
1183 | hifi |= 0x0004; | 1183 | hifi |= 0x0004; |
1184 | break; | 1184 | break; |
1185 | case SNDRV_PCM_FORMAT_S24_LE: | 1185 | case 24: |
1186 | hifi |= 0x0008; | 1186 | hifi |= 0x0008; |
1187 | break; | 1187 | break; |
1188 | case SNDRV_PCM_FORMAT_S32_LE: | 1188 | case 32: |
1189 | hifi |= 0x000c; | 1189 | hifi |= 0x000c; |
1190 | break; | 1190 | break; |
1191 | } | 1191 | } |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index c61aeb38efb8..180e7a098726 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -426,16 +426,16 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream, | |||
426 | wm8770 = snd_soc_codec_get_drvdata(codec); | 426 | wm8770 = snd_soc_codec_get_drvdata(codec); |
427 | 427 | ||
428 | iface = 0; | 428 | iface = 0; |
429 | switch (params_format(params)) { | 429 | switch (params_width(params)) { |
430 | case SNDRV_PCM_FORMAT_S16_LE: | 430 | case 16: |
431 | break; | 431 | break; |
432 | case SNDRV_PCM_FORMAT_S20_3LE: | 432 | case 20: |
433 | iface |= 0x10; | 433 | iface |= 0x10; |
434 | break; | 434 | break; |
435 | case SNDRV_PCM_FORMAT_S24_LE: | 435 | case 24: |
436 | iface |= 0x20; | 436 | iface |= 0x20; |
437 | break; | 437 | break; |
438 | case SNDRV_PCM_FORMAT_S32_LE: | 438 | case 32: |
439 | iface |= 0x30; | 439 | iface |= 0x30; |
440 | break; | 440 | break; |
441 | } | 441 | } |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index d96e5963ee35..0ea01dfcb6e1 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -270,19 +270,19 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, | |||
270 | 270 | ||
271 | codec = dai->codec; | 271 | codec = dai->codec; |
272 | 272 | ||
273 | switch (params_format(params)) { | 273 | switch (params_width(params)) { |
274 | case SNDRV_PCM_FORMAT_S16_LE: | 274 | case 16: |
275 | blen = 0x0; | 275 | blen = 0x0; |
276 | break; | 276 | break; |
277 | case SNDRV_PCM_FORMAT_S20_3LE: | 277 | case 20: |
278 | blen = 0x1; | 278 | blen = 0x1; |
279 | break; | 279 | break; |
280 | case SNDRV_PCM_FORMAT_S24_LE: | 280 | case 24: |
281 | blen = 0x2; | 281 | blen = 0x2; |
282 | break; | 282 | break; |
283 | default: | 283 | default: |
284 | dev_err(dai->dev, "Unsupported word length: %u\n", | 284 | dev_err(dai->dev, "Unsupported word length: %u\n", |
285 | params_format(params)); | 285 | params_width(params)); |
286 | return -EINVAL; | 286 | return -EINVAL; |
287 | } | 287 | } |
288 | 288 | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index d09fdce57f5a..44a5f1511f0f 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -640,16 +640,16 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, | |||
640 | 640 | ||
641 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; | 641 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; |
642 | 642 | ||
643 | switch (params_format(params)) { | 643 | switch (params_width(params)) { |
644 | case SNDRV_PCM_FORMAT_S16_LE: | 644 | case 16: |
645 | break; | 645 | break; |
646 | case SNDRV_PCM_FORMAT_S20_3LE: | 646 | case 20: |
647 | reg |= 0x20; | 647 | reg |= 0x20; |
648 | break; | 648 | break; |
649 | case SNDRV_PCM_FORMAT_S24_LE: | 649 | case 24: |
650 | reg |= 0x40; | 650 | reg |= 0x40; |
651 | break; | 651 | break; |
652 | case SNDRV_PCM_FORMAT_S32_LE: | 652 | case 32: |
653 | reg |= 0x60; | 653 | reg |= 0x60; |
654 | break; | 654 | break; |
655 | default: | 655 | default: |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index b84940c359a1..aa0984864e76 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -281,8 +281,7 @@ static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, | |||
281 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, | 281 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, |
282 | enum snd_soc_dapm_type event, int subseq) | 282 | enum snd_soc_dapm_type event, int subseq) |
283 | { | 283 | { |
284 | struct snd_soc_codec *codec = container_of(dapm, | 284 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
285 | struct snd_soc_codec, dapm); | ||
286 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 285 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
287 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; | 286 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; |
288 | int i, val; | 287 | int i, val; |
@@ -1477,19 +1476,19 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1477 | 1476 | ||
1478 | aif1 &= ~WM8903_AIF_WL_MASK; | 1477 | aif1 &= ~WM8903_AIF_WL_MASK; |
1479 | bclk = 2 * fs; | 1478 | bclk = 2 * fs; |
1480 | switch (params_format(params)) { | 1479 | switch (params_width(params)) { |
1481 | case SNDRV_PCM_FORMAT_S16_LE: | 1480 | case 16: |
1482 | bclk *= 16; | 1481 | bclk *= 16; |
1483 | break; | 1482 | break; |
1484 | case SNDRV_PCM_FORMAT_S20_3LE: | 1483 | case 20: |
1485 | bclk *= 20; | 1484 | bclk *= 20; |
1486 | aif1 |= 0x4; | 1485 | aif1 |= 0x4; |
1487 | break; | 1486 | break; |
1488 | case SNDRV_PCM_FORMAT_S24_LE: | 1487 | case 24: |
1489 | bclk *= 24; | 1488 | bclk *= 24; |
1490 | aif1 |= 0x8; | 1489 | aif1 |= 0x8; |
1491 | break; | 1490 | break; |
1492 | case SNDRV_PCM_FORMAT_S32_LE: | 1491 | case 32: |
1493 | bclk *= 32; | 1492 | bclk *= 32; |
1494 | aif1 |= 0xc; | 1493 | aif1 |= 0xc; |
1495 | break; | 1494 | break; |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7c549949c54..4d2d2b1380d5 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/clk.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -49,6 +50,7 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { | |||
49 | /* codec private data */ | 50 | /* codec private data */ |
50 | struct wm8904_priv { | 51 | struct wm8904_priv { |
51 | struct regmap *regmap; | 52 | struct regmap *regmap; |
53 | struct clk *mclk; | ||
52 | 54 | ||
53 | enum wm8904_type devtype; | 55 | enum wm8904_type devtype; |
54 | 56 | ||
@@ -1290,16 +1292,16 @@ static int wm8904_hw_params(struct snd_pcm_substream *substream, | |||
1290 | wm8904->bclk = snd_soc_params_to_bclk(params); | 1292 | wm8904->bclk = snd_soc_params_to_bclk(params); |
1291 | } | 1293 | } |
1292 | 1294 | ||
1293 | switch (params_format(params)) { | 1295 | switch (params_width(params)) { |
1294 | case SNDRV_PCM_FORMAT_S16_LE: | 1296 | case 16: |
1295 | break; | 1297 | break; |
1296 | case SNDRV_PCM_FORMAT_S20_3LE: | 1298 | case 20: |
1297 | aif1 |= 0x40; | 1299 | aif1 |= 0x40; |
1298 | break; | 1300 | break; |
1299 | case SNDRV_PCM_FORMAT_S24_LE: | 1301 | case 24: |
1300 | aif1 |= 0x80; | 1302 | aif1 |= 0x80; |
1301 | break; | 1303 | break; |
1302 | case SNDRV_PCM_FORMAT_S32_LE: | 1304 | case 32: |
1303 | aif1 |= 0xc0; | 1305 | aif1 |= 0xc0; |
1304 | break; | 1306 | break; |
1305 | default: | 1307 | default: |
@@ -1828,6 +1830,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1828 | 1830 | ||
1829 | switch (level) { | 1831 | switch (level) { |
1830 | case SND_SOC_BIAS_ON: | 1832 | case SND_SOC_BIAS_ON: |
1833 | clk_prepare_enable(wm8904->mclk); | ||
1831 | break; | 1834 | break; |
1832 | 1835 | ||
1833 | case SND_SOC_BIAS_PREPARE: | 1836 | case SND_SOC_BIAS_PREPARE: |
@@ -1894,6 +1897,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1894 | 1897 | ||
1895 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), | 1898 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), |
1896 | wm8904->supplies); | 1899 | wm8904->supplies); |
1900 | clk_disable_unprepare(wm8904->mclk); | ||
1897 | break; | 1901 | break; |
1898 | } | 1902 | } |
1899 | codec->dapm.bias_level = level; | 1903 | codec->dapm.bias_level = level; |
@@ -2013,12 +2017,8 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) | |||
2013 | /* We need an array of texts for the enum API */ | 2017 | /* We need an array of texts for the enum API */ |
2014 | wm8904->drc_texts = kmalloc(sizeof(char *) | 2018 | wm8904->drc_texts = kmalloc(sizeof(char *) |
2015 | * pdata->num_drc_cfgs, GFP_KERNEL); | 2019 | * pdata->num_drc_cfgs, GFP_KERNEL); |
2016 | if (!wm8904->drc_texts) { | 2020 | if (!wm8904->drc_texts) |
2017 | dev_err(codec->dev, | ||
2018 | "Failed to allocate %d DRC config texts\n", | ||
2019 | pdata->num_drc_cfgs); | ||
2020 | return; | 2021 | return; |
2021 | } | ||
2022 | 2022 | ||
2023 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 2023 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
2024 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; | 2024 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; |
@@ -2110,6 +2110,13 @@ static int wm8904_i2c_probe(struct i2c_client *i2c, | |||
2110 | if (wm8904 == NULL) | 2110 | if (wm8904 == NULL) |
2111 | return -ENOMEM; | 2111 | return -ENOMEM; |
2112 | 2112 | ||
2113 | wm8904->mclk = devm_clk_get(&i2c->dev, "mclk"); | ||
2114 | if (IS_ERR(wm8904->mclk)) { | ||
2115 | ret = PTR_ERR(wm8904->mclk); | ||
2116 | dev_err(&i2c->dev, "Failed to get MCLK\n"); | ||
2117 | return ret; | ||
2118 | } | ||
2119 | |||
2113 | wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap); | 2120 | wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap); |
2114 | if (IS_ERR(wm8904->regmap)) { | 2121 | if (IS_ERR(wm8904->regmap)) { |
2115 | ret = PTR_ERR(wm8904->regmap); | 2122 | ret = PTR_ERR(wm8904->regmap); |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index fc6eec9ad66b..52011043e54c 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -430,19 +430,19 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, | |||
430 | if (ret) | 430 | if (ret) |
431 | goto error_ret; | 431 | goto error_ret; |
432 | 432 | ||
433 | switch (params_format(params)) { | 433 | switch (params_width(params)) { |
434 | case SNDRV_PCM_FORMAT_S8: | 434 | case 8: |
435 | companding = companding | (1 << 5); | 435 | companding = companding | (1 << 5); |
436 | break; | 436 | break; |
437 | case SNDRV_PCM_FORMAT_S16_LE: | 437 | case 16: |
438 | break; | 438 | break; |
439 | case SNDRV_PCM_FORMAT_S20_3LE: | 439 | case 20: |
440 | iface |= (1 << 5); | 440 | iface |= (1 << 5); |
441 | break; | 441 | break; |
442 | case SNDRV_PCM_FORMAT_S24_LE: | 442 | case 24: |
443 | iface |= (2 << 5); | 443 | iface |= (2 << 5); |
444 | break; | 444 | break; |
445 | case SNDRV_PCM_FORMAT_S32_LE: | 445 | case 32: |
446 | iface |= (3 << 5); | 446 | iface |= (3 << 5); |
447 | break; | 447 | break; |
448 | } | 448 | } |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 2a35108f233d..09d91d9dc4ee 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -597,17 +597,17 @@ static int wm8955_hw_params(struct snd_pcm_substream *substream, | |||
597 | int ret; | 597 | int ret; |
598 | int wl; | 598 | int wl; |
599 | 599 | ||
600 | switch (params_format(params)) { | 600 | switch (params_width(params)) { |
601 | case SNDRV_PCM_FORMAT_S16_LE: | 601 | case 16: |
602 | wl = 0; | 602 | wl = 0; |
603 | break; | 603 | break; |
604 | case SNDRV_PCM_FORMAT_S20_3LE: | 604 | case 20: |
605 | wl = 0x4; | 605 | wl = 0x4; |
606 | break; | 606 | break; |
607 | case SNDRV_PCM_FORMAT_S24_LE: | 607 | case 24: |
608 | wl = 0x8; | 608 | wl = 0x8; |
609 | break; | 609 | break; |
610 | case SNDRV_PCM_FORMAT_S32_LE: | 610 | case 32: |
611 | wl = 0xc; | 611 | wl = 0xc; |
612 | break; | 612 | break; |
613 | default: | 613 | default: |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b2ebb104d879..0dada7f0105e 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -934,12 +934,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
934 | /* We need an array of texts for the enum API */ | 934 | /* We need an array of texts for the enum API */ |
935 | wm8994->mbc_texts = kmalloc(sizeof(char *) | 935 | wm8994->mbc_texts = kmalloc(sizeof(char *) |
936 | * pdata->num_mbc_cfgs, GFP_KERNEL); | 936 | * pdata->num_mbc_cfgs, GFP_KERNEL); |
937 | if (!wm8994->mbc_texts) { | 937 | if (!wm8994->mbc_texts) |
938 | dev_err(wm8994->hubs.codec->dev, | ||
939 | "Failed to allocate %d MBC config texts\n", | ||
940 | pdata->num_mbc_cfgs); | ||
941 | return; | 938 | return; |
942 | } | ||
943 | 939 | ||
944 | for (i = 0; i < pdata->num_mbc_cfgs; i++) | 940 | for (i = 0; i < pdata->num_mbc_cfgs; i++) |
945 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; | 941 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; |
@@ -963,12 +959,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
963 | /* We need an array of texts for the enum API */ | 959 | /* We need an array of texts for the enum API */ |
964 | wm8994->vss_texts = kmalloc(sizeof(char *) | 960 | wm8994->vss_texts = kmalloc(sizeof(char *) |
965 | * pdata->num_vss_cfgs, GFP_KERNEL); | 961 | * pdata->num_vss_cfgs, GFP_KERNEL); |
966 | if (!wm8994->vss_texts) { | 962 | if (!wm8994->vss_texts) |
967 | dev_err(wm8994->hubs.codec->dev, | ||
968 | "Failed to allocate %d VSS config texts\n", | ||
969 | pdata->num_vss_cfgs); | ||
970 | return; | 963 | return; |
971 | } | ||
972 | 964 | ||
973 | for (i = 0; i < pdata->num_vss_cfgs; i++) | 965 | for (i = 0; i < pdata->num_vss_cfgs; i++) |
974 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; | 966 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; |
@@ -993,12 +985,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
993 | /* We need an array of texts for the enum API */ | 985 | /* We need an array of texts for the enum API */ |
994 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | 986 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) |
995 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | 987 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); |
996 | if (!wm8994->vss_hpf_texts) { | 988 | if (!wm8994->vss_hpf_texts) |
997 | dev_err(wm8994->hubs.codec->dev, | ||
998 | "Failed to allocate %d VSS HPF config texts\n", | ||
999 | pdata->num_vss_hpf_cfgs); | ||
1000 | return; | 989 | return; |
1001 | } | ||
1002 | 990 | ||
1003 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) | 991 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) |
1004 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; | 992 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; |
@@ -1024,12 +1012,8 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1024 | /* We need an array of texts for the enum API */ | 1012 | /* We need an array of texts for the enum API */ |
1025 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | 1013 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) |
1026 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | 1014 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); |
1027 | if (!wm8994->enh_eq_texts) { | 1015 | if (!wm8994->enh_eq_texts) |
1028 | dev_err(wm8994->hubs.codec->dev, | ||
1029 | "Failed to allocate %d enhanced EQ config texts\n", | ||
1030 | pdata->num_enh_eq_cfgs); | ||
1031 | return; | 1016 | return; |
1032 | } | ||
1033 | 1017 | ||
1034 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) | 1018 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) |
1035 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; | 1019 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index a145d0431b63..4dc4e85116cd 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -472,7 +472,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec) | |||
472 | * list each time to find the desired power state do so now | 472 | * list each time to find the desired power state do so now |
473 | * and save the result. | 473 | * and save the result. |
474 | */ | 474 | */ |
475 | list_for_each_entry(w, &codec->card->widgets, list) { | 475 | list_for_each_entry(w, &codec->component.card->widgets, list) { |
476 | if (w->dapm != &codec->dapm) | 476 | if (w->dapm != &codec->dapm) |
477 | continue; | 477 | continue; |
478 | if (strcmp(w->name, "LOUT1 PGA") == 0) | 478 | if (strcmp(w->name, "LOUT1 PGA") == 0) |
@@ -567,24 +567,21 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
567 | struct snd_soc_codec *codec = dai->codec; | 567 | struct snd_soc_codec *codec = dai->codec; |
568 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 568 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
569 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 569 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
570 | snd_pcm_format_t format = params_format(params); | ||
571 | int i; | 570 | int i; |
572 | 571 | ||
573 | /* bit size */ | 572 | /* bit size */ |
574 | switch (format) { | 573 | switch (params_width(params)) { |
575 | case SNDRV_PCM_FORMAT_S16_LE: | 574 | case 16: |
576 | case SNDRV_PCM_FORMAT_S16_BE: | ||
577 | break; | 575 | break; |
578 | case SNDRV_PCM_FORMAT_S20_3LE: | 576 | case 20: |
579 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
580 | iface |= 0x0004; | 577 | iface |= 0x0004; |
581 | break; | 578 | break; |
582 | case SNDRV_PCM_FORMAT_S24_LE: | 579 | case 24: |
583 | case SNDRV_PCM_FORMAT_S24_BE: | ||
584 | iface |= 0x0008; | 580 | iface |= 0x0008; |
585 | break; | 581 | break; |
586 | default: | 582 | default: |
587 | dev_err(codec->dev, "unsupported format %i\n", format); | 583 | dev_err(codec->dev, "unsupported width %d\n", |
584 | params_width(params)); | ||
588 | return -EINVAL; | 585 | return -EINVAL; |
589 | } | 586 | } |
590 | 587 | ||
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 9c88f04442b3..41d23e920ad5 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -565,16 +565,16 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, | |||
565 | 565 | ||
566 | reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); | 566 | reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); |
567 | reg &= ~WM8961_WL_MASK; | 567 | reg &= ~WM8961_WL_MASK; |
568 | switch (params_format(params)) { | 568 | switch (params_width(params)) { |
569 | case SNDRV_PCM_FORMAT_S16_LE: | 569 | case 16: |
570 | break; | 570 | break; |
571 | case SNDRV_PCM_FORMAT_S20_3LE: | 571 | case 20: |
572 | reg |= 1 << WM8961_WL_SHIFT; | 572 | reg |= 1 << WM8961_WL_SHIFT; |
573 | break; | 573 | break; |
574 | case SNDRV_PCM_FORMAT_S24_LE: | 574 | case 24: |
575 | reg |= 2 << WM8961_WL_SHIFT; | 575 | reg |= 2 << WM8961_WL_SHIFT; |
576 | break; | 576 | break; |
577 | case SNDRV_PCM_FORMAT_S32_LE: | 577 | case 32: |
578 | reg |= 3 << WM8961_WL_SHIFT; | 578 | reg |= 3 << WM8961_WL_SHIFT; |
579 | break; | 579 | break; |
580 | default: | 580 | default: |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index ca2fda9d72be..1098ae32f1f9 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
19 | #include <linux/gcd.h> | 20 | #include <linux/gcd.h> |
@@ -2586,16 +2587,16 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2586 | if (wm8962->lrclk % 8000 == 0) | 2587 | if (wm8962->lrclk % 8000 == 0) |
2587 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; | 2588 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; |
2588 | 2589 | ||
2589 | switch (params_format(params)) { | 2590 | switch (params_width(params)) { |
2590 | case SNDRV_PCM_FORMAT_S16_LE: | 2591 | case 16: |
2591 | break; | 2592 | break; |
2592 | case SNDRV_PCM_FORMAT_S20_3LE: | 2593 | case 20: |
2593 | aif0 |= 0x4; | 2594 | aif0 |= 0x4; |
2594 | break; | 2595 | break; |
2595 | case SNDRV_PCM_FORMAT_S24_LE: | 2596 | case 24: |
2596 | aif0 |= 0x8; | 2597 | aif0 |= 0x8; |
2597 | break; | 2598 | break; |
2598 | case SNDRV_PCM_FORMAT_S32_LE: | 2599 | case 32: |
2599 | aif0 |= 0xc; | 2600 | aif0 |= 0xc; |
2600 | break; | 2601 | break; |
2601 | default: | 2602 | default: |
@@ -3541,6 +3542,8 @@ static int wm8962_set_pdata_from_of(struct i2c_client *i2c, | |||
3541 | pdata->gpio_init[i] = 0x0; | 3542 | pdata->gpio_init[i] = 0x0; |
3542 | } | 3543 | } |
3543 | 3544 | ||
3545 | pdata->mclk = devm_clk_get(&i2c->dev, NULL); | ||
3546 | |||
3544 | return 0; | 3547 | return 0; |
3545 | } | 3548 | } |
3546 | 3549 | ||
@@ -3572,6 +3575,14 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3572 | return ret; | 3575 | return ret; |
3573 | } | 3576 | } |
3574 | 3577 | ||
3578 | /* Mark the mclk pointer to NULL if no mclk assigned */ | ||
3579 | if (IS_ERR(wm8962->pdata.mclk)) { | ||
3580 | /* But do not ignore the request for probe defer */ | ||
3581 | if (PTR_ERR(wm8962->pdata.mclk) == -EPROBE_DEFER) | ||
3582 | return -EPROBE_DEFER; | ||
3583 | wm8962->pdata.mclk = NULL; | ||
3584 | } | ||
3585 | |||
3575 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3586 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
3576 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3587 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
3577 | 3588 | ||
@@ -3780,6 +3791,12 @@ static int wm8962_runtime_resume(struct device *dev) | |||
3780 | struct wm8962_priv *wm8962 = dev_get_drvdata(dev); | 3791 | struct wm8962_priv *wm8962 = dev_get_drvdata(dev); |
3781 | int ret; | 3792 | int ret; |
3782 | 3793 | ||
3794 | ret = clk_prepare_enable(wm8962->pdata.mclk); | ||
3795 | if (ret) { | ||
3796 | dev_err(dev, "Failed to enable MCLK: %d\n", ret); | ||
3797 | return ret; | ||
3798 | } | ||
3799 | |||
3783 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), | 3800 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), |
3784 | wm8962->supplies); | 3801 | wm8962->supplies); |
3785 | if (ret != 0) { | 3802 | if (ret != 0) { |
@@ -3839,6 +3856,8 @@ static int wm8962_runtime_suspend(struct device *dev) | |||
3839 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), | 3856 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), |
3840 | wm8962->supplies); | 3857 | wm8962->supplies); |
3841 | 3858 | ||
3859 | clk_disable_unprepare(wm8962->pdata.mclk); | ||
3860 | |||
3842 | return 0; | 3861 | return 0; |
3843 | } | 3862 | } |
3844 | #endif | 3863 | #endif |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 09b7b4200221..0499cd4cfb71 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -517,16 +517,16 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, | |||
517 | int coeff = get_coeff(wm8971->sysclk, params_rate(params)); | 517 | int coeff = get_coeff(wm8971->sysclk, params_rate(params)); |
518 | 518 | ||
519 | /* bit size */ | 519 | /* bit size */ |
520 | switch (params_format(params)) { | 520 | switch (params_width(params)) { |
521 | case SNDRV_PCM_FORMAT_S16_LE: | 521 | case 16: |
522 | break; | 522 | break; |
523 | case SNDRV_PCM_FORMAT_S20_3LE: | 523 | case 20: |
524 | iface |= 0x0004; | 524 | iface |= 0x0004; |
525 | break; | 525 | break; |
526 | case SNDRV_PCM_FORMAT_S24_LE: | 526 | case 24: |
527 | iface |= 0x0008; | 527 | iface |= 0x0008; |
528 | break; | 528 | break; |
529 | case SNDRV_PCM_FORMAT_S32_LE: | 529 | case 32: |
530 | iface |= 0x000c; | 530 | iface |= 0x000c; |
531 | break; | 531 | break; |
532 | } | 532 | } |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 0627c56fa44e..682e9eda1019 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -445,16 +445,16 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, | |||
445 | u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; | 445 | u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; |
446 | 446 | ||
447 | /* bit size */ | 447 | /* bit size */ |
448 | switch (params_format(params)) { | 448 | switch (params_width(params)) { |
449 | case SNDRV_PCM_FORMAT_S16_LE: | 449 | case 16: |
450 | break; | 450 | break; |
451 | case SNDRV_PCM_FORMAT_S20_3LE: | 451 | case 20: |
452 | iface |= 0x0020; | 452 | iface |= 0x0020; |
453 | break; | 453 | break; |
454 | case SNDRV_PCM_FORMAT_S24_LE: | 454 | case 24: |
455 | iface |= 0x0040; | 455 | iface |= 0x0040; |
456 | break; | 456 | break; |
457 | case SNDRV_PCM_FORMAT_S32_LE: | 457 | case 32: |
458 | iface |= 0x0060; | 458 | iface |= 0x0060; |
459 | break; | 459 | break; |
460 | } | 460 | } |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 28ef46c91f62..ee2ba574952b 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -736,16 +736,16 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, | |||
736 | return -EINVAL; | 736 | return -EINVAL; |
737 | 737 | ||
738 | /* bit size */ | 738 | /* bit size */ |
739 | switch (params_format(params)) { | 739 | switch (params_width(params)) { |
740 | case SNDRV_PCM_FORMAT_S16_LE: | 740 | case 16: |
741 | break; | 741 | break; |
742 | case SNDRV_PCM_FORMAT_S20_3LE: | 742 | case 20: |
743 | iface_ctl |= 0x20; | 743 | iface_ctl |= 0x20; |
744 | break; | 744 | break; |
745 | case SNDRV_PCM_FORMAT_S24_LE: | 745 | case 24: |
746 | iface_ctl |= 0x40; | 746 | iface_ctl |= 0x40; |
747 | break; | 747 | break; |
748 | case SNDRV_PCM_FORMAT_S32_LE: | 748 | case 32: |
749 | iface_ctl |= 0x60; | 749 | iface_ctl |= 0x60; |
750 | break; | 750 | break; |
751 | } | 751 | } |
@@ -817,8 +817,8 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, | |||
817 | wm8978->sysclk == WM8978_MCLK ? | 817 | wm8978->sysclk == WM8978_MCLK ? |
818 | ", consider using PLL" : ""); | 818 | ", consider using PLL" : ""); |
819 | 819 | ||
820 | dev_dbg(codec->dev, "%s: fmt %d, rate %u, MCLK divisor #%d\n", __func__, | 820 | dev_dbg(codec->dev, "%s: width %d, rate %u, MCLK divisor #%d\n", __func__, |
821 | params_format(params), params_rate(params), best); | 821 | params_width(params), params_rate(params), best); |
822 | 822 | ||
823 | /* MCLK divisor mask = 0xe0 */ | 823 | /* MCLK divisor mask = 0xe0 */ |
824 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, best << 5); | 824 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, best << 5); |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 19d5baa38f5c..ac5defda8824 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -719,22 +719,22 @@ static int wm8983_hw_params(struct snd_pcm_substream *substream, | |||
719 | 719 | ||
720 | wm8983->bclk = ret; | 720 | wm8983->bclk = ret; |
721 | 721 | ||
722 | switch (params_format(params)) { | 722 | switch (params_width(params)) { |
723 | case SNDRV_PCM_FORMAT_S16_LE: | 723 | case 16: |
724 | blen = 0x0; | 724 | blen = 0x0; |
725 | break; | 725 | break; |
726 | case SNDRV_PCM_FORMAT_S20_3LE: | 726 | case 20: |
727 | blen = 0x1; | 727 | blen = 0x1; |
728 | break; | 728 | break; |
729 | case SNDRV_PCM_FORMAT_S24_LE: | 729 | case 24: |
730 | blen = 0x2; | 730 | blen = 0x2; |
731 | break; | 731 | break; |
732 | case SNDRV_PCM_FORMAT_S32_LE: | 732 | case 32: |
733 | blen = 0x3; | 733 | blen = 0x3; |
734 | break; | 734 | break; |
735 | default: | 735 | default: |
736 | dev_err(dai->dev, "Unsupported word length %u\n", | 736 | dev_err(dai->dev, "Unsupported word length %u\n", |
737 | params_format(params)); | 737 | params_width(params)); |
738 | return -EINVAL; | 738 | return -EINVAL; |
739 | } | 739 | } |
740 | 740 | ||
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 0f5780c09f3a..ee380190399f 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -698,22 +698,22 @@ static int wm8985_hw_params(struct snd_pcm_substream *substream, | |||
698 | if ((int)wm8985->bclk < 0) | 698 | if ((int)wm8985->bclk < 0) |
699 | return wm8985->bclk; | 699 | return wm8985->bclk; |
700 | 700 | ||
701 | switch (params_format(params)) { | 701 | switch (params_width(params)) { |
702 | case SNDRV_PCM_FORMAT_S16_LE: | 702 | case 16: |
703 | blen = 0x0; | 703 | blen = 0x0; |
704 | break; | 704 | break; |
705 | case SNDRV_PCM_FORMAT_S20_3LE: | 705 | case 20: |
706 | blen = 0x1; | 706 | blen = 0x1; |
707 | break; | 707 | break; |
708 | case SNDRV_PCM_FORMAT_S24_LE: | 708 | case 24: |
709 | blen = 0x2; | 709 | blen = 0x2; |
710 | break; | 710 | break; |
711 | case SNDRV_PCM_FORMAT_S32_LE: | 711 | case 32: |
712 | blen = 0x3; | 712 | blen = 0x3; |
713 | break; | 713 | break; |
714 | default: | 714 | default: |
715 | dev_err(dai->dev, "Unsupported word length %u\n", | 715 | dev_err(dai->dev, "Unsupported word length %u\n", |
716 | params_format(params)); | 716 | params_width(params)); |
717 | return -EINVAL; | 717 | return -EINVAL; |
718 | } | 718 | } |
719 | 719 | ||
@@ -980,9 +980,6 @@ static int wm8985_resume(struct snd_soc_codec *codec) | |||
980 | 980 | ||
981 | static int wm8985_remove(struct snd_soc_codec *codec) | 981 | static int wm8985_remove(struct snd_soc_codec *codec) |
982 | { | 982 | { |
983 | struct wm8985_priv *wm8985; | ||
984 | |||
985 | wm8985 = snd_soc_codec_get_drvdata(codec); | ||
986 | wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); | 983 | wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); |
987 | return 0; | 984 | return 0; |
988 | } | 985 | } |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index d3fea46d58e8..a5130d965146 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -687,16 +687,16 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, | |||
687 | } | 687 | } |
688 | 688 | ||
689 | /* bit size */ | 689 | /* bit size */ |
690 | switch (params_format(params)) { | 690 | switch (params_width(params)) { |
691 | case SNDRV_PCM_FORMAT_S16_LE: | 691 | case 16: |
692 | break; | 692 | break; |
693 | case SNDRV_PCM_FORMAT_S20_3LE: | 693 | case 20: |
694 | iface |= 0x0004; | 694 | iface |= 0x0004; |
695 | break; | 695 | break; |
696 | case SNDRV_PCM_FORMAT_S24_LE: | 696 | case 24: |
697 | iface |= 0x0008; | 697 | iface |= 0x0008; |
698 | break; | 698 | break; |
699 | case SNDRV_PCM_FORMAT_S32_LE: | 699 | case 32: |
700 | iface |= 0x000c; | 700 | iface |= 0x000c; |
701 | break; | 701 | break; |
702 | } | 702 | } |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index b5c1f0f07058..03e43e3f395e 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -1073,16 +1073,16 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, | |||
1073 | 1073 | ||
1074 | audio1 &= ~WM8990_AIF_WL_MASK; | 1074 | audio1 &= ~WM8990_AIF_WL_MASK; |
1075 | /* bit size */ | 1075 | /* bit size */ |
1076 | switch (params_format(params)) { | 1076 | switch (params_width(params)) { |
1077 | case SNDRV_PCM_FORMAT_S16_LE: | 1077 | case 16: |
1078 | break; | 1078 | break; |
1079 | case SNDRV_PCM_FORMAT_S20_3LE: | 1079 | case 20: |
1080 | audio1 |= WM8990_AIF_WL_20BITS; | 1080 | audio1 |= WM8990_AIF_WL_20BITS; |
1081 | break; | 1081 | break; |
1082 | case SNDRV_PCM_FORMAT_S24_LE: | 1082 | case 24: |
1083 | audio1 |= WM8990_AIF_WL_24BITS; | 1083 | audio1 |= WM8990_AIF_WL_24BITS; |
1084 | break; | 1084 | break; |
1085 | case SNDRV_PCM_FORMAT_S32_LE: | 1085 | case 32: |
1086 | audio1 |= WM8990_AIF_WL_32BITS; | 1086 | audio1 |= WM8990_AIF_WL_32BITS; |
1087 | break; | 1087 | break; |
1088 | } | 1088 | } |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index b8fd284fc0c0..d0be89731cdb 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -1081,16 +1081,16 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream, | |||
1081 | 1081 | ||
1082 | audio1 &= ~WM8991_AIF_WL_MASK; | 1082 | audio1 &= ~WM8991_AIF_WL_MASK; |
1083 | /* bit size */ | 1083 | /* bit size */ |
1084 | switch (params_format(params)) { | 1084 | switch (params_width(params)) { |
1085 | case SNDRV_PCM_FORMAT_S16_LE: | 1085 | case 16: |
1086 | break; | 1086 | break; |
1087 | case SNDRV_PCM_FORMAT_S20_3LE: | 1087 | case 20: |
1088 | audio1 |= WM8991_AIF_WL_20BITS; | 1088 | audio1 |= WM8991_AIF_WL_20BITS; |
1089 | break; | 1089 | break; |
1090 | case SNDRV_PCM_FORMAT_S24_LE: | 1090 | case 24: |
1091 | audio1 |= WM8991_AIF_WL_24BITS; | 1091 | audio1 |= WM8991_AIF_WL_24BITS; |
1092 | break; | 1092 | break; |
1093 | case SNDRV_PCM_FORMAT_S32_LE: | 1093 | case 32: |
1094 | audio1 |= WM8991_AIF_WL_32BITS; | 1094 | audio1 |= WM8991_AIF_WL_32BITS; |
1095 | break; | 1095 | break; |
1096 | } | 1096 | } |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index f825dc04ebe1..93b14eda355a 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1214,19 +1214,19 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, | |||
1214 | wm8993->tdm_slots, wm8993->tdm_width); | 1214 | wm8993->tdm_slots, wm8993->tdm_width); |
1215 | wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots; | 1215 | wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots; |
1216 | } else { | 1216 | } else { |
1217 | switch (params_format(params)) { | 1217 | switch (params_width(params)) { |
1218 | case SNDRV_PCM_FORMAT_S16_LE: | 1218 | case 16: |
1219 | wm8993->bclk *= 16; | 1219 | wm8993->bclk *= 16; |
1220 | break; | 1220 | break; |
1221 | case SNDRV_PCM_FORMAT_S20_3LE: | 1221 | case 20: |
1222 | wm8993->bclk *= 20; | 1222 | wm8993->bclk *= 20; |
1223 | aif1 |= 0x8; | 1223 | aif1 |= 0x8; |
1224 | break; | 1224 | break; |
1225 | case SNDRV_PCM_FORMAT_S24_LE: | 1225 | case 24: |
1226 | wm8993->bclk *= 24; | 1226 | wm8993->bclk *= 24; |
1227 | aif1 |= 0x10; | 1227 | aif1 |= 0x10; |
1228 | break; | 1228 | break; |
1229 | case SNDRV_PCM_FORMAT_S32_LE: | 1229 | case 32: |
1230 | wm8993->bclk *= 32; | 1230 | wm8993->bclk *= 32; |
1231 | aif1 |= 0x18; | 1231 | aif1 |= 0x18; |
1232 | break; | 1232 | break; |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 247b39013fba..6cc0566dc29a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -2815,19 +2815,19 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2815 | } | 2815 | } |
2816 | 2816 | ||
2817 | bclk_rate = params_rate(params); | 2817 | bclk_rate = params_rate(params); |
2818 | switch (params_format(params)) { | 2818 | switch (params_width(params)) { |
2819 | case SNDRV_PCM_FORMAT_S16_LE: | 2819 | case 16: |
2820 | bclk_rate *= 16; | 2820 | bclk_rate *= 16; |
2821 | break; | 2821 | break; |
2822 | case SNDRV_PCM_FORMAT_S20_3LE: | 2822 | case 20: |
2823 | bclk_rate *= 20; | 2823 | bclk_rate *= 20; |
2824 | aif1 |= 0x20; | 2824 | aif1 |= 0x20; |
2825 | break; | 2825 | break; |
2826 | case SNDRV_PCM_FORMAT_S24_LE: | 2826 | case 24: |
2827 | bclk_rate *= 24; | 2827 | bclk_rate *= 24; |
2828 | aif1 |= 0x40; | 2828 | aif1 |= 0x40; |
2829 | break; | 2829 | break; |
2830 | case SNDRV_PCM_FORMAT_S32_LE: | 2830 | case 32: |
2831 | bclk_rate *= 32; | 2831 | bclk_rate *= 32; |
2832 | aif1 |= 0x60; | 2832 | aif1 |= 0x60; |
2833 | break; | 2833 | break; |
@@ -2966,16 +2966,16 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, | |||
2966 | return 0; | 2966 | return 0; |
2967 | } | 2967 | } |
2968 | 2968 | ||
2969 | switch (params_format(params)) { | 2969 | switch (params_width(params)) { |
2970 | case SNDRV_PCM_FORMAT_S16_LE: | 2970 | case 16: |
2971 | break; | 2971 | break; |
2972 | case SNDRV_PCM_FORMAT_S20_3LE: | 2972 | case 20: |
2973 | aif1 |= 0x20; | 2973 | aif1 |= 0x20; |
2974 | break; | 2974 | break; |
2975 | case SNDRV_PCM_FORMAT_S24_LE: | 2975 | case 24: |
2976 | aif1 |= 0x40; | 2976 | aif1 |= 0x40; |
2977 | break; | 2977 | break; |
2978 | case SNDRV_PCM_FORMAT_S32_LE: | 2978 | case 32: |
2979 | aif1 |= 0x60; | 2979 | aif1 |= 0x60; |
2980 | break; | 2980 | break; |
2981 | default: | 2981 | default: |
@@ -3296,12 +3296,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3296 | /* We need an array of texts for the enum API */ | 3296 | /* We need an array of texts for the enum API */ |
3297 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, | 3297 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, |
3298 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); | 3298 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); |
3299 | if (!wm8994->drc_texts) { | 3299 | if (!wm8994->drc_texts) |
3300 | dev_err(wm8994->hubs.codec->dev, | ||
3301 | "Failed to allocate %d DRC config texts\n", | ||
3302 | pdata->num_drc_cfgs); | ||
3303 | return; | 3300 | return; |
3304 | } | ||
3305 | 3301 | ||
3306 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 3302 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
3307 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; | 3303 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; |
@@ -3505,6 +3501,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3505 | return IRQ_HANDLED; | 3501 | return IRQ_HANDLED; |
3506 | } | 3502 | } |
3507 | 3503 | ||
3504 | /* Should be called with accdet_lock held */ | ||
3508 | static void wm1811_micd_stop(struct snd_soc_codec *codec) | 3505 | static void wm1811_micd_stop(struct snd_soc_codec *codec) |
3509 | { | 3506 | { |
3510 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3507 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -3512,14 +3509,10 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec) | |||
3512 | if (!wm8994->jackdet) | 3509 | if (!wm8994->jackdet) |
3513 | return; | 3510 | return; |
3514 | 3511 | ||
3515 | mutex_lock(&wm8994->accdet_lock); | ||
3516 | |||
3517 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); | 3512 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); |
3518 | 3513 | ||
3519 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | 3514 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); |
3520 | 3515 | ||
3521 | mutex_unlock(&wm8994->accdet_lock); | ||
3522 | |||
3523 | if (wm8994->wm8994->pdata.jd_ext_cap) | 3516 | if (wm8994->wm8994->pdata.jd_ext_cap) |
3524 | snd_soc_dapm_disable_pin(&codec->dapm, | 3517 | snd_soc_dapm_disable_pin(&codec->dapm, |
3525 | "MICBIAS2"); | 3518 | "MICBIAS2"); |
@@ -3560,10 +3553,10 @@ static void wm8958_open_circuit_work(struct work_struct *work) | |||
3560 | open_circuit_work.work); | 3553 | open_circuit_work.work); |
3561 | struct device *dev = wm8994->wm8994->dev; | 3554 | struct device *dev = wm8994->wm8994->dev; |
3562 | 3555 | ||
3563 | wm1811_micd_stop(wm8994->hubs.codec); | ||
3564 | |||
3565 | mutex_lock(&wm8994->accdet_lock); | 3556 | mutex_lock(&wm8994->accdet_lock); |
3566 | 3557 | ||
3558 | wm1811_micd_stop(wm8994->hubs.codec); | ||
3559 | |||
3567 | dev_dbg(dev, "Reporting open circuit\n"); | 3560 | dev_dbg(dev, "Reporting open circuit\n"); |
3568 | 3561 | ||
3569 | wm8994->jack_mic = false; | 3562 | wm8994->jack_mic = false; |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 863a2c38bcb5..cae4ac5a5730 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -1597,21 +1597,21 @@ static int wm8995_hw_params(struct snd_pcm_substream *substream, | |||
1597 | return bclk_rate; | 1597 | return bclk_rate; |
1598 | 1598 | ||
1599 | aif1 = 0; | 1599 | aif1 = 0; |
1600 | switch (params_format(params)) { | 1600 | switch (params_width(params)) { |
1601 | case SNDRV_PCM_FORMAT_S16_LE: | 1601 | case 16: |
1602 | break; | 1602 | break; |
1603 | case SNDRV_PCM_FORMAT_S20_3LE: | 1603 | case 20: |
1604 | aif1 |= (0x1 << WM8995_AIF1_WL_SHIFT); | 1604 | aif1 |= (0x1 << WM8995_AIF1_WL_SHIFT); |
1605 | break; | 1605 | break; |
1606 | case SNDRV_PCM_FORMAT_S24_LE: | 1606 | case 24: |
1607 | aif1 |= (0x2 << WM8995_AIF1_WL_SHIFT); | 1607 | aif1 |= (0x2 << WM8995_AIF1_WL_SHIFT); |
1608 | break; | 1608 | break; |
1609 | case SNDRV_PCM_FORMAT_S32_LE: | 1609 | case 32: |
1610 | aif1 |= (0x3 << WM8995_AIF1_WL_SHIFT); | 1610 | aif1 |= (0x3 << WM8995_AIF1_WL_SHIFT); |
1611 | break; | 1611 | break; |
1612 | default: | 1612 | default: |
1613 | dev_err(dai->dev, "Unsupported word length %u\n", | 1613 | dev_err(dai->dev, "Unsupported word length %u\n", |
1614 | params_format(params)); | 1614 | params_width(params)); |
1615 | return -EINVAL; | 1615 | return -EINVAL; |
1616 | } | 1616 | } |
1617 | 1617 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 69266332760e..f16ff4f56923 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -620,15 +620,12 @@ static int bg_event(struct snd_soc_dapm_widget *w, | |||
620 | static int cp_event(struct snd_soc_dapm_widget *w, | 620 | static int cp_event(struct snd_soc_dapm_widget *w, |
621 | struct snd_kcontrol *kcontrol, int event) | 621 | struct snd_kcontrol *kcontrol, int event) |
622 | { | 622 | { |
623 | int ret = 0; | ||
624 | |||
625 | switch (event) { | 623 | switch (event) { |
626 | case SND_SOC_DAPM_POST_PMU: | 624 | case SND_SOC_DAPM_POST_PMU: |
627 | msleep(5); | 625 | msleep(5); |
628 | break; | 626 | break; |
629 | default: | 627 | default: |
630 | WARN(1, "Invalid event %d\n", event); | 628 | WARN(1, "Invalid event %d\n", event); |
631 | ret = -EINVAL; | ||
632 | } | 629 | } |
633 | 630 | ||
634 | return 0; | 631 | return 0; |
@@ -690,8 +687,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
690 | static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | 687 | static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, |
691 | enum snd_soc_dapm_type event, int subseq) | 688 | enum snd_soc_dapm_type event, int subseq) |
692 | { | 689 | { |
693 | struct snd_soc_codec *codec = container_of(dapm, | 690 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
694 | struct snd_soc_codec, dapm); | ||
695 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 691 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
696 | u16 val, mask; | 692 | u16 val, mask; |
697 | 693 | ||
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index bb9b47b956aa..ab33fe596519 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -967,6 +967,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = { | |||
967 | }, | 967 | }, |
968 | .ops = &arizona_dai_ops, | 968 | .ops = &arizona_dai_ops, |
969 | .symmetric_rates = 1, | 969 | .symmetric_rates = 1, |
970 | .symmetric_samplebits = 1, | ||
970 | }, | 971 | }, |
971 | { | 972 | { |
972 | .name = "wm8997-aif2", | 973 | .name = "wm8997-aif2", |
@@ -988,6 +989,7 @@ static struct snd_soc_dai_driver wm8997_dai[] = { | |||
988 | }, | 989 | }, |
989 | .ops = &arizona_dai_ops, | 990 | .ops = &arizona_dai_ops, |
990 | .symmetric_rates = 1, | 991 | .symmetric_rates = 1, |
992 | .symmetric_samplebits = 1, | ||
991 | }, | 993 | }, |
992 | { | 994 | { |
993 | .name = "wm8997-slim1", | 995 | .name = "wm8997-slim1", |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 185eb97769e7..0cdc9e2184ab 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1029,19 +1029,19 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, | |||
1029 | /* Otherwise work out a BCLK from the sample size */ | 1029 | /* Otherwise work out a BCLK from the sample size */ |
1030 | wm9081->bclk = 2 * wm9081->fs; | 1030 | wm9081->bclk = 2 * wm9081->fs; |
1031 | 1031 | ||
1032 | switch (params_format(params)) { | 1032 | switch (params_width(params)) { |
1033 | case SNDRV_PCM_FORMAT_S16_LE: | 1033 | case 16: |
1034 | wm9081->bclk *= 16; | 1034 | wm9081->bclk *= 16; |
1035 | break; | 1035 | break; |
1036 | case SNDRV_PCM_FORMAT_S20_3LE: | 1036 | case 20: |
1037 | wm9081->bclk *= 20; | 1037 | wm9081->bclk *= 20; |
1038 | aif2 |= 0x4; | 1038 | aif2 |= 0x4; |
1039 | break; | 1039 | break; |
1040 | case SNDRV_PCM_FORMAT_S24_LE: | 1040 | case 24: |
1041 | wm9081->bclk *= 24; | 1041 | wm9081->bclk *= 24; |
1042 | aif2 |= 0x8; | 1042 | aif2 |= 0x8; |
1043 | break; | 1043 | break; |
1044 | case SNDRV_PCM_FORMAT_S32_LE: | 1044 | case 32: |
1045 | wm9081->bclk *= 32; | 1045 | wm9081->bclk *= 32; |
1046 | aif2 |= 0xc; | 1046 | aif2 |= 0xc; |
1047 | break; | 1047 | break; |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 87934171f063..a13f0725611a 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -613,10 +613,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
613 | int ret; | 613 | int ret; |
614 | 614 | ||
615 | wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL); | 615 | wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL); |
616 | if (wm9090 == NULL) { | 616 | if (!wm9090) |
617 | dev_err(&i2c->dev, "Can not allocate memory\n"); | ||
618 | return -ENOMEM; | 617 | return -ENOMEM; |
619 | } | ||
620 | 618 | ||
621 | wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap); | 619 | wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap); |
622 | if (IS_ERR(wm9090->regmap)) { | 620 | if (IS_ERR(wm9090->regmap)) { |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 2a9c6d11330c..bddee30a4bc7 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -953,16 +953,16 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, | |||
953 | struct snd_soc_codec *codec = dai->codec; | 953 | struct snd_soc_codec *codec = dai->codec; |
954 | u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; | 954 | u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; |
955 | 955 | ||
956 | switch (params_format(params)) { | 956 | switch (params_width(params)) { |
957 | case SNDRV_PCM_FORMAT_S16_LE: | 957 | case 16: |
958 | break; | 958 | break; |
959 | case SNDRV_PCM_FORMAT_S20_3LE: | 959 | case 20: |
960 | reg |= 0x0004; | 960 | reg |= 0x0004; |
961 | break; | 961 | break; |
962 | case SNDRV_PCM_FORMAT_S24_LE: | 962 | case 24: |
963 | reg |= 0x0008; | 963 | reg |= 0x0008; |
964 | break; | 964 | break; |
965 | case SNDRV_PCM_FORMAT_S32_LE: | 965 | case 32: |
966 | reg |= 0x000c; | 966 | reg |= 0x000c; |
967 | break; | 967 | break; |
968 | } | 968 | } |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 060027182dcb..f412a9911a75 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -1382,7 +1382,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1382 | int ret; | 1382 | int ret; |
1383 | int val; | 1383 | int val; |
1384 | 1384 | ||
1385 | dsp->card = codec->card; | 1385 | dsp->card = codec->component.card; |
1386 | 1386 | ||
1387 | switch (event) { | 1387 | switch (event) { |
1388 | case SND_SOC_DAPM_POST_PMU: | 1388 | case SND_SOC_DAPM_POST_PMU: |
@@ -1617,7 +1617,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | |||
1617 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1617 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1618 | struct wm_adsp *dsp = &dsps[w->shift]; | 1618 | struct wm_adsp *dsp = &dsps[w->shift]; |
1619 | 1619 | ||
1620 | dsp->card = codec->card; | 1620 | dsp->card = codec->component.card; |
1621 | 1621 | ||
1622 | switch (event) { | 1622 | switch (event) { |
1623 | case SND_SOC_DAPM_PRE_PMU: | 1623 | case SND_SOC_DAPM_PRE_PMU: |
@@ -1758,3 +1758,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
1758 | return 0; | 1758 | return 0; |
1759 | } | 1759 | } |
1760 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1760 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
1761 | |||
1762 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 916817fe6632..374537d5e179 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -183,10 +183,8 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
183 | return; | 183 | return; |
184 | 184 | ||
185 | cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL); | 185 | cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL); |
186 | if (!cache) { | 186 | if (!cache) |
187 | dev_err(codec->dev, "Failed to allocate DCS cache entry\n"); | ||
188 | return; | 187 | return; |
189 | } | ||
190 | 188 | ||
191 | cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME); | 189 | cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME); |
192 | cache->left &= WM8993_HPOUT1L_VOL_MASK; | 190 | cache->left &= WM8993_HPOUT1L_VOL_MASK; |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 50a098749b9e..d69510c53239 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -1,12 +1,29 @@ | |||
1 | config SND_DAVINCI_SOC | 1 | config SND_DAVINCI_SOC |
2 | tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips" | 2 | tristate "SoC Audio for TI DAVINCI" |
3 | depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX | 3 | depends on ARCH_DAVINCI |
4 | |||
5 | config SND_EDMA_SOC | ||
6 | tristate "SoC Audio for Texas Instruments chips using eDMA (AM33XX/43XX)" | ||
7 | depends on SOC_AM33XX || SOC_AM43XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
9 | help | ||
10 | Say Y or M here if you want audio support for TI SoC which uses eDMA. | ||
11 | The following line of SoCs are supported by this platform driver: | ||
12 | - AM335x | ||
13 | - AM437x/AM438x | ||
4 | 14 | ||
5 | config SND_DAVINCI_SOC_I2S | 15 | config SND_DAVINCI_SOC_I2S |
6 | tristate | 16 | tristate |
7 | 17 | ||
8 | config SND_DAVINCI_SOC_MCASP | 18 | config SND_DAVINCI_SOC_MCASP |
9 | tristate | 19 | tristate "Multichannel Audio Serial Port (McASP) support" |
20 | depends on SND_DAVINCI_SOC || SND_OMAP_SOC || SND_EDMA_SOC | ||
21 | help | ||
22 | Say Y or M here if you want to have support for McASP IP found in | ||
23 | various Texas Instruments SoCs like: | ||
24 | - daVinci devices | ||
25 | - Sitara line of SoCs (AM335x, AM438x, etc) | ||
26 | - DRA7x devices | ||
10 | 27 | ||
11 | config SND_DAVINCI_SOC_VCIF | 28 | config SND_DAVINCI_SOC_VCIF |
12 | tristate | 29 | tristate |
@@ -18,7 +35,7 @@ config SND_DAVINCI_SOC_GENERIC_EVM | |||
18 | 35 | ||
19 | config SND_AM33XX_SOC_EVM | 36 | config SND_AM33XX_SOC_EVM |
20 | tristate "SoC Audio for the AM33XX chip based boards" | 37 | tristate "SoC Audio for the AM33XX chip based boards" |
21 | depends on SND_DAVINCI_SOC && SOC_AM33XX && I2C | 38 | depends on SND_EDMA_SOC && SOC_AM33XX && I2C |
22 | select SND_DAVINCI_SOC_GENERIC_EVM | 39 | select SND_DAVINCI_SOC_GENERIC_EVM |
23 | help | 40 | help |
24 | Say Y or M if you want to add support for SoC audio on AM33XX | 41 | Say Y or M if you want to add support for SoC audio on AM33XX |
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index 744d4d9a0184..09bf2ba92d38 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -1,10 +1,12 @@ | |||
1 | # DAVINCI Platform Support | 1 | # DAVINCI Platform Support |
2 | snd-soc-davinci-objs := davinci-pcm.o | 2 | snd-soc-davinci-objs := davinci-pcm.o |
3 | snd-soc-edma-objs := edma-pcm.o | ||
3 | snd-soc-davinci-i2s-objs := davinci-i2s.o | 4 | snd-soc-davinci-i2s-objs := davinci-i2s.o |
4 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o | 5 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o |
5 | snd-soc-davinci-vcif-objs:= davinci-vcif.o | 6 | snd-soc-davinci-vcif-objs:= davinci-vcif.o |
6 | 7 | ||
7 | obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o | 8 | obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o |
9 | obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o | ||
8 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o | 10 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o |
9 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o | 11 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o |
10 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o | 12 | obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 9afb14629a17..c28508da34cf 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
29 | 29 | ||
30 | #include <sound/asoundef.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -36,6 +37,7 @@ | |||
36 | #include <sound/omap-pcm.h> | 37 | #include <sound/omap-pcm.h> |
37 | 38 | ||
38 | #include "davinci-pcm.h" | 39 | #include "davinci-pcm.h" |
40 | #include "edma-pcm.h" | ||
39 | #include "davinci-mcasp.h" | 41 | #include "davinci-mcasp.h" |
40 | 42 | ||
41 | #define MCASP_MAX_AFIFO_DEPTH 64 | 43 | #define MCASP_MAX_AFIFO_DEPTH 64 |
@@ -63,6 +65,7 @@ struct davinci_mcasp { | |||
63 | u8 num_serializer; | 65 | u8 num_serializer; |
64 | u8 *serial_dir; | 66 | u8 *serial_dir; |
65 | u8 version; | 67 | u8 version; |
68 | u8 bclk_div; | ||
66 | u16 bclk_lrclk_ratio; | 69 | u16 bclk_lrclk_ratio; |
67 | int streams; | 70 | int streams; |
68 | 71 | ||
@@ -417,6 +420,7 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div | |||
417 | ACLKXDIV(div - 1), ACLKXDIV_MASK); | 420 | ACLKXDIV(div - 1), ACLKXDIV_MASK); |
418 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, | 421 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
419 | ACLKRDIV(div - 1), ACLKRDIV_MASK); | 422 | ACLKRDIV(div - 1), ACLKRDIV_MASK); |
423 | mcasp->bclk_div = div; | ||
420 | break; | 424 | break; |
421 | 425 | ||
422 | case 2: /* BCLK/LRCLK ratio */ | 426 | case 2: /* BCLK/LRCLK ratio */ |
@@ -637,8 +641,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) | |||
637 | } | 641 | } |
638 | 642 | ||
639 | /* S/PDIF */ | 643 | /* S/PDIF */ |
640 | static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) | 644 | static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, |
645 | unsigned int rate) | ||
641 | { | 646 | { |
647 | u32 cs_value = 0; | ||
648 | u8 *cs_bytes = (u8*) &cs_value; | ||
649 | |||
642 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 | 650 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 |
643 | and LSB first */ | 651 | and LSB first */ |
644 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); | 652 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); |
@@ -660,6 +668,46 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) | |||
660 | /* Enable the DIT */ | 668 | /* Enable the DIT */ |
661 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); | 669 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); |
662 | 670 | ||
671 | /* Set S/PDIF channel status bits */ | ||
672 | cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT; | ||
673 | cs_bytes[1] = IEC958_AES1_CON_PCM_CODER; | ||
674 | |||
675 | switch (rate) { | ||
676 | case 22050: | ||
677 | cs_bytes[3] |= IEC958_AES3_CON_FS_22050; | ||
678 | break; | ||
679 | case 24000: | ||
680 | cs_bytes[3] |= IEC958_AES3_CON_FS_24000; | ||
681 | break; | ||
682 | case 32000: | ||
683 | cs_bytes[3] |= IEC958_AES3_CON_FS_32000; | ||
684 | break; | ||
685 | case 44100: | ||
686 | cs_bytes[3] |= IEC958_AES3_CON_FS_44100; | ||
687 | break; | ||
688 | case 48000: | ||
689 | cs_bytes[3] |= IEC958_AES3_CON_FS_48000; | ||
690 | break; | ||
691 | case 88200: | ||
692 | cs_bytes[3] |= IEC958_AES3_CON_FS_88200; | ||
693 | break; | ||
694 | case 96000: | ||
695 | cs_bytes[3] |= IEC958_AES3_CON_FS_96000; | ||
696 | break; | ||
697 | case 176400: | ||
698 | cs_bytes[3] |= IEC958_AES3_CON_FS_176400; | ||
699 | break; | ||
700 | case 192000: | ||
701 | cs_bytes[3] |= IEC958_AES3_CON_FS_192000; | ||
702 | break; | ||
703 | default: | ||
704 | printk(KERN_WARNING "unsupported sampling rate: %d\n", rate); | ||
705 | return -EINVAL; | ||
706 | } | ||
707 | |||
708 | mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value); | ||
709 | mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value); | ||
710 | |||
663 | return 0; | 711 | return 0; |
664 | } | 712 | } |
665 | 713 | ||
@@ -675,15 +723,22 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
675 | int period_size = params_period_size(params); | 723 | int period_size = params_period_size(params); |
676 | int ret; | 724 | int ret; |
677 | 725 | ||
678 | /* If mcasp is BCLK master we need to set BCLK divider */ | 726 | /* |
679 | if (mcasp->bclk_master) { | 727 | * If mcasp is BCLK master, and a BCLK divider was not provided by |
728 | * the machine driver, we need to calculate the ratio. | ||
729 | */ | ||
730 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { | ||
680 | unsigned int bclk_freq = snd_soc_params_to_bclk(params); | 731 | unsigned int bclk_freq = snd_soc_params_to_bclk(params); |
732 | unsigned int div = mcasp->sysclk_freq / bclk_freq; | ||
681 | if (mcasp->sysclk_freq % bclk_freq != 0) { | 733 | if (mcasp->sysclk_freq % bclk_freq != 0) { |
682 | dev_err(mcasp->dev, "Can't produce required BCLK\n"); | 734 | if (((mcasp->sysclk_freq / div) - bclk_freq) > |
683 | return -EINVAL; | 735 | (bclk_freq - (mcasp->sysclk_freq / (div+1)))) |
736 | div++; | ||
737 | dev_warn(mcasp->dev, | ||
738 | "Inaccurate BCLK: %u Hz / %u != %u Hz\n", | ||
739 | mcasp->sysclk_freq, div, bclk_freq); | ||
684 | } | 740 | } |
685 | davinci_mcasp_set_clkdiv( | 741 | davinci_mcasp_set_clkdiv(cpu_dai, 1, div); |
686 | cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); | ||
687 | } | 742 | } |
688 | 743 | ||
689 | ret = mcasp_common_hw_param(mcasp, substream->stream, | 744 | ret = mcasp_common_hw_param(mcasp, substream->stream, |
@@ -692,7 +747,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
692 | return ret; | 747 | return ret; |
693 | 748 | ||
694 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) | 749 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
695 | ret = mcasp_dit_hw_param(mcasp); | 750 | ret = mcasp_dit_hw_param(mcasp, params_rate(params)); |
696 | else | 751 | else |
697 | ret = mcasp_i2s_hw_param(mcasp, substream->stream); | 752 | ret = mcasp_i2s_hw_param(mcasp, substream->stream); |
698 | 753 | ||
@@ -720,6 +775,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
720 | 775 | ||
721 | case SNDRV_PCM_FORMAT_U24_LE: | 776 | case SNDRV_PCM_FORMAT_U24_LE: |
722 | case SNDRV_PCM_FORMAT_S24_LE: | 777 | case SNDRV_PCM_FORMAT_S24_LE: |
778 | dma_params->data_type = 4; | ||
779 | word_length = 24; | ||
780 | break; | ||
781 | |||
723 | case SNDRV_PCM_FORMAT_U32_LE: | 782 | case SNDRV_PCM_FORMAT_U32_LE: |
724 | case SNDRV_PCM_FORMAT_S32_LE: | 783 | case SNDRV_PCM_FORMAT_S32_LE: |
725 | dma_params->data_type = 4; | 784 | dma_params->data_type = 4; |
@@ -778,7 +837,7 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) | |||
778 | { | 837 | { |
779 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | 838 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
780 | 839 | ||
781 | if (mcasp->version == MCASP_VERSION_4) { | 840 | if (mcasp->version >= MCASP_VERSION_3) { |
782 | /* Using dmaengine PCM */ | 841 | /* Using dmaengine PCM */ |
783 | dai->playback_dma_data = | 842 | dai->playback_dma_data = |
784 | &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; | 843 | &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; |
@@ -1223,14 +1282,28 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1223 | goto err; | 1282 | goto err; |
1224 | 1283 | ||
1225 | switch (mcasp->version) { | 1284 | switch (mcasp->version) { |
1285 | #if IS_BUILTIN(CONFIG_SND_DAVINCI_SOC) || \ | ||
1286 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1287 | IS_MODULE(CONFIG_SND_DAVINCI_SOC)) | ||
1226 | case MCASP_VERSION_1: | 1288 | case MCASP_VERSION_1: |
1227 | case MCASP_VERSION_2: | 1289 | case MCASP_VERSION_2: |
1228 | case MCASP_VERSION_3: | ||
1229 | ret = davinci_soc_platform_register(&pdev->dev); | 1290 | ret = davinci_soc_platform_register(&pdev->dev); |
1230 | break; | 1291 | break; |
1292 | #endif | ||
1293 | #if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ | ||
1294 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1295 | IS_MODULE(CONFIG_SND_EDMA_SOC)) | ||
1296 | case MCASP_VERSION_3: | ||
1297 | ret = edma_pcm_platform_register(&pdev->dev); | ||
1298 | break; | ||
1299 | #endif | ||
1300 | #if IS_BUILTIN(CONFIG_SND_OMAP_SOC) || \ | ||
1301 | (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ | ||
1302 | IS_MODULE(CONFIG_SND_OMAP_SOC)) | ||
1231 | case MCASP_VERSION_4: | 1303 | case MCASP_VERSION_4: |
1232 | ret = omap_pcm_platform_register(&pdev->dev); | 1304 | ret = omap_pcm_platform_register(&pdev->dev); |
1233 | break; | 1305 | break; |
1306 | #endif | ||
1234 | default: | 1307 | default: |
1235 | dev_err(&pdev->dev, "Invalid McASP version: %d\n", | 1308 | dev_err(&pdev->dev, "Invalid McASP version: %d\n", |
1236 | mcasp->version); | 1309 | mcasp->version); |
diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c index d38afb1c61ae..605e643133db 100644 --- a/sound/soc/davinci/edma-pcm.c +++ b/sound/soc/davinci/edma-pcm.c | |||
@@ -28,8 +28,8 @@ | |||
28 | static const struct snd_pcm_hardware edma_pcm_hardware = { | 28 | static const struct snd_pcm_hardware edma_pcm_hardware = { |
29 | .info = SNDRV_PCM_INFO_MMAP | | 29 | .info = SNDRV_PCM_INFO_MMAP | |
30 | SNDRV_PCM_INFO_MMAP_VALID | | 30 | SNDRV_PCM_INFO_MMAP_VALID | |
31 | SNDRV_PCM_INFO_BATCH | | ||
32 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | | 31 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | |
32 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | | ||
33 | SNDRV_PCM_INFO_INTERLEAVED, | 33 | SNDRV_PCM_INFO_INTERLEAVED, |
34 | .buffer_bytes_max = 128 * 1024, | 34 | .buffer_bytes_max = 128 * 1024, |
35 | .period_bytes_min = 32, | 35 | .period_bytes_min = 32, |
diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h index 894c378c0f74..b0957744851c 100644 --- a/sound/soc/davinci/edma-pcm.h +++ b/sound/soc/davinci/edma-pcm.h | |||
@@ -20,6 +20,13 @@ | |||
20 | #ifndef __EDMA_PCM_H__ | 20 | #ifndef __EDMA_PCM_H__ |
21 | #define __EDMA_PCM_H__ | 21 | #define __EDMA_PCM_H__ |
22 | 22 | ||
23 | #if IS_ENABLED(CONFIG_SND_EDMA_SOC) | ||
23 | int edma_pcm_platform_register(struct device *dev); | 24 | int edma_pcm_platform_register(struct device *dev); |
25 | #else | ||
26 | static inline int edma_pcm_platform_register(struct device *dev) | ||
27 | { | ||
28 | return 0; | ||
29 | } | ||
30 | #endif /* CONFIG_SND_EDMA_SOC */ | ||
24 | 31 | ||
25 | #endif /* __EDMA_PCM_H__ */ | 32 | #endif /* __EDMA_PCM_H__ */ |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 37933629cbed..f54a8fc99291 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -2,9 +2,20 @@ menu "SoC Audio for Freescale CPUs" | |||
2 | 2 | ||
3 | comment "Common SoC Audio options for Freescale CPUs:" | 3 | comment "Common SoC Audio options for Freescale CPUs:" |
4 | 4 | ||
5 | config SND_SOC_FSL_ASRC | ||
6 | tristate "Asynchronous Sample Rate Converter (ASRC) module support" | ||
7 | select REGMAP_MMIO | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
9 | help | ||
10 | Say Y if you want to add Asynchronous Sample Rate Converter (ASRC) | ||
11 | support for the Freescale CPUs. | ||
12 | This option is only useful for out-of-tree drivers since | ||
13 | in-tree drivers select it automatically. | ||
14 | |||
5 | config SND_SOC_FSL_SAI | 15 | config SND_SOC_FSL_SAI |
6 | tristate "Synchronous Audio Interface (SAI) module support" | 16 | tristate "Synchronous Audio Interface (SAI) module support" |
7 | select REGMAP_MMIO | 17 | select REGMAP_MMIO |
18 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | 19 | select SND_SOC_GENERIC_DMAENGINE_PCM |
9 | help | 20 | help |
10 | Say Y if you want to add Synchronous Audio Interface (SAI) | 21 | Say Y if you want to add Synchronous Audio Interface (SAI) |
@@ -15,7 +26,7 @@ config SND_SOC_FSL_SAI | |||
15 | config SND_SOC_FSL_SSI | 26 | config SND_SOC_FSL_SSI |
16 | tristate "Synchronous Serial Interface module support" | 27 | tristate "Synchronous Serial Interface module support" |
17 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | 28 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n |
18 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC | 29 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC) |
19 | select REGMAP_MMIO | 30 | select REGMAP_MMIO |
20 | help | 31 | help |
21 | Say Y if you want to add Synchronous Serial Interface (SSI) | 32 | Say Y if you want to add Synchronous Serial Interface (SSI) |
@@ -27,7 +38,7 @@ config SND_SOC_FSL_SPDIF | |||
27 | tristate "Sony/Philips Digital Interface module support" | 38 | tristate "Sony/Philips Digital Interface module support" |
28 | select REGMAP_MMIO | 39 | select REGMAP_MMIO |
29 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | 40 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n |
30 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && ARCH_MXC | 41 | select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC) |
31 | help | 42 | help |
32 | Say Y if you want to add Sony/Philips Digital Interface (SPDIF) | 43 | Say Y if you want to add Sony/Philips Digital Interface (SPDIF) |
33 | support for the Freescale CPUs. | 44 | support for the Freescale CPUs. |
@@ -37,6 +48,7 @@ config SND_SOC_FSL_SPDIF | |||
37 | config SND_SOC_FSL_ESAI | 48 | config SND_SOC_FSL_ESAI |
38 | tristate "Enhanced Serial Audio Interface (ESAI) module support" | 49 | tristate "Enhanced Serial Audio Interface (ESAI) module support" |
39 | select REGMAP_MMIO | 50 | select REGMAP_MMIO |
51 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | ||
40 | select SND_SOC_FSL_UTILS | 52 | select SND_SOC_FSL_UTILS |
41 | help | 53 | help |
42 | Say Y if you want to add Enhanced Synchronous Audio Interface | 54 | Say Y if you want to add Enhanced Synchronous Audio Interface |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index db254e358c18..9ff59267eac9 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o | |||
11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o | 11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o |
12 | 12 | ||
13 | # Freescale SSI/DMA/SAI/SPDIF Support | 13 | # Freescale SSI/DMA/SAI/SPDIF Support |
14 | snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o | ||
14 | snd-soc-fsl-sai-objs := fsl_sai.o | 15 | snd-soc-fsl-sai-objs := fsl_sai.o |
15 | snd-soc-fsl-ssi-y := fsl_ssi.o | 16 | snd-soc-fsl-ssi-y := fsl_ssi.o |
16 | snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o | 17 | snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o |
@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o | |||
18 | snd-soc-fsl-esai-objs := fsl_esai.o | 19 | snd-soc-fsl-esai-objs := fsl_esai.o |
19 | snd-soc-fsl-utils-objs := fsl_utils.o | 20 | snd-soc-fsl-utils-objs := fsl_utils.o |
20 | snd-soc-fsl-dma-objs := fsl_dma.o | 21 | snd-soc-fsl-dma-objs := fsl_dma.o |
22 | obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o | ||
21 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o | 23 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o |
22 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 24 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
23 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o | 25 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o |
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c new file mode 100644 index 000000000000..822110420b71 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -0,0 +1,995 @@ | |||
1 | /* | ||
2 | * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/dma-mapping.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/platform_data/dma-imx.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <sound/dmaengine_pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | |||
23 | #include "fsl_asrc.h" | ||
24 | |||
25 | #define IDEAL_RATIO_DECIMAL_DEPTH 26 | ||
26 | |||
27 | #define pair_err(fmt, ...) \ | ||
28 | dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) | ||
29 | |||
30 | #define pair_dbg(fmt, ...) \ | ||
31 | dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) | ||
32 | |||
33 | /* Sample rates are aligned with that defined in pcm.h file */ | ||
34 | static const u8 process_option[][8][2] = { | ||
35 | /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */ | ||
36 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */ | ||
37 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */ | ||
38 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */ | ||
39 | {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */ | ||
40 | {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */ | ||
41 | {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */ | ||
42 | {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */ | ||
43 | {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */ | ||
44 | {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */ | ||
45 | {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */ | ||
46 | {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */ | ||
47 | {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */ | ||
48 | {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */ | ||
49 | }; | ||
50 | |||
51 | /* Corresponding to process_option */ | ||
52 | static int supported_input_rate[] = { | ||
53 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, | ||
54 | 96000, 176400, 192000, | ||
55 | }; | ||
56 | |||
57 | static int supported_asrc_rate[] = { | ||
58 | 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * The following tables map the relationship between asrc_inclk/asrc_outclk in | ||
63 | * fsl_asrc.h and the registers of ASRCSR | ||
64 | */ | ||
65 | static unsigned char input_clk_map_imx35[] = { | ||
66 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, | ||
67 | }; | ||
68 | |||
69 | static unsigned char output_clk_map_imx35[] = { | ||
70 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, | ||
71 | }; | ||
72 | |||
73 | /* i.MX53 uses the same map for input and output */ | ||
74 | static unsigned char input_clk_map_imx53[] = { | ||
75 | /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ | ||
76 | 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd, | ||
77 | }; | ||
78 | |||
79 | static unsigned char output_clk_map_imx53[] = { | ||
80 | /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ | ||
81 | 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd, | ||
82 | }; | ||
83 | |||
84 | static unsigned char *clk_map[2]; | ||
85 | |||
86 | /** | ||
87 | * Request ASRC pair | ||
88 | * | ||
89 | * It assigns pair by the order of A->C->B because allocation of pair B, | ||
90 | * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A | ||
91 | * while pair A and pair C are comparatively independent. | ||
92 | */ | ||
93 | static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) | ||
94 | { | ||
95 | enum asrc_pair_index index = ASRC_INVALID_PAIR; | ||
96 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
97 | struct device *dev = &asrc_priv->pdev->dev; | ||
98 | unsigned long lock_flags; | ||
99 | int i, ret = 0; | ||
100 | |||
101 | spin_lock_irqsave(&asrc_priv->lock, lock_flags); | ||
102 | |||
103 | for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) { | ||
104 | if (asrc_priv->pair[i] != NULL) | ||
105 | continue; | ||
106 | |||
107 | index = i; | ||
108 | |||
109 | if (i != ASRC_PAIR_B) | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | if (index == ASRC_INVALID_PAIR) { | ||
114 | dev_err(dev, "all pairs are busy now\n"); | ||
115 | ret = -EBUSY; | ||
116 | } else if (asrc_priv->channel_avail < channels) { | ||
117 | dev_err(dev, "can't afford required channels: %d\n", channels); | ||
118 | ret = -EINVAL; | ||
119 | } else { | ||
120 | asrc_priv->channel_avail -= channels; | ||
121 | asrc_priv->pair[index] = pair; | ||
122 | pair->channels = channels; | ||
123 | pair->index = index; | ||
124 | } | ||
125 | |||
126 | spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Release ASRC pair | ||
133 | * | ||
134 | * It clears the resource from asrc_priv and releases the occupied channels. | ||
135 | */ | ||
136 | static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) | ||
137 | { | ||
138 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
139 | enum asrc_pair_index index = pair->index; | ||
140 | unsigned long lock_flags; | ||
141 | |||
142 | /* Make sure the pair is disabled */ | ||
143 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
144 | ASRCTR_ASRCEi_MASK(index), 0); | ||
145 | |||
146 | spin_lock_irqsave(&asrc_priv->lock, lock_flags); | ||
147 | |||
148 | asrc_priv->channel_avail += pair->channels; | ||
149 | asrc_priv->pair[index] = NULL; | ||
150 | pair->error = 0; | ||
151 | |||
152 | spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Configure input and output thresholds | ||
157 | */ | ||
158 | static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) | ||
159 | { | ||
160 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
161 | enum asrc_pair_index index = pair->index; | ||
162 | |||
163 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), | ||
164 | ASRMCRi_EXTTHRSHi_MASK | | ||
165 | ASRMCRi_INFIFO_THRESHOLD_MASK | | ||
166 | ASRMCRi_OUTFIFO_THRESHOLD_MASK, | ||
167 | ASRMCRi_EXTTHRSHi | | ||
168 | ASRMCRi_INFIFO_THRESHOLD(in) | | ||
169 | ASRMCRi_OUTFIFO_THRESHOLD(out)); | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * Calculate the total divisor between asrck clock rate and sample rate | ||
174 | * | ||
175 | * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider | ||
176 | */ | ||
177 | static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) | ||
178 | { | ||
179 | u32 ps; | ||
180 | |||
181 | /* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */ | ||
182 | for (ps = 0; div > 8; ps++) | ||
183 | div >>= 1; | ||
184 | |||
185 | return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Calculate and set the ratio for Ideal Ratio mode only | ||
190 | * | ||
191 | * The ratio is a 32-bit fixed point value with 26 fractional bits. | ||
192 | */ | ||
193 | static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, | ||
194 | int inrate, int outrate) | ||
195 | { | ||
196 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
197 | enum asrc_pair_index index = pair->index; | ||
198 | unsigned long ratio; | ||
199 | int i; | ||
200 | |||
201 | if (!outrate) { | ||
202 | pair_err("output rate should not be zero\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | /* Calculate the intergal part of the ratio */ | ||
207 | ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH; | ||
208 | |||
209 | /* ... and then the 26 depth decimal part */ | ||
210 | inrate %= outrate; | ||
211 | |||
212 | for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) { | ||
213 | inrate <<= 1; | ||
214 | |||
215 | if (inrate < outrate) | ||
216 | continue; | ||
217 | |||
218 | ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i); | ||
219 | inrate -= outrate; | ||
220 | |||
221 | if (!inrate) | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio); | ||
226 | regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * Configure the assigned ASRC pair | ||
233 | * | ||
234 | * It configures those ASRC registers according to a configuration instance | ||
235 | * of struct asrc_config which includes in/output sample rate, width, channel | ||
236 | * and clock settings. | ||
237 | */ | ||
238 | static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) | ||
239 | { | ||
240 | struct asrc_config *config = pair->config; | ||
241 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
242 | enum asrc_pair_index index = pair->index; | ||
243 | u32 inrate, outrate, indiv, outdiv; | ||
244 | u32 clk_index[2], div[2]; | ||
245 | int in, out, channels; | ||
246 | struct clk *clk; | ||
247 | bool ideal; | ||
248 | |||
249 | if (!config) { | ||
250 | pair_err("invalid pair config\n"); | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | /* Validate channels */ | ||
255 | if (config->channel_num < 1 || config->channel_num > 10) { | ||
256 | pair_err("does not support %d channels\n", config->channel_num); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | /* Validate output width */ | ||
261 | if (config->output_word_width == ASRC_WIDTH_8_BIT) { | ||
262 | pair_err("does not support 8bit width output\n"); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
266 | inrate = config->input_sample_rate; | ||
267 | outrate = config->output_sample_rate; | ||
268 | ideal = config->inclk == INCLK_NONE; | ||
269 | |||
270 | /* Validate input and output sample rates */ | ||
271 | for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) | ||
272 | if (inrate == supported_input_rate[in]) | ||
273 | break; | ||
274 | |||
275 | if (in == ARRAY_SIZE(supported_input_rate)) { | ||
276 | pair_err("unsupported input sample rate: %dHz\n", inrate); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++) | ||
281 | if (outrate == supported_asrc_rate[out]) | ||
282 | break; | ||
283 | |||
284 | if (out == ARRAY_SIZE(supported_asrc_rate)) { | ||
285 | pair_err("unsupported output sample rate: %dHz\n", outrate); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | /* Validate input and output clock sources */ | ||
290 | clk_index[IN] = clk_map[IN][config->inclk]; | ||
291 | clk_index[OUT] = clk_map[OUT][config->outclk]; | ||
292 | |||
293 | /* We only have output clock for ideal ratio mode */ | ||
294 | clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; | ||
295 | |||
296 | div[IN] = clk_get_rate(clk) / inrate; | ||
297 | if (div[IN] == 0) { | ||
298 | pair_err("failed to support input sample rate %dHz by asrck_%x\n", | ||
299 | inrate, clk_index[ideal ? OUT : IN]); | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | clk = asrc_priv->asrck_clk[clk_index[OUT]]; | ||
304 | |||
305 | /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */ | ||
306 | if (ideal) | ||
307 | div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE; | ||
308 | else | ||
309 | div[OUT] = clk_get_rate(clk) / outrate; | ||
310 | |||
311 | if (div[OUT] == 0) { | ||
312 | pair_err("failed to support output sample rate %dHz by asrck_%x\n", | ||
313 | outrate, clk_index[OUT]); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | /* Set the channel number */ | ||
318 | channels = config->channel_num; | ||
319 | |||
320 | if (asrc_priv->channel_bits < 4) | ||
321 | channels /= 2; | ||
322 | |||
323 | /* Update channels for current pair */ | ||
324 | regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR, | ||
325 | ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits), | ||
326 | ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits)); | ||
327 | |||
328 | /* Default setting: Automatic selection for processing mode */ | ||
329 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
330 | ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index)); | ||
331 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
332 | ASRCTR_USRi_MASK(index), 0); | ||
333 | |||
334 | /* Set the input and output clock sources */ | ||
335 | regmap_update_bits(asrc_priv->regmap, REG_ASRCSR, | ||
336 | ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index), | ||
337 | ASRCSR_AICS(index, clk_index[IN]) | | ||
338 | ASRCSR_AOCS(index, clk_index[OUT])); | ||
339 | |||
340 | /* Calculate the input clock divisors */ | ||
341 | indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]); | ||
342 | outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]); | ||
343 | |||
344 | /* Suppose indiv and outdiv includes prescaler, so add its MASK too */ | ||
345 | regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index), | ||
346 | ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) | | ||
347 | ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index), | ||
348 | ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv)); | ||
349 | |||
350 | /* Implement word_width configurations */ | ||
351 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index), | ||
352 | ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK, | ||
353 | ASRMCR1i_OW16(config->output_word_width) | | ||
354 | ASRMCR1i_IWD(config->input_word_width)); | ||
355 | |||
356 | /* Enable BUFFER STALL */ | ||
357 | regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), | ||
358 | ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi); | ||
359 | |||
360 | /* Set default thresholds for input and output FIFO */ | ||
361 | fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD, | ||
362 | ASRC_INPUTFIFO_THRESHOLD); | ||
363 | |||
364 | /* Configure the followings only for Ideal Ratio mode */ | ||
365 | if (!ideal) | ||
366 | return 0; | ||
367 | |||
368 | /* Clear ASTSx bit to use Ideal Ratio mode */ | ||
369 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
370 | ASRCTR_ATSi_MASK(index), 0); | ||
371 | |||
372 | /* Enable Ideal Ratio mode */ | ||
373 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
374 | ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), | ||
375 | ASRCTR_IDR(index) | ASRCTR_USR(index)); | ||
376 | |||
377 | /* Apply configurations for pre- and post-processing */ | ||
378 | regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, | ||
379 | ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), | ||
380 | ASRCFG_PREMOD(index, process_option[in][out][0]) | | ||
381 | ASRCFG_POSTMOD(index, process_option[in][out][1])); | ||
382 | |||
383 | return fsl_asrc_set_ideal_ratio(pair, inrate, outrate); | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * Start the assigned ASRC pair | ||
388 | * | ||
389 | * It enables the assigned pair and makes it stopped at the stall level. | ||
390 | */ | ||
391 | static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) | ||
392 | { | ||
393 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
394 | enum asrc_pair_index index = pair->index; | ||
395 | int reg, retry = 10, i; | ||
396 | |||
397 | /* Enable the current pair */ | ||
398 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
399 | ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index)); | ||
400 | |||
401 | /* Wait for status of initialization */ | ||
402 | do { | ||
403 | udelay(5); | ||
404 | regmap_read(asrc_priv->regmap, REG_ASRCFG, ®); | ||
405 | reg &= ASRCFG_INIRQi_MASK(index); | ||
406 | } while (!reg && --retry); | ||
407 | |||
408 | /* Make the input fifo to ASRC STALL level */ | ||
409 | regmap_read(asrc_priv->regmap, REG_ASRCNCR, ®); | ||
410 | for (i = 0; i < pair->channels * 4; i++) | ||
411 | regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0); | ||
412 | |||
413 | /* Enable overload interrupt */ | ||
414 | regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE); | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * Stop the assigned ASRC pair | ||
419 | */ | ||
420 | static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) | ||
421 | { | ||
422 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
423 | enum asrc_pair_index index = pair->index; | ||
424 | |||
425 | /* Stop the current pair */ | ||
426 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
427 | ASRCTR_ASRCEi_MASK(index), 0); | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * Get DMA channel according to the pair and direction. | ||
432 | */ | ||
433 | struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) | ||
434 | { | ||
435 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
436 | enum asrc_pair_index index = pair->index; | ||
437 | char name[4]; | ||
438 | |||
439 | sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a'); | ||
440 | |||
441 | return dma_request_slave_channel(&asrc_priv->pdev->dev, name); | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel); | ||
444 | |||
445 | static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, | ||
446 | struct snd_pcm_hw_params *params, | ||
447 | struct snd_soc_dai *dai) | ||
448 | { | ||
449 | struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); | ||
450 | int width = snd_pcm_format_width(params_format(params)); | ||
451 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
452 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
453 | unsigned int channels = params_channels(params); | ||
454 | unsigned int rate = params_rate(params); | ||
455 | struct asrc_config config; | ||
456 | int word_width, ret; | ||
457 | |||
458 | ret = fsl_asrc_request_pair(channels, pair); | ||
459 | if (ret) { | ||
460 | dev_err(dai->dev, "fail to request asrc pair\n"); | ||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | pair->config = &config; | ||
465 | |||
466 | if (width == 16) | ||
467 | width = ASRC_WIDTH_16_BIT; | ||
468 | else | ||
469 | width = ASRC_WIDTH_24_BIT; | ||
470 | |||
471 | if (asrc_priv->asrc_width == 16) | ||
472 | word_width = ASRC_WIDTH_16_BIT; | ||
473 | else | ||
474 | word_width = ASRC_WIDTH_24_BIT; | ||
475 | |||
476 | config.pair = pair->index; | ||
477 | config.channel_num = channels; | ||
478 | config.inclk = INCLK_NONE; | ||
479 | config.outclk = OUTCLK_ASRCK1_CLK; | ||
480 | |||
481 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
482 | config.input_word_width = width; | ||
483 | config.output_word_width = word_width; | ||
484 | config.input_sample_rate = rate; | ||
485 | config.output_sample_rate = asrc_priv->asrc_rate; | ||
486 | } else { | ||
487 | config.input_word_width = word_width; | ||
488 | config.output_word_width = width; | ||
489 | config.input_sample_rate = asrc_priv->asrc_rate; | ||
490 | config.output_sample_rate = rate; | ||
491 | } | ||
492 | |||
493 | ret = fsl_asrc_config_pair(pair); | ||
494 | if (ret) { | ||
495 | dev_err(dai->dev, "fail to config asrc pair\n"); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream, | ||
503 | struct snd_soc_dai *dai) | ||
504 | { | ||
505 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
506 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
507 | |||
508 | if (pair) | ||
509 | fsl_asrc_release_pair(pair); | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
515 | struct snd_soc_dai *dai) | ||
516 | { | ||
517 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
518 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
519 | |||
520 | switch (cmd) { | ||
521 | case SNDRV_PCM_TRIGGER_START: | ||
522 | case SNDRV_PCM_TRIGGER_RESUME: | ||
523 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
524 | fsl_asrc_start_pair(pair); | ||
525 | break; | ||
526 | case SNDRV_PCM_TRIGGER_STOP: | ||
527 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
528 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
529 | fsl_asrc_stop_pair(pair); | ||
530 | break; | ||
531 | default: | ||
532 | return -EINVAL; | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static struct snd_soc_dai_ops fsl_asrc_dai_ops = { | ||
539 | .hw_params = fsl_asrc_dai_hw_params, | ||
540 | .hw_free = fsl_asrc_dai_hw_free, | ||
541 | .trigger = fsl_asrc_dai_trigger, | ||
542 | }; | ||
543 | |||
544 | static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) | ||
545 | { | ||
546 | struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); | ||
547 | |||
548 | snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx, | ||
549 | &asrc_priv->dma_params_rx); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | #define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000 | ||
555 | #define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ | ||
556 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
557 | SNDRV_PCM_FMTBIT_S20_3LE) | ||
558 | |||
559 | static struct snd_soc_dai_driver fsl_asrc_dai = { | ||
560 | .probe = fsl_asrc_dai_probe, | ||
561 | .playback = { | ||
562 | .stream_name = "ASRC-Playback", | ||
563 | .channels_min = 1, | ||
564 | .channels_max = 10, | ||
565 | .rates = FSL_ASRC_RATES, | ||
566 | .formats = FSL_ASRC_FORMATS, | ||
567 | }, | ||
568 | .capture = { | ||
569 | .stream_name = "ASRC-Capture", | ||
570 | .channels_min = 1, | ||
571 | .channels_max = 10, | ||
572 | .rates = FSL_ASRC_RATES, | ||
573 | .formats = FSL_ASRC_FORMATS, | ||
574 | }, | ||
575 | .ops = &fsl_asrc_dai_ops, | ||
576 | }; | ||
577 | |||
578 | static const struct snd_soc_component_driver fsl_asrc_component = { | ||
579 | .name = "fsl-asrc-dai", | ||
580 | }; | ||
581 | |||
582 | static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg) | ||
583 | { | ||
584 | switch (reg) { | ||
585 | case REG_ASRCTR: | ||
586 | case REG_ASRIER: | ||
587 | case REG_ASRCNCR: | ||
588 | case REG_ASRCFG: | ||
589 | case REG_ASRCSR: | ||
590 | case REG_ASRCDR1: | ||
591 | case REG_ASRCDR2: | ||
592 | case REG_ASRSTR: | ||
593 | case REG_ASRPM1: | ||
594 | case REG_ASRPM2: | ||
595 | case REG_ASRPM3: | ||
596 | case REG_ASRPM4: | ||
597 | case REG_ASRPM5: | ||
598 | case REG_ASRTFR1: | ||
599 | case REG_ASRCCR: | ||
600 | case REG_ASRDOA: | ||
601 | case REG_ASRDOB: | ||
602 | case REG_ASRDOC: | ||
603 | case REG_ASRIDRHA: | ||
604 | case REG_ASRIDRLA: | ||
605 | case REG_ASRIDRHB: | ||
606 | case REG_ASRIDRLB: | ||
607 | case REG_ASRIDRHC: | ||
608 | case REG_ASRIDRLC: | ||
609 | case REG_ASR76K: | ||
610 | case REG_ASR56K: | ||
611 | case REG_ASRMCRA: | ||
612 | case REG_ASRFSTA: | ||
613 | case REG_ASRMCRB: | ||
614 | case REG_ASRFSTB: | ||
615 | case REG_ASRMCRC: | ||
616 | case REG_ASRFSTC: | ||
617 | case REG_ASRMCR1A: | ||
618 | case REG_ASRMCR1B: | ||
619 | case REG_ASRMCR1C: | ||
620 | return true; | ||
621 | default: | ||
622 | return false; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg) | ||
627 | { | ||
628 | switch (reg) { | ||
629 | case REG_ASRSTR: | ||
630 | case REG_ASRDIA: | ||
631 | case REG_ASRDIB: | ||
632 | case REG_ASRDIC: | ||
633 | case REG_ASRDOA: | ||
634 | case REG_ASRDOB: | ||
635 | case REG_ASRDOC: | ||
636 | case REG_ASRFSTA: | ||
637 | case REG_ASRFSTB: | ||
638 | case REG_ASRFSTC: | ||
639 | case REG_ASRCFG: | ||
640 | return true; | ||
641 | default: | ||
642 | return false; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg) | ||
647 | { | ||
648 | switch (reg) { | ||
649 | case REG_ASRCTR: | ||
650 | case REG_ASRIER: | ||
651 | case REG_ASRCNCR: | ||
652 | case REG_ASRCFG: | ||
653 | case REG_ASRCSR: | ||
654 | case REG_ASRCDR1: | ||
655 | case REG_ASRCDR2: | ||
656 | case REG_ASRSTR: | ||
657 | case REG_ASRPM1: | ||
658 | case REG_ASRPM2: | ||
659 | case REG_ASRPM3: | ||
660 | case REG_ASRPM4: | ||
661 | case REG_ASRPM5: | ||
662 | case REG_ASRTFR1: | ||
663 | case REG_ASRCCR: | ||
664 | case REG_ASRDIA: | ||
665 | case REG_ASRDIB: | ||
666 | case REG_ASRDIC: | ||
667 | case REG_ASRIDRHA: | ||
668 | case REG_ASRIDRLA: | ||
669 | case REG_ASRIDRHB: | ||
670 | case REG_ASRIDRLB: | ||
671 | case REG_ASRIDRHC: | ||
672 | case REG_ASRIDRLC: | ||
673 | case REG_ASR76K: | ||
674 | case REG_ASR56K: | ||
675 | case REG_ASRMCRA: | ||
676 | case REG_ASRMCRB: | ||
677 | case REG_ASRMCRC: | ||
678 | case REG_ASRMCR1A: | ||
679 | case REG_ASRMCR1B: | ||
680 | case REG_ASRMCR1C: | ||
681 | return true; | ||
682 | default: | ||
683 | return false; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static struct regmap_config fsl_asrc_regmap_config = { | ||
688 | .reg_bits = 32, | ||
689 | .reg_stride = 4, | ||
690 | .val_bits = 32, | ||
691 | |||
692 | .max_register = REG_ASRMCR1C, | ||
693 | .readable_reg = fsl_asrc_readable_reg, | ||
694 | .volatile_reg = fsl_asrc_volatile_reg, | ||
695 | .writeable_reg = fsl_asrc_writeable_reg, | ||
696 | .cache_type = REGCACHE_RBTREE, | ||
697 | }; | ||
698 | |||
699 | /** | ||
700 | * Initialize ASRC registers with a default configurations | ||
701 | */ | ||
702 | static int fsl_asrc_init(struct fsl_asrc *asrc_priv) | ||
703 | { | ||
704 | /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */ | ||
705 | regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN); | ||
706 | |||
707 | /* Disable interrupt by default */ | ||
708 | regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0); | ||
709 | |||
710 | /* Apply recommended settings for parameters from Reference Manual */ | ||
711 | regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff); | ||
712 | regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555); | ||
713 | regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280); | ||
714 | regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280); | ||
715 | regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280); | ||
716 | |||
717 | /* Base address for task queue FIFO. Set to 0x7C */ | ||
718 | regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1, | ||
719 | ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc)); | ||
720 | |||
721 | /* Set the processing clock for 76KHz to 133M */ | ||
722 | regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6); | ||
723 | |||
724 | /* Set the processing clock for 56KHz to 133M */ | ||
725 | return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * Interrupt handler for ASRC | ||
730 | */ | ||
731 | static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) | ||
732 | { | ||
733 | struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id; | ||
734 | struct device *dev = &asrc_priv->pdev->dev; | ||
735 | enum asrc_pair_index index; | ||
736 | u32 status; | ||
737 | |||
738 | regmap_read(asrc_priv->regmap, REG_ASRSTR, &status); | ||
739 | |||
740 | /* Clean overload error */ | ||
741 | regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE); | ||
742 | |||
743 | /* | ||
744 | * We here use dev_dbg() for all exceptions because ASRC itself does | ||
745 | * not care if FIFO overflowed or underrun while a warning in the | ||
746 | * interrupt would result a ridged conversion. | ||
747 | */ | ||
748 | for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) { | ||
749 | if (!asrc_priv->pair[index]) | ||
750 | continue; | ||
751 | |||
752 | if (status & ASRSTR_ATQOL) { | ||
753 | asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD; | ||
754 | dev_dbg(dev, "ASRC Task Queue FIFO overload\n"); | ||
755 | } | ||
756 | |||
757 | if (status & ASRSTR_AOOL(index)) { | ||
758 | asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD; | ||
759 | pair_dbg("Output Task Overload\n"); | ||
760 | } | ||
761 | |||
762 | if (status & ASRSTR_AIOL(index)) { | ||
763 | asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD; | ||
764 | pair_dbg("Input Task Overload\n"); | ||
765 | } | ||
766 | |||
767 | if (status & ASRSTR_AODO(index)) { | ||
768 | asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW; | ||
769 | pair_dbg("Output Data Buffer has overflowed\n"); | ||
770 | } | ||
771 | |||
772 | if (status & ASRSTR_AIDU(index)) { | ||
773 | asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN; | ||
774 | pair_dbg("Input Data Buffer has underflowed\n"); | ||
775 | } | ||
776 | } | ||
777 | |||
778 | return IRQ_HANDLED; | ||
779 | } | ||
780 | |||
781 | static int fsl_asrc_probe(struct platform_device *pdev) | ||
782 | { | ||
783 | struct device_node *np = pdev->dev.of_node; | ||
784 | struct fsl_asrc *asrc_priv; | ||
785 | struct resource *res; | ||
786 | void __iomem *regs; | ||
787 | int irq, ret, i; | ||
788 | char tmp[16]; | ||
789 | |||
790 | asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL); | ||
791 | if (!asrc_priv) | ||
792 | return -ENOMEM; | ||
793 | |||
794 | asrc_priv->pdev = pdev; | ||
795 | strcpy(asrc_priv->name, np->name); | ||
796 | |||
797 | /* Get the addresses and IRQ */ | ||
798 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
799 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
800 | if (IS_ERR(regs)) | ||
801 | return PTR_ERR(regs); | ||
802 | |||
803 | asrc_priv->paddr = res->start; | ||
804 | |||
805 | /* Register regmap and let it prepare core clock */ | ||
806 | if (of_property_read_bool(np, "big-endian")) | ||
807 | fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
808 | |||
809 | asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, | ||
810 | &fsl_asrc_regmap_config); | ||
811 | if (IS_ERR(asrc_priv->regmap)) { | ||
812 | dev_err(&pdev->dev, "failed to init regmap\n"); | ||
813 | return PTR_ERR(asrc_priv->regmap); | ||
814 | } | ||
815 | |||
816 | irq = platform_get_irq(pdev, 0); | ||
817 | if (irq < 0) { | ||
818 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
819 | return irq; | ||
820 | } | ||
821 | |||
822 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, | ||
823 | asrc_priv->name, asrc_priv); | ||
824 | if (ret) { | ||
825 | dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem"); | ||
830 | if (IS_ERR(asrc_priv->mem_clk)) { | ||
831 | dev_err(&pdev->dev, "failed to get mem clock\n"); | ||
832 | return PTR_ERR(asrc_priv->mem_clk); | ||
833 | } | ||
834 | |||
835 | asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); | ||
836 | if (IS_ERR(asrc_priv->ipg_clk)) { | ||
837 | dev_err(&pdev->dev, "failed to get ipg clock\n"); | ||
838 | return PTR_ERR(asrc_priv->ipg_clk); | ||
839 | } | ||
840 | |||
841 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { | ||
842 | sprintf(tmp, "asrck_%x", i); | ||
843 | asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); | ||
844 | if (IS_ERR(asrc_priv->asrck_clk[i])) { | ||
845 | dev_err(&pdev->dev, "failed to get %s clock\n", tmp); | ||
846 | return PTR_ERR(asrc_priv->asrck_clk[i]); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) { | ||
851 | asrc_priv->channel_bits = 3; | ||
852 | clk_map[IN] = input_clk_map_imx35; | ||
853 | clk_map[OUT] = output_clk_map_imx35; | ||
854 | } else { | ||
855 | asrc_priv->channel_bits = 4; | ||
856 | clk_map[IN] = input_clk_map_imx53; | ||
857 | clk_map[OUT] = output_clk_map_imx53; | ||
858 | } | ||
859 | |||
860 | ret = fsl_asrc_init(asrc_priv); | ||
861 | if (ret) { | ||
862 | dev_err(&pdev->dev, "failed to init asrc %d\n", ret); | ||
863 | return -EINVAL; | ||
864 | } | ||
865 | |||
866 | asrc_priv->channel_avail = 10; | ||
867 | |||
868 | ret = of_property_read_u32(np, "fsl,asrc-rate", | ||
869 | &asrc_priv->asrc_rate); | ||
870 | if (ret) { | ||
871 | dev_err(&pdev->dev, "failed to get output rate\n"); | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | |||
875 | ret = of_property_read_u32(np, "fsl,asrc-width", | ||
876 | &asrc_priv->asrc_width); | ||
877 | if (ret) { | ||
878 | dev_err(&pdev->dev, "failed to get output width\n"); | ||
879 | return -EINVAL; | ||
880 | } | ||
881 | |||
882 | if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) { | ||
883 | dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n"); | ||
884 | asrc_priv->asrc_width = 24; | ||
885 | } | ||
886 | |||
887 | platform_set_drvdata(pdev, asrc_priv); | ||
888 | pm_runtime_enable(&pdev->dev); | ||
889 | spin_lock_init(&asrc_priv->lock); | ||
890 | |||
891 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, | ||
892 | &fsl_asrc_dai, 1); | ||
893 | if (ret) { | ||
894 | dev_err(&pdev->dev, "failed to register ASoC DAI\n"); | ||
895 | return ret; | ||
896 | } | ||
897 | |||
898 | ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform); | ||
899 | if (ret) { | ||
900 | dev_err(&pdev->dev, "failed to register ASoC platform\n"); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | dev_info(&pdev->dev, "driver registered\n"); | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | #ifdef CONFIG_PM_RUNTIME | ||
910 | static int fsl_asrc_runtime_resume(struct device *dev) | ||
911 | { | ||
912 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
913 | int i; | ||
914 | |||
915 | clk_prepare_enable(asrc_priv->mem_clk); | ||
916 | clk_prepare_enable(asrc_priv->ipg_clk); | ||
917 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) | ||
918 | clk_prepare_enable(asrc_priv->asrck_clk[i]); | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int fsl_asrc_runtime_suspend(struct device *dev) | ||
924 | { | ||
925 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
926 | int i; | ||
927 | |||
928 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) | ||
929 | clk_disable_unprepare(asrc_priv->asrck_clk[i]); | ||
930 | clk_disable_unprepare(asrc_priv->ipg_clk); | ||
931 | clk_disable_unprepare(asrc_priv->mem_clk); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | #endif /* CONFIG_PM_RUNTIME */ | ||
936 | |||
937 | #ifdef CONFIG_PM_SLEEP | ||
938 | static int fsl_asrc_suspend(struct device *dev) | ||
939 | { | ||
940 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
941 | |||
942 | regcache_cache_only(asrc_priv->regmap, true); | ||
943 | regcache_mark_dirty(asrc_priv->regmap); | ||
944 | |||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | static int fsl_asrc_resume(struct device *dev) | ||
949 | { | ||
950 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
951 | u32 asrctr; | ||
952 | |||
953 | /* Stop all pairs provisionally */ | ||
954 | regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr); | ||
955 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
956 | ASRCTR_ASRCEi_ALL_MASK, 0); | ||
957 | |||
958 | /* Restore all registers */ | ||
959 | regcache_cache_only(asrc_priv->regmap, false); | ||
960 | regcache_sync(asrc_priv->regmap); | ||
961 | |||
962 | /* Restart enabled pairs */ | ||
963 | regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, | ||
964 | ASRCTR_ASRCEi_ALL_MASK, asrctr); | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | #endif /* CONFIG_PM_SLEEP */ | ||
969 | |||
970 | static const struct dev_pm_ops fsl_asrc_pm = { | ||
971 | SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) | ||
972 | SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume) | ||
973 | }; | ||
974 | |||
975 | static const struct of_device_id fsl_asrc_ids[] = { | ||
976 | { .compatible = "fsl,imx35-asrc", }, | ||
977 | { .compatible = "fsl,imx53-asrc", }, | ||
978 | {} | ||
979 | }; | ||
980 | MODULE_DEVICE_TABLE(of, fsl_asrc_ids); | ||
981 | |||
982 | static struct platform_driver fsl_asrc_driver = { | ||
983 | .probe = fsl_asrc_probe, | ||
984 | .driver = { | ||
985 | .name = "fsl-asrc", | ||
986 | .of_match_table = fsl_asrc_ids, | ||
987 | .pm = &fsl_asrc_pm, | ||
988 | }, | ||
989 | }; | ||
990 | module_platform_driver(fsl_asrc_driver); | ||
991 | |||
992 | MODULE_DESCRIPTION("Freescale ASRC ASoC driver"); | ||
993 | MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>"); | ||
994 | MODULE_ALIAS("platform:fsl-asrc"); | ||
995 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h new file mode 100644 index 000000000000..a3f211f53c23 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc.h | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * fsl_asrc.h - Freescale ASRC ALSA SoC header file | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #ifndef _FSL_ASRC_H | ||
14 | #define _FSL_ASRC_H | ||
15 | |||
16 | #define IN 0 | ||
17 | #define OUT 1 | ||
18 | |||
19 | #define ASRC_DMA_BUFFER_NUM 2 | ||
20 | #define ASRC_INPUTFIFO_THRESHOLD 32 | ||
21 | #define ASRC_OUTPUTFIFO_THRESHOLD 32 | ||
22 | #define ASRC_FIFO_THRESHOLD_MIN 0 | ||
23 | #define ASRC_FIFO_THRESHOLD_MAX 63 | ||
24 | #define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4) | ||
25 | #define ASRC_MAX_BUFFER_SIZE (1024 * 48) | ||
26 | #define ASRC_OUTPUT_LAST_SAMPLE 8 | ||
27 | |||
28 | #define IDEAL_RATIO_RATE 1000000 | ||
29 | |||
30 | #define REG_ASRCTR 0x00 | ||
31 | #define REG_ASRIER 0x04 | ||
32 | #define REG_ASRCNCR 0x0C | ||
33 | #define REG_ASRCFG 0x10 | ||
34 | #define REG_ASRCSR 0x14 | ||
35 | |||
36 | #define REG_ASRCDR1 0x18 | ||
37 | #define REG_ASRCDR2 0x1C | ||
38 | #define REG_ASRCDR(i) ((i < 2) ? REG_ASRCDR1 : REG_ASRCDR2) | ||
39 | |||
40 | #define REG_ASRSTR 0x20 | ||
41 | #define REG_ASRRA 0x24 | ||
42 | #define REG_ASRRB 0x28 | ||
43 | #define REG_ASRRC 0x2C | ||
44 | #define REG_ASRPM1 0x40 | ||
45 | #define REG_ASRPM2 0x44 | ||
46 | #define REG_ASRPM3 0x48 | ||
47 | #define REG_ASRPM4 0x4C | ||
48 | #define REG_ASRPM5 0x50 | ||
49 | #define REG_ASRTFR1 0x54 | ||
50 | #define REG_ASRCCR 0x5C | ||
51 | |||
52 | #define REG_ASRDIA 0x60 | ||
53 | #define REG_ASRDOA 0x64 | ||
54 | #define REG_ASRDIB 0x68 | ||
55 | #define REG_ASRDOB 0x6C | ||
56 | #define REG_ASRDIC 0x70 | ||
57 | #define REG_ASRDOC 0x74 | ||
58 | #define REG_ASRDI(i) (REG_ASRDIA + (i << 3)) | ||
59 | #define REG_ASRDO(i) (REG_ASRDOA + (i << 3)) | ||
60 | #define REG_ASRDx(x, i) (x == IN ? REG_ASRDI(i) : REG_ASRDO(i)) | ||
61 | |||
62 | #define REG_ASRIDRHA 0x80 | ||
63 | #define REG_ASRIDRLA 0x84 | ||
64 | #define REG_ASRIDRHB 0x88 | ||
65 | #define REG_ASRIDRLB 0x8C | ||
66 | #define REG_ASRIDRHC 0x90 | ||
67 | #define REG_ASRIDRLC 0x94 | ||
68 | #define REG_ASRIDRH(i) (REG_ASRIDRHA + (i << 3)) | ||
69 | #define REG_ASRIDRL(i) (REG_ASRIDRLA + (i << 3)) | ||
70 | |||
71 | #define REG_ASR76K 0x98 | ||
72 | #define REG_ASR56K 0x9C | ||
73 | |||
74 | #define REG_ASRMCRA 0xA0 | ||
75 | #define REG_ASRFSTA 0xA4 | ||
76 | #define REG_ASRMCRB 0xA8 | ||
77 | #define REG_ASRFSTB 0xAC | ||
78 | #define REG_ASRMCRC 0xB0 | ||
79 | #define REG_ASRFSTC 0xB4 | ||
80 | #define REG_ASRMCR(i) (REG_ASRMCRA + (i << 3)) | ||
81 | #define REG_ASRFST(i) (REG_ASRFSTA + (i << 3)) | ||
82 | |||
83 | #define REG_ASRMCR1A 0xC0 | ||
84 | #define REG_ASRMCR1B 0xC4 | ||
85 | #define REG_ASRMCR1C 0xC8 | ||
86 | #define REG_ASRMCR1(i) (REG_ASRMCR1A + (i << 2)) | ||
87 | |||
88 | |||
89 | /* REG0 0x00 REG_ASRCTR */ | ||
90 | #define ASRCTR_ATSi_SHIFT(i) (20 + i) | ||
91 | #define ASRCTR_ATSi_MASK(i) (1 << ASRCTR_ATSi_SHIFT(i)) | ||
92 | #define ASRCTR_ATS(i) (1 << ASRCTR_ATSi_SHIFT(i)) | ||
93 | #define ASRCTR_USRi_SHIFT(i) (14 + (i << 1)) | ||
94 | #define ASRCTR_USRi_MASK(i) (1 << ASRCTR_USRi_SHIFT(i)) | ||
95 | #define ASRCTR_USR(i) (1 << ASRCTR_USRi_SHIFT(i)) | ||
96 | #define ASRCTR_IDRi_SHIFT(i) (13 + (i << 1)) | ||
97 | #define ASRCTR_IDRi_MASK(i) (1 << ASRCTR_IDRi_SHIFT(i)) | ||
98 | #define ASRCTR_IDR(i) (1 << ASRCTR_IDRi_SHIFT(i)) | ||
99 | #define ASRCTR_SRST_SHIFT 4 | ||
100 | #define ASRCTR_SRST_MASK (1 << ASRCTR_SRST_SHIFT) | ||
101 | #define ASRCTR_SRST (1 << ASRCTR_SRST_SHIFT) | ||
102 | #define ASRCTR_ASRCEi_SHIFT(i) (1 + i) | ||
103 | #define ASRCTR_ASRCEi_MASK(i) (1 << ASRCTR_ASRCEi_SHIFT(i)) | ||
104 | #define ASRCTR_ASRCE(i) (1 << ASRCTR_ASRCEi_SHIFT(i)) | ||
105 | #define ASRCTR_ASRCEi_ALL_MASK (0x7 << ASRCTR_ASRCEi_SHIFT(0)) | ||
106 | #define ASRCTR_ASRCEN_SHIFT 0 | ||
107 | #define ASRCTR_ASRCEN_MASK (1 << ASRCTR_ASRCEN_SHIFT) | ||
108 | #define ASRCTR_ASRCEN (1 << ASRCTR_ASRCEN_SHIFT) | ||
109 | |||
110 | /* REG1 0x04 REG_ASRIER */ | ||
111 | #define ASRIER_AFPWE_SHIFT 7 | ||
112 | #define ASRIER_AFPWE_MASK (1 << ASRIER_AFPWE_SHIFT) | ||
113 | #define ASRIER_AFPWE (1 << ASRIER_AFPWE_SHIFT) | ||
114 | #define ASRIER_AOLIE_SHIFT 6 | ||
115 | #define ASRIER_AOLIE_MASK (1 << ASRIER_AOLIE_SHIFT) | ||
116 | #define ASRIER_AOLIE (1 << ASRIER_AOLIE_SHIFT) | ||
117 | #define ASRIER_ADOEi_SHIFT(i) (3 + i) | ||
118 | #define ASRIER_ADOEi_MASK(i) (1 << ASRIER_ADOEi_SHIFT(i)) | ||
119 | #define ASRIER_ADOE(i) (1 << ASRIER_ADOEi_SHIFT(i)) | ||
120 | #define ASRIER_ADIEi_SHIFT(i) (0 + i) | ||
121 | #define ASRIER_ADIEi_MASK(i) (1 << ASRIER_ADIEi_SHIFT(i)) | ||
122 | #define ASRIER_ADIE(i) (1 << ASRIER_ADIEi_SHIFT(i)) | ||
123 | |||
124 | /* REG2 0x0C REG_ASRCNCR */ | ||
125 | #define ASRCNCR_ANCi_SHIFT(i, b) (b * i) | ||
126 | #define ASRCNCR_ANCi_MASK(i, b) (((1 << b) - 1) << ASRCNCR_ANCi_SHIFT(i, b)) | ||
127 | #define ASRCNCR_ANCi(i, v, b) ((v << ASRCNCR_ANCi_SHIFT(i, b)) & ASRCNCR_ANCi_MASK(i, b)) | ||
128 | |||
129 | /* REG3 0x10 REG_ASRCFG */ | ||
130 | #define ASRCFG_INIRQi_SHIFT(i) (21 + i) | ||
131 | #define ASRCFG_INIRQi_MASK(i) (1 << ASRCFG_INIRQi_SHIFT(i)) | ||
132 | #define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i)) | ||
133 | #define ASRCFG_NDPRi_SHIFT(i) (18 + i) | ||
134 | #define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i)) | ||
135 | #define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i)) | ||
136 | #define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2)) | ||
137 | #define ASRCFG_POSTMODi_WIDTH 2 | ||
138 | #define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i)) | ||
139 | #define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i)) | ||
140 | #define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i)) | ||
141 | #define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i)) | ||
142 | #define ASRCFG_POSTMODi_DOWN(i) (2 << ASRCFG_POSTMODi_SHIFT(i)) | ||
143 | #define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2)) | ||
144 | #define ASRCFG_PREMODi_WIDTH 2 | ||
145 | #define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i)) | ||
146 | #define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i)) | ||
147 | #define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i)) | ||
148 | #define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i)) | ||
149 | #define ASRCFG_PREMODi_DOWN(i) (2 << ASRCFG_PREMODi_SHIFT(i)) | ||
150 | #define ASRCFG_PREMODi_BYPASS(i) (3 << ASRCFG_PREMODi_SHIFT(i)) | ||
151 | |||
152 | /* REG4 0x14 REG_ASRCSR */ | ||
153 | #define ASRCSR_AxCSi_WIDTH 4 | ||
154 | #define ASRCSR_AxCSi_MASK ((1 << ASRCSR_AxCSi_WIDTH) - 1) | ||
155 | #define ASRCSR_AOCSi_SHIFT(i) (12 + (i << 2)) | ||
156 | #define ASRCSR_AOCSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AOCSi_SHIFT(i)) | ||
157 | #define ASRCSR_AOCS(i, v) ((v) << ASRCSR_AOCSi_SHIFT(i)) | ||
158 | #define ASRCSR_AICSi_SHIFT(i) (i << 2) | ||
159 | #define ASRCSR_AICSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AICSi_SHIFT(i)) | ||
160 | #define ASRCSR_AICS(i, v) ((v) << ASRCSR_AICSi_SHIFT(i)) | ||
161 | |||
162 | /* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */ | ||
163 | #define ASRCDRi_AxCPi_WIDTH 3 | ||
164 | #define ASRCDRi_AICPi_SHIFT(i) (0 + (i % 2) * 6) | ||
165 | #define ASRCDRi_AICPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICPi_SHIFT(i)) | ||
166 | #define ASRCDRi_AICP(i, v) ((v) << ASRCDRi_AICPi_SHIFT(i)) | ||
167 | #define ASRCDRi_AICDi_SHIFT(i) (3 + (i % 2) * 6) | ||
168 | #define ASRCDRi_AICDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICDi_SHIFT(i)) | ||
169 | #define ASRCDRi_AICD(i, v) ((v) << ASRCDRi_AICDi_SHIFT(i)) | ||
170 | #define ASRCDRi_AOCPi_SHIFT(i) ((i < 2) ? 12 + i * 6 : 6) | ||
171 | #define ASRCDRi_AOCPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCPi_SHIFT(i)) | ||
172 | #define ASRCDRi_AOCP(i, v) ((v) << ASRCDRi_AOCPi_SHIFT(i)) | ||
173 | #define ASRCDRi_AOCDi_SHIFT(i) ((i < 2) ? 15 + i * 6 : 9) | ||
174 | #define ASRCDRi_AOCDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCDi_SHIFT(i)) | ||
175 | #define ASRCDRi_AOCD(i, v) ((v) << ASRCDRi_AOCDi_SHIFT(i)) | ||
176 | |||
177 | /* REG7 0x20 REG_ASRSTR */ | ||
178 | #define ASRSTR_DSLCNT_SHIFT 21 | ||
179 | #define ASRSTR_DSLCNT_MASK (1 << ASRSTR_DSLCNT_SHIFT) | ||
180 | #define ASRSTR_DSLCNT (1 << ASRSTR_DSLCNT_SHIFT) | ||
181 | #define ASRSTR_ATQOL_SHIFT 20 | ||
182 | #define ASRSTR_ATQOL_MASK (1 << ASRSTR_ATQOL_SHIFT) | ||
183 | #define ASRSTR_ATQOL (1 << ASRSTR_ATQOL_SHIFT) | ||
184 | #define ASRSTR_AOOLi_SHIFT(i) (17 + i) | ||
185 | #define ASRSTR_AOOLi_MASK(i) (1 << ASRSTR_AOOLi_SHIFT(i)) | ||
186 | #define ASRSTR_AOOL(i) (1 << ASRSTR_AOOLi_SHIFT(i)) | ||
187 | #define ASRSTR_AIOLi_SHIFT(i) (14 + i) | ||
188 | #define ASRSTR_AIOLi_MASK(i) (1 << ASRSTR_AIOLi_SHIFT(i)) | ||
189 | #define ASRSTR_AIOL(i) (1 << ASRSTR_AIOLi_SHIFT(i)) | ||
190 | #define ASRSTR_AODOi_SHIFT(i) (11 + i) | ||
191 | #define ASRSTR_AODOi_MASK(i) (1 << ASRSTR_AODOi_SHIFT(i)) | ||
192 | #define ASRSTR_AODO(i) (1 << ASRSTR_AODOi_SHIFT(i)) | ||
193 | #define ASRSTR_AIDUi_SHIFT(i) (8 + i) | ||
194 | #define ASRSTR_AIDUi_MASK(i) (1 << ASRSTR_AIDUi_SHIFT(i)) | ||
195 | #define ASRSTR_AIDU(i) (1 << ASRSTR_AIDUi_SHIFT(i)) | ||
196 | #define ASRSTR_FPWT_SHIFT 7 | ||
197 | #define ASRSTR_FPWT_MASK (1 << ASRSTR_FPWT_SHIFT) | ||
198 | #define ASRSTR_FPWT (1 << ASRSTR_FPWT_SHIFT) | ||
199 | #define ASRSTR_AOLE_SHIFT 6 | ||
200 | #define ASRSTR_AOLE_MASK (1 << ASRSTR_AOLE_SHIFT) | ||
201 | #define ASRSTR_AOLE (1 << ASRSTR_AOLE_SHIFT) | ||
202 | #define ASRSTR_AODEi_SHIFT(i) (3 + i) | ||
203 | #define ASRSTR_AODFi_MASK(i) (1 << ASRSTR_AODEi_SHIFT(i)) | ||
204 | #define ASRSTR_AODF(i) (1 << ASRSTR_AODEi_SHIFT(i)) | ||
205 | #define ASRSTR_AIDEi_SHIFT(i) (0 + i) | ||
206 | #define ASRSTR_AIDEi_MASK(i) (1 << ASRSTR_AIDEi_SHIFT(i)) | ||
207 | #define ASRSTR_AIDE(i) (1 << ASRSTR_AIDEi_SHIFT(i)) | ||
208 | |||
209 | /* REG10 0x54 REG_ASRTFR1 */ | ||
210 | #define ASRTFR1_TF_BASE_WIDTH 7 | ||
211 | #define ASRTFR1_TF_BASE_SHIFT 6 | ||
212 | #define ASRTFR1_TF_BASE_MASK (((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT) | ||
213 | #define ASRTFR1_TF_BASE(i) ((i) << ASRTFR1_TF_BASE_SHIFT) | ||
214 | |||
215 | /* | ||
216 | * REG22 0xA0 REG_ASRMCRA | ||
217 | * REG24 0xA8 REG_ASRMCRB | ||
218 | * REG26 0xB0 REG_ASRMCRC | ||
219 | */ | ||
220 | #define ASRMCRi_ZEROBUFi_SHIFT 23 | ||
221 | #define ASRMCRi_ZEROBUFi_MASK (1 << ASRMCRi_ZEROBUFi_SHIFT) | ||
222 | #define ASRMCRi_ZEROBUFi (1 << ASRMCRi_ZEROBUFi_SHIFT) | ||
223 | #define ASRMCRi_EXTTHRSHi_SHIFT 22 | ||
224 | #define ASRMCRi_EXTTHRSHi_MASK (1 << ASRMCRi_EXTTHRSHi_SHIFT) | ||
225 | #define ASRMCRi_EXTTHRSHi (1 << ASRMCRi_EXTTHRSHi_SHIFT) | ||
226 | #define ASRMCRi_BUFSTALLi_SHIFT 21 | ||
227 | #define ASRMCRi_BUFSTALLi_MASK (1 << ASRMCRi_BUFSTALLi_SHIFT) | ||
228 | #define ASRMCRi_BUFSTALLi (1 << ASRMCRi_BUFSTALLi_SHIFT) | ||
229 | #define ASRMCRi_BYPASSPOLYi_SHIFT 20 | ||
230 | #define ASRMCRi_BYPASSPOLYi_MASK (1 << ASRMCRi_BYPASSPOLYi_SHIFT) | ||
231 | #define ASRMCRi_BYPASSPOLYi (1 << ASRMCRi_BYPASSPOLYi_SHIFT) | ||
232 | #define ASRMCRi_OUTFIFO_THRESHOLD_WIDTH 6 | ||
233 | #define ASRMCRi_OUTFIFO_THRESHOLD_SHIFT 12 | ||
234 | #define ASRMCRi_OUTFIFO_THRESHOLD_MASK (((1 << ASRMCRi_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) | ||
235 | #define ASRMCRi_OUTFIFO_THRESHOLD(v) (((v) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRi_OUTFIFO_THRESHOLD_MASK) | ||
236 | #define ASRMCRi_RSYNIFi_SHIFT 11 | ||
237 | #define ASRMCRi_RSYNIFi_MASK (1 << ASRMCRi_RSYNIFi_SHIFT) | ||
238 | #define ASRMCRi_RSYNIFi (1 << ASRMCRi_RSYNIFi_SHIFT) | ||
239 | #define ASRMCRi_RSYNOFi_SHIFT 10 | ||
240 | #define ASRMCRi_RSYNOFi_MASK (1 << ASRMCRi_RSYNOFi_SHIFT) | ||
241 | #define ASRMCRi_RSYNOFi (1 << ASRMCRi_RSYNOFi_SHIFT) | ||
242 | #define ASRMCRi_INFIFO_THRESHOLD_WIDTH 6 | ||
243 | #define ASRMCRi_INFIFO_THRESHOLD_SHIFT 0 | ||
244 | #define ASRMCRi_INFIFO_THRESHOLD_MASK (((1 << ASRMCRi_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) | ||
245 | #define ASRMCRi_INFIFO_THRESHOLD(v) (((v) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) & ASRMCRi_INFIFO_THRESHOLD_MASK) | ||
246 | |||
247 | /* | ||
248 | * REG23 0xA4 REG_ASRFSTA | ||
249 | * REG25 0xAC REG_ASRFSTB | ||
250 | * REG27 0xB4 REG_ASRFSTC | ||
251 | */ | ||
252 | #define ASRFSTi_OAFi_SHIFT 23 | ||
253 | #define ASRFSTi_OAFi_MASK (1 << ASRFSTi_OAFi_SHIFT) | ||
254 | #define ASRFSTi_OAFi (1 << ASRFSTi_OAFi_SHIFT) | ||
255 | #define ASRFSTi_OUTPUT_FIFO_WIDTH 7 | ||
256 | #define ASRFSTi_OUTPUT_FIFO_SHIFT 12 | ||
257 | #define ASRFSTi_OUTPUT_FIFO_MASK (((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT) | ||
258 | #define ASRFSTi_IAEi_SHIFT 11 | ||
259 | #define ASRFSTi_IAEi_MASK (1 << ASRFSTi_OAFi_SHIFT) | ||
260 | #define ASRFSTi_IAEi (1 << ASRFSTi_OAFi_SHIFT) | ||
261 | #define ASRFSTi_INPUT_FIFO_WIDTH 7 | ||
262 | #define ASRFSTi_INPUT_FIFO_SHIFT 0 | ||
263 | #define ASRFSTi_INPUT_FIFO_MASK ((1 << ASRFSTi_INPUT_FIFO_WIDTH) - 1) | ||
264 | |||
265 | /* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1i */ | ||
266 | #define ASRMCR1i_IWD_WIDTH 3 | ||
267 | #define ASRMCR1i_IWD_SHIFT 9 | ||
268 | #define ASRMCR1i_IWD_MASK (((1 << ASRMCR1i_IWD_WIDTH) - 1) << ASRMCR1i_IWD_SHIFT) | ||
269 | #define ASRMCR1i_IWD(v) ((v) << ASRMCR1i_IWD_SHIFT) | ||
270 | #define ASRMCR1i_IMSB_SHIFT 8 | ||
271 | #define ASRMCR1i_IMSB_MASK (1 << ASRMCR1i_IMSB_SHIFT) | ||
272 | #define ASRMCR1i_IMSB_MSB (1 << ASRMCR1i_IMSB_SHIFT) | ||
273 | #define ASRMCR1i_IMSB_LSB (0 << ASRMCR1i_IMSB_SHIFT) | ||
274 | #define ASRMCR1i_OMSB_SHIFT 2 | ||
275 | #define ASRMCR1i_OMSB_MASK (1 << ASRMCR1i_OMSB_SHIFT) | ||
276 | #define ASRMCR1i_OMSB_MSB (1 << ASRMCR1i_OMSB_SHIFT) | ||
277 | #define ASRMCR1i_OMSB_LSB (0 << ASRMCR1i_OMSB_SHIFT) | ||
278 | #define ASRMCR1i_OSGN_SHIFT 1 | ||
279 | #define ASRMCR1i_OSGN_MASK (1 << ASRMCR1i_OSGN_SHIFT) | ||
280 | #define ASRMCR1i_OSGN (1 << ASRMCR1i_OSGN_SHIFT) | ||
281 | #define ASRMCR1i_OW16_SHIFT 0 | ||
282 | #define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT) | ||
283 | #define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT) | ||
284 | |||
285 | |||
286 | enum asrc_pair_index { | ||
287 | ASRC_INVALID_PAIR = -1, | ||
288 | ASRC_PAIR_A = 0, | ||
289 | ASRC_PAIR_B = 1, | ||
290 | ASRC_PAIR_C = 2, | ||
291 | }; | ||
292 | |||
293 | #define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1) | ||
294 | |||
295 | enum asrc_inclk { | ||
296 | INCLK_NONE = 0x03, | ||
297 | INCLK_ESAI_RX = 0x00, | ||
298 | INCLK_SSI1_RX = 0x01, | ||
299 | INCLK_SSI2_RX = 0x02, | ||
300 | INCLK_SSI3_RX = 0x07, | ||
301 | INCLK_SPDIF_RX = 0x04, | ||
302 | INCLK_MLB_CLK = 0x05, | ||
303 | INCLK_PAD = 0x06, | ||
304 | INCLK_ESAI_TX = 0x08, | ||
305 | INCLK_SSI1_TX = 0x09, | ||
306 | INCLK_SSI2_TX = 0x0a, | ||
307 | INCLK_SSI3_TX = 0x0b, | ||
308 | INCLK_SPDIF_TX = 0x0c, | ||
309 | INCLK_ASRCK1_CLK = 0x0f, | ||
310 | }; | ||
311 | |||
312 | enum asrc_outclk { | ||
313 | OUTCLK_NONE = 0x03, | ||
314 | OUTCLK_ESAI_TX = 0x00, | ||
315 | OUTCLK_SSI1_TX = 0x01, | ||
316 | OUTCLK_SSI2_TX = 0x02, | ||
317 | OUTCLK_SSI3_TX = 0x07, | ||
318 | OUTCLK_SPDIF_TX = 0x04, | ||
319 | OUTCLK_MLB_CLK = 0x05, | ||
320 | OUTCLK_PAD = 0x06, | ||
321 | OUTCLK_ESAI_RX = 0x08, | ||
322 | OUTCLK_SSI1_RX = 0x09, | ||
323 | OUTCLK_SSI2_RX = 0x0a, | ||
324 | OUTCLK_SSI3_RX = 0x0b, | ||
325 | OUTCLK_SPDIF_RX = 0x0c, | ||
326 | OUTCLK_ASRCK1_CLK = 0x0f, | ||
327 | }; | ||
328 | |||
329 | #define ASRC_CLK_MAX_NUM 16 | ||
330 | |||
331 | enum asrc_word_width { | ||
332 | ASRC_WIDTH_24_BIT = 0, | ||
333 | ASRC_WIDTH_16_BIT = 1, | ||
334 | ASRC_WIDTH_8_BIT = 2, | ||
335 | }; | ||
336 | |||
337 | struct asrc_config { | ||
338 | enum asrc_pair_index pair; | ||
339 | unsigned int channel_num; | ||
340 | unsigned int buffer_num; | ||
341 | unsigned int dma_buffer_size; | ||
342 | unsigned int input_sample_rate; | ||
343 | unsigned int output_sample_rate; | ||
344 | enum asrc_word_width input_word_width; | ||
345 | enum asrc_word_width output_word_width; | ||
346 | enum asrc_inclk inclk; | ||
347 | enum asrc_outclk outclk; | ||
348 | }; | ||
349 | |||
350 | struct asrc_req { | ||
351 | unsigned int chn_num; | ||
352 | enum asrc_pair_index index; | ||
353 | }; | ||
354 | |||
355 | struct asrc_querybuf { | ||
356 | unsigned int buffer_index; | ||
357 | unsigned int input_length; | ||
358 | unsigned int output_length; | ||
359 | unsigned long input_offset; | ||
360 | unsigned long output_offset; | ||
361 | }; | ||
362 | |||
363 | struct asrc_convert_buffer { | ||
364 | void *input_buffer_vaddr; | ||
365 | void *output_buffer_vaddr; | ||
366 | unsigned int input_buffer_length; | ||
367 | unsigned int output_buffer_length; | ||
368 | }; | ||
369 | |||
370 | struct asrc_status_flags { | ||
371 | enum asrc_pair_index index; | ||
372 | unsigned int overload_error; | ||
373 | }; | ||
374 | |||
375 | enum asrc_error_status { | ||
376 | ASRC_TASK_Q_OVERLOAD = 0x01, | ||
377 | ASRC_OUTPUT_TASK_OVERLOAD = 0x02, | ||
378 | ASRC_INPUT_TASK_OVERLOAD = 0x04, | ||
379 | ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08, | ||
380 | ASRC_INPUT_BUFFER_UNDERRUN = 0x10, | ||
381 | }; | ||
382 | |||
383 | struct dma_block { | ||
384 | dma_addr_t dma_paddr; | ||
385 | void *dma_vaddr; | ||
386 | unsigned int length; | ||
387 | }; | ||
388 | |||
389 | /** | ||
390 | * fsl_asrc_pair: ASRC Pair private data | ||
391 | * | ||
392 | * @asrc_priv: pointer to its parent module | ||
393 | * @config: configuration profile | ||
394 | * @error: error record | ||
395 | * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C) | ||
396 | * @channels: occupied channel number | ||
397 | * @desc: input and output dma descriptors | ||
398 | * @dma_chan: inputer and output DMA channels | ||
399 | * @dma_data: private dma data | ||
400 | * @pos: hardware pointer position | ||
401 | * @private: pair private area | ||
402 | */ | ||
403 | struct fsl_asrc_pair { | ||
404 | struct fsl_asrc *asrc_priv; | ||
405 | struct asrc_config *config; | ||
406 | unsigned int error; | ||
407 | |||
408 | enum asrc_pair_index index; | ||
409 | unsigned int channels; | ||
410 | |||
411 | struct dma_async_tx_descriptor *desc[2]; | ||
412 | struct dma_chan *dma_chan[2]; | ||
413 | struct imx_dma_data dma_data; | ||
414 | unsigned int pos; | ||
415 | |||
416 | void *private; | ||
417 | }; | ||
418 | |||
419 | /** | ||
420 | * fsl_asrc_pair: ASRC private data | ||
421 | * | ||
422 | * @dma_params_rx: DMA parameters for receive channel | ||
423 | * @dma_params_tx: DMA parameters for transmit channel | ||
424 | * @pdev: platform device pointer | ||
425 | * @regmap: regmap handler | ||
426 | * @paddr: physical address to the base address of registers | ||
427 | * @mem_clk: clock source to access register | ||
428 | * @ipg_clk: clock source to drive peripheral | ||
429 | * @asrck_clk: clock sources to driver ASRC internal logic | ||
430 | * @lock: spin lock for resource protection | ||
431 | * @pair: pair pointers | ||
432 | * @channel_bits: width of ASRCNCR register for each pair | ||
433 | * @channel_avail: non-occupied channel numbers | ||
434 | * @asrc_rate: default sample rate for ASoC Back-Ends | ||
435 | * @asrc_width: default sample width for ASoC Back-Ends | ||
436 | * @name: driver name | ||
437 | */ | ||
438 | struct fsl_asrc { | ||
439 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
440 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
441 | struct platform_device *pdev; | ||
442 | struct regmap *regmap; | ||
443 | unsigned long paddr; | ||
444 | struct clk *mem_clk; | ||
445 | struct clk *ipg_clk; | ||
446 | struct clk *asrck_clk[ASRC_CLK_MAX_NUM]; | ||
447 | spinlock_t lock; | ||
448 | |||
449 | struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM]; | ||
450 | unsigned int channel_bits; | ||
451 | unsigned int channel_avail; | ||
452 | |||
453 | int asrc_rate; | ||
454 | int asrc_width; | ||
455 | |||
456 | char name[32]; | ||
457 | }; | ||
458 | |||
459 | extern struct snd_soc_platform_driver fsl_asrc_platform; | ||
460 | struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir); | ||
461 | #endif /* _FSL_ASRC_H */ | ||
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c new file mode 100644 index 000000000000..ffc000bc1f15 --- /dev/null +++ b/sound/soc/fsl/fsl_asrc_dma.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * Freescale ASRC ALSA SoC Platform (DMA) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_data/dma-imx.h> | ||
16 | #include <sound/dmaengine_pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | |||
19 | #include "fsl_asrc.h" | ||
20 | |||
21 | #define FSL_ASRC_DMABUF_SIZE (256 * 1024) | ||
22 | |||
23 | static struct snd_pcm_hardware snd_imx_hardware = { | ||
24 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
25 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
26 | SNDRV_PCM_INFO_MMAP | | ||
27 | SNDRV_PCM_INFO_MMAP_VALID | | ||
28 | SNDRV_PCM_INFO_PAUSE | | ||
29 | SNDRV_PCM_INFO_RESUME, | ||
30 | .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE, | ||
31 | .period_bytes_min = 128, | ||
32 | .period_bytes_max = 65535, /* Limited by SDMA engine */ | ||
33 | .periods_min = 2, | ||
34 | .periods_max = 255, | ||
35 | .fifo_size = 0, | ||
36 | }; | ||
37 | |||
38 | static bool filter(struct dma_chan *chan, void *param) | ||
39 | { | ||
40 | if (!imx_dma_is_general_purpose(chan)) | ||
41 | return false; | ||
42 | |||
43 | chan->private = param; | ||
44 | |||
45 | return true; | ||
46 | } | ||
47 | |||
48 | static void fsl_asrc_dma_complete(void *arg) | ||
49 | { | ||
50 | struct snd_pcm_substream *substream = arg; | ||
51 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
52 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
53 | |||
54 | pair->pos += snd_pcm_lib_period_bytes(substream); | ||
55 | if (pair->pos >= snd_pcm_lib_buffer_bytes(substream)) | ||
56 | pair->pos = 0; | ||
57 | |||
58 | snd_pcm_period_elapsed(substream); | ||
59 | } | ||
60 | |||
61 | static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream) | ||
62 | { | ||
63 | u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN; | ||
64 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
65 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
66 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
67 | struct device *dev = rtd->platform->dev; | ||
68 | unsigned long flags = DMA_CTRL_ACK; | ||
69 | |||
70 | /* Prepare and submit Front-End DMA channel */ | ||
71 | if (!substream->runtime->no_period_wakeup) | ||
72 | flags |= DMA_PREP_INTERRUPT; | ||
73 | |||
74 | pair->pos = 0; | ||
75 | pair->desc[!dir] = dmaengine_prep_dma_cyclic( | ||
76 | pair->dma_chan[!dir], runtime->dma_addr, | ||
77 | snd_pcm_lib_buffer_bytes(substream), | ||
78 | snd_pcm_lib_period_bytes(substream), | ||
79 | dir == OUT ? DMA_TO_DEVICE : DMA_FROM_DEVICE, flags); | ||
80 | if (!pair->desc[!dir]) { | ||
81 | dev_err(dev, "failed to prepare slave DMA for Front-End\n"); | ||
82 | return -ENOMEM; | ||
83 | } | ||
84 | |||
85 | pair->desc[!dir]->callback = fsl_asrc_dma_complete; | ||
86 | pair->desc[!dir]->callback_param = substream; | ||
87 | |||
88 | dmaengine_submit(pair->desc[!dir]); | ||
89 | |||
90 | /* Prepare and submit Back-End DMA channel */ | ||
91 | pair->desc[dir] = dmaengine_prep_dma_cyclic( | ||
92 | pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0); | ||
93 | if (!pair->desc[dir]) { | ||
94 | dev_err(dev, "failed to prepare slave DMA for Back-End\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
98 | dmaengine_submit(pair->desc[dir]); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
104 | { | ||
105 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
106 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
107 | int ret; | ||
108 | |||
109 | switch (cmd) { | ||
110 | case SNDRV_PCM_TRIGGER_START: | ||
111 | case SNDRV_PCM_TRIGGER_RESUME: | ||
112 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
113 | ret = fsl_asrc_dma_prepare_and_submit(substream); | ||
114 | if (ret) | ||
115 | return ret; | ||
116 | dma_async_issue_pending(pair->dma_chan[IN]); | ||
117 | dma_async_issue_pending(pair->dma_chan[OUT]); | ||
118 | break; | ||
119 | case SNDRV_PCM_TRIGGER_STOP: | ||
120 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
121 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
122 | dmaengine_terminate_all(pair->dma_chan[OUT]); | ||
123 | dmaengine_terminate_all(pair->dma_chan[IN]); | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream, | ||
133 | struct snd_pcm_hw_params *params) | ||
134 | { | ||
135 | enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
136 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
137 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
138 | struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; | ||
139 | struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; | ||
140 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
141 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
142 | struct fsl_asrc *asrc_priv = pair->asrc_priv; | ||
143 | struct dma_slave_config config_fe, config_be; | ||
144 | enum asrc_pair_index index = pair->index; | ||
145 | struct device *dev = rtd->platform->dev; | ||
146 | int stream = substream->stream; | ||
147 | struct imx_dma_data *tmp_data; | ||
148 | struct snd_soc_dpcm *dpcm; | ||
149 | struct dma_chan *tmp_chan; | ||
150 | struct device *dev_be; | ||
151 | u8 dir = tx ? OUT : IN; | ||
152 | dma_cap_mask_t mask; | ||
153 | int ret; | ||
154 | |||
155 | /* Fetch the Back-End dma_data from DPCM */ | ||
156 | list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) { | ||
157 | struct snd_soc_pcm_runtime *be = dpcm->be; | ||
158 | struct snd_pcm_substream *substream_be; | ||
159 | struct snd_soc_dai *dai = be->cpu_dai; | ||
160 | |||
161 | if (dpcm->fe != rtd) | ||
162 | continue; | ||
163 | |||
164 | substream_be = snd_soc_dpcm_get_substream(be, stream); | ||
165 | dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be); | ||
166 | dev_be = dai->dev; | ||
167 | break; | ||
168 | } | ||
169 | |||
170 | if (!dma_params_be) { | ||
171 | dev_err(dev, "failed to get the substream of Back-End\n"); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | /* Override dma_data of the Front-End and config its dmaengine */ | ||
176 | dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
177 | dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index); | ||
178 | dma_params_fe->maxburst = dma_params_be->maxburst; | ||
179 | |||
180 | pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir); | ||
181 | if (!pair->dma_chan[!dir]) { | ||
182 | dev_err(dev, "failed to request DMA channel\n"); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | memset(&config_fe, 0, sizeof(config_fe)); | ||
187 | ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe); | ||
188 | if (ret) { | ||
189 | dev_err(dev, "failed to prepare DMA config for Front-End\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe); | ||
194 | if (ret) { | ||
195 | dev_err(dev, "failed to config DMA channel for Front-End\n"); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | /* Request and config DMA channel for Back-End */ | ||
200 | dma_cap_zero(mask); | ||
201 | dma_cap_set(DMA_SLAVE, mask); | ||
202 | dma_cap_set(DMA_CYCLIC, mask); | ||
203 | |||
204 | /* Get DMA request of Back-End */ | ||
205 | tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); | ||
206 | tmp_data = tmp_chan->private; | ||
207 | pair->dma_data.dma_request = tmp_data->dma_request; | ||
208 | dma_release_channel(tmp_chan); | ||
209 | |||
210 | /* Get DMA request of Front-End */ | ||
211 | tmp_chan = fsl_asrc_get_dma_channel(pair, dir); | ||
212 | tmp_data = tmp_chan->private; | ||
213 | pair->dma_data.dma_request2 = tmp_data->dma_request; | ||
214 | pair->dma_data.peripheral_type = tmp_data->peripheral_type; | ||
215 | pair->dma_data.priority = tmp_data->priority; | ||
216 | dma_release_channel(tmp_chan); | ||
217 | |||
218 | pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data); | ||
219 | if (!pair->dma_chan[dir]) { | ||
220 | dev_err(dev, "failed to request DMA channel for Back-End\n"); | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | |||
224 | if (asrc_priv->asrc_width == 16) | ||
225 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
226 | else | ||
227 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
228 | |||
229 | config_be.direction = DMA_DEV_TO_DEV; | ||
230 | config_be.src_addr_width = buswidth; | ||
231 | config_be.src_maxburst = dma_params_be->maxburst; | ||
232 | config_be.dst_addr_width = buswidth; | ||
233 | config_be.dst_maxburst = dma_params_be->maxburst; | ||
234 | |||
235 | if (tx) { | ||
236 | config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index); | ||
237 | config_be.dst_addr = dma_params_be->addr; | ||
238 | } else { | ||
239 | config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index); | ||
240 | config_be.src_addr = dma_params_be->addr; | ||
241 | } | ||
242 | |||
243 | ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be); | ||
244 | if (ret) { | ||
245 | dev_err(dev, "failed to config DMA channel for Back-End\n"); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
257 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
258 | |||
259 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
260 | |||
261 | if (pair->dma_chan[IN]) | ||
262 | dma_release_channel(pair->dma_chan[IN]); | ||
263 | |||
264 | if (pair->dma_chan[OUT]) | ||
265 | dma_release_channel(pair->dma_chan[OUT]); | ||
266 | |||
267 | pair->dma_chan[IN] = NULL; | ||
268 | pair->dma_chan[OUT] = NULL; | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream) | ||
274 | { | ||
275 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
276 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
277 | struct device *dev = rtd->platform->dev; | ||
278 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | ||
279 | struct fsl_asrc_pair *pair; | ||
280 | |||
281 | pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL); | ||
282 | if (!pair) { | ||
283 | dev_err(dev, "failed to allocate pair\n"); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | |||
287 | pair->asrc_priv = asrc_priv; | ||
288 | |||
289 | runtime->private_data = pair; | ||
290 | |||
291 | snd_pcm_hw_constraint_integer(substream->runtime, | ||
292 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
293 | snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream) | ||
299 | { | ||
300 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
301 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
302 | struct fsl_asrc *asrc_priv; | ||
303 | |||
304 | if (!pair) | ||
305 | return 0; | ||
306 | |||
307 | asrc_priv = pair->asrc_priv; | ||
308 | |||
309 | if (asrc_priv->pair[pair->index] == pair) | ||
310 | asrc_priv->pair[pair->index] = NULL; | ||
311 | |||
312 | kfree(pair); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream) | ||
318 | { | ||
319 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
320 | struct fsl_asrc_pair *pair = runtime->private_data; | ||
321 | |||
322 | return bytes_to_frames(substream->runtime, pair->pos); | ||
323 | } | ||
324 | |||
325 | static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = { | ||
326 | .ioctl = snd_pcm_lib_ioctl, | ||
327 | .hw_params = fsl_asrc_dma_hw_params, | ||
328 | .hw_free = fsl_asrc_dma_hw_free, | ||
329 | .trigger = fsl_asrc_dma_trigger, | ||
330 | .open = fsl_asrc_dma_startup, | ||
331 | .close = fsl_asrc_dma_shutdown, | ||
332 | .pointer = fsl_asrc_dma_pcm_pointer, | ||
333 | }; | ||
334 | |||
335 | static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
336 | { | ||
337 | struct snd_card *card = rtd->card->snd_card; | ||
338 | struct snd_pcm_substream *substream; | ||
339 | struct snd_pcm *pcm = rtd->pcm; | ||
340 | int ret, i; | ||
341 | |||
342 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
343 | if (ret) { | ||
344 | dev_err(card->dev, "failed to set DMA mask\n"); | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { | ||
349 | substream = pcm->streams[i].substream; | ||
350 | if (!substream) | ||
351 | continue; | ||
352 | |||
353 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev, | ||
354 | FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer); | ||
355 | if (ret) { | ||
356 | dev_err(card->dev, "failed to allocate DMA buffer\n"); | ||
357 | goto err; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | return 0; | ||
362 | |||
363 | err: | ||
364 | if (--i == 0 && pcm->streams[i].substream) | ||
365 | snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm) | ||
371 | { | ||
372 | struct snd_pcm_substream *substream; | ||
373 | int i; | ||
374 | |||
375 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { | ||
376 | substream = pcm->streams[i].substream; | ||
377 | if (!substream) | ||
378 | continue; | ||
379 | |||
380 | snd_dma_free_pages(&substream->dma_buffer); | ||
381 | substream->dma_buffer.area = NULL; | ||
382 | substream->dma_buffer.addr = 0; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | struct snd_soc_platform_driver fsl_asrc_platform = { | ||
387 | .ops = &fsl_asrc_dma_pcm_ops, | ||
388 | .pcm_new = fsl_asrc_dma_pcm_new, | ||
389 | .pcm_free = fsl_asrc_dma_pcm_free, | ||
390 | }; | ||
391 | EXPORT_SYMBOL_GPL(fsl_asrc_platform); | ||
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d719caf26dc2..72d154e7dd03 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -624,12 +624,14 @@ static int fsl_esai_dai_probe(struct snd_soc_dai *dai) | |||
624 | static struct snd_soc_dai_driver fsl_esai_dai = { | 624 | static struct snd_soc_dai_driver fsl_esai_dai = { |
625 | .probe = fsl_esai_dai_probe, | 625 | .probe = fsl_esai_dai_probe, |
626 | .playback = { | 626 | .playback = { |
627 | .stream_name = "CPU-Playback", | ||
627 | .channels_min = 1, | 628 | .channels_min = 1, |
628 | .channels_max = 12, | 629 | .channels_max = 12, |
629 | .rates = FSL_ESAI_RATES, | 630 | .rates = FSL_ESAI_RATES, |
630 | .formats = FSL_ESAI_FORMATS, | 631 | .formats = FSL_ESAI_FORMATS, |
631 | }, | 632 | }, |
632 | .capture = { | 633 | .capture = { |
634 | .stream_name = "CPU-Capture", | ||
633 | .channels_min = 1, | 635 | .channels_min = 1, |
634 | .channels_max = 8, | 636 | .channels_max = 8, |
635 | .rates = FSL_ESAI_RATES, | 637 | .rates = FSL_ESAI_RATES, |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index c5a0e8af8226..faa049797897 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -106,7 +106,7 @@ irq_rx: | |||
106 | xcsr &= ~FSL_SAI_CSR_xF_MASK; | 106 | xcsr &= ~FSL_SAI_CSR_xF_MASK; |
107 | 107 | ||
108 | if (flags) | 108 | if (flags) |
109 | regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); | 109 | regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr); |
110 | 110 | ||
111 | out: | 111 | out: |
112 | if (irq_none) | 112 | if (irq_none) |
@@ -327,7 +327,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
327 | { | 327 | { |
328 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 328 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
329 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 329 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
330 | u32 tcsr, rcsr; | 330 | u32 xcsr, count = 100; |
331 | 331 | ||
332 | /* | 332 | /* |
333 | * The transmitter bit clock and frame sync are to be | 333 | * The transmitter bit clock and frame sync are to be |
@@ -338,9 +338,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, | 338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, |
339 | FSL_SAI_CR2_SYNC); | 339 | FSL_SAI_CR2_SYNC); |
340 | 340 | ||
341 | regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); | ||
342 | regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); | ||
343 | |||
344 | /* | 341 | /* |
345 | * It is recommended that the transmitter is the last enabled | 342 | * It is recommended that the transmitter is the last enabled |
346 | * and the first disabled. | 343 | * and the first disabled. |
@@ -349,17 +346,16 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
349 | case SNDRV_PCM_TRIGGER_START: | 346 | case SNDRV_PCM_TRIGGER_START: |
350 | case SNDRV_PCM_TRIGGER_RESUME: | 347 | case SNDRV_PCM_TRIGGER_RESUME: |
351 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 348 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
352 | if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) { | 349 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), |
353 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 350 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); |
354 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 351 | |
355 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 352 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, |
356 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 353 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); |
357 | } | 354 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, |
355 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | ||
358 | 356 | ||
359 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 357 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), |
360 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); | 358 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); |
361 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | ||
362 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); | ||
363 | break; | 359 | break; |
364 | case SNDRV_PCM_TRIGGER_STOP: | 360 | case SNDRV_PCM_TRIGGER_STOP: |
365 | case SNDRV_PCM_TRIGGER_SUSPEND: | 361 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -370,11 +366,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
370 | FSL_SAI_CSR_xIE_MASK, 0); | 366 | FSL_SAI_CSR_xIE_MASK, 0); |
371 | 367 | ||
372 | /* Check if the opposite FRDE is also disabled */ | 368 | /* Check if the opposite FRDE is also disabled */ |
373 | if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) { | 369 | regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr); |
370 | if (!(xcsr & FSL_SAI_CSR_FRDE)) { | ||
371 | /* Disable both directions and reset their FIFOs */ | ||
374 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 372 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, |
375 | FSL_SAI_CSR_TERE, 0); | 373 | FSL_SAI_CSR_TERE, 0); |
376 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 374 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, |
377 | FSL_SAI_CSR_TERE, 0); | 375 | FSL_SAI_CSR_TERE, 0); |
376 | |||
377 | /* TERE will remain set till the end of current frame */ | ||
378 | do { | ||
379 | udelay(10); | ||
380 | regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr); | ||
381 | } while (--count && xcsr & FSL_SAI_CSR_TERE); | ||
382 | |||
383 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | ||
384 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | ||
385 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | ||
386 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | ||
378 | } | 387 | } |
379 | break; | 388 | break; |
380 | default: | 389 | default: |
@@ -446,12 +455,14 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | |||
446 | static struct snd_soc_dai_driver fsl_sai_dai = { | 455 | static struct snd_soc_dai_driver fsl_sai_dai = { |
447 | .probe = fsl_sai_dai_probe, | 456 | .probe = fsl_sai_dai_probe, |
448 | .playback = { | 457 | .playback = { |
458 | .stream_name = "CPU-Playback", | ||
449 | .channels_min = 1, | 459 | .channels_min = 1, |
450 | .channels_max = 2, | 460 | .channels_max = 2, |
451 | .rates = SNDRV_PCM_RATE_8000_96000, | 461 | .rates = SNDRV_PCM_RATE_8000_96000, |
452 | .formats = FSL_SAI_FORMATS, | 462 | .formats = FSL_SAI_FORMATS, |
453 | }, | 463 | }, |
454 | .capture = { | 464 | .capture = { |
465 | .stream_name = "CPU-Capture", | ||
455 | .channels_min = 1, | 466 | .channels_min = 1, |
456 | .channels_max = 2, | 467 | .channels_max = 2, |
457 | .rates = SNDRV_PCM_RATE_8000_96000, | 468 | .rates = SNDRV_PCM_RATE_8000_96000, |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index d7a60614dd21..70acfe4a9bd5 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -32,10 +32,13 @@ | |||
32 | #define FSL_SPDIF_TXFIFO_WML 0x8 | 32 | #define FSL_SPDIF_TXFIFO_WML 0x8 |
33 | #define FSL_SPDIF_RXFIFO_WML 0x8 | 33 | #define FSL_SPDIF_RXFIFO_WML 0x8 |
34 | 34 | ||
35 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) | 35 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) |
36 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\ | 36 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL |\ |
37 | INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\ | 37 | INT_URX_OV | INT_QRX_FUL | INT_QRX_OV |\ |
38 | INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED) | 38 | INT_UQ_SYNC | INT_UQ_ERR | INT_RXFIFO_RESYNC |\ |
39 | INT_LOSS_LOCK | INT_DPLL_LOCKED) | ||
40 | |||
41 | #define SIE_INTR_FOR(tx) (tx ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE) | ||
39 | 42 | ||
40 | /* Index list for the values that has if (DPLL Locked) condition */ | 43 | /* Index list for the values that has if (DPLL Locked) condition */ |
41 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; | 44 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; |
@@ -96,7 +99,7 @@ struct fsl_spdif_priv { | |||
96 | struct platform_device *pdev; | 99 | struct platform_device *pdev; |
97 | struct regmap *regmap; | 100 | struct regmap *regmap; |
98 | bool dpll_locked; | 101 | bool dpll_locked; |
99 | u16 txrate[SPDIF_TXRATE_MAX]; | 102 | u32 txrate[SPDIF_TXRATE_MAX]; |
100 | u8 txclk_df[SPDIF_TXRATE_MAX]; | 103 | u8 txclk_df[SPDIF_TXRATE_MAX]; |
101 | u8 sysclk_df[SPDIF_TXRATE_MAX]; | 104 | u8 sysclk_df[SPDIF_TXRATE_MAX]; |
102 | u8 txclk_src[SPDIF_TXRATE_MAX]; | 105 | u8 txclk_src[SPDIF_TXRATE_MAX]; |
@@ -137,10 +140,9 @@ static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv) | |||
137 | 140 | ||
138 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); | 141 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); |
139 | 142 | ||
140 | if (!spdif_priv->dpll_locked) { | 143 | /* Clear illegal symbol if DPLL unlocked since no audio stream */ |
141 | /* DPLL unlocked seems no audio stream */ | 144 | if (!spdif_priv->dpll_locked) |
142 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); | 145 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); |
143 | } | ||
144 | } | 146 | } |
145 | 147 | ||
146 | /* U/Q Channel receive register full */ | 148 | /* U/Q Channel receive register full */ |
@@ -335,8 +337,8 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv) | |||
335 | u32 ch_status; | 337 | u32 ch_status; |
336 | 338 | ||
337 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | | 339 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | |
338 | (bitrev8(ctrl->ch_status[1]) << 8) | | 340 | (bitrev8(ctrl->ch_status[1]) << 8) | |
339 | bitrev8(ctrl->ch_status[2]); | 341 | bitrev8(ctrl->ch_status[2]); |
340 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); | 342 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); |
341 | 343 | ||
342 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); | 344 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); |
@@ -390,6 +392,14 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, | |||
390 | rate = SPDIF_TXRATE_48000; | 392 | rate = SPDIF_TXRATE_48000; |
391 | csfs = IEC958_AES3_CON_FS_48000; | 393 | csfs = IEC958_AES3_CON_FS_48000; |
392 | break; | 394 | break; |
395 | case 96000: | ||
396 | rate = SPDIF_TXRATE_96000; | ||
397 | csfs = IEC958_AES3_CON_FS_96000; | ||
398 | break; | ||
399 | case 192000: | ||
400 | rate = SPDIF_TXRATE_192000; | ||
401 | csfs = IEC958_AES3_CON_FS_192000; | ||
402 | break; | ||
393 | default: | 403 | default: |
394 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); | 404 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); |
395 | return -EINVAL; | 405 | return -EINVAL; |
@@ -433,13 +443,12 @@ clk_set_bypass: | |||
433 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); | 443 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); |
434 | 444 | ||
435 | /* select clock source and divisor */ | 445 | /* select clock source and divisor */ |
436 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DF(txclk_df); | 446 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | |
437 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK; | 447 | STC_TXCLK_DF(txclk_df) | STC_SYSCLK_DF(sysclk_df); |
448 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | | ||
449 | STC_TXCLK_DF_MASK | STC_SYSCLK_DF_MASK; | ||
438 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); | 450 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); |
439 | 451 | ||
440 | regmap_update_bits(regmap, REG_SPDIF_STC, | ||
441 | STC_SYSCLK_DF_MASK, STC_SYSCLK_DF(sysclk_df)); | ||
442 | |||
443 | dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n", | 452 | dev_dbg(&pdev->dev, "set sample rate to %dHz for %dHz playback\n", |
444 | spdif_priv->txrate[rate], sample_rate); | 453 | spdif_priv->txrate[rate], sample_rate); |
445 | 454 | ||
@@ -553,7 +562,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, | |||
553 | return ret; | 562 | return ret; |
554 | } | 563 | } |
555 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, | 564 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, |
556 | IEC958_AES3_CON_CLOCK_1000PPM); | 565 | IEC958_AES3_CON_CLOCK_1000PPM); |
557 | spdif_write_channel_status(spdif_priv); | 566 | spdif_write_channel_status(spdif_priv); |
558 | } else { | 567 | } else { |
559 | /* Setup rx clock source */ | 568 | /* Setup rx clock source */ |
@@ -569,9 +578,9 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream, | |||
569 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 578 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
570 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 579 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
571 | struct regmap *regmap = spdif_priv->regmap; | 580 | struct regmap *regmap = spdif_priv->regmap; |
572 | int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 581 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
573 | u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE; | 582 | u32 intr = SIE_INTR_FOR(tx); |
574 | u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;; | 583 | u32 dmaen = SCR_DMA_xX_EN(tx); |
575 | 584 | ||
576 | switch (cmd) { | 585 | switch (cmd) { |
577 | case SNDRV_PCM_TRIGGER_START: | 586 | case SNDRV_PCM_TRIGGER_START: |
@@ -662,9 +671,8 @@ static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol, | |||
662 | u32 cstatus, val; | 671 | u32 cstatus, val; |
663 | 672 | ||
664 | regmap_read(regmap, REG_SPDIF_SIS, &val); | 673 | regmap_read(regmap, REG_SPDIF_SIS, &val); |
665 | if (!(val & INT_CNEW)) { | 674 | if (!(val & INT_CNEW)) |
666 | return -EAGAIN; | 675 | return -EAGAIN; |
667 | } | ||
668 | 676 | ||
669 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); | 677 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); |
670 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; | 678 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; |
@@ -693,15 +701,14 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol, | |||
693 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 701 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
694 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | 702 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; |
695 | unsigned long flags; | 703 | unsigned long flags; |
696 | int ret = 0; | 704 | int ret = -EAGAIN; |
697 | 705 | ||
698 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | 706 | spin_lock_irqsave(&ctrl->ctl_lock, flags); |
699 | if (ctrl->ready_buf) { | 707 | if (ctrl->ready_buf) { |
700 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; | 708 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; |
701 | memcpy(&ucontrol->value.iec958.subcode[0], | 709 | memcpy(&ucontrol->value.iec958.subcode[0], |
702 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); | 710 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); |
703 | } else { | 711 | ret = 0; |
704 | ret = -EAGAIN; | ||
705 | } | 712 | } |
706 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | 713 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); |
707 | 714 | ||
@@ -726,15 +733,14 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, | |||
726 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 733 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
727 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | 734 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; |
728 | unsigned long flags; | 735 | unsigned long flags; |
729 | int ret = 0; | 736 | int ret = -EAGAIN; |
730 | 737 | ||
731 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | 738 | spin_lock_irqsave(&ctrl->ctl_lock, flags); |
732 | if (ctrl->ready_buf) { | 739 | if (ctrl->ready_buf) { |
733 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; | 740 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; |
734 | memcpy(&ucontrol->value.bytes.data[0], | 741 | memcpy(&ucontrol->value.bytes.data[0], |
735 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); | 742 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); |
736 | } else { | 743 | ret = 0; |
737 | ret = -EAGAIN; | ||
738 | } | 744 | } |
739 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | 745 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); |
740 | 746 | ||
@@ -799,10 +805,10 @@ static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv, | |||
799 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); | 805 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); |
800 | 806 | ||
801 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; | 807 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; |
802 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) { | 808 | |
803 | /* Get bus clock from system */ | 809 | /* Get bus clock from system */ |
810 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) | ||
804 | busclk_freq = clk_get_rate(spdif_priv->sysclk); | 811 | busclk_freq = clk_get_rate(spdif_priv->sysclk); |
805 | } | ||
806 | 812 | ||
807 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ | 813 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ |
808 | tmpval64 = (u64) busclk_freq * freqmeas; | 814 | tmpval64 = (u64) busclk_freq * freqmeas; |
@@ -826,12 +832,12 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol, | |||
826 | { | 832 | { |
827 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | 833 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); |
828 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | 834 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); |
829 | int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); | 835 | int rate = 0; |
830 | 836 | ||
831 | if (spdif_priv->dpll_locked) | 837 | if (spdif_priv->dpll_locked) |
832 | ucontrol->value.integer.value[0] = rate; | 838 | rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); |
833 | else | 839 | |
834 | ucontrol->value.integer.value[0] = 0; | 840 | ucontrol->value.integer.value[0] = rate; |
835 | 841 | ||
836 | return 0; | 842 | return 0; |
837 | } | 843 | } |
@@ -969,12 +975,14 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) | |||
969 | static struct snd_soc_dai_driver fsl_spdif_dai = { | 975 | static struct snd_soc_dai_driver fsl_spdif_dai = { |
970 | .probe = &fsl_spdif_dai_probe, | 976 | .probe = &fsl_spdif_dai_probe, |
971 | .playback = { | 977 | .playback = { |
978 | .stream_name = "CPU-Playback", | ||
972 | .channels_min = 2, | 979 | .channels_min = 2, |
973 | .channels_max = 2, | 980 | .channels_max = 2, |
974 | .rates = FSL_SPDIF_RATES_PLAYBACK, | 981 | .rates = FSL_SPDIF_RATES_PLAYBACK, |
975 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, | 982 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, |
976 | }, | 983 | }, |
977 | .capture = { | 984 | .capture = { |
985 | .stream_name = "CPU-Capture", | ||
978 | .channels_min = 2, | 986 | .channels_min = 2, |
979 | .channels_max = 2, | 987 | .channels_max = 2, |
980 | .rates = FSL_SPDIF_RATES_CAPTURE, | 988 | .rates = FSL_SPDIF_RATES_CAPTURE, |
@@ -1046,7 +1054,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | |||
1046 | struct clk *clk, u64 savesub, | 1054 | struct clk *clk, u64 savesub, |
1047 | enum spdif_txrate index, bool round) | 1055 | enum spdif_txrate index, bool round) |
1048 | { | 1056 | { |
1049 | const u32 rate[] = { 32000, 44100, 48000 }; | 1057 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
1050 | bool is_sysclk = clk == spdif_priv->sysclk; | 1058 | bool is_sysclk = clk == spdif_priv->sysclk; |
1051 | u64 rate_ideal, rate_actual, sub; | 1059 | u64 rate_ideal, rate_actual, sub; |
1052 | u32 sysclk_dfmin, sysclk_dfmax; | 1060 | u32 sysclk_dfmin, sysclk_dfmax; |
@@ -1105,7 +1113,7 @@ out: | |||
1105 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, | 1113 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, |
1106 | enum spdif_txrate index) | 1114 | enum spdif_txrate index) |
1107 | { | 1115 | { |
1108 | const u32 rate[] = { 32000, 44100, 48000 }; | 1116 | const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; |
1109 | struct platform_device *pdev = spdif_priv->pdev; | 1117 | struct platform_device *pdev = spdif_priv->pdev; |
1110 | struct device *dev = &pdev->dev; | 1118 | struct device *dev = &pdev->dev; |
1111 | u64 savesub = 100000, ret; | 1119 | u64 savesub = 100000, ret; |
@@ -1238,12 +1246,12 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1238 | spin_lock_init(&ctrl->ctl_lock); | 1246 | spin_lock_init(&ctrl->ctl_lock); |
1239 | 1247 | ||
1240 | /* Init tx channel status default value */ | 1248 | /* Init tx channel status default value */ |
1241 | ctrl->ch_status[0] = | 1249 | ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT | |
1242 | IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015; | 1250 | IEC958_AES0_CON_EMPHASIS_5015; |
1243 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; | 1251 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; |
1244 | ctrl->ch_status[2] = 0x00; | 1252 | ctrl->ch_status[2] = 0x00; |
1245 | ctrl->ch_status[3] = | 1253 | ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 | |
1246 | IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM; | 1254 | IEC958_AES3_CON_CLOCK_1000PPM; |
1247 | 1255 | ||
1248 | spdif_priv->dpll_locked = false; | 1256 | spdif_priv->dpll_locked = false; |
1249 | 1257 | ||
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h index 16fde4b927d3..00bd3514c610 100644 --- a/sound/soc/fsl/fsl_spdif.h +++ b/sound/soc/fsl/fsl_spdif.h | |||
@@ -93,6 +93,8 @@ | |||
93 | #define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET) | 93 | #define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET) |
94 | #define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET) | 94 | #define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET) |
95 | 95 | ||
96 | #define SCR_DMA_xX_EN(tx) (tx ? SCR_DMA_TX_EN : SCR_DMA_RX_EN) | ||
97 | |||
96 | /* SPDIF CDText control */ | 98 | /* SPDIF CDText control */ |
97 | #define SRCD_CD_USER_OFFSET 1 | 99 | #define SRCD_CD_USER_OFFSET 1 |
98 | #define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET) | 100 | #define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET) |
@@ -164,8 +166,10 @@ enum spdif_txrate { | |||
164 | SPDIF_TXRATE_32000 = 0, | 166 | SPDIF_TXRATE_32000 = 0, |
165 | SPDIF_TXRATE_44100, | 167 | SPDIF_TXRATE_44100, |
166 | SPDIF_TXRATE_48000, | 168 | SPDIF_TXRATE_48000, |
169 | SPDIF_TXRATE_96000, | ||
170 | SPDIF_TXRATE_192000, | ||
167 | }; | 171 | }; |
168 | #define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1) | 172 | #define SPDIF_TXRATE_MAX (SPDIF_TXRATE_192000 + 1) |
169 | 173 | ||
170 | 174 | ||
171 | #define SPDIF_CSTATUS_BYTE 6 | 175 | #define SPDIF_CSTATUS_BYTE 6 |
@@ -175,7 +179,9 @@ enum spdif_txrate { | |||
175 | 179 | ||
176 | #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ | 180 | #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ |
177 | SNDRV_PCM_RATE_44100 | \ | 181 | SNDRV_PCM_RATE_44100 | \ |
178 | SNDRV_PCM_RATE_48000) | 182 | SNDRV_PCM_RATE_48000 | \ |
183 | SNDRV_PCM_RATE_96000 | \ | ||
184 | SNDRV_PCM_RATE_192000) | ||
179 | 185 | ||
180 | #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \ | 186 | #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \ |
181 | SNDRV_PCM_RATE_32000 | \ | 187 | SNDRV_PCM_RATE_32000 | \ |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 9bfef55d77d1..87eb5776a39b 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -590,8 +590,8 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, | |||
590 | else | 590 | else |
591 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); | 591 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); |
592 | 592 | ||
593 | do_div(clkrate, factor); | 593 | clkrate /= factor; |
594 | afreq = (u32)clkrate / (i + 1); | 594 | afreq = clkrate / (i + 1); |
595 | 595 | ||
596 | if (freq == afreq) | 596 | if (freq == afreq) |
597 | sub = 0; | 597 | sub = 0; |
@@ -1032,12 +1032,14 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | |||
1032 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | 1032 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { |
1033 | .probe = fsl_ssi_dai_probe, | 1033 | .probe = fsl_ssi_dai_probe, |
1034 | .playback = { | 1034 | .playback = { |
1035 | .stream_name = "CPU-Playback", | ||
1035 | .channels_min = 1, | 1036 | .channels_min = 1, |
1036 | .channels_max = 2, | 1037 | .channels_max = 2, |
1037 | .rates = FSLSSI_I2S_RATES, | 1038 | .rates = FSLSSI_I2S_RATES, |
1038 | .formats = FSLSSI_I2S_FORMATS, | 1039 | .formats = FSLSSI_I2S_FORMATS, |
1039 | }, | 1040 | }, |
1040 | .capture = { | 1041 | .capture = { |
1042 | .stream_name = "CPU-Capture", | ||
1041 | .channels_min = 1, | 1043 | .channels_min = 1, |
1042 | .channels_max = 2, | 1044 | .channels_max = 2, |
1043 | .rates = FSLSSI_I2S_RATES, | 1045 | .rates = FSLSSI_I2S_RATES, |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 267717aa96c1..46f9beb6b273 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -67,7 +67,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, | |||
67 | { | 67 | { |
68 | ssize_t ret; | 68 | ssize_t ret; |
69 | char *buf; | 69 | char *buf; |
70 | int port = (int)file->private_data; | 70 | uintptr_t port = (uintptr_t)file->private_data; |
71 | u32 pdcr, ptcr; | 71 | u32 pdcr, ptcr; |
72 | 72 | ||
73 | if (audmux_clk) { | 73 | if (audmux_clk) { |
@@ -147,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = { | |||
147 | 147 | ||
148 | static void audmux_debugfs_init(void) | 148 | static void audmux_debugfs_init(void) |
149 | { | 149 | { |
150 | int i; | 150 | uintptr_t i; |
151 | char buf[20]; | 151 | char buf[20]; |
152 | 152 | ||
153 | audmux_debugfs_root = debugfs_create_dir("audmux", NULL); | 153 | audmux_debugfs_root = debugfs_create_dir("audmux", NULL); |
@@ -157,10 +157,10 @@ static void audmux_debugfs_init(void) | |||
157 | } | 157 | } |
158 | 158 | ||
159 | for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { | 159 | for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { |
160 | snprintf(buf, sizeof(buf), "ssi%d", i); | 160 | snprintf(buf, sizeof(buf), "ssi%lu", i); |
161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, | 161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, |
162 | (void *)i, &audmux_debugfs_fops)) | 162 | (void *)i, &audmux_debugfs_fops)) |
163 | pr_warning("Failed to create AUDMUX port %d debugfs file\n", | 163 | pr_warning("Failed to create AUDMUX port %lu debugfs file\n", |
164 | i); | 164 | i); |
165 | } | 165 | } |
166 | } | 166 | } |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 03a7fdcdf114..159e517fa09a 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -116,6 +116,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
116 | { | 116 | { |
117 | struct device_node *node; | 117 | struct device_node *node; |
118 | struct clk *clk; | 118 | struct clk *clk; |
119 | u32 val; | ||
119 | int ret; | 120 | int ret; |
120 | 121 | ||
121 | /* | 122 | /* |
@@ -151,10 +152,8 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
151 | } | 152 | } |
152 | 153 | ||
153 | dai->sysclk = clk_get_rate(clk); | 154 | dai->sysclk = clk_get_rate(clk); |
154 | } else if (of_property_read_bool(np, "system-clock-frequency")) { | 155 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
155 | of_property_read_u32(np, | 156 | dai->sysclk = val; |
156 | "system-clock-frequency", | ||
157 | &dai->sysclk); | ||
158 | } else { | 157 | } else { |
159 | clk = of_clk_get(node, 0); | 158 | clk = of_clk_get(node, 0); |
160 | if (!IS_ERR(clk)) | 159 | if (!IS_ERR(clk)) |
@@ -303,6 +302,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
303 | { | 302 | { |
304 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 303 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; |
305 | struct simple_dai_props *dai_props = priv->dai_props; | 304 | struct simple_dai_props *dai_props = priv->dai_props; |
305 | u32 val; | ||
306 | int ret; | 306 | int ret; |
307 | 307 | ||
308 | /* parsing the card name from DT */ | 308 | /* parsing the card name from DT */ |
@@ -325,8 +325,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
325 | } | 325 | } |
326 | 326 | ||
327 | /* Factor to mclk, used in hw_params() */ | 327 | /* Factor to mclk, used in hw_params() */ |
328 | of_property_read_u32(node, "simple-audio-card,mclk-fs", | 328 | ret = of_property_read_u32(node, "simple-audio-card,mclk-fs", &val); |
329 | &priv->mclk_fs); | 329 | if (ret == 0) |
330 | priv->mclk_fs = val; | ||
330 | 331 | ||
331 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? | 332 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? |
332 | priv->snd_card.name : ""); | 333 | priv->snd_card.name : ""); |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index c30fedb3e149..f5b4a9c79cdf 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
58 | help | 58 | help |
59 | This adds audio driver for Intel Baytrail platform based boards | 59 | This adds audio driver for Intel Baytrail platform based boards |
60 | with the MAX98090 audio codec. | 60 | with the MAX98090 audio codec. |
61 | |||
62 | config SND_SOC_INTEL_BROADWELL_MACH | ||
63 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | ||
64 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC | ||
65 | select SND_SOC_INTEL_HASWELL | ||
66 | select SND_COMPRESS_OFFLOAD | ||
67 | select SND_SOC_RT286 | ||
68 | help | ||
69 | This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell | ||
70 | Ultrabook platforms. | ||
71 | Say Y if you have such a device | ||
72 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 4bfca79a42ba..7acbfc43a0c6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o | |||
24 | snd-soc-sst-haswell-objs := haswell.o | 24 | snd-soc-sst-haswell-objs := haswell.o |
25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o | 25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o |
26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | 26 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o |
27 | snd-soc-sst-broadwell-objs := broadwell.o | ||
27 | 28 | ||
28 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 29 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
29 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
30 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | 31 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o |
32 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | ||
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c new file mode 100644 index 000000000000..0e550f14028f --- /dev/null +++ b/sound/soc/intel/broadwell.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Intel Broadwell Wildcatpoint SST Audio | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include "sst-dsp.h" | ||
25 | #include "sst-haswell-ipc.h" | ||
26 | |||
27 | #include "../codecs/rt286.h" | ||
28 | |||
29 | static const struct snd_soc_dapm_widget broadwell_widgets[] = { | ||
30 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
31 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
32 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
33 | SND_SOC_DAPM_MIC("DMIC1", NULL), | ||
34 | SND_SOC_DAPM_MIC("DMIC2", NULL), | ||
35 | SND_SOC_DAPM_LINE("Line Jack", NULL), | ||
36 | }; | ||
37 | |||
38 | static const struct snd_soc_dapm_route broadwell_rt286_map[] = { | ||
39 | |||
40 | /* speaker */ | ||
41 | {"Speaker", NULL, "SPOR"}, | ||
42 | {"Speaker", NULL, "SPOL"}, | ||
43 | |||
44 | /* HP jack connectors - unknown if we have jack deteck */ | ||
45 | {"Headphones", NULL, "HPO Pin"}, | ||
46 | |||
47 | /* other jacks */ | ||
48 | {"MIC1", NULL, "Mic Jack"}, | ||
49 | {"LINE1", NULL, "Line Jack"}, | ||
50 | |||
51 | /* digital mics */ | ||
52 | {"DMIC1 Pin", NULL, "DMIC1"}, | ||
53 | {"DMIC2 Pin", NULL, "DMIC2"}, | ||
54 | |||
55 | /* CODEC BE connections */ | ||
56 | {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, | ||
57 | {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, | ||
58 | }; | ||
59 | |||
60 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
61 | struct snd_pcm_hw_params *params) | ||
62 | { | ||
63 | struct snd_interval *rate = hw_param_interval(params, | ||
64 | SNDRV_PCM_HW_PARAM_RATE); | ||
65 | struct snd_interval *channels = hw_param_interval(params, | ||
66 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
67 | |||
68 | /* The ADSP will covert the FE rate to 48k, stereo */ | ||
69 | rate->min = rate->max = 48000; | ||
70 | channels->min = channels->max = 2; | ||
71 | |||
72 | /* set SSP0 to 16 bit */ | ||
73 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
74 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
75 | SNDRV_PCM_FORMAT_S16_LE); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, | ||
80 | struct snd_pcm_hw_params *params) | ||
81 | { | ||
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
83 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
84 | int ret; | ||
85 | |||
86 | ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, | ||
87 | SND_SOC_CLOCK_IN); | ||
88 | |||
89 | if (ret < 0) { | ||
90 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static struct snd_soc_ops broadwell_rt286_ops = { | ||
98 | .hw_params = broadwell_rt286_hw_params, | ||
99 | }; | ||
100 | |||
101 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | ||
102 | { | ||
103 | struct snd_soc_codec *codec = rtd->codec; | ||
104 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
105 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | ||
106 | struct sst_hsw *broadwell = pdata->dsp; | ||
107 | int ret; | ||
108 | |||
109 | /* Set ADSP SSP port settings */ | ||
110 | ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, | ||
111 | SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, | ||
112 | SST_HSW_DEVICE_CLOCK_MASTER, 9); | ||
113 | if (ret < 0) { | ||
114 | dev_err(rtd->dev, "error: failed to set device config\n"); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* always connected - check HP for jack detect */ | ||
119 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
120 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
121 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
122 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | ||
123 | snd_soc_dapm_enable_pin(dapm, "DMIC1"); | ||
124 | snd_soc_dapm_enable_pin(dapm, "DMIC2"); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* broadwell digital audio interface glue - connects codec <--> CPU */ | ||
130 | static struct snd_soc_dai_link broadwell_rt286_dais[] = { | ||
131 | /* Front End DAI links */ | ||
132 | { | ||
133 | .name = "System PCM", | ||
134 | .stream_name = "System Playback", | ||
135 | .cpu_dai_name = "System Pin", | ||
136 | .platform_name = "haswell-pcm-audio", | ||
137 | .dynamic = 1, | ||
138 | .codec_name = "snd-soc-dummy", | ||
139 | .codec_dai_name = "snd-soc-dummy-dai", | ||
140 | .init = broadwell_rtd_init, | ||
141 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
142 | .dpcm_playback = 1, | ||
143 | }, | ||
144 | { | ||
145 | .name = "Offload0", | ||
146 | .stream_name = "Offload0 Playback", | ||
147 | .cpu_dai_name = "Offload0 Pin", | ||
148 | .platform_name = "haswell-pcm-audio", | ||
149 | .dynamic = 1, | ||
150 | .codec_name = "snd-soc-dummy", | ||
151 | .codec_dai_name = "snd-soc-dummy-dai", | ||
152 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
153 | .dpcm_playback = 1, | ||
154 | }, | ||
155 | { | ||
156 | .name = "Offload1", | ||
157 | .stream_name = "Offload1 Playback", | ||
158 | .cpu_dai_name = "Offload1 Pin", | ||
159 | .platform_name = "haswell-pcm-audio", | ||
160 | .dynamic = 1, | ||
161 | .codec_name = "snd-soc-dummy", | ||
162 | .codec_dai_name = "snd-soc-dummy-dai", | ||
163 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
164 | .dpcm_playback = 1, | ||
165 | }, | ||
166 | { | ||
167 | .name = "Loopback PCM", | ||
168 | .stream_name = "Loopback", | ||
169 | .cpu_dai_name = "Loopback Pin", | ||
170 | .platform_name = "haswell-pcm-audio", | ||
171 | .dynamic = 0, | ||
172 | .codec_name = "snd-soc-dummy", | ||
173 | .codec_dai_name = "snd-soc-dummy-dai", | ||
174 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
175 | .dpcm_capture = 1, | ||
176 | }, | ||
177 | { | ||
178 | .name = "Capture PCM", | ||
179 | .stream_name = "Capture", | ||
180 | .cpu_dai_name = "Capture Pin", | ||
181 | .platform_name = "haswell-pcm-audio", | ||
182 | .dynamic = 1, | ||
183 | .codec_name = "snd-soc-dummy", | ||
184 | .codec_dai_name = "snd-soc-dummy-dai", | ||
185 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
186 | .dpcm_capture = 1, | ||
187 | }, | ||
188 | |||
189 | /* Back End DAI links */ | ||
190 | { | ||
191 | /* SSP0 - Codec */ | ||
192 | .name = "Codec", | ||
193 | .be_id = 0, | ||
194 | .cpu_dai_name = "snd-soc-dummy-dai", | ||
195 | .platform_name = "snd-soc-dummy", | ||
196 | .no_pcm = 1, | ||
197 | .codec_name = "i2c-INT343A:00", | ||
198 | .codec_dai_name = "rt286-aif1", | ||
199 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
200 | SND_SOC_DAIFMT_CBS_CFS, | ||
201 | .ignore_suspend = 1, | ||
202 | .ignore_pmdown_time = 1, | ||
203 | .be_hw_params_fixup = broadwell_ssp0_fixup, | ||
204 | .ops = &broadwell_rt286_ops, | ||
205 | .dpcm_playback = 1, | ||
206 | .dpcm_capture = 1, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | /* broadwell audio machine driver for WPT + RT286S */ | ||
211 | static struct snd_soc_card broadwell_rt286 = { | ||
212 | .name = "broadwell-rt286", | ||
213 | .owner = THIS_MODULE, | ||
214 | .dai_link = broadwell_rt286_dais, | ||
215 | .num_links = ARRAY_SIZE(broadwell_rt286_dais), | ||
216 | .dapm_widgets = broadwell_widgets, | ||
217 | .num_dapm_widgets = ARRAY_SIZE(broadwell_widgets), | ||
218 | .dapm_routes = broadwell_rt286_map, | ||
219 | .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map), | ||
220 | .fully_routed = true, | ||
221 | }; | ||
222 | |||
223 | static int broadwell_audio_probe(struct platform_device *pdev) | ||
224 | { | ||
225 | broadwell_rt286.dev = &pdev->dev; | ||
226 | |||
227 | return snd_soc_register_card(&broadwell_rt286); | ||
228 | } | ||
229 | |||
230 | static int broadwell_audio_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | snd_soc_unregister_card(&broadwell_rt286); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct platform_driver broadwell_audio = { | ||
237 | .probe = broadwell_audio_probe, | ||
238 | .remove = broadwell_audio_remove, | ||
239 | .driver = { | ||
240 | .name = "broadwell-audio", | ||
241 | .owner = THIS_MODULE, | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | module_platform_driver(broadwell_audio) | ||
246 | |||
247 | /* Module information */ | ||
248 | MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); | ||
249 | MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell"); | ||
250 | MODULE_LICENSE("GPL v2"); | ||
251 | MODULE_ALIAS("platform:broadwell-audio"); | ||
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 5fc98c64a3f4..b8b8af571ef1 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c | |||
@@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { | |||
39 | 39 | ||
40 | static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { | 40 | static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { |
41 | {"IN34", NULL, "Headset Mic"}, | 41 | {"IN34", NULL, "Headset Mic"}, |
42 | {"IN34", NULL, "MICBIAS"}, | 42 | {"Headset Mic", NULL, "MICBIAS"}, |
43 | {"MICBIAS", NULL, "Headset Mic"}, | ||
44 | {"DMICL", NULL, "Int Mic"}, | 43 | {"DMICL", NULL, "Int Mic"}, |
45 | {"Headphone", NULL, "HPL"}, | 44 | {"Headphone", NULL, "HPL"}, |
46 | {"Headphone", NULL, "HPR"}, | 45 | {"Headphone", NULL, "HPR"}, |
@@ -64,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
64 | .pin = "Headset Mic", | 63 | .pin = "Headset Mic", |
65 | .mask = SND_JACK_MICROPHONE, | 64 | .mask = SND_JACK_MICROPHONE, |
66 | }, | 65 | }, |
67 | { | ||
68 | .pin = "Ext Spk", | ||
69 | .mask = SND_JACK_LINEOUT, | ||
70 | }, | ||
71 | { | ||
72 | .pin = "Int Mic", | ||
73 | .mask = SND_JACK_LINEIN, | ||
74 | }, | ||
75 | }; | 66 | }; |
76 | 67 | ||
77 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
@@ -84,7 +75,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { | |||
84 | { | 75 | { |
85 | .name = "mic-gpio", | 76 | .name = "mic-gpio", |
86 | .idx = 1, | 77 | .idx = 1, |
87 | .report = SND_JACK_MICROPHONE | SND_JACK_LINEIN, | 78 | .invert = 1, |
79 | .report = SND_JACK_MICROPHONE, | ||
88 | .debounce_time = 200, | 80 | .debounce_time = 200, |
89 | }, | 81 | }, |
90 | }; | 82 | }; |
@@ -108,7 +100,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
108 | } | 100 | } |
109 | 101 | ||
110 | /* Enable jack detection */ | 102 | /* Enable jack detection */ |
111 | ret = snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, jack); | 103 | ret = snd_soc_jack_new(codec, "Headset", |
104 | SND_JACK_LINEOUT | SND_JACK_HEADSET, jack); | ||
112 | if (ret) | 105 | if (ret) |
113 | return ret; | 106 | return ret; |
114 | 107 | ||
@@ -117,13 +110,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
117 | if (ret) | 110 | if (ret) |
118 | return ret; | 111 | return ret; |
119 | 112 | ||
120 | ret = snd_soc_jack_add_gpiods(card->dev->parent, jack, | 113 | return snd_soc_jack_add_gpiods(card->dev->parent, jack, |
121 | ARRAY_SIZE(hs_jack_gpios), | 114 | ARRAY_SIZE(hs_jack_gpios), |
122 | hs_jack_gpios); | 115 | hs_jack_gpios); |
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
126 | return max98090_mic_detect(codec, jack); | ||
127 | } | 116 | } |
128 | 117 | ||
129 | static struct snd_soc_dai_link byt_max98090_dais[] = { | 118 | static struct snd_soc_dai_link byt_max98090_dais[] = { |
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 53d160d39972..234a58de3c53 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | 36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { |
37 | {"Headset Mic", NULL, "MICBIAS1"}, | ||
37 | {"IN2P", NULL, "Headset Mic"}, | 38 | {"IN2P", NULL, "Headset Mic"}, |
38 | {"IN2N", NULL, "Headset Mic"}, | 39 | {"IN2N", NULL, "Headset Mic"}, |
39 | {"DMIC1", NULL, "Internal Mic"}, | 40 | {"DMIC1", NULL, "Internal Mic"}, |
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h new file mode 100644 index 000000000000..14063ab8c7c5 --- /dev/null +++ b/sound/soc/intel/sst-atom-controls.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013-14 Intel Corp | ||
3 | * Author: Ramesh Babu <ramesh.babu.koul@intel.com> | ||
4 | * Omair M Abdullah <omair.m.abdullah@intel.com> | ||
5 | * Samreen Nilofer <samreen.nilofer@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef __SST_CONTROLS_V2_H__ | ||
22 | #define __SST_CONTROLS_V2_H__ | ||
23 | |||
24 | enum { | ||
25 | MERR_DPCM_AUDIO = 0, | ||
26 | MERR_DPCM_COMPR, | ||
27 | }; | ||
28 | |||
29 | |||
30 | #endif | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index d207b22ea330..67673a2c0f41 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c | |||
@@ -122,6 +122,26 @@ struct sst_byt_tstamp { | |||
122 | u32 channel_peak[8]; | 122 | u32 channel_peak[8]; |
123 | } __packed; | 123 | } __packed; |
124 | 124 | ||
125 | struct sst_byt_fw_version { | ||
126 | u8 build; | ||
127 | u8 minor; | ||
128 | u8 major; | ||
129 | u8 type; | ||
130 | } __packed; | ||
131 | |||
132 | struct sst_byt_fw_build_info { | ||
133 | u8 date[16]; | ||
134 | u8 time[16]; | ||
135 | } __packed; | ||
136 | |||
137 | struct sst_byt_fw_init { | ||
138 | struct sst_byt_fw_version fw_version; | ||
139 | struct sst_byt_fw_build_info build_info; | ||
140 | u16 result; | ||
141 | u8 module_id; | ||
142 | u8 debug_info; | ||
143 | } __packed; | ||
144 | |||
125 | /* driver internal IPC message structure */ | 145 | /* driver internal IPC message structure */ |
126 | struct ipc_message { | 146 | struct ipc_message { |
127 | struct list_head list; | 147 | struct list_head list; |
@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
868 | { | 888 | { |
869 | struct sst_byt *byt; | 889 | struct sst_byt *byt; |
870 | struct sst_fw *byt_sst_fw; | 890 | struct sst_fw *byt_sst_fw; |
891 | struct sst_byt_fw_init init; | ||
871 | int err; | 892 | int err; |
872 | 893 | ||
873 | dev_dbg(dev, "initialising Byt DSP IPC\n"); | 894 | dev_dbg(dev, "initialising Byt DSP IPC\n"); |
@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
929 | goto boot_err; | 950 | goto boot_err; |
930 | } | 951 | } |
931 | 952 | ||
953 | /* show firmware information */ | ||
954 | sst_dsp_inbox_read(byt->dsp, &init, sizeof(init)); | ||
955 | dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n", | ||
956 | init.fw_version.major, init.fw_version.minor, | ||
957 | init.fw_version.build, init.fw_version.type); | ||
958 | dev_info(byt->dev, "Build type: %x\n", init.fw_version.type); | ||
959 | dev_info(byt->dev, "Build date: %s %s\n", | ||
960 | init.build_info.date, init.build_info.time); | ||
961 | |||
932 | pdata->dsp = byt; | 962 | pdata->dsp = byt; |
933 | byt->fw = byt_sst_fw; | 963 | byt->fw = byt_sst_fw; |
934 | 964 | ||
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 8eab97368ea7..599401c0c655 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = { | |||
32 | SNDRV_PCM_INFO_PAUSE | | 32 | SNDRV_PCM_INFO_PAUSE | |
33 | SNDRV_PCM_INFO_RESUME, | 33 | SNDRV_PCM_INFO_RESUME, |
34 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 34 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
35 | SNDRV_PCM_FORMAT_S24_LE, | 35 | SNDRV_PCM_FMTBIT_S24_LE, |
36 | .period_bytes_min = 384, | 36 | .period_bytes_min = 384, |
37 | .period_bytes_max = 48000, | 37 | .period_bytes_max = 48000, |
38 | .periods_min = 2, | 38 | .periods_min = 2, |
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 0b715b20a2d7..cd23060a0d86 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); | |||
224 | 224 | ||
225 | void sst_dsp_dump(struct sst_dsp *sst) | 225 | void sst_dsp_dump(struct sst_dsp *sst) |
226 | { | 226 | { |
227 | sst->ops->dump(sst); | 227 | if (sst->ops->dump) |
228 | sst->ops->dump(sst); | ||
228 | } | 229 | } |
229 | EXPORT_SYMBOL_GPL(sst_dsp_dump); | 230 | EXPORT_SYMBOL_GPL(sst_dsp_dump); |
230 | 231 | ||
231 | void sst_dsp_reset(struct sst_dsp *sst) | 232 | void sst_dsp_reset(struct sst_dsp *sst) |
232 | { | 233 | { |
233 | sst->ops->reset(sst); | 234 | if (sst->ops->reset) |
235 | sst->ops->reset(sst); | ||
234 | } | 236 | } |
235 | EXPORT_SYMBOL_GPL(sst_dsp_reset); | 237 | EXPORT_SYMBOL_GPL(sst_dsp_reset); |
236 | 238 | ||
237 | int sst_dsp_boot(struct sst_dsp *sst) | 239 | int sst_dsp_boot(struct sst_dsp *sst) |
238 | { | 240 | { |
239 | sst->ops->boot(sst); | 241 | if (sst->ops->boot) |
242 | sst->ops->boot(sst); | ||
243 | |||
240 | return 0; | 244 | return 0; |
241 | } | 245 | } |
242 | EXPORT_SYMBOL_GPL(sst_dsp_boot); | 246 | EXPORT_SYMBOL_GPL(sst_dsp_boot); |
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index e44423be66c4..3165dfa97408 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h | |||
@@ -52,7 +52,11 @@ | |||
52 | #define SST_CLKCTL 0x78 | 52 | #define SST_CLKCTL 0x78 |
53 | #define SST_CSR2 0x80 | 53 | #define SST_CSR2 0x80 |
54 | #define SST_LTRC 0xE0 | 54 | #define SST_LTRC 0xE0 |
55 | #define SST_HDMC 0xE8 | 55 | #define SST_HMDC 0xE8 |
56 | |||
57 | #define SST_SHIM_BEGIN SST_CSR | ||
58 | #define SST_SHIM_END SST_HDMC | ||
59 | |||
56 | #define SST_DBGO 0xF0 | 60 | #define SST_DBGO 0xF0 |
57 | 61 | ||
58 | #define SST_SHIM_SIZE 0x100 | 62 | #define SST_SHIM_SIZE 0x100 |
@@ -73,6 +77,8 @@ | |||
73 | #define SST_CSR_S0IOCS (0x1 << 21) | 77 | #define SST_CSR_S0IOCS (0x1 << 21) |
74 | #define SST_CSR_S1IOCS (0x1 << 23) | 78 | #define SST_CSR_S1IOCS (0x1 << 23) |
75 | #define SST_CSR_LPCS (0x1 << 31) | 79 | #define SST_CSR_LPCS (0x1 << 31) |
80 | #define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS) | ||
81 | #define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1) | ||
76 | #define SST_BYT_CSR_RST (0x1 << 0) | 82 | #define SST_BYT_CSR_RST (0x1 << 0) |
77 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) | 83 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) |
78 | #define SST_BYT_CSR_STALL (0x1 << 2) | 84 | #define SST_BYT_CSR_STALL (0x1 << 2) |
@@ -92,6 +98,14 @@ | |||
92 | #define SST_IMRX_DONE (0x1 << 0) | 98 | #define SST_IMRX_DONE (0x1 << 0) |
93 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) | 99 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) |
94 | 100 | ||
101 | /* IMRD / IMD */ | ||
102 | #define SST_IMRD_DONE (0x1 << 0) | ||
103 | #define SST_IMRD_BUSY (0x1 << 1) | ||
104 | #define SST_IMRD_SSP0 (0x1 << 16) | ||
105 | #define SST_IMRD_DMAC0 (0x1 << 21) | ||
106 | #define SST_IMRD_DMAC1 (0x1 << 22) | ||
107 | #define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1) | ||
108 | |||
95 | /* IPCX / IPCC */ | 109 | /* IPCX / IPCC */ |
96 | #define SST_IPCX_DONE (0x1 << 30) | 110 | #define SST_IPCX_DONE (0x1 << 30) |
97 | #define SST_IPCX_BUSY (0x1 << 31) | 111 | #define SST_IPCX_BUSY (0x1 << 31) |
@@ -118,9 +132,21 @@ | |||
118 | /* LTRC */ | 132 | /* LTRC */ |
119 | #define SST_LTRC_VAL(x) (x << 0) | 133 | #define SST_LTRC_VAL(x) (x << 0) |
120 | 134 | ||
121 | /* HDMC */ | 135 | /* HMDC */ |
122 | #define SST_HDMC_HDDA0(x) (x << 0) | 136 | #define SST_HMDC_HDDA0(x) (x << 0) |
123 | #define SST_HDMC_HDDA1(x) (x << 7) | 137 | #define SST_HMDC_HDDA1(x) (x << 7) |
138 | #define SST_HMDC_HDDA_E0_CH0 1 | ||
139 | #define SST_HMDC_HDDA_E0_CH1 2 | ||
140 | #define SST_HMDC_HDDA_E0_CH2 4 | ||
141 | #define SST_HMDC_HDDA_E0_CH3 8 | ||
142 | #define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0) | ||
143 | #define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1) | ||
144 | #define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2) | ||
145 | #define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3) | ||
146 | #define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \ | ||
147 | SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3) | ||
148 | #define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \ | ||
149 | SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3) | ||
124 | 150 | ||
125 | 151 | ||
126 | /* SST Vendor Defined Registers and bits */ | 152 | /* SST Vendor Defined Registers and bits */ |
@@ -130,11 +156,16 @@ | |||
130 | #define SST_VDRTCTL3 0xaC | 156 | #define SST_VDRTCTL3 0xaC |
131 | 157 | ||
132 | /* VDRTCTL0 */ | 158 | /* VDRTCTL0 */ |
159 | #define SST_VDRTCL0_APLLSE_MASK 1 | ||
133 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 | 160 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 |
134 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) | 161 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) |
135 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 | 162 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 |
136 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) | 163 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) |
137 | 164 | ||
165 | /* PMCS */ | ||
166 | #define SST_PMCS 0x84 | ||
167 | #define SST_PMCS_PS_MASK 0x3 | ||
168 | |||
138 | struct sst_dsp; | 169 | struct sst_dsp; |
139 | 170 | ||
140 | /* | 171 | /* |
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 535f517629fd..4b6c163c10ff 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -28,9 +28,6 @@ | |||
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
30 | 30 | ||
31 | #include <linux/acpi.h> | ||
32 | #include <acpi/acpi_bus.h> | ||
33 | |||
34 | #include "sst-dsp.h" | 31 | #include "sst-dsp.h" |
35 | #include "sst-dsp-priv.h" | 32 | #include "sst-dsp-priv.h" |
36 | #include "sst-haswell-ipc.h" | 33 | #include "sst-haswell-ipc.h" |
@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst) | |||
272 | SST_CSR2_SDFD_SSP1); | 269 | SST_CSR2_SDFD_SSP1); |
273 | 270 | ||
274 | /* enable DMA engine 0,1 all channels to access host memory */ | 271 | /* enable DMA engine 0,1 all channels to access host memory */ |
275 | sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, | 272 | sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC, |
276 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), | 273 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff), |
277 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); | 274 | SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff)); |
278 | 275 | ||
279 | /* disable all clock gating */ | 276 | /* disable all clock gating */ |
280 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); | 277 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); |
@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = { | |||
313 | 310 | ||
314 | /* wild cat point ADSP mem regions */ | 311 | /* wild cat point ADSP mem regions */ |
315 | static const struct sst_adsp_memregion wpt_region[] = { | 312 | static const struct sst_adsp_memregion wpt_region[] = { |
316 | {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | 313 | {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */ |
317 | {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ | ||
318 | {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ | ||
319 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ | 314 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ |
320 | }; | 315 | }; |
321 | 316 | ||
@@ -339,26 +334,56 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
339 | return 0; | 334 | return 0; |
340 | } | 335 | } |
341 | 336 | ||
337 | struct sst_sram_shift { | ||
338 | u32 dev_id; /* SST Device IDs */ | ||
339 | u32 iram_shift; | ||
340 | u32 dram_shift; | ||
341 | }; | ||
342 | |||
343 | static const struct sst_sram_shift sram_shift[] = { | ||
344 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ | ||
345 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ | ||
346 | }; | ||
342 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | 347 | static u32 hsw_block_get_bit(struct sst_mem_block *block) |
343 | { | 348 | { |
344 | u32 bit = 0, shift = 0; | 349 | u32 bit = 0, shift = 0, index; |
350 | struct sst_dsp *sst = block->dsp; | ||
345 | 351 | ||
346 | switch (block->type) { | 352 | for (index = 0; index < ARRAY_SIZE(sram_shift); index++) { |
347 | case SST_MEM_DRAM: | 353 | if (sram_shift[index].dev_id == sst->id) |
348 | shift = 16; | 354 | break; |
349 | break; | ||
350 | case SST_MEM_IRAM: | ||
351 | shift = 6; | ||
352 | break; | ||
353 | default: | ||
354 | return 0; | ||
355 | } | 355 | } |
356 | 356 | ||
357 | if (index < ARRAY_SIZE(sram_shift)) { | ||
358 | switch (block->type) { | ||
359 | case SST_MEM_DRAM: | ||
360 | shift = sram_shift[index].dram_shift; | ||
361 | break; | ||
362 | case SST_MEM_IRAM: | ||
363 | shift = sram_shift[index].iram_shift; | ||
364 | break; | ||
365 | default: | ||
366 | shift = 0; | ||
367 | } | ||
368 | } else | ||
369 | shift = 0; | ||
370 | |||
357 | bit = 1 << (block->index + shift); | 371 | bit = 1 << (block->index + shift); |
358 | 372 | ||
359 | return bit; | 373 | return bit; |
360 | } | 374 | } |
361 | 375 | ||
376 | /*dummy read a SRAM block.*/ | ||
377 | static void sst_mem_block_dummy_read(struct sst_mem_block *block) | ||
378 | { | ||
379 | u32 size; | ||
380 | u8 tmp_buf[4]; | ||
381 | struct sst_dsp *sst = block->dsp; | ||
382 | |||
383 | size = block->size > 4 ? 4 : block->size; | ||
384 | memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size); | ||
385 | } | ||
386 | |||
362 | /* enable 32kB memory block - locks held by caller */ | 387 | /* enable 32kB memory block - locks held by caller */ |
363 | static int hsw_block_enable(struct sst_mem_block *block) | 388 | static int hsw_block_enable(struct sst_mem_block *block) |
364 | { | 389 | { |
@@ -378,6 +403,8 @@ static int hsw_block_enable(struct sst_mem_block *block) | |||
378 | /* wait 18 DSP clock ticks */ | 403 | /* wait 18 DSP clock ticks */ |
379 | udelay(10); | 404 | udelay(10); |
380 | 405 | ||
406 | /*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/ | ||
407 | sst_mem_block_dummy_read(block); | ||
381 | return 0; | 408 | return 0; |
382 | } | 409 | } |
383 | 410 | ||
@@ -488,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
488 | } | 515 | } |
489 | } | 516 | } |
490 | 517 | ||
491 | /* set default power gating mask */ | 518 | /* set default power gating control, enable power gating control for all blocks. that is, |
492 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); | 519 | can't be accessed, please enable each block before accessing. */ |
520 | writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
493 | 521 | ||
494 | return 0; | 522 | return 0; |
495 | } | 523 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 434236343ddf..b6291516dbbf 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready { | |||
183 | u32 inbox_size; | 183 | u32 inbox_size; |
184 | u32 outbox_size; | 184 | u32 outbox_size; |
185 | u32 fw_info_size; | 185 | u32 fw_info_size; |
186 | u8 fw_info[1]; | 186 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; |
187 | } __attribute__((packed)); | 187 | } __attribute__((packed)); |
188 | 188 | ||
189 | struct ipc_message { | 189 | struct ipc_message { |
@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work) | |||
457 | return; | 457 | return; |
458 | } | 458 | } |
459 | 459 | ||
460 | /* if the DSP is busy we will TX messages after IRQ */ | 460 | /* if the DSP is busy, we will TX messages after IRQ. |
461 | * also postpone if we are in the middle of procesing completion irq*/ | ||
461 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); | 462 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); |
462 | if (ipcx & SST_IPCX_BUSY) { | 463 | if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) { |
463 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | 464 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); |
464 | return; | 465 | return; |
465 | } | 466 | } |
@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, | |||
502 | ipc_shim_dbg(hsw, "message timeout"); | 503 | ipc_shim_dbg(hsw, "message timeout"); |
503 | 504 | ||
504 | trace_ipc_error("error message timeout for", msg->header); | 505 | trace_ipc_error("error message timeout for", msg->header); |
506 | list_del(&msg->list); | ||
505 | ret = -ETIMEDOUT; | 507 | ret = -ETIMEDOUT; |
506 | } else { | 508 | } else { |
507 | 509 | ||
@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
569 | { | 571 | { |
570 | struct sst_hsw_ipc_fw_ready fw_ready; | 572 | struct sst_hsw_ipc_fw_ready fw_ready; |
571 | u32 offset; | 573 | u32 offset; |
574 | u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; | ||
575 | char *tmp[5], *pinfo; | ||
576 | int i = 0; | ||
572 | 577 | ||
573 | offset = (header & 0x1FFFFFFF) << 3; | 578 | offset = (header & 0x1FFFFFFF) << 3; |
574 | 579 | ||
@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | |||
589 | fw_ready.inbox_offset, fw_ready.inbox_size); | 594 | fw_ready.inbox_offset, fw_ready.inbox_size); |
590 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", | 595 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", |
591 | fw_ready.outbox_offset, fw_ready.outbox_size); | 596 | fw_ready.outbox_offset, fw_ready.outbox_size); |
597 | if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) { | ||
598 | fw_ready.fw_info[fw_ready.fw_info_size] = 0; | ||
599 | dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info); | ||
600 | |||
601 | /* log the FW version info got from the mailbox here. */ | ||
602 | memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size); | ||
603 | pinfo = &fw_info[0]; | ||
604 | for (i = 0; i < sizeof(tmp) / sizeof(char *); i++) | ||
605 | tmp[i] = strsep(&pinfo, " "); | ||
606 | dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - " | ||
607 | "version: %s.%s, build %s, source commit id: %s\n", | ||
608 | tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); | ||
609 | } | ||
592 | } | 610 | } |
593 | 611 | ||
594 | static void hsw_notification_work(struct work_struct *work) | 612 | static void hsw_notification_work(struct work_struct *work) |
@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) | |||
671 | switch (stream_msg) { | 689 | switch (stream_msg) { |
672 | case IPC_STR_STAGE_MESSAGE: | 690 | case IPC_STR_STAGE_MESSAGE: |
673 | case IPC_STR_NOTIFICATION: | 691 | case IPC_STR_NOTIFICATION: |
692 | break; | ||
674 | case IPC_STR_RESET: | 693 | case IPC_STR_RESET: |
694 | trace_ipc_notification("stream reset", stream->reply.stream_hw_id); | ||
675 | break; | 695 | break; |
676 | case IPC_STR_PAUSE: | 696 | case IPC_STR_PAUSE: |
677 | stream->running = false; | 697 | stream->running = false; |
@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | |||
762 | } | 782 | } |
763 | 783 | ||
764 | /* update any stream states */ | 784 | /* update any stream states */ |
765 | hsw_stream_update(hsw, msg); | 785 | if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE) |
786 | hsw_stream_update(hsw, msg); | ||
766 | 787 | ||
767 | /* wake up and return the error if we have waiters on this message ? */ | 788 | /* wake up and return the error if we have waiters on this message ? */ |
768 | list_del(&msg->list); | 789 | list_del(&msg->list); |
@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1628 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) | 1649 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) |
1629 | { | 1650 | { |
1630 | u32 header, state_; | 1651 | u32 header, state_; |
1631 | int ret; | 1652 | int ret, item; |
1632 | 1653 | ||
1633 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | 1654 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); |
1634 | state_ = state; | 1655 | state_ = state; |
@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1642 | return ret; | 1663 | return ret; |
1643 | } | 1664 | } |
1644 | 1665 | ||
1666 | for (item = 0; item < dx->entries_no; item++) { | ||
1667 | dev_dbg(hsw->dev, | ||
1668 | "Item[%d] offset[%x] - size[%x] - source[%x]\n", | ||
1669 | item, dx->mem_info[item].offset, | ||
1670 | dx->mem_info[item].size, | ||
1671 | dx->mem_info[item].source); | ||
1672 | } | ||
1645 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", | 1673 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", |
1646 | dx->entries_no, state); | 1674 | dx->entries_no, state); |
1647 | 1675 | ||
@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | |||
1775 | 1803 | ||
1776 | /* get the FW version */ | 1804 | /* get the FW version */ |
1777 | sst_hsw_fw_get_version(hsw, &version); | 1805 | sst_hsw_fw_get_version(hsw, &version); |
1778 | dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", | ||
1779 | version.type, version.major, version.minor, version.build); | ||
1780 | 1806 | ||
1781 | /* get the globalmixer */ | 1807 | /* get the globalmixer */ |
1782 | ret = sst_hsw_mixer_get_info(hsw); | 1808 | ret = sst_hsw_mixer_get_info(hsw); |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 058efb17c568..61bf6da4bb02 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { | |||
80 | SNDRV_PCM_INFO_PAUSE | | 80 | SNDRV_PCM_INFO_PAUSE | |
81 | SNDRV_PCM_INFO_RESUME | | 81 | SNDRV_PCM_INFO_RESUME | |
82 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | 82 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
83 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | | 83 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
84 | SNDRV_PCM_FMTBIT_S32_LE, | 84 | SNDRV_PCM_FMTBIT_S32_LE, |
85 | .period_bytes_min = PAGE_SIZE, | 85 | .period_bytes_min = PAGE_SIZE, |
86 | .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, | 86 | .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, |
@@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
400 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); | 400 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); |
401 | break; | 401 | break; |
402 | case SNDRV_PCM_FORMAT_S24_LE: | 402 | case SNDRV_PCM_FORMAT_S24_LE: |
403 | bits = SST_HSW_DEPTH_24BIT; | 403 | bits = SST_HSW_DEPTH_32BIT; |
404 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 24); | ||
405 | break; | ||
406 | case SNDRV_PCM_FORMAT_S8: | ||
407 | bits = SST_HSW_DEPTH_8BIT; | ||
408 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 8); | ||
409 | break; | ||
410 | case SNDRV_PCM_FORMAT_S32_LE: | ||
411 | bits = SST_HSW_DEPTH_32BIT; | ||
404 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); | 412 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); |
405 | break; | 413 | break; |
406 | default: | 414 | default: |
@@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
685 | } | 693 | } |
686 | 694 | ||
687 | #define HSW_FORMATS \ | 695 | #define HSW_FORMATS \ |
688 | (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ | 696 | (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
689 | SNDRV_PCM_FMTBIT_S32_LE) | 697 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ |
698 | SNDRV_PCM_FMTBIT_S8) | ||
690 | 699 | ||
691 | static struct snd_soc_dai_driver hsw_dais[] = { | 700 | static struct snd_soc_dai_driver hsw_dais[] = { |
692 | { | 701 | { |
@@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
696 | .channels_min = 2, | 705 | .channels_min = 2, |
697 | .channels_max = 2, | 706 | .channels_max = 2, |
698 | .rates = SNDRV_PCM_RATE_48000, | 707 | .rates = SNDRV_PCM_RATE_48000, |
699 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 708 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
700 | }, | 709 | }, |
701 | }, | 710 | }, |
702 | { | 711 | { |
@@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
727 | .stream_name = "Loopback Capture", | 736 | .stream_name = "Loopback Capture", |
728 | .channels_min = 2, | 737 | .channels_min = 2, |
729 | .channels_max = 2, | 738 | .channels_max = 2, |
730 | .rates = SNDRV_PCM_RATE_8000_192000, | 739 | .rates = SNDRV_PCM_RATE_48000, |
731 | .formats = HSW_FORMATS, | 740 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
732 | }, | 741 | }, |
733 | }, | 742 | }, |
734 | { | 743 | { |
@@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { | |||
737 | .stream_name = "Analog Capture", | 746 | .stream_name = "Analog Capture", |
738 | .channels_min = 2, | 747 | .channels_min = 2, |
739 | .channels_max = 2, | 748 | .channels_max = 2, |
740 | .rates = SNDRV_PCM_RATE_8000_192000, | 749 | .rates = SNDRV_PCM_RATE_48000, |
741 | .formats = HSW_FORMATS, | 750 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, |
742 | }, | 751 | }, |
743 | }, | 752 | }, |
744 | }; | 753 | }; |
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h index 8d482d76475a..4257263157cd 100644 --- a/sound/soc/intel/sst-mfld-dsp.h +++ b/sound/soc/intel/sst-mfld-dsp.h | |||
@@ -3,7 +3,7 @@ | |||
3 | /* | 3 | /* |
4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine | 4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine |
5 | * | 5 | * |
6 | * Copyright (C) 2008-12 Intel Corporation | 6 | * Copyright (C) 2008-14 Intel Corporation |
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | 7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> |
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9 | * | 9 | * |
@@ -19,6 +19,142 @@ | |||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define SST_MAX_BIN_BYTES 1024 | ||
23 | |||
24 | #define MAX_DBG_RW_BYTES 80 | ||
25 | #define MAX_NUM_SCATTER_BUFFERS 8 | ||
26 | #define MAX_LOOP_BACK_DWORDS 8 | ||
27 | /* IPC base address and mailbox, timestamp offsets */ | ||
28 | #define SST_MAILBOX_SIZE 0x0400 | ||
29 | #define SST_MAILBOX_SEND 0x0000 | ||
30 | #define SST_TIME_STAMP 0x1800 | ||
31 | #define SST_TIME_STAMP_MRFLD 0x800 | ||
32 | #define SST_RESERVED_OFFSET 0x1A00 | ||
33 | #define SST_SCU_LPE_MAILBOX 0x1000 | ||
34 | #define SST_LPE_SCU_MAILBOX 0x1400 | ||
35 | #define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16) | ||
36 | #define PROCESS_MSG 0x80 | ||
37 | |||
38 | /* Message ID's for IPC messages */ | ||
39 | /* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */ | ||
40 | |||
41 | /* I2L Firmware/Codec Download msgs */ | ||
42 | #define IPC_IA_PREP_LIB_DNLD 0x01 | ||
43 | #define IPC_IA_LIB_DNLD_CMPLT 0x02 | ||
44 | #define IPC_IA_GET_FW_VERSION 0x04 | ||
45 | #define IPC_IA_GET_FW_BUILD_INF 0x05 | ||
46 | #define IPC_IA_GET_FW_INFO 0x06 | ||
47 | #define IPC_IA_GET_FW_CTXT 0x07 | ||
48 | #define IPC_IA_SET_FW_CTXT 0x08 | ||
49 | #define IPC_IA_PREPARE_SHUTDOWN 0x31 | ||
50 | /* I2L Codec Config/control msgs */ | ||
51 | #define IPC_PREP_D3 0x10 | ||
52 | #define IPC_IA_SET_CODEC_PARAMS 0x10 | ||
53 | #define IPC_IA_GET_CODEC_PARAMS 0x11 | ||
54 | #define IPC_IA_SET_PPP_PARAMS 0x12 | ||
55 | #define IPC_IA_GET_PPP_PARAMS 0x13 | ||
56 | #define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA | ||
57 | #define IPC_IA_ALG_PARAMS 0x1A | ||
58 | #define IPC_IA_TUNING_PARAMS 0x1B | ||
59 | #define IPC_IA_SET_RUNTIME_PARAMS 0x1C | ||
60 | #define IPC_IA_SET_PARAMS 0x1 | ||
61 | #define IPC_IA_GET_PARAMS 0x2 | ||
62 | |||
63 | #define IPC_EFFECTS_CREATE 0xE | ||
64 | #define IPC_EFFECTS_DESTROY 0xF | ||
65 | |||
66 | /* I2L Stream config/control msgs */ | ||
67 | #define IPC_IA_ALLOC_STREAM_MRFLD 0x2 | ||
68 | #define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */ | ||
69 | #define IPC_IA_FREE_STREAM_MRFLD 0x03 | ||
70 | #define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */ | ||
71 | #define IPC_IA_SET_STREAM_PARAMS 0x22 | ||
72 | #define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12 | ||
73 | #define IPC_IA_GET_STREAM_PARAMS 0x23 | ||
74 | #define IPC_IA_PAUSE_STREAM 0x24 | ||
75 | #define IPC_IA_PAUSE_STREAM_MRFLD 0x4 | ||
76 | #define IPC_IA_RESUME_STREAM 0x25 | ||
77 | #define IPC_IA_RESUME_STREAM_MRFLD 0x5 | ||
78 | #define IPC_IA_DROP_STREAM 0x26 | ||
79 | #define IPC_IA_DROP_STREAM_MRFLD 0x07 | ||
80 | #define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */ | ||
81 | #define IPC_IA_DRAIN_STREAM_MRFLD 0x8 | ||
82 | #define IPC_IA_CONTROL_ROUTING 0x29 | ||
83 | #define IPC_IA_VTSV_UPDATE_MODULES 0x20 | ||
84 | #define IPC_IA_VTSV_DETECTED 0x21 | ||
85 | |||
86 | #define IPC_IA_START_STREAM_MRFLD 0X06 | ||
87 | #define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */ | ||
88 | |||
89 | #define IPC_IA_SET_GAIN_MRFLD 0x21 | ||
90 | /* Debug msgs */ | ||
91 | #define IPC_IA_DBG_MEM_READ 0x40 | ||
92 | #define IPC_IA_DBG_MEM_WRITE 0x41 | ||
93 | #define IPC_IA_DBG_LOOP_BACK 0x42 | ||
94 | #define IPC_IA_DBG_LOG_ENABLE 0x45 | ||
95 | #define IPC_IA_DBG_SET_PROBE_PARAMS 0x47 | ||
96 | |||
97 | /* L2I Firmware/Codec Download msgs */ | ||
98 | #define IPC_IA_FW_INIT_CMPLT 0x81 | ||
99 | #define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01 | ||
100 | #define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11 | ||
101 | |||
102 | /* L2I Codec Config/control msgs */ | ||
103 | #define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */ | ||
104 | |||
105 | #define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */ | ||
106 | #define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */ | ||
107 | #define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */ | ||
108 | #define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */ | ||
109 | #define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */ | ||
110 | #define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */ | ||
111 | |||
112 | #define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */ | ||
113 | /* L2S messages */ | ||
114 | #define IPC_SC_DDR_LINK_UP 0xC0 | ||
115 | #define IPC_SC_DDR_LINK_DOWN 0xC1 | ||
116 | #define IPC_SC_SET_LPECLK_REQ 0xC2 | ||
117 | #define IPC_SC_SSP_BIT_BANG 0xC3 | ||
118 | |||
119 | /* L2I Error reporting msgs */ | ||
120 | #define IPC_IA_MEM_ALLOC_FAIL 0xE0 | ||
121 | #define IPC_IA_PROC_ERR 0xE1 /* error in processing a | ||
122 | stream can be used by playback and | ||
123 | capture modules */ | ||
124 | |||
125 | /* L2I Debug msgs */ | ||
126 | #define IPC_IA_PRINT_STRING 0xF0 | ||
127 | |||
128 | /* Buffer under-run */ | ||
129 | #define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B | ||
130 | |||
131 | /* Mrfld specific defines: | ||
132 | * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR) | ||
133 | * received from FW, the format is: | ||
134 | * - IPC High: pvt_id is set to zero. Always short message. | ||
135 | * - msg_id is in lower 16-bits of IPC low payload. | ||
136 | * - pipe_id is in higher 16-bits of IPC low payload for period_elapsed. | ||
137 | * - error id is in higher 16-bits of IPC low payload for async errors. | ||
138 | */ | ||
139 | #define SST_ASYNC_DRV_ID 0 | ||
140 | |||
141 | /* Command Response or Acknowledge message to any IPC message will have | ||
142 | * same message ID and stream ID information which is sent. | ||
143 | * There is no specific Ack message ID. The data field is used as response | ||
144 | * meaning. | ||
145 | */ | ||
146 | enum ackData { | ||
147 | IPC_ACK_SUCCESS = 0, | ||
148 | IPC_ACK_FAILURE, | ||
149 | }; | ||
150 | |||
151 | enum ipc_ia_msg_id { | ||
152 | IPC_CMD = 1, /*!< Task Control message ID */ | ||
153 | IPC_SET_PARAMS = 2,/*!< Task Set param message ID */ | ||
154 | IPC_GET_PARAMS = 3, /*!< Task Get param message ID */ | ||
155 | IPC_INVALID = 0xFF, /*!<Task Get param message ID */ | ||
156 | }; | ||
157 | |||
22 | enum sst_codec_types { | 158 | enum sst_codec_types { |
23 | /* AUDIO/MUSIC CODEC Type Definitions */ | 159 | /* AUDIO/MUSIC CODEC Type Definitions */ |
24 | SST_CODEC_TYPE_UNKNOWN = 0, | 160 | SST_CODEC_TYPE_UNKNOWN = 0, |
@@ -35,14 +171,157 @@ enum stream_type { | |||
35 | SST_STREAM_TYPE_MUSIC = 1, | 171 | SST_STREAM_TYPE_MUSIC = 1, |
36 | }; | 172 | }; |
37 | 173 | ||
174 | enum sst_error_codes { | ||
175 | /* Error code,response to msgId: Description */ | ||
176 | /* Common error codes */ | ||
177 | SST_SUCCESS = 0, /* Success */ | ||
178 | SST_ERR_INVALID_STREAM_ID = 1, | ||
179 | SST_ERR_INVALID_MSG_ID = 2, | ||
180 | SST_ERR_INVALID_STREAM_OP = 3, | ||
181 | SST_ERR_INVALID_PARAMS = 4, | ||
182 | SST_ERR_INVALID_CODEC = 5, | ||
183 | SST_ERR_INVALID_MEDIA_TYPE = 6, | ||
184 | SST_ERR_STREAM_ERR = 7, | ||
185 | |||
186 | SST_ERR_STREAM_IN_USE = 15, | ||
187 | }; | ||
188 | |||
189 | struct ipc_dsp_hdr { | ||
190 | u16 mod_index_id:8; /*!< DSP Command ID specific to tasks */ | ||
191 | u16 pipe_id:8; /*!< instance of the module in the pipeline */ | ||
192 | u16 mod_id; /*!< Pipe_id */ | ||
193 | u16 cmd_id; /*!< Module ID = lpe_algo_types_t */ | ||
194 | u16 length; /*!< Length of the payload only */ | ||
195 | } __packed; | ||
196 | |||
197 | union ipc_header_high { | ||
198 | struct { | ||
199 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
200 | u32 task_id:4; /* Task ID associated with this comand */ | ||
201 | u32 drv_id:4; /* Identifier for the driver to track*/ | ||
202 | u32 rsvd1:8; /* Reserved */ | ||
203 | u32 result:4; /* Reserved */ | ||
204 | u32 res_rqd:1; /* Response rqd */ | ||
205 | u32 large:1; /* Large Message if large = 1 */ | ||
206 | u32 done:1; /* bit 30 - Done bit */ | ||
207 | u32 busy:1; /* bit 31 - busy bit*/ | ||
208 | } part; | ||
209 | u32 full; | ||
210 | } __packed; | ||
211 | /* IPC header */ | ||
212 | union ipc_header_mrfld { | ||
213 | struct { | ||
214 | u32 header_low_payload; | ||
215 | union ipc_header_high header_high; | ||
216 | } p; | ||
217 | u64 full; | ||
218 | } __packed; | ||
219 | /* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/ | ||
220 | |||
221 | /* IPC Header */ | ||
222 | union ipc_header { | ||
223 | struct { | ||
224 | u32 msg_id:8; /* Message ID - Max 256 Message Types */ | ||
225 | u32 str_id:5; | ||
226 | u32 large:1; /* Large Message if large = 1 */ | ||
227 | u32 reserved:2; /* Reserved for future use */ | ||
228 | u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */ | ||
229 | u32 done:1; /* bit 30 */ | ||
230 | u32 busy:1; /* bit 31 */ | ||
231 | } part; | ||
232 | u32 full; | ||
233 | } __packed; | ||
234 | |||
235 | /* Firmware build info */ | ||
236 | struct sst_fw_build_info { | ||
237 | unsigned char date[16]; /* Firmware build date */ | ||
238 | unsigned char time[16]; /* Firmware build time */ | ||
239 | } __packed; | ||
240 | |||
241 | /* Firmware Version info */ | ||
242 | struct snd_sst_fw_version { | ||
243 | u8 build; /* build number*/ | ||
244 | u8 minor; /* minor number*/ | ||
245 | u8 major; /* major number*/ | ||
246 | u8 type; /* build type */ | ||
247 | }; | ||
248 | |||
249 | struct ipc_header_fw_init { | ||
250 | struct snd_sst_fw_version fw_version;/* Firmware version details */ | ||
251 | struct sst_fw_build_info build_info; | ||
252 | u16 result; /* Fw init result */ | ||
253 | u8 module_id; /* Module ID in case of error */ | ||
254 | u8 debug_info; /* Debug info from Module ID in case of fail */ | ||
255 | } __packed; | ||
256 | |||
257 | struct snd_sst_tstamp { | ||
258 | u64 ring_buffer_counter; /* PB/CP: Bytes copied from/to DDR. */ | ||
259 | u64 hardware_counter; /* PB/CP: Bytes DMAed to/from SSP. */ | ||
260 | u64 frames_decoded; | ||
261 | u64 bytes_decoded; | ||
262 | u64 bytes_copied; | ||
263 | u32 sampling_frequency; | ||
264 | u32 channel_peak[8]; | ||
265 | } __packed; | ||
266 | |||
267 | /* Stream type params struture for Alloc stream */ | ||
268 | struct snd_sst_str_type { | ||
269 | u8 codec_type; /* Codec type */ | ||
270 | u8 str_type; /* 1 = voice 2 = music */ | ||
271 | u8 operation; /* Playback or Capture */ | ||
272 | u8 protected_str; /* 0=Non DRM, 1=DRM */ | ||
273 | u8 time_slots; | ||
274 | u8 reserved; /* Reserved */ | ||
275 | u16 result; /* Result used for acknowledgment */ | ||
276 | } __packed; | ||
277 | |||
278 | /* Library info structure */ | ||
279 | struct module_info { | ||
280 | u32 lib_version; | ||
281 | u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/ | ||
282 | u32 media_type; | ||
283 | u8 lib_name[12]; | ||
284 | u32 lib_caps; | ||
285 | unsigned char b_date[16]; /* Lib build date */ | ||
286 | unsigned char b_time[16]; /* Lib build time */ | ||
287 | } __packed; | ||
288 | |||
289 | /* Library slot info */ | ||
290 | struct lib_slot_info { | ||
291 | u8 slot_num; /* 1 or 2 */ | ||
292 | u8 reserved1; | ||
293 | u16 reserved2; | ||
294 | u32 iram_size; /* slot size in IRAM */ | ||
295 | u32 dram_size; /* slot size in DRAM */ | ||
296 | u32 iram_offset; /* starting offset of slot in IRAM */ | ||
297 | u32 dram_offset; /* starting offset of slot in DRAM */ | ||
298 | } __packed; | ||
299 | |||
300 | struct snd_ppp_mixer_params { | ||
301 | __u32 type; /*Type of the parameter */ | ||
302 | __u32 size; | ||
303 | __u32 input_stream_bitmap; /*Input stream Bit Map*/ | ||
304 | } __packed; | ||
305 | |||
306 | struct snd_sst_lib_download { | ||
307 | struct module_info lib_info; /* library info type, capabilities etc */ | ||
308 | struct lib_slot_info slot_info; /* slot info to be downloaded */ | ||
309 | u32 mod_entry_pt; | ||
310 | }; | ||
311 | |||
312 | struct snd_sst_lib_download_info { | ||
313 | struct snd_sst_lib_download dload_lib; | ||
314 | u16 result; /* Result used for acknowledgment */ | ||
315 | u8 pvt_id; /* Private ID */ | ||
316 | u8 reserved; /* for alignment */ | ||
317 | }; | ||
38 | struct snd_pcm_params { | 318 | struct snd_pcm_params { |
39 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 319 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
40 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 320 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
41 | u32 reserved; /* Bitrate in bits per second */ | 321 | u8 use_offload_path; /* 0-PCM using period elpased & ALSA interfaces |
42 | u32 sfreq; /* Sampling rate in Hz */ | 322 | 1-PCM stream via compressed interface */ |
43 | u8 use_offload_path; | ||
44 | u8 reserved2; | 323 | u8 reserved2; |
45 | u16 reserved3; | 324 | u32 sfreq; /* Sampling rate in Hz */ |
46 | u8 channel_map[8]; | 325 | u8 channel_map[8]; |
47 | } __packed; | 326 | } __packed; |
48 | 327 | ||
@@ -76,6 +355,7 @@ struct snd_aac_params { | |||
76 | struct snd_wma_params { | 355 | struct snd_wma_params { |
77 | u8 num_chan; /* 1=Mono, 2=Stereo */ | 356 | u8 num_chan; /* 1=Mono, 2=Stereo */ |
78 | u8 pcm_wd_sz; /* 16/24 - bit*/ | 357 | u8 pcm_wd_sz; /* 16/24 - bit*/ |
358 | u16 reserved1; | ||
79 | u32 brate; /* Use the hard coded value. */ | 359 | u32 brate; /* Use the hard coded value. */ |
80 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | 360 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ |
81 | u32 channel_mask; /* Channel Mask */ | 361 | u32 channel_mask; /* Channel Mask */ |
@@ -101,26 +381,153 @@ struct sst_address_info { | |||
101 | }; | 381 | }; |
102 | 382 | ||
103 | struct snd_sst_alloc_params_ext { | 383 | struct snd_sst_alloc_params_ext { |
104 | struct sst_address_info ring_buf_info[8]; | 384 | __u16 sg_count; |
105 | u8 sg_count; | 385 | __u16 reserved; |
106 | u8 reserved; | 386 | __u32 frag_size; /*Number of samples after which period elapsed |
107 | u16 reserved2; | ||
108 | u32 frag_size; /*Number of samples after which period elapsed | ||
109 | message is sent valid only if path = 0*/ | 387 | message is sent valid only if path = 0*/ |
110 | } __packed; | 388 | struct sst_address_info ring_buf_info[8]; |
389 | }; | ||
111 | 390 | ||
112 | struct snd_sst_stream_params { | 391 | struct snd_sst_stream_params { |
113 | union snd_sst_codec_params uc; | 392 | union snd_sst_codec_params uc; |
114 | } __packed; | 393 | } __packed; |
115 | 394 | ||
116 | struct snd_sst_params { | 395 | struct snd_sst_params { |
396 | u32 result; | ||
117 | u32 stream_id; | 397 | u32 stream_id; |
118 | u8 codec; | 398 | u8 codec; |
119 | u8 ops; | 399 | u8 ops; |
120 | u8 stream_type; | 400 | u8 stream_type; |
121 | u8 device_type; | 401 | u8 device_type; |
402 | u8 task; | ||
122 | struct snd_sst_stream_params sparams; | 403 | struct snd_sst_stream_params sparams; |
123 | struct snd_sst_alloc_params_ext aparams; | 404 | struct snd_sst_alloc_params_ext aparams; |
124 | }; | 405 | }; |
125 | 406 | ||
407 | struct snd_sst_alloc_mrfld { | ||
408 | u16 codec_type; | ||
409 | u8 operation; | ||
410 | u8 sg_count; | ||
411 | struct sst_address_info ring_buf_info[8]; | ||
412 | u32 frag_size; | ||
413 | u32 ts; | ||
414 | struct snd_sst_stream_params codec_params; | ||
415 | } __packed; | ||
416 | |||
417 | /* Alloc stream params structure */ | ||
418 | struct snd_sst_alloc_params { | ||
419 | struct snd_sst_str_type str_type; | ||
420 | struct snd_sst_stream_params stream_params; | ||
421 | struct snd_sst_alloc_params_ext alloc_params; | ||
422 | } __packed; | ||
423 | |||
424 | /* Alloc stream response message */ | ||
425 | struct snd_sst_alloc_response { | ||
426 | struct snd_sst_str_type str_type; /* Stream type for allocation */ | ||
427 | struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */ | ||
428 | }; | ||
429 | |||
430 | /* Drop response */ | ||
431 | struct snd_sst_drop_response { | ||
432 | u32 result; | ||
433 | u32 bytes; | ||
434 | }; | ||
435 | |||
436 | struct snd_sst_async_msg { | ||
437 | u32 msg_id; /* Async msg id */ | ||
438 | u32 payload[0]; | ||
439 | }; | ||
440 | |||
441 | struct snd_sst_async_err_msg { | ||
442 | u32 fw_resp; /* Firmware Result */ | ||
443 | u32 lib_resp; /*Library result */ | ||
444 | } __packed; | ||
445 | |||
446 | struct snd_sst_vol { | ||
447 | u32 stream_id; | ||
448 | s32 volume; | ||
449 | u32 ramp_duration; | ||
450 | u32 ramp_type; /* Ramp type, default=0 */ | ||
451 | }; | ||
452 | |||
453 | /* Gain library parameters for mrfld | ||
454 | * based on DSP command spec v0.82 | ||
455 | */ | ||
456 | struct snd_sst_gain_v2 { | ||
457 | u16 gain_cell_num; /* num of gain cells to modify*/ | ||
458 | u8 cell_nbr_idx; /* instance index*/ | ||
459 | u8 cell_path_idx; /* pipe-id */ | ||
460 | u16 module_id; /*module id */ | ||
461 | u16 left_cell_gain; /* left gain value in dB*/ | ||
462 | u16 right_cell_gain; /* right gain value in dB*/ | ||
463 | u16 gain_time_const; /* gain time constant*/ | ||
464 | } __packed; | ||
465 | |||
466 | struct snd_sst_mute { | ||
467 | u32 stream_id; | ||
468 | u32 mute; | ||
469 | }; | ||
470 | |||
471 | struct snd_sst_runtime_params { | ||
472 | u8 type; | ||
473 | u8 str_id; | ||
474 | u8 size; | ||
475 | u8 rsvd; | ||
476 | void *addr; | ||
477 | } __packed; | ||
478 | |||
479 | enum stream_param_type { | ||
480 | SST_SET_TIME_SLOT = 0, | ||
481 | SST_SET_CHANNEL_INFO = 1, | ||
482 | OTHERS = 2, /*reserved for future params*/ | ||
483 | }; | ||
484 | |||
485 | /* CSV Voice call routing structure */ | ||
486 | struct snd_sst_control_routing { | ||
487 | u8 control; /* 0=start, 1=Stop */ | ||
488 | u8 reserved[3]; /* Reserved- for 32 bit alignment */ | ||
489 | }; | ||
490 | |||
491 | struct ipc_post { | ||
492 | struct list_head node; | ||
493 | union ipc_header header; /* driver specific */ | ||
494 | bool is_large; | ||
495 | bool is_process_reply; | ||
496 | union ipc_header_mrfld mrfld_header; | ||
497 | char *mailbox_data; | ||
498 | }; | ||
499 | |||
500 | struct snd_sst_ctxt_params { | ||
501 | u32 address; /* Physical Address in DDR where the context is stored */ | ||
502 | u32 size; /* size of the context */ | ||
503 | }; | ||
504 | |||
505 | struct snd_sst_lpe_log_params { | ||
506 | u8 dbg_type; | ||
507 | u8 module_id; | ||
508 | u8 log_level; | ||
509 | u8 reserved; | ||
510 | } __packed; | ||
511 | |||
512 | enum snd_sst_bytes_type { | ||
513 | SND_SST_BYTES_SET = 0x1, | ||
514 | SND_SST_BYTES_GET = 0x2, | ||
515 | }; | ||
516 | |||
517 | struct snd_sst_bytes_v2 { | ||
518 | u8 type; | ||
519 | u8 ipc_msg; | ||
520 | u8 block; | ||
521 | u8 task_id; | ||
522 | u8 pipe_id; | ||
523 | u8 rsvd; | ||
524 | u16 len; | ||
525 | char bytes[0]; | ||
526 | }; | ||
527 | |||
528 | #define MAX_VTSV_FILES 2 | ||
529 | struct snd_sst_vtsv_info { | ||
530 | struct sst_address_info vfiles[MAX_VTSV_FILES]; | ||
531 | } __packed; | ||
532 | |||
126 | #endif /* __SST_MFLD_DSP_H__ */ | 533 | #endif /* __SST_MFLD_DSP_H__ */ |
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c index 02abd19fce1d..29c059ca19e8 100644 --- a/sound/soc/intel/sst-mfld-platform-compress.c +++ b/sound/soc/intel/sst-mfld-platform-compress.c | |||
@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | |||
100 | int retval; | 100 | int retval; |
101 | struct snd_sst_params str_params; | 101 | struct snd_sst_params str_params; |
102 | struct sst_compress_cb cb; | 102 | struct sst_compress_cb cb; |
103 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
104 | struct snd_soc_platform *platform = rtd->platform; | ||
105 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
103 | 106 | ||
104 | stream = cstream->runtime->private_data; | 107 | stream = cstream->runtime->private_data; |
105 | /* construct fw structure for this*/ | 108 | /* construct fw structure for this*/ |
106 | memset(&str_params, 0, sizeof(str_params)); | 109 | memset(&str_params, 0, sizeof(str_params)); |
107 | 110 | ||
108 | str_params.ops = STREAM_OPS_PLAYBACK; | 111 | /* fill the device type and stream id to pass to SST driver */ |
109 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | 112 | retval = sst_fill_stream_params(cstream, ctx, &str_params, true); |
110 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | 113 | pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval); |
114 | if (retval < 0) | ||
115 | return retval; | ||
111 | 116 | ||
112 | switch (params->codec.id) { | 117 | switch (params->codec.id) { |
113 | case SND_AUDIOCODEC_MP3: { | 118 | case SND_AUDIOCODEC_MP3: { |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 7c790f51d259..706212a6a68c 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sst_mfld_platform.c - Intel MID Platform driver | 2 | * sst_mfld_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2013 Intel Corp | 4 | * Copyright (C) 2010-2014 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
@@ -27,7 +27,9 @@ | |||
27 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
28 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
29 | #include <sound/compress_driver.h> | 29 | #include <sound/compress_driver.h> |
30 | #include <asm/platform_sst_audio.h> | ||
30 | #include "sst-mfld-platform.h" | 31 | #include "sst-mfld-platform.h" |
32 | #include "sst-atom-controls.h" | ||
31 | 33 | ||
32 | struct sst_device *sst; | 34 | struct sst_device *sst; |
33 | static DEFINE_MUTEX(sst_lock); | 35 | static DEFINE_MUTEX(sst_lock); |
@@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = { | |||
92 | .fifo_size = SST_FIFO_SIZE, | 94 | .fifo_size = SST_FIFO_SIZE, |
93 | }; | 95 | }; |
94 | 96 | ||
97 | static struct sst_dev_stream_map dpcm_strm_map[] = { | ||
98 | {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */ | ||
99 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0}, | ||
100 | {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0}, | ||
101 | {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0}, | ||
102 | }; | ||
103 | |||
95 | /* MFLD - MSIC */ | 104 | /* MFLD - MSIC */ |
96 | static struct snd_soc_dai_driver sst_platform_dai[] = { | 105 | static struct snd_soc_dai_driver sst_platform_dai[] = { |
97 | { | 106 | { |
@@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream) | |||
143 | return state; | 152 | return state; |
144 | } | 153 | } |
145 | 154 | ||
155 | static void sst_fill_alloc_params(struct snd_pcm_substream *substream, | ||
156 | struct snd_sst_alloc_params_ext *alloc_param) | ||
157 | { | ||
158 | unsigned int channels; | ||
159 | snd_pcm_uframes_t period_size; | ||
160 | ssize_t periodbytes; | ||
161 | ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | ||
162 | u32 buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
163 | |||
164 | channels = substream->runtime->channels; | ||
165 | period_size = substream->runtime->period_size; | ||
166 | periodbytes = samples_to_bytes(substream->runtime, period_size); | ||
167 | alloc_param->ring_buf_info[0].addr = buffer_addr; | ||
168 | alloc_param->ring_buf_info[0].size = buffer_bytes; | ||
169 | alloc_param->sg_count = 1; | ||
170 | alloc_param->reserved = 0; | ||
171 | alloc_param->frag_size = periodbytes * channels; | ||
172 | |||
173 | } | ||
146 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, | 174 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, |
147 | struct sst_pcm_params *param) | 175 | struct snd_sst_stream_params *param) |
148 | { | 176 | { |
177 | param->uc.pcm_params.num_chan = (u8) substream->runtime->channels; | ||
178 | param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits; | ||
179 | param->uc.pcm_params.sfreq = substream->runtime->rate; | ||
180 | |||
181 | /* PCM stream via ALSA interface */ | ||
182 | param->uc.pcm_params.use_offload_path = 0; | ||
183 | param->uc.pcm_params.reserved2 = 0; | ||
184 | memset(param->uc.pcm_params.channel_map, 0, sizeof(u8)); | ||
149 | 185 | ||
150 | param->num_chan = (u8) substream->runtime->channels; | ||
151 | param->pcm_wd_sz = substream->runtime->sample_bits; | ||
152 | param->reserved = 0; | ||
153 | param->sfreq = substream->runtime->rate; | ||
154 | param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); | ||
155 | param->period_count = substream->runtime->period_size; | ||
156 | param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); | ||
157 | pr_debug("period_cnt = %d\n", param->period_count); | ||
158 | pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); | ||
159 | } | 186 | } |
160 | 187 | ||
161 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) | 188 | static int sst_get_stream_mapping(int dev, int sdev, int dir, |
189 | struct sst_dev_stream_map *map, int size) | ||
190 | { | ||
191 | int i; | ||
192 | |||
193 | if (map == NULL) | ||
194 | return -EINVAL; | ||
195 | |||
196 | |||
197 | /* index 0 is not used in stream map */ | ||
198 | for (i = 1; i < size; i++) { | ||
199 | if ((map[i].dev_num == dev) && (map[i].direction == dir)) | ||
200 | return i; | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int sst_fill_stream_params(void *substream, | ||
206 | const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress) | ||
207 | { | ||
208 | int map_size; | ||
209 | int index; | ||
210 | struct sst_dev_stream_map *map; | ||
211 | struct snd_pcm_substream *pstream = NULL; | ||
212 | struct snd_compr_stream *cstream = NULL; | ||
213 | |||
214 | map = ctx->pdata->pdev_strm_map; | ||
215 | map_size = ctx->pdata->strm_map_size; | ||
216 | |||
217 | if (is_compress == true) | ||
218 | cstream = (struct snd_compr_stream *)substream; | ||
219 | else | ||
220 | pstream = (struct snd_pcm_substream *)substream; | ||
221 | |||
222 | str_params->stream_type = SST_STREAM_TYPE_MUSIC; | ||
223 | |||
224 | /* For pcm streams */ | ||
225 | if (pstream) { | ||
226 | index = sst_get_stream_mapping(pstream->pcm->device, | ||
227 | pstream->number, pstream->stream, | ||
228 | map, map_size); | ||
229 | if (index <= 0) | ||
230 | return -EINVAL; | ||
231 | |||
232 | str_params->stream_id = index; | ||
233 | str_params->device_type = map[index].device_id; | ||
234 | str_params->task = map[index].task_id; | ||
235 | |||
236 | str_params->ops = (u8)pstream->stream; | ||
237 | } | ||
238 | |||
239 | if (cstream) { | ||
240 | index = sst_get_stream_mapping(cstream->device->device, | ||
241 | 0, cstream->direction, | ||
242 | map, map_size); | ||
243 | if (index <= 0) | ||
244 | return -EINVAL; | ||
245 | str_params->stream_id = index; | ||
246 | str_params->device_type = map[index].device_id; | ||
247 | str_params->task = map[index].task_id; | ||
248 | |||
249 | str_params->ops = (u8)cstream->direction; | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | ||
255 | struct snd_soc_platform *platform) | ||
162 | { | 256 | { |
163 | struct sst_runtime_stream *stream = | 257 | struct sst_runtime_stream *stream = |
164 | substream->runtime->private_data; | 258 | substream->runtime->private_data; |
165 | struct sst_pcm_params param = {0}; | 259 | struct snd_sst_stream_params param = {{{0,},},}; |
166 | struct sst_stream_params str_params = {0}; | 260 | struct snd_sst_params str_params = {0}; |
167 | int ret_val; | 261 | struct snd_sst_alloc_params_ext alloc_params = {0}; |
262 | int ret_val = 0; | ||
263 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | ||
168 | 264 | ||
169 | /* set codec params and inform SST driver the same */ | 265 | /* set codec params and inform SST driver the same */ |
170 | sst_fill_pcm_params(substream, ¶m); | 266 | sst_fill_pcm_params(substream, ¶m); |
267 | sst_fill_alloc_params(substream, &alloc_params); | ||
171 | substream->runtime->dma_area = substream->dma_buffer.area; | 268 | substream->runtime->dma_area = substream->dma_buffer.area; |
172 | str_params.sparams = param; | 269 | str_params.sparams = param; |
173 | str_params.codec = param.codec; | 270 | str_params.aparams = alloc_params; |
174 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 271 | str_params.codec = SST_CODEC_TYPE_PCM; |
175 | str_params.ops = STREAM_OPS_PLAYBACK; | 272 | |
176 | str_params.device_type = substream->pcm->device + 1; | 273 | /* fill the device type and stream id to pass to SST driver */ |
177 | pr_debug("Playbck stream,Device %d\n", | 274 | ret_val = sst_fill_stream_params(substream, ctx, &str_params, false); |
178 | substream->pcm->device); | ||
179 | } else { | ||
180 | str_params.ops = STREAM_OPS_CAPTURE; | ||
181 | str_params.device_type = SND_SST_DEVICE_CAPTURE; | ||
182 | pr_debug("Capture stream,Device %d\n", | ||
183 | substream->pcm->device); | ||
184 | } | ||
185 | ret_val = stream->ops->open(&str_params); | ||
186 | pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); | ||
187 | if (ret_val < 0) | 275 | if (ret_val < 0) |
188 | return ret_val; | 276 | return ret_val; |
189 | 277 | ||
190 | stream->stream_info.str_id = ret_val; | 278 | stream->stream_info.str_id = str_params.stream_id; |
191 | pr_debug("str id : %d\n", stream->stream_info.str_id); | 279 | |
280 | ret_val = stream->ops->open(&str_params); | ||
281 | if (ret_val <= 0) | ||
282 | return ret_val; | ||
283 | |||
284 | |||
192 | return ret_val; | 285 | return ret_val; |
193 | } | 286 | } |
194 | 287 | ||
195 | static void sst_period_elapsed(void *mad_substream) | 288 | static void sst_period_elapsed(void *arg) |
196 | { | 289 | { |
197 | struct snd_pcm_substream *substream = mad_substream; | 290 | struct snd_pcm_substream *substream = arg; |
198 | struct sst_runtime_stream *stream; | 291 | struct sst_runtime_stream *stream; |
199 | int status; | 292 | int status; |
200 | 293 | ||
@@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
218 | pr_debug("setting buffer ptr param\n"); | 311 | pr_debug("setting buffer ptr param\n"); |
219 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 312 | sst_set_stream_status(stream, SST_PLATFORM_INIT); |
220 | stream->stream_info.period_elapsed = sst_period_elapsed; | 313 | stream->stream_info.period_elapsed = sst_period_elapsed; |
221 | stream->stream_info.mad_substream = substream; | 314 | stream->stream_info.arg = substream; |
222 | stream->stream_info.buffer_ptr = 0; | 315 | stream->stream_info.buffer_ptr = 0; |
223 | stream->stream_info.sfreq = substream->runtime->rate; | 316 | stream->stream_info.sfreq = substream->runtime->rate; |
224 | ret_val = stream->ops->device_control( | 317 | ret_val = stream->ops->device_control( |
@@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
230 | } | 323 | } |
231 | /* end -- helper functions */ | 324 | /* end -- helper functions */ |
232 | 325 | ||
233 | static int sst_platform_open(struct snd_pcm_substream *substream) | 326 | static int sst_media_open(struct snd_pcm_substream *substream, |
327 | struct snd_soc_dai *dai) | ||
234 | { | 328 | { |
329 | int ret_val = 0; | ||
235 | struct snd_pcm_runtime *runtime = substream->runtime; | 330 | struct snd_pcm_runtime *runtime = substream->runtime; |
236 | struct sst_runtime_stream *stream; | 331 | struct sst_runtime_stream *stream; |
237 | int ret_val; | ||
238 | |||
239 | pr_debug("sst_platform_open called\n"); | ||
240 | |||
241 | snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); | ||
242 | ret_val = snd_pcm_hw_constraint_integer(runtime, | ||
243 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
244 | if (ret_val < 0) | ||
245 | return ret_val; | ||
246 | 332 | ||
247 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | 333 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
248 | if (!stream) | 334 | if (!stream) |
@@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream) | |||
251 | 337 | ||
252 | /* get the sst ops */ | 338 | /* get the sst ops */ |
253 | mutex_lock(&sst_lock); | 339 | mutex_lock(&sst_lock); |
254 | if (!sst) { | 340 | if (!sst || |
341 | !try_module_get(sst->dev->driver->owner)) { | ||
255 | pr_err("no device available to run\n"); | 342 | pr_err("no device available to run\n"); |
256 | mutex_unlock(&sst_lock); | 343 | ret_val = -ENODEV; |
257 | kfree(stream); | 344 | goto out_ops; |
258 | return -ENODEV; | ||
259 | } | ||
260 | if (!try_module_get(sst->dev->driver->owner)) { | ||
261 | mutex_unlock(&sst_lock); | ||
262 | kfree(stream); | ||
263 | return -ENODEV; | ||
264 | } | 345 | } |
265 | stream->ops = sst->ops; | 346 | stream->ops = sst->ops; |
266 | mutex_unlock(&sst_lock); | 347 | mutex_unlock(&sst_lock); |
267 | 348 | ||
268 | stream->stream_info.str_id = 0; | 349 | stream->stream_info.str_id = 0; |
269 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 350 | |
270 | stream->stream_info.mad_substream = substream; | 351 | stream->stream_info.arg = substream; |
271 | /* allocate memory for SST API set */ | 352 | /* allocate memory for SST API set */ |
272 | runtime->private_data = stream; | 353 | runtime->private_data = stream; |
273 | 354 | ||
274 | return 0; | 355 | /* Make sure, that the period size is always even */ |
356 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
357 | SNDRV_PCM_HW_PARAM_PERIODS, 2); | ||
358 | |||
359 | return snd_pcm_hw_constraint_integer(runtime, | ||
360 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
361 | out_ops: | ||
362 | kfree(stream); | ||
363 | mutex_unlock(&sst_lock); | ||
364 | return ret_val; | ||
275 | } | 365 | } |
276 | 366 | ||
277 | static int sst_platform_close(struct snd_pcm_substream *substream) | 367 | static void sst_media_close(struct snd_pcm_substream *substream, |
368 | struct snd_soc_dai *dai) | ||
278 | { | 369 | { |
279 | struct sst_runtime_stream *stream; | 370 | struct sst_runtime_stream *stream; |
280 | int ret_val = 0, str_id; | 371 | int ret_val = 0, str_id; |
281 | 372 | ||
282 | pr_debug("sst_platform_close called\n"); | ||
283 | stream = substream->runtime->private_data; | 373 | stream = substream->runtime->private_data; |
284 | str_id = stream->stream_info.str_id; | 374 | str_id = stream->stream_info.str_id; |
285 | if (str_id) | 375 | if (str_id) |
286 | ret_val = stream->ops->close(str_id); | 376 | ret_val = stream->ops->close(str_id); |
287 | module_put(sst->dev->driver->owner); | 377 | module_put(sst->dev->driver->owner); |
288 | kfree(stream); | 378 | kfree(stream); |
289 | return ret_val; | ||
290 | } | 379 | } |
291 | 380 | ||
292 | static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | 381 | static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform, |
382 | struct snd_pcm_substream *substream) | ||
383 | { | ||
384 | struct sst_data *sst = snd_soc_platform_get_drvdata(platform); | ||
385 | struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map; | ||
386 | struct sst_runtime_stream *stream = | ||
387 | substream->runtime->private_data; | ||
388 | u32 str_id = stream->stream_info.str_id; | ||
389 | unsigned int pipe_id; | ||
390 | pipe_id = map[str_id].device_id; | ||
391 | |||
392 | pr_debug("%s: got pipe_id = %#x for str_id = %d\n", | ||
393 | __func__, pipe_id, str_id); | ||
394 | return pipe_id; | ||
395 | } | ||
396 | |||
397 | static int sst_media_prepare(struct snd_pcm_substream *substream, | ||
398 | struct snd_soc_dai *dai) | ||
293 | { | 399 | { |
294 | struct sst_runtime_stream *stream; | 400 | struct sst_runtime_stream *stream; |
295 | int ret_val = 0, str_id; | 401 | int ret_val = 0, str_id; |
296 | 402 | ||
297 | pr_debug("sst_platform_pcm_prepare called\n"); | ||
298 | stream = substream->runtime->private_data; | 403 | stream = substream->runtime->private_data; |
299 | str_id = stream->stream_info.str_id; | 404 | str_id = stream->stream_info.str_id; |
300 | if (stream->stream_info.str_id) { | 405 | if (stream->stream_info.str_id) { |
@@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
303 | return ret_val; | 408 | return ret_val; |
304 | } | 409 | } |
305 | 410 | ||
306 | ret_val = sst_platform_alloc_stream(substream); | 411 | ret_val = sst_platform_alloc_stream(substream, dai->platform); |
307 | if (ret_val < 0) | 412 | if (ret_val <= 0) |
308 | return ret_val; | 413 | return ret_val; |
309 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), | 414 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), |
310 | "%d", stream->stream_info.str_id); | 415 | "%d", stream->stream_info.str_id); |
@@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | |||
316 | return ret_val; | 421 | return ret_val; |
317 | } | 422 | } |
318 | 423 | ||
424 | static int sst_media_hw_params(struct snd_pcm_substream *substream, | ||
425 | struct snd_pcm_hw_params *params, | ||
426 | struct snd_soc_dai *dai) | ||
427 | { | ||
428 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
429 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int sst_media_hw_free(struct snd_pcm_substream *substream, | ||
434 | struct snd_soc_dai *dai) | ||
435 | { | ||
436 | return snd_pcm_lib_free_pages(substream); | ||
437 | } | ||
438 | |||
439 | static struct snd_soc_dai_ops sst_media_dai_ops = { | ||
440 | .startup = sst_media_open, | ||
441 | .shutdown = sst_media_close, | ||
442 | .prepare = sst_media_prepare, | ||
443 | .hw_params = sst_media_hw_params, | ||
444 | .hw_free = sst_media_hw_free, | ||
445 | }; | ||
446 | |||
447 | static int sst_platform_open(struct snd_pcm_substream *substream) | ||
448 | { | ||
449 | struct snd_pcm_runtime *runtime; | ||
450 | |||
451 | if (substream->pcm->internal) | ||
452 | return 0; | ||
453 | |||
454 | runtime = substream->runtime; | ||
455 | runtime->hw = sst_platform_pcm_hw; | ||
456 | return 0; | ||
457 | } | ||
458 | |||
319 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | 459 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, |
320 | int cmd) | 460 | int cmd) |
321 | { | 461 | { |
@@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | |||
331 | pr_debug("sst: Trigger Start\n"); | 471 | pr_debug("sst: Trigger Start\n"); |
332 | str_cmd = SST_SND_START; | 472 | str_cmd = SST_SND_START; |
333 | status = SST_PLATFORM_RUNNING; | 473 | status = SST_PLATFORM_RUNNING; |
334 | stream->stream_info.mad_substream = substream; | 474 | stream->stream_info.arg = substream; |
335 | break; | 475 | break; |
336 | case SNDRV_PCM_TRIGGER_STOP: | 476 | case SNDRV_PCM_TRIGGER_STOP: |
337 | pr_debug("sst: in stop\n"); | 477 | pr_debug("sst: in stop\n"); |
@@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer | |||
377 | pr_err("sst: error code = %d\n", ret_val); | 517 | pr_err("sst: error code = %d\n", ret_val); |
378 | return ret_val; | 518 | return ret_val; |
379 | } | 519 | } |
380 | return stream->stream_info.buffer_ptr; | 520 | substream->runtime->delay = str_info->pcm_delay; |
381 | } | 521 | return str_info->buffer_ptr; |
382 | |||
383 | static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, | ||
384 | struct snd_pcm_hw_params *params) | ||
385 | { | ||
386 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
387 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) | ||
393 | { | ||
394 | return snd_pcm_lib_free_pages(substream); | ||
395 | } | 522 | } |
396 | 523 | ||
397 | static struct snd_pcm_ops sst_platform_ops = { | 524 | static struct snd_pcm_ops sst_platform_ops = { |
398 | .open = sst_platform_open, | 525 | .open = sst_platform_open, |
399 | .close = sst_platform_close, | ||
400 | .ioctl = snd_pcm_lib_ioctl, | 526 | .ioctl = snd_pcm_lib_ioctl, |
401 | .prepare = sst_platform_pcm_prepare, | ||
402 | .trigger = sst_platform_pcm_trigger, | 527 | .trigger = sst_platform_pcm_trigger, |
403 | .pointer = sst_platform_pcm_pointer, | 528 | .pointer = sst_platform_pcm_pointer, |
404 | .hw_params = sst_platform_pcm_hw_params, | ||
405 | .hw_free = sst_platform_pcm_hw_free, | ||
406 | }; | 529 | }; |
407 | 530 | ||
408 | static void sst_pcm_free(struct snd_pcm *pcm) | 531 | static void sst_pcm_free(struct snd_pcm *pcm) |
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm) | |||
413 | 536 | ||
414 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | 537 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
415 | { | 538 | { |
539 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
416 | struct snd_pcm *pcm = rtd->pcm; | 540 | struct snd_pcm *pcm = rtd->pcm; |
417 | int retval = 0; | 541 | int retval = 0; |
418 | 542 | ||
419 | pr_debug("sst_pcm_new called\n"); | 543 | if (dai->driver->playback.channels_min || |
420 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || | 544 | dai->driver->capture.channels_min) { |
421 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
422 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, | 545 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, |
423 | SNDRV_DMA_TYPE_CONTINUOUS, | 546 | SNDRV_DMA_TYPE_CONTINUOUS, |
424 | snd_dma_continuous_data(GFP_KERNEL), | 547 | snd_dma_continuous_data(GFP_DMA), |
425 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 548 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
426 | if (retval) { | 549 | if (retval) { |
427 | pr_err("dma buffer allocationf fail\n"); | 550 | pr_err("dma buffer allocationf fail\n"); |
@@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = { | |||
445 | 568 | ||
446 | static int sst_platform_probe(struct platform_device *pdev) | 569 | static int sst_platform_probe(struct platform_device *pdev) |
447 | { | 570 | { |
571 | struct sst_data *drv; | ||
448 | int ret; | 572 | int ret; |
573 | struct sst_platform_data *pdata; | ||
574 | |||
575 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); | ||
576 | if (drv == NULL) { | ||
577 | pr_err("kzalloc failed\n"); | ||
578 | return -ENOMEM; | ||
579 | } | ||
580 | |||
581 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
582 | if (pdata == NULL) { | ||
583 | pr_err("kzalloc failed for pdata\n"); | ||
584 | return -ENOMEM; | ||
585 | } | ||
586 | |||
587 | pdata->pdev_strm_map = dpcm_strm_map; | ||
588 | pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map); | ||
589 | drv->pdata = pdata; | ||
590 | mutex_init(&drv->lock); | ||
591 | dev_set_drvdata(&pdev->dev, drv); | ||
449 | 592 | ||
450 | pr_debug("sst_platform_probe called\n"); | ||
451 | sst = NULL; | ||
452 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); | 593 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); |
453 | if (ret) { | 594 | if (ret) { |
454 | pr_err("registering soc platform failed\n"); | 595 | pr_err("registering soc platform failed\n"); |
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 6c5e7dc49e3c..6c6a42c08e24 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h | |||
@@ -39,9 +39,10 @@ extern struct sst_device *sst; | |||
39 | 39 | ||
40 | struct pcm_stream_info { | 40 | struct pcm_stream_info { |
41 | int str_id; | 41 | int str_id; |
42 | void *mad_substream; | 42 | void *arg; |
43 | void (*period_elapsed) (void *mad_substream); | 43 | void (*period_elapsed) (void *arg); |
44 | unsigned long long buffer_ptr; | 44 | unsigned long long buffer_ptr; |
45 | unsigned long long pcm_delay; | ||
45 | int sfreq; | 46 | int sfreq; |
46 | }; | 47 | }; |
47 | 48 | ||
@@ -62,7 +63,9 @@ enum sst_controls { | |||
62 | SST_SND_BUFFER_POINTER = 0x05, | 63 | SST_SND_BUFFER_POINTER = 0x05, |
63 | SST_SND_STREAM_INIT = 0x06, | 64 | SST_SND_STREAM_INIT = 0x06, |
64 | SST_SND_START = 0x07, | 65 | SST_SND_START = 0x07, |
65 | SST_MAX_CONTROLS = 0x07, | 66 | SST_SET_BYTE_STREAM = 0x100A, |
67 | SST_GET_BYTE_STREAM = 0x100B, | ||
68 | SST_MAX_CONTROLS = SST_GET_BYTE_STREAM, | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | enum sst_stream_ops { | 71 | enum sst_stream_ops { |
@@ -124,8 +127,9 @@ struct compress_sst_ops { | |||
124 | }; | 127 | }; |
125 | 128 | ||
126 | struct sst_ops { | 129 | struct sst_ops { |
127 | int (*open) (struct sst_stream_params *str_param); | 130 | int (*open) (struct snd_sst_params *str_param); |
128 | int (*device_control) (int cmd, void *arg); | 131 | int (*device_control) (int cmd, void *arg); |
132 | int (*set_generic_params)(enum sst_controls cmd, void *arg); | ||
129 | int (*close) (unsigned int str_id); | 133 | int (*close) (unsigned int str_id); |
130 | }; | 134 | }; |
131 | 135 | ||
@@ -143,10 +147,27 @@ struct sst_device { | |||
143 | char *name; | 147 | char *name; |
144 | struct device *dev; | 148 | struct device *dev; |
145 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
150 | struct platform_device *pdev; | ||
146 | struct compress_sst_ops *compr_ops; | 151 | struct compress_sst_ops *compr_ops; |
147 | }; | 152 | }; |
148 | 153 | ||
154 | struct sst_data; | ||
149 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); | 155 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); |
156 | int sst_fill_stream_params(void *substream, const struct sst_data *ctx, | ||
157 | struct snd_sst_params *str_params, bool is_compress); | ||
158 | |||
159 | struct sst_algo_int_control_v2 { | ||
160 | struct soc_mixer_control mc; | ||
161 | u16 module_id; /* module identifieer */ | ||
162 | u16 pipe_id; /* location info: pipe_id + instance_id */ | ||
163 | u16 instance_id; | ||
164 | unsigned int value; /* Value received is stored here */ | ||
165 | }; | ||
166 | struct sst_data { | ||
167 | struct platform_device *pdev; | ||
168 | struct sst_platform_data *pdata; | ||
169 | struct mutex lock; | ||
170 | }; | ||
150 | int sst_register_dsp(struct sst_device *sst); | 171 | int sst_register_dsp(struct sst_device *sst); |
151 | int sst_unregister_dsp(struct sst_device *sst); | 172 | int sst_unregister_dsp(struct sst_device *sst); |
152 | #endif | 173 | #endif |
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 06f4e8aa93ae..132bb83f8e99 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_KIRKWOOD_SOC | 1 | config SND_KIRKWOOD_SOC |
2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" | 2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" |
3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST | 3 | depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the Kirkwood I2S interface. You will also need to select the | 6 | the Kirkwood I2S interface. You will also need to select the |
@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB | |||
15 | Say Y if you want to add support for SoC audio on | 15 | Say Y if you want to add support for SoC audio on |
16 | the Armada 370 Development Board. | 16 | the Armada 370 Development Board. |
17 | 17 | ||
18 | config SND_KIRKWOOD_SOC_OPENRD | ||
19 | tristate "SoC Audio support for Kirkwood Openrd Client" | ||
20 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) | ||
21 | depends on I2C | ||
22 | select SND_SOC_CS42L51 | ||
23 | help | ||
24 | Say Y if you want to add support for SoC audio on | ||
25 | Openrd Client. | ||
26 | |||
27 | config SND_KIRKWOOD_SOC_T5325 | ||
28 | tristate "SoC Audio support for HP t5325" | ||
29 | depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C | ||
30 | select SND_SOC_ALC5623 | ||
31 | help | ||
32 | Say Y if you want to add support for SoC audio on | ||
33 | the HP t5325 thin client. | ||
34 | |||
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 7c1d8fe09e6b..c36b03d8006c 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile | |||
@@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o | |||
2 | 2 | ||
3 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o | 3 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o |
4 | 4 | ||
5 | snd-soc-openrd-objs := kirkwood-openrd.o | ||
6 | snd-soc-t5325-objs := kirkwood-t5325.o | ||
7 | snd-soc-armada-370-db-objs := armada-370-db.o | 5 | snd-soc-armada-370-db-objs := armada-370-db.o |
8 | 6 | ||
9 | obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o | 7 | obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o |
10 | obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o | ||
11 | obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o | ||
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index aac22fccdcdc..4cf2245950d7 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -28,11 +28,12 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) | |||
28 | } | 28 | } |
29 | 29 | ||
30 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { | 30 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { |
31 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | 31 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
32 | SNDRV_PCM_INFO_MMAP | | 32 | SNDRV_PCM_INFO_MMAP | |
33 | SNDRV_PCM_INFO_MMAP_VALID | | 33 | SNDRV_PCM_INFO_MMAP_VALID | |
34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
35 | SNDRV_PCM_INFO_PAUSE), | 35 | SNDRV_PCM_INFO_PAUSE | |
36 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
36 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, | 37 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, |
37 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, | 38 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, |
38 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, | 39 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, |
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 9f842222e798..0704cd6d2314 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
212 | KIRKWOOD_PLAYCTL_SIZE_MASK); | 212 | KIRKWOOD_PLAYCTL_SIZE_MASK); |
213 | priv->ctl_play |= ctl_play; | 213 | priv->ctl_play |= ctl_play; |
214 | } else { | 214 | } else { |
215 | priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; | 215 | priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK | |
216 | KIRKWOOD_RECCTL_SIZE_MASK); | ||
216 | priv->ctl_rec |= ctl_rec; | 217 | priv->ctl_rec |= ctl_rec; |
217 | } | 218 | } |
218 | 219 | ||
@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
221 | return 0; | 222 | return 0; |
222 | } | 223 | } |
223 | 224 | ||
225 | static unsigned kirkwood_i2s_play_mute(unsigned ctl) | ||
226 | { | ||
227 | if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN)) | ||
228 | ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE; | ||
229 | if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN)) | ||
230 | ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE; | ||
231 | return ctl; | ||
232 | } | ||
233 | |||
224 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | 234 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, |
225 | int cmd, struct snd_soc_dai *dai) | 235 | int cmd, struct snd_soc_dai *dai) |
226 | { | 236 | { |
237 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
227 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | 238 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); |
228 | uint32_t ctl, value; | 239 | uint32_t ctl, value; |
229 | 240 | ||
230 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); | 241 | ctl = readl(priv->io + KIRKWOOD_PLAYCTL); |
231 | if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { | 242 | if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) { |
232 | unsigned timeout = 5000; | 243 | unsigned timeout = 5000; |
233 | /* | 244 | /* |
234 | * The Armada510 spec says that if we enter pause mode, the | 245 | * The Armada510 spec says that if we enter pause mode, the |
@@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
256 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ | 267 | ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ |
257 | else | 268 | else |
258 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ | 269 | ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ |
259 | 270 | ctl = kirkwood_i2s_play_mute(ctl); | |
260 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; | 271 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
261 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 272 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
262 | 273 | ||
263 | /* enable interrupts */ | 274 | /* enable interrupts */ |
264 | value = readl(priv->io + KIRKWOOD_INT_MASK); | 275 | if (!runtime->no_period_wakeup) { |
265 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; | 276 | value = readl(priv->io + KIRKWOOD_INT_MASK); |
266 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 277 | value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; |
278 | writel(value, priv->io + KIRKWOOD_INT_MASK); | ||
279 | } | ||
267 | 280 | ||
268 | /* enable playback */ | 281 | /* enable playback */ |
269 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); | 282 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
295 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 308 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
296 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | | 309 | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | |
297 | KIRKWOOD_PLAYCTL_SPDIF_MUTE); | 310 | KIRKWOOD_PLAYCTL_SPDIF_MUTE); |
311 | ctl = kirkwood_i2s_play_mute(ctl); | ||
298 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); | 312 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
299 | break; | 313 | break; |
300 | 314 | ||
@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | |||
322 | else | 336 | else |
323 | ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ | 337 | ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ |
324 | 338 | ||
325 | value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN | | 339 | value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK; |
326 | KIRKWOOD_RECCTL_SPDIF_EN); | ||
327 | writel(value, priv->io + KIRKWOOD_RECCTL); | 340 | writel(value, priv->io + KIRKWOOD_RECCTL); |
328 | 341 | ||
329 | /* enable interrupts */ | 342 | /* enable interrupts */ |
@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | |||
347 | 360 | ||
348 | /* disable all records */ | 361 | /* disable all records */ |
349 | value = readl(priv->io + KIRKWOOD_RECCTL); | 362 | value = readl(priv->io + KIRKWOOD_RECCTL); |
350 | value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); | 363 | value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; |
351 | writel(value, priv->io + KIRKWOOD_RECCTL); | 364 | writel(value, priv->io + KIRKWOOD_RECCTL); |
352 | break; | 365 | break; |
353 | 366 | ||
@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv) | |||
411 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 424 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
412 | 425 | ||
413 | value = readl(priv->io + KIRKWOOD_RECCTL); | 426 | value = readl(priv->io + KIRKWOOD_RECCTL); |
414 | value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); | 427 | value &= ~KIRKWOOD_RECCTL_ENABLE_MASK; |
415 | writel(value, priv->io + KIRKWOOD_RECCTL); | 428 | writel(value, priv->io + KIRKWOOD_RECCTL); |
416 | 429 | ||
417 | return 0; | 430 | return 0; |
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c deleted file mode 100644 index 65f2a5b9ec3b..000000000000 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ /dev/null | |||
@@ -1,109 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-openrd.c | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <apatard@mandriva.com> | ||
5 | * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
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/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <linux/platform_data/asoc-kirkwood.h> | ||
20 | #include "../codecs/cs42l51.h" | ||
21 | |||
22 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, | ||
23 | struct snd_pcm_hw_params *params) | ||
24 | { | ||
25 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
26 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
27 | unsigned int freq; | ||
28 | |||
29 | switch (params_rate(params)) { | ||
30 | default: | ||
31 | case 44100: | ||
32 | freq = 11289600; | ||
33 | break; | ||
34 | case 48000: | ||
35 | freq = 12288000; | ||
36 | break; | ||
37 | case 96000: | ||
38 | freq = 24576000; | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); | ||
43 | |||
44 | } | ||
45 | |||
46 | static struct snd_soc_ops openrd_client_ops = { | ||
47 | .hw_params = openrd_client_hw_params, | ||
48 | }; | ||
49 | |||
50 | |||
51 | static struct snd_soc_dai_link openrd_client_dai[] = { | ||
52 | { | ||
53 | .name = "CS42L51", | ||
54 | .stream_name = "CS42L51 HiFi", | ||
55 | .cpu_dai_name = "i2s", | ||
56 | .platform_name = "mvebu-audio", | ||
57 | .codec_dai_name = "cs42l51-hifi", | ||
58 | .codec_name = "cs42l51-codec.0-004a", | ||
59 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
60 | .ops = &openrd_client_ops, | ||
61 | }, | ||
62 | }; | ||
63 | |||
64 | |||
65 | static struct snd_soc_card openrd_client = { | ||
66 | .name = "OpenRD Client", | ||
67 | .owner = THIS_MODULE, | ||
68 | .dai_link = openrd_client_dai, | ||
69 | .num_links = ARRAY_SIZE(openrd_client_dai), | ||
70 | }; | ||
71 | |||
72 | static int openrd_probe(struct platform_device *pdev) | ||
73 | { | ||
74 | struct snd_soc_card *card = &openrd_client; | ||
75 | int ret; | ||
76 | |||
77 | card->dev = &pdev->dev; | ||
78 | |||
79 | ret = snd_soc_register_card(card); | ||
80 | if (ret) | ||
81 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
82 | ret); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int openrd_remove(struct platform_device *pdev) | ||
87 | { | ||
88 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
89 | |||
90 | snd_soc_unregister_card(card); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct platform_driver openrd_driver = { | ||
95 | .driver = { | ||
96 | .name = "openrd-client-audio", | ||
97 | .owner = THIS_MODULE, | ||
98 | }, | ||
99 | .probe = openrd_probe, | ||
100 | .remove = openrd_remove, | ||
101 | }; | ||
102 | |||
103 | module_platform_driver(openrd_driver); | ||
104 | |||
105 | /* Module information */ | ||
106 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | ||
107 | MODULE_DESCRIPTION("ALSA SoC OpenRD Client"); | ||
108 | MODULE_LICENSE("GPL"); | ||
109 | MODULE_ALIAS("platform:openrd-client-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c deleted file mode 100644 index 844b8415a011..000000000000 --- a/sound/soc/kirkwood/kirkwood-t5325.c +++ /dev/null | |||
@@ -1,116 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-t5325.c | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
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 <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <linux/platform_data/asoc-kirkwood.h> | ||
19 | #include "../codecs/alc5623.h" | ||
20 | |||
21 | static int t5325_hw_params(struct snd_pcm_substream *substream, | ||
22 | struct snd_pcm_hw_params *params) | ||
23 | { | ||
24 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
25 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
26 | unsigned int freq; | ||
27 | |||
28 | freq = params_rate(params) * 256; | ||
29 | |||
30 | return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); | ||
31 | |||
32 | } | ||
33 | |||
34 | static struct snd_soc_ops t5325_ops = { | ||
35 | .hw_params = t5325_hw_params, | ||
36 | }; | ||
37 | |||
38 | static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = { | ||
39 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
40 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
41 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
42 | }; | ||
43 | |||
44 | static const struct snd_soc_dapm_route t5325_route[] = { | ||
45 | { "Headphone Jack", NULL, "HPL" }, | ||
46 | { "Headphone Jack", NULL, "HPR" }, | ||
47 | |||
48 | {"Speaker", NULL, "SPKOUT"}, | ||
49 | {"Speaker", NULL, "SPKOUTN"}, | ||
50 | |||
51 | { "MIC1", NULL, "Mic Jack" }, | ||
52 | { "MIC2", NULL, "Mic Jack" }, | ||
53 | }; | ||
54 | |||
55 | static struct snd_soc_dai_link t5325_dai[] = { | ||
56 | { | ||
57 | .name = "ALC5621", | ||
58 | .stream_name = "ALC5621 HiFi", | ||
59 | .cpu_dai_name = "i2s", | ||
60 | .platform_name = "mvebu-audio", | ||
61 | .codec_dai_name = "alc5621-hifi", | ||
62 | .codec_name = "alc562x-codec.0-001a", | ||
63 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
64 | .ops = &t5325_ops, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static struct snd_soc_card t5325 = { | ||
69 | .name = "t5325", | ||
70 | .owner = THIS_MODULE, | ||
71 | .dai_link = t5325_dai, | ||
72 | .num_links = ARRAY_SIZE(t5325_dai), | ||
73 | |||
74 | .dapm_widgets = t5325_dapm_widgets, | ||
75 | .num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets), | ||
76 | .dapm_routes = t5325_route, | ||
77 | .num_dapm_routes = ARRAY_SIZE(t5325_route), | ||
78 | }; | ||
79 | |||
80 | static int t5325_probe(struct platform_device *pdev) | ||
81 | { | ||
82 | struct snd_soc_card *card = &t5325; | ||
83 | int ret; | ||
84 | |||
85 | card->dev = &pdev->dev; | ||
86 | |||
87 | ret = snd_soc_register_card(card); | ||
88 | if (ret) | ||
89 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
90 | ret); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static int t5325_remove(struct platform_device *pdev) | ||
95 | { | ||
96 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
97 | |||
98 | snd_soc_unregister_card(card); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static struct platform_driver t5325_driver = { | ||
103 | .driver = { | ||
104 | .name = "t5325-audio", | ||
105 | .owner = THIS_MODULE, | ||
106 | }, | ||
107 | .probe = t5325_probe, | ||
108 | .remove = t5325_remove, | ||
109 | }; | ||
110 | |||
111 | module_platform_driver(t5325_driver); | ||
112 | |||
113 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | ||
114 | MODULE_DESCRIPTION("ALSA SoC t5325 audio client"); | ||
115 | MODULE_LICENSE("GPL"); | ||
116 | MODULE_ALIAS("platform:t5325-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h index bf23afbba1d7..90e32a781424 100644 --- a/sound/soc/kirkwood/kirkwood.h +++ b/sound/soc/kirkwood/kirkwood.h | |||
@@ -38,6 +38,9 @@ | |||
38 | #define KIRKWOOD_RECCTL_SIZE_24 (1<<0) | 38 | #define KIRKWOOD_RECCTL_SIZE_24 (1<<0) |
39 | #define KIRKWOOD_RECCTL_SIZE_32 (0<<0) | 39 | #define KIRKWOOD_RECCTL_SIZE_32 (0<<0) |
40 | 40 | ||
41 | #define KIRKWOOD_RECCTL_ENABLE_MASK (KIRKWOOD_RECCTL_SPDIF_EN | \ | ||
42 | KIRKWOOD_RECCTL_I2S_EN) | ||
43 | |||
41 | #define KIRKWOOD_REC_BUF_ADDR 0x1004 | 44 | #define KIRKWOOD_REC_BUF_ADDR 0x1004 |
42 | #define KIRKWOOD_REC_BUF_SIZE 0x1008 | 45 | #define KIRKWOOD_REC_BUF_SIZE 0x1008 |
43 | #define KIRKWOOD_REC_BYTE_COUNT 0x100C | 46 | #define KIRKWOOD_REC_BYTE_COUNT 0x100C |
@@ -121,9 +124,9 @@ | |||
121 | 124 | ||
122 | /* Theses values come from the marvell alsa driver */ | 125 | /* Theses values come from the marvell alsa driver */ |
123 | /* need to find where they come from */ | 126 | /* need to find where they come from */ |
124 | #define KIRKWOOD_SND_MIN_PERIODS 8 | 127 | #define KIRKWOOD_SND_MIN_PERIODS 2 |
125 | #define KIRKWOOD_SND_MAX_PERIODS 16 | 128 | #define KIRKWOOD_SND_MAX_PERIODS 16 |
126 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x800 | 129 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 256 |
127 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000 | 130 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000 |
128 | #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ | 131 | #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ |
129 | * KIRKWOOD_SND_MAX_PERIODS) | 132 | * KIRKWOOD_SND_MAX_PERIODS) |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 0cc41f94de4e..8c9cc64a9dfb 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -301,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty) | |||
301 | static void cx81801_close(struct tty_struct *tty) | 301 | static void cx81801_close(struct tty_struct *tty) |
302 | { | 302 | { |
303 | struct snd_soc_codec *codec = tty->disc_data; | 303 | struct snd_soc_codec *codec = tty->disc_data; |
304 | struct snd_soc_dapm_context *dapm = &codec->card->dapm; | 304 | struct snd_soc_dapm_context *dapm = &codec->component.card->dapm; |
305 | 305 | ||
306 | del_timer_sync(&cx81801_timer); | 306 | del_timer_sync(&cx81801_timer); |
307 | 307 | ||
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 6925d7141215..0f34e28a3d55 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -466,7 +466,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
466 | 466 | ||
467 | mutex_init(&dmic->mutex); | 467 | mutex_init(&dmic->mutex); |
468 | 468 | ||
469 | dmic->fclk = clk_get(dmic->dev, "fck"); | 469 | dmic->fclk = devm_clk_get(dmic->dev, "fck"); |
470 | if (IS_ERR(dmic->fclk)) { | 470 | if (IS_ERR(dmic->fclk)) { |
471 | dev_err(dmic->dev, "cant get fck\n"); | 471 | dev_err(dmic->dev, "cant get fck\n"); |
472 | return -ENODEV; | 472 | return -ENODEV; |
@@ -475,8 +475,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
475 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); | 475 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); |
476 | if (!res) { | 476 | if (!res) { |
477 | dev_err(dmic->dev, "invalid dma memory resource\n"); | 477 | dev_err(dmic->dev, "invalid dma memory resource\n"); |
478 | ret = -ENODEV; | 478 | return -ENODEV; |
479 | goto err_put_clk; | ||
480 | } | 479 | } |
481 | dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; | 480 | dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; |
482 | 481 | ||
@@ -484,34 +483,19 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
484 | 483 | ||
485 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 484 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
486 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); | 485 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); |
487 | if (IS_ERR(dmic->io_base)) { | 486 | if (IS_ERR(dmic->io_base)) |
488 | ret = PTR_ERR(dmic->io_base); | 487 | return PTR_ERR(dmic->io_base); |
489 | goto err_put_clk; | ||
490 | } | ||
491 | 488 | ||
492 | 489 | ||
493 | ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, | 490 | ret = devm_snd_soc_register_component(&pdev->dev, |
494 | &omap_dmic_dai, 1); | 491 | &omap_dmic_component, |
492 | &omap_dmic_dai, 1); | ||
495 | if (ret) | 493 | if (ret) |
496 | goto err_put_clk; | 494 | return ret; |
497 | 495 | ||
498 | ret = omap_pcm_platform_register(&pdev->dev); | 496 | ret = omap_pcm_platform_register(&pdev->dev); |
499 | if (ret) | 497 | if (ret) |
500 | goto err_put_clk; | 498 | return ret; |
501 | |||
502 | return 0; | ||
503 | |||
504 | err_put_clk: | ||
505 | clk_put(dmic->fclk); | ||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | static int asoc_dmic_remove(struct platform_device *pdev) | ||
510 | { | ||
511 | struct omap_dmic *dmic = platform_get_drvdata(pdev); | ||
512 | |||
513 | snd_soc_unregister_component(&pdev->dev); | ||
514 | clk_put(dmic->fclk); | ||
515 | 499 | ||
516 | return 0; | 500 | return 0; |
517 | } | 501 | } |
@@ -529,7 +513,6 @@ static struct platform_driver asoc_dmic_driver = { | |||
529 | .of_match_table = omap_dmic_of_match, | 513 | .of_match_table = omap_dmic_of_match, |
530 | }, | 514 | }, |
531 | .probe = asoc_dmic_probe, | 515 | .probe = asoc_dmic_probe, |
532 | .remove = asoc_dmic_remove, | ||
533 | }; | 516 | }; |
534 | 517 | ||
535 | module_platform_driver(asoc_dmic_driver); | 518 | module_platform_driver(asoc_dmic_driver); |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index efe2cd699b77..bd3ef2a88be0 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -805,8 +805,9 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) | |||
805 | if (ret) | 805 | if (ret) |
806 | return ret; | 806 | return ret; |
807 | 807 | ||
808 | ret = snd_soc_register_component(&pdev->dev, &omap_mcbsp_component, | 808 | ret = devm_snd_soc_register_component(&pdev->dev, |
809 | &omap_mcbsp_dai, 1); | 809 | &omap_mcbsp_component, |
810 | &omap_mcbsp_dai, 1); | ||
810 | if (ret) | 811 | if (ret) |
811 | return ret; | 812 | return ret; |
812 | 813 | ||
@@ -817,8 +818,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) | |||
817 | { | 818 | { |
818 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); | 819 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); |
819 | 820 | ||
820 | snd_soc_unregister_component(&pdev->dev); | ||
821 | |||
822 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 821 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
823 | mcbsp->pdata->ops->free(mcbsp->id); | 822 | mcbsp->pdata->ops->free(mcbsp->id); |
824 | 823 | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 8d809f8509c8..f4b05bc23e4b 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
32 | #include <sound/dmaengine_pcm.h> | 32 | #include <sound/dmaengine_pcm.h> |
33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
34 | #include <sound/omap-pcm.h> | ||
34 | 35 | ||
35 | #ifdef CONFIG_ARCH_OMAP1 | 36 | #ifdef CONFIG_ARCH_OMAP1 |
36 | #define pcm_omap1510() cpu_is_omap1510() | 37 | #define pcm_omap1510() cpu_is_omap1510() |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 199a8b377553..0109f6c2334e 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -723,7 +723,8 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) | |||
723 | ssp_handle = of_parse_phandle(dev->of_node, "port", 0); | 723 | ssp_handle = of_parse_phandle(dev->of_node, "port", 0); |
724 | if (!ssp_handle) { | 724 | if (!ssp_handle) { |
725 | dev_err(dev, "unable to get 'port' phandle\n"); | 725 | dev_err(dev, "unable to get 'port' phandle\n"); |
726 | return -ENODEV; | 726 | ret = -ENODEV; |
727 | goto err_priv; | ||
727 | } | 728 | } |
728 | 729 | ||
729 | priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); | 730 | priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig new file mode 100644 index 000000000000..c196a466eef6 --- /dev/null +++ b/sound/soc/rockchip/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config SND_SOC_ROCKCHIP | ||
2 | tristate "ASoC support for Rockchip" | ||
3 | depends on COMPILE_TEST || ARCH_ROCKCHIP | ||
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
5 | select SND_ROCKCHIP_I2S | ||
6 | help | ||
7 | Say Y or M if you want to add support for codecs attached to | ||
8 | the Rockchip SoCs' Audio interfaces. You will also need to | ||
9 | select the audio interfaces to support below. | ||
10 | |||
11 | config SND_ROCKCHIP_I2S | ||
12 | tristate | ||
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile new file mode 100644 index 000000000000..1006418e1394 --- /dev/null +++ b/sound/soc/rockchip/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # ROCKCHIP Platform Support | ||
2 | snd-soc-i2s-objs := rockchip_i2s.o | ||
3 | |||
4 | obj-$(CONFIG_SND_ROCKCHIP_I2S) += snd-soc-i2s.o | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c new file mode 100644 index 000000000000..8d8e4b59049f --- /dev/null +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -0,0 +1,529 @@ | |||
1 | /* sound/soc/rockchip/rockchip_i2s.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver | ||
4 | * | ||
5 | * Copyright (c) 2014 Rockchip Electronics Co. Ltd. | ||
6 | * Author: Jianqun <jay.xu@rock-chips.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/delay.h> | ||
15 | #include <linux/of_gpio.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/pm_runtime.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/dmaengine_pcm.h> | ||
21 | |||
22 | #include "rockchip_i2s.h" | ||
23 | |||
24 | #define DRV_NAME "rockchip-i2s" | ||
25 | |||
26 | struct rk_i2s_dev { | ||
27 | struct device *dev; | ||
28 | |||
29 | struct clk *hclk; | ||
30 | struct clk *mclk; | ||
31 | |||
32 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
33 | struct snd_dmaengine_dai_dma_data playback_dma_data; | ||
34 | |||
35 | struct regmap *regmap; | ||
36 | |||
37 | /* | ||
38 | * Used to indicate the tx/rx status. | ||
39 | * I2S controller hopes to start the tx and rx together, | ||
40 | * also to stop them when they are both try to stop. | ||
41 | */ | ||
42 | bool tx_start; | ||
43 | bool rx_start; | ||
44 | }; | ||
45 | |||
46 | static int i2s_runtime_suspend(struct device *dev) | ||
47 | { | ||
48 | struct rk_i2s_dev *i2s = dev_get_drvdata(dev); | ||
49 | |||
50 | clk_disable_unprepare(i2s->mclk); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int i2s_runtime_resume(struct device *dev) | ||
56 | { | ||
57 | struct rk_i2s_dev *i2s = dev_get_drvdata(dev); | ||
58 | int ret; | ||
59 | |||
60 | ret = clk_prepare_enable(i2s->mclk); | ||
61 | if (ret) { | ||
62 | dev_err(i2s->dev, "clock enable failed %d\n", ret); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) | ||
70 | { | ||
71 | return snd_soc_dai_get_drvdata(dai); | ||
72 | } | ||
73 | |||
74 | static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) | ||
75 | { | ||
76 | unsigned int val = 0; | ||
77 | int retry = 10; | ||
78 | |||
79 | if (on) { | ||
80 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
81 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); | ||
82 | |||
83 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
84 | I2S_XFER_TXS_START | I2S_XFER_RXS_START, | ||
85 | I2S_XFER_TXS_START | I2S_XFER_RXS_START); | ||
86 | |||
87 | i2s->tx_start = true; | ||
88 | } else { | ||
89 | i2s->tx_start = false; | ||
90 | |||
91 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
92 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); | ||
93 | |||
94 | if (!i2s->rx_start) { | ||
95 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
96 | I2S_XFER_TXS_START | | ||
97 | I2S_XFER_RXS_START, | ||
98 | I2S_XFER_TXS_STOP | | ||
99 | I2S_XFER_RXS_STOP); | ||
100 | |||
101 | regmap_update_bits(i2s->regmap, I2S_CLR, | ||
102 | I2S_CLR_TXC | I2S_CLR_RXC, | ||
103 | I2S_CLR_TXC | I2S_CLR_RXC); | ||
104 | |||
105 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
106 | |||
107 | /* Should wait for clear operation to finish */ | ||
108 | while (val) { | ||
109 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
110 | retry--; | ||
111 | if (!retry) | ||
112 | dev_warn(i2s->dev, "fail to clear\n"); | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) | ||
119 | { | ||
120 | unsigned int val = 0; | ||
121 | int retry = 10; | ||
122 | |||
123 | if (on) { | ||
124 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
125 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); | ||
126 | |||
127 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
128 | I2S_XFER_TXS_START | I2S_XFER_RXS_START, | ||
129 | I2S_XFER_TXS_START | I2S_XFER_RXS_START); | ||
130 | |||
131 | i2s->rx_start = true; | ||
132 | } else { | ||
133 | i2s->rx_start = false; | ||
134 | |||
135 | regmap_update_bits(i2s->regmap, I2S_DMACR, | ||
136 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); | ||
137 | |||
138 | if (!i2s->tx_start) { | ||
139 | regmap_update_bits(i2s->regmap, I2S_XFER, | ||
140 | I2S_XFER_TXS_START | | ||
141 | I2S_XFER_RXS_START, | ||
142 | I2S_XFER_TXS_STOP | | ||
143 | I2S_XFER_RXS_STOP); | ||
144 | |||
145 | regmap_update_bits(i2s->regmap, I2S_CLR, | ||
146 | I2S_CLR_TXC | I2S_CLR_RXC, | ||
147 | I2S_CLR_TXC | I2S_CLR_RXC); | ||
148 | |||
149 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
150 | |||
151 | /* Should wait for clear operation to finish */ | ||
152 | while (val) { | ||
153 | regmap_read(i2s->regmap, I2S_CLR, &val); | ||
154 | retry--; | ||
155 | if (!retry) | ||
156 | dev_warn(i2s->dev, "fail to clear\n"); | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||
163 | unsigned int fmt) | ||
164 | { | ||
165 | struct rk_i2s_dev *i2s = to_info(cpu_dai); | ||
166 | unsigned int mask = 0, val = 0; | ||
167 | |||
168 | mask = I2S_CKR_MSS_SLAVE; | ||
169 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
170 | case SND_SOC_DAIFMT_CBS_CFS: | ||
171 | val = I2S_CKR_MSS_SLAVE; | ||
172 | break; | ||
173 | case SND_SOC_DAIFMT_CBM_CFM: | ||
174 | val = I2S_CKR_MSS_MASTER; | ||
175 | break; | ||
176 | default: | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); | ||
181 | |||
182 | mask = I2S_TXCR_IBM_MASK; | ||
183 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
184 | case SND_SOC_DAIFMT_RIGHT_J: | ||
185 | val = I2S_TXCR_IBM_RSJM; | ||
186 | break; | ||
187 | case SND_SOC_DAIFMT_LEFT_J: | ||
188 | val = I2S_TXCR_IBM_LSJM; | ||
189 | break; | ||
190 | case SND_SOC_DAIFMT_I2S: | ||
191 | val = I2S_TXCR_IBM_NORMAL; | ||
192 | break; | ||
193 | default: | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); | ||
198 | |||
199 | mask = I2S_RXCR_IBM_MASK; | ||
200 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
201 | case SND_SOC_DAIFMT_RIGHT_J: | ||
202 | val = I2S_RXCR_IBM_RSJM; | ||
203 | break; | ||
204 | case SND_SOC_DAIFMT_LEFT_J: | ||
205 | val = I2S_RXCR_IBM_LSJM; | ||
206 | break; | ||
207 | case SND_SOC_DAIFMT_I2S: | ||
208 | val = I2S_RXCR_IBM_NORMAL; | ||
209 | break; | ||
210 | default: | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | ||
220 | struct snd_pcm_hw_params *params, | ||
221 | struct snd_soc_dai *dai) | ||
222 | { | ||
223 | struct rk_i2s_dev *i2s = to_info(dai); | ||
224 | unsigned int val = 0; | ||
225 | |||
226 | switch (params_format(params)) { | ||
227 | case SNDRV_PCM_FORMAT_S8: | ||
228 | val |= I2S_TXCR_VDW(8); | ||
229 | break; | ||
230 | case SNDRV_PCM_FORMAT_S16_LE: | ||
231 | val |= I2S_TXCR_VDW(16); | ||
232 | break; | ||
233 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
234 | val |= I2S_TXCR_VDW(20); | ||
235 | break; | ||
236 | case SNDRV_PCM_FORMAT_S24_LE: | ||
237 | val |= I2S_TXCR_VDW(24); | ||
238 | break; | ||
239 | default: | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); | ||
244 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); | ||
245 | |||
246 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
247 | dai->playback_dma_data = &i2s->playback_dma_data; | ||
248 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, | ||
249 | I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE); | ||
250 | } else { | ||
251 | dai->capture_dma_data = &i2s->capture_dma_data; | ||
252 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, | ||
253 | I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE); | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, | ||
260 | int cmd, struct snd_soc_dai *dai) | ||
261 | { | ||
262 | struct rk_i2s_dev *i2s = to_info(dai); | ||
263 | int ret = 0; | ||
264 | |||
265 | switch (cmd) { | ||
266 | case SNDRV_PCM_TRIGGER_START: | ||
267 | case SNDRV_PCM_TRIGGER_RESUME: | ||
268 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
269 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
270 | rockchip_snd_rxctrl(i2s, 1); | ||
271 | else | ||
272 | rockchip_snd_txctrl(i2s, 1); | ||
273 | break; | ||
274 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
275 | case SNDRV_PCM_TRIGGER_STOP: | ||
276 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
277 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
278 | rockchip_snd_rxctrl(i2s, 0); | ||
279 | else | ||
280 | rockchip_snd_txctrl(i2s, 0); | ||
281 | break; | ||
282 | default: | ||
283 | ret = -EINVAL; | ||
284 | break; | ||
285 | } | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | ||
291 | unsigned int freq, int dir) | ||
292 | { | ||
293 | struct rk_i2s_dev *i2s = to_info(cpu_dai); | ||
294 | int ret; | ||
295 | |||
296 | ret = clk_set_rate(i2s->mclk, freq); | ||
297 | if (ret) | ||
298 | dev_err(i2s->dev, "Fail to set mclk %d\n", ret); | ||
299 | |||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { | ||
304 | .hw_params = rockchip_i2s_hw_params, | ||
305 | .set_sysclk = rockchip_i2s_set_sysclk, | ||
306 | .set_fmt = rockchip_i2s_set_fmt, | ||
307 | .trigger = rockchip_i2s_trigger, | ||
308 | }; | ||
309 | |||
310 | static struct snd_soc_dai_driver rockchip_i2s_dai = { | ||
311 | .playback = { | ||
312 | .channels_min = 2, | ||
313 | .channels_max = 8, | ||
314 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
315 | .formats = (SNDRV_PCM_FMTBIT_S8 | | ||
316 | SNDRV_PCM_FMTBIT_S16_LE | | ||
317 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
318 | SNDRV_PCM_FMTBIT_S24_LE), | ||
319 | }, | ||
320 | .capture = { | ||
321 | .channels_min = 2, | ||
322 | .channels_max = 2, | ||
323 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
324 | .formats = (SNDRV_PCM_FMTBIT_S8 | | ||
325 | SNDRV_PCM_FMTBIT_S16_LE | | ||
326 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
327 | SNDRV_PCM_FMTBIT_S24_LE), | ||
328 | }, | ||
329 | .ops = &rockchip_i2s_dai_ops, | ||
330 | }; | ||
331 | |||
332 | static const struct snd_soc_component_driver rockchip_i2s_component = { | ||
333 | .name = DRV_NAME, | ||
334 | }; | ||
335 | |||
336 | static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg) | ||
337 | { | ||
338 | switch (reg) { | ||
339 | case I2S_TXCR: | ||
340 | case I2S_RXCR: | ||
341 | case I2S_CKR: | ||
342 | case I2S_DMACR: | ||
343 | case I2S_INTCR: | ||
344 | case I2S_XFER: | ||
345 | case I2S_CLR: | ||
346 | case I2S_TXDR: | ||
347 | return true; | ||
348 | default: | ||
349 | return false; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) | ||
354 | { | ||
355 | switch (reg) { | ||
356 | case I2S_TXCR: | ||
357 | case I2S_RXCR: | ||
358 | case I2S_CKR: | ||
359 | case I2S_DMACR: | ||
360 | case I2S_INTCR: | ||
361 | case I2S_XFER: | ||
362 | case I2S_CLR: | ||
363 | case I2S_RXDR: | ||
364 | return true; | ||
365 | default: | ||
366 | return false; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
371 | { | ||
372 | switch (reg) { | ||
373 | case I2S_FIFOLR: | ||
374 | case I2S_INTSR: | ||
375 | return true; | ||
376 | default: | ||
377 | return false; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) | ||
382 | { | ||
383 | switch (reg) { | ||
384 | case I2S_FIFOLR: | ||
385 | return true; | ||
386 | default: | ||
387 | return false; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | static const struct regmap_config rockchip_i2s_regmap_config = { | ||
392 | .reg_bits = 32, | ||
393 | .reg_stride = 4, | ||
394 | .val_bits = 32, | ||
395 | .max_register = I2S_RXDR, | ||
396 | .writeable_reg = rockchip_i2s_wr_reg, | ||
397 | .readable_reg = rockchip_i2s_rd_reg, | ||
398 | .volatile_reg = rockchip_i2s_volatile_reg, | ||
399 | .precious_reg = rockchip_i2s_precious_reg, | ||
400 | .cache_type = REGCACHE_FLAT, | ||
401 | }; | ||
402 | |||
403 | static int rockchip_i2s_probe(struct platform_device *pdev) | ||
404 | { | ||
405 | struct rk_i2s_dev *i2s; | ||
406 | struct resource *res; | ||
407 | void __iomem *regs; | ||
408 | int ret; | ||
409 | |||
410 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | ||
411 | if (!i2s) { | ||
412 | dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n"); | ||
413 | return -ENOMEM; | ||
414 | } | ||
415 | |||
416 | /* try to prepare related clocks */ | ||
417 | i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); | ||
418 | if (IS_ERR(i2s->hclk)) { | ||
419 | dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n"); | ||
420 | return PTR_ERR(i2s->hclk); | ||
421 | } | ||
422 | |||
423 | i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); | ||
424 | if (IS_ERR(i2s->mclk)) { | ||
425 | dev_err(&pdev->dev, "Can't retrieve i2s master clock\n"); | ||
426 | return PTR_ERR(i2s->mclk); | ||
427 | } | ||
428 | |||
429 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
430 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
431 | if (IS_ERR(regs)) | ||
432 | return PTR_ERR(regs); | ||
433 | |||
434 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | ||
435 | &rockchip_i2s_regmap_config); | ||
436 | if (IS_ERR(i2s->regmap)) { | ||
437 | dev_err(&pdev->dev, | ||
438 | "Failed to initialise managed register map\n"); | ||
439 | return PTR_ERR(i2s->regmap); | ||
440 | } | ||
441 | |||
442 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; | ||
443 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
444 | i2s->playback_dma_data.maxburst = 16; | ||
445 | |||
446 | i2s->capture_dma_data.addr = res->start + I2S_RXDR; | ||
447 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
448 | i2s->capture_dma_data.maxburst = 16; | ||
449 | |||
450 | i2s->dev = &pdev->dev; | ||
451 | dev_set_drvdata(&pdev->dev, i2s); | ||
452 | |||
453 | pm_runtime_enable(&pdev->dev); | ||
454 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
455 | ret = i2s_runtime_resume(&pdev->dev); | ||
456 | if (ret) | ||
457 | goto err_pm_disable; | ||
458 | } | ||
459 | |||
460 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
461 | &rockchip_i2s_component, | ||
462 | &rockchip_i2s_dai, 1); | ||
463 | if (ret) { | ||
464 | dev_err(&pdev->dev, "Could not register DAI\n"); | ||
465 | goto err_suspend; | ||
466 | } | ||
467 | |||
468 | ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
469 | if (ret) { | ||
470 | dev_err(&pdev->dev, "Could not register PCM\n"); | ||
471 | goto err_pcm_register; | ||
472 | } | ||
473 | |||
474 | return 0; | ||
475 | |||
476 | err_pcm_register: | ||
477 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
478 | err_suspend: | ||
479 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
480 | i2s_runtime_suspend(&pdev->dev); | ||
481 | err_pm_disable: | ||
482 | pm_runtime_disable(&pdev->dev); | ||
483 | |||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | static int rockchip_i2s_remove(struct platform_device *pdev) | ||
488 | { | ||
489 | struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev); | ||
490 | |||
491 | pm_runtime_disable(&pdev->dev); | ||
492 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
493 | i2s_runtime_suspend(&pdev->dev); | ||
494 | |||
495 | clk_disable_unprepare(i2s->mclk); | ||
496 | clk_disable_unprepare(i2s->hclk); | ||
497 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
498 | snd_soc_unregister_component(&pdev->dev); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static const struct of_device_id rockchip_i2s_match[] = { | ||
504 | { .compatible = "rockchip,rk3066-i2s", }, | ||
505 | {}, | ||
506 | }; | ||
507 | |||
508 | static const struct dev_pm_ops rockchip_i2s_pm_ops = { | ||
509 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, | ||
510 | NULL) | ||
511 | }; | ||
512 | |||
513 | static struct platform_driver rockchip_i2s_driver = { | ||
514 | .probe = rockchip_i2s_probe, | ||
515 | .remove = rockchip_i2s_remove, | ||
516 | .driver = { | ||
517 | .name = DRV_NAME, | ||
518 | .owner = THIS_MODULE, | ||
519 | .of_match_table = of_match_ptr(rockchip_i2s_match), | ||
520 | .pm = &rockchip_i2s_pm_ops, | ||
521 | }, | ||
522 | }; | ||
523 | module_platform_driver(rockchip_i2s_driver); | ||
524 | |||
525 | MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); | ||
526 | MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>"); | ||
527 | MODULE_LICENSE("GPL v2"); | ||
528 | MODULE_ALIAS("platform:" DRV_NAME); | ||
529 | MODULE_DEVICE_TABLE(of, rockchip_i2s_match); | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h new file mode 100644 index 000000000000..89a5d8bc6ee7 --- /dev/null +++ b/sound/soc/rockchip/rockchip_i2s.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * sound/soc/rockchip/rockchip_i2s.h | ||
3 | * | ||
4 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver | ||
5 | * | ||
6 | * Copyright (c) 2014 Rockchip Electronics Co. Ltd. | ||
7 | * Author: Jianqun xu <jay.xu@rock-chips.com> | ||
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 | #ifndef _ROCKCHIP_IIS_H | ||
15 | #define _ROCKCHIP_IIS_H | ||
16 | |||
17 | /* | ||
18 | * TXCR | ||
19 | * transmit operation control register | ||
20 | */ | ||
21 | #define I2S_TXCR_RCNT_SHIFT 17 | ||
22 | #define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT) | ||
23 | #define I2S_TXCR_CSR_SHIFT 15 | ||
24 | #define I2S_TXCR_CSR(x) (x << I2S_TXCR_CSR_SHIFT) | ||
25 | #define I2S_TXCR_CSR_MASK (3 << I2S_TXCR_CSR_SHIFT) | ||
26 | #define I2S_TXCR_HWT BIT(14) | ||
27 | #define I2S_TXCR_SJM_SHIFT 12 | ||
28 | #define I2S_TXCR_SJM_R (0 << I2S_TXCR_SJM_SHIFT) | ||
29 | #define I2S_TXCR_SJM_L (1 << I2S_TXCR_SJM_SHIFT) | ||
30 | #define I2S_TXCR_FBM_SHIFT 11 | ||
31 | #define I2S_TXCR_FBM_MSB (0 << I2S_TXCR_FBM_SHIFT) | ||
32 | #define I2S_TXCR_FBM_LSB (1 << I2S_TXCR_FBM_SHIFT) | ||
33 | #define I2S_TXCR_IBM_SHIFT 9 | ||
34 | #define I2S_TXCR_IBM_NORMAL (0 << I2S_TXCR_IBM_SHIFT) | ||
35 | #define I2S_TXCR_IBM_LSJM (1 << I2S_TXCR_IBM_SHIFT) | ||
36 | #define I2S_TXCR_IBM_RSJM (2 << I2S_TXCR_IBM_SHIFT) | ||
37 | #define I2S_TXCR_IBM_MASK (3 << I2S_TXCR_IBM_SHIFT) | ||
38 | #define I2S_TXCR_PBM_SHIFT 7 | ||
39 | #define I2S_TXCR_PBM_MODE(x) (x << I2S_TXCR_PBM_SHIFT) | ||
40 | #define I2S_TXCR_PBM_MASK (3 << I2S_TXCR_PBM_SHIFT) | ||
41 | #define I2S_TXCR_TFS_SHIFT 5 | ||
42 | #define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) | ||
43 | #define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) | ||
44 | #define I2S_TXCR_VDW_SHIFT 0 | ||
45 | #define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) | ||
46 | #define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) | ||
47 | |||
48 | /* | ||
49 | * RXCR | ||
50 | * receive operation control register | ||
51 | */ | ||
52 | #define I2S_RXCR_HWT BIT(14) | ||
53 | #define I2S_RXCR_SJM_SHIFT 12 | ||
54 | #define I2S_RXCR_SJM_R (0 << I2S_RXCR_SJM_SHIFT) | ||
55 | #define I2S_RXCR_SJM_L (1 << I2S_RXCR_SJM_SHIFT) | ||
56 | #define I2S_RXCR_FBM_SHIFT 11 | ||
57 | #define I2S_RXCR_FBM_MSB (0 << I2S_RXCR_FBM_SHIFT) | ||
58 | #define I2S_RXCR_FBM_LSB (1 << I2S_RXCR_FBM_SHIFT) | ||
59 | #define I2S_RXCR_IBM_SHIFT 9 | ||
60 | #define I2S_RXCR_IBM_NORMAL (0 << I2S_RXCR_IBM_SHIFT) | ||
61 | #define I2S_RXCR_IBM_LSJM (1 << I2S_RXCR_IBM_SHIFT) | ||
62 | #define I2S_RXCR_IBM_RSJM (2 << I2S_RXCR_IBM_SHIFT) | ||
63 | #define I2S_RXCR_IBM_MASK (3 << I2S_RXCR_IBM_SHIFT) | ||
64 | #define I2S_RXCR_PBM_SHIFT 7 | ||
65 | #define I2S_RXCR_PBM_MODE(x) (x << I2S_RXCR_PBM_SHIFT) | ||
66 | #define I2S_RXCR_PBM_MASK (3 << I2S_RXCR_PBM_SHIFT) | ||
67 | #define I2S_RXCR_TFS_SHIFT 5 | ||
68 | #define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) | ||
69 | #define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) | ||
70 | #define I2S_RXCR_VDW_SHIFT 0 | ||
71 | #define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) | ||
72 | #define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) | ||
73 | |||
74 | /* | ||
75 | * CKR | ||
76 | * clock generation register | ||
77 | */ | ||
78 | #define I2S_CKR_MSS_SHIFT 27 | ||
79 | #define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT) | ||
80 | #define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) | ||
81 | #define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) | ||
82 | #define I2S_CKR_CKP_SHIFT 26 | ||
83 | #define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) | ||
84 | #define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) | ||
85 | #define I2S_CKR_RLP_SHIFT 25 | ||
86 | #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) | ||
87 | #define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) | ||
88 | #define I2S_CKR_TLP_SHIFT 24 | ||
89 | #define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) | ||
90 | #define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) | ||
91 | #define I2S_CKR_MDIV_SHIFT 16 | ||
92 | #define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) | ||
93 | #define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT) | ||
94 | #define I2S_CKR_RSD_SHIFT 8 | ||
95 | #define I2S_CKR_RSD(x) ((x - 1) << I2S_CKR_RSD_SHIFT) | ||
96 | #define I2S_CKR_RSD_MASK (0xff << I2S_CKR_RSD_SHIFT) | ||
97 | #define I2S_CKR_TSD_SHIFT 0 | ||
98 | #define I2S_CKR_TSD(x) ((x - 1) << I2S_CKR_TSD_SHIFT) | ||
99 | #define I2S_CKR_TSD_MASK (0xff << I2S_CKR_TSD_SHIFT) | ||
100 | |||
101 | /* | ||
102 | * FIFOLR | ||
103 | * FIFO level register | ||
104 | */ | ||
105 | #define I2S_FIFOLR_RFL_SHIFT 24 | ||
106 | #define I2S_FIFOLR_RFL_MASK (0x3f << I2S_FIFOLR_RFL_SHIFT) | ||
107 | #define I2S_FIFOLR_TFL3_SHIFT 18 | ||
108 | #define I2S_FIFOLR_TFL3_MASK (0x3f << I2S_FIFOLR_TFL3_SHIFT) | ||
109 | #define I2S_FIFOLR_TFL2_SHIFT 12 | ||
110 | #define I2S_FIFOLR_TFL2_MASK (0x3f << I2S_FIFOLR_TFL2_SHIFT) | ||
111 | #define I2S_FIFOLR_TFL1_SHIFT 6 | ||
112 | #define I2S_FIFOLR_TFL1_MASK (0x3f << I2S_FIFOLR_TFL1_SHIFT) | ||
113 | #define I2S_FIFOLR_TFL0_SHIFT 0 | ||
114 | #define I2S_FIFOLR_TFL0_MASK (0x3f << I2S_FIFOLR_TFL0_SHIFT) | ||
115 | |||
116 | /* | ||
117 | * DMACR | ||
118 | * DMA control register | ||
119 | */ | ||
120 | #define I2S_DMACR_RDE_SHIFT 24 | ||
121 | #define I2S_DMACR_RDE_DISABLE (0 << I2S_DMACR_RDE_SHIFT) | ||
122 | #define I2S_DMACR_RDE_ENABLE (1 << I2S_DMACR_RDE_SHIFT) | ||
123 | #define I2S_DMACR_RDL_SHIFT 16 | ||
124 | #define I2S_DMACR_RDL(x) ((x - 1) << I2S_DMACR_RDL_SHIFT) | ||
125 | #define I2S_DMACR_RDL_MASK (0x1f << I2S_DMACR_RDL_SHIFT) | ||
126 | #define I2S_DMACR_TDE_SHIFT 8 | ||
127 | #define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) | ||
128 | #define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) | ||
129 | #define I2S_DMACR_TDL_SHIFT 0 | ||
130 | #define I2S_DMACR_TDL(x) ((x - 1) << I2S_DMACR_TDL_SHIFT) | ||
131 | #define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) | ||
132 | |||
133 | /* | ||
134 | * INTCR | ||
135 | * interrupt control register | ||
136 | */ | ||
137 | #define I2S_INTCR_RFT_SHIFT 20 | ||
138 | #define I2S_INTCR_RFT(x) ((x - 1) << I2S_INTCR_RFT_SHIFT) | ||
139 | #define I2S_INTCR_RXOIC BIT(18) | ||
140 | #define I2S_INTCR_RXOIE_SHIFT 17 | ||
141 | #define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT) | ||
142 | #define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT) | ||
143 | #define I2S_INTCR_RXFIE_SHIFT 16 | ||
144 | #define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT) | ||
145 | #define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT) | ||
146 | #define I2S_INTCR_TFT_SHIFT 4 | ||
147 | #define I2S_INTCR_TFT(x) ((x - 1) << I2S_INTCR_TFT_SHIFT) | ||
148 | #define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT) | ||
149 | #define I2S_INTCR_TXUIC BIT(2) | ||
150 | #define I2S_INTCR_TXUIE_SHIFT 1 | ||
151 | #define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT) | ||
152 | #define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT) | ||
153 | |||
154 | /* | ||
155 | * INTSR | ||
156 | * interrupt status register | ||
157 | */ | ||
158 | #define I2S_INTSR_TXEIE_SHIFT 0 | ||
159 | #define I2S_INTSR_TXEIE_DISABLE (0 << I2S_INTSR_TXEIE_SHIFT) | ||
160 | #define I2S_INTSR_TXEIE_ENABLE (1 << I2S_INTSR_TXEIE_SHIFT) | ||
161 | #define I2S_INTSR_RXOI_SHIFT 17 | ||
162 | #define I2S_INTSR_RXOI_INA (0 << I2S_INTSR_RXOI_SHIFT) | ||
163 | #define I2S_INTSR_RXOI_ACT (1 << I2S_INTSR_RXOI_SHIFT) | ||
164 | #define I2S_INTSR_RXFI_SHIFT 16 | ||
165 | #define I2S_INTSR_RXFI_INA (0 << I2S_INTSR_RXFI_SHIFT) | ||
166 | #define I2S_INTSR_RXFI_ACT (1 << I2S_INTSR_RXFI_SHIFT) | ||
167 | #define I2S_INTSR_TXUI_SHIFT 1 | ||
168 | #define I2S_INTSR_TXUI_INA (0 << I2S_INTSR_TXUI_SHIFT) | ||
169 | #define I2S_INTSR_TXUI_ACT (1 << I2S_INTSR_TXUI_SHIFT) | ||
170 | #define I2S_INTSR_TXEI_SHIFT 0 | ||
171 | #define I2S_INTSR_TXEI_INA (0 << I2S_INTSR_TXEI_SHIFT) | ||
172 | #define I2S_INTSR_TXEI_ACT (1 << I2S_INTSR_TXEI_SHIFT) | ||
173 | |||
174 | /* | ||
175 | * XFER | ||
176 | * Transfer start register | ||
177 | */ | ||
178 | #define I2S_XFER_RXS_SHIFT 1 | ||
179 | #define I2S_XFER_RXS_STOP (0 << I2S_XFER_RXS_SHIFT) | ||
180 | #define I2S_XFER_RXS_START (1 << I2S_XFER_RXS_SHIFT) | ||
181 | #define I2S_XFER_TXS_SHIFT 0 | ||
182 | #define I2S_XFER_TXS_STOP (0 << I2S_XFER_TXS_SHIFT) | ||
183 | #define I2S_XFER_TXS_START (1 << I2S_XFER_TXS_SHIFT) | ||
184 | |||
185 | /* | ||
186 | * CLR | ||
187 | * clear SCLK domain logic register | ||
188 | */ | ||
189 | #define I2S_CLR_RXC BIT(1) | ||
190 | #define I2S_CLR_TXC BIT(0) | ||
191 | |||
192 | /* | ||
193 | * TXDR | ||
194 | * Transimt FIFO data register, write only. | ||
195 | */ | ||
196 | #define I2S_TXDR_MASK (0xff) | ||
197 | |||
198 | /* | ||
199 | * RXDR | ||
200 | * Receive FIFO data register, write only. | ||
201 | */ | ||
202 | #define I2S_RXDR_MASK (0xff) | ||
203 | |||
204 | /* Clock divider id */ | ||
205 | enum { | ||
206 | ROCKCHIP_DIV_MCLK = 0, | ||
207 | ROCKCHIP_DIV_BCLK, | ||
208 | }; | ||
209 | |||
210 | /* I2S REGS */ | ||
211 | #define I2S_TXCR (0x0000) | ||
212 | #define I2S_RXCR (0x0004) | ||
213 | #define I2S_CKR (0x0008) | ||
214 | #define I2S_FIFOLR (0x000c) | ||
215 | #define I2S_DMACR (0x0010) | ||
216 | #define I2S_INTCR (0x0014) | ||
217 | #define I2S_INTSR (0x0018) | ||
218 | #define I2S_XFER (0x001c) | ||
219 | #define I2S_CLR (0x0020) | ||
220 | #define I2S_TXDR (0x0024) | ||
221 | #define I2S_RXDR (0x0028) | ||
222 | |||
223 | #endif /* _ROCKCHIP_IIS_H */ | ||
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig index c74eb3d4a47c..f244a2566f20 100644 --- a/sound/soc/s6000/Kconfig +++ b/sound/soc/s6000/Kconfig | |||
@@ -1,17 +1,24 @@ | |||
1 | config SND_S6000_SOC | 1 | config SND_S6000_SOC |
2 | tristate "SoC Audio for the Stretch s6000 family" | 2 | tristate "SoC Audio for the Stretch s6000 family" |
3 | depends on XTENSA_VARIANT_S6000 | 3 | depends on XTENSA_VARIANT_S6000 || COMPILE_TEST |
4 | depends on HAS_IOMEM | ||
5 | select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000 | ||
4 | help | 6 | help |
5 | Say Y or M if you want to add support for codecs attached to | 7 | Say Y or M if you want to add support for codecs attached to |
6 | s6000 family chips. You will also need to select the platform | 8 | s6000 family chips. You will also need to select the platform |
7 | to support below. | 9 | to support below. |
8 | 10 | ||
11 | config SND_S6000_SOC_PCM | ||
12 | tristate | ||
13 | |||
9 | config SND_S6000_SOC_I2S | 14 | config SND_S6000_SOC_I2S |
10 | tristate | 15 | tristate |
11 | 16 | ||
12 | config SND_S6000_SOC_S6IPCAM | 17 | config SND_S6000_SOC_S6IPCAM |
13 | tristate "SoC Audio support for Stretch 6105 IP Camera" | 18 | bool "SoC Audio support for Stretch 6105 IP Camera" |
14 | depends on SND_S6000_SOC && XTENSA_PLATFORM_S6105 | 19 | depends on SND_S6000_SOC=y |
20 | depends on I2C=y | ||
21 | depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST | ||
15 | select SND_S6000_SOC_I2S | 22 | select SND_S6000_SOC_I2S |
16 | select SND_SOC_TLV320AIC3X | 23 | select SND_SOC_TLV320AIC3X |
17 | help | 24 | help |
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile index 7a613612e010..0f0ae2a012aa 100644 --- a/sound/soc/s6000/Makefile +++ b/sound/soc/s6000/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | snd-soc-s6000-objs := s6000-pcm.o | 2 | snd-soc-s6000-objs := s6000-pcm.o |
3 | snd-soc-s6000-i2s-objs := s6000-i2s.o | 3 | snd-soc-s6000-i2s-objs := s6000-i2s.o |
4 | 4 | ||
5 | obj-$(CONFIG_SND_S6000_SOC) += snd-soc-s6000.o | 5 | obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o |
6 | obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o | 6 | obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o |
7 | 7 | ||
8 | # s6105 Machine Support | 8 | # s6105 Machine Support |
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 7eba7979b9af..1c8d01166e5b 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c | |||
@@ -570,7 +570,7 @@ err_release_none: | |||
570 | return ret; | 570 | return ret; |
571 | } | 571 | } |
572 | 572 | ||
573 | static void s6000_i2s_remove(struct platform_device *pdev) | 573 | static int s6000_i2s_remove(struct platform_device *pdev) |
574 | { | 574 | { |
575 | struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); | 575 | struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); |
576 | struct resource *region; | 576 | struct resource *region; |
@@ -597,6 +597,8 @@ static void s6000_i2s_remove(struct platform_device *pdev) | |||
597 | iounmap(mmio); | 597 | iounmap(mmio); |
598 | region = platform_get_resource(pdev, IORESOURCE_IO, 0); | 598 | region = platform_get_resource(pdev, IORESOURCE_IO, 0); |
599 | release_mem_region(region->start, resource_size(region)); | 599 | release_mem_region(region->start, resource_size(region)); |
600 | |||
601 | return 0; | ||
600 | } | 602 | } |
601 | 603 | ||
602 | static struct platform_driver s6000_i2s_driver = { | 604 | static struct platform_driver s6000_i2s_driver = { |
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 0b21d1dc80c1..3510c01f8a6a 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <sound/pcm.h> | 19 | #include <sound/pcm.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include <variant/dmac.h> | ||
23 | |||
24 | #include "s6000-pcm.h" | 22 | #include "s6000-pcm.h" |
25 | #include "s6000-i2s.h" | 23 | #include "s6000-i2s.h" |
26 | 24 | ||
@@ -135,22 +133,8 @@ static const struct snd_kcontrol_new audio_out_mux = { | |||
135 | /* Logic for a aic3x as connected on the s6105 ip camera ref design */ | 133 | /* Logic for a aic3x as connected on the s6105 ip camera ref design */ |
136 | static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) | 134 | static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) |
137 | { | 135 | { |
138 | struct snd_soc_codec *codec = rtd->codec; | ||
139 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
140 | struct snd_soc_card *card = rtd->card; | 136 | struct snd_soc_card *card = rtd->card; |
141 | 137 | ||
142 | /* not present */ | ||
143 | snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); | ||
144 | snd_soc_dapm_nc_pin(dapm, "LINE2L"); | ||
145 | snd_soc_dapm_nc_pin(dapm, "LINE2R"); | ||
146 | |||
147 | /* not connected */ | ||
148 | snd_soc_dapm_nc_pin(dapm, "MIC3L"); /* LINE2L on this chip */ | ||
149 | snd_soc_dapm_nc_pin(dapm, "MIC3R"); /* LINE2R on this chip */ | ||
150 | snd_soc_dapm_nc_pin(dapm, "LLOUT"); | ||
151 | snd_soc_dapm_nc_pin(dapm, "RLOUT"); | ||
152 | snd_soc_dapm_nc_pin(dapm, "HPRCOM"); | ||
153 | |||
154 | /* must correspond to audio_out_mux.private_value initializer */ | 138 | /* must correspond to audio_out_mux.private_value initializer */ |
155 | snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); | 139 | snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); |
156 | 140 | ||
@@ -182,6 +166,7 @@ static struct snd_soc_card snd_soc_card_s6105 = { | |||
182 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), | 166 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), |
183 | .dapm_routes = audio_map, | 167 | .dapm_routes = audio_map, |
184 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 168 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
169 | .fully_routed = true, | ||
185 | }; | 170 | }; |
186 | 171 | ||
187 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { | 172 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 753b8c93ab51..55a38697443d 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,25 +1,16 @@ | |||
1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on PLAT_SAMSUNG | 3 | depends on PLAT_SAMSUNG |
4 | select S3C2410_DMA if ARCH_S3C24XX | 4 | depends on S3C64XX_PL080 || !ARCH_S3C64XX |
5 | select S3C64XX_PL080 if ARCH_S3C64XX | 5 | depends on S3C24XX_DMAC || !ARCH_S3C24XX |
6 | select SND_S3C_DMA if !ARCH_S3C24XX | 6 | select SND_SOC_GENERIC_DMAENGINE_PCM |
7 | select SND_S3C_DMA_LEGACY if ARCH_S3C24XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX | ||
9 | help | 7 | help |
10 | Say Y or M if you want to add support for codecs attached to | 8 | Say Y or M if you want to add support for codecs attached to |
11 | the Samsung SoCs' Audio interfaces. You will also need to | 9 | the Samsung SoCs' Audio interfaces. You will also need to |
12 | select the audio interfaces to support below. | 10 | select the audio interfaces to support below. |
13 | 11 | ||
14 | config SND_S3C_DMA | ||
15 | tristate | ||
16 | |||
17 | config SND_S3C_DMA_LEGACY | ||
18 | tristate | ||
19 | |||
20 | config SND_S3C24XX_I2S | 12 | config SND_S3C24XX_I2S |
21 | tristate | 13 | tristate |
22 | select S3C24XX_DMA | ||
23 | 14 | ||
24 | config SND_S3C_I2SV2_SOC | 15 | config SND_S3C_I2SV2_SOC |
25 | tristate | 16 | tristate |
@@ -27,7 +18,6 @@ config SND_S3C_I2SV2_SOC | |||
27 | config SND_S3C2412_SOC_I2S | 18 | config SND_S3C2412_SOC_I2S |
28 | tristate | 19 | tristate |
29 | select SND_S3C_I2SV2_SOC | 20 | select SND_S3C_I2SV2_SOC |
30 | select S3C2410_DMA | ||
31 | 21 | ||
32 | config SND_SAMSUNG_PCM | 22 | config SND_SAMSUNG_PCM |
33 | tristate | 23 | tristate |
@@ -55,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753 | |||
55 | 45 | ||
56 | config SND_SOC_SAMSUNG_JIVE_WM8750 | 46 | config SND_SOC_SAMSUNG_JIVE_WM8750 |
57 | tristate "SoC I2S Audio support for Jive" | 47 | tristate "SoC I2S Audio support for Jive" |
58 | depends on SND_SOC_SAMSUNG && MACH_JIVE | 48 | depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C |
59 | select SND_SOC_WM8750 | 49 | select SND_SOC_WM8750 |
60 | select SND_S3C2412_SOC_I2S | 50 | select SND_S3C2412_SOC_I2S |
61 | help | 51 | help |
@@ -63,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
63 | 53 | ||
64 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 54 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
65 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 55 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
66 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 56 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
67 | depends on REGMAP_I2C | 57 | depends on REGMAP_I2C |
68 | select SND_SOC_WM8580 | 58 | select SND_SOC_WM8580 |
69 | select SND_SAMSUNG_I2S | 59 | select SND_SAMSUNG_I2S |
@@ -83,7 +73,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 | |||
83 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 | 73 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 |
84 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | 74 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" |
85 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 | 75 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 |
86 | select S3C2410_DMA | ||
87 | select AC97_BUS | 76 | select AC97_BUS |
88 | select SND_SOC_AC97_CODEC | 77 | select SND_SOC_AC97_CODEC |
89 | select SND_SAMSUNG_AC97 | 78 | select SND_SAMSUNG_AC97 |
@@ -94,7 +83,6 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710 | |||
94 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 | 83 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 |
95 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" | 84 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" |
96 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX | 85 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX |
97 | select S3C2410_DMA | ||
98 | select AC97_BUS | 86 | select AC97_BUS |
99 | select SND_SOC_AC97_CODEC | 87 | select SND_SOC_AC97_CODEC |
100 | select SND_SAMSUNG_AC97 | 88 | select SND_SAMSUNG_AC97 |
@@ -154,7 +142,7 @@ config SND_SOC_SAMSUNG_SMDK_WM9713 | |||
154 | 142 | ||
155 | config SND_SOC_SMARTQ | 143 | config SND_SOC_SMARTQ |
156 | tristate "SoC I2S Audio support for SmartQ board" | 144 | tristate "SoC I2S Audio support for SmartQ board" |
157 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ | 145 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C |
158 | select SND_SAMSUNG_I2S | 146 | select SND_SAMSUNG_I2S |
159 | select SND_SOC_WM8750 | 147 | select SND_SOC_WM8750 |
160 | 148 | ||
@@ -178,7 +166,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
178 | 166 | ||
179 | config SND_SOC_SMDK_WM8580_PCM | 167 | config SND_SOC_SMDK_WM8580_PCM |
180 | tristate "SoC PCM Audio support for WM8580 on SMDK" | 168 | tristate "SoC PCM Audio support for WM8580 on SMDK" |
181 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 169 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) |
182 | depends on REGMAP_I2C | 170 | depends on REGMAP_I2C |
183 | select SND_SOC_WM8580 | 171 | select SND_SOC_WM8580 |
184 | select SND_SAMSUNG_PCM | 172 | select SND_SAMSUNG_PCM |
@@ -206,7 +194,7 @@ config SND_SOC_SPEYSIDE | |||
206 | 194 | ||
207 | config SND_SOC_TOBERMORY | 195 | config SND_SOC_TOBERMORY |
208 | tristate "Audio support for Wolfson Tobermory" | 196 | tristate "Audio support for Wolfson Tobermory" |
209 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT | 197 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C |
210 | select SND_SAMSUNG_I2S | 198 | select SND_SAMSUNG_I2S |
211 | select SND_SOC_WM8962 | 199 | select SND_SOC_WM8962 |
212 | 200 | ||
@@ -222,7 +210,7 @@ config SND_SOC_BELLS | |||
222 | 210 | ||
223 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
224 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
225 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C |
226 | select SND_SAMSUNG_I2S | 214 | select SND_SAMSUNG_I2S |
227 | select SND_SOC_WM5100 | 215 | select SND_SOC_WM5100 |
228 | select SND_SOC_WM9081 | 216 | select SND_SOC_WM9081 |
@@ -236,10 +224,18 @@ config SND_SOC_LITTLEMILL | |||
236 | 224 | ||
237 | config SND_SOC_SNOW | 225 | config SND_SOC_SNOW |
238 | tristate "Audio support for Google Snow boards" | 226 | tristate "Audio support for Google Snow boards" |
239 | depends on SND_SOC_SAMSUNG | 227 | depends on SND_SOC_SAMSUNG && I2C |
240 | select SND_SOC_MAX98090 | 228 | select SND_SOC_MAX98090 |
241 | select SND_SOC_MAX98095 | 229 | select SND_SOC_MAX98095 |
242 | select SND_SAMSUNG_I2S | 230 | select SND_SAMSUNG_I2S |
243 | help | 231 | help |
244 | Say Y if you want to add audio support for various Snow | 232 | Say Y if you want to add audio support for various Snow |
245 | boards based on Exynos5 series of SoCs. | 233 | boards based on Exynos5 series of SoCs. |
234 | |||
235 | config SND_SOC_ODROIDX2 | ||
236 | tristate "Audio support for Odroid-X2 and Odroid-U3" | ||
237 | depends on SND_SOC_SAMSUNG | ||
238 | select SND_SOC_MAX98090 | ||
239 | select SND_SAMSUNG_I2S | ||
240 | help | ||
241 | Say Y here to enable audio support for the Odroid-X2/U3. | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 6d0212ba571c..91505ddaaf95 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c-dma-objs := dmaengine.o | 2 | snd-soc-s3c-dma-objs := dmaengine.o |
3 | snd-soc-s3c-dma-legacy-objs := dma.o | ||
4 | snd-soc-idma-objs := idma.o | 3 | snd-soc-idma-objs := idma.o |
5 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
6 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
@@ -10,8 +9,7 @@ snd-soc-samsung-spdif-objs := spdif.o | |||
10 | snd-soc-pcm-objs := pcm.o | 9 | snd-soc-pcm-objs := pcm.o |
11 | snd-soc-i2s-objs := i2s.o | 10 | snd-soc-i2s-objs := i2s.o |
12 | 11 | ||
13 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o | 12 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o |
14 | obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o | ||
15 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
16 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | 14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o |
17 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
@@ -46,6 +44,7 @@ snd-soc-tobermory-objs := tobermory.o | |||
46 | snd-soc-lowland-objs := lowland.o | 44 | snd-soc-lowland-objs := lowland.o |
47 | snd-soc-littlemill-objs := littlemill.o | 45 | snd-soc-littlemill-objs := littlemill.o |
48 | snd-soc-bells-objs := bells.o | 46 | snd-soc-bells-objs := bells.o |
47 | snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o | ||
49 | 48 | ||
50 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 49 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
51 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 50 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -71,3 +70,4 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | |||
71 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 70 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
72 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 71 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
73 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | 72 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o |
73 | obj-$(CONFIG_SND_SOC_ODROIDX2) += snd-soc-odroidx2-max98090.o | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 68d9303047e8..e1615113fd84 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include <mach/dma.h> | ||
23 | #include "regs-ac97.h" | 22 | #include "regs-ac97.h" |
24 | #include <linux/platform_data/asoc-s3c.h> | 23 | #include <linux/platform_data/asoc-s3c.h> |
25 | 24 | ||
@@ -39,30 +38,15 @@ struct s3c_ac97_info { | |||
39 | }; | 38 | }; |
40 | static struct s3c_ac97_info s3c_ac97; | 39 | static struct s3c_ac97_info s3c_ac97; |
41 | 40 | ||
42 | static struct s3c_dma_client s3c_dma_client_out = { | ||
43 | .name = "AC97 PCMOut" | ||
44 | }; | ||
45 | |||
46 | static struct s3c_dma_client s3c_dma_client_in = { | ||
47 | .name = "AC97 PCMIn" | ||
48 | }; | ||
49 | |||
50 | static struct s3c_dma_client s3c_dma_client_micin = { | ||
51 | .name = "AC97 MicIn" | ||
52 | }; | ||
53 | |||
54 | static struct s3c_dma_params s3c_ac97_pcm_out = { | 41 | static struct s3c_dma_params s3c_ac97_pcm_out = { |
55 | .client = &s3c_dma_client_out, | ||
56 | .dma_size = 4, | 42 | .dma_size = 4, |
57 | }; | 43 | }; |
58 | 44 | ||
59 | static struct s3c_dma_params s3c_ac97_pcm_in = { | 45 | static struct s3c_dma_params s3c_ac97_pcm_in = { |
60 | .client = &s3c_dma_client_in, | ||
61 | .dma_size = 4, | 46 | .dma_size = 4, |
62 | }; | 47 | }; |
63 | 48 | ||
64 | static struct s3c_dma_params s3c_ac97_mic_in = { | 49 | static struct s3c_dma_params s3c_ac97_mic_in = { |
65 | .client = &s3c_dma_client_micin, | ||
66 | .dma_size = 4, | 50 | .dma_size = 4, |
67 | }; | 51 | }; |
68 | 52 | ||
@@ -225,9 +209,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
225 | struct snd_soc_dai *dai) | 209 | struct snd_soc_dai *dai) |
226 | { | 210 | { |
227 | u32 ac_glbctrl; | 211 | u32 ac_glbctrl; |
228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
229 | struct s3c_dma_params *dma_data = | ||
230 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
231 | 212 | ||
232 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 213 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
233 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 214 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
@@ -253,11 +234,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
253 | 234 | ||
254 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 235 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
255 | 236 | ||
256 | if (!dma_data->ops) | ||
257 | dma_data->ops = samsung_dma_get_ops(); | ||
258 | |||
259 | dma_data->ops->started(dma_data->channel); | ||
260 | |||
261 | return 0; | 237 | return 0; |
262 | } | 238 | } |
263 | 239 | ||
@@ -265,9 +241,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
265 | int cmd, struct snd_soc_dai *dai) | 241 | int cmd, struct snd_soc_dai *dai) |
266 | { | 242 | { |
267 | u32 ac_glbctrl; | 243 | u32 ac_glbctrl; |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
269 | struct s3c_dma_params *dma_data = | ||
270 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
271 | 244 | ||
272 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 245 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
273 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | 246 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; |
@@ -287,11 +260,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
287 | 260 | ||
288 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 261 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
289 | 262 | ||
290 | if (!dma_data->ops) | ||
291 | dma_data->ops = samsung_dma_get_ops(); | ||
292 | |||
293 | dma_data->ops->started(dma_data->channel); | ||
294 | |||
295 | return 0; | 263 | return 0; |
296 | } | 264 | } |
297 | 265 | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c deleted file mode 100644 index d9dc7bcc0336..000000000000 --- a/sound/soc/samsung/dma.c +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /* | ||
2 | * dma.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2006 Wolfson Microelectronics PLC. | ||
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
6 | * | ||
7 | * Copyright 2004-2005 Simtec Electronics | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * Ben Dooks <ben@simtec.co.uk> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <mach/dma.h> | ||
27 | |||
28 | #include "dma.h" | ||
29 | |||
30 | #define ST_RUNNING (1<<0) | ||
31 | #define ST_OPENED (1<<1) | ||
32 | |||
33 | static const struct snd_pcm_hardware dma_hardware = { | ||
34 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
36 | SNDRV_PCM_INFO_MMAP | | ||
37 | SNDRV_PCM_INFO_MMAP_VALID, | ||
38 | .buffer_bytes_max = 128*1024, | ||
39 | .period_bytes_min = PAGE_SIZE, | ||
40 | .period_bytes_max = PAGE_SIZE*2, | ||
41 | .periods_min = 2, | ||
42 | .periods_max = 128, | ||
43 | .fifo_size = 32, | ||
44 | }; | ||
45 | |||
46 | struct runtime_data { | ||
47 | spinlock_t lock; | ||
48 | int state; | ||
49 | unsigned int dma_loaded; | ||
50 | unsigned int dma_period; | ||
51 | dma_addr_t dma_start; | ||
52 | dma_addr_t dma_pos; | ||
53 | dma_addr_t dma_end; | ||
54 | struct s3c_dma_params *params; | ||
55 | }; | ||
56 | |||
57 | static void audio_buffdone(void *data); | ||
58 | |||
59 | /* dma_enqueue | ||
60 | * | ||
61 | * place a dma buffer onto the queue for the dma system | ||
62 | * to handle. | ||
63 | */ | ||
64 | static void dma_enqueue(struct snd_pcm_substream *substream) | ||
65 | { | ||
66 | struct runtime_data *prtd = substream->runtime->private_data; | ||
67 | dma_addr_t pos = prtd->dma_pos; | ||
68 | unsigned int limit; | ||
69 | struct samsung_dma_prep dma_info; | ||
70 | |||
71 | pr_debug("Entered %s\n", __func__); | ||
72 | |||
73 | limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | ||
74 | |||
75 | pr_debug("%s: loaded %d, limit %d\n", | ||
76 | __func__, prtd->dma_loaded, limit); | ||
77 | |||
78 | dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); | ||
79 | dma_info.direction = | ||
80 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
81 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
82 | dma_info.fp = audio_buffdone; | ||
83 | dma_info.fp_param = substream; | ||
84 | dma_info.period = prtd->dma_period; | ||
85 | dma_info.len = prtd->dma_period*limit; | ||
86 | |||
87 | if (dma_info.cap == DMA_CYCLIC) { | ||
88 | dma_info.buf = pos; | ||
89 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
90 | prtd->dma_loaded += limit; | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | while (prtd->dma_loaded < limit) { | ||
95 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); | ||
96 | |||
97 | if ((pos + dma_info.period) > prtd->dma_end) { | ||
98 | dma_info.period = prtd->dma_end - pos; | ||
99 | pr_debug("%s: corrected dma len %ld\n", | ||
100 | __func__, dma_info.period); | ||
101 | } | ||
102 | |||
103 | dma_info.buf = pos; | ||
104 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
105 | |||
106 | prtd->dma_loaded++; | ||
107 | pos += prtd->dma_period; | ||
108 | if (pos >= prtd->dma_end) | ||
109 | pos = prtd->dma_start; | ||
110 | } | ||
111 | |||
112 | prtd->dma_pos = pos; | ||
113 | } | ||
114 | |||
115 | static void audio_buffdone(void *data) | ||
116 | { | ||
117 | struct snd_pcm_substream *substream = data; | ||
118 | struct runtime_data *prtd = substream->runtime->private_data; | ||
119 | |||
120 | pr_debug("Entered %s\n", __func__); | ||
121 | |||
122 | if (prtd->state & ST_RUNNING) { | ||
123 | prtd->dma_pos += prtd->dma_period; | ||
124 | if (prtd->dma_pos >= prtd->dma_end) | ||
125 | prtd->dma_pos = prtd->dma_start; | ||
126 | |||
127 | if (substream) | ||
128 | snd_pcm_period_elapsed(substream); | ||
129 | |||
130 | spin_lock(&prtd->lock); | ||
131 | if (!samsung_dma_has_circular()) { | ||
132 | prtd->dma_loaded--; | ||
133 | dma_enqueue(substream); | ||
134 | } | ||
135 | spin_unlock(&prtd->lock); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int dma_hw_params(struct snd_pcm_substream *substream, | ||
140 | struct snd_pcm_hw_params *params) | ||
141 | { | ||
142 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
143 | struct runtime_data *prtd = runtime->private_data; | ||
144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
145 | unsigned long totbytes = params_buffer_bytes(params); | ||
146 | struct s3c_dma_params *dma = | ||
147 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
148 | struct samsung_dma_req req; | ||
149 | struct samsung_dma_config config; | ||
150 | |||
151 | pr_debug("Entered %s\n", __func__); | ||
152 | |||
153 | /* return if this is a bufferless transfer e.g. | ||
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
155 | if (!dma) | ||
156 | return 0; | ||
157 | |||
158 | /* this may get called several times by oss emulation | ||
159 | * with different params -HW */ | ||
160 | if (prtd->params == NULL) { | ||
161 | /* prepare DMA */ | ||
162 | prtd->params = dma; | ||
163 | |||
164 | pr_debug("params %p, client %p, channel %d\n", prtd->params, | ||
165 | prtd->params->client, prtd->params->channel); | ||
166 | |||
167 | prtd->params->ops = samsung_dma_get_ops(); | ||
168 | |||
169 | req.cap = (samsung_dma_has_circular() ? | ||
170 | DMA_CYCLIC : DMA_SLAVE); | ||
171 | req.client = prtd->params->client; | ||
172 | config.direction = | ||
173 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
174 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
175 | config.width = prtd->params->dma_size; | ||
176 | config.fifo = prtd->params->dma_addr; | ||
177 | prtd->params->ch = prtd->params->ops->request( | ||
178 | prtd->params->channel, &req, rtd->cpu_dai->dev, | ||
179 | prtd->params->ch_name); | ||
180 | if (!prtd->params->ch) { | ||
181 | pr_err("Failed to allocate DMA channel\n"); | ||
182 | return -ENXIO; | ||
183 | } | ||
184 | prtd->params->ops->config(prtd->params->ch, &config); | ||
185 | } | ||
186 | |||
187 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
188 | |||
189 | runtime->dma_bytes = totbytes; | ||
190 | |||
191 | spin_lock_irq(&prtd->lock); | ||
192 | prtd->dma_loaded = 0; | ||
193 | prtd->dma_period = params_period_bytes(params); | ||
194 | prtd->dma_start = runtime->dma_addr; | ||
195 | prtd->dma_pos = prtd->dma_start; | ||
196 | prtd->dma_end = prtd->dma_start + totbytes; | ||
197 | spin_unlock_irq(&prtd->lock); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int dma_hw_free(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | struct runtime_data *prtd = substream->runtime->private_data; | ||
205 | |||
206 | pr_debug("Entered %s\n", __func__); | ||
207 | |||
208 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
209 | |||
210 | if (prtd->params) { | ||
211 | prtd->params->ops->flush(prtd->params->ch); | ||
212 | prtd->params->ops->release(prtd->params->ch, | ||
213 | prtd->params->client); | ||
214 | prtd->params = NULL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int dma_prepare(struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct runtime_data *prtd = substream->runtime->private_data; | ||
223 | int ret = 0; | ||
224 | |||
225 | pr_debug("Entered %s\n", __func__); | ||
226 | |||
227 | /* return if this is a bufferless transfer e.g. | ||
228 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
229 | if (!prtd->params) | ||
230 | return 0; | ||
231 | |||
232 | /* flush the DMA channel */ | ||
233 | prtd->params->ops->flush(prtd->params->ch); | ||
234 | |||
235 | prtd->dma_loaded = 0; | ||
236 | prtd->dma_pos = prtd->dma_start; | ||
237 | |||
238 | /* enqueue dma buffers */ | ||
239 | dma_enqueue(substream); | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
245 | { | ||
246 | struct runtime_data *prtd = substream->runtime->private_data; | ||
247 | int ret = 0; | ||
248 | |||
249 | pr_debug("Entered %s\n", __func__); | ||
250 | |||
251 | spin_lock(&prtd->lock); | ||
252 | |||
253 | switch (cmd) { | ||
254 | case SNDRV_PCM_TRIGGER_START: | ||
255 | prtd->state |= ST_RUNNING; | ||
256 | prtd->params->ops->trigger(prtd->params->ch); | ||
257 | break; | ||
258 | |||
259 | case SNDRV_PCM_TRIGGER_STOP: | ||
260 | prtd->state &= ~ST_RUNNING; | ||
261 | prtd->params->ops->stop(prtd->params->ch); | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ret = -EINVAL; | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | spin_unlock(&prtd->lock); | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static snd_pcm_uframes_t | ||
275 | dma_pointer(struct snd_pcm_substream *substream) | ||
276 | { | ||
277 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
278 | struct runtime_data *prtd = runtime->private_data; | ||
279 | unsigned long res; | ||
280 | |||
281 | pr_debug("Entered %s\n", __func__); | ||
282 | |||
283 | res = prtd->dma_pos - prtd->dma_start; | ||
284 | |||
285 | pr_debug("Pointer offset: %lu\n", res); | ||
286 | |||
287 | /* we seem to be getting the odd error from the pcm library due | ||
288 | * to out-of-bounds pointers. this is maybe due to the dma engine | ||
289 | * not having loaded the new values for the channel before being | ||
290 | * called... (todo - fix ) | ||
291 | */ | ||
292 | |||
293 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { | ||
294 | if (res == snd_pcm_lib_buffer_bytes(substream)) | ||
295 | res = 0; | ||
296 | } | ||
297 | |||
298 | return bytes_to_frames(substream->runtime, res); | ||
299 | } | ||
300 | |||
301 | static int dma_open(struct snd_pcm_substream *substream) | ||
302 | { | ||
303 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
304 | struct runtime_data *prtd; | ||
305 | |||
306 | pr_debug("Entered %s\n", __func__); | ||
307 | |||
308 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
309 | snd_soc_set_runtime_hwparams(substream, &dma_hardware); | ||
310 | |||
311 | prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); | ||
312 | if (prtd == NULL) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | spin_lock_init(&prtd->lock); | ||
316 | |||
317 | runtime->private_data = prtd; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int dma_close(struct snd_pcm_substream *substream) | ||
322 | { | ||
323 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
324 | struct runtime_data *prtd = runtime->private_data; | ||
325 | |||
326 | pr_debug("Entered %s\n", __func__); | ||
327 | |||
328 | if (!prtd) | ||
329 | pr_debug("dma_close called with prtd == NULL\n"); | ||
330 | |||
331 | kfree(prtd); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int dma_mmap(struct snd_pcm_substream *substream, | ||
337 | struct vm_area_struct *vma) | ||
338 | { | ||
339 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
340 | |||
341 | pr_debug("Entered %s\n", __func__); | ||
342 | |||
343 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
344 | runtime->dma_area, | ||
345 | runtime->dma_addr, | ||
346 | runtime->dma_bytes); | ||
347 | } | ||
348 | |||
349 | static struct snd_pcm_ops dma_ops = { | ||
350 | .open = dma_open, | ||
351 | .close = dma_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = dma_hw_params, | ||
354 | .hw_free = dma_hw_free, | ||
355 | .prepare = dma_prepare, | ||
356 | .trigger = dma_trigger, | ||
357 | .pointer = dma_pointer, | ||
358 | .mmap = dma_mmap, | ||
359 | }; | ||
360 | |||
361 | static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
362 | { | ||
363 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
364 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
365 | size_t size = dma_hardware.buffer_bytes_max; | ||
366 | |||
367 | pr_debug("Entered %s\n", __func__); | ||
368 | |||
369 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
370 | buf->dev.dev = pcm->card->dev; | ||
371 | buf->private_data = NULL; | ||
372 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
373 | &buf->addr, GFP_KERNEL); | ||
374 | if (!buf->area) | ||
375 | return -ENOMEM; | ||
376 | buf->bytes = size; | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static void dma_free_dma_buffers(struct snd_pcm *pcm) | ||
381 | { | ||
382 | struct snd_pcm_substream *substream; | ||
383 | struct snd_dma_buffer *buf; | ||
384 | int stream; | ||
385 | |||
386 | pr_debug("Entered %s\n", __func__); | ||
387 | |||
388 | for (stream = 0; stream < 2; stream++) { | ||
389 | substream = pcm->streams[stream].substream; | ||
390 | if (!substream) | ||
391 | continue; | ||
392 | |||
393 | buf = &substream->dma_buffer; | ||
394 | if (!buf->area) | ||
395 | continue; | ||
396 | |||
397 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
398 | buf->area, buf->addr); | ||
399 | buf->area = NULL; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int dma_new(struct snd_soc_pcm_runtime *rtd) | ||
404 | { | ||
405 | struct snd_card *card = rtd->card->snd_card; | ||
406 | struct snd_pcm *pcm = rtd->pcm; | ||
407 | int ret; | ||
408 | |||
409 | pr_debug("Entered %s\n", __func__); | ||
410 | |||
411 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
416 | ret = preallocate_dma_buffer(pcm, | ||
417 | SNDRV_PCM_STREAM_PLAYBACK); | ||
418 | if (ret) | ||
419 | goto out; | ||
420 | } | ||
421 | |||
422 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
423 | ret = preallocate_dma_buffer(pcm, | ||
424 | SNDRV_PCM_STREAM_CAPTURE); | ||
425 | if (ret) | ||
426 | goto out; | ||
427 | } | ||
428 | out: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static struct snd_soc_platform_driver samsung_asoc_platform = { | ||
433 | .ops = &dma_ops, | ||
434 | .pcm_new = dma_new, | ||
435 | .pcm_free = dma_free_dma_buffers, | ||
436 | }; | ||
437 | |||
438 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
439 | struct s3c_dma_params *playback, | ||
440 | struct s3c_dma_params *capture) | ||
441 | { | ||
442 | snd_soc_dai_init_dma_data(dai, playback, capture); | ||
443 | } | ||
444 | EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); | ||
445 | |||
446 | int samsung_asoc_dma_platform_register(struct device *dev) | ||
447 | { | ||
448 | return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); | ||
449 | } | ||
450 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
451 | |||
452 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
453 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); | ||
454 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 070ab0f09609..0e85dcfec023 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
@@ -14,17 +14,10 @@ | |||
14 | 14 | ||
15 | #include <sound/dmaengine_pcm.h> | 15 | #include <sound/dmaengine_pcm.h> |
16 | 16 | ||
17 | struct s3c_dma_client { | ||
18 | char *name; | ||
19 | }; | ||
20 | |||
21 | struct s3c_dma_params { | 17 | struct s3c_dma_params { |
22 | struct s3c_dma_client *client; /* stream identifier */ | ||
23 | int channel; /* Channel ID */ | 18 | int channel; /* Channel ID */ |
24 | dma_addr_t dma_addr; | 19 | dma_addr_t dma_addr; |
25 | int dma_size; /* Size of the DMA transfer */ | 20 | int dma_size; /* Size of the DMA transfer */ |
26 | unsigned ch; | ||
27 | struct samsung_dma_ops *ops; | ||
28 | char *ch_name; | 21 | char *ch_name; |
29 | struct snd_dmaengine_dai_dma_data dma_data; | 22 | struct snd_dmaengine_dai_dma_data dma_data; |
30 | }; | 23 | }; |
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index a0e4e7948909..506f5bf6d082 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/amba/pl08x.h> | 19 | #include <linux/amba/pl08x.h> |
20 | #include <linux/platform_data/dma-s3c24xx.h> | ||
20 | 21 | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -29,6 +30,8 @@ | |||
29 | 30 | ||
30 | #ifdef CONFIG_ARCH_S3C64XX | 31 | #ifdef CONFIG_ARCH_S3C64XX |
31 | #define filter_fn pl08x_filter_id | 32 | #define filter_fn pl08x_filter_id |
33 | #elif defined(CONFIG_ARCH_S3C24XX) | ||
34 | #define filter_fn s3c24xx_dma_filter | ||
32 | #else | 35 | #else |
33 | #define filter_fn NULL | 36 | #define filter_fn NULL |
34 | #endif | 37 | #endif |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 2ac76fa3e742..03eec22f0f46 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -68,6 +68,8 @@ struct i2s_dai { | |||
68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ | 68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ |
69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ | 69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ |
70 | unsigned mode; | 70 | unsigned mode; |
71 | /* CDCLK pin direction: 0 - input, 1 - output */ | ||
72 | unsigned int cdclk_out:1; | ||
71 | /* Driver for this DAI */ | 73 | /* Driver for this DAI */ |
72 | struct snd_soc_dai_driver i2s_dai_drv; | 74 | struct snd_soc_dai_driver i2s_dai_drv; |
73 | /* DMA parameters */ | 75 | /* DMA parameters */ |
@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
737 | 739 | ||
738 | spin_unlock_irqrestore(&lock, flags); | 740 | spin_unlock_irqrestore(&lock, flags); |
739 | 741 | ||
742 | if (!is_opened(other) && i2s->cdclk_out) | ||
743 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | ||
744 | 0, SND_SOC_CLOCK_OUT); | ||
740 | return 0; | 745 | return 0; |
741 | } | 746 | } |
742 | 747 | ||
@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, | |||
752 | i2s->mode &= ~DAI_OPENED; | 757 | i2s->mode &= ~DAI_OPENED; |
753 | i2s->mode &= ~DAI_MANAGER; | 758 | i2s->mode &= ~DAI_MANAGER; |
754 | 759 | ||
755 | if (is_opened(other)) | 760 | if (is_opened(other)) { |
756 | other->mode |= DAI_MANAGER; | 761 | other->mode |= DAI_MANAGER; |
757 | 762 | } else { | |
763 | u32 mod = readl(i2s->addr + I2SMOD); | ||
764 | i2s->cdclk_out = !(mod & MOD_CDCLKCON); | ||
765 | other->cdclk_out = i2s->cdclk_out; | ||
766 | } | ||
758 | /* Reset any constraint on RFS and BFS */ | 767 | /* Reset any constraint on RFS and BFS */ |
759 | i2s->rfs = 0; | 768 | i2s->rfs = 0; |
760 | i2s->bfs = 0; | 769 | i2s->bfs = 0; |
@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) | |||
920 | { | 929 | { |
921 | struct i2s_dai *i2s = to_info(dai); | 930 | struct i2s_dai *i2s = to_info(dai); |
922 | 931 | ||
923 | if (dai->active) { | 932 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); |
924 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); | 933 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); |
925 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); | 934 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); |
926 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); | ||
927 | } | ||
928 | 935 | ||
929 | return 0; | 936 | return 0; |
930 | } | 937 | } |
@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai) | |||
933 | { | 940 | { |
934 | struct i2s_dai *i2s = to_info(dai); | 941 | struct i2s_dai *i2s = to_info(dai); |
935 | 942 | ||
936 | if (dai->active) { | 943 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); |
937 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); | 944 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); |
938 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); | 945 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); |
939 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); | ||
940 | } | ||
941 | 946 | ||
942 | return 0; | 947 | return 0; |
943 | } | 948 | } |
@@ -1216,11 +1221,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1216 | 1221 | ||
1217 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; | 1222 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; |
1218 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; | 1223 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; |
1219 | pri_dai->dma_playback.client = | ||
1220 | (struct s3c_dma_client *)&pri_dai->dma_playback; | ||
1221 | pri_dai->dma_playback.ch_name = "tx"; | 1224 | pri_dai->dma_playback.ch_name = "tx"; |
1222 | pri_dai->dma_capture.client = | ||
1223 | (struct s3c_dma_client *)&pri_dai->dma_capture; | ||
1224 | pri_dai->dma_capture.ch_name = "rx"; | 1225 | pri_dai->dma_capture.ch_name = "rx"; |
1225 | pri_dai->dma_playback.dma_size = 4; | 1226 | pri_dai->dma_playback.dma_size = 4; |
1226 | pri_dai->dma_capture.dma_size = 4; | 1227 | pri_dai->dma_capture.dma_size = 4; |
@@ -1238,8 +1239,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1238 | goto err; | 1239 | goto err; |
1239 | } | 1240 | } |
1240 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; | 1241 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; |
1241 | sec_dai->dma_playback.client = | ||
1242 | (struct s3c_dma_client *)&sec_dai->dma_playback; | ||
1243 | sec_dai->dma_playback.ch_name = "tx-sec"; | 1242 | sec_dai->dma_playback.ch_name = "tx-sec"; |
1244 | 1243 | ||
1245 | if (!np) { | 1244 | if (!np) { |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 8cc5770abb39..db6cefa18017 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c | |||
@@ -261,10 +261,9 @@ static int idma_mmap(struct snd_pcm_substream *substream, | |||
261 | static irqreturn_t iis_irq(int irqno, void *dev_id) | 261 | static irqreturn_t iis_irq(int irqno, void *dev_id) |
262 | { | 262 | { |
263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; | 263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; |
264 | u32 iiscon, iisahb, val, addr; | 264 | u32 iisahb, val, addr; |
265 | 265 | ||
266 | iisahb = readl(idma.regs + I2SAHB); | 266 | iisahb = readl(idma.regs + I2SAHB); |
267 | iiscon = readl(idma.regs + I2SCON); | ||
268 | 267 | ||
269 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; | 268 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; |
270 | 269 | ||
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c new file mode 100644 index 000000000000..278edf9e2a87 --- /dev/null +++ b/sound/soc/samsung/odroidx2_max98090.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/of.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <sound/soc.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include "i2s.h" | ||
15 | |||
16 | struct odroidx2_drv_data { | ||
17 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
18 | unsigned int num_dapm_widgets; | ||
19 | }; | ||
20 | |||
21 | /* The I2S CDCLK output clock frequency for the MAX98090 codec */ | ||
22 | #define MAX98090_MCLK 19200000 | ||
23 | |||
24 | static int odroidx2_late_probe(struct snd_soc_card *card) | ||
25 | { | ||
26 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
27 | struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai; | ||
28 | int ret; | ||
29 | |||
30 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, | ||
31 | SND_SOC_CLOCK_IN); | ||
32 | if (ret < 0) | ||
33 | return ret; | ||
34 | |||
35 | /* Set the cpu DAI configuration in order to use CDCLK */ | ||
36 | return snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, | ||
37 | 0, SND_SOC_CLOCK_OUT); | ||
38 | } | ||
39 | |||
40 | static const struct snd_soc_dapm_widget odroidx2_dapm_widgets[] = { | ||
41 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
42 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
43 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
44 | }; | ||
45 | |||
46 | static const struct snd_soc_dapm_widget odroidu3_dapm_widgets[] = { | ||
47 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
48 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
49 | }; | ||
50 | |||
51 | static struct snd_soc_dai_link odroidx2_dai[] = { | ||
52 | { | ||
53 | .name = "MAX98090", | ||
54 | .stream_name = "MAX98090 PCM", | ||
55 | .codec_dai_name = "HiFi", | ||
56 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
57 | SND_SOC_DAIFMT_CBM_CFM, | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | static struct snd_soc_card odroidx2 = { | ||
62 | .owner = THIS_MODULE, | ||
63 | .dai_link = odroidx2_dai, | ||
64 | .num_links = ARRAY_SIZE(odroidx2_dai), | ||
65 | .fully_routed = true, | ||
66 | .late_probe = odroidx2_late_probe, | ||
67 | }; | ||
68 | |||
69 | struct odroidx2_drv_data odroidx2_drvdata = { | ||
70 | .dapm_widgets = odroidx2_dapm_widgets, | ||
71 | .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets), | ||
72 | }; | ||
73 | |||
74 | struct odroidx2_drv_data odroidu3_drvdata = { | ||
75 | .dapm_widgets = odroidu3_dapm_widgets, | ||
76 | .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets), | ||
77 | }; | ||
78 | |||
79 | static const struct of_device_id odroidx2_audio_of_match[] = { | ||
80 | { | ||
81 | .compatible = "samsung,odroidx2-audio", | ||
82 | .data = &odroidx2_drvdata, | ||
83 | }, { | ||
84 | .compatible = "samsung,odroidu3-audio", | ||
85 | .data = &odroidu3_drvdata, | ||
86 | }, | ||
87 | { }, | ||
88 | }; | ||
89 | MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match); | ||
90 | |||
91 | static int odroidx2_audio_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct device_node *snd_node = pdev->dev.of_node; | ||
94 | struct snd_soc_card *card = &odroidx2; | ||
95 | struct device_node *i2s_node, *codec_node; | ||
96 | struct odroidx2_drv_data *dd; | ||
97 | const struct of_device_id *of_id; | ||
98 | int ret; | ||
99 | |||
100 | of_id = of_match_node(odroidx2_audio_of_match, snd_node); | ||
101 | dd = (struct odroidx2_drv_data *)of_id->data; | ||
102 | |||
103 | card->num_dapm_widgets = dd->num_dapm_widgets; | ||
104 | card->dapm_widgets = dd->dapm_widgets; | ||
105 | |||
106 | card->dev = &pdev->dev; | ||
107 | |||
108 | ret = snd_soc_of_parse_card_name(card, "samsung,model"); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | codec_node = of_parse_phandle(snd_node, "samsung,audio-codec", 0); | ||
117 | if (!codec_node) { | ||
118 | dev_err(&pdev->dev, | ||
119 | "Failed parsing samsung,i2s-codec property\n"); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | i2s_node = of_parse_phandle(snd_node, "samsung,i2s-controller", 0); | ||
124 | if (!i2s_node) { | ||
125 | dev_err(&pdev->dev, | ||
126 | "Failed parsing samsung,i2s-controller property\n"); | ||
127 | ret = -EINVAL; | ||
128 | goto err_put_codec_n; | ||
129 | } | ||
130 | |||
131 | odroidx2_dai[0].codec_of_node = codec_node; | ||
132 | odroidx2_dai[0].cpu_of_node = i2s_node; | ||
133 | odroidx2_dai[0].platform_of_node = i2s_node; | ||
134 | |||
135 | ret = snd_soc_register_card(card); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
138 | ret); | ||
139 | goto err_put_i2s_n; | ||
140 | } | ||
141 | return 0; | ||
142 | |||
143 | err_put_i2s_n: | ||
144 | of_node_put(i2s_node); | ||
145 | err_put_codec_n: | ||
146 | of_node_put(codec_node); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static int odroidx2_audio_remove(struct platform_device *pdev) | ||
151 | { | ||
152 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
153 | |||
154 | snd_soc_unregister_card(card); | ||
155 | |||
156 | of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node); | ||
157 | of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static struct platform_driver odroidx2_audio_driver = { | ||
163 | .driver = { | ||
164 | .name = "odroidx2-audio", | ||
165 | .owner = THIS_MODULE, | ||
166 | .of_match_table = odroidx2_audio_of_match, | ||
167 | .pm = &snd_soc_pm_ops, | ||
168 | }, | ||
169 | .probe = odroidx2_audio_probe, | ||
170 | .remove = odroidx2_audio_remove, | ||
171 | }; | ||
172 | module_platform_driver(odroidx2_audio_driver); | ||
173 | |||
174 | MODULE_AUTHOR("Chen Zhen <zhen1.chen@samsung.com>"); | ||
175 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | ||
176 | MODULE_DESCRIPTION("ALSA SoC Odroid X2/U3 Audio Support"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 4c5f97fe45c8..bac034b15a27 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -131,32 +131,20 @@ struct s3c_pcm_info { | |||
131 | struct s3c_dma_params *dma_capture; | 131 | struct s3c_dma_params *dma_capture; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static struct s3c_dma_client s3c_pcm_dma_client_out = { | ||
135 | .name = "PCM Stereo out" | ||
136 | }; | ||
137 | |||
138 | static struct s3c_dma_client s3c_pcm_dma_client_in = { | ||
139 | .name = "PCM Stereo in" | ||
140 | }; | ||
141 | |||
142 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { | 134 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { |
143 | [0] = { | 135 | [0] = { |
144 | .client = &s3c_pcm_dma_client_out, | ||
145 | .dma_size = 4, | 136 | .dma_size = 4, |
146 | }, | 137 | }, |
147 | [1] = { | 138 | [1] = { |
148 | .client = &s3c_pcm_dma_client_out, | ||
149 | .dma_size = 4, | 139 | .dma_size = 4, |
150 | }, | 140 | }, |
151 | }; | 141 | }; |
152 | 142 | ||
153 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { | 143 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { |
154 | [0] = { | 144 | [0] = { |
155 | .client = &s3c_pcm_dma_client_in, | ||
156 | .dma_size = 4, | 145 | .dma_size = 4, |
157 | }, | 146 | }, |
158 | [1] = { | 147 | [1] = { |
159 | .client = &s3c_pcm_dma_client_in, | ||
160 | .dma_size = 4, | 148 | .dma_size = 4, |
161 | }, | 149 | }, |
162 | }; | 150 | }; |
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 0ff4bbe23af3..df65c5b494b1 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
24 | 24 | ||
25 | #include <mach/dma.h> | ||
26 | |||
27 | #include "regs-i2s-v2.h" | 25 | #include "regs-i2s-v2.h" |
28 | #include "s3c-i2s-v2.h" | 26 | #include "s3c-i2s-v2.h" |
29 | #include "dma.h" | 27 | #include "dma.h" |
@@ -392,8 +390,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
392 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 390 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
393 | unsigned long irqs; | 391 | unsigned long irqs; |
394 | int ret = 0; | 392 | int ret = 0; |
395 | struct s3c_dma_params *dma_data = | ||
396 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
397 | 393 | ||
398 | pr_debug("Entered %s\n", __func__); | 394 | pr_debug("Entered %s\n", __func__); |
399 | 395 | ||
@@ -424,13 +420,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
424 | 420 | ||
425 | local_irq_restore(irqs); | 421 | local_irq_restore(irqs); |
426 | 422 | ||
427 | /* | ||
428 | * Load the next buffer to DMA to meet the reqirement | ||
429 | * of the auto reload mechanism of S3C24XX. | ||
430 | * This call won't bother S3C64XX. | ||
431 | */ | ||
432 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
433 | |||
434 | break; | 423 | break; |
435 | 424 | ||
436 | case SNDRV_PCM_TRIGGER_STOP: | 425 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -644,12 +633,6 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, | |||
644 | /* record our i2s structure for later use in the callbacks */ | 633 | /* record our i2s structure for later use in the callbacks */ |
645 | snd_soc_dai_set_drvdata(dai, i2s); | 634 | snd_soc_dai_set_drvdata(dai, i2s); |
646 | 635 | ||
647 | i2s->regs = ioremap(base, 0x100); | ||
648 | if (i2s->regs == NULL) { | ||
649 | dev_err(dev, "cannot ioremap registers\n"); | ||
650 | return -ENXIO; | ||
651 | } | ||
652 | |||
653 | i2s->iis_pclk = clk_get(dev, "iis"); | 636 | i2s->iis_pclk = clk_get(dev, "iis"); |
654 | if (IS_ERR(i2s->iis_pclk)) { | 637 | if (IS_ERR(i2s->iis_pclk)) { |
655 | dev_err(dev, "failed to get iis_clock\n"); | 638 | dev_err(dev, "failed to get iis_clock\n"); |
@@ -729,7 +712,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, | |||
729 | struct snd_soc_component_driver *cmp_drv, | 712 | struct snd_soc_component_driver *cmp_drv, |
730 | struct snd_soc_dai_driver *dai_drv) | 713 | struct snd_soc_dai_driver *dai_drv) |
731 | { | 714 | { |
732 | struct snd_soc_dai_ops *ops = dai_drv->ops; | 715 | struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops; |
733 | 716 | ||
734 | ops->trigger = s3c2412_i2s_trigger; | 717 | ops->trigger = s3c2412_i2s_trigger; |
735 | if (!ops->hw_params) | 718 | if (!ops->hw_params) |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 08c059be9104..27b339c6580e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -33,25 +33,15 @@ | |||
33 | #include "regs-i2s-v2.h" | 33 | #include "regs-i2s-v2.h" |
34 | #include "s3c2412-i2s.h" | 34 | #include "s3c2412-i2s.h" |
35 | 35 | ||
36 | static struct s3c_dma_client s3c2412_dma_client_out = { | ||
37 | .name = "I2S PCM Stereo out" | ||
38 | }; | ||
39 | |||
40 | static struct s3c_dma_client s3c2412_dma_client_in = { | ||
41 | .name = "I2S PCM Stereo in" | ||
42 | }; | ||
43 | |||
44 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { | 36 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { |
45 | .client = &s3c2412_dma_client_out, | ||
46 | .channel = DMACH_I2S_OUT, | 37 | .channel = DMACH_I2S_OUT, |
47 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, | 38 | .ch_name = "tx", |
48 | .dma_size = 4, | 39 | .dma_size = 4, |
49 | }; | 40 | }; |
50 | 41 | ||
51 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | 42 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { |
52 | .client = &s3c2412_dma_client_in, | ||
53 | .channel = DMACH_I2S_IN, | 43 | .channel = DMACH_I2S_IN, |
54 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, | 44 | .ch_name = "rx", |
55 | .dma_size = 4, | 45 | .dma_size = 4, |
56 | }; | 46 | }; |
57 | 47 | ||
@@ -63,6 +53,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
63 | 53 | ||
64 | pr_debug("Entered %s\n", __func__); | 54 | pr_debug("Entered %s\n", __func__); |
65 | 55 | ||
56 | samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, | ||
57 | &s3c2412_i2s_pcm_stereo_in); | ||
58 | |||
66 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); | 59 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); |
67 | if (ret) | 60 | if (ret) |
68 | return ret; | 61 | return ret; |
@@ -70,17 +63,16 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
70 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; | 63 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
71 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 64 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
72 | 65 | ||
73 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); | 66 | s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk"); |
74 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { | 67 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { |
75 | pr_err("failed to get i2sclk clock\n"); | 68 | pr_err("failed to get i2sclk clock\n"); |
76 | iounmap(s3c2412_i2s.regs); | ||
77 | return PTR_ERR(s3c2412_i2s.iis_cclk); | 69 | return PTR_ERR(s3c2412_i2s.iis_cclk); |
78 | } | 70 | } |
79 | 71 | ||
80 | /* Set MPLL as the source for IIS CLK */ | 72 | /* Set MPLL as the source for IIS CLK */ |
81 | 73 | ||
82 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); | 74 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); |
83 | clk_enable(s3c2412_i2s.iis_cclk); | 75 | clk_prepare_enable(s3c2412_i2s.iis_cclk); |
84 | 76 | ||
85 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; | 77 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; |
86 | 78 | ||
@@ -93,9 +85,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
93 | 85 | ||
94 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) | 86 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) |
95 | { | 87 | { |
96 | clk_disable(s3c2412_i2s.iis_cclk); | 88 | clk_disable_unprepare(s3c2412_i2s.iis_cclk); |
97 | clk_put(s3c2412_i2s.iis_cclk); | ||
98 | iounmap(s3c2412_i2s.regs); | ||
99 | 89 | ||
100 | return 0; | 90 | return 0; |
101 | } | 91 | } |
@@ -105,18 +95,10 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | |||
105 | struct snd_soc_dai *cpu_dai) | 95 | struct snd_soc_dai *cpu_dai) |
106 | { | 96 | { |
107 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); | 97 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
108 | struct s3c_dma_params *dma_data; | ||
109 | u32 iismod; | 98 | u32 iismod; |
110 | 99 | ||
111 | pr_debug("Entered %s\n", __func__); | 100 | pr_debug("Entered %s\n", __func__); |
112 | 101 | ||
113 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
114 | dma_data = i2s->dma_playback; | ||
115 | else | ||
116 | dma_data = i2s->dma_capture; | ||
117 | |||
118 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
119 | |||
120 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 102 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
121 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | 103 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); |
122 | 104 | ||
@@ -169,6 +151,15 @@ static const struct snd_soc_component_driver s3c2412_i2s_component = { | |||
169 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) | 151 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) |
170 | { | 152 | { |
171 | int ret = 0; | 153 | int ret = 0; |
154 | struct resource *res; | ||
155 | |||
156 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
157 | s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
158 | if (IS_ERR(s3c2412_i2s.regs)) | ||
159 | return PTR_ERR(s3c2412_i2s.regs); | ||
160 | |||
161 | s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD; | ||
162 | s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD; | ||
172 | 163 | ||
173 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, | 164 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, |
174 | &s3c2412_i2s_component, | 165 | &s3c2412_i2s_component, |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 9aba9fb7df0e..e87d9a2053b8 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -31,25 +31,15 @@ | |||
31 | #include "dma.h" | 31 | #include "dma.h" |
32 | #include "s3c24xx-i2s.h" | 32 | #include "s3c24xx-i2s.h" |
33 | 33 | ||
34 | static struct s3c_dma_client s3c24xx_dma_client_out = { | ||
35 | .name = "I2S PCM Stereo out" | ||
36 | }; | ||
37 | |||
38 | static struct s3c_dma_client s3c24xx_dma_client_in = { | ||
39 | .name = "I2S PCM Stereo in" | ||
40 | }; | ||
41 | |||
42 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { | 34 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { |
43 | .client = &s3c24xx_dma_client_out, | ||
44 | .channel = DMACH_I2S_OUT, | 35 | .channel = DMACH_I2S_OUT, |
45 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 36 | .ch_name = "tx", |
46 | .dma_size = 2, | 37 | .dma_size = 2, |
47 | }; | 38 | }; |
48 | 39 | ||
49 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { | 40 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { |
50 | .client = &s3c24xx_dma_client_in, | ||
51 | .channel = DMACH_I2S_IN, | 41 | .channel = DMACH_I2S_IN, |
52 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 42 | .ch_name = "rx", |
53 | .dma_size = 2, | 43 | .dma_size = 2, |
54 | }; | 44 | }; |
55 | 45 | ||
@@ -231,18 +221,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
231 | struct snd_pcm_hw_params *params, | 221 | struct snd_pcm_hw_params *params, |
232 | struct snd_soc_dai *dai) | 222 | struct snd_soc_dai *dai) |
233 | { | 223 | { |
234 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 224 | struct snd_dmaengine_dai_dma_data *dma_data; |
235 | struct s3c_dma_params *dma_data; | ||
236 | u32 iismod; | 225 | u32 iismod; |
237 | 226 | ||
238 | pr_debug("Entered %s\n", __func__); | 227 | pr_debug("Entered %s\n", __func__); |
239 | 228 | ||
240 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 229 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
241 | dma_data = &s3c24xx_i2s_pcm_stereo_out; | ||
242 | else | ||
243 | dma_data = &s3c24xx_i2s_pcm_stereo_in; | ||
244 | |||
245 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); | ||
246 | 230 | ||
247 | /* Working copies of register */ | 231 | /* Working copies of register */ |
248 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 232 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -251,11 +235,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
251 | switch (params_width(params)) { | 235 | switch (params_width(params)) { |
252 | case 8: | 236 | case 8: |
253 | iismod &= ~S3C2410_IISMOD_16BIT; | 237 | iismod &= ~S3C2410_IISMOD_16BIT; |
254 | dma_data->dma_size = 1; | 238 | dma_data->addr_width = 1; |
255 | break; | 239 | break; |
256 | case 16: | 240 | case 16: |
257 | iismod |= S3C2410_IISMOD_16BIT; | 241 | iismod |= S3C2410_IISMOD_16BIT; |
258 | dma_data->dma_size = 2; | 242 | dma_data->addr_width = 2; |
259 | break; | 243 | break; |
260 | default: | 244 | default: |
261 | return -EINVAL; | 245 | return -EINVAL; |
@@ -270,8 +254,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
270 | struct snd_soc_dai *dai) | 254 | struct snd_soc_dai *dai) |
271 | { | 255 | { |
272 | int ret = 0; | 256 | int ret = 0; |
273 | struct s3c_dma_params *dma_data = | ||
274 | snd_soc_dai_get_dma_data(dai, substream); | ||
275 | 257 | ||
276 | pr_debug("Entered %s\n", __func__); | 258 | pr_debug("Entered %s\n", __func__); |
277 | 259 | ||
@@ -290,7 +272,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
290 | else | 272 | else |
291 | s3c24xx_snd_txctrl(1); | 273 | s3c24xx_snd_txctrl(1); |
292 | 274 | ||
293 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
294 | break; | 275 | break; |
295 | case SNDRV_PCM_TRIGGER_STOP: | 276 | case SNDRV_PCM_TRIGGER_STOP: |
296 | case SNDRV_PCM_TRIGGER_SUSPEND: | 277 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -380,17 +361,15 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
380 | { | 361 | { |
381 | pr_debug("Entered %s\n", __func__); | 362 | pr_debug("Entered %s\n", __func__); |
382 | 363 | ||
383 | s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); | 364 | samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, |
384 | if (s3c24xx_i2s.regs == NULL) | 365 | &s3c24xx_i2s_pcm_stereo_in); |
385 | return -ENXIO; | ||
386 | 366 | ||
387 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); | 367 | s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis"); |
388 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { | 368 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { |
389 | pr_err("failed to get iis_clock\n"); | 369 | pr_err("failed to get iis_clock\n"); |
390 | iounmap(s3c24xx_i2s.regs); | ||
391 | return PTR_ERR(s3c24xx_i2s.iis_clk); | 370 | return PTR_ERR(s3c24xx_i2s.iis_clk); |
392 | } | 371 | } |
393 | clk_enable(s3c24xx_i2s.iis_clk); | 372 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
394 | 373 | ||
395 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ | 374 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ |
396 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), | 375 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), |
@@ -414,7 +393,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
414 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 393 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
415 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); | 394 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); |
416 | 395 | ||
417 | clk_disable(s3c24xx_i2s.iis_clk); | 396 | clk_disable_unprepare(s3c24xx_i2s.iis_clk); |
418 | 397 | ||
419 | return 0; | 398 | return 0; |
420 | } | 399 | } |
@@ -422,7 +401,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
422 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | 401 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
423 | { | 402 | { |
424 | pr_debug("Entered %s\n", __func__); | 403 | pr_debug("Entered %s\n", __func__); |
425 | clk_enable(s3c24xx_i2s.iis_clk); | 404 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
426 | 405 | ||
427 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); | 406 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); |
428 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 407 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -474,6 +453,19 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { | |||
474 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | 453 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) |
475 | { | 454 | { |
476 | int ret = 0; | 455 | int ret = 0; |
456 | struct resource *res; | ||
457 | |||
458 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
459 | if (!res) { | ||
460 | dev_err(&pdev->dev, "Can't get IO resource.\n"); | ||
461 | return -ENOENT; | ||
462 | } | ||
463 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
464 | if (s3c24xx_i2s.regs == NULL) | ||
465 | return -ENXIO; | ||
466 | |||
467 | s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; | ||
468 | s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; | ||
477 | 469 | ||
478 | ret = devm_snd_soc_register_component(&pdev->dev, | 470 | ret = devm_snd_soc_register_component(&pdev->dev, |
479 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); | 471 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index e119aaa91c28..63d079303561 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * o '0' means 'OFF' | 25 | * o '0' means 'OFF' |
26 | * o 'X' means 'Don't care' | 26 | * o 'X' means 'Don't care' |
27 | * | 27 | * |
28 | * SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-1111 | 28 | * SMDK6410 Base B/D: CFG1-0000, CFG2-1111 |
29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 | 29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 |
30 | */ | 30 | */ |
31 | 31 | ||
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 014c177840ba..0acf5d0eed53 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c | |||
@@ -92,6 +92,9 @@ static int snow_probe(struct platform_device *pdev) | |||
92 | 92 | ||
93 | card->dev = &pdev->dev; | 93 | card->dev = &pdev->dev; |
94 | 94 | ||
95 | /* Update card-name if provided through DT, else use default name */ | ||
96 | snd_soc_of_parse_card_name(card, "samsung,model"); | ||
97 | |||
95 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 98 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
96 | if (ret) { | 99 | if (ret) { |
97 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 100 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
@@ -103,6 +106,7 @@ static int snow_probe(struct platform_device *pdev) | |||
103 | 106 | ||
104 | static const struct of_device_id snow_of_match[] = { | 107 | static const struct of_device_id snow_of_match[] = { |
105 | { .compatible = "google,snow-audio-max98090", }, | 108 | { .compatible = "google,snow-audio-max98090", }, |
109 | { .compatible = "google,snow-audio-max98091", }, | ||
106 | { .compatible = "google,snow-audio-max98095", }, | 110 | { .compatible = "google,snow-audio-max98095", }, |
107 | {}, | 111 | {}, |
108 | }; | 112 | }; |
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index d9ffc48fce5e..d7d2e208f486 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c | |||
@@ -93,10 +93,6 @@ struct samsung_spdif_info { | |||
93 | struct s3c_dma_params *dma_playback; | 93 | struct s3c_dma_params *dma_playback; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static struct s3c_dma_client spdif_dma_client_out = { | ||
97 | .name = "S/PDIF Stereo out", | ||
98 | }; | ||
99 | |||
100 | static struct s3c_dma_params spdif_stereo_out; | 96 | static struct s3c_dma_params spdif_stereo_out; |
101 | static struct samsung_spdif_info spdif_info; | 97 | static struct samsung_spdif_info spdif_info; |
102 | 98 | ||
@@ -435,7 +431,6 @@ static int spdif_probe(struct platform_device *pdev) | |||
435 | } | 431 | } |
436 | 432 | ||
437 | spdif_stereo_out.dma_size = 2; | 433 | spdif_stereo_out.dma_size = 2; |
438 | spdif_stereo_out.client = &spdif_dma_client_out; | ||
439 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; | 434 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; |
440 | spdif_stereo_out.channel = dma_res->start; | 435 | spdif_stereo_out.channel = dma_res->start; |
441 | 436 | ||
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index b43fdf0d08af..80245b6eebd6 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU | |||
37 | config SND_SOC_RCAR | 37 | config SND_SOC_RCAR |
38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" |
39 | select SND_SIMPLE_CARD | 39 | select SND_SIMPLE_CARD |
40 | select REGMAP | 40 | select REGMAP_MMIO |
41 | help | 41 | help |
42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support | 42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support |
43 | 43 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 710a079a7377..c76344350e44 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -232,11 +232,7 @@ struct fsi_stream { | |||
232 | * these are for DMAEngine | 232 | * these are for DMAEngine |
233 | */ | 233 | */ |
234 | struct dma_chan *chan; | 234 | struct dma_chan *chan; |
235 | struct work_struct work; | ||
236 | dma_addr_t dma; | ||
237 | int dma_id; | 235 | int dma_id; |
238 | int loop_cnt; | ||
239 | int additional_pos; | ||
240 | }; | 236 | }; |
241 | 237 | ||
242 | struct fsi_clk { | 238 | struct fsi_clk { |
@@ -264,12 +260,12 @@ struct fsi_priv { | |||
264 | u32 fmt; | 260 | u32 fmt; |
265 | 261 | ||
266 | int chan_num:16; | 262 | int chan_num:16; |
267 | int clk_master:1; | 263 | unsigned int clk_master:1; |
268 | int clk_cpg:1; | 264 | unsigned int clk_cpg:1; |
269 | int spdif:1; | 265 | unsigned int spdif:1; |
270 | int enable_stream:1; | 266 | unsigned int enable_stream:1; |
271 | int bit_clk_inv:1; | 267 | unsigned int bit_clk_inv:1; |
272 | int lr_clk_inv:1; | 268 | unsigned int lr_clk_inv:1; |
273 | }; | 269 | }; |
274 | 270 | ||
275 | struct fsi_stream_handler { | 271 | struct fsi_stream_handler { |
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev, | |||
1042 | return ret; | 1038 | return ret; |
1043 | } | 1039 | } |
1044 | 1040 | ||
1041 | static void fsi_pointer_update(struct fsi_stream *io, int size) | ||
1042 | { | ||
1043 | io->buff_sample_pos += size; | ||
1044 | |||
1045 | if (io->buff_sample_pos >= | ||
1046 | io->period_samples * (io->period_pos + 1)) { | ||
1047 | struct snd_pcm_substream *substream = io->substream; | ||
1048 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1049 | |||
1050 | io->period_pos++; | ||
1051 | |||
1052 | if (io->period_pos >= runtime->periods) { | ||
1053 | io->buff_sample_pos = 0; | ||
1054 | io->period_pos = 0; | ||
1055 | } | ||
1056 | |||
1057 | snd_pcm_period_elapsed(substream); | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1045 | /* | 1061 | /* |
1046 | * pio data transfer handler | 1062 | * pio data transfer handler |
1047 | */ | 1063 | */ |
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1108 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), | 1124 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), |
1109 | int samples) | 1125 | int samples) |
1110 | { | 1126 | { |
1111 | struct snd_pcm_runtime *runtime; | ||
1112 | struct snd_pcm_substream *substream; | ||
1113 | u8 *buf; | 1127 | u8 *buf; |
1114 | int over_period; | ||
1115 | 1128 | ||
1116 | if (!fsi_stream_is_working(fsi, io)) | 1129 | if (!fsi_stream_is_working(fsi, io)) |
1117 | return -EINVAL; | 1130 | return -EINVAL; |
1118 | 1131 | ||
1119 | over_period = 0; | ||
1120 | substream = io->substream; | ||
1121 | runtime = substream->runtime; | ||
1122 | |||
1123 | /* FSI FIFO has limit. | ||
1124 | * So, this driver can not send periods data at a time | ||
1125 | */ | ||
1126 | if (io->buff_sample_pos >= | ||
1127 | io->period_samples * (io->period_pos + 1)) { | ||
1128 | |||
1129 | over_period = 1; | ||
1130 | io->period_pos = (io->period_pos + 1) % runtime->periods; | ||
1131 | |||
1132 | if (0 == io->period_pos) | ||
1133 | io->buff_sample_pos = 0; | ||
1134 | } | ||
1135 | |||
1136 | buf = fsi_pio_get_area(fsi, io); | 1132 | buf = fsi_pio_get_area(fsi, io); |
1137 | 1133 | ||
1138 | switch (io->sample_width) { | 1134 | switch (io->sample_width) { |
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1146 | return -EINVAL; | 1142 | return -EINVAL; |
1147 | } | 1143 | } |
1148 | 1144 | ||
1149 | /* update buff_sample_pos */ | 1145 | fsi_pointer_update(io, samples); |
1150 | io->buff_sample_pos += samples; | ||
1151 | |||
1152 | if (over_period) | ||
1153 | snd_pcm_period_elapsed(substream); | ||
1154 | 1146 | ||
1155 | return 0; | 1147 | return 0; |
1156 | } | 1148 | } |
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
1279 | */ | 1271 | */ |
1280 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | 1272 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) |
1281 | { | 1273 | { |
1282 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1283 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1284 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1285 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1286 | |||
1287 | /* | 1274 | /* |
1288 | * 24bit data : 24bit bus / package in back | 1275 | * 24bit data : 24bit bus / package in back |
1289 | * 16bit data : 16bit bus / stream mode | 1276 | * 16bit data : 16bit bus / stream mode |
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1291 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | 1278 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | |
1292 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | 1279 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); |
1293 | 1280 | ||
1294 | io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */ | ||
1295 | io->additional_pos = 0; | ||
1296 | io->dma = dma_map_single(dai->dev, runtime->dma_area, | ||
1297 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1298 | return 0; | 1281 | return 0; |
1299 | } | 1282 | } |
1300 | 1283 | ||
1301 | static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io) | ||
1302 | { | ||
1303 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1304 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1305 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1306 | |||
1307 | dma_unmap_single(dai->dev, io->dma, | ||
1308 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional) | ||
1313 | { | ||
1314 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1315 | int period = io->period_pos + additional; | ||
1316 | |||
1317 | if (period >= runtime->periods) | ||
1318 | period = 0; | ||
1319 | |||
1320 | return io->dma + samples_to_bytes(runtime, period * io->period_samples); | ||
1321 | } | ||
1322 | |||
1323 | static void fsi_dma_complete(void *data) | 1284 | static void fsi_dma_complete(void *data) |
1324 | { | 1285 | { |
1325 | struct fsi_stream *io = (struct fsi_stream *)data; | 1286 | struct fsi_stream *io = (struct fsi_stream *)data; |
1326 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1287 | struct fsi_priv *fsi = fsi_stream_to_priv(io); |
1327 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1328 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1329 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1330 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1331 | 1288 | ||
1332 | dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0), | 1289 | fsi_pointer_update(io, io->period_samples); |
1333 | samples_to_bytes(runtime, io->period_samples), dir); | ||
1334 | |||
1335 | io->buff_sample_pos += io->period_samples; | ||
1336 | io->period_pos++; | ||
1337 | |||
1338 | if (io->period_pos >= runtime->periods) { | ||
1339 | io->period_pos = 0; | ||
1340 | io->buff_sample_pos = 0; | ||
1341 | } | ||
1342 | 1290 | ||
1343 | fsi_count_fifo_err(fsi); | 1291 | fsi_count_fifo_err(fsi); |
1344 | fsi_stream_transfer(io); | ||
1345 | |||
1346 | snd_pcm_period_elapsed(io->substream); | ||
1347 | } | 1292 | } |
1348 | 1293 | ||
1349 | static void fsi_dma_do_work(struct work_struct *work) | 1294 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1350 | { | 1295 | { |
1351 | struct fsi_stream *io = container_of(work, struct fsi_stream, work); | 1296 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); |
1352 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1297 | struct snd_pcm_substream *substream = io->substream; |
1353 | struct snd_soc_dai *dai; | ||
1354 | struct dma_async_tx_descriptor *desc; | 1298 | struct dma_async_tx_descriptor *desc; |
1355 | struct snd_pcm_runtime *runtime; | ||
1356 | enum dma_data_direction dir; | ||
1357 | int is_play = fsi_stream_is_play(fsi, io); | 1299 | int is_play = fsi_stream_is_play(fsi, io); |
1358 | int len, i; | 1300 | enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
1359 | dma_addr_t buf; | 1301 | int ret = -EIO; |
1360 | 1302 | ||
1361 | if (!fsi_stream_is_working(fsi, io)) | 1303 | desc = dmaengine_prep_dma_cyclic(io->chan, |
1362 | return; | 1304 | substream->runtime->dma_addr, |
1363 | 1305 | snd_pcm_lib_buffer_bytes(substream), | |
1364 | dai = fsi_get_dai(io->substream); | 1306 | snd_pcm_lib_period_bytes(substream), |
1365 | runtime = io->substream->runtime; | 1307 | dir, |
1366 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1308 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1367 | len = samples_to_bytes(runtime, io->period_samples); | 1309 | if (!desc) { |
1368 | 1310 | dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n"); | |
1369 | for (i = 0; i < io->loop_cnt; i++) { | 1311 | goto fsi_dma_transfer_err; |
1370 | buf = fsi_dma_get_area(io, io->additional_pos); | 1312 | } |
1371 | |||
1372 | dma_sync_single_for_device(dai->dev, buf, len, dir); | ||
1373 | |||
1374 | desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, | ||
1375 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1376 | if (!desc) { | ||
1377 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); | ||
1378 | return; | ||
1379 | } | ||
1380 | |||
1381 | desc->callback = fsi_dma_complete; | ||
1382 | desc->callback_param = io; | ||
1383 | |||
1384 | if (dmaengine_submit(desc) < 0) { | ||
1385 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1386 | return; | ||
1387 | } | ||
1388 | 1313 | ||
1389 | dma_async_issue_pending(io->chan); | 1314 | desc->callback = fsi_dma_complete; |
1315 | desc->callback_param = io; | ||
1390 | 1316 | ||
1391 | io->additional_pos = 1; | 1317 | if (dmaengine_submit(desc) < 0) { |
1318 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1319 | goto fsi_dma_transfer_err; | ||
1392 | } | 1320 | } |
1393 | 1321 | ||
1394 | io->loop_cnt = 1; | 1322 | dma_async_issue_pending(io->chan); |
1395 | 1323 | ||
1396 | /* | 1324 | /* |
1397 | * FIXME | 1325 | * FIXME |
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work) | |||
1408 | fsi_reg_write(fsi, DIFF_ST, 0); | 1336 | fsi_reg_write(fsi, DIFF_ST, 0); |
1409 | } | 1337 | } |
1410 | } | 1338 | } |
1411 | } | ||
1412 | 1339 | ||
1413 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1340 | ret = 0; |
1414 | { | ||
1415 | schedule_work(&io->work); | ||
1416 | 1341 | ||
1417 | return 0; | 1342 | fsi_dma_transfer_err: |
1343 | return ret; | ||
1418 | } | 1344 | } |
1419 | 1345 | ||
1420 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1346 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev | |||
1475 | return fsi_stream_probe(fsi, dev); | 1401 | return fsi_stream_probe(fsi, dev); |
1476 | } | 1402 | } |
1477 | 1403 | ||
1478 | INIT_WORK(&io->work, fsi_dma_do_work); | ||
1479 | |||
1480 | return 0; | 1404 | return 0; |
1481 | } | 1405 | } |
1482 | 1406 | ||
1483 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | 1407 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) |
1484 | { | 1408 | { |
1485 | cancel_work_sync(&io->work); | ||
1486 | |||
1487 | fsi_stream_stop(fsi, io); | 1409 | fsi_stream_stop(fsi, io); |
1488 | 1410 | ||
1489 | if (io->chan) | 1411 | if (io->chan) |
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1495 | 1417 | ||
1496 | static struct fsi_stream_handler fsi_dma_push_handler = { | 1418 | static struct fsi_stream_handler fsi_dma_push_handler = { |
1497 | .init = fsi_dma_init, | 1419 | .init = fsi_dma_init, |
1498 | .quit = fsi_dma_quit, | ||
1499 | .probe = fsi_dma_probe, | 1420 | .probe = fsi_dma_probe, |
1500 | .transfer = fsi_dma_transfer, | 1421 | .transfer = fsi_dma_transfer, |
1501 | .remove = fsi_dma_remove, | 1422 | .remove = fsi_dma_remove, |
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1657 | if (!ret) | 1578 | if (!ret) |
1658 | ret = fsi_hw_startup(fsi, io, dai->dev); | 1579 | ret = fsi_hw_startup(fsi, io, dai->dev); |
1659 | if (!ret) | 1580 | if (!ret) |
1660 | ret = fsi_stream_transfer(io); | 1581 | ret = fsi_stream_start(fsi, io); |
1661 | if (!ret) | 1582 | if (!ret) |
1662 | fsi_stream_start(fsi, io); | 1583 | ret = fsi_stream_transfer(io); |
1663 | break; | 1584 | break; |
1664 | case SNDRV_PCM_TRIGGER_STOP: | 1585 | case SNDRV_PCM_TRIGGER_STOP: |
1665 | if (!ret) | 1586 | if (!ret) |
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm) | |||
1850 | 1771 | ||
1851 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) | 1772 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) |
1852 | { | 1773 | { |
1853 | struct snd_pcm *pcm = rtd->pcm; | ||
1854 | |||
1855 | /* | ||
1856 | * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | ||
1857 | * in MMAP mode (i.e. aplay -M) | ||
1858 | */ | ||
1859 | return snd_pcm_lib_preallocate_pages_for_all( | 1774 | return snd_pcm_lib_preallocate_pages_for_all( |
1860 | pcm, | 1775 | rtd->pcm, |
1861 | SNDRV_DMA_TYPE_CONTINUOUS, | 1776 | SNDRV_DMA_TYPE_DEV, |
1862 | snd_dma_continuous_data(GFP_KERNEL), | 1777 | rtd->card->snd_card->dev, |
1863 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | 1778 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
1864 | } | 1779 | } |
1865 | 1780 | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4e86265f625c..19f78963e8b9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
138 | return mod->ops->name; | 138 | return mod->ops->name; |
139 | } | 139 | } |
140 | 140 | ||
141 | char *rsnd_mod_dma_name(struct rsnd_mod *mod) | ||
142 | { | ||
143 | if (!mod || !mod->ops) | ||
144 | return "unknown"; | ||
145 | |||
146 | if (!mod->ops->dma_name) | ||
147 | return mod->ops->name; | ||
148 | |||
149 | return mod->ops->dma_name(mod); | ||
150 | } | ||
151 | |||
141 | void rsnd_mod_init(struct rsnd_priv *priv, | 152 | void rsnd_mod_init(struct rsnd_priv *priv, |
142 | struct rsnd_mod *mod, | 153 | struct rsnd_mod *mod, |
143 | struct rsnd_mod_ops *ops, | 154 | struct rsnd_mod_ops *ops, |
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
153 | /* | 164 | /* |
154 | * rsnd_dma functions | 165 | * rsnd_dma functions |
155 | */ | 166 | */ |
156 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
157 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
158 | { | ||
159 | /* push next A or B plane */ | ||
160 | dma->submit_loop = 1; | ||
161 | schedule_work(&dma->work); | ||
162 | } | ||
163 | |||
164 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
165 | { | ||
166 | /* push both A and B plane*/ | ||
167 | dma->offset = 0; | ||
168 | dma->submit_loop = 2; | ||
169 | __rsnd_dma_start(dma); | ||
170 | } | ||
171 | |||
172 | void rsnd_dma_stop(struct rsnd_dma *dma) | 167 | void rsnd_dma_stop(struct rsnd_dma *dma) |
173 | { | 168 | { |
174 | dma->submit_loop = 0; | ||
175 | cancel_work_sync(&dma->work); | ||
176 | dmaengine_terminate_all(dma->chan); | 169 | dmaengine_terminate_all(dma->chan); |
177 | } | 170 | } |
178 | 171 | ||
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data) | |||
180 | { | 173 | { |
181 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 174 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
182 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 175 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
183 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
184 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 176 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
185 | unsigned long flags; | ||
186 | |||
187 | rsnd_lock(priv, flags); | ||
188 | 177 | ||
189 | /* | 178 | /* |
190 | * Renesas sound Gen1 needs 1 DMAC, | 179 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data) | |||
197 | * rsnd_dai_pointer_update() will be called twice, | 186 | * rsnd_dai_pointer_update() will be called twice, |
198 | * ant it will breaks io->byte_pos | 187 | * ant it will breaks io->byte_pos |
199 | */ | 188 | */ |
200 | if (dma->submit_loop) | ||
201 | rsnd_dma_continue(dma); | ||
202 | |||
203 | rsnd_unlock(priv, flags); | ||
204 | 189 | ||
205 | rsnd_dai_pointer_update(io, io->byte_per_period); | 190 | rsnd_dai_pointer_update(io, io->byte_per_period); |
206 | } | 191 | } |
207 | 192 | ||
208 | static void __rsnd_dma_start(struct rsnd_dma *dma) | 193 | void rsnd_dma_start(struct rsnd_dma *dma) |
209 | { | 194 | { |
210 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 195 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
211 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
212 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 197 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
213 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 198 | struct snd_pcm_substream *substream = io->substream; |
214 | struct device *dev = rsnd_priv_to_dev(priv); | 199 | struct device *dev = rsnd_priv_to_dev(priv); |
215 | struct dma_async_tx_descriptor *desc; | 200 | struct dma_async_tx_descriptor *desc; |
216 | dma_addr_t buf; | ||
217 | size_t len = io->byte_per_period; | ||
218 | int i; | ||
219 | 201 | ||
220 | for (i = 0; i < dma->submit_loop; i++) { | 202 | desc = dmaengine_prep_dma_cyclic(dma->chan, |
221 | 203 | (dma->addr) ? dma->addr : | |
222 | buf = runtime->dma_addr + | 204 | substream->runtime->dma_addr, |
223 | rsnd_dai_pointer_offset(io, dma->offset + len); | 205 | snd_pcm_lib_buffer_bytes(substream), |
224 | dma->offset = len; | 206 | snd_pcm_lib_period_bytes(substream), |
225 | 207 | dma->dir, | |
226 | desc = dmaengine_prep_slave_single( | 208 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
227 | dma->chan, buf, len, dma->dir, | ||
228 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
229 | if (!desc) { | ||
230 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
231 | return; | ||
232 | } | ||
233 | 209 | ||
234 | desc->callback = rsnd_dma_complete; | 210 | if (!desc) { |
235 | desc->callback_param = dma; | 211 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
212 | return; | ||
213 | } | ||
236 | 214 | ||
237 | if (dmaengine_submit(desc) < 0) { | 215 | desc->callback = rsnd_dma_complete; |
238 | dev_err(dev, "dmaengine_submit() fail\n"); | 216 | desc->callback_param = dma; |
239 | return; | ||
240 | } | ||
241 | 217 | ||
242 | dma_async_issue_pending(dma->chan); | 218 | if (dmaengine_submit(desc) < 0) { |
219 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
220 | return; | ||
243 | } | 221 | } |
244 | } | ||
245 | |||
246 | static void rsnd_dma_do_work(struct work_struct *work) | ||
247 | { | ||
248 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
249 | 222 | ||
250 | __rsnd_dma_start(dma); | 223 | dma_async_issue_pending(dma->chan); |
251 | } | 224 | } |
252 | 225 | ||
253 | int rsnd_dma_available(struct rsnd_dma *dma) | 226 | int rsnd_dma_available(struct rsnd_dma *dma) |
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) | |||
261 | { | 234 | { |
262 | if (mod) | 235 | if (mod) |
263 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", | 236 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", |
264 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 237 | rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); |
265 | else | 238 | else |
266 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); | 239 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); |
267 | 240 | ||
268 | } | 241 | } |
269 | 242 | ||
270 | static void rsnd_dma_of_name(struct rsnd_dma *dma, | 243 | static void rsnd_dma_of_name(struct rsnd_mod *mod_from, |
271 | int is_play, char *dma_name) | 244 | struct rsnd_mod *mod_to, |
245 | char *dma_name) | ||
246 | { | ||
247 | int index = 0; | ||
248 | |||
249 | index = _rsnd_dma_of_name(dma_name + index, mod_from); | ||
250 | *(dma_name + index++) = '_'; | ||
251 | index = _rsnd_dma_of_name(dma_name + index, mod_to); | ||
252 | } | ||
253 | |||
254 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | ||
255 | int is_play, | ||
256 | struct rsnd_mod **mod_from, | ||
257 | struct rsnd_mod **mod_to) | ||
272 | { | 258 | { |
273 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 259 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
274 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); | 260 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); |
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
276 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 262 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
277 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 263 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
278 | struct rsnd_mod *mod[MOD_MAX]; | 264 | struct rsnd_mod *mod[MOD_MAX]; |
279 | struct rsnd_mod *src_mod, *dst_mod; | ||
280 | int i, index; | 265 | int i, index; |
281 | 266 | ||
282 | 267 | ||
@@ -297,31 +282,34 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
297 | for (i = 1; i < MOD_MAX; i++) { | 282 | for (i = 1; i < MOD_MAX; i++) { |
298 | if (!src) { | 283 | if (!src) { |
299 | mod[i] = ssi; | 284 | mod[i] = ssi; |
300 | break; | ||
301 | } else if (!dvc) { | 285 | } else if (!dvc) { |
302 | mod[i] = src; | 286 | mod[i] = src; |
303 | src = NULL; | 287 | src = NULL; |
304 | } else { | 288 | } else { |
305 | mod[i] = dvc; | 289 | if ((!is_play) && (this == src)) |
290 | this = dvc; | ||
291 | |||
292 | mod[i] = (is_play) ? src : dvc; | ||
293 | i++; | ||
294 | mod[i] = (is_play) ? dvc : src; | ||
295 | src = NULL; | ||
306 | dvc = NULL; | 296 | dvc = NULL; |
307 | } | 297 | } |
308 | 298 | ||
309 | if (mod[i] == this) | 299 | if (mod[i] == this) |
310 | index = i; | 300 | index = i; |
301 | |||
302 | if (mod[i] == ssi) | ||
303 | break; | ||
311 | } | 304 | } |
312 | 305 | ||
313 | if (is_play) { | 306 | if (is_play) { |
314 | src_mod = mod[index - 1]; | 307 | *mod_from = mod[index - 1]; |
315 | dst_mod = mod[index]; | 308 | *mod_to = mod[index]; |
316 | } else { | 309 | } else { |
317 | src_mod = mod[index]; | 310 | *mod_from = mod[index]; |
318 | dst_mod = mod[index - 1]; | 311 | *mod_to = mod[index - 1]; |
319 | } | 312 | } |
320 | |||
321 | index = 0; | ||
322 | index = _rsnd_dma_of_name(dma_name + index, src_mod); | ||
323 | *(dma_name + index++) = '_'; | ||
324 | index = _rsnd_dma_of_name(dma_name + index, dst_mod); | ||
325 | } | 313 | } |
326 | 314 | ||
327 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 315 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
@@ -329,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
329 | { | 317 | { |
330 | struct device *dev = rsnd_priv_to_dev(priv); | 318 | struct device *dev = rsnd_priv_to_dev(priv); |
331 | struct dma_slave_config cfg; | 319 | struct dma_slave_config cfg; |
320 | struct rsnd_mod *mod_from; | ||
321 | struct rsnd_mod *mod_to; | ||
332 | char dma_name[DMA_NAME_SIZE]; | 322 | char dma_name[DMA_NAME_SIZE]; |
333 | dma_cap_mask_t mask; | 323 | dma_cap_mask_t mask; |
334 | int ret; | 324 | int ret; |
@@ -341,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
341 | dma_cap_zero(mask); | 331 | dma_cap_zero(mask); |
342 | dma_cap_set(DMA_SLAVE, mask); | 332 | dma_cap_set(DMA_SLAVE, mask); |
343 | 333 | ||
344 | if (dev->of_node) | 334 | rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); |
345 | rsnd_dma_of_name(dma, is_play, dma_name); | 335 | rsnd_dma_of_name(mod_from, mod_to, dma_name); |
346 | else | ||
347 | snprintf(dma_name, DMA_NAME_SIZE, | ||
348 | is_play ? "tx" : "rx"); | ||
349 | 336 | ||
350 | dev_dbg(dev, "dma name : %s\n", dma_name); | 337 | cfg.slave_id = id; |
338 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | ||
339 | cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); | ||
340 | cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); | ||
341 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
342 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
343 | |||
344 | dev_dbg(dev, "dma : %s %pad -> %pad\n", | ||
345 | dma_name, &cfg.src_addr, &cfg.dst_addr); | ||
351 | 346 | ||
352 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 347 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
353 | (void *)id, dev, | 348 | (void *)id, dev, |
@@ -357,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
357 | return -EIO; | 352 | return -EIO; |
358 | } | 353 | } |
359 | 354 | ||
360 | rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id); | ||
361 | |||
362 | ret = dmaengine_slave_config(dma->chan, &cfg); | 355 | ret = dmaengine_slave_config(dma->chan, &cfg); |
363 | if (ret < 0) | 356 | if (ret < 0) |
364 | goto rsnd_dma_init_err; | 357 | goto rsnd_dma_init_err; |
365 | 358 | ||
366 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 359 | dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; |
367 | INIT_WORK(&dma->work, rsnd_dma_do_work); | 360 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
368 | 361 | ||
369 | return 0; | 362 | return 0; |
370 | 363 | ||
@@ -631,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
631 | return -EINVAL; | 624 | return -EINVAL; |
632 | } | 625 | } |
633 | 626 | ||
634 | /* set clock inversion */ | ||
635 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
636 | case SND_SOC_DAIFMT_NB_IF: | ||
637 | rdai->bit_clk_inv = 0; | ||
638 | rdai->frm_clk_inv = 1; | ||
639 | break; | ||
640 | case SND_SOC_DAIFMT_IB_NF: | ||
641 | rdai->bit_clk_inv = 1; | ||
642 | rdai->frm_clk_inv = 0; | ||
643 | break; | ||
644 | case SND_SOC_DAIFMT_IB_IF: | ||
645 | rdai->bit_clk_inv = 1; | ||
646 | rdai->frm_clk_inv = 1; | ||
647 | break; | ||
648 | case SND_SOC_DAIFMT_NB_NF: | ||
649 | default: | ||
650 | rdai->bit_clk_inv = 0; | ||
651 | rdai->frm_clk_inv = 0; | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | /* set format */ | 627 | /* set format */ |
656 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 628 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
657 | case SND_SOC_DAIFMT_I2S: | 629 | case SND_SOC_DAIFMT_I2S: |
658 | rdai->sys_delay = 0; | 630 | rdai->sys_delay = 0; |
659 | rdai->data_alignment = 0; | 631 | rdai->data_alignment = 0; |
632 | rdai->frm_clk_inv = 0; | ||
660 | break; | 633 | break; |
661 | case SND_SOC_DAIFMT_LEFT_J: | 634 | case SND_SOC_DAIFMT_LEFT_J: |
662 | rdai->sys_delay = 1; | 635 | rdai->sys_delay = 1; |
663 | rdai->data_alignment = 0; | 636 | rdai->data_alignment = 0; |
637 | rdai->frm_clk_inv = 1; | ||
664 | break; | 638 | break; |
665 | case SND_SOC_DAIFMT_RIGHT_J: | 639 | case SND_SOC_DAIFMT_RIGHT_J: |
666 | rdai->sys_delay = 1; | 640 | rdai->sys_delay = 1; |
667 | rdai->data_alignment = 1; | 641 | rdai->data_alignment = 1; |
642 | rdai->frm_clk_inv = 1; | ||
643 | break; | ||
644 | } | ||
645 | |||
646 | /* set clock inversion */ | ||
647 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
648 | case SND_SOC_DAIFMT_NB_IF: | ||
649 | rdai->bit_clk_inv = rdai->bit_clk_inv; | ||
650 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_IB_NF: | ||
653 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
654 | rdai->frm_clk_inv = rdai->frm_clk_inv; | ||
655 | break; | ||
656 | case SND_SOC_DAIFMT_IB_IF: | ||
657 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
658 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
659 | break; | ||
660 | case SND_SOC_DAIFMT_NB_NF: | ||
661 | default: | ||
668 | break; | 662 | break; |
669 | } | 663 | } |
670 | 664 | ||
@@ -734,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
734 | struct device_node *dai_node, *dai_np; | 728 | struct device_node *dai_node, *dai_np; |
735 | struct device_node *ssi_node, *ssi_np; | 729 | struct device_node *ssi_node, *ssi_np; |
736 | struct device_node *src_node, *src_np; | 730 | struct device_node *src_node, *src_np; |
731 | struct device_node *dvc_node, *dvc_np; | ||
737 | struct device_node *playback, *capture; | 732 | struct device_node *playback, *capture; |
738 | struct rsnd_dai_platform_info *dai_info; | 733 | struct rsnd_dai_platform_info *dai_info; |
739 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 734 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
740 | struct device *dev = &pdev->dev; | 735 | struct device *dev = &pdev->dev; |
741 | int nr, i; | 736 | int nr, i; |
742 | int dai_i, ssi_i, src_i; | 737 | int dai_i, ssi_i, src_i, dvc_i; |
743 | 738 | ||
744 | if (!of_data) | 739 | if (!of_data) |
745 | return; | 740 | return; |
@@ -765,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
765 | 760 | ||
766 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); | 761 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); |
767 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); | 762 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); |
763 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
768 | 764 | ||
769 | #define mod_parse(name) \ | 765 | #define mod_parse(name) \ |
770 | if (name##_node) { \ | 766 | if (name##_node) { \ |
@@ -800,6 +796,7 @@ if (name##_node) { \ | |||
800 | 796 | ||
801 | mod_parse(ssi); | 797 | mod_parse(ssi); |
802 | mod_parse(src); | 798 | mod_parse(src); |
799 | mod_parse(dvc); | ||
803 | 800 | ||
804 | if (playback) | 801 | if (playback) |
805 | of_node_put(playback); | 802 | of_node_put(playback); |
@@ -948,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
948 | 945 | ||
949 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | 946 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
950 | { | 947 | { |
951 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 948 | struct snd_soc_dai *dai = rtd->cpu_dai; |
952 | struct rsnd_dai *rdai; | 949 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
953 | int i, ret; | 950 | int ret; |
954 | 951 | ||
955 | for_each_rsnd_dai(rdai, priv, i) { | 952 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); |
956 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | 953 | if (ret) |
957 | if (ret) | 954 | return ret; |
958 | return ret; | ||
959 | 955 | ||
960 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | 956 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); |
961 | if (ret) | 957 | if (ret) |
962 | return ret; | 958 | return ret; |
963 | } | ||
964 | 959 | ||
965 | return snd_pcm_lib_preallocate_pages_for_all( | 960 | return snd_pcm_lib_preallocate_pages_for_all( |
966 | rtd->pcm, | 961 | rtd->pcm, |
@@ -1047,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1047 | for_each_rsnd_dai(rdai, priv, i) { | 1042 | for_each_rsnd_dai(rdai, priv, i) { |
1048 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); | 1043 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); |
1049 | if (ret) | 1044 | if (ret) |
1050 | return ret; | 1045 | goto exit_snd_probe; |
1051 | 1046 | ||
1052 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); | 1047 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); |
1053 | if (ret) | 1048 | if (ret) |
1054 | return ret; | 1049 | goto exit_snd_probe; |
1055 | } | 1050 | } |
1056 | 1051 | ||
1057 | /* | 1052 | /* |
@@ -1079,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1079 | 1074 | ||
1080 | exit_snd_soc: | 1075 | exit_snd_soc: |
1081 | snd_soc_unregister_platform(dev); | 1076 | snd_soc_unregister_platform(dev); |
1077 | exit_snd_probe: | ||
1078 | for_each_rsnd_dai(rdai, priv, i) { | ||
1079 | rsnd_dai_call(remove, &rdai->playback, rdai); | ||
1080 | rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1081 | } | ||
1082 | 1082 | ||
1083 | return ret; | 1083 | return ret; |
1084 | } | 1084 | } |
@@ -1087,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1087 | { | 1087 | { |
1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | 1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); |
1089 | struct rsnd_dai *rdai; | 1089 | struct rsnd_dai *rdai; |
1090 | int ret, i; | 1090 | int ret = 0, i; |
1091 | 1091 | ||
1092 | pm_runtime_disable(&pdev->dev); | 1092 | pm_runtime_disable(&pdev->dev); |
1093 | 1093 | ||
1094 | for_each_rsnd_dai(rdai, priv, i) { | 1094 | for_each_rsnd_dai(rdai, priv, i) { |
1095 | ret = rsnd_dai_call(remove, &rdai->playback, rdai); | 1095 | ret |= rsnd_dai_call(remove, &rdai->playback, rdai); |
1096 | if (ret) | 1096 | ret |= rsnd_dai_call(remove, &rdai->capture, rdai); |
1097 | return ret; | ||
1098 | |||
1099 | ret = rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1100 | if (ret) | ||
1101 | return ret; | ||
1102 | } | 1097 | } |
1103 | 1098 | ||
1104 | return 0; | 1099 | return ret; |
1105 | } | 1100 | } |
1106 | 1101 | ||
1107 | static struct platform_driver rsnd_driver = { | 1102 | static struct platform_driver rsnd_driver = { |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index ed0007006899..3f443930c2b1 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -20,7 +20,8 @@ struct rsnd_dvc { | |||
20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | 20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ |
21 | struct rsnd_mod mod; | 21 | struct rsnd_mod mod; |
22 | struct clk *clk; | 22 | struct clk *clk; |
23 | long volume[RSND_DVC_VOLUME_NUM]; | 23 | u8 volume[RSND_DVC_VOLUME_NUM]; |
24 | u8 mute[RSND_DVC_VOLUME_NUM]; | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | #define rsnd_mod_to_dvc(_mod) \ | 27 | #define rsnd_mod_to_dvc(_mod) \ |
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | |||
37 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 38 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
38 | u32 max = (0x00800000 - 1); | 39 | u32 max = (0x00800000 - 1); |
39 | u32 vol[RSND_DVC_VOLUME_NUM]; | 40 | u32 vol[RSND_DVC_VOLUME_NUM]; |
41 | u32 mute = 0; | ||
40 | int i; | 42 | int i; |
41 | 43 | ||
42 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 44 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
43 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; | 45 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; |
46 | mute |= (!!dvc->mute[i]) << i; | ||
47 | } | ||
44 | 48 | ||
45 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); | 49 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); |
46 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); | 50 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); |
51 | |||
52 | rsnd_mod_write(mod, DVC_ZCMCR, mute); | ||
47 | } | 53 | } |
48 | 54 | ||
49 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 55 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, |
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
96 | 102 | ||
97 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | 103 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); |
98 | 104 | ||
99 | /* enable Volume */ | 105 | /* enable Volume / Mute */ |
100 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); | 106 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101); |
101 | 107 | ||
102 | /* ch0/ch1 Volume */ | 108 | /* ch0/ch1 Volume */ |
103 | rsnd_dvc_volume_update(dvc_mod); | 109 | rsnd_dvc_volume_update(dvc_mod); |
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
140 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | 146 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, |
141 | struct snd_ctl_elem_info *uinfo) | 147 | struct snd_ctl_elem_info *uinfo) |
142 | { | 148 | { |
143 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 149 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
150 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
151 | u8 *val = (u8 *)kctrl->private_value; | ||
152 | |||
144 | uinfo->count = RSND_DVC_VOLUME_NUM; | 153 | uinfo->count = RSND_DVC_VOLUME_NUM; |
145 | uinfo->value.integer.min = 0; | 154 | uinfo->value.integer.min = 0; |
146 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | 155 | |
156 | if (val == dvc->volume) { | ||
157 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
158 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | ||
159 | } else { | ||
160 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
161 | uinfo->value.integer.max = 1; | ||
162 | } | ||
147 | 163 | ||
148 | return 0; | 164 | return 0; |
149 | } | 165 | } |
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | |||
151 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, | 167 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, |
152 | struct snd_ctl_elem_value *ucontrol) | 168 | struct snd_ctl_elem_value *ucontrol) |
153 | { | 169 | { |
154 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 170 | u8 *val = (u8 *)kctrl->private_value; |
155 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
156 | int i; | 171 | int i; |
157 | 172 | ||
158 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 173 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) |
159 | ucontrol->value.integer.value[i] = dvc->volume[i]; | 174 | ucontrol->value.integer.value[i] = val[i]; |
160 | 175 | ||
161 | return 0; | 176 | return 0; |
162 | } | 177 | } |
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, | |||
165 | struct snd_ctl_elem_value *ucontrol) | 180 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 181 | { |
167 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 182 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
168 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 183 | u8 *val = (u8 *)kctrl->private_value; |
169 | int i, change = 0; | 184 | int i, change = 0; |
170 | 185 | ||
171 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | 186 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
172 | if (ucontrol->value.integer.value[i] < 0 || | 187 | change |= (ucontrol->value.integer.value[i] != val[i]); |
173 | ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) | 188 | val[i] = ucontrol->value.integer.value[i]; |
174 | return -EINVAL; | ||
175 | |||
176 | change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); | ||
177 | } | 189 | } |
178 | 190 | ||
179 | if (change) { | 191 | if (change) |
180 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
181 | dvc->volume[i] = ucontrol->value.integer.value[i]; | ||
182 | |||
183 | rsnd_dvc_volume_update(mod); | 192 | rsnd_dvc_volume_update(mod); |
184 | } | ||
185 | 193 | ||
186 | return change; | 194 | return change; |
187 | } | 195 | } |
188 | 196 | ||
189 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 197 | static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
190 | struct rsnd_dai *rdai, | 198 | struct rsnd_dai *rdai, |
191 | struct snd_soc_pcm_runtime *rtd) | 199 | struct snd_soc_pcm_runtime *rtd, |
200 | const unsigned char *name, | ||
201 | u8 *private) | ||
192 | { | 202 | { |
193 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
194 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
195 | struct device *dev = rsnd_priv_to_dev(priv); | ||
196 | struct snd_card *card = rtd->card->snd_card; | 203 | struct snd_card *card = rtd->card->snd_card; |
197 | struct snd_kcontrol *kctrl; | 204 | struct snd_kcontrol *kctrl; |
198 | static struct snd_kcontrol_new knew = { | 205 | struct snd_kcontrol_new knew = { |
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 206 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
200 | .name = "Playback Volume", | 207 | .name = name, |
201 | .info = rsnd_dvc_volume_info, | 208 | .info = rsnd_dvc_volume_info, |
202 | .get = rsnd_dvc_volume_get, | 209 | .get = rsnd_dvc_volume_get, |
203 | .put = rsnd_dvc_volume_put, | 210 | .put = rsnd_dvc_volume_put, |
211 | .private_value = (unsigned long)private, | ||
204 | }; | 212 | }; |
205 | int ret; | 213 | int ret; |
206 | 214 | ||
207 | if (!rsnd_dai_is_play(rdai, io)) { | ||
208 | dev_err(dev, "DVC%d is connected to Capture DAI\n", | ||
209 | rsnd_mod_id(mod)); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | kctrl = snd_ctl_new1(&knew, mod); | 215 | kctrl = snd_ctl_new1(&knew, mod); |
214 | if (!kctrl) | 216 | if (!kctrl) |
215 | return -ENOMEM; | 217 | return -ENOMEM; |
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
221 | return 0; | 223 | return 0; |
222 | } | 224 | } |
223 | 225 | ||
226 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | ||
227 | struct rsnd_dai *rdai, | ||
228 | struct snd_soc_pcm_runtime *rtd) | ||
229 | { | ||
230 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
231 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
232 | int ret; | ||
233 | |||
234 | /* Volume */ | ||
235 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
236 | rsnd_dai_is_play(rdai, io) ? | ||
237 | "DVC Out Playback Volume" : "DVC In Capture Volume", | ||
238 | dvc->volume); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | /* Mute */ | ||
243 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
244 | rsnd_dai_is_play(rdai, io) ? | ||
245 | "DVC Out Mute Switch" : "DVC In Mute Switch", | ||
246 | dvc->mute); | ||
247 | if (ret < 0) | ||
248 | return ret; | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
224 | static struct rsnd_mod_ops rsnd_dvc_ops = { | 253 | static struct rsnd_mod_ops rsnd_dvc_ops = { |
225 | .name = DVC_NAME, | 254 | .name = DVC_NAME, |
226 | .probe = rsnd_dvc_probe_gen2, | 255 | .probe = rsnd_dvc_probe_gen2, |
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) | |||
239 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; | 268 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; |
240 | } | 269 | } |
241 | 270 | ||
271 | static void rsnd_of_parse_dvc(struct platform_device *pdev, | ||
272 | const struct rsnd_of_data *of_data, | ||
273 | struct rsnd_priv *priv) | ||
274 | { | ||
275 | struct device_node *node; | ||
276 | struct rsnd_dvc_platform_info *dvc_info; | ||
277 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
278 | struct device *dev = &pdev->dev; | ||
279 | int nr; | ||
280 | |||
281 | if (!of_data) | ||
282 | return; | ||
283 | |||
284 | node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
285 | if (!node) | ||
286 | return; | ||
287 | |||
288 | nr = of_get_child_count(node); | ||
289 | if (!nr) | ||
290 | goto rsnd_of_parse_dvc_end; | ||
291 | |||
292 | dvc_info = devm_kzalloc(dev, | ||
293 | sizeof(struct rsnd_dvc_platform_info) * nr, | ||
294 | GFP_KERNEL); | ||
295 | if (!dvc_info) { | ||
296 | dev_err(dev, "dvc info allocation error\n"); | ||
297 | goto rsnd_of_parse_dvc_end; | ||
298 | } | ||
299 | |||
300 | info->dvc_info = dvc_info; | ||
301 | info->dvc_info_nr = nr; | ||
302 | |||
303 | rsnd_of_parse_dvc_end: | ||
304 | of_node_put(node); | ||
305 | } | ||
306 | |||
242 | int rsnd_dvc_probe(struct platform_device *pdev, | 307 | int rsnd_dvc_probe(struct platform_device *pdev, |
243 | const struct rsnd_of_data *of_data, | 308 | const struct rsnd_of_data *of_data, |
244 | struct rsnd_priv *priv) | 309 | struct rsnd_priv *priv) |
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
250 | char name[RSND_DVC_NAME_SIZE]; | 315 | char name[RSND_DVC_NAME_SIZE]; |
251 | int i, nr; | 316 | int i, nr; |
252 | 317 | ||
318 | rsnd_of_parse_dvc(pdev, of_data, priv); | ||
319 | |||
253 | nr = info->dvc_info_nr; | 320 | nr = info->dvc_info_nr; |
254 | if (!nr) | 321 | if (!nr) |
255 | return 0; | 322 | return 0; |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 1dd2b7d38c2c..3fdf3be7b99a 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -15,63 +15,35 @@ struct rsnd_gen { | |||
15 | 15 | ||
16 | struct rsnd_gen_ops *ops; | 16 | struct rsnd_gen_ops *ops; |
17 | 17 | ||
18 | struct regmap *regmap; | 18 | struct regmap *regmap[RSND_BASE_MAX]; |
19 | struct regmap_field *regs[RSND_REG_MAX]; | 19 | struct regmap_field *regs[RSND_REG_MAX]; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | 22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) |
23 | 23 | ||
24 | #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ | 24 | struct rsnd_regmap_field_conf { |
25 | [id] = { \ | 25 | int idx; |
26 | .reg = (unsigned int)gen->base[reg_id] + offset, \ | 26 | unsigned int reg_offset; |
27 | .lsb = 0, \ | 27 | unsigned int id_offset; |
28 | .msb = 31, \ | 28 | }; |
29 | .id_size = _id_size, \ | ||
30 | .id_offset = _id_offset, \ | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | * basic function | ||
35 | */ | ||
36 | static int rsnd_regmap_write32(void *context, const void *_data, size_t count) | ||
37 | { | ||
38 | struct rsnd_priv *priv = context; | ||
39 | struct device *dev = rsnd_priv_to_dev(priv); | ||
40 | u32 *data = (u32 *)_data; | ||
41 | u32 val = data[1]; | ||
42 | void __iomem *reg = (void *)data[0]; | ||
43 | |||
44 | iowrite32(val, reg); | ||
45 | |||
46 | dev_dbg(dev, "w %p : %08x\n", reg, val); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int rsnd_regmap_read32(void *context, | ||
52 | const void *_data, size_t reg_size, | ||
53 | void *_val, size_t val_size) | ||
54 | { | ||
55 | struct rsnd_priv *priv = context; | ||
56 | struct device *dev = rsnd_priv_to_dev(priv); | ||
57 | u32 *data = (u32 *)_data; | ||
58 | u32 *val = (u32 *)_val; | ||
59 | void __iomem *reg = (void *)data[0]; | ||
60 | |||
61 | *val = ioread32(reg); | ||
62 | |||
63 | dev_dbg(dev, "r %p : %08x\n", reg, *val); | ||
64 | 29 | ||
65 | return 0; | 30 | #define RSND_REG_SET(id, offset, _id_offset) \ |
31 | { \ | ||
32 | .idx = id, \ | ||
33 | .reg_offset = offset, \ | ||
34 | .id_offset = _id_offset, \ | ||
66 | } | 35 | } |
36 | /* single address mapping */ | ||
37 | #define RSND_GEN_S_REG(id, offset) \ | ||
38 | RSND_REG_SET(RSND_REG_##id, offset, 0) | ||
67 | 39 | ||
68 | static struct regmap_bus rsnd_regmap_bus = { | 40 | /* multi address mapping */ |
69 | .write = rsnd_regmap_write32, | 41 | #define RSND_GEN_M_REG(id, offset, _id_offset) \ |
70 | .read = rsnd_regmap_read32, | 42 | RSND_REG_SET(RSND_REG_##id, offset, _id_offset) |
71 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
72 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
73 | }; | ||
74 | 43 | ||
44 | /* | ||
45 | * basic function | ||
46 | */ | ||
75 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | 47 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, |
76 | struct rsnd_gen *gen, enum rsnd_reg reg) | 48 | struct rsnd_gen *gen, enum rsnd_reg reg) |
77 | { | 49 | { |
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | |||
88 | u32 rsnd_read(struct rsnd_priv *priv, | 60 | u32 rsnd_read(struct rsnd_priv *priv, |
89 | struct rsnd_mod *mod, enum rsnd_reg reg) | 61 | struct rsnd_mod *mod, enum rsnd_reg reg) |
90 | { | 62 | { |
63 | struct device *dev = rsnd_priv_to_dev(priv); | ||
91 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 64 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
92 | u32 val; | 65 | u32 val; |
93 | 66 | ||
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv, | |||
96 | 69 | ||
97 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | 70 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
98 | 71 | ||
72 | dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val); | ||
73 | |||
99 | return val; | 74 | return val; |
100 | } | 75 | } |
101 | 76 | ||
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv, | |||
103 | struct rsnd_mod *mod, | 78 | struct rsnd_mod *mod, |
104 | enum rsnd_reg reg, u32 data) | 79 | enum rsnd_reg reg, u32 data) |
105 | { | 80 | { |
81 | struct device *dev = rsnd_priv_to_dev(priv); | ||
106 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 82 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
107 | 83 | ||
108 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 84 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
109 | return; | 85 | return; |
110 | 86 | ||
111 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 87 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
88 | |||
89 | dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data); | ||
112 | } | 90 | } |
113 | 91 | ||
114 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | 92 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, |
115 | enum rsnd_reg reg, u32 mask, u32 data) | 93 | enum rsnd_reg reg, u32 mask, u32 data) |
116 | { | 94 | { |
95 | struct device *dev = rsnd_priv_to_dev(priv); | ||
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 96 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
118 | 97 | ||
119 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 98 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
121 | 100 | ||
122 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | 101 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
123 | mask, data); | 102 | mask, data); |
103 | |||
104 | dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n", | ||
105 | rsnd_mod_name(mod), reg, data, mask); | ||
124 | } | 106 | } |
125 | 107 | ||
126 | static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | 108 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ |
127 | struct rsnd_gen *gen, | 109 | _rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf)) |
128 | struct reg_field *regf) | 110 | static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, |
111 | int id_size, | ||
112 | int reg_id, | ||
113 | struct rsnd_regmap_field_conf *conf, | ||
114 | int conf_size) | ||
129 | { | 115 | { |
130 | int i; | 116 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
131 | struct device *dev = rsnd_priv_to_dev(priv); | 118 | struct device *dev = rsnd_priv_to_dev(priv); |
119 | struct resource *res; | ||
132 | struct regmap_config regc; | 120 | struct regmap_config regc; |
121 | struct regmap_field *regs; | ||
122 | struct regmap *regmap; | ||
123 | struct reg_field regf; | ||
124 | void __iomem *base; | ||
125 | int i; | ||
133 | 126 | ||
134 | memset(®c, 0, sizeof(regc)); | 127 | memset(®c, 0, sizeof(regc)); |
135 | regc.reg_bits = 32; | 128 | regc.reg_bits = 32; |
136 | regc.val_bits = 32; | 129 | regc.val_bits = 32; |
130 | regc.reg_stride = 4; | ||
137 | 131 | ||
138 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); | 132 | res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); |
139 | if (IS_ERR(gen->regmap)) { | 133 | if (!res) |
140 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | 134 | return -ENODEV; |
141 | return PTR_ERR(gen->regmap); | ||
142 | } | ||
143 | 135 | ||
144 | for (i = 0; i < RSND_REG_MAX; i++) { | 136 | base = devm_ioremap_resource(dev, res); |
145 | gen->regs[i] = NULL; | 137 | if (IS_ERR(base)) |
146 | if (!regf[i].reg) | 138 | return PTR_ERR(base); |
147 | continue; | ||
148 | 139 | ||
149 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | 140 | regmap = devm_regmap_init_mmio(dev, base, ®c); |
150 | if (IS_ERR(gen->regs[i])) | 141 | if (IS_ERR(regmap)) |
151 | return PTR_ERR(gen->regs[i]); | 142 | return PTR_ERR(regmap); |
152 | 143 | ||
144 | gen->base[reg_id] = base; | ||
145 | gen->regmap[reg_id] = regmap; | ||
146 | |||
147 | for (i = 0; i < conf_size; i++) { | ||
148 | |||
149 | regf.reg = conf[i].reg_offset; | ||
150 | regf.id_offset = conf[i].id_offset; | ||
151 | regf.lsb = 0; | ||
152 | regf.msb = 31; | ||
153 | regf.id_size = id_size; | ||
154 | |||
155 | regs = devm_regmap_field_alloc(dev, regmap, regf); | ||
156 | if (IS_ERR(regs)) | ||
157 | return PTR_ERR(regs); | ||
158 | |||
159 | gen->regs[conf[i].idx] = regs; | ||
153 | } | 160 | } |
154 | 161 | ||
155 | return 0; | 162 | return 0; |
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
165 | * | 172 | * |
166 | * ex) R-Car H2 case | 173 | * ex) R-Car H2 case |
167 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out | 174 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out |
168 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 | 175 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c |
176 | * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 | ||
169 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 | 177 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 |
170 | * CMD : 0xec500000 / 0xec008000 0xec308000 | 178 | * CMD : 0xec500000 / / 0xec008000 0xec308000 |
171 | */ | 179 | */ |
172 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) | 180 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) |
173 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) | 181 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) |
174 | 182 | ||
175 | #define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 183 | #define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
176 | #define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 184 | #define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
185 | |||
186 | #define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
187 | #define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
177 | 188 | ||
178 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) | 189 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) |
179 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) | 190 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) |
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
184 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) | 195 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) |
185 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) | 196 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) |
186 | 197 | ||
187 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 198 | static dma_addr_t |
188 | struct rsnd_dma *dma, | 199 | rsnd_gen2_dma_addr(struct rsnd_priv *priv, |
189 | struct dma_slave_config *cfg, | 200 | struct rsnd_mod *mod, |
190 | int is_play, int slave_id) | 201 | int is_play, int is_from) |
191 | { | 202 | { |
192 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); | 203 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
193 | struct device *dev = rsnd_priv_to_dev(priv); | 204 | struct device *dev = rsnd_priv_to_dev(priv); |
194 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | ||
195 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 205 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
196 | dma_addr_t ssi_reg = platform_get_resource(pdev, | 206 | dma_addr_t ssi_reg = platform_get_resource(pdev, |
197 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; | 207 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; |
@@ -202,170 +212,152 @@ void rsnd_gen_dma_addr(struct rsnd_priv *priv, | |||
202 | int use_dvc = !!rsnd_io_to_mod_dvc(io); | 212 | int use_dvc = !!rsnd_io_to_mod_dvc(io); |
203 | int id = rsnd_mod_id(mod); | 213 | int id = rsnd_mod_id(mod); |
204 | struct dma_addr { | 214 | struct dma_addr { |
205 | dma_addr_t src_addr; | 215 | dma_addr_t out_addr; |
206 | dma_addr_t dst_addr; | 216 | dma_addr_t in_addr; |
207 | } dma_addrs[2][2][3] = { | 217 | } dma_addrs[3][2][3] = { |
208 | { /* SRC */ | 218 | /* SRC */ |
209 | /* Capture */ | 219 | {{{ 0, 0 }, |
210 | {{ 0, 0 }, | 220 | /* Capture */ |
211 | { RDMA_SRC_O_N(src, id), 0 }, | 221 | { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, |
212 | { RDMA_CMD_O_N(src, id), 0 }}, | 222 | { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, |
213 | /* Playback */ | 223 | /* Playback */ |
214 | {{ 0, 0, }, | 224 | {{ 0, 0, }, |
215 | { 0, RDMA_SRC_I_N(src, id) }, | 225 | { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, |
216 | { 0, RDMA_SRC_I_N(src, id) }} | 226 | { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } |
217 | }, { /* SSI */ | 227 | }, |
218 | /* Capture */ | 228 | /* SSI */ |
219 | {{ RDMA_SSI_O_N(ssi, id), 0 }, | 229 | /* Capture */ |
220 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, | 230 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, |
221 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, | 231 | { RDMA_SSIU_O_P(ssi, id), 0 }, |
222 | /* Playback */ | 232 | { RDMA_SSIU_O_P(ssi, id), 0 } }, |
223 | {{ 0, RDMA_SSI_I_N(ssi, id) }, | 233 | /* Playback */ |
224 | { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, | 234 | {{ 0, RDMA_SSI_I_N(ssi, id) }, |
225 | { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} | 235 | { 0, RDMA_SSIU_I_P(ssi, id) }, |
226 | } | 236 | { 0, RDMA_SSIU_I_P(ssi, id) } } |
237 | }, | ||
238 | /* SSIU */ | ||
239 | /* Capture */ | ||
240 | {{{ RDMA_SSIU_O_N(ssi, id), 0 }, | ||
241 | { RDMA_SSIU_O_P(ssi, id), 0 }, | ||
242 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | ||
243 | /* Playback */ | ||
244 | {{ 0, RDMA_SSIU_I_N(ssi, id) }, | ||
245 | { 0, RDMA_SSIU_I_P(ssi, id) }, | ||
246 | { 0, RDMA_SSIU_I_P(ssi, id) } } }, | ||
227 | }; | 247 | }; |
228 | 248 | ||
229 | cfg->slave_id = slave_id; | 249 | /* it shouldn't happen */ |
230 | cfg->src_addr = 0; | 250 | if (use_dvc & !use_src) |
231 | cfg->dst_addr = 0; | 251 | dev_err(dev, "DVC is selected without SRC\n"); |
232 | cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | 252 | |
253 | /* use SSIU or SSI ? */ | ||
254 | if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) | ||
255 | is_ssi++; | ||
256 | |||
257 | return (is_from) ? | ||
258 | dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : | ||
259 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | ||
260 | } | ||
233 | 261 | ||
262 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, | ||
263 | struct rsnd_mod *mod, | ||
264 | int is_play, int is_from) | ||
265 | { | ||
234 | /* | 266 | /* |
235 | * gen1 uses default DMA addr | 267 | * gen1 uses default DMA addr |
236 | */ | 268 | */ |
237 | if (rsnd_is_gen1(priv)) | 269 | if (rsnd_is_gen1(priv)) |
238 | return; | 270 | return 0; |
239 | |||
240 | /* it shouldn't happen */ | ||
241 | if (use_dvc & !use_src) { | ||
242 | dev_err(dev, "DVC is selected without SRC\n"); | ||
243 | return; | ||
244 | } | ||
245 | 271 | ||
246 | cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; | 272 | if (!mod) |
247 | cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; | 273 | return 0; |
248 | 274 | ||
249 | dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n", | 275 | return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); |
250 | id, cfg->src_addr, cfg->dst_addr); | ||
251 | } | 276 | } |
252 | 277 | ||
253 | /* | 278 | /* |
254 | * Gen2 | 279 | * Gen2 |
255 | */ | 280 | */ |
256 | |||
257 | /* single address mapping */ | ||
258 | #define RSND_GEN2_S_REG(gen, reg, id, offset) \ | ||
259 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) | ||
260 | |||
261 | /* multi address mapping */ | ||
262 | #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ | ||
263 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) | ||
264 | |||
265 | static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
266 | { | ||
267 | struct reg_field regf[RSND_REG_MAX] = { | ||
268 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | ||
269 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | ||
270 | /* FIXME: it needs SSI_MODE2/3 in the future */ | ||
271 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), | ||
272 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), | ||
273 | RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), | ||
274 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | ||
275 | |||
276 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | ||
277 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | ||
278 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | ||
279 | RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), | ||
280 | RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), | ||
281 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | ||
282 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | ||
283 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | ||
284 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), | ||
285 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), | ||
286 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | ||
287 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | ||
288 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | ||
289 | RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), | ||
290 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), | ||
291 | RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), | ||
292 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), | ||
293 | RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), | ||
294 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), | ||
295 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), | ||
296 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), | ||
297 | |||
298 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | ||
299 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | ||
300 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | ||
301 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
302 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
303 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | ||
304 | RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), | ||
305 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), | ||
306 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), | ||
307 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), | ||
308 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), | ||
309 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), | ||
310 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), | ||
311 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), | ||
312 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | ||
313 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | ||
314 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | ||
315 | RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), | ||
316 | |||
317 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
318 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
319 | RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
320 | RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
321 | RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
322 | }; | ||
323 | |||
324 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
325 | } | ||
326 | |||
327 | static int rsnd_gen2_probe(struct platform_device *pdev, | 281 | static int rsnd_gen2_probe(struct platform_device *pdev, |
328 | struct rsnd_priv *priv) | 282 | struct rsnd_priv *priv) |
329 | { | 283 | { |
330 | struct device *dev = rsnd_priv_to_dev(priv); | 284 | struct device *dev = rsnd_priv_to_dev(priv); |
331 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 285 | struct rsnd_regmap_field_conf conf_ssiu[] = { |
332 | struct resource *scu_res; | 286 | RSND_GEN_S_REG(SSI_MODE0, 0x800), |
333 | struct resource *adg_res; | 287 | RSND_GEN_S_REG(SSI_MODE1, 0x804), |
334 | struct resource *ssiu_res; | 288 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
335 | struct resource *ssi_res; | 289 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), |
336 | int ret; | 290 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), |
337 | 291 | RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), | |
338 | /* | 292 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), |
339 | * map address | 293 | RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), |
340 | */ | 294 | }; |
341 | scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); | 295 | struct rsnd_regmap_field_conf conf_scu[] = { |
342 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); | 296 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
343 | ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); | 297 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
344 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); | 298 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
345 | 299 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), | |
346 | gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); | 300 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), |
347 | gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); | 301 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
348 | gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); | 302 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
349 | gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); | 303 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), |
350 | if (IS_ERR(gen->base[RSND_GEN2_SCU]) || | 304 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
351 | IS_ERR(gen->base[RSND_GEN2_ADG]) || | 305 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
352 | IS_ERR(gen->base[RSND_GEN2_SSIU]) || | 306 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
353 | IS_ERR(gen->base[RSND_GEN2_SSI])) | 307 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), |
354 | return -ENODEV; | 308 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), |
355 | 309 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), | |
356 | ret = rsnd_gen2_regmap_init(priv, gen); | 310 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), |
357 | if (ret < 0) | 311 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), |
358 | return ret; | 312 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), |
359 | 313 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), | |
360 | dev_dbg(dev, "Gen2 device probed\n"); | 314 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), |
361 | dev_dbg(dev, "SCU : %pap => %p\n", &scu_res->start, | 315 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), |
362 | gen->base[RSND_GEN2_SCU]); | 316 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), |
363 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | 317 | }; |
364 | gen->base[RSND_GEN2_ADG]); | 318 | struct rsnd_regmap_field_conf conf_adg[] = { |
365 | dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start, | 319 | RSND_GEN_S_REG(BRRA, 0x00), |
366 | gen->base[RSND_GEN2_SSIU]); | 320 | RSND_GEN_S_REG(BRRB, 0x04), |
367 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | 321 | RSND_GEN_S_REG(SSICKR, 0x08), |
368 | gen->base[RSND_GEN2_SSI]); | 322 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), |
323 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
324 | RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), | ||
325 | RSND_GEN_S_REG(DIV_EN, 0x30), | ||
326 | RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), | ||
327 | RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), | ||
328 | RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), | ||
329 | RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), | ||
330 | RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), | ||
331 | RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), | ||
332 | RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), | ||
333 | RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), | ||
334 | RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), | ||
335 | RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), | ||
336 | RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), | ||
337 | }; | ||
338 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
339 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
340 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
341 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
342 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
343 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
344 | }; | ||
345 | int ret_ssiu; | ||
346 | int ret_scu; | ||
347 | int ret_adg; | ||
348 | int ret_ssi; | ||
349 | |||
350 | ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu); | ||
351 | ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, conf_scu); | ||
352 | ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, conf_adg); | ||
353 | ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, conf_ssi); | ||
354 | if (ret_ssiu < 0 || | ||
355 | ret_scu < 0 || | ||
356 | ret_adg < 0 || | ||
357 | ret_ssi < 0) | ||
358 | return ret_ssiu | ret_scu | ret_adg | ret_ssi; | ||
359 | |||
360 | dev_dbg(dev, "Gen2 is probed\n"); | ||
369 | 361 | ||
370 | return 0; | 362 | return 0; |
371 | } | 363 | } |
@@ -374,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
374 | * Gen1 | 366 | * Gen1 |
375 | */ | 367 | */ |
376 | 368 | ||
377 | /* single address mapping */ | ||
378 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ | ||
379 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) | ||
380 | |||
381 | /* multi address mapping */ | ||
382 | #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ | ||
383 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) | ||
384 | |||
385 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
386 | { | ||
387 | struct reg_field regf[RSND_REG_MAX] = { | ||
388 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), | ||
389 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), | ||
390 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), | ||
391 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), | ||
392 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), | ||
393 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | ||
394 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), | ||
395 | RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), | ||
396 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), | ||
397 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), | ||
398 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), | ||
399 | RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), | ||
400 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), | ||
401 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), | ||
402 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), | ||
403 | RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), | ||
404 | |||
405 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), | ||
406 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), | ||
407 | RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), | ||
408 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
409 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
410 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), | ||
411 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), | ||
412 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), | ||
413 | |||
414 | RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
415 | RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
416 | RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
417 | RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
418 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
419 | }; | ||
420 | |||
421 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
422 | } | ||
423 | |||
424 | static int rsnd_gen1_probe(struct platform_device *pdev, | 369 | static int rsnd_gen1_probe(struct platform_device *pdev, |
425 | struct rsnd_priv *priv) | 370 | struct rsnd_priv *priv) |
426 | { | 371 | { |
427 | struct device *dev = rsnd_priv_to_dev(priv); | 372 | struct device *dev = rsnd_priv_to_dev(priv); |
428 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 373 | struct rsnd_regmap_field_conf conf_sru[] = { |
429 | struct resource *sru_res; | 374 | RSND_GEN_S_REG(SRC_ROUTE_SEL, 0x00), |
430 | struct resource *adg_res; | 375 | RSND_GEN_S_REG(SRC_TMG_SEL0, 0x08), |
431 | struct resource *ssi_res; | 376 | RSND_GEN_S_REG(SRC_TMG_SEL1, 0x0c), |
432 | int ret; | 377 | RSND_GEN_S_REG(SRC_TMG_SEL2, 0x10), |
433 | 378 | RSND_GEN_S_REG(SRC_ROUTE_CTRL, 0xc0), | |
434 | /* | 379 | RSND_GEN_S_REG(SSI_MODE0, 0xD0), |
435 | * map address | 380 | RSND_GEN_S_REG(SSI_MODE1, 0xD4), |
436 | */ | 381 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x20, 0x4), |
437 | sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); | 382 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0x50, 0x8), |
438 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); | 383 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
439 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); | 384 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
440 | 385 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | |
441 | gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); | 386 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
442 | gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); | 387 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
443 | gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); | 388 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
444 | if (IS_ERR(gen->base[RSND_GEN1_SRU]) || | 389 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), |
445 | IS_ERR(gen->base[RSND_GEN1_ADG]) || | 390 | }; |
446 | IS_ERR(gen->base[RSND_GEN1_SSI])) | 391 | struct rsnd_regmap_field_conf conf_adg[] = { |
447 | return -ENODEV; | 392 | RSND_GEN_S_REG(BRRA, 0x00), |
393 | RSND_GEN_S_REG(BRRB, 0x04), | ||
394 | RSND_GEN_S_REG(SSICKR, 0x08), | ||
395 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), | ||
396 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
397 | RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18), | ||
398 | RSND_GEN_S_REG(AUDIO_CLK_SEL4, 0x1c), | ||
399 | RSND_GEN_S_REG(AUDIO_CLK_SEL5, 0x20), | ||
400 | }; | ||
401 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
402 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
403 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
404 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
405 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
406 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
407 | }; | ||
408 | int ret_sru; | ||
409 | int ret_adg; | ||
410 | int ret_ssi; | ||
448 | 411 | ||
449 | ret = rsnd_gen1_regmap_init(priv, gen); | 412 | ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, conf_sru); |
450 | if (ret < 0) | 413 | ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, conf_adg); |
451 | return ret; | 414 | ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, conf_ssi); |
415 | if (ret_sru < 0 || | ||
416 | ret_adg < 0 || | ||
417 | ret_ssi < 0) | ||
418 | return ret_sru | ret_adg | ret_ssi; | ||
452 | 419 | ||
453 | dev_dbg(dev, "Gen1 device probed\n"); | 420 | dev_dbg(dev, "Gen1 is probed\n"); |
454 | dev_dbg(dev, "SRU : %pap => %p\n", &sru_res->start, | ||
455 | gen->base[RSND_GEN1_SRU]); | ||
456 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | ||
457 | gen->base[RSND_GEN1_ADG]); | ||
458 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | ||
459 | gen->base[RSND_GEN1_SSI]); | ||
460 | 421 | ||
461 | return 0; | 422 | return 0; |
462 | |||
463 | } | 423 | } |
464 | 424 | ||
465 | /* | 425 | /* |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 39d98af5ee05..d119adf97c9c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -90,6 +90,7 @@ enum rsnd_reg { | |||
90 | RSND_REG_SHARE19, | 90 | RSND_REG_SHARE19, |
91 | RSND_REG_SHARE20, | 91 | RSND_REG_SHARE20, |
92 | RSND_REG_SHARE21, | 92 | RSND_REG_SHARE21, |
93 | RSND_REG_SHARE22, | ||
93 | 94 | ||
94 | RSND_REG_MAX, | 95 | RSND_REG_MAX, |
95 | }; | 96 | }; |
@@ -127,6 +128,7 @@ enum rsnd_reg { | |||
127 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | 128 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 |
128 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | 129 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 |
129 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | 130 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 |
131 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 | ||
130 | 132 | ||
131 | struct rsnd_of_data; | 133 | struct rsnd_of_data; |
132 | struct rsnd_priv; | 134 | struct rsnd_priv; |
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); | |||
156 | */ | 158 | */ |
157 | struct rsnd_dma { | 159 | struct rsnd_dma { |
158 | struct sh_dmae_slave slave; | 160 | struct sh_dmae_slave slave; |
159 | struct work_struct work; | ||
160 | struct dma_chan *chan; | 161 | struct dma_chan *chan; |
161 | enum dma_data_direction dir; | 162 | enum dma_transfer_direction dir; |
162 | 163 | dma_addr_t addr; | |
163 | int submit_loop; | ||
164 | int offset; /* it cares A/B plane */ | ||
165 | }; | 164 | }; |
166 | 165 | ||
167 | void rsnd_dma_start(struct rsnd_dma *dma); | 166 | void rsnd_dma_start(struct rsnd_dma *dma); |
@@ -185,6 +184,7 @@ enum rsnd_mod_type { | |||
185 | 184 | ||
186 | struct rsnd_mod_ops { | 185 | struct rsnd_mod_ops { |
187 | char *name; | 186 | char *name; |
187 | char* (*dma_name)(struct rsnd_mod *mod); | ||
188 | int (*probe)(struct rsnd_mod *mod, | 188 | int (*probe)(struct rsnd_mod *mod, |
189 | struct rsnd_dai *rdai); | 189 | struct rsnd_dai *rdai); |
190 | int (*remove)(struct rsnd_mod *mod, | 190 | int (*remove)(struct rsnd_mod *mod, |
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
224 | enum rsnd_mod_type type, | 224 | enum rsnd_mod_type type, |
225 | int id); | 225 | int id); |
226 | char *rsnd_mod_name(struct rsnd_mod *mod); | 226 | char *rsnd_mod_name(struct rsnd_mod *mod); |
227 | char *rsnd_mod_dma_name(struct rsnd_mod *mod); | ||
227 | 228 | ||
228 | /* | 229 | /* |
229 | * R-Car sound DAI | 230 | * R-Car sound DAI |
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
281 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | 282 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, |
282 | struct rsnd_mod *mod, | 283 | struct rsnd_mod *mod, |
283 | enum rsnd_reg reg); | 284 | enum rsnd_reg reg); |
284 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 285 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, |
285 | struct rsnd_dma *dma, | 286 | struct rsnd_mod *mod, |
286 | struct dma_slave_config *cfg, | 287 | int is_play, int is_from); |
287 | int is_play, int slave_id); | ||
288 | 288 | ||
289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) | 289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) |
290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) | 290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) |
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); | |||
391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | 391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, |
392 | struct rsnd_dai_stream *io, | 392 | struct rsnd_dai_stream *io, |
393 | struct snd_pcm_runtime *runtime); | 393 | struct snd_pcm_runtime *runtime); |
394 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 394 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
395 | struct rsnd_dai *rdai); | 395 | struct rsnd_dai *rdai, |
396 | int use_busif); | ||
397 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
398 | struct rsnd_dai *rdai, | ||
399 | int use_busif); | ||
396 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | 400 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, |
397 | struct rsnd_dai *rdai); | 401 | struct rsnd_dai *rdai); |
398 | 402 | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 200eda019bc7..9183e0145503 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -106,18 +106,19 @@ struct rsnd_src { | |||
106 | /* | 106 | /* |
107 | * Gen1/Gen2 common functions | 107 | * Gen1/Gen2 common functions |
108 | */ | 108 | */ |
109 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 109 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
110 | struct rsnd_dai *rdai) | 110 | struct rsnd_dai *rdai, |
111 | int use_busif) | ||
111 | { | 112 | { |
112 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); | 113 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); |
113 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 114 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
114 | int ssi_id = rsnd_mod_id(ssi_mod); | 115 | int ssi_id = rsnd_mod_id(ssi_mod); |
115 | 116 | ||
116 | /* | 117 | /* |
117 | * SSI_MODE0 | 118 | * SSI_MODE0 |
118 | */ | 119 | */ |
119 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), | 120 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), |
120 | src_mod ? 0 : (1 << ssi_id)); | 121 | !use_busif << ssi_id); |
121 | 122 | ||
122 | /* | 123 | /* |
123 | * SSI_MODE1 | 124 | * SSI_MODE1 |
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | |||
143 | 0x2 << shift : 0x1 << shift); | 144 | 0x2 << shift : 0x1 << shift); |
144 | } | 145 | } |
145 | 146 | ||
147 | /* | ||
148 | * DMA settings for SSIU | ||
149 | */ | ||
150 | if (use_busif) { | ||
151 | u32 val = 0x76543210; | ||
152 | u32 mask = ~0; | ||
153 | |||
154 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, | ||
155 | rsnd_get_adinr(ssi_mod)); | ||
156 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); | ||
157 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); | ||
158 | |||
159 | mask <<= runtime->channels * 4; | ||
160 | val = val & mask; | ||
161 | |||
162 | switch (runtime->sample_bits) { | ||
163 | case 16: | ||
164 | val |= 0x67452301 & ~mask; | ||
165 | break; | ||
166 | case 32: | ||
167 | val |= 0x76543210 & ~mask; | ||
168 | break; | ||
169 | } | ||
170 | rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); | ||
171 | |||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
178 | struct rsnd_dai *rdai, | ||
179 | int use_busif) | ||
180 | { | ||
181 | /* | ||
182 | * DMA settings for SSIU | ||
183 | */ | ||
184 | if (use_busif) | ||
185 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0); | ||
186 | |||
146 | return 0; | 187 | return 0; |
147 | } | 188 | } |
148 | 189 | ||
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { | |||
461 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | 502 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, |
462 | struct rsnd_dai *rdai) | 503 | struct rsnd_dai *rdai) |
463 | { | 504 | { |
505 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
506 | struct device *dev = rsnd_priv_to_dev(priv); | ||
507 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
508 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
509 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
510 | uint ratio; | ||
464 | int ret; | 511 | int ret; |
465 | 512 | ||
513 | /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ | ||
514 | if (!rsnd_src_convert_rate(src)) | ||
515 | ratio = 0; | ||
516 | else if (rsnd_src_convert_rate(src) > runtime->rate) | ||
517 | ratio = 100 * rsnd_src_convert_rate(src) / runtime->rate; | ||
518 | else | ||
519 | ratio = 100 * runtime->rate / rsnd_src_convert_rate(src); | ||
520 | |||
521 | if (ratio > 600) { | ||
522 | dev_err(dev, "FSO/FSI ratio error\n"); | ||
523 | return -EINVAL; | ||
524 | } | ||
525 | |||
466 | ret = rsnd_src_set_convert_rate(mod, rdai); | 526 | ret = rsnd_src_set_convert_rate(mod, rdai); |
467 | if (ret < 0) | 527 | if (ret < 0) |
468 | return ret; | 528 | return ret; |
469 | 529 | ||
470 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod)); | ||
471 | rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); | ||
472 | |||
473 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | 530 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); |
474 | 531 | ||
475 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | 532 | switch (rsnd_mod_id(mod)) { |
533 | case 5: | ||
534 | case 6: | ||
535 | case 7: | ||
536 | case 8: | ||
537 | rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); | ||
538 | break; | ||
539 | default: | ||
540 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | ||
541 | break; | ||
542 | } | ||
543 | |||
476 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); | 544 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); |
477 | 545 | ||
478 | return 0; | 546 | return 0; |
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, | |||
554 | 622 | ||
555 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | 623 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); |
556 | 624 | ||
557 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | ||
558 | rsnd_mod_write(mod, SRC_CTRL, val); | 625 | rsnd_mod_write(mod, SRC_CTRL, val); |
559 | 626 | ||
560 | return rsnd_src_start(mod, rdai); | 627 | return rsnd_src_start(mod, rdai); |
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | |||
565 | { | 632 | { |
566 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 633 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
567 | 634 | ||
568 | rsnd_mod_write(mod, SSI_CTRL, 0); | ||
569 | rsnd_mod_write(mod, SRC_CTRL, 0); | 635 | rsnd_mod_write(mod, SRC_CTRL, 0); |
570 | 636 | ||
571 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | 637 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2df723df5d19..34e84009162b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -90,6 +90,20 @@ struct rsnd_ssi { | |||
90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
92 | 92 | ||
93 | static int rsnd_ssi_use_busif(struct rsnd_mod *mod) | ||
94 | { | ||
95 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
96 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
97 | int use_busif = 0; | ||
98 | |||
99 | if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) | ||
100 | use_busif = 1; | ||
101 | if (rsnd_io_to_mod_src(io)) | ||
102 | use_busif = 1; | ||
103 | |||
104 | return use_busif; | ||
105 | } | ||
106 | |||
93 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, | 107 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, |
94 | u32 bit) | 108 | u32 bit) |
95 | { | 109 | { |
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
289 | ssi->cr_own = cr; | 303 | ssi->cr_own = cr; |
290 | ssi->err = -1; /* ignore 1st error */ | 304 | ssi->err = -1; /* ignore 1st error */ |
291 | 305 | ||
292 | rsnd_src_ssi_mode_init(mod, rdai); | ||
293 | |||
294 | return 0; | 306 | return 0; |
295 | } | 307 | } |
296 | 308 | ||
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | |||
389 | /* enable PIO IRQ */ | 401 | /* enable PIO IRQ */ |
390 | ssi->cr_etc = UIEN | OIEN | DIEN; | 402 | ssi->cr_etc = UIEN | OIEN | DIEN; |
391 | 403 | ||
404 | rsnd_src_ssiu_start(mod, rdai, 0); | ||
405 | |||
392 | rsnd_src_enable_ssi_irq(mod, rdai); | 406 | rsnd_src_enable_ssi_irq(mod, rdai); |
393 | 407 | ||
394 | rsnd_ssi_hw_start(ssi, rdai, io); | 408 | rsnd_ssi_hw_start(ssi, rdai, io); |
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | |||
405 | 419 | ||
406 | rsnd_ssi_hw_stop(ssi, rdai); | 420 | rsnd_ssi_hw_stop(ssi, rdai); |
407 | 421 | ||
422 | rsnd_src_ssiu_stop(mod, rdai, 0); | ||
423 | |||
408 | return 0; | 424 | return 0; |
409 | } | 425 | } |
410 | 426 | ||
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | |||
457 | /* enable DMA transfer */ | 473 | /* enable DMA transfer */ |
458 | ssi->cr_etc = DMEN; | 474 | ssi->cr_etc = DMEN; |
459 | 475 | ||
476 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | ||
477 | |||
460 | rsnd_dma_start(dma); | 478 | rsnd_dma_start(dma); |
461 | 479 | ||
462 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | 480 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); |
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | |||
482 | 500 | ||
483 | rsnd_dma_stop(dma); | 501 | rsnd_dma_stop(dma); |
484 | 502 | ||
503 | rsnd_src_ssiu_stop(mod, rdai, 1); | ||
504 | |||
485 | return 0; | 505 | return 0; |
486 | } | 506 | } |
487 | 507 | ||
508 | static char *rsnd_ssi_dma_name(struct rsnd_mod *mod) | ||
509 | { | ||
510 | return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME; | ||
511 | } | ||
512 | |||
488 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | 513 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { |
489 | .name = SSI_NAME, | 514 | .name = SSI_NAME, |
515 | .dma_name = rsnd_ssi_dma_name, | ||
490 | .probe = rsnd_ssi_dma_probe, | 516 | .probe = rsnd_ssi_dma_probe, |
491 | .remove = rsnd_ssi_dma_remove, | 517 | .remove = rsnd_ssi_dma_remove, |
492 | .init = rsnd_ssi_init, | 518 | .init = rsnd_ssi_init, |
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev, | |||
595 | */ | 621 | */ |
596 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? | 622 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? |
597 | 0 : 1; | 623 | 0 : 1; |
624 | |||
625 | if (of_get_property(np, "no-busif", NULL)) | ||
626 | ssi_info->flags |= RSND_SSI_NO_BUSIF; | ||
598 | } | 627 | } |
599 | 628 | ||
600 | rsnd_of_parse_ssi_end: | 629 | rsnd_of_parse_ssi_end: |
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig index 89e89429b04a..840058dcad09 100644 --- a/sound/soc/sirf/Kconfig +++ b/sound/soc/sirf/Kconfig | |||
@@ -12,3 +12,9 @@ config SND_SOC_SIRF_AUDIO | |||
12 | config SND_SOC_SIRF_AUDIO_PORT | 12 | config SND_SOC_SIRF_AUDIO_PORT |
13 | select REGMAP_MMIO | 13 | select REGMAP_MMIO |
14 | tristate | 14 | tristate |
15 | |||
16 | config SND_SOC_SIRF_USP | ||
17 | tristate "SoC Audio (I2S protocol) for SiRF SoC USP interface" | ||
18 | depends on SND_SOC_SIRF | ||
19 | select REGMAP_MMIO | ||
20 | tristate | ||
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile index 913b93231d4e..dd917f20f12f 100644 --- a/sound/soc/sirf/Makefile +++ b/sound/soc/sirf/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | snd-soc-sirf-audio-objs := sirf-audio.o | 1 | snd-soc-sirf-audio-objs := sirf-audio.o |
2 | snd-soc-sirf-audio-port-objs := sirf-audio-port.o | 2 | snd-soc-sirf-audio-port-objs := sirf-audio-port.o |
3 | snd-soc-sirf-usp-objs := sirf-usp.o | ||
3 | 4 | ||
4 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o | 5 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o |
5 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o | 6 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o |
7 | obj-$(CONFIG_SND_SOC_SIRF_USP) += snd-soc-sirf-usp.o | ||
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c new file mode 100644 index 000000000000..3a730374e259 --- /dev/null +++ b/sound/soc/sirf/sirf-usp.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * SiRF USP in I2S/DSP mode | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/io.h> | ||
10 | #include <linux/of.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/pm_runtime.h> | ||
13 | #include <sound/soc.h> | ||
14 | #include <sound/pcm_params.h> | ||
15 | #include <sound/dmaengine_pcm.h> | ||
16 | |||
17 | #include "sirf-usp.h" | ||
18 | |||
19 | struct sirf_usp { | ||
20 | struct regmap *regmap; | ||
21 | struct clk *clk; | ||
22 | u32 mode1_reg; | ||
23 | u32 mode2_reg; | ||
24 | int daifmt_format; | ||
25 | struct snd_dmaengine_dai_dma_data playback_dma_data; | ||
26 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
27 | }; | ||
28 | |||
29 | static void sirf_usp_tx_enable(struct sirf_usp *usp) | ||
30 | { | ||
31 | regmap_update_bits(usp->regmap, USP_TX_FIFO_OP, | ||
32 | USP_TX_FIFO_RESET, USP_TX_FIFO_RESET); | ||
33 | regmap_write(usp->regmap, USP_TX_FIFO_OP, 0); | ||
34 | |||
35 | regmap_update_bits(usp->regmap, USP_TX_FIFO_OP, | ||
36 | USP_TX_FIFO_START, USP_TX_FIFO_START); | ||
37 | |||
38 | regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, | ||
39 | USP_TX_ENA, USP_TX_ENA); | ||
40 | } | ||
41 | |||
42 | static void sirf_usp_tx_disable(struct sirf_usp *usp) | ||
43 | { | ||
44 | regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, | ||
45 | USP_TX_ENA, ~USP_TX_ENA); | ||
46 | /* FIFO stop */ | ||
47 | regmap_write(usp->regmap, USP_TX_FIFO_OP, 0); | ||
48 | } | ||
49 | |||
50 | static void sirf_usp_rx_enable(struct sirf_usp *usp) | ||
51 | { | ||
52 | regmap_update_bits(usp->regmap, USP_RX_FIFO_OP, | ||
53 | USP_RX_FIFO_RESET, USP_RX_FIFO_RESET); | ||
54 | regmap_write(usp->regmap, USP_RX_FIFO_OP, 0); | ||
55 | |||
56 | regmap_update_bits(usp->regmap, USP_RX_FIFO_OP, | ||
57 | USP_RX_FIFO_START, USP_RX_FIFO_START); | ||
58 | |||
59 | regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, | ||
60 | USP_RX_ENA, USP_RX_ENA); | ||
61 | } | ||
62 | |||
63 | static void sirf_usp_rx_disable(struct sirf_usp *usp) | ||
64 | { | ||
65 | regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, | ||
66 | USP_RX_ENA, ~USP_RX_ENA); | ||
67 | /* FIFO stop */ | ||
68 | regmap_write(usp->regmap, USP_RX_FIFO_OP, 0); | ||
69 | } | ||
70 | |||
71 | static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai) | ||
72 | { | ||
73 | struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); | ||
74 | snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data, | ||
75 | &usp->capture_dma_data); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai, | ||
80 | unsigned int fmt) | ||
81 | { | ||
82 | struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); | ||
83 | |||
84 | /* set master/slave audio interface */ | ||
85 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
86 | case SND_SOC_DAIFMT_CBM_CFM: | ||
87 | break; | ||
88 | default: | ||
89 | dev_err(dai->dev, "Only CBM and CFM supported\n"); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
94 | case SND_SOC_DAIFMT_I2S: | ||
95 | case SND_SOC_DAIFMT_DSP_A: | ||
96 | usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
97 | break; | ||
98 | default: | ||
99 | dev_err(dai->dev, "Only I2S and DSP_A format supported\n"); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static void sirf_usp_i2s_init(struct sirf_usp *usp) | ||
107 | { | ||
108 | /* Configure RISC mode */ | ||
109 | regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE, | ||
110 | USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL); | ||
111 | |||
112 | /* | ||
113 | * Configure DMA IO Length register | ||
114 | * Set no limit, USP can receive data continuously until it is diabled | ||
115 | */ | ||
116 | regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0); | ||
117 | regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0); | ||
118 | |||
119 | /* Configure Mode2 register */ | ||
120 | regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) | | ||
121 | (0 << USP_TXD_DELAY_LEN_OFFSET) | | ||
122 | USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE); | ||
123 | |||
124 | /* Configure Mode1 register */ | ||
125 | regmap_write(usp->regmap, USP_MODE1, | ||
126 | USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING | | ||
127 | USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 | | ||
128 | USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE); | ||
129 | |||
130 | /* Configure RX DMA IO Control register */ | ||
131 | regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0); | ||
132 | |||
133 | /* Congiure RX FIFO Control register */ | ||
134 | regmap_write(usp->regmap, USP_RX_FIFO_CTRL, | ||
135 | (USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) | | ||
136 | (USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET)); | ||
137 | |||
138 | /* Congiure RX FIFO Level Check register */ | ||
139 | regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK, | ||
140 | RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B)); | ||
141 | |||
142 | /* Configure TX DMA IO Control register*/ | ||
143 | regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0); | ||
144 | |||
145 | /* Configure TX FIFO Control register */ | ||
146 | regmap_write(usp->regmap, USP_TX_FIFO_CTRL, | ||
147 | (USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) | | ||
148 | (USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET)); | ||
149 | /* Congiure TX FIFO Level Check register */ | ||
150 | regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK, | ||
151 | TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04)); | ||
152 | } | ||
153 | |||
154 | static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | ||
155 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
156 | { | ||
157 | struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); | ||
158 | u32 data_len, frame_len, shifter_len; | ||
159 | |||
160 | switch (params_format(params)) { | ||
161 | case SNDRV_PCM_FORMAT_S16_LE: | ||
162 | data_len = 16; | ||
163 | frame_len = 16; | ||
164 | break; | ||
165 | case SNDRV_PCM_FORMAT_S24_LE: | ||
166 | data_len = 24; | ||
167 | frame_len = 32; | ||
168 | break; | ||
169 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
170 | data_len = 24; | ||
171 | frame_len = 24; | ||
172 | break; | ||
173 | default: | ||
174 | dev_err(dai->dev, "Format unsupported\n"); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | shifter_len = data_len; | ||
179 | |||
180 | switch (usp->daifmt_format) { | ||
181 | case SND_SOC_DAIFMT_I2S: | ||
182 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | ||
183 | USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); | ||
184 | break; | ||
185 | case SND_SOC_DAIFMT_DSP_A: | ||
186 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | ||
187 | USP_I2S_SYNC_CHG, 0); | ||
188 | frame_len = data_len * params_channels(params); | ||
189 | data_len = frame_len; | ||
190 | break; | ||
191 | default: | ||
192 | dev_err(dai->dev, "Only support I2S and DSP_A mode\n"); | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
197 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, | ||
198 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK | ||
199 | | USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE, | ||
200 | ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET) | ||
201 | | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET) | ||
202 | | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET) | ||
203 | | USP_TXC_SLAVE_CLK_SAMPLE); | ||
204 | else | ||
205 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | ||
206 | USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK | ||
207 | | USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE, | ||
208 | ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET) | ||
209 | | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET) | ||
210 | | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET) | ||
211 | | USP_SINGLE_SYNC_MODE); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | ||
217 | struct snd_soc_dai *dai) | ||
218 | { | ||
219 | struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); | ||
220 | |||
221 | switch (cmd) { | ||
222 | case SNDRV_PCM_TRIGGER_START: | ||
223 | case SNDRV_PCM_TRIGGER_RESUME: | ||
224 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
225 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
226 | sirf_usp_tx_enable(usp); | ||
227 | else | ||
228 | sirf_usp_rx_enable(usp); | ||
229 | break; | ||
230 | case SNDRV_PCM_TRIGGER_STOP: | ||
231 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
232 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
233 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
234 | sirf_usp_tx_disable(usp); | ||
235 | else | ||
236 | sirf_usp_rx_disable(usp); | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = { | ||
244 | .trigger = sirf_usp_pcm_trigger, | ||
245 | .set_fmt = sirf_usp_pcm_set_dai_fmt, | ||
246 | .hw_params = sirf_usp_pcm_hw_params, | ||
247 | }; | ||
248 | |||
249 | static struct snd_soc_dai_driver sirf_usp_pcm_dai = { | ||
250 | .probe = sirf_usp_pcm_dai_probe, | ||
251 | .name = "sirf-usp-pcm", | ||
252 | .id = 0, | ||
253 | .playback = { | ||
254 | .stream_name = "SiRF USP PCM Playback", | ||
255 | .channels_min = 1, | ||
256 | .channels_max = 2, | ||
257 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
258 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
259 | SNDRV_PCM_FMTBIT_S24_3LE, | ||
260 | }, | ||
261 | .capture = { | ||
262 | .stream_name = "SiRF USP PCM Capture", | ||
263 | .channels_min = 1, | ||
264 | .channels_max = 2, | ||
265 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
266 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
267 | SNDRV_PCM_FMTBIT_S24_3LE, | ||
268 | }, | ||
269 | .ops = &sirf_usp_pcm_dai_ops, | ||
270 | }; | ||
271 | |||
272 | static int sirf_usp_pcm_runtime_suspend(struct device *dev) | ||
273 | { | ||
274 | struct sirf_usp *usp = dev_get_drvdata(dev); | ||
275 | clk_disable_unprepare(usp->clk); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int sirf_usp_pcm_runtime_resume(struct device *dev) | ||
280 | { | ||
281 | struct sirf_usp *usp = dev_get_drvdata(dev); | ||
282 | int ret; | ||
283 | ret = clk_prepare_enable(usp->clk); | ||
284 | if (ret) { | ||
285 | dev_err(dev, "clk_enable failed: %d\n", ret); | ||
286 | return ret; | ||
287 | } | ||
288 | sirf_usp_i2s_init(usp); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | #ifdef CONFIG_PM_SLEEP | ||
293 | static int sirf_usp_pcm_suspend(struct device *dev) | ||
294 | { | ||
295 | struct sirf_usp *usp = dev_get_drvdata(dev); | ||
296 | |||
297 | if (!pm_runtime_status_suspended(dev)) { | ||
298 | regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg); | ||
299 | regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg); | ||
300 | sirf_usp_pcm_runtime_suspend(dev); | ||
301 | } | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int sirf_usp_pcm_resume(struct device *dev) | ||
306 | { | ||
307 | struct sirf_usp *usp = dev_get_drvdata(dev); | ||
308 | int ret; | ||
309 | |||
310 | if (!pm_runtime_status_suspended(dev)) { | ||
311 | ret = sirf_usp_pcm_runtime_resume(dev); | ||
312 | if (ret) | ||
313 | return ret; | ||
314 | regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg); | ||
315 | regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg); | ||
316 | } | ||
317 | return 0; | ||
318 | } | ||
319 | #endif | ||
320 | |||
321 | static const struct snd_soc_component_driver sirf_usp_component = { | ||
322 | .name = "sirf-usp", | ||
323 | }; | ||
324 | |||
325 | static const struct regmap_config sirf_usp_regmap_config = { | ||
326 | .reg_bits = 32, | ||
327 | .reg_stride = 4, | ||
328 | .val_bits = 32, | ||
329 | .max_register = USP_RX_FIFO_DATA, | ||
330 | .cache_type = REGCACHE_NONE, | ||
331 | }; | ||
332 | |||
333 | static int sirf_usp_pcm_probe(struct platform_device *pdev) | ||
334 | { | ||
335 | int ret; | ||
336 | struct sirf_usp *usp; | ||
337 | void __iomem *base; | ||
338 | struct resource *mem_res; | ||
339 | |||
340 | usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp), | ||
341 | GFP_KERNEL); | ||
342 | if (!usp) | ||
343 | return -ENOMEM; | ||
344 | |||
345 | platform_set_drvdata(pdev, usp); | ||
346 | |||
347 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
348 | base = devm_ioremap(&pdev->dev, mem_res->start, | ||
349 | resource_size(mem_res)); | ||
350 | if (base == NULL) | ||
351 | return -ENOMEM; | ||
352 | usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
353 | &sirf_usp_regmap_config); | ||
354 | if (IS_ERR(usp->regmap)) | ||
355 | return PTR_ERR(usp->regmap); | ||
356 | |||
357 | usp->clk = devm_clk_get(&pdev->dev, NULL); | ||
358 | if (IS_ERR(usp->clk)) { | ||
359 | dev_err(&pdev->dev, "Get clock failed.\n"); | ||
360 | return PTR_ERR(usp->clk); | ||
361 | } | ||
362 | |||
363 | pm_runtime_enable(&pdev->dev); | ||
364 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
365 | ret = sirf_usp_pcm_runtime_resume(&pdev->dev); | ||
366 | if (ret) | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component, | ||
371 | &sirf_usp_pcm_dai, 1); | ||
372 | if (ret) { | ||
373 | dev_err(&pdev->dev, "Register Audio SoC dai failed.\n"); | ||
374 | return ret; | ||
375 | } | ||
376 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
377 | } | ||
378 | |||
379 | static int sirf_usp_pcm_remove(struct platform_device *pdev) | ||
380 | { | ||
381 | if (!pm_runtime_enabled(&pdev->dev)) | ||
382 | sirf_usp_pcm_runtime_suspend(&pdev->dev); | ||
383 | else | ||
384 | pm_runtime_disable(&pdev->dev); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static const struct of_device_id sirf_usp_pcm_of_match[] = { | ||
389 | { .compatible = "sirf,prima2-usp-pcm", }, | ||
390 | {} | ||
391 | }; | ||
392 | MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match); | ||
393 | |||
394 | static const struct dev_pm_ops sirf_usp_pcm_pm_ops = { | ||
395 | SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend, | ||
396 | sirf_usp_pcm_runtime_resume, NULL) | ||
397 | SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume) | ||
398 | }; | ||
399 | |||
400 | static struct platform_driver sirf_usp_pcm_driver = { | ||
401 | .driver = { | ||
402 | .name = "sirf-usp-pcm", | ||
403 | .owner = THIS_MODULE, | ||
404 | .of_match_table = sirf_usp_pcm_of_match, | ||
405 | .pm = &sirf_usp_pcm_pm_ops, | ||
406 | }, | ||
407 | .probe = sirf_usp_pcm_probe, | ||
408 | .remove = sirf_usp_pcm_remove, | ||
409 | }; | ||
410 | |||
411 | module_platform_driver(sirf_usp_pcm_driver); | ||
412 | |||
413 | MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver"); | ||
414 | MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); | ||
415 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/sirf/sirf-usp.h b/sound/soc/sirf/sirf-usp.h new file mode 100644 index 000000000000..bf0201cb15bc --- /dev/null +++ b/sound/soc/sirf/sirf-usp.h | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-prima2/include/mach/sirfsoc_usp.h | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _SIRF_USP_H | ||
10 | #define _SIRF_USP_H | ||
11 | |||
12 | /* USP Registers */ | ||
13 | #define USP_MODE1 0x00 | ||
14 | #define USP_MODE2 0x04 | ||
15 | #define USP_TX_FRAME_CTRL 0x08 | ||
16 | #define USP_RX_FRAME_CTRL 0x0C | ||
17 | #define USP_TX_RX_ENABLE 0x10 | ||
18 | #define USP_INT_ENABLE 0x14 | ||
19 | #define USP_INT_STATUS 0x18 | ||
20 | #define USP_PIN_IO_DATA 0x1C | ||
21 | #define USP_RISC_DSP_MODE 0x20 | ||
22 | #define USP_AYSNC_PARAM_REG 0x24 | ||
23 | #define USP_IRDA_X_MODE_DIV 0x28 | ||
24 | #define USP_SM_CFG 0x2C | ||
25 | #define USP_TX_DMA_IO_CTRL 0x100 | ||
26 | #define USP_TX_DMA_IO_LEN 0x104 | ||
27 | #define USP_TX_FIFO_CTRL 0x108 | ||
28 | #define USP_TX_FIFO_LEVEL_CHK 0x10C | ||
29 | #define USP_TX_FIFO_OP 0x110 | ||
30 | #define USP_TX_FIFO_STATUS 0x114 | ||
31 | #define USP_TX_FIFO_DATA 0x118 | ||
32 | #define USP_RX_DMA_IO_CTRL 0x120 | ||
33 | #define USP_RX_DMA_IO_LEN 0x124 | ||
34 | #define USP_RX_FIFO_CTRL 0x128 | ||
35 | #define USP_RX_FIFO_LEVEL_CHK 0x12C | ||
36 | #define USP_RX_FIFO_OP 0x130 | ||
37 | #define USP_RX_FIFO_STATUS 0x134 | ||
38 | #define USP_RX_FIFO_DATA 0x138 | ||
39 | |||
40 | /* USP MODE register-1 */ | ||
41 | #define USP_SYNC_MODE 0x00000001 | ||
42 | #define USP_CLOCK_MODE_SLAVE 0x00000002 | ||
43 | #define USP_LOOP_BACK_EN 0x00000004 | ||
44 | #define USP_HPSIR_EN 0x00000008 | ||
45 | #define USP_ENDIAN_CTRL_LSBF 0x00000010 | ||
46 | #define USP_EN 0x00000020 | ||
47 | #define USP_RXD_ACT_EDGE_FALLING 0x00000040 | ||
48 | #define USP_TXD_ACT_EDGE_FALLING 0x00000080 | ||
49 | #define USP_RFS_ACT_LEVEL_LOGIC1 0x00000100 | ||
50 | #define USP_TFS_ACT_LEVEL_LOGIC1 0x00000200 | ||
51 | #define USP_SCLK_IDLE_MODE_TOGGLE 0x00000400 | ||
52 | #define USP_SCLK_IDLE_LEVEL_LOGIC1 0x00000800 | ||
53 | #define USP_SCLK_PIN_MODE_IO 0x00001000 | ||
54 | #define USP_RFS_PIN_MODE_IO 0x00002000 | ||
55 | #define USP_TFS_PIN_MODE_IO 0x00004000 | ||
56 | #define USP_RXD_PIN_MODE_IO 0x00008000 | ||
57 | #define USP_TXD_PIN_MODE_IO 0x00010000 | ||
58 | #define USP_SCLK_IO_MODE_INPUT 0x00020000 | ||
59 | #define USP_RFS_IO_MODE_INPUT 0x00040000 | ||
60 | #define USP_TFS_IO_MODE_INPUT 0x00080000 | ||
61 | #define USP_RXD_IO_MODE_INPUT 0x00100000 | ||
62 | #define USP_TXD_IO_MODE_INPUT 0x00200000 | ||
63 | #define USP_IRDA_WIDTH_DIV_MASK 0x3FC00000 | ||
64 | #define USP_IRDA_WIDTH_DIV_OFFSET 0 | ||
65 | #define USP_IRDA_IDLE_LEVEL_HIGH 0x40000000 | ||
66 | #define USP_TX_UFLOW_REPEAT_ZERO 0x80000000 | ||
67 | #define USP_TX_ENDIAN_MODE 0x00000020 | ||
68 | #define USP_RX_ENDIAN_MODE 0x00000020 | ||
69 | |||
70 | /* USP Mode Register-2 */ | ||
71 | #define USP_RXD_DELAY_LEN_MASK 0x000000FF | ||
72 | #define USP_RXD_DELAY_LEN_OFFSET 0 | ||
73 | |||
74 | #define USP_TXD_DELAY_LEN_MASK 0x0000FF00 | ||
75 | #define USP_TXD_DELAY_LEN_OFFSET 8 | ||
76 | |||
77 | #define USP_ENA_CTRL_MODE 0x00010000 | ||
78 | #define USP_FRAME_CTRL_MODE 0x00020000 | ||
79 | #define USP_TFS_SOURCE_MODE 0x00040000 | ||
80 | #define USP_TFS_MS_MODE 0x00080000 | ||
81 | #define USP_CLK_DIVISOR_MASK 0x7FE00000 | ||
82 | #define USP_CLK_DIVISOR_OFFSET 21 | ||
83 | |||
84 | #define USP_TFS_CLK_SLAVE_MODE (1<<20) | ||
85 | #define USP_RFS_CLK_SLAVE_MODE (1<<19) | ||
86 | |||
87 | #define USP_IRDA_DATA_WIDTH 0x80000000 | ||
88 | |||
89 | /* USP Transmit Frame Control Register */ | ||
90 | |||
91 | #define USP_TXC_DATA_LEN_MASK 0x000000FF | ||
92 | #define USP_TXC_DATA_LEN_OFFSET 0 | ||
93 | |||
94 | #define USP_TXC_SYNC_LEN_MASK 0x0000FF00 | ||
95 | #define USP_TXC_SYNC_LEN_OFFSET 8 | ||
96 | |||
97 | #define USP_TXC_FRAME_LEN_MASK 0x00FF0000 | ||
98 | #define USP_TXC_FRAME_LEN_OFFSET 16 | ||
99 | |||
100 | #define USP_TXC_SHIFTER_LEN_MASK 0x1F000000 | ||
101 | #define USP_TXC_SHIFTER_LEN_OFFSET 24 | ||
102 | |||
103 | #define USP_TXC_SLAVE_CLK_SAMPLE 0x20000000 | ||
104 | |||
105 | #define USP_TXC_CLK_DIVISOR_MASK 0xC0000000 | ||
106 | #define USP_TXC_CLK_DIVISOR_OFFSET 30 | ||
107 | |||
108 | /* USP Receive Frame Control Register */ | ||
109 | |||
110 | #define USP_RXC_DATA_LEN_MASK 0x000000FF | ||
111 | #define USP_RXC_DATA_LEN_OFFSET 0 | ||
112 | |||
113 | #define USP_RXC_FRAME_LEN_MASK 0x0000FF00 | ||
114 | #define USP_RXC_FRAME_LEN_OFFSET 8 | ||
115 | |||
116 | #define USP_RXC_SHIFTER_LEN_MASK 0x001F0000 | ||
117 | #define USP_RXC_SHIFTER_LEN_OFFSET 16 | ||
118 | |||
119 | #define USP_START_EDGE_MODE 0x00800000 | ||
120 | #define USP_I2S_SYNC_CHG 0x00200000 | ||
121 | |||
122 | #define USP_RXC_CLK_DIVISOR_MASK 0x0F000000 | ||
123 | #define USP_RXC_CLK_DIVISOR_OFFSET 24 | ||
124 | #define USP_SINGLE_SYNC_MODE 0x00400000 | ||
125 | |||
126 | /* Tx - RX Enable Register */ | ||
127 | |||
128 | #define USP_RX_ENA 0x00000001 | ||
129 | #define USP_TX_ENA 0x00000002 | ||
130 | |||
131 | /* USP Interrupt Enable and status Register */ | ||
132 | #define USP_RX_DONE_INT 0x00000001 | ||
133 | #define USP_TX_DONE_INT 0x00000002 | ||
134 | #define USP_RX_OFLOW_INT 0x00000004 | ||
135 | #define USP_TX_UFLOW_INT 0x00000008 | ||
136 | #define USP_RX_IO_DMA_INT 0x00000010 | ||
137 | #define USP_TX_IO_DMA_INT 0x00000020 | ||
138 | #define USP_RXFIFO_FULL_INT 0x00000040 | ||
139 | #define USP_TXFIFO_EMPTY_INT 0x00000080 | ||
140 | #define USP_RXFIFO_THD_INT 0x00000100 | ||
141 | #define USP_TXFIFO_THD_INT 0x00000200 | ||
142 | #define USP_UART_FRM_ERR_INT 0x00000400 | ||
143 | #define USP_RX_TIMEOUT_INT 0x00000800 | ||
144 | #define USP_TX_ALLOUT_INT 0x00001000 | ||
145 | #define USP_RXD_BREAK_INT 0x00008000 | ||
146 | |||
147 | /* All possible TX interruots */ | ||
148 | #define USP_TX_INTERRUPT (USP_TX_DONE_INT|USP_TX_UFLOW_INT|\ | ||
149 | USP_TX_IO_DMA_INT|\ | ||
150 | USP_TXFIFO_EMPTY_INT|\ | ||
151 | USP_TXFIFO_THD_INT) | ||
152 | /* All possible RX interruots */ | ||
153 | #define USP_RX_INTERRUPT (USP_RX_DONE_INT|USP_RX_OFLOW_INT|\ | ||
154 | USP_RX_IO_DMA_INT|\ | ||
155 | USP_RXFIFO_FULL_INT|\ | ||
156 | USP_RXFIFO_THD_INT|\ | ||
157 | USP_RXFIFO_THD_INT|USP_RX_TIMEOUT_INT) | ||
158 | |||
159 | #define USP_INT_ALL 0x1FFF | ||
160 | |||
161 | /* USP Pin I/O Data Register */ | ||
162 | |||
163 | #define USP_RFS_PIN_VALUE_MASK 0x00000001 | ||
164 | #define USP_TFS_PIN_VALUE_MASK 0x00000002 | ||
165 | #define USP_RXD_PIN_VALUE_MASK 0x00000004 | ||
166 | #define USP_TXD_PIN_VALUE_MASK 0x00000008 | ||
167 | #define USP_SCLK_PIN_VALUE_MASK 0x00000010 | ||
168 | |||
169 | /* USP RISC/DSP Mode Register */ | ||
170 | #define USP_RISC_DSP_SEL 0x00000001 | ||
171 | |||
172 | /* USP ASYNC PARAMETER Register*/ | ||
173 | |||
174 | #define USP_ASYNC_TIMEOUT_MASK 0x0000FFFF | ||
175 | #define USP_ASYNC_TIMEOUT_OFFSET 0 | ||
176 | #define USP_ASYNC_TIMEOUT(x) (((x)&USP_ASYNC_TIMEOUT_MASK) \ | ||
177 | <<USP_ASYNC_TIMEOUT_OFFSET) | ||
178 | |||
179 | #define USP_ASYNC_DIV2_MASK 0x003F0000 | ||
180 | #define USP_ASYNC_DIV2_OFFSET 16 | ||
181 | |||
182 | /* USP TX DMA I/O MODE Register */ | ||
183 | #define USP_TX_MODE_IO 0x00000001 | ||
184 | |||
185 | /* USP TX DMA I/O Length Register */ | ||
186 | #define USP_TX_DATA_LEN_MASK 0xFFFFFFFF | ||
187 | #define USP_TX_DATA_LEN_OFFSET 0 | ||
188 | |||
189 | /* USP TX FIFO Control Register */ | ||
190 | #define USP_TX_FIFO_WIDTH_MASK 0x00000003 | ||
191 | #define USP_TX_FIFO_WIDTH_OFFSET 0 | ||
192 | |||
193 | #define USP_TX_FIFO_THD_MASK 0x000001FC | ||
194 | #define USP_TX_FIFO_THD_OFFSET 2 | ||
195 | |||
196 | /* USP TX FIFO Level Check Register */ | ||
197 | #define USP_TX_FIFO_LEVEL_CHECK_MASK 0x1F | ||
198 | #define USP_TX_FIFO_SC_OFFSET 0 | ||
199 | #define USP_TX_FIFO_LC_OFFSET 10 | ||
200 | #define USP_TX_FIFO_HC_OFFSET 20 | ||
201 | |||
202 | #define TX_FIFO_SC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
203 | << USP_TX_FIFO_SC_OFFSET) | ||
204 | #define TX_FIFO_LC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
205 | << USP_TX_FIFO_LC_OFFSET) | ||
206 | #define TX_FIFO_HC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
207 | << USP_TX_FIFO_HC_OFFSET) | ||
208 | |||
209 | /* USP TX FIFO Operation Register */ | ||
210 | #define USP_TX_FIFO_RESET 0x00000001 | ||
211 | #define USP_TX_FIFO_START 0x00000002 | ||
212 | |||
213 | /* USP TX FIFO Status Register */ | ||
214 | #define USP_TX_FIFO_LEVEL_MASK 0x0000007F | ||
215 | #define USP_TX_FIFO_LEVEL_OFFSET 0 | ||
216 | |||
217 | #define USP_TX_FIFO_FULL 0x00000080 | ||
218 | #define USP_TX_FIFO_EMPTY 0x00000100 | ||
219 | |||
220 | /* USP TX FIFO Data Register */ | ||
221 | #define USP_TX_FIFO_DATA_MASK 0xFFFFFFFF | ||
222 | #define USP_TX_FIFO_DATA_OFFSET 0 | ||
223 | |||
224 | /* USP RX DMA I/O MODE Register */ | ||
225 | #define USP_RX_MODE_IO 0x00000001 | ||
226 | #define USP_RX_DMA_FLUSH 0x00000004 | ||
227 | |||
228 | /* USP RX DMA I/O Length Register */ | ||
229 | #define USP_RX_DATA_LEN_MASK 0xFFFFFFFF | ||
230 | #define USP_RX_DATA_LEN_OFFSET 0 | ||
231 | |||
232 | /* USP RX FIFO Control Register */ | ||
233 | #define USP_RX_FIFO_WIDTH_MASK 0x00000003 | ||
234 | #define USP_RX_FIFO_WIDTH_OFFSET 0 | ||
235 | |||
236 | #define USP_RX_FIFO_THD_MASK 0x000001FC | ||
237 | #define USP_RX_FIFO_THD_OFFSET 2 | ||
238 | |||
239 | /* USP RX FIFO Level Check Register */ | ||
240 | |||
241 | #define USP_RX_FIFO_LEVEL_CHECK_MASK 0x1F | ||
242 | #define USP_RX_FIFO_SC_OFFSET 0 | ||
243 | #define USP_RX_FIFO_LC_OFFSET 10 | ||
244 | #define USP_RX_FIFO_HC_OFFSET 20 | ||
245 | |||
246 | #define RX_FIFO_SC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
247 | << USP_RX_FIFO_SC_OFFSET) | ||
248 | #define RX_FIFO_LC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
249 | << USP_RX_FIFO_LC_OFFSET) | ||
250 | #define RX_FIFO_HC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
251 | << USP_RX_FIFO_HC_OFFSET) | ||
252 | |||
253 | /* USP RX FIFO Operation Register */ | ||
254 | #define USP_RX_FIFO_RESET 0x00000001 | ||
255 | #define USP_RX_FIFO_START 0x00000002 | ||
256 | |||
257 | /* USP RX FIFO Status Register */ | ||
258 | |||
259 | #define USP_RX_FIFO_LEVEL_MASK 0x0000007F | ||
260 | #define USP_RX_FIFO_LEVEL_OFFSET 0 | ||
261 | |||
262 | #define USP_RX_FIFO_FULL 0x00000080 | ||
263 | #define USP_RX_FIFO_EMPTY 0x00000100 | ||
264 | |||
265 | /* USP RX FIFO Data Register */ | ||
266 | |||
267 | #define USP_RX_FIFO_DATA_MASK 0xFFFFFFFF | ||
268 | #define USP_RX_FIFO_DATA_OFFSET 0 | ||
269 | |||
270 | /* | ||
271 | * When rx thd irq occur, sender just disable tx empty irq, | ||
272 | * Remaining data in tx fifo wil also be sent out. | ||
273 | */ | ||
274 | #define USP_FIFO_SIZE 128 | ||
275 | #define USP_TX_FIFO_THRESHOLD (USP_FIFO_SIZE/2) | ||
276 | #define USP_RX_FIFO_THRESHOLD (USP_FIFO_SIZE/2) | ||
277 | |||
278 | /* FIFO_WIDTH for the USP_TX_FIFO_CTRL and USP_RX_FIFO_CTRL registers */ | ||
279 | #define USP_FIFO_WIDTH_BYTE 0x00 | ||
280 | #define USP_FIFO_WIDTH_WORD 0x01 | ||
281 | #define USP_FIFO_WIDTH_DWORD 0x02 | ||
282 | |||
283 | #define USP_ASYNC_DIV2 16 | ||
284 | |||
285 | #define USP_PLUGOUT_RETRY_CNT 2 | ||
286 | |||
287 | #define USP_TX_RX_FIFO_WIDTH_DWORD 2 | ||
288 | |||
289 | #define SIRF_USP_DIV_MCLK 0 | ||
290 | |||
291 | #define SIRF_USP_I2S_TFS_SYNC 0 | ||
292 | #define SIRF_USP_I2S_RFS_SYNC 1 | ||
293 | #endif | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 00e70b6c7da2..a9f82b5aba9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
78 | mutex_init(&codec->cache_rw_mutex); | 78 | mutex_init(&codec->cache_rw_mutex); |
79 | 79 | ||
80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", | 80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", |
81 | codec->name); | 81 | codec->component.name); |
82 | 82 | ||
83 | if (codec_drv->reg_cache_default) | 83 | if (codec_drv->reg_cache_default) |
84 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | 84 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, |
@@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
98 | int snd_soc_cache_exit(struct snd_soc_codec *codec) | 98 | int snd_soc_cache_exit(struct snd_soc_codec *codec) |
99 | { | 99 | { |
100 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", | 100 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", |
101 | codec->name); | 101 | codec->component.name); |
102 | |||
103 | kfree(codec->reg_cache); | 102 | kfree(codec->reg_cache); |
104 | codec->reg_cache = NULL; | 103 | codec->reg_cache = NULL; |
105 | return 0; | 104 | return 0; |
@@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec) | |||
192 | return 0; | 191 | return 0; |
193 | 192 | ||
194 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", | 193 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", |
195 | codec->name); | 194 | codec->component.name); |
196 | trace_snd_soc_cache_sync(codec, name, "start"); | 195 | trace_snd_soc_cache_sync(codec, name, "start"); |
197 | ret = snd_soc_flat_cache_sync(codec); | 196 | ret = snd_soc_flat_cache_sync(codec); |
198 | if (!ret) | 197 | if (!ret) |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 10f7f1da2aca..27c06acce205 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
37 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | 37 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { |
38 | ret = platform->driver->compr_ops->open(cstream); | 38 | ret = platform->driver->compr_ops->open(cstream); |
39 | if (ret < 0) { | 39 | if (ret < 0) { |
40 | pr_err("compress asoc: can't open platform %s\n", platform->name); | 40 | pr_err("compress asoc: can't open platform %s\n", |
41 | platform->component.name); | ||
41 | goto out; | 42 | goto out; |
42 | } | 43 | } |
43 | } | 44 | } |
@@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) | |||
84 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | 85 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { |
85 | ret = platform->driver->compr_ops->open(cstream); | 86 | ret = platform->driver->compr_ops->open(cstream); |
86 | if (ret < 0) { | 87 | if (ret < 0) { |
87 | pr_err("compress asoc: can't open platform %s\n", platform->name); | 88 | pr_err("compress asoc: can't open platform %s\n", |
89 | platform->component.name); | ||
88 | goto out; | 90 | goto out; |
89 | } | 91 | } |
90 | } | 92 | } |
@@ -627,6 +629,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
627 | char new_name[64]; | 629 | char new_name[64]; |
628 | int ret = 0, direction = 0; | 630 | int ret = 0, direction = 0; |
629 | 631 | ||
632 | if (rtd->num_codecs > 1) { | ||
633 | dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n"); | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
630 | /* check client and interface hw capabilities */ | 637 | /* check client and interface hw capabilities */ |
631 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | 638 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
632 | rtd->dai_link->stream_name, codec_dai->name, num); | 639 | rtd->dai_link->stream_name, codec_dai->name, num); |
@@ -680,7 +687,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
680 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); | 687 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); |
681 | if (ret < 0) { | 688 | if (ret < 0) { |
682 | pr_err("compress asoc: can't create compress for codec %s\n", | 689 | pr_err("compress asoc: can't create compress for codec %s\n", |
683 | codec->name); | 690 | codec->component.name); |
684 | goto compr_err; | 691 | goto compr_err; |
685 | } | 692 | } |
686 | 693 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b87d7d882e6d..d4bfd4a9076f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -270,12 +270,33 @@ static const struct file_operations codec_reg_fops = { | |||
270 | .llseek = default_llseek, | 270 | .llseek = default_llseek, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static struct dentry *soc_debugfs_create_dir(struct dentry *parent, | ||
274 | const char *fmt, ...) | ||
275 | { | ||
276 | struct dentry *de; | ||
277 | va_list ap; | ||
278 | char *s; | ||
279 | |||
280 | va_start(ap, fmt); | ||
281 | s = kvasprintf(GFP_KERNEL, fmt, ap); | ||
282 | va_end(ap); | ||
283 | |||
284 | if (!s) | ||
285 | return NULL; | ||
286 | |||
287 | de = debugfs_create_dir(s, parent); | ||
288 | kfree(s); | ||
289 | |||
290 | return de; | ||
291 | } | ||
292 | |||
273 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 293 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
274 | { | 294 | { |
275 | struct dentry *debugfs_card_root = codec->card->debugfs_card_root; | 295 | struct dentry *debugfs_card_root = codec->component.card->debugfs_card_root; |
276 | 296 | ||
277 | codec->debugfs_codec_root = debugfs_create_dir(codec->name, | 297 | codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root, |
278 | debugfs_card_root); | 298 | "codec:%s", |
299 | codec->component.name); | ||
279 | if (!codec->debugfs_codec_root) { | 300 | if (!codec->debugfs_codec_root) { |
280 | dev_warn(codec->dev, | 301 | dev_warn(codec->dev, |
281 | "ASoC: Failed to create codec debugfs directory\n"); | 302 | "ASoC: Failed to create codec debugfs directory\n"); |
@@ -304,17 +325,18 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | |||
304 | 325 | ||
305 | static void soc_init_platform_debugfs(struct snd_soc_platform *platform) | 326 | static void soc_init_platform_debugfs(struct snd_soc_platform *platform) |
306 | { | 327 | { |
307 | struct dentry *debugfs_card_root = platform->card->debugfs_card_root; | 328 | struct dentry *debugfs_card_root = platform->component.card->debugfs_card_root; |
308 | 329 | ||
309 | platform->debugfs_platform_root = debugfs_create_dir(platform->name, | 330 | platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root, |
310 | debugfs_card_root); | 331 | "platform:%s", |
332 | platform->component.name); | ||
311 | if (!platform->debugfs_platform_root) { | 333 | if (!platform->debugfs_platform_root) { |
312 | dev_warn(platform->dev, | 334 | dev_warn(platform->dev, |
313 | "ASoC: Failed to create platform debugfs directory\n"); | 335 | "ASoC: Failed to create platform debugfs directory\n"); |
314 | return; | 336 | return; |
315 | } | 337 | } |
316 | 338 | ||
317 | snd_soc_dapm_debugfs_init(&platform->dapm, | 339 | snd_soc_dapm_debugfs_init(&platform->component.dapm, |
318 | platform->debugfs_platform_root); | 340 | platform->debugfs_platform_root); |
319 | } | 341 | } |
320 | 342 | ||
@@ -335,7 +357,7 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, | |||
335 | 357 | ||
336 | list_for_each_entry(codec, &codec_list, list) { | 358 | list_for_each_entry(codec, &codec_list, list) { |
337 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", | 359 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
338 | codec->name); | 360 | codec->component.name); |
339 | if (len >= 0) | 361 | if (len >= 0) |
340 | ret += len; | 362 | ret += len; |
341 | if (ret > PAGE_SIZE) { | 363 | if (ret > PAGE_SIZE) { |
@@ -406,7 +428,7 @@ static ssize_t platform_list_read_file(struct file *file, | |||
406 | 428 | ||
407 | list_for_each_entry(platform, &platform_list, list) { | 429 | list_for_each_entry(platform, &platform_list, list) { |
408 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", | 430 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
409 | platform->name); | 431 | platform->component.name); |
410 | if (len >= 0) | 432 | if (len >= 0) |
411 | ret += len; | 433 | ret += len; |
412 | if (ret > PAGE_SIZE) { | 434 | if (ret > PAGE_SIZE) { |
@@ -524,11 +546,12 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
524 | int err; | 546 | int err; |
525 | 547 | ||
526 | codec->ac97->dev.bus = &ac97_bus_type; | 548 | codec->ac97->dev.bus = &ac97_bus_type; |
527 | codec->ac97->dev.parent = codec->card->dev; | 549 | codec->ac97->dev.parent = codec->component.card->dev; |
528 | codec->ac97->dev.release = soc_ac97_device_release; | 550 | codec->ac97->dev.release = soc_ac97_device_release; |
529 | 551 | ||
530 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | 552 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", |
531 | codec->card->snd_card->number, 0, codec->name); | 553 | codec->component.card->snd_card->number, 0, |
554 | codec->component.name); | ||
532 | err = device_register(&codec->ac97->dev); | 555 | err = device_register(&codec->ac97->dev); |
533 | if (err < 0) { | 556 | if (err < 0) { |
534 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | 557 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); |
@@ -554,7 +577,7 @@ int snd_soc_suspend(struct device *dev) | |||
554 | { | 577 | { |
555 | struct snd_soc_card *card = dev_get_drvdata(dev); | 578 | struct snd_soc_card *card = dev_get_drvdata(dev); |
556 | struct snd_soc_codec *codec; | 579 | struct snd_soc_codec *codec; |
557 | int i; | 580 | int i, j; |
558 | 581 | ||
559 | /* If the initialization of this soc device failed, there is no codec | 582 | /* If the initialization of this soc device failed, there is no codec |
560 | * associated with it. Just bail out in this case. | 583 | * associated with it. Just bail out in this case. |
@@ -574,14 +597,17 @@ int snd_soc_suspend(struct device *dev) | |||
574 | 597 | ||
575 | /* mute any active DACs */ | 598 | /* mute any active DACs */ |
576 | for (i = 0; i < card->num_rtd; i++) { | 599 | for (i = 0; i < card->num_rtd; i++) { |
577 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; | ||
578 | struct snd_soc_dai_driver *drv = dai->driver; | ||
579 | 600 | ||
580 | if (card->rtd[i].dai_link->ignore_suspend) | 601 | if (card->rtd[i].dai_link->ignore_suspend) |
581 | continue; | 602 | continue; |
582 | 603 | ||
583 | if (drv->ops->digital_mute && dai->playback_active) | 604 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
584 | drv->ops->digital_mute(dai, 1); | 605 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; |
606 | struct snd_soc_dai_driver *drv = dai->driver; | ||
607 | |||
608 | if (drv->ops->digital_mute && dai->playback_active) | ||
609 | drv->ops->digital_mute(dai, 1); | ||
610 | } | ||
585 | } | 611 | } |
586 | 612 | ||
587 | /* suspend all pcms */ | 613 | /* suspend all pcms */ |
@@ -612,8 +638,12 @@ int snd_soc_suspend(struct device *dev) | |||
612 | 638 | ||
613 | /* close any waiting streams and save state */ | 639 | /* close any waiting streams and save state */ |
614 | for (i = 0; i < card->num_rtd; i++) { | 640 | for (i = 0; i < card->num_rtd; i++) { |
641 | struct snd_soc_dai **codec_dais = card->rtd[i].codec_dais; | ||
615 | flush_delayed_work(&card->rtd[i].delayed_work); | 642 | flush_delayed_work(&card->rtd[i].delayed_work); |
616 | card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level; | 643 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
644 | codec_dais[j]->codec->dapm.suspend_bias_level = | ||
645 | codec_dais[j]->codec->dapm.bias_level; | ||
646 | } | ||
617 | } | 647 | } |
618 | 648 | ||
619 | for (i = 0; i < card->num_rtd; i++) { | 649 | for (i = 0; i < card->num_rtd; i++) { |
@@ -697,7 +727,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
697 | struct snd_soc_card *card = | 727 | struct snd_soc_card *card = |
698 | container_of(work, struct snd_soc_card, deferred_resume_work); | 728 | container_of(work, struct snd_soc_card, deferred_resume_work); |
699 | struct snd_soc_codec *codec; | 729 | struct snd_soc_codec *codec; |
700 | int i; | 730 | int i, j; |
701 | 731 | ||
702 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 732 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
703 | * so userspace apps are blocked from touching us | 733 | * so userspace apps are blocked from touching us |
@@ -758,14 +788,17 @@ static void soc_resume_deferred(struct work_struct *work) | |||
758 | 788 | ||
759 | /* unmute any active DACs */ | 789 | /* unmute any active DACs */ |
760 | for (i = 0; i < card->num_rtd; i++) { | 790 | for (i = 0; i < card->num_rtd; i++) { |
761 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; | ||
762 | struct snd_soc_dai_driver *drv = dai->driver; | ||
763 | 791 | ||
764 | if (card->rtd[i].dai_link->ignore_suspend) | 792 | if (card->rtd[i].dai_link->ignore_suspend) |
765 | continue; | 793 | continue; |
766 | 794 | ||
767 | if (drv->ops->digital_mute && dai->playback_active) | 795 | for (j = 0; j < card->rtd[i].num_codecs; j++) { |
768 | drv->ops->digital_mute(dai, 0); | 796 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; |
797 | struct snd_soc_dai_driver *drv = dai->driver; | ||
798 | |||
799 | if (drv->ops->digital_mute && dai->playback_active) | ||
800 | drv->ops->digital_mute(dai, 0); | ||
801 | } | ||
769 | } | 802 | } |
770 | 803 | ||
771 | for (i = 0; i < card->num_rtd; i++) { | 804 | for (i = 0; i < card->num_rtd; i++) { |
@@ -810,12 +843,19 @@ int snd_soc_resume(struct device *dev) | |||
810 | 843 | ||
811 | /* activate pins from sleep state */ | 844 | /* activate pins from sleep state */ |
812 | for (i = 0; i < card->num_rtd; i++) { | 845 | for (i = 0; i < card->num_rtd; i++) { |
813 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 846 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
814 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 847 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
848 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
849 | int j; | ||
850 | |||
815 | if (cpu_dai->active) | 851 | if (cpu_dai->active) |
816 | pinctrl_pm_select_default_state(cpu_dai->dev); | 852 | pinctrl_pm_select_default_state(cpu_dai->dev); |
817 | if (codec_dai->active) | 853 | |
818 | pinctrl_pm_select_default_state(codec_dai->dev); | 854 | for (j = 0; j < rtd->num_codecs; j++) { |
855 | struct snd_soc_dai *codec_dai = codec_dais[j]; | ||
856 | if (codec_dai->active) | ||
857 | pinctrl_pm_select_default_state(codec_dai->dev); | ||
858 | } | ||
819 | } | 859 | } |
820 | 860 | ||
821 | /* AC97 devices might have other drivers hanging off them so | 861 | /* AC97 devices might have other drivers hanging off them so |
@@ -847,8 +887,9 @@ EXPORT_SYMBOL_GPL(snd_soc_resume); | |||
847 | static const struct snd_soc_dai_ops null_dai_ops = { | 887 | static const struct snd_soc_dai_ops null_dai_ops = { |
848 | }; | 888 | }; |
849 | 889 | ||
850 | static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_node, | 890 | static struct snd_soc_codec *soc_find_codec( |
851 | const char *codec_name) | 891 | const struct device_node *codec_of_node, |
892 | const char *codec_name) | ||
852 | { | 893 | { |
853 | struct snd_soc_codec *codec; | 894 | struct snd_soc_codec *codec; |
854 | 895 | ||
@@ -857,7 +898,7 @@ static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_n | |||
857 | if (codec->dev->of_node != codec_of_node) | 898 | if (codec->dev->of_node != codec_of_node) |
858 | continue; | 899 | continue; |
859 | } else { | 900 | } else { |
860 | if (strcmp(codec->name, codec_name)) | 901 | if (strcmp(codec->component.name, codec_name)) |
861 | continue; | 902 | continue; |
862 | } | 903 | } |
863 | 904 | ||
@@ -886,9 +927,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
886 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 927 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
887 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 928 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
888 | struct snd_soc_component *component; | 929 | struct snd_soc_component *component; |
930 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; | ||
931 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | ||
889 | struct snd_soc_platform *platform; | 932 | struct snd_soc_platform *platform; |
890 | struct snd_soc_dai *cpu_dai; | 933 | struct snd_soc_dai *cpu_dai; |
891 | const char *platform_name; | 934 | const char *platform_name; |
935 | int i; | ||
892 | 936 | ||
893 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 937 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); |
894 | 938 | ||
@@ -915,24 +959,30 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
915 | return -EPROBE_DEFER; | 959 | return -EPROBE_DEFER; |
916 | } | 960 | } |
917 | 961 | ||
918 | /* Find CODEC from registered list */ | 962 | rtd->num_codecs = dai_link->num_codecs; |
919 | rtd->codec = soc_find_codec(dai_link->codec_of_node, | ||
920 | dai_link->codec_name); | ||
921 | if (!rtd->codec) { | ||
922 | dev_err(card->dev, "ASoC: CODEC %s not registered\n", | ||
923 | dai_link->codec_name); | ||
924 | return -EPROBE_DEFER; | ||
925 | } | ||
926 | 963 | ||
927 | /* Find CODEC DAI from registered list */ | 964 | /* Find CODEC from registered CODECs */ |
928 | rtd->codec_dai = soc_find_codec_dai(rtd->codec, | 965 | for (i = 0; i < rtd->num_codecs; i++) { |
929 | dai_link->codec_dai_name); | 966 | struct snd_soc_codec *codec; |
930 | if (!rtd->codec_dai) { | 967 | codec = soc_find_codec(codecs[i].of_node, codecs[i].name); |
931 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | 968 | if (!codec) { |
932 | dai_link->codec_dai_name); | 969 | dev_err(card->dev, "ASoC: CODEC %s not registered\n", |
933 | return -EPROBE_DEFER; | 970 | codecs[i].name); |
971 | return -EPROBE_DEFER; | ||
972 | } | ||
973 | |||
974 | codec_dais[i] = soc_find_codec_dai(codec, codecs[i].dai_name); | ||
975 | if (!codec_dais[i]) { | ||
976 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | ||
977 | codecs[i].dai_name); | ||
978 | return -EPROBE_DEFER; | ||
979 | } | ||
934 | } | 980 | } |
935 | 981 | ||
982 | /* Single codec links expect codec and codec_dai in runtime data */ | ||
983 | rtd->codec_dai = codec_dais[0]; | ||
984 | rtd->codec = rtd->codec_dai->codec; | ||
985 | |||
936 | /* if there's no platform we match on the empty platform */ | 986 | /* if there's no platform we match on the empty platform */ |
937 | platform_name = dai_link->platform_name; | 987 | platform_name = dai_link->platform_name; |
938 | if (!platform_name && !dai_link->platform_of_node) | 988 | if (!platform_name && !dai_link->platform_of_node) |
@@ -945,7 +995,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
945 | dai_link->platform_of_node) | 995 | dai_link->platform_of_node) |
946 | continue; | 996 | continue; |
947 | } else { | 997 | } else { |
948 | if (strcmp(platform->name, platform_name)) | 998 | if (strcmp(platform->component.name, platform_name)) |
949 | continue; | 999 | continue; |
950 | } | 1000 | } |
951 | 1001 | ||
@@ -974,11 +1024,10 @@ static int soc_remove_platform(struct snd_soc_platform *platform) | |||
974 | } | 1024 | } |
975 | 1025 | ||
976 | /* Make sure all DAPM widgets are freed */ | 1026 | /* Make sure all DAPM widgets are freed */ |
977 | snd_soc_dapm_free(&platform->dapm); | 1027 | snd_soc_dapm_free(&platform->component.dapm); |
978 | 1028 | ||
979 | soc_cleanup_platform_debugfs(platform); | 1029 | soc_cleanup_platform_debugfs(platform); |
980 | platform->probed = 0; | 1030 | platform->probed = 0; |
981 | list_del(&platform->card_list); | ||
982 | module_put(platform->dev->driver->owner); | 1031 | module_put(platform->dev->driver->owner); |
983 | 1032 | ||
984 | return 0; | 1033 | return 0; |
@@ -1023,8 +1072,8 @@ static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) | |||
1023 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | 1072 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) |
1024 | { | 1073 | { |
1025 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1074 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1026 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1075 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1027 | int err; | 1076 | int i, err; |
1028 | 1077 | ||
1029 | /* unregister the rtd device */ | 1078 | /* unregister the rtd device */ |
1030 | if (rtd->dev_registered) { | 1079 | if (rtd->dev_registered) { |
@@ -1035,7 +1084,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1035 | } | 1084 | } |
1036 | 1085 | ||
1037 | /* remove the CODEC DAI */ | 1086 | /* remove the CODEC DAI */ |
1038 | soc_remove_codec_dai(codec_dai, order); | 1087 | for (i = 0; i < rtd->num_codecs; i++) |
1088 | soc_remove_codec_dai(rtd->codec_dais[i], order); | ||
1039 | 1089 | ||
1040 | /* remove the cpu_dai */ | 1090 | /* remove the cpu_dai */ |
1041 | if (cpu_dai && cpu_dai->probed && | 1091 | if (cpu_dai && cpu_dai->probed && |
@@ -1048,11 +1098,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1048 | cpu_dai->name, err); | 1098 | cpu_dai->name, err); |
1049 | } | 1099 | } |
1050 | cpu_dai->probed = 0; | 1100 | cpu_dai->probed = 0; |
1051 | 1101 | if (!cpu_dai->codec) | |
1052 | if (!cpu_dai->codec) { | ||
1053 | snd_soc_dapm_free(&cpu_dai->dapm); | ||
1054 | module_put(cpu_dai->dev->driver->owner); | 1102 | module_put(cpu_dai->dev->driver->owner); |
1055 | } | ||
1056 | } | 1103 | } |
1057 | } | 1104 | } |
1058 | 1105 | ||
@@ -1061,9 +1108,9 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1061 | { | 1108 | { |
1062 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1109 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1063 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1110 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1064 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1065 | struct snd_soc_platform *platform = rtd->platform; | 1111 | struct snd_soc_platform *platform = rtd->platform; |
1066 | struct snd_soc_codec *codec; | 1112 | struct snd_soc_codec *codec; |
1113 | int i; | ||
1067 | 1114 | ||
1068 | /* remove the platform */ | 1115 | /* remove the platform */ |
1069 | if (platform && platform->probed && | 1116 | if (platform && platform->probed && |
@@ -1072,8 +1119,8 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1072 | } | 1119 | } |
1073 | 1120 | ||
1074 | /* remove the CODEC-side CODEC */ | 1121 | /* remove the CODEC-side CODEC */ |
1075 | if (codec_dai) { | 1122 | for (i = 0; i < rtd->num_codecs; i++) { |
1076 | codec = codec_dai->codec; | 1123 | codec = rtd->codec_dais[i]->codec; |
1077 | if (codec && codec->probed && | 1124 | if (codec && codec->probed && |
1078 | codec->driver->remove_order == order) | 1125 | codec->driver->remove_order == order) |
1079 | soc_remove_codec(codec); | 1126 | soc_remove_codec(codec); |
@@ -1108,7 +1155,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card) | |||
1108 | } | 1155 | } |
1109 | 1156 | ||
1110 | static void soc_set_name_prefix(struct snd_soc_card *card, | 1157 | static void soc_set_name_prefix(struct snd_soc_card *card, |
1111 | struct snd_soc_codec *codec) | 1158 | struct snd_soc_component *component) |
1112 | { | 1159 | { |
1113 | int i; | 1160 | int i; |
1114 | 1161 | ||
@@ -1117,11 +1164,11 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1117 | 1164 | ||
1118 | for (i = 0; i < card->num_configs; i++) { | 1165 | for (i = 0; i < card->num_configs; i++) { |
1119 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; | 1166 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; |
1120 | if (map->of_node && codec->dev->of_node != map->of_node) | 1167 | if (map->of_node && component->dev->of_node != map->of_node) |
1121 | continue; | 1168 | continue; |
1122 | if (map->dev_name && strcmp(codec->name, map->dev_name)) | 1169 | if (map->dev_name && strcmp(component->name, map->dev_name)) |
1123 | continue; | 1170 | continue; |
1124 | codec->name_prefix = map->name_prefix; | 1171 | component->name_prefix = map->name_prefix; |
1125 | break; | 1172 | break; |
1126 | } | 1173 | } |
1127 | } | 1174 | } |
@@ -1133,9 +1180,9 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1133 | const struct snd_soc_codec_driver *driver = codec->driver; | 1180 | const struct snd_soc_codec_driver *driver = codec->driver; |
1134 | struct snd_soc_dai *dai; | 1181 | struct snd_soc_dai *dai; |
1135 | 1182 | ||
1136 | codec->card = card; | 1183 | codec->component.card = card; |
1137 | codec->dapm.card = card; | 1184 | codec->dapm.card = card; |
1138 | soc_set_name_prefix(card, codec); | 1185 | soc_set_name_prefix(card, &codec->component); |
1139 | 1186 | ||
1140 | if (!try_module_get(codec->dev->driver->owner)) | 1187 | if (!try_module_get(codec->dev->driver->owner)) |
1141 | return -ENODEV; | 1188 | return -ENODEV; |
@@ -1177,7 +1224,7 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1177 | WARN(codec->dapm.idle_bias_off && | 1224 | WARN(codec->dapm.idle_bias_off && |
1178 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, | 1225 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, |
1179 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | 1226 | "codec %s can not start from non-off bias with idle_bias_off==1\n", |
1180 | codec->name); | 1227 | codec->component.name); |
1181 | } | 1228 | } |
1182 | 1229 | ||
1183 | if (driver->controls) | 1230 | if (driver->controls) |
@@ -1209,8 +1256,8 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1209 | struct snd_soc_component *component; | 1256 | struct snd_soc_component *component; |
1210 | struct snd_soc_dai *dai; | 1257 | struct snd_soc_dai *dai; |
1211 | 1258 | ||
1212 | platform->card = card; | 1259 | platform->component.card = card; |
1213 | platform->dapm.card = card; | 1260 | platform->component.dapm.card = card; |
1214 | 1261 | ||
1215 | if (!try_module_get(platform->dev->driver->owner)) | 1262 | if (!try_module_get(platform->dev->driver->owner)) |
1216 | return -ENODEV; | 1263 | return -ENODEV; |
@@ -1218,7 +1265,7 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1218 | soc_init_platform_debugfs(platform); | 1265 | soc_init_platform_debugfs(platform); |
1219 | 1266 | ||
1220 | if (driver->dapm_widgets) | 1267 | if (driver->dapm_widgets) |
1221 | snd_soc_dapm_new_controls(&platform->dapm, | 1268 | snd_soc_dapm_new_controls(&platform->component.dapm, |
1222 | driver->dapm_widgets, driver->num_dapm_widgets); | 1269 | driver->dapm_widgets, driver->num_dapm_widgets); |
1223 | 1270 | ||
1224 | /* Create DAPM widgets for each DAI stream */ | 1271 | /* Create DAPM widgets for each DAI stream */ |
@@ -1226,10 +1273,11 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1226 | if (component->dev != platform->dev) | 1273 | if (component->dev != platform->dev) |
1227 | continue; | 1274 | continue; |
1228 | list_for_each_entry(dai, &component->dai_list, list) | 1275 | list_for_each_entry(dai, &component->dai_list, list) |
1229 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); | 1276 | snd_soc_dapm_new_dai_widgets(&platform->component.dapm, |
1277 | dai); | ||
1230 | } | 1278 | } |
1231 | 1279 | ||
1232 | platform->dapm.idle_bias_off = 1; | 1280 | platform->component.dapm.idle_bias_off = 1; |
1233 | 1281 | ||
1234 | if (driver->probe) { | 1282 | if (driver->probe) { |
1235 | ret = driver->probe(platform); | 1283 | ret = driver->probe(platform); |
@@ -1244,13 +1292,12 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1244 | snd_soc_add_platform_controls(platform, driver->controls, | 1292 | snd_soc_add_platform_controls(platform, driver->controls, |
1245 | driver->num_controls); | 1293 | driver->num_controls); |
1246 | if (driver->dapm_routes) | 1294 | if (driver->dapm_routes) |
1247 | snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes, | 1295 | snd_soc_dapm_add_routes(&platform->component.dapm, |
1248 | driver->num_dapm_routes); | 1296 | driver->dapm_routes, driver->num_dapm_routes); |
1249 | 1297 | ||
1250 | /* mark platform as probed and add to card platform list */ | 1298 | /* mark platform as probed and add to card platform list */ |
1251 | platform->probed = 1; | 1299 | platform->probed = 1; |
1252 | list_add(&platform->card_list, &card->platform_dev_list); | 1300 | list_add(&platform->component.dapm.list, &card->dapm_list); |
1253 | list_add(&platform->dapm.list, &card->dapm_list); | ||
1254 | 1301 | ||
1255 | return 0; | 1302 | return 0; |
1256 | 1303 | ||
@@ -1266,83 +1313,17 @@ static void rtd_release(struct device *dev) | |||
1266 | kfree(dev); | 1313 | kfree(dev); |
1267 | } | 1314 | } |
1268 | 1315 | ||
1269 | static int soc_aux_dev_init(struct snd_soc_card *card, | 1316 | static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, |
1270 | struct snd_soc_codec *codec, | 1317 | const char *name) |
1271 | int num) | ||
1272 | { | ||
1273 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1274 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1275 | int ret; | ||
1276 | |||
1277 | rtd->card = card; | ||
1278 | |||
1279 | /* do machine specific initialization */ | ||
1280 | if (aux_dev->init) { | ||
1281 | ret = aux_dev->init(&codec->dapm); | ||
1282 | if (ret < 0) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1286 | rtd->codec = codec; | ||
1287 | |||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static int soc_dai_link_init(struct snd_soc_card *card, | ||
1292 | struct snd_soc_codec *codec, | ||
1293 | int num) | ||
1294 | { | 1318 | { |
1295 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | ||
1296 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1297 | int ret; | ||
1298 | |||
1299 | rtd->card = card; | ||
1300 | |||
1301 | /* do machine specific initialization */ | ||
1302 | if (dai_link->init) { | ||
1303 | ret = dai_link->init(rtd); | ||
1304 | if (ret < 0) | ||
1305 | return ret; | ||
1306 | } | ||
1307 | |||
1308 | rtd->codec = codec; | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static int soc_post_component_init(struct snd_soc_card *card, | ||
1314 | struct snd_soc_codec *codec, | ||
1315 | int num, int dailess) | ||
1316 | { | ||
1317 | struct snd_soc_dai_link *dai_link = NULL; | ||
1318 | struct snd_soc_aux_dev *aux_dev = NULL; | ||
1319 | struct snd_soc_pcm_runtime *rtd; | ||
1320 | const char *name; | ||
1321 | int ret = 0; | 1319 | int ret = 0; |
1322 | 1320 | ||
1323 | if (!dailess) { | ||
1324 | dai_link = &card->dai_link[num]; | ||
1325 | rtd = &card->rtd[num]; | ||
1326 | name = dai_link->name; | ||
1327 | ret = soc_dai_link_init(card, codec, num); | ||
1328 | } else { | ||
1329 | aux_dev = &card->aux_dev[num]; | ||
1330 | rtd = &card->rtd_aux[num]; | ||
1331 | name = aux_dev->name; | ||
1332 | ret = soc_aux_dev_init(card, codec, num); | ||
1333 | } | ||
1334 | |||
1335 | if (ret < 0) { | ||
1336 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret); | ||
1337 | return ret; | ||
1338 | } | ||
1339 | |||
1340 | /* register the rtd device */ | 1321 | /* register the rtd device */ |
1341 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); | 1322 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); |
1342 | if (!rtd->dev) | 1323 | if (!rtd->dev) |
1343 | return -ENOMEM; | 1324 | return -ENOMEM; |
1344 | device_initialize(rtd->dev); | 1325 | device_initialize(rtd->dev); |
1345 | rtd->dev->parent = card->dev; | 1326 | rtd->dev->parent = rtd->card->dev; |
1346 | rtd->dev->release = rtd_release; | 1327 | rtd->dev->release = rtd_release; |
1347 | rtd->dev->init_name = name; | 1328 | rtd->dev->init_name = name; |
1348 | dev_set_drvdata(rtd->dev, rtd); | 1329 | dev_set_drvdata(rtd->dev, rtd); |
@@ -1355,7 +1336,7 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1355 | if (ret < 0) { | 1336 | if (ret < 0) { |
1356 | /* calling put_device() here to free the rtd->dev */ | 1337 | /* calling put_device() here to free the rtd->dev */ |
1357 | put_device(rtd->dev); | 1338 | put_device(rtd->dev); |
1358 | dev_err(card->dev, | 1339 | dev_err(rtd->card->dev, |
1359 | "ASoC: failed to register runtime device: %d\n", ret); | 1340 | "ASoC: failed to register runtime device: %d\n", ret); |
1360 | return ret; | 1341 | return ret; |
1361 | } | 1342 | } |
@@ -1364,26 +1345,15 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1364 | /* add DAPM sysfs entries for this codec */ | 1345 | /* add DAPM sysfs entries for this codec */ |
1365 | ret = snd_soc_dapm_sys_add(rtd->dev); | 1346 | ret = snd_soc_dapm_sys_add(rtd->dev); |
1366 | if (ret < 0) | 1347 | if (ret < 0) |
1367 | dev_err(codec->dev, | 1348 | dev_err(rtd->dev, |
1368 | "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); | 1349 | "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); |
1369 | 1350 | ||
1370 | /* add codec sysfs entries */ | 1351 | /* add codec sysfs entries */ |
1371 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); | 1352 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); |
1372 | if (ret < 0) | 1353 | if (ret < 0) |
1373 | dev_err(codec->dev, | 1354 | dev_err(rtd->dev, |
1374 | "ASoC: failed to add codec sysfs files: %d\n", ret); | 1355 | "ASoC: failed to add codec sysfs files: %d\n", ret); |
1375 | 1356 | ||
1376 | #ifdef CONFIG_DEBUG_FS | ||
1377 | /* add DPCM sysfs entries */ | ||
1378 | if (!dailess && !dai_link->dynamic) | ||
1379 | goto out; | ||
1380 | |||
1381 | ret = soc_dpcm_debugfs_add(rtd); | ||
1382 | if (ret < 0) | ||
1383 | dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret); | ||
1384 | |||
1385 | out: | ||
1386 | #endif | ||
1387 | return 0; | 1357 | return 0; |
1388 | } | 1358 | } |
1389 | 1359 | ||
@@ -1392,9 +1362,8 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1392 | { | 1362 | { |
1393 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1363 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1394 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1364 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1395 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1396 | struct snd_soc_platform *platform = rtd->platform; | 1365 | struct snd_soc_platform *platform = rtd->platform; |
1397 | int ret; | 1366 | int i, ret; |
1398 | 1367 | ||
1399 | /* probe the CPU-side component, if it is a CODEC */ | 1368 | /* probe the CPU-side component, if it is a CODEC */ |
1400 | if (cpu_dai->codec && | 1369 | if (cpu_dai->codec && |
@@ -1405,12 +1374,14 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1405 | return ret; | 1374 | return ret; |
1406 | } | 1375 | } |
1407 | 1376 | ||
1408 | /* probe the CODEC-side component */ | 1377 | /* probe the CODEC-side components */ |
1409 | if (!codec_dai->codec->probed && | 1378 | for (i = 0; i < rtd->num_codecs; i++) { |
1410 | codec_dai->codec->driver->probe_order == order) { | 1379 | if (!rtd->codec_dais[i]->codec->probed && |
1411 | ret = soc_probe_codec(card, codec_dai->codec); | 1380 | rtd->codec_dais[i]->codec->driver->probe_order == order) { |
1412 | if (ret < 0) | 1381 | ret = soc_probe_codec(card, rtd->codec_dais[i]->codec); |
1413 | return ret; | 1382 | if (ret < 0) |
1383 | return ret; | ||
1384 | } | ||
1414 | } | 1385 | } |
1415 | 1386 | ||
1416 | /* probe the platform */ | 1387 | /* probe the platform */ |
@@ -1450,12 +1421,16 @@ static int soc_probe_codec_dai(struct snd_soc_card *card, | |||
1450 | 1421 | ||
1451 | static int soc_link_dai_widgets(struct snd_soc_card *card, | 1422 | static int soc_link_dai_widgets(struct snd_soc_card *card, |
1452 | struct snd_soc_dai_link *dai_link, | 1423 | struct snd_soc_dai_link *dai_link, |
1453 | struct snd_soc_dai *cpu_dai, | 1424 | struct snd_soc_pcm_runtime *rtd) |
1454 | struct snd_soc_dai *codec_dai) | ||
1455 | { | 1425 | { |
1426 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1427 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1456 | struct snd_soc_dapm_widget *play_w, *capture_w; | 1428 | struct snd_soc_dapm_widget *play_w, *capture_w; |
1457 | int ret; | 1429 | int ret; |
1458 | 1430 | ||
1431 | if (rtd->num_codecs > 1) | ||
1432 | dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n"); | ||
1433 | |||
1459 | /* link the DAI widgets */ | 1434 | /* link the DAI widgets */ |
1460 | play_w = codec_dai->playback_widget; | 1435 | play_w = codec_dai->playback_widget; |
1461 | capture_w = cpu_dai->capture_widget; | 1436 | capture_w = cpu_dai->capture_widget; |
@@ -1488,19 +1463,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1488 | { | 1463 | { |
1489 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1464 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1490 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1465 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1491 | struct snd_soc_codec *codec = rtd->codec; | ||
1492 | struct snd_soc_platform *platform = rtd->platform; | 1466 | struct snd_soc_platform *platform = rtd->platform; |
1493 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1494 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1467 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1495 | int ret; | 1468 | int i, ret; |
1496 | 1469 | ||
1497 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1470 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
1498 | card->name, num, order); | 1471 | card->name, num, order); |
1499 | 1472 | ||
1500 | /* config components */ | 1473 | /* config components */ |
1501 | cpu_dai->platform = platform; | 1474 | cpu_dai->platform = platform; |
1502 | codec_dai->card = card; | ||
1503 | cpu_dai->card = card; | 1475 | cpu_dai->card = card; |
1476 | for (i = 0; i < rtd->num_codecs; i++) | ||
1477 | rtd->codec_dais[i]->card = card; | ||
1504 | 1478 | ||
1505 | /* set default power off timeout */ | 1479 | /* set default power off timeout */ |
1506 | rtd->pmdown_time = pmdown_time; | 1480 | rtd->pmdown_time = pmdown_time; |
@@ -1509,11 +1483,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1509 | if (!cpu_dai->probed && | 1483 | if (!cpu_dai->probed && |
1510 | cpu_dai->driver->probe_order == order) { | 1484 | cpu_dai->driver->probe_order == order) { |
1511 | if (!cpu_dai->codec) { | 1485 | if (!cpu_dai->codec) { |
1512 | cpu_dai->dapm.card = card; | ||
1513 | if (!try_module_get(cpu_dai->dev->driver->owner)) | 1486 | if (!try_module_get(cpu_dai->dev->driver->owner)) |
1514 | return -ENODEV; | 1487 | return -ENODEV; |
1515 | |||
1516 | list_add(&cpu_dai->dapm.list, &card->dapm_list); | ||
1517 | } | 1488 | } |
1518 | 1489 | ||
1519 | if (cpu_dai->driver->probe) { | 1490 | if (cpu_dai->driver->probe) { |
@@ -1530,18 +1501,43 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1530 | } | 1501 | } |
1531 | 1502 | ||
1532 | /* probe the CODEC DAI */ | 1503 | /* probe the CODEC DAI */ |
1533 | ret = soc_probe_codec_dai(card, codec_dai, order); | 1504 | for (i = 0; i < rtd->num_codecs; i++) { |
1534 | if (ret) | 1505 | ret = soc_probe_codec_dai(card, rtd->codec_dais[i], order); |
1535 | return ret; | 1506 | if (ret) |
1507 | return ret; | ||
1508 | } | ||
1536 | 1509 | ||
1537 | /* complete DAI probe during last probe */ | 1510 | /* complete DAI probe during last probe */ |
1538 | if (order != SND_SOC_COMP_ORDER_LAST) | 1511 | if (order != SND_SOC_COMP_ORDER_LAST) |
1539 | return 0; | 1512 | return 0; |
1540 | 1513 | ||
1541 | ret = soc_post_component_init(card, codec, num, 0); | 1514 | /* do machine specific initialization */ |
1515 | if (dai_link->init) { | ||
1516 | ret = dai_link->init(rtd); | ||
1517 | if (ret < 0) { | ||
1518 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", | ||
1519 | dai_link->name, ret); | ||
1520 | return ret; | ||
1521 | } | ||
1522 | } | ||
1523 | |||
1524 | ret = soc_post_component_init(rtd, dai_link->name); | ||
1542 | if (ret) | 1525 | if (ret) |
1543 | return ret; | 1526 | return ret; |
1544 | 1527 | ||
1528 | #ifdef CONFIG_DEBUG_FS | ||
1529 | /* add DPCM sysfs entries */ | ||
1530 | if (dai_link->dynamic) { | ||
1531 | ret = soc_dpcm_debugfs_add(rtd); | ||
1532 | if (ret < 0) { | ||
1533 | dev_err(rtd->dev, | ||
1534 | "ASoC: failed to add dpcm sysfs entries: %d\n", | ||
1535 | ret); | ||
1536 | return ret; | ||
1537 | } | ||
1538 | } | ||
1539 | #endif | ||
1540 | |||
1545 | ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); | 1541 | ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); |
1546 | if (ret < 0) | 1542 | if (ret < 0) |
1547 | dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", | 1543 | dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", |
@@ -1570,16 +1566,18 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1570 | codec2codec_close_delayed_work); | 1566 | codec2codec_close_delayed_work); |
1571 | 1567 | ||
1572 | /* link the DAI widgets */ | 1568 | /* link the DAI widgets */ |
1573 | ret = soc_link_dai_widgets(card, dai_link, | 1569 | ret = soc_link_dai_widgets(card, dai_link, rtd); |
1574 | cpu_dai, codec_dai); | ||
1575 | if (ret) | 1570 | if (ret) |
1576 | return ret; | 1571 | return ret; |
1577 | } | 1572 | } |
1578 | } | 1573 | } |
1579 | 1574 | ||
1580 | /* add platform data for AC97 devices */ | 1575 | /* add platform data for AC97 devices */ |
1581 | if (rtd->codec_dai->driver->ac97_control) | 1576 | for (i = 0; i < rtd->num_codecs; i++) { |
1582 | snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); | 1577 | if (rtd->codec_dais[i]->driver->ac97_control) |
1578 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
1579 | rtd->cpu_dai->ac97_pdata); | ||
1580 | } | ||
1583 | 1581 | ||
1584 | return 0; | 1582 | return 0; |
1585 | } | 1583 | } |
@@ -1617,11 +1615,6 @@ static int soc_register_ac97_codec(struct snd_soc_codec *codec, | |||
1617 | return 0; | 1615 | return 0; |
1618 | } | 1616 | } |
1619 | 1617 | ||
1620 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1621 | { | ||
1622 | return soc_register_ac97_codec(rtd->codec, rtd->codec_dai); | ||
1623 | } | ||
1624 | |||
1625 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | 1618 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) |
1626 | { | 1619 | { |
1627 | if (codec->ac97_registered) { | 1620 | if (codec->ac97_registered) { |
@@ -1630,74 +1623,77 @@ static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | |||
1630 | } | 1623 | } |
1631 | } | 1624 | } |
1632 | 1625 | ||
1633 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | 1626 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) |
1634 | { | 1627 | { |
1635 | soc_unregister_ac97_codec(rtd->codec); | 1628 | int i, ret; |
1636 | } | ||
1637 | #endif | ||
1638 | 1629 | ||
1639 | static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card, | 1630 | for (i = 0; i < rtd->num_codecs; i++) { |
1640 | int num) | 1631 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
1641 | { | ||
1642 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1643 | struct snd_soc_codec *codec; | ||
1644 | 1632 | ||
1645 | /* find CODEC from registered CODECs */ | 1633 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); |
1646 | list_for_each_entry(codec, &codec_list, list) { | 1634 | if (ret) { |
1647 | if (aux_dev->codec_of_node && | 1635 | while (--i >= 0) |
1648 | (codec->dev->of_node != aux_dev->codec_of_node)) | 1636 | soc_unregister_ac97_codec(codec_dai->codec); |
1649 | continue; | 1637 | return ret; |
1650 | if (aux_dev->codec_name && strcmp(codec->name, aux_dev->codec_name)) | 1638 | } |
1651 | continue; | ||
1652 | return codec; | ||
1653 | } | 1639 | } |
1654 | 1640 | ||
1655 | return NULL; | 1641 | return 0; |
1656 | } | 1642 | } |
1657 | 1643 | ||
1658 | static int soc_check_aux_dev(struct snd_soc_card *card, int num) | 1644 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) |
1659 | { | 1645 | { |
1660 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1646 | int i; |
1661 | const char *codecname = aux_dev->codec_name; | ||
1662 | struct snd_soc_codec *codec = soc_find_matching_codec(card, num); | ||
1663 | |||
1664 | if (codec) | ||
1665 | return 0; | ||
1666 | if (aux_dev->codec_of_node) | ||
1667 | codecname = of_node_full_name(aux_dev->codec_of_node); | ||
1668 | 1647 | ||
1669 | dev_err(card->dev, "ASoC: %s not registered\n", codecname); | 1648 | for (i = 0; i < rtd->num_codecs; i++) |
1670 | return -EPROBE_DEFER; | 1649 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); |
1671 | } | 1650 | } |
1651 | #endif | ||
1672 | 1652 | ||
1673 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | 1653 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) |
1674 | { | 1654 | { |
1655 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1675 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1656 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1676 | const char *codecname = aux_dev->codec_name; | 1657 | const char *codecname = aux_dev->codec_name; |
1677 | int ret = -ENODEV; | ||
1678 | struct snd_soc_codec *codec = soc_find_matching_codec(card, num); | ||
1679 | 1658 | ||
1680 | if (!codec) { | 1659 | rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname); |
1660 | if (!rtd->codec) { | ||
1681 | if (aux_dev->codec_of_node) | 1661 | if (aux_dev->codec_of_node) |
1682 | codecname = of_node_full_name(aux_dev->codec_of_node); | 1662 | codecname = of_node_full_name(aux_dev->codec_of_node); |
1683 | 1663 | ||
1684 | /* codec not found */ | 1664 | dev_err(card->dev, "ASoC: %s not registered\n", codecname); |
1685 | dev_err(card->dev, "ASoC: codec %s not found", codecname); | ||
1686 | return -EPROBE_DEFER; | 1665 | return -EPROBE_DEFER; |
1687 | } | 1666 | } |
1688 | 1667 | ||
1689 | if (codec->probed) { | 1668 | return 0; |
1690 | dev_err(codec->dev, "ASoC: codec already probed"); | 1669 | } |
1670 | |||
1671 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | ||
1672 | { | ||
1673 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1674 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1675 | int ret; | ||
1676 | |||
1677 | if (rtd->codec->probed) { | ||
1678 | dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); | ||
1691 | return -EBUSY; | 1679 | return -EBUSY; |
1692 | } | 1680 | } |
1693 | 1681 | ||
1694 | ret = soc_probe_codec(card, codec); | 1682 | ret = soc_probe_codec(card, rtd->codec); |
1695 | if (ret < 0) | 1683 | if (ret < 0) |
1696 | return ret; | 1684 | return ret; |
1697 | 1685 | ||
1698 | ret = soc_post_component_init(card, codec, num, 1); | 1686 | /* do machine specific initialization */ |
1687 | if (aux_dev->init) { | ||
1688 | ret = aux_dev->init(&rtd->codec->dapm); | ||
1689 | if (ret < 0) { | ||
1690 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", | ||
1691 | aux_dev->name, ret); | ||
1692 | return ret; | ||
1693 | } | ||
1694 | } | ||
1699 | 1695 | ||
1700 | return ret; | 1696 | return soc_post_component_init(rtd, aux_dev->name); |
1701 | } | 1697 | } |
1702 | 1698 | ||
1703 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | 1699 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) |
@@ -1749,9 +1745,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1749 | goto base_error; | 1745 | goto base_error; |
1750 | } | 1746 | } |
1751 | 1747 | ||
1752 | /* check aux_devs too */ | 1748 | /* bind aux_devs too */ |
1753 | for (i = 0; i < card->num_aux_devs; i++) { | 1749 | for (i = 0; i < card->num_aux_devs; i++) { |
1754 | ret = soc_check_aux_dev(card, i); | 1750 | ret = soc_bind_aux_dev(card, i); |
1755 | if (ret != 0) | 1751 | if (ret != 0) |
1756 | goto base_error; | 1752 | goto base_error; |
1757 | } | 1753 | } |
@@ -1849,16 +1845,23 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1849 | card->num_dapm_routes); | 1845 | card->num_dapm_routes); |
1850 | 1846 | ||
1851 | for (i = 0; i < card->num_links; i++) { | 1847 | for (i = 0; i < card->num_links; i++) { |
1848 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1852 | dai_link = &card->dai_link[i]; | 1849 | dai_link = &card->dai_link[i]; |
1853 | dai_fmt = dai_link->dai_fmt; | 1850 | dai_fmt = dai_link->dai_fmt; |
1854 | 1851 | ||
1855 | if (dai_fmt) { | 1852 | if (dai_fmt) { |
1856 | ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai, | 1853 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
1857 | dai_fmt); | 1854 | int j; |
1858 | if (ret != 0 && ret != -ENOTSUPP) | 1855 | |
1859 | dev_warn(card->rtd[i].codec_dai->dev, | 1856 | for (j = 0; j < rtd->num_codecs; j++) { |
1860 | "ASoC: Failed to set DAI format: %d\n", | 1857 | struct snd_soc_dai *codec_dai = codec_dais[j]; |
1861 | ret); | 1858 | |
1859 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); | ||
1860 | if (ret != 0 && ret != -ENOTSUPP) | ||
1861 | dev_warn(codec_dai->dev, | ||
1862 | "ASoC: Failed to set DAI format: %d\n", | ||
1863 | ret); | ||
1864 | } | ||
1862 | } | 1865 | } |
1863 | 1866 | ||
1864 | /* If this is a regular CPU link there will be a platform */ | 1867 | /* If this is a regular CPU link there will be a platform */ |
@@ -1927,8 +1930,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1927 | } | 1930 | } |
1928 | 1931 | ||
1929 | if (card->fully_routed) | 1932 | if (card->fully_routed) |
1930 | list_for_each_entry(codec, &card->codec_dev_list, card_list) | 1933 | snd_soc_dapm_auto_nc_pins(card); |
1931 | snd_soc_dapm_auto_nc_codec_pins(codec); | ||
1932 | 1934 | ||
1933 | snd_soc_dapm_new_widgets(card); | 1935 | snd_soc_dapm_new_widgets(card); |
1934 | 1936 | ||
@@ -2058,10 +2060,15 @@ int snd_soc_poweroff(struct device *dev) | |||
2058 | 2060 | ||
2059 | /* deactivate pins to sleep state */ | 2061 | /* deactivate pins to sleep state */ |
2060 | for (i = 0; i < card->num_rtd; i++) { | 2062 | for (i = 0; i < card->num_rtd; i++) { |
2061 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 2063 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
2062 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 2064 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2063 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 2065 | int j; |
2066 | |||
2064 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 2067 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
2068 | for (j = 0; j < rtd->num_codecs; j++) { | ||
2069 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
2070 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
2071 | } | ||
2065 | } | 2072 | } |
2066 | 2073 | ||
2067 | return 0; | 2074 | return 0; |
@@ -2387,6 +2394,25 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | |||
2387 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | 2394 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); |
2388 | 2395 | ||
2389 | /** | 2396 | /** |
2397 | * snd_soc_add_component_controls - Add an array of controls to a component. | ||
2398 | * | ||
2399 | * @component: Component to add controls to | ||
2400 | * @controls: Array of controls to add | ||
2401 | * @num_controls: Number of elements in the array | ||
2402 | * | ||
2403 | * Return: 0 for success, else error. | ||
2404 | */ | ||
2405 | int snd_soc_add_component_controls(struct snd_soc_component *component, | ||
2406 | const struct snd_kcontrol_new *controls, unsigned int num_controls) | ||
2407 | { | ||
2408 | struct snd_card *card = component->card->snd_card; | ||
2409 | |||
2410 | return snd_soc_add_controls(card, component->dev, controls, | ||
2411 | num_controls, component->name_prefix, component); | ||
2412 | } | ||
2413 | EXPORT_SYMBOL_GPL(snd_soc_add_component_controls); | ||
2414 | |||
2415 | /** | ||
2390 | * snd_soc_add_codec_controls - add an array of controls to a codec. | 2416 | * snd_soc_add_codec_controls - add an array of controls to a codec. |
2391 | * Convenience function to add a list of controls. Many codecs were | 2417 | * Convenience function to add a list of controls. Many codecs were |
2392 | * duplicating this code. | 2418 | * duplicating this code. |
@@ -2398,12 +2424,10 @@ EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | |||
2398 | * Return 0 for success, else error. | 2424 | * Return 0 for success, else error. |
2399 | */ | 2425 | */ |
2400 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, | 2426 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, |
2401 | const struct snd_kcontrol_new *controls, int num_controls) | 2427 | const struct snd_kcontrol_new *controls, unsigned int num_controls) |
2402 | { | 2428 | { |
2403 | struct snd_card *card = codec->card->snd_card; | 2429 | return snd_soc_add_component_controls(&codec->component, controls, |
2404 | 2430 | num_controls); | |
2405 | return snd_soc_add_controls(card, codec->dev, controls, num_controls, | ||
2406 | codec->name_prefix, &codec->component); | ||
2407 | } | 2431 | } |
2408 | EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); | 2432 | EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); |
2409 | 2433 | ||
@@ -2418,12 +2442,10 @@ EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); | |||
2418 | * Return 0 for success, else error. | 2442 | * Return 0 for success, else error. |
2419 | */ | 2443 | */ |
2420 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, | 2444 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, |
2421 | const struct snd_kcontrol_new *controls, int num_controls) | 2445 | const struct snd_kcontrol_new *controls, unsigned int num_controls) |
2422 | { | 2446 | { |
2423 | struct snd_card *card = platform->card->snd_card; | 2447 | return snd_soc_add_component_controls(&platform->component, controls, |
2424 | 2448 | num_controls); | |
2425 | return snd_soc_add_controls(card, platform->dev, controls, num_controls, | ||
2426 | NULL, &platform->component); | ||
2427 | } | 2449 | } |
2428 | EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls); | 2450 | EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls); |
2429 | 2451 | ||
@@ -3095,7 +3117,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | |||
3095 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | 3117 | int snd_soc_limit_volume(struct snd_soc_codec *codec, |
3096 | const char *name, int max) | 3118 | const char *name, int max) |
3097 | { | 3119 | { |
3098 | struct snd_card *card = codec->card->snd_card; | 3120 | struct snd_card *card = codec->component.card->snd_card; |
3099 | struct snd_kcontrol *kctl; | 3121 | struct snd_kcontrol *kctl; |
3100 | struct soc_mixer_control *mc; | 3122 | struct soc_mixer_control *mc; |
3101 | int found = 0; | 3123 | int found = 0; |
@@ -3267,6 +3289,27 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | |||
3267 | } | 3289 | } |
3268 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | 3290 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); |
3269 | 3291 | ||
3292 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
3293 | unsigned int size, unsigned int __user *tlv) | ||
3294 | { | ||
3295 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3296 | unsigned int count = size < params->max ? size : params->max; | ||
3297 | int ret = -ENXIO; | ||
3298 | |||
3299 | switch (op_flag) { | ||
3300 | case SNDRV_CTL_TLV_OP_READ: | ||
3301 | if (params->get) | ||
3302 | ret = params->get(tlv, count); | ||
3303 | break; | ||
3304 | case SNDRV_CTL_TLV_OP_WRITE: | ||
3305 | if (params->put) | ||
3306 | ret = params->put(tlv, count); | ||
3307 | break; | ||
3308 | } | ||
3309 | return ret; | ||
3310 | } | ||
3311 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
3312 | |||
3270 | /** | 3313 | /** |
3271 | * snd_soc_info_xr_sx - signed multi register info callback | 3314 | * snd_soc_info_xr_sx - signed multi register info callback |
3272 | * @kcontrol: mreg control | 3315 | * @kcontrol: mreg control |
@@ -3641,6 +3684,9 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | |||
3641 | else | 3684 | else |
3642 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | 3685 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); |
3643 | 3686 | ||
3687 | dai->tx_mask = tx_mask; | ||
3688 | dai->rx_mask = rx_mask; | ||
3689 | |||
3644 | if (dai->driver && dai->driver->ops->set_tdm_slot) | 3690 | if (dai->driver && dai->driver->ops->set_tdm_slot) |
3645 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | 3691 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, |
3646 | slots, slot_width); | 3692 | slots, slot_width); |
@@ -3713,6 +3759,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | |||
3713 | } | 3759 | } |
3714 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 3760 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
3715 | 3761 | ||
3762 | static int snd_soc_init_multicodec(struct snd_soc_card *card, | ||
3763 | struct snd_soc_dai_link *dai_link) | ||
3764 | { | ||
3765 | /* Legacy codec/codec_dai link is a single entry in multicodec */ | ||
3766 | if (dai_link->codec_name || dai_link->codec_of_node || | ||
3767 | dai_link->codec_dai_name) { | ||
3768 | dai_link->num_codecs = 1; | ||
3769 | |||
3770 | dai_link->codecs = devm_kzalloc(card->dev, | ||
3771 | sizeof(struct snd_soc_dai_link_component), | ||
3772 | GFP_KERNEL); | ||
3773 | if (!dai_link->codecs) | ||
3774 | return -ENOMEM; | ||
3775 | |||
3776 | dai_link->codecs[0].name = dai_link->codec_name; | ||
3777 | dai_link->codecs[0].of_node = dai_link->codec_of_node; | ||
3778 | dai_link->codecs[0].dai_name = dai_link->codec_dai_name; | ||
3779 | } | ||
3780 | |||
3781 | if (!dai_link->codecs) { | ||
3782 | dev_err(card->dev, "ASoC: DAI link has no CODECs\n"); | ||
3783 | return -EINVAL; | ||
3784 | } | ||
3785 | |||
3786 | return 0; | ||
3787 | } | ||
3788 | |||
3716 | /** | 3789 | /** |
3717 | * snd_soc_register_card - Register a card with the ASoC core | 3790 | * snd_soc_register_card - Register a card with the ASoC core |
3718 | * | 3791 | * |
@@ -3721,7 +3794,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | |||
3721 | */ | 3794 | */ |
3722 | int snd_soc_register_card(struct snd_soc_card *card) | 3795 | int snd_soc_register_card(struct snd_soc_card *card) |
3723 | { | 3796 | { |
3724 | int i, ret; | 3797 | int i, j, ret; |
3725 | 3798 | ||
3726 | if (!card->name || !card->dev) | 3799 | if (!card->name || !card->dev) |
3727 | return -EINVAL; | 3800 | return -EINVAL; |
@@ -3729,22 +3802,29 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3729 | for (i = 0; i < card->num_links; i++) { | 3802 | for (i = 0; i < card->num_links; i++) { |
3730 | struct snd_soc_dai_link *link = &card->dai_link[i]; | 3803 | struct snd_soc_dai_link *link = &card->dai_link[i]; |
3731 | 3804 | ||
3732 | /* | 3805 | ret = snd_soc_init_multicodec(card, link); |
3733 | * Codec must be specified by 1 of name or OF node, | 3806 | if (ret) { |
3734 | * not both or neither. | 3807 | dev_err(card->dev, "ASoC: failed to init multicodec\n"); |
3735 | */ | 3808 | return ret; |
3736 | if (!!link->codec_name == !!link->codec_of_node) { | ||
3737 | dev_err(card->dev, | ||
3738 | "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
3739 | link->name); | ||
3740 | return -EINVAL; | ||
3741 | } | 3809 | } |
3742 | /* Codec DAI name must be specified */ | 3810 | |
3743 | if (!link->codec_dai_name) { | 3811 | for (j = 0; j < link->num_codecs; j++) { |
3744 | dev_err(card->dev, | 3812 | /* |
3745 | "ASoC: codec_dai_name not set for %s\n", | 3813 | * Codec must be specified by 1 of name or OF node, |
3746 | link->name); | 3814 | * not both or neither. |
3747 | return -EINVAL; | 3815 | */ |
3816 | if (!!link->codecs[j].name == | ||
3817 | !!link->codecs[j].of_node) { | ||
3818 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
3819 | link->name); | ||
3820 | return -EINVAL; | ||
3821 | } | ||
3822 | /* Codec DAI name must be specified */ | ||
3823 | if (!link->codecs[j].dai_name) { | ||
3824 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", | ||
3825 | link->name); | ||
3826 | return -EINVAL; | ||
3827 | } | ||
3748 | } | 3828 | } |
3749 | 3829 | ||
3750 | /* | 3830 | /* |
@@ -3797,8 +3877,19 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3797 | card->num_rtd = 0; | 3877 | card->num_rtd = 0; |
3798 | card->rtd_aux = &card->rtd[card->num_links]; | 3878 | card->rtd_aux = &card->rtd[card->num_links]; |
3799 | 3879 | ||
3800 | for (i = 0; i < card->num_links; i++) | 3880 | for (i = 0; i < card->num_links; i++) { |
3881 | card->rtd[i].card = card; | ||
3801 | card->rtd[i].dai_link = &card->dai_link[i]; | 3882 | card->rtd[i].dai_link = &card->dai_link[i]; |
3883 | card->rtd[i].codec_dais = devm_kzalloc(card->dev, | ||
3884 | sizeof(struct snd_soc_dai *) * | ||
3885 | (card->rtd[i].dai_link->num_codecs), | ||
3886 | GFP_KERNEL); | ||
3887 | if (card->rtd[i].codec_dais == NULL) | ||
3888 | return -ENOMEM; | ||
3889 | } | ||
3890 | |||
3891 | for (i = 0; i < card->num_aux_devs; i++) | ||
3892 | card->rtd_aux[i].card = card; | ||
3802 | 3893 | ||
3803 | INIT_LIST_HEAD(&card->dapm_dirty); | 3894 | INIT_LIST_HEAD(&card->dapm_dirty); |
3804 | card->instantiated = 0; | 3895 | card->instantiated = 0; |
@@ -3811,10 +3902,16 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3811 | 3902 | ||
3812 | /* deactivate pins to sleep state */ | 3903 | /* deactivate pins to sleep state */ |
3813 | for (i = 0; i < card->num_rtd; i++) { | 3904 | for (i = 0; i < card->num_rtd; i++) { |
3814 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 3905 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
3815 | struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; | 3906 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
3816 | if (!codec_dai->active) | 3907 | int j; |
3817 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 3908 | |
3909 | for (j = 0; j < rtd->num_codecs; j++) { | ||
3910 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
3911 | if (!codec_dai->active) | ||
3912 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
3913 | } | ||
3914 | |||
3818 | if (!cpu_dai->active) | 3915 | if (!cpu_dai->active) |
3819 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 3916 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
3820 | } | 3917 | } |
@@ -3921,16 +4018,14 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) | |||
3921 | * snd_soc_register_dais - Register a DAI with the ASoC core | 4018 | * snd_soc_register_dais - Register a DAI with the ASoC core |
3922 | * | 4019 | * |
3923 | * @component: The component the DAIs are registered for | 4020 | * @component: The component the DAIs are registered for |
3924 | * @codec: The CODEC that the DAIs are registered for, NULL if the component is | ||
3925 | * not a CODEC. | ||
3926 | * @dai_drv: DAI driver to use for the DAIs | 4021 | * @dai_drv: DAI driver to use for the DAIs |
3927 | * @count: Number of DAIs | 4022 | * @count: Number of DAIs |
3928 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the | 4023 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the |
3929 | * parent's name. | 4024 | * parent's name. |
3930 | */ | 4025 | */ |
3931 | static int snd_soc_register_dais(struct snd_soc_component *component, | 4026 | static int snd_soc_register_dais(struct snd_soc_component *component, |
3932 | struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, | 4027 | struct snd_soc_dai_driver *dai_drv, size_t count, |
3933 | size_t count, bool legacy_dai_naming) | 4028 | bool legacy_dai_naming) |
3934 | { | 4029 | { |
3935 | struct device *dev = component->dev; | 4030 | struct device *dev = component->dev; |
3936 | struct snd_soc_dai *dai; | 4031 | struct snd_soc_dai *dai; |
@@ -3939,6 +4034,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
3939 | 4034 | ||
3940 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); | 4035 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); |
3941 | 4036 | ||
4037 | component->dai_drv = dai_drv; | ||
4038 | component->num_dai = count; | ||
4039 | |||
3942 | for (i = 0; i < count; i++) { | 4040 | for (i = 0; i < count; i++) { |
3943 | 4041 | ||
3944 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); | 4042 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); |
@@ -3971,16 +4069,11 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
3971 | } | 4069 | } |
3972 | 4070 | ||
3973 | dai->component = component; | 4071 | dai->component = component; |
3974 | dai->codec = codec; | ||
3975 | dai->dev = dev; | 4072 | dai->dev = dev; |
3976 | dai->driver = &dai_drv[i]; | 4073 | dai->driver = &dai_drv[i]; |
3977 | dai->dapm.dev = dev; | ||
3978 | if (!dai->driver->ops) | 4074 | if (!dai->driver->ops) |
3979 | dai->driver->ops = &null_dai_ops; | 4075 | dai->driver->ops = &null_dai_ops; |
3980 | 4076 | ||
3981 | if (!dai->codec) | ||
3982 | dai->dapm.idle_bias_off = 1; | ||
3983 | |||
3984 | list_add(&dai->list, &component->dai_list); | 4077 | list_add(&dai->list, &component->dai_list); |
3985 | 4078 | ||
3986 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); | 4079 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); |
@@ -3994,60 +4087,82 @@ err: | |||
3994 | return ret; | 4087 | return ret; |
3995 | } | 4088 | } |
3996 | 4089 | ||
3997 | /** | 4090 | static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, |
3998 | * snd_soc_register_component - Register a component with the ASoC core | 4091 | enum snd_soc_dapm_type type, int subseq) |
3999 | * | ||
4000 | */ | ||
4001 | static int | ||
4002 | __snd_soc_register_component(struct device *dev, | ||
4003 | struct snd_soc_component *cmpnt, | ||
4004 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4005 | struct snd_soc_codec *codec, | ||
4006 | struct snd_soc_dai_driver *dai_drv, | ||
4007 | int num_dai, bool allow_single_dai) | ||
4008 | { | 4092 | { |
4009 | int ret; | 4093 | struct snd_soc_component *component = dapm->component; |
4010 | 4094 | ||
4011 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | 4095 | component->driver->seq_notifier(component, type, subseq); |
4096 | } | ||
4012 | 4097 | ||
4013 | if (!cmpnt) { | 4098 | static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, |
4014 | dev_err(dev, "ASoC: Failed to connecting component\n"); | 4099 | int event) |
4015 | return -ENOMEM; | 4100 | { |
4016 | } | 4101 | struct snd_soc_component *component = dapm->component; |
4017 | 4102 | ||
4018 | mutex_init(&cmpnt->io_mutex); | 4103 | return component->driver->stream_event(component, event); |
4104 | } | ||
4105 | |||
4106 | static int snd_soc_component_initialize(struct snd_soc_component *component, | ||
4107 | const struct snd_soc_component_driver *driver, struct device *dev) | ||
4108 | { | ||
4109 | struct snd_soc_dapm_context *dapm; | ||
4019 | 4110 | ||
4020 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | 4111 | component->name = fmt_single_name(dev, &component->id); |
4021 | if (!cmpnt->name) { | 4112 | if (!component->name) { |
4022 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | 4113 | dev_err(dev, "ASoC: Failed to allocate name\n"); |
4023 | return -ENOMEM; | 4114 | return -ENOMEM; |
4024 | } | 4115 | } |
4025 | 4116 | ||
4026 | cmpnt->dev = dev; | 4117 | component->dev = dev; |
4027 | cmpnt->driver = cmpnt_drv; | 4118 | component->driver = driver; |
4028 | cmpnt->dai_drv = dai_drv; | ||
4029 | cmpnt->num_dai = num_dai; | ||
4030 | INIT_LIST_HEAD(&cmpnt->dai_list); | ||
4031 | 4119 | ||
4032 | ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, | 4120 | if (!component->dapm_ptr) |
4033 | allow_single_dai); | 4121 | component->dapm_ptr = &component->dapm; |
4034 | if (ret < 0) { | 4122 | |
4035 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4123 | dapm = component->dapm_ptr; |
4036 | goto error_component_name; | 4124 | dapm->dev = dev; |
4037 | } | 4125 | dapm->component = component; |
4126 | dapm->bias_level = SND_SOC_BIAS_OFF; | ||
4127 | if (driver->seq_notifier) | ||
4128 | dapm->seq_notifier = snd_soc_component_seq_notifier; | ||
4129 | if (driver->stream_event) | ||
4130 | dapm->stream_event = snd_soc_component_stream_event; | ||
4131 | |||
4132 | INIT_LIST_HEAD(&component->dai_list); | ||
4133 | mutex_init(&component->io_mutex); | ||
4038 | 4134 | ||
4135 | return 0; | ||
4136 | } | ||
4137 | |||
4138 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | ||
4139 | { | ||
4140 | list_add(&component->list, &component_list); | ||
4141 | } | ||
4142 | |||
4143 | static void snd_soc_component_add(struct snd_soc_component *component) | ||
4144 | { | ||
4039 | mutex_lock(&client_mutex); | 4145 | mutex_lock(&client_mutex); |
4040 | list_add(&cmpnt->list, &component_list); | 4146 | snd_soc_component_add_unlocked(component); |
4041 | mutex_unlock(&client_mutex); | 4147 | mutex_unlock(&client_mutex); |
4148 | } | ||
4042 | 4149 | ||
4043 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | 4150 | static void snd_soc_component_cleanup(struct snd_soc_component *component) |
4044 | 4151 | { | |
4045 | return ret; | 4152 | snd_soc_unregister_dais(component); |
4153 | kfree(component->name); | ||
4154 | } | ||
4046 | 4155 | ||
4047 | error_component_name: | 4156 | static void snd_soc_component_del_unlocked(struct snd_soc_component *component) |
4048 | kfree(cmpnt->name); | 4157 | { |
4158 | list_del(&component->list); | ||
4159 | } | ||
4049 | 4160 | ||
4050 | return ret; | 4161 | static void snd_soc_component_del(struct snd_soc_component *component) |
4162 | { | ||
4163 | mutex_lock(&client_mutex); | ||
4164 | snd_soc_component_del_unlocked(component); | ||
4165 | mutex_unlock(&client_mutex); | ||
4051 | } | 4166 | } |
4052 | 4167 | ||
4053 | int snd_soc_register_component(struct device *dev, | 4168 | int snd_soc_register_component(struct device *dev, |
@@ -4056,32 +4171,38 @@ int snd_soc_register_component(struct device *dev, | |||
4056 | int num_dai) | 4171 | int num_dai) |
4057 | { | 4172 | { |
4058 | struct snd_soc_component *cmpnt; | 4173 | struct snd_soc_component *cmpnt; |
4174 | int ret; | ||
4059 | 4175 | ||
4060 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | 4176 | cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL); |
4061 | if (!cmpnt) { | 4177 | if (!cmpnt) { |
4062 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | 4178 | dev_err(dev, "ASoC: Failed to allocate memory\n"); |
4063 | return -ENOMEM; | 4179 | return -ENOMEM; |
4064 | } | 4180 | } |
4065 | 4181 | ||
4182 | ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev); | ||
4183 | if (ret) | ||
4184 | goto err_free; | ||
4185 | |||
4066 | cmpnt->ignore_pmdown_time = true; | 4186 | cmpnt->ignore_pmdown_time = true; |
4067 | cmpnt->registered_as_component = true; | 4187 | cmpnt->registered_as_component = true; |
4068 | 4188 | ||
4069 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, | 4189 | ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true); |
4070 | dai_drv, num_dai, true); | 4190 | if (ret < 0) { |
4071 | } | 4191 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4072 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | 4192 | goto err_cleanup; |
4193 | } | ||
4073 | 4194 | ||
4074 | static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt) | 4195 | snd_soc_component_add(cmpnt); |
4075 | { | ||
4076 | snd_soc_unregister_dais(cmpnt); | ||
4077 | 4196 | ||
4078 | mutex_lock(&client_mutex); | 4197 | return 0; |
4079 | list_del(&cmpnt->list); | ||
4080 | mutex_unlock(&client_mutex); | ||
4081 | 4198 | ||
4082 | dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | 4199 | err_cleanup: |
4083 | kfree(cmpnt->name); | 4200 | snd_soc_component_cleanup(cmpnt); |
4201 | err_free: | ||
4202 | kfree(cmpnt); | ||
4203 | return ret; | ||
4084 | } | 4204 | } |
4205 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4085 | 4206 | ||
4086 | /** | 4207 | /** |
4087 | * snd_soc_unregister_component - Unregister a component from the ASoC core | 4208 | * snd_soc_unregister_component - Unregister a component from the ASoC core |
@@ -4098,7 +4219,9 @@ void snd_soc_unregister_component(struct device *dev) | |||
4098 | return; | 4219 | return; |
4099 | 4220 | ||
4100 | found: | 4221 | found: |
4101 | __snd_soc_unregister_component(cmpnt); | 4222 | snd_soc_component_del(cmpnt); |
4223 | snd_soc_component_cleanup(cmpnt); | ||
4224 | kfree(cmpnt); | ||
4102 | } | 4225 | } |
4103 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | 4226 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); |
4104 | 4227 | ||
@@ -4131,37 +4254,25 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | |||
4131 | { | 4254 | { |
4132 | int ret; | 4255 | int ret; |
4133 | 4256 | ||
4134 | /* create platform component name */ | 4257 | ret = snd_soc_component_initialize(&platform->component, |
4135 | platform->name = fmt_single_name(dev, &platform->id); | 4258 | &platform_drv->component_driver, dev); |
4136 | if (platform->name == NULL) | 4259 | if (ret) |
4137 | return -ENOMEM; | 4260 | return ret; |
4138 | 4261 | ||
4139 | platform->dev = dev; | 4262 | platform->dev = dev; |
4140 | platform->driver = platform_drv; | 4263 | platform->driver = platform_drv; |
4141 | platform->dapm.dev = dev; | ||
4142 | platform->dapm.platform = platform; | ||
4143 | platform->dapm.component = &platform->component; | ||
4144 | platform->dapm.stream_event = platform_drv->stream_event; | ||
4145 | if (platform_drv->write) | 4264 | if (platform_drv->write) |
4146 | platform->component.write = snd_soc_platform_drv_write; | 4265 | platform->component.write = snd_soc_platform_drv_write; |
4147 | if (platform_drv->read) | 4266 | if (platform_drv->read) |
4148 | platform->component.read = snd_soc_platform_drv_read; | 4267 | platform->component.read = snd_soc_platform_drv_read; |
4149 | 4268 | ||
4150 | /* register component */ | ||
4151 | ret = __snd_soc_register_component(dev, &platform->component, | ||
4152 | &platform_drv->component_driver, | ||
4153 | NULL, NULL, 0, false); | ||
4154 | if (ret < 0) { | ||
4155 | dev_err(platform->component.dev, | ||
4156 | "ASoC: Failed to register component: %d\n", ret); | ||
4157 | return ret; | ||
4158 | } | ||
4159 | |||
4160 | mutex_lock(&client_mutex); | 4269 | mutex_lock(&client_mutex); |
4270 | snd_soc_component_add_unlocked(&platform->component); | ||
4161 | list_add(&platform->list, &platform_list); | 4271 | list_add(&platform->list, &platform_list); |
4162 | mutex_unlock(&client_mutex); | 4272 | mutex_unlock(&client_mutex); |
4163 | 4273 | ||
4164 | dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name); | 4274 | dev_dbg(dev, "ASoC: Registered platform '%s'\n", |
4275 | platform->component.name); | ||
4165 | 4276 | ||
4166 | return 0; | 4277 | return 0; |
4167 | } | 4278 | } |
@@ -4198,15 +4309,16 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform); | |||
4198 | */ | 4309 | */ |
4199 | void snd_soc_remove_platform(struct snd_soc_platform *platform) | 4310 | void snd_soc_remove_platform(struct snd_soc_platform *platform) |
4200 | { | 4311 | { |
4201 | __snd_soc_unregister_component(&platform->component); | ||
4202 | 4312 | ||
4203 | mutex_lock(&client_mutex); | 4313 | mutex_lock(&client_mutex); |
4204 | list_del(&platform->list); | 4314 | list_del(&platform->list); |
4315 | snd_soc_component_del_unlocked(&platform->component); | ||
4205 | mutex_unlock(&client_mutex); | 4316 | mutex_unlock(&client_mutex); |
4206 | 4317 | ||
4318 | snd_soc_component_cleanup(&platform->component); | ||
4319 | |||
4207 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", | 4320 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", |
4208 | platform->name); | 4321 | platform->component.name); |
4209 | kfree(platform->name); | ||
4210 | } | 4322 | } |
4211 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); | 4323 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); |
4212 | 4324 | ||
@@ -4292,6 +4404,14 @@ static int snd_soc_codec_drv_read(struct snd_soc_component *component, | |||
4292 | return 0; | 4404 | return 0; |
4293 | } | 4405 | } |
4294 | 4406 | ||
4407 | static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm, | ||
4408 | enum snd_soc_bias_level level) | ||
4409 | { | ||
4410 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
4411 | |||
4412 | return codec->driver->set_bias_level(codec, level); | ||
4413 | } | ||
4414 | |||
4295 | /** | 4415 | /** |
4296 | * snd_soc_register_codec - Register a codec with the ASoC core | 4416 | * snd_soc_register_codec - Register a codec with the ASoC core |
4297 | * | 4417 | * |
@@ -4303,6 +4423,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4303 | int num_dai) | 4423 | int num_dai) |
4304 | { | 4424 | { |
4305 | struct snd_soc_codec *codec; | 4425 | struct snd_soc_codec *codec; |
4426 | struct snd_soc_dai *dai; | ||
4306 | struct regmap *regmap; | 4427 | struct regmap *regmap; |
4307 | int ret, i; | 4428 | int ret, i; |
4308 | 4429 | ||
@@ -4312,24 +4433,23 @@ int snd_soc_register_codec(struct device *dev, | |||
4312 | if (codec == NULL) | 4433 | if (codec == NULL) |
4313 | return -ENOMEM; | 4434 | return -ENOMEM; |
4314 | 4435 | ||
4315 | /* create CODEC component name */ | 4436 | codec->component.dapm_ptr = &codec->dapm; |
4316 | codec->name = fmt_single_name(dev, &codec->id); | 4437 | |
4317 | if (codec->name == NULL) { | 4438 | ret = snd_soc_component_initialize(&codec->component, |
4318 | ret = -ENOMEM; | 4439 | &codec_drv->component_driver, dev); |
4319 | goto fail_codec; | 4440 | if (ret) |
4320 | } | 4441 | goto err_free; |
4321 | 4442 | ||
4322 | if (codec_drv->write) | 4443 | if (codec_drv->write) |
4323 | codec->component.write = snd_soc_codec_drv_write; | 4444 | codec->component.write = snd_soc_codec_drv_write; |
4324 | if (codec_drv->read) | 4445 | if (codec_drv->read) |
4325 | codec->component.read = snd_soc_codec_drv_read; | 4446 | codec->component.read = snd_soc_codec_drv_read; |
4326 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4447 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4327 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
4328 | codec->dapm.dev = dev; | ||
4329 | codec->dapm.codec = codec; | 4448 | codec->dapm.codec = codec; |
4330 | codec->dapm.component = &codec->component; | 4449 | if (codec_drv->seq_notifier) |
4331 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 4450 | codec->dapm.seq_notifier = codec_drv->seq_notifier; |
4332 | codec->dapm.stream_event = codec_drv->stream_event; | 4451 | if (codec_drv->set_bias_level) |
4452 | codec->dapm.set_bias_level = snd_soc_codec_set_bias_level; | ||
4333 | codec->dev = dev; | 4453 | codec->dev = dev; |
4334 | codec->driver = codec_drv; | 4454 | codec->driver = codec_drv; |
4335 | codec->component.val_bytes = codec_drv->reg_word_size; | 4455 | codec->component.val_bytes = codec_drv->reg_word_size; |
@@ -4348,7 +4468,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4348 | dev_err(codec->dev, | 4468 | dev_err(codec->dev, |
4349 | "Failed to set cache I/O:%d\n", | 4469 | "Failed to set cache I/O:%d\n", |
4350 | ret); | 4470 | ret); |
4351 | return ret; | 4471 | goto err_cleanup; |
4352 | } | 4472 | } |
4353 | } | 4473 | } |
4354 | } | 4474 | } |
@@ -4358,29 +4478,27 @@ int snd_soc_register_codec(struct device *dev, | |||
4358 | fixup_codec_formats(&dai_drv[i].capture); | 4478 | fixup_codec_formats(&dai_drv[i].capture); |
4359 | } | 4479 | } |
4360 | 4480 | ||
4361 | mutex_lock(&client_mutex); | 4481 | ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false); |
4362 | list_add(&codec->list, &codec_list); | ||
4363 | mutex_unlock(&client_mutex); | ||
4364 | |||
4365 | /* register component */ | ||
4366 | ret = __snd_soc_register_component(dev, &codec->component, | ||
4367 | &codec_drv->component_driver, | ||
4368 | codec, dai_drv, num_dai, false); | ||
4369 | if (ret < 0) { | 4482 | if (ret < 0) { |
4370 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); | 4483 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4371 | goto fail_codec_name; | 4484 | goto err_cleanup; |
4372 | } | 4485 | } |
4373 | 4486 | ||
4374 | dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name); | 4487 | list_for_each_entry(dai, &codec->component.dai_list, list) |
4375 | return 0; | 4488 | dai->codec = codec; |
4376 | 4489 | ||
4377 | fail_codec_name: | ||
4378 | mutex_lock(&client_mutex); | 4490 | mutex_lock(&client_mutex); |
4379 | list_del(&codec->list); | 4491 | snd_soc_component_add_unlocked(&codec->component); |
4492 | list_add(&codec->list, &codec_list); | ||
4380 | mutex_unlock(&client_mutex); | 4493 | mutex_unlock(&client_mutex); |
4381 | 4494 | ||
4382 | kfree(codec->name); | 4495 | dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", |
4383 | fail_codec: | 4496 | codec->component.name); |
4497 | return 0; | ||
4498 | |||
4499 | err_cleanup: | ||
4500 | snd_soc_component_cleanup(&codec->component); | ||
4501 | err_free: | ||
4384 | kfree(codec); | 4502 | kfree(codec); |
4385 | return ret; | 4503 | return ret; |
4386 | } | 4504 | } |
@@ -4402,16 +4520,17 @@ void snd_soc_unregister_codec(struct device *dev) | |||
4402 | return; | 4520 | return; |
4403 | 4521 | ||
4404 | found: | 4522 | found: |
4405 | __snd_soc_unregister_component(&codec->component); | ||
4406 | 4523 | ||
4407 | mutex_lock(&client_mutex); | 4524 | mutex_lock(&client_mutex); |
4408 | list_del(&codec->list); | 4525 | list_del(&codec->list); |
4526 | snd_soc_component_del_unlocked(&codec->component); | ||
4409 | mutex_unlock(&client_mutex); | 4527 | mutex_unlock(&client_mutex); |
4410 | 4528 | ||
4411 | dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name); | 4529 | dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", |
4530 | codec->component.name); | ||
4412 | 4531 | ||
4532 | snd_soc_component_cleanup(&codec->component); | ||
4413 | snd_soc_cache_exit(codec); | 4533 | snd_soc_cache_exit(codec); |
4414 | kfree(codec->name); | ||
4415 | kfree(codec); | 4534 | kfree(codec); |
4416 | } | 4535 | } |
4417 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 4536 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
@@ -4420,9 +4539,16 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | |||
4420 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, | 4539 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, |
4421 | const char *propname) | 4540 | const char *propname) |
4422 | { | 4541 | { |
4423 | struct device_node *np = card->dev->of_node; | 4542 | struct device_node *np; |
4424 | int ret; | 4543 | int ret; |
4425 | 4544 | ||
4545 | if (!card->dev) { | ||
4546 | pr_err("card->dev is not set before calling %s\n", __func__); | ||
4547 | return -EINVAL; | ||
4548 | } | ||
4549 | |||
4550 | np = card->dev->of_node; | ||
4551 | |||
4426 | ret = of_property_read_string_index(np, propname, 0, &card->name); | 4552 | ret = of_property_read_string_index(np, propname, 0, &card->name); |
4427 | /* | 4553 | /* |
4428 | * EINVAL means the property does not exist. This is fine providing | 4554 | * EINVAL means the property does not exist. This is fine providing |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index cdc837ed144d..8348352dc2c6 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -350,12 +350,27 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, | |||
350 | } | 350 | } |
351 | 351 | ||
352 | /** | 352 | /** |
353 | * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a | ||
354 | * kcontrol | ||
355 | * @kcontrol: The kcontrol | ||
356 | * | ||
357 | * Note: This function must only be used on kcontrols that are known to have | ||
358 | * been registered for a CODEC. Otherwise the behaviour is undefined. | ||
359 | */ | ||
360 | struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( | ||
361 | struct snd_kcontrol *kcontrol) | ||
362 | { | ||
363 | return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm; | ||
364 | } | ||
365 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm); | ||
366 | |||
367 | /** | ||
353 | * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol | 368 | * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol |
354 | * @kcontrol: The kcontrol | 369 | * @kcontrol: The kcontrol |
355 | */ | 370 | */ |
356 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) | 371 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) |
357 | { | 372 | { |
358 | return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec; | 373 | return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol)); |
359 | } | 374 | } |
360 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); | 375 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); |
361 | 376 | ||
@@ -375,23 +390,38 @@ static void dapm_reset(struct snd_soc_card *card) | |||
375 | } | 390 | } |
376 | } | 391 | } |
377 | 392 | ||
378 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, | 393 | static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) |
394 | { | ||
395 | if (!dapm->component) | ||
396 | return NULL; | ||
397 | return dapm->component->name_prefix; | ||
398 | } | ||
399 | |||
400 | static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg, | ||
379 | unsigned int *value) | 401 | unsigned int *value) |
380 | { | 402 | { |
381 | if (!w->dapm->component) | 403 | if (!dapm->component) |
382 | return -EIO; | 404 | return -EIO; |
383 | return snd_soc_component_read(w->dapm->component, reg, value); | 405 | return snd_soc_component_read(dapm->component, reg, value); |
384 | } | 406 | } |
385 | 407 | ||
386 | static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, | 408 | static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, |
387 | int reg, unsigned int mask, unsigned int value) | 409 | int reg, unsigned int mask, unsigned int value) |
388 | { | 410 | { |
389 | if (!w->dapm->component) | 411 | if (!dapm->component) |
390 | return -EIO; | 412 | return -EIO; |
391 | return snd_soc_component_update_bits_async(w->dapm->component, reg, | 413 | return snd_soc_component_update_bits_async(dapm->component, reg, |
392 | mask, value); | 414 | mask, value); |
393 | } | 415 | } |
394 | 416 | ||
417 | static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm, | ||
418 | int reg, unsigned int mask, unsigned int value) | ||
419 | { | ||
420 | if (!dapm->component) | ||
421 | return -EIO; | ||
422 | return snd_soc_component_test_bits(dapm->component, reg, mask, value); | ||
423 | } | ||
424 | |||
395 | static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) | 425 | static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) |
396 | { | 426 | { |
397 | if (dapm->component) | 427 | if (dapm->component) |
@@ -420,15 +450,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
420 | if (ret != 0) | 450 | if (ret != 0) |
421 | goto out; | 451 | goto out; |
422 | 452 | ||
423 | if (dapm->codec) { | 453 | if (dapm->set_bias_level) |
424 | if (dapm->codec->driver->set_bias_level) | 454 | ret = dapm->set_bias_level(dapm, level); |
425 | ret = dapm->codec->driver->set_bias_level(dapm->codec, | 455 | else if (!card || dapm != &card->dapm) |
426 | level); | ||
427 | else | ||
428 | dapm->bias_level = level; | ||
429 | } else if (!card || dapm != &card->dapm) { | ||
430 | dapm->bias_level = level; | 456 | dapm->bias_level = level; |
431 | } | ||
432 | 457 | ||
433 | if (ret != 0) | 458 | if (ret != 0) |
434 | goto out; | 459 | goto out; |
@@ -452,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
452 | int i; | 477 | int i; |
453 | 478 | ||
454 | if (e->reg != SND_SOC_NOPM) { | 479 | if (e->reg != SND_SOC_NOPM) { |
455 | soc_widget_read(dest, e->reg, &val); | 480 | soc_dapm_read(dapm, e->reg, &val); |
456 | val = (val >> e->shift_l) & e->mask; | 481 | val = (val >> e->shift_l) & e->mask; |
457 | item = snd_soc_enum_val_to_item(e, val); | 482 | item = snd_soc_enum_val_to_item(e, val); |
458 | } else { | 483 | } else { |
@@ -496,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
496 | unsigned int val; | 521 | unsigned int val; |
497 | 522 | ||
498 | if (reg != SND_SOC_NOPM) { | 523 | if (reg != SND_SOC_NOPM) { |
499 | soc_widget_read(w, reg, &val); | 524 | soc_dapm_read(w->dapm, reg, &val); |
500 | val = (val >> shift) & mask; | 525 | val = (val >> shift) & mask; |
501 | if (invert) | 526 | if (invert) |
502 | val = max - val; | 527 | val = max - val; |
@@ -570,11 +595,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
570 | const char *name; | 595 | const char *name; |
571 | int ret; | 596 | int ret; |
572 | 597 | ||
573 | if (dapm->codec) | 598 | prefix = soc_dapm_prefix(dapm); |
574 | prefix = dapm->codec->name_prefix; | ||
575 | else | ||
576 | prefix = NULL; | ||
577 | |||
578 | if (prefix) | 599 | if (prefix) |
579 | prefix_len = strlen(prefix) + 1; | 600 | prefix_len = strlen(prefix) + 1; |
580 | else | 601 | else |
@@ -1308,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card, | |||
1308 | static void dapm_seq_run_coalesced(struct snd_soc_card *card, | 1329 | static void dapm_seq_run_coalesced(struct snd_soc_card *card, |
1309 | struct list_head *pending) | 1330 | struct list_head *pending) |
1310 | { | 1331 | { |
1332 | struct snd_soc_dapm_context *dapm; | ||
1311 | struct snd_soc_dapm_widget *w; | 1333 | struct snd_soc_dapm_widget *w; |
1312 | int reg; | 1334 | int reg; |
1313 | unsigned int value = 0; | 1335 | unsigned int value = 0; |
1314 | unsigned int mask = 0; | 1336 | unsigned int mask = 0; |
1315 | 1337 | ||
1316 | reg = list_first_entry(pending, struct snd_soc_dapm_widget, | 1338 | w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list); |
1317 | power_list)->reg; | 1339 | reg = w->reg; |
1340 | dapm = w->dapm; | ||
1318 | 1341 | ||
1319 | list_for_each_entry(w, pending, power_list) { | 1342 | list_for_each_entry(w, pending, power_list) { |
1320 | WARN_ON(reg != w->reg); | 1343 | WARN_ON(reg != w->reg || dapm != w->dapm); |
1321 | w->power = w->new_power; | 1344 | w->power = w->new_power; |
1322 | 1345 | ||
1323 | mask |= w->mask << w->shift; | 1346 | mask |= w->mask << w->shift; |
@@ -1326,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, | |||
1326 | else | 1349 | else |
1327 | value |= w->off_val << w->shift; | 1350 | value |= w->off_val << w->shift; |
1328 | 1351 | ||
1329 | pop_dbg(w->dapm->dev, card->pop_time, | 1352 | pop_dbg(dapm->dev, card->pop_time, |
1330 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", | 1353 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", |
1331 | w->name, reg, value, mask); | 1354 | w->name, reg, value, mask); |
1332 | 1355 | ||
@@ -1339,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, | |||
1339 | /* Any widget will do, they should all be updating the | 1362 | /* Any widget will do, they should all be updating the |
1340 | * same register. | 1363 | * same register. |
1341 | */ | 1364 | */ |
1342 | w = list_first_entry(pending, struct snd_soc_dapm_widget, | ||
1343 | power_list); | ||
1344 | 1365 | ||
1345 | pop_dbg(w->dapm->dev, card->pop_time, | 1366 | pop_dbg(dapm->dev, card->pop_time, |
1346 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 1367 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
1347 | value, mask, reg, card->pop_time); | 1368 | value, mask, reg, card->pop_time); |
1348 | pop_wait(card->pop_time); | 1369 | pop_wait(card->pop_time); |
1349 | soc_widget_update_bits(w, reg, mask, value); | 1370 | soc_dapm_update_bits(dapm, reg, mask, value); |
1350 | } | 1371 | } |
1351 | 1372 | ||
1352 | list_for_each_entry(w, pending, power_list) { | 1373 | list_for_each_entry(w, pending, power_list) { |
@@ -1492,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card) | |||
1492 | if (!w) | 1513 | if (!w) |
1493 | return; | 1514 | return; |
1494 | 1515 | ||
1495 | ret = soc_widget_update_bits(w, update->reg, update->mask, update->val); | 1516 | ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask, |
1517 | update->val); | ||
1496 | if (ret < 0) | 1518 | if (ret < 0) |
1497 | dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", | 1519 | dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", |
1498 | w->name, ret); | 1520 | w->name, ret); |
@@ -2062,17 +2084,13 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, | |||
2062 | } | 2084 | } |
2063 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); | 2085 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); |
2064 | 2086 | ||
2065 | /* show dapm widget status in sys fs */ | 2087 | static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf) |
2066 | static ssize_t dapm_widget_show(struct device *dev, | ||
2067 | struct device_attribute *attr, char *buf) | ||
2068 | { | 2088 | { |
2069 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | ||
2070 | struct snd_soc_codec *codec =rtd->codec; | ||
2071 | struct snd_soc_dapm_widget *w; | 2089 | struct snd_soc_dapm_widget *w; |
2072 | int count = 0; | 2090 | int count = 0; |
2073 | char *state = "not set"; | 2091 | char *state = "not set"; |
2074 | 2092 | ||
2075 | list_for_each_entry(w, &codec->card->widgets, list) { | 2093 | list_for_each_entry(w, &codec->component.card->widgets, list) { |
2076 | if (w->dapm != &codec->dapm) | 2094 | if (w->dapm != &codec->dapm) |
2077 | continue; | 2095 | continue; |
2078 | 2096 | ||
@@ -2120,6 +2138,21 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2120 | return count; | 2138 | return count; |
2121 | } | 2139 | } |
2122 | 2140 | ||
2141 | /* show dapm widget status in sys fs */ | ||
2142 | static ssize_t dapm_widget_show(struct device *dev, | ||
2143 | struct device_attribute *attr, char *buf) | ||
2144 | { | ||
2145 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | ||
2146 | int i, count = 0; | ||
2147 | |||
2148 | for (i = 0; i < rtd->num_codecs; i++) { | ||
2149 | struct snd_soc_codec *codec = rtd->codec_dais[i]->codec; | ||
2150 | count += dapm_widget_show_codec(codec, buf + count); | ||
2151 | } | ||
2152 | |||
2153 | return count; | ||
2154 | } | ||
2155 | |||
2123 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | 2156 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); |
2124 | 2157 | ||
2125 | int snd_soc_dapm_sys_add(struct device *dev) | 2158 | int snd_soc_dapm_sys_add(struct device *dev) |
@@ -2371,14 +2404,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2371 | const char *source; | 2404 | const char *source; |
2372 | char prefixed_sink[80]; | 2405 | char prefixed_sink[80]; |
2373 | char prefixed_source[80]; | 2406 | char prefixed_source[80]; |
2407 | const char *prefix; | ||
2374 | int ret; | 2408 | int ret; |
2375 | 2409 | ||
2376 | if (dapm->codec && dapm->codec->name_prefix) { | 2410 | prefix = soc_dapm_prefix(dapm); |
2411 | if (prefix) { | ||
2377 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 2412 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
2378 | dapm->codec->name_prefix, route->sink); | 2413 | prefix, route->sink); |
2379 | sink = prefixed_sink; | 2414 | sink = prefixed_sink; |
2380 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | 2415 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", |
2381 | dapm->codec->name_prefix, route->source); | 2416 | prefix, route->source); |
2382 | source = prefixed_source; | 2417 | source = prefixed_source; |
2383 | } else { | 2418 | } else { |
2384 | sink = route->sink; | 2419 | sink = route->sink; |
@@ -2439,6 +2474,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2439 | const char *source; | 2474 | const char *source; |
2440 | char prefixed_sink[80]; | 2475 | char prefixed_sink[80]; |
2441 | char prefixed_source[80]; | 2476 | char prefixed_source[80]; |
2477 | const char *prefix; | ||
2442 | 2478 | ||
2443 | if (route->control) { | 2479 | if (route->control) { |
2444 | dev_err(dapm->dev, | 2480 | dev_err(dapm->dev, |
@@ -2446,12 +2482,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2446 | return -EINVAL; | 2482 | return -EINVAL; |
2447 | } | 2483 | } |
2448 | 2484 | ||
2449 | if (dapm->codec && dapm->codec->name_prefix) { | 2485 | prefix = soc_dapm_prefix(dapm); |
2486 | if (prefix) { | ||
2450 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 2487 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
2451 | dapm->codec->name_prefix, route->sink); | 2488 | prefix, route->sink); |
2452 | sink = prefixed_sink; | 2489 | sink = prefixed_sink; |
2453 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | 2490 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", |
2454 | dapm->codec->name_prefix, route->source); | 2491 | prefix, route->source); |
2455 | source = prefixed_source; | 2492 | source = prefixed_source; |
2456 | } else { | 2493 | } else { |
2457 | sink = route->sink; | 2494 | sink = route->sink; |
@@ -2670,7 +2707,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
2670 | 2707 | ||
2671 | /* Read the initial power state from the device */ | 2708 | /* Read the initial power state from the device */ |
2672 | if (w->reg >= 0) { | 2709 | if (w->reg >= 0) { |
2673 | soc_widget_read(w, w->reg, &val); | 2710 | soc_dapm_read(w->dapm, w->reg, &val); |
2674 | val = val >> w->shift; | 2711 | val = val >> w->shift; |
2675 | val &= w->mask; | 2712 | val &= w->mask; |
2676 | if (val == w->on_val) | 2713 | if (val == w->on_val) |
@@ -2701,8 +2738,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | |||
2701 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | 2738 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
2702 | struct snd_ctl_elem_value *ucontrol) | 2739 | struct snd_ctl_elem_value *ucontrol) |
2703 | { | 2740 | { |
2704 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2741 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2705 | struct snd_soc_card *card = codec->card; | 2742 | struct snd_soc_card *card = dapm->card; |
2706 | struct soc_mixer_control *mc = | 2743 | struct soc_mixer_control *mc = |
2707 | (struct soc_mixer_control *)kcontrol->private_value; | 2744 | (struct soc_mixer_control *)kcontrol->private_value; |
2708 | int reg = mc->reg; | 2745 | int reg = mc->reg; |
@@ -2711,17 +2748,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2711 | unsigned int mask = (1 << fls(max)) - 1; | 2748 | unsigned int mask = (1 << fls(max)) - 1; |
2712 | unsigned int invert = mc->invert; | 2749 | unsigned int invert = mc->invert; |
2713 | unsigned int val; | 2750 | unsigned int val; |
2751 | int ret = 0; | ||
2714 | 2752 | ||
2715 | if (snd_soc_volsw_is_stereo(mc)) | 2753 | if (snd_soc_volsw_is_stereo(mc)) |
2716 | dev_warn(codec->dapm.dev, | 2754 | dev_warn(dapm->dev, |
2717 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2755 | "ASoC: Control '%s' is stereo, which is not supported\n", |
2718 | kcontrol->id.name); | 2756 | kcontrol->id.name); |
2719 | 2757 | ||
2720 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2758 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2721 | if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) | 2759 | if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { |
2722 | val = (snd_soc_read(codec, reg) >> shift) & mask; | 2760 | ret = soc_dapm_read(dapm, reg, &val); |
2723 | else | 2761 | val = (val >> shift) & mask; |
2762 | } else { | ||
2724 | val = dapm_kcontrol_get_value(kcontrol); | 2763 | val = dapm_kcontrol_get_value(kcontrol); |
2764 | } | ||
2725 | mutex_unlock(&card->dapm_mutex); | 2765 | mutex_unlock(&card->dapm_mutex); |
2726 | 2766 | ||
2727 | if (invert) | 2767 | if (invert) |
@@ -2729,7 +2769,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2729 | else | 2769 | else |
2730 | ucontrol->value.integer.value[0] = val; | 2770 | ucontrol->value.integer.value[0] = val; |
2731 | 2771 | ||
2732 | return 0; | 2772 | return ret; |
2733 | } | 2773 | } |
2734 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | 2774 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); |
2735 | 2775 | ||
@@ -2745,8 +2785,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | |||
2745 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 2785 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
2746 | struct snd_ctl_elem_value *ucontrol) | 2786 | struct snd_ctl_elem_value *ucontrol) |
2747 | { | 2787 | { |
2748 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2788 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2749 | struct snd_soc_card *card = codec->card; | 2789 | struct snd_soc_card *card = dapm->card; |
2750 | struct soc_mixer_control *mc = | 2790 | struct soc_mixer_control *mc = |
2751 | (struct soc_mixer_control *)kcontrol->private_value; | 2791 | (struct soc_mixer_control *)kcontrol->private_value; |
2752 | int reg = mc->reg; | 2792 | int reg = mc->reg; |
@@ -2760,7 +2800,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2760 | int ret = 0; | 2800 | int ret = 0; |
2761 | 2801 | ||
2762 | if (snd_soc_volsw_is_stereo(mc)) | 2802 | if (snd_soc_volsw_is_stereo(mc)) |
2763 | dev_warn(codec->dapm.dev, | 2803 | dev_warn(dapm->dev, |
2764 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2804 | "ASoC: Control '%s' is stereo, which is not supported\n", |
2765 | kcontrol->id.name); | 2805 | kcontrol->id.name); |
2766 | 2806 | ||
@@ -2778,7 +2818,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2778 | mask = mask << shift; | 2818 | mask = mask << shift; |
2779 | val = val << shift; | 2819 | val = val << shift; |
2780 | 2820 | ||
2781 | reg_change = snd_soc_test_bits(codec, reg, mask, val); | 2821 | reg_change = soc_dapm_test_bits(dapm, reg, mask, val); |
2782 | } | 2822 | } |
2783 | 2823 | ||
2784 | if (change || reg_change) { | 2824 | if (change || reg_change) { |
@@ -2817,12 +2857,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | |||
2817 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | 2857 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, |
2818 | struct snd_ctl_elem_value *ucontrol) | 2858 | struct snd_ctl_elem_value *ucontrol) |
2819 | { | 2859 | { |
2820 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2860 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2821 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2861 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2822 | unsigned int reg_val, val; | 2862 | unsigned int reg_val, val; |
2863 | int ret = 0; | ||
2823 | 2864 | ||
2824 | if (e->reg != SND_SOC_NOPM) | 2865 | if (e->reg != SND_SOC_NOPM) |
2825 | reg_val = snd_soc_read(codec, e->reg); | 2866 | ret = soc_dapm_read(dapm, e->reg, ®_val); |
2826 | else | 2867 | else |
2827 | reg_val = dapm_kcontrol_get_value(kcontrol); | 2868 | reg_val = dapm_kcontrol_get_value(kcontrol); |
2828 | 2869 | ||
@@ -2834,7 +2875,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2834 | ucontrol->value.enumerated.item[1] = val; | 2875 | ucontrol->value.enumerated.item[1] = val; |
2835 | } | 2876 | } |
2836 | 2877 | ||
2837 | return 0; | 2878 | return ret; |
2838 | } | 2879 | } |
2839 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | 2880 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); |
2840 | 2881 | ||
@@ -2850,8 +2891,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | |||
2850 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 2891 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
2851 | struct snd_ctl_elem_value *ucontrol) | 2892 | struct snd_ctl_elem_value *ucontrol) |
2852 | { | 2893 | { |
2853 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2894 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
2854 | struct snd_soc_card *card = codec->card; | 2895 | struct snd_soc_card *card = dapm->card; |
2855 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2896 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2856 | unsigned int *item = ucontrol->value.enumerated.item; | 2897 | unsigned int *item = ucontrol->value.enumerated.item; |
2857 | unsigned int val, change; | 2898 | unsigned int val, change; |
@@ -2874,7 +2915,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2874 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2915 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2875 | 2916 | ||
2876 | if (e->reg != SND_SOC_NOPM) | 2917 | if (e->reg != SND_SOC_NOPM) |
2877 | change = snd_soc_test_bits(codec, e->reg, mask, val); | 2918 | change = soc_dapm_test_bits(dapm, e->reg, mask, val); |
2878 | else | 2919 | else |
2879 | change = dapm_kcontrol_set_value(kcontrol, val); | 2920 | change = dapm_kcontrol_set_value(kcontrol, val); |
2880 | 2921 | ||
@@ -2971,6 +3012,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2971 | const struct snd_soc_dapm_widget *widget) | 3012 | const struct snd_soc_dapm_widget *widget) |
2972 | { | 3013 | { |
2973 | struct snd_soc_dapm_widget *w; | 3014 | struct snd_soc_dapm_widget *w; |
3015 | const char *prefix; | ||
2974 | int ret; | 3016 | int ret; |
2975 | 3017 | ||
2976 | if ((w = dapm_cnew_widget(widget)) == NULL) | 3018 | if ((w = dapm_cnew_widget(widget)) == NULL) |
@@ -3011,9 +3053,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3011 | break; | 3053 | break; |
3012 | } | 3054 | } |
3013 | 3055 | ||
3014 | if (dapm->codec && dapm->codec->name_prefix) | 3056 | prefix = soc_dapm_prefix(dapm); |
3015 | w->name = kasprintf(GFP_KERNEL, "%s %s", | 3057 | if (prefix) |
3016 | dapm->codec->name_prefix, widget->name); | 3058 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); |
3017 | else | 3059 | else |
3018 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); | 3060 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); |
3019 | 3061 | ||
@@ -3066,7 +3108,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3066 | 3108 | ||
3067 | w->dapm = dapm; | 3109 | w->dapm = dapm; |
3068 | w->codec = dapm->codec; | 3110 | w->codec = dapm->codec; |
3069 | w->platform = dapm->platform; | ||
3070 | INIT_LIST_HEAD(&w->sources); | 3111 | INIT_LIST_HEAD(&w->sources); |
3071 | INIT_LIST_HEAD(&w->sinks); | 3112 | INIT_LIST_HEAD(&w->sinks); |
3072 | INIT_LIST_HEAD(&w->list); | 3113 | INIT_LIST_HEAD(&w->list); |
@@ -3173,27 +3214,15 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3173 | 3214 | ||
3174 | switch (event) { | 3215 | switch (event) { |
3175 | case SND_SOC_DAPM_PRE_PMU: | 3216 | case SND_SOC_DAPM_PRE_PMU: |
3176 | if (source->driver->ops && source->driver->ops->hw_params) { | 3217 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; |
3177 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3218 | ret = soc_dai_hw_params(&substream, params, source); |
3178 | ret = source->driver->ops->hw_params(&substream, | 3219 | if (ret < 0) |
3179 | params, source); | 3220 | goto out; |
3180 | if (ret != 0) { | ||
3181 | dev_err(source->dev, | ||
3182 | "ASoC: hw_params() failed: %d\n", ret); | ||
3183 | goto out; | ||
3184 | } | ||
3185 | } | ||
3186 | 3221 | ||
3187 | if (sink->driver->ops && sink->driver->ops->hw_params) { | 3222 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; |
3188 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3223 | ret = soc_dai_hw_params(&substream, params, sink); |
3189 | ret = sink->driver->ops->hw_params(&substream, params, | 3224 | if (ret < 0) |
3190 | sink); | 3225 | goto out; |
3191 | if (ret != 0) { | ||
3192 | dev_err(sink->dev, | ||
3193 | "ASoC: hw_params() failed: %d\n", ret); | ||
3194 | goto out; | ||
3195 | } | ||
3196 | } | ||
3197 | break; | 3226 | break; |
3198 | 3227 | ||
3199 | case SND_SOC_DAPM_POST_PMU: | 3228 | case SND_SOC_DAPM_POST_PMU: |
@@ -3365,25 +3394,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
3365 | return 0; | 3394 | return 0; |
3366 | } | 3395 | } |
3367 | 3396 | ||
3368 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | 3397 | static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, |
3398 | struct snd_soc_pcm_runtime *rtd) | ||
3369 | { | 3399 | { |
3370 | struct snd_soc_pcm_runtime *rtd = card->rtd; | 3400 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
3371 | struct snd_soc_dapm_widget *sink, *source; | 3401 | struct snd_soc_dapm_widget *sink, *source; |
3372 | struct snd_soc_dai *cpu_dai, *codec_dai; | ||
3373 | int i; | 3402 | int i; |
3374 | 3403 | ||
3375 | /* for each BE DAI link... */ | 3404 | for (i = 0; i < rtd->num_codecs; i++) { |
3376 | for (i = 0; i < card->num_rtd; i++) { | 3405 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
3377 | rtd = &card->rtd[i]; | ||
3378 | cpu_dai = rtd->cpu_dai; | ||
3379 | codec_dai = rtd->codec_dai; | ||
3380 | |||
3381 | /* | ||
3382 | * dynamic FE links have no fixed DAI mapping. | ||
3383 | * CODEC<->CODEC links have no direct connection. | ||
3384 | */ | ||
3385 | if (rtd->dai_link->dynamic || rtd->dai_link->params) | ||
3386 | continue; | ||
3387 | 3406 | ||
3388 | /* there is no point in connecting BE DAI links with dummies */ | 3407 | /* there is no point in connecting BE DAI links with dummies */ |
3389 | if (snd_soc_dai_is_dummy(codec_dai) || | 3408 | if (snd_soc_dai_is_dummy(codec_dai) || |
@@ -3395,8 +3414,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
3395 | source = cpu_dai->playback_widget; | 3414 | source = cpu_dai->playback_widget; |
3396 | sink = codec_dai->playback_widget; | 3415 | sink = codec_dai->playback_widget; |
3397 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 3416 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
3398 | cpu_dai->codec->name, source->name, | 3417 | cpu_dai->component->name, source->name, |
3399 | codec_dai->platform->name, sink->name); | 3418 | codec_dai->component->name, sink->name); |
3400 | 3419 | ||
3401 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 3420 | snd_soc_dapm_add_path(&card->dapm, source, sink, |
3402 | NULL, NULL); | 3421 | NULL, NULL); |
@@ -3407,8 +3426,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
3407 | source = codec_dai->capture_widget; | 3426 | source = codec_dai->capture_widget; |
3408 | sink = cpu_dai->capture_widget; | 3427 | sink = cpu_dai->capture_widget; |
3409 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 3428 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
3410 | codec_dai->codec->name, source->name, | 3429 | codec_dai->component->name, source->name, |
3411 | cpu_dai->platform->name, sink->name); | 3430 | cpu_dai->component->name, sink->name); |
3412 | 3431 | ||
3413 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 3432 | snd_soc_dapm_add_path(&card->dapm, source, sink, |
3414 | NULL, NULL); | 3433 | NULL, NULL); |
@@ -3445,11 +3464,34 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3445 | } | 3464 | } |
3446 | } | 3465 | } |
3447 | 3466 | ||
3467 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | ||
3468 | { | ||
3469 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
3470 | int i; | ||
3471 | |||
3472 | /* for each BE DAI link... */ | ||
3473 | for (i = 0; i < card->num_rtd; i++) { | ||
3474 | rtd = &card->rtd[i]; | ||
3475 | |||
3476 | /* | ||
3477 | * dynamic FE links have no fixed DAI mapping. | ||
3478 | * CODEC<->CODEC links have no direct connection. | ||
3479 | */ | ||
3480 | if (rtd->dai_link->dynamic || rtd->dai_link->params) | ||
3481 | continue; | ||
3482 | |||
3483 | dapm_connect_dai_link_widgets(card, rtd); | ||
3484 | } | ||
3485 | } | ||
3486 | |||
3448 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | 3487 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, |
3449 | int event) | 3488 | int event) |
3450 | { | 3489 | { |
3490 | int i; | ||
3491 | |||
3451 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); | 3492 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); |
3452 | soc_dapm_dai_stream_event(rtd->codec_dai, stream, event); | 3493 | for (i = 0; i < rtd->num_codecs; i++) |
3494 | soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event); | ||
3453 | 3495 | ||
3454 | dapm_power_widgets(rtd->card, event); | 3496 | dapm_power_widgets(rtd->card, event); |
3455 | } | 3497 | } |
@@ -3758,36 +3800,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, | |||
3758 | } | 3800 | } |
3759 | 3801 | ||
3760 | /** | 3802 | /** |
3761 | * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins | 3803 | * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins |
3762 | * @codec: The codec whose pins should be processed | 3804 | * @card: The card whose pins should be processed |
3763 | * | 3805 | * |
3764 | * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec | 3806 | * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card |
3765 | * which are unused. Pins are used if they are connected externally to the | 3807 | * which are unused. Pins are used if they are connected externally to a |
3766 | * codec, whether that be to some other device, or a loop-back connection to | 3808 | * component, whether that be to some other device, or a loop-back connection to |
3767 | * the codec itself. | 3809 | * the component itself. |
3768 | */ | 3810 | */ |
3769 | void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec) | 3811 | void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card) |
3770 | { | 3812 | { |
3771 | struct snd_soc_card *card = codec->card; | ||
3772 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
3773 | struct snd_soc_dapm_widget *w; | 3813 | struct snd_soc_dapm_widget *w; |
3774 | 3814 | ||
3775 | dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n", | 3815 | dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm); |
3776 | &card->dapm, &codec->dapm); | ||
3777 | 3816 | ||
3778 | list_for_each_entry(w, &card->widgets, list) { | 3817 | list_for_each_entry(w, &card->widgets, list) { |
3779 | if (w->dapm != dapm) | ||
3780 | continue; | ||
3781 | switch (w->id) { | 3818 | switch (w->id) { |
3782 | case snd_soc_dapm_input: | 3819 | case snd_soc_dapm_input: |
3783 | case snd_soc_dapm_output: | 3820 | case snd_soc_dapm_output: |
3784 | case snd_soc_dapm_micbias: | 3821 | case snd_soc_dapm_micbias: |
3785 | dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n", | 3822 | dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n", |
3786 | w->name); | 3823 | w->name); |
3787 | if (!snd_soc_dapm_widget_in_card_paths(card, w)) { | 3824 | if (!snd_soc_dapm_widget_in_card_paths(card, w)) { |
3788 | dev_dbg(codec->dev, | 3825 | dev_dbg(card->dev, |
3789 | "... Not in map; disabling\n"); | 3826 | "... Not in map; disabling\n"); |
3790 | snd_soc_dapm_nc_pin(dapm, w->name); | 3827 | snd_soc_dapm_nc_pin(w->dapm, w->name); |
3791 | } | 3828 | } |
3792 | break; | 3829 | break; |
3793 | default: | 3830 | default: |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 5bace124ef43..6307f85e871b 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -119,7 +119,10 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
119 | struct snd_dmaengine_dai_dma_data *dma_data; | 119 | struct snd_dmaengine_dai_dma_data *dma_data; |
120 | struct dma_slave_caps dma_caps; | 120 | struct dma_slave_caps dma_caps; |
121 | struct snd_pcm_hardware hw; | 121 | struct snd_pcm_hardware hw; |
122 | int ret; | 122 | u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | |
123 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
124 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
125 | int i, ret; | ||
123 | 126 | ||
124 | if (pcm->config && pcm->config->pcm_hardware) | 127 | if (pcm->config && pcm->config->pcm_hardware) |
125 | return snd_soc_set_runtime_hwparams(substream, | 128 | return snd_soc_set_runtime_hwparams(substream, |
@@ -146,6 +149,38 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
146 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; | 149 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; |
147 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) | 150 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) |
148 | hw.info |= SNDRV_PCM_INFO_BATCH; | 151 | hw.info |= SNDRV_PCM_INFO_BATCH; |
152 | |||
153 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
154 | addr_widths = dma_caps.dstn_addr_widths; | ||
155 | else | ||
156 | addr_widths = dma_caps.src_addr_widths; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Prepare formats mask for valid/allowed sample types. If the dma does | ||
161 | * not have support for the given physical word size, it needs to be | ||
162 | * masked out so user space can not use the format which produces | ||
163 | * corrupted audio. | ||
164 | * In case the dma driver does not implement the slave_caps the default | ||
165 | * assumption is that it supports 1, 2 and 4 bytes widths. | ||
166 | */ | ||
167 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { | ||
168 | int bits = snd_pcm_format_physical_width(i); | ||
169 | |||
170 | /* Enable only samples with DMA supported physical widths */ | ||
171 | switch (bits) { | ||
172 | case 8: | ||
173 | case 16: | ||
174 | case 24: | ||
175 | case 32: | ||
176 | case 64: | ||
177 | if (addr_widths & (1 << (bits / 8))) | ||
178 | hw.formats |= (1LL << i); | ||
179 | break; | ||
180 | default: | ||
181 | /* Unsupported types */ | ||
182 | break; | ||
183 | } | ||
149 | } | 184 | } |
150 | 185 | ||
151 | return snd_soc_set_runtime_hwparams(substream, &hw); | 186 | return snd_soc_set_runtime_hwparams(substream, &hw); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index d0d98810af91..ab47fea997a3 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -43,7 +43,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, | |||
43 | INIT_LIST_HEAD(&jack->jack_zones); | 43 | INIT_LIST_HEAD(&jack->jack_zones); |
44 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | 44 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); |
45 | 45 | ||
46 | return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); | 46 | return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack); |
47 | } | 47 | } |
48 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); | 48 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); |
49 | 49 | ||
@@ -260,7 +260,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) | |||
260 | static irqreturn_t gpio_handler(int irq, void *data) | 260 | static irqreturn_t gpio_handler(int irq, void *data) |
261 | { | 261 | { |
262 | struct snd_soc_jack_gpio *gpio = data; | 262 | struct snd_soc_jack_gpio *gpio = data; |
263 | struct device *dev = gpio->jack->codec->card->dev; | 263 | struct device *dev = gpio->jack->codec->component.card->dev; |
264 | 264 | ||
265 | trace_snd_soc_jack_irq(gpio->name); | 265 | trace_snd_soc_jack_irq(gpio->name); |
266 | 266 | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 54d18f22a33e..731fdb5b5f9b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (C) 2010 Texas Instruments Inc. | 7 | * Copyright (C) 2010 Texas Instruments Inc. |
8 | * | 8 | * |
9 | * Authors: Liam Girdwood <lrg@ti.com> | 9 | * Authors: Liam Girdwood <lrg@ti.com> |
10 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | 10 | * Mark Brown <broonie@opensource.wolfsonmicro.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify it | 12 | * This program is free software; you can redistribute it and/or modify it |
13 | * under the terms of the GNU General Public License as published by the | 13 | * under the terms of the GNU General Public License as published by the |
@@ -47,22 +47,26 @@ | |||
47 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | 47 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) |
48 | { | 48 | { |
49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
50 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 50 | int i; |
51 | 51 | ||
52 | lockdep_assert_held(&rtd->pcm_mutex); | 52 | lockdep_assert_held(&rtd->pcm_mutex); |
53 | 53 | ||
54 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 54 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
55 | cpu_dai->playback_active++; | 55 | cpu_dai->playback_active++; |
56 | codec_dai->playback_active++; | 56 | for (i = 0; i < rtd->num_codecs; i++) |
57 | rtd->codec_dais[i]->playback_active++; | ||
57 | } else { | 58 | } else { |
58 | cpu_dai->capture_active++; | 59 | cpu_dai->capture_active++; |
59 | codec_dai->capture_active++; | 60 | for (i = 0; i < rtd->num_codecs; i++) |
61 | rtd->codec_dais[i]->capture_active++; | ||
60 | } | 62 | } |
61 | 63 | ||
62 | cpu_dai->active++; | 64 | cpu_dai->active++; |
63 | codec_dai->active++; | ||
64 | cpu_dai->component->active++; | 65 | cpu_dai->component->active++; |
65 | codec_dai->component->active++; | 66 | for (i = 0; i < rtd->num_codecs; i++) { |
67 | rtd->codec_dais[i]->active++; | ||
68 | rtd->codec_dais[i]->component->active++; | ||
69 | } | ||
66 | } | 70 | } |
67 | 71 | ||
68 | /** | 72 | /** |
@@ -78,22 +82,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
78 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | 82 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) |
79 | { | 83 | { |
80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 84 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
81 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 85 | int i; |
82 | 86 | ||
83 | lockdep_assert_held(&rtd->pcm_mutex); | 87 | lockdep_assert_held(&rtd->pcm_mutex); |
84 | 88 | ||
85 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 89 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
86 | cpu_dai->playback_active--; | 90 | cpu_dai->playback_active--; |
87 | codec_dai->playback_active--; | 91 | for (i = 0; i < rtd->num_codecs; i++) |
92 | rtd->codec_dais[i]->playback_active--; | ||
88 | } else { | 93 | } else { |
89 | cpu_dai->capture_active--; | 94 | cpu_dai->capture_active--; |
90 | codec_dai->capture_active--; | 95 | for (i = 0; i < rtd->num_codecs; i++) |
96 | rtd->codec_dais[i]->capture_active--; | ||
91 | } | 97 | } |
92 | 98 | ||
93 | cpu_dai->active--; | 99 | cpu_dai->active--; |
94 | codec_dai->active--; | ||
95 | cpu_dai->component->active--; | 100 | cpu_dai->component->active--; |
96 | codec_dai->component->active--; | 101 | for (i = 0; i < rtd->num_codecs; i++) { |
102 | rtd->codec_dais[i]->component->active--; | ||
103 | rtd->codec_dais[i]->active--; | ||
104 | } | ||
97 | } | 105 | } |
98 | 106 | ||
99 | /** | 107 | /** |
@@ -107,11 +115,16 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
107 | */ | 115 | */ |
108 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) | 116 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) |
109 | { | 117 | { |
118 | int i; | ||
119 | bool ignore = true; | ||
120 | |||
110 | if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) | 121 | if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) |
111 | return true; | 122 | return true; |
112 | 123 | ||
113 | return rtd->cpu_dai->component->ignore_pmdown_time && | 124 | for (i = 0; i < rtd->num_codecs; i++) |
114 | rtd->codec_dai->component->ignore_pmdown_time; | 125 | ignore &= rtd->codec_dais[i]->component->ignore_pmdown_time; |
126 | |||
127 | return rtd->cpu_dai->component->ignore_pmdown_time && ignore; | ||
115 | } | 128 | } |
116 | 129 | ||
117 | /** | 130 | /** |
@@ -222,8 +235,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
222 | { | 235 | { |
223 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 236 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
224 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 237 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 238 | unsigned int rate, channels, sample_bits, symmetry, i; |
226 | unsigned int rate, channels, sample_bits, symmetry; | ||
227 | 239 | ||
228 | rate = params_rate(params); | 240 | rate = params_rate(params); |
229 | channels = params_channels(params); | 241 | channels = params_channels(params); |
@@ -231,8 +243,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
231 | 243 | ||
232 | /* reject unmatched parameters when applying symmetry */ | 244 | /* reject unmatched parameters when applying symmetry */ |
233 | symmetry = cpu_dai->driver->symmetric_rates || | 245 | symmetry = cpu_dai->driver->symmetric_rates || |
234 | codec_dai->driver->symmetric_rates || | ||
235 | rtd->dai_link->symmetric_rates; | 246 | rtd->dai_link->symmetric_rates; |
247 | |||
248 | for (i = 0; i < rtd->num_codecs; i++) | ||
249 | symmetry |= rtd->codec_dais[i]->driver->symmetric_rates; | ||
250 | |||
236 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { | 251 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { |
237 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", | 252 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", |
238 | cpu_dai->rate, rate); | 253 | cpu_dai->rate, rate); |
@@ -240,8 +255,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
240 | } | 255 | } |
241 | 256 | ||
242 | symmetry = cpu_dai->driver->symmetric_channels || | 257 | symmetry = cpu_dai->driver->symmetric_channels || |
243 | codec_dai->driver->symmetric_channels || | ||
244 | rtd->dai_link->symmetric_channels; | 258 | rtd->dai_link->symmetric_channels; |
259 | |||
260 | for (i = 0; i < rtd->num_codecs; i++) | ||
261 | symmetry |= rtd->codec_dais[i]->driver->symmetric_channels; | ||
262 | |||
245 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { | 263 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { |
246 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", | 264 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", |
247 | cpu_dai->channels, channels); | 265 | cpu_dai->channels, channels); |
@@ -249,8 +267,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
249 | } | 267 | } |
250 | 268 | ||
251 | symmetry = cpu_dai->driver->symmetric_samplebits || | 269 | symmetry = cpu_dai->driver->symmetric_samplebits || |
252 | codec_dai->driver->symmetric_samplebits || | ||
253 | rtd->dai_link->symmetric_samplebits; | 270 | rtd->dai_link->symmetric_samplebits; |
271 | |||
272 | for (i = 0; i < rtd->num_codecs; i++) | ||
273 | symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits; | ||
274 | |||
254 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { | 275 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { |
255 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", | 276 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", |
256 | cpu_dai->sample_bits, sample_bits); | 277 | cpu_dai->sample_bits, sample_bits); |
@@ -264,15 +285,20 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) | |||
264 | { | 285 | { |
265 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
266 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; | 287 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; |
267 | struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver; | ||
268 | struct snd_soc_dai_link *link = rtd->dai_link; | 288 | struct snd_soc_dai_link *link = rtd->dai_link; |
289 | unsigned int symmetry, i; | ||
269 | 290 | ||
270 | return cpu_driver->symmetric_rates || codec_driver->symmetric_rates || | 291 | symmetry = cpu_driver->symmetric_rates || link->symmetric_rates || |
271 | link->symmetric_rates || cpu_driver->symmetric_channels || | 292 | cpu_driver->symmetric_channels || link->symmetric_channels || |
272 | codec_driver->symmetric_channels || link->symmetric_channels || | 293 | cpu_driver->symmetric_samplebits || link->symmetric_samplebits; |
273 | cpu_driver->symmetric_samplebits || | 294 | |
274 | codec_driver->symmetric_samplebits || | 295 | for (i = 0; i < rtd->num_codecs; i++) |
275 | link->symmetric_samplebits; | 296 | symmetry = symmetry || |
297 | rtd->codec_dais[i]->driver->symmetric_rates || | ||
298 | rtd->codec_dais[i]->driver->symmetric_channels || | ||
299 | rtd->codec_dais[i]->driver->symmetric_samplebits; | ||
300 | |||
301 | return symmetry; | ||
276 | } | 302 | } |
277 | 303 | ||
278 | /* | 304 | /* |
@@ -284,15 +310,10 @@ static int sample_sizes[] = { | |||
284 | 24, 32, | 310 | 24, 32, |
285 | }; | 311 | }; |
286 | 312 | ||
287 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | 313 | static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) |
288 | struct snd_soc_dai *dai) | ||
289 | { | 314 | { |
290 | int ret, i, bits; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
291 | 316 | int ret, i; | |
292 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
293 | bits = dai->driver->playback.sig_bits; | ||
294 | else | ||
295 | bits = dai->driver->capture.sig_bits; | ||
296 | 317 | ||
297 | if (!bits) | 318 | if (!bits) |
298 | return; | 319 | return; |
@@ -304,38 +325,105 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | |||
304 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, | 325 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, |
305 | sample_sizes[i], bits); | 326 | sample_sizes[i], bits); |
306 | if (ret != 0) | 327 | if (ret != 0) |
307 | dev_warn(dai->dev, | 328 | dev_warn(rtd->dev, |
308 | "ASoC: Failed to set MSB %d/%d: %d\n", | 329 | "ASoC: Failed to set MSB %d/%d: %d\n", |
309 | bits, sample_sizes[i], ret); | 330 | bits, sample_sizes[i], ret); |
310 | } | 331 | } |
311 | } | 332 | } |
312 | 333 | ||
313 | static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | 334 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) |
314 | struct snd_soc_pcm_stream *codec_stream, | 335 | { |
315 | struct snd_soc_pcm_stream *cpu_stream) | 336 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
337 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
338 | struct snd_soc_dai *codec_dai; | ||
339 | int i; | ||
340 | unsigned int bits = 0, cpu_bits; | ||
341 | |||
342 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
343 | for (i = 0; i < rtd->num_codecs; i++) { | ||
344 | codec_dai = rtd->codec_dais[i]; | ||
345 | if (codec_dai->driver->playback.sig_bits == 0) { | ||
346 | bits = 0; | ||
347 | break; | ||
348 | } | ||
349 | bits = max(codec_dai->driver->playback.sig_bits, bits); | ||
350 | } | ||
351 | cpu_bits = cpu_dai->driver->playback.sig_bits; | ||
352 | } else { | ||
353 | for (i = 0; i < rtd->num_codecs; i++) { | ||
354 | codec_dai = rtd->codec_dais[i]; | ||
355 | if (codec_dai->driver->playback.sig_bits == 0) { | ||
356 | bits = 0; | ||
357 | break; | ||
358 | } | ||
359 | bits = max(codec_dai->driver->capture.sig_bits, bits); | ||
360 | } | ||
361 | cpu_bits = cpu_dai->driver->capture.sig_bits; | ||
362 | } | ||
363 | |||
364 | soc_pcm_set_msb(substream, bits); | ||
365 | soc_pcm_set_msb(substream, cpu_bits); | ||
366 | } | ||
367 | |||
368 | static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) | ||
316 | { | 369 | { |
370 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
317 | struct snd_pcm_hardware *hw = &runtime->hw; | 371 | struct snd_pcm_hardware *hw = &runtime->hw; |
372 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
373 | struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver; | ||
374 | struct snd_soc_dai_driver *codec_dai_drv; | ||
375 | struct snd_soc_pcm_stream *codec_stream; | ||
376 | struct snd_soc_pcm_stream *cpu_stream; | ||
377 | unsigned int chan_min = 0, chan_max = UINT_MAX; | ||
378 | unsigned int rate_min = 0, rate_max = UINT_MAX; | ||
379 | unsigned int rates = UINT_MAX; | ||
380 | u64 formats = ULLONG_MAX; | ||
381 | int i; | ||
318 | 382 | ||
319 | hw->channels_min = max(codec_stream->channels_min, | 383 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
320 | cpu_stream->channels_min); | 384 | cpu_stream = &cpu_dai_drv->playback; |
321 | hw->channels_max = min(codec_stream->channels_max, | ||
322 | cpu_stream->channels_max); | ||
323 | if (hw->formats) | ||
324 | hw->formats &= codec_stream->formats & cpu_stream->formats; | ||
325 | else | 385 | else |
326 | hw->formats = codec_stream->formats & cpu_stream->formats; | 386 | cpu_stream = &cpu_dai_drv->capture; |
327 | hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates, | ||
328 | cpu_stream->rates); | ||
329 | 387 | ||
330 | hw->rate_min = 0; | 388 | /* first calculate min/max only for CODECs in the DAI link */ |
331 | hw->rate_max = UINT_MAX; | 389 | for (i = 0; i < rtd->num_codecs; i++) { |
390 | codec_dai_drv = rtd->codec_dais[i]->driver; | ||
391 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
392 | codec_stream = &codec_dai_drv->playback; | ||
393 | else | ||
394 | codec_stream = &codec_dai_drv->capture; | ||
395 | chan_min = max(chan_min, codec_stream->channels_min); | ||
396 | chan_max = min(chan_max, codec_stream->channels_max); | ||
397 | rate_min = max(rate_min, codec_stream->rate_min); | ||
398 | rate_max = min_not_zero(rate_max, codec_stream->rate_max); | ||
399 | formats &= codec_stream->formats; | ||
400 | rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * chan min/max cannot be enforced if there are multiple CODEC DAIs | ||
405 | * connected to a single CPU DAI, use CPU DAI's directly and let | ||
406 | * channel allocation be fixed up later | ||
407 | */ | ||
408 | if (rtd->num_codecs > 1) { | ||
409 | chan_min = cpu_stream->channels_min; | ||
410 | chan_max = cpu_stream->channels_max; | ||
411 | } | ||
412 | |||
413 | hw->channels_min = max(chan_min, cpu_stream->channels_min); | ||
414 | hw->channels_max = min(chan_max, cpu_stream->channels_max); | ||
415 | if (hw->formats) | ||
416 | hw->formats &= formats & cpu_stream->formats; | ||
417 | else | ||
418 | hw->formats = formats & cpu_stream->formats; | ||
419 | hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates); | ||
332 | 420 | ||
333 | snd_pcm_limit_hw_rates(runtime); | 421 | snd_pcm_limit_hw_rates(runtime); |
334 | 422 | ||
335 | hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); | 423 | hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); |
336 | hw->rate_min = max(hw->rate_min, codec_stream->rate_min); | 424 | hw->rate_min = max(hw->rate_min, rate_min); |
337 | hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); | 425 | hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); |
338 | hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max); | 426 | hw->rate_max = min_not_zero(hw->rate_max, rate_max); |
339 | } | 427 | } |
340 | 428 | ||
341 | /* | 429 | /* |
@@ -349,15 +437,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
349 | struct snd_pcm_runtime *runtime = substream->runtime; | 437 | struct snd_pcm_runtime *runtime = substream->runtime; |
350 | struct snd_soc_platform *platform = rtd->platform; | 438 | struct snd_soc_platform *platform = rtd->platform; |
351 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 439 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
352 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 440 | struct snd_soc_dai *codec_dai; |
353 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | 441 | const char *codec_dai_name = "multicodec"; |
354 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | 442 | int i, ret = 0; |
355 | int ret = 0; | ||
356 | 443 | ||
357 | pinctrl_pm_select_default_state(cpu_dai->dev); | 444 | pinctrl_pm_select_default_state(cpu_dai->dev); |
358 | pinctrl_pm_select_default_state(codec_dai->dev); | 445 | for (i = 0; i < rtd->num_codecs; i++) |
446 | pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev); | ||
359 | pm_runtime_get_sync(cpu_dai->dev); | 447 | pm_runtime_get_sync(cpu_dai->dev); |
360 | pm_runtime_get_sync(codec_dai->dev); | 448 | for (i = 0; i < rtd->num_codecs; i++) |
449 | pm_runtime_get_sync(rtd->codec_dais[i]->dev); | ||
361 | pm_runtime_get_sync(platform->dev); | 450 | pm_runtime_get_sync(platform->dev); |
362 | 451 | ||
363 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 452 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
@@ -376,18 +465,28 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
376 | ret = platform->driver->ops->open(substream); | 465 | ret = platform->driver->ops->open(substream); |
377 | if (ret < 0) { | 466 | if (ret < 0) { |
378 | dev_err(platform->dev, "ASoC: can't open platform" | 467 | dev_err(platform->dev, "ASoC: can't open platform" |
379 | " %s: %d\n", platform->name, ret); | 468 | " %s: %d\n", platform->component.name, ret); |
380 | goto platform_err; | 469 | goto platform_err; |
381 | } | 470 | } |
382 | } | 471 | } |
383 | 472 | ||
384 | if (codec_dai->driver->ops && codec_dai->driver->ops->startup) { | 473 | for (i = 0; i < rtd->num_codecs; i++) { |
385 | ret = codec_dai->driver->ops->startup(substream, codec_dai); | 474 | codec_dai = rtd->codec_dais[i]; |
386 | if (ret < 0) { | 475 | if (codec_dai->driver->ops && codec_dai->driver->ops->startup) { |
387 | dev_err(codec_dai->dev, "ASoC: can't open codec" | 476 | ret = codec_dai->driver->ops->startup(substream, |
388 | " %s: %d\n", codec_dai->name, ret); | 477 | codec_dai); |
389 | goto codec_dai_err; | 478 | if (ret < 0) { |
479 | dev_err(codec_dai->dev, | ||
480 | "ASoC: can't open codec %s: %d\n", | ||
481 | codec_dai->name, ret); | ||
482 | goto codec_dai_err; | ||
483 | } | ||
390 | } | 484 | } |
485 | |||
486 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
487 | codec_dai->tx_mask = 0; | ||
488 | else | ||
489 | codec_dai->rx_mask = 0; | ||
391 | } | 490 | } |
392 | 491 | ||
393 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { | 492 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { |
@@ -404,13 +503,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
404 | goto dynamic; | 503 | goto dynamic; |
405 | 504 | ||
406 | /* Check that the codec and cpu DAIs are compatible */ | 505 | /* Check that the codec and cpu DAIs are compatible */ |
407 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 506 | soc_pcm_init_runtime_hw(substream); |
408 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback, | 507 | |
409 | &cpu_dai_drv->playback); | 508 | if (rtd->num_codecs == 1) |
410 | } else { | 509 | codec_dai_name = rtd->codec_dai->name; |
411 | soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture, | ||
412 | &cpu_dai_drv->capture); | ||
413 | } | ||
414 | 510 | ||
415 | if (soc_pcm_has_symmetry(substream)) | 511 | if (soc_pcm_has_symmetry(substream)) |
416 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; | 512 | runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; |
@@ -418,23 +514,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
418 | ret = -EINVAL; | 514 | ret = -EINVAL; |
419 | if (!runtime->hw.rates) { | 515 | if (!runtime->hw.rates) { |
420 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", | 516 | printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", |
421 | codec_dai->name, cpu_dai->name); | 517 | codec_dai_name, cpu_dai->name); |
422 | goto config_err; | 518 | goto config_err; |
423 | } | 519 | } |
424 | if (!runtime->hw.formats) { | 520 | if (!runtime->hw.formats) { |
425 | printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", | 521 | printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", |
426 | codec_dai->name, cpu_dai->name); | 522 | codec_dai_name, cpu_dai->name); |
427 | goto config_err; | 523 | goto config_err; |
428 | } | 524 | } |
429 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || | 525 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || |
430 | runtime->hw.channels_min > runtime->hw.channels_max) { | 526 | runtime->hw.channels_min > runtime->hw.channels_max) { |
431 | printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", | 527 | printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", |
432 | codec_dai->name, cpu_dai->name); | 528 | codec_dai_name, cpu_dai->name); |
433 | goto config_err; | 529 | goto config_err; |
434 | } | 530 | } |
435 | 531 | ||
436 | soc_pcm_apply_msb(substream, codec_dai); | 532 | soc_pcm_apply_msb(substream); |
437 | soc_pcm_apply_msb(substream, cpu_dai); | ||
438 | 533 | ||
439 | /* Symmetry only applies if we've already got an active stream. */ | 534 | /* Symmetry only applies if we've already got an active stream. */ |
440 | if (cpu_dai->active) { | 535 | if (cpu_dai->active) { |
@@ -443,14 +538,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
443 | goto config_err; | 538 | goto config_err; |
444 | } | 539 | } |
445 | 540 | ||
446 | if (codec_dai->active) { | 541 | for (i = 0; i < rtd->num_codecs; i++) { |
447 | ret = soc_pcm_apply_symmetry(substream, codec_dai); | 542 | if (rtd->codec_dais[i]->active) { |
448 | if (ret != 0) | 543 | ret = soc_pcm_apply_symmetry(substream, |
449 | goto config_err; | 544 | rtd->codec_dais[i]); |
545 | if (ret != 0) | ||
546 | goto config_err; | ||
547 | } | ||
450 | } | 548 | } |
451 | 549 | ||
452 | pr_debug("ASoC: %s <-> %s info:\n", | 550 | pr_debug("ASoC: %s <-> %s info:\n", |
453 | codec_dai->name, cpu_dai->name); | 551 | codec_dai_name, cpu_dai->name); |
454 | pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); | 552 | pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); |
455 | pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, | 553 | pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, |
456 | runtime->hw.channels_max); | 554 | runtime->hw.channels_max); |
@@ -469,10 +567,15 @@ config_err: | |||
469 | rtd->dai_link->ops->shutdown(substream); | 567 | rtd->dai_link->ops->shutdown(substream); |
470 | 568 | ||
471 | machine_err: | 569 | machine_err: |
472 | if (codec_dai->driver->ops->shutdown) | 570 | i = rtd->num_codecs; |
473 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
474 | 571 | ||
475 | codec_dai_err: | 572 | codec_dai_err: |
573 | while (--i >= 0) { | ||
574 | codec_dai = rtd->codec_dais[i]; | ||
575 | if (codec_dai->driver->ops->shutdown) | ||
576 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
577 | } | ||
578 | |||
476 | if (platform->driver->ops && platform->driver->ops->close) | 579 | if (platform->driver->ops && platform->driver->ops->close) |
477 | platform->driver->ops->close(substream); | 580 | platform->driver->ops->close(substream); |
478 | 581 | ||
@@ -483,10 +586,13 @@ out: | |||
483 | mutex_unlock(&rtd->pcm_mutex); | 586 | mutex_unlock(&rtd->pcm_mutex); |
484 | 587 | ||
485 | pm_runtime_put(platform->dev); | 588 | pm_runtime_put(platform->dev); |
486 | pm_runtime_put(codec_dai->dev); | 589 | for (i = 0; i < rtd->num_codecs; i++) |
590 | pm_runtime_put(rtd->codec_dais[i]->dev); | ||
487 | pm_runtime_put(cpu_dai->dev); | 591 | pm_runtime_put(cpu_dai->dev); |
488 | if (!codec_dai->active) | 592 | for (i = 0; i < rtd->num_codecs; i++) { |
489 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 593 | if (!rtd->codec_dais[i]->active) |
594 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | ||
595 | } | ||
490 | if (!cpu_dai->active) | 596 | if (!cpu_dai->active) |
491 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 597 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
492 | 598 | ||
@@ -502,7 +608,7 @@ static void close_delayed_work(struct work_struct *work) | |||
502 | { | 608 | { |
503 | struct snd_soc_pcm_runtime *rtd = | 609 | struct snd_soc_pcm_runtime *rtd = |
504 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 610 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
505 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 611 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; |
506 | 612 | ||
507 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 613 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
508 | 614 | ||
@@ -531,7 +637,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
531 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 637 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
532 | struct snd_soc_platform *platform = rtd->platform; | 638 | struct snd_soc_platform *platform = rtd->platform; |
533 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 639 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
534 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 640 | struct snd_soc_dai *codec_dai; |
641 | int i; | ||
535 | 642 | ||
536 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 643 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
537 | 644 | ||
@@ -541,14 +648,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
541 | if (!cpu_dai->active) | 648 | if (!cpu_dai->active) |
542 | cpu_dai->rate = 0; | 649 | cpu_dai->rate = 0; |
543 | 650 | ||
544 | if (!codec_dai->active) | 651 | for (i = 0; i < rtd->num_codecs; i++) { |
545 | codec_dai->rate = 0; | 652 | codec_dai = rtd->codec_dais[i]; |
653 | if (!codec_dai->active) | ||
654 | codec_dai->rate = 0; | ||
655 | } | ||
546 | 656 | ||
547 | if (cpu_dai->driver->ops->shutdown) | 657 | if (cpu_dai->driver->ops->shutdown) |
548 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 658 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
549 | 659 | ||
550 | if (codec_dai->driver->ops->shutdown) | 660 | for (i = 0; i < rtd->num_codecs; i++) { |
551 | codec_dai->driver->ops->shutdown(substream, codec_dai); | 661 | codec_dai = rtd->codec_dais[i]; |
662 | if (codec_dai->driver->ops->shutdown) | ||
663 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
664 | } | ||
552 | 665 | ||
553 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | 666 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) |
554 | rtd->dai_link->ops->shutdown(substream); | 667 | rtd->dai_link->ops->shutdown(substream); |
@@ -578,10 +691,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
578 | mutex_unlock(&rtd->pcm_mutex); | 691 | mutex_unlock(&rtd->pcm_mutex); |
579 | 692 | ||
580 | pm_runtime_put(platform->dev); | 693 | pm_runtime_put(platform->dev); |
581 | pm_runtime_put(codec_dai->dev); | 694 | for (i = 0; i < rtd->num_codecs; i++) |
695 | pm_runtime_put(rtd->codec_dais[i]->dev); | ||
582 | pm_runtime_put(cpu_dai->dev); | 696 | pm_runtime_put(cpu_dai->dev); |
583 | if (!codec_dai->active) | 697 | for (i = 0; i < rtd->num_codecs; i++) { |
584 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 698 | if (!rtd->codec_dais[i]->active) |
699 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | ||
700 | } | ||
585 | if (!cpu_dai->active) | 701 | if (!cpu_dai->active) |
586 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 702 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
587 | 703 | ||
@@ -598,8 +714,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
598 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 714 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
599 | struct snd_soc_platform *platform = rtd->platform; | 715 | struct snd_soc_platform *platform = rtd->platform; |
600 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 716 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
601 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 717 | struct snd_soc_dai *codec_dai; |
602 | int ret = 0; | 718 | int i, ret = 0; |
603 | 719 | ||
604 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 720 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
605 | 721 | ||
@@ -621,12 +737,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
621 | } | 737 | } |
622 | } | 738 | } |
623 | 739 | ||
624 | if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) { | 740 | for (i = 0; i < rtd->num_codecs; i++) { |
625 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); | 741 | codec_dai = rtd->codec_dais[i]; |
626 | if (ret < 0) { | 742 | if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) { |
627 | dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n", | 743 | ret = codec_dai->driver->ops->prepare(substream, |
628 | ret); | 744 | codec_dai); |
629 | goto out; | 745 | if (ret < 0) { |
746 | dev_err(codec_dai->dev, | ||
747 | "ASoC: DAI prepare error: %d\n", ret); | ||
748 | goto out; | ||
749 | } | ||
630 | } | 750 | } |
631 | } | 751 | } |
632 | 752 | ||
@@ -649,13 +769,44 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
649 | snd_soc_dapm_stream_event(rtd, substream->stream, | 769 | snd_soc_dapm_stream_event(rtd, substream->stream, |
650 | SND_SOC_DAPM_STREAM_START); | 770 | SND_SOC_DAPM_STREAM_START); |
651 | 771 | ||
652 | snd_soc_dai_digital_mute(codec_dai, 0, substream->stream); | 772 | for (i = 0; i < rtd->num_codecs; i++) |
773 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, | ||
774 | substream->stream); | ||
653 | 775 | ||
654 | out: | 776 | out: |
655 | mutex_unlock(&rtd->pcm_mutex); | 777 | mutex_unlock(&rtd->pcm_mutex); |
656 | return ret; | 778 | return ret; |
657 | } | 779 | } |
658 | 780 | ||
781 | static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, | ||
782 | unsigned int mask) | ||
783 | { | ||
784 | struct snd_interval *interval; | ||
785 | int channels = hweight_long(mask); | ||
786 | |||
787 | interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
788 | interval->min = channels; | ||
789 | interval->max = channels; | ||
790 | } | ||
791 | |||
792 | int soc_dai_hw_params(struct snd_pcm_substream *substream, | ||
793 | struct snd_pcm_hw_params *params, | ||
794 | struct snd_soc_dai *dai) | ||
795 | { | ||
796 | int ret; | ||
797 | |||
798 | if (dai->driver->ops && dai->driver->ops->hw_params) { | ||
799 | ret = dai->driver->ops->hw_params(substream, params, dai); | ||
800 | if (ret < 0) { | ||
801 | dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", | ||
802 | dai->name, ret); | ||
803 | return ret; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
659 | /* | 810 | /* |
660 | * Called by ALSA when the hardware params are set by application. This | 811 | * Called by ALSA when the hardware params are set by application. This |
661 | * function can also be called multiple times and can allocate buffers | 812 | * function can also be called multiple times and can allocate buffers |
@@ -667,8 +818,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
667 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 818 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
668 | struct snd_soc_platform *platform = rtd->platform; | 819 | struct snd_soc_platform *platform = rtd->platform; |
669 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 820 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
670 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 821 | int i, ret = 0; |
671 | int ret = 0; | ||
672 | 822 | ||
673 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 823 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
674 | 824 | ||
@@ -685,29 +835,40 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
685 | } | 835 | } |
686 | } | 836 | } |
687 | 837 | ||
688 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) { | 838 | for (i = 0; i < rtd->num_codecs; i++) { |
689 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); | 839 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
690 | if (ret < 0) { | 840 | struct snd_pcm_hw_params codec_params; |
691 | dev_err(codec_dai->dev, "ASoC: can't set %s hw params:" | 841 | |
692 | " %d\n", codec_dai->name, ret); | 842 | /* copy params for each codec */ |
843 | codec_params = *params; | ||
844 | |||
845 | /* fixup params based on TDM slot masks */ | ||
846 | if (codec_dai->tx_mask) | ||
847 | soc_pcm_codec_params_fixup(&codec_params, | ||
848 | codec_dai->tx_mask); | ||
849 | if (codec_dai->rx_mask) | ||
850 | soc_pcm_codec_params_fixup(&codec_params, | ||
851 | codec_dai->rx_mask); | ||
852 | |||
853 | ret = soc_dai_hw_params(substream, &codec_params, codec_dai); | ||
854 | if(ret < 0) | ||
693 | goto codec_err; | 855 | goto codec_err; |
694 | } | ||
695 | } | ||
696 | 856 | ||
697 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) { | 857 | codec_dai->rate = params_rate(&codec_params); |
698 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); | 858 | codec_dai->channels = params_channels(&codec_params); |
699 | if (ret < 0) { | 859 | codec_dai->sample_bits = snd_pcm_format_physical_width( |
700 | dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n", | 860 | params_format(&codec_params)); |
701 | cpu_dai->name, ret); | ||
702 | goto interface_err; | ||
703 | } | ||
704 | } | 861 | } |
705 | 862 | ||
863 | ret = soc_dai_hw_params(substream, params, cpu_dai); | ||
864 | if (ret < 0) | ||
865 | goto interface_err; | ||
866 | |||
706 | if (platform->driver->ops && platform->driver->ops->hw_params) { | 867 | if (platform->driver->ops && platform->driver->ops->hw_params) { |
707 | ret = platform->driver->ops->hw_params(substream, params); | 868 | ret = platform->driver->ops->hw_params(substream, params); |
708 | if (ret < 0) { | 869 | if (ret < 0) { |
709 | dev_err(platform->dev, "ASoC: %s hw params failed: %d\n", | 870 | dev_err(platform->dev, "ASoC: %s hw params failed: %d\n", |
710 | platform->name, ret); | 871 | platform->component.name, ret); |
711 | goto platform_err; | 872 | goto platform_err; |
712 | } | 873 | } |
713 | } | 874 | } |
@@ -718,11 +879,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
718 | cpu_dai->sample_bits = | 879 | cpu_dai->sample_bits = |
719 | snd_pcm_format_physical_width(params_format(params)); | 880 | snd_pcm_format_physical_width(params_format(params)); |
720 | 881 | ||
721 | codec_dai->rate = params_rate(params); | ||
722 | codec_dai->channels = params_channels(params); | ||
723 | codec_dai->sample_bits = | ||
724 | snd_pcm_format_physical_width(params_format(params)); | ||
725 | |||
726 | out: | 882 | out: |
727 | mutex_unlock(&rtd->pcm_mutex); | 883 | mutex_unlock(&rtd->pcm_mutex); |
728 | return ret; | 884 | return ret; |
@@ -732,10 +888,16 @@ platform_err: | |||
732 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 888 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
733 | 889 | ||
734 | interface_err: | 890 | interface_err: |
735 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | 891 | i = rtd->num_codecs; |
736 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
737 | 892 | ||
738 | codec_err: | 893 | codec_err: |
894 | while (--i >= 0) { | ||
895 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
896 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | ||
897 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
898 | codec_dai->rate = 0; | ||
899 | } | ||
900 | |||
739 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 901 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
740 | rtd->dai_link->ops->hw_free(substream); | 902 | rtd->dai_link->ops->hw_free(substream); |
741 | 903 | ||
@@ -751,8 +913,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
751 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 913 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
752 | struct snd_soc_platform *platform = rtd->platform; | 914 | struct snd_soc_platform *platform = rtd->platform; |
753 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 915 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
754 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 916 | struct snd_soc_dai *codec_dai; |
755 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 917 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
918 | int i; | ||
756 | 919 | ||
757 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 920 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
758 | 921 | ||
@@ -763,16 +926,22 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
763 | cpu_dai->sample_bits = 0; | 926 | cpu_dai->sample_bits = 0; |
764 | } | 927 | } |
765 | 928 | ||
766 | if (codec_dai->active == 1) { | 929 | for (i = 0; i < rtd->num_codecs; i++) { |
767 | codec_dai->rate = 0; | 930 | codec_dai = rtd->codec_dais[i]; |
768 | codec_dai->channels = 0; | 931 | if (codec_dai->active == 1) { |
769 | codec_dai->sample_bits = 0; | 932 | codec_dai->rate = 0; |
933 | codec_dai->channels = 0; | ||
934 | codec_dai->sample_bits = 0; | ||
935 | } | ||
770 | } | 936 | } |
771 | 937 | ||
772 | /* apply codec digital mute */ | 938 | /* apply codec digital mute */ |
773 | if ((playback && codec_dai->playback_active == 1) || | 939 | for (i = 0; i < rtd->num_codecs; i++) { |
774 | (!playback && codec_dai->capture_active == 1)) | 940 | if ((playback && rtd->codec_dais[i]->playback_active == 1) || |
775 | snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); | 941 | (!playback && rtd->codec_dais[i]->capture_active == 1)) |
942 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 1, | ||
943 | substream->stream); | ||
944 | } | ||
776 | 945 | ||
777 | /* free any machine hw params */ | 946 | /* free any machine hw params */ |
778 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 947 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
@@ -783,8 +952,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
783 | platform->driver->ops->hw_free(substream); | 952 | platform->driver->ops->hw_free(substream); |
784 | 953 | ||
785 | /* now free hw params for the DAIs */ | 954 | /* now free hw params for the DAIs */ |
786 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | 955 | for (i = 0; i < rtd->num_codecs; i++) { |
787 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 956 | codec_dai = rtd->codec_dais[i]; |
957 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) | ||
958 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
959 | } | ||
788 | 960 | ||
789 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) | 961 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) |
790 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 962 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
@@ -798,13 +970,17 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
798 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 970 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
799 | struct snd_soc_platform *platform = rtd->platform; | 971 | struct snd_soc_platform *platform = rtd->platform; |
800 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 972 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
801 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 973 | struct snd_soc_dai *codec_dai; |
802 | int ret; | 974 | int i, ret; |
803 | 975 | ||
804 | if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) { | 976 | for (i = 0; i < rtd->num_codecs; i++) { |
805 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); | 977 | codec_dai = rtd->codec_dais[i]; |
806 | if (ret < 0) | 978 | if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) { |
807 | return ret; | 979 | ret = codec_dai->driver->ops->trigger(substream, |
980 | cmd, codec_dai); | ||
981 | if (ret < 0) | ||
982 | return ret; | ||
983 | } | ||
808 | } | 984 | } |
809 | 985 | ||
810 | if (platform->driver->ops && platform->driver->ops->trigger) { | 986 | if (platform->driver->ops && platform->driver->ops->trigger) { |
@@ -834,14 +1010,18 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
834 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1010 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
835 | struct snd_soc_platform *platform = rtd->platform; | 1011 | struct snd_soc_platform *platform = rtd->platform; |
836 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1012 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
837 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 1013 | struct snd_soc_dai *codec_dai; |
838 | int ret; | 1014 | int i, ret; |
839 | 1015 | ||
840 | if (codec_dai->driver->ops && | 1016 | for (i = 0; i < rtd->num_codecs; i++) { |
841 | codec_dai->driver->ops->bespoke_trigger) { | 1017 | codec_dai = rtd->codec_dais[i]; |
842 | ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai); | 1018 | if (codec_dai->driver->ops && |
843 | if (ret < 0) | 1019 | codec_dai->driver->ops->bespoke_trigger) { |
844 | return ret; | 1020 | ret = codec_dai->driver->ops->bespoke_trigger(substream, |
1021 | cmd, codec_dai); | ||
1022 | if (ret < 0) | ||
1023 | return ret; | ||
1024 | } | ||
845 | } | 1025 | } |
846 | 1026 | ||
847 | if (platform->driver->bespoke_trigger) { | 1027 | if (platform->driver->bespoke_trigger) { |
@@ -867,10 +1047,12 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
867 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1047 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
868 | struct snd_soc_platform *platform = rtd->platform; | 1048 | struct snd_soc_platform *platform = rtd->platform; |
869 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1049 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
870 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 1050 | struct snd_soc_dai *codec_dai; |
871 | struct snd_pcm_runtime *runtime = substream->runtime; | 1051 | struct snd_pcm_runtime *runtime = substream->runtime; |
872 | snd_pcm_uframes_t offset = 0; | 1052 | snd_pcm_uframes_t offset = 0; |
873 | snd_pcm_sframes_t delay = 0; | 1053 | snd_pcm_sframes_t delay = 0; |
1054 | snd_pcm_sframes_t codec_delay = 0; | ||
1055 | int i; | ||
874 | 1056 | ||
875 | if (platform->driver->ops && platform->driver->ops->pointer) | 1057 | if (platform->driver->ops && platform->driver->ops->pointer) |
876 | offset = platform->driver->ops->pointer(substream); | 1058 | offset = platform->driver->ops->pointer(substream); |
@@ -878,11 +1060,21 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
878 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) | 1060 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) |
879 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | 1061 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); |
880 | 1062 | ||
881 | if (codec_dai->driver->ops && codec_dai->driver->ops->delay) | 1063 | for (i = 0; i < rtd->num_codecs; i++) { |
882 | delay += codec_dai->driver->ops->delay(substream, codec_dai); | 1064 | codec_dai = rtd->codec_dais[i]; |
1065 | if (codec_dai->driver->ops && codec_dai->driver->ops->delay) | ||
1066 | codec_delay = max(codec_delay, | ||
1067 | codec_dai->driver->ops->delay(substream, | ||
1068 | codec_dai)); | ||
1069 | } | ||
1070 | delay += codec_delay; | ||
883 | 1071 | ||
1072 | /* | ||
1073 | * None of the existing platform drivers implement delay(), so | ||
1074 | * for now the codec_dai of first multicodec entry is used | ||
1075 | */ | ||
884 | if (platform->driver->delay) | 1076 | if (platform->driver->delay) |
885 | delay += platform->driver->delay(substream, codec_dai); | 1077 | delay += platform->driver->delay(substream, rtd->codec_dais[0]); |
886 | 1078 | ||
887 | runtime->delay = delay; | 1079 | runtime->delay = delay; |
888 | 1080 | ||
@@ -985,7 +1177,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
985 | struct snd_soc_dapm_widget *widget, int stream) | 1177 | struct snd_soc_dapm_widget *widget, int stream) |
986 | { | 1178 | { |
987 | struct snd_soc_pcm_runtime *be; | 1179 | struct snd_soc_pcm_runtime *be; |
988 | int i; | 1180 | int i, j; |
989 | 1181 | ||
990 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1182 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
991 | for (i = 0; i < card->num_links; i++) { | 1183 | for (i = 0; i < card->num_links; i++) { |
@@ -994,9 +1186,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
994 | if (!be->dai_link->no_pcm) | 1186 | if (!be->dai_link->no_pcm) |
995 | continue; | 1187 | continue; |
996 | 1188 | ||
997 | if (be->cpu_dai->playback_widget == widget || | 1189 | if (be->cpu_dai->playback_widget == widget) |
998 | be->codec_dai->playback_widget == widget) | ||
999 | return be; | 1190 | return be; |
1191 | |||
1192 | for (j = 0; j < be->num_codecs; j++) { | ||
1193 | struct snd_soc_dai *dai = be->codec_dais[j]; | ||
1194 | if (dai->playback_widget == widget) | ||
1195 | return be; | ||
1196 | } | ||
1000 | } | 1197 | } |
1001 | } else { | 1198 | } else { |
1002 | 1199 | ||
@@ -1006,9 +1203,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
1006 | if (!be->dai_link->no_pcm) | 1203 | if (!be->dai_link->no_pcm) |
1007 | continue; | 1204 | continue; |
1008 | 1205 | ||
1009 | if (be->cpu_dai->capture_widget == widget || | 1206 | if (be->cpu_dai->capture_widget == widget) |
1010 | be->codec_dai->capture_widget == widget) | ||
1011 | return be; | 1207 | return be; |
1208 | |||
1209 | for (j = 0; j < be->num_codecs; j++) { | ||
1210 | struct snd_soc_dai *dai = be->codec_dais[j]; | ||
1211 | if (dai->capture_widget == widget) | ||
1212 | return be; | ||
1213 | } | ||
1012 | } | 1214 | } |
1013 | } | 1215 | } |
1014 | 1216 | ||
@@ -1071,6 +1273,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1071 | 1273 | ||
1072 | /* Destroy any old FE <--> BE connections */ | 1274 | /* Destroy any old FE <--> BE connections */ |
1073 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1275 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { |
1276 | unsigned int i; | ||
1074 | 1277 | ||
1075 | /* is there a valid CPU DAI widget for this BE */ | 1278 | /* is there a valid CPU DAI widget for this BE */ |
1076 | widget = dai_get_widget(dpcm->be->cpu_dai, stream); | 1279 | widget = dai_get_widget(dpcm->be->cpu_dai, stream); |
@@ -1080,11 +1283,14 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1080 | continue; | 1283 | continue; |
1081 | 1284 | ||
1082 | /* is there a valid CODEC DAI widget for this BE */ | 1285 | /* is there a valid CODEC DAI widget for this BE */ |
1083 | widget = dai_get_widget(dpcm->be->codec_dai, stream); | 1286 | for (i = 0; i < dpcm->be->num_codecs; i++) { |
1287 | struct snd_soc_dai *dai = dpcm->be->codec_dais[i]; | ||
1288 | widget = dai_get_widget(dai, stream); | ||
1084 | 1289 | ||
1085 | /* prune the BE if it's no longer in our active list */ | 1290 | /* prune the BE if it's no longer in our active list */ |
1086 | if (widget && widget_in_list(list, widget)) | 1291 | if (widget && widget_in_list(list, widget)) |
1087 | continue; | 1292 | continue; |
1293 | } | ||
1088 | 1294 | ||
1089 | dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n", | 1295 | dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n", |
1090 | stream ? "capture" : "playback", | 1296 | stream ? "capture" : "playback", |
@@ -2069,6 +2275,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) | |||
2069 | dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); | 2275 | dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); |
2070 | } | 2276 | } |
2071 | 2277 | ||
2278 | dpcm_path_put(&list); | ||
2072 | capture: | 2279 | capture: |
2073 | /* skip if FE doesn't have capture capability */ | 2280 | /* skip if FE doesn't have capture capability */ |
2074 | if (!fe->cpu_dai->driver->capture.channels_min) | 2281 | if (!fe->cpu_dai->driver->capture.channels_min) |
@@ -2113,16 +2320,22 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) | |||
2113 | list_for_each_entry(dpcm, clients, list_be) { | 2320 | list_for_each_entry(dpcm, clients, list_be) { |
2114 | 2321 | ||
2115 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2322 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2116 | struct snd_soc_dai *dai = be->codec_dai; | 2323 | int i; |
2117 | struct snd_soc_dai_driver *drv = dai->driver; | ||
2118 | 2324 | ||
2119 | if (be->dai_link->ignore_suspend) | 2325 | if (be->dai_link->ignore_suspend) |
2120 | continue; | 2326 | continue; |
2121 | 2327 | ||
2122 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name); | 2328 | for (i = 0; i < be->num_codecs; i++) { |
2329 | struct snd_soc_dai *dai = be->codec_dais[i]; | ||
2330 | struct snd_soc_dai_driver *drv = dai->driver; | ||
2331 | |||
2332 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", | ||
2333 | be->dai_link->name); | ||
2123 | 2334 | ||
2124 | if (drv->ops && drv->ops->digital_mute && dai->playback_active) | 2335 | if (drv->ops && drv->ops->digital_mute && |
2125 | drv->ops->digital_mute(dai, mute); | 2336 | dai->playback_active) |
2337 | drv->ops->digital_mute(dai, mute); | ||
2338 | } | ||
2126 | } | 2339 | } |
2127 | 2340 | ||
2128 | return 0; | 2341 | return 0; |
@@ -2187,22 +2400,27 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2187 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | 2400 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
2188 | { | 2401 | { |
2189 | struct snd_soc_platform *platform = rtd->platform; | 2402 | struct snd_soc_platform *platform = rtd->platform; |
2190 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 2403 | struct snd_soc_dai *codec_dai; |
2191 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2404 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2192 | struct snd_pcm *pcm; | 2405 | struct snd_pcm *pcm; |
2193 | char new_name[64]; | 2406 | char new_name[64]; |
2194 | int ret = 0, playback = 0, capture = 0; | 2407 | int ret = 0, playback = 0, capture = 0; |
2408 | int i; | ||
2195 | 2409 | ||
2196 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { | 2410 | if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { |
2197 | playback = rtd->dai_link->dpcm_playback; | 2411 | playback = rtd->dai_link->dpcm_playback; |
2198 | capture = rtd->dai_link->dpcm_capture; | 2412 | capture = rtd->dai_link->dpcm_capture; |
2199 | } else { | 2413 | } else { |
2200 | if (codec_dai->driver->playback.channels_min && | 2414 | for (i = 0; i < rtd->num_codecs; i++) { |
2201 | cpu_dai->driver->playback.channels_min) | 2415 | codec_dai = rtd->codec_dais[i]; |
2202 | playback = 1; | 2416 | if (codec_dai->driver->playback.channels_min) |
2203 | if (codec_dai->driver->capture.channels_min && | 2417 | playback = 1; |
2204 | cpu_dai->driver->capture.channels_min) | 2418 | if (codec_dai->driver->capture.channels_min) |
2205 | capture = 1; | 2419 | capture = 1; |
2420 | } | ||
2421 | |||
2422 | capture = capture && cpu_dai->driver->capture.channels_min; | ||
2423 | playback = playback && cpu_dai->driver->playback.channels_min; | ||
2206 | } | 2424 | } |
2207 | 2425 | ||
2208 | if (rtd->dai_link->playback_only) { | 2426 | if (rtd->dai_link->playback_only) { |
@@ -2228,7 +2446,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2228 | rtd->dai_link->stream_name); | 2446 | rtd->dai_link->stream_name); |
2229 | else | 2447 | else |
2230 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | 2448 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
2231 | rtd->dai_link->stream_name, codec_dai->name, num); | 2449 | rtd->dai_link->stream_name, |
2450 | (rtd->num_codecs > 1) ? | ||
2451 | "multicodec" : rtd->codec_dai->name, num); | ||
2232 | 2452 | ||
2233 | ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, | 2453 | ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, |
2234 | capture, &pcm); | 2454 | capture, &pcm); |
@@ -2301,8 +2521,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2301 | 2521 | ||
2302 | pcm->private_free = platform->driver->pcm_free; | 2522 | pcm->private_free = platform->driver->pcm_free; |
2303 | out: | 2523 | out: |
2304 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name, | 2524 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", |
2305 | cpu_dai->name); | 2525 | (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, |
2526 | cpu_dai->name); | ||
2306 | return ret; | 2527 | return ret; |
2307 | } | 2528 | } |
2308 | 2529 | ||
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 02734bd4f09b..a83aff09dce2 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c | |||
@@ -41,8 +41,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, | |||
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
44 | struct snd_soc_codec *codec = codec_dai->codec; | 44 | struct snd_soc_card *card = rtd->card; |
45 | struct snd_soc_card *card = codec->card; | ||
46 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); | 45 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); |
47 | int srate, mclk; | 46 | int srate, mclk; |
48 | int err; | 47 | int err; |
@@ -105,7 +104,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
105 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 104 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
106 | struct snd_soc_codec *codec = codec_dai->codec; | 105 | struct snd_soc_codec *codec = codec_dai->codec; |
107 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 106 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
108 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); | 107 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card); |
109 | 108 | ||
110 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, | 109 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, |
111 | &tegra_alc5632_hs_jack); | 110 | &tegra_alc5632_hs_jack); |
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index ce73e1f62c4b..b86cd9936ef1 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c | |||
@@ -49,8 +49,7 @@ static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, | |||
49 | { | 49 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
52 | struct snd_soc_codec *codec = codec_dai->codec; | 52 | struct snd_soc_card *card = rtd->card; |
53 | struct snd_soc_card *card = codec->card; | ||
54 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); | 53 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); |
55 | int srate, mclk; | 54 | int srate, mclk; |
56 | int err; | 55 | int err; |
@@ -127,7 +126,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
127 | { | 126 | { |
128 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 127 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
129 | struct snd_soc_codec *codec = codec_dai->codec; | 128 | struct snd_soc_codec *codec = codec_dai->codec; |
130 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card); | 129 | struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card); |
131 | 130 | ||
132 | if (gpio_is_valid(machine->gpio_hp_det)) { | 131 | if (gpio_is_valid(machine->gpio_hp_det)) { |
133 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | 132 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, |
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 4feb16a99e02..a6898831fb9f 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c | |||
@@ -51,8 +51,7 @@ static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream, | |||
51 | { | 51 | { |
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
54 | struct snd_soc_codec *codec = codec_dai->codec; | 54 | struct snd_soc_card *card = rtd->card; |
55 | struct snd_soc_card *card = codec->card; | ||
56 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); | 55 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); |
57 | int srate, mclk; | 56 | int srate, mclk; |
58 | int err; | 57 | int err; |
@@ -110,7 +109,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
110 | { | 109 | { |
111 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 110 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
112 | struct snd_soc_codec *codec = codec_dai->codec; | 111 | struct snd_soc_codec *codec = codec_dai->codec; |
113 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card); | 112 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card); |
114 | 113 | ||
115 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | 114 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, |
116 | &tegra_rt5640_hp_jack); | 115 | &tegra_rt5640_hp_jack); |
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 8e774d1a243c..769e28f6642e 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c | |||
@@ -55,8 +55,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, | |||
55 | { | 55 | { |
56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
57 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 57 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
58 | struct snd_soc_codec *codec = codec_dai->codec; | 58 | struct snd_soc_card *card = rtd->card; |
59 | struct snd_soc_card *card = codec->card; | ||
60 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); | 59 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); |
61 | int srate, mclk; | 60 | int srate, mclk; |
62 | int err; | 61 | int err; |
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0939661df60b..86e05e938585 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -60,8 +60,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | |||
60 | { | 60 | { |
61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
63 | struct snd_soc_codec *codec = codec_dai->codec; | 63 | struct snd_soc_card *card = rtd->card; |
64 | struct snd_soc_card *card = codec->card; | ||
65 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 64 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
66 | int srate, mclk; | 65 | int srate, mclk; |
67 | int err; | 66 | int err; |
@@ -173,7 +172,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
173 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 172 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
174 | struct snd_soc_codec *codec = codec_dai->codec; | 173 | struct snd_soc_codec *codec = codec_dai->codec; |
175 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 174 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
176 | struct snd_soc_card *card = codec->card; | 175 | struct snd_soc_card *card = rtd->card; |
177 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 176 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
178 | 177 | ||
179 | if (gpio_is_valid(machine->gpio_hp_det)) { | 178 | if (gpio_is_valid(machine->gpio_hp_det)) { |
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 734bfcd21148..589d2d9b553a 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c | |||
@@ -50,8 +50,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, | |||
50 | { | 50 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | struct snd_soc_codec *codec = codec_dai->codec; | 53 | struct snd_soc_card *card = rtd->card; |
54 | struct snd_soc_card *card = codec->card; | ||
55 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); | 54 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); |
56 | int srate, mclk; | 55 | int srate, mclk; |
57 | int err; | 56 | int err; |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index be1b1aa96b7e..b2c3d0d5dca3 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -2534,12 +2534,10 @@ static int snd_dbri_create(struct snd_card *card, | |||
2534 | dbri->op = op; | 2534 | dbri->op = op; |
2535 | dbri->irq = irq; | 2535 | dbri->irq = irq; |
2536 | 2536 | ||
2537 | dbri->dma = dma_alloc_coherent(&op->dev, | 2537 | dbri->dma = dma_zalloc_coherent(&op->dev, sizeof(struct dbri_dma), |
2538 | sizeof(struct dbri_dma), | 2538 | &dbri->dma_dvma, GFP_ATOMIC); |
2539 | &dbri->dma_dvma, GFP_ATOMIC); | ||
2540 | if (!dbri->dma) | 2539 | if (!dbri->dma) |
2541 | return -ENOMEM; | 2540 | return -ENOMEM; |
2542 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); | ||
2543 | 2541 | ||
2544 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", | 2542 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", |
2545 | dbri->dma, dbri->dma_dvma); | 2543 | dbri->dma, dbri->dma_dvma); |
diff --git a/sound/usb/card.c b/sound/usb/card.c index a09e5f3519e3..7ecd0e8a5c51 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -680,6 +680,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | |||
680 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | 680 | struct snd_usb_audio *chip = usb_get_intfdata(intf); |
681 | struct snd_usb_stream *as; | 681 | struct snd_usb_stream *as; |
682 | struct usb_mixer_interface *mixer; | 682 | struct usb_mixer_interface *mixer; |
683 | struct list_head *p; | ||
683 | 684 | ||
684 | if (chip == (void *)-1L) | 685 | if (chip == (void *)-1L) |
685 | return 0; | 686 | return 0; |
@@ -692,6 +693,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | |||
692 | as->substream[0].need_setup_ep = | 693 | as->substream[0].need_setup_ep = |
693 | as->substream[1].need_setup_ep = true; | 694 | as->substream[1].need_setup_ep = true; |
694 | } | 695 | } |
696 | list_for_each(p, &chip->midi_list) { | ||
697 | snd_usbmidi_suspend(p); | ||
698 | } | ||
695 | } | 699 | } |
696 | } else { | 700 | } else { |
697 | /* | 701 | /* |
@@ -713,6 +717,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) | |||
713 | { | 717 | { |
714 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | 718 | struct snd_usb_audio *chip = usb_get_intfdata(intf); |
715 | struct usb_mixer_interface *mixer; | 719 | struct usb_mixer_interface *mixer; |
720 | struct list_head *p; | ||
716 | int err = 0; | 721 | int err = 0; |
717 | 722 | ||
718 | if (chip == (void *)-1L) | 723 | if (chip == (void *)-1L) |
@@ -731,6 +736,10 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) | |||
731 | goto err_out; | 736 | goto err_out; |
732 | } | 737 | } |
733 | 738 | ||
739 | list_for_each(p, &chip->midi_list) { | ||
740 | snd_usbmidi_resume(p); | ||
741 | } | ||
742 | |||
734 | if (!chip->autosuspended) | 743 | if (!chip->autosuspended) |
735 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); | 744 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); |
736 | chip->autosuspended = 0; | 745 | chip->autosuspended = 0; |
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 9da74d2e8eee..7b166c2be0f7 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -102,8 +102,8 @@ struct usb_protocol_ops { | |||
102 | void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int); | 102 | void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int); |
103 | void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb); | 103 | void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb); |
104 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); | 104 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); |
105 | void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*); | 105 | void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint *); |
106 | void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*); | 106 | void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint *); |
107 | }; | 107 | }; |
108 | 108 | ||
109 | struct snd_usb_midi { | 109 | struct snd_usb_midi { |
@@ -112,7 +112,7 @@ struct snd_usb_midi { | |||
112 | struct usb_interface *iface; | 112 | struct usb_interface *iface; |
113 | const struct snd_usb_audio_quirk *quirk; | 113 | const struct snd_usb_audio_quirk *quirk; |
114 | struct snd_rawmidi *rmidi; | 114 | struct snd_rawmidi *rmidi; |
115 | struct usb_protocol_ops* usb_protocol_ops; | 115 | struct usb_protocol_ops *usb_protocol_ops; |
116 | struct list_head list; | 116 | struct list_head list; |
117 | struct timer_list error_timer; | 117 | struct timer_list error_timer; |
118 | spinlock_t disc_lock; | 118 | spinlock_t disc_lock; |
@@ -134,7 +134,7 @@ struct snd_usb_midi { | |||
134 | }; | 134 | }; |
135 | 135 | ||
136 | struct snd_usb_midi_out_endpoint { | 136 | struct snd_usb_midi_out_endpoint { |
137 | struct snd_usb_midi* umidi; | 137 | struct snd_usb_midi *umidi; |
138 | struct out_urb_context { | 138 | struct out_urb_context { |
139 | struct urb *urb; | 139 | struct urb *urb; |
140 | struct snd_usb_midi_out_endpoint *ep; | 140 | struct snd_usb_midi_out_endpoint *ep; |
@@ -147,7 +147,7 @@ struct snd_usb_midi_out_endpoint { | |||
147 | spinlock_t buffer_lock; | 147 | spinlock_t buffer_lock; |
148 | 148 | ||
149 | struct usbmidi_out_port { | 149 | struct usbmidi_out_port { |
150 | struct snd_usb_midi_out_endpoint* ep; | 150 | struct snd_usb_midi_out_endpoint *ep; |
151 | struct snd_rawmidi_substream *substream; | 151 | struct snd_rawmidi_substream *substream; |
152 | int active; | 152 | int active; |
153 | uint8_t cable; /* cable number << 4 */ | 153 | uint8_t cable; /* cable number << 4 */ |
@@ -167,8 +167,8 @@ struct snd_usb_midi_out_endpoint { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | struct snd_usb_midi_in_endpoint { | 169 | struct snd_usb_midi_in_endpoint { |
170 | struct snd_usb_midi* umidi; | 170 | struct snd_usb_midi *umidi; |
171 | struct urb* urbs[INPUT_URBS]; | 171 | struct urb *urbs[INPUT_URBS]; |
172 | struct usbmidi_in_port { | 172 | struct usbmidi_in_port { |
173 | struct snd_rawmidi_substream *substream; | 173 | struct snd_rawmidi_substream *substream; |
174 | u8 running_status_length; | 174 | u8 running_status_length; |
@@ -178,7 +178,7 @@ struct snd_usb_midi_in_endpoint { | |||
178 | int current_port; | 178 | int current_port; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep); | 181 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep); |
182 | 182 | ||
183 | static const uint8_t snd_usbmidi_cin_length[] = { | 183 | static const uint8_t snd_usbmidi_cin_length[] = { |
184 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | 184 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 |
@@ -187,7 +187,7 @@ static const uint8_t snd_usbmidi_cin_length[] = { | |||
187 | /* | 187 | /* |
188 | * Submits the URB, with error handling. | 188 | * Submits the URB, with error handling. |
189 | */ | 189 | */ |
190 | static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags) | 190 | static int snd_usbmidi_submit_urb(struct urb *urb, gfp_t flags) |
191 | { | 191 | { |
192 | int err = usb_submit_urb(urb, flags); | 192 | int err = usb_submit_urb(urb, flags); |
193 | if (err < 0 && err != -ENODEV) | 193 | if (err < 0 && err != -ENODEV) |
@@ -221,10 +221,10 @@ static int snd_usbmidi_urb_error(const struct urb *urb) | |||
221 | /* | 221 | /* |
222 | * Receives a chunk of MIDI data. | 222 | * Receives a chunk of MIDI data. |
223 | */ | 223 | */ |
224 | static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int portidx, | 224 | static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint *ep, |
225 | uint8_t* data, int length) | 225 | int portidx, uint8_t *data, int length) |
226 | { | 226 | { |
227 | struct usbmidi_in_port* port = &ep->ports[portidx]; | 227 | struct usbmidi_in_port *port = &ep->ports[portidx]; |
228 | 228 | ||
229 | if (!port->substream) { | 229 | if (!port->substream) { |
230 | dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!\n", portidx); | 230 | dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!\n", portidx); |
@@ -250,9 +250,9 @@ static void dump_urb(const char *type, const u8 *data, int length) | |||
250 | /* | 250 | /* |
251 | * Processes the data read from the device. | 251 | * Processes the data read from the device. |
252 | */ | 252 | */ |
253 | static void snd_usbmidi_in_urb_complete(struct urb* urb) | 253 | static void snd_usbmidi_in_urb_complete(struct urb *urb) |
254 | { | 254 | { |
255 | struct snd_usb_midi_in_endpoint* ep = urb->context; | 255 | struct snd_usb_midi_in_endpoint *ep = urb->context; |
256 | 256 | ||
257 | if (urb->status == 0) { | 257 | if (urb->status == 0) { |
258 | dump_urb("received", urb->transfer_buffer, urb->actual_length); | 258 | dump_urb("received", urb->transfer_buffer, urb->actual_length); |
@@ -274,10 +274,10 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb) | |||
274 | snd_usbmidi_submit_urb(urb, GFP_ATOMIC); | 274 | snd_usbmidi_submit_urb(urb, GFP_ATOMIC); |
275 | } | 275 | } |
276 | 276 | ||
277 | static void snd_usbmidi_out_urb_complete(struct urb* urb) | 277 | static void snd_usbmidi_out_urb_complete(struct urb *urb) |
278 | { | 278 | { |
279 | struct out_urb_context *context = urb->context; | 279 | struct out_urb_context *context = urb->context; |
280 | struct snd_usb_midi_out_endpoint* ep = context->ep; | 280 | struct snd_usb_midi_out_endpoint *ep = context->ep; |
281 | unsigned int urb_index; | 281 | unsigned int urb_index; |
282 | 282 | ||
283 | spin_lock(&ep->buffer_lock); | 283 | spin_lock(&ep->buffer_lock); |
@@ -304,10 +304,10 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb) | |||
304 | * This is called when some data should be transferred to the device | 304 | * This is called when some data should be transferred to the device |
305 | * (from one or more substreams). | 305 | * (from one or more substreams). |
306 | */ | 306 | */ |
307 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep) | 307 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep) |
308 | { | 308 | { |
309 | unsigned int urb_index; | 309 | unsigned int urb_index; |
310 | struct urb* urb; | 310 | struct urb *urb; |
311 | unsigned long flags; | 311 | unsigned long flags; |
312 | 312 | ||
313 | spin_lock_irqsave(&ep->buffer_lock, flags); | 313 | spin_lock_irqsave(&ep->buffer_lock, flags); |
@@ -343,7 +343,8 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep) | |||
343 | 343 | ||
344 | static void snd_usbmidi_out_tasklet(unsigned long data) | 344 | static void snd_usbmidi_out_tasklet(unsigned long data) |
345 | { | 345 | { |
346 | struct snd_usb_midi_out_endpoint* ep = (struct snd_usb_midi_out_endpoint *) data; | 346 | struct snd_usb_midi_out_endpoint *ep = |
347 | (struct snd_usb_midi_out_endpoint *) data; | ||
347 | 348 | ||
348 | snd_usbmidi_do_output(ep); | 349 | snd_usbmidi_do_output(ep); |
349 | } | 350 | } |
@@ -375,7 +376,7 @@ static void snd_usbmidi_error_timer(unsigned long data) | |||
375 | } | 376 | } |
376 | 377 | ||
377 | /* helper function to send static data that may not DMA-able */ | 378 | /* helper function to send static data that may not DMA-able */ |
378 | static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep, | 379 | static int send_bulk_static_data(struct snd_usb_midi_out_endpoint *ep, |
379 | const void *data, int len) | 380 | const void *data, int len) |
380 | { | 381 | { |
381 | int err = 0; | 382 | int err = 0; |
@@ -396,8 +397,8 @@ static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep, | |||
396 | * fourth byte in each packet, and uses length instead of CIN. | 397 | * fourth byte in each packet, and uses length instead of CIN. |
397 | */ | 398 | */ |
398 | 399 | ||
399 | static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep, | 400 | static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint *ep, |
400 | uint8_t* buffer, int buffer_length) | 401 | uint8_t *buffer, int buffer_length) |
401 | { | 402 | { |
402 | int i; | 403 | int i; |
403 | 404 | ||
@@ -405,12 +406,13 @@ static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep, | |||
405 | if (buffer[i] != 0) { | 406 | if (buffer[i] != 0) { |
406 | int cable = buffer[i] >> 4; | 407 | int cable = buffer[i] >> 4; |
407 | int length = snd_usbmidi_cin_length[buffer[i] & 0x0f]; | 408 | int length = snd_usbmidi_cin_length[buffer[i] & 0x0f]; |
408 | snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); | 409 | snd_usbmidi_input_data(ep, cable, &buffer[i + 1], |
410 | length); | ||
409 | } | 411 | } |
410 | } | 412 | } |
411 | 413 | ||
412 | static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep, | 414 | static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint *ep, |
413 | uint8_t* buffer, int buffer_length) | 415 | uint8_t *buffer, int buffer_length) |
414 | { | 416 | { |
415 | int i; | 417 | int i; |
416 | 418 | ||
@@ -427,8 +429,8 @@ static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep, | |||
427 | * the data bytes but not the status byte and that is marked with CIN 4. | 429 | * the data bytes but not the status byte and that is marked with CIN 4. |
428 | */ | 430 | */ |
429 | static void snd_usbmidi_maudio_broken_running_status_input( | 431 | static void snd_usbmidi_maudio_broken_running_status_input( |
430 | struct snd_usb_midi_in_endpoint* ep, | 432 | struct snd_usb_midi_in_endpoint *ep, |
431 | uint8_t* buffer, int buffer_length) | 433 | uint8_t *buffer, int buffer_length) |
432 | { | 434 | { |
433 | int i; | 435 | int i; |
434 | 436 | ||
@@ -458,7 +460,8 @@ static void snd_usbmidi_maudio_broken_running_status_input( | |||
458 | * doesn't use this format.) | 460 | * doesn't use this format.) |
459 | */ | 461 | */ |
460 | port->running_status_length = 0; | 462 | port->running_status_length = 0; |
461 | snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); | 463 | snd_usbmidi_input_data(ep, cable, &buffer[i + 1], |
464 | length); | ||
462 | } | 465 | } |
463 | } | 466 | } |
464 | 467 | ||
@@ -479,11 +482,13 @@ static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep, | |||
479 | /* | 482 | /* |
480 | * Adds one USB MIDI packet to the output buffer. | 483 | * Adds one USB MIDI packet to the output buffer. |
481 | */ | 484 | */ |
482 | static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, | 485 | static void snd_usbmidi_output_standard_packet(struct urb *urb, uint8_t p0, |
483 | uint8_t p1, uint8_t p2, uint8_t p3) | 486 | uint8_t p1, uint8_t p2, |
487 | uint8_t p3) | ||
484 | { | 488 | { |
485 | 489 | ||
486 | uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; | 490 | uint8_t *buf = |
491 | (uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length; | ||
487 | buf[0] = p0; | 492 | buf[0] = p0; |
488 | buf[1] = p1; | 493 | buf[1] = p1; |
489 | buf[2] = p2; | 494 | buf[2] = p2; |
@@ -494,11 +499,13 @@ static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, | |||
494 | /* | 499 | /* |
495 | * Adds one Midiman packet to the output buffer. | 500 | * Adds one Midiman packet to the output buffer. |
496 | */ | 501 | */ |
497 | static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0, | 502 | static void snd_usbmidi_output_midiman_packet(struct urb *urb, uint8_t p0, |
498 | uint8_t p1, uint8_t p2, uint8_t p3) | 503 | uint8_t p1, uint8_t p2, |
504 | uint8_t p3) | ||
499 | { | 505 | { |
500 | 506 | ||
501 | uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; | 507 | uint8_t *buf = |
508 | (uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length; | ||
502 | buf[0] = p1; | 509 | buf[0] = p1; |
503 | buf[1] = p2; | 510 | buf[1] = p2; |
504 | buf[2] = p3; | 511 | buf[2] = p3; |
@@ -509,8 +516,8 @@ static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0, | |||
509 | /* | 516 | /* |
510 | * Converts MIDI commands to USB MIDI packets. | 517 | * Converts MIDI commands to USB MIDI packets. |
511 | */ | 518 | */ |
512 | static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port, | 519 | static void snd_usbmidi_transmit_byte(struct usbmidi_out_port *port, |
513 | uint8_t b, struct urb* urb) | 520 | uint8_t b, struct urb *urb) |
514 | { | 521 | { |
515 | uint8_t p0 = port->cable; | 522 | uint8_t p0 = port->cable; |
516 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) = | 523 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) = |
@@ -547,10 +554,12 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port, | |||
547 | output_packet(urb, p0 | 0x05, 0xf7, 0, 0); | 554 | output_packet(urb, p0 | 0x05, 0xf7, 0, 0); |
548 | break; | 555 | break; |
549 | case STATE_SYSEX_1: | 556 | case STATE_SYSEX_1: |
550 | output_packet(urb, p0 | 0x06, port->data[0], 0xf7, 0); | 557 | output_packet(urb, p0 | 0x06, port->data[0], |
558 | 0xf7, 0); | ||
551 | break; | 559 | break; |
552 | case STATE_SYSEX_2: | 560 | case STATE_SYSEX_2: |
553 | output_packet(urb, p0 | 0x07, port->data[0], port->data[1], 0xf7); | 561 | output_packet(urb, p0 | 0x07, port->data[0], |
562 | port->data[1], 0xf7); | ||
554 | break; | 563 | break; |
555 | } | 564 | } |
556 | port->state = STATE_UNKNOWN; | 565 | port->state = STATE_UNKNOWN; |
@@ -596,21 +605,22 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port, | |||
596 | port->state = STATE_SYSEX_2; | 605 | port->state = STATE_SYSEX_2; |
597 | break; | 606 | break; |
598 | case STATE_SYSEX_2: | 607 | case STATE_SYSEX_2: |
599 | output_packet(urb, p0 | 0x04, port->data[0], port->data[1], b); | 608 | output_packet(urb, p0 | 0x04, port->data[0], |
609 | port->data[1], b); | ||
600 | port->state = STATE_SYSEX_0; | 610 | port->state = STATE_SYSEX_0; |
601 | break; | 611 | break; |
602 | } | 612 | } |
603 | } | 613 | } |
604 | } | 614 | } |
605 | 615 | ||
606 | static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep, | 616 | static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep, |
607 | struct urb *urb) | 617 | struct urb *urb) |
608 | { | 618 | { |
609 | int p; | 619 | int p; |
610 | 620 | ||
611 | /* FIXME: lower-numbered ports can starve higher-numbered ports */ | 621 | /* FIXME: lower-numbered ports can starve higher-numbered ports */ |
612 | for (p = 0; p < 0x10; ++p) { | 622 | for (p = 0; p < 0x10; ++p) { |
613 | struct usbmidi_out_port* port = &ep->ports[p]; | 623 | struct usbmidi_out_port *port = &ep->ports[p]; |
614 | if (!port->active) | 624 | if (!port->active) |
615 | continue; | 625 | continue; |
616 | while (urb->transfer_buffer_length + 3 < ep->max_transfer) { | 626 | while (urb->transfer_buffer_length + 3 < ep->max_transfer) { |
@@ -753,18 +763,18 @@ static struct usb_protocol_ops snd_usbmidi_akai_ops = { | |||
753 | * at the third byte. | 763 | * at the third byte. |
754 | */ | 764 | */ |
755 | 765 | ||
756 | static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep, | 766 | static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint *ep, |
757 | uint8_t* buffer, int buffer_length) | 767 | uint8_t *buffer, int buffer_length) |
758 | { | 768 | { |
759 | if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1) | 769 | if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1) |
760 | return; | 770 | return; |
761 | snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); | 771 | snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); |
762 | } | 772 | } |
763 | 773 | ||
764 | static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep, | 774 | static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint *ep, |
765 | struct urb *urb) | 775 | struct urb *urb) |
766 | { | 776 | { |
767 | uint8_t* transfer_buffer; | 777 | uint8_t *transfer_buffer; |
768 | int count; | 778 | int count; |
769 | 779 | ||
770 | if (!ep->ports[0].active) | 780 | if (!ep->ports[0].active) |
@@ -791,13 +801,13 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = { | |||
791 | * "raw" protocol: just move raw MIDI bytes from/to the endpoint | 801 | * "raw" protocol: just move raw MIDI bytes from/to the endpoint |
792 | */ | 802 | */ |
793 | 803 | ||
794 | static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep, | 804 | static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint *ep, |
795 | uint8_t* buffer, int buffer_length) | 805 | uint8_t *buffer, int buffer_length) |
796 | { | 806 | { |
797 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); | 807 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); |
798 | } | 808 | } |
799 | 809 | ||
800 | static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep, | 810 | static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint *ep, |
801 | struct urb *urb) | 811 | struct urb *urb) |
802 | { | 812 | { |
803 | int count; | 813 | int count; |
@@ -823,8 +833,8 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = { | |||
823 | * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes. | 833 | * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes. |
824 | */ | 834 | */ |
825 | 835 | ||
826 | static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep, | 836 | static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint *ep, |
827 | uint8_t* buffer, int buffer_length) | 837 | uint8_t *buffer, int buffer_length) |
828 | { | 838 | { |
829 | if (buffer_length > 2) | 839 | if (buffer_length > 2) |
830 | snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2); | 840 | snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2); |
@@ -883,7 +893,7 @@ static struct usb_protocol_ops snd_usbmidi_122l_ops = { | |||
883 | * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching. | 893 | * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching. |
884 | */ | 894 | */ |
885 | 895 | ||
886 | static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep) | 896 | static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint *ep) |
887 | { | 897 | { |
888 | static const u8 init_data[] = { | 898 | static const u8 init_data[] = { |
889 | /* initialization magic: "get version" */ | 899 | /* initialization magic: "get version" */ |
@@ -900,7 +910,7 @@ static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep) | |||
900 | send_bulk_static_data(ep, init_data, sizeof(init_data)); | 910 | send_bulk_static_data(ep, init_data, sizeof(init_data)); |
901 | } | 911 | } |
902 | 912 | ||
903 | static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep) | 913 | static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint *ep) |
904 | { | 914 | { |
905 | static const u8 finish_data[] = { | 915 | static const u8 finish_data[] = { |
906 | /* switch to patch mode with last preset */ | 916 | /* switch to patch mode with last preset */ |
@@ -916,8 +926,8 @@ static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep) | |||
916 | send_bulk_static_data(ep, finish_data, sizeof(finish_data)); | 926 | send_bulk_static_data(ep, finish_data, sizeof(finish_data)); |
917 | } | 927 | } |
918 | 928 | ||
919 | static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep, | 929 | static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint *ep, |
920 | uint8_t* buffer, int buffer_length) | 930 | uint8_t *buffer, int buffer_length) |
921 | { | 931 | { |
922 | int i; | 932 | int i; |
923 | 933 | ||
@@ -960,18 +970,18 @@ static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep, | |||
960 | } | 970 | } |
961 | } | 971 | } |
962 | 972 | ||
963 | static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep, | 973 | static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint *ep, |
964 | struct urb *urb) | 974 | struct urb *urb) |
965 | { | 975 | { |
966 | int port0 = ep->current_port; | 976 | int port0 = ep->current_port; |
967 | uint8_t* buf = urb->transfer_buffer; | 977 | uint8_t *buf = urb->transfer_buffer; |
968 | int buf_free = ep->max_transfer; | 978 | int buf_free = ep->max_transfer; |
969 | int length, i; | 979 | int length, i; |
970 | 980 | ||
971 | for (i = 0; i < 0x10; ++i) { | 981 | for (i = 0; i < 0x10; ++i) { |
972 | /* round-robin, starting at the last current port */ | 982 | /* round-robin, starting at the last current port */ |
973 | int portnum = (port0 + i) & 15; | 983 | int portnum = (port0 + i) & 15; |
974 | struct usbmidi_out_port* port = &ep->ports[portnum]; | 984 | struct usbmidi_out_port *port = &ep->ports[portnum]; |
975 | 985 | ||
976 | if (!port->active) | 986 | if (!port->active) |
977 | continue; | 987 | continue; |
@@ -1015,7 +1025,7 @@ static struct usb_protocol_ops snd_usbmidi_emagic_ops = { | |||
1015 | }; | 1025 | }; |
1016 | 1026 | ||
1017 | 1027 | ||
1018 | static void update_roland_altsetting(struct snd_usb_midi* umidi) | 1028 | static void update_roland_altsetting(struct snd_usb_midi *umidi) |
1019 | { | 1029 | { |
1020 | struct usb_interface *intf; | 1030 | struct usb_interface *intf; |
1021 | struct usb_host_interface *hostif; | 1031 | struct usb_host_interface *hostif; |
@@ -1037,7 +1047,7 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi) | |||
1037 | static int substream_open(struct snd_rawmidi_substream *substream, int dir, | 1047 | static int substream_open(struct snd_rawmidi_substream *substream, int dir, |
1038 | int open) | 1048 | int open) |
1039 | { | 1049 | { |
1040 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | 1050 | struct snd_usb_midi *umidi = substream->rmidi->private_data; |
1041 | struct snd_kcontrol *ctl; | 1051 | struct snd_kcontrol *ctl; |
1042 | 1052 | ||
1043 | down_read(&umidi->disc_rwsem); | 1053 | down_read(&umidi->disc_rwsem); |
@@ -1051,7 +1061,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, | |||
1051 | if (!umidi->opened[0] && !umidi->opened[1]) { | 1061 | if (!umidi->opened[0] && !umidi->opened[1]) { |
1052 | if (umidi->roland_load_ctl) { | 1062 | if (umidi->roland_load_ctl) { |
1053 | ctl = umidi->roland_load_ctl; | 1063 | ctl = umidi->roland_load_ctl; |
1054 | ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | 1064 | ctl->vd[0].access |= |
1065 | SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
1055 | snd_ctl_notify(umidi->card, | 1066 | snd_ctl_notify(umidi->card, |
1056 | SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); | 1067 | SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); |
1057 | update_roland_altsetting(umidi); | 1068 | update_roland_altsetting(umidi); |
@@ -1067,7 +1078,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, | |||
1067 | if (!umidi->opened[0] && !umidi->opened[1]) { | 1078 | if (!umidi->opened[0] && !umidi->opened[1]) { |
1068 | if (umidi->roland_load_ctl) { | 1079 | if (umidi->roland_load_ctl) { |
1069 | ctl = umidi->roland_load_ctl; | 1080 | ctl = umidi->roland_load_ctl; |
1070 | ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | 1081 | ctl->vd[0].access &= |
1082 | ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
1071 | snd_ctl_notify(umidi->card, | 1083 | snd_ctl_notify(umidi->card, |
1072 | SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); | 1084 | SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); |
1073 | } | 1085 | } |
@@ -1080,8 +1092,8 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, | |||
1080 | 1092 | ||
1081 | static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | 1093 | static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) |
1082 | { | 1094 | { |
1083 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | 1095 | struct snd_usb_midi *umidi = substream->rmidi->private_data; |
1084 | struct usbmidi_out_port* port = NULL; | 1096 | struct usbmidi_out_port *port = NULL; |
1085 | int i, j; | 1097 | int i, j; |
1086 | 1098 | ||
1087 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) | 1099 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) |
@@ -1106,9 +1118,11 @@ static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) | |||
1106 | return substream_open(substream, 0, 0); | 1118 | return substream_open(substream, 0, 0); |
1107 | } | 1119 | } |
1108 | 1120 | ||
1109 | static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) | 1121 | static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, |
1122 | int up) | ||
1110 | { | 1123 | { |
1111 | struct usbmidi_out_port* port = (struct usbmidi_out_port*)substream->runtime->private_data; | 1124 | struct usbmidi_out_port *port = |
1125 | (struct usbmidi_out_port *)substream->runtime->private_data; | ||
1112 | 1126 | ||
1113 | port->active = up; | 1127 | port->active = up; |
1114 | if (up) { | 1128 | if (up) { |
@@ -1125,7 +1139,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, | |||
1125 | 1139 | ||
1126 | static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) | 1140 | static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) |
1127 | { | 1141 | { |
1128 | struct usbmidi_out_port* port = substream->runtime->private_data; | 1142 | struct usbmidi_out_port *port = substream->runtime->private_data; |
1129 | struct snd_usb_midi_out_endpoint *ep = port->ep; | 1143 | struct snd_usb_midi_out_endpoint *ep = port->ep; |
1130 | unsigned int drain_urbs; | 1144 | unsigned int drain_urbs; |
1131 | DEFINE_WAIT(wait); | 1145 | DEFINE_WAIT(wait); |
@@ -1164,9 +1178,10 @@ static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) | |||
1164 | return substream_open(substream, 1, 0); | 1178 | return substream_open(substream, 1, 0); |
1165 | } | 1179 | } |
1166 | 1180 | ||
1167 | static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) | 1181 | static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, |
1182 | int up) | ||
1168 | { | 1183 | { |
1169 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | 1184 | struct snd_usb_midi *umidi = substream->rmidi->private_data; |
1170 | 1185 | ||
1171 | if (up) | 1186 | if (up) |
1172 | set_bit(substream->number, &umidi->input_triggered); | 1187 | set_bit(substream->number, &umidi->input_triggered); |
@@ -1199,7 +1214,7 @@ static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb, | |||
1199 | * Frees an input endpoint. | 1214 | * Frees an input endpoint. |
1200 | * May be called when ep hasn't been initialized completely. | 1215 | * May be called when ep hasn't been initialized completely. |
1201 | */ | 1216 | */ |
1202 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) | 1217 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint *ep) |
1203 | { | 1218 | { |
1204 | unsigned int i; | 1219 | unsigned int i; |
1205 | 1220 | ||
@@ -1213,12 +1228,12 @@ static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) | |||
1213 | /* | 1228 | /* |
1214 | * Creates an input endpoint. | 1229 | * Creates an input endpoint. |
1215 | */ | 1230 | */ |
1216 | static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | 1231 | static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi, |
1217 | struct snd_usb_midi_endpoint_info* ep_info, | 1232 | struct snd_usb_midi_endpoint_info *ep_info, |
1218 | struct snd_usb_midi_endpoint* rep) | 1233 | struct snd_usb_midi_endpoint *rep) |
1219 | { | 1234 | { |
1220 | struct snd_usb_midi_in_endpoint* ep; | 1235 | struct snd_usb_midi_in_endpoint *ep; |
1221 | void* buffer; | 1236 | void *buffer; |
1222 | unsigned int pipe; | 1237 | unsigned int pipe; |
1223 | int length; | 1238 | int length; |
1224 | unsigned int i; | 1239 | unsigned int i; |
@@ -1289,14 +1304,14 @@ static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep | |||
1289 | /* | 1304 | /* |
1290 | * Creates an output endpoint, and initializes output ports. | 1305 | * Creates an output endpoint, and initializes output ports. |
1291 | */ | 1306 | */ |
1292 | static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | 1307 | static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, |
1293 | struct snd_usb_midi_endpoint_info* ep_info, | 1308 | struct snd_usb_midi_endpoint_info *ep_info, |
1294 | struct snd_usb_midi_endpoint* rep) | 1309 | struct snd_usb_midi_endpoint *rep) |
1295 | { | 1310 | { |
1296 | struct snd_usb_midi_out_endpoint* ep; | 1311 | struct snd_usb_midi_out_endpoint *ep; |
1297 | unsigned int i; | 1312 | unsigned int i; |
1298 | unsigned int pipe; | 1313 | unsigned int pipe; |
1299 | void* buffer; | 1314 | void *buffer; |
1300 | 1315 | ||
1301 | rep->out = NULL; | 1316 | rep->out = NULL; |
1302 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 1317 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
@@ -1381,12 +1396,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | |||
1381 | /* | 1396 | /* |
1382 | * Frees everything. | 1397 | * Frees everything. |
1383 | */ | 1398 | */ |
1384 | static void snd_usbmidi_free(struct snd_usb_midi* umidi) | 1399 | static void snd_usbmidi_free(struct snd_usb_midi *umidi) |
1385 | { | 1400 | { |
1386 | int i; | 1401 | int i; |
1387 | 1402 | ||
1388 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 1403 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
1389 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 1404 | struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; |
1390 | if (ep->out) | 1405 | if (ep->out) |
1391 | snd_usbmidi_out_endpoint_delete(ep->out); | 1406 | snd_usbmidi_out_endpoint_delete(ep->out); |
1392 | if (ep->in) | 1407 | if (ep->in) |
@@ -1399,9 +1414,9 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi) | |||
1399 | /* | 1414 | /* |
1400 | * Unlinks all URBs (must be done before the usb_device is deleted). | 1415 | * Unlinks all URBs (must be done before the usb_device is deleted). |
1401 | */ | 1416 | */ |
1402 | void snd_usbmidi_disconnect(struct list_head* p) | 1417 | void snd_usbmidi_disconnect(struct list_head *p) |
1403 | { | 1418 | { |
1404 | struct snd_usb_midi* umidi; | 1419 | struct snd_usb_midi *umidi; |
1405 | unsigned int i, j; | 1420 | unsigned int i, j; |
1406 | 1421 | ||
1407 | umidi = list_entry(p, struct snd_usb_midi, list); | 1422 | umidi = list_entry(p, struct snd_usb_midi, list); |
@@ -1417,7 +1432,7 @@ void snd_usbmidi_disconnect(struct list_head* p) | |||
1417 | up_write(&umidi->disc_rwsem); | 1432 | up_write(&umidi->disc_rwsem); |
1418 | 1433 | ||
1419 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 1434 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
1420 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 1435 | struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; |
1421 | if (ep->out) | 1436 | if (ep->out) |
1422 | tasklet_kill(&ep->out->tasklet); | 1437 | tasklet_kill(&ep->out->tasklet); |
1423 | if (ep->out) { | 1438 | if (ep->out) { |
@@ -1448,16 +1463,18 @@ EXPORT_SYMBOL(snd_usbmidi_disconnect); | |||
1448 | 1463 | ||
1449 | static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi) | 1464 | static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi) |
1450 | { | 1465 | { |
1451 | struct snd_usb_midi* umidi = rmidi->private_data; | 1466 | struct snd_usb_midi *umidi = rmidi->private_data; |
1452 | snd_usbmidi_free(umidi); | 1467 | snd_usbmidi_free(umidi); |
1453 | } | 1468 | } |
1454 | 1469 | ||
1455 | static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi, | 1470 | static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi *umidi, |
1456 | int stream, int number) | 1471 | int stream, |
1472 | int number) | ||
1457 | { | 1473 | { |
1458 | struct snd_rawmidi_substream *substream; | 1474 | struct snd_rawmidi_substream *substream; |
1459 | 1475 | ||
1460 | list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams, list) { | 1476 | list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams, |
1477 | list) { | ||
1461 | if (substream->number == number) | 1478 | if (substream->number == number) |
1462 | return substream; | 1479 | return substream; |
1463 | } | 1480 | } |
@@ -1633,7 +1650,7 @@ static struct port_info { | |||
1633 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER), | 1650 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER), |
1634 | }; | 1651 | }; |
1635 | 1652 | ||
1636 | static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number) | 1653 | static struct port_info *find_port_info(struct snd_usb_midi *umidi, int number) |
1637 | { | 1654 | { |
1638 | int i; | 1655 | int i; |
1639 | 1656 | ||
@@ -1659,16 +1676,18 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, | |||
1659 | } | 1676 | } |
1660 | } | 1677 | } |
1661 | 1678 | ||
1662 | static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, | 1679 | static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, |
1663 | int stream, int number, | 1680 | int stream, int number, |
1664 | struct snd_rawmidi_substream ** rsubstream) | 1681 | struct snd_rawmidi_substream **rsubstream) |
1665 | { | 1682 | { |
1666 | struct port_info *port_info; | 1683 | struct port_info *port_info; |
1667 | const char *name_format; | 1684 | const char *name_format; |
1668 | 1685 | ||
1669 | struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); | 1686 | struct snd_rawmidi_substream *substream = |
1687 | snd_usbmidi_find_substream(umidi, stream, number); | ||
1670 | if (!substream) { | 1688 | if (!substream) { |
1671 | dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream, number); | 1689 | dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream, |
1690 | number); | ||
1672 | return; | 1691 | return; |
1673 | } | 1692 | } |
1674 | 1693 | ||
@@ -1684,21 +1703,23 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, | |||
1684 | /* | 1703 | /* |
1685 | * Creates the endpoints and their ports. | 1704 | * Creates the endpoints and their ports. |
1686 | */ | 1705 | */ |
1687 | static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi, | 1706 | static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi, |
1688 | struct snd_usb_midi_endpoint_info* endpoints) | 1707 | struct snd_usb_midi_endpoint_info *endpoints) |
1689 | { | 1708 | { |
1690 | int i, j, err; | 1709 | int i, j, err; |
1691 | int out_ports = 0, in_ports = 0; | 1710 | int out_ports = 0, in_ports = 0; |
1692 | 1711 | ||
1693 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 1712 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
1694 | if (endpoints[i].out_cables) { | 1713 | if (endpoints[i].out_cables) { |
1695 | err = snd_usbmidi_out_endpoint_create(umidi, &endpoints[i], | 1714 | err = snd_usbmidi_out_endpoint_create(umidi, |
1715 | &endpoints[i], | ||
1696 | &umidi->endpoints[i]); | 1716 | &umidi->endpoints[i]); |
1697 | if (err < 0) | 1717 | if (err < 0) |
1698 | return err; | 1718 | return err; |
1699 | } | 1719 | } |
1700 | if (endpoints[i].in_cables) { | 1720 | if (endpoints[i].in_cables) { |
1701 | err = snd_usbmidi_in_endpoint_create(umidi, &endpoints[i], | 1721 | err = snd_usbmidi_in_endpoint_create(umidi, |
1722 | &endpoints[i], | ||
1702 | &umidi->endpoints[i]); | 1723 | &umidi->endpoints[i]); |
1703 | if (err < 0) | 1724 | if (err < 0) |
1704 | return err; | 1725 | return err; |
@@ -1706,12 +1727,16 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi, | |||
1706 | 1727 | ||
1707 | for (j = 0; j < 0x10; ++j) { | 1728 | for (j = 0; j < 0x10; ++j) { |
1708 | if (endpoints[i].out_cables & (1 << j)) { | 1729 | if (endpoints[i].out_cables & (1 << j)) { |
1709 | snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, out_ports, | 1730 | snd_usbmidi_init_substream(umidi, |
1731 | SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
1732 | out_ports, | ||
1710 | &umidi->endpoints[i].out->ports[j].substream); | 1733 | &umidi->endpoints[i].out->ports[j].substream); |
1711 | ++out_ports; | 1734 | ++out_ports; |
1712 | } | 1735 | } |
1713 | if (endpoints[i].in_cables & (1 << j)) { | 1736 | if (endpoints[i].in_cables & (1 << j)) { |
1714 | snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, in_ports, | 1737 | snd_usbmidi_init_substream(umidi, |
1738 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
1739 | in_ports, | ||
1715 | &umidi->endpoints[i].in->ports[j].substream); | 1740 | &umidi->endpoints[i].in->ports[j].substream); |
1716 | ++in_ports; | 1741 | ++in_ports; |
1717 | } | 1742 | } |
@@ -1725,16 +1750,16 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi, | |||
1725 | /* | 1750 | /* |
1726 | * Returns MIDIStreaming device capabilities. | 1751 | * Returns MIDIStreaming device capabilities. |
1727 | */ | 1752 | */ |
1728 | static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | 1753 | static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, |
1729 | struct snd_usb_midi_endpoint_info* endpoints) | 1754 | struct snd_usb_midi_endpoint_info *endpoints) |
1730 | { | 1755 | { |
1731 | struct usb_interface* intf; | 1756 | struct usb_interface *intf; |
1732 | struct usb_host_interface *hostif; | 1757 | struct usb_host_interface *hostif; |
1733 | struct usb_interface_descriptor* intfd; | 1758 | struct usb_interface_descriptor *intfd; |
1734 | struct usb_ms_header_descriptor* ms_header; | 1759 | struct usb_ms_header_descriptor *ms_header; |
1735 | struct usb_host_endpoint *hostep; | 1760 | struct usb_host_endpoint *hostep; |
1736 | struct usb_endpoint_descriptor* ep; | 1761 | struct usb_endpoint_descriptor *ep; |
1737 | struct usb_ms_endpoint_descriptor* ms_ep; | 1762 | struct usb_ms_endpoint_descriptor *ms_ep; |
1738 | int i, epidx; | 1763 | int i, epidx; |
1739 | 1764 | ||
1740 | intf = umidi->iface; | 1765 | intf = umidi->iface; |
@@ -1742,7 +1767,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1742 | return -ENXIO; | 1767 | return -ENXIO; |
1743 | hostif = &intf->altsetting[0]; | 1768 | hostif = &intf->altsetting[0]; |
1744 | intfd = get_iface_desc(hostif); | 1769 | intfd = get_iface_desc(hostif); |
1745 | ms_header = (struct usb_ms_header_descriptor*)hostif->extra; | 1770 | ms_header = (struct usb_ms_header_descriptor *)hostif->extra; |
1746 | if (hostif->extralen >= 7 && | 1771 | if (hostif->extralen >= 7 && |
1747 | ms_header->bLength >= 7 && | 1772 | ms_header->bLength >= 7 && |
1748 | ms_header->bDescriptorType == USB_DT_CS_INTERFACE && | 1773 | ms_header->bDescriptorType == USB_DT_CS_INTERFACE && |
@@ -1759,7 +1784,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1759 | ep = get_ep_desc(hostep); | 1784 | ep = get_ep_desc(hostep); |
1760 | if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep)) | 1785 | if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep)) |
1761 | continue; | 1786 | continue; |
1762 | ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra; | 1787 | ms_ep = (struct usb_ms_endpoint_descriptor *)hostep->extra; |
1763 | if (hostep->extralen < 4 || | 1788 | if (hostep->extralen < 4 || |
1764 | ms_ep->bLength < 4 || | 1789 | ms_ep->bLength < 4 || |
1765 | ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT || | 1790 | ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT || |
@@ -1783,9 +1808,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1783 | * ESI MIDI Mate that try to use them anyway. | 1808 | * ESI MIDI Mate that try to use them anyway. |
1784 | */ | 1809 | */ |
1785 | endpoints[epidx].out_interval = 1; | 1810 | endpoints[epidx].out_interval = 1; |
1786 | endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; | 1811 | endpoints[epidx].out_cables = |
1812 | (1 << ms_ep->bNumEmbMIDIJack) - 1; | ||
1787 | dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", | 1813 | dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", |
1788 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); | 1814 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); |
1789 | } else { | 1815 | } else { |
1790 | if (endpoints[epidx].in_ep) { | 1816 | if (endpoints[epidx].in_ep) { |
1791 | if (++epidx >= MIDI_MAX_ENDPOINTS) { | 1817 | if (++epidx >= MIDI_MAX_ENDPOINTS) { |
@@ -1799,9 +1825,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, | |||
1799 | endpoints[epidx].in_interval = ep->bInterval; | 1825 | endpoints[epidx].in_interval = ep->bInterval; |
1800 | else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW) | 1826 | else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW) |
1801 | endpoints[epidx].in_interval = 1; | 1827 | endpoints[epidx].in_interval = 1; |
1802 | endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; | 1828 | endpoints[epidx].in_cables = |
1829 | (1 << ms_ep->bNumEmbMIDIJack) - 1; | ||
1803 | dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", | 1830 | dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", |
1804 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); | 1831 | ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); |
1805 | } | 1832 | } |
1806 | } | 1833 | } |
1807 | return 0; | 1834 | return 0; |
@@ -1825,7 +1852,7 @@ static int roland_load_get(struct snd_kcontrol *kcontrol, | |||
1825 | static int roland_load_put(struct snd_kcontrol *kcontrol, | 1852 | static int roland_load_put(struct snd_kcontrol *kcontrol, |
1826 | struct snd_ctl_elem_value *value) | 1853 | struct snd_ctl_elem_value *value) |
1827 | { | 1854 | { |
1828 | struct snd_usb_midi* umidi = kcontrol->private_data; | 1855 | struct snd_usb_midi *umidi = kcontrol->private_data; |
1829 | int changed; | 1856 | int changed; |
1830 | 1857 | ||
1831 | if (value->value.enumerated.item[0] > 1) | 1858 | if (value->value.enumerated.item[0] > 1) |
@@ -1851,11 +1878,11 @@ static struct snd_kcontrol_new roland_load_ctl = { | |||
1851 | * On Roland devices, use the second alternate setting to be able to use | 1878 | * On Roland devices, use the second alternate setting to be able to use |
1852 | * the interrupt input endpoint. | 1879 | * the interrupt input endpoint. |
1853 | */ | 1880 | */ |
1854 | static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi) | 1881 | static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi *umidi) |
1855 | { | 1882 | { |
1856 | struct usb_interface* intf; | 1883 | struct usb_interface *intf; |
1857 | struct usb_host_interface *hostif; | 1884 | struct usb_host_interface *hostif; |
1858 | struct usb_interface_descriptor* intfd; | 1885 | struct usb_interface_descriptor *intfd; |
1859 | 1886 | ||
1860 | intf = umidi->iface; | 1887 | intf = umidi->iface; |
1861 | if (!intf || intf->num_altsetting != 2) | 1888 | if (!intf || intf->num_altsetting != 2) |
@@ -1864,8 +1891,10 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi) | |||
1864 | hostif = &intf->altsetting[1]; | 1891 | hostif = &intf->altsetting[1]; |
1865 | intfd = get_iface_desc(hostif); | 1892 | intfd = get_iface_desc(hostif); |
1866 | if (intfd->bNumEndpoints != 2 || | 1893 | if (intfd->bNumEndpoints != 2 || |
1867 | (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || | 1894 | (get_endpoint(hostif, 0)->bmAttributes & |
1868 | (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) | 1895 | USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || |
1896 | (get_endpoint(hostif, 1)->bmAttributes & | ||
1897 | USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) | ||
1869 | return; | 1898 | return; |
1870 | 1899 | ||
1871 | dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep\n", | 1900 | dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep\n", |
@@ -1881,14 +1910,14 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi) | |||
1881 | /* | 1910 | /* |
1882 | * Try to find any usable endpoints in the interface. | 1911 | * Try to find any usable endpoints in the interface. |
1883 | */ | 1912 | */ |
1884 | static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi, | 1913 | static int snd_usbmidi_detect_endpoints(struct snd_usb_midi *umidi, |
1885 | struct snd_usb_midi_endpoint_info* endpoint, | 1914 | struct snd_usb_midi_endpoint_info *endpoint, |
1886 | int max_endpoints) | 1915 | int max_endpoints) |
1887 | { | 1916 | { |
1888 | struct usb_interface* intf; | 1917 | struct usb_interface *intf; |
1889 | struct usb_host_interface *hostif; | 1918 | struct usb_host_interface *hostif; |
1890 | struct usb_interface_descriptor* intfd; | 1919 | struct usb_interface_descriptor *intfd; |
1891 | struct usb_endpoint_descriptor* epd; | 1920 | struct usb_endpoint_descriptor *epd; |
1892 | int i, out_eps = 0, in_eps = 0; | 1921 | int i, out_eps = 0, in_eps = 0; |
1893 | 1922 | ||
1894 | if (USB_ID_VENDOR(umidi->usb_id) == 0x0582) | 1923 | if (USB_ID_VENDOR(umidi->usb_id) == 0x0582) |
@@ -1929,8 +1958,8 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi, | |||
1929 | /* | 1958 | /* |
1930 | * Detects the endpoints for one-port-per-endpoint protocols. | 1959 | * Detects the endpoints for one-port-per-endpoint protocols. |
1931 | */ | 1960 | */ |
1932 | static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi, | 1961 | static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi *umidi, |
1933 | struct snd_usb_midi_endpoint_info* endpoints) | 1962 | struct snd_usb_midi_endpoint_info *endpoints) |
1934 | { | 1963 | { |
1935 | int err, i; | 1964 | int err, i; |
1936 | 1965 | ||
@@ -1947,13 +1976,13 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi, | |||
1947 | /* | 1976 | /* |
1948 | * Detects the endpoints and ports of Yamaha devices. | 1977 | * Detects the endpoints and ports of Yamaha devices. |
1949 | */ | 1978 | */ |
1950 | static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | 1979 | static int snd_usbmidi_detect_yamaha(struct snd_usb_midi *umidi, |
1951 | struct snd_usb_midi_endpoint_info* endpoint) | 1980 | struct snd_usb_midi_endpoint_info *endpoint) |
1952 | { | 1981 | { |
1953 | struct usb_interface* intf; | 1982 | struct usb_interface *intf; |
1954 | struct usb_host_interface *hostif; | 1983 | struct usb_host_interface *hostif; |
1955 | struct usb_interface_descriptor* intfd; | 1984 | struct usb_interface_descriptor *intfd; |
1956 | uint8_t* cs_desc; | 1985 | uint8_t *cs_desc; |
1957 | 1986 | ||
1958 | intf = umidi->iface; | 1987 | intf = umidi->iface; |
1959 | if (!intf) | 1988 | if (!intf) |
@@ -1972,9 +2001,11 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | |||
1972 | cs_desc += cs_desc[0]) { | 2001 | cs_desc += cs_desc[0]) { |
1973 | if (cs_desc[1] == USB_DT_CS_INTERFACE) { | 2002 | if (cs_desc[1] == USB_DT_CS_INTERFACE) { |
1974 | if (cs_desc[2] == UAC_MIDI_IN_JACK) | 2003 | if (cs_desc[2] == UAC_MIDI_IN_JACK) |
1975 | endpoint->in_cables = (endpoint->in_cables << 1) | 1; | 2004 | endpoint->in_cables = |
2005 | (endpoint->in_cables << 1) | 1; | ||
1976 | else if (cs_desc[2] == UAC_MIDI_OUT_JACK) | 2006 | else if (cs_desc[2] == UAC_MIDI_OUT_JACK) |
1977 | endpoint->out_cables = (endpoint->out_cables << 1) | 1; | 2007 | endpoint->out_cables = |
2008 | (endpoint->out_cables << 1) | 1; | ||
1978 | } | 2009 | } |
1979 | } | 2010 | } |
1980 | if (!endpoint->in_cables && !endpoint->out_cables) | 2011 | if (!endpoint->in_cables && !endpoint->out_cables) |
@@ -1986,12 +2017,12 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | |||
1986 | /* | 2017 | /* |
1987 | * Detects the endpoints and ports of Roland devices. | 2018 | * Detects the endpoints and ports of Roland devices. |
1988 | */ | 2019 | */ |
1989 | static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi, | 2020 | static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi, |
1990 | struct snd_usb_midi_endpoint_info* endpoint) | 2021 | struct snd_usb_midi_endpoint_info *endpoint) |
1991 | { | 2022 | { |
1992 | struct usb_interface* intf; | 2023 | struct usb_interface *intf; |
1993 | struct usb_host_interface *hostif; | 2024 | struct usb_host_interface *hostif; |
1994 | u8* cs_desc; | 2025 | u8 *cs_desc; |
1995 | 2026 | ||
1996 | intf = umidi->iface; | 2027 | intf = umidi->iface; |
1997 | if (!intf) | 2028 | if (!intf) |
@@ -2024,14 +2055,14 @@ static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi, | |||
2024 | /* | 2055 | /* |
2025 | * Creates the endpoints and their ports for Midiman devices. | 2056 | * Creates the endpoints and their ports for Midiman devices. |
2026 | */ | 2057 | */ |
2027 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | 2058 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi, |
2028 | struct snd_usb_midi_endpoint_info* endpoint) | 2059 | struct snd_usb_midi_endpoint_info *endpoint) |
2029 | { | 2060 | { |
2030 | struct snd_usb_midi_endpoint_info ep_info; | 2061 | struct snd_usb_midi_endpoint_info ep_info; |
2031 | struct usb_interface* intf; | 2062 | struct usb_interface *intf; |
2032 | struct usb_host_interface *hostif; | 2063 | struct usb_host_interface *hostif; |
2033 | struct usb_interface_descriptor* intfd; | 2064 | struct usb_interface_descriptor *intfd; |
2034 | struct usb_endpoint_descriptor* epd; | 2065 | struct usb_endpoint_descriptor *epd; |
2035 | int cable, err; | 2066 | int cable, err; |
2036 | 2067 | ||
2037 | intf = umidi->iface; | 2068 | intf = umidi->iface; |
@@ -2068,39 +2099,50 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | |||
2068 | epd = get_endpoint(hostif, 4); | 2099 | epd = get_endpoint(hostif, 4); |
2069 | if (!usb_endpoint_dir_out(epd) || | 2100 | if (!usb_endpoint_dir_out(epd) || |
2070 | !usb_endpoint_xfer_bulk(epd)) { | 2101 | !usb_endpoint_xfer_bulk(epd)) { |
2071 | dev_dbg(&umidi->dev->dev, "endpoint[4] isn't bulk output\n"); | 2102 | dev_dbg(&umidi->dev->dev, |
2103 | "endpoint[4] isn't bulk output\n"); | ||
2072 | return -ENXIO; | 2104 | return -ENXIO; |
2073 | } | 2105 | } |
2074 | } | 2106 | } |
2075 | 2107 | ||
2076 | ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 2108 | ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & |
2109 | USB_ENDPOINT_NUMBER_MASK; | ||
2077 | ep_info.out_interval = 0; | 2110 | ep_info.out_interval = 0; |
2078 | ep_info.out_cables = endpoint->out_cables & 0x5555; | 2111 | ep_info.out_cables = endpoint->out_cables & 0x5555; |
2079 | err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); | 2112 | err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, |
2113 | &umidi->endpoints[0]); | ||
2080 | if (err < 0) | 2114 | if (err < 0) |
2081 | return err; | 2115 | return err; |
2082 | 2116 | ||
2083 | ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 2117 | ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & |
2118 | USB_ENDPOINT_NUMBER_MASK; | ||
2084 | ep_info.in_interval = get_endpoint(hostif, 0)->bInterval; | 2119 | ep_info.in_interval = get_endpoint(hostif, 0)->bInterval; |
2085 | ep_info.in_cables = endpoint->in_cables; | 2120 | ep_info.in_cables = endpoint->in_cables; |
2086 | err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); | 2121 | err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, |
2122 | &umidi->endpoints[0]); | ||
2087 | if (err < 0) | 2123 | if (err < 0) |
2088 | return err; | 2124 | return err; |
2089 | 2125 | ||
2090 | if (endpoint->out_cables > 0x0001) { | 2126 | if (endpoint->out_cables > 0x0001) { |
2091 | ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 2127 | ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & |
2128 | USB_ENDPOINT_NUMBER_MASK; | ||
2092 | ep_info.out_cables = endpoint->out_cables & 0xaaaa; | 2129 | ep_info.out_cables = endpoint->out_cables & 0xaaaa; |
2093 | err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]); | 2130 | err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, |
2131 | &umidi->endpoints[1]); | ||
2094 | if (err < 0) | 2132 | if (err < 0) |
2095 | return err; | 2133 | return err; |
2096 | } | 2134 | } |
2097 | 2135 | ||
2098 | for (cable = 0; cable < 0x10; ++cable) { | 2136 | for (cable = 0; cable < 0x10; ++cable) { |
2099 | if (endpoint->out_cables & (1 << cable)) | 2137 | if (endpoint->out_cables & (1 << cable)) |
2100 | snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, cable, | 2138 | snd_usbmidi_init_substream(umidi, |
2139 | SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
2140 | cable, | ||
2101 | &umidi->endpoints[cable & 1].out->ports[cable].substream); | 2141 | &umidi->endpoints[cable & 1].out->ports[cable].substream); |
2102 | if (endpoint->in_cables & (1 << cable)) | 2142 | if (endpoint->in_cables & (1 << cable)) |
2103 | snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, cable, | 2143 | snd_usbmidi_init_substream(umidi, |
2144 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
2145 | cable, | ||
2104 | &umidi->endpoints[0].in->ports[cable].substream); | 2146 | &umidi->endpoints[0].in->ports[cable].substream); |
2105 | } | 2147 | } |
2106 | return 0; | 2148 | return 0; |
@@ -2110,7 +2152,7 @@ static struct snd_rawmidi_global_ops snd_usbmidi_ops = { | |||
2110 | .get_port_info = snd_usbmidi_get_port_info, | 2152 | .get_port_info = snd_usbmidi_get_port_info, |
2111 | }; | 2153 | }; |
2112 | 2154 | ||
2113 | static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | 2155 | static int snd_usbmidi_create_rawmidi(struct snd_usb_midi *umidi, |
2114 | int out_ports, int in_ports) | 2156 | int out_ports, int in_ports) |
2115 | { | 2157 | { |
2116 | struct snd_rawmidi *rmidi; | 2158 | struct snd_rawmidi *rmidi; |
@@ -2128,8 +2170,10 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | |||
2128 | rmidi->ops = &snd_usbmidi_ops; | 2170 | rmidi->ops = &snd_usbmidi_ops; |
2129 | rmidi->private_data = umidi; | 2171 | rmidi->private_data = umidi; |
2130 | rmidi->private_free = snd_usbmidi_rawmidi_free; | 2172 | rmidi->private_free = snd_usbmidi_rawmidi_free; |
2131 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); | 2173 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, |
2132 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input_ops); | 2174 | &snd_usbmidi_output_ops); |
2175 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
2176 | &snd_usbmidi_input_ops); | ||
2133 | 2177 | ||
2134 | umidi->rmidi = rmidi; | 2178 | umidi->rmidi = rmidi; |
2135 | return 0; | 2179 | return 0; |
@@ -2138,16 +2182,16 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | |||
2138 | /* | 2182 | /* |
2139 | * Temporarily stop input. | 2183 | * Temporarily stop input. |
2140 | */ | 2184 | */ |
2141 | void snd_usbmidi_input_stop(struct list_head* p) | 2185 | void snd_usbmidi_input_stop(struct list_head *p) |
2142 | { | 2186 | { |
2143 | struct snd_usb_midi* umidi; | 2187 | struct snd_usb_midi *umidi; |
2144 | unsigned int i, j; | 2188 | unsigned int i, j; |
2145 | 2189 | ||
2146 | umidi = list_entry(p, struct snd_usb_midi, list); | 2190 | umidi = list_entry(p, struct snd_usb_midi, list); |
2147 | if (!umidi->input_running) | 2191 | if (!umidi->input_running) |
2148 | return; | 2192 | return; |
2149 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 2193 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
2150 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 2194 | struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; |
2151 | if (ep->in) | 2195 | if (ep->in) |
2152 | for (j = 0; j < INPUT_URBS; ++j) | 2196 | for (j = 0; j < INPUT_URBS; ++j) |
2153 | usb_kill_urb(ep->in->urbs[j]); | 2197 | usb_kill_urb(ep->in->urbs[j]); |
@@ -2156,14 +2200,14 @@ void snd_usbmidi_input_stop(struct list_head* p) | |||
2156 | } | 2200 | } |
2157 | EXPORT_SYMBOL(snd_usbmidi_input_stop); | 2201 | EXPORT_SYMBOL(snd_usbmidi_input_stop); |
2158 | 2202 | ||
2159 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) | 2203 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint *ep) |
2160 | { | 2204 | { |
2161 | unsigned int i; | 2205 | unsigned int i; |
2162 | 2206 | ||
2163 | if (!ep) | 2207 | if (!ep) |
2164 | return; | 2208 | return; |
2165 | for (i = 0; i < INPUT_URBS; ++i) { | 2209 | for (i = 0; i < INPUT_URBS; ++i) { |
2166 | struct urb* urb = ep->urbs[i]; | 2210 | struct urb *urb = ep->urbs[i]; |
2167 | urb->dev = ep->umidi->dev; | 2211 | urb->dev = ep->umidi->dev; |
2168 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); | 2212 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); |
2169 | } | 2213 | } |
@@ -2172,9 +2216,9 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) | |||
2172 | /* | 2216 | /* |
2173 | * Resume input after a call to snd_usbmidi_input_stop(). | 2217 | * Resume input after a call to snd_usbmidi_input_stop(). |
2174 | */ | 2218 | */ |
2175 | void snd_usbmidi_input_start(struct list_head* p) | 2219 | void snd_usbmidi_input_start(struct list_head *p) |
2176 | { | 2220 | { |
2177 | struct snd_usb_midi* umidi; | 2221 | struct snd_usb_midi *umidi; |
2178 | int i; | 2222 | int i; |
2179 | 2223 | ||
2180 | umidi = list_entry(p, struct snd_usb_midi, list); | 2224 | umidi = list_entry(p, struct snd_usb_midi, list); |
@@ -2187,14 +2231,42 @@ void snd_usbmidi_input_start(struct list_head* p) | |||
2187 | EXPORT_SYMBOL(snd_usbmidi_input_start); | 2231 | EXPORT_SYMBOL(snd_usbmidi_input_start); |
2188 | 2232 | ||
2189 | /* | 2233 | /* |
2234 | * Prepare for suspend. Typically called from the USB suspend callback. | ||
2235 | */ | ||
2236 | void snd_usbmidi_suspend(struct list_head *p) | ||
2237 | { | ||
2238 | struct snd_usb_midi *umidi; | ||
2239 | |||
2240 | umidi = list_entry(p, struct snd_usb_midi, list); | ||
2241 | mutex_lock(&umidi->mutex); | ||
2242 | snd_usbmidi_input_stop(p); | ||
2243 | mutex_unlock(&umidi->mutex); | ||
2244 | } | ||
2245 | EXPORT_SYMBOL(snd_usbmidi_suspend); | ||
2246 | |||
2247 | /* | ||
2248 | * Resume. Typically called from the USB resume callback. | ||
2249 | */ | ||
2250 | void snd_usbmidi_resume(struct list_head *p) | ||
2251 | { | ||
2252 | struct snd_usb_midi *umidi; | ||
2253 | |||
2254 | umidi = list_entry(p, struct snd_usb_midi, list); | ||
2255 | mutex_lock(&umidi->mutex); | ||
2256 | snd_usbmidi_input_start(p); | ||
2257 | mutex_unlock(&umidi->mutex); | ||
2258 | } | ||
2259 | EXPORT_SYMBOL(snd_usbmidi_resume); | ||
2260 | |||
2261 | /* | ||
2190 | * Creates and registers everything needed for a MIDI streaming interface. | 2262 | * Creates and registers everything needed for a MIDI streaming interface. |
2191 | */ | 2263 | */ |
2192 | int snd_usbmidi_create(struct snd_card *card, | 2264 | int snd_usbmidi_create(struct snd_card *card, |
2193 | struct usb_interface* iface, | 2265 | struct usb_interface *iface, |
2194 | struct list_head *midi_list, | 2266 | struct list_head *midi_list, |
2195 | const struct snd_usb_audio_quirk* quirk) | 2267 | const struct snd_usb_audio_quirk *quirk) |
2196 | { | 2268 | { |
2197 | struct snd_usb_midi* umidi; | 2269 | struct snd_usb_midi *umidi; |
2198 | struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; | 2270 | struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; |
2199 | int out_ports, in_ports; | 2271 | int out_ports, in_ports; |
2200 | int i, err; | 2272 | int i, err; |
@@ -2292,7 +2364,8 @@ int snd_usbmidi_create(struct snd_card *card, | |||
2292 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 2364 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
2293 | break; | 2365 | break; |
2294 | default: | 2366 | default: |
2295 | dev_err(&umidi->dev->dev, "invalid quirk type %d\n", quirk->type); | 2367 | dev_err(&umidi->dev->dev, "invalid quirk type %d\n", |
2368 | quirk->type); | ||
2296 | err = -ENXIO; | 2369 | err = -ENXIO; |
2297 | break; | 2370 | break; |
2298 | } | 2371 | } |
diff --git a/sound/usb/midi.h b/sound/usb/midi.h index 2fca80b744c0..ad8a3211f8e7 100644 --- a/sound/usb/midi.h +++ b/sound/usb/midi.h | |||
@@ -43,8 +43,10 @@ int snd_usbmidi_create(struct snd_card *card, | |||
43 | struct usb_interface *iface, | 43 | struct usb_interface *iface, |
44 | struct list_head *midi_list, | 44 | struct list_head *midi_list, |
45 | const struct snd_usb_audio_quirk *quirk); | 45 | const struct snd_usb_audio_quirk *quirk); |
46 | void snd_usbmidi_input_stop(struct list_head* p); | 46 | void snd_usbmidi_input_stop(struct list_head *p); |
47 | void snd_usbmidi_input_start(struct list_head* p); | 47 | void snd_usbmidi_input_start(struct list_head *p); |
48 | void snd_usbmidi_disconnect(struct list_head *p); | 48 | void snd_usbmidi_disconnect(struct list_head *p); |
49 | void snd_usbmidi_suspend(struct list_head *p); | ||
50 | void snd_usbmidi_resume(struct list_head *p); | ||
49 | 51 | ||
50 | #endif /* __USBMIDI_H */ | 52 | #endif /* __USBMIDI_H */ |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 0b728d886f0d..2e4a9dbc51fa 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -1340,12 +1340,11 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1340 | */ | 1340 | */ |
1341 | if (range > 384) { | 1341 | if (range > 384) { |
1342 | usb_audio_warn(state->chip, | 1342 | usb_audio_warn(state->chip, |
1343 | "Warning! Unlikely big volume range (=%u), " | 1343 | "Warning! Unlikely big volume range (=%u), cval->res is probably wrong.", |
1344 | "cval->res is probably wrong.", | ||
1345 | range); | 1344 | range); |
1346 | usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, " | 1345 | usb_audio_warn(state->chip, |
1347 | "val = %d/%d/%d", cval->id, | 1346 | "[%d] FU [%s] ch = %d, val = %d/%d/%d", |
1348 | kctl->id.name, cval->channels, | 1347 | cval->id, kctl->id.name, cval->channels, |
1349 | cval->min, cval->max, cval->res); | 1348 | cval->min, cval->max, cval->res); |
1350 | } | 1349 | } |
1351 | 1350 | ||
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 7c57f2268dd7..19a921eb75f1 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -670,7 +670,7 @@ static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev) | |||
670 | /* set the initial volume and don't change; other values are either | 670 | /* set the initial volume and don't change; other values are either |
671 | * too loud or silent due to firmware bug (bko#65251) | 671 | * too loud or silent due to firmware bug (bko#65251) |
672 | */ | 672 | */ |
673 | u8 buf[2] = { 0x74, 0xdc }; | 673 | u8 buf[2] = { 0x74, 0xe3 }; |
674 | return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | 674 | return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
675 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 675 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
676 | UAC_FU_VOLUME << 8, 9 << 8, buf, 2); | 676 | UAC_FU_VOLUME << 8, 9 << 8, buf, 2); |