ASoC: wsa881x: update temperature reading sequence

Temperature reading sequence is updated in wsa881x version 2.0.
This change is to add new sequence for temperature reading.

Change-Id: Ide1dbc5ef450c5e67f10ee038a5763b9d45008f6
Signed-off-by: Vidyakumar Athota <vathota@codeaurora.org>
This commit is contained in:
Vidyakumar Athota 2015-08-10 21:16:24 -07:00 committed by Gerrit - the friendly Code Review server
parent 95317388d6
commit 5923a37c0b
4 changed files with 114 additions and 92 deletions

View file

@ -927,6 +927,39 @@ static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec,
return ret;
}
static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
struct wsa_temp_register *wsa_temp_reg)
{
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
if (!wsa881x) {
dev_err(codec->dev, "%s: wsa881x is NULL\n", __func__);
return -EINVAL;
}
wsa881x_resource_acquire(codec, true);
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, false);
return 0;
}
static int wsa881x_probe(struct snd_soc_codec *codec)
{
struct i2c_client *client;
@ -950,10 +983,8 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
wsa_pdata[wsa881x_index].spk_pa_gain = SPK_GAIN_12DB;
wsa_pdata[wsa881x_index].codec = codec;
wsa_pdata[wsa881x_index].tz_pdata.codec = codec;
wsa_pdata[wsa881x_index].tz_pdata.dig_base = WSA881X_DIGITAL_BASE;
wsa_pdata[wsa881x_index].tz_pdata.ana_base = WSA881X_ANALOG_BASE;
wsa_pdata[wsa881x_index].tz_pdata.wsa_resource_acquire =
wsa881x_resource_acquire;
wsa_pdata[wsa881x_index].tz_pdata.wsa_temp_reg_read =
wsa881x_temp_reg_read;
snd_soc_codec_set_drvdata(codec, &wsa_pdata[wsa881x_index]);
wsa881x_init_thermal(&wsa_pdata[wsa881x_index].tz_pdata);

View file

@ -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 (ret) {
pr_err("%s: wsa acquire failed: %d\n", __func__, ret);
return ret;
if (pdata->wsa_temp_reg_read) {
ret = pdata->wsa_temp_reg_read(codec, &reg);
if (ret) {
pr_err("%s: temperature register read failed: %d\n",
__func__, ret);
return ret;
}
} else {
pr_err("%s: wsa_temp_reg_read is NULL\n", __func__);
return -EINVAL;
}
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;
/*
* 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",
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;
}

View file

@ -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);

View file

@ -912,8 +912,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;
@ -933,7 +933,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;
}
@ -979,10 +998,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;
}