Beispiel #1
0
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
{
	u32 ch_reg;
	struct i2s_clk_config_data *config = &dev->config;


	i2s_disable_channels(dev, stream);

	for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
			i2s_write_reg(dev->i2s_base, TCR(ch_reg),
				      dev->xfer_resolution);
			i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
				      dev->fifo_th - 1);
			i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
		} else {
			i2s_write_reg(dev->i2s_base, RCR(ch_reg),
				      dev->xfer_resolution);
			i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
				      dev->fifo_th - 1);
			i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
		}

	}
}
static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
	struct i2s_clk_config_data *config = &dev->config;
	u32 ccr, xfer_resolution, ch_reg, irq;
	int ret;

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		config->data_width = 16;
		ccr = 0x00;
		xfer_resolution = 0x02;
		break;

	case SNDRV_PCM_FORMAT_S24_LE:
		config->data_width = 24;
		ccr = 0x08;
		xfer_resolution = 0x04;
		break;

	case SNDRV_PCM_FORMAT_S32_LE:
		config->data_width = 32;
		ccr = 0x10;
		xfer_resolution = 0x05;
		break;

	default:
		dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt");
		return -EINVAL;
	}

	config->chan_nr = params_channels(params);

	switch (config->chan_nr) {
	case EIGHT_CHANNEL_SUPPORT:
		ch_reg = 3;
		break;
	case SIX_CHANNEL_SUPPORT:
		ch_reg = 2;
		break;
	case FOUR_CHANNEL_SUPPORT:
		ch_reg = 1;
		break;
	case TWO_CHANNEL_SUPPORT:
		ch_reg = 0;
		break;
	default:
		dev_err(dev->dev, "channel not supported\n");
		return -EINVAL;
	}

	i2s_disable_channels(dev, substream->stream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
		i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
		i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
	} else {
		i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
		i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
		irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
		i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
		i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
	}

	i2s_write_reg(dev->i2s_base, CCR, ccr);

	config->sample_rate = params_rate(params);

	if (!dev->i2s_clk_cfg)
		return -EINVAL;

	ret = dev->i2s_clk_cfg(config);
	if (ret < 0) {
		dev_err(dev->dev, "runtime audio clk config fail\n");
		return ret;
	}

	return 0;
}