/**
 * ctp_read_adc_temp - read ADC sensor to get the temperature
 * @tmp: op parameter where temperature get's read
 *
 * Returns 0 if success else -1 or -ERANGE
 */
static int platform_read_adc_temp(int *temp,
			const int bptherm_curve_data
			[BPTHERM_CURVE_MAX_SAMPLES][BPTHERM_CURVE_MAX_VALUES])
{
	int gpadc_sensor_val = 0;
	int ret;

	pr_debug("%s, handle = %x\n", __func__,
				(unsigned int)chgr_gpadc_handle);

	if (chgr_gpadc_handle == NULL) {
		ret = -ENODEV;
		goto read_adc_exit;
	}

	ret = intel_mid_gpadc_sample(chgr_gpadc_handle,
				GPADC_BPTHERM_SAMPLE_COUNT,
				&gpadc_sensor_val);
	if (ret) {
		pr_err("EM:%s:adc driver api returned error(%d)\n",
							__func__, ret);
		goto read_adc_exit;
	}

	ret = platform_adc_to_temp(gpadc_sensor_val, temp, bptherm_curve_data);
read_adc_exit:
	return ret;
}
/**
 * mid_read_temp - read sensors for temperature
 * @temp: holds the current temperature for the sensor after reading
 *
 * reads the adc_code from the channel and converts it to real
 * temperature. The converted value is stored in temp.
 *
 * Can sleep
 */
