Example #1
0
static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	int		i;
	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
	void		*pDAQ = chip->mappedbase + DARQ_DATA_BUFF;

	chip->capture_sample_size = snd_pcm_format_width(params_format(params));
	chip->capture_channels = params_channels(params);
	chip->capture_sample_rate = params_rate(params);

	for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
		writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
		writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
		writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
	}
	return 0;
}
Example #2
0
static int jz_pcm_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct device *dev = dai->dev;
	struct jz_pcm *jz_pcm = dev_get_drvdata(dai->dev);
	int fmt_width = snd_pcm_format_width(params_format(params));
	enum dma_slave_buswidth buswidth;
	int trigger;

	PCM_DEBUG_MSG("enter %s, substream = %s\n",
			__func__,
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture");

	if (!((1 << params_format(params)) & JZ_PCM_FORMATS) ||
			params_channels(params) != 1 ||
			params_rate(params) != 8000) {
		dev_err(dai->dev, "hw params not inval channel %d params %x\n",
				params_channels(params), params_format(params));
		return -EINVAL;
	}

	/* format 8 bit or 16 bit*/
	if (fmt_width == 8)
		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
	else
		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		jz_pcm->tx_dma_data.buswidth = buswidth;
		jz_pcm->tx_dma_data.max_burst = (PCM_TFIFO_DEPTH * buswidth)/2;
		trigger = PCM_TFIFO_DEPTH - (jz_pcm->tx_dma_data.max_burst/(int)buswidth);
		__pcm_set_oss_sample_size(dev, fmt_width == 8 ? 0 : 1);
		__pcm_set_transmit_trigger(dev, trigger);
		snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_pcm->tx_dma_data);
	} else {
		jz_pcm->rx_dma_data.buswidth = buswidth;
		jz_pcm->rx_dma_data.max_burst = (PCM_RFIFO_DEPTH * buswidth)/2;
		trigger = jz_pcm->rx_dma_data.max_burst/(int)buswidth;
		__pcm_set_iss_sample_size(dev, fmt_width == 8 ? 0 : 1);
		__pcm_set_receive_trigger(dev, trigger);
		snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_pcm->rx_dma_data);
	}
	return 0;
}
Example #3
0
static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_dummy_pcm *dpcm = runtime->private_data;
	unsigned int bps;

	bps = runtime->rate * runtime->channels;
	bps *= snd_pcm_format_width(runtime->format);
	bps /= 8;
	if (bps <= 0)
		return -EINVAL;
	dpcm->pcm_bps = bps;
	dpcm->pcm_jiffie = bps / HZ;
	dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
	dpcm->pcm_irq_pos = 0;
	dpcm->pcm_buf_pos = 0;
	return 0;
}
Example #4
0
static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
			      struct snd_pcm_hw_params *params,
			      struct snd_soc_dai *dai)
{
	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
	u32 width = snd_pcm_format_width(params_format(params));
	u32 channels = params_channels(params);
	u32 bclk, mask, val, ret;

	bclk = params_rate(params) * esai_priv->slot_width * 2;

	ret = fsl_esai_set_bclk(dai, tx, bclk);
	if (ret)
		return ret;

	/* Use Normal mode to support monaural audio */
	regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
			   ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
			   ESAI_xCR_xMOD_NETWORK : 0);

	regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
			   ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);

	mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
	      (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
	val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
	     (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels));

	regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);

	mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
	val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0);

	regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);

	/* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */
	regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
			   ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
	regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
			   ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
	return 0;
}
Example #5
0
/**
 * fsl_ssi_prepare: prepare the SSI.
 *
 * Most of the SSI registers have been programmed in the startup function,
 * but the word length must be programmed here.  Unfortunately, programming
 * the SxCCR.WL bits requires the SSI to be temporarily disabled.  This can
 * cause a problem with supporting simultaneous playback and capture.  If
 * the SSI is already playing a stream, then that stream may be temporarily
 * stopped when you start capture.
 *
 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
 * clock master.
 */
static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;

	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;

	if (substream == ssi_private->first_stream) {
		u32 wl;

		/* The SSI should always be disabled at this points (SSIEN=0) */
		wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));

		/* In synchronous mode, the SSI uses STCCR for capture */
		clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
	}

	return 0;
}
Example #6
0
static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_dummy_pcm *dpcm = runtime->private_data;
	int bps;

	bps = snd_pcm_format_width(runtime->format) * runtime->rate * runtime->channels / 8;

	if (bps <= 0)
		return -EINVAL;

	dpcm->pcm_bps = bps;
	dpcm->pcm_hz = HZ;
	dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
	dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
	dpcm->pcm_irq_pos = 0;
	dpcm->pcm_buf_pos = 0;
	snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));

	return 0;
}
Example #7
0
/**
 * fsl_ssi_hw_params - program the sample size
 *
 * Most of the SSI registers have been programmed in the startup function,
 * but the word length must be programmed here.  Unfortunately, programming
 * the SxCCR.WL bits requires the SSI to be temporarily disabled.  This can
 * cause a problem with supporting simultaneous playback and capture.  If
 * the SSI is already playing a stream, then that stream may be temporarily
 * stopped when you start capture.
 *
 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
 * clock master.
 */
