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; }
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; }
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; }
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; }
/** * 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; }
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; }
/** * 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; }
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; }
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); }
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(¶ms); 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); }
/** * 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; }
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; }
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; }
/* 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); }
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; }
/* 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; }
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; }
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; }
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; }
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; }
static int pcm512x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); int alen; int gpio; int clock_output; int master_mode; int ret; dev_dbg(codec->dev, "hw_params %u Hz, %u channels\n", params_rate(params), params_channels(params)); switch (snd_pcm_format_width(params_format(params))) { case 16: alen = PCM512x_ALEN_16; break; case 20: alen = PCM512x_ALEN_20; break; case 24: alen = PCM512x_ALEN_24; break; case 32: alen = PCM512x_ALEN_32; break; default: dev_err(codec->dev, "Bad frame size: %d\n", snd_pcm_format_width(params_format(params))); return -EINVAL; } switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable slave mode: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_DCAS, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock divider autoset: %d\n", ret); return ret; } return 0; case SND_SOC_DAIFMT_CBM_CFM: clock_output = PCM512x_BCKO | PCM512x_LRKO; master_mode = PCM512x_RLRK | PCM512x_RBCK; break; case SND_SOC_DAIFMT_CBM_CFS: clock_output = PCM512x_BCKO; master_mode = PCM512x_RBCK; break; default: return -EINVAL; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1, PCM512x_ALEN, alen); if (ret != 0) { dev_err(codec->dev, "Failed to set frame size: %d\n", ret); return ret; } if (pcm512x->pll_out) { ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_A: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_B: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } } else { ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS | PCM512x_IPLK); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, 0); if (ret != 0) { dev_err(codec->dev, "Failed to disable pll: %d\n", ret); return ret; } } ret = pcm512x_set_dividers(dai, params); if (ret != 0) return ret; if (pcm512x->pll_out) { ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF, PCM512x_SREF, PCM512x_SREF_GPIO); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio as pllref: %d\n", ret); return ret; } gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN, PCM512x_GREF, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio %d as pllin: %d\n", pcm512x->pll_in, ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, PCM512x_PLLE); if (ret != 0) { dev_err(codec->dev, "Failed to enable pll: %d\n", ret); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, clock_output); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock output: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE, PCM512x_RLRK | PCM512x_RBCK, master_mode); if (ret != 0) { dev_err(codec->dev, "Failed to enable master mode: %d\n", ret); return ret; } if (pcm512x->pll_out) { gpio = PCM512x_G1OE << (pcm512x->pll_out - 1); ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, gpio, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to enable gpio %d: %d\n", pcm512x->pll_out, ret); return ret; } gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1; ret = regmap_update_bits(pcm512x->regmap, gpio, PCM512x_GxSL, PCM512x_GxSL_PLLCK); if (ret != 0) { dev_err(codec->dev, "Failed to output pll on %d: %d\n", ret, pcm512x->pll_out); return ret; } gpio = PCM512x_G1OE << (4 - 1); ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, gpio, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to enable gpio %d: %d\n", 4, ret); return ret; } gpio = PCM512x_GPIO_OUTPUT_1 + 4 - 1; ret = regmap_update_bits(pcm512x->regmap, gpio, PCM512x_GxSL, PCM512x_GxSL_PLLLK); if (ret != 0) { dev_err(codec->dev, "Failed to output pll lock on %d: %d\n", ret, 4); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_HALT); if (ret != 0) { dev_err(codec->dev, "Failed to halt clocks: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_RESUME); if (ret != 0) { dev_err(codec->dev, "Failed to resume clocks: %d\n", ret); return ret; } return 0; }
static 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; }
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); }
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; }
/* * 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; }