diff options
Diffstat (limited to 'sound')
40 files changed, 1229 insertions, 1583 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 61a64d281905..8b9e70105dd2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o -snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o +snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) snd-soc-core-objs += soc-generic-dmaengine-pcm.o diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 3109db7b9017..612e5801003f 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -50,7 +50,7 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, buf->area = dma_alloc_coherent(pcm->card->dev, size, &buf->addr, GFP_KERNEL); pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n", - (void *)buf->area, (void *)buf->addr, size); + (void *)buf->area, (void *)(long)buf->addr, size); if (!buf->area) return -ENOMEM; diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c index c02405cc007d..5810a0603f2f 100644 --- a/sound/soc/blackfin/bf6xx-i2s.c +++ b/sound/soc/blackfin/bf6xx-i2s.c @@ -88,6 +88,7 @@ static int bfin_i2s_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S8: param.spctl |= 0x70; sport->wdsize = 1; + break; case SNDRV_PCM_FORMAT_S16_LE: param.spctl |= 0xf0; sport->wdsize = 2; diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 8af04343cc1a..75d0ad5d2dcb 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -16,6 +16,7 @@ #include <linux/mfd/88pm860x.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/regmap.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -140,6 +141,7 @@ struct pm860x_priv { unsigned int filter; struct snd_soc_codec *codec; struct i2c_client *i2c; + struct regmap *regmap; struct pm860x_chip *chip; struct pm860x_det det; @@ -269,48 +271,6 @@ static struct st_gain st_table[] = { { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0}, }; -static int pm860x_volatile(unsigned int reg) -{ - BUG_ON(reg >= REG_CACHE_SIZE); - - switch (reg) { - case PM860X_AUDIO_SUPPLIES_2: - return 1; - } - - return 0; -} - -static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - unsigned char *cache = codec->reg_cache; - - BUG_ON(reg >= REG_CACHE_SIZE); - - if (pm860x_volatile(reg)) - return cache[reg]; - - reg += REG_CACHE_BASE; - - return pm860x_reg_read(codec->control_data, reg); -} - -static int pm860x_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - unsigned char *cache = codec->reg_cache; - - BUG_ON(reg >= REG_CACHE_SIZE); - - if (!pm860x_volatile(reg)) - cache[reg] = (unsigned char)value; - - reg += REG_CACHE_BASE; - - return pm860x_reg_write(codec->control_data, reg, value); -} - static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -349,6 +309,9 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol, val = ucontrol->value.integer.value[0]; val2 = ucontrol->value.integer.value[1]; + if (val >= ARRAY_SIZE(st_table) || val2 >= ARRAY_SIZE(st_table)) + return -EINVAL; + err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m); if (err < 0) return err; @@ -1166,6 +1129,7 @@ static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, static int pm860x_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); int data; switch (level) { @@ -1179,17 +1143,17 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec, if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { /* Enable Audio PLL & Audio section */ data = AUDIO_PLL | AUDIO_SECTION_ON; - pm860x_reg_write(codec->control_data, REG_MISC2, data); + pm860x_reg_write(pm860x->i2c, REG_MISC2, data); udelay(300); data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON; - pm860x_reg_write(codec->control_data, REG_MISC2, data); + pm860x_reg_write(pm860x->i2c, REG_MISC2, data); } break; case SND_SOC_BIAS_OFF: data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON; - pm860x_set_bits(codec->control_data, REG_MISC2, data, 0); + pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0); break; } codec->dapm.bias_level = level; @@ -1319,17 +1283,17 @@ int pm860x_hs_jack_detect(struct snd_soc_codec *codec, pm860x->det.lo_shrt = lo_shrt; if (det & SND_JACK_HEADPHONE) - pm860x_set_bits(codec->control_data, REG_HS_DET, + pm860x_set_bits(pm860x->i2c, REG_HS_DET, EN_HS_DET, EN_HS_DET); /* headset short detect */ if (hs_shrt) { data = CLR_SHORT_HS2 | CLR_SHORT_HS1; - pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); + pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data); } /* Lineout short detect */ if (lo_shrt) { data = CLR_SHORT_LO2 | CLR_SHORT_LO1; - pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); + pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data); } /* sync status */ @@ -1347,7 +1311,7 @@ int pm860x_mic_jack_detect(struct snd_soc_codec *codec, pm860x->det.mic_det = det; if (det & SND_JACK_MICROPHONE) - pm860x_set_bits(codec->control_data, REG_MIC_DET, + pm860x_set_bits(pm860x->i2c, REG_MIC_DET, MICDET_MASK, MICDET_MASK); /* sync status */ @@ -1363,7 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; - codec->control_data = pm860x->i2c; + codec->control_data = pm860x->regmap; for (i = 0; i < 4; i++) { ret = request_threaded_irq(pm860x->irq[i], NULL, @@ -1377,14 +1341,6 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE, - REG_CACHE_SIZE, codec->reg_cache); - if (ret < 0) { - dev_err(codec->dev, "Failed to fill register cache: %d\n", - ret); - goto out; - } - return 0; out: @@ -1407,10 +1363,6 @@ static int pm860x_remove(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_pm860x = { .probe = pm860x_probe, .remove = pm860x_remove, - .read = pm860x_read_reg_cache, - .write = pm860x_write_reg_cache, - .reg_cache_size = REG_CACHE_SIZE, - .reg_word_size = sizeof(u8), .set_bias_level = pm860x_set_bias_level, .controls = pm860x_snd_controls, @@ -1436,6 +1388,8 @@ static int pm860x_codec_probe(struct platform_device *pdev) pm860x->chip = chip; pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; + pm860x->regmap = (chip->id == CHIP_PM8607) ? chip->regmap + : chip->regmap_companion; platform_set_drvdata(pdev, pm860x); for (i = 0; i < 4; i++) { diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h index 3364ba4a3607..f7282f4f4a79 100644 --- a/sound/soc/codecs/88pm860x-codec.h +++ b/sound/soc/codecs/88pm860x-codec.h @@ -12,67 +12,66 @@ #ifndef __88PM860X_H #define __88PM860X_H -/* The offset of these registers are 0xb0 */ -#define PM860X_PCM_IFACE_1 0x00 -#define PM860X_PCM_IFACE_2 0x01 -#define PM860X_PCM_IFACE_3 0x02 -#define PM860X_PCM_RATE 0x03 -#define PM860X_EC_PATH 0x04 -#define PM860X_SIDETONE_L_GAIN 0x05 -#define PM860X_SIDETONE_R_GAIN 0x06 -#define PM860X_SIDETONE_SHIFT 0x07 -#define PM860X_ADC_OFFSET_1 0x08 -#define PM860X_ADC_OFFSET_2 0x09 -#define PM860X_DMIC_DELAY 0x0a +#define PM860X_PCM_IFACE_1 0xb0 +#define PM860X_PCM_IFACE_2 0xb1 +#define PM860X_PCM_IFACE_3 0xb2 +#define PM860X_PCM_RATE 0xb3 +#define PM860X_EC_PATH 0xb4 +#define PM860X_SIDETONE_L_GAIN 0xb5 +#define PM860X_SIDETONE_R_GAIN 0xb6 +#define PM860X_SIDETONE_SHIFT 0xb7 +#define PM860X_ADC_OFFSET_1 0xb8 +#define PM860X_ADC_OFFSET_2 0xb9 +#define PM860X_DMIC_DELAY 0xba -#define PM860X_I2S_IFACE_1 0x0b -#define PM860X_I2S_IFACE_2 0x0c -#define PM860X_I2S_IFACE_3 0x0d -#define PM860X_I2S_IFACE_4 0x0e -#define PM860X_EQUALIZER_N0_1 0x0f -#define PM860X_EQUALIZER_N0_2 0x10 -#define PM860X_EQUALIZER_N1_1 0x11 -#define PM860X_EQUALIZER_N1_2 0x12 -#define PM860X_EQUALIZER_D1_1 0x13 -#define PM860X_EQUALIZER_D1_2 0x14 -#define PM860X_LOFI_GAIN_LEFT 0x15 -#define PM860X_LOFI_GAIN_RIGHT 0x16 -#define PM860X_HIFIL_GAIN_LEFT 0x17 -#define PM860X_HIFIL_GAIN_RIGHT 0x18 -#define PM860X_HIFIR_GAIN_LEFT 0x19 -#define PM860X_HIFIR_GAIN_RIGHT 0x1a -#define PM860X_DAC_OFFSET 0x1b -#define PM860X_OFFSET_LEFT_1 0x1c -#define PM860X_OFFSET_LEFT_2 0x1d -#define PM860X_OFFSET_RIGHT_1 0x1e -#define PM860X_OFFSET_RIGHT_2 0x1f -#define PM860X_ADC_ANA_1 0x20 -#define PM860X_ADC_ANA_2 0x21 -#define PM860X_ADC_ANA_3 0x22 -#define PM860X_ADC_ANA_4 0x23 -#define PM860X_ANA_TO_ANA 0x24 -#define PM860X_HS1_CTRL 0x25 -#define PM860X_HS2_CTRL 0x26 -#define PM860X_LO1_CTRL 0x27 -#define PM860X_LO2_CTRL 0x28 -#define PM860X_EAR_CTRL_1 0x29 -#define PM860X_EAR_CTRL_2 0x2a -#define PM860X_AUDIO_SUPPLIES_1 0x2b -#define PM860X_AUDIO_SUPPLIES_2 0x2c -#define PM860X_ADC_EN_1 0x2d -#define PM860X_ADC_EN_2 0x2e -#define PM860X_DAC_EN_1 0x2f -#define PM860X_DAC_EN_2 0x31 -#define PM860X_AUDIO_CAL_1 0x32 -#define PM860X_AUDIO_CAL_2 0x33 -#define PM860X_AUDIO_CAL_3 0x34 -#define PM860X_AUDIO_CAL_4 0x35 -#define PM860X_AUDIO_CAL_5 0x36 -#define PM860X_ANA_INPUT_SEL_1 0x37 -#define PM860X_ANA_INPUT_SEL_2 0x38 +#define PM860X_I2S_IFACE_1 0xbb +#define PM860X_I2S_IFACE_2 0xbc +#define PM860X_I2S_IFACE_3 0xbd +#define PM860X_I2S_IFACE_4 0xbe +#define PM860X_EQUALIZER_N0_1 0xbf +#define PM860X_EQUALIZER_N0_2 0xc0 +#define PM860X_EQUALIZER_N1_1 0xc1 +#define PM860X_EQUALIZER_N1_2 0xc2 +#define PM860X_EQUALIZER_D1_1 0xc3 +#define PM860X_EQUALIZER_D1_2 0xc4 +#define PM860X_LOFI_GAIN_LEFT 0xc5 +#define PM860X_LOFI_GAIN_RIGHT 0xc6 +#define PM860X_HIFIL_GAIN_LEFT 0xc7 +#define PM860X_HIFIL_GAIN_RIGHT 0xc8 +#define PM860X_HIFIR_GAIN_LEFT 0xc9 +#define PM860X_HIFIR_GAIN_RIGHT 0xca +#define PM860X_DAC_OFFSET 0xcb +#define PM860X_OFFSET_LEFT_1 0xcc +#define PM860X_OFFSET_LEFT_2 0xcd +#define PM860X_OFFSET_RIGHT_1 0xce +#define PM860X_OFFSET_RIGHT_2 0xcf +#define PM860X_ADC_ANA_1 0xd0 +#define PM860X_ADC_ANA_2 0xd1 +#define PM860X_ADC_ANA_3 0xd2 +#define PM860X_ADC_ANA_4 0xd3 +#define PM860X_ANA_TO_ANA 0xd4 +#define PM860X_HS1_CTRL 0xd5 +#define PM860X_HS2_CTRL 0xd6 +#define PM860X_LO1_CTRL 0xd7 +#define PM860X_LO2_CTRL 0xd8 +#define PM860X_EAR_CTRL_1 0xd9 +#define PM860X_EAR_CTRL_2 0xda +#define PM860X_AUDIO_SUPPLIES_1 0xdb +#define PM860X_AUDIO_SUPPLIES_2 0xdc +#define PM860X_ADC_EN_1 0xdd +#define PM860X_ADC_EN_2 0xde +#define PM860X_DAC_EN_1 0xdf +#define PM860X_DAC_EN_2 0xe1 +#define PM860X_AUDIO_CAL_1 0xe2 +#define PM860X_AUDIO_CAL_2 0xe3 +#define PM860X_AUDIO_CAL_3 0xe4 +#define PM860X_AUDIO_CAL_4 0xe5 +#define PM860X_AUDIO_CAL_5 0xe6 +#define PM860X_ANA_INPUT_SEL_1 0xe7 +#define PM860X_ANA_INPUT_SEL_2 0xe8 -#define PM860X_PCM_IFACE_4 0x39 -#define PM860X_I2S_IFACE_5 0x3a +#define PM860X_PCM_IFACE_4 0xe9 +#define PM860X_I2S_IFACE_5 0xea #define PM860X_SHORTS 0x3b #define PM860X_PLL_ADJ_1 0x3c diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index b8ba0adacfce..a0394a8f2257 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -126,6 +126,8 @@ struct ab8500_codec_drvdata_dbg { /* Private data for AB8500 device-driver */ struct ab8500_codec_drvdata { + struct regmap *regmap; + /* Sidetone */ long *sid_fir_values; enum sid_state sid_status; @@ -166,49 +168,35 @@ static inline const char *amic_type_str(enum amic_type type) */ /* Read a register from the audio-bank of AB8500 */ -static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec, - unsigned int reg) +static int ab8500_codec_read_reg(void *context, unsigned int reg, + unsigned int *value) { + struct device *dev = context; int status; - unsigned int value = 0; u8 value8; - status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO, - reg, &value8); - if (status < 0) { - dev_err(codec->dev, - "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n", - __func__, (u8)AB8500_AUDIO, (u8)reg, status); - } else { - dev_dbg(codec->dev, - "%s: Read 0x%02x from register 0x%02x:0x%02x\n", - __func__, value8, (u8)AB8500_AUDIO, (u8)reg); - value = (unsigned int)value8; - } + status = abx500_get_register_interruptible(dev, AB8500_AUDIO, + reg, &value8); + *value = (unsigned int)value8; - return value; + return status; } /* Write to a register in the audio-bank of AB8500 */ -static int ab8500_codec_write_reg(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) +static int ab8500_codec_write_reg(void *context, unsigned int reg, + unsigned int value) { - int status; - - status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO, - reg, value); - if (status < 0) - dev_err(codec->dev, - "%s: ERROR: Register (%02x:%02x) write failed (%d).\n", - __func__, (u8)AB8500_AUDIO, (u8)reg, status); - else - dev_dbg(codec->dev, - "%s: Wrote 0x%02x into register %02x:%02x\n", - __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg); + struct device *dev = context; - return status; + return abx500_set_register_interruptible(dev, AB8500_AUDIO, + reg, value); } +static const struct regmap_config ab8500_codec_regmap = { + .reg_read = ab8500_codec_read_reg, + .reg_write = ab8500_codec_write_reg, +}; + /* * Controls - DAPM */ @@ -1225,13 +1213,18 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); struct device *dev = codec->dev; bool apply_fir, apply_iir; - int req, status; + unsigned int req; + int status; dev_dbg(dev, "%s: Enter.\n", __func__); mutex_lock(&drvdata->anc_lock); req = ucontrol->value.integer.value[0]; + if (req >= ARRAY_SIZE(enum_anc_state)) { + status = -EINVAL; + goto cleanup; + } if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR && req != ANC_APPLY_IIR) { dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", @@ -2480,9 +2473,13 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) dev_dbg(dev, "%s: Enter.\n", __func__); + snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + /* Setup AB8500 according to board-settings */ pdata = dev_get_platdata(dev->parent); + codec->control_data = drvdata->regmap; + if (np) { if (!pdata) pdata = devm_kzalloc(dev, @@ -2527,12 +2524,10 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) } /* Override HW-defaults */ - ab8500_codec_write_reg(codec, - AB8500_ANACONF5, - BIT(AB8500_ANACONF5_HSAUTOEN)); - ab8500_codec_write_reg(codec, - AB8500_SHORTCIRCONF, - BIT(AB8500_SHORTCIRCONF_HSZCDDIS)); + snd_soc_write(codec, AB8500_ANACONF5, + BIT(AB8500_ANACONF5_HSAUTOEN)); + snd_soc_write(codec, AB8500_SHORTCIRCONF, + BIT(AB8500_SHORTCIRCONF_HSZCDDIS)); /* Add filter controls */ status = snd_soc_add_codec_controls(codec, ab8500_filter_controls, @@ -2562,9 +2557,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver ab8500_codec_driver = { .probe = ab8500_codec_probe, - .read = ab8500_codec_read_reg, - .write = ab8500_codec_write_reg, - .reg_word_size = sizeof(u8), .controls = ab8500_ctrls, .num_controls = ARRAY_SIZE(ab8500_ctrls), .dapm_widgets = ab8500_dapm_widgets, @@ -2587,6 +2579,15 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev) drvdata->anc_status = ANC_UNCONFIGURED; dev_set_drvdata(&pdev->dev, drvdata); + drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev, + &ab8500_codec_regmap); + if (IS_ERR(drvdata->regmap)) { + status = PTR_ERR(drvdata->regmap); + dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n", + __func__, status); + return status; + } + dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, ab8500_codec_dai, @@ -2601,7 +2602,7 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev) static int ab8500_codec_driver_remove(struct platform_device *pdev) { - dev_info(&pdev->dev, "%s Enter.\n", __func__); + dev_dbg(&pdev->dev, "%s Enter.\n", __func__); snd_soc_unregister_codec(&pdev->dev); diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 71059c07ae7b..b4819dcd4f4d 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -45,8 +45,6 @@ #define AK4104_TX_TXE (1 << 0) #define AK4104_TX_V (1 << 1) -#define DRV_NAME "ak4104-codec" - struct ak4104_private { struct regmap *regmap; }; @@ -291,12 +289,19 @@ static const struct of_device_id ak4104_of_match[] = { }; MODULE_DEVICE_TABLE(of, ak4104_of_match); +static const struct spi_device_id ak4104_id_table[] = { + { "ak4104", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, ak4104_id_table); + static struct spi_driver ak4104_spi_driver = { .driver = { - .name = DRV_NAME, + .name = "ak4104", .owner = THIS_MODULE, .of_match_table = ak4104_of_match, }, + .id_table = ak4104_id_table, .probe = ak4104_spi_probe, .remove = ak4104_spi_remove, }; diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 2d0378709702..21c35ed778cc 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -352,7 +352,6 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) */ default: return -EINVAL; - break; } snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data); @@ -405,7 +404,6 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream, break; default: return -EINVAL; - break; } snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate); diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 657808ba1418..6f05b17d1965 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1477,21 +1477,25 @@ static void arizona_enable_fll(struct arizona_fll *fll, { struct arizona *arizona = fll->arizona; int ret; + bool use_sync = false; /* * If we have both REFCLK and SYNCCLK then enable both, * otherwise apply the SYNCCLK settings to REFCLK. */ - if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) { + if (fll->ref_src >= 0 && fll->ref_freq && + fll->ref_src != fll->sync_src) { regmap_update_bits(arizona->regmap, fll->base + 5, ARIZONA_FLL1_OUTDIV_MASK, ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, false); - if (fll->sync_src >= 0) + if (fll->sync_src >= 0) { arizona_apply_fll(arizona, fll->base + 0x10, sync, fll->sync_src, true); + use_sync = true; + } } else if (fll->sync_src >= 0) { regmap_update_bits(arizona->regmap, fll->base + 5, ARIZONA_FLL1_OUTDIV_MASK, @@ -1511,7 +1515,7 @@ static void arizona_enable_fll(struct arizona_fll *fll, * Increase the bandwidth if we're not using a low frequency * sync source. */ - if (fll->sync_src >= 0 && fll->sync_freq > 100000) + if (use_sync && fll->sync_freq > 100000) regmap_update_bits(arizona->regmap, fll->base + 0x17, ARIZONA_FLL1_SYNC_BW, 0); else @@ -1526,8 +1530,7 @@ static void arizona_enable_fll(struct arizona_fll *fll, regmap_update_bits(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); - if (fll->ref_src >= 0 && fll->sync_src >= 0 && - fll->ref_src != fll->sync_src) + if (use_sync) regmap_update_bits(arizona->regmap, fll->base + 0x11, ARIZONA_FLL1_SYNC_ENA, ARIZONA_FLL1_SYNC_ENA); @@ -1561,10 +1564,12 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source, if (fll->ref_src == source && fll->ref_freq == Fref) return 0; - if (fll->fout && Fref > 0) { - ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); - if (ret != 0) - return ret; + if (fll->fout) { + if (Fref > 0) { + ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); + if (ret != 0) + return ret; + } if (fll->sync_src >= 0) { ret = arizona_calc_fll(fll, &sync, fll->sync_freq, diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 23316c887b19..43737a27d79c 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -38,24 +38,6 @@ #include <sound/soc.h> #include <sound/initval.h> -static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct davinci_vc *davinci_vc = codec->control_data; - - return readl(davinci_vc->base + reg); -} - -static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct davinci_vc *davinci_vc = codec->control_data; - - writel(value, davinci_vc->base + reg); - - return 0; -} - static const struct snd_kcontrol_new cq93vc_snd_controls[] = { SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0), SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0), @@ -64,13 +46,15 @@ static const struct snd_kcontrol_new cq93vc_snd_controls[] = { static int cq93vc_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE; + u8 reg; if (mute) - cq93vc_write(codec, DAVINCI_VC_REG09, - reg | DAVINCI_VC_REG09_MUTE); + reg = DAVINCI_VC_REG09_MUTE; else - cq93vc_write(codec, DAVINCI_VC_REG09, reg); + reg = 0; + + snd_soc_update_bits(codec, DAVINCI_VC_REG09, DAVINCI_VC_REG09_MUTE, + reg); return 0; } @@ -79,7 +63,7 @@ static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; - struct davinci_vc *davinci_vc = codec->control_data; + struct davinci_vc *davinci_vc = codec->dev->platform_data; switch (freq) { case 22579200: @@ -97,18 +81,18 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec, { switch (level) { case SND_SOC_BIAS_ON: - cq93vc_write(codec, DAVINCI_VC_REG12, + snd_soc_write(codec, DAVINCI_VC_REG12, DAVINCI_VC_REG12_POWER_ALL_ON); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - cq93vc_write(codec, DAVINCI_VC_REG12, + snd_soc_write(codec, DAVINCI_VC_REG12, DAVINCI_VC_REG12_POWER_ALL_OFF); break; case SND_SOC_BIAS_OFF: /* force all power off */ - cq93vc_write(codec, DAVINCI_VC_REG12, + snd_soc_write(codec, DAVINCI_VC_REG12, DAVINCI_VC_REG12_POWER_ALL_OFF); break; } @@ -154,11 +138,9 @@ static int cq93vc_probe(struct snd_soc_codec *codec) struct davinci_vc *davinci_vc = codec->dev->platform_data; davinci_vc->cq93vc.codec = codec; - codec->control_data = davinci_vc; + codec->control_data = davinci_vc->regmap; - /* Set controls */ - snd_soc_add_codec_controls(codec, cq93vc_snd_controls, - ARRAY_SIZE(cq93vc_snd_controls)); + snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP); /* Off, with power on */ cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -174,12 +156,12 @@ static int cq93vc_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { - .read = cq93vc_read, - .write = cq93vc_write, .set_bias_level = cq93vc_set_bias_level, .probe = cq93vc_probe, .remove = cq93vc_remove, .resume = cq93vc_resume, + .controls = cq93vc_snd_controls, + .num_controls = ARRAY_SIZE(cq93vc_snd_controls), }; static int cq93vc_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 566a367c94fa..66ceee22fdad 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -38,294 +39,223 @@ struct max98088_cdata { }; struct max98088_priv { - enum max98088_type devtype; - struct max98088_pdata *pdata; - unsigned int sysclk; - struct max98088_cdata dai[2]; - int eq_textcnt; - const char **eq_texts; - struct soc_enum eq_enum; - u8 ina_state; - u8 inb_state; - unsigned int ex_mode; - unsigned int digmic; - unsigned int mic1pre; - unsigned int mic2pre; - unsigned int extmic_mode; + struct regmap *regmap; + enum max98088_type devtype; + struct max98088_pdata *pdata; + unsigned int sysclk; + struct max98088_cdata dai[2]; + int eq_textcnt; + const char **eq_texts; + struct soc_enum eq_enum; + u8 ina_state; + u8 inb_state; + unsigned int ex_mode; + unsigned int digmic; + unsigned int mic1pre; + unsigned int mic2pre; + unsigned int extmic_mode; }; -static const u8 max98088_reg[M98088_REG_CNT] = { - 0x00, /* 00 IRQ status */ - 0x00, /* 01 MIC status */ - 0x00, /* 02 jack status */ - 0x00, /* 03 battery voltage */ - 0x00, /* 04 */ - 0x00, /* 05 */ - 0x00, /* 06 */ - 0x00, /* 07 */ - 0x00, /* 08 */ - 0x00, /* 09 */ - 0x00, /* 0A */ - 0x00, /* 0B */ - 0x00, /* 0C */ - 0x00, /* 0D */ - 0x00, /* 0E */ - 0x00, /* 0F interrupt enable */ - - 0x00, /* 10 master clock */ - 0x00, /* 11 DAI1 clock mode */ - 0x00, /* 12 DAI1 clock control */ - 0x00, /* 13 DAI1 clock control */ - 0x00, /* 14 DAI1 format */ - 0x00, /* 15 DAI1 clock */ - 0x00, /* 16 DAI1 config */ - 0x00, /* 17 DAI1 TDM */ - 0x00, /* 18 DAI1 filters */ - 0x00, /* 19 DAI2 clock mode */ - 0x00, /* 1A DAI2 clock control */ - 0x00, /* 1B DAI2 clock control */ - 0x00, /* 1C DAI2 format */ - 0x00, /* 1D DAI2 clock */ - 0x00, /* 1E DAI2 config */ - 0x00, /* 1F DAI2 TDM */ - - 0x00, /* 20 DAI2 filters */ - 0x00, /* 21 data config */ - 0x00, /* 22 DAC mixer */ - 0x00, /* 23 left ADC mixer */ - 0x00, /* 24 right ADC mixer */ - 0x00, /* 25 left HP mixer */ - 0x00, /* 26 right HP mixer */ - 0x00, /* 27 HP control */ - 0x00, /* 28 left REC mixer */ - 0x00, /* 29 right REC mixer */ - 0x00, /* 2A REC control */ - 0x00, /* 2B left SPK mixer */ - 0x00, /* 2C right SPK mixer */ - 0x00, /* 2D SPK control */ - 0x00, /* 2E sidetone */ - 0x00, /* 2F DAI1 playback level */ - - 0x00, /* 30 DAI1 playback level */ - 0x00, /* 31 DAI2 playback level */ - 0x00, /* 32 DAI2 playbakc level */ - 0x00, /* 33 left ADC level */ - 0x00, /* 34 right ADC level */ - 0x00, /* 35 MIC1 level */ - 0x00, /* 36 MIC2 level */ - 0x00, /* 37 INA level */ - 0x00, /* 38 INB level */ - 0x00, /* 39 left HP volume */ - 0x00, /* 3A right HP volume */ - 0x00, /* 3B left REC volume */ - 0x00, /* 3C right REC volume */ - 0x00, /* 3D left SPK volume */ - 0x00, /* 3E right SPK volume */ - 0x00, /* 3F MIC config */ - - 0x00, /* 40 MIC threshold */ - 0x00, /* 41 excursion limiter filter */ - 0x00, /* 42 excursion limiter threshold */ - 0x00, /* 43 ALC */ - 0x00, /* 44 power limiter threshold */ - 0x00, /* 45 power limiter config */ - 0x00, /* 46 distortion limiter config */ - 0x00, /* 47 audio input */ - 0x00, /* 48 microphone */ - 0x00, /* 49 level control */ - 0x00, /* 4A bypass switches */ - 0x00, /* 4B jack detect */ - 0x00, /* 4C input enable */ - 0x00, /* 4D output enable */ - 0xF0, /* 4E bias control */ - 0x00, /* 4F DAC power */ - - 0x0F, /* 50 DAC power */ - 0x00, /* 51 system */ - 0x00, /* 52 DAI1 EQ1 */ - 0x00, /* 53 DAI1 EQ1 */ - 0x00, /* 54 DAI1 EQ1 */ - 0x00, /* 55 DAI1 EQ1 */ - 0x00, /* 56 DAI1 EQ1 */ - 0x00, /* 57 DAI1 EQ1 */ - 0x00, /* 58 DAI1 EQ1 */ - 0x00, /* 59 DAI1 EQ1 */ - 0x00, /* 5A DAI1 EQ1 */ - 0x00, /* 5B DAI1 EQ1 */ - 0x00, /* 5C DAI1 EQ2 */ - 0x00, /* 5D DAI1 EQ2 */ - 0x00, /* 5E DAI1 EQ2 */ - 0x00, /* 5F DAI1 EQ2 */ - - 0x00, /* 60 DAI1 EQ2 */ - 0x00, /* 61 DAI1 EQ2 */ - 0x00, /* 62 DAI1 EQ2 */ - 0x00, /* 63 DAI1 EQ2 */ - 0x00, /* 64 DAI1 EQ2 */ - 0x00, /* 65 DAI1 EQ2 */ - 0x00, /* 66 DAI1 EQ3 */ - 0x00, /* 67 DAI1 EQ3 */ - 0x00, /* 68 DAI1 EQ3 */ - 0x00, /* 69 DAI1 EQ3 */ - 0x00, /* 6A DAI1 EQ3 */ - 0x00, /* 6B DAI1 EQ3 */ - 0x00, /* 6C DAI1 EQ3 */ - 0x00, /* 6D DAI1 EQ3 */ - 0x00, /* 6E DAI1 EQ3 */ - 0x00, /* 6F DAI1 EQ3 */ - - 0x00, /* 70 DAI1 EQ4 */ - 0x00, /* 71 DAI1 EQ4 */ - 0x00, /* 72 DAI1 EQ4 */ - 0x00, /* 73 DAI1 EQ4 */ - 0x00, /* 74 DAI1 EQ4 */ - 0x00, /* 75 DAI1 EQ4 */ - 0x00, /* 76 DAI1 EQ4 */ - 0x00, /* 77 DAI1 EQ4 */ - 0x00, /* 78 DAI1 EQ4 */ - 0x00, /* 79 DAI1 EQ4 */ - 0x00, /* 7A DAI1 EQ5 */ - 0x00, /* 7B DAI1 EQ5 */ - 0x00, /* 7C DAI1 EQ5 */ - 0x00, /* 7D DAI1 EQ5 */ - 0x00, /* 7E DAI1 EQ5 */ - 0x00, /* 7F DAI1 EQ5 */ - - 0x00, /* 80 DAI1 EQ5 */ - 0x00, /* 81 DAI1 EQ5 */ - 0x00, /* 82 DAI1 EQ5 */ - 0x00, /* 83 DAI1 EQ5 */ - 0x00, /* 84 DAI2 EQ1 */ - 0x00, /* 85 DAI2 EQ1 */ - 0x00, /* 86 DAI2 EQ1 */ - 0x00, /* 87 DAI2 EQ1 */ - 0x00, /* 88 DAI2 EQ1 */ - 0x00, /* 89 DAI2 EQ1 */ - 0x00, /* 8A DAI2 EQ1 */ - 0x00, /* 8B DAI2 EQ1 */ - 0x00, /* 8C DAI2 EQ1 */ - 0x00, /* 8D DAI2 EQ1 */ - 0x00, /* 8E DAI2 EQ2 */ - 0x00, /* 8F DAI2 EQ2 */ - - 0x00, /* 90 DAI2 EQ2 */ - 0x00, /* 91 DAI2 EQ2 */ - 0x00, /* 92 DAI2 EQ2 */ - 0x00, /* 93 DAI2 EQ2 */ - 0x00, /* 94 DAI2 EQ2 */ - 0x00, /* 95 DAI2 EQ2 */ - 0x00, /* 96 DAI2 EQ2 */ - 0x00, /* 97 DAI2 EQ2 */ - 0x00, /* 98 DAI2 EQ3 */ - 0x00, /* 99 DAI2 EQ3 */ - 0x00, /* 9A DAI2 EQ3 */ - 0x00, /* 9B DAI2 EQ3 */ - 0x00, /* 9C DAI2 EQ3 */ - 0x00, /* 9D DAI2 EQ3 */ - 0x00, /* 9E DAI2 EQ3 */ - 0x00, /* 9F DAI2 EQ3 */ - - 0x00, /* A0 DAI2 EQ3 */ - 0x00, /* A1 DAI2 EQ3 */ - 0x00, /* A2 DAI2 EQ4 */ - 0x00, /* A3 DAI2 EQ4 */ - 0x00, /* A4 DAI2 EQ4 */ - 0x00, /* A5 DAI2 EQ4 */ - 0x00, /* A6 DAI2 EQ4 */ - 0x00, /* A7 DAI2 EQ4 */ - 0x00, /* A8 DAI2 EQ4 */ - 0x00, /* A9 DAI2 EQ4 */ - 0x00, /* AA DAI2 EQ4 */ - 0x00, /* AB DAI2 EQ4 */ - 0x00, /* AC DAI2 EQ5 */ - 0x00, /* AD DAI2 EQ5 */ - 0x00, /* AE DAI2 EQ5 */ - 0x00, /* AF DAI2 EQ5 */ - - 0x00, /* B0 DAI2 EQ5 */ - 0x00, /* B1 DAI2 EQ5 */ - 0x00, /* B2 DAI2 EQ5 */ - 0x00, /* B3 DAI2 EQ5 */ - 0x00, /* B4 DAI2 EQ5 */ - 0x00, /* B5 DAI2 EQ5 */ - 0x00, /* B6 DAI1 biquad */ - 0x00, /* B7 DAI1 biquad */ - 0x00, /* B8 DAI1 biquad */ - 0x00, /* B9 DAI1 biquad */ - 0x00, /* BA DAI1 biquad */ - 0x00, /* BB DAI1 biquad */ - 0x00, /* BC DAI1 biquad */ - 0x00, /* BD DAI1 biquad */ - 0x00, /* BE DAI1 biquad */ - 0x00, /* BF DAI1 biquad */ - - 0x00, /* C0 DAI2 biquad */ - 0x00, /* C1 DAI2 biquad */ - 0x00, /* C2 DAI2 biquad */ - 0x00, /* C3 DAI2 biquad */ - 0x00, /* C4 DAI2 biquad */ - 0x00, /* C5 DAI2 biquad */ - 0x00, /* C6 DAI2 biquad */ - 0x00, /* C7 DAI2 biquad */ - 0x00, /* C8 DAI2 biquad */ - 0x00, /* C9 DAI2 biquad */ - 0x00, /* CA */ - 0x00, /* CB */ - 0x00, /* CC */ - 0x00, /* CD */ - 0x00, /* CE */ - 0x00, /* CF */ - - 0x00, /* D0 */ - 0x00, /* D1 */ - 0x00, /* D2 */ - 0x00, /* D3 */ - 0x00, /* D4 */ - 0x00, /* D5 */ - 0x00, /* D6 */ - 0x00, /* D7 */ - 0x00, /* D8 */ - 0x00, /* D9 */ - 0x00, /* DA */ - 0x70, /* DB */ - 0x00, /* DC */ - 0x00, /* DD */ - 0x00, /* DE */ - 0x00, /* DF */ - - 0x00, /* E0 */ - 0x00, /* E1 */ - 0x00, /* E2 */ - 0x00, /* E3 */ - 0x00, /* E4 */ - 0x00, /* E5 */ - 0x00, /* E6 */ - 0x00, /* E7 */ - 0x00, /* E8 */ - 0x00, /* E9 */ - 0x00, /* EA */ - 0x00, /* EB */ - 0x00, /* EC */ - 0x00, /* ED */ - 0x00, /* EE */ - 0x00, /* EF */ - - 0x00, /* F0 */ - 0x00, /* F1 */ - 0x00, /* F2 */ - 0x00, /* F3 */ - 0x00, /* F4 */ - 0x00, /* F5 */ - 0x00, /* F6 */ - 0x00, /* F7 */ - 0x00, /* F8 */ - 0x00, /* F9 */ - 0x00, /* FA */ - 0x00, /* FB */ - 0x00, /* FC */ - 0x00, /* FD */ - 0x00, /* FE */ - 0x00, /* FF */ +static const struct reg_default max98088_reg[] = { + { 0xf, 0x00 }, /* 0F interrupt enable */ + + { 0x10, 0x00 }, /* 10 master clock */ + { 0x11, 0x00 }, /* 11 DAI1 clock mode */ + { 0x12, 0x00 }, /* 12 DAI1 clock control */ + { 0x13, 0x00 }, /* 13 DAI1 clock control */ + { 0x14, 0x00 }, /* 14 DAI1 format */ + { 0x15, 0x00 }, /* 15 DAI1 clock */ + { 0x16, 0x00 }, /* 16 DAI1 config */ + { 0x17, 0x00 }, /* 17 DAI1 TDM */ + { 0x18, 0x00 }, /* 18 DAI1 filters */ + { 0x19, 0x00 }, /* 19 DAI2 clock mode */ + { 0x1a, 0x00 }, /* 1A DAI2 clock control */ + { 0x1b, 0x00 }, /* 1B DAI2 clock control */ + { 0x1c, 0x00 }, /* 1C DAI2 format */ + { 0x1d, 0x00 }, /* 1D DAI2 clock */ + { 0x1e, 0x00 }, /* 1E DAI2 config */ + { 0x1f, 0x00 }, /* 1F DAI2 TDM */ + + { 0x20, 0x00 }, /* 20 DAI2 filters */ + { 0x21, 0x00 }, /* 21 data config */ + { 0x22, 0x00 }, /* 22 DAC mixer */ + { 0x23, 0x00 }, /* 23 left ADC mixer */ + { 0x24, 0x00 }, /* 24 right ADC mixer */ + { 0x25, 0x00 }, /* 25 left HP mixer */ + { 0x26, 0x00 }, /* 26 right HP mixer */ + { 0x27, 0x00 }, /* 27 HP control */ + { 0x28, 0x00 }, /* 28 left REC mixer */ + { 0x29, 0x00 }, /* 29 right REC mixer */ + { 0x2a, 0x00 }, /* 2A REC control */ + { 0x2b, 0x00 }, /* 2B left SPK mixer */ + { 0x2c, 0x00 }, /* 2C right SPK mixer */ + { 0x2d, 0x00 }, /* 2D SPK control */ + { 0x2e, 0x00 }, /* 2E sidetone */ + { 0x2f, 0x00 }, /* 2F DAI1 playback level */ + + { 0x30, 0x00 }, /* 30 DAI1 playback level */ + { 0x31, 0x00 }, /* 31 DAI2 playback level */ + { 0x32, 0x00 }, /* 32 DAI2 playbakc level */ + { 0x33, 0x00 }, /* 33 left ADC level */ + { 0x34, 0x00 }, /* 34 right ADC level */ + { 0x35, 0x00 }, /* 35 MIC1 level */ + { 0x36, 0x00 }, /* 36 MIC2 level */ + { 0x37, 0x00 }, /* 37 INA level */ + { 0x38, 0x00 }, /* 38 INB level */ + { 0x39, 0x00 }, /* 39 left HP volume */ + { 0x3a, 0x00 }, /* 3A right HP volume */ + { 0x3b, 0x00 }, /* 3B left REC volume */ + { 0x3c, 0x00 }, /* 3C right REC volume */ + { 0x3d, 0x00 }, /* 3D left SPK volume */ + { 0x3e, 0x00 }, /* 3E right SPK volume */ + { 0x3f, 0x00 }, /* 3F MIC config */ + + { 0x40, 0x00 }, /* 40 MIC threshold */ + { 0x41, 0x00 }, /* 41 excursion limiter filter */ + { 0x42, 0x00 }, /* 42 excursion limiter threshold */ + { 0x43, 0x00 }, /* 43 ALC */ + { 0x44, 0x00 }, /* 44 power limiter threshold */ + { 0x45, 0x00 }, /* 45 power limiter config */ + { 0x46, 0x00 }, /* 46 distortion limiter config */ + { 0x47, 0x00 }, /* 47 audio input */ + { 0x48, 0x00 }, /* 48 microphone */ + { 0x49, 0x00 }, /* 49 level control */ + { 0x4a, 0x00 }, /* 4A bypass switches */ + { 0x4b, 0x00 }, /* 4B jack detect */ + { 0x4c, 0x00 }, /* 4C input enable */ + { 0x4d, 0x00 }, /* 4D output enable */ + { 0x4e, 0xF0 }, /* 4E bias control */ + { 0x4f, 0x00 }, /* 4F DAC power */ + + { 0x50, 0x0F }, /* 50 DAC power */ + { 0x51, 0x00 }, /* 51 system */ + { 0x52, 0x00 }, /* 52 DAI1 EQ1 */ + { 0x53, 0x00 }, /* 53 DAI1 EQ1 */ + { 0x54, 0x00 }, /* 54 DAI1 EQ1 */ + { 0x55, 0x00 }, /* 55 DAI1 EQ1 */ + { 0x56, 0x00 }, /* 56 DAI1 EQ1 */ + { 0x57, 0x00 }, /* 57 DAI1 EQ1 */ + { 0x58, 0x00 }, /* 58 DAI1 EQ1 */ + { 0x59, 0x00 }, /* 59 DAI1 EQ1 */ + { 0x5a, 0x00 }, /* 5A DAI1 EQ1 */ + { 0x5b, 0x00 }, /* 5B DAI1 EQ1 */ + { 0x5c, 0x00 }, /* 5C DAI1 EQ2 */ + { 0x5d, 0x00 }, /* 5D DAI1 EQ2 */ + { 0x5e, 0x00 }, /* 5E DAI1 EQ2 */ + { 0x5f, 0x00 }, /* 5F DAI1 EQ2 */ + + { 0x60, 0x00 }, /* 60 DAI1 EQ2 */ + { 0x61, 0x00 }, /* 61 DAI1 EQ2 */ + { 0x62, 0x00 }, /* 62 DAI1 EQ2 */ + { 0x63, 0x00 }, /* 63 DAI1 EQ2 */ + { 0x64, 0x00 }, /* 64 DAI1 EQ2 */ + { 0x65, 0x00 }, /* 65 DAI1 EQ2 */ + { 0x66, 0x00 }, /* 66 DAI1 EQ3 */ + { 0x67, 0x00 }, /* 67 DAI1 EQ3 */ + { 0x68, 0x00 }, /* 68 DAI1 EQ3 */ + { 0x69, 0x00 }, /* 69 DAI1 EQ3 */ + { 0x6a, 0x00 }, /* 6A DAI1 EQ3 */ + { 0x6b, 0x00 }, /* 6B DAI1 EQ3 */ + { 0x6c, 0x00 }, /* 6C DAI1 EQ3 */ + { 0x6d, 0x00 }, /* 6D DAI1 EQ3 */ + { 0x6e, 0x00 }, /* 6E DAI1 EQ3 */ + { 0x6f, 0x00 }, /* 6F DAI1 EQ3 */ + + { 0x70, 0x00 }, /* 70 DAI1 EQ4 */ + { 0x71, 0x00 }, /* 71 DAI1 EQ4 */ + { 0x72, 0x00 }, /* 72 DAI1 EQ4 */ + { 0x73, 0x00 }, /* 73 DAI1 EQ4 */ + { 0x74, 0x00 }, /* 74 DAI1 EQ4 */ + { 0x75, 0x00 }, /* 75 DAI1 EQ4 */ + { 0x76, 0x00 }, /* 76 DAI1 EQ4 */ + { 0x77, 0x00 }, /* 77 DAI1 EQ4 */ + { 0x78, 0x00 }, /* 78 DAI1 EQ4 */ + { 0x79, 0x00 }, /* 79 DAI1 EQ4 */ + { 0x7a, 0x00 }, /* 7A DAI1 EQ5 */ + { 0x7b, 0x00 }, /* 7B DAI1 EQ5 */ + { 0x7c, 0x00 }, /* 7C DAI1 EQ5 */ + { 0x7d, 0x00 }, /* 7D DAI1 EQ5 */ + { 0x7e, 0x00 }, /* 7E DAI1 EQ5 */ + { 0x7f, 0x00 }, /* 7F DAI1 EQ5 */ + + { 0x80, 0x00 }, /* 80 DAI1 EQ5 */ + { 0x81, 0x00 }, /* 81 DAI1 EQ5 */ + { 0x82, 0x00 }, /* 82 DAI1 EQ5 */ + { 0x83, 0x00 }, /* 83 DAI1 EQ5 */ + { 0x84, 0x00 }, /* 84 DAI2 EQ1 */ + { 0x85, 0x00 }, /* 85 DAI2 EQ1 */ + { 0x86, 0x00 }, /* 86 DAI2 EQ1 */ + { 0x87, 0x00 }, /* 87 DAI2 EQ1 */ + { 0x88, 0x00 }, /* 88 DAI2 EQ1 */ + { 0x89, 0x00 }, /* 89 DAI2 EQ1 */ + { 0x8a, 0x00 }, /* 8A DAI2 EQ1 */ + { 0x8b, 0x00 }, /* 8B DAI2 EQ1 */ + { 0x8c, 0x00 }, /* 8C DAI2 EQ1 */ + { 0x8d, 0x00 }, /* 8D DAI2 EQ1 */ + { 0x8e, 0x00 }, /* 8E DAI2 EQ2 */ + { 0x8f, 0x00 }, /* 8F DAI2 EQ2 */ + + { 0x90, 0x00 }, /* 90 DAI2 EQ2 */ + { 0x91, 0x00 }, /* 91 DAI2 EQ2 */ + { 0x92, 0x00 }, /* 92 DAI2 EQ2 */ + { 0x93, 0x00 }, /* 93 DAI2 EQ2 */ + { 0x94, 0x00 }, /* 94 DAI2 EQ2 */ + { 0x95, 0x00 }, /* 95 DAI2 EQ2 */ + { 0x96, 0x00 }, /* 96 DAI2 EQ2 */ + { 0x97, 0x00 }, /* 97 DAI2 EQ2 */ + { 0x98, 0x00 }, /* 98 DAI2 EQ3 */ + { 0x99, 0x00 }, /* 99 DAI2 EQ3 */ + { 0x9a, 0x00 }, /* 9A DAI2 EQ3 */ + { 0x9b, 0x00 }, /* 9B DAI2 EQ3 */ + { 0x9c, 0x00 }, /* 9C DAI2 EQ3 */ + { 0x9d, 0x00 }, /* 9D DAI2 EQ3 */ + { 0x9e, 0x00 }, /* 9E DAI2 EQ3 */ + { 0x9f, 0x00 }, /* 9F DAI2 EQ3 */ + + { 0xa0, 0x00 }, /* A0 DAI2 EQ3 */ + { 0xa1, 0x00 }, /* A1 DAI2 EQ3 */ + { 0xa2, 0x00 }, /* A2 DAI2 EQ4 */ + { 0xa3, 0x00 }, /* A3 DAI2 EQ4 */ + { 0xa4, 0x00 }, /* A4 DAI2 EQ4 */ + { 0xa5, 0x00 }, /* A5 DAI2 EQ4 */ + { 0xa6, 0x00 }, /* A6 DAI2 EQ4 */ + { 0xa7, 0x00 }, /* A7 DAI2 EQ4 */ + { 0xa8, 0x00 }, /* A8 DAI2 EQ4 */ + { 0xa9, 0x00 }, /* A9 DAI2 EQ4 */ + { 0xaa, 0x00 }, /* AA DAI2 EQ4 */ + { 0xab, 0x00 }, /* AB DAI2 EQ4 */ + { 0xac, 0x00 }, /* AC DAI2 EQ5 */ + { 0xad, 0x00 }, /* AD DAI2 EQ5 */ + { 0xae, 0x00 }, /* AE DAI2 EQ5 */ + { 0xaf, 0x00 }, /* AF DAI2 EQ5 */ + + { 0xb0, 0x00 }, /* B0 DAI2 EQ5 */ + { 0xb1, 0x00 }, /* B1 DAI2 EQ5 */ + { 0xb2, 0x00 }, /* B2 DAI2 EQ5 */ + { 0xb3, 0x00 }, /* B3 DAI2 EQ5 */ + { 0xb4, 0x00 }, /* B4 DAI2 EQ5 */ + { 0xb5, 0x00 }, /* B5 DAI2 EQ5 */ + { 0xb6, 0x00 }, /* B6 DAI1 biquad */ + { 0xb7, 0x00 }, /* B7 DAI1 biquad */ + { 0xb8 ,0x00 }, /* B8 DAI1 biquad */ + { 0xb9, 0x00 }, /* B9 DAI1 biquad */ + { 0xba, 0x00 }, /* BA DAI1 biquad */ + { 0xbb, 0x00 }, /* BB DAI1 biquad */ + { 0xbc, 0x00 }, /* BC DAI1 biquad */ + { 0xbd, 0x00 }, /* BD DAI1 biquad */ + { 0xbe, 0x00 }, /* BE DAI1 biquad */ + { 0xbf, 0x00 }, /* BF DAI1 biquad */ + + { 0xc0, 0x00 }, /* C0 DAI2 biquad */ + { 0xc1, 0x00 }, /* C1 DAI2 biquad */ + { 0xc2, 0x00 }, /* C2 DAI2 biquad */ + { 0xc3, 0x00 }, /* C3 DAI2 biquad */ + { 0xc4, 0x00 }, /* C4 DAI2 biquad */ + { 0xc5, 0x00 }, /* C5 DAI2 biquad */ + { 0xc6, 0x00 }, /* C6 DAI2 biquad */ + { 0xc7, 0x00 }, /* C7 DAI2 biquad */ + { 0xc8, 0x00 }, /* C8 DAI2 biquad */ + { 0xc9, 0x00 }, /* C9 DAI2 biquad */ }; static struct { @@ -606,11 +536,28 @@ static struct { { 0xFF, 0x00, 1 }, /* FF */ }; -static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool max98088_readable_register(struct device *dev, unsigned int reg) +{ + return max98088_access[reg].readable; +} + +static bool max98088_volatile_register(struct device *dev, unsigned int reg) { return max98088_access[reg].vol; } +static const struct regmap_config max98088_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .readable_reg = max98088_readable_register, + .volatile_reg = max98088_volatile_register, + .max_register = 0xff, + + .reg_defaults = max98088_reg, + .num_reg_defaults = ARRAY_SIZE(max98088_reg), + .cache_type = REGCACHE_RBTREE, +}; /* * Load equalizer DSP coefficient configurations registers @@ -1610,58 +1557,34 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) return 0; } -static void max98088_sync_cache(struct snd_soc_codec *codec) -{ - u8 *reg_cache = codec->reg_cache; - int i; - - if (!codec->cache_sync) - return; - - codec->cache_only = 0; - - /* write back cached values if they're writeable and - * different from the hardware default. - */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { - if (!max98088_access[i].writable) - continue; - - if (reg_cache[i] == max98088_reg[i]) - continue; - - snd_soc_write(codec, i, reg_cache[i]); - } - - codec->cache_sync = 0; -} - static int max98088_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - max98088_sync_cache(codec); - - snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, - M98088_MBEN, M98088_MBEN); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, - M98088_MBEN, 0); - codec->cache_sync = 1; - break; - } - codec->dapm.bias_level = level; - return 0; + struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + regcache_sync(max98088->regmap); + + snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, + M98088_MBEN, M98088_MBEN); + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, + M98088_MBEN, 0); + regcache_mark_dirty(max98088->regmap); + break; + } + codec->dapm.bias_level = level; + return 0; } #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 @@ -1988,9 +1911,9 @@ static int max98088_probe(struct snd_soc_codec *codec) struct max98088_cdata *cdata; int ret = 0; - codec->cache_sync = 1; + regcache_mark_dirty(max98088->regmap); - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -2048,9 +1971,6 @@ static int max98088_probe(struct snd_soc_codec *codec) max98088_handle_pdata(codec); - snd_soc_add_codec_controls(codec, max98088_snd_controls, - ARRAY_SIZE(max98088_snd_controls)); - err_access: return ret; } @@ -2066,15 +1986,13 @@ static int max98088_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_max98088 = { - .probe = max98088_probe, - .remove = max98088_remove, - .suspend = max98088_suspend, - .resume = max98088_resume, - .set_bias_level = max98088_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max98088_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = max98088_reg, - .volatile_register = max98088_volatile_register, + .probe = max98088_probe, + .remove = max98088_remove, + .suspend = max98088_suspend, + .resume = max98088_resume, + .set_bias_level = max98088_set_bias_level, + .controls = max98088_snd_controls, + .num_controls = ARRAY_SIZE(max98088_snd_controls), .dapm_widgets = max98088_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), .dapm_routes = max98088_audio_map, @@ -2082,7 +2000,7 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = { }; static int max98088_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct max98088_priv *max98088; int ret; @@ -2092,6 +2010,10 @@ static int max98088_i2c_probe(struct i2c_client *i2c, if (max98088 == NULL) return -ENOMEM; + max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap); + if (IS_ERR(max98088->regmap)) + return PTR_ERR(max98088->regmap); + max98088->devtype = id->driver_data; i2c_set_clientdata(i2c, max98088); diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 41cdd1642970..8fb072455802 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -39,6 +39,7 @@ struct max98095_cdata { }; struct max98095_priv { + struct regmap *regmap; enum max98095_type devtype; struct max98095_pdata *pdata; unsigned int sysclk; @@ -56,263 +57,145 @@ struct max98095_priv { struct snd_soc_jack *mic_jack; }; -static const u8 max98095_reg_def[M98095_REG_CNT] = { - 0x00, /* 00 */ - 0x00, /* 01 */ - 0x00, /* 02 */ - 0x00, /* 03 */ - 0x00, /* 04 */ - 0x00, /* 05 */ - 0x00, /* 06 */ - 0x00, /* 07 */ - 0x00, /* 08 */ - 0x00, /* 09 */ - 0x00, /* 0A */ - 0x00, /* 0B */ - 0x00, /* 0C */ - 0x00, /* 0D */ - 0x00, /* 0E */ - 0x00, /* 0F */ - 0x00, /* 10 */ - 0x00, /* 11 */ - 0x00, /* 12 */ - 0x00, /* 13 */ - 0x00, /* 14 */ - 0x00, /* 15 */ - 0x00, /* 16 */ - 0x00, /* 17 */ - 0x00, /* 18 */ - 0x00, /* 19 */ - 0x00, /* 1A */ - 0x00, /* 1B */ - 0x00, /* 1C */ - 0x00, /* 1D */ - 0x00, /* 1E */ - 0x00, /* 1F */ - 0x00, /* 20 */ - 0x00, /* 21 */ - 0x00, /* 22 */ - 0x00, /* 23 */ - 0x00, /* 24 */ - 0x00, /* 25 */ - 0x00, /* 26 */ - 0x00, /* 27 */ - 0x00, /* 28 */ - 0x00, /* 29 */ - 0x00, /* 2A */ - 0x00, /* 2B */ - 0x00, /* 2C */ - 0x00, /* 2D */ - 0x00, /* 2E */ - 0x00, /* 2F */ - 0x00, /* 30 */ - 0x00, /* 31 */ - 0x00, /* 32 */ - 0x00, /* 33 */ - 0x00, /* 34 */ - 0x00, /* 35 */ - 0x00, /* 36 */ - 0x00, /* 37 */ - 0x00, /* 38 */ - 0x00, /* 39 */ - 0x00, /* 3A */ - 0x00, /* 3B */ - 0x00, /* 3C */ - 0x00, /* 3D */ - 0x00, /* 3E */ - 0x00, /* 3F */ - 0x00, /* 40 */ - 0x00, /* 41 */ - 0x00, /* 42 */ - 0x00, /* 43 */ - 0x00, /* 44 */ - 0x00, /* 45 */ - 0x00, /* 46 */ - 0x00, /* 47 */ - 0x00, /* 48 */ - 0x00, /* 49 */ - 0x00, /* 4A */ - 0x00, /* 4B */ - 0x00, /* 4C */ - 0x00, /* 4D */ - 0x00, /* 4E */ - 0x00, /* 4F */ - 0x00, /* 50 */ - 0x00, /* 51 */ - 0x00, /* 52 */ - 0x00, /* 53 */ - 0x00, /* 54 */ - 0x00, /* 55 */ - 0x00, /* 56 */ - 0x00, /* 57 */ - 0x00, /* 58 */ - 0x00, /* 59 */ - 0x00, /* 5A */ - 0x00, /* 5B */ - 0x00, /* 5C */ - 0x00, /* 5D */ - 0x00, /* 5E */ - 0x00, /* 5F */ - 0x00, /* 60 */ - 0x00, /* 61 */ - 0x00, /* 62 */ - 0x00, /* 63 */ - 0x00, /* 64 */ - 0x00, /* 65 */ - 0x00, /* 66 */ - 0x00, /* 67 */ - 0x00, /* 68 */ - 0x00, /* 69 */ - 0x00, /* 6A */ - 0x00, /* 6B */ - 0x00, /* 6C */ - 0x00, /* 6D */ - 0x00, /* 6E */ - 0x00, /* 6F */ - 0x00, /* 70 */ - 0x00, /* 71 */ - 0x00, /* 72 */ - 0x00, /* 73 */ - 0x00, /* 74 */ - 0x00, /* 75 */ - 0x00, /* 76 */ - 0x00, /* 77 */ - 0x00, /* 78 */ - 0x00, /* 79 */ - 0x00, /* 7A */ - 0x00, /* 7B */ - 0x00, /* 7C */ - 0x00, /* 7D */ - 0x00, /* 7E */ - 0x00, /* 7F */ - 0x00, /* 80 */ - 0x00, /* 81 */ - 0x00, /* 82 */ - 0x00, /* 83 */ - 0x00, /* 84 */ - 0x00, /* 85 */ - 0x00, /* 86 */ - 0x00, /* 87 */ - 0x00, /* 88 */ - 0x00, /* 89 */ - 0x00, /* 8A */ - 0x00, /* 8B */ - 0x00, /* 8C */ - 0x00, /* 8D */ - 0x00, /* 8E */ - 0x00, /* 8F */ - 0x00, /* 90 */ - 0x00, /* 91 */ - 0x30, /* 92 */ - 0xF0, /* 93 */ - 0x00, /* 94 */ - 0x00, /* 95 */ - 0x3F, /* 96 */ - 0x00, /* 97 */ - 0x00, /* 98 */ - 0x00, /* 99 */ - 0x00, /* 9A */ - 0x00, /* 9B */ - 0x00, /* 9C */ - 0x00, /* 9D */ - 0x00, /* 9E */ - 0x00, /* 9F */ - 0x00, /* A0 */ - 0x00, /* A1 */ - 0x00, /* A2 */ - 0x00, /* A3 */ - 0x00, /* A4 */ - 0x00, /* A5 */ - 0x00, /* A6 */ - 0x00, /* A7 */ - 0x00, /* A8 */ - 0x00, /* A9 */ - 0x00, /* AA */ - 0x00, /* AB */ - 0x00, /* AC */ - 0x00, /* AD */ - 0x00, /* AE */ - 0x00, /* AF */ - 0x00, /* B0 */ - 0x00, /* B1 */ - 0x00, /* B2 */ - 0x00, /* B3 */ - 0x00, /* B4 */ - 0x00, /* B5 */ - 0x00, /* B6 */ - 0x00, /* B7 */ - 0x00, /* B8 */ - 0x00, /* B9 */ - 0x00, /* BA */ - 0x00, /* BB */ - 0x00, /* BC */ - 0x00, /* BD */ - 0x00, /* BE */ - 0x00, /* BF */ - 0x00, /* C0 */ - 0x00, /* C1 */ - 0x00, /* C2 */ - 0x00, /* C3 */ - 0x00, /* C4 */ - 0x00, /* C5 */ - 0x00, /* C6 */ - 0x00, /* C7 */ - 0x00, /* C8 */ - 0x00, /* C9 */ - 0x00, /* CA */ - 0x00, /* CB */ - 0x00, /* CC */ - 0x00, /* CD */ - 0x00, /* CE */ - 0x00, /* CF */ - 0x00, /* D0 */ - 0x00, /* D1 */ - 0x00, /* D2 */ - 0x00, /* D3 */ - 0x00, /* D4 */ - 0x00, /* D5 */ - 0x00, /* D6 */ - 0x00, /* D7 */ - 0x00, /* D8 */ - 0x00, /* D9 */ - 0x00, /* DA */ - 0x00, /* DB */ - 0x00, /* DC */ - 0x00, /* DD */ - 0x00, /* DE */ - 0x00, /* DF */ - 0x00, /* E0 */ - 0x00, /* E1 */ - 0x00, /* E2 */ - 0x00, /* E3 */ - 0x00, /* E4 */ - 0x00, /* E5 */ - 0x00, /* E6 */ - 0x00, /* E7 */ - 0x00, /* E8 */ - 0x00, /* E9 */ - 0x00, /* EA */ - 0x00, /* EB */ - 0x00, /* EC */ - 0x00, /* ED */ - 0x00, /* EE */ - 0x00, /* EF */ - 0x00, /* F0 */ - 0x00, /* F1 */ - 0x00, /* F2 */ - 0x00, /* F3 */ - 0x00, /* F4 */ - 0x00, /* F5 */ - 0x00, /* F6 */ - 0x00, /* F7 */ - 0x00, /* F8 */ - 0x00, /* F9 */ - 0x00, /* FA */ - 0x00, /* FB */ - 0x00, /* FC */ - 0x00, /* FD */ - 0x00, /* FE */ - 0x00, /* FF */ +static const struct reg_default max98095_reg_def[] = { + { 0xf, 0x00 }, /* 0F */ + { 0x10, 0x00 }, /* 10 */ + { 0x11, 0x00 }, /* 11 */ + { 0x12, 0x00 }, /* 12 */ + { 0x13, 0x00 }, /* 13 */ + { 0x14, 0x00 }, /* 14 */ + { 0x15, 0x00 }, /* 15 */ + { 0x16, 0x00 }, /* 16 */ + { 0x17, 0x00 }, /* 17 */ + { 0x18, 0x00 }, /* 18 */ + { 0x19, 0x00 }, /* 19 */ + { 0x1a, 0x00 }, /* 1A */ + { 0x1b, 0x00 }, /* 1B */ + { 0x1c, 0x00 }, /* 1C */ + { 0x1d, 0x00 }, /* 1D */ + { 0x1e, 0x00 }, /* 1E */ + { 0x1f, 0x00 }, /* 1F */ + { 0x20, 0x00 }, /* 20 */ + { 0x21, 0x00 }, /* 21 */ + { 0x22, 0x00 }, /* 22 */ + { 0x23, 0x00 }, /* 23 */ + { 0x24, 0x00 }, /* 24 */ + { 0x25, 0x00 }, /* 25 */ + { 0x26, 0x00 }, /* 26 */ + { 0x27, 0x00 }, /* 27 */ + { 0x28, 0x00 }, /* 28 */ + { 0x29, 0x00 }, /* 29 */ + { 0x2a, 0x00 }, /* 2A */ + { 0x2b, 0x00 }, /* 2B */ + { 0x2c, 0x00 }, /* 2C */ + { 0x2d, 0x00 }, /* 2D */ + { 0x2e, 0x00 }, /* 2E */ + { 0x2f, 0x00 }, /* 2F */ + { 0x30, 0x00 }, /* 30 */ + { 0x31, 0x00 }, /* 31 */ + { 0x32, 0x00 }, /* 32 */ + { 0x33, 0x00 }, /* 33 */ + { 0x34, 0x00 }, /* 34 */ + { 0x35, 0x00 }, /* 35 */ + { 0x36, 0x00 }, /* 36 */ + { 0x37, 0x00 }, /* 37 */ + { 0x38, 0x00 }, /* 38 */ + { 0x39, 0x00 }, /* 39 */ + { 0x3a, 0x00 }, /* 3A */ + { 0x3b, 0x00 }, /* 3B */ + { 0x3c, 0x00 }, /* 3C */ + { 0x3d, 0x00 }, /* 3D */ + { 0x3e, 0x00 }, /* 3E */ + { 0x3f, 0x00 }, /* 3F */ + { 0x40, 0x00 }, /* 40 */ + { 0x41, 0x00 }, /* 41 */ + { 0x42, 0x00 }, /* 42 */ + { 0x43, 0x00 }, /* 43 */ + { 0x44, 0x00 }, /* 44 */ + { 0x45, 0x00 }, /* 45 */ + { 0x46, 0x00 }, /* 46 */ + { 0x47, 0x00 }, /* 47 */ + { 0x48, 0x00 }, /* 48 */ + { 0x49, 0x00 }, /* 49 */ + { 0x4a, 0x00 }, /* 4A */ + { 0x4b, 0x00 }, /* 4B */ + { 0x4c, 0x00 }, /* 4C */ + { 0x4d, 0x00 }, /* 4D */ + { 0x4e, 0x00 }, /* 4E */ + { 0x4f, 0x00 }, /* 4F */ + { 0x50, 0x00 }, /* 50 */ + { 0x51, 0x00 }, /* 51 */ + { 0x52, 0x00 }, /* 52 */ + { 0x53, 0x00 }, /* 53 */ + { 0x54, 0x00 }, /* 54 */ + { 0x55, 0x00 }, /* 55 */ + { 0x56, 0x00 }, /* 56 */ + { 0x57, 0x00 }, /* 57 */ + { 0x58, 0x00 }, /* 58 */ + { 0x59, 0x00 }, /* 59 */ + { 0x5a, 0x00 }, /* 5A */ + { 0x5b, 0x00 }, /* 5B */ + { 0x5c, 0x00 }, /* 5C */ + { 0x5d, 0x00 }, /* 5D */ + { 0x5e, 0x00 }, /* 5E */ + { 0x5f, 0x00 }, /* 5F */ + { 0x60, 0x00 }, /* 60 */ + { 0x61, 0x00 }, /* 61 */ + { 0x62, 0x00 }, /* 62 */ + { 0x63, 0x00 }, /* 63 */ + { 0x64, 0x00 }, /* 64 */ + { 0x65, 0x00 }, /* 65 */ + { 0x66, 0x00 }, /* 66 */ + { 0x67, 0x00 }, /* 67 */ + { 0x68, 0x00 }, /* 68 */ + { 0x69, 0x00 }, /* 69 */ + { 0x6a, 0x00 }, /* 6A */ + { 0x6b, 0x00 }, /* 6B */ + { 0x6c, 0x00 }, /* 6C */ + { 0x6d, 0x00 }, /* 6D */ + { 0x6e, 0x00 }, /* 6E */ + { 0x6f, 0x00 }, /* 6F */ + { 0x70, 0x00 }, /* 70 */ + { 0x71, 0x00 }, /* 71 */ + { 0x72, 0x00 }, /* 72 */ + { 0x73, 0x00 }, /* 73 */ + { 0x74, 0x00 }, /* 74 */ + { 0x75, 0x00 }, /* 75 */ + { 0x76, 0x00 }, /* 76 */ + { 0x77, 0x00 }, /* 77 */ + { 0x78, 0x00 }, /* 78 */ + { 0x79, 0x00 }, /* 79 */ + { 0x7a, 0x00 }, /* 7A */ + { 0x7b, 0x00 }, /* 7B */ + { 0x7c, 0x00 }, /* 7C */ + { 0x7d, 0x00 }, /* 7D */ + { 0x7e, 0x00 }, /* 7E */ + { 0x7f, 0x00 }, /* 7F */ + { 0x80, 0x00 }, /* 80 */ + { 0x81, 0x00 }, /* 81 */ + { 0x82, 0x00 }, /* 82 */ + { 0x83, 0x00 }, /* 83 */ + { 0x84, 0x00 }, /* 84 */ + { 0x85, 0x00 }, /* 85 */ + { 0x86, 0x00 }, /* 86 */ + { 0x87, 0x00 }, /* 87 */ + { 0x88, 0x00 }, /* 88 */ + { 0x89, 0x00 }, /* 89 */ + { 0x8a, 0x00 }, /* 8A */ + { 0x8b, 0x00 }, /* 8B */ + { 0x8c, 0x00 }, /* 8C */ + { 0x8d, 0x00 }, /* 8D */ + { 0x8e, 0x00 }, /* 8E */ + { 0x8f, 0x00 }, /* 8F */ + { 0x90, 0x00 }, /* 90 */ + { 0x91, 0x00 }, /* 91 */ + { 0x92, 0x30 }, /* 92 */ + { 0x93, 0xF0 }, /* 93 */ + { 0x94, 0x00 }, /* 94 */ + { 0x95, 0x00 }, /* 95 */ + { 0x96, 0x3F }, /* 96 */ + { 0x97, 0x00 }, /* 97 */ + { 0xff, 0x00 }, /* FF */ }; static struct { @@ -577,14 +460,14 @@ static struct { { 0xFF, 0x00 }, /* FF */ }; -static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg) +static bool max98095_readable(struct device *dev, unsigned int reg) { if (reg >= M98095_REG_CNT) return 0; return max98095_access[reg].readable != 0; } -static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg) +static bool max98095_volatile(struct device *dev, unsigned int reg) { if (reg > M98095_REG_MAX_CACHED) return 1; @@ -611,22 +494,18 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg) return 0; } -/* - * Filter coefficients are in a separate register segment - * and they share the address space of the normal registers. - * The coefficient registers do not need or share the cache. - */ -static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret; +static const struct regmap_config max98095_regmap = { + .reg_bits = 8, + .val_bits = 8, - codec->cache_bypass = 1; - ret = snd_soc_write(codec, reg, value); - codec->cache_bypass = 0; + .reg_defaults = max98095_reg_def, + .num_reg_defaults = ARRAY_SIZE(max98095_reg_def), + .max_register = M98095_0FF_REV_ID, + .cache_type = REGCACHE_RBTREE, - return ret ? -EIO : 0; -} + .readable_reg = max98095_readable, + .volatile_reg = max98095_volatile, +}; /* * Load equalizer DSP coefficient configurations registers @@ -648,8 +527,8 @@ static void m98095_eq_band(struct snd_soc_codec *codec, unsigned int dai, /* Step through the registers and coefs */ for (i = 0; i < M98095_COEFS_PER_BAND; i++) { - max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i])); - max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i])); + snd_soc_write(codec, eq_reg++, M98095_BYTE1(coefs[i])); + snd_soc_write(codec, eq_reg++, M98095_BYTE0(coefs[i])); } } @@ -673,8 +552,8 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, /* Step through the registers and coefs */ for (i = 0; i < M98095_COEFS_PER_BAND; i++) { - max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i])); - max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i])); + snd_soc_write(codec, bq_reg++, M98095_BYTE1(coefs[i])); + snd_soc_write(codec, bq_reg++, M98095_BYTE0(coefs[i])); } } @@ -1285,14 +1164,6 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = { {"MIC2 Input", NULL, "MIC2"}, }; -static int max98095_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_add_codec_controls(codec, max98095_snd_controls, - ARRAY_SIZE(max98095_snd_controls)); - - return 0; -} - /* codec mclk clock divider coefficients */ static const struct { u32 rate; @@ -1748,6 +1619,7 @@ static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai, static int max98095_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { @@ -1759,7 +1631,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); + ret = regcache_sync(max98095->regmap); if (ret != 0) { dev_err(codec->dev, "Failed to sync cache: %d\n", ret); @@ -1774,7 +1646,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, M98095_090_PWR_EN_IN, M98095_MBEN, 0); - codec->cache_sync = 1; + regcache_mark_dirty(max98095->regmap); break; } codec->dapm.bias_level = level; @@ -1863,7 +1735,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, struct max98095_pdata *pdata = max98095->pdata; int channel = max98095_get_eq_channel(kcontrol->id.name); struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; + unsigned int sel = ucontrol->value.integer.value[0]; struct max98095_eq_cfg *coef_set; int fs, best, best_val, i; int regmask, regsave; @@ -2016,7 +1888,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, struct max98095_pdata *pdata = max98095->pdata; int channel = max98095_get_bq_channel(codec, kcontrol->id.name); struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; + unsigned int sel = ucontrol->value.integer.value[0]; struct max98095_biquad_cfg *coef_set; int fs, best, best_val, i; int regmask, regsave; @@ -2341,7 +2213,7 @@ static int max98095_reset(struct snd_soc_codec *codec) /* Reset to hardware default for registers, as there is not * a soft reset hardware control register */ for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { - ret = snd_soc_write(codec, i, max98095_reg_def[i]); + ret = snd_soc_write(codec, i, snd_soc_read(codec, i)); if (ret < 0) { dev_err(codec->dev, "Failed to reset: %d\n", ret); return ret; @@ -2358,7 +2230,7 @@ static int max98095_probe(struct snd_soc_codec *codec) struct i2c_client *client; int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -2447,8 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec) snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN, M98095_SHDNRUN); - max98095_add_widgets(codec); - return 0; err_irq: @@ -2480,11 +2350,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max98095 = { .suspend = max98095_suspend, .resume = max98095_resume, .set_bias_level = max98095_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max98095_reg_def), - .reg_word_size = sizeof(u8), - .reg_cache_default = max98095_reg_def, - .readable_register = max98095_readable, - .volatile_register = max98095_volatile, + .controls = max98095_snd_controls, + .num_controls = ARRAY_SIZE(max98095_snd_controls), .dapm_widgets = max98095_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), .dapm_routes = max98095_audio_map, @@ -2502,6 +2369,13 @@ static int max98095_i2c_probe(struct i2c_client *i2c, if (max98095 == NULL) return -ENOMEM; + max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap); + if (IS_ERR(max98095->regmap)) { + ret = PTR_ERR(max98095->regmap); + dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); + return ret; + } + max98095->devtype = id->driver_data; i2c_set_clientdata(i2c, max98095); max98095->pdata = i2c->dev.platform_data; diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 58c38a5b481c..c5dd61785f8d 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -27,18 +28,26 @@ #include "max9850.h" struct max9850_priv { + struct regmap *regmap; unsigned int sysclk; }; /* max9850 register cache */ -static const u8 max9850_reg[MAX9850_CACHEREGNUM] = { - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +static const struct reg_default max9850_reg[] = { + { 2, 0x0c }, + { 3, 0x00 }, + { 4, 0x00 }, + { 5, 0x00 }, + { 6, 0x00 }, + { 7, 0x00 }, + { 8, 0x00 }, + { 9, 0x00 }, + { 10, 0x00 }, }; /* these registers are not used at the moment but provided for the sake of * completeness */ -static int max9850_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) +static bool max9850_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case MAX9850_STATUSA: @@ -49,6 +58,15 @@ static int max9850_volatile_register(struct snd_soc_codec *codec, } } +static const struct regmap_config max9850_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = MAX9850_DIGITAL_AUDIO, + .volatile_reg = max9850_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + static const unsigned int max9850_tlv[] = { TLV_DB_RANGE_HEAD(4), 0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0), @@ -225,6 +243,7 @@ static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static int max9850_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { @@ -234,7 +253,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); + ret = regcache_sync(max9850->regmap); if (ret) { dev_err(codec->dev, "Failed to sync cache: %d\n", ret); @@ -295,7 +314,7 @@ static int max9850_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -316,10 +335,6 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = { .suspend = max9850_suspend, .resume = max9850_resume, .set_bias_level = max9850_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max9850_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = max9850_reg, - .volatile_register = max9850_volatile_register, .controls = max9850_controls, .num_controls = ARRAY_SIZE(max9850_controls), @@ -340,6 +355,10 @@ static int max9850_i2c_probe(struct i2c_client *i2c, if (max9850 == NULL) return -ENOMEM; + max9850->regmap = devm_regmap_init_i2c(i2c, &max9850_regmap); + if (IS_ERR(max9850->regmap)) + return PTR_ERR(max9850->regmap); + i2c_set_clientdata(i2c, max9850); ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index ea141e1d6f28..eedbf05b8e96 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -30,16 +30,10 @@ #include <sound/soc.h> #include <sound/initval.h> #include <sound/soc-dapm.h> +#include <linux/regmap.h> #include "mc13783.h" -#define MC13783_AUDIO_RX0 36 -#define MC13783_AUDIO_RX1 37 -#define MC13783_AUDIO_TX 38 -#define MC13783_SSI_NETWORK 39 -#define MC13783_AUDIO_CODEC 40 -#define MC13783_AUDIO_DAC 41 - #define AUDIO_RX0_ALSPEN (1 << 5) #define AUDIO_RX0_ALSPSEL (1 << 7) #define AUDIO_RX0_ADDCDC (1 << 21) @@ -95,45 +89,12 @@ struct mc13783_priv { struct mc13xxx *mc13xxx; + struct regmap *regmap; enum mc13783_ssi_port adc_ssi_port; enum mc13783_ssi_port dac_ssi_port; }; -static unsigned int mc13783_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - unsigned int value = 0; - - mc13xxx_lock(priv->mc13xxx); - - mc13xxx_reg_read(priv->mc13xxx, reg, &value); - - mc13xxx_unlock(priv->mc13xxx); - - return value; -} - -static int mc13783_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - int ret; - - mc13xxx_lock(priv->mc13xxx); - - ret = mc13xxx_reg_write(priv->mc13xxx, reg, value); - - /* include errata fix for spi audio problems */ - if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC) - ret = mc13xxx_reg_write(priv->mc13xxx, reg, value); - - mc13xxx_unlock(priv->mc13xxx); - - return ret; -} - /* Mapping between sample rates and register value */ static unsigned int mc13783_rates[] = { 8000, 11025, 12000, 16000, @@ -587,8 +548,14 @@ static struct snd_kcontrol_new mc13783_control_list[] = { static int mc13783_probe(struct snd_soc_codec *codec) { struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); + int ret; - mc13xxx_lock(priv->mc13xxx); + codec->control_data = dev_get_regmap(codec->dev->parent, NULL); + ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } /* these are the reset values */ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893); @@ -612,8 +579,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, 0, AUDIO_SSI_SEL); - mc13xxx_unlock(priv->mc13xxx); - return 0; } @@ -621,13 +586,9 @@ static int mc13783_remove(struct snd_soc_codec *codec) { struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - mc13xxx_lock(priv->mc13xxx); - /* Make sure VAUDIOON is off */ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0); - mc13xxx_unlock(priv->mc13xxx); - return 0; } @@ -717,8 +678,6 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = { static struct snd_soc_codec_driver soc_codec_dev_mc13783 = { .probe = mc13783_probe, .remove = mc13783_remove, - .read = mc13783_read, - .write = mc13783_write, .controls = mc13783_control_list, .num_controls = ARRAY_SIZE(mc13783_control_list), .dapm_widgets = mc13783_dapm_widgets, diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index c26a8f814b18..641eeeb00c5c 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -21,6 +21,7 @@ #include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/acpi.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -926,7 +927,7 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w, return 0; } -void hp_amp_power_on(struct snd_soc_codec *codec) +static void hp_amp_power_on(struct snd_soc_codec *codec) { struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); @@ -1609,7 +1610,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream, rt5640->lrck[dai->id] = params_rate(params); pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]); if (pre_div < 0) { - dev_err(codec->dev, "Unsupported clock setting\n"); + dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", + rt5640->lrck[dai->id], dai->id); return -EINVAL; } frame_size = snd_soc_params_to_frame_size(params); @@ -2080,6 +2082,14 @@ static const struct i2c_device_id rt5640_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); +#ifdef CONFIG_ACPI +static struct acpi_device_id rt5640_acpi_match[] = { + { "INT33CA", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match); +#endif + static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np) { rt5640->pdata.in1_diff = of_property_read_bool(np, @@ -2199,6 +2209,7 @@ static struct i2c_driver rt5640_i2c_driver = { .driver = { .name = "rt5640", .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(rt5640_acpi_match), }, .probe = rt5640_i2c_probe, .remove = rt5640_i2c_remove, diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index fd7c45b9ed5a..2f8161c1d5f0 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -27,6 +27,10 @@ #include "davinci-i2s.h" #include "davinci-mcasp.h" +struct snd_soc_card_drvdata_davinci { + unsigned sysclk; +}; + #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) static int evm_hw_params(struct snd_pcm_substream *substream, @@ -35,27 +39,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *soc_card = codec->card; int ret = 0; - unsigned sysclk; - - /* ASP1 on DM355 EVM is clocked by an external oscillator */ - if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || - machine_is_davinci_dm365_evm()) - sysclk = 27000000; - - /* ASP0 in DM6446 EVM is clocked by U55, as configured by - * board-dm644x-evm.c using GPIOs from U18. There are six - * options; here we "know" we use a 48 KHz sample rate. - */ - else if (machine_is_davinci_evm()) - sysclk = 12288000; - - else if (machine_is_davinci_da830_evm() || - machine_is_davinci_da850_evm()) - sysclk = 24576000; - - else - return -EINVAL; + unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) + snd_soc_card_get_drvdata(soc_card))->sysclk; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); @@ -243,35 +231,65 @@ static struct snd_soc_dai_link da850_evm_dai = { }; /* davinci dm6446 evm audio machine driver */ +/* + * ASP0 in DM6446 EVM is clocked by U55, as configured by + * board-dm644x-evm.c using GPIOs from U18. There are six + * options; here we "know" we use a 48 KHz sample rate. + */ +static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = { + .sysclk = 12288000, +}; + static struct snd_soc_card dm6446_snd_soc_card_evm = { .name = "DaVinci DM6446 EVM", .owner = THIS_MODULE, .dai_link = &dm6446_evm_dai, .num_links = 1, + .drvdata = &dm6446_snd_soc_card_drvdata, }; /* davinci dm355 evm audio machine driver */ +/* ASP1 on DM355 EVM is clocked by an external oscillator */ +static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm355_snd_soc_card_evm = { .name = "DaVinci DM355 EVM", .owner = THIS_MODULE, .dai_link = &dm355_evm_dai, .num_links = 1, + .drvdata = &dm355_snd_soc_card_drvdata, }; /* davinci dm365 evm audio machine driver */ +static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm365_snd_soc_card_evm = { .name = "DaVinci DM365 EVM", .owner = THIS_MODULE, .dai_link = &dm365_evm_dai, .num_links = 1, + .drvdata = &dm365_snd_soc_card_drvdata, }; /* davinci dm6467 evm audio machine driver */ +static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm6467_snd_soc_card_evm = { .name = "DaVinci DM6467 EVM", .owner = THIS_MODULE, .dai_link = dm6467_evm_dai, .num_links = ARRAY_SIZE(dm6467_evm_dai), + .drvdata = &dm6467_snd_soc_card_drvdata, +}; + +static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = { + .sysclk = 24576000, }; static struct snd_soc_card da830_snd_soc_card = { @@ -279,6 +297,11 @@ static struct snd_soc_card da830_snd_soc_card = { .owner = THIS_MODULE, .dai_link = &da830_evm_dai, .num_links = 1, + .drvdata = &da830_snd_soc_card_drvdata, +}; + +static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = { + .sysclk = 24576000, }; static struct snd_soc_card da850_snd_soc_card = { @@ -286,6 +309,7 @@ static struct snd_soc_card da850_snd_soc_card = { .owner = THIS_MODULE, .dai_link = &da850_evm_dai, .num_links = 1, + .drvdata = &da850_snd_soc_card_drvdata, }; static struct platform_device *evm_snd_device; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 3920c3e849ce..ff1f34766ee3 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -963,7 +963,7 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) return true; default: return false; - }; + } } static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) @@ -982,7 +982,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) return true; default: return false; - }; + } } static const struct regmap_config fsl_spdif_regmap_config = { @@ -1172,23 +1172,16 @@ static int fsl_spdif_probe(struct platform_device *pdev) /* Register with ASoC */ dev_set_drvdata(&pdev->dev, spdif_priv); - ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component, - &spdif_priv->cpu_dai_drv, 1); + ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, + &spdif_priv->cpu_dai_drv, 1); if (ret) { dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); return ret; } ret = imx_pcm_dma_init(pdev); - if (ret) { + if (ret) dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); - goto error_component; - } - - return ret; - -error_component: - snd_soc_unregister_component(&pdev->dev); return ret; } @@ -1196,7 +1189,6 @@ error_component: static int fsl_spdif_remove(struct platform_device *pdev) { imx_pcm_dma_exit(pdev); - snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c6b743978d5e..35e277379b86 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -469,19 +469,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * parameters, then the second stream may be * constrained to the wrong sample rate or size. */ - if (!first_runtime->sample_bits) { - dev_err(substream->pcm->card->dev, - "set sample size in %s stream first\n", - substream->stream == - SNDRV_PCM_STREAM_PLAYBACK - ? "capture" : "playback"); - return -EAGAIN; - } - - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + if (first_runtime->sample_bits) { + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, first_runtime->sample_bits, first_runtime->sample_bits); + } } ssi_private->second_stream = substream; @@ -748,7 +741,7 @@ static void fsl_ssi_ac97_init(void) fsl_ssi_setup(fsl_ac97_data); } -void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, +static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct ccsr_ssi *ssi = fsl_ac97_data->ssi; @@ -770,7 +763,7 @@ void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, udelay(100); } -unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, +static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { struct ccsr_ssi *ssi = fsl_ac97_data->ssi; @@ -936,7 +929,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) ssi_private->ssi_phys = res.start; ssi_private->irq = irq_of_parse_and_map(np, 0); - if (ssi_private->irq == NO_IRQ) { + if (!ssi_private->irq) { dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); return -ENXIO; } @@ -1135,7 +1128,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) if (ssi_private->ssi_on_imx) imx_pcm_dma_exit(pdev); snd_soc_unregister_component(&pdev->dev); - dev_set_drvdata(&pdev->dev, NULL); device_remove_file(&pdev->dev, &ssi_private->dev_attr); if (ssi_private->ssi_on_imx) clk_disable_unprepare(ssi_private->clk); diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 46c5b4fdfc52..6f4bdc89ae3c 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -62,7 +62,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) struct device_node *ssi_np, *codec_np; struct platform_device *ssi_pdev; struct i2c_client *codec_dev; - struct imx_sgtl5000_data *data; + struct imx_sgtl5000_data *data = NULL; int int_port, ext_port; int ret; @@ -128,7 +128,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } - data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); + data->codec_clk = clk_get(&codec_dev->dev, NULL); if (IS_ERR(data->codec_clk)) { ret = PTR_ERR(data->codec_clk); goto fail; @@ -159,7 +159,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets); - ret = snd_soc_register_card(&data->card); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); goto fail; @@ -172,6 +172,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) return 0; fail: + if (data && !IS_ERR(data->codec_clk)) + clk_put(data->codec_clk); if (ssi_np) of_node_put(ssi_np); if (codec_np) @@ -184,7 +186,7 @@ static int imx_sgtl5000_remove(struct platform_device *pdev) { struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); - snd_soc_unregister_card(&data->card); + clk_put(data->codec_clk); return 0; } @@ -202,7 +204,6 @@ static struct platform_driver imx_sgtl5000_driver = { .of_match_table = imx_sgtl5000_dt_ids, }, .probe = imx_sgtl5000_probe, - .remove = imx_sgtl5000_remove, }; module_platform_driver(imx_sgtl5000_driver); diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 816013b0ebba..8499d5292f08 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -87,7 +87,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) if (ret) goto error_dir; - ret = snd_soc_register_card(&data->card); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); goto error_dir; @@ -119,8 +119,6 @@ static int imx_spdif_audio_remove(struct platform_device *pdev) if (data->txdev) platform_device_unregister(data->txdev); - snd_soc_unregister_card(&data->card); - return 0; } diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 722afe69169e..6c6066618f3b 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -266,7 +266,7 @@ static int imx_wm8962_probe(struct platform_device *pdev) data->card.late_probe = imx_wm8962_late_probe; data->card.set_bias_level = imx_wm8962_set_bias_level; - ret = snd_soc_register_card(&data->card); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); goto clk_fail; @@ -296,7 +296,6 @@ static int imx_wm8962_remove(struct platform_device *pdev) if (!IS_ERR(data->codec_clk)) clk_disable_unprepare(data->codec_clk); - snd_soc_unregister_card(&data->card); return 0; } diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index b238434f92b0..0c85c4e1a1ae 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -29,9 +29,7 @@ #define KIRKWOOD_FORMATS \ (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE | \ - SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \ - SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE) + SNDRV_PCM_FMTBIT_S32_LE) static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) { diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index ee363845759e..d3d4c32434f7 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c @@ -400,7 +400,7 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) } /* register the soc card */ snd_soc_card_mfld.dev = &pdev->dev; - ret_val = snd_soc_register_card(&snd_soc_card_mfld); + ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_mfld); if (ret_val) { pr_debug("snd_soc_register_card failed %d\n", ret_val); return ret_val; @@ -410,20 +410,12 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) return 0; } -static int snd_mfld_mc_remove(struct platform_device *pdev) -{ - pr_debug("snd_mfld_mc_remove called\n"); - snd_soc_unregister_card(&snd_soc_card_mfld); - return 0; -} - static struct platform_driver snd_mfld_mc_driver = { .driver = { .owner = THIS_MODULE, .name = "msic_audio", }, .probe = snd_mfld_mc_probe, - .remove = snd_mfld_mc_remove, }; module_platform_driver(snd_mfld_mc_driver); diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b56b8a0e8deb..14152f6f70dd 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -768,8 +768,8 @@ static int mxs_saif_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "failed to init clocks\n"); } - ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, - &mxs_saif_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component, + &mxs_saif_dai, 1); if (ret) { dev_err(&pdev->dev, "register DAI failed\n"); return ret; @@ -778,21 +778,15 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = mxs_pcm_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - goto failed_pdev_alloc; + return ret; } return 0; - -failed_pdev_alloc: - snd_soc_unregister_component(&pdev->dev); - - return ret; } static int mxs_saif_remove(struct platform_device *pdev) { mxs_pcm_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 4bb273786ff3..61822cc53bd3 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = { .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), }; -static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) +static int mxs_sgtl5000_probe(struct platform_device *pdev) { + struct snd_soc_card *card = &mxs_sgtl5000; + int ret, i; struct device_node *np = pdev->dev.of_node; struct device_node *saif_np[2], *codec_np; - int i; - - if (!np) - return 1; /* no device tree */ saif_np[0] = of_parse_phandle(np, "saif-controllers", 0); saif_np[1] = of_parse_phandle(np, "saif-controllers", 1); @@ -152,18 +150,6 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) of_node_put(saif_np[0]); of_node_put(saif_np[1]); - return 0; -} - -static int mxs_sgtl5000_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &mxs_sgtl5000; - int ret; - - ret = mxs_sgtl5000_probe_dt(pdev); - if (ret < 0) - return ret; - /* * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). * The Sgtl5000 sysclk is derived from saif0 mclk and it's range diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 90d2a7cd2563..cd9ee167959d 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -490,14 +490,9 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) mcpdm->dev = &pdev->dev; - return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component, - &omap_mcpdm_dai, 1); -} - -static int asoc_mcpdm_remove(struct platform_device *pdev) -{ - snd_soc_unregister_component(&pdev->dev); - return 0; + return devm_snd_soc_register_component(&pdev->dev, + &omap_mcpdm_component, + &omap_mcpdm_dai, 1); } static const struct of_device_id omap_mcpdm_of_match[] = { @@ -514,7 +509,6 @@ static struct platform_driver asoc_mcpdm_driver = { }, .probe = asoc_mcpdm_probe, - .remove = asoc_mcpdm_remove, }; module_platform_driver(asoc_mcpdm_driver); diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 2a9324f794d8..6a8d6b5f160d 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c @@ -338,9 +338,9 @@ static int omap_twl4030_probe(struct platform_device *pdev) } snd_soc_card_set_drvdata(card, priv); - ret = snd_soc_register_card(card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", ret); return ret; } @@ -357,7 +357,6 @@ static int omap_twl4030_remove(struct platform_device *pdev) snd_soc_jack_free_gpios(&priv->hs_jack, ARRAY_SIZE(hs_jack_gpios), hs_jack_gpios); - snd_soc_unregister_card(card); return 0; } diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 41752a5fe3b0..5bf5f1f7cac5 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -455,8 +455,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) priv->dai_fmt = (unsigned int) -1; platform_set_drvdata(pdev, priv); - return snd_soc_register_component(&pdev->dev, &mmp_sspa_component, - &mmp_sspa_dai, 1); + return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, + &mmp_sspa_dai, 1); } static int asoc_mmp_sspa_remove(struct platform_device *pdev) @@ -466,7 +466,6 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) clk_disable(priv->audio_clk); clk_put(priv->audio_clk); clk_put(priv->sysclk); - snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 29e246803626..84f5d8b76679 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -356,6 +356,7 @@ static struct snd_soc_dapm_widget bells_widgets[] = { static struct snd_soc_dapm_route bells_routes[] = { { "Sub CLK_SYS", NULL, "OPCLK" }, + { "CLKIN", NULL, "OPCLK" }, { "DMIC", NULL, "MICBIAS2" }, { "IN2L", NULL, "DMIC" }, diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index b302f3b7a587..32956df8f50c 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1060,7 +1060,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops; i2s->i2s_dai_drv.suspend = i2s_suspend; i2s->i2s_dai_drv.resume = i2s_resume; - i2s->i2s_dai_drv.playback.channels_min = 2; + i2s->i2s_dai_drv.playback.channels_min = 1; i2s->i2s_dai_drv.playback.channels_max = 2; i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES; i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS; @@ -1143,9 +1143,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unable to get drvdata\n"); return -EFAULT; } - snd_soc_register_component(&sec_dai->pdev->dev, - &samsung_i2s_component, - &sec_dai->i2s_dai_drv, 1); + devm_snd_soc_register_component(&sec_dai->pdev->dev, + &samsung_i2s_component, + &sec_dai->i2s_dai_drv, 1); samsung_asoc_dma_platform_register(&pdev->dev); return 0; } @@ -1258,8 +1258,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) goto err; } - snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component, - &pri_dai->i2s_dai_drv, 1); + devm_snd_soc_register_component(&pri_dai->pdev->dev, + &samsung_i2s_component, + &pri_dai->i2s_dai_drv, 1); pm_runtime_enable(&pdev->dev); @@ -1294,7 +1295,6 @@ static int samsung_i2s_remove(struct platform_device *pdev) i2s->sec_dai = NULL; samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 5fd7a05a9b9e..831972d24fb9 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -193,7 +193,7 @@ static int smdk_audio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, board); - ret = snd_soc_register_card(card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); @@ -201,15 +201,6 @@ static int smdk_audio_probe(struct platform_device *pdev) return ret; } -static int smdk_audio_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - static struct platform_driver smdk_audio_driver = { .driver = { .name = "smdk-audio-wm8894", @@ -217,7 +208,6 @@ static struct platform_driver smdk_audio_driver = { .of_match_table = of_match_ptr(samsung_wm8994_of_match), }, .probe = smdk_audio_probe, - .remove = smdk_audio_remove, }; module_platform_driver(smdk_audio_driver); diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index d80deb7ccf13..9430097979a5 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -8,7 +8,6 @@ * for more details. */ #include <linux/sh_clk.h> -#include <mach/clock.h> #include "rsnd.h" #define CLKA 0 @@ -22,6 +21,7 @@ struct rsnd_adg { int rate_of_441khz_div_6; int rate_of_48khz_div_6; + u32 ckr; }; #define for_each_rsnd_clk(pos, adg, i) \ @@ -116,6 +116,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) found_clock: + /* see rsnd_adg_ssi_clk_init() */ + rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr); + rsnd_mod_write(mod, BRRA, 0x00000002); /* 1/6 */ + rsnd_mod_write(mod, BRRB, 0x00000002); /* 1/6 */ + /* * This "mod" = "ssi" here. * we can get "ssi id" from mod @@ -182,9 +187,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } } - rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr); - rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */ - rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */ + adg->ckr = ckr; } int rsnd_adg_probe(struct platform_device *pdev, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index a35706028514..fc83f0f2aead 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -106,51 +106,6 @@ (!(priv->info->func) ? -ENODEV : \ priv->info->func(param)) - -/* - * basic function - */ -u32 rsnd_read(struct rsnd_priv *priv, - struct rsnd_mod *mod, enum rsnd_reg reg) -{ - void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); - - BUG_ON(!base); - - return ioread32(base); -} - -void rsnd_write(struct rsnd_priv *priv, - struct rsnd_mod *mod, - enum rsnd_reg reg, u32 data) -{ - void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); - struct device *dev = rsnd_priv_to_dev(priv); - - BUG_ON(!base); - - dev_dbg(dev, "w %p : %08x\n", base, data); - - iowrite32(data, base); -} - -void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, - enum rsnd_reg reg, u32 mask, u32 data) -{ - void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); - struct device *dev = rsnd_priv_to_dev(priv); - u32 val; - - BUG_ON(!base); - - val = ioread32(base); - val &= ~mask; - val |= data & mask; - iowrite32(val, base); - - dev_dbg(dev, "s %p : %08x\n", base, val); -} - /* * rsnd_mod functions */ diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index babb203b43b7..61212ee97c28 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -11,6 +11,11 @@ #include "rsnd.h" struct rsnd_gen_ops { + int (*probe)(struct platform_device *pdev, + struct rcar_snd_info *info, + struct rsnd_priv *priv); + void (*remove)(struct platform_device *pdev, + struct rsnd_priv *priv); int (*path_init)(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); @@ -19,21 +24,97 @@ struct rsnd_gen_ops { struct rsnd_dai_stream *io); }; -struct rsnd_gen_reg_map { - int index; /* -1 : not supported */ - u32 offset_id; /* offset of ssi0, ssi1, ssi2... */ - u32 offset_adr; /* offset of SSICR, SSISR, ... */ -}; - struct rsnd_gen { void __iomem *base[RSND_BASE_MAX]; - struct rsnd_gen_reg_map reg_map[RSND_REG_MAX]; struct rsnd_gen_ops *ops; + + struct regmap *regmap; + struct regmap_field *regs[RSND_REG_MAX]; }; #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) +#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ + [id] = { \ + .reg = (unsigned int)gen->base[reg_id] + offset, \ + .lsb = 0, \ + .msb = 31, \ + .id_size = _id_size, \ + .id_offset = _id_offset, \ + } + +/* + * basic function + */ +static int rsnd_regmap_write32(void *context, const void *_data, size_t count) +{ + struct rsnd_priv *priv = context; + struct device *dev = rsnd_priv_to_dev(priv); + u32 *data = (u32 *)_data; + u32 val = data[1]; + void __iomem *reg = (void *)data[0]; + + iowrite32(val, reg); + + dev_dbg(dev, "w %p : %08x\n", reg, val); + + return 0; +} + +static int rsnd_regmap_read32(void *context, + const void *_data, size_t reg_size, + void *_val, size_t val_size) +{ + struct rsnd_priv *priv = context; + struct device *dev = rsnd_priv_to_dev(priv); + u32 *data = (u32 *)_data; + u32 *val = (u32 *)_val; + void __iomem *reg = (void *)data[0]; + + *val = ioread32(reg); + + dev_dbg(dev, "r %p : %08x\n", reg, *val); + + return 0; +} + +static struct regmap_bus rsnd_regmap_bus = { + .write = rsnd_regmap_write32, + .read = rsnd_regmap_read32, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +u32 rsnd_read(struct rsnd_priv *priv, + struct rsnd_mod *mod, enum rsnd_reg reg) +{ + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + u32 val; + + regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); + + return val; +} + +void rsnd_write(struct rsnd_priv *priv, + struct rsnd_mod *mod, + enum rsnd_reg reg, u32 data) +{ + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + + regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); +} + +void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, + enum rsnd_reg reg, u32 mask, u32 data) +{ + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + + regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), + mask, data); +} + /* * Gen2 * will be filled in the future @@ -98,44 +179,64 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, return ret; } -static struct rsnd_gen_ops rsnd_gen1_ops = { - .path_init = rsnd_gen1_path_init, - .path_exit = rsnd_gen1_path_exit, -}; +/* single address mapping */ +#define RSND_GEN1_S_REG(gen, reg, id, offset) \ + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) -#define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \ - do { \ - (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \ - (g)->reg_map[RSND_REG_##i].offset_id = oi; \ - (g)->reg_map[RSND_REG_##i].offset_adr = oa; \ - } while (0) +/* multi address mapping */ +#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) -static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen) +static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) { - RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00); - RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08); - RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c); - RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10); - RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0); - RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0); - RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4); - RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20); - RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214); - - RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00); - RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04); - RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08); - RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c); - RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10); - RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18); - RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c); - RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20); - - RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00); - RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04); - RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08); - RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c); - RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20); + int i; + struct device *dev = rsnd_priv_to_dev(priv); + struct regmap_config regc; + struct reg_field regf[RSND_REG_MAX] = { + RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), + RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), + RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), + RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), + RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0), + RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), + RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), + RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), + RSND_GEN1_M_REG(gen, SRU, BUSIF_ADINR, 0x214, 0x40), + + RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), + RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), + RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), + + RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), + RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), + RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), + RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), + RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), + }; + + memset(®c, 0, sizeof(regc)); + regc.reg_bits = 32; + regc.val_bits = 32; + + gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); + if (IS_ERR(gen->regmap)) { + dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); + return PTR_ERR(gen->regmap); + } + + for (i = 0; i < RSND_REG_MAX; i++) { + gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); + if (IS_ERR(gen->regs[i])) + return PTR_ERR(gen->regs[i]); + + } + + return 0; } static int rsnd_gen1_probe(struct platform_device *pdev, @@ -147,6 +248,7 @@ static int rsnd_gen1_probe(struct platform_device *pdev, struct resource *sru_res; struct resource *adg_res; struct resource *ssi_res; + int ret; /* * map address @@ -163,8 +265,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev, IS_ERR(gen->base[RSND_GEN1_SSI])) return -ENODEV; - gen->ops = &rsnd_gen1_ops; - rsnd_gen1_reg_map_init(gen); + ret = rsnd_gen1_regmap_init(priv, gen); + if (ret < 0) + return ret; dev_dbg(dev, "Gen1 device probed\n"); dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, @@ -183,6 +286,13 @@ static void rsnd_gen1_remove(struct platform_device *pdev, { } +static struct rsnd_gen_ops rsnd_gen1_ops = { + .probe = rsnd_gen1_probe, + .remove = rsnd_gen1_remove, + .path_init = rsnd_gen1_path_init, + .path_exit = rsnd_gen1_path_exit, +}; + /* * Gen */ @@ -204,46 +314,12 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv, return gen->ops->path_exit(priv, rdai, io); } -void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, - struct rsnd_mod *mod, - enum rsnd_reg reg) -{ - struct rsnd_gen *gen = rsnd_priv_to_gen(priv); - struct device *dev = rsnd_priv_to_dev(priv); - int index; - u32 offset_id, offset_adr; - - if (reg >= RSND_REG_MAX) { - dev_err(dev, "rsnd_reg reg error\n"); - return NULL; - } - - index = gen->reg_map[reg].index; - offset_id = gen->reg_map[reg].offset_id; - offset_adr = gen->reg_map[reg].offset_adr; - - if (index < 0) { - dev_err(dev, "unsupported reg access %d\n", reg); - return NULL; - } - - if (offset_id && mod) - offset_id *= rsnd_mod_id(mod); - - /* - * index/offset were set on gen1/gen2 - */ - - return gen->base[index] + offset_id + offset_adr; -} - int rsnd_gen_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; - int i; gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { @@ -251,30 +327,23 @@ int rsnd_gen_probe(struct platform_device *pdev, return -ENOMEM; } - priv->gen = gen; - - /* - * see - * rsnd_reg_get() - * rsnd_gen_probe() - */ - for (i = 0; i < RSND_REG_MAX; i++) - gen->reg_map[i].index = -1; - - /* - * init each module - */ if (rsnd_is_gen1(priv)) - return rsnd_gen1_probe(pdev, info, priv); + gen->ops = &rsnd_gen1_ops; - dev_err(dev, "unknown generation R-Car sound device\n"); + if (!gen->ops) { + dev_err(dev, "unknown generation R-Car sound device\n"); + return -ENODEV; + } - return -ENODEV; + priv->gen = gen; + + return gen->ops->probe(pdev, info, priv); } void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - if (rsnd_is_gen1(priv)) - rsnd_gen1_remove(pdev, priv); + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + + gen->ops->remove(pdev, priv); } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9cc6986a8cfb..3868aaf41cc4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -78,10 +78,6 @@ struct rsnd_dai_stream; #define rsnd_mod_bset(m, r, s, d) \ rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) -#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r) -#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d) -#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d) - u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 data); diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index e72f55428f0b..1b6663f45b34 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -11,12 +11,9 @@ * option) any later version. */ -#include <linux/i2c.h> -#include <linux/spi/spi.h> #include <sound/soc.h> -#include <linux/bitmap.h> -#include <linux/rbtree.h> #include <linux/export.h> +#include <linux/slab.h> #include <trace/events/asoc.h> @@ -66,126 +63,42 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, return -1; } -static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) +int snd_soc_cache_init(struct snd_soc_codec *codec) { - int i; - int ret; - const struct snd_soc_codec_driver *codec_drv; - unsigned int val; + const struct snd_soc_codec_driver *codec_drv = codec->driver; + size_t reg_size; - codec_drv = codec->driver; - for (i = 0; i < codec_drv->reg_cache_size; ++i) { - ret = snd_soc_cache_read(codec, i, &val); - if (ret) - return ret; - if (codec->reg_def_copy) - if (snd_soc_get_cache_val(codec->reg_def_copy, - i, codec_drv->reg_word_size) == val) - continue; + reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; - WARN_ON(!snd_soc_codec_writable_register(codec, i)); - - ret = snd_soc_write(codec, i, val); - if (ret) - return ret; - dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n", - i, val); - } - return 0; -} - -static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - snd_soc_set_cache_val(codec->reg_cache, reg, value, - codec->driver->reg_word_size); - return 0; -} - -static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, - unsigned int reg, unsigned int *value) -{ - *value = snd_soc_get_cache_val(codec->reg_cache, reg, - codec->driver->reg_word_size); - return 0; -} + mutex_init(&codec->cache_rw_mutex); -static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec) -{ - if (!codec->reg_cache) - return 0; - kfree(codec->reg_cache); - codec->reg_cache = NULL; - return 0; -} + dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", + codec->name); -static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) -{ - if (codec->reg_def_copy) - codec->reg_cache = kmemdup(codec->reg_def_copy, - codec->reg_size, GFP_KERNEL); + if (codec_drv->reg_cache_default) + codec->reg_cache = kmemdup(codec_drv->reg_cache_default, + reg_size, GFP_KERNEL); else - codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL); + codec->reg_cache = kzalloc(reg_size, GFP_KERNEL); if (!codec->reg_cache) return -ENOMEM; return 0; } -/* an array of all supported compression types */ -static const struct snd_soc_cache_ops cache_types[] = { - /* Flat *must* be the first entry for fallback */ - { - .id = SND_SOC_FLAT_COMPRESSION, - .name = "flat", - .init = snd_soc_flat_cache_init, - .exit = snd_soc_flat_cache_exit, - .read = snd_soc_flat_cache_read, - .write = snd_soc_flat_cache_write, - .sync = snd_soc_flat_cache_sync - }, -}; - -int snd_soc_cache_init(struct snd_soc_codec *codec) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cache_types); ++i) - if (cache_types[i].id == codec->compress_type) - break; - - /* Fall back to flat compression */ - if (i == ARRAY_SIZE(cache_types)) { - dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n", - codec->compress_type); - i = 0; - } - - mutex_init(&codec->cache_rw_mutex); - codec->cache_ops = &cache_types[i]; - - if (codec->cache_ops->init) { - if (codec->cache_ops->name) - dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n", - codec->cache_ops->name, codec->name); - return codec->cache_ops->init(codec); - } - return -ENOSYS; -} - /* * NOTE: keep in mind that this function might be called * multiple times. */ int snd_soc_cache_exit(struct snd_soc_codec *codec) { - if (codec->cache_ops && codec->cache_ops->exit) { - if (codec->cache_ops->name) - dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n", - codec->cache_ops->name, codec->name); - return codec->cache_ops->exit(codec); - } - return -ENOSYS; + dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", + codec->name); + if (!codec->reg_cache) + return 0; + kfree(codec->reg_cache); + codec->reg_cache = NULL; + return 0; } /** @@ -198,18 +111,15 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) int snd_soc_cache_read(struct snd_soc_codec *codec, unsigned int reg, unsigned int *value) { - int ret; + if (!value) + return -EINVAL; mutex_lock(&codec->cache_rw_mutex); - - if (value && codec->cache_ops && codec->cache_ops->read) { - ret = codec->cache_ops->read(codec, reg, value); - mutex_unlock(&codec->cache_rw_mutex); - return ret; - } - + *value = snd_soc_get_cache_val(codec->reg_cache, reg, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); - return -ENOSYS; + + return 0; } EXPORT_SYMBOL_GPL(snd_soc_cache_read); @@ -223,20 +133,42 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_read); int snd_soc_cache_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { + mutex_lock(&codec->cache_rw_mutex); + snd_soc_set_cache_val(codec->reg_cache, reg, value, + codec->driver->reg_word_size); + mutex_unlock(&codec->cache_rw_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_cache_write); + +static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) +{ + int i; int ret; + const struct snd_soc_codec_driver *codec_drv; + unsigned int val; - mutex_lock(&codec->cache_rw_mutex); + codec_drv = codec->driver; + for (i = 0; i < codec_drv->reg_cache_size; ++i) { + ret = snd_soc_cache_read(codec, i, &val); + if (ret) + return ret; + if (codec_drv->reg_cache_default) + if (snd_soc_get_cache_val(codec_drv->reg_cache_default, + i, codec_drv->reg_word_size) == val) + continue; - if (codec->cache_ops && codec->cache_ops->write) { - ret = codec->cache_ops->write(codec, reg, value); - mutex_unlock(&codec->cache_rw_mutex); - return ret; - } + WARN_ON(!snd_soc_codec_writable_register(codec, i)); - mutex_unlock(&codec->cache_rw_mutex); - return -ENOSYS; + ret = snd_soc_write(codec, i, val); + if (ret) + return ret; + dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n", + i, val); + } + return 0; } -EXPORT_SYMBOL_GPL(snd_soc_cache_write); /** * snd_soc_cache_sync: Sync the register cache with the hardware. @@ -249,92 +181,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write); */ int snd_soc_cache_sync(struct snd_soc_codec *codec) { + const char *name = "flat"; int ret; - const char *name; - if (!codec->cache_sync) { + if (!codec->cache_sync) return 0; - } - - if (!codec->cache_ops || !codec->cache_ops->sync) - return -ENOSYS; - if (codec->cache_ops->name) - name = codec->cache_ops->name; - else - name = "unknown"; - - if (codec->cache_ops->name) - dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n", - codec->cache_ops->name, codec->name); + dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", + codec->name); trace_snd_soc_cache_sync(codec, name, "start"); - ret = codec->cache_ops->sync(codec); + ret = snd_soc_flat_cache_sync(codec); if (!ret) codec->cache_sync = 0; trace_snd_soc_cache_sync(codec, name, "end"); return ret; } EXPORT_SYMBOL_GPL(snd_soc_cache_sync); - -static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec, - unsigned int reg) -{ - const struct snd_soc_codec_driver *codec_drv; - unsigned int min, max, index; - - codec_drv = codec->driver; - min = 0; - max = codec_drv->reg_access_size - 1; - do { - index = (min + max) / 2; - if (codec_drv->reg_access_default[index].reg == reg) - return index; - if (codec_drv->reg_access_default[index].reg < reg) - min = index + 1; - else - max = index; - } while (min <= max); - return -1; -} - -int snd_soc_default_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - int index; - - if (reg >= codec->driver->reg_cache_size) - return 1; - index = snd_soc_get_reg_access_index(codec, reg); - if (index < 0) - return 0; - return codec->driver->reg_access_default[index].vol; -} -EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register); - -int snd_soc_default_readable_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - int index; - - if (reg >= codec->driver->reg_cache_size) - return 1; - index = snd_soc_get_reg_access_index(codec, reg); - if (index < 0) - return 0; - return codec->driver->reg_access_default[index].read; -} -EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); - -int snd_soc_default_writable_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - int index; - - if (reg >= codec->driver->reg_cache_size) - return 1; - index = snd_soc_get_reg_access_index(codec, reg); - if (index < 0) - return 0; - return codec->driver->reg_access_default[index].write; -} -EXPORT_SYMBOL_GPL(snd_soc_default_writable_register); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4d0561312f3b..4280c70ba0ee 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1380,7 +1380,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) return -ENODEV; list_add(&cpu_dai->dapm.list, &card->dapm_list); - snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); } if (cpu_dai->driver->probe) { @@ -1590,17 +1589,13 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) soc_remove_codec(codec); } -static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, - enum snd_soc_compress_type compress_type) +static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) { int ret; if (codec->cache_init) return 0; - /* override the compress_type if necessary */ - if (compress_type && codec->compress_type != compress_type) - codec->compress_type = compress_type; ret = snd_soc_cache_init(codec); if (ret < 0) { dev_err(codec->dev, @@ -1615,8 +1610,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, static int snd_soc_instantiate_card(struct snd_soc_card *card) { struct snd_soc_codec *codec; - struct snd_soc_codec_conf *codec_conf; - enum snd_soc_compress_type compress_type; struct snd_soc_dai_link *dai_link; int ret, i, order, dai_fmt; @@ -1640,19 +1633,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) list_for_each_entry(codec, &codec_list, list) { if (codec->cache_init) continue; - /* by default we don't override the compress_type */ - compress_type = 0; - /* check to see if we need to override the compress_type */ - for (i = 0; i < card->num_configs; ++i) { - codec_conf = &card->codec_conf[i]; - if (!strcmp(codec->name, codec_conf->dev_name)) { - compress_type = codec_conf->compress_type; - if (compress_type && compress_type - != codec->compress_type) - break; - } - } - ret = snd_soc_init_codec_cache(codec, compress_type); + ret = snd_soc_init_codec_cache(codec); if (ret < 0) goto base_error; } @@ -2298,13 +2279,6 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec, } EXPORT_SYMBOL_GPL(snd_soc_write); -unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec, - unsigned int reg, const void *data, size_t len) -{ - return codec->bulk_write_raw(codec, reg, data, len); -} -EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw); - /** * snd_soc_update_bits - update codec register bits * @codec: audio codec @@ -3577,6 +3551,22 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); /** + * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. + * @dai: DAI + * @ratio Ratio of BCLK to Sample rate. + * + * Configures the DAI for a preset BCLK to sample rate ratio. + */ +int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + if (dai->driver && dai->driver->ops->set_bclk_ratio) + return dai->driver->ops->set_bclk_ratio(dai, ratio); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); + +/** * snd_soc_dai_set_fmt - configure DAI hardware audio format. * @dai: DAI * @fmt: SND_SOC_DAIFMT_ format value. @@ -4021,6 +4011,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count) } /** + * snd_soc_register_component - Register a component with the ASoC core + * + */ +static int +__snd_soc_register_component(struct device *dev, + struct snd_soc_component *cmpnt, + const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_dai_driver *dai_drv, + int num_dai, bool allow_single_dai) +{ + int ret; + + dev_dbg(dev, "component register %s\n", dev_name(dev)); + + if (!cmpnt) { + dev_err(dev, "ASoC: Failed to connecting component\n"); + return -ENOMEM; + } + + cmpnt->name = fmt_single_name(dev, &cmpnt->id); + if (!cmpnt->name) { + dev_err(dev, "ASoC: Failed to simplifying name\n"); + return -ENOMEM; + } + + cmpnt->dev = dev; + cmpnt->driver = cmpnt_drv; + cmpnt->num_dai = num_dai; + + /* + * snd_soc_register_dai() uses fmt_single_name(), and + * snd_soc_register_dais() uses fmt_multiple_name() + * for dai->name which is used for name based matching + * + * this function is used from cpu/codec. + * allow_single_dai flag can ignore "codec" driver reworking + * since it had been used snd_soc_register_dais(), + */ + if ((1 == num_dai) && allow_single_dai) + ret = snd_soc_register_dai(dev, dai_drv); + else + ret = snd_soc_register_dais(dev, dai_drv, num_dai); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); + goto error_component_name; + } + + mutex_lock(&client_mutex); + list_add(&cmpnt->list, &component_list); + mutex_unlock(&client_mutex); + + dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); + + return ret; + +error_component_name: + kfree(cmpnt->name); + + return ret; +} + +int snd_soc_register_component(struct device *dev, + const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_dai_driver *dai_drv, + int num_dai) +{ + struct snd_soc_component *cmpnt; + + cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); + if (!cmpnt) { + dev_err(dev, "ASoC: Failed to allocate memory\n"); + return -ENOMEM; + } + + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, + dai_drv, num_dai, true); +} +EXPORT_SYMBOL_GPL(snd_soc_register_component); + +/** + * snd_soc_unregister_component - Unregister a component from the ASoC core + * + */ +void snd_soc_unregister_component(struct device *dev) +{ + struct snd_soc_component *cmpnt; + + list_for_each_entry(cmpnt, &component_list, list) { + if (dev == cmpnt->dev) + goto found; + } + return; + +found: + snd_soc_unregister_dais(dev, cmpnt->num_dai); + + mutex_lock(&client_mutex); + list_del(&cmpnt->list); + mutex_unlock(&client_mutex); + + dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); + kfree(cmpnt->name); +} +EXPORT_SYMBOL_GPL(snd_soc_unregister_component); + +/** * snd_soc_add_platform - Add a platform to the ASoC core * @dev: The parent device for the platform * @platform: The platform to add @@ -4166,7 +4262,6 @@ int snd_soc_register_codec(struct device *dev, struct snd_soc_dai_driver *dai_drv, int num_dai) { - size_t reg_size; struct snd_soc_codec *codec; int ret, i; @@ -4183,11 +4278,6 @@ int snd_soc_register_codec(struct device *dev, goto fail_codec; } - if (codec_drv->compress_type) - codec->compress_type = codec_drv->compress_type; - else - codec->compress_type = SND_SOC_FLAT_COMPRESSION; - codec->write = codec_drv->write; codec->read = codec_drv->read; codec->volatile_register = codec_drv->volatile_register; @@ -4204,35 +4294,6 @@ int snd_soc_register_codec(struct device *dev, codec->num_dai = num_dai; mutex_init(&codec->mutex); - /* allocate CODEC register cache */ - if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { - reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; - codec->reg_size = reg_size; - /* it is necessary to make a copy of the default register cache - * because in the case of using a compression type that requires - * the default register cache to be marked as the - * kernel might have freed the array by the time we initialize - * the cache. - */ - if (codec_drv->reg_cache_default) { - codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default, - reg_size, GFP_KERNEL); - if (!codec->reg_def_copy) { - ret = -ENOMEM; - goto fail_codec_name; - } - } - } - - if (codec_drv->reg_access_size && codec_drv->reg_access_default) { - if (!codec->volatile_register) - codec->volatile_register = snd_soc_default_volatile_register; - if (!codec->readable_register) - codec->readable_register = snd_soc_default_readable_register; - if (!codec->writable_register) - codec->writable_register = snd_soc_default_writable_register; - } - for (i = 0; i < num_dai; i++) { fixup_codec_formats(&dai_drv[i].playback); fixup_codec_formats(&dai_drv[i].capture); @@ -4242,10 +4303,12 @@ int snd_soc_register_codec(struct device *dev, list_add(&codec->list, &codec_list); mutex_unlock(&client_mutex); - /* register any DAIs */ - ret = snd_soc_register_dais(dev, dai_drv, num_dai); + /* register component */ + ret = __snd_soc_register_component(dev, &codec->component, + &codec_drv->component_driver, + dai_drv, num_dai, false); if (ret < 0) { - dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret); + dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); goto fail_codec_name; } @@ -4280,7 +4343,7 @@ void snd_soc_unregister_codec(struct device *dev) return; found: - snd_soc_unregister_dais(dev, codec->num_dai); + snd_soc_unregister_component(dev); mutex_lock(&client_mutex); list_del(&codec->list); @@ -4289,98 +4352,11 @@ found: dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name); snd_soc_cache_exit(codec); - kfree(codec->reg_def_copy); kfree(codec->name); kfree(codec); } EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); - -/** - * snd_soc_register_component - Register a component with the ASoC core - * - */ -int snd_soc_register_component(struct device *dev, - const struct snd_soc_component_driver *cmpnt_drv, - struct snd_soc_dai_driver *dai_drv, - int num_dai) -{ - struct snd_soc_component *cmpnt; - int ret; - - dev_dbg(dev, "component register %s\n", dev_name(dev)); - - cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); - if (!cmpnt) { - dev_err(dev, "ASoC: Failed to allocate memory\n"); - return -ENOMEM; - } - - cmpnt->name = fmt_single_name(dev, &cmpnt->id); - if (!cmpnt->name) { - dev_err(dev, "ASoC: Failed to simplifying name\n"); - return -ENOMEM; - } - - cmpnt->dev = dev; - cmpnt->driver = cmpnt_drv; - cmpnt->num_dai = num_dai; - - /* - * snd_soc_register_dai() uses fmt_single_name(), and - * snd_soc_register_dais() uses fmt_multiple_name() - * for dai->name which is used for name based matching - */ - if (1 == num_dai) - ret = snd_soc_register_dai(dev, dai_drv); - else - ret = snd_soc_register_dais(dev, dai_drv, num_dai); - if (ret < 0) { - dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); - goto error_component_name; - } - - mutex_lock(&client_mutex); - list_add(&cmpnt->list, &component_list); - mutex_unlock(&client_mutex); - - dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); - - return ret; - -error_component_name: - kfree(cmpnt->name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_register_component); - -/** - * snd_soc_unregister_component - Unregister a component from the ASoC core - * - */ -void snd_soc_unregister_component(struct device *dev) -{ - struct snd_soc_component *cmpnt; - - list_for_each_entry(cmpnt, &component_list, list) { - if (dev == cmpnt->dev) - goto found; - } - return; - -found: - snd_soc_unregister_dais(dev, cmpnt->num_dai); - - mutex_lock(&client_mutex); - list_del(&cmpnt->list); - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); - kfree(cmpnt->name); -} -EXPORT_SYMBOL_GPL(snd_soc_unregister_component); - /* Retrieve a card's name from device tree */ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname) @@ -4568,6 +4544,41 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); +int snd_soc_of_get_dai_name(struct device_node *of_node, + const char **dai_name) +{ + struct snd_soc_component *pos; + struct of_phandle_args args; + int ret; + + ret = of_parse_phandle_with_args(of_node, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret) + return ret; + + ret = -EPROBE_DEFER; + + mutex_lock(&client_mutex); + list_for_each_entry(pos, &component_list, list) { + if (pos->dev->of_node != args.np) + continue; + + if (!pos->driver->of_xlate_dai_name) { + ret = -ENOSYS; + break; + } + + ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name); + break; + } + mutex_unlock(&client_mutex); + + of_node_put(args.np); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); + static int __init snd_soc_init(void) { #ifdef CONFIG_DEBUG_FS diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c new file mode 100644 index 000000000000..b1d732255c02 --- /dev/null +++ b/sound/soc/soc-devres.c @@ -0,0 +1,86 @@ +/* + * soc-devres.c -- ALSA SoC Audio Layer devres functions + * + * Copyright (C) 2013 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <sound/soc.h> + +static void devm_component_release(struct device *dev, void *res) +{ + snd_soc_unregister_component(*(struct device **)res); +} + +/** + * devm_snd_soc_register_component - resource managed component registration + * @dev: Device used to manage component + * @cmpnt_drv: Component driver + * @dai_drv: DAI driver + * @num_dai: Number of DAIs to register + * + * Register a component with automatic unregistration when the device is + * unregistered. + */ +int devm_snd_soc_register_component(struct device *dev, + const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_dai_driver *dai_drv, int num_dai) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); + if (ret == 0) { + *ptr = dev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); + +static void devm_card_release(struct device *dev, void *res) +{ + snd_soc_unregister_card(*(struct snd_soc_card **)res); +} + +/** + * devm_snd_soc_register_card - resource managed card registration + * @dev: Device used to manage card + * @card: Card to register + * + * Register a card with automatic unregistration when the device is + * unregistered. + */ +int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = snd_soc_register_card(card); + if (ret == 0) { + *ptr = dev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 122c0c18b9dd..4f11d23f2062 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -65,31 +65,6 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) return val; } -/* Primitive bulk write support for soc-cache. The data pointed to by - * `data' needs to already be in the form the hardware expects. Any - * data written through this function will not go through the cache as - * it only handles writing to volatile or out of bounds registers. - * - * This is currently only supported for devices using the regmap API - * wrappers. - */ -static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, - unsigned int reg, - const void *data, size_t len) -{ - /* To ensure that we don't get out of sync with the cache, check - * whether the base register is volatile or if we've directly asked - * to bypass the cache. Out of bounds registers are considered - * volatile. - */ - if (!codec->cache_bypass - && !snd_soc_codec_volatile_register(codec, reg) - && reg < codec->driver->reg_cache_size) - return -EINVAL; - - return regmap_raw_write(codec->control_data, reg, data, len); -} - /** * snd_soc_codec_set_cache_io: Set up standard I/O functions. * @@ -119,7 +94,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, memset(&config, 0, sizeof(config)); codec->write = hw_write; codec->read = hw_read; - codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; config.reg_bits = addr_bits; config.val_bits = data_bits; diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 29b211e9c060..5e633659c1b3 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -75,7 +75,11 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { static int dummy_dma_open(struct snd_pcm_substream *substream) { - snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + /* BE's dont need dummy params */ + if (!rtd->dai_link->no_pcm) + snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); return 0; } |