static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
{
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	unsigned int sample_size =
		snd_pcm_format_width(params_format(hw_params));
	u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
	int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
	unsigned int channels = params_channels(hw_params);

	/*
	 * If we're in synchronous mode, and the SSI is already enabled,
	 * then STCCR is already set properly.
	 */
	if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
		return 0;

	/*
	 * FIXME: The documentation says that SxCCR[WL] should not be
	 * modified while the SSI is enabled.  The only time this can
	 * happen is if we're trying to do simultaneous playback and
	 * capture in asynchronous mode.  Unfortunately, I have been enable
	 * to get that to work at all on the P1022DS.  Therefore, we don't
	 * bother to disable/enable the SSI when setting SxCCR[WL], because
	 * the SSI will stop anyway.  Maybe one day, this will get fixed.
	 */

	/* In synchronous mode, the SSI uses STCCR for capture */
	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
	    ssi_private->cpu_dai_drv.symmetric_rates)
		write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
	else
		write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);

	write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
			channels == 1 ? 0 : ssi_private->i2s_mode);

	return 0;
}
Example #8
0
static int jz_dmic_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct device *dev = dai->dev;
	int channels = params_channels(params);
	int rate = params_rate(params);
	struct jz_dmic *jz_dmic = dev_get_drvdata(dai->dev);
	int fmt_width = snd_pcm_format_width(params_format(params));
	enum dma_slave_buswidth buswidth;
	int trigger;

	DMIC_DEBUG_MSG("enter %s, substream = %s\n",__func__,"capture");

	if (!((1 << params_format(params)) & JZ_DMIC_FORMATS)
			||channels < 1||channels > 4|| rate > 48000||rate < 8000
			||fmt_width != 16) {
		dev_err(dai->dev, "hw params not inval channel %d params %x rate %d fmt_width %d\n",
				channels, params_format(params),rate,fmt_width);
		return -EINVAL;
	}

	if (jz_dmic->unpack_enable)
		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
	else
		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		jz_dmic->rx_dma_data.buswidth = buswidth;
		jz_dmic->rx_dma_data.max_burst = (DMIC_FIFO_DEPTH * buswidth)/2;
		trigger = jz_dmic->rx_dma_data.max_burst/(int)buswidth;
		__dmic_set_request(dev, trigger);
		__dmic_set_chnum(dev, channels - 1);
		dmic_set_rate(dev,rate);
		snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_dmic->rx_dma_data);
	} else {
		dev_err(dai->dev, "DMIC is a capture device\n");
	}
	return 0;
}
Example #9
0
static void set_wm8785_params(struct oxygen *chip,
			      struct snd_pcm_hw_params *params)
{
	unsigned int value;

	wm8785_write(chip, WM8785_R7, 0);

	value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST;
	if (params_rate(params) <= 48000)
		value |= WM8785_OSR_SINGLE;
	else if (params_rate(params) <= 96000)
		value |= WM8785_OSR_DOUBLE;
	else
		value |= WM8785_OSR_QUAD;
	wm8785_write(chip, WM8785_R0, value);

	if (snd_pcm_format_width(params_format(params)) <= 16)
		value = WM8785_WL_16;
	else
		value = WM8785_WL_24;
	wm8785_write(chip, WM8785_R1, value);
}
Example #10
0
int
snd_send(FILE * fp, size_t n)
{
    snd_pcm_format_t format;
    unsigned int    nchannels;
    snd_pcm_uframes_t period;
    snd_pcm_hw_params_t *params;
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_current(pcm, params);
    snd_pcm_hw_params_get_format(params, &format);
    snd_pcm_hw_params_get_channels(params, &nchannels);
    snd_pcm_hw_params_get_period_size(params, &period, 0);
    int             framesize =
        snd_pcm_format_width(format) / 8 * nchannels;
    unsigned char   buf[period * framesize * 128];
    size_t          l;
    while (n > sizeof(buf)) {
        if ((l = fread(buf, 1, sizeof(buf), fp))) {
            switch (snd_pcm_writei(pcm, buf, l / framesize)) {
            case -EBADF:
                return -1;
            case -EPIPE:
#ifndef NDEBUG
                snd_pcm_recover(pcm, -EPIPE, 0);
#else
                snd_pcm_prepare(pcm);
#endif
            }
        } else
            goto EOS;
        n -= l;
    }
    if ((l = fread(buf, 1, n, fp)))
        snd_pcm_writei(pcm, buf, l / framesize);
    if (l < n)
      EOS:if (ftell(fp) > 0)
            eputs("Unexpected end of stream");
    return snd_pcm_drain(pcm);
}
Example #11
0
/**
 * fsl_ssi_prepare: prepare the SSI.
 *
 * Most of the SSI registers have been programmed in the startup function,
 * but the word length must be programmed here.  Unfortunately, programming
 * the SxCCR.WL bits requires the SSI to be temporarily disabled.  This can
 * cause a problem with supporting simultaneous playback and capture.  If
 * the SSI is already playing a stream, then that stream may be temporarily
 * stopped when you start capture.
 *
 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
 * clock master.
 */
