예제 #1
0
static int es705_set_tristate(struct snd_soc_dai *dai, int tristate)
{
	unsigned int msg, resp;
	int ret;
	static int old_tristate = -1;

	return 0;

	if (escore_priv.flag.is_fw_ready == 0) {
		pr_warn("%s(): es705 firmware is not ready, abort\n", __func__);
		return 0;
	}

	//if (old_tristate == tristate)
	//	return 0;

	printk("++%s()++: %s DHWPT\n", __func__,
		   tristate == ES705_DHWPT_RST ? "disable" : "enable");

	switch (tristate) {
	case ES705_DHWPT_RST:
	case ES705_DHWPT_A_B:
	case ES705_DHWPT_A_C:
	case ES705_DHWPT_A_D:
	case ES705_DHWPT_B_A:
	case ES705_DHWPT_B_C:
	case ES705_DHWPT_B_D:
	case ES705_DHWPT_C_A:
	case ES705_DHWPT_C_B:
	case ES705_DHWPT_C_D:
	case ES705_DHWPT_D_A:
	case ES705_DHWPT_D_B:
	case ES705_DHWPT_D_C:
		break;
	default:
		dev_err(dai->dev, "Unsupported dhwpt mode %d\n", tristate);
		ret = -EINVAL;
		goto out;
	}

	msg = ES705_DHWPT_COMMAND + tristate;
	ret = escore_cmd(&escore_priv, msg, &resp);
	if (ret < 0) {
		dev_err(dai->dev, "escore_cmd: send %08x failed\n", msg);
		goto out;
	}

	old_tristate = tristate;

out:
	return ret;
}
int macro_cmd(void *ctx, u32 cmd)
{
	struct escore_priv *escore = (struct escore_priv *)ctx;
	int rc;
	rc = escore_cmd(escore, cmd);
	if (!(cmd & BIT(28))) {
		pr_debug("escore: cmd=0x%08x Response:0x%08x\n", cmd,
				escore->bus.last_response);
	} else {
		pr_debug("escore: cmd=0x%08x\n", cmd);
	}
	return rc;
}
int escore_write(struct snd_soc_codec *codec, unsigned int reg,
		       unsigned int value)
{
	struct escore_priv *escore = &escore_priv;
	struct escore_api_access *api_access;
	u32 api_word[2] = {0};
	int msg_len;
	unsigned int val_mask;
	int i;
	int rc = 0;

	if (reg > escore->api_addr_max) {
		pr_err("%s(): invalid address = 0x%04x\n", __func__, reg);
		return -EINVAL;
	}

	pr_debug("%s(): reg=%08x val=%d\n", __func__, reg, value);

	api_access = &escore->escore_api_access[reg];
	msg_len = api_access->write_msg_len;
	val_mask = (1 << get_bitmask_order(api_access->val_max)) - 1;
	memcpy((char *)api_word, (char *)api_access->write_msg, msg_len);

	switch (msg_len) {
	case 8:
		api_word[1] |= (val_mask & value);
		break;
	case 4:
		api_word[0] |= (val_mask & value);
		break;
	}

	pr_debug("%s(): mutex lock\n", __func__);
	mutex_lock(&escore->api_mutex);
	for (i = 0; i < msg_len / 4; i++) {
		rc = escore_cmd(escore, api_word[i]);
		if (rc < 0) {
			pr_err("%s(): escore_cmd()", __func__);
			pr_info("%s(): mutex unlock\n", __func__);
			mutex_unlock(&escore->api_mutex);
			return rc;
		}
	}
	pr_debug("%s(): mutex unlock\n", __func__);
	mutex_unlock(&escore->api_mutex);

	return rc;
}
int escore_write_block(struct escore_priv *escore, const u32 *cmd_block)
{
	int rc = 0;

	pr_debug("%s(): pm_runtime_get_sync()\n", __func__);
	pr_debug("%s(): mutex lock\n", __func__);
	mutex_lock(&escore->api_mutex);
	while (*cmd_block != 0xffffffff) {
		escore_cmd(escore, *cmd_block);
		usleep_range(1000, 1000);
		cmd_block++;
	}
	pr_debug("%s(): mutex unlock\n", __func__);
	mutex_unlock(&escore->api_mutex);
	pr_debug("%s(): pm_runtime_put_autosuspend()\n", __func__);

	return rc;
}
unsigned int escore_read(struct snd_soc_codec *codec,
			       unsigned int reg)
{
	struct escore_priv *escore = &escore_priv;
	struct escore_api_access *api_access;
	u32 api_word[2] = {0};
	unsigned int msg_len;
	unsigned int value;
	int rc;

	if (reg > escore->api_addr_max) {
		pr_err("%s(): invalid address = 0x%04x\n", __func__, reg);
		return -EINVAL;
	}

	api_access = &escore->escore_api_access[reg];
	msg_len = api_access->read_msg_len;
	memcpy((char *)api_word, (char *)api_access->read_msg, msg_len);

	pr_debug("%s(): mutex lock\n", __func__);
	mutex_lock(&escore->api_mutex);
	rc = escore_cmd(escore, api_word[0]);
	if (rc < 0) {
		pr_err("%s(): escore_xxxx_write()", __func__);
		pr_debug("%s(): mutex unlock\n", __func__);
		mutex_unlock(&escore->api_mutex);
		return rc;
	}
	api_word[0] = escore->last_response;
	pr_debug("%s(): mutex unlock\n", __func__);
	mutex_unlock(&escore->api_mutex);

	value = api_word[0] & 0xffff;

	return value;
}
예제 #6
0
static int es705_hw_params(struct snd_pcm_substream *substream,
			       struct snd_pcm_hw_params *params,
			       struct snd_soc_dai *dai)
{
	unsigned int base = dai->driver->base;
	unsigned int msg, resp;
	int ret, val;
	u32 cmd_block[3];

