Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branches 'asoc/topic/nau8825' and 'asoc/topic/pxa' into asoc-next

+1843 -228
+102
Documentation/devicetree/bindings/sound/nau8825.txt
··· 1 + Nuvoton NAU8825 audio codec 2 + 3 + This device supports I2C only. 4 + 5 + Required properties: 6 + - compatible : Must be "nuvoton,nau8825" 7 + 8 + - reg : the I2C address of the device. This is either 0x1a (CSB=0) or 0x1b (CSB=1). 9 + 10 + Optional properties: 11 + - nuvoton,jkdet-enable: Enable jack detection via JKDET pin. 12 + - nuvoton,jkdet-pull-enable: Enable JKDET pin pull. If set - pin pull enabled, 13 + otherwise pin in high impedance state. 14 + - nuvoton,jkdet-pull-up: Pull-up JKDET pin. If set then JKDET pin is pull up, otherwise pull down. 15 + - nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low. 16 + 17 + - nuvoton,vref-impedance: VREF Impedance selection 18 + 0 - Open 19 + 1 - 25 kOhm 20 + 2 - 125 kOhm 21 + 3 - 2.5 kOhm 22 + 23 + - nuvoton,micbias-voltage: Micbias voltage level. 24 + 0 - VDDA 25 + 1 - VDDA 26 + 2 - VDDA * 1.1 27 + 3 - VDDA * 1.2 28 + 4 - VDDA * 1.3 29 + 5 - VDDA * 1.4 30 + 6 - VDDA * 1.53 31 + 7 - VDDA * 1.53 32 + 33 + - nuvoton,sar-threshold-num: Number of buttons supported 34 + - nuvoton,sar-threshold: Impedance threshold for each button. Array that contains up to 8 buttons configuration. SAR value is calculated as 35 + SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) 36 + where MICBIAS is configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by 'nuvoton,sar-voltage', R - button impedance. 37 + Refer datasheet section 10.2 for more information about threshold calculation. 38 + 39 + - nuvoton,sar-hysteresis: Button impedance measurement hysteresis. 40 + 41 + - nuvoton,sar-voltage: Reference voltage for button impedance measurement. 42 + 0 - VDDA 43 + 1 - VDDA 44 + 2 - VDDA * 1.1 45 + 3 - VDDA * 1.2 46 + 4 - VDDA * 1.3 47 + 5 - VDDA * 1.4 48 + 6 - VDDA * 1.53 49 + 7 - VDDA * 1.53 50 + 51 + - nuvoton,sar-compare-time: SAR compare time 52 + 0 - 500 ns 53 + 1 - 1 us 54 + 2 - 2 us 55 + 3 - 4 us 56 + 57 + - nuvoton,sar-sampling-time: SAR sampling time 58 + 0 - 2 us 59 + 1 - 4 us 60 + 2 - 8 us 61 + 3 - 16 us 62 + 63 + - nuvoton,short-key-debounce: Button short key press debounce time. 64 + 0 - 30 ms 65 + 1 - 50 ms 66 + 2 - 100 ms 67 + 3 - 30 ms 68 + 69 + - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms 70 + - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms 71 + 72 + - clocks: list of phandle and clock specifier pairs according to common clock bindings for the 73 + clocks described in clock-names 74 + - clock-names: should include "mclk" for the MCLK master clock 75 + 76 + Example: 77 + 78 + headset: nau8825@1a { 79 + compatible = "nuvoton,nau8825"; 80 + reg = <0x1a>; 81 + interrupt-parent = <&gpio>; 82 + interrupts = <TEGRA_GPIO(E, 6) IRQ_TYPE_LEVEL_LOW>; 83 + nuvoton,jkdet-enable; 84 + nuvoton,jkdet-pull-enable; 85 + nuvoton,jkdet-pull-up; 86 + nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; 87 + nuvoton,vref-impedance = <2>; 88 + nuvoton,micbias-voltage = <6>; 89 + // Setup 4 buttons impedance according to Android specification 90 + nuvoton,sar-threshold-num = <4>; 91 + nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; 92 + nuvoton,sar-hysteresis = <1>; 93 + nuvoton,sar-voltage = <0>; 94 + nuvoton,sar-compare-time = <0>; 95 + nuvoton,sar-sampling-time = <0>; 96 + nuvoton,short-key-debounce = <2>; 97 + nuvoton,jack-insert-debounce = <7>; 98 + nuvoton,jack-eject-debounce = <7>; 99 + 100 + clock-names = "mclk"; 101 + clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; 102 + };
-1
include/sound/pxa2xx-lib.h
··· 12 12 extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd); 13 13 extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream); 14 14 extern int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream); 15 - extern void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id); 16 15 extern int __pxa2xx_pcm_open(struct snd_pcm_substream *substream); 17 16 extern int __pxa2xx_pcm_close(struct snd_pcm_substream *substream); 18 17 extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
+11 -2
sound/arm/pxa2xx-ac97.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/platform_device.h> 17 17 #include <linux/dmaengine.h> 18 + #include <linux/dma/pxa-dma.h> 18 19 19 20 #include <sound/core.h> 20 21 #include <sound/pcm.h> ··· 44 43 .reset = pxa2xx_ac97_reset, 45 44 }; 46 45 47 - static unsigned long pxa2xx_ac97_pcm_out_req = 12; 46 + static struct pxad_param pxa2xx_ac97_pcm_out_req = { 47 + .prio = PXAD_PRIO_LOWEST, 48 + .drcmr = 12, 49 + }; 50 + 48 51 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = { 49 52 .addr = __PREG(PCDR), 50 53 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, ··· 56 51 .filter_data = &pxa2xx_ac97_pcm_out_req, 57 52 }; 58 53 59 - static unsigned long pxa2xx_ac97_pcm_in_req = 11; 54 + static struct pxad_param pxa2xx_ac97_pcm_in_req = { 55 + .prio = PXAD_PRIO_LOWEST, 56 + .drcmr = 11, 57 + }; 58 + 60 59 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = { 61 60 .addr = __PREG(PCDR), 62 61 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+36 -165
sound/arm/pxa2xx-pcm-lib.c
··· 8 8 #include <linux/module.h> 9 9 #include <linux/dma-mapping.h> 10 10 #include <linux/dmaengine.h> 11 + #include <linux/dma/pxa-dma.h> 11 12 12 13 #include <sound/core.h> 13 14 #include <sound/pcm.h> 14 15 #include <sound/pcm_params.h> 15 16 #include <sound/pxa2xx-lib.h> 16 17 #include <sound/dmaengine_pcm.h> 17 - 18 - #include <mach/dma.h> 19 18 20 19 #include "pxa2xx-pcm.h" 21 20 ··· 30 31 .period_bytes_min = 32, 31 32 .period_bytes_max = 8192 - 32, 32 33 .periods_min = 1, 33 - .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), 34 + .periods_max = 256, 34 35 .buffer_bytes_max = 128 * 1024, 35 36 .fifo_size = 32, 36 37 }; ··· 38 39 int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 39 40 struct snd_pcm_hw_params *params) 40 41 { 41 - struct snd_pcm_runtime *runtime = substream->runtime; 42 - struct pxa2xx_runtime_data *rtd = runtime->private_data; 43 - size_t totsize = params_buffer_bytes(params); 44 - size_t period = params_period_bytes(params); 45 - pxa_dma_desc *dma_desc; 46 - dma_addr_t dma_buff_phys, next_desc_phys; 47 - u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; 42 + struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); 43 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 44 + struct snd_dmaengine_dai_dma_data *dma_params; 45 + struct dma_slave_config config; 46 + int ret; 48 47 49 - /* temporary transition hack */ 50 - switch (rtd->params->addr_width) { 51 - case DMA_SLAVE_BUSWIDTH_1_BYTE: 52 - dcmd |= DCMD_WIDTH1; 53 - break; 54 - case DMA_SLAVE_BUSWIDTH_2_BYTES: 55 - dcmd |= DCMD_WIDTH2; 56 - break; 57 - case DMA_SLAVE_BUSWIDTH_4_BYTES: 58 - dcmd |= DCMD_WIDTH4; 59 - break; 60 - default: 61 - /* can't happen */ 62 - break; 63 - } 48 + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 49 + if (!dma_params) 50 + return 0; 64 51 65 - switch (rtd->params->maxburst) { 66 - case 8: 67 - dcmd |= DCMD_BURST8; 68 - break; 69 - case 16: 70 - dcmd |= DCMD_BURST16; 71 - break; 72 - case 32: 73 - dcmd |= DCMD_BURST32; 74 - break; 75 - } 52 + ret = snd_hwparams_to_dma_slave_config(substream, params, &config); 53 + if (ret) 54 + return ret; 55 + 56 + snd_dmaengine_pcm_set_config_from_dai_data(substream, 57 + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream), 58 + &config); 59 + 60 + ret = dmaengine_slave_config(chan, &config); 61 + if (ret) 62 + return ret; 76 63 77 64 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 78 - runtime->dma_bytes = totsize; 79 - 80 - dma_desc = rtd->dma_desc_array; 81 - next_desc_phys = rtd->dma_desc_array_phys; 82 - dma_buff_phys = runtime->dma_addr; 83 - do { 84 - next_desc_phys += sizeof(pxa_dma_desc); 85 - dma_desc->ddadr = next_desc_phys; 86 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 87 - dma_desc->dsadr = dma_buff_phys; 88 - dma_desc->dtadr = rtd->params->addr; 89 - } else { 90 - dma_desc->dsadr = rtd->params->addr; 91 - dma_desc->dtadr = dma_buff_phys; 92 - } 93 - if (period > totsize) 94 - period = totsize; 95 - dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN; 96 - dma_desc++; 97 - dma_buff_phys += period; 98 - } while (totsize -= period); 99 - dma_desc[-1].ddadr = rtd->dma_desc_array_phys; 100 65 101 66 return 0; 102 67 } ··· 68 105 69 106 int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) 70 107 { 71 - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; 72 - 73 - if (rtd && rtd->params && rtd->params->filter_data) { 74 - unsigned long req = *(unsigned long *) rtd->params->filter_data; 75 - DRCMR(req) = 0; 76 - } 77 - 78 108 snd_pcm_set_runtime_buffer(substream, NULL); 79 109 return 0; 80 110 } ··· 75 119 76 120 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 77 121 { 78 - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 79 - int ret = 0; 80 - 81 - switch (cmd) { 82 - case SNDRV_PCM_TRIGGER_START: 83 - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; 84 - DCSR(prtd->dma_ch) = DCSR_RUN; 85 - break; 86 - 87 - case SNDRV_PCM_TRIGGER_STOP: 88 - case SNDRV_PCM_TRIGGER_SUSPEND: 89 - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 90 - DCSR(prtd->dma_ch) &= ~DCSR_RUN; 91 - break; 92 - 93 - case SNDRV_PCM_TRIGGER_RESUME: 94 - DCSR(prtd->dma_ch) |= DCSR_RUN; 95 - break; 96 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 97 - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; 98 - DCSR(prtd->dma_ch) |= DCSR_RUN; 99 - break; 100 - 101 - default: 102 - ret = -EINVAL; 103 - } 104 - 105 - return ret; 122 + return snd_dmaengine_pcm_trigger(substream, cmd); 106 123 } 107 124 EXPORT_SYMBOL(pxa2xx_pcm_trigger); 108 125 109 126 snd_pcm_uframes_t 110 127 pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) 111 128 { 112 - struct snd_pcm_runtime *runtime = substream->runtime; 113 - struct pxa2xx_runtime_data *prtd = runtime->private_data; 114 - 115 - dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 116 - DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); 117 - snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); 118 - 119 - if (x == runtime->buffer_size) 120 - x = 0; 121 - return x; 129 + return snd_dmaengine_pcm_pointer(substream); 122 130 } 123 131 EXPORT_SYMBOL(pxa2xx_pcm_pointer); 124 132 125 133 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) 126 134 { 127 - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 128 - unsigned long req; 129 - 130 - if (!prtd || !prtd->params) 131 - return 0; 132 - 133 - if (prtd->dma_ch == -1) 134 - return -EINVAL; 135 - 136 - DCSR(prtd->dma_ch) &= ~DCSR_RUN; 137 - DCSR(prtd->dma_ch) = 0; 138 - DCMD(prtd->dma_ch) = 0; 139 - req = *(unsigned long *) prtd->params->filter_data; 140 - DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD; 141 - 142 135 return 0; 143 136 } 144 137 EXPORT_SYMBOL(__pxa2xx_pcm_prepare); 145 138 146 - void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) 147 - { 148 - struct snd_pcm_substream *substream = dev_id; 149 - int dcsr; 150 - 151 - dcsr = DCSR(dma_ch); 152 - DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; 153 - 154 - if (dcsr & DCSR_ENDINTR) { 155 - snd_pcm_period_elapsed(substream); 156 - } else { 157 - printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n", 158 - dma_ch, dcsr); 159 - snd_pcm_stop_xrun(substream); 160 - } 161 - } 162 - EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); 163 - 164 139 int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) 165 140 { 141 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 166 142 struct snd_pcm_runtime *runtime = substream->runtime; 167 - struct pxa2xx_runtime_data *rtd; 143 + struct snd_dmaengine_dai_dma_data *dma_params; 168 144 int ret; 169 145 170 146 runtime->hw = pxa2xx_pcm_hardware; 147 + 148 + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 149 + if (!dma_params) 150 + return 0; 171 151 172 152 /* 173 153 * For mysterious reasons (and despite what the manual says) ··· 113 221 ret = snd_pcm_hw_constraint_step(runtime, 0, 114 222 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 115 223 if (ret) 116 - goto out; 224 + return ret; 117 225 118 226 ret = snd_pcm_hw_constraint_step(runtime, 0, 119 227 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 120 228 if (ret) 121 - goto out; 229 + return ret; 122 230 123 231 ret = snd_pcm_hw_constraint_integer(runtime, 124 232 SNDRV_PCM_HW_PARAM_PERIODS); 125 233 if (ret < 0) 126 - goto out; 234 + return ret; 127 235 128 - ret = -ENOMEM; 129 - rtd = kzalloc(sizeof(*rtd), GFP_KERNEL); 130 - if (!rtd) 131 - goto out; 132 - rtd->dma_desc_array = 133 - dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, 134 - &rtd->dma_desc_array_phys, GFP_KERNEL); 135 - if (!rtd->dma_desc_array) 136 - goto err1; 137 - 138 - rtd->dma_ch = -1; 139 - runtime->private_data = rtd; 140 - return 0; 141 - 142 - err1: 143 - kfree(rtd); 144 - out: 145 - return ret; 236 + return snd_dmaengine_pcm_open_request_chan(substream, 237 + pxad_filter_fn, 238 + dma_params->filter_data); 146 239 } 147 240 EXPORT_SYMBOL(__pxa2xx_pcm_open); 148 241 149 242 int __pxa2xx_pcm_close(struct snd_pcm_substream *substream) 150 243 { 151 - struct snd_pcm_runtime *runtime = substream->runtime; 152 - struct pxa2xx_runtime_data *rtd = runtime->private_data; 153 - 154 - dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, 155 - rtd->dma_desc_array, rtd->dma_desc_array_phys); 156 - kfree(rtd); 157 - return 0; 244 + return snd_dmaengine_pcm_close_release_chan(substream); 158 245 } 159 246 EXPORT_SYMBOL(__pxa2xx_pcm_close); 160 247
+3 -9
sound/arm/pxa2xx-pcm.c
··· 46 46 47 47 rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 48 48 client->playback_params : client->capture_params; 49 - ret = pxa_request_dma("dma", DMA_PRIO_LOW, 50 - pxa2xx_pcm_dma_irq, substream); 51 - if (ret < 0) 52 - goto err2; 53 - rtd->dma_ch = ret; 54 49 55 50 ret = client->startup(substream); 56 51 if (!ret) 57 - goto out; 52 + goto err2; 58 53 59 - pxa_free_dma(rtd->dma_ch); 54 + return 0; 55 + 60 56 err2: 61 57 __pxa2xx_pcm_close(substream); 62 58 out: ··· 62 66 static int pxa2xx_pcm_close(struct snd_pcm_substream *substream) 63 67 { 64 68 struct pxa2xx_pcm_client *client = substream->private_data; 65 - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; 66 69 67 - pxa_free_dma(rtd->dma_ch); 68 70 client->shutdown(substream); 69 71 70 72 return __pxa2xx_pcm_close(substream);
-2
sound/arm/pxa2xx-pcm.h
··· 13 13 struct pxa2xx_runtime_data { 14 14 int dma_ch; 15 15 struct snd_dmaengine_dai_dma_data *params; 16 - struct pxa_dma_desc *dma_desc_array; 17 - dma_addr_t dma_desc_array_phys; 18 16 }; 19 17 20 18 struct pxa2xx_pcm_client {
+4
sound/soc/codecs/Kconfig
··· 81 81 select SND_SOC_MAX9877 if I2C 82 82 select SND_SOC_MC13783 if MFD_MC13XXX 83 83 select SND_SOC_ML26124 if I2C 84 + select SND_SOC_NAU8825 if I2C 84 85 select SND_SOC_PCM1681 if I2C 85 86 select SND_SOC_PCM1792A if SPI_MASTER 86 87 select SND_SOC_PCM3008 ··· 906 905 tristate 907 906 908 907 config SND_SOC_ML26124 908 + tristate 909 + 910 + config SND_SOC_NAU8825 909 911 tristate 910 912 911 913 config SND_SOC_TPA6130A2
+2
sound/soc/codecs/Makefile
··· 74 74 snd-soc-max9850-objs := max9850.o 75 75 snd-soc-mc13783-objs := mc13783.o 76 76 snd-soc-ml26124-objs := ml26124.o 77 + snd-soc-nau8825-objs := nau8825.o 77 78 snd-soc-pcm1681-objs := pcm1681.o 78 79 snd-soc-pcm1792a-codec-objs := pcm1792a.o 79 80 snd-soc-pcm3008-objs := pcm3008.o ··· 269 268 obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 270 269 obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 271 270 obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 271 + obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o 272 272 obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o 273 273 obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o 274 274 obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+1309
sound/soc/codecs/nau8825.c
··· 1 + /* 2 + * Nuvoton NAU8825 audio codec driver 3 + * 4 + * Copyright 2015 Google Chromium project. 5 + * Author: Anatol Pomozov <anatol@chromium.org> 6 + * Copyright 2015 Nuvoton Technology Corp. 7 + * Co-author: Meng-Huang Kuo <mhkuo@nuvoton.com> 8 + * 9 + * Licensed under the GPL-2. 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/delay.h> 14 + #include <linux/init.h> 15 + #include <linux/i2c.h> 16 + #include <linux/regmap.h> 17 + #include <linux/slab.h> 18 + #include <linux/clk.h> 19 + #include <linux/acpi.h> 20 + #include <linux/math64.h> 21 + 22 + #include <sound/initval.h> 23 + #include <sound/tlv.h> 24 + #include <sound/core.h> 25 + #include <sound/pcm.h> 26 + #include <sound/pcm_params.h> 27 + #include <sound/soc.h> 28 + #include <sound/jack.h> 29 + 30 + 31 + #include "nau8825.h" 32 + 33 + #define NAU_FREF_MAX 13500000 34 + #define NAU_FVCO_MAX 100000000 35 + #define NAU_FVCO_MIN 90000000 36 + 37 + struct nau8825_fll { 38 + int mclk_src; 39 + int ratio; 40 + int fll_frac; 41 + int fll_int; 42 + int clk_ref_div; 43 + }; 44 + 45 + struct nau8825_fll_attr { 46 + unsigned int param; 47 + unsigned int val; 48 + }; 49 + 50 + /* scaling for mclk from sysclk_src output */ 51 + static const struct nau8825_fll_attr mclk_src_scaling[] = { 52 + { 1, 0x0 }, 53 + { 2, 0x2 }, 54 + { 4, 0x3 }, 55 + { 8, 0x4 }, 56 + { 16, 0x5 }, 57 + { 32, 0x6 }, 58 + { 3, 0x7 }, 59 + { 6, 0xa }, 60 + { 12, 0xb }, 61 + { 24, 0xc }, 62 + { 48, 0xd }, 63 + { 96, 0xe }, 64 + { 5, 0xf }, 65 + }; 66 + 67 + /* ratio for input clk freq */ 68 + static const struct nau8825_fll_attr fll_ratio[] = { 69 + { 512000, 0x01 }, 70 + { 256000, 0x02 }, 71 + { 128000, 0x04 }, 72 + { 64000, 0x08 }, 73 + { 32000, 0x10 }, 74 + { 8000, 0x20 }, 75 + { 4000, 0x40 }, 76 + }; 77 + 78 + static const struct nau8825_fll_attr fll_pre_scalar[] = { 79 + { 1, 0x0 }, 80 + { 2, 0x1 }, 81 + { 4, 0x2 }, 82 + { 8, 0x3 }, 83 + }; 84 + 85 + static const struct reg_default nau8825_reg_defaults[] = { 86 + { NAU8825_REG_ENA_CTRL, 0x00ff }, 87 + { NAU8825_REG_CLK_DIVIDER, 0x0050 }, 88 + { NAU8825_REG_FLL1, 0x0 }, 89 + { NAU8825_REG_FLL2, 0x3126 }, 90 + { NAU8825_REG_FLL3, 0x0008 }, 91 + { NAU8825_REG_FLL4, 0x0010 }, 92 + { NAU8825_REG_FLL5, 0x0 }, 93 + { NAU8825_REG_FLL6, 0x6000 }, 94 + { NAU8825_REG_FLL_VCO_RSV, 0xf13c }, 95 + { NAU8825_REG_HSD_CTRL, 0x000c }, 96 + { NAU8825_REG_JACK_DET_CTRL, 0x0 }, 97 + { NAU8825_REG_INTERRUPT_MASK, 0x0 }, 98 + { NAU8825_REG_INTERRUPT_DIS_CTRL, 0xffff }, 99 + { NAU8825_REG_SAR_CTRL, 0x0015 }, 100 + { NAU8825_REG_KEYDET_CTRL, 0x0110 }, 101 + { NAU8825_REG_VDET_THRESHOLD_1, 0x0 }, 102 + { NAU8825_REG_VDET_THRESHOLD_2, 0x0 }, 103 + { NAU8825_REG_VDET_THRESHOLD_3, 0x0 }, 104 + { NAU8825_REG_VDET_THRESHOLD_4, 0x0 }, 105 + { NAU8825_REG_GPIO34_CTRL, 0x0 }, 106 + { NAU8825_REG_GPIO12_CTRL, 0x0 }, 107 + { NAU8825_REG_TDM_CTRL, 0x0 }, 108 + { NAU8825_REG_I2S_PCM_CTRL1, 0x000b }, 109 + { NAU8825_REG_I2S_PCM_CTRL2, 0x8010 }, 110 + { NAU8825_REG_LEFT_TIME_SLOT, 0x0 }, 111 + { NAU8825_REG_RIGHT_TIME_SLOT, 0x0 }, 112 + { NAU8825_REG_BIQ_CTRL, 0x0 }, 113 + { NAU8825_REG_BIQ_COF1, 0x0 }, 114 + { NAU8825_REG_BIQ_COF2, 0x0 }, 115 + { NAU8825_REG_BIQ_COF3, 0x0 }, 116 + { NAU8825_REG_BIQ_COF4, 0x0 }, 117 + { NAU8825_REG_BIQ_COF5, 0x0 }, 118 + { NAU8825_REG_BIQ_COF6, 0x0 }, 119 + { NAU8825_REG_BIQ_COF7, 0x0 }, 120 + { NAU8825_REG_BIQ_COF8, 0x0 }, 121 + { NAU8825_REG_BIQ_COF9, 0x0 }, 122 + { NAU8825_REG_BIQ_COF10, 0x0 }, 123 + { NAU8825_REG_ADC_RATE, 0x0010 }, 124 + { NAU8825_REG_DAC_CTRL1, 0x0001 }, 125 + { NAU8825_REG_DAC_CTRL2, 0x0 }, 126 + { NAU8825_REG_DAC_DGAIN_CTRL, 0x0 }, 127 + { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf }, 128 + { NAU8825_REG_MUTE_CTRL, 0x0 }, 129 + { NAU8825_REG_HSVOL_CTRL, 0x0 }, 130 + { NAU8825_REG_DACL_CTRL, 0x02cf }, 131 + { NAU8825_REG_DACR_CTRL, 0x00cf }, 132 + { NAU8825_REG_ADC_DRC_KNEE_IP12, 0x1486 }, 133 + { NAU8825_REG_ADC_DRC_KNEE_IP34, 0x0f12 }, 134 + { NAU8825_REG_ADC_DRC_SLOPES, 0x25ff }, 135 + { NAU8825_REG_ADC_DRC_ATKDCY, 0x3457 }, 136 + { NAU8825_REG_DAC_DRC_KNEE_IP12, 0x1486 }, 137 + { NAU8825_REG_DAC_DRC_KNEE_IP34, 0x0f12 }, 138 + { NAU8825_REG_DAC_DRC_SLOPES, 0x25f9 }, 139 + { NAU8825_REG_DAC_DRC_ATKDCY, 0x3457 }, 140 + { NAU8825_REG_IMM_MODE_CTRL, 0x0 }, 141 + { NAU8825_REG_CLASSG_CTRL, 0x0 }, 142 + { NAU8825_REG_OPT_EFUSE_CTRL, 0x0 }, 143 + { NAU8825_REG_MISC_CTRL, 0x0 }, 144 + { NAU8825_REG_BIAS_ADJ, 0x0 }, 145 + { NAU8825_REG_TRIM_SETTINGS, 0x0 }, 146 + { NAU8825_REG_ANALOG_CONTROL_1, 0x0 }, 147 + { NAU8825_REG_ANALOG_CONTROL_2, 0x0 }, 148 + { NAU8825_REG_ANALOG_ADC_1, 0x0011 }, 149 + { NAU8825_REG_ANALOG_ADC_2, 0x0020 }, 150 + { NAU8825_REG_RDAC, 0x0008 }, 151 + { NAU8825_REG_MIC_BIAS, 0x0006 }, 152 + { NAU8825_REG_BOOST, 0x0 }, 153 + { NAU8825_REG_FEPGA, 0x0 }, 154 + { NAU8825_REG_POWER_UP_CONTROL, 0x0 }, 155 + { NAU8825_REG_CHARGE_PUMP, 0x0 }, 156 + }; 157 + 158 + static bool nau8825_readable_reg(struct device *dev, unsigned int reg) 159 + { 160 + switch (reg) { 161 + case NAU8825_REG_ENA_CTRL: 162 + case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: 163 + case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: 164 + case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: 165 + case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: 166 + case NAU8825_REG_ADC_DRC_KNEE_IP12 ... NAU8825_REG_ADC_DRC_ATKDCY: 167 + case NAU8825_REG_DAC_DRC_KNEE_IP12 ... NAU8825_REG_DAC_DRC_ATKDCY: 168 + case NAU8825_REG_IMM_MODE_CTRL ... NAU8825_REG_IMM_RMS_R: 169 + case NAU8825_REG_CLASSG_CTRL ... NAU8825_REG_OPT_EFUSE_CTRL: 170 + case NAU8825_REG_MISC_CTRL: 171 + case NAU8825_REG_I2C_DEVICE_ID ... NAU8825_REG_SARDOUT_RAM_STATUS: 172 + case NAU8825_REG_BIAS_ADJ: 173 + case NAU8825_REG_TRIM_SETTINGS ... NAU8825_REG_ANALOG_CONTROL_2: 174 + case NAU8825_REG_ANALOG_ADC_1 ... NAU8825_REG_MIC_BIAS: 175 + case NAU8825_REG_BOOST ... NAU8825_REG_FEPGA: 176 + case NAU8825_REG_POWER_UP_CONTROL ... NAU8825_REG_GENERAL_STATUS: 177 + return true; 178 + default: 179 + return false; 180 + } 181 + 182 + } 183 + 184 + static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) 185 + { 186 + switch (reg) { 187 + case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL: 188 + case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: 189 + case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: 190 + case NAU8825_REG_INTERRUPT_MASK: 191 + case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: 192 + case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: 193 + case NAU8825_REG_ADC_DRC_KNEE_IP12 ... NAU8825_REG_ADC_DRC_ATKDCY: 194 + case NAU8825_REG_DAC_DRC_KNEE_IP12 ... NAU8825_REG_DAC_DRC_ATKDCY: 195 + case NAU8825_REG_IMM_MODE_CTRL: 196 + case NAU8825_REG_CLASSG_CTRL ... NAU8825_REG_OPT_EFUSE_CTRL: 197 + case NAU8825_REG_MISC_CTRL: 198 + case NAU8825_REG_BIAS_ADJ: 199 + case NAU8825_REG_TRIM_SETTINGS ... NAU8825_REG_ANALOG_CONTROL_2: 200 + case NAU8825_REG_ANALOG_ADC_1 ... NAU8825_REG_MIC_BIAS: 201 + case NAU8825_REG_BOOST ... NAU8825_REG_FEPGA: 202 + case NAU8825_REG_POWER_UP_CONTROL ... NAU8825_REG_CHARGE_PUMP: 203 + return true; 204 + default: 205 + return false; 206 + } 207 + } 208 + 209 + static bool nau8825_volatile_reg(struct device *dev, unsigned int reg) 210 + { 211 + switch (reg) { 212 + case NAU8825_REG_RESET: 213 + case NAU8825_REG_IRQ_STATUS: 214 + case NAU8825_REG_INT_CLR_KEY_STATUS: 215 + case NAU8825_REG_IMM_RMS_L: 216 + case NAU8825_REG_IMM_RMS_R: 217 + case NAU8825_REG_I2C_DEVICE_ID: 218 + case NAU8825_REG_SARDOUT_RAM_STATUS: 219 + case NAU8825_REG_CHARGE_PUMP_INPUT_READ: 220 + case NAU8825_REG_GENERAL_STATUS: 221 + return true; 222 + default: 223 + return false; 224 + } 225 + } 226 + 227 + static int nau8825_pump_event(struct snd_soc_dapm_widget *w, 228 + struct snd_kcontrol *kcontrol, int event) 229 + { 230 + switch (event) { 231 + case SND_SOC_DAPM_POST_PMU: 232 + /* Prevent startup click by letting charge pump to ramp up */ 233 + msleep(10); 234 + break; 235 + default: 236 + return -EINVAL; 237 + } 238 + 239 + return 0; 240 + } 241 + 242 + static const char * const nau8825_adc_decimation[] = { 243 + "32", "64", "128", "256" 244 + }; 245 + 246 + static const struct soc_enum nau8825_adc_decimation_enum = 247 + SOC_ENUM_SINGLE(NAU8825_REG_ADC_RATE, NAU8825_ADC_SYNC_DOWN_SFT, 248 + ARRAY_SIZE(nau8825_adc_decimation), nau8825_adc_decimation); 249 + 250 + static const char * const nau8825_dac_oversampl[] = { 251 + "64", "256", "128", "", "32" 252 + }; 253 + 254 + static const struct soc_enum nau8825_dac_oversampl_enum = 255 + SOC_ENUM_SINGLE(NAU8825_REG_DAC_CTRL1, NAU8825_DAC_OVERSAMPLE_SFT, 256 + ARRAY_SIZE(nau8825_dac_oversampl), nau8825_dac_oversampl); 257 + 258 + static const DECLARE_TLV_DB_MINMAX_MUTE(adc_vol_tlv, -10300, 2400); 259 + static const DECLARE_TLV_DB_MINMAX_MUTE(sidetone_vol_tlv, -4200, 0); 260 + static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -5400, 0); 261 + static const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600); 262 + static const DECLARE_TLV_DB_MINMAX_MUTE(crosstalk_vol_tlv, -9600, 2400); 263 + 264 + static const struct snd_kcontrol_new nau8825_controls[] = { 265 + SOC_SINGLE_TLV("Mic Volume", NAU8825_REG_ADC_DGAIN_CTRL, 266 + 0, 0xff, 0, adc_vol_tlv), 267 + SOC_DOUBLE_TLV("Headphone Bypass Volume", NAU8825_REG_ADC_DGAIN_CTRL, 268 + 12, 8, 0x0f, 0, sidetone_vol_tlv), 269 + SOC_DOUBLE_TLV("Headphone Volume", NAU8825_REG_HSVOL_CTRL, 270 + 6, 0, 0x3f, 1, dac_vol_tlv), 271 + SOC_SINGLE_TLV("Frontend PGA Volume", NAU8825_REG_POWER_UP_CONTROL, 272 + 8, 37, 0, fepga_gain_tlv), 273 + SOC_DOUBLE_TLV("Headphone Crosstalk Volume", NAU8825_REG_DAC_DGAIN_CTRL, 274 + 0, 8, 0xff, 0, crosstalk_vol_tlv), 275 + 276 + SOC_ENUM("ADC Decimation Rate", nau8825_adc_decimation_enum), 277 + SOC_ENUM("DAC Oversampling Rate", nau8825_dac_oversampl_enum), 278 + }; 279 + 280 + /* DAC Mux 0x33[9] and 0x34[9] */ 281 + static const char * const nau8825_dac_src[] = { 282 + "DACL", "DACR", 283 + }; 284 + 285 + static SOC_ENUM_SINGLE_DECL( 286 + nau8825_dacl_enum, NAU8825_REG_DACL_CTRL, 287 + NAU8825_DACL_CH_SEL_SFT, nau8825_dac_src); 288 + 289 + static SOC_ENUM_SINGLE_DECL( 290 + nau8825_dacr_enum, NAU8825_REG_DACR_CTRL, 291 + NAU8825_DACR_CH_SEL_SFT, nau8825_dac_src); 292 + 293 + static const struct snd_kcontrol_new nau8825_dacl_mux = 294 + SOC_DAPM_ENUM("DACL Source", nau8825_dacl_enum); 295 + 296 + static const struct snd_kcontrol_new nau8825_dacr_mux = 297 + SOC_DAPM_ENUM("DACR Source", nau8825_dacr_enum); 298 + 299 + 300 + static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { 301 + SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, NAU8825_REG_I2S_PCM_CTRL2, 302 + 15, 1), 303 + 304 + SND_SOC_DAPM_INPUT("MIC"), 305 + SND_SOC_DAPM_MICBIAS("MICBIAS", NAU8825_REG_MIC_BIAS, 8, 0), 306 + 307 + SND_SOC_DAPM_PGA("Frontend PGA", NAU8825_REG_POWER_UP_CONTROL, 14, 0, 308 + NULL, 0), 309 + 310 + SND_SOC_DAPM_ADC("ADC", NULL, NAU8825_REG_ENA_CTRL, 8, 0), 311 + SND_SOC_DAPM_SUPPLY("ADC Clock", NAU8825_REG_ENA_CTRL, 7, 0, NULL, 0), 312 + SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL, 313 + 0), 314 + 315 + /* ADC for button press detection */ 316 + SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, 317 + NAU8825_SAR_ADC_EN_SFT, 0), 318 + 319 + SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), 320 + SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), 321 + SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), 322 + SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0), 323 + 324 + SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, 325 + NAU8825_ENABLE_DACR_SFT, 0), 326 + SND_SOC_DAPM_DAC("DDACL", NULL, NAU8825_REG_ENA_CTRL, 327 + NAU8825_ENABLE_DACL_SFT, 0), 328 + SND_SOC_DAPM_SUPPLY("DDAC Clock", NAU8825_REG_ENA_CTRL, 6, 0, NULL, 0), 329 + 330 + SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), 331 + SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux), 332 + 333 + SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), 334 + SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), 335 + SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 336 + 0), 337 + 338 + SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0, 339 + nau8825_pump_event, SND_SOC_DAPM_POST_PMU), 340 + 341 + SND_SOC_DAPM_PGA("Output Driver R Stage 1", 342 + NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), 343 + SND_SOC_DAPM_PGA("Output Driver L Stage 1", 344 + NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), 345 + SND_SOC_DAPM_PGA("Output Driver R Stage 2", 346 + NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), 347 + SND_SOC_DAPM_PGA("Output Driver L Stage 2", 348 + NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), 349 + SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1, 350 + NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), 351 + SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1, 352 + NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0), 353 + 354 + SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0), 355 + SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0), 356 + 357 + SND_SOC_DAPM_OUTPUT("HPOL"), 358 + SND_SOC_DAPM_OUTPUT("HPOR"), 359 + }; 360 + 361 + static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { 362 + {"Frontend PGA", NULL, "MIC"}, 363 + {"ADC", NULL, "Frontend PGA"}, 364 + {"ADC", NULL, "ADC Clock"}, 365 + {"ADC", NULL, "ADC Power"}, 366 + {"AIFTX", NULL, "ADC"}, 367 + 368 + {"DDACL", NULL, "Playback"}, 369 + {"DDACR", NULL, "Playback"}, 370 + {"DDACL", NULL, "DDAC Clock"}, 371 + {"DDACR", NULL, "DDAC Clock"}, 372 + {"DACL Mux", "DACL", "DDACL"}, 373 + {"DACL Mux", "DACR", "DDACR"}, 374 + {"DACR Mux", "DACL", "DDACL"}, 375 + {"DACR Mux", "DACR", "DDACR"}, 376 + {"HP amp L", NULL, "DACL Mux"}, 377 + {"HP amp R", NULL, "DACR Mux"}, 378 + {"HP amp L", NULL, "HP amp power"}, 379 + {"HP amp R", NULL, "HP amp power"}, 380 + {"ADACL", NULL, "HP amp L"}, 381 + {"ADACR", NULL, "HP amp R"}, 382 + {"ADACL", NULL, "ADACL Clock"}, 383 + {"ADACR", NULL, "ADACR Clock"}, 384 + {"Output Driver L Stage 1", NULL, "ADACL"}, 385 + {"Output Driver R Stage 1", NULL, "ADACR"}, 386 + {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, 387 + {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, 388 + {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, 389 + {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"}, 390 + {"Output DACL", NULL, "Output Driver L Stage 3"}, 391 + {"Output DACR", NULL, "Output Driver R Stage 3"}, 392 + {"HPOL", NULL, "Output DACL"}, 393 + {"HPOR", NULL, "Output DACR"}, 394 + {"HPOL", NULL, "Charge Pump"}, 395 + {"HPOR", NULL, "Charge Pump"}, 396 + }; 397 + 398 + static int nau8825_hw_params(struct snd_pcm_substream *substream, 399 + struct snd_pcm_hw_params *params, 400 + struct snd_soc_dai *dai) 401 + { 402 + struct snd_soc_codec *codec = dai->codec; 403 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 404 + unsigned int val_len = 0; 405 + 406 + switch (params_width(params)) { 407 + case 16: 408 + val_len |= NAU8825_I2S_DL_16; 409 + break; 410 + case 20: 411 + val_len |= NAU8825_I2S_DL_20; 412 + break; 413 + case 24: 414 + val_len |= NAU8825_I2S_DL_24; 415 + break; 416 + case 32: 417 + val_len |= NAU8825_I2S_DL_32; 418 + break; 419 + default: 420 + return -EINVAL; 421 + } 422 + 423 + regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, 424 + NAU8825_I2S_DL_MASK, val_len); 425 + 426 + return 0; 427 + } 428 + 429 + static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 430 + { 431 + struct snd_soc_codec *codec = codec_dai->codec; 432 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 433 + unsigned int ctrl1_val = 0, ctrl2_val = 0; 434 + 435 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 436 + case SND_SOC_DAIFMT_CBM_CFM: 437 + ctrl2_val |= NAU8825_I2S_MS_MASTER; 438 + break; 439 + case SND_SOC_DAIFMT_CBS_CFS: 440 + break; 441 + default: 442 + return -EINVAL; 443 + } 444 + 445 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 446 + case SND_SOC_DAIFMT_NB_NF: 447 + break; 448 + case SND_SOC_DAIFMT_IB_NF: 449 + ctrl1_val |= NAU8825_I2S_BP_INV; 450 + break; 451 + default: 452 + return -EINVAL; 453 + } 454 + 455 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 456 + case SND_SOC_DAIFMT_I2S: 457 + ctrl1_val |= NAU8825_I2S_DF_I2S; 458 + break; 459 + case SND_SOC_DAIFMT_LEFT_J: 460 + ctrl1_val |= NAU8825_I2S_DF_LEFT; 461 + break; 462 + case SND_SOC_DAIFMT_RIGHT_J: 463 + ctrl1_val |= NAU8825_I2S_DF_RIGTH; 464 + break; 465 + case SND_SOC_DAIFMT_DSP_A: 466 + ctrl1_val |= NAU8825_I2S_DF_PCM_AB; 467 + break; 468 + case SND_SOC_DAIFMT_DSP_B: 469 + ctrl1_val |= NAU8825_I2S_DF_PCM_AB; 470 + ctrl1_val |= NAU8825_I2S_PCMB_EN; 471 + break; 472 + default: 473 + return -EINVAL; 474 + } 475 + 476 + regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, 477 + NAU8825_I2S_DL_MASK | NAU8825_I2S_DF_MASK | 478 + NAU8825_I2S_BP_MASK | NAU8825_I2S_PCMB_MASK, 479 + ctrl1_val); 480 + regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, 481 + NAU8825_I2S_MS_MASK, ctrl2_val); 482 + 483 + return 0; 484 + } 485 + 486 + static const struct snd_soc_dai_ops nau8825_dai_ops = { 487 + .hw_params = nau8825_hw_params, 488 + .set_fmt = nau8825_set_dai_fmt, 489 + }; 490 + 491 + #define NAU8825_RATES SNDRV_PCM_RATE_8000_192000 492 + #define NAU8825_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ 493 + | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 494 + 495 + static struct snd_soc_dai_driver nau8825_dai = { 496 + .name = "nau8825-hifi", 497 + .playback = { 498 + .stream_name = "Playback", 499 + .channels_min = 1, 500 + .channels_max = 2, 501 + .rates = NAU8825_RATES, 502 + .formats = NAU8825_FORMATS, 503 + }, 504 + .capture = { 505 + .stream_name = "Capture", 506 + .channels_min = 1, 507 + .channels_max = 1, 508 + .rates = NAU8825_RATES, 509 + .formats = NAU8825_FORMATS, 510 + }, 511 + .ops = &nau8825_dai_ops, 512 + }; 513 + 514 + /** 515 + * nau8825_enable_jack_detect - Specify a jack for event reporting 516 + * 517 + * @component: component to register the jack with 518 + * @jack: jack to use to report headset and button events on 519 + * 520 + * After this function has been called the headset insert/remove and button 521 + * events will be routed to the given jack. Jack can be null to stop 522 + * reporting. 523 + */ 524 + int nau8825_enable_jack_detect(struct snd_soc_codec *codec, 525 + struct snd_soc_jack *jack) 526 + { 527 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 528 + struct regmap *regmap = nau8825->regmap; 529 + 530 + nau8825->jack = jack; 531 + 532 + /* Ground HP Outputs[1:0], needed for headset auto detection 533 + * Enable Automatic Mic/Gnd switching reading on insert interrupt[6] 534 + */ 535 + regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 536 + NAU8825_HSD_AUTO_MODE | NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, 537 + NAU8825_HSD_AUTO_MODE | NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L); 538 + 539 + regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 540 + NAU8825_IRQ_HEADSET_COMPLETE_EN | NAU8825_IRQ_EJECT_EN, 0); 541 + 542 + return 0; 543 + } 544 + EXPORT_SYMBOL_GPL(nau8825_enable_jack_detect); 545 + 546 + 547 + static bool nau8825_is_jack_inserted(struct regmap *regmap) 548 + { 549 + int status; 550 + 551 + regmap_read(regmap, NAU8825_REG_I2C_DEVICE_ID, &status); 552 + return !(status & NAU8825_GPIO2JD1); 553 + } 554 + 555 + static void nau8825_restart_jack_detection(struct regmap *regmap) 556 + { 557 + /* this will restart the entire jack detection process including MIC/GND 558 + * switching and create interrupts. We have to go from 0 to 1 and back 559 + * to 0 to restart. 560 + */ 561 + regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, 562 + NAU8825_JACK_DET_RESTART, NAU8825_JACK_DET_RESTART); 563 + regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, 564 + NAU8825_JACK_DET_RESTART, 0); 565 + } 566 + 567 + static void nau8825_eject_jack(struct nau8825 *nau8825) 568 + { 569 + struct snd_soc_dapm_context *dapm = nau8825->dapm; 570 + struct regmap *regmap = nau8825->regmap; 571 + 572 + snd_soc_dapm_disable_pin(dapm, "SAR"); 573 + snd_soc_dapm_disable_pin(dapm, "MICBIAS"); 574 + /* Detach 2kOhm Resistors from MICBIAS to MICGND1/2 */ 575 + regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, 576 + NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 0); 577 + /* ground HPL/HPR, MICGRND1/2 */ 578 + regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0xf, 0xf); 579 + 580 + snd_soc_dapm_sync(dapm); 581 + } 582 + 583 + static int nau8825_button_decode(int value) 584 + { 585 + int buttons = 0; 586 + 587 + /* The chip supports up to 8 buttons, but ALSA defines only 6 buttons */ 588 + if (value & BIT(0)) 589 + buttons |= SND_JACK_BTN_0; 590 + if (value & BIT(1)) 591 + buttons |= SND_JACK_BTN_1; 592 + if (value & BIT(2)) 593 + buttons |= SND_JACK_BTN_2; 594 + if (value & BIT(3)) 595 + buttons |= SND_JACK_BTN_3; 596 + if (value & BIT(4)) 597 + buttons |= SND_JACK_BTN_4; 598 + if (value & BIT(5)) 599 + buttons |= SND_JACK_BTN_5; 600 + 601 + return buttons; 602 + } 603 + 604 + static int nau8825_jack_insert(struct nau8825 *nau8825) 605 + { 606 + struct regmap *regmap = nau8825->regmap; 607 + struct snd_soc_dapm_context *dapm = nau8825->dapm; 608 + int jack_status_reg, mic_detected; 609 + int type = 0; 610 + 611 + regmap_read(regmap, NAU8825_REG_GENERAL_STATUS, &jack_status_reg); 612 + mic_detected = (jack_status_reg >> 10) & 3; 613 + 614 + switch (mic_detected) { 615 + case 0: 616 + /* no mic */ 617 + type = SND_JACK_HEADPHONE; 618 + break; 619 + case 1: 620 + dev_dbg(nau8825->dev, "OMTP (micgnd1) mic connected\n"); 621 + type = SND_JACK_HEADSET; 622 + 623 + /* Unground MICGND1 */ 624 + regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 3 << 2, 625 + 1 << 2); 626 + /* Attach 2kOhm Resistor from MICBIAS to MICGND1 */ 627 + regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, 628 + NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 629 + NAU8825_MICBIAS_JKR2); 630 + /* Attach SARADC to MICGND1 */ 631 + regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, 632 + NAU8825_SAR_INPUT_MASK, 633 + NAU8825_SAR_INPUT_JKR2); 634 + 635 + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); 636 + snd_soc_dapm_force_enable_pin(dapm, "SAR"); 637 + snd_soc_dapm_sync(dapm); 638 + break; 639 + case 2: 640 + case 3: 641 + dev_dbg(nau8825->dev, "CTIA (micgnd2) mic connected\n"); 642 + type = SND_JACK_HEADSET; 643 + 644 + /* Unground MICGND2 */ 645 + regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 3 << 2, 646 + 2 << 2); 647 + /* Attach 2kOhm Resistor from MICBIAS to MICGND2 */ 648 + regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, 649 + NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 650 + NAU8825_MICBIAS_JKSLV); 651 + /* Attach SARADC to MICGND2 */ 652 + regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, 653 + NAU8825_SAR_INPUT_MASK, 654 + NAU8825_SAR_INPUT_JKSLV); 655 + 656 + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); 657 + snd_soc_dapm_force_enable_pin(dapm, "SAR"); 658 + snd_soc_dapm_sync(dapm); 659 + break; 660 + } 661 + 662 + if (type & SND_JACK_HEADPHONE) { 663 + /* Unground HPL/R */ 664 + regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0); 665 + } 666 + 667 + return type; 668 + } 669 + 670 + #define NAU8825_BUTTONS (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ 671 + SND_JACK_BTN_2 | SND_JACK_BTN_3) 672 + 673 + static irqreturn_t nau8825_interrupt(int irq, void *data) 674 + { 675 + struct nau8825 *nau8825 = (struct nau8825 *)data; 676 + struct regmap *regmap = nau8825->regmap; 677 + int active_irq, clear_irq = 0, event = 0, event_mask = 0; 678 + 679 + regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq); 680 + 681 + if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) == 682 + NAU8825_JACK_EJECTION_DETECTED) { 683 + 684 + nau8825_eject_jack(nau8825); 685 + event_mask |= SND_JACK_HEADSET; 686 + clear_irq = NAU8825_JACK_EJECTION_IRQ_MASK; 687 + } else if (active_irq & NAU8825_KEY_SHORT_PRESS_IRQ) { 688 + int key_status; 689 + 690 + regmap_read(regmap, NAU8825_REG_INT_CLR_KEY_STATUS, 691 + &key_status); 692 + 693 + /* upper 8 bits of the register are for short pressed keys, 694 + * lower 8 bits - for long pressed buttons 695 + */ 696 + nau8825->button_pressed = nau8825_button_decode( 697 + key_status >> 8); 698 + 699 + event |= nau8825->button_pressed; 700 + event_mask |= NAU8825_BUTTONS; 701 + clear_irq = NAU8825_KEY_SHORT_PRESS_IRQ; 702 + } else if (active_irq & NAU8825_KEY_RELEASE_IRQ) { 703 + event_mask = NAU8825_BUTTONS; 704 + clear_irq = NAU8825_KEY_RELEASE_IRQ; 705 + } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) { 706 + if (nau8825_is_jack_inserted(regmap)) { 707 + event |= nau8825_jack_insert(nau8825); 708 + } else { 709 + dev_warn(nau8825->dev, "Headset completion IRQ fired but no headset connected\n"); 710 + nau8825_eject_jack(nau8825); 711 + } 712 + 713 + event_mask |= SND_JACK_HEADSET; 714 + clear_irq = NAU8825_HEADSET_COMPLETION_IRQ; 715 + } 716 + 717 + if (!clear_irq) 718 + clear_irq = active_irq; 719 + /* clears the rightmost interruption */ 720 + regmap_write(regmap, NAU8825_REG_INT_CLR_KEY_STATUS, clear_irq); 721 + 722 + if (event_mask) 723 + snd_soc_jack_report(nau8825->jack, event, event_mask); 724 + 725 + return IRQ_HANDLED; 726 + } 727 + 728 + static void nau8825_setup_buttons(struct nau8825 *nau8825) 729 + { 730 + struct regmap *regmap = nau8825->regmap; 731 + 732 + regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, 733 + NAU8825_SAR_TRACKING_GAIN_MASK, 734 + nau8825->sar_voltage << NAU8825_SAR_TRACKING_GAIN_SFT); 735 + regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, 736 + NAU8825_SAR_COMPARE_TIME_MASK, 737 + nau8825->sar_compare_time << NAU8825_SAR_COMPARE_TIME_SFT); 738 + regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, 739 + NAU8825_SAR_SAMPLING_TIME_MASK, 740 + nau8825->sar_sampling_time << NAU8825_SAR_SAMPLING_TIME_SFT); 741 + 742 + regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, 743 + NAU8825_KEYDET_LEVELS_NR_MASK, 744 + (nau8825->sar_threshold_num - 1) << NAU8825_KEYDET_LEVELS_NR_SFT); 745 + regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, 746 + NAU8825_KEYDET_HYSTERESIS_MASK, 747 + nau8825->sar_hysteresis << NAU8825_KEYDET_HYSTERESIS_SFT); 748 + regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, 749 + NAU8825_KEYDET_SHORTKEY_DEBOUNCE_MASK, 750 + nau8825->key_debounce << NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT); 751 + 752 + regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_1, 753 + (nau8825->sar_threshold[0] << 8) | nau8825->sar_threshold[1]); 754 + regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_2, 755 + (nau8825->sar_threshold[2] << 8) | nau8825->sar_threshold[3]); 756 + regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_3, 757 + (nau8825->sar_threshold[4] << 8) | nau8825->sar_threshold[5]); 758 + regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_4, 759 + (nau8825->sar_threshold[6] << 8) | nau8825->sar_threshold[7]); 760 + 761 + /* Enable short press and release interruptions */ 762 + regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 763 + NAU8825_IRQ_KEY_SHORT_PRESS_EN | NAU8825_IRQ_KEY_RELEASE_EN, 764 + 0); 765 + } 766 + 767 + static void nau8825_init_regs(struct nau8825 *nau8825) 768 + { 769 + struct regmap *regmap = nau8825->regmap; 770 + 771 + /* Enable Bias/Vmid */ 772 + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, 773 + NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); 774 + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, 775 + NAU8825_GLOBAL_BIAS_EN, NAU8825_GLOBAL_BIAS_EN); 776 + 777 + /* VMID Tieoff */ 778 + regmap_update_bits(regmap, NAU8825_REG_BIAS_ADJ, 779 + NAU8825_BIAS_VMID_SEL_MASK, 780 + nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT); 781 + /* Disable Boost Driver, Automatic Short circuit protection enable */ 782 + regmap_update_bits(regmap, NAU8825_REG_BOOST, 783 + NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | 784 + NAU8825_SHORT_SHUTDOWN_EN, 785 + NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | 786 + NAU8825_SHORT_SHUTDOWN_EN); 787 + 788 + regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, 789 + NAU8825_JKDET_OUTPUT_EN, 790 + nau8825->jkdet_enable ? 0 : NAU8825_JKDET_OUTPUT_EN); 791 + regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, 792 + NAU8825_JKDET_PULL_EN, 793 + nau8825->jkdet_pull_enable ? 0 : NAU8825_JKDET_PULL_EN); 794 + regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, 795 + NAU8825_JKDET_PULL_UP, 796 + nau8825->jkdet_pull_up ? NAU8825_JKDET_PULL_UP : 0); 797 + regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, 798 + NAU8825_JACK_POLARITY, 799 + /* jkdet_polarity - 1 is for active-low */ 800 + nau8825->jkdet_polarity ? 0 : NAU8825_JACK_POLARITY); 801 + 802 + regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, 803 + NAU8825_JACK_INSERT_DEBOUNCE_MASK, 804 + nau8825->jack_insert_debounce << NAU8825_JACK_INSERT_DEBOUNCE_SFT); 805 + regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, 806 + NAU8825_JACK_EJECT_DEBOUNCE_MASK, 807 + nau8825->jack_eject_debounce << NAU8825_JACK_EJECT_DEBOUNCE_SFT); 808 + 809 + /* Mask unneeded IRQs: 1 - disable, 0 - enable */ 810 + regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 0x7ff, 0x7ff); 811 + 812 + regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, 813 + NAU8825_MICBIAS_VOLTAGE_MASK, nau8825->micbias_voltage); 814 + 815 + if (nau8825->sar_threshold_num) 816 + nau8825_setup_buttons(nau8825); 817 + 818 + /* Default oversampling/decimations settings are unusable 819 + * (audible hiss). Set it to something better. 820 + */ 821 + regmap_update_bits(regmap, NAU8825_REG_ADC_RATE, 822 + NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); 823 + regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, 824 + NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); 825 + } 826 + 827 + static const struct regmap_config nau8825_regmap_config = { 828 + .val_bits = 16, 829 + .reg_bits = 16, 830 + 831 + .max_register = NAU8825_REG_MAX, 832 + .readable_reg = nau8825_readable_reg, 833 + .writeable_reg = nau8825_writeable_reg, 834 + .volatile_reg = nau8825_volatile_reg, 835 + 836 + .cache_type = REGCACHE_RBTREE, 837 + .reg_defaults = nau8825_reg_defaults, 838 + .num_reg_defaults = ARRAY_SIZE(nau8825_reg_defaults), 839 + }; 840 + 841 + static int nau8825_codec_probe(struct snd_soc_codec *codec) 842 + { 843 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 844 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 845 + 846 + nau8825->dapm = dapm; 847 + 848 + /* The interrupt clock is gated by x1[10:8], 849 + * one of them needs to be enabled all the time for 850 + * interrupts to happen. 851 + */ 852 + snd_soc_dapm_force_enable_pin(dapm, "DDACR"); 853 + snd_soc_dapm_sync(dapm); 854 + 855 + /* Unmask interruptions. Handler uses dapm object so we can enable 856 + * interruptions only after dapm is fully initialized. 857 + */ 858 + regmap_write(nau8825->regmap, NAU8825_REG_INTERRUPT_DIS_CTRL, 0); 859 + nau8825_restart_jack_detection(nau8825->regmap); 860 + 861 + return 0; 862 + } 863 + 864 + /** 865 + * nau8825_calc_fll_param - Calculate FLL parameters. 866 + * @fll_in: external clock provided to codec. 867 + * @fs: sampling rate. 868 + * @fll_param: Pointer to structure of FLL parameters. 869 + * 870 + * Calculate FLL parameters to configure codec. 871 + * 872 + * Returns 0 for success or negative error code. 873 + */ 874 + static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, 875 + struct nau8825_fll *fll_param) 876 + { 877 + u64 fvco; 878 + unsigned int fref, i; 879 + 880 + /* Ensure the reference clock frequency (FREF) is <= 13.5MHz by dividing 881 + * freq_in by 1, 2, 4, or 8 using FLL pre-scalar. 882 + * FREF = freq_in / NAU8825_FLL_REF_DIV_MASK 883 + */ 884 + for (i = 0; i < ARRAY_SIZE(fll_pre_scalar); i++) { 885 + fref = fll_in / fll_pre_scalar[i].param; 886 + if (fref <= NAU_FREF_MAX) 887 + break; 888 + } 889 + if (i == ARRAY_SIZE(fll_pre_scalar)) 890 + return -EINVAL; 891 + fll_param->clk_ref_div = fll_pre_scalar[i].val; 892 + 893 + /* Choose the FLL ratio based on FREF */ 894 + for (i = 0; i < ARRAY_SIZE(fll_ratio); i++) { 895 + if (fref >= fll_ratio[i].param) 896 + break; 897 + } 898 + if (i == ARRAY_SIZE(fll_ratio)) 899 + return -EINVAL; 900 + fll_param->ratio = fll_ratio[i].val; 901 + 902 + /* Calculate the frequency of DCO (FDCO) given freq_out = 256 * Fs. 903 + * FDCO must be within the 90MHz - 100MHz or the FFL cannot be 904 + * guaranteed across the full range of operation. 905 + * FDCO = freq_out * 2 * mclk_src_scaling 906 + */ 907 + for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { 908 + fvco = 256 * fs * 2 * mclk_src_scaling[i].param; 909 + if (NAU_FVCO_MIN < fvco && fvco < NAU_FVCO_MAX) 910 + break; 911 + } 912 + if (i == ARRAY_SIZE(mclk_src_scaling)) 913 + return -EINVAL; 914 + fll_param->mclk_src = mclk_src_scaling[i].val; 915 + 916 + /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional 917 + * input based on FDCO, FREF and FLL ratio. 918 + */ 919 + fvco = div_u64(fvco << 16, fref * fll_param->ratio); 920 + fll_param->fll_int = (fvco >> 16) & 0x3FF; 921 + fll_param->fll_frac = fvco & 0xFFFF; 922 + return 0; 923 + } 924 + 925 + static void nau8825_fll_apply(struct nau8825 *nau8825, 926 + struct nau8825_fll *fll_param) 927 + { 928 + regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, 929 + NAU8825_CLK_MCLK_SRC_MASK, fll_param->mclk_src); 930 + regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1, 931 + NAU8825_FLL_RATIO_MASK, fll_param->ratio); 932 + /* FLL 16-bit fractional input */ 933 + regmap_write(nau8825->regmap, NAU8825_REG_FLL2, fll_param->fll_frac); 934 + /* FLL 10-bit integer input */ 935 + regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL3, 936 + NAU8825_FLL_INTEGER_MASK, fll_param->fll_int); 937 + /* FLL pre-scaler */ 938 + regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL4, 939 + NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div); 940 + /* select divided VCO input */ 941 + regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, 942 + NAU8825_FLL_FILTER_SW_MASK, 0x0000); 943 + /* FLL sigma delta modulator enable */ 944 + regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, 945 + NAU8825_SDM_EN_MASK, NAU8825_SDM_EN); 946 + } 947 + 948 + /* freq_out must be 256*Fs in order to achieve the best performance */ 949 + static int nau8825_set_pll(struct snd_soc_codec *codec, int pll_id, int source, 950 + unsigned int freq_in, unsigned int freq_out) 951 + { 952 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 953 + struct nau8825_fll fll_param; 954 + int ret, fs; 955 + 956 + fs = freq_out / 256; 957 + ret = nau8825_calc_fll_param(freq_in, fs, &fll_param); 958 + if (ret < 0) { 959 + dev_err(codec->dev, "Unsupported input clock %d\n", freq_in); 960 + return ret; 961 + } 962 + dev_dbg(codec->dev, "mclk_src=%x ratio=%x fll_frac=%x fll_int=%x clk_ref_div=%x\n", 963 + fll_param.mclk_src, fll_param.ratio, fll_param.fll_frac, 964 + fll_param.fll_int, fll_param.clk_ref_div); 965 + 966 + nau8825_fll_apply(nau8825, &fll_param); 967 + mdelay(2); 968 + regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, 969 + NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); 970 + return 0; 971 + } 972 + 973 + static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, 974 + unsigned int freq) 975 + { 976 + struct regmap *regmap = nau8825->regmap; 977 + int ret; 978 + 979 + switch (clk_id) { 980 + case NAU8825_CLK_MCLK: 981 + regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, 982 + NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK); 983 + regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); 984 + 985 + /* We selected MCLK source but the clock itself managed externally */ 986 + if (!nau8825->mclk) 987 + break; 988 + 989 + if (!nau8825->mclk_freq) { 990 + ret = clk_prepare_enable(nau8825->mclk); 991 + if (ret) { 992 + dev_err(nau8825->dev, "Unable to prepare codec mclk\n"); 993 + return ret; 994 + } 995 + } 996 + 997 + if (nau8825->mclk_freq != freq) { 998 + nau8825->mclk_freq = freq; 999 + 1000 + freq = clk_round_rate(nau8825->mclk, freq); 1001 + ret = clk_set_rate(nau8825->mclk, freq); 1002 + if (ret) { 1003 + dev_err(nau8825->dev, "Unable to set mclk rate\n"); 1004 + return ret; 1005 + } 1006 + } 1007 + 1008 + break; 1009 + case NAU8825_CLK_INTERNAL: 1010 + regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 1011 + NAU8825_DCO_EN); 1012 + regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, 1013 + NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); 1014 + 1015 + if (nau8825->mclk_freq) { 1016 + clk_disable_unprepare(nau8825->mclk); 1017 + nau8825->mclk_freq = 0; 1018 + } 1019 + 1020 + break; 1021 + default: 1022 + dev_err(nau8825->dev, "Invalid clock id (%d)\n", clk_id); 1023 + return -EINVAL; 1024 + } 1025 + 1026 + dev_dbg(nau8825->dev, "Sysclk is %dHz and clock id is %d\n", freq, 1027 + clk_id); 1028 + return 0; 1029 + } 1030 + 1031 + static int nau8825_set_sysclk(struct snd_soc_codec *codec, int clk_id, 1032 + int source, unsigned int freq, int dir) 1033 + { 1034 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1035 + 1036 + return nau8825_configure_sysclk(nau8825, clk_id, freq); 1037 + } 1038 + 1039 + static int nau8825_set_bias_level(struct snd_soc_codec *codec, 1040 + enum snd_soc_bias_level level) 1041 + { 1042 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1043 + int ret; 1044 + 1045 + switch (level) { 1046 + case SND_SOC_BIAS_ON: 1047 + break; 1048 + 1049 + case SND_SOC_BIAS_PREPARE: 1050 + break; 1051 + 1052 + case SND_SOC_BIAS_STANDBY: 1053 + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 1054 + if (nau8825->mclk_freq) { 1055 + ret = clk_prepare_enable(nau8825->mclk); 1056 + if (ret) { 1057 + dev_err(nau8825->dev, "Unable to prepare codec mclk\n"); 1058 + return ret; 1059 + } 1060 + } 1061 + 1062 + ret = regcache_sync(nau8825->regmap); 1063 + if (ret) { 1064 + dev_err(codec->dev, 1065 + "Failed to sync cache: %d\n", ret); 1066 + return ret; 1067 + } 1068 + } 1069 + 1070 + break; 1071 + 1072 + case SND_SOC_BIAS_OFF: 1073 + if (nau8825->mclk_freq) 1074 + clk_disable_unprepare(nau8825->mclk); 1075 + 1076 + regcache_mark_dirty(nau8825->regmap); 1077 + break; 1078 + } 1079 + return 0; 1080 + } 1081 + 1082 + static struct snd_soc_codec_driver nau8825_codec_driver = { 1083 + .probe = nau8825_codec_probe, 1084 + .set_sysclk = nau8825_set_sysclk, 1085 + .set_pll = nau8825_set_pll, 1086 + .set_bias_level = nau8825_set_bias_level, 1087 + .suspend_bias_off = true, 1088 + 1089 + .controls = nau8825_controls, 1090 + .num_controls = ARRAY_SIZE(nau8825_controls), 1091 + .dapm_widgets = nau8825_dapm_widgets, 1092 + .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), 1093 + .dapm_routes = nau8825_dapm_routes, 1094 + .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), 1095 + }; 1096 + 1097 + static void nau8825_reset_chip(struct regmap *regmap) 1098 + { 1099 + regmap_write(regmap, NAU8825_REG_RESET, 0x00); 1100 + regmap_write(regmap, NAU8825_REG_RESET, 0x00); 1101 + } 1102 + 1103 + static void nau8825_print_device_properties(struct nau8825 *nau8825) 1104 + { 1105 + int i; 1106 + struct device *dev = nau8825->dev; 1107 + 1108 + dev_dbg(dev, "jkdet-enable: %d\n", nau8825->jkdet_enable); 1109 + dev_dbg(dev, "jkdet-pull-enable: %d\n", nau8825->jkdet_pull_enable); 1110 + dev_dbg(dev, "jkdet-pull-up: %d\n", nau8825->jkdet_pull_up); 1111 + dev_dbg(dev, "jkdet-polarity: %d\n", nau8825->jkdet_polarity); 1112 + dev_dbg(dev, "micbias-voltage: %d\n", nau8825->micbias_voltage); 1113 + dev_dbg(dev, "vref-impedance: %d\n", nau8825->vref_impedance); 1114 + 1115 + dev_dbg(dev, "sar-threshold-num: %d\n", nau8825->sar_threshold_num); 1116 + for (i = 0; i < nau8825->sar_threshold_num; i++) 1117 + dev_dbg(dev, "sar-threshold[%d]=%d\n", i, 1118 + nau8825->sar_threshold[i]); 1119 + 1120 + dev_dbg(dev, "sar-hysteresis: %d\n", nau8825->sar_hysteresis); 1121 + dev_dbg(dev, "sar-voltage: %d\n", nau8825->sar_voltage); 1122 + dev_dbg(dev, "sar-compare-time: %d\n", nau8825->sar_compare_time); 1123 + dev_dbg(dev, "sar-sampling-time: %d\n", nau8825->sar_sampling_time); 1124 + dev_dbg(dev, "short-key-debounce: %d\n", nau8825->key_debounce); 1125 + dev_dbg(dev, "jack-insert-debounce: %d\n", 1126 + nau8825->jack_insert_debounce); 1127 + dev_dbg(dev, "jack-eject-debounce: %d\n", 1128 + nau8825->jack_eject_debounce); 1129 + } 1130 + 1131 + static int nau8825_read_device_properties(struct device *dev, 1132 + struct nau8825 *nau8825) { 1133 + 1134 + nau8825->jkdet_enable = device_property_read_bool(dev, 1135 + "nuvoton,jkdet-enable"); 1136 + nau8825->jkdet_pull_enable = device_property_read_bool(dev, 1137 + "nuvoton,jkdet-pull-enable"); 1138 + nau8825->jkdet_pull_up = device_property_read_bool(dev, 1139 + "nuvoton,jkdet-pull-up"); 1140 + device_property_read_u32(dev, "nuvoton,jkdet-polarity", 1141 + &nau8825->jkdet_polarity); 1142 + device_property_read_u32(dev, "nuvoton,micbias-voltage", 1143 + &nau8825->micbias_voltage); 1144 + device_property_read_u32(dev, "nuvoton,vref-impedance", 1145 + &nau8825->vref_impedance); 1146 + device_property_read_u32(dev, "nuvoton,sar-threshold-num", 1147 + &nau8825->sar_threshold_num); 1148 + device_property_read_u32_array(dev, "nuvoton,sar-threshold", 1149 + nau8825->sar_threshold, nau8825->sar_threshold_num); 1150 + device_property_read_u32(dev, "nuvoton,sar-hysteresis", 1151 + &nau8825->sar_hysteresis); 1152 + device_property_read_u32(dev, "nuvoton,sar-voltage", 1153 + &nau8825->sar_voltage); 1154 + device_property_read_u32(dev, "nuvoton,sar-compare-time", 1155 + &nau8825->sar_compare_time); 1156 + device_property_read_u32(dev, "nuvoton,sar-sampling-time", 1157 + &nau8825->sar_sampling_time); 1158 + device_property_read_u32(dev, "nuvoton,short-key-debounce", 1159 + &nau8825->key_debounce); 1160 + device_property_read_u32(dev, "nuvoton,jack-insert-debounce", 1161 + &nau8825->jack_insert_debounce); 1162 + device_property_read_u32(dev, "nuvoton,jack-eject-debounce", 1163 + &nau8825->jack_eject_debounce); 1164 + 1165 + nau8825->mclk = devm_clk_get(dev, "mclk"); 1166 + if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { 1167 + return -EPROBE_DEFER; 1168 + } else if (PTR_ERR(nau8825->mclk) == -ENOENT) { 1169 + /* The MCLK is managed externally or not used at all */ 1170 + nau8825->mclk = NULL; 1171 + dev_info(dev, "No 'mclk' clock found, assume MCLK is managed externally"); 1172 + } else if (IS_ERR(nau8825->mclk)) { 1173 + return -EINVAL; 1174 + } 1175 + 1176 + return 0; 1177 + } 1178 + 1179 + static int nau8825_setup_irq(struct nau8825 *nau8825) 1180 + { 1181 + struct regmap *regmap = nau8825->regmap; 1182 + int ret; 1183 + 1184 + /* IRQ Output Enable */ 1185 + regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 1186 + NAU8825_IRQ_OUTPUT_EN, NAU8825_IRQ_OUTPUT_EN); 1187 + 1188 + /* Enable internal VCO needed for interruptions */ 1189 + nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0); 1190 + 1191 + /* Enable DDACR needed for interrupts 1192 + * It is the same as force_enable_pin("DDACR") we do later 1193 + */ 1194 + regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, 1195 + NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); 1196 + 1197 + /* Chip needs one FSCLK cycle in order to generate interrupts, 1198 + * as we cannot guarantee one will be provided by the system. Turning 1199 + * master mode on then off enables us to generate that FSCLK cycle 1200 + * with a minimum of contention on the clock bus. 1201 + */ 1202 + regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 1203 + NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER); 1204 + regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 1205 + NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE); 1206 + 1207 + ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL, 1208 + nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, 1209 + "nau8825", nau8825); 1210 + 1211 + if (ret) { 1212 + dev_err(nau8825->dev, "Cannot request irq %d (%d)\n", 1213 + nau8825->irq, ret); 1214 + return ret; 1215 + } 1216 + 1217 + return 0; 1218 + } 1219 + 1220 + static int nau8825_i2c_probe(struct i2c_client *i2c, 1221 + const struct i2c_device_id *id) 1222 + { 1223 + struct device *dev = &i2c->dev; 1224 + struct nau8825 *nau8825 = dev_get_platdata(&i2c->dev); 1225 + int ret, value; 1226 + 1227 + if (!nau8825) { 1228 + nau8825 = devm_kzalloc(dev, sizeof(*nau8825), GFP_KERNEL); 1229 + if (!nau8825) 1230 + return -ENOMEM; 1231 + ret = nau8825_read_device_properties(dev, nau8825); 1232 + if (ret) 1233 + return ret; 1234 + } 1235 + 1236 + i2c_set_clientdata(i2c, nau8825); 1237 + 1238 + nau8825->regmap = devm_regmap_init_i2c(i2c, &nau8825_regmap_config); 1239 + if (IS_ERR(nau8825->regmap)) 1240 + return PTR_ERR(nau8825->regmap); 1241 + nau8825->dev = dev; 1242 + nau8825->irq = i2c->irq; 1243 + 1244 + nau8825_print_device_properties(nau8825); 1245 + 1246 + nau8825_reset_chip(nau8825->regmap); 1247 + ret = regmap_read(nau8825->regmap, NAU8825_REG_I2C_DEVICE_ID, &value); 1248 + if (ret < 0) { 1249 + dev_err(dev, "Failed to read device id from the NAU8825: %d\n", 1250 + ret); 1251 + return ret; 1252 + } 1253 + if ((value & NAU8825_SOFTWARE_ID_MASK) != 1254 + NAU8825_SOFTWARE_ID_NAU8825) { 1255 + dev_err(dev, "Not a NAU8825 chip\n"); 1256 + return -ENODEV; 1257 + } 1258 + 1259 + nau8825_init_regs(nau8825); 1260 + 1261 + if (i2c->irq) 1262 + nau8825_setup_irq(nau8825); 1263 + 1264 + return snd_soc_register_codec(&i2c->dev, &nau8825_codec_driver, 1265 + &nau8825_dai, 1); 1266 + } 1267 + 1268 + static int nau8825_i2c_remove(struct i2c_client *client) 1269 + { 1270 + snd_soc_unregister_codec(&client->dev); 1271 + return 0; 1272 + } 1273 + 1274 + static const struct i2c_device_id nau8825_i2c_ids[] = { 1275 + { "nau8825", 0 }, 1276 + { } 1277 + }; 1278 + 1279 + #ifdef CONFIG_OF 1280 + static const struct of_device_id nau8825_of_ids[] = { 1281 + { .compatible = "nuvoton,nau8825", }, 1282 + {} 1283 + }; 1284 + MODULE_DEVICE_TABLE(of, nau8825_of_ids); 1285 + #endif 1286 + 1287 + #ifdef CONFIG_ACPI 1288 + static const struct acpi_device_id nau8825_acpi_match[] = { 1289 + { "10508825", 0 }, 1290 + {}, 1291 + }; 1292 + MODULE_DEVICE_TABLE(acpi, nau8825_acpi_match); 1293 + #endif 1294 + 1295 + static struct i2c_driver nau8825_driver = { 1296 + .driver = { 1297 + .name = "nau8825", 1298 + .of_match_table = of_match_ptr(nau8825_of_ids), 1299 + .acpi_match_table = ACPI_PTR(nau8825_acpi_match), 1300 + }, 1301 + .probe = nau8825_i2c_probe, 1302 + .remove = nau8825_i2c_remove, 1303 + .id_table = nau8825_i2c_ids, 1304 + }; 1305 + module_i2c_driver(nau8825_driver); 1306 + 1307 + MODULE_DESCRIPTION("ASoC nau8825 driver"); 1308 + MODULE_AUTHOR("Anatol Pomozov <anatol@chromium.org>"); 1309 + MODULE_LICENSE("GPL");
+341
sound/soc/codecs/nau8825.h
··· 1 + /* 2 + * NAU8825 ALSA SoC audio driver 3 + * 4 + * Copyright 2015 Google Inc. 5 + * Author: Anatol Pomozov <anatol.pomozov@chrominium.org> 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 __NAU8825_H__ 13 + #define __NAU8825_H__ 14 + 15 + #define NAU8825_REG_RESET 0x00 16 + #define NAU8825_REG_ENA_CTRL 0x01 17 + #define NAU8825_REG_CLK_DIVIDER 0x03 18 + #define NAU8825_REG_FLL1 0x04 19 + #define NAU8825_REG_FLL2 0x05 20 + #define NAU8825_REG_FLL3 0x06 21 + #define NAU8825_REG_FLL4 0x07 22 + #define NAU8825_REG_FLL5 0x08 23 + #define NAU8825_REG_FLL6 0x09 24 + #define NAU8825_REG_FLL_VCO_RSV 0x0a 25 + #define NAU8825_REG_HSD_CTRL 0x0c 26 + #define NAU8825_REG_JACK_DET_CTRL 0x0d 27 + #define NAU8825_REG_INTERRUPT_MASK 0x0f 28 + #define NAU8825_REG_IRQ_STATUS 0x10 29 + #define NAU8825_REG_INT_CLR_KEY_STATUS 0x11 30 + #define NAU8825_REG_INTERRUPT_DIS_CTRL 0x12 31 + #define NAU8825_REG_SAR_CTRL 0x13 32 + #define NAU8825_REG_KEYDET_CTRL 0x14 33 + #define NAU8825_REG_VDET_THRESHOLD_1 0x15 34 + #define NAU8825_REG_VDET_THRESHOLD_2 0x16 35 + #define NAU8825_REG_VDET_THRESHOLD_3 0x17 36 + #define NAU8825_REG_VDET_THRESHOLD_4 0x18 37 + #define NAU8825_REG_GPIO34_CTRL 0x19 38 + #define NAU8825_REG_GPIO12_CTRL 0x1a 39 + #define NAU8825_REG_TDM_CTRL 0x1b 40 + #define NAU8825_REG_I2S_PCM_CTRL1 0x1c 41 + #define NAU8825_REG_I2S_PCM_CTRL2 0x1d 42 + #define NAU8825_REG_LEFT_TIME_SLOT 0x1e 43 + #define NAU8825_REG_RIGHT_TIME_SLOT 0x1f 44 + #define NAU8825_REG_BIQ_CTRL 0x20 45 + #define NAU8825_REG_BIQ_COF1 0x21 46 + #define NAU8825_REG_BIQ_COF2 0x22 47 + #define NAU8825_REG_BIQ_COF3 0x23 48 + #define NAU8825_REG_BIQ_COF4 0x24 49 + #define NAU8825_REG_BIQ_COF5 0x25 50 + #define NAU8825_REG_BIQ_COF6 0x26 51 + #define NAU8825_REG_BIQ_COF7 0x27 52 + #define NAU8825_REG_BIQ_COF8 0x28 53 + #define NAU8825_REG_BIQ_COF9 0x29 54 + #define NAU8825_REG_BIQ_COF10 0x2a 55 + #define NAU8825_REG_ADC_RATE 0x2b 56 + #define NAU8825_REG_DAC_CTRL1 0x2c 57 + #define NAU8825_REG_DAC_CTRL2 0x2d 58 + #define NAU8825_REG_DAC_DGAIN_CTRL 0x2f 59 + #define NAU8825_REG_ADC_DGAIN_CTRL 0x30 60 + #define NAU8825_REG_MUTE_CTRL 0x31 61 + #define NAU8825_REG_HSVOL_CTRL 0x32 62 + #define NAU8825_REG_DACL_CTRL 0x33 63 + #define NAU8825_REG_DACR_CTRL 0x34 64 + #define NAU8825_REG_ADC_DRC_KNEE_IP12 0x38 65 + #define NAU8825_REG_ADC_DRC_KNEE_IP34 0x39 66 + #define NAU8825_REG_ADC_DRC_SLOPES 0x3a 67 + #define NAU8825_REG_ADC_DRC_ATKDCY 0x3b 68 + #define NAU8825_REG_DAC_DRC_KNEE_IP12 0x45 69 + #define NAU8825_REG_DAC_DRC_KNEE_IP34 0x46 70 + #define NAU8825_REG_DAC_DRC_SLOPES 0x47 71 + #define NAU8825_REG_DAC_DRC_ATKDCY 0x48 72 + #define NAU8825_REG_IMM_MODE_CTRL 0x4c 73 + #define NAU8825_REG_IMM_RMS_L 0x4d 74 + #define NAU8825_REG_IMM_RMS_R 0x4e 75 + #define NAU8825_REG_CLASSG_CTRL 0x50 76 + #define NAU8825_REG_OPT_EFUSE_CTRL 0x51 77 + #define NAU8825_REG_MISC_CTRL 0x55 78 + #define NAU8825_REG_I2C_DEVICE_ID 0x58 79 + #define NAU8825_REG_SARDOUT_RAM_STATUS 0x59 80 + #define NAU8825_REG_BIAS_ADJ 0x66 81 + #define NAU8825_REG_TRIM_SETTINGS 0x68 82 + #define NAU8825_REG_ANALOG_CONTROL_1 0x69 83 + #define NAU8825_REG_ANALOG_CONTROL_2 0x6a 84 + #define NAU8825_REG_ANALOG_ADC_1 0x71 85 + #define NAU8825_REG_ANALOG_ADC_2 0x72 86 + #define NAU8825_REG_RDAC 0x73 87 + #define NAU8825_REG_MIC_BIAS 0x74 88 + #define NAU8825_REG_BOOST 0x76 89 + #define NAU8825_REG_FEPGA 0x77 90 + #define NAU8825_REG_POWER_UP_CONTROL 0x7f 91 + #define NAU8825_REG_CHARGE_PUMP 0x80 92 + #define NAU8825_REG_CHARGE_PUMP_INPUT_READ 0x81 93 + #define NAU8825_REG_GENERAL_STATUS 0x82 94 + #define NAU8825_REG_MAX NAU8825_REG_GENERAL_STATUS 95 + 96 + /* ENA_CTRL (0x1) */ 97 + #define NAU8825_ENABLE_DACR_SFT 10 98 + #define NAU8825_ENABLE_DACR (1 << NAU8825_ENABLE_DACR_SFT) 99 + #define NAU8825_ENABLE_DACL_SFT 9 100 + #define NAU8825_ENABLE_ADC_SFT 8 101 + #define NAU8825_ENABLE_SAR_SFT 1 102 + 103 + /* CLK_DIVIDER (0x3) */ 104 + #define NAU8825_CLK_SRC_SFT 15 105 + #define NAU8825_CLK_SRC_MASK (1 << NAU8825_CLK_SRC_SFT) 106 + #define NAU8825_CLK_SRC_VCO (1 << NAU8825_CLK_SRC_SFT) 107 + #define NAU8825_CLK_SRC_MCLK (0 << NAU8825_CLK_SRC_SFT) 108 + #define NAU8825_CLK_MCLK_SRC_MASK (0xf << 0) 109 + 110 + /* FLL1 (0x04) */ 111 + #define NAU8825_FLL_RATIO_MASK (0x7f << 0) 112 + 113 + /* FLL3 (0x06) */ 114 + #define NAU8825_FLL_INTEGER_MASK (0x3ff << 0) 115 + 116 + /* FLL4 (0x07) */ 117 + #define NAU8825_FLL_REF_DIV_MASK (0x3 << 10) 118 + 119 + /* FLL5 (0x08) */ 120 + #define NAU8825_FLL_FILTER_SW_MASK (0x1 << 14) 121 + 122 + /* FLL6 (0x9) */ 123 + #define NAU8825_DCO_EN_MASK (0x1 << 15) 124 + #define NAU8825_DCO_EN (0x1 << 15) 125 + #define NAU8825_DCO_DIS (0x0 << 15) 126 + #define NAU8825_SDM_EN_MASK (0x1 << 14) 127 + #define NAU8825_SDM_EN (0x1 << 14) 128 + #define NAU8825_SDM_DIS (0x0 << 14) 129 + 130 + /* HSD_CTRL (0xc) */ 131 + #define NAU8825_HSD_AUTO_MODE (1 << 6) 132 + /* 0 - short to GND, 1 - open */ 133 + #define NAU8825_SPKR_DWN1R (1 << 1) 134 + #define NAU8825_SPKR_DWN1L (1 << 0) 135 + 136 + /* JACK_DET_CTRL (0xd) */ 137 + #define NAU8825_JACK_DET_RESTART (1 << 9) 138 + #define NAU8825_JACK_INSERT_DEBOUNCE_SFT 5 139 + #define NAU8825_JACK_INSERT_DEBOUNCE_MASK (0x7 << NAU8825_JACK_INSERT_DEBOUNCE_SFT) 140 + #define NAU8825_JACK_EJECT_DEBOUNCE_SFT 2 141 + #define NAU8825_JACK_EJECT_DEBOUNCE_MASK (0x7 << NAU8825_JACK_EJECT_DEBOUNCE_SFT) 142 + #define NAU8825_JACK_POLARITY (1 << 1) /* 0 - active low, 1 - active high */ 143 + 144 + /* INTERRUPT_MASK (0xf) */ 145 + #define NAU8825_IRQ_OUTPUT_EN (1 << 11) 146 + #define NAU8825_IRQ_HEADSET_COMPLETE_EN (1 << 10) 147 + #define NAU8825_IRQ_KEY_RELEASE_EN (1 << 7) 148 + #define NAU8825_IRQ_KEY_SHORT_PRESS_EN (1 << 5) 149 + #define NAU8825_IRQ_EJECT_EN (1 << 2) 150 + 151 + /* IRQ_STATUS (0x10) */ 152 + #define NAU8825_HEADSET_COMPLETION_IRQ (1 << 10) 153 + #define NAU8825_SHORT_CIRCUIT_IRQ (1 << 9) 154 + #define NAU8825_IMPEDANCE_MEAS_IRQ (1 << 8) 155 + #define NAU8825_KEY_IRQ_MASK (0x7 << 5) 156 + #define NAU8825_KEY_RELEASE_IRQ (1 << 7) 157 + #define NAU8825_KEY_LONG_PRESS_IRQ (1 << 6) 158 + #define NAU8825_KEY_SHORT_PRESS_IRQ (1 << 5) 159 + #define NAU8825_MIC_DETECTION_IRQ (1 << 4) 160 + #define NAU8825_JACK_EJECTION_IRQ_MASK (3 << 2) 161 + #define NAU8825_JACK_EJECTION_DETECTED (1 << 2) 162 + #define NAU8825_JACK_INSERTION_IRQ_MASK (3 << 0) 163 + #define NAU8825_JACK_INSERTION_DETECTED (1 << 0) 164 + 165 + /* INTERRUPT_DIS_CTRL (0x12) */ 166 + #define NAU8825_IRQ_HEADSET_COMPLETE_DIS (1 << 10) 167 + #define NAU8825_IRQ_KEY_RELEASE_DIS (1 << 7) 168 + #define NAU8825_IRQ_KEY_SHORT_PRESS_DIS (1 << 5) 169 + #define NAU8825_IRQ_EJECT_DIS (1 << 2) 170 + 171 + /* SAR_CTRL (0x13) */ 172 + #define NAU8825_SAR_ADC_EN_SFT 12 173 + #define NAU8825_SAR_ADC_EN (1 << NAU8825_SAR_ADC_EN_SFT) 174 + #define NAU8825_SAR_INPUT_MASK (1 << 11) 175 + #define NAU8825_SAR_INPUT_JKSLV (1 << 11) 176 + #define NAU8825_SAR_INPUT_JKR2 (0 << 11) 177 + #define NAU8825_SAR_TRACKING_GAIN_SFT 8 178 + #define NAU8825_SAR_TRACKING_GAIN_MASK (0x7 << NAU8825_SAR_TRACKING_GAIN_SFT) 179 + #define NAU8825_SAR_COMPARE_TIME_SFT 2 180 + #define NAU8825_SAR_COMPARE_TIME_MASK (3 << 2) 181 + #define NAU8825_SAR_SAMPLING_TIME_SFT 0 182 + #define NAU8825_SAR_SAMPLING_TIME_MASK (3 << 0) 183 + 184 + /* KEYDET_CTRL (0x14) */ 185 + #define NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT 12 186 + #define NAU8825_KEYDET_SHORTKEY_DEBOUNCE_MASK (0x3 << NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT) 187 + #define NAU8825_KEYDET_LEVELS_NR_SFT 8 188 + #define NAU8825_KEYDET_LEVELS_NR_MASK (0x7 << 8) 189 + #define NAU8825_KEYDET_HYSTERESIS_SFT 0 190 + #define NAU8825_KEYDET_HYSTERESIS_MASK 0xf 191 + 192 + /* GPIO12_CTRL (0x1a) */ 193 + #define NAU8825_JKDET_PULL_UP (1 << 11) /* 0 - pull down, 1 - pull up */ 194 + #define NAU8825_JKDET_PULL_EN (1 << 9) /* 0 - enable pull, 1 - disable */ 195 + #define NAU8825_JKDET_OUTPUT_EN (1 << 8) /* 0 - enable input, 1 - enable output */ 196 + 197 + /* I2S_PCM_CTRL1 (0x1c) */ 198 + #define NAU8825_I2S_BP_SFT 7 199 + #define NAU8825_I2S_BP_MASK (1 << NAU8825_I2S_BP_SFT) 200 + #define NAU8825_I2S_BP_INV (1 << NAU8825_I2S_BP_SFT) 201 + #define NAU8825_I2S_PCMB_SFT 6 202 + #define NAU8825_I2S_PCMB_MASK (1 << NAU8825_I2S_PCMB_SFT) 203 + #define NAU8825_I2S_PCMB_EN (1 << NAU8825_I2S_PCMB_SFT) 204 + #define NAU8825_I2S_DL_SFT 2 205 + #define NAU8825_I2S_DL_MASK (0x3 << NAU8825_I2S_DL_SFT) 206 + #define NAU8825_I2S_DL_16 (0 << NAU8825_I2S_DL_SFT) 207 + #define NAU8825_I2S_DL_20 (1 << NAU8825_I2S_DL_SFT) 208 + #define NAU8825_I2S_DL_24 (2 << NAU8825_I2S_DL_SFT) 209 + #define NAU8825_I2S_DL_32 (3 << NAU8825_I2S_DL_SFT) 210 + #define NAU8825_I2S_DF_SFT 0 211 + #define NAU8825_I2S_DF_MASK (0x3 << NAU8825_I2S_DF_SFT) 212 + #define NAU8825_I2S_DF_RIGTH (0 << NAU8825_I2S_DF_SFT) 213 + #define NAU8825_I2S_DF_LEFT (1 << NAU8825_I2S_DF_SFT) 214 + #define NAU8825_I2S_DF_I2S (2 << NAU8825_I2S_DF_SFT) 215 + #define NAU8825_I2S_DF_PCM_AB (3 << NAU8825_I2S_DF_SFT) 216 + 217 + /* I2S_PCM_CTRL2 (0x1d) */ 218 + #define NAU8825_I2S_TRISTATE (1 << 15) /* 0 - normal mode, 1 - Hi-Z output */ 219 + #define NAU8825_I2S_MS_SFT 3 220 + #define NAU8825_I2S_MS_MASK (1 << NAU8825_I2S_MS_SFT) 221 + #define NAU8825_I2S_MS_MASTER (1 << NAU8825_I2S_MS_SFT) 222 + #define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT) 223 + 224 + /* ADC_RATE (0x2b) */ 225 + #define NAU8825_ADC_SYNC_DOWN_SFT 0 226 + #define NAU8825_ADC_SYNC_DOWN_MASK 0x3 227 + #define NAU8825_ADC_SYNC_DOWN_32 0 228 + #define NAU8825_ADC_SYNC_DOWN_64 1 229 + #define NAU8825_ADC_SYNC_DOWN_128 2 230 + #define NAU8825_ADC_SYNC_DOWN_256 3 231 + 232 + /* DAC_CTRL1 (0x2c) */ 233 + #define NAU8825_DAC_CLIP_OFF (1 << 7) 234 + #define NAU8825_DAC_OVERSAMPLE_SFT 0 235 + #define NAU8825_DAC_OVERSAMPLE_MASK 0x7 236 + #define NAU8825_DAC_OVERSAMPLE_64 0 237 + #define NAU8825_DAC_OVERSAMPLE_256 1 238 + #define NAU8825_DAC_OVERSAMPLE_128 2 239 + #define NAU8825_DAC_OVERSAMPLE_32 4 240 + 241 + /* MUTE_CTRL (0x31) */ 242 + #define NAU8825_DAC_ZERO_CROSSING_EN (1 << 9) 243 + #define NAU8825_DAC_SOFT_MUTE (1 << 9) 244 + 245 + /* HSVOL_CTRL (0x32) */ 246 + #define NAU8825_HP_MUTE (1 << 15) 247 + 248 + /* DACL_CTRL (0x33) */ 249 + #define NAU8825_DACL_CH_SEL_SFT 9 250 + 251 + /* DACR_CTRL (0x34) */ 252 + #define NAU8825_DACR_CH_SEL_SFT 9 253 + 254 + /* I2C_DEVICE_ID (0x58) */ 255 + #define NAU8825_GPIO2JD1 (1 << 7) 256 + #define NAU8825_SOFTWARE_ID_MASK 0x3 257 + #define NAU8825_SOFTWARE_ID_NAU8825 0x0 258 + 259 + /* BIAS_ADJ (0x66) */ 260 + #define NAU8825_BIAS_VMID (1 << 6) 261 + #define NAU8825_BIAS_VMID_SEL_SFT 4 262 + #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) 263 + 264 + /* ANALOG_CONTROL_2 (0x6a) */ 265 + #define NAU8825_HP_NON_CLASSG_CURRENT_2xADJ (1 << 12) 266 + #define NAU8825_DAC_CAPACITOR_MSB (1 << 1) 267 + #define NAU8825_DAC_CAPACITOR_LSB (1 << 0) 268 + 269 + /* ANALOG_ADC_2 (0x72) */ 270 + #define NAU8825_ADC_VREFSEL_MASK (0x3 << 8) 271 + #define NAU8825_ADC_VREFSEL_ANALOG (0 << 8) 272 + #define NAU8825_ADC_VREFSEL_VMID (1 << 8) 273 + #define NAU8825_ADC_VREFSEL_VMID_PLUS_0_5DB (2 << 8) 274 + #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) 275 + #define NAU8825_POWERUP_ADCL (1 << 6) 276 + 277 + /* MIC_BIAS (0x74) */ 278 + #define NAU8825_MICBIAS_JKSLV (1 << 14) 279 + #define NAU8825_MICBIAS_JKR2 (1 << 12) 280 + #define NAU8825_MICBIAS_POWERUP_SFT 8 281 + #define NAU8825_MICBIAS_VOLTAGE_SFT 0 282 + #define NAU8825_MICBIAS_VOLTAGE_MASK 0x7 283 + 284 + /* BOOST (0x76) */ 285 + #define NAU8825_PRECHARGE_DIS (1 << 13) 286 + #define NAU8825_GLOBAL_BIAS_EN (1 << 12) 287 + #define NAU8825_HP_BOOST_G_DIS (1 << 8) 288 + #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6) 289 + 290 + /* POWER_UP_CONTROL (0x7f) */ 291 + #define NAU8825_POWERUP_INTEGR_R (1 << 5) 292 + #define NAU8825_POWERUP_INTEGR_L (1 << 4) 293 + #define NAU8825_POWERUP_DRV_IN_R (1 << 3) 294 + #define NAU8825_POWERUP_DRV_IN_L (1 << 2) 295 + #define NAU8825_POWERUP_HP_DRV_R (1 << 1) 296 + #define NAU8825_POWERUP_HP_DRV_L (1 << 0) 297 + 298 + /* CHARGE_PUMP (0x80) */ 299 + #define NAU8825_JAMNODCLOW (1 << 10) 300 + #define NAU8825_POWER_DOWN_DACR (1 << 9) 301 + #define NAU8825_POWER_DOWN_DACL (1 << 8) 302 + #define NAU8825_CHANRGE_PUMP_EN (1 << 5) 303 + 304 + 305 + /* System Clock Source */ 306 + enum { 307 + NAU8825_CLK_MCLK = 0, 308 + NAU8825_CLK_INTERNAL, 309 + }; 310 + 311 + struct nau8825 { 312 + struct device *dev; 313 + struct regmap *regmap; 314 + struct snd_soc_dapm_context *dapm; 315 + struct snd_soc_jack *jack; 316 + struct clk *mclk; 317 + int irq; 318 + int mclk_freq; /* 0 - mclk is disabled */ 319 + int button_pressed; 320 + int micbias_voltage; 321 + int vref_impedance; 322 + bool jkdet_enable; 323 + bool jkdet_pull_enable; 324 + bool jkdet_pull_up; 325 + int jkdet_polarity; 326 + int sar_threshold_num; 327 + int sar_threshold[8]; 328 + int sar_hysteresis; 329 + int sar_voltage; 330 + int sar_compare_time; 331 + int sar_sampling_time; 332 + int key_debounce; 333 + int jack_insert_debounce; 334 + int jack_eject_debounce; 335 + }; 336 + 337 + int nau8825_enable_jack_detect(struct snd_soc_codec *codec, 338 + struct snd_soc_jack *jack); 339 + 340 + 341 + #endif /* __NAU8825_H__ */
+32 -17
sound/soc/pxa/pxa2xx-ac97.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/platform_device.h> 17 17 #include <linux/dmaengine.h> 18 + #include <linux/dma/pxa-dma.h> 18 19 19 20 #include <sound/core.h> 20 21 #include <sound/ac97_codec.h> ··· 50 49 .reset = pxa2xx_ac97_cold_reset, 51 50 }; 52 51 53 - static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 11; 52 + static struct pxad_param pxa2xx_ac97_pcm_stereo_in_req = { 53 + .prio = PXAD_PRIO_LOWEST, 54 + .drcmr = 11, 55 + }; 56 + 54 57 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { 55 58 .addr = __PREG(PCDR), 56 59 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, ··· 62 57 .filter_data = &pxa2xx_ac97_pcm_stereo_in_req, 63 58 }; 64 59 65 - static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 12; 60 + static struct pxad_param pxa2xx_ac97_pcm_stereo_out_req = { 61 + .prio = PXAD_PRIO_LOWEST, 62 + .drcmr = 12, 63 + }; 64 + 66 65 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = { 67 66 .addr = __PREG(PCDR), 68 67 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, ··· 74 65 .filter_data = &pxa2xx_ac97_pcm_stereo_out_req, 75 66 }; 76 67 77 - static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10; 68 + static struct pxad_param pxa2xx_ac97_pcm_aux_mono_out_req = { 69 + .prio = PXAD_PRIO_LOWEST, 70 + .drcmr = 10, 71 + }; 78 72 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = { 79 73 .addr = __PREG(MODR), 80 74 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, ··· 85 73 .filter_data = &pxa2xx_ac97_pcm_aux_mono_out_req, 86 74 }; 87 75 88 - static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9; 76 + static struct pxad_param pxa2xx_ac97_pcm_aux_mono_in_req = { 77 + .prio = PXAD_PRIO_LOWEST, 78 + .drcmr = 9, 79 + }; 89 80 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = { 90 81 .addr = __PREG(MODR), 91 82 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, ··· 96 81 .filter_data = &pxa2xx_ac97_pcm_aux_mono_in_req, 97 82 }; 98 83 99 - static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8; 84 + static struct pxad_param pxa2xx_ac97_pcm_aux_mic_mono_req = { 85 + .prio = PXAD_PRIO_LOWEST, 86 + .drcmr = 8, 87 + }; 100 88 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = { 101 89 .addr = __PREG(MCDR), 102 90 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, ··· 107 89 .filter_data = &pxa2xx_ac97_pcm_aux_mic_mono_req, 108 90 }; 109 91 110 - static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 111 - struct snd_pcm_hw_params *params, 112 - struct snd_soc_dai *cpu_dai) 92 + static int pxa2xx_ac97_hifi_startup(struct snd_pcm_substream *substream, 93 + struct snd_soc_dai *cpu_dai) 113 94 { 114 95 struct snd_dmaengine_dai_dma_data *dma_data; 115 96 ··· 122 105 return 0; 123 106 } 124 107 125 - static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, 126 - struct snd_pcm_hw_params *params, 127 - struct snd_soc_dai *cpu_dai) 108 + static int pxa2xx_ac97_aux_startup(struct snd_pcm_substream *substream, 109 + struct snd_soc_dai *cpu_dai) 128 110 { 129 111 struct snd_dmaengine_dai_dma_data *dma_data; 130 112 ··· 137 121 return 0; 138 122 } 139 123 140 - static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, 141 - struct snd_pcm_hw_params *params, 142 - struct snd_soc_dai *cpu_dai) 124 + static int pxa2xx_ac97_mic_startup(struct snd_pcm_substream *substream, 125 + struct snd_soc_dai *cpu_dai) 143 126 { 144 127 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 145 128 return -ENODEV; ··· 154 139 SNDRV_PCM_RATE_48000) 155 140 156 141 static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = { 157 - .hw_params = pxa2xx_ac97_hw_params, 142 + .startup = pxa2xx_ac97_hifi_startup, 158 143 }; 159 144 160 145 static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { 161 - .hw_params = pxa2xx_ac97_hw_aux_params, 146 + .startup = pxa2xx_ac97_aux_startup, 162 147 }; 163 148 164 149 static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { 165 - .hw_params = pxa2xx_ac97_hw_mic_params, 150 + .startup = pxa2xx_ac97_mic_startup, 166 151 }; 167 152 168 153 /*
+3
sound/soc/pxa/pxa2xx-i2s.c
··· 319 319 /* Along with FIFO servicing */ 320 320 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); 321 321 322 + snd_soc_dai_init_dma_data(dai, &pxa2xx_i2s_pcm_stereo_out, 323 + &pxa2xx_i2s_pcm_stereo_in); 324 + 322 325 return 0; 323 326 } 324 327
-32
sound/soc/pxa/pxa2xx-pcm.c
··· 15 15 #include <linux/dmaengine.h> 16 16 #include <linux/of.h> 17 17 18 - #include <mach/dma.h> 19 - 20 18 #include <sound/core.h> 21 19 #include <sound/soc.h> 22 20 #include <sound/pxa2xx-lib.h> ··· 25 27 static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 26 28 struct snd_pcm_hw_params *params) 27 29 { 28 - struct snd_pcm_runtime *runtime = substream->runtime; 29 - struct pxa2xx_runtime_data *prtd = runtime->private_data; 30 30 struct snd_soc_pcm_runtime *rtd = substream->private_data; 31 31 struct snd_dmaengine_dai_dma_data *dma; 32 - int ret; 33 32 34 33 dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 35 34 ··· 35 40 if (!dma) 36 41 return 0; 37 42 38 - /* this may get called several times by oss emulation 39 - * with different params */ 40 - if (prtd->params == NULL) { 41 - prtd->params = dma; 42 - ret = pxa_request_dma("name", DMA_PRIO_LOW, 43 - pxa2xx_pcm_dma_irq, substream); 44 - if (ret < 0) 45 - return ret; 46 - prtd->dma_ch = ret; 47 - } else if (prtd->params != dma) { 48 - pxa_free_dma(prtd->dma_ch); 49 - prtd->params = dma; 50 - ret = pxa_request_dma("name", DMA_PRIO_LOW, 51 - pxa2xx_pcm_dma_irq, substream); 52 - if (ret < 0) 53 - return ret; 54 - prtd->dma_ch = ret; 55 - } 56 - 57 43 return __pxa2xx_pcm_hw_params(substream, params); 58 44 } 59 45 60 46 static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) 61 47 { 62 - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 63 - 64 48 __pxa2xx_pcm_hw_free(substream); 65 - 66 - if (prtd->dma_ch >= 0) { 67 - pxa_free_dma(prtd->dma_ch); 68 - prtd->dma_ch = -1; 69 - prtd->params = NULL; 70 - } 71 49 72 50 return 0; 73 51 }