static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;

	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	u32 wl;

	wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));

	clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
	else
		clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);

	setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);

	return 0;
}
Example #12
0
static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	int	i;
	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
	void	*pDAQ =	chip->mappedbase + DAPQ_DATA_BUFF;

	chip->play_sample_size = snd_pcm_format_width(params_format(params));
	chip->play_channels = params_channels(params);
	chip->play_sample_rate = params_rate(params);

	for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
		writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
		writew(chip->play_channels, pDAQ + DAQDS_wChannels);
		writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
	}
	/* dont do this here:
	 * snd_msnd_calibrate_adc(chip->play_sample_rate);
	 */

	return 0;
}
Example #13
0
static int loopback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct loopback_pcm *dpcm = runtime->private_data;
	struct loopback_cable *cable = dpcm->cable;
	int bps, salign;

	salign = (snd_pcm_format_width(runtime->format) *
						runtime->channels) / 8;
	bps = salign * runtime->rate;
	if (bps <= 0 || salign <= 0)
		return -EINVAL;

	dpcm->buf_pos = 0;
	dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		
		dpcm->silent_size = dpcm->pcm_buffer_size;
		snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
					   runtime->buffer_size * runtime->channels);
	}

	dpcm->irq_pos = 0;
	dpcm->period_update_pending = 0;
	dpcm->pcm_bps = bps;
	dpcm->pcm_salign = salign;
	dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);

	mutex_lock(&dpcm->loopback->cable_lock);
	if (!(cable->valid & ~(1 << substream->stream)) ||
            (get_setup(dpcm)->notify &&
	     substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
		params_change(substream);
	cable->valid |= 1 << substream->stream;
	mutex_unlock(&dpcm->loopback->cable_lock);

	return 0;
}
Example #14
0
/* hw_params callback */
static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
	int err;

	audio_info(" .. IN\n");

	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
	if (err < 0) {
		audio_error
			(" pcm_lib_malloc failed to allocated pages for buffers\n");
		return err;
	}

	alsa_stream->channels = params_channels(params);
	alsa_stream->params_rate = params_rate(params);
	alsa_stream->pcm_format_width = snd_pcm_format_width(params_format(params));
	audio_info(" .. OUT\n");

	return err;
}
static void generate_sine(uint8_t *frames, int channel, int count, double *_phase) {
  double phase = *_phase;
  double max_phase = 1.0 / freq;
  double step = 1.0 / (double)rate;
  double res;
  float fres;
  int    chn;
  int32_t  ires;
  int8_t *samp8 = (int8_t*) frames;
  int16_t *samp16 = (int16_t*) frames;
  int32_t *samp32 = (int32_t*) frames;
  float   *samp_f = (float*) frames;
  int sample_size_bits = snd_pcm_format_width(format); 

  while (count-- > 0) {
    //res = sin((phase * 2 * M_PI) / max_phase - M_PI) * 32767;
    //res = sin((phase * 2 * M_PI) / max_phase - M_PI) * 32767;
    //res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
    //if (res > 0) res = 10000;
    //if (res < 0) res = -10000;

    /* printf("%e\n",res); */
    //ires = res;
    //ires = ((16 - (count & 0xf)) <<24);
    //ires = 0;

    for(chn=0;chn<channels;chn++) {
      if (sample_size_bits == 8) {
        if (chn==channel) {
          res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
          ires = res;
	  *samp8++ = ires >> 24;
	  //*samp8++ = 0x12;
        } else {
	  *samp8++ = 0;
        }
      } else if (sample_size_bits == 16) {
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
                            int* sampleSizeInBytes, int* significantBits,
                            int* isSigned, int* isBigEndian, int* enc) {

    *sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
    *significantBits = snd_pcm_format_width(alsaFormat);

    // defaults
    *enc = 0; // PCM
    *isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
    *isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);

    // non-PCM formats
    if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
        *sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
    }
    else if (alsaFormat == SND_PCM_FORMAT_A_LAW) {     // A-Law
        *sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
    }
    else if (snd_pcm_format_linear(alsaFormat) < 1) {
        return 0;
    }
    return (*sampleSizeInBytes > 0);
}
Example #17
0
bool VoiceStreamer::initDevice() {
   int err;

   if ((err = snd_output_stdio_attach(&output, stdout, 0)) < 0) {
      printf("Output failed: %s\n", snd_strerror(err));
      return false;
   }

   if ((err = snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 
               SND_PCM_NONBLOCK)) < 0) {
      printf("Playback open error: %s\n", snd_strerror(err));
      return false;
   }
   if ((err = snd_pcm_open(&chandle, "default" , SND_PCM_STREAM_CAPTURE, 
               SND_PCM_NONBLOCK)) < 0) {
      printf("Record open error: %s\n", snd_strerror(err));
      return false;
   }

   latency = latency_min - 4;
   buffer = new char[(latency_max*snd_pcm_format_width(format)/8)*2];

//   if (setparams_p(phandle, &latency) < 0) 
//      return false;
   if (setparams_c(chandle, &latency) < 0) 
      return false;
   if ((err = snd_pcm_start(chandle)) < 0) {
      printf("Go error: %s\n", snd_strerror(err));
      exit(EXIT_FAILURE);
   }

   frames_in = frames_out = 0;
   in_max = 0;

   return true;
}
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;
}
Example #19
0
/* this may get called several times by oss emulation */
static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
	struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
	struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
	struct sst_byt *byt = pdata->byt;
	u32 rate, bits;
	u8 channels;
	int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);

	dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data);

	ret = sst_byt_stream_type(byt, pcm_data->stream,
				  1, 1, !playback);
	if (ret < 0) {
		dev_err(rtd->dev, "failed to set stream format %d\n", ret);
		return ret;
	}

	rate = params_rate(params);
	ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate);
	if (ret < 0) {
		dev_err(rtd->dev, "could not set rate %d\n", rate);
		return ret;
	}

	bits = snd_pcm_format_width(params_format(params));
	ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits);
	if (ret < 0) {
		dev_err(rtd->dev, "could not set formats %d\n",
			params_rate(params));
		return ret;
	}

	channels = (u8)(params_channels(params) & 0xF);
	ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels);
	if (ret < 0) {
		dev_err(rtd->dev, "could not set channels %d\n",
			params_rate(params));
		return ret;
	}

	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));

	ret = sst_byt_stream_buffer(byt, pcm_data->stream,
				    substream->dma_buffer.addr,
				    params_buffer_bytes(params));
	if (ret < 0) {
		dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret);
		return ret;
	}

	ret = sst_byt_stream_commit(byt, pcm_data->stream);
	if (ret < 0) {
		dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret);
		return ret;
	}

	return 0;
}
Example #20
0
static int
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
{
    int status = 0;
    int format = 0;
    SDL_AudioFormat test_format = 0;
    int found = 0;
    snd_pcm_channel_setup_t csetup;
    snd_pcm_channel_params_t cparams;

    /* Initialize all variables that we clean on shutdown */
    this->hidden =
        (struct SDL_PrivateAudioData *) SDL_calloc(1,
                                                   (sizeof
                                                    (struct
                                                     SDL_PrivateAudioData)));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));

    /* Initialize channel transfer parameters to default */
    QSA_InitAudioParams(&cparams);

    /* Initialize channel direction: capture or playback */
    this->hidden->iscapture = iscapture;

    /* Find deviceid and cardid by device name for playback */
    if ((!this->hidden->iscapture) && (devname != NULL)) {
        uint32_t device;
        int32_t status;

        /* Search in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_playback_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_playback_device[device].deviceno;
                this->hidden->cardno = qsa_playback_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_playback_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such playback device");
            }
        } while (1);
    }

    /* Find deviceid and cardid by device name for capture */
    if ((this->hidden->iscapture) && (devname != NULL)) {
        /* Search in the capture devices */
        uint32_t device;
        int32_t status;

        /* Searching in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_capture_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_capture_device[device].deviceno;
                this->hidden->cardno = qsa_capture_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_capture_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such capture device");
            }
        } while (1);
    }

    /* Check if SDL requested default audio device */
    if (devname == NULL) {
        /* Open system default audio device */
        if (!this->hidden->iscapture) {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_PLAYBACK);
        } else {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_CAPTURE);
        }
    } else {
        /* Open requested audio device */
        if (!this->hidden->iscapture) {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_PLAYBACK);
        } else {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_CAPTURE);
        }
    }

    /* Check if requested device is opened */
    if (status < 0) {
        this->hidden->audio_handle = NULL;
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_open", status);
    }

    if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
        /* Disable QSA MMAP plugin for buggy audio drivers */
        status =
            snd_pcm_plugin_set_disable(this->hidden->audio_handle,
                                       PLUGIN_DISABLE_MMAP);
        if (status < 0) {
            QSA_CloseDevice(this);
            return QSA_SetError("snd_pcm_plugin_set_disable", status);
        }
    }

    /* Try for a closest match on audio format */
    format = 0;
    /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
    found = 0;

    for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
        /* if match found set format to equivalent QSA format */
        switch (test_format) {
        case AUDIO_U8:
            {
                format = SND_PCM_SFMT_U8;
                found = 1;
            }
            break;
        case AUDIO_S8:
            {
                format = SND_PCM_SFMT_S8;
                found = 1;
            }
            break;
        case AUDIO_S16LSB:
            {
                format = SND_PCM_SFMT_S16_LE;
                found = 1;
            }
            break;
        case AUDIO_S16MSB:
            {
                format = SND_PCM_SFMT_S16_BE;
                found = 1;
            }
            break;
        case AUDIO_U16LSB:
            {
                format = SND_PCM_SFMT_U16_LE;
                found = 1;
            }
            break;
        case AUDIO_U16MSB:
            {
                format = SND_PCM_SFMT_U16_BE;
                found = 1;
            }
            break;
        case AUDIO_S32LSB:
            {
                format = SND_PCM_SFMT_S32_LE;
                found = 1;
            }
            break;
        case AUDIO_S32MSB:
            {
                format = SND_PCM_SFMT_S32_BE;
                found = 1;
            }
            break;
        case AUDIO_F32LSB:
            {
                format = SND_PCM_SFMT_FLOAT_LE;
                found = 1;
            }
            break;
        case AUDIO_F32MSB:
            {
                format = SND_PCM_SFMT_FLOAT_BE;
                found = 1;
            }
            break;
        default:
            {
                break;
            }
        }

        if (!found) {
            test_format = SDL_NextAudioFormat();
        }
    }

    /* assumes test_format not 0 on success */
    if (test_format == 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Couldn't find any hardware audio formats");
    }

    this->spec.format = test_format;

    /* Set the audio format */
    cparams.format.format = format;

    /* Set mono/stereo/4ch/6ch/8ch audio */
    cparams.format.voices = this->spec.channels;

    /* Set rate */
    cparams.format.rate = this->spec.freq;

    /* Setup the transfer parameters according to cparams */
    status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_channel_params", status);
    }

    /* Make sure channel is setup right one last time */
    SDL_memset(&csetup, 0, sizeof(csetup));
    if (!this->hidden->iscapture) {
        csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    } else {
        csetup.channel = SND_PCM_CHANNEL_CAPTURE;
    }

    /* Setup an audio channel */
    if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Unable to setup channel");
    }

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    this->hidden->pcm_len = this->spec.size;

    if (this->hidden->pcm_len == 0) {
        this->hidden->pcm_len =
            csetup.buf.block.frag_size * this->spec.channels *
            (snd_pcm_format_width(format) / 8);
    }

    /*
     * Allocate memory to the audio buffer and initialize with silence
     *  (Note that buffer size must be a multiple of fragment size, so find
     *  closest multiple)
     */
    this->hidden->pcm_buf =
        (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
    if (this->hidden->pcm_buf == NULL) {
        QSA_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->pcm_buf, this->spec.silence,
               this->hidden->pcm_len);

    /* get the file descriptor */
    if (!this->hidden->iscapture) {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_PLAYBACK);
    } else {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_CAPTURE);
    }

    if (this->hidden->audio_fd < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_file_descriptor", status);
    }

    /* Prepare an audio channel */
    if (!this->hidden->iscapture) {
        /* Prepare audio playback */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_PLAYBACK);
    } else {
        /* Prepare audio capture */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_CAPTURE);
    }

    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_plugin_prepare", status);
    }

    /* We're really ready to rock and roll. :-) */
    return 0;
}
static int wm8776_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 wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
	int iface_reg, iface;
	int ratio_shift, master;
	int i;

	switch (dai->driver->id) {
	case WM8776_DAI_DAC:
		iface_reg = WM8776_DACIFCTRL;
		master = 0x80;
		ratio_shift = 4;
		break;
	case WM8776_DAI_ADC:
		iface_reg = WM8776_ADCIFCTRL;
		master = 0x100;
		ratio_shift = 0;
		break;
	default:
		return -EINVAL;
	}

	/* Set word length */
	switch (snd_pcm_format_width(params_format(params))) {
	case 16:
		iface = 0;
		break;
	case 20:
		iface = 0x10;
		break;
	case 24:
		iface = 0x20;
		break;
	case 32:
		iface = 0x30;
		break;
	default:
		dev_err(codec->dev, "Unsupported sample size: %i\n",
			snd_pcm_format_width(params_format(params)));
		return -EINVAL;
	}

	/* Only need to set MCLK/LRCLK ratio if we're master */
	if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
		for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
			if (wm8776->sysclk[dai->driver->id] / params_rate(params)
			    == mclk_ratios[i])
				break;
		}

		if (i == ARRAY_SIZE(mclk_ratios)) {
			dev_err(codec->dev,
				"Unable to configure MCLK ratio %d/%d\n",
				wm8776->sysclk[dai->driver->id], params_rate(params));
			return -EINVAL;
		}

		dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);

		snd_soc_update_bits(codec, WM8776_MSTRCTRL,
				    0x7 << ratio_shift, i << ratio_shift);
	} else {
		dev_dbg(codec->dev, "DAI in slave mode\n");
	}

	snd_soc_update_bits(codec, iface_reg, 0x30, iface);

	return 0;
}
Example #22
0
static int es705_hw_params(struct snd_pcm_substream *substream,
			       struct snd_pcm_hw_params *params,
			       struct snd_soc_dai *dai)
{
	unsigned int base = dai->driver->base;
	unsigned int msg, resp;
	int ret, val;
	u32 cmd_block[3];