	return 0;

	if (escore_priv.flag.is_fw_ready == 0) {
		pr_warn("%s(port-%c): es705 firmware is not ready, abort\n",
				__func__, PORT_NAME(base));
		return 0;
	}

	/* word length */
	//if (es705_ports[PORT_ID(base)].wl != params_format(params))
	{
		printk("++%s(port-%c)++: format=%d\n", __func__, PORT_NAME(base),
			   params_format(params));

		val = snd_pcm_format_width(params_format(params)) - 1;
		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_WORDLENGHT;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}

		es705_ports[PORT_ID(base)].wl = params_format(params);
	}

	/* sample rate */
	//if (es705_ports[PORT_ID(base)].rate != params_rate(params))
	{
		printk("++%s(port-%c)++: rate=%d\n", __func__, PORT_NAME(base),
			   params_rate(params));

		msg = ES705_PORT_GET_PARAM + base + ES705_PORT_CLOCK;
		ret = escore_cmd(&escore_priv, msg, &resp);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send %08x failed\n", msg);
			goto out;
		}

		val = (resp & 0x100) + (params_rate(params) / 1000);
		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_CLOCK;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}

		es705_ports[PORT_ID(base)].rate = params_rate(params);
	}

out:
	return ret;
}
예제 #7
0
static int es705_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	unsigned int base = dai->driver->base;
	unsigned int msg, resp;
	int ret = 0, val;
	u32 cmd_block[3];

	return 0;

	if (escore_priv.flag.is_fw_ready == 0) {
		pr_warn("%s(): es705 firmware is not ready, abort\n", __func__);
		return 0;
	}

	//if (es705_ports[PORT_ID(base)].fmt == fmt)
	//	return 0;

	/* port mode */
	if (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
		printk("++%s(port-%c)++: port-mode=%s\n", __func__, PORT_NAME(base),
			   (fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S ?
			   "i2s" : "pcm");

		switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
		case SND_SOC_DAIFMT_DSP_A:
			val = 0x00;
			break;
		case SND_SOC_DAIFMT_I2S:
			val = 0x01;
			break;
		default:
			dev_err(dai->dev, "Unsupported DAI format %d\n",
					fmt & SND_SOC_DAIFMT_FORMAT_MASK);
			ret =  -EINVAL;
			goto out;
		}

		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_MODE;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}

		/* latch edge: Tx on Falling Edge, Rx on Rising Edge */
		if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
			cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_LATCHEDGE;
			cmd_block[1] = ES705_PORT_SET_PARAM + 0x01;
			cmd_block[2] = 0xffffffff;
			ret = escore_write_block(&escore_priv, cmd_block);
			if (ret < 0) {
				dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
					cmd_block[0], cmd_block[2]);
				goto out;
			}
		}
	}

	/* master mode */
	if (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
		printk("++%s(port-%c)++: clock-mode=%s\n", __func__, PORT_NAME(base),
			   (fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS ?
			   "slave" : "master");

		msg = ES705_PORT_GET_PARAM + base + ES705_PORT_CLOCK;
		ret = escore_cmd(&escore_priv, msg, &resp);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send %08x failed\n", msg);
			goto out;
		}

		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
		case SND_SOC_DAIFMT_CBS_CFS:
			val = resp & 0xff; // slave: bit8 = 0
			break;
		case SND_SOC_DAIFMT_CBM_CFM:
			val = (resp & 0xff) | 0x100; // master: bit8 = 1
			break;
		default:
			dev_err(dai->dev, "Unsupported master mode %d\n",
					fmt & SND_SOC_DAIFMT_MASTER_MASK);
			ret = -EINVAL;
			goto out;
		}

		cmd_block[0] = ES705_PORT_PARAM_ID + base + ES705_PORT_CLOCK;
		cmd_block[1] = ES705_PORT_SET_PARAM + val;
		cmd_block[2] = 0xffffffff;
		ret = escore_write_block(&escore_priv, cmd_block);
		if (ret < 0) {
			dev_err(dai->dev, "escore_cmd: send [%08x %08x] failed\n",
				cmd_block[0], cmd_block[2]);
			goto out;
		}
	}

	es705_ports[PORT_ID(base)].fmt = fmt;

