bool mi2s_set_codec_input_path(uint8_t channels, uint8_t size) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; mutex_lock(&the_mi2s_state.mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, CODEC_RX); mi2s_master(mi2s, CODEC_RX, 1); /* Enable clock crossing synchronization of WR DMA ACK */ mi2s_set_input_clk_synch(mi2s, CODEC_RX); /* Set word type */ if (size <= WT_MAX) mi2s_set_word_type(mi2s, CODEC_RX, size); else ret_val = MI2S_FALSE; mi2s_set_input_num_channels(mi2s, CODEC_RX, channels); /* Enable SD line */ mi2s_set_sd(mi2s, CODEC_RX, MI2S_SD_0_EN_MAP); /* Release device from reset */ mi2s_release(mi2s, CODEC_RX); mutex_unlock(&mi2s->mutex_lock); mb(); return ret_val; }
bool mi2s_set_hdmi_input_path(uint8_t channels, uint8_t size, uint8_t sd_line) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ if (size <= WT_MAX) mi2s_set_word_type(mi2s, HDMI, size); else ret_val = MI2S_FALSE; /* Enable clock crossing synchronization of WR DMA ACK */ mi2s_set_input_clk_synch(mi2s, HDMI); /* Ensure channels parameter is valid (non-zero, less than max, * and even or mono) */ if ((channels > 0) && (channels <= MAX_NUM_CHANNELS_IN) && ((channels == 1) || (channels % 2 == 0))) { mi2s_set_input_num_channels(mi2s, HDMI, channels); } else { ret_val = MI2S_FALSE; } /* Ensure sd_line parameter is valid (0-max) */ if (sd_line < MAX_SD_LINES) { /* Enable single SD line for Rx */ mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line)); } else { ret_val = MI2S_FALSE; } /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); return ret_val; }
bool mi2s_set_hdmi_input_path(uint8_t channels, uint8_t size, uint8_t sd_line_mask) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; u8 sd_line, num_of_sd_lines = 0; void __iomem *baddr; uint32_t val; pr_debug("%s: channels = %u size = %u sd_line_mask = 0x%x\n", __func__, channels, size, sd_line_mask); if ((channels != 1) && (channels != MAX_NUM_CHANNELS_IN)) { pr_err("%s: invalid number of channels. channels = %u\n", __func__, channels); return MI2S_FALSE; } if (size > WT_MAX) { pr_err("%s: mi2s word size can not be greater than 32 bits\n", __func__); return MI2S_FALSE; } sd_line_mask &= MI2S_SD_LINE_MASK; if (!sd_line_mask) { pr_err("%s: Did not set any data lines to use " " sd_line_mask =0x%x\n", __func__, sd_line_mask); return MI2S_FALSE; } num_of_sd_lines = num_of_bits_set(sd_line_mask); if (num_of_sd_lines != 1) { pr_err("%s: for two channel input only one SD lines is" " needed. num_of_sd_lines = %u sd_line_mask = 0x%x\n", __func__, num_of_sd_lines, sd_line_mask); return MI2S_FALSE; } /*Second argument to find_first_bit should be maximum number of bits interested*/ sd_line = find_first_bit((unsigned long *)&sd_line_mask, sizeof(sd_line_mask) * 8); pr_debug("sd_line = %d\n", sd_line); /* Ensure sd_line parameter is valid (0-max) */ if (sd_line > MAX_SD_LINES) { pr_err("%s: Line number can not be greater than = %u\n", __func__, MAX_SD_LINES); return MI2S_FALSE; } mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ mi2s_set_word_type(mi2s, HDMI, size); /* Enable clock crossing synchronization of WR DMA ACK */ mi2s_set_input_clk_synch(mi2s, HDMI); /* Ensure channels parameter is valid (non-zero, less than max, * and even or mono) */ mi2s_set_input_num_channels(mi2s, HDMI, channels); mi2s_set_input_sd_line(mi2s, HDMI, sd_line); mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line)); baddr = get_base_addr(mi2s, HDMI); val = readl(baddr + MI2S_MODE_OFFSET); pr_debug("%s(): MI2S_MODE = 0x%x\n", __func__, val); val = readl(baddr + MI2S_RX_MODE_OFFSET); pr_debug("%s(): MI2S_RX_MODE = 0x%x\n", __func__, val); /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); mb(); return ret_val; }
bool mi2s_set_hdmi_output_path(uint8_t channels, uint8_t size, uint8_t sd_line_mask) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; u8 sd_line, num_of_sd_lines = 0; void __iomem *baddr; uint32_t val; pr_debug("%s: channels = %u size = %u sd_line_mask = 0x%x\n", __func__, channels, size, sd_line_mask); if ((channels == 0) || (channels > MAX_NUM_CHANNELS_OUT) || ((channels != 1) && (channels % 2 != 0))) { pr_err("%s: invalid number of channels. channels = %u\n", __func__, channels); return MI2S_FALSE; } sd_line_mask &= MI2S_SD_LINE_MASK; if (!sd_line_mask) { pr_err("%s: Did not set any data lines to use " " sd_line_mask =0x%x\n", __func__, sd_line_mask); return MI2S_FALSE; } mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ if (size <= WT_MAX) mi2s_set_word_type(mi2s, HDMI, size); else ret_val = MI2S_FALSE; /* Enable clock crossing synchronization of RD DMA ACK */ mi2s_set_output_clk_synch(mi2s, HDMI); mi2s_set_output_num_channels(mi2s, HDMI, channels); num_of_sd_lines = num_of_bits_set(sd_line_mask); /*Second argument to find_first_bit should be maximum number of bit*/ sd_line = find_first_bit((unsigned long *)&sd_line_mask, sizeof(sd_line_mask) * 8); pr_debug("sd_line = %d\n", sd_line); if (channels == 1) { if (num_of_sd_lines != 1) { pr_err("%s: for one channel only one SD lines is" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if (sd_line != 0) { pr_err("%s: for one channel tx, need to use SD_0 " "sd_line = %u\n", __func__, sd_line); ret_val = MI2S_FALSE; goto error; } /* Enable SD line 0 for Tx (only option for * mono audio) */ mi2s_set_sd(mi2s, HDMI, MI2S_SD_0_EN_MAP | MI2S_SD_0_TX_MAP); } else if (channels == 2) { if (num_of_sd_lines != 1) { pr_err("%s: for two channel only one SD lines is" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } /* Enable single SD line for Tx */ mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line) | (MI2S_SD_0_TX_MAP << sd_line)); /* Set 2-channel mapping */ mi2s_set_output_2ch_map(mi2s, HDMI, sd_line); } else if (channels == 4) { if (num_of_sd_lines != 2) { pr_err("%s: for 4 channels two SD lines are" " needed. num_of_sd_lines = %u\\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if ((sd_line_mask && MI2S_SD_0) && (sd_line_mask && MI2S_SD_1)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_FALSE); } else if ((sd_line_mask && MI2S_SD_2) && (sd_line_mask && MI2S_SD_3)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_TRUE); } else { pr_err("%s: for 4 channels invalid SD lines usage" " sd_line_mask = 0x%x\n", __func__, sd_line_mask); ret_val = MI2S_FALSE; goto error; } } else if (channels == 6) { if (num_of_sd_lines != 3) { pr_err("%s: for 6 channels three SD lines are" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } if ((sd_line_mask && MI2S_SD_0) && (sd_line_mask && MI2S_SD_1) && (sd_line_mask && MI2S_SD_2)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP)); } else if ((sd_line_mask && MI2S_SD_1) && (sd_line_mask && MI2S_SD_2) && (sd_line_mask && MI2S_SD_3)) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); } else { pr_err("%s: for 6 channels invalid SD lines usage" " sd_line_mask = 0x%x\n", __func__, sd_line_mask); ret_val = MI2S_FALSE; goto error; } } else if (channels == 8) { if (num_of_sd_lines != 4) { pr_err("%s: for 8 channels four SD lines are" " needed. num_of_sd_lines = %u\n", __func__, num_of_sd_lines); ret_val = MI2S_FALSE; goto error; } mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); } else { pr_err("%s: invalid number channels = %u\n", __func__, channels); ret_val = MI2S_FALSE; goto error; } baddr = get_base_addr(mi2s, HDMI); val = readl(baddr + MI2S_MODE_OFFSET); pr_debug("%s(): MI2S_MODE = 0x%x\n", __func__, val); val = readl(baddr + MI2S_TX_MODE_OFFSET); pr_debug("%s(): MI2S_TX_MODE = 0x%x\n", __func__, val); error: /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); mb(); return ret_val; }
bool mi2s_set_hdmi_output_path(uint8_t channels, uint8_t size, uint8_t sd_line) { bool ret_val = MI2S_TRUE; struct mi2s_state *mi2s = &the_mi2s_state; mutex_lock(&mi2s->mutex_lock); /* Put device in reset */ mi2s_reset(mi2s, HDMI); mi2s_master(mi2s, HDMI, 1); /* Set word type */ if (size <= WT_MAX) mi2s_set_word_type(mi2s, HDMI, size); else ret_val = MI2S_FALSE; /* Enable clock crossing synchronization of RD DMA ACK */ mi2s_set_output_clk_synch(mi2s, HDMI); /* Ensure channels parameter is valid (non-zero), * less than max, and even or mono) */ if ((channels > 0) && (channels <= MAX_NUM_CHANNELS_OUT) && ((channels == 1) || (channels % 2 == 0))) mi2s_set_output_num_channels(mi2s, HDMI, channels); else ret_val = MI2S_FALSE; /* Ensure sd_line parameter is valid (0-max) */ if (sd_line < MAX_SD_LINES) { if (channels == 1) { /* Enable SD line 0 for Tx (only option for * mono audio) */ mi2s_set_sd(mi2s, HDMI, MI2S_SD_0_EN_MAP | MI2S_SD_0_TX_MAP); } else if (channels == 2) { /* Enable single SD line for Tx */ mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP << sd_line) | (MI2S_SD_0_TX_MAP << sd_line)); /* Set 2-channel mapping */ mi2s_set_output_2ch_map(mi2s, HDMI, sd_line); } else if (channels == 4) { /* Enable 2 adjacent SD lines and map accordingly. * We map to SDs 0 & 1 or 2 & 3 depending on which * of those ranges contain the current sd_line * parameter */ if (sd_line < 2) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_FALSE); } else if (sd_line >= 2) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); mi2s_set_output_4ch_map(mi2s, HDMI, MI2S_TRUE); } else { printk("err\n"); } } else if (channels == 6) { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP)); } else { mi2s_set_sd(mi2s, HDMI, (MI2S_SD_0_EN_MAP | MI2S_SD_1_EN_MAP | MI2S_SD_2_EN_MAP | MI2S_SD_3_EN_MAP) | (MI2S_SD_0_TX_MAP | MI2S_SD_1_TX_MAP | MI2S_SD_2_TX_MAP | MI2S_SD_3_TX_MAP)); } } else ret_val = MI2S_FALSE; /* Release device from reset */ mi2s_release(mi2s, HDMI); mutex_unlock(&mi2s->mutex_lock); return ret_val; }