int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, int source, unsigned int freq, int dir) { struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona *arizona = priv->arizona; char *name; unsigned int reg; unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK; unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT; unsigned int *clk; switch (clk_id) { case ARIZONA_CLK_SYSCLK: name = "SYSCLK"; reg = ARIZONA_SYSTEM_CLOCK_1; clk = &priv->sysclk; mask |= ARIZONA_SYSCLK_FRAC; break; case ARIZONA_CLK_ASYNCCLK: name = "ASYNCCLK"; reg = ARIZONA_ASYNC_CLOCK_1; clk = &priv->asyncclk; break; case ARIZONA_CLK_OPCLK: case ARIZONA_CLK_ASYNC_OPCLK: return arizona_set_opclk(codec, clk_id, freq); default: return -EINVAL; } switch (freq) { case 5644800: case 6144000: break; case 11289600: case 12288000: val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; break; case 22579200: case 24576000: val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; break; case 45158400: case 49152000: val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; break; case 67737600: case 73728000: val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT; break; case 90316800: case 98304000: val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT; break; case 135475200: case 147456000: val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; break; default: return -EINVAL; } *clk = freq; if (freq % 6144000) val |= ARIZONA_SYSCLK_FRAC; dev_dbg(arizona->dev, "%s set to %uHz\n", name, freq); //printk("---------------------- here we are %u,%u,%s,%i,%i\n",val,freq,name,reg,mask); return regmap_update_bits(arizona->regmap, reg, mask, val); }
/** * sta32x_hw_params - program the STA32X with the given hardware parameters. * @substream: the audio stream * @params: the hardware parameters to set * @dai: the SOC DAI (ignored) * * This function programs the hardware with the values provided. * Specifically, the sample rate and the data format. */ static int sta32x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); unsigned int rate; int i, mcs = -1, ir = -1; u8 confa, confb; rate = params_rate(params); pr_debug("rate: %u\n", rate); for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) if (interpolation_ratios[i].fs == rate) { ir = interpolation_ratios[i].ir; break; } if (ir < 0) return -EINVAL; for (i = 0; mclk_ratios[ir][i].ratio; i++) if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { mcs = mclk_ratios[ir][i].mcs; break; } if (mcs < 0) return -EINVAL; confa = snd_soc_read(codec, STA32X_CONFA); confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK); confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT); confb = snd_soc_read(codec, STA32X_CONFB); confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); switch (params_width(params)) { case 24: pr_debug("24bit\n"); /* fall through */ case 32: pr_debug("24bit or 32bit\n"); switch (sta32x->format) { case SND_SOC_DAIFMT_I2S: confb |= 0x0; break; case SND_SOC_DAIFMT_LEFT_J: confb |= 0x1; break; case SND_SOC_DAIFMT_RIGHT_J: confb |= 0x2; break; } break; case 20: pr_debug("20bit\n"); switch (sta32x->format) { case SND_SOC_DAIFMT_I2S: confb |= 0x4; break; case SND_SOC_DAIFMT_LEFT_J: confb |= 0x5; break; case SND_SOC_DAIFMT_RIGHT_J: confb |= 0x6; break; } break; case 18: pr_debug("18bit\n"); switch (sta32x->format) { case SND_SOC_DAIFMT_I2S: confb |= 0x8; break; case SND_SOC_DAIFMT_LEFT_J: confb |= 0x9; break; case SND_SOC_DAIFMT_RIGHT_J: confb |= 0xa; break; } break; case 16: pr_debug("16bit\n"); switch (sta32x->format) { case SND_SOC_DAIFMT_I2S: confb |= 0x0; break; case SND_SOC_DAIFMT_LEFT_J: confb |= 0xd; break; case SND_SOC_DAIFMT_RIGHT_J: confb |= 0xe; break; } break; default: return -EINVAL; } snd_soc_write(codec, STA32X_CONFA, confa); snd_soc_write(codec, STA32X_CONFB, confb); return 0; }
static int aic31xx_setup_pll(struct snd_soc_codec *codec, struct snd_pcm_hw_params *params) { struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int bclk_score = snd_soc_params_to_frame_size(params); int mclk_p = aic31xx->sysclk / aic31xx->p_div; int bclk_n = 0; int match = -1; int i; /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); snd_soc_update_bits(codec, AIC31XX_IFACE2, AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { if (aic31xx_divs[i].rate == params_rate(params) && aic31xx_divs[i].mclk_p == mclk_p) { int s = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) % snd_soc_params_to_frame_size(params); int bn = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) / snd_soc_params_to_frame_size(params); if (s < bclk_score && bn > 0) { match = i; bclk_n = bn; bclk_score = s; } } } if (match == -1) { dev_err(codec->dev, "%s: Sample rate (%u) and format not supported\n", __func__, params_rate(params)); /* See bellow for details how fix this. */ return -EINVAL; } if (bclk_score != 0) { dev_warn(codec->dev, "Can not produce exact bitclock"); /* This is fine if using dsp format, but if using i2s there may be trouble. To fix the issue edit the aic31xx_divs table for your mclk and sample rate. Details can be found from: http://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf Section: 5.6 CLOCK Generation and PLL */ } i = match; /* PLL configuration */ snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, (aic31xx->p_div << 4) | 0x01); snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); snd_soc_write(codec, AIC31XX_PLLDMSB, aic31xx_divs[i].pll_d >> 8); snd_soc_write(codec, AIC31XX_PLLDLSB, aic31xx_divs[i].pll_d & 0xff); /* DAC dividers configuration */ snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, aic31xx_divs[i].ndac); snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, aic31xx_divs[i].mdac); snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); /* ADC dividers configuration. Write reset value 1 if not used. */ snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); /* Bit clock divider configuration. */ snd_soc_update_bits(codec, AIC31XX_BCLKN, AIC31XX_PLL_MASK, bclk_n); aic31xx->rate_div_line = i; dev_dbg(codec->dev, "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, aic31xx->p_div, aic31xx_divs[i].dosr, aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, aic31xx_divs[i].madc, bclk_n); return 0; }
static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int width) { struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); unsigned int ctrl0, ctrl1, drv; unsigned int slot[4]; unsigned int i; int ret; if (slots == 0) { /* 0 = No fixed slot width */ adau1977->slot_width = 0; adau1977->max_master_fs = 192000; return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, ADAU1977_SAI_CTRL0_SAI_I2S); } if (rx_mask == 0 || tx_mask != 0) return -EINVAL; drv = 0; for (i = 0; i < 4; i++) { slot[i] = __ffs(rx_mask); drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); rx_mask &= ~(1 << slot[i]); if (slot[i] >= slots) return -EINVAL; if (rx_mask == 0) break; } if (rx_mask != 0) return -EINVAL; switch (width) { case 16: ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; break; case 24: /* We can only generate 16 bit or 32 bit wide slots */ if (adau1977->master) return -EINVAL; ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; break; case 32: ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; break; default: return -EINVAL; } switch (slots) { case 2: ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; break; case 4: ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; break; case 8: ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; break; case 16: ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; break; default: return -EINVAL; } ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, ADAU1977_SAI_OVERTEMP_DRV_C(0) | ADAU1977_SAI_OVERTEMP_DRV_C(1) | ADAU1977_SAI_OVERTEMP_DRV_C(2) | ADAU1977_SAI_OVERTEMP_DRV_C(3), drv); if (ret) return ret; ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12, (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); if (ret) return ret; ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34, (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); if (ret) return ret; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0); if (ret) return ret; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1); if (ret) return ret; adau1977->slot_width = width; /* In master mode the maximum bitclock is 24.576 MHz */ adau1977->max_master_fs = min(192000, 24576000 / width / slots); return 0; }
static int cs4271_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); int i, ret; unsigned int ratio, val; if (cs4271->enable_soft_reset) { /* * Put the codec in soft reset and back again in case it's not * currently streaming data. This way of bringing the codec in * sync to the current clocks is not explicitly documented in * the data sheet, but it seems to work fine, and in contrast * to a read hardware reset, we don't have to sync back all * registers every time. */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !dai->capture_active) || (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !dai->playback_active)) { ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN, CS4271_MODE2_PDN); if (ret < 0) return ret; ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN, 0); if (ret < 0) return ret; } } cs4271->rate = params_rate(params); /* Configure DAC */ if (cs4271->rate < 50000) val = CS4271_MODE1_MODE_1X; else if (cs4271->rate < 100000) val = CS4271_MODE1_MODE_2X; else val = CS4271_MODE1_MODE_4X; ratio = cs4271->mclk / cs4271->rate; for (i = 0; i < CS4171_NR_RATIOS; i++) if ((cs4271_clk_tab[i].master == cs4271->master) && (cs4271_clk_tab[i].speed_mode == val) && (cs4271_clk_tab[i].ratio == ratio)) break; if (i == CS4171_NR_RATIOS) { dev_err(codec->dev, "Invalid sample rate\n"); return -EINVAL; } val |= cs4271_clk_tab[i].ratio_mask; ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1, CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); if (ret < 0) return ret; return cs4271_set_deemph(codec); }
static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); struct list_head xfer_list; struct wm0010_boot_xfer *xfer; int ret; struct completion done; const struct firmware *fw; const struct dfw_binrec *rec; const struct dfw_inforec *inforec; u64 *img; u8 *out, dsp; u32 len, offset; INIT_LIST_HEAD(&xfer_list); ret = request_firmware(&fw, name, codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request application(%s): %d\n", name, ret); return ret; } rec = (const struct dfw_binrec *)fw->data; inforec = (const struct dfw_inforec *)rec->data; offset = 0; dsp = inforec->dsp_target; wm0010->boot_failed = false; if (WARN_ON(!list_empty(&xfer_list))) return -EINVAL; init_completion(&done); /* First record should be INFO */ if (rec->command != DFW_CMD_INFO) { dev_err(codec->dev, "First record not INFO\r\n"); ret = -EINVAL; goto abort; } if (inforec->info_version != INFO_VERSION) { dev_err(codec->dev, "Unsupported version (%02d) of INFO record\r\n", inforec->info_version); ret = -EINVAL; goto abort; } dev_dbg(codec->dev, "Version v%02d INFO record found\r\n", inforec->info_version); /* Check it's a DSP file */ if (dsp != DEVICE_ID_WM0010) { dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); ret = -EINVAL; goto abort; } /* Skip the info record as we don't need to send it */ offset += ((rec->length) + 8); rec = (void *)&rec->data[rec->length]; while (offset < fw->size) { dev_dbg(codec->dev, "Packet: command %d, data length = 0x%x\r\n", rec->command, rec->length); len = rec->length + 8; xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); if (!xfer) { ret = -ENOMEM; goto abort; } xfer->codec = codec; list_add_tail(&xfer->list, &xfer_list); out = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!out) { ret = -ENOMEM; goto abort1; } xfer->t.rx_buf = out; img = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort1; } xfer->t.tx_buf = img; byte_swap_64((u64 *)&rec->command, img, len); spi_message_init(&xfer->m); xfer->m.complete = wm0010_boot_xfer_complete; xfer->m.context = xfer; xfer->t.len = len; xfer->t.bits_per_word = 8; if (!wm0010->pll_running) { xfer->t.speed_hz = wm0010->sysclk / 6; } else { xfer->t.speed_hz = wm0010->max_spi_freq; if (wm0010->board_max_spi_speed && (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) xfer->t.speed_hz = wm0010->board_max_spi_speed; } /* Store max usable spi frequency for later use */ wm0010->max_spi_freq = xfer->t.speed_hz; spi_message_add_tail(&xfer->t, &xfer->m); offset += ((rec->length) + 8); rec = (void *)&rec->data[rec->length]; if (offset >= fw->size) { dev_dbg(codec->dev, "All transfers scheduled\n"); xfer->done = &done; } ret = spi_async(spi, &xfer->m); if (ret != 0) { dev_err(codec->dev, "Write failed: %d\n", ret); goto abort1; } if (wm0010->boot_failed) { dev_dbg(codec->dev, "Boot fail!\n"); ret = -EINVAL; goto abort1; } } wait_for_completion(&done); ret = 0; abort1: while (!list_empty(&xfer_list)) { xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, list); kfree(xfer->t.rx_buf); kfree(xfer->t.tx_buf); list_del(&xfer->list); kfree(xfer); } abort: release_firmware(fw); return ret; }
static int wm0010_boot(struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); unsigned long flags; int ret; const struct firmware *fw; struct spi_message m; struct spi_transfer t; struct dfw_pllrec pll_rec; u32 *p, len; u64 *img_swap; u8 *out; int i; spin_lock_irqsave(&wm0010->irq_lock, flags); if (wm0010->state != WM0010_POWER_OFF) dev_warn(wm0010->dev, "DSP already powered up!\n"); spin_unlock_irqrestore(&wm0010->irq_lock, flags); if (wm0010->sysclk > 26000000) { dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); ret = -ECANCELED; goto err; } mutex_lock(&wm0010->lock); wm0010->pll_running = false; dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); if (ret != 0) { dev_err(&spi->dev, "Failed to enable core supplies: %d\n", ret); mutex_unlock(&wm0010->lock); goto err; } ret = regulator_enable(wm0010->dbvdd); if (ret != 0) { dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); goto err_core; } /* Release reset */ gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_OUT_OF_RESET; spin_unlock_irqrestore(&wm0010->irq_lock, flags); /* First the bootloader */ ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request stage2 loader: %d\n", ret); goto abort; } if (!wait_for_completion_timeout(&wm0010->boot_completion, msecs_to_jiffies(20))) dev_err(codec->dev, "Failed to get interrupt from DSP\n"); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_BOOTROM; spin_unlock_irqrestore(&wm0010->irq_lock, flags); ret = wm0010_stage2_load(codec); if (ret) goto abort; if (!wait_for_completion_timeout(&wm0010->boot_completion, msecs_to_jiffies(20))) dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_STAGE2; spin_unlock_irqrestore(&wm0010->irq_lock, flags); /* Only initialise PLL if max_spi_freq initialised */ if (wm0010->max_spi_freq) { /* Initialise a PLL record */ memset(&pll_rec, 0, sizeof(pll_rec)); pll_rec.command = DFW_CMD_PLL; pll_rec.length = (sizeof(pll_rec) - 8); /* On wm0010 only the CLKCTRL1 value is used */ pll_rec.clkctrl1 = wm0010->pll_clkctrl1; ret = -ENOMEM; len = pll_rec.length + 8; out = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!out) { dev_err(codec->dev, "Failed to allocate RX buffer\n"); goto abort; } img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA); if (!img_swap) goto abort; /* We need to re-order for 0010 */ byte_swap_64((u64 *)&pll_rec, img_swap, len); spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; t.tx_buf = img_swap; t.len = len; t.bits_per_word = 8; t.speed_hz = wm0010->sysclk / 6; spi_message_add_tail(&t, &m); ret = spi_sync(spi, &m); if (ret != 0) { dev_err(codec->dev, "First PLL write failed: %d\n", ret); goto abort; } /* Use a second send of the message to get the return status */ ret = spi_sync(spi, &m); if (ret != 0) { dev_err(codec->dev, "Second PLL write failed: %d\n", ret); goto abort; } p = (u32 *)out; /* Look for PLL active code from the DSP */ for (i = 0; i < len / 4; i++) { if (*p == 0x0e00ed0f) { dev_dbg(codec->dev, "PLL packet received\n"); wm0010->pll_running = true; break; } p++; } kfree(img_swap); kfree(out); } else dev_dbg(codec->dev, "Not enabling DSP PLL."); ret = wm0010_firmware_load("wm0010.dfw", codec); if (ret != 0) goto abort; spin_lock_irqsave(&wm0010->irq_lock, flags); wm0010->state = WM0010_FIRMWARE; spin_unlock_irqrestore(&wm0010->irq_lock, flags); mutex_unlock(&wm0010->lock); return 0; abort: /* Put the chip back into reset */ wm0010_halt(codec); mutex_unlock(&wm0010->lock); return ret; err_core: mutex_unlock(&wm0010->lock); regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); err: return ret; }
static int wm8955_configure_clocking(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); int i, ret, val; int clocking = 0; int srate = 0; int sr = -1; struct pll_factors pll; /* If we're not running a sample rate currently just pick one */ if (wm8955->fs == 0) wm8955->fs = 8000; /* Can we generate an exact output? */ for (i = 0; i < ARRAY_SIZE(clock_cfgs); i++) { if (wm8955->fs != clock_cfgs[i].fs) continue; sr = i; if (wm8955->mclk_rate == clock_cfgs[i].mclk) break; } /* We should never get here with an unsupported sample rate */ if (sr == -1) { dev_err(codec->dev, "Sample rate %dHz unsupported\n", wm8955->fs); WARN_ON(sr == -1); return -EINVAL; } if (i == ARRAY_SIZE(clock_cfgs)) { /* If we can't generate the right clock from MCLK then * we should configure the PLL to supply us with an * appropriate clock. */ clocking |= WM8955_MCLKSEL; /* Use the last divider configuration we saw for the * sample rate. */ ret = wm8995_pll_factors(codec->dev, wm8955->mclk_rate, clock_cfgs[sr].mclk, &pll); if (ret != 0) { dev_err(codec->dev, "Unable to generate %dHz from %dHz MCLK\n", wm8955->fs, wm8955->mclk_rate); return -EINVAL; } snd_soc_update_bits(codec, WM8955_PLL_CONTROL_1, WM8955_N_MASK | WM8955_K_21_18_MASK, (pll.n << WM8955_N_SHIFT) | pll.k >> 18); snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, WM8955_K_17_9_MASK, (pll.k >> 9) & WM8955_K_17_9_MASK); snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, WM8955_K_8_0_MASK, pll.k & WM8955_K_8_0_MASK); if (pll.k) snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, WM8955_KEN, WM8955_KEN); else snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, WM8955_KEN, 0); if (pll.outdiv) val = WM8955_PLL_RB | WM8955_PLLOUTDIV2; else val = WM8955_PLL_RB; /* Now start the PLL running */ snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, WM8955_PLL_RB | WM8955_PLLOUTDIV2, val); snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, WM8955_PLLEN, WM8955_PLLEN); }
static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { struct snd_soc_codec *codec = dai->codec; struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); struct rl6231_pll_code pll_code; int ret; if (source == rt5616->pll_src && freq_in == rt5616->pll_in && freq_out == rt5616->pll_out) return 0; if (!freq_in || !freq_out) { dev_dbg(codec->dev, "PLL disabled\n"); rt5616->pll_in = 0; rt5616->pll_out = 0; snd_soc_update_bits(codec, RT5616_GLB_CLK, RT5616_SCLK_SRC_MASK, RT5616_SCLK_SRC_MCLK); return 0; } switch (source) { case RT5616_PLL1_S_MCLK: snd_soc_update_bits(codec, RT5616_GLB_CLK, RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_MCLK); break; case RT5616_PLL1_S_BCLK1: case RT5616_PLL1_S_BCLK2: snd_soc_update_bits(codec, RT5616_GLB_CLK, RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_BCLK1); break; default: dev_err(codec->dev, "Unknown PLL source %d\n", source); return -EINVAL; } ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); if (ret < 0) { dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); return ret; } dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code, pll_code.k_code); snd_soc_write(codec, RT5616_PLL_CTRL1, pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code); snd_soc_write(codec, RT5616_PLL_CTRL2, (pll_code.m_bp ? 0 : pll_code.m_code) << RT5616_PLL_M_SFT | pll_code.m_bp << RT5616_PLL_M_BP_SFT); rt5616->pll_in = freq_in; rt5616->pll_out = freq_out; rt5616->pll_src = source; return 0; }
static int max98925_probe(struct snd_soc_codec *codec) { struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); struct max98925_cdata *cdata; int ret = 0; int reg = 0; dev_info(codec->dev, "MONO - built on %s at %s\n", __DATE__, __TIME__); dev_info(codec->dev, "build number %s\n", MAX98925_REVISION); max98925->codec = codec; codec->control_data = max98925->regmap; ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } max98925->sysclk = 12288000; max98925->volume = 0x07; cdata = &max98925->dai[0]; cdata->rate = (unsigned)-1; cdata->fmt = (unsigned)-1; reg = 0; ret = regmap_read(max98925->regmap, MAX98925_R0FF_VERSION, ®); if ((ret < 0) || ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1) && (reg != MAX98925_VERSION2) && (reg != MAX98925_VERSION3))) { dev_err(codec->dev, "device initialization error (%d 0x%02X)\n", ret, reg); goto err_access; } dev_info(codec->dev, "device version 0x%02X\n", reg); regmap_write(max98925->regmap, MAX98925_R038_GLOBAL_ENABLE, 0x00); /* It's not the default but we need to set DAI_DLY */ regmap_write(max98925->regmap, MAX98925_R020_FORMAT, MAX98925_DAI_DLY_MASK); regmap_write(max98925->regmap, MAX98925_R021_TDM_SLOT_SELECT, 0xC8); regmap_write(max98925->regmap, MAX98925_R027_DOUT_HIZ_CFG1, 0xFF); regmap_write(max98925->regmap, MAX98925_R028_DOUT_HIZ_CFG2, 0xFF); regmap_write(max98925->regmap, MAX98925_R029_DOUT_HIZ_CFG3, 0xFF); regmap_write(max98925->regmap, MAX98925_R02A_DOUT_HIZ_CFG4, 0xF0); regmap_write(max98925->regmap, MAX98925_R02C_FILTERS, 0xD8); regmap_write(max98925->regmap, MAX98925_R034_ALC_CONFIGURATION, 0x12); /*****************************************************************/ /* Set boost output to minimum until DSM is implemented */ regmap_write(max98925->regmap, MAX98925_R037_CONFIGURATION, 0xF0); /*****************************************************************/ /* Disable ALC muting */ regmap_write(max98925->regmap, MAX98925_R03A_BOOST_LIMITER, 0xF8); regmap_update_bits(max98925->regmap, MAX98925_R02D_GAIN, MAX98925_DAC_IN_SEL_MASK, MAX98925_DAC_IN_SEL_DIV2_SUMMED_DAI); max98925_handle_pdata(codec); max98925_add_widgets(codec); err_access: msg_maxim("%s: exit %d\n", __func__, ret); return ret; }
static void wm8400_codec_reset(struct snd_soc_codec *codec) { struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); wm8400_reset_codec_reg_cache(wm8400->wm8400); }
static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); struct max98925_cdata *cdata; unsigned int invert = 0; msg_maxim("%s: fmt 0x%08X\n", __func__, fmt); cdata = &max98925->dai[0]; cdata->fmt = fmt; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: max98925_set_slave(max98925); break; case SND_SOC_DAIFMT_CBM_CFM: max98925_set_master(max98925); break; case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBM_CFS: default: dev_err(codec->dev, "DAI clock mode unsupported"); return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: msg_maxim("%s: set SND_SOC_DAIFMT_I2S\n", __func__); break; case SND_SOC_DAIFMT_LEFT_J: msg_maxim("%s: set SND_SOC_DAIFMT_LEFT_J\n", __func__); break; case SND_SOC_DAIFMT_DSP_A: msg_maxim("%s: set SND_SOC_DAIFMT_DSP_A\n", __func__); default: dev_err(codec->dev, "DAI format unsupported, fmt:0x%x", fmt); return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_NB_IF: invert = MAX98925_DAI_WCI_MASK; break; case SND_SOC_DAIFMT_IB_NF: invert = MAX98925_DAI_BCI_MASK; break; case SND_SOC_DAIFMT_IB_IF: invert = MAX98925_DAI_BCI_MASK | MAX98925_DAI_WCI_MASK; break; default: dev_err(codec->dev, "DAI invert mode unsupported"); return -EINVAL; } regmap_update_bits(max98925->regmap, MAX98925_R020_FORMAT, MAX98925_DAI_BCI_MASK | MAX98925_DAI_BCI_MASK, invert); return 0; }
void tabla_codec_enable_micbias2(struct snd_soc_codec *codec) { #if 1 pr_info("%s\n", __func__ ); snd_soc_write(codec, TABLA_A_MICB_CFILT_2_CTL, 0x80); snd_soc_write(codec, TABLA_A_MICB_2_CTL, 0xb6); snd_soc_write(codec, TABLA_A_LDO_H_MODE_1, 0xCD); snd_soc_write(codec, TABLA_A_MICB_CFILT_2_VAL, 0x68); #else #if 0 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x0F, 0x0D); snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0); snd_soc_write(codec, TABLA_A_MICB_CFILT_2_VAL, 0x68); snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x60, 0x20); snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x0E, 0x0A); snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_2_CTL, 0x80, 0x80); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); #else struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec); // short bias_value; tabla->mbhc_polling_active = true; snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01); snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0); snd_soc_write(codec, TABLA_A_MICB_CFILT_2_CTL, 0x00); snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x1F, 0x16); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84); snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x80); snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x1F, 0x1C); snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40); snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x00); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x6); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); snd_soc_update_bits(codec, TABLA_A_MICB_2_MBHC, 0x10, 0x10); snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x01); //tabla_codec_calibrate_hs_polling(codec); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL, 0xFF); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL, 0x00); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xEE); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0xFC); snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xCE); snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL, 3); snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL, 9); snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL, 30); snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 120); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL, 0x78, 0x58); snd_soc_write(codec, TABLA_A_CDC_MBHC_B2_CTL, 11); //bias_value = tabla_codec_measure_micbias_voltage(codec, 0); snd_soc_write(codec, TABLA_A_MICB_CFILT_2_CTL, 0x40); snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL); tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL); tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE); //tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF); snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x0); #endif #endif }
static int arizona_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; unsigned int val; int base = dai->driver->base; const int *rates; int i, ret, bclk_target; int bclk, lrclk, wl, frame, sr_val; //printk("Arizona: hw params start\n"); if (params_rate(params) % 8000) rates = &arizona_44k1_bclk_rates[0]; else rates = &arizona_48k_bclk_rates[0]; /* Force BCLK to stereo for I2S */ bclk_target = snd_soc_params_to_bclk(params); val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); if (val & ARIZONA_AIF1_FMT_MASK && params_channels(params) == 1) { arizona_aif_err(dai, "Forcing stereo mode\n"); bclk_target *= 2; } for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { if (rates[i] >= bclk_target && rates[i] % params_rate(params) == 0) { bclk = i; break; } } if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) if (arizona_sr_vals[i] == params_rate(params)) break; if (i == ARRAY_SIZE(arizona_sr_vals)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } sr_val = i; lrclk = rates[bclk] / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); wl = snd_pcm_format_width(params_format(params)); frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; /* * We will need to be more flexible than this in future, * currently we use a single sample rate for SYSCLK. */ switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: /* SR2 is forced to 8kHz */ if (params_rate(params) != 8000) { snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, ARIZONA_SAMPLE_RATE_1_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 0); } else { snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_2, ARIZONA_SAMPLE_RATE_2_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 1); } break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 8); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, ARIZONA_AIF1TX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, ARIZONA_AIF1RX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1RX_WL_MASK | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); // HLL will add this in //ret=wm2000_check_poll(); //printk("Arizona: hw params start 1\n"); return 0; //ret; }
static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); u8 hppllctl, lppllctl; hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL); lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); switch (clk_id) { case TWL6040_SYSCLK_SEL_LPPLL: switch (freq) { case 32768: /* headset dac and driver must be in low-power mode */ headset_power_mode(codec, 0); /* clk32k input requires low-power pll */ lppllctl |= TWL6040_LPLLENA; twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); mdelay(5); lppllctl &= ~TWL6040_HPLLSEL; twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); hppllctl &= ~TWL6040_HPLLENA; twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl); break; default: dev_err(codec->dev, "unknown mclk freq %d\n", freq); return -EINVAL; } /* lppll divider */ switch (priv->sysclk) { case 17640000: lppllctl |= TWL6040_LPLLFIN; break; case 19200000: lppllctl &= ~TWL6040_LPLLFIN; break; default: /* sysclk not yet configured */ lppllctl &= ~TWL6040_LPLLFIN; priv->sysclk = 19200000; break; } twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); priv->pll = TWL6040_LPPLL_ID; priv->sysclk_constraints = &lp_constraints; break; case TWL6040_SYSCLK_SEL_HPPLL: hppllctl &= ~TWL6040_MCLK_MSK; switch (freq) { case 12000000: /* mclk input, pll enabled */ hppllctl |= TWL6040_MCLK_12000KHZ | TWL6040_HPLLSQRBP | TWL6040_HPLLENA; break; case 19200000: /* mclk input, pll disabled */ hppllctl |= TWL6040_MCLK_19200KHZ | TWL6040_HPLLSQRENA | TWL6040_HPLLBP; break; case 26000000: /* mclk input, pll enabled */ hppllctl |= TWL6040_MCLK_26000KHZ | TWL6040_HPLLSQRBP | TWL6040_HPLLENA; break; case 38400000: /* clk slicer, pll disabled */ hppllctl |= TWL6040_MCLK_38400KHZ | TWL6040_HPLLSQRENA | TWL6040_HPLLBP; break; default: dev_err(codec->dev, "unknown mclk freq %d\n", freq); return -EINVAL; } /* headset dac and driver must be in high-performance mode */ headset_power_mode(codec, 1); twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl); udelay(500); lppllctl |= TWL6040_HPLLSEL; twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); lppllctl &= ~TWL6040_LPLLENA; twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); /* high-performance pll can provide only 19.2 MHz */ priv->pll = TWL6040_HPPLL_ID; priv->sysclk = 19200000; priv->sysclk_constraints = &hp_constraints; break; default: dev_err(codec->dev, "unknown clk_id %d\n", clk_id); return -EINVAL; } return 0; }
static int rt5616_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* * SND_SOC_BIAS_PREPARE is called while preparing for a * transition to ON or away from ON. If current bias_level * is SND_SOC_BIAS_ON, then it is preparing for a transition * away from ON. Disable the clock in that case, otherwise * enable it. */ if (IS_ERR(rt5616->mclk)) break; if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { clk_disable_unprepare(rt5616->mclk); } else { ret = clk_prepare_enable(rt5616->mclk); if (ret) return ret; } break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2); mdelay(10); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_FV1 | RT5616_PWR_FV2, RT5616_PWR_FV1 | RT5616_PWR_FV2); snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, RT5616_D_GATE_EN); } break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, 0); snd_soc_write(codec, RT5616_PWR_DIG1, 0x0000); snd_soc_write(codec, RT5616_PWR_DIG2, 0x0000); snd_soc_write(codec, RT5616_PWR_VOL, 0x0000); snd_soc_write(codec, RT5616_PWR_MIXER, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG1, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG2, 0x0000); break; default: break; } return 0; }
static void wm0010_boot_xfer_complete(void *data) { struct wm0010_boot_xfer *xfer = data; struct snd_soc_codec *codec = xfer->codec; struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); u32 *out32 = xfer->t.rx_buf; int i; if (xfer->m.status != 0) { dev_err(codec->dev, "SPI transfer failed: %d\n", xfer->m.status); wm0010_mark_boot_failure(wm0010); if (xfer->done) complete(xfer->done); return; } for (i = 0; i < xfer->t.len / 4; i++) { dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); switch (be32_to_cpu(out32[i])) { case 0xe0e0e0e0: dev_err(codec->dev, "%d: ROM error reported in stage 2\n", i); wm0010_mark_boot_failure(wm0010); break; case 0x55555555: if (wm0010->state < WM0010_STAGE2) break; dev_err(codec->dev, "%d: ROM bootloader running in stage 2\n", i); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0000: dev_dbg(codec->dev, "Stage2 loader running\n"); break; case 0x0fed0007: dev_dbg(codec->dev, "CODE_HDR packet received\n"); break; case 0x0fed0008: dev_dbg(codec->dev, "CODE_DATA packet received\n"); break; case 0x0fed0009: dev_dbg(codec->dev, "Download complete\n"); break; case 0x0fed000c: dev_dbg(codec->dev, "Application start\n"); break; case 0x0fed000e: dev_dbg(codec->dev, "PLL packet received\n"); wm0010->pll_running = true; break; case 0x0fed0025: dev_err(codec->dev, "Device reports image too long\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed002c: dev_err(codec->dev, "Device reports bad SPI packet\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0031: dev_err(codec->dev, "Device reports SPI read overflow\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0032: dev_err(codec->dev, "Device reports SPI underclock\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0033: dev_err(codec->dev, "Device reports bad header packet\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0034: dev_err(codec->dev, "Device reports invalid packet type\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0035: dev_err(codec->dev, "Device reports data before header error\n"); wm0010_mark_boot_failure(wm0010); break; case 0x0fed0038: dev_err(codec->dev, "Device reports invalid PLL packet\n"); break; case 0x0fed003a: dev_err(codec->dev, "Device reports packet alignment error\n"); wm0010_mark_boot_failure(wm0010); break; default: dev_err(codec->dev, "Unrecognised return 0x%x\n", be32_to_cpu(out32[i])); wm0010_mark_boot_failure(wm0010); break; } if (wm0010->boot_failed) break; } if (xfer->done) complete(xfer->done); }
static int max9867_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); unsigned int ni_h, ni_l; int value; value = get_ni_value(max9867->sysclk, params_rate(params)); if (value < 0) return value; ni_h = (0xFF00 & value) >> 8; ni_l = 0x00FF & value; /* set up the ni value */ regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, MAX9867_NI_HIGH_MASK, ni_h); regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, MAX9867_NI_LOW_MASK, ni_l); if (!max9867->master) { /* * digital pll locks on to any externally supplied LRCLK signal * and also enable rapid lock mode. */ regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK); regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, MAX9867_PLL, MAX9867_PLL); } else { unsigned long int bclk_rate, pclk_bclk_ratio; int bclk_value; bclk_rate = params_rate(params) * 2 * params_width(params); pclk_bclk_ratio = max9867->pclk/bclk_rate; switch (params_width(params)) { case 8: case 16: switch (pclk_bclk_ratio) { case 2: bclk_value = MAX9867_IFC1B_PCLK_2; break; case 4: bclk_value = MAX9867_IFC1B_PCLK_4; break; case 8: bclk_value = MAX9867_IFC1B_PCLK_8; break; case 16: bclk_value = MAX9867_IFC1B_PCLK_16; break; default: dev_err(codec->dev, "unsupported sampling rate\n"); return -EINVAL; } break; case 24: bclk_value = MAX9867_IFC1B_24BIT; break; case 32: bclk_value = MAX9867_IFC1B_32BIT; break; default: dev_err(codec->dev, "unsupported sampling rate\n"); return -EINVAL; } regmap_update_bits(max9867->regmap, MAX9867_IFC1B, MAX9867_IFC1B_BCLK_MASK, bclk_value); } return 0; }
static int wm0010_stage2_load(struct snd_soc_codec *codec) { struct spi_device *spi = to_spi_device(codec->dev); struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); const struct firmware *fw; struct spi_message m; struct spi_transfer t; u32 *img; u8 *out; int i; int ret = 0; ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request stage2 loader: %d\n", ret); return ret; } dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort2; } out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); if (!out) { ret = -ENOMEM; goto abort1; } memcpy(img, &fw->data[0], fw->size); spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; t.tx_buf = img; t.len = fw->size; t.bits_per_word = 8; t.speed_hz = wm0010->sysclk / 10; spi_message_add_tail(&t, &m); dev_dbg(codec->dev, "Starting initial download at %dHz\n", t.speed_hz); ret = spi_sync(spi, &m); if (ret != 0) { dev_err(codec->dev, "Initial download failed: %d\n", ret); goto abort; } /* Look for errors from the boot ROM */ for (i = 0; i < fw->size; i++) { if (out[i] != 0x55) { dev_err(codec->dev, "Boot ROM error: %x in %d\n", out[i], i); wm0010_mark_boot_failure(wm0010); ret = -EBUSY; goto abort; } } abort: kfree(out); abort1: kfree(img); abort2: release_firmware(fw); return ret; }
/* pll_rate = pllin_rate * R * J.D / P * 1 <= R <= 16 * 1 <= J <= 63 * 0 <= D <= 9999 * 1 <= P <= 15 * 64 MHz <= pll_rate <= 100 MHz * if D == 0 * 1 MHz <= pllin_rate / P <= 20 MHz * else if D > 0 * 6.667 MHz <= pllin_rate / P <= 20 MHz * 4 <= J <= 11 * R = 1 */ static int pcm512x_find_pll_coeff(struct snd_soc_dai *dai, unsigned long pllin_rate, unsigned long pll_rate) { struct device *dev = dai->dev; struct snd_soc_codec *codec = dai->codec; struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); unsigned long common; int R, J, D, P; unsigned long K; /* 10000 * J.D */ unsigned long num; unsigned long den; common = gcd(pll_rate, pllin_rate); dev_dbg(dev, "pll %lu pllin %lu common %lu\n", pll_rate, pllin_rate, common); num = pll_rate / common; den = pllin_rate / common; /* pllin_rate / P (or here, den) cannot be greater than 20 MHz */ if (pllin_rate / den > 20000000 && num < 8) { num *= 20000000 / (pllin_rate / den); den *= 20000000 / (pllin_rate / den); } dev_dbg(dev, "num / den = %lu / %lu\n", num, den); P = den; if (den <= 15 && num <= 16 * 63 && 1000000 <= pllin_rate / P && pllin_rate / P <= 20000000) { /* Try the case with D = 0 */ D = 0; /* factor 'num' into J and R, such that R <= 16 and J <= 63 */ for (R = 16; R; R--) { if (num % R) continue; J = num / R; if (J == 0 || J > 63) continue; dev_dbg(dev, "R * J / P = %d * %d / %d\n", R, J, P); pcm512x->real_pll = pll_rate; goto done; } /* no luck */ } R = 1; if (num > 0xffffffffUL / 10000) goto fallback; /* Try to find an exact pll_rate using the D > 0 case */ common = gcd(10000 * num, den); num = 10000 * num / common; den /= common; dev_dbg(dev, "num %lu den %lu common %lu\n", num, den, common); for (P = den; P <= 15; P++) { if (pllin_rate / P < 6667000 || 200000000 < pllin_rate / P) continue; if (num * P % den) continue; K = num * P / den; /* J == 12 is ok if D == 0 */ if (K < 40000 || K > 120000) continue; J = K / 10000; D = K % 10000; dev_dbg(dev, "J.D / P = %d.%04d / %d\n", J, D, P); pcm512x->real_pll = pll_rate; goto done; } /* Fall back to an approximate pll_rate */ fallback: /* find smallest possible P */ P = DIV_ROUND_UP(pllin_rate, 20000000); if (!P) P = 1; else if (P > 15) { dev_err(dev, "Need a slower clock as pll-input\n"); return -EINVAL; } if (pllin_rate / P < 6667000) { dev_err(dev, "Need a faster clock as pll-input\n"); return -EINVAL; } K = DIV_ROUND_CLOSEST_ULL(10000ULL * pll_rate * P, pllin_rate); if (K < 40000) K = 40000; /* J == 12 is ok if D == 0 */ if (K > 120000) K = 120000; J = K / 10000; D = K % 10000; dev_dbg(dev, "J.D / P ~ %d.%04d / %d\n", J, D, P); pcm512x->real_pll = DIV_ROUND_DOWN_ULL((u64)K * pllin_rate, 10000 * P); done: pcm512x->pll_r = R; pcm512x->pll_j = J; pcm512x->pll_d = D; pcm512x->pll_p = P; return 0; }
static int adau1977_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); unsigned int rate = params_rate(params); unsigned int slot_width; unsigned int ctrl0, ctrl0_mask; unsigned int ctrl1; int mcs, fs; int ret; fs = adau1977_lookup_fs(rate); if (fs < 0) return fs; if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { mcs = adau1977_lookup_mcs(adau1977, rate, fs); if (mcs < 0) return mcs; } else { mcs = 0; } ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; ctrl0 = fs; if (adau1977->right_j) { switch (params_width(params)) { case 16: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; break; case 24: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; break; default: return -EINVAL; } ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; } if (adau1977->master) { switch (params_width(params)) { case 16: ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; slot_width = 16; break; case 24: case 32: ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; slot_width = 32; break; default: return -EINVAL; } /* In TDM mode there is a fixed slot width */ if (adau1977->slot_width) slot_width = adau1977->slot_width; if (slot_width == 16) ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; else ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | ADAU1977_SAI_CTRL1_BCLKRATE_MASK, ctrl1); if (ret < 0) return ret; } ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, ctrl0_mask, ctrl0); if (ret < 0) return ret; return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, ADAU1977_PLL_MCS_MASK, mcs); }
static int pcm512x_set_dividers(struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) { struct device *dev = dai->dev; struct snd_soc_codec *codec = dai->codec; struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); unsigned long pllin_rate = 0; unsigned long pll_rate; unsigned long sck_rate; unsigned long mck_rate; unsigned long bclk_rate; unsigned long sample_rate; unsigned long osr_rate; unsigned long dacsrc_rate; int bclk_div; int lrclk_div; int dsp_div; int dac_div; unsigned long dac_rate; int ncp_div; int osr_div; int ret; int idac; int fssp; int gpio; lrclk_div = snd_soc_params_to_frame_size(params); if (lrclk_div == 0) { dev_err(dev, "No LRCLK?\n"); return -EINVAL; } if (!pcm512x->pll_out) { sck_rate = clk_get_rate(pcm512x->sclk); bclk_div = params->rate_den * 64 / lrclk_div; bclk_rate = DIV_ROUND_CLOSEST(sck_rate, bclk_div); mck_rate = sck_rate; } else { ret = snd_soc_params_to_bclk(params); if (ret < 0) { dev_err(dev, "Failed to find suitable BCLK: %d\n", ret); return ret; } if (ret == 0) { dev_err(dev, "No BCLK?\n"); return -EINVAL; } bclk_rate = ret; pllin_rate = clk_get_rate(pcm512x->sclk); sck_rate = pcm512x_find_sck(dai, bclk_rate); if (!sck_rate) return -EINVAL; pll_rate = 4 * sck_rate; ret = pcm512x_find_pll_coeff(dai, pllin_rate, pll_rate); if (ret != 0) return ret; ret = regmap_write(pcm512x->regmap, PCM512x_PLL_COEFF_0, pcm512x->pll_p - 1); if (ret != 0) { dev_err(dev, "Failed to write PLL P: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_PLL_COEFF_1, pcm512x->pll_j); if (ret != 0) { dev_err(dev, "Failed to write PLL J: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_PLL_COEFF_2, pcm512x->pll_d >> 8); if (ret != 0) { dev_err(dev, "Failed to write PLL D msb: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_PLL_COEFF_3, pcm512x->pll_d & 0xff); if (ret != 0) { dev_err(dev, "Failed to write PLL D lsb: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_PLL_COEFF_4, pcm512x->pll_r - 1); if (ret != 0) { dev_err(dev, "Failed to write PLL R: %d\n", ret); return ret; } mck_rate = pcm512x->real_pll; bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate); } if (bclk_div > 128) { dev_err(dev, "Failed to find BCLK divider\n"); return -EINVAL; } /* the actual rate */ sample_rate = sck_rate / bclk_div / lrclk_div; osr_rate = 16 * sample_rate; /* run DSP no faster than 50 MHz */ dsp_div = mck_rate > 50000000 ? 2 : 1; dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate); if (dac_rate) { /* the desired clock rate is "compatible" with the pll input * clock, so use that clock as dac input instead of the pll * output clock since the pll will introduce jitter and thus * noise. */ dev_dbg(dev, "using pll input as dac input\n"); ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF, PCM512x_SDAC, PCM512x_SDAC_GPIO); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio as dacref: %d\n", ret); return ret; } gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN, PCM512x_GREF, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio %d as dacin: %d\n", pcm512x->pll_in, ret); return ret; } dacsrc_rate = pllin_rate; } else { /* run DAC no faster than 6144000 Hz */ unsigned long dac_mul = 6144000 / osr_rate; unsigned long sck_mul = sck_rate / osr_rate; for (; dac_mul; dac_mul--) { if (!(sck_mul % dac_mul)) break; } if (!dac_mul) { dev_err(dev, "Failed to find DAC rate\n"); return -EINVAL; } dac_rate = dac_mul * osr_rate; dev_dbg(dev, "dac_rate %lu sample_rate %lu\n", dac_rate, sample_rate); ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF, PCM512x_SDAC, PCM512x_SDAC_SCK); if (ret != 0) { dev_err(codec->dev, "Failed to set sck as dacref: %d\n", ret); return ret; } dacsrc_rate = sck_rate; } dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate); if (dac_div > 128) { dev_err(dev, "Failed to find DAC divider\n"); return -EINVAL; } ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000); if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) { /* run NCP no faster than 2048000 Hz, but why? */ ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000); if (ncp_div > 128) { dev_err(dev, "Failed to find NCP divider\n"); return -EINVAL; } } osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate); if (osr_div > 128) { dev_err(dev, "Failed to find OSR divider\n"); return -EINVAL; } idac = mck_rate / (dsp_div * sample_rate); ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1); if (ret != 0) { dev_err(dev, "Failed to write DSP divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1); if (ret != 0) { dev_err(dev, "Failed to write DAC divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1); if (ret != 0) { dev_err(dev, "Failed to write NCP divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1); if (ret != 0) { dev_err(dev, "Failed to write OSR divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_MASTER_CLKDIV_1, bclk_div - 1); if (ret != 0) { dev_err(dev, "Failed to write BCLK divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_MASTER_CLKDIV_2, lrclk_div - 1); if (ret != 0) { dev_err(dev, "Failed to write LRCLK divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8); if (ret != 0) { dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff); if (ret != 0) { dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret); return ret; } if (sample_rate <= 48000) fssp = PCM512x_FSSP_48KHZ; else if (sample_rate <= 96000) fssp = PCM512x_FSSP_96KHZ; else if (sample_rate <= 192000) fssp = PCM512x_FSSP_192KHZ; else fssp = PCM512x_FSSP_384KHZ; ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE, PCM512x_FSSP, fssp); if (ret != 0) { dev_err(codec->dev, "Failed to set fs speed: %d\n", ret); return ret; } dev_dbg(codec->dev, "DSP divider %d\n", dsp_div); dev_dbg(codec->dev, "DAC divider %d\n", dac_div); dev_dbg(codec->dev, "NCP divider %d\n", ncp_div); dev_dbg(codec->dev, "OSR divider %d\n", osr_div); dev_dbg(codec->dev, "BCK divider %d\n", bclk_div); dev_dbg(codec->dev, "LRCK divider %d\n", lrclk_div); dev_dbg(codec->dev, "IDAC %d\n", idac); dev_dbg(codec->dev, "1<<FSSP %d\n", 1 << fssp); return 0; }
static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; bool invert_lrclk; int ret; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: adau1977->master = false; break; case SND_SOC_DAIFMT_CBM_CFM: ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; adau1977->master = true; break; default: return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: invert_lrclk = false; break; case SND_SOC_DAIFMT_IB_NF: block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; invert_lrclk = false; break; case SND_SOC_DAIFMT_NB_IF: invert_lrclk = true; break; case SND_SOC_DAIFMT_IB_IF: block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; invert_lrclk = true; break; default: return -EINVAL; } adau1977->right_j = false; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; break; case SND_SOC_DAIFMT_LEFT_J: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; invert_lrclk = !invert_lrclk; break; case SND_SOC_DAIFMT_RIGHT_J: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; adau1977->right_j = true; invert_lrclk = !invert_lrclk; break; case SND_SOC_DAIFMT_DSP_A: ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; invert_lrclk = false; break; case SND_SOC_DAIFMT_DSP_B: ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; invert_lrclk = false; break; default: return -EINVAL; } if (invert_lrclk) block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, ADAU1977_BLOCK_POWER_SAI_LR_POL | ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power); if (ret) return ret; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_FMT_MASK, ctrl0); if (ret) return ret; return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, ctrl1); }
static int pcm512x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); int alen; int gpio; int clock_output; int master_mode; int ret; dev_dbg(codec->dev, "hw_params %u Hz, %u channels\n", params_rate(params), params_channels(params)); switch (snd_pcm_format_width(params_format(params))) { case 16: alen = PCM512x_ALEN_16; break; case 20: alen = PCM512x_ALEN_20; break; case 24: alen = PCM512x_ALEN_24; break; case 32: alen = PCM512x_ALEN_32; break; default: dev_err(codec->dev, "Bad frame size: %d\n", snd_pcm_format_width(params_format(params))); return -EINVAL; } switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable slave mode: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_DCAS, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock divider autoset: %d\n", ret); return ret; } return 0; case SND_SOC_DAIFMT_CBM_CFM: clock_output = PCM512x_BCKO | PCM512x_LRKO; master_mode = PCM512x_RLRK | PCM512x_RBCK; break; case SND_SOC_DAIFMT_CBM_CFS: clock_output = PCM512x_BCKO; master_mode = PCM512x_RBCK; break; default: return -EINVAL; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1, PCM512x_ALEN, alen); if (ret != 0) { dev_err(codec->dev, "Failed to set frame size: %d\n", ret); return ret; } if (pcm512x->pll_out) { ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_A: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_B: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } } else { ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS | PCM512x_IPLK); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, 0); if (ret != 0) { dev_err(codec->dev, "Failed to disable pll: %d\n", ret); return ret; } } ret = pcm512x_set_dividers(dai, params); if (ret != 0) return ret; if (pcm512x->pll_out) { ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF, PCM512x_SREF, PCM512x_SREF_GPIO); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio as pllref: %d\n", ret); return ret; } gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN, PCM512x_GREF, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio %d as pllin: %d\n", pcm512x->pll_in, ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, PCM512x_PLLE); if (ret != 0) { dev_err(codec->dev, "Failed to enable pll: %d\n", ret); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, clock_output); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock output: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE, PCM512x_RLRK | PCM512x_RBCK, master_mode); if (ret != 0) { dev_err(codec->dev, "Failed to enable master mode: %d\n", ret); return ret; } if (pcm512x->pll_out) { gpio = PCM512x_G1OE << (pcm512x->pll_out - 1); ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, gpio, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to enable gpio %d: %d\n", pcm512x->pll_out, ret); return ret; } gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1; ret = regmap_update_bits(pcm512x->regmap, gpio, PCM512x_GxSL, PCM512x_GxSL_PLLCK); if (ret != 0) { dev_err(codec->dev, "Failed to output pll on %d: %d\n", ret, pcm512x->pll_out); return ret; } gpio = PCM512x_G1OE << (4 - 1); ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, gpio, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to enable gpio %d: %d\n", 4, ret); return ret; } gpio = PCM512x_GPIO_OUTPUT_1 + 4 - 1; ret = regmap_update_bits(pcm512x->regmap, gpio, PCM512x_GxSL, PCM512x_GxSL_PLLLK); if (ret != 0) { dev_err(codec->dev, "Failed to output pll lock on %d: %d\n", ret, 4); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_HALT); if (ret != 0) { dev_err(codec->dev, "Failed to halt clocks: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_RESUME); if (ret != 0) { dev_err(codec->dev, "Failed to resume clocks: %d\n", ret); return ret; } return 0; }
static int wm8737_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* VMID at 2*75k */ snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, WM8737_VMIDSEL_MASK, 0); break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); return ret; } regcache_sync(wm8737->regmap); /* Fast VMID ramp at 2*2.5k */ snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, WM8737_VMIDSEL_MASK, 2 << WM8737_VMIDSEL_SHIFT); /* Bring VMID up */ snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, WM8737_VMID_MASK | WM8737_VREF_MASK, WM8737_VMID_MASK | WM8737_VREF_MASK); msleep(500); } /* VMID at 2*300k */ snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, WM8737_VMIDSEL_MASK, 1 << WM8737_VMIDSEL_SHIFT); break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, WM8737_VMID_MASK | WM8737_VREF_MASK, 0); regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); break; } codec->dapm.bias_level = level; return 0; }
static int rk610_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); u16 iface = 0; spk_ctrl_fun(GPIO_LOW); rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: iface = 0x0040; break; case SND_SOC_DAIFMT_CBS_CFS: iface = 0x0000; break; default: return -EINVAL; } /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: iface |= 0x0002; break; case SND_SOC_DAIFMT_RIGHT_J: break; case SND_SOC_DAIFMT_LEFT_J: iface |= 0x0001; break; case SND_SOC_DAIFMT_DSP_A: iface |= 0x0003; break; case SND_SOC_DAIFMT_DSP_B: iface |= 0x0013; break; default: return -EINVAL; } /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_IF: iface |= 0x0090; break; case SND_SOC_DAIFMT_IB_NF: iface |= 0x0080; break; case SND_SOC_DAIFMT_NB_IF: iface |= 0x0010; break; default: return -EINVAL; } DBG("Enter::%s----%d iface=%x\n",__FUNCTION__,__LINE__,iface); rk610_codec_write(codec, ACCELCODEC_R09, iface); return 0; }
static int sta32x_probe(struct snd_soc_codec *codec) { struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); int i, ret = 0, thermal = 0; sta32x->codec = codec; sta32x->pdata = dev_get_platdata(codec->dev); ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); return ret; } /* Chip documentation explicitly requires that the reset values * of reserved register bits are left untouched. * Write the register default value to cache for reserved registers, * so the write to the these registers are suppressed by the cache * restore code when it skips writes of default registers. */ regcache_cache_only(sta32x->regmap, true); snd_soc_write(codec, STA32X_CONFC, 0xc2); snd_soc_write(codec, STA32X_CONFE, 0xc2); snd_soc_write(codec, STA32X_CONFF, 0x5c); snd_soc_write(codec, STA32X_MMUTE, 0x10); snd_soc_write(codec, STA32X_AUTO1, 0x60); snd_soc_write(codec, STA32X_AUTO3, 0x00); snd_soc_write(codec, STA32X_C3CFG, 0x40); regcache_cache_only(sta32x->regmap, false); /* set thermal warning adjustment and recovery */ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) thermal |= STA32X_CONFA_TWAB; if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE)) thermal |= STA32X_CONFA_TWRB; snd_soc_update_bits(codec, STA32X_CONFA, STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, thermal); /* select output configuration */ snd_soc_update_bits(codec, STA32X_CONFF, STA32X_CONFF_OCFG_MASK, sta32x->pdata->output_conf << STA32X_CONFF_OCFG_SHIFT); /* channel to output mapping */ snd_soc_update_bits(codec, STA32X_C1CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch1_output_mapping << STA32X_CxCFG_OM_SHIFT); snd_soc_update_bits(codec, STA32X_C2CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch2_output_mapping << STA32X_CxCFG_OM_SHIFT); snd_soc_update_bits(codec, STA32X_C3CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch3_output_mapping << STA32X_CxCFG_OM_SHIFT); /* initialize coefficient shadow RAM with reset values */ for (i = 4; i <= 49; i += 5) sta32x->coef_shadow[i] = 0x400000; for (i = 50; i <= 54; i++) sta32x->coef_shadow[i] = 0x7fffff; sta32x->coef_shadow[55] = 0x5a9df7; sta32x->coef_shadow[56] = 0x7fffff; sta32x->coef_shadow[59] = 0x7fffff; sta32x->coef_shadow[60] = 0x400000; sta32x->coef_shadow[61] = 0x400000; if (sta32x->pdata->needs_esd_watchdog) INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; }
static int twl6040_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); int audpwron = priv->audpwron; int naudint = priv->naudint; int ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (priv->codec_powered) break; if (gpio_is_valid(audpwron)) { /* use AUDPWRON line */ gpio_set_value(audpwron, 1); /* wait for power-up completion */ ret = twl6040_power_up_completion(codec, naudint); if (ret) return ret; /* sync registers updated during power-up sequence */ twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL); twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL); } else { /* use manual power-up sequence */ twl6040_power_up(codec); priv->codec_powered = 1; } /* initialize vdd/vss registers with reg_cache */ twl6040_init_vdd_regs(codec); break; case SND_SOC_BIAS_OFF: if (!priv->codec_powered) break; if (gpio_is_valid(audpwron)) { /* use AUDPWRON line */ gpio_set_value(audpwron, 0); /* power-down sequence latency */ udelay(500); /* sync registers updated during power-down sequence */ twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL); twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL, 0x00); } else { /* use manual power-down sequence */ twl6040_power_down(codec); } priv->codec_powered = 0; break; } codec->bias_level = level; return 0; }
static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); unsigned int hw_params = 0; if (substream == uda134x->slave_substream) { pr_debug("%s ignoring hw_params for slave substream\n", __func__); return 0; } pr_debug("%s sysclk: %d, rate:%d\n", __func__, uda134x->sysclk, params_rate(params)); /* set SYSCLK / fs ratio */ switch (uda134x->sysclk / params_rate(params)) { case 512: break; case 384: hw_params |= (1<<4); break; case 256: hw_params |= (1<<5); break; default: printk(KERN_ERR "%s unsupported fs\n", __func__); return -EINVAL; } pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__, uda134x->dai_fmt, params_format(params)); /* set DAI format and word length */ switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_RIGHT_J: switch (params_width(params)) { case 16: hw_params |= (1<<1); break; case 18: hw_params |= (1<<2); break; case 20: hw_params |= ((1<<2) | (1<<1)); break; default: printk(KERN_ERR "%s unsupported format (right)\n", __func__); return -EINVAL; } break; case SND_SOC_DAIFMT_LEFT_J: hw_params |= (1<<3); break; default: printk(KERN_ERR "%s unsupported format\n", __func__); return -EINVAL; } return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params); }
int rt_codec_dsp_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { struct rt_codec_cmd rt_codec; int *buf; int *p; int ret; struct rt3261_dsp_param param; //int mask1 = 0, mask2 = 0; struct rt_codec_cmd __user *_rt_codec = (struct rt_codec_cmd *)arg; struct snd_soc_codec *codec = hw->private_data; struct rt3261_priv *rt3261 = snd_soc_codec_get_drvdata(codec); if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) { dev_err(codec->dev, "copy_from_user faild\n"); return -EFAULT; } dev_dbg(codec->dev, "rt_codec.number=%d\n",rt_codec.number); buf = kmalloc(sizeof(*buf) * rt_codec.number, GFP_KERNEL); if (buf == NULL) return -ENOMEM; if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number)) { goto err; } ret = snd_soc_update_bits(codec, RT3261_PWR_DIG2, RT3261_PWR_I2S_DSP, RT3261_PWR_I2S_DSP); if (ret < 0) { dev_err(codec->dev, "Failed to power up DSP IIS interface: %d\n", ret); goto err; } switch (cmd) { case RT_READ_CODEC_DSP_IOCTL: for (p = buf; p < buf + rt_codec.number/2; p++) *(p+rt_codec.number/2) = rt3261_dsp_read(codec, *p); if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number)) goto err; break; case RT_WRITE_CODEC_DSP_IOCTL: param.cmd_fmt = 0x00e0; param.cmd = RT3261_DSP_CMD_MW; p = buf; param.addr = *p; param.data = *(p+rt_codec.number/2); if(codec == NULL) { dev_dbg(codec->dev, "codec is null\n"); break; } for (p = buf; p < buf + rt_codec.number/2; p++) rt3261_dsp_write(codec, ¶m); break; case RT_GET_CODEC_DSP_MODE_IOCTL: *buf = rt3261->dsp_sw; if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number)) goto err; break; default: dev_info(codec->dev, "unsported dsp command\n"); break; } kfree(buf); return 0; err: kfree(buf); return -EFAULT; }