	return 0;

	if (escore_priv.flag.is_fw_ready == 0) {
		pr_warn("%s(port-%c): es705 firmware is not ready, abort\n",
				__func__, PORT_NAME(base));
		return 0;
	}

	/* word length */
	//if (es705_ports[PORT_ID(base)].wl != params_format(params))
	{
		printk("++%s(port-%c)++: format=%d\n", __func__, PORT_NAME(base),
			   params_format(params));

		val = snd_pcm_format_width(params_format(params)) - 1;
		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_WORDLENGHT;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}

		es705_ports[PORT_ID(base)].wl = params_format(params);
	}

	/* sample rate */
	//if (es705_ports[PORT_ID(base)].rate != params_rate(params))
	{
		printk("++%s(port-%c)++: rate=%d\n", __func__, PORT_NAME(base),
			   params_rate(params));

		msg = ES705_PORT_GET_PARAM + base + ES705_PORT_CLOCK;
		ret = escore_cmd(&escore_priv, msg, &resp);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send %08x failed\n", msg);
			goto out;
		}

		val = (resp & 0x100) + (params_rate(params) / 1000);
		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_CLOCK;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}

		es705_ports[PORT_ID(base)].rate = params_rate(params);
	}

out:
	return ret;
}
Example #23
0
static int uni_player_prepare_pcm(struct uniperif *player,
				  struct snd_pcm_runtime *runtime)
{
	int output_frame_size, slot_width, clk_div;

