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; }