.num_resources = ARRAY_SIZE(osk5912_cf_resources), .resource = osk5912_cf_resources, }; #define DEFAULT_BITPERSAMPLE 16 static struct omap_mcbsp_reg_cfg mcbsp_regs = { .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), .spcr1 = RINTM(3) | RRST, .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0), .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16), .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) | XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG, .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16), .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1), .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1), /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */ }; static struct omap_alsa_codec_config alsa_config = { .name = "OSK AIC23", .mcbsp_regs_alsa = &mcbsp_regs, .codec_configure_dev = NULL, /* aic23_configure, */ .codec_set_samplerate = NULL, /* aic23_set_samplerate, */ .codec_clock_setup = NULL, /* aic23_clock_setup, */ .codec_clock_on = NULL, /* aic23_clock_on, */ .codec_clock_off = NULL, /* aic23_clock_off, */ .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */ };
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; unsigned long port; unsigned int format, div, framesize, master; dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream); port = omap_mcbsp_dma_reg_params(bus_id, substream->stream); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: return -EINVAL; } if (cpu_is_omap34xx() || cpu_is_omap44xx()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = omap_mcbsp_get_max_tx_threshold( mcbsp_data->bus_id); else max_thrsh = omap_mcbsp_get_max_rx_threshold( mcbsp_data->bus_id); /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: * McBSP threshold = sDMA frame size = period_size * Otherwise we switch to sDMA packet mode: * McBSP threshold = sDMA packet size * sDMA frame size = period size */ if (period_words > max_thrsh) { int divider = 0; /* * Look for the biggest threshold value, which * divides the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; sync_mode = OMAP_DMA_SYNC_PACKET; } else { sync_mode = OMAP_DMA_SYNC_FRAME; } } } dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; dma_data->dma_req = dma; dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); if (mcbsp_data->configured) { /* McBSP already configured by another stream */ return 0; } regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7)); regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { /* 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); } regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ 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); break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); break; default: /* Unsupported PCM format */ return -EINVAL; } /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; framesize = (mcbsp_data->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " "channels\n", __func__); return -EINVAL; } } else framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ regs->srgr2 &= ~FPER(0xfff); regs->srgr1 &= ~FWID(0xff); switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } omap_mcbsp_config(bus_id, &mcbsp_data->regs); mcbsp_data->wlen = wlen; mcbsp_data->configured = 1; 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 omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; struct omap_pcm_dma_data *dma_data; int wlen, channels, wpf; int pkt_size = 0; unsigned int format, div, framesize, master; dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: wlen = 32; break; default: return -EINVAL; } if (mcbsp->pdata->buffer_size) { dma_data->set_threshold = omap_mcbsp_set_threshold; if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; int divider = 0; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = mcbsp->max_tx_thres; else max_thrsh = mcbsp->max_rx_thres; /* * Use sDMA packet mode if McBSP is in threshold mode: * If period words less than the FIFO size the packet * size is set to the number of period words, otherwise * Look for the biggest threshold value which divides * the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; } } dma_data->packet_size = pkt_size; if (mcbsp->configured) { /* McBSP already configured by another stream */ return 0; } regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7)); regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels; if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { /* 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); } regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ 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); break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); break; default: /* Unsupported PCM format */ return -EINVAL; } /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { div = mcbsp->clk_div ? mcbsp->clk_div : 1; framesize = (mcbsp->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " "channels\n", __func__); return -EINVAL; } } else framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ regs->srgr2 &= ~FPER(0xfff); regs->srgr1 &= ~FWID(0xff); switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs); mcbsp->wlen = wlen; mcbsp->configured = 1; return 0; }
static void omap1610_set_samplerate(long val) { int divisor = 0; int fs_44kHz = 0; /* We don't want to mess with clocks when frames are in flight */ /* TODO - could call omap1510_dma_flush_all, or could poll on enable bit to wait for DMA writes to stop. */ /* wait for any frame to complete */ udelay(125); DPRINTK(__FUNCTION__ " %d\n", val); /* * We have the following clock sources: * 12.000 MHz * * Available sampling rates: * 48kHz, 44.1kHz, 32kHz, 29.4kHz, 24kHz, * 22 kHz, 16 kHz, 14.7kHz, 12kHz, 11kHz, * 9.6kHz, 8.8kHz, 8kHz, (7.3kHz) * Won't bother supporting those in (). */ if (val >= 48000) { val = 48000; fs_44kHz=0; divisor=0; /* division to 1 */ } else if (val >= 44100) { val = 44100; fs_44kHz=1; divisor=0; /* division to 1 */ } else if (val >= 32000) { val = 32000; fs_44kHz=0; divisor=1; /* division to 1.5 */ } else if (val >= 29400) { val = 29400; fs_44kHz=1; divisor=1; /* division to 1.5 */ } else if (val >= 24000) { val = 24000; fs_44kHz=0; divisor=2; /* division to 2 */ } else if (val >= 22050) { val = 22050; fs_44kHz=1; divisor=2; /* division to 2 */ } else if (val >= 16000) { val = 16000; fs_44kHz=0; divisor=3; /* division to 3 */ } else if (val >= 14700) { val = 14700; fs_44kHz=1; divisor=3; /* division to 3 */ } else if (val >= 12000) { val = 12000; fs_44kHz=0; divisor=4; /* division to 4 */ } else if (val >= 11025) { val = 11025; fs_44kHz=1; divisor=4; /* division to 4 */ } else if (val >= 9600) { val = 9600; fs_44kHz=0; divisor=5; /* division to 5 */ } else if (val >= 8820) { val = 8820; fs_44kHz=1; divisor=5; /* division to 5 */ } else if( val >= 8000) { val = 8000; fs_44kHz=0; divisor=7; /* division to 6 */ } else { val = 7350; fs_44kHz=1; divisor=7; /* division to 6 */ } omap1610_tsc2101_write(TSC2101_AUDIO_CTRL_3, (fs_44kHz<<13)|(1<<11)); omap1610_tsc2101_write(TSC2101_AUDIO_CTRL_1, (divisor<<3)|divisor); if(fs_44kHz) { /* pll enable, P, J */ omap1610_tsc2101_write(TSC2101_PLL_PROG_1, (1<<15)|(1<<8)|(7<<2)); /* D (NB: in decimal!) */ omap1610_tsc2101_write(TSC2101_PLL_PROG_2, 5264<<2); } else { omap1610_tsc2101_write(TSC2101_PLL_PROG_1, (1<<15)|(1<<8)|(8<<2)); omap1610_tsc2101_write(TSC2101_PLL_PROG_2, 1920<<2); } #ifdef MCBSP_I2S_MASTER /* Set Sample Rate at McBSP Formula : Codec System Clock = CODEC_CLOCK, or half if clock_divider = 1; clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1); FWID = BitsPerSample - 1; FPER = (BitsPerSample * 2) - 1; */ { int clkgdv=0; outw((FWID(15) | CLKGDV(clkgdv)), AUDIO_SRGR1); outw((GSYNC | CLKSP | FSGM | FPER(31)), AUDIO_SRGR2); } #endif audio_samplerate = val; FN_OUT(0); }
.chip_select = 1, .max_speed_hz = 16000000, .platform_data = &h2_tsc2101_platform_data, }, }; static struct omap_mcbsp_reg_cfg mcbsp_regs = { .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), .spcr1 = RINTM(3) | RRST, .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1), .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16), .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) | XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG, .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16), .srgr1 = FWID(15), .srgr2 = GSYNC | CLKSP | FSGM | FPER(31), .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP, /*.pcr0 = CLKXP | CLKRP,*/ /* mcbsp: slave */ }; static struct omap_alsa_codec_config alsa_config = { .name = "H2 TSC2101", .mcbsp_regs_alsa = &mcbsp_regs, .codec_configure_dev = NULL, /* tsc2101_configure, */ .codec_set_samplerate = NULL, /* tsc2101_set_samplerate, */ .codec_clock_setup = NULL, /* tsc2101_clock_setup, */ .codec_clock_on = NULL, /* tsc2101_clock_on, */ .codec_clock_off = NULL, /* tsc2101_clock_off, */ .get_default_samplerate = NULL, /* tsc2101_get_default_samplerate, */
/* * Sample rate changing */ void tsc2101_set_samplerate(long sample_rate) { u8 count = 0; u16 data = 0; int clkgdv = 0; u16 srgr1, srgr2; /* wait for any frame to complete */ udelay(125); ADEBUG(); sample_rate = sample_rate; /* Search for the right sample rate */ while ((rate_reg_info[count].sample_rate != sample_rate) && (count < NUMBER_SAMPLE_RATES_SUPPORTED)) { count++; } if (count == NUMBER_SAMPLE_RATES_SUPPORTED) { printk(KERN_ERR "Invalid Sample Rate %d requested\n", (int) sample_rate); return; // -EPERM; } /* Set AC1 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1); /* Clear prev settings */ data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07)); data |= AC1_DACFS(rate_reg_info[count].divisor) | AC1_ADCFS(rate_reg_info[count].divisor); tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data); /* Set the AC3 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3); /*Clear prev settings */ data &= ~(AC3_REFFS | AC3_SLVMS); data |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0; #ifdef TSC_MASTER data |= AC3_SLVMS; #endif /* #ifdef TSC_MASTER */ tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data); /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use. * If MCLK rate is something else, these values must be changed. * See the tsc2101 specification for the details. */ if (rate_reg_info[count].fs_44kHz) { /* samplerate = (44.1kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */ } else { /* samplerate = (48.kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */ } /* Set the sample rate */ #ifndef TSC_MASTER clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1)); if (clkgdv) srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); else return (1); /* Stereo Mode */ srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)); #else srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1))); #endif /* end of #ifdef TSC_MASTER */ OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2); OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1); }
void omap2_mcbsp_set_srg_cfg_param(unsigned int id, int interface_mode, struct omap_mcbsp_reg_cfg *mcbsp_cfg, struct omap_mcbsp_srg_fsg_cfg *param) { struct omap_mcbsp *mcbsp = mcbsp_ptr[id]; void __iomem *io_base; u32 clk_rate, clkgdv; io_base = mcbsp->io_base; mcbsp->interface_mode = interface_mode; mcbsp_cfg->srgr1 = FWID(param->pulse_width); if (interface_mode == OMAP_MCBSP_MASTER) { clk_rate = clk_get_rate(mcbsp->fclk); clkgdv = clk_rate / (param->sample_rate * (param->bits_per_sample - 1)); if (clkgdv > 0xFF) clkgdv = 0xFF; mcbsp_cfg->srgr1 = mcbsp_cfg->srgr1 | CLKGDV(clkgdv); } if (param->dlb) mcbsp_cfg->spcr1 = mcbsp_cfg->spcr1 & ~(ALB); if (param->sync_mode == OMAP_MCBSP_SRG_FREERUNNING) mcbsp_cfg->spcr2 = mcbsp_cfg->spcr2 | FREE; mcbsp_cfg->srgr2 = FPER(param->period)|(param->fsgm? FSGM : 0); switch (param->srg_src) { case OMAP_MCBSP_SRGCLKSRC_CLKS: mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(SCLKME); mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(CLKSM); /* * McBSP master operation at low voltage is only possible if * CLKSP=0 In Master mode, if client driver tries to configiure * input clock polarity as falling edge, we force it to Rising */ if ((param->polarity == OMAP_MCBSP_CLKS_POLARITY_RISING) || (interface_mode == OMAP_MCBSP_MASTER)) mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(CLKSP); else mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (CLKSP); break; case OMAP_MCBSP_SRGCLKSRC_FCLK: mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(SCLKME); mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (CLKSM); break; case OMAP_MCBSP_SRGCLKSRC_CLKR: mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | (SCLKME); mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(CLKSM); if (param->polarity == OMAP_MCBSP_CLKR_POLARITY_FALLING) mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(CLKRP); else mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | (CLKRP); break; case OMAP_MCBSP_SRGCLKSRC_CLKX: mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | (SCLKME); mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (CLKSM); if (param->polarity == OMAP_MCBSP_CLKX_POLARITY_RISING) mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(CLKXP); else mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | (CLKXP); break; } if (param->sync_mode == OMAP_MCBSP_SRG_FREERUNNING) mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(GSYNC); else if (param->sync_mode == OMAP_MCBSP_SRG_RUNNING) mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (GSYNC); mcbsp_cfg->xccr = OMAP_MCBSP_READ(mcbsp, XCCR) & ~(XDISABLE); if (param->dlb) mcbsp_cfg->xccr = mcbsp_cfg->xccr | (DILB); mcbsp_cfg->rccr = OMAP_MCBSP_READ(mcbsp, RCCR) & ~(RDISABLE); return; }
int davinci_set_samplerate(long sample_rate) { u8 count = 0; u8 j_val = 0; u16 d_val = 0; /* wait for any frame to complete */ udelay(125); /* Search for the right sample rate */ while ((reg_info[count].sample_rate != sample_rate) && (count < NUMBER_SAMPLE_RATES_SUPPORTED)) { count++; } if (count == NUMBER_SAMPLE_RATES_SUPPORTED) { DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } /* CODEC DATAPATH SETUP */ /* Fsref to 48kHz, dual rate mode upto 96kHz */ if (reg_info[count].Fsref == 96000) audio_aic33_write(REGISTER_ADDR7, FS_REF_DEFAULT_48 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz, dual rate mode upto 88.2kHz */ else if (reg_info[count].Fsref == 88200) audio_aic33_write(REGISTER_ADDR7, FS_REF_44_1 | ADC_DUAL_RATE_MODE | DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 48kHz */ else if (reg_info[count].Fsref == 48000) audio_aic33_write(REGISTER_ADDR7, FS_REF_DEFAULT_48 | LDAC_LCHAN | RDAC_RCHAN); /* Fsref to 44.1kHz */ else if (reg_info[count].Fsref == 44100) audio_aic33_write(REGISTER_ADDR7, FS_REF_44_1 | LDAC_LCHAN | RDAC_RCHAN); /* Codec sample rate select */ audio_aic33_write(REGISTER_ADDR2, reg_info[count].data); /* If PLL is to be used for generation of Fsref Generate the Fsref using the PLL */ /*Enable the PLL | Q-value | P-value */ audio_aic33_write(REGISTER_ADDR3, PLL_ENABLE | 0x10 | 0x02); if ((reg_info[count].Fsref == 96000) || (reg_info[count].Fsref == 48000)) { /* * For MCLK = 22.5792 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 8.7075, which results in J = 8, * D = 7075 * * For MCLK = 27 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 7.2818, which results in J = 7, * D = 2818 * * For MCLK = 33.8688 MHz and to get Fsref = 48kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R= 1, K = 5.8049, which results in J = 5, * D = 8049 */ switch (aic33_mclk) { case MCLK_22: j_val = 8; d_val = 7075; break; case MCLK_27: j_val = 7; d_val = 2818; break; case MCLK_33: j_val = 5; d_val = 8049; break; default: printk(KERN_ERR "unknown audio codec frequency \n"); } } else if ((reg_info[count].Fsref == 88200) || (reg_info[count].Fsref == 44100)) { /* * MCLK = 22.5792 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 8.0000, which results in J = 8, * D = 0000 * * MCLK = 27 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 6.6901, which results in J = 6, * D = 6901 * * MCLK = 33.8688 MHz and to get Fsref = 44.1kHz * Fsref = (MCLK * k * R)/(2048 * p); * Select P = 2, R =1, K = 5.3333, which results in J = 5, * D = 3333 */ switch (aic33_mclk) { case MCLK_22: j_val = 8; d_val = 0; break; case MCLK_27: j_val = 6; d_val = 6901; break; case MCLK_33: j_val = 5; d_val = 3333; break; default: printk(KERN_ERR "unknown audio codec frequency \n"); } } /* J-value */ audio_aic33_write(REGISTER_ADDR4, j_val << 2); /* D-value 8-MSB's */ audio_aic33_write(REGISTER_ADDR5, (unsigned char)(d_val >> 6)); /* D-value 6-LSB's */ audio_aic33_write(REGISTER_ADDR6, (unsigned char)(d_val << 2)); audio_samplerate = sample_rate; #ifndef AIC33_MASTER { int clkgdv = 0; unsigned long clkval = 0; struct clk *mbspclk; /* Set Sample Rate at McBSP Formula : Codec System Clock = Input clock to McBSP; clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1); FWID = BitsPerSample - 1; FPER = (BitsPerSample * 2) - 1; */ mbspclk = davinci_mcbsp_get_clock(); if (mbspclk == NULL) { DPRINTK(" Failed to get internal clock to MCBSP"); return -EPERM; } clkval = clk_get_rate(mbspclk); DPRINTK("mcbsp_clk = %ld\n", clkval); if (clkval) clkgdv = (clkval / (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1; else { DPRINTK(" Failed to get the MCBSP clock\n"); return -EPERM; } DPRINTK("clkgdv = %d\n", clkgdv); if (clkgdv > 255 || clkgdv < 0) { /* For requested sampling rate, the input clock to MCBSP cant be devided down to get the in range clock divider value for 16 bits sample */ DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate); return -EPERM; } initial_config.srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); initial_config.srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)); davinci_mcbsp_stop_tx(AUDIO_MCBSP); davinci_mcbsp_stop_rx(AUDIO_MCBSP); davinci_mcbsp_config(AUDIO_MCBSP, &initial_config); } #endif /* AIC33_MASTER */ return 0; }