	/* Force slot width to 32 in I2S mode (HW constraint) */
	if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
		SND_SOC_DAIFMT_I2S)
		slot_width = 32;
	else
		slot_width = snd_pcm_format_width(runtime->format);

	output_frame_size = slot_width * runtime->channels;

	clk_div = player->mclk / runtime->rate;
	/*
	 * For 32 bits subframe clk_div must be a multiple of 128,
	 * for 16 bits must be a multiple of 64
	 */
	if ((slot_width == 32) && (clk_div % 128)) {
		dev_err(player->dev, "%s: invalid clk_div\n", __func__);
		return -EINVAL;
	}

	if ((slot_width == 16) && (clk_div % 64)) {
		dev_err(player->dev, "%s: invalid clk_div\n", __func__);
		return -EINVAL;
	}

	/*
	 * Number of bits per subframe (which is one channel sample)
	 * on output - Transfer 16 or 32 bits from FIFO
	 */
	switch (slot_width) {
	case 32:
		SET_UNIPERIF_I2S_FMT_NBIT_32(player);
		SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player);
		break;
	case 16:
		SET_UNIPERIF_I2S_FMT_NBIT_16(player);
		SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(player);
		break;
	default:
		dev_err(player->dev, "subframe format not supported\n");
		return -EINVAL;
	}

	/* Configure data memory format */
	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		/* One data word contains two samples */
		SET_UNIPERIF_CONFIG_MEM_FMT_16_16(player);
		break;

	case SNDRV_PCM_FORMAT_S32_LE:
		/*
		 * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits
		 * on the left than zeros (if less than 32 bytes)"... ;-)
		 */
		SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player);
		break;

	default:
		dev_err(player->dev, "format not supported\n");
		return -EINVAL;
	}

	/* Set rounding to off */
	SET_UNIPERIF_CTRL_ROUNDING_OFF(player);

	/* Set clock divisor */
	SET_UNIPERIF_CTRL_DIVIDER(player, clk_div / (2 * output_frame_size));

	/* Number of channelsmust be even*/
	if ((runtime->channels % 2) || (runtime->channels < 2) ||
	    (runtime->channels > 10)) {
		dev_err(player->dev, "%s: invalid nb of channels\n", __func__);
		return -EINVAL;
	}

	SET_UNIPERIF_I2S_FMT_NUM_CH(player, runtime->channels / 2);

	/* Set 1-bit audio format to disabled */
	SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player);

	SET_UNIPERIF_I2S_FMT_ORDER_MSB(player);

	/* No iec958 formatting as outputting to DAC  */
	SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player);

	return 0;
}
Example #24
0
static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params,
	struct snd_soc_dai *dai)
{
	struct snd_soc_component *component = dai->component;
	struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
	unsigned int sampling_rate = 0;
	unsigned int chan_sz = 0;

	/* pcm mode configuration */
	switch (snd_pcm_format_width(params_format(params))) {
	case 16:
		chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
		break;
	case 24:
		chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
		break;
	case 32:
		chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
		break;
	default:
		dev_err(component->dev, "format unsupported %d\n",
			params_format(params));
		goto err;
	}

