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;
}
Exemple #2
0
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;
}
Exemple #5
0
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;
}