Пример #1
0
int route_tx_enable(int path, int en)
{
	pr_aud_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
	if (en) {
		/* Uplink_Wakeup */
		aic3254_config(CODEC_UPLINK_ON, ARRAY_SIZE(CODEC_UPLINK_ON));
		/* Path switching */
		switch (path) {
		case CALL_UPLINK_IMIC_RECEIVER:
		case CALL_UPLINK_IMIC_HEADSET:
		case CALL_UPLINK_IMIC_SPEAKER:
		case VOICERECORD_IMIC:
			/* By pass */
			aic3254_config(MECHA_Uplink_IMIC,
					ARRAY_SIZE(MECHA_Uplink_IMIC));
			break;
		case CALL_UPLINK_EMIC_HEADSET:
		case VOICERECORD_EMIC:
			aic3254_config(Uplink_EMIC,
					ARRAY_SIZE(Uplink_EMIC));
			break;
		}
	} else {
		/* Uplink_Off */
		aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
	}

	return 0;
}
Пример #2
0
static int spi_aic3254_probe(struct spi_device *aic3254)
{
	pr_aud_info("%s\n", __func__);

	codec_dev = aic3254;

	/* Boot up */
#if 0
	aic3254_config(CODEC_INIT_REG, ARRAY_SIZE(CODEC_INIT_REG));
	aic3254_config(CODEC_DOWNLINK_OFF, ARRAY_SIZE(CODEC_DOWNLINK_OFF));
	aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
	aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
#endif

	aic3254_tx_mode = UPLINK_OFF;
	aic3254_rx_mode = DOWNLINK_OFF;

	/* request space for firmware data of AIC3254 */
	aic3254_uplink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
	aic3254_downlink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
	aic3254_minidsp = init_2d_array(MINIDSP_ROW_MAX, MINIDSP_COL_MAX);
	bulk_tx = kcalloc(MINIDSP_COL_MAX * 2 , sizeof(uint8_t), GFP_KERNEL);
	spin_lock_init(&spinlock);
	return 0;
}
Пример #3
0
void aic3254_set_mic_bias(int en)
{
	if (en)
		aic3254_config(CODEC_MICBIAS_ON, ARRAY_SIZE(CODEC_MICBIAS_ON));
	else
		aic3254_config(CODEC_MICBIAS_OFF, ARRAY_SIZE(CODEC_MICBIAS_OFF));
}
Пример #4
0
static void aic3254_rx_config(int mode)
{
	/* use default setting when rx table doesn't be updated*/
	if (aic3254_downlink == NULL) {
		if (mode == DOWNLINK_OFF)
			route_rx_enable(mode, 0);
		else
			route_rx_enable(mode, 1);
		return;
	}

	if (mode != DOWNLINK_OFF && mode != POWER_OFF) {
		/* Downlink Wakeup */
		pr_aud_info("downlink wakeup len(%d)\n",
			(aic3254_downlink[DOWNLINK_WAKEUP][0].data-1));
		aic3254_config(
			&aic3254_downlink[DOWNLINK_WAKEUP][1],
			aic3254_downlink[DOWNLINK_WAKEUP][0].data);
	}

	/* route rx device */
	pr_aud_info("downlink RX %d len(%d)\n", mode,
		(aic3254_downlink[mode][0].data-1));
	aic3254_config(&aic3254_downlink[mode][1],
				aic3254_downlink[mode][0].data);
}
Пример #5
0
static void aic3254_tx_config(int mode)
{
	/* use default setting when tx table doesn't be updated*/
	if (aic3254_uplink == NULL) {
		if (mode == UPLINK_OFF)
			route_tx_enable(mode, 0);
		else
			route_tx_enable(mode, 1);
		return;
	}

	if (mode != UPLINK_OFF && mode != POWER_OFF) {
		/* uplink_Wakeup */
		pr_aud_info("uplink wakeup len(%d)\n",
			(aic3254_uplink[UPLINK_WAKEUP][0].data-1));
		aic3254_config(
			&aic3254_uplink[UPLINK_WAKEUP][1],
			aic3254_uplink[UPLINK_WAKEUP][0].data);
	}

	/* route tx device */
	pr_aud_info("uplink TX %d len(%d)\n", mode,
		(aic3254_uplink[mode][0].data-1));
	aic3254_config(&aic3254_uplink[mode][1],
			aic3254_uplink[mode][0].data);
}
Пример #6
0
static void aic3254_powerdown(void)
{
	struct ecodec_aic3254_state *drv = &codec_clk;
	if (aic3254_tx_mode != UPLINK_OFF || aic3254_rx_mode != DOWNLINK_OFF)
		return;

	pr_aud_info("%s: power off AIC3254\n", __func__);
	wake_lock(&drv->idlelock);
	if (aic3254_uplink != NULL)
		aic3254_config(&aic3254_uplink[POWER_OFF][1],
				aic3254_uplink[POWER_OFF][0].data);
	else
		aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));

