On Tue, Sep 03, 2024 at 02:44:33PM +0900, Kiseok Jo wrote:
This looks basically fine, there's some mostly minor or stylistic things below but nothing too major.
+static int sma1307_regmap_write(struct sma1307_priv *sma1307,
unsigned int reg, unsigned int val)
+{
- int ret = 0;
- int cnt = sma1307->retry_cnt;
- while (cnt--) {
ret = regmap_write(sma1307->regmap, reg, val);
if (ret == 0)
break;
- }
If the hardware is actually stable we probably shouldn't bother with these wrappers. If they really are needed then we might want to consider having regmap support doing retries.
- if (sma1307->force_mute_status == val)
change = false;
- else {
change = true;
sma1307->force_mute_status = val;
- }
If one side of the if has {} both sides should.
- } else {
dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
__func__, kcontrol->id.name);
return -EINVAL;
- }
We shouldn't log errors that userspace can easily trigger like this, it lets people DoS the logs - just return the error code (a bunch of the other controls have this).
+static int sma1307_reset_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
- struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
- bool val = (bool)ucontrol->value.integer.value[0];
- if (sma1307->reset == val)
return false;
- sma1307->reset = val;
- if (ucontrol->value.integer.value[0] != 0
&& ucontrol->value.integer.value[0] != 1) {
dev_err(sma1307->dev, "%s: Invalid value\n", __func__);
return false;
- }
You probably don't need to store a value here, you can just always read 0 for the control. It's how other similar one shot controls work IIRC.
- sma1307_regmap_update_bits(sma1307, SMA1307_00_SYSTEM_CTRL,
SMA1307_RESET_MASK, SMA1307_RESET_ON);
- sma1307_reset(component);
This should really generate a change notification for all the controls with non-default values (or all the controls would be easier and probably fine, it's not like this is going to be a particularly pretty process for userspace whatever happens). snd_ctl_notify() does this.
It'd also be good to have a comment about why we've got this.
+static int sma1307_dapm_amp_enable_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct snd_soc_dapm_context *dapm =
snd_soc_dapm_kcontrol_dapm(kcontrol);
- struct sma1307_priv *sma1307 =
snd_soc_component_get_drvdata(dapm->component);
- int val = (int)ucontrol->value.integer.value[0];
- bool change;
- if ((val < 0) || (val > 1)) {
dev_err(sma1307->dev, "%s: Out of range\n", __func__);
return -EINVAL;
- }
- if (sma1307->dapm_amp_en != val) {
change = true;
sma1307->dapm_amp_en = val;
I didn't manage to find what reads this value - do we need this control at all, I'm not clear what it does? If it's for stopping the amp from coming on the normal approach is for the board to register a _PIN_SWITCH() DAPM control attached to whatever the end output is for the path, that will cause DAPM to not power anything in the output path up.
A similar thing is true for at least the binary_mode control, I can't see where the written value is read.
+static void sma1307_check_fault_worker(struct work_struct *work) +{
- ret = sma1307_regmap_read(sma1307, SMA1307_FA_STATUS1, &status1_val);
- if (ret != 0) {
dev_err(sma1307->dev,
"%s: failed to read SMA1307_FA_STATUS1 : %d\n",
__func__, ret);
return;
- }
- ret = sma1307_regmap_read(sma1307, SMA1307_FB_STATUS2, &status2_val);
- if (ret != 0) {
dev_err(sma1307->dev,
"%s: failed to read SMA1307_FB_STATUS2 : %d\n",
__func__, ret);
return;
- }
If we manage to read one of the registers should we perhaps soldier on and try to report any errors it shows? Probably a bit academic.
- if (~status1_val & SMA1307_OT1_OK_STATUS) {
dev_crit(sma1307->dev,
"%s: OT1(Over Temperature Level 1)\n", __func__);
if (sma1307->sw_ot1_prot) {
/* Volume control (Current Volume -3dB) */
if ((sma1307->cur_vol + 6) <= 0xFA)
sma1307_regmap_write(sma1307,
SMA1307_0A_SPK_VOL,
sma1307->cur_vol + 6);
}
sma1307->tsdw_cnt++;
This is changing a user visible control so it should really generate an event, although given that it should never happen it's not the end of the world. Given that a lot of other speaker drivers have a similar setup with warning and critical temperature alerts I actually wonder if we should consider factoring this out as a helper other things can use, that's definitely a separate thing though and you don't need to do it right now.
+static DEVICE_ATTR_RW(check_fault_period);
Any reason the fault stuff isn't an ALSA control?
+static const struct regmap_config sma_i2c_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = SMA1307_FF_DEVICE_INDEX,
- .readable_reg = sma1307_readable_register,
- .writeable_reg = sma1307_writeable_register,
- .volatile_reg = sma1307_volatile_register,
- .cache_type = REGCACHE_NONE,
_NONE is the default, although given that you've described the volatile registers I don't see why you wouldn't just enable _MAPLE. There's regcache_drop_region() which can be used to throw away cached values during reset if you want to do that. Most drivers use a cache to help make suspend/resume easier to implement - if the device looses power you can just write the cache contents back to it to restore most userspace visible things.
Not doing a cache (or suspend/resume) is also OK though, it can always be implemented when needed.
+++ b/sound/soc/codecs/sma1307.h @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later
- sma1307.h -- sma1307 ALSA SoC Audio driver
- r005,
- Copyright 2023 Iron Device Corporation
2024 now!