Exemple #1
0
int asrc_config_pair(struct asrc_config *config)
{
	int err = 0;
	int reg, tmp, channel_num;
	unsigned long lock_flags;
	/* Set the channel number */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCNCR_REG);
	spin_lock_irqsave(&data_lock, lock_flags);
	g_asrc_data->asrc_pair[config->pair].chn_num = config->channel_num;
	spin_unlock_irqrestore(&data_lock, lock_flags);
	reg &=
	    ~((0xFFFFFFFF >> (32 - mxc_asrc_data->channel_bits)) <<
	      (mxc_asrc_data->channel_bits * config->pair));
	if (mxc_asrc_data->channel_bits > 3)
		channel_num = config->channel_num;
	else
		channel_num = (config->channel_num + 1) / 2;
	tmp = channel_num << (mxc_asrc_data->channel_bits * config->pair);
	reg |= tmp;
	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCNCR_REG);

	/* Set the clock source */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCSR_REG);
	tmp = ~(0x0f << (config->pair << 2));
	reg &= tmp;
	tmp = ~(0x0f << (12 + (config->pair << 2)));
	reg &= tmp;
	reg |=
	    ((config->inclk << (config->pair << 2)) | (config->
						       outclk << (12 +
								  (config->
								   pair <<
								   2))));

	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCSR_REG);

	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG);
	if ((config->inclk & 0x0f) != INCLK_NONE) {
		reg |= (1 << (20 + config->pair));
		reg &= ~(1 << (14 + (config->pair << 1)));
		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG);
	} else {
		reg &= ~(1 << (20 + config->pair));
		reg |= (0x03 << (13 + (config->pair << 1)));
		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG);
		err =
		    asrc_set_clock_ratio(config->pair,
					 config->input_sample_rate,
					 config->output_sample_rate);
		if (err < 0)
			return err;
	}

	err = asrc_set_process_configuration(config->pair,
					     config->input_sample_rate,
					     config->output_sample_rate);
	return err;
}
int asrc_config_pair(struct asrc_config *config)
{
	u32 inrate = config->input_sample_rate, indiv;
	u32 outrate = config->output_sample_rate, outdiv;
	int ret, channels, index = config->pair;
	unsigned long lock_flags;

	/* Set the channel number */
	spin_lock_irqsave(&data_lock, lock_flags);
	asrc->asrc_pair[index].chn_num = config->channel_num;
	spin_unlock_irqrestore(&data_lock, lock_flags);

	if (asrc->channel_bits > 3)
		channels = config->channel_num;
	else
		channels = (config->channel_num + 1) / 2;

	/* Update channel number of current pair */
	regmap_update_bits(asrc->regmap, REG_ASRCNCR,
			ASRCNCR_ANCx_MASK(index, asrc->channel_bits),
			ASRCNCR_ANCx_set(index, channels, asrc->channel_bits));

	/* Set the clock source */
	regmap_update_bits(asrc->regmap, REG_ASRCSR,
			ASRCSR_AICSx_MASK(index) | ASRCSR_AOCSx_MASK(index),
			ASRCSR_AICS(index, input_clk_map[config->inclk]) |
			ASRCSR_AOCS(index, output_clk_map[config->outclk]));

	/* Default setting: Automatic selection for processing mode */
	regmap_update_bits(asrc->regmap, REG_ASRCTR,
			ASRCTR_ATSx_MASK(index), ASRCTR_ATS(index));
	regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_USRx_MASK(index), 0);

	/* Default Input Clock Divider Setting */
	switch (config->inclk & ASRCSR_AxCSx_MASK) {
	case INCLK_SPDIF_RX:
		indiv = ASRC_PRESCALER_SPDIF_RX;
		break;
	case INCLK_SPDIF_TX:
		indiv = ASRC_PRESCALER_SPDIF_TX;
		break;
	case INCLK_ASRCK1_CLK:
		indiv = asrc_get_asrck_clock_divider(inrate);
		break;
	default:
		switch (config->input_word_width) {
		case ASRC_WIDTH_16_BIT:
			indiv = ASRC_PRESCALER_I2S_16BIT;
			break;
		case ASRC_WIDTH_24_BIT:
			indiv = ASRC_PRESCALER_I2S_24BIT;
			break;
		default:
			pair_err("unsupported input word width %d\n",
					config->input_word_width);
			return -EINVAL;
		}
		break;
	}

	/* Default Output Clock Divider Setting */
	switch (config->outclk & ASRCSR_AxCSx_MASK) {
	case OUTCLK_SPDIF_RX:
		outdiv = ASRC_PRESCALER_SPDIF_RX;
		break;
	case OUTCLK_SPDIF_TX:
		outdiv = ASRC_PRESCALER_SPDIF_TX;
		break;
	case OUTCLK_ASRCK1_CLK:
		if ((config->inclk & ASRCSR_AxCSx_MASK) == INCLK_NONE)
			outdiv = ASRC_PRESCALER_IDEAL_RATIO;
		else
			outdiv = asrc_get_asrck_clock_divider(outrate);
		break;
	default:
		switch (config->output_word_width) {
		case ASRC_WIDTH_16_BIT:
			outdiv = ASRC_PRESCALER_I2S_16BIT;
			break;
		case ASRC_WIDTH_24_BIT:
			outdiv = ASRC_PRESCALER_I2S_24BIT;
			break;
		default:
			pair_err("unsupported output word width %d\n",
					config->input_word_width);
			return -EINVAL;
		}
		break;
	}

	/* indiv and outdiv'd include prescaler's value, so add its MASK too */
	regmap_update_bits(asrc->regmap, REG_ASRCDR(index),
			ASRCDRx_AOCPx_MASK(index) | ASRCDRx_AICPx_MASK(index) |
			ASRCDRx_AOCDx_MASK(index) | ASRCDRx_AICDx_MASK(index),
			ASRCDRx_AOCP(index, outdiv) | ASRCDRx_AICP(index, indiv));

	/* Check whether ideal ratio is a must */
	switch (config->inclk & ASRCSR_AxCSx_MASK) {
	case INCLK_NONE:
		/* Clear ASTSx bit to use ideal ratio */
		regmap_update_bits(asrc->regmap, REG_ASRCTR,
				ASRCTR_ATSx_MASK(index), 0);

		regmap_update_bits(asrc->regmap, REG_ASRCTR,
				ASRCTR_IDRx_MASK(index) | ASRCTR_USRx_MASK(index),
				ASRCTR_IDR(index) | ASRCTR_USR(index));

		ret = asrc_set_clock_ratio(index, inrate, outrate);
		if (ret)
			return ret;

		ret = asrc_set_process_configuration(index, inrate, outrate);
		if (ret)
			return ret;

		break;
	case INCLK_ASRCK1_CLK:
		/* This case and default are both remained for v1 */
		if (inrate == 44100 || inrate == 88200) {
			pair_err("unsupported sample rate %d by selected clock\n",
					inrate);
			return -EINVAL;
		}
		break;
	default:
		if ((config->outclk & ASRCSR_AxCSx_MASK) != OUTCLK_ASRCK1_CLK)
			break;

		if (outrate == 44100 || outrate == 88200) {
			pair_err("unsupported sample rate %d by selected clock\n",
					outrate);
			return -EINVAL;
		}
		break;
	}

	/* Config input and output wordwidth */
	if (config->output_word_width == ASRC_WIDTH_8_BIT) {
		pair_err("unsupported wordwidth for output: 8bit\n");
		pair_err("output only support: 16bit or 24bit\n");
		return -EINVAL;
	}

	regmap_update_bits(asrc->regmap, REG_ASRMCR1(index),
			ASRMCR1x_OW16_MASK | ASRMCR1x_IWD_MASK,
			ASRMCR1x_OW16(config->output_word_width) |
			ASRMCR1x_IWD(config->input_word_width));

	/* Enable BUFFER STALL */
	regmap_update_bits(asrc->regmap, REG_ASRMCR(index),
			ASRMCRx_BUFSTALLx_MASK, ASRMCRx_BUFSTALLx);

	/* Set Threshold for input and output FIFO */
	return asrc_set_watermark(index, ASRC_INPUTFIFO_THRESHOLD,
			ASRC_INPUTFIFO_THRESHOLD);
}
int asrc_config_pair(struct asrc_config *config)
{
	int err = 0;
	int reg, tmp, channel_num;
	unsigned long lock_flags;
	/* Set the channel number */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCNCR_REG);
	spin_lock_irqsave(&data_lock, lock_flags);
	g_asrc_data->asrc_pair[config->pair].chn_num = config->channel_num;
	spin_unlock_irqrestore(&data_lock, lock_flags);
	reg &=
	    ~((0xFFFFFFFF >> (32 - mxc_asrc_data->channel_bits)) <<
	      (mxc_asrc_data->channel_bits * config->pair));
	if (mxc_asrc_data->channel_bits > 3)
		channel_num = config->channel_num;
	else
		channel_num = (config->channel_num + 1) / 2;
	tmp = channel_num << (mxc_asrc_data->channel_bits * config->pair);
	reg |= tmp;
	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCNCR_REG);

	/* Set the clock source */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCSR_REG);
	tmp = ~(0x0f << (config->pair << 2));
	reg &= tmp;
	tmp = ~(0x0f << (12 + (config->pair << 2)));
	reg &= tmp;
	reg |=
	    ((input_clk_map[config->inclk] << (config->pair << 2)) | (output_clk_map[config->
						       outclk] << (12 +
								  (config->
								   pair <<
								   2))));

	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCSR_REG);

	/* default setting */
	/* automatic selection for processing mode */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG);
	reg |= (1 << (20 + config->pair));
	reg &= ~(1 << (14 + (config->pair << 1)));

	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG);

	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRRA_REG);
	reg &= 0xffbfffff;
	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRRA_REG);

	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG);
	reg = reg & (~(1 << 23));
	__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG);

	/* Default Clock Divider Setting */
	reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG);
	if (config->pair == ASRC_PAIR_A) {
		reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG);
		reg &= 0xfc0fc0;
		/* Input Part */
		if ((config->inclk & 0x0f) == INCLK_SPDIF_RX)
			reg |= 7 << AICPA;
		else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX)
			reg |= 6 << AICPA;
		else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 input_sample_rate);
			reg |= tmp << AICPA;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AICPA;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AICPA;
			else
				err = -EFAULT;
		}
		/* Output Part */
		if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX)
			reg |= 7 << AOCPA;
		else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX)
			reg |= 6 << AOCPA;
		else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 output_sample_rate);
			reg |= tmp << AOCPA;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AOCPA;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AOCPA;
			else
				err = -EFAULT;
		}

		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR1_REG);

	} else if (config->pair == ASRC_PAIR_B) {
		reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG);
		reg &= 0x03f03f;
		/* Input Part */
		if ((config->inclk & 0x0f) == INCLK_SPDIF_RX)
			reg |= 7 << AICPB;
		else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX)
			reg |= 6 << AICPB;
		else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 input_sample_rate);
			reg |= tmp << AICPB;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AICPB;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AICPB;
			else
				err = -EFAULT;
		}
		/* Output Part */
		if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX)
			reg |= 7 << AOCPB;
		else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX)
			reg |= 6 << AOCPB;
		else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 output_sample_rate);
			reg |= tmp << AOCPB;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AOCPB;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AOCPB;
			else
				err = -EFAULT;
		}

		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR1_REG);

	} else {
		reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR2_REG);
		reg &= 0;
		/* Input Part */
		if ((config->inclk & 0x0f) == INCLK_SPDIF_RX)
			reg |= 7 << AICPC;
		else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX)
			reg |= 6 << AICPC;
		else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 input_sample_rate);
			reg |= tmp << AICPC;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AICPC;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AICPC;
			else
				err = -EFAULT;
		}
		/* Output Part */
		if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX)
			reg |= 7 << AOCPC;
		else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX)
			reg |= 6 << AOCPC;
		else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) {
			tmp =
			    asrc_get_asrck_clock_divider(config->
							 output_sample_rate);
			reg |= tmp << AOCPC;
		} else {
			if (config->word_width == 16 || config->word_width == 8)
				reg |= 5 << AOCPC;
			else if (config->word_width == 32
				 || config->word_width == 24)
				reg |= 6 << AOCPC;
			else
				err = -EFAULT;
		}
		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR2_REG);

	}

	/* check whether ideal ratio is a must */
	if ((config->inclk & 0x0f) == INCLK_NONE) {
		reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG);
		reg &= ~(1 << (20 + config->pair));
		reg |= (0x03 << (13 + (config->pair << 1)));
		__raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG);
		err = asrc_set_clock_ratio(config->pair,
					   config->input_sample_rate,
					   config->output_sample_rate);
		if (err < 0)
			return err;

		err = asrc_set_process_configuration(config->pair,
						     config->input_sample_rate,
						     config->
						     output_sample_rate);
		if (err < 0)
			return err;
	} else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) {
		if (config->input_sample_rate == 44100
		    || config->input_sample_rate == 88200) {
			pr_info
			    ("ASRC core clock cann't support sample rate %d\n",
			     config->input_sample_rate);
			err = -EFAULT;
		}
	} else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) {
		if (config->output_sample_rate == 44100
		    || config->output_sample_rate == 88200) {
			pr_info
			    ("ASRC core clock cann't support sample rate %d\n",
			     config->input_sample_rate);
			err = -EFAULT;
		}
	}

	return err;
}