#if defined(CONFIG_ARCH_MSM7X30)
	if (drv->enabled) {
		/* Disable MI2S RX master block */
		/* Disable MI2S RX bit clock */
		clk_disable(drv->rx_sclk);
		clk_disable(drv->rx_mclk);
		drv->enabled = 0;
		printk("%s: disable CLK\n", __func__);
	}
#endif

	wake_unlock(&drv->idlelock);
	return;
}
Пример #7
0
static void aic3254_loopback(int mode)
{
	if (!(ctl_ops->lb_dsp_init &&
		ctl_ops->lb_receiver_imic &&
		ctl_ops->lb_speaker_imic &&
		ctl_ops->lb_headset_emic)) {
		pr_aud_info("%s: AIC3254 LOOPBACK not supported\n", __func__);
		return;
	}

	/* Init AIC3254 A00 */
	aic3254_config(ctl_ops->lb_dsp_init->data, ctl_ops->lb_dsp_init->len);

	pr_aud_info("%s: set AIC3254 in LOOPBACK mode\n", __func__);
	switch (mode) {
	case 0:
		/* receiver v.s. imic */
		aic3254_config(ctl_ops->lb_receiver_imic->data,
				ctl_ops->lb_receiver_imic->len);
		break;
	case 1:
		/* speaker v.s. imic */
		aic3254_config(ctl_ops->lb_speaker_imic->data,
				ctl_ops->lb_speaker_imic->len);
		break;
	case 2:
		/* headphone v.s emic */
		aic3254_config(ctl_ops->lb_headset_emic->data,
				ctl_ops->lb_headset_emic->len);
		break;
	case 13:
		/* receiver v.s 2nd mic */
		if (ctl_ops->lb_receiver_bmic)
			aic3254_config(ctl_ops->lb_receiver_bmic->data,
				ctl_ops->lb_receiver_bmic->len);
		else
			pr_aud_info("%s: receiver v.s. 2nd mic loopback not supported\n", __func__);
		break;

	case 14:
		/* speaker v.s 2nd mic */
		if (ctl_ops->lb_speaker_bmic)
			aic3254_config(ctl_ops->lb_speaker_bmic->data,
				ctl_ops->lb_speaker_bmic->len);
		else
			pr_aud_info("%s: speaker v.s. 2nd mic loopback not supported\n", __func__);
		break;

	case 15:
		/* headphone v.s 2nd mic */
		if (ctl_ops->lb_headset_bmic)
			aic3254_config(ctl_ops->lb_headset_bmic->data,
				ctl_ops->lb_headset_bmic->len);
		else
			pr_aud_info("%s: headset v.s. 2nd mic loopback not supported\n", __func__);
		break;
	default:
		break;
	}
}
Пример #8
0
static void aic3254_powerdown(void)
{
	int64_t t1, t2;
#if defined(CONFIG_ARCH_MSM7X30)
	struct ecodec_aic3254_state *drv = &codec_clk;
#endif


	if (aic3254_tx_mode != UPLINK_OFF || aic3254_rx_mode != DOWNLINK_OFF)
		return;

	t1 = ktime_to_ms(ktime_get());

	spi_aic3254_prevent_sleep();
	if (aic3254_uplink != NULL) {
		pr_aud_info("power off AIC3254 len(%d)++\n",
			(aic3254_uplink[POWER_OFF][0].data-1));
		aic3254_config(&aic3254_uplink[POWER_OFF][1],
				aic3254_uplink[POWER_OFF][0].data);
	} else {
		pr_aud_info("power off AIC3254 len(%d)++\n",
			(ARRAY_SIZE(CODEC_POWER_OFF)));
		aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
	}

#if defined(CONFIG_ARCH_MSM7X30)
	if (drv->enabled) {
		/* Disable MI2S RX master block */
		/* Disable MI2S RX bit clock */
		clk_disable(drv->rx_sclk);
		clk_disable(drv->rx_mclk);
		drv->enabled = 0;
		pr_aud_info("%s: disable CLK\n", __func__);
	}
#endif

	spi_aic3254_allow_sleep();

	t2 = ktime_to_ms(ktime_get())-t1;
	pr_aud_info("power off AIC3254 %lldms --\n", t2);
	return;
}
Пример #9
0
int route_rx_enable(int path, int en)
{
	pr_aud_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
	if (en) {
		/* Downlink_Wakeup */
		aic3254_config(CODEC_DOWNLINK_ON,
				ARRAY_SIZE(CODEC_DOWNLINK_ON));
		/* Path switching */
		switch (path) {
		case FM_OUT_HEADSET:
			/* FM headset */
			aic3254_config(FM_In_Headphone,
					ARRAY_SIZE(FM_In_Headphone));
			aic3254_config(FM_Out_Headphone,
					ARRAY_SIZE(FM_Out_Headphone));
			break;
		case FM_OUT_SPEAKER:
			/* FM speaker */
			aic3254_config(FM_In_SPK,
					ARRAY_SIZE(FM_In_SPK));
			aic3254_config(FM_Out_SPK,
					ARRAY_SIZE(FM_Out_SPK));
			break;
		default:
			/* By pass */
			aic3254_config(Downlink_IMIC_Receiver,
					ARRAY_SIZE(Downlink_IMIC_Receiver));
			break;
		}
	} else {
		/* Downlink_Off */
		aic3254_config(CODEC_DOWNLINK_OFF,
				ARRAY_SIZE(CODEC_DOWNLINK_OFF));
	}

	return 0;
}
Пример #10
0
static int aic3254_set_config(int config_tbl, int idx, int en)
{
	int rc = 0, len = 0;
	int64_t t1, t2;
#if defined(CONFIG_ARCH_MSM7X30)
	struct ecodec_aic3254_state *drv = &codec_clk;
#endif

	mutex_lock(&lock);
	spi_aic3254_prevent_sleep();

#if defined(CONFIG_ARCH_MSM7X30)
	if (drv->enabled == 0) {
		/* enable MI2S RX master block */
		/* enable MI2S RX bit clock */
		clk_enable(drv->rx_mclk);
		clk_enable(drv->rx_sclk);
		pr_aud_info("%s: enable CLK\n", __func__);
		drv->enabled = 1;
	}
#endif

	switch (config_tbl) {
	case AIC3254_CONFIG_TX:
		/* TX */
		pr_aud_info("%s: enable tx\n", __func__);
		if (en) {
			if (ctl_ops->tx_amp_enable)
				ctl_ops->tx_amp_enable(0);

			aic3254_tx_config(idx);
			aic3254_tx_mode = idx;

			if (ctl_ops->tx_amp_enable)
				ctl_ops->tx_amp_enable(1);
		} else {
			aic3254_tx_config(UPLINK_OFF);
			aic3254_tx_mode = UPLINK_OFF;
		}
		break;
	case AIC3254_CONFIG_RX:
		/* RX */
		pr_aud_info("%s: enable rx\n", __func__);
		if (en) {
			if (ctl_ops->rx_amp_enable)
				ctl_ops->rx_amp_enable(0);

			aic3254_rx_config(idx);
			aic3254_rx_mode = idx;

			if (ctl_ops->rx_amp_enable)
				ctl_ops->rx_amp_enable(1);
		} else {
			aic3254_rx_config(DOWNLINK_OFF);
			aic3254_rx_mode = DOWNLINK_OFF;
		}
		break;
	case AIC3254_CONFIG_MEDIA:
		if (aic3254_minidsp == NULL) {
			rc = -EFAULT;
			break;
		}

		len = (aic3254_minidsp[idx][0].reg << 8)
			| aic3254_minidsp[idx][0].data;

		pr_aud_info("%s: configure miniDSP index(%d) len = %d ++\n",
			__func__, idx, len);
		pr_aud_info("%s: rx mode %d, tx mode %d\n",
			__func__, aic3254_rx_mode, aic3254_tx_mode);

		t1 = ktime_to_ms(ktime_get());

		if (ctl_ops->rx_amp_enable)
			ctl_ops->rx_amp_enable(0);

		/* step 1: power off first */
		if (aic3254_rx_mode != DOWNLINK_OFF)
			aic3254_rx_config(DOWNLINK_OFF);

		/* step 2: config DSP */
		aic3254_config(&aic3254_minidsp[idx][1], len);

		/* step 3: switch back to original path */
		if (aic3254_rx_mode != DOWNLINK_OFF)
			aic3254_rx_config(aic3254_rx_mode);
		if (aic3254_tx_mode != UPLINK_OFF)
			aic3254_tx_config(aic3254_tx_mode);

		t2 = ktime_to_ms(ktime_get())-t1;

		if (ctl_ops->rx_amp_enable)
			ctl_ops->rx_amp_enable(1);

		pr_aud_info("%s: configure miniDSP index(%d) time: %lldms --\n",
			__func__, idx, (t2));
		break;
	}

	spi_aic3254_allow_sleep();
	mutex_unlock(&lock);
	return rc;
}
Пример #11
0
static int aic3254_set_config(int config_tbl, int idx, int en)
{
	int len;
	struct ecodec_aic3254_state *drv = &codec_clk;
	pr_aud_info("%s: table(0x%X) index(%d)\n", __func__, config_tbl, idx);

	wake_lock(&drv->idlelock);

#if defined(CONFIG_ARCH_MSM7X30)
	if (drv->enabled == 0) {
		/* enable MI2S RX master block */
		/* enable MI2S RX bit clock */
		clk_enable(drv->rx_mclk);
		clk_enable(drv->rx_sclk);
		printk("%s: enable CLK\n", __func__);
		drv->enabled = 1;
	}
#endif

	switch (config_tbl) {
	case AIC3254_CONFIG_TX:
		/* TX */
		pr_aud_info("%s: enable tx\n", __func__);
		if (en) {
			if (ctl_ops->tx_amp_enable)
				ctl_ops->tx_amp_enable(0);

			aic3254_tx_config(idx);
			aic3254_tx_mode = idx;

			if (ctl_ops->tx_amp_enable)
				ctl_ops->tx_amp_enable(1);
		} else {
			aic3254_tx_config(UPLINK_OFF);
			aic3254_tx_mode = UPLINK_OFF;
		}
		break;
	case AIC3254_CONFIG_RX:
		/* RX */
		pr_aud_info("%s: enable rx\n", __func__);
		if (en) {
			if (ctl_ops->rx_amp_enable)
				ctl_ops->rx_amp_enable(0);

			aic3254_rx_config(idx);
			aic3254_rx_mode = idx;

			if (ctl_ops->rx_amp_enable)
				ctl_ops->rx_amp_enable(1);
		} else {
			aic3254_rx_config(DOWNLINK_OFF);
			aic3254_rx_mode = DOWNLINK_OFF;
		}
		break;
	case AIC3254_CONFIG_MEDIA:
		if (aic3254_minidsp == NULL)
			return -EFAULT;
		len = (aic3254_minidsp[idx][0].reg << 8)
			| aic3254_minidsp[idx][0].data;

		pr_aud_info("%s: miniDSP command len = %d\n", __func__, len);
		pr_aud_info("%s: rx mode %d, tx mode %d\n",
			__func__, aic3254_rx_mode, aic3254_tx_mode);

		if (ctl_ops->rx_amp_enable)
			ctl_ops->rx_amp_enable(0);

		/* step 1: power off first */
		if (aic3254_rx_mode != DOWNLINK_OFF)
			aic3254_rx_config(DOWNLINK_OFF);

		/* step 2: config DSP */
		aic3254_config(&aic3254_minidsp[idx][1], len);

		/* step 3: switch back to original path */
		if (aic3254_rx_mode != DOWNLINK_OFF)
			aic3254_rx_config(aic3254_rx_mode);
		if (aic3254_tx_mode != UPLINK_OFF)
			aic3254_tx_config(aic3254_tx_mode);

		if (ctl_ops->rx_amp_enable)
			ctl_ops->rx_amp_enable(1);

		pr_aud_info("%s: configure minidsp done\n", __func__);
		break;
	}

	wake_unlock(&drv->idlelock);
	return 0;
}