static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp)
{
	struct thermal_device_info *td_info = tzd->devdata;
	int ret;
	long curr_temp, bp_temp = 0;
	int indx = td_info->sensor_index; /* Required Index */

	mutex_lock(&ipcinfo->cacheinfo.lock);

	if (!ipcinfo->cacheinfo.is_cached_data_initialized ||
	time_after(jiffies, ipcinfo->cacheinfo.last_updated + HZ)) {
		ret = intel_mid_gpadc_sample(
			ipcinfo->therm_adc_handle, 1,
			&ipcinfo->cacheinfo.cached_values[0],
			&ipcinfo->cacheinfo.cached_values[1],
			&ipcinfo->cacheinfo.cached_values[2],
			&ipcinfo->cacheinfo.cached_values[3]);
		if (ret)
			goto exit;
		ipcinfo->cacheinfo.last_updated = jiffies;
		ipcinfo->cacheinfo.is_cached_data_initialized = true;
	}

	/* Convert ADC value to temperature */
	ret = adc_to_temp(td_info->direct,
		ipcinfo->cacheinfo.cached_values[indx],
		&curr_temp);
	if (ret)
		goto exit;

	switch (indx) {
	case SKIN0_INDEX:
		*temp = SKIN0_TEMP(curr_temp);
		break;
	case SKIN1_INDEX:
#ifdef CONFIG_BOARD_CTP
		ret = adc_to_temp(td_info->direct,
			ipcinfo->cacheinfo.cached_values[BPTHERM_INDEX],
			&bp_temp);
		if (ret)
			goto exit;
		bp_temp = (bp_temp * BPTHERM_SLOPE)/1000 + BPTHERM_INTERCEPT;
#endif
		*temp = SKIN1_TEMP(curr_temp);

		/* Max(Back Skin Thermistor temp, BPTHERM value) */
		if (bp_temp > *temp)
			*temp = bp_temp;
		break;
	default:
		*temp = curr_temp;
	}

exit:
	mutex_unlock(&ipcinfo->cacheinfo.lock);
	return ret;
}
/* reads the voltage level from the ADC Driver*/
unsigned int mfld_jack_read_voltage(struct snd_soc_jack *jack)
{
	unsigned int mic_bias;
	struct mfld_mc_private *ctx =
			snd_soc_card_get_drvdata(jack->codec->card);

	/* Reads the mic bias value */
	if (!ctx->mfld_jack_lp_flag)
		/* GPADC MIC BIAS takes around a 50ms to settle down and
		* get sampled porperly, reading earlier than this causes to
		* read incorrect values */
		msleep(50);
	intel_mid_gpadc_sample(ctx->audio_adc_handle,
			MFLD_ADC_SAMPLE_COUNT, &mic_bias);
	mic_bias = (mic_bias * MFLD_ADC_ONE_LSB_MULTIPLIER) / 1000;
	pr_debug("mic bias = %dmV\n", mic_bias);
	return mic_bias;
}
/* This function checks if the inserted accessory is thermal probe.
   If yes, keeps the bias and mux approprate for thermal
   probe so that the sensor driver can just read the adc voltage.
   Informs userspace and sensor driver of the insertion event
   and returns true
   If no, keeps the settings for Audio and returns false
*/
bool mfld_therm_probe_on_connect(struct snd_soc_jack *jack)
{
	int voltage = 0;
	int gpio_state;
	bool tp_status = false;
	void *adc_handle =  NULL;
	struct mfld_mc_private *ctx =
		snd_soc_card_get_drvdata(jack->codec->card);
	struct mfld_therm_probe_data  *tp_data_ptr;

	tp_data_ptr = &ctx->tp_data;

	gpio_state = mfld_read_jack_gpio(ctx);
	if (gpio_state != 0) {
		/* This situation can occur during bootup without any accessory
		   connected. We reach here because we initiate accessory
		   detection manually in the init function */
		pr_debug("In therm probe check; but no acc attached;"
			" returning\n");
		return tp_status;
	}
	/*If audio jack already connected;dont proceed with thermal probe det*/
	if (jack->status & (SND_JACK_HEADSET | SND_JACK_HEADPHONE)) {
		pr_debug("Therm probe det: spurious intr: Audio Jack "
					" already connected\n");
		return false;
	}
	/*If thermal probe already connected;dont proceed with det*/
	if (tp_data_ptr->tp_status) {
		pr_debug("Therm probe det: spurious intr:Thermal probe "
					" already connected\n");
		return true;
	}

	if (tp_data_ptr->tp_en_gpio < 0) {
		pr_err("therm probe gpio not valid; returning\n");
		/* If therm probe en gpio is not valid right channel
		   audio will also not work. But atleast enable left
		   channel audio(unground HSL/HSR) and return */
		snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(1), 0);
		return tp_status;
	}

	/* GPADC handle for therm probe detection; ADC channel is allocated
	   and deallocated in this fuction so that sensor driver can allocate
	   it and read the ADC after we report thermal probe connection*/
	adc_handle = intel_mid_gpadc_alloc(MFLD_THERM_PROBE_SENSOR,
			tp_data_ptr->tp_adc_ch_id);
	if (!adc_handle) {
		pr_err("therm probe adc handle not valid; returning\n");
		/* If therm probe adc handle is not valid, enable audio
		   and return. UnGround HSL and HSR of MSIC and Mux right
		   ch. headset pin to HSR of MSIC */
		snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(1), 0);
		gpio_direction_output(tp_data_ptr->tp_en_gpio, 1);
		return tp_status;
	}


	/* Ground HSL and HSR of MSIC */
	snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(1), BIT(1));
	/* Mux right ch. headset pin to ADC*/
	gpio_direction_output(tp_data_ptr->tp_en_gpio, 0);

	/* Enable mic bias 2 for therm probe check */
	mfld_jack_enable_mic_bias_gen(jack->codec, "AMIC2Bias");
	msleep(50);

	/* Read ADIN11 */
	intel_mid_gpadc_sample(adc_handle, 1, &voltage);
	voltage = (voltage * MFLD_ADC_ONE_LSB_MULTIPLIER) / 1000;

	intel_mid_gpadc_free(adc_handle);

	if (voltage < MFLD_TP_VOLT_THLD_LOW ||
			voltage > MFLD_TP_VOLT_THLD_HI) {

		/* Connected accessory is not thermal probe.
		   Enable audio jack detection and audio */
		/* UnGround HSL and HSR of MSIC */
		snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(1), 0);
		/* Mux right ch. headset pin to HSR of MSIC */
		gpio_direction_output(tp_data_ptr->tp_en_gpio, 1);
		mfld_jack_disable_mic_bias_gen(jack->codec, "AMIC2Bias");
		tp_status = false;
	} else {

		tp_status = true;
		if (tp_data_ptr->tp_status != tp_status) {
			tp_data_ptr->tp_status = tp_status;
			pr_debug("thermal probe connected\n");
		}
	}
	pr_debug("%s: therm_probe_state = %d voltage = %d\n", __func__,
			tp_status, voltage);
	return tp_status;
}