On 7/18/08, Jon Smirl <jonsmirl@xxxxxxxxx> wrote: > The MPC5200 has three clock configurations > > 1) Clock out, normal master mode > 2) Clock in, normal slave mode > 3) Something Freescale calls cellphone slave but it is more like clock > distribution. > > In cellslave mode one i2s port is in normal slave mode. The clock from > this port is used to drive up to three other i2s ports in master mode. > > I have two choices for set_sysclk: > #define SND_SOC_CLOCK_IN 0 > #define SND_SOC_CLOCK_OUT 1 > > When the clock frequency changes I need to notify the i2s drivers for > the dependent channels. Do we need a third choice, > SND_SOC_CLOCK_SLAVE? Alternatively I can use another clock id value. I can implement it like this, in cellslave mode I just record the frequency, CLOCK_OUT not in cellslave mode needs to set up the internal MPC clock generation (which can't make accurate audio clocks). static int psc_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct psc_i2s *psc_i2s = cpu_dai->private_data; dev_dbg(psc_i2s->dev, "psc_i2s_set_sysclk(cpu_dai=%p, freq=%ui, dir=%i)\n", cpu_dai, freq, dir); switch (dir) { case SND_SOC_CLOCK_IN: return 0; case SND_SOC_CLOCK_OUT: default: if (!(psc_i2s->sicr & MPC52xx_PSC_SICR_CELLSLAVE)) { /* implement me */ /* compute and set the needed dividers for the internal clock */ return -EINVAL; } psc_i2s->sysclk = freq; return -EINVAL; } } static int psc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; u32 sicr, rate, bits, bitblk, err, wordclk; dev_dbg(psc_i2s->dev, "%s(substream=%p) p_size=%i p_bytes=%i" " periods=%i buffer_size=%i buffer_bytes=%i\n", __FUNCTION__, substream, params_period_size(params), params_period_bytes(params), params_periods(params), params_buffer_size(params), params_buffer_bytes(params)); sicr = psc_i2s->sicr; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: sicr |= MPC52xx_PSC_SICR_SIM_CODEC_8; bits = 8; break; case SNDRV_PCM_FORMAT_S16_BE: sicr |= MPC52xx_PSC_SICR_SIM_CODEC_16; bits = 16; break; case SNDRV_PCM_FORMAT_S24_BE: sicr |= MPC52xx_PSC_SICR_SIM_CODEC_24; bits = 24; break; case SNDRV_PCM_FORMAT_S32_BE: sicr |= MPC52xx_PSC_SICR_SIM_CODEC_32; bits = 32; break; default: dev_dbg(psc_i2s->dev, "invalid format\n"); return -EINVAL; } out_be32(&psc_i2s->psc_regs->sicr, sicr); if (psc_i2s->sysclk) { switch (params_rate(params)) { case SNDRV_PCM_RATE_5512: rate = 5512; break; case SNDRV_PCM_RATE_8000: rate = 8000; break; case SNDRV_PCM_RATE_11025: rate = 11025; break; case SNDRV_PCM_RATE_16000: rate = 16000; break; case SNDRV_PCM_RATE_22050: rate = 22050; break; case SNDRV_PCM_RATE_32000: rate = 32000; break; case SNDRV_PCM_RATE_44100: rate = 44100; break; case SNDRV_PCM_RATE_48000: rate = 48000; break; case SNDRV_PCM_RATE_64000: rate = 64000; break; case SNDRV_PCM_RATE_88200: rate = 88200; break; case SNDRV_PCM_RATE_96000: rate = 96000; break; case SNDRV_PCM_RATE_176400: rate = 176400; break; case SNDRV_PCM_RATE_192000: rate = 192000; break; default: dev_dbg(psc_i2s->dev, "invalid format\n"); return -EINVAL; } bitclk = psc_i2s->sysclk / rate; wordclk = bitclk / bits; out_be32(&psc_i2s->psc_regs->ccr, (bitclk - 1) << 24 | (wordclk << 16); } //rc = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); //if (rc) { // dev_err(psc_i2s->dev, "could not allocate dma buffer\n"); // return rc; //} snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; } > > > -- > Jon Smirl > jonsmirl@xxxxxxxxx > -- Jon Smirl jonsmirl@xxxxxxxxx _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel