Example #1
0
static int asrc_set_process_configuration(enum asrc_pair_index index,
					int inrate, int outrate)
{
	int in, out;

	for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) {
		if (inrate == supported_input_rate[in])
			break;
	}

	if (in == ARRAY_SIZE(supported_input_rate)) {
		dev_err(asrc->dev, "unsupported input sample rate: %d\n", in);
		return -EINVAL;
	}

	for (out = 0; out < ARRAY_SIZE(supported_output_rate); out++) {
		if (outrate == supported_output_rate[out])
			break;
	}

	if (out == ARRAY_SIZE(supported_output_rate)) {
		dev_err(asrc->dev, "unsupported output sample rate: %d\n", out);
		return -EINVAL;
	}

	regmap_update_bits(asrc->regmap, REG_ASRCFG,
			ASRCFG_PREMODx_MASK(index) | ASRCFG_POSTMODx_MASK(index),
			ASRCFG_PREMOD(index, asrc_process_table[in][out][0]) |
			ASRCFG_POSTMOD(index, asrc_process_table[in][out][1]));

	return 0;
}
Example #2
0
/**
 * Configure the assigned ASRC pair
 *
 * It configures those ASRC registers according to a configuration instance
 * of struct asrc_config which includes in/output sample rate, width, channel
 * and clock settings.
 */
static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
{
	struct asrc_config *config = pair->config;
	struct fsl_asrc *asrc_priv = pair->asrc_priv;
	enum asrc_pair_index index = pair->index;
	u32 inrate, outrate, indiv, outdiv;
	u32 clk_index[2], div[2];
	int in, out, channels;
	struct clk *clk;
	bool ideal;

	if (!config) {
		pair_err("invalid pair config\n");
		return -EINVAL;
	}

	/* Validate channels */
	if (config->channel_num < 1 || config->channel_num > 10) {
		pair_err("does not support %d channels\n", config->channel_num);
		return -EINVAL;
	}

	/* Validate output width */
	if (config->output_word_width == ASRC_WIDTH_8_BIT) {
		pair_err("does not support 8bit width output\n");
		return -EINVAL;
	}

	inrate = config->input_sample_rate;
	outrate = config->output_sample_rate;
	ideal = config->inclk == INCLK_NONE;

	/* Validate input and output sample rates */
	for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
		if (inrate == supported_input_rate[in])
			break;

	if (in == ARRAY_SIZE(supported_input_rate)) {
		pair_err("unsupported input sample rate: %dHz\n", inrate);
		return -EINVAL;
	}

	for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++)
		if (outrate == supported_asrc_rate[out])
			break;

	if (out == ARRAY_SIZE(supported_asrc_rate)) {
		pair_err("unsupported output sample rate: %dHz\n", outrate);
		return -EINVAL;
	}

	/* Validate input and output clock sources */
	clk_index[IN] = clk_map[IN][config->inclk];
	clk_index[OUT] = clk_map[OUT][config->outclk];

	/* We only have output clock for ideal ratio mode */
	clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];

	div[IN] = clk_get_rate(clk) / inrate;
	if (div[IN] == 0) {
		pair_err("failed to support input sample rate %dHz by asrck_%x\n",
				inrate, clk_index[ideal ? OUT : IN]);
		return -EINVAL;
	}

	clk = asrc_priv->asrck_clk[clk_index[OUT]];

	/* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
	if (ideal)
		div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
	else
		div[OUT] = clk_get_rate(clk) / outrate;

	if (div[OUT] == 0) {
		pair_err("failed to support output sample rate %dHz by asrck_%x\n",
				outrate, clk_index[OUT]);
		return -EINVAL;
	}

	/* Set the channel number */
	channels = config->channel_num;

	if (asrc_priv->channel_bits < 4)
		channels /= 2;

	/* Update channels for current pair */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR,
			   ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits),
			   ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits));

	/* Default setting: Automatic selection for processing mode */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
			   ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
			   ASRCTR_USRi_MASK(index), 0);

	/* Set the input and output clock sources */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCSR,
			   ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index),
			   ASRCSR_AICS(index, clk_index[IN]) |
			   ASRCSR_AOCS(index, clk_index[OUT]));

	/* Calculate the input clock divisors */
	indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]);
	outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]);

	/* Suppose indiv and outdiv includes prescaler, so add its MASK too */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index),
			   ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) |
			   ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index),
			   ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv));

	/* Implement word_width configurations */
	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
			   ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
			   ASRMCR1i_OW16(config->output_word_width) |
			   ASRMCR1i_IWD(config->input_word_width));

	/* Enable BUFFER STALL */
	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
			   ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi);

	/* Set default thresholds for input and output FIFO */
	fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD,
				ASRC_INPUTFIFO_THRESHOLD);

	/* Configure the followings only for Ideal Ratio mode */
	if (!ideal)
		return 0;

	/* Clear ASTSx bit to use Ideal Ratio mode */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
			   ASRCTR_ATSi_MASK(index), 0);

	/* Enable Ideal Ratio mode */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
			   ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
			   ASRCTR_IDR(index) | ASRCTR_USR(index));

	/* Apply configurations for pre- and post-processing */
	regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
			   ASRCFG_PREMODi_MASK(index) |	ASRCFG_POSTMODi_MASK(index),
			   ASRCFG_PREMOD(index, process_option[in][out][0]) |
			   ASRCFG_POSTMOD(index, process_option[in][out][1]));

	return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
}