Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef984a51 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wsa881x: update temperature reading sequence"

parents d5631440 d93f7c15
Loading
Loading
Loading
Loading
+44 −76
Original line number Diff line number Diff line
@@ -22,65 +22,19 @@
#define T2_TEMP 150
#define LOW_TEMP_THRESHOLD 5
#define HIGH_TEMP_THRESHOLD 45
#define WSA881X_OTP_REG_1	0x0081
#define WSA881X_OTP_REG_2	0x0082
#define WSA881X_OTP_REG_3	0x0083
#define WSA881X_OTP_REG_4	0x0084
#define WSA881X_TEMP_DOUT_MSB	0x000A
#define WSA881X_TEMP_DOUT_LSB	0x000B
#define TEMP_INVALID	0xFFFF
#define WSA881X_THERMAL_TEMP_OP 0x0003

static void calculate_temp(long *temp_val, int dmeas,
			struct snd_soc_codec *codec,
			int dig_base_addr)
{
	/* Tmeas = T1 + ((Dmeas - D1)/(D2 - D1))(T2 - T1) */
	int t1 = T1_TEMP;
	int t2 = T2_TEMP;
	int d1_lsb, d1_msb, d2_lsb, d2_msb;
	int d1, d2;

	d1_msb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_1);
	d1_lsb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_2);
	d2_msb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_3);
	d2_lsb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_4);

	/*
	 * Temperature register values are expected to be in the
	 * following range.
	 * d1_msb  = 68 - 92 and d1_lsb  = 0, 64, 128, 192
	 * d2_msb  = 185 -218 and  d2_lsb  = 0, 64, 128, 192
	 */
	if ((d1_msb < 68 || d1_msb > 92) ||
	    (!(d1_lsb == 0 || d1_lsb == 64 || d1_lsb == 128 ||
		d1_lsb == 192)) ||
	    (d2_msb < 185 || d2_msb > 218) ||
	    (!(d2_lsb == 0 || d2_lsb == 64 || d2_lsb == 128 ||
		d2_lsb == 192))){
		printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
				   __func__, d1_msb, d1_lsb, d2_msb, d2_lsb);
	}

	d1 = ((d1_msb << 0x8) | d1_lsb) >> 0x6;
	d2 = ((d2_msb << 0x8) | d2_lsb) >> 0x6;

	if (d1 == d2) {
		*temp_val = TEMP_INVALID;
		return;
	}
	*temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1));
}

static int wsa881x_get_temp(struct thermal_zone_device *thermal,
			unsigned long *temp)
{
	struct wsa881x_tz_priv *pdata;
	struct snd_soc_codec *codec;
	int dmeas_cur_msb, dmeas_cur_lsb;
	int dmeas;
	struct wsa_temp_register reg;
	int dmeas, d1, d2;
	int ret = 0;
	long temp_val;
	int t1 = T1_TEMP;
	int t2 = T2_TEMP;

	if (thermal->devdata) {
		pdata = thermal->devdata;
@@ -94,37 +48,51 @@ static int wsa881x_get_temp(struct thermal_zone_device *thermal,
		pr_err("%s: pdata is NULL\n", __func__);
		return -EINVAL;
	}
	ret = pdata->wsa_resource_acquire(codec, true);
	if (pdata->wsa_temp_reg_read) {
		ret = pdata->wsa_temp_reg_read(codec, &reg);
		if (ret) {
		pr_err("%s: wsa acquire failed: %d\n", __func__, ret);
			pr_err("%s: temperature register read failed: %d\n",
				__func__, ret);
			return ret;
		}
	snd_soc_update_bits(codec,
			    pdata->ana_base + WSA881X_THERMAL_TEMP_OP,
			    0x04, 0x04);
	dmeas_cur_msb =
		snd_soc_read(codec,
			pdata->ana_base + WSA881X_TEMP_DOUT_MSB);
	dmeas_cur_lsb =
		snd_soc_read(codec,
			pdata->ana_base + WSA881X_TEMP_DOUT_LSB);
	dmeas = ((dmeas_cur_msb << 0x8) | dmeas_cur_lsb) >> 0x6;
	pr_debug("%s: dmeas: %d\n", __func__, dmeas);
	calculate_temp(&temp_val, dmeas, codec, pdata->dig_base);
	*temp = temp_val;
	} else {
		pr_err("%s: wsa_temp_reg_read is NULL\n", __func__);
		return -EINVAL;
	}
	/*
	 * Temperature register values are expected to be in the
	 * following range.
	 * d1_msb  = 68 - 92 and d1_lsb  = 0, 64, 128, 192
	 * d2_msb  = 185 -218 and  d2_lsb  = 0, 64, 128, 192
	 */
	if ((reg.d1_msb < 68 || reg.d1_msb > 92) ||
	    (!(reg.d1_lsb == 0 || reg.d1_lsb == 64 || reg.d1_lsb == 128 ||
		reg.d1_lsb == 192)) ||
	    (reg.d2_msb < 185 || reg.d2_msb > 218) ||
	    (!(reg.d2_lsb == 0 || reg.d2_lsb == 64 || reg.d2_lsb == 128 ||
		reg.d2_lsb == 192))) {
		printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
				   __func__, reg.d1_msb, reg.d1_lsb, reg.d2_msb,
				   reg.d2_lsb);
	}
	dmeas = ((reg.dmeas_msb << 0x8) | reg.dmeas_lsb) >> 0x6;
	d1 = ((reg.d1_msb << 0x8) | reg.d1_lsb) >> 0x6;
	d2 = ((reg.d2_msb << 0x8) | reg.d2_lsb) >> 0x6;

	if (d1 == d2)
		temp_val = TEMP_INVALID;
	else
		temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1));

	if (temp_val <= LOW_TEMP_THRESHOLD ||
		temp_val >= HIGH_TEMP_THRESHOLD) {
		printk_ratelimited("%s: T0: %ld is out of range[%d, %d]\n",
				   __func__, temp_val, LOW_TEMP_THRESHOLD,
				   HIGH_TEMP_THRESHOLD);
		ret = -EAGAIN;
		goto rel;
	}
	pr_debug("%s: t0 measured: %ld\n", __func__, temp_val);
