0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
};
+/* V2 uses the same map for input and output */
static unsigned char input_clk_map_v2[] = {
- 0, 1, 2, 3, 4, 5, 0xf, 0xf, 0xf, 8, 9, 0xa, 0xb, 0xc, 0xf, 0xd,
+/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf*/
+ 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
};
static unsigned char output_clk_map_v2[] = {
- 8, 9, 0xa, 0, 0xc, 0x5, 0xf, 0xf, 0, 1, 2, 0xf, 0xf, 4, 0xf, 0xd,
+/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf*/
+ 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
};
static unsigned char *input_clk_map, *output_clk_map;
int err = 0;
unsigned long lock_flags;
struct asrc_pair *pair;
+ int imax = 0, busy = 0, i;
+
spin_lock_irqsave(&data_lock, lock_flags);
- if (chn_num > 2) {
- pair = &g_asrc->asrc_pair[ASRC_PAIR_B];
- if (pair->active || (chn_num > pair->chn_max))
- err = -EBUSY;
- else {
- *index = ASRC_PAIR_B;
- pair->chn_num = chn_num;
- pair->active = 1;
+ for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
+ pair = &g_asrc->asrc_pair[i];
+ if (chn_num > pair->chn_max) {
+ imax++;
+ continue;
+ } else if (pair->active) {
+ busy++;
+ continue;
}
+ /* Save the current qualified pair */
+ *index = i;
+
+ /* Check if this pair is a perfect one */
+ if (chn_num == pair->chn_max)
+ break;
+ }
+
+ if (imax >= ASRC_PAIR_MAX_NUM) {
+ pr_err("No pair could afford requested channel number.\n");
+ err = -EINVAL;
+ } else if (busy >= ASRC_PAIR_MAX_NUM) {
+ pr_err("All pairs are busy now.\n");
+ err = -EBUSY;
+ } else if (busy + imax >= ASRC_PAIR_MAX_NUM) {
+ pr_err("All affordable pairs are busy now.\n");
+ err = -EBUSY;
} else {
- pair = &g_asrc->asrc_pair[ASRC_PAIR_A];
- if (pair->active || (pair->chn_max == 0)) {
- pair = &g_asrc->asrc_pair[ASRC_PAIR_C];
- if (pair->active || (pair->chn_max == 0))
- err = -EBUSY;
- else {
- *index = ASRC_PAIR_C;
- pair->chn_num = 2;
- pair->active = 1;
- }
- } else {
- *index = ASRC_PAIR_A;
- pair->chn_num = 2;
- pair->active = 1;
- }
+ pair = &g_asrc->asrc_pair[*index];
+ pair->chn_num = chn_num;
+ pair->active = 1;
}
+
spin_unlock_irqrestore(&data_lock, lock_flags);
if (!err) {
int err = 0;
int reg, tmp, channel_num;
unsigned long lock_flags;
+ unsigned long aicp_shift, aocp_shift;
+ unsigned long asrc_asrcdr_reg, dp_clear_mask;
+
/* Set the channel number */
reg = __raw_readl(g_asrc->vaddr + ASRC_ASRCNCR_REG);
spin_lock_irqsave(&data_lock, lock_flags);
__raw_writel(reg, g_asrc->vaddr + ASRC_ASRCTR_REG);
/* Default Clock Divider Setting */
- reg = __raw_readl(g_asrc->vaddr + ASRC_ASRCDR1_REG);
- if (config->pair == ASRC_PAIR_A) {
- reg = __raw_readl(g_asrc->vaddr + 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->input_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AICPA;
- else if (config->input_word_width == ASRC_WIDTH_24_BIT)
- 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) &&
- ((config->inclk & 0x0f) == INCLK_NONE))
- reg |= 5 << 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->output_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AOCPA;
- else if (config->output_word_width == ASRC_WIDTH_24_BIT)
- reg |= 6 << AOCPA;
- else
- err = -EFAULT;
- }
-
- __raw_writel(reg, g_asrc->vaddr + ASRC_ASRCDR1_REG);
-
- } else if (config->pair == ASRC_PAIR_B) {
- reg = __raw_readl(g_asrc->vaddr + 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->input_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AICPB;
- else if (config->input_word_width == ASRC_WIDTH_24_BIT)
- 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) &&
- ((config->inclk & 0x0f) == INCLK_NONE))
- reg |= 5 << 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->output_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AOCPB;
- else if (config->output_word_width == ASRC_WIDTH_24_BIT)
- reg |= 6 << AOCPB;
- else
- err = -EFAULT;
- }
-
- __raw_writel(reg, g_asrc->vaddr + ASRC_ASRCDR1_REG);
+ switch (config->pair) {
+ case ASRC_PAIR_A:
+ asrc_asrcdr_reg = ASRC_ASRCDR1_REG;
+ dp_clear_mask = 0xfc0fc0;
+ aicp_shift = AICPA;
+ aocp_shift = AOCPA;
+ break;
+ case ASRC_PAIR_B:
+ asrc_asrcdr_reg = ASRC_ASRCDR1_REG;
+ dp_clear_mask = 0x03f03f;
+ aicp_shift = AICPB;
+ aocp_shift = AOCPB;
+ break;
+ case ASRC_PAIR_C:
+ asrc_asrcdr_reg = ASRC_ASRCDR2_REG;
+ dp_clear_mask = 0x00;
+ aicp_shift = AICPC;
+ aocp_shift = AOCPC;
+ break;
+ default:
+ pr_err("Invalid Pair number %d\n", config->pair);
+ return -EFAULT;
+ }
+ reg = __raw_readl(g_asrc->vaddr + asrc_asrcdr_reg);
+ reg &= dp_clear_mask;
+ /* Input Part */
+ if ((config->inclk & 0x0f) == INCLK_SPDIF_RX)
+ reg |= 7 << aicp_shift;
+ else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX)
+ reg |= 6 << aicp_shift;
+ else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) {
+ tmp = asrc_get_asrck_clock_divider(config->input_sample_rate);
+ reg |= tmp << aicp_shift;
} else {
- reg = __raw_readl(g_asrc->vaddr + 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->input_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AICPC;
- else if (config->input_word_width == ASRC_WIDTH_24_BIT)
- 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) &&
- ((config->inclk & 0x0f) == INCLK_NONE))
- reg |= 5 << 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->output_word_width == ASRC_WIDTH_16_BIT)
- reg |= 5 << AOCPC;
- else if (config->output_word_width == ASRC_WIDTH_24_BIT)
- reg |= 6 << AOCPC;
- else
- err = -EFAULT;
- }
- __raw_writel(reg, g_asrc->vaddr + ASRC_ASRCDR2_REG);
-
+ if (config->input_word_width == ASRC_WIDTH_16_BIT)
+ reg |= 5 << aicp_shift;
+ else if (config->input_word_width == ASRC_WIDTH_24_BIT)
+ reg |= 6 << aicp_shift;
+ else
+ err = -EFAULT;
}
+ /* Output Part */
+ if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX)
+ reg |= 7 << aocp_shift;
+ else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX)
+ reg |= 6 << aocp_shift;
+ else if (((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK)
+ && ((config->inclk & 0x0f) == INCLK_NONE))
+ reg |= 5 << aocp_shift;
+ else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) {
+ tmp = asrc_get_asrck_clock_divider(config->output_sample_rate);
+ reg |= tmp << aocp_shift;
+ } else {
+ if (config->output_word_width == ASRC_WIDTH_16_BIT)
+ reg |= 5 << aocp_shift;
+ else if (config->output_word_width == ASRC_WIDTH_24_BIT)
+ reg |= 6 << aocp_shift;
+ else
+ err = -EFAULT;
+ }
+ __raw_writel(reg, g_asrc->vaddr + asrc_asrcdr_reg);
/* check whether ideal ratio is a must */
if ((config->inclk & 0x0f) == INCLK_NONE) {
}
}
- if ((config->inclk == INCLK_NONE) &&
- (config->outclk == OUTCLK_ESAI_TX)) {
- reg = __raw_readl(g_asrc->vaddr + ASRC_ASRCTR_REG);
- reg &= ~(1 << (20 + config->pair));
- reg |= (0x03 << (13 + (config->pair << 1)));
- __raw_writel(reg, g_asrc->vaddr + 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;
- }
-
/* Config input and output wordwidth */
reg = __raw_readl(
g_asrc->vaddr + ASRC_ASRMCR1A_REG + (config->pair << 2));
__raw_writel(0x001f00, g_asrc->vaddr + ASRC_ASRTFR1);
/* Set the processing clock for 76KHz, 133M */
- __raw_writel(0x30E, g_asrc->vaddr + ASRC_ASR76K_REG);
+ __raw_writel(0x06D6, g_asrc->vaddr + ASRC_ASR76K_REG);
/* Set the processing clock for 56KHz, 133M */
- __raw_writel(0x0426, g_asrc->vaddr + ASRC_ASR56K_REG);
+ __raw_writel(0x0947, g_asrc->vaddr + ASRC_ASR56K_REG);
return 0;
}
total = 10;
else
total = 5;
- if ((na + nb + nc) != total) {
- pr_info("Wrong ASRCNR settings\n");
- return -EFAULT;
+
+ if ((na + nb + nc) > total) {
+ pr_err("Don't surpass %d for total.\n", total);
+ return -EINVAL;
+ } else if (na % 2 != 0 || nb % 2 != 0 || nc % 2 != 0) {
+ pr_err("Please set an even number for each pair.\n");
+ return -EINVAL;
+ } else if (na < 0 || nb < 0 || nc < 0) {
+ pr_err("Please set an positive number for each pair.\n");
+ return -EINVAL;
}
+
reg = na | (nb << g_asrc->mxc_asrc_data->channel_bits) |
(nc << (g_asrc->mxc_asrc_data->channel_bits * 2));
+ /* Update chn_max */
+ g_asrc->asrc_pair[ASRC_PAIR_A].chn_max = na;
+ g_asrc->asrc_pair[ASRC_PAIR_B].chn_max = nb;
+ g_asrc->asrc_pair[ASRC_PAIR_C].chn_max = nc;
+
clk_enable(g_asrc->mxc_asrc_data->asrc_core_clk);
__raw_writel(reg, g_asrc->vaddr + ASRC_ASRCNCR_REG);
clk_disable(g_asrc->mxc_asrc_data->asrc_core_clk);
{
int irq = platform_get_irq(pdev, 0);
free_irq(irq, NULL);
- kfree(g_asrc);
- g_asrc->mxc_asrc_data = NULL;
iounmap((unsigned long __iomem *)g_asrc->vaddr);
remove_proc_entry("ChSettings", g_asrc->proc_asrc);
remove_proc_entry(ASRC_PROC_PATH, NULL);
device_destroy(g_asrc->asrc_class, MKDEV(g_asrc->asrc_major, 0));
class_destroy(g_asrc->asrc_class);
unregister_chrdev(g_asrc->asrc_major, "mxc_asrc");
+ kfree(g_asrc);
return 0;
}