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);
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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);
    }
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
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, &reg);
	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;
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
/* 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;
}
Ejemplo n.º 21
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);
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
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);
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
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);
}
Ejemplo n.º 30
0
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, &param);
		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;
}