예제 #1
0
파일: board-osk.c 프로젝트: ForayJones/iods
	.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, */
};
예제 #2
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_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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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);
}
예제 #6
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, */
예제 #7
0
/*
 * 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);
}
예제 #8
0
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;
	}
예제 #9
0
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;
}