	max98373->ch_size = snd_pcm_format_width(params_format(params));

	regmap_update_bits(max98373->regmap,
		MAX98373_R2024_PCM_DATA_FMT_CFG,
		MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);

	dev_dbg(component->dev, "format supported %d",
		params_format(params));

	/* sampling rate configuration */
	switch (params_rate(params)) {
	case 8000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_8000;
		break;
	case 11025:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_11025;
		break;
	case 12000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_12000;
		break;
	case 16000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_16000;
		break;
	case 22050:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_22050;
		break;
	case 24000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_24000;
		break;
	case 32000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_32000;
		break;
	case 44100:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_44100;
		break;
	case 48000:
		sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
		break;
	default:
		dev_err(component->dev, "rate %d not supported\n",
			params_rate(params));
		goto err;
	}

	/* set DAI_SR to correct LRCLK frequency */
	regmap_update_bits(max98373->regmap,
		MAX98373_R2027_PCM_SR_SETUP_1,
		MAX98373_PCM_SR_SET1_SR_MASK,
		sampling_rate);
	regmap_update_bits(max98373->regmap,
		MAX98373_R2028_PCM_SR_SETUP_2,
		MAX98373_PCM_SR_SET2_SR_MASK,
		sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT);

	/* set sampling rate of IV */
	if (max98373->interleave_mode &&
	    sampling_rate > MAX98373_PCM_SR_SET1_SR_16000)
		regmap_update_bits(max98373->regmap,
			MAX98373_R2028_PCM_SR_SETUP_2,
			MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
			sampling_rate - 3);
	else
		regmap_update_bits(max98373->regmap,
			MAX98373_R2028_PCM_SR_SETUP_2,
			MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
			sampling_rate);

	return max98373_set_clock(component, params);
err:
	return -EINVAL;
}
Example #25
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;
}
Example #26
0
static ALCboolean qsa_reset_playback(ALCdevice* device)
{
    qsa_data* data=(qsa_data*)device->ExtraData;
    int32_t format=-1;

    switch(device->FmtType)
    {
        case DevFmtByte:
             format=SND_PCM_SFMT_S8;
             break;
        case DevFmtUByte:
             format=SND_PCM_SFMT_U8;
             break;
        case DevFmtShort:
             format=SND_PCM_SFMT_S16_LE;
             break;
        case DevFmtUShort:
             format=SND_PCM_SFMT_U16_LE;
             break;
        case DevFmtInt:
             format=SND_PCM_SFMT_S32_LE;
             break;
        case DevFmtUInt:
             format=SND_PCM_SFMT_U32_LE;
             break;
        case DevFmtFloat:
             format=SND_PCM_SFMT_FLOAT_LE;
             break;
    }

    /* we actually don't want to block on writes */
    snd_pcm_nonblock_mode(data->pcmHandle, 1);
    /* Disable mmap to control data transfer to the audio device */
    snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
    snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS);

    // configure a sound channel
    memset(&data->cparams, 0, sizeof(data->cparams));
    data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK;
    data->cparams.mode=SND_PCM_MODE_BLOCK;
    data->cparams.start_mode=SND_PCM_START_FULL;
    data->cparams.stop_mode=SND_PCM_STOP_STOP;

    data->cparams.buf.block.frag_size=device->UpdateSize*
        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
    data->cparams.buf.block.frags_max=device->NumUpdates;
    data->cparams.buf.block.frags_min=device->NumUpdates;

    data->cparams.format.interleave=1;
    data->cparams.format.rate=device->Frequency;
    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
    data->cparams.format.format=format;

    if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
    {
        int original_rate=data->cparams.format.rate;
        int original_voices=data->cparams.format.voices;
        int original_format=data->cparams.format.format;
        int it;
        int jt;

        for (it=0; it<1; it++)
        {
            /* Check for second pass */
            if (it==1)
            {
                original_rate=ratelist[0].rate;
                original_voices=channellist[0].channels;
                original_format=formatlist[0].format;
            }

            do {
                /* At first downgrade sample format */
                jt=0;
                do {
                    if (formatlist[jt].format==data->cparams.format.format)
                    {
                        data->cparams.format.format=formatlist[jt+1].format;
                        break;
                    }
                    if (formatlist[jt].format==0)
                    {
                        data->cparams.format.format=0;
                        break;
                    }
                    jt++;
                } while(1);

                if (data->cparams.format.format==0)
                {
                    data->cparams.format.format=original_format;

                    /* At secod downgrade sample rate */
                    jt=0;
                    do {
                        if (ratelist[jt].rate==data->cparams.format.rate)
                        {
                            data->cparams.format.rate=ratelist[jt+1].rate;
                            break;
                        }
                        if (ratelist[jt].rate==0)
                        {
                            data->cparams.format.rate=0;
                            break;
                        }
                        jt++;
                    } while(1);

                    if (data->cparams.format.rate==0)
                    {
                        data->cparams.format.rate=original_rate;
                        data->cparams.format.format=original_format;

                        /* At third downgrade channels number */
                        jt=0;
                        do {
                            if(channellist[jt].channels==data->cparams.format.voices)
                            {
                                data->cparams.format.voices=channellist[jt+1].channels;
                                break;
                            }
                            if (channellist[jt].channels==0)
                            {
                                data->cparams.format.voices=0;
                                break;
                            }
                           jt++;
                        } while(1);
                    }

                    if (data->cparams.format.voices==0)
                    {
                        break;
                    }
                }

                data->cparams.buf.block.frag_size=device->UpdateSize*
                    data->cparams.format.voices*
                    snd_pcm_format_width(data->cparams.format.format)/8;
                data->cparams.buf.block.frags_max=device->NumUpdates;
                data->cparams.buf.block.frags_min=device->NumUpdates;
                if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
                {
                    continue;
                }
                else
                {
                    break;
                }
            } while(1);

            if (data->cparams.format.voices!=0)
            {
                break;
            }
        }

        if (data->cparams.format.voices==0)
        {
            return ALC_FALSE;
        }
    }

    if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
    {
        return ALC_FALSE;
    }

    memset(&data->csetup, 0, sizeof(data->csetup));
    data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK;
    if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0)
    {
        return ALC_FALSE;
    }

    /* now fill back to the our AL device */
    device->Frequency=data->cparams.format.rate;

    switch (data->cparams.format.voices)
    {
        case 1:
             device->FmtChans=DevFmtMono;
             break;
        case 2:
             device->FmtChans=DevFmtStereo;
             break;
        case 4:
             device->FmtChans=DevFmtQuad;
             break;
        case 6:
             device->FmtChans=DevFmtX51;
             break;
        case 7:
             device->FmtChans=DevFmtX61;
             break;
        case 8:
             device->FmtChans=DevFmtX71;
             break;
        default:
             device->FmtChans=DevFmtMono;
             break;
    }

    switch (data->cparams.format.format)
    {
        case SND_PCM_SFMT_S8:
             device->FmtType=DevFmtByte;
             break;
        case SND_PCM_SFMT_U8:
             device->FmtType=DevFmtUByte;
             break;
        case SND_PCM_SFMT_S16_LE:
             device->FmtType=DevFmtShort;
             break;
        case SND_PCM_SFMT_U16_LE:
             device->FmtType=DevFmtUShort;
             break;
        case SND_PCM_SFMT_S32_LE:
             device->FmtType=DevFmtInt;
             break;
        case SND_PCM_SFMT_U32_LE:
             device->FmtType=DevFmtUInt;
             break;
        case SND_PCM_SFMT_FLOAT_LE:
             device->FmtType=DevFmtFloat;
             break;
        default:
             device->FmtType=DevFmtShort;
             break;
    }

    SetDefaultChannelOrder(device);

    device->UpdateSize=data->csetup.buf.block.frag_size/
        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
    device->NumUpdates=data->csetup.buf.block.frags;

    data->size=data->csetup.buf.block.frag_size;
    data->buffer=malloc(data->size);
    if (!data->buffer)
    {
        return ALC_FALSE;
    }

    return ALC_TRUE;
}
Example #27
0
static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int rval;
	int format;
	Uint16 test_format;
	int twidth;
	int found;

