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

ASoC: hisilicon: Add hi6210 i2s audio driver

Add driver for hi6210 i2s controller found on hi6220 boards.

Signed-off-by: Andy Green <andy.green@linaro.org>
[jstultz: Forward ported to mainline, fairly major rework
based on suggestions from Mark Brown]
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Andy Green and committed by
Mark Brown
0bf750f4 9e615f63

+912
+1
sound/soc/Kconfig
··· 47 47 source "sound/soc/davinci/Kconfig" 48 48 source "sound/soc/dwc/Kconfig" 49 49 source "sound/soc/fsl/Kconfig" 50 + source "sound/soc/hisilicon/Kconfig" 50 51 source "sound/soc/jz4740/Kconfig" 51 52 source "sound/soc/nuc900/Kconfig" 52 53 source "sound/soc/omap/Kconfig"
+1
sound/soc/Makefile
··· 27 27 obj-$(CONFIG_SND_SOC) += davinci/ 28 28 obj-$(CONFIG_SND_SOC) += dwc/ 29 29 obj-$(CONFIG_SND_SOC) += fsl/ 30 + obj-$(CONFIG_SND_SOC) += hisilicon/ 30 31 obj-$(CONFIG_SND_SOC) += jz4740/ 31 32 obj-$(CONFIG_SND_SOC) += img/ 32 33 obj-$(CONFIG_SND_SOC) += intel/
+5
sound/soc/hisilicon/Kconfig
··· 1 + config SND_I2S_HI6210_I2S 2 + tristate "Hisilicon I2S controller" 3 + select SND_SOC_GENERIC_DMAENGINE_PCM 4 + help 5 + Hisilicon I2S
+1
sound/soc/hisilicon/Makefile
··· 1 + obj-$(CONFIG_SND_I2S_HI6210_I2S) += hi6210-i2s.o
+628
sound/soc/hisilicon/hi6210-i2s.c
··· 1 + /* 2 + * linux/sound/soc/m8m/hi6210_i2s.c - I2S IP driver 3 + * 4 + * Copyright (C) 2015 Linaro, Ltd 5 + * Author: Andy Green <andy.green@linaro.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 as published by 9 + * the Free Software Foundation, version 2 of the License. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * This driver only deals with S2 interface (BT) 17 + */ 18 + 19 + #include <linux/init.h> 20 + #include <linux/module.h> 21 + #include <linux/device.h> 22 + #include <linux/delay.h> 23 + #include <linux/clk.h> 24 + #include <linux/jiffies.h> 25 + #include <linux/io.h> 26 + #include <linux/gpio.h> 27 + #include <sound/core.h> 28 + #include <sound/pcm.h> 29 + #include <sound/pcm_params.h> 30 + #include <sound/dmaengine_pcm.h> 31 + #include <sound/initval.h> 32 + #include <sound/soc.h> 33 + #include <linux/interrupt.h> 34 + #include <linux/reset.h> 35 + #include <linux/of_address.h> 36 + #include <linux/of_irq.h> 37 + #include <linux/mfd/syscon.h> 38 + #include <linux/reset-controller.h> 39 + #include <linux/clk.h> 40 + 41 + #include "hi6210-i2s.h" 42 + 43 + struct hi6210_i2s { 44 + struct device *dev; 45 + struct reset_control *rc; 46 + struct clk *clk[8]; 47 + int clocks; 48 + struct snd_soc_dai_driver dai; 49 + void __iomem *base; 50 + struct regmap *sysctrl; 51 + phys_addr_t base_phys; 52 + struct snd_dmaengine_dai_dma_data dma_data[2]; 53 + int clk_rate; 54 + spinlock_t lock; 55 + int rate; 56 + int format; 57 + u8 bits; 58 + u8 channels; 59 + u8 id; 60 + u8 channel_length; 61 + u8 use; 62 + u32 master:1; 63 + u32 status:1; 64 + }; 65 + 66 + #define SC_PERIPH_CLKEN1 0x210 67 + #define SC_PERIPH_CLKDIS1 0x214 68 + 69 + #define SC_PERIPH_CLKEN3 0x230 70 + #define SC_PERIPH_CLKDIS3 0x234 71 + 72 + #define SC_PERIPH_CLKEN12 0x270 73 + #define SC_PERIPH_CLKDIS12 0x274 74 + 75 + #define SC_PERIPH_RSTEN1 0x310 76 + #define SC_PERIPH_RSTDIS1 0x314 77 + #define SC_PERIPH_RSTSTAT1 0x318 78 + 79 + #define SC_PERIPH_RSTEN2 0x320 80 + #define SC_PERIPH_RSTDIS2 0x324 81 + #define SC_PERIPH_RSTSTAT2 0x328 82 + 83 + #define SOC_PMCTRL_BBPPLLALIAS 0x48 84 + 85 + enum { 86 + CLK_DACODEC, 87 + CLK_I2S_BASE, 88 + }; 89 + 90 + static inline void hi6210_write_reg(struct hi6210_i2s *i2s, int reg, u32 val) 91 + { 92 + writel(val, i2s->base + reg); 93 + } 94 + 95 + static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg) 96 + { 97 + return readl(i2s->base + reg); 98 + } 99 + 100 + int hi6210_i2s_startup(struct snd_pcm_substream *substream, 101 + struct snd_soc_dai *cpu_dai) 102 + { 103 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 104 + int ret, n; 105 + u32 val; 106 + 107 + /* deassert reset on ABB */ 108 + regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val); 109 + if (val & BIT(4)) 110 + regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4)); 111 + 112 + for (n = 0; n < i2s->clocks; n++) { 113 + ret = clk_prepare_enable(i2s->clk[n]); 114 + if (ret) { 115 + while (n--) 116 + clk_disable_unprepare(i2s->clk[n]); 117 + return ret; 118 + } 119 + } 120 + 121 + ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000); 122 + if (ret) { 123 + dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n", 124 + __func__, ret); 125 + return ret; 126 + } 127 + 128 + /* enable clock before frequency division */ 129 + regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9)); 130 + 131 + /* enable codec working clock / == "codec bus clock" */ 132 + regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5)); 133 + 134 + /* deassert reset on codec / interface clock / working clock */ 135 + regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5)); 136 + regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS1, BIT(5)); 137 + 138 + /* not interested in i2s irqs */ 139 + val = hi6210_read_reg(i2s, HII2S_CODEC_IRQ_MASK); 140 + val |= 0x3f; 141 + hi6210_write_reg(i2s, HII2S_CODEC_IRQ_MASK, val); 142 + 143 + 144 + /* reset the stereo downlink fifo */ 145 + val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1); 146 + val |= (BIT(5) | BIT(4)); 147 + hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val); 148 + 149 + val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1); 150 + val &= ~(BIT(5) | BIT(4)); 151 + hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val); 152 + 153 + 154 + val = hi6210_read_reg(i2s, HII2S_SW_RST_N); 155 + val &= ~(HII2S_SW_RST_N__ST_DL_WORDLEN_MASK << 156 + HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT); 157 + val |= (HII2S_BITS_16 << HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT); 158 + hi6210_write_reg(i2s, HII2S_SW_RST_N, val); 159 + 160 + val = hi6210_read_reg(i2s, HII2S_MISC_CFG); 161 + /* mux 11/12 = APB not i2s */ 162 + val &= ~HII2S_MISC_CFG__ST_DL_TEST_SEL; 163 + /* BT R ch 0 = mixer op of DACR ch */ 164 + val &= ~HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL; 165 + val &= ~HII2S_MISC_CFG__S2_DOUT_TEST_SEL; 166 + 167 + val |= HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL; 168 + /* BT L ch = 1 = mux 7 = "mixer output of DACL */ 169 + val |= HII2S_MISC_CFG__S2_DOUT_TEST_SEL; 170 + hi6210_write_reg(i2s, HII2S_MISC_CFG, val); 171 + 172 + val = hi6210_read_reg(i2s, HII2S_SW_RST_N); 173 + val |= HII2S_SW_RST_N__SW_RST_N; 174 + hi6210_write_reg(i2s, HII2S_SW_RST_N, val); 175 + 176 + return 0; 177 + } 178 + void hi6210_i2s_shutdown(struct snd_pcm_substream *substream, 179 + struct snd_soc_dai *cpu_dai) 180 + { 181 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 182 + int n; 183 + 184 + for (n = 0; n < i2s->clocks; n++) 185 + clk_disable_unprepare(i2s->clk[n]); 186 + 187 + regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5)); 188 + } 189 + 190 + static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on) 191 + { 192 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 193 + u32 val; 194 + 195 + spin_lock(&i2s->lock); 196 + if (on) { 197 + /* enable S2 TX */ 198 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 199 + val |= HII2S_I2S_CFG__S2_IF_TX_EN; 200 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 201 + } else { 202 + /* disable S2 TX */ 203 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 204 + val &= ~HII2S_I2S_CFG__S2_IF_TX_EN; 205 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 206 + } 207 + spin_unlock(&i2s->lock); 208 + } 209 + 210 + static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on) 211 + { 212 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 213 + u32 val; 214 + 215 + spin_lock(&i2s->lock); 216 + if (on) { 217 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 218 + val |= HII2S_I2S_CFG__S2_IF_RX_EN; 219 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 220 + } else { 221 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 222 + val &= ~HII2S_I2S_CFG__S2_IF_RX_EN; 223 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 224 + } 225 + spin_unlock(&i2s->lock); 226 + } 227 + 228 + static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 229 + { 230 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 231 + 232 + /* 233 + * We don't actually set the hardware until the hw_params 234 + * call, but we need to validate the user input here. 235 + */ 236 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 237 + case SND_SOC_DAIFMT_CBM_CFM: 238 + case SND_SOC_DAIFMT_CBS_CFS: 239 + break; 240 + default: 241 + return -EINVAL; 242 + } 243 + 244 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 245 + case SND_SOC_DAIFMT_I2S: 246 + case SND_SOC_DAIFMT_LEFT_J: 247 + case SND_SOC_DAIFMT_RIGHT_J: 248 + break; 249 + default: 250 + return -EINVAL; 251 + } 252 + 253 + i2s->format = fmt; 254 + i2s->master = (i2s->format & SND_SOC_DAIFMT_MASTER_MASK) == 255 + SND_SOC_DAIFMT_CBS_CFS; 256 + 257 + return 0; 258 + } 259 + 260 + static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream, 261 + struct snd_pcm_hw_params *params, 262 + struct snd_soc_dai *cpu_dai) 263 + { 264 + struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); 265 + u32 bits = 0, rate = 0, signed_data = 0, fmt = 0; 266 + u32 val; 267 + struct snd_dmaengine_dai_dma_data *dma_data; 268 + 269 + switch (params_format(params)) { 270 + case SNDRV_PCM_FORMAT_U16_LE: 271 + signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; 272 + /* fallthru */ 273 + case SNDRV_PCM_FORMAT_S16_LE: 274 + bits = HII2S_BITS_16; 275 + break; 276 + case SNDRV_PCM_FORMAT_U24_LE: 277 + signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; 278 + /* fallthru */ 279 + case SNDRV_PCM_FORMAT_S24_LE: 280 + bits = HII2S_BITS_24; 281 + break; 282 + default: 283 + dev_err(cpu_dai->dev, "Bad format\n"); 284 + return -EINVAL; 285 + } 286 + 287 + 288 + switch (params_rate(params)) { 289 + case 8000: 290 + rate = HII2S_FS_RATE_8KHZ; 291 + break; 292 + case 16000: 293 + rate = HII2S_FS_RATE_16KHZ; 294 + break; 295 + case 32000: 296 + rate = HII2S_FS_RATE_32KHZ; 297 + break; 298 + case 48000: 299 + rate = HII2S_FS_RATE_48KHZ; 300 + break; 301 + case 96000: 302 + rate = HII2S_FS_RATE_96KHZ; 303 + break; 304 + case 192000: 305 + rate = HII2S_FS_RATE_192KHZ; 306 + break; 307 + default: 308 + dev_err(cpu_dai->dev, "Bad rate: %d\n", params_rate(params)); 309 + return -EINVAL; 310 + } 311 + 312 + if (!(params_channels(params))) { 313 + dev_err(cpu_dai->dev, "Bad channels\n"); 314 + return -EINVAL; 315 + } 316 + 317 + dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); 318 + 319 + switch (bits) { 320 + case HII2S_BITS_24: 321 + i2s->bits = 32; 322 + dma_data->addr_width = 3; 323 + break; 324 + default: 325 + i2s->bits = 16; 326 + dma_data->addr_width = 2; 327 + } 328 + i2s->rate = params_rate(params); 329 + i2s->channels = params_channels(params); 330 + i2s->channel_length = i2s->channels * i2s->bits; 331 + 332 + val = hi6210_read_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG); 333 + val &= ~((HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_MASK << 334 + HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) | 335 + (HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_MASK << 336 + HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) | 337 + (HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_MASK << 338 + HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) | 339 + (HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_MASK << 340 + HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT)); 341 + val |= ((16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) | 342 + (30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) | 343 + (16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) | 344 + (30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT)); 345 + hi6210_write_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG, val); 346 + 347 + 348 + val = hi6210_read_reg(i2s, HII2S_IF_CLK_EN_CFG); 349 + val |= (BIT(19) | BIT(18) | BIT(17) | 350 + HII2S_IF_CLK_EN_CFG__S2_IF_CLK_EN | 351 + HII2S_IF_CLK_EN_CFG__S2_OL_MIXER_EN | 352 + HII2S_IF_CLK_EN_CFG__S2_OL_SRC_EN | 353 + HII2S_IF_CLK_EN_CFG__ST_DL_R_EN | 354 + HII2S_IF_CLK_EN_CFG__ST_DL_L_EN); 355 + hi6210_write_reg(i2s, HII2S_IF_CLK_EN_CFG, val); 356 + 357 + 358 + val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG); 359 + val &= ~(HII2S_DIG_FILTER_CLK_EN_CFG__DACR_SDM_EN | 360 + HII2S_DIG_FILTER_CLK_EN_CFG__DACR_HBF2I_EN | 361 + HII2S_DIG_FILTER_CLK_EN_CFG__DACR_AGC_EN | 362 + HII2S_DIG_FILTER_CLK_EN_CFG__DACL_SDM_EN | 363 + HII2S_DIG_FILTER_CLK_EN_CFG__DACL_HBF2I_EN | 364 + HII2S_DIG_FILTER_CLK_EN_CFG__DACL_AGC_EN); 365 + val |= (HII2S_DIG_FILTER_CLK_EN_CFG__DACR_MIXER_EN | 366 + HII2S_DIG_FILTER_CLK_EN_CFG__DACL_MIXER_EN); 367 + hi6210_write_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG, val); 368 + 369 + 370 + val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG); 371 + val &= ~(HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN2_MUTE | 372 + HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN2_MUTE); 373 + hi6210_write_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG, val); 374 + 375 + val = hi6210_read_reg(i2s, HII2S_MUX_TOP_MODULE_CFG); 376 + val &= ~(HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN1_MUTE | 377 + HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN2_MUTE | 378 + HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN1_MUTE | 379 + HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN2_MUTE); 380 + hi6210_write_reg(i2s, HII2S_MUX_TOP_MODULE_CFG, val); 381 + 382 + 383 + switch (i2s->format & SND_SOC_DAIFMT_MASTER_MASK) { 384 + case SND_SOC_DAIFMT_CBM_CFM: 385 + i2s->master = false; 386 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 387 + val |= HII2S_I2S_CFG__S2_MST_SLV; 388 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 389 + break; 390 + case SND_SOC_DAIFMT_CBS_CFS: 391 + i2s->master = true; 392 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 393 + val &= ~HII2S_I2S_CFG__S2_MST_SLV; 394 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 395 + break; 396 + default: 397 + WARN_ONCE(1, "Invalid i2s->fmt MASTER_MASK. This shouldn't happen\n"); 398 + } 399 + 400 + switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { 401 + case SND_SOC_DAIFMT_I2S: 402 + fmt = HII2S_FORMAT_I2S; 403 + break; 404 + case SND_SOC_DAIFMT_LEFT_J: 405 + fmt = HII2S_FORMAT_LEFT_JUST; 406 + break; 407 + case SND_SOC_DAIFMT_RIGHT_J: 408 + fmt = HII2S_FORMAT_RIGHT_JUST; 409 + break; 410 + default: 411 + WARN_ONCE(1, "Invalid i2s->fmt FORMAT_MASK. This shouldn't happen\n"); 412 + } 413 + 414 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 415 + val &= ~(HII2S_I2S_CFG__S2_FUNC_MODE_MASK << 416 + HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT); 417 + val |= fmt << HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT; 418 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 419 + 420 + 421 + val = hi6210_read_reg(i2s, HII2S_CLK_SEL); 422 + val &= ~(HII2S_CLK_SEL__I2S_BT_FM_SEL | /* BT gets the I2S */ 423 + HII2S_CLK_SEL__EXT_12_288MHZ_SEL); 424 + hi6210_write_reg(i2s, HII2S_CLK_SEL, val); 425 + 426 + dma_data->maxburst = 2; 427 + 428 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 429 + dma_data->addr = i2s->base_phys + HII2S_ST_DL_CHANNEL; 430 + else 431 + dma_data->addr = i2s->base_phys + HII2S_STEREO_UPLINK_CHANNEL; 432 + 433 + switch (i2s->channels) { 434 + case 1: 435 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 436 + val |= HII2S_I2S_CFG__S2_FRAME_MODE; 437 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 438 + break; 439 + default: 440 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 441 + val &= ~HII2S_I2S_CFG__S2_FRAME_MODE; 442 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 443 + } 444 + 445 + /* clear loopback, set signed type and word length */ 446 + val = hi6210_read_reg(i2s, HII2S_I2S_CFG); 447 + val &= ~HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; 448 + val &= ~(HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_MASK << 449 + HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT); 450 + val &= ~(HII2S_I2S_CFG__S2_DIRECT_LOOP_MASK << 451 + HII2S_I2S_CFG__S2_DIRECT_LOOP_SHIFT); 452 + val |= signed_data; 453 + val |= (bits << HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT); 454 + hi6210_write_reg(i2s, HII2S_I2S_CFG, val); 455 + 456 + 457 + if (!i2s->master) 458 + return 0; 459 + 460 + /* set DAC and related units to correct rate */ 461 + val = hi6210_read_reg(i2s, HII2S_FS_CFG); 462 + val &= ~(HII2S_FS_CFG__FS_S2_MASK << HII2S_FS_CFG__FS_S2_SHIFT); 463 + val &= ~(HII2S_FS_CFG__FS_DACLR_MASK << HII2S_FS_CFG__FS_DACLR_SHIFT); 464 + val &= ~(HII2S_FS_CFG__FS_ST_DL_R_MASK << 465 + HII2S_FS_CFG__FS_ST_DL_R_SHIFT); 466 + val &= ~(HII2S_FS_CFG__FS_ST_DL_L_MASK << 467 + HII2S_FS_CFG__FS_ST_DL_L_SHIFT); 468 + val |= (rate << HII2S_FS_CFG__FS_S2_SHIFT); 469 + val |= (rate << HII2S_FS_CFG__FS_DACLR_SHIFT); 470 + val |= (rate << HII2S_FS_CFG__FS_ST_DL_R_SHIFT); 471 + val |= (rate << HII2S_FS_CFG__FS_ST_DL_L_SHIFT); 472 + hi6210_write_reg(i2s, HII2S_FS_CFG, val); 473 + 474 + return 0; 475 + } 476 + 477 + static int hi6210_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 478 + struct snd_soc_dai *cpu_dai) 479 + { 480 + pr_debug("%s\n", __func__); 481 + switch (cmd) { 482 + case SNDRV_PCM_TRIGGER_START: 483 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 484 + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 485 + hi6210_i2s_rxctrl(cpu_dai, 1); 486 + else 487 + hi6210_i2s_txctrl(cpu_dai, 1); 488 + break; 489 + case SNDRV_PCM_TRIGGER_STOP: 490 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 491 + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 492 + hi6210_i2s_rxctrl(cpu_dai, 0); 493 + else 494 + hi6210_i2s_txctrl(cpu_dai, 0); 495 + break; 496 + default: 497 + dev_err(cpu_dai->dev, "uknown cmd\n"); 498 + return -EINVAL; 499 + } 500 + return 0; 501 + } 502 + 503 + static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai) 504 + { 505 + struct hi6210_i2s *i2s = snd_soc_dai_get_drvdata(dai); 506 + 507 + snd_soc_dai_init_dma_data(dai, 508 + &i2s->dma_data[SNDRV_PCM_STREAM_PLAYBACK], 509 + &i2s->dma_data[SNDRV_PCM_STREAM_CAPTURE]); 510 + 511 + return 0; 512 + } 513 + 514 + 515 + static struct snd_soc_dai_ops hi6210_i2s_dai_ops = { 516 + .trigger = hi6210_i2s_trigger, 517 + .hw_params = hi6210_i2s_hw_params, 518 + .set_fmt = hi6210_i2s_set_fmt, 519 + .startup = hi6210_i2s_startup, 520 + .shutdown = hi6210_i2s_shutdown, 521 + }; 522 + 523 + struct snd_soc_dai_driver hi6210_i2s_dai_init = { 524 + .probe = hi6210_i2s_dai_probe, 525 + .playback = { 526 + .channels_min = 2, 527 + .channels_max = 2, 528 + .formats = SNDRV_PCM_FMTBIT_S16_LE | 529 + SNDRV_PCM_FMTBIT_U16_LE, 530 + .rates = SNDRV_PCM_RATE_48000, 531 + }, 532 + .capture = { 533 + .channels_min = 2, 534 + .channels_max = 2, 535 + .formats = SNDRV_PCM_FMTBIT_S16_LE | 536 + SNDRV_PCM_FMTBIT_U16_LE, 537 + .rates = SNDRV_PCM_RATE_48000, 538 + }, 539 + .ops = &hi6210_i2s_dai_ops, 540 + }; 541 + 542 + static const struct snd_soc_component_driver hi6210_i2s_i2s_comp = { 543 + .name = "hi6210_i2s-i2s", 544 + }; 545 + 546 + static int hi6210_i2s_probe(struct platform_device *pdev) 547 + { 548 + struct device_node *node = pdev->dev.of_node; 549 + struct device *dev = &pdev->dev; 550 + struct hi6210_i2s *i2s; 551 + struct resource *res; 552 + int ret; 553 + 554 + i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); 555 + if (!i2s) 556 + return -ENOMEM; 557 + 558 + i2s->dev = dev; 559 + spin_lock_init(&i2s->lock); 560 + 561 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 562 + i2s->base = devm_ioremap_resource(dev, res); 563 + if (IS_ERR(i2s->base)) 564 + return PTR_ERR(i2s->base); 565 + 566 + i2s->base_phys = (phys_addr_t)res->start; 567 + i2s->dai = hi6210_i2s_dai_init; 568 + 569 + dev_set_drvdata(&pdev->dev, i2s); 570 + 571 + i2s->sysctrl = syscon_regmap_lookup_by_phandle(node, 572 + "hisilicon,sysctrl-syscon"); 573 + if (IS_ERR(i2s->sysctrl)) 574 + return PTR_ERR(i2s->sysctrl); 575 + 576 + i2s->clk[CLK_DACODEC] = devm_clk_get(&pdev->dev, "dacodec"); 577 + if (IS_ERR_OR_NULL(i2s->clk[CLK_DACODEC])) 578 + return PTR_ERR(i2s->clk[CLK_DACODEC]); 579 + i2s->clocks++; 580 + 581 + i2s->clk[CLK_I2S_BASE] = devm_clk_get(&pdev->dev, "i2s-base"); 582 + if (IS_ERR_OR_NULL(i2s->clk[CLK_I2S_BASE])) 583 + return PTR_ERR(i2s->clk[CLK_I2S_BASE]); 584 + i2s->clocks++; 585 + 586 + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 587 + if (ret) 588 + return ret; 589 + 590 + ret = snd_soc_register_component(&pdev->dev, &hi6210_i2s_i2s_comp, 591 + &i2s->dai, 1); 592 + if (ret) { 593 + dev_err(&pdev->dev, "Failed to register dai\n"); 594 + return ret; 595 + } 596 + 597 + return 0; 598 + } 599 + 600 + static int hi6210_i2s_remove(struct platform_device *pdev) 601 + { 602 + snd_soc_unregister_component(&pdev->dev); 603 + dev_set_drvdata(&pdev->dev, NULL); 604 + 605 + return 0; 606 + } 607 + 608 + static const struct of_device_id hi6210_i2s_dt_ids[] = { 609 + { .compatible = "hisilicon,hi6210-i2s" }, 610 + { /* sentinel */ } 611 + }; 612 + 613 + MODULE_DEVICE_TABLE(of, hi6210_i2s_dt_ids); 614 + 615 + static struct platform_driver hi6210_i2s_driver = { 616 + .probe = hi6210_i2s_probe, 617 + .remove = hi6210_i2s_remove, 618 + .driver = { 619 + .name = "hi6210_i2s", 620 + .of_match_table = hi6210_i2s_dt_ids, 621 + }, 622 + }; 623 + 624 + module_platform_driver(hi6210_i2s_driver); 625 + 626 + MODULE_DESCRIPTION("Hisilicon HI6210 I2S driver"); 627 + MODULE_AUTHOR("Andy Green <andy.green@linaro.org>"); 628 + MODULE_LICENSE("GPL");
+276
sound/soc/hisilicon/hi6210-i2s.h
··· 1 + /* 2 + * linux/sound/soc/hisilicon/hi6210-i2s.h 3 + * 4 + * Copyright (C) 2015 Linaro, Ltd 5 + * Author: Andy Green <andy.green@linaro.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 as published by 9 + * the Free Software Foundation, version 2 of the License. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + * 19 + * Note at least on 6220, S2 == BT, S1 == Digital FM Radio IF 20 + */ 21 + 22 + #ifndef _HI6210_I2S_H 23 + #define _HI6210_I2S_H 24 + 25 + #define HII2S_SW_RST_N 0 26 + 27 + #define HII2S_SW_RST_N__STEREO_UPLINK_WORDLEN_SHIFT 28 28 + #define HII2S_SW_RST_N__STEREO_UPLINK_WORDLEN_MASK 3 29 + #define HII2S_SW_RST_N__THIRDMD_UPLINK_WORDLEN_SHIFT 26 30 + #define HII2S_SW_RST_N__THIRDMD_UPLINK_WORDLEN_MASK 3 31 + #define HII2S_SW_RST_N__VOICE_UPLINK_WORDLEN_SHIFT 24 32 + #define HII2S_SW_RST_N__VOICE_UPLINK_WORDLEN_MASK 3 33 + #define HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT 20 34 + #define HII2S_SW_RST_N__ST_DL_WORDLEN_MASK 3 35 + #define HII2S_SW_RST_N__THIRDMD_DLINK_WORDLEN_SHIFT 18 36 + #define HII2S_SW_RST_N__THIRDMD_DLINK_WORDLEN_MASK 3 37 + #define HII2S_SW_RST_N__VOICE_DLINK_WORDLEN_SHIFT 16 38 + #define HII2S_SW_RST_N__VOICE_DLINK_WORDLEN_MASK 3 39 + 40 + #define HII2S_SW_RST_N__SW_RST_N BIT(0) 41 + 42 + enum hi6210_bits { 43 + HII2S_BITS_16, 44 + HII2S_BITS_18, 45 + HII2S_BITS_20, 46 + HII2S_BITS_24, 47 + }; 48 + 49 + 50 + #define HII2S_IF_CLK_EN_CFG 4 51 + 52 + #define HII2S_IF_CLK_EN_CFG__THIRDMD_UPLINK_EN BIT(25) 53 + #define HII2S_IF_CLK_EN_CFG__THIRDMD_DLINK_EN BIT(24) 54 + #define HII2S_IF_CLK_EN_CFG__S3_IF_CLK_EN BIT(20) 55 + #define HII2S_IF_CLK_EN_CFG__S2_IF_CLK_EN BIT(16) 56 + #define HII2S_IF_CLK_EN_CFG__S2_OL_MIXER_EN BIT(15) 57 + #define HII2S_IF_CLK_EN_CFG__S2_OL_SRC_EN BIT(14) 58 + #define HII2S_IF_CLK_EN_CFG__S2_IR_PGA_EN BIT(13) 59 + #define HII2S_IF_CLK_EN_CFG__S2_IL_PGA_EN BIT(12) 60 + #define HII2S_IF_CLK_EN_CFG__S1_IR_PGA_EN BIT(10) 61 + #define HII2S_IF_CLK_EN_CFG__S1_IL_PGA_EN BIT(9) 62 + #define HII2S_IF_CLK_EN_CFG__S1_IF_CLK_EN BIT(8) 63 + #define HII2S_IF_CLK_EN_CFG__VOICE_DLINK_SRC_EN BIT(7) 64 + #define HII2S_IF_CLK_EN_CFG__VOICE_DLINK_EN BIT(6) 65 + #define HII2S_IF_CLK_EN_CFG__ST_DL_R_EN BIT(5) 66 + #define HII2S_IF_CLK_EN_CFG__ST_DL_L_EN BIT(4) 67 + #define HII2S_IF_CLK_EN_CFG__VOICE_UPLINK_R_EN BIT(3) 68 + #define HII2S_IF_CLK_EN_CFG__VOICE_UPLINK_L_EN BIT(2) 69 + #define HII2S_IF_CLK_EN_CFG__STEREO_UPLINK_R_EN BIT(1) 70 + #define HII2S_IF_CLK_EN_CFG__STEREO_UPLINK_L_EN BIT(0) 71 + 72 + #define HII2S_DIG_FILTER_CLK_EN_CFG 8 73 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACR_SDM_EN BIT(30) 74 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACR_HBF2I_EN BIT(28) 75 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACR_MIXER_EN BIT(25) 76 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACR_AGC_EN BIT(24) 77 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACL_SDM_EN BIT(22) 78 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACL_HBF2I_EN BIT(20) 79 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACL_MIXER_EN BIT(17) 80 + #define HII2S_DIG_FILTER_CLK_EN_CFG__DACL_AGC_EN BIT(16) 81 + 82 + #define HII2S_FS_CFG 0xc 83 + 84 + #define HII2S_FS_CFG__FS_S2_SHIFT 28 85 + #define HII2S_FS_CFG__FS_S2_MASK 7 86 + #define HII2S_FS_CFG__FS_S1_SHIFT 24 87 + #define HII2S_FS_CFG__FS_S1_MASK 7 88 + #define HII2S_FS_CFG__FS_ADCLR_SHIFT 20 89 + #define HII2S_FS_CFG__FS_ADCLR_MASK 7 90 + #define HII2S_FS_CFG__FS_DACLR_SHIFT 16 91 + #define HII2S_FS_CFG__FS_DACLR_MASK 7 92 + #define HII2S_FS_CFG__FS_ST_DL_R_SHIFT 8 93 + #define HII2S_FS_CFG__FS_ST_DL_R_MASK 7 94 + #define HII2S_FS_CFG__FS_ST_DL_L_SHIFT 4 95 + #define HII2S_FS_CFG__FS_ST_DL_L_MASK 7 96 + #define HII2S_FS_CFG__FS_VOICE_DLINK_SHIFT 0 97 + #define HII2S_FS_CFG__FS_VOICE_DLINK_MASK 7 98 + 99 + enum hi6210_i2s_rates { 100 + HII2S_FS_RATE_8KHZ = 0, 101 + HII2S_FS_RATE_16KHZ = 1, 102 + HII2S_FS_RATE_32KHZ = 2, 103 + HII2S_FS_RATE_48KHZ = 4, 104 + HII2S_FS_RATE_96KHZ = 5, 105 + HII2S_FS_RATE_192KHZ = 6, 106 + }; 107 + 108 + #define HII2S_I2S_CFG 0x10 109 + 110 + #define HII2S_I2S_CFG__S2_IF_TX_EN BIT(31) 111 + #define HII2S_I2S_CFG__S2_IF_RX_EN BIT(30) 112 + #define HII2S_I2S_CFG__S2_FRAME_MODE BIT(29) 113 + #define HII2S_I2S_CFG__S2_MST_SLV BIT(28) 114 + #define HII2S_I2S_CFG__S2_LRCK_MODE BIT(27) 115 + #define HII2S_I2S_CFG__S2_CHNNL_MODE BIT(26) 116 + #define HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT 24 117 + #define HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_MASK 3 118 + #define HII2S_I2S_CFG__S2_DIRECT_LOOP_SHIFT 22 119 + #define HII2S_I2S_CFG__S2_DIRECT_LOOP_MASK 3 120 + #define HII2S_I2S_CFG__S2_TX_CLK_SEL BIT(21) 121 + #define HII2S_I2S_CFG__S2_RX_CLK_SEL BIT(20) 122 + #define HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT BIT(19) 123 + #define HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT 16 124 + #define HII2S_I2S_CFG__S2_FUNC_MODE_MASK 7 125 + #define HII2S_I2S_CFG__S1_IF_TX_EN BIT(15) 126 + #define HII2S_I2S_CFG__S1_IF_RX_EN BIT(14) 127 + #define HII2S_I2S_CFG__S1_FRAME_MODE BIT(13) 128 + #define HII2S_I2S_CFG__S1_MST_SLV BIT(12) 129 + #define HII2S_I2S_CFG__S1_LRCK_MODE BIT(11) 130 + #define HII2S_I2S_CFG__S1_CHNNL_MODE BIT(10) 131 + #define HII2S_I2S_CFG__S1_CODEC_IO_WORDLENGTH_SHIFT 8 132 + #define HII2S_I2S_CFG__S1_CODEC_IO_WORDLENGTH_MASK 3 133 + #define HII2S_I2S_CFG__S1_DIRECT_LOOP_SHIFT 6 134 + #define HII2S_I2S_CFG__S1_DIRECT_LOOP_MASK 3 135 + #define HII2S_I2S_CFG__S1_TX_CLK_SEL BIT(5) 136 + #define HII2S_I2S_CFG__S1_RX_CLK_SEL BIT(4) 137 + #define HII2S_I2S_CFG__S1_CODEC_DATA_FORMAT BIT(3) 138 + #define HII2S_I2S_CFG__S1_FUNC_MODE_SHIFT 0 139 + #define HII2S_I2S_CFG__S1_FUNC_MODE_MASK 7 140 + 141 + enum hi6210_i2s_formats { 142 + HII2S_FORMAT_I2S, 143 + HII2S_FORMAT_PCM_STD, 144 + HII2S_FORMAT_PCM_USER, 145 + HII2S_FORMAT_LEFT_JUST, 146 + HII2S_FORMAT_RIGHT_JUST, 147 + }; 148 + 149 + #define HII2S_DIG_FILTER_MODULE_CFG 0x14 150 + 151 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_GAIN_SHIFT 28 152 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_GAIN_MASK 3 153 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN4_MUTE BIT(27) 154 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN3_MUTE BIT(26) 155 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN2_MUTE BIT(25) 156 + #define HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN1_MUTE BIT(24) 157 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_GAIN_SHIFT 20 158 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_GAIN_MASK 3 159 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN4_MUTE BIT(19) 160 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN3_MUTE BIT(18) 161 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN2_MUTE BIT(17) 162 + #define HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN1_MUTE BIT(16) 163 + #define HII2S_DIG_FILTER_MODULE_CFG__SW_DACR_SDM_DITHER BIT(9) 164 + #define HII2S_DIG_FILTER_MODULE_CFG__SW_DACL_SDM_DITHER BIT(8) 165 + #define HII2S_DIG_FILTER_MODULE_CFG__LM_CODEC_DAC2ADC_SHIFT 4 166 + #define HII2S_DIG_FILTER_MODULE_CFG__LM_CODEC_DAC2ADC_MASK 7 167 + #define HII2S_DIG_FILTER_MODULE_CFG__RM_CODEC_DAC2ADC_SHIFT 0 168 + #define HII2S_DIG_FILTER_MODULE_CFG__RM_CODEC_DAC2ADC_MASK 7 169 + 170 + enum hi6210_gains { 171 + HII2S_GAIN_100PC, 172 + HII2S_GAIN_50PC, 173 + HII2S_GAIN_25PC, 174 + }; 175 + 176 + #define HII2S_MUX_TOP_MODULE_CFG 0x18 177 + 178 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_GAIN_SHIFT 14 179 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_GAIN_MASK 3 180 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN2_MUTE BIT(13) 181 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN1_MUTE BIT(12) 182 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_GAIN_SHIFT 10 183 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_GAIN_MASK 3 184 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN2_MUTE BIT(9) 185 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN1_MUTE BIT(8) 186 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_SRC_RDY BIT(6) 187 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_SRC_MODE_SHIFT 4 188 + #define HII2S_MUX_TOP_MODULE_CFG__S2_OL_SRC_MODE_MASK 3 189 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_SRC_RDY BIT(3) 190 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_SRC_MODE_SHIFT 0 191 + #define HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_SRC_MODE_MASK 7 192 + 193 + enum hi6210_s2_src_mode { 194 + HII2S_S2_SRC_MODE_3, 195 + HII2S_S2_SRC_MODE_12, 196 + HII2S_S2_SRC_MODE_6, 197 + HII2S_S2_SRC_MODE_2, 198 + }; 199 + 200 + enum hi6210_voice_dlink_src_mode { 201 + HII2S_VOICE_DL_SRC_MODE_12 = 1, 202 + HII2S_VOICE_DL_SRC_MODE_6, 203 + HII2S_VOICE_DL_SRC_MODE_2, 204 + HII2S_VOICE_DL_SRC_MODE_3, 205 + }; 206 + 207 + #define HII2S_ADC_PGA_CFG 0x1c 208 + #define HII2S_S1_INPUT_PGA_CFG 0x20 209 + #define HII2S_S2_INPUT_PGA_CFG 0x24 210 + #define HII2S_ST_DL_PGA_CFG 0x28 211 + #define HII2S_VOICE_SIDETONE_DLINK_PGA_CFG 0x2c 212 + #define HII2S_APB_AFIFO_CFG_1 0x30 213 + #define HII2S_APB_AFIFO_CFG_2 0x34 214 + #define HII2S_ST_DL_FIFO_TH_CFG 0x38 215 + 216 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT 24 217 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_MASK 0x1f 218 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT 16 219 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_MASK 0x1f 220 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT 8 221 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_MASK 0x1f 222 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT 0 223 + #define HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_MASK 0x1f 224 + 225 + #define HII2S_STEREO_UPLINK_FIFO_TH_CFG 0x3c 226 + #define HII2S_VOICE_UPLINK_FIFO_TH_CFG 0x40 227 + #define HII2S_CODEC_IRQ_MASK 0x44 228 + #define HII2S_CODEC_IRQ 0x48 229 + #define HII2S_DACL_AGC_CFG_1 0x4c 230 + #define HII2S_DACL_AGC_CFG_2 0x50 231 + #define HII2S_DACR_AGC_CFG_1 0x54 232 + #define HII2S_DACR_AGC_CFG_2 0x58 233 + #define HII2S_DMIC_SIF_CFG 0x5c 234 + #define HII2S_MISC_CFG 0x60 235 + 236 + #define HII2S_MISC_CFG__THIRDMD_DLINK_TEST_SEL BIT(17) 237 + #define HII2S_MISC_CFG__THIRDMD_DLINK_DIN_SEL BIT(16) 238 + #define HII2S_MISC_CFG__S3_DOUT_RIGHT_SEL BIT(14) 239 + #define HII2S_MISC_CFG__S3_DOUT_LEFT_SEL BIT(13) 240 + #define HII2S_MISC_CFG__S3_DIN_TEST_SEL BIT(12) 241 + #define HII2S_MISC_CFG__VOICE_DLINK_SRC_UP_DOUT_VLD_SEL BIT(8) 242 + #define HII2S_MISC_CFG__VOICE_DLINK_TEST_SEL BIT(7) 243 + #define HII2S_MISC_CFG__VOICE_DLINK_DIN_SEL BIT(6) 244 + #define HII2S_MISC_CFG__ST_DL_TEST_SEL BIT(4) 245 + #define HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL BIT(3) 246 + #define HII2S_MISC_CFG__S2_DOUT_TEST_SEL BIT(2) 247 + #define HII2S_MISC_CFG__S1_DOUT_TEST_SEL BIT(1) 248 + #define HII2S_MISC_CFG__S2_DOUT_LEFT_SEL BIT(0) 249 + 250 + #define HII2S_S2_SRC_CFG 0x64 251 + #define HII2S_MEM_CFG 0x68 252 + #define HII2S_THIRDMD_PCM_PGA_CFG 0x6c 253 + #define HII2S_THIRD_MODEM_FIFO_TH 0x70 254 + #define HII2S_S3_ANTI_FREQ_JITTER_TX_INC_CNT 0x74 255 + #define HII2S_S3_ANTI_FREQ_JITTER_TX_DEC_CNT 0x78 256 + #define HII2S_S3_ANTI_FREQ_JITTER_RX_INC_CNT 0x7c 257 + #define HII2S_S3_ANTI_FREQ_JITTER_RX_DEC_CNT 0x80 258 + #define HII2S_ANTI_FREQ_JITTER_EN 0x84 259 + #define HII2S_CLK_SEL 0x88 260 + 261 + /* 0 = BT owns the i2s */ 262 + #define HII2S_CLK_SEL__I2S_BT_FM_SEL BIT(0) 263 + /* 0 = internal source, 1 = ext */ 264 + #define HII2S_CLK_SEL__EXT_12_288MHZ_SEL BIT(1) 265 + 266 + 267 + #define HII2S_THIRDMD_DLINK_CHANNEL 0xe8 268 + #define HII2S_THIRDMD_ULINK_CHANNEL 0xec 269 + #define HII2S_VOICE_DLINK_CHANNEL 0xf0 270 + 271 + /* shovel data in here for playback */ 272 + #define HII2S_ST_DL_CHANNEL 0xf4 273 + #define HII2S_STEREO_UPLINK_CHANNEL 0xf8 274 + #define HII2S_VOICE_UPLINK_CHANNEL 0xfc 275 + 276 + #endif/* _HI6210_I2S_H */