[alsa-devel] [PATCH 1/3] ASoC: SSM2602: Add sysclk based rate constraints
Not all advertised rates are available for all sysclk frequencies. Add additional sysclk based rate constraints.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ssm2602.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 4c94fd2..dcedd74 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -53,6 +53,7 @@ enum ssm2602_type { /* codec private data */ struct ssm2602_priv { unsigned int sysclk; + struct snd_pcm_hw_constraint_list *sysclk_constraints; enum snd_soc_control_type control_type; struct snd_pcm_substream *master_substream; struct snd_pcm_substream *slave_substream; @@ -195,6 +196,24 @@ static const struct snd_soc_dapm_route ssm2604_routes[] = { {"ADC", NULL, "Line Input"}, };
+static const unsigned int ssm2602_rates_12288000[] = { + 8000, 32000, 48000, 96000, +}; + +static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { + .list = ssm2602_rates_12288000, + .count = ARRAY_SIZE(ssm2602_rates_12288000), +}; + +static const unsigned int ssm2602_rates_11289600[] = { + 8000, 44100, 88200, +}; + +static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { + .list = ssm2602_rates_11289600, + .count = ARRAY_SIZE(ssm2602_rates_11289600), +}; + struct ssm2602_coeff { u32 mclk; u32 rate; @@ -320,6 +339,12 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, } else ssm2602->master_substream = substream;
+ if (ssm2602->sysclk_constraints) { + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + ssm2602->sysclk_constraints); + } + return 0; }
@@ -361,16 +386,21 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, return -EINVAL;
switch (freq) { - case 11289600: - case 12000000: case 12288000: - case 16934400: case 18432000: - ssm2602->sysclk = freq; + ssm2602->sysclk_constraints = &ssm2602_constraints_12288000; + break; + case 11289600: + case 16934400: + ssm2602->sysclk_constraints = &ssm2602_constraints_11289600; + break; + case 12000000: + ssm2602->sysclk_constraints = NULL; break; default: return -EINVAL; } + ssm2602->sysclk = freq; } else { unsigned int mask;
We have never really updated that version number and probably never will, so just remove it.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ssm2602.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index dcedd74..aef8a49 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -43,8 +43,6 @@
#include "ssm2602.h"
-#define SSM2602_VERSION "0.1" - enum ssm2602_type { SSM2602, SSM2604, @@ -608,8 +606,6 @@ static int ssm260x_probe(struct snd_soc_codec *codec) struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret;
- pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
Mostly a one to one converion. On one occasion the patch replaces a snd_soc_read-snd_soc_write sequence with regmap_update_bits though as it helps to keep the conversion simple.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ssm2602.c | 87 +++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 30 deletions(-)
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index aef8a49..079066f 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -33,6 +33,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/spi/spi.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -52,10 +53,11 @@ enum ssm2602_type { struct ssm2602_priv { unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; - enum snd_soc_control_type control_type; struct snd_pcm_substream *master_substream; struct snd_pcm_substream *slave_substream;
+ struct regmap *regmap; + enum ssm2602_type type; unsigned int clk_out_pwr; }; @@ -72,7 +74,6 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { 0x0000, 0x0000 };
-#define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0)
/*Appending several "None"s just for OSS mixer use*/ static const char *ssm2602_input_select[] = { @@ -273,8 +274,8 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_codec *codec = dai->codec; struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3; int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); + unsigned int iface;
if (substream == ssm2602->slave_substream) { dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); @@ -284,23 +285,27 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, if (srate < 0) return srate;
- snd_soc_write(codec, SSM2602_SRATE, srate); + regmap_write(ssm2602->regmap, SSM2602_SRATE, srate);
/* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: + iface = 0x0; break; case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; + iface = 0x4; break; case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; + iface = 0x8; break; case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; + iface = 0xc; break; + default: + return -EINVAL; } - snd_soc_write(codec, SSM2602_IFACE, iface); + regmap_update_bits(ssm2602->regmap, SSM2602_IFACE, + IFACE_AUDIO_DATA_LEN, iface); return 0; }
@@ -361,14 +366,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
static int ssm2602_mute(struct snd_soc_dai *dai, int mute) { - struct snd_soc_codec *codec = dai->codec; + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec);
if (mute) - snd_soc_update_bits(codec, SSM2602_APDIGI, + regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI, APDIGI_ENABLE_DAC_MUTE, APDIGI_ENABLE_DAC_MUTE); else - snd_soc_update_bits(codec, SSM2602_APDIGI, + regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI, APDIGI_ENABLE_DAC_MUTE, 0); return 0; } @@ -418,7 +423,7 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, else ssm2602->clk_out_pwr &= ~mask;
- snd_soc_update_bits(codec, SSM2602_PWR, + regmap_update_bits(ssm2602->regmap, SSM2602_PWR, PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr); }
@@ -428,8 +433,8 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec_dai->codec); + unsigned int iface = 0;
/* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -480,7 +485,7 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, }
/* set iface */ - snd_soc_write(codec, SSM2602_IFACE, iface); + regmap_write(ssm2602->regmap, SSM2602_IFACE, iface); return 0; }
@@ -492,7 +497,7 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: /* vref/mid on, osc and clkout on if enabled */ - snd_soc_update_bits(codec, SSM2602_PWR, + regmap_update_bits(ssm2602->regmap, SSM2602_PWR, PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr); break; @@ -500,13 +505,13 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - snd_soc_update_bits(codec, SSM2602_PWR, + regmap_update_bits(ssm2602->regmap, SSM2602_PWR, PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, PWR_CLK_OUT_PDN | PWR_OSC_PDN); break; case SND_SOC_BIAS_OFF: /* everything off */ - snd_soc_update_bits(codec, SSM2602_PWR, + regmap_update_bits(ssm2602->regmap, SSM2602_PWR, PWR_POWER_OFF, PWR_POWER_OFF); break;
@@ -565,12 +570,13 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
static int ssm2602_probe(struct snd_soc_codec *codec) { + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret;
- snd_soc_update_bits(codec, SSM2602_LOUT1V, + regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V, LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH); - snd_soc_update_bits(codec, SSM2602_ROUT1V, + regmap_update_bits(ssm2602->regmap, SSM2602_ROUT1V, ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls, @@ -606,25 +612,26 @@ static int ssm260x_probe(struct snd_soc_codec *codec) struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type); + codec->control_data = ssm2602->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; }
- ret = ssm2602_reset(codec); + ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); return ret; }
/* set the update bits */ - snd_soc_update_bits(codec, SSM2602_LINVOL, + regmap_update_bits(ssm2602->regmap, SSM2602_LINVOL, LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH); - snd_soc_update_bits(codec, SSM2602_RINVOL, + regmap_update_bits(ssm2602->regmap, SSM2602_RINVOL, RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH); /*select Line in as default input*/ - snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | + regmap_write(ssm2602->regmap, SSM2602_APANA, APANA_SELECT_DAC | APANA_ENABLE_MIC_BOOST);
switch (ssm2602->type) { @@ -657,9 +664,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { .suspend = ssm2602_suspend, .resume = ssm2602_resume, .set_bias_level = ssm2602_set_bias_level, - .reg_cache_size = ARRAY_SIZE(ssm2602_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = ssm2602_reg,
.controls = ssm260x_snd_controls, .num_controls = ARRAY_SIZE(ssm260x_snd_controls), @@ -669,6 +673,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), };
+static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) +{ + return reg == SSM2602_RESET; +} + +static const struct regmap_config ssm2602_regmap_config = { + .val_bits = 9, + .reg_bits = 7, + + .max_register = SSM2602_RESET, + .volatile_reg = ssm2602_register_volatile, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults_raw = ssm2602_reg, + .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit ssm2602_spi_probe(struct spi_device *spi) { @@ -681,9 +702,12 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi) return -ENOMEM;
spi_set_drvdata(spi, ssm2602); - ssm2602->control_type = SND_SOC_SPI; ssm2602->type = SSM2602;
+ ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config); + if (IS_ERR(ssm2602->regmap)) + return PTR_ERR(ssm2602->regmap); + ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_ssm2602, &ssm2602_dai, 1); return ret; @@ -724,9 +748,12 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c, return -ENOMEM;
i2c_set_clientdata(i2c, ssm2602); - ssm2602->control_type = SND_SOC_I2C; ssm2602->type = id->driver_data;
+ ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config); + if (IS_ERR(ssm2602->regmap)) + return PTR_ERR(ssm2602->regmap); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ssm2602, &ssm2602_dai, 1); return ret;
participants (2)
-
Lars-Peter Clausen
-
Mark Brown