#ifdef DEBUG_AUDIO
		fprintf(stderr, "NTO_OpenAudio\n");
#endif
	
	audio_handle = NULL;
	 this->enabled = 0;

	if ( pcm_buf != NULL ) {
		free((Uint8 *)pcm_buf); 
		pcm_buf = NULL;
	}
	 
	/* initialize channel transfer parameters to default */
	init_pcm_cparams(&cparams);

	/* Open the audio device */
	
	rval = snd_pcm_open_preferred(&audio_handle, &card_no, &device_no, OPEN_FLAGS);
	if ( rval < 0 ) {
		SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval));
		return(-1);
	}

    /* set to nonblocking mode */
    if ((rval = snd_pcm_nonblock_mode(audio_handle, 1))<0) //I assume 1 means on
    {
        SDL_SetError("snd_pcm_nonblock_mode failed: %s\n", snd_strerror(rval));
        return(-1);
    }

    /* enable count status parameter */
    if ((rval = snd_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0)
    {
        SDL_SetError("snd_plugin_set_disable failed: %s\n", snd_strerror(rval));
        return(-1);
    }


	/* Try for a closest match on audio format */
	format = 0;
 	found = 0; // can't use format as SND_PCM_SFMT_U8 = 0 in nto
	for ( test_format = SDL_FirstAudioFormat(spec->format);	!found ; ) 

	{
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples);
#endif
			/* if match found set format to equivalent ALSA format */
        switch ( test_format ) {
			case AUDIO_U8:
				format = SND_PCM_SFMT_U8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S8:
				format = SND_PCM_SFMT_S8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S16LSB:
				format = SND_PCM_SFMT_S16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_S16MSB:
				format = SND_PCM_SFMT_S16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16LSB:
				format = SND_PCM_SFMT_U16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16MSB:
				format = SND_PCM_SFMT_U16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			default:
				break;
		}
		if ( ! found ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	
	/* assumes test_format not 0 on success */
	if ( test_format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	
	spec->format = test_format;

	/* Set the audio format */
	cparams.format.format = format;

	/* Set mono or stereo audio (currently only two channels supported) */
	cparams.format.voices = spec->channels;
	
#ifdef DEBUG_AUDIO
	fprintf(stderr,"intializing channels %d\n", cparams.format.voices);
#endif

	
	/* Set rate */
	cparams.format.rate = spec->freq ;

	/* Setup the transfer parameters according to cparams */
	rval = snd_pcm_plugin_params(audio_handle, &cparams);
	if (rval < 0) {
		SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval));
		return(-1);
	}

    /*  Make sure channel is setup right one last time */
    memset( &csetup, 0, sizeof( csetup ) );
    csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 )
    {
        SDL_SetError("Unable to setup playback channel\n" );
        return(-1);
    }
    else
    {
#ifdef DEBUG_AUDIO
        fprintf(stderr,"requested format: %d\n",cparams.format.format);
        fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size);
        fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max);

        fprintf(stderr,"real format: %d\n", csetup.format.format );
        fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size );
		fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max );
#endif // DEBUG_AUDIO
    }


    /*  Allocate memory to the audio buffer and initialize with silence
        (Note that buffer size must be a multiple of fragment size, so find closest multiple)
    */
    
    twidth = snd_pcm_format_width(format);
    if (twidth < 0) {
        printf("snd_pcm_format_width failed\n");
        twidth = 0;
    }
    
#ifdef DEBUG_AUDIO
    fprintf(stderr,"format is %d bits wide\n",twidth);