rel:
	ret = pdata->wsa_resource_acquire(codec, false);
	if (ret)
		pr_err("%s: wsa release failed: %d\n", __func__, ret);
	*temp = temp_val;
	pr_debug("%s: t0 measured: %ld dmeas = %d, d1 = %d, d2 = %d\n",
		  __func__, temp_val, dmeas, d1, d2);
	return ret;
}

+12 −5
Original line number Diff line number Diff line
@@ -15,15 +15,22 @@
#include <linux/thermal.h>
#include <sound/soc.h>

typedef int32_t (*wsa_rsrc_acquire)(struct snd_soc_codec *codec, bool enable);

struct wsa_temp_register {
	u8 d1_msb;
	u8 d1_lsb;
	u8 d2_msb;
	u8 d2_lsb;
	u8 dmeas_msb;
	u8 dmeas_lsb;
};
typedef int32_t (*wsa_temp_register_read)(struct snd_soc_codec *codec,
					struct wsa_temp_register *wsa_temp_reg);
struct wsa881x_tz_priv {
	struct thermal_zone_device *tz_dev;
	struct snd_soc_codec *codec;
	int dig_base;
	int ana_base;
	struct wsa_temp_register *wsa_temp_reg;
	char name[80];
	wsa_rsrc_acquire wsa_resource_acquire;
	wsa_temp_register_read wsa_temp_reg_read;
};

int wsa881x_init_thermal(struct wsa881x_tz_priv *tz_pdata);
+23 −7
Original line number Diff line number Diff line
@@ -902,8 +902,8 @@ static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec,
	return 0;
}

static int32_t wsa881x_thermal_resource_acquire(struct snd_soc_codec *codec,
						bool enable)
static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
				     struct wsa_temp_register *wsa_temp_reg)
{
	struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
	struct swr_device *dev;
@@ -923,7 +923,26 @@ static int32_t wsa881x_thermal_resource_acquire(struct snd_soc_codec *codec,
		}
		regcache_sync(wsa881x->regmap);
	}
	wsa881x_resource_acquire(codec, enable);
	wsa881x_resource_acquire(codec, ENABLE);

	snd_soc_update_bits(codec, WSA881X_TEMP_OP, 0x04, 0x04);
	if (WSA881X_IS_2_0(wsa881x->version)) {
		snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
		wsa_temp_reg->dmeas_msb = snd_soc_read(codec, WSA881X_TEMP_MSB);
		wsa_temp_reg->dmeas_lsb = snd_soc_read(codec, WSA881X_TEMP_LSB);
		snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x01);
	} else {
		wsa_temp_reg->dmeas_msb = snd_soc_read(codec,
						   WSA881X_TEMP_DOUT_MSB);
		wsa_temp_reg->dmeas_lsb = snd_soc_read(codec,
						   WSA881X_TEMP_DOUT_LSB);
	}
	wsa_temp_reg->d1_msb = snd_soc_read(codec, WSA881X_OTP_REG_1);
	wsa_temp_reg->d1_lsb = snd_soc_read(codec, WSA881X_OTP_REG_2);
	wsa_temp_reg->d2_msb = snd_soc_read(codec, WSA881X_OTP_REG_3);
	wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4);

	wsa881x_resource_acquire(codec, DISABLE);

	return 0;
}
@@ -962,10 +981,7 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
	wsa881x->clk_cnt = 0;
	wsa881x->state = WSA881X_DEV_UP;
	wsa881x->tz_pdata.codec = codec;
	wsa881x->tz_pdata.dig_base = WSA881X_DIGITAL_BASE;
	wsa881x->tz_pdata.ana_base = WSA881X_ANALOG_BASE;
	wsa881x->tz_pdata.wsa_resource_acquire =
				wsa881x_thermal_resource_acquire;
	wsa881x->tz_pdata.wsa_temp_reg_read = wsa881x_temp_reg_read;
	wsa881x_init_thermal(&wsa881x->tz_pdata);
	return ret;
}