out:
	return ret;
}
예제 #8
0
/* This function must be called with access_lock acquired */
static int escore_uart_int_osc_calibration(struct escore_priv *escore)
{
	u16 configure_uart = cpu_to_be16(0x00);
	int sync_retry = ES_SYNC_MAX_RETRY;
	u32 resp;
	int rc = 0;

	if (escore->bus.ops.high_bw_open) {
		rc = escore->bus.ops.high_bw_open(escore);
		if (rc < 0) {
			dev_err(escore->dev, "%s(): high_bw_open failed %d\n",
			__func__, rc);
			goto exit_osc_calib;
		}
	}

	do {
		rc = escore_cmd(escore,
				(ES_INT_OSC_MEASURE_START_VS << 16),
				&resp);
		if (rc) {
			dev_err(escore->dev, "%s(): sending start UART calibration command failed %d",
					__func__, rc);
			continue;
		}

		rc = escore->bus.ops.high_bw_write(escore,
			&configure_uart, sizeof(configure_uart));
		if (rc < 0) {
			dev_err(escore->dev, "%s(): sending configure command on uart failed %d",
					__func__, rc);
			continue;
		}

		usleep_range(5000, 5005);

		rc = escore_cmd(escore,
				(ES_INT_OSC_MEASURE_QUERY_VS << 16),
				&resp);
		if (rc) {
			dev_err(escore->dev, "%s(): sending check UART calibration command failed %d",
					__func__, rc);
		} else if (resp ==
				(ES_INT_OSC_MEASURE_QUERY_VS << 16)) {
			dev_dbg(escore->dev, "%s(): caliberation was successful",
					__func__);
			break;
		} else {
			dev_err(escore->dev, "%s(): caliberation response 0x%08x",
					__func__, resp);
		}

	} while (--sync_retry);

	dev_dbg(escore->dev, "%s(), number of tries made : %d",
		__func__, ES_SYNC_MAX_RETRY - sync_retry + 1);

	if (!sync_retry) {
		/* In case of any issue switch the clock to ext oscillator */
		rc = escore_switch_ext_osc(escore);
		if (rc) {
			dev_err(escore->dev,
				"%s(): Error switching to external OSC %d\n",
				__func__, rc);
		}
	}
	usleep_range(2000, 2005);

	if (escore->bus.ops.high_bw_close) {
		dev_dbg(escore->dev, "%s(), closing the UART",
							__func__);
		escore->bus.ops.high_bw_close(escore);
	}

exit_osc_calib:
	return rc;
}
예제 #9
0
파일: escore-vs.c 프로젝트: SelfImp/m75
int escore_vs_load(struct escore_priv *escore)
{
	struct escore_voice_sense *voice_sense =
			(struct escore_voice_sense *) escore->voice_sense;
	int rc = 0;
	int write_size = ES_VS_FW_CHUNK;
	int data_remaining = voice_sense->vs->size;
	u32 sync_cmd = (ES_EVENT_RESPONSE_CMD << 16) | ES_SYNC_INTR_RISING_EDGE;
	u32 resp;

	BUG_ON(voice_sense->vs->size == 0);

	if (!escore->boot_ops.setup || !escore->boot_ops.finish) {
		dev_err(escore->dev,
			"%s(): boot setup or finish function undefined\n",
			__func__);
		rc = -EIO;
		goto escore_vs_fw_download_failed;
	}

	rc = escore->boot_ops.setup(escore);
	if (rc) {
		dev_err(escore->dev, "%s(): fw download start error\n",
			__func__);
		goto escore_vs_fw_download_failed;
	}

	dev_dbg(escore->dev, "%s(): write vs firmware image\n", __func__);

	while (data_remaining) {
		rc = escore->bus.ops.high_bw_write(escore,
			((char *)voice_sense->vs->data)
			+ (voice_sense->vs->size - data_remaining), write_size);

		data_remaining -= write_size;

		dev_dbg(escore->dev,
			"data_remaining = %d, write_size = %d\n",
			data_remaining, write_size);

		if (rc) {
			dev_err(escore->dev,
				"%s(): vs firmware image write error\n",
				__func__);
			rc = -EIO;
			goto escore_vs_fw_download_failed;
		} else if (data_remaining < write_size) {
			write_size = data_remaining;
		}

		usleep_range(2000, 2000);
	}

	escore->mode = VOICESENSE;

	if (((struct escore_voice_sense *)escore->voice_sense)->vs_irq != true)
		escore_vs_init_intr(escore);

	rc = escore->boot_ops.finish(escore);
	if (rc) {
		dev_err(escore->dev, "%s() vs fw download finish error\n",
			__func__);
		goto escore_vs_fw_download_failed;
	} else {
		/* Enable Voice Sense Event INTR to Host */
		rc = escore_cmd(escore, sync_cmd, &resp);
		if (rc)
			dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
								__func__, rc);

		if (resp != sync_cmd) {
			dev_err(escore->dev,
				"%s(): Enable VS Event INTR fail\n", __func__);
			goto escore_vs_fw_download_failed;
		}
	}

	dev_dbg(escore->dev, "%s(): fw download done\n", __func__);