#endif      
    
    pcm_len = spec->size ;
    
  
#ifdef DEBUG_AUDIO    
    fprintf(stderr,"pcm_len set to %d\n", pcm_len);
#endif
    
    if (pcm_len == 0)
    {
        pcm_len = csetup.buf.block.frag_size;
    }
    
    pcm_buf = (Uint8*)malloc(pcm_len);
    if (pcm_buf == NULL) {
        SDL_SetError("pcm_buf malloc failed\n");
        return(-1);
    }
    memset(pcm_buf,spec->silence,pcm_len);

#ifdef DEBUG_AUDIO
	fprintf(stderr,"pcm_buf malloced and silenced.\n");
#endif

    /* get the file descriptor */
    if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
       fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd);
    }

	/* Trigger audio playback */
	rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK);
	if (rval < 0) {
       SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval));
       return(-1);
	}
	
	 this->enabled = 1;
	 
	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Example #28
0
static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct gus_pcm_private *pcmp = runtime->private_data;
	struct snd_gus_card * gus = pcmp->gus;
	unsigned long flags;
	unsigned char voice_ctrl, ramp_ctrl;
	unsigned short rate;
	unsigned int curr, begin, end;
	unsigned short vol;
	unsigned char pan;
	unsigned int voice;

	spin_lock_irqsave(&pcmp->lock, flags);
	if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
		spin_unlock_irqrestore(&pcmp->lock, flags);
		return;
	}
	pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE;
	pcmp->final_volume = 0;
	spin_unlock_irqrestore(&pcmp->lock, flags);
	rate = snd_gf1_translate_freq(gus, runtime->rate << 4);
	/* enable WAVE IRQ */
	voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20;
	/* enable RAMP IRQ + rollover */
	ramp_ctrl = 0x24;
	if (pcmp->blocks == 1) {
		voice_ctrl |= 0x08;	/* loop enable */
		ramp_ctrl &= ~0x04;	/* disable rollover */
	}
	for (voice = 0; voice < pcmp->voices; voice++) {
		begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels);
		curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels;
		end = curr + (pcmp->block_size / runtime->channels);
		end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1;
		/*
		snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, "
			   "ctrl=0x%x, ramp=0x%x, rate=0x%x\n",
			   curr, begin, end, voice_ctrl, ramp_ctrl, rate);
		*/
		pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8;
		vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
		spin_lock_irqsave(&gus->reg_lock, flags);
		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
		snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan);
		snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4);
		snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
		if (!gus->gf1.enh_mode) {
			snd_gf1_delay(gus);
			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
		}
		spin_unlock_irqrestore(&gus->reg_lock, flags);
	}
	spin_lock_irqsave(&gus->reg_lock, flags);
	for (voice = 0; voice < pcmp->voices; voice++) {
		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
		if (gus->gf1.enh_mode)
			snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00);	/* deactivate voice */
		snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
		voice_ctrl &= ~0x20;
	}
	voice_ctrl |= 0x20;
	if (!gus->gf1.enh_mode) {
		snd_gf1_delay(gus);
		for (voice = 0; voice < pcmp->voices; voice++) {
			snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
			snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
			voice_ctrl &= ~0x20;	/* disable IRQ for next voice */
		}
	}
	spin_unlock_irqrestore(&gus->reg_lock, flags);
}
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 *arizona = priv->arizona;
	int base = dai->driver->base;
	const int *rates;
	int i, ret, val;
	int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
	int bclk, lrclk, wl, frame, bclk_target;

	if (params_rate(params) % 8000)
		rates = &arizona_44k1_bclk_rates[0];
	else
		rates = &arizona_48k_bclk_rates[0];

	bclk_target = snd_soc_params_to_bclk(params);
	if (chan_limit && chan_limit < params_channels(params)) {
		arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
		bclk_target /= params_channels(params);
		bclk_target *= chan_limit;
	}

	/* Force stereo for I2S mode */
	val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
	if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
		arizona_aif_dbg(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;
	}

	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;

	ret = arizona_hw_params_rate(substream, params, dai);
	if (ret != 0)
		return ret;

	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);

	return 0;
}
Example #30
0
/*
 *  set sampling rate according to the substream
 */
static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
{
	struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
	struct snd_ps3_avsetting_info avs;
	int ret;

	avs = card->avs;

	pr_debug("%s: called freq=%d width=%d\n", __func__,
		 substream->runtime->rate,
		 snd_pcm_format_width(substream->runtime->format));

	pr_debug("%s: before freq=%d width=%d\n", __func__,
		 card->avs.avs_audio_rate, card->avs.avs_audio_width);

	/* sample rate */
	switch (substream->runtime->rate) {
	case 44100:
		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_44K;
		break;
	case 48000:
		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K;
		break;
	case 88200:
		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_88K;
		break;
	case 96000:
		avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_96K;
		break;
	default:
		pr_info("%s: invalid rate %d\n", __func__,
			substream->runtime->rate);
		return 1;
	}

	/* width */
	switch (snd_pcm_format_width(substream->runtime->format)) {
	case 16:
		avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
		break;
	case 24:
		avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_24;
		break;
	default:
		pr_info("%s: invalid width %d\n", __func__,
			snd_pcm_format_width(substream->runtime->format));
		return 1;
	}

	memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8);

	if (memcmp(&card->avs, &avs, sizeof(avs))) {
		pr_debug("%s: after freq=%d width=%d\n", __func__,
			 card->avs.avs_audio_rate, card->avs.avs_audio_width);

		card->avs = avs;
		snd_ps3_change_avsetting(card);
		ret = 0;
	} else
		ret = 1;

	/* check CS non-audio bit and mute accordingly */
	if (avs.avs_cs_info[0] & 0x02)
		ps3av_audio_mute_analog(1); /* mute if non-audio */
	else
		ps3av_audio_mute_analog(0);

	return ret;
}