diff --git a/sound/soc/codecs/wsa881x-analog.c b/sound/soc/codecs/wsa881x-analog.c index b94668e07e9a..31fb054dd326 100644 --- a/sound/soc/codecs/wsa881x-analog.c +++ b/sound/soc/codecs/wsa881x-analog.c @@ -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); diff --git a/sound/soc/codecs/wsa881x-temp-sensor.c b/sound/soc/codecs/wsa881x-temp-sensor.c index 22cc5cb1f7a9..d2c6238a030e 100644 --- a/sound/soc/codecs/wsa881x-temp-sensor.c +++ b/sound/soc/codecs/wsa881x-temp-sensor.c @@ -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, ®); + 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; } diff --git a/sound/soc/codecs/wsa881x-temp-sensor.h b/sound/soc/codecs/wsa881x-temp-sensor.h index 40a408de9881..baab68574b90 100644 --- a/sound/soc/codecs/wsa881x-temp-sensor.h +++ b/sound/soc/codecs/wsa881x-temp-sensor.h @@ -15,15 +15,22 @@ #include #include -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); diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index dc8ca4c8c3ca..63f1686629b5 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -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; }