escore_vs_fw_download_failed:
	return rc;
}
예제 #10
0
파일: escore-vs.c 프로젝트: SelfImp/m75
static int escore_vs_isr(struct notifier_block *self, unsigned long action,
		void *dev)
{
	struct escore_priv *escore = (struct escore_priv *)dev;
	struct escore_voice_sense *voice_sense =
		(struct escore_voice_sense *) escore->voice_sense;
	u32 smooth_mute = ES_SET_SMOOTH_MUTE << 16 | ES_SMOOTH_MUTE_ZERO;
	u32 es_set_power_level = ES_SET_POWER_LEVEL << 16 | ES_POWER_LEVEL_6;
	u32 resp;
	int rc = 0;

	dev_dbg(escore->dev, "%s(): Event: 0x%04x\n", __func__, (u32)action);

	if ((action & 0xFF) != ES_VS_INTR_EVENT) {
		dev_err(escore->dev, "%s(): Invalid event callback 0x%04x\n",
				__func__, (u32) action);
		return NOTIFY_DONE;
	}
	dev_info(escore->dev, "%s(): VS event detected 0x%04x\n",
				__func__, (u32) action);

	if (voice_sense->cvs_preset != 0xFFFF && voice_sense->cvs_preset != 0) {
		escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
		escore->vs_pm_state = ES_PM_NORMAL;
		escore->non_vs_pm_state = ES_PM_NORMAL;
		escore->mode = STANDARD;
	}

	mutex_lock(&voice_sense->vs_event_mutex);
	voice_sense->vs_get_event = action;
	mutex_unlock(&voice_sense->vs_event_mutex);

	/* If CVS preset is set (other than 0xFFFF), earSmart chip is
	 * in CVS mode. To make it switch from internal to external
	 * oscillator, send power level command with highest power
	 * level
	 */
	if (voice_sense->cvs_preset != 0xFFFF &&
			voice_sense->cvs_preset != 0) {

		rc = escore_cmd(escore, smooth_mute, &resp);
		if (rc < 0) {
			pr_err("%s(): Error setting smooth mute\n", __func__);
			goto voiceq_isr_exit;
		}
		usleep_range(2000, 2005);
		rc = escore_cmd(escore, es_set_power_level, &resp);
		if (rc < 0) {
			pr_err("%s(): Error setting power level\n", __func__);
			goto voiceq_isr_exit;
		}
		usleep_range(2000, 2005);

		/* Each time earSmart chip comes in BOSKO mode after
		 * VS detect, CVS mode will be disabled */
		voice_sense->cvs_preset = 0;
	}
	kobject_uevent(&escore->dev->kobj, KOBJ_CHANGE);

	return NOTIFY_OK;

voiceq_isr_exit:
	return NOTIFY_DONE;
}