static int psc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; u32 mode; dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" " periods=%i buffer_size=%i buffer_bytes=%i\n", __func__, substream, params_period_size(params), params_period_bytes(params), params_periods(params), params_buffer_size(params), params_buffer_bytes(params)); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: mode = MPC52xx_PSC_SICR_SIM_CODEC_8; break; case SNDRV_PCM_FORMAT_S16_BE: mode = MPC52xx_PSC_SICR_SIM_CODEC_16; break; case SNDRV_PCM_FORMAT_S24_BE: mode = MPC52xx_PSC_SICR_SIM_CODEC_24; break; case SNDRV_PCM_FORMAT_S32_BE: mode = MPC52xx_PSC_SICR_SIM_CODEC_32; break; default: dev_dbg(psc_dma->dev, "invalid format\n"); return -EINVAL; } out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode); return 0; }
static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_ali *codec = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ali_voice *pvoice = runtime->private_data; struct snd_ali_voice *evoice = pvoice->extra; int err; err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (err < 0) return err; /* voice management */ if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) { if (!evoice) { evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1); if (!evoice) return -ENOMEM; pvoice->extra = evoice; evoice->substream = substream; } } else { if (evoice) { snd_ali_free_voice(codec, evoice); pvoice->extra = evoice = NULL; } } return 0; }
static int s5pc1xx_12s1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai_link *dai = rtd->dai; struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); unsigned long iismod; if(g_spdif_out) return s5pc1xx_spdif_hw_params(substream, params, socdai); else s5pc1xx_spdif_power_off(); s3cdbg("Entered %s\n", __FUNCTION__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dai->cpu_dai->dma_data = i2s->dma_playback; } else { dai->cpu_dai->dma_data = i2s->dma_capture; } /* Working copies of registers */ iismod = readl(i2s->regs + S5PC1XX_IISMOD); iismod &= ~S5PC1XX_IISMOD_BLCMASK; /* Multi channel enable */ switch (params_channels(params)) { case 1: s3cdbg("s3c i2s: 1 channel\n"); break; case 2: s3cdbg("s3c i2s: 2 channel\n"); break; case 4: s3cdbg("s3c i2s: 4 channel\n"); break; case 6: s3cdbg("s3c i2s: 6 channel\n"); break; default: printk(KERN_ERR "s3c-i2s-v32: %d channels unsupported\n", params_channels(params)); return -EINVAL; } /* Set the bit rate */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= S5PC1XX_IISMOD_BLC8BIT; break; case SNDRV_PCM_FORMAT_S16_LE: iismod |= S5PC1XX_IISMOD_BLC16BIT; break; case SNDRV_PCM_FORMAT_S24_LE: iismod |= S5PC1XX_IISMOD_BLC24BIT; break; default: return -EINVAL; } writel(iismod, i2s->regs + S5PC1XX_IISMOD); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) s3cdbg("%s : IISMOD [0x%08x]\n",__FUNCTION__, readl(i2s->regs + S5PC1XX_IISMOD)); s3cdbg("s3c: params_channels %d\n", params_channels(params)); s3cdbg("s3c: params_format %d\n", params_format(params)); s3cdbg("s3c: params_subformat %d\n", params_subformat(params)); s3cdbg("s3c: params_period_size %d\n", params_period_size(params)); s3cdbg("s3c: params_period_bytes %d\n", params_period_bytes(params)); s3cdbg("s3c: params_periods %d\n", params_periods(params)); s3cdbg("s3c: params_buffer_size %d\n", params_buffer_size(params)); s3cdbg("s3c: params_buffer_bytes %d\n", params_buffer_bytes(params)); return 0; }
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; int uninitialized_var(wlen); int uninitialized_var(channels); int uninitialized_var(wpf); unsigned long uninitialized_var(port); unsigned int uninitialized_var(format); int xfer_size = 0; if (cpu_class_is_omap1()) { dma = omap1_dma_reqs[bus_id][substream->stream]; port = omap1_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap2420()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap2420_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap2430()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap2430_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; xfer_size = omap34xx_mcbsp_thresholds[bus_id] [substream->stream]; /* reset the xfer_size to the integral multiple of the buffer size. This is for DMA packet mode transfer */ if (xfer_size) { int buffer_size = params_buffer_size(params); if (xfer_size > buffer_size) { printk(KERN_DEBUG "buffer_size is %d \n", buffer_size); xfer_size = 0; } else if (params_channels(params) == 1) { /* Mono needs 16 bits DMA, no FIFO */ xfer_size = 1; } else { int temp = buffer_size / xfer_size; while (buffer_size % xfer_size) { temp++; xfer_size = buffer_size / (temp); } } } } else { return -ENODEV; } omap_mcbsp_dai_dma_params[id][substream->stream].name = substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; omap_mcbsp_dai_dma_params[id][substream->stream].xfer_size = xfer_size; cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; if (mcbsp_data->configured) { /* McBSP already configured by another stream */ return 0; } format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); if (format == SND_SOC_DAIFMT_SPDIF) { regs->xcr2 &= ~(XPHASE); regs->rcr2 &= ~(RPHASE); /* Don't care about channels number and frame length 2. Set 4 frames (frame length 1) */ regs->xcr1 |= XFRLEN1(4 - 1); regs->rcr1 |= RFRLEN1(1 - 1); } else { switch (channels) { case 2: if (format == SND_SOC_DAIFMT_I2S) { /* Use dual-phase frames */ regs->rcr2 |= RPHASE; regs->xcr2 |= XPHASE; /* Set 1 word per (McBSP) frame for phase1 and phase2 */ wpf--; regs->rcr2 |= RFRLEN2(wpf - 1); regs->xcr2 |= XFRLEN2(wpf - 1); } else if (format == SND_SOC_DAIFMT_I2S_1PHASE || format == SND_SOC_DAIFMT_DSP_A_1PHASE) { printk(KERN_DEBUG "Configure McBSP for 1 phase\n"); regs->xcr2 &= ~(XPHASE); regs->rcr2 &= ~(RPHASE); wpf--; } case 1: case 4: /* Set word per (McBSP) frame for phase1 */ regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); break; default: /* Unsupported number of channels */ return -EINVAL; } } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ wlen = 16; if (format == SND_SOC_DAIFMT_SPDIF || (channels != 1 && (format == SND_SOC_DAIFMT_I2S_1PHASE || format == SND_SOC_DAIFMT_DSP_A_1PHASE))) { regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); omap_mcbsp_dai_dma_params[id] [SNDRV_PCM_STREAM_PLAYBACK].dma_word_size = 32; omap_mcbsp_dai_dma_params[id] [SNDRV_PCM_STREAM_CAPTURE].dma_word_size = 32; } else { regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); omap_mcbsp_dai_dma_params[id] [substream->stream].dma_word_size = 16; } break; case SNDRV_PCM_FORMAT_S8: /* Set word lengths */ wlen = 8; if (format == SND_SOC_DAIFMT_SPDIF || (channels != 1 && (format == SND_SOC_DAIFMT_I2S_1PHASE || format == SND_SOC_DAIFMT_DSP_A_1PHASE))) { regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); omap_mcbsp_dai_dma_params[id] [SNDRV_PCM_STREAM_PLAYBACK].dma_word_size = 16; omap_mcbsp_dai_dma_params[id] [SNDRV_PCM_STREAM_CAPTURE].dma_word_size = 16; } else { regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_8); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_8); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_8); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_8); omap_mcbsp_dai_dma_params[id] [substream->stream].dma_word_size = 8; } break; default: /* Unsupported PCM format */ return -EINVAL; } /* Set FS period and length in terms of bit clock periods */ switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_I2S_1PHASE: regs->srgr2 |= FPER(wlen * channels - 1); regs->srgr1 |= FWID(wlen - 1); break; case SND_SOC_DAIFMT_DSP_A_1PHASE: case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(wlen * channels - 1); regs->srgr1 |= FWID(0); break; case SND_SOC_DAIFMT_SPDIF: regs->srgr2 |= FPER(4 * 32 - 1); regs->srgr1 |= FWID(0); break; } regs->xccr |= XDMAEN; regs->wken = XRDYEN; regs->rccr |= RDMAEN; omap_mcbsp_config(bus_id, &mcbsp_data->regs); if ((bus_id == 1) && (xfer_size != 0)) { printk(KERN_DEBUG "Configure McBSP TX FIFO threshold to %d\n", xfer_size); omap_mcbsp_set_tx_threshold(bus_id, xfer_size); } /* We want to be able to change stuff (like channels number) dynamically */ //mcbsp_data->configured = 1; return 0; }
static int bcm947xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct bcm947xx_runtime_data *brtd = runtime->private_data; //struct bcm947xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; bcm947xx_i2s_info_t *snd_bcm = rtd->dai->cpu_dai->private_data; unsigned long totbytes; unsigned int dma_ofs; unsigned long flags; DBG("%s %s\n", __FUNCTION__, bcm947xx_direction_str(substream)); /* RX DMA requires a data offset due to the RX status header. * Although there is a register setting to make the status header offset * zero, it doesn't seem to work with 4709. */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dma_ofs = BCM947XX_DMA_RXOFS_BYTES; } else { dma_ofs = 0; } /* Total bytes in the DMA buffer (excluding period fragement), including unused and * header bytes. */ totbytes = params_buffer_bytes(params); totbytes += params_periods(params) * (BCM947XX_DMA_DATA_BYTES_MAX - params_period_bytes(params)); /* Account for period fragment. */ if (params_buffer_bytes(params) > params_periods(params) * params_period_bytes(params)) { totbytes += dma_ofs; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); spin_lock_irqsave(&brtd->lock, flags); brtd->dma_limit = params_periods(params); //runtime->hw.periods_min; brtd->dma_period = params_period_bytes(params); /* Virtual address of our runtime buffer */ brtd->dma_start = (dma_addr_t)runtime->dma_area; brtd->dma_end = brtd->dma_start + totbytes; brtd->dma_ofs = dma_ofs; if (!(snd_bcm->in_use & ~(1 << substream->stream))) { /* Other stream not in-use (we own the settings). */ /* It's safe to set the joint settings and mark as in-use. */ bcm947xx_pcm_set_joint_duplex_settings(snd_bcm, params); snd_bcm->in_use |= (1 << substream->stream); } else if (!bcm947xx_pcm_joint_duplex_settings_equal(snd_bcm, params)) { /* Joint settings don't match; therefore, we're not in-use; bail. */ DBG("%s joint duplex settings not equal\n", __FUNCTION__); snd_pcm_set_runtime_buffer(substream, NULL); snd_bcm->in_use &= ~(1 << substream->stream); return -EBUSY; } else { /* Joint settings matched, and perhaps our first time; mark as in-use! */ snd_bcm->in_use |= (1 << substream->stream); } spin_unlock_irqrestore(&brtd->lock, flags); if (BCM947XX_PCM_DEBUG_ON) { size_t buffer_size = params_buffer_size(params); size_t buffer_bytes = params_buffer_bytes(params); size_t period_size = params_period_size(params); size_t period_bytes = params_period_bytes(params); size_t periods = params_periods(params); DBG("%s: dma_limit %d dma_ofs %d dma_addr %p dma_bytes %d dma_start %p dma_end %p\n", __FUNCTION__, brtd->dma_limit, brtd->dma_ofs, (void *)runtime->dma_addr, runtime->dma_bytes, (void *)brtd->dma_start, (void *)brtd->dma_end); DBG("%s: buffer_size %d buffer_bytes %d\n", __FUNCTION__, buffer_size, buffer_bytes); DBG("%s: period_size %d period_bytes %d periods %d\n", __FUNCTION__, period_size, period_bytes, periods); } return 0; }
static int s3c_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; unsigned long iiscon; unsigned long iismod; unsigned long iisfcon; s3cdbg("Entered %s\n", __FUNCTION__); writel((readl(S3C2410_MISCCR) & ~(7<<8))|(1<<8), S3C2410_MISCCR); /*Set I2C port to controll WM8753 codec*/ s3c2410_gpio_pullup(S3C2410_GPE15, 0); s3c2410_gpio_pullup(S3C2410_GPE14, 0); s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA); s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL); #if defined CONFIG_SND_SOC_I2S_V40 /* Configure the I2S pins in correct mode */ writel(0x0, S3C2450_GPESEL); s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK); s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); writel(readl(S3C2410_GPEUP)| 0x3ff, S3C2410_GPEUP); writel(readl(S3C2450_GPBSEL)|(0x3<<3), S3C2450_GPBSEL); writel(readl(S3C2410_GPBUP)|(0xF<<18), S3C2410_GPBUP); #elif defined CONFIG_SND_SOC_I2S_V32 /* Configure the I2S pins in correct mode */ writel(0x0, S3C2450_GPLSEL); s3c2410_gpio_cfgpin(S3C2410_GPL4, S3C2450_GPL4_I2S1_SCLK); s3c2410_gpio_cfgpin(S3C2410_GPL5, S3C2450_GPL5_I2S1_CDCLK); s3c2410_gpio_cfgpin(S3C2410_GPL6, S3C2450_GPL6_I2S1_SDI); s3c2410_gpio_cfgpin(S3C2410_GPL7, S3C2450_GPL7_I2S1_SDO); s3c2410_gpio_cfgpin(S3C2443_GPJ13, S3C2450_GPJ13_I2S1_LRCK); writel(readl(S3C2410_GPLUP)| (0xf<<4), S3C2410_GPLUP); writel(readl(S3C2443_GPJDN)| (0x3<<26), S3C2443_GPJDN); #else printk("Error: S3C2450 I2S configration \n",); #endif if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; } else { rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in; } /* Working copies of registers */ iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); iisfcon = readl(s3c24xx_i2s.regs + S3C2443_IISFIC); iiscon |= S3C_IIS0CON_TXDMACTIVE; iiscon |= S3C_IIS0CON_RXDMACTIVE; iismod &= ~S3C_IIS0MOD_CLK_MASK; iismod |= S3C_IIS0MOD_IMS_EXTERNAL_MASTER| S3C_IIS0MOD_INTERNAL_CLK; iismod &= ~S3C_IIS0MOD_MODE_MASK; iismod |= S3C_IIS0MOD_TXRXMODE; /* Multi channel enable */ iismod &= ~S3C_IIS0MOD_DCE_MASK; switch (params_channels(params)) { case 6: printk("s3c i2s: 5.1channel\n"); iismod |= S3C_IIS0MOD_DCE_SD1; iismod |= S3C_IIS0MOD_DCE_SD2; break; case 4: printk("s3c i2s: 4 channel\n"); iismod |= S3C_IIS0MOD_DCE_SD1; break; case 2: printk("s3c i2s: 2 channel\n"); break; default: printk(KERN_ERR "s3c-i2s-v40: %d channels unsupported\n", params_channels(params)); return -EINVAL; } /* Set the bit rate */ #if 0 iismod &= ~0x6000; #endif switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= S3C_IIS0MOD_8BIT; iismod &= ~S3C_IIS0MOD_BFS_MASK; iismod |= S3C_IIS0MOD_32FS; iismod &= ~S3C_IIS0MOD_FS_MASK; iismod |= S3C_IIS0MOD_384FS; break; case SNDRV_PCM_FORMAT_S16_LE: iismod &= ~S3C_IIS0MOD_FS_MASK; iismod &= ~S3C_IIS0MOD_BFS_MASK; iismod |= S3C_IIS0MOD_384FS | S3C_IIS0MOD_32FS; iismod &= ~S3C_IIS0MOD_BLC_MASK; iismod |= S3C_IIS0MOD_16BIT; break; case SNDRV_PCM_FORMAT_S24_LE: iismod &= ~S3C_IIS0MOD_FS_MASK; iismod &= ~S3C_IIS0MOD_BFS_MASK; iismod |= S3C_IIS0MOD_384FS | S3C_IIS0MOD_48FS; iismod &= ~S3C_IIS0MOD_BLC_MASK; iismod |= S3C_IIS0MOD_24BIT; break; default: return -EINVAL; } iisfcon |= S3C_IIS_TX_FLUSH; iisfcon |= S3C_IIS_RX_FLUSH; writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); iismod &= ~S3C_IIS0MOD_FM_MASK; writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); writel(iisfcon, s3c24xx_i2s.regs + S3C2443_IISFIC); /* Tx, Rx fifo flush bit clear */ iisfcon &= ~(S3C_IIS_TX_FLUSH | S3C_IIS_RX_FLUSH); writel(iisfcon, s3c24xx_i2s.regs + S3C2443_IISFIC); s3cdbg("s3c iis mode: 0x%08x\n", readl(s3c24xx_i2s.regs + S3C2410_IISMOD)); s3cdbg("s3c: params_channels %d\n", params_channels(params)); s3cdbg("s3c: params_format %d\n", params_format(params)); s3cdbg("s3c: params_subformat %d\n", params_subformat(params)); s3cdbg("s3c: params_period_size %d\n", params_period_size(params)); s3cdbg("s3c: params_period_bytes %d\n", params_period_bytes(params)); s3cdbg("s3c: params_periods %d\n", params_periods(params)); s3cdbg("s3c: params_buffer_size %d\n", params_buffer_size(params)); s3cdbg("s3c: params_buffer_bytes %d\n", params_buffer_bytes(params)); s3cdbg("s3c: params_tick_time %d\n", params_tick_time(params)); return 0; }
static int s3c_i2s_v50_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; unsigned long iiscon; unsigned long iismod; unsigned long iisfcon; s3cdbg("Entered %s\n", __FUNCTION__); s5pc1xx_i2s.master = 1; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { rtd->dai->cpu_dai->dma_data = &s5pc1xx_i2s_pcm_stereo_out; } else { rtd->dai->cpu_dai->dma_data = &s5pc1xx_i2s_pcm_stereo_in; } /* Working copies of registers */ iiscon = readl(s5pc1xx_i2s.regs + S3C64XX_IIS0CON); iismod = readl(s5pc1xx_i2s.regs + S3C64XX_IIS0MOD); iisfcon = readl(s5pc1xx_i2s.regs + S3C64XX_IIS0FIC); /* is port used by another stream */ if (!(iiscon & S3C64XX_IIS0CON_I2SACTIVE)) { /* Clear BFS field [2:1] */ iismod &= ~(0x3<<1); iismod |= S3C64XX_IIS0MOD_32FS | S3C64XX_IIS0MOD_INTERNAL_CLK; if (!s5pc1xx_i2s.master) iismod |= S3C64XX_IISMOD_SLAVE; else iismod |= S3C64XX_IIS0MOD_IMS_EXTERNAL_MASTER; } iiscon |= S3C64XX_IISCON_FTXURINTEN; iiscon |= S3C64XX_IIS0CON_TXDMACTIVE; iiscon |= S3C64XX_IIS0CON_RXDMACTIVE; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { iismod |= S3C64XX_IIS0MOD_TXMODE; iisfcon |= S3C64XX_IIS_TX_FLUSH; } else { iismod |= S3C64XX_IIS0MOD_RXMODE; iisfcon |= S3C64XX_IIS_RX_FLUSH; } /* Multi channel enable */ iismod &= ~S3C64XX_IIS0MOD_DCE_MASK; switch (params_channels(params)) { case 6: printk("s3c i2s: 5.1channel\n"); iismod |= S3C64XX_IIS0MOD_DCE_SD2; iismod |= S3C64XX_IIS0MOD_DCE_SD2; break; case 4: printk("s3c i2s: 4 channel\n"); iismod |= S3C64XX_IIS0MOD_DCE_SD2; break; case 2: printk("s3c i2s: 2 channel\n"); break; default: printk(KERN_ERR "s3c-i2s-v50: %d channels unsupported\n", params_channels(params)); return -EINVAL; } /* Set the bit rate */ iismod &= ~0x6000; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: iismod &= ~S3C64XX_IIS0MOD_FS_MASK; iismod |= S3C64XX_IIS0MOD_256FS | S3C64XX_IIS0MOD_32FS; iismod &= ~(0x3<<13); iismod |= S3C64XX_IIS0MOD_16BIT; break; case SNDRV_PCM_FORMAT_S8: iismod |= S3C64XX_IIS0MOD_8BIT; break; case SNDRV_PCM_FORMAT_S24_LE: iismod &= ~S3C64XX_IIS0MOD_FS_MASK; iismod |= S3C64XX_IIS0MOD_384FS | S3C64XX_IIS0MOD_48FS; iismod &= ~(0x3<<13); iismod |= S3C64XX_IIS0MOD_24BIT; break; default: return -EINVAL; } writel(iisfcon, s5pc1xx_i2s.regs + S3C64XX_IIS0FIC); writel(iiscon, s5pc1xx_i2s.regs + S3C64XX_IIS0CON); writel(iismod, s5pc1xx_i2s.regs + S3C64XX_IIS0MOD); // Tx, Rx fifo flush bit clear iisfcon &= ~(S3C64XX_IIS_TX_FLUSH | S3C64XX_IIS_RX_FLUSH); writel(iisfcon, s5pc1xx_i2s.regs + S3C64XX_IIS0FIC); s3cdbg("s3c iis mode: 0x%08x\n", readl(s5pc1xx_i2s.regs + S3C64XX_IIS0MOD)); s3cdbg("s3c: params_channels %d\n", params_channels(params)); s3cdbg("s3c: params_format %d\n", params_format(params)); s3cdbg("s3c: params_subformat %d\n", params_subformat(params)); s3cdbg("s3c: params_period_size %d\n", params_period_size(params)); s3cdbg("s3c: params_period_bytes %d\n", params_period_bytes(params)); s3cdbg("s3c: params_periods %d\n", params_periods(params)); s3cdbg("s3c: params_buffer_size %d\n", params_buffer_size(params)); s3cdbg("s3c: params_buffer_bytes %d\n", params_buffer_bytes(params)); // s3cdbg("s3c: params_tick_time %d\n", params_tick_time(params)); s3cdbg("hw_params: IISCON: %lx IISMOD: %lx\n", iiscon, iismod); return 0; }
static int s3c_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; u32 iismod; debug_msg("%s\n", __FUNCTION__); #ifdef CONFIG_S3C_DMA_PL080_SOL rtd->dai->cpu_dai->dma_data = s3c_i2s_dai.dma_data; #endif #ifdef CONFIG_S3C_DMA_PL080 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rtd->dai->cpu_dai->dma_data = &s3c_i2s_pcm_stereo_out; else rtd->dai->cpu_dai->dma_data = &s3c_i2s_pcm_stereo_in; #endif /* Working copies of register */ iismod = readl(s3c_i2s.regs + S3C_IISMOD); iismod &= ~S3C_IISMOD_BLCMASK; #ifdef CONFIG_S3C_DMA_PL080 /* TODO */ switch(params_channels(params)) { case 1: s3c_i2s_pcm_stereo_in.dma_size = 2; break; case 2: s3c_i2s_pcm_stereo_in.dma_size = 4; break; case 4: break; case 6: break; default: break; } #endif /* RFS & BFS are set by dai_link(machine specific) code via set_clkdiv */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= S3C_IISMOD_8BIT; break; case SNDRV_PCM_FORMAT_S16_LE: iismod |= S3C_IISMOD_16BIT; break; case SNDRV_PCM_FORMAT_S24_LE: iismod |= S3C_IISMOD_24BIT; break; default: return -EINVAL; } writel(iismod, s3c_i2s.regs + S3C_IISMOD); debug_msg("s3c iis mode: 0x%08x\n", readl(s3c6410_i2s.regs + S3C64XX_IIS0MOD)); debug_msg("s3c: params_channels %d\n", params_channels(params)); debug_msg("s3c: params_format %d\n", params_format(params)); debug_msg("s3c: params_subformat %d\n", params_subformat(params)); debug_msg("s3c: params_period_size %d\n", params_period_size(params)); debug_msg("s3c: params_period_bytes %d\n", params_period_bytes(params)); debug_msg("s3c: params_periods %d\n", params_periods(params)); debug_msg("s3c: params_buffer_size %d\n", params_buffer_size(params)); debug_msg("s3c: params_buffer_bytes %d\n", params_buffer_bytes(params)); debug_msg("hw_params: IISMOD: %x\n", iismod); return 0; }