diff options
Diffstat (limited to 'sound/soc/codecs/ak4641.c')
| -rw-r--r-- | sound/soc/codecs/ak4641.c | 222 |
1 files changed, 106 insertions, 116 deletions
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 5f9af1fb76e8..9db8cdb26d33 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ak4641.c -- AK4641 ALSA Soc Audio driver * @@ -5,10 +6,6 @@ * Copyright (C) 2011 Dmitry Artamonow <mad_soft@inbox.ru> * * Based on ak4535.c by Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> @@ -17,6 +14,7 @@ #include <linux/gpio.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -26,10 +24,31 @@ #include <sound/tlv.h> #include <sound/ak4641.h> -#include "ak4641.h" +/* AK4641 register space */ +#define AK4641_PM1 0x00 +#define AK4641_PM2 0x01 +#define AK4641_SIG1 0x02 +#define AK4641_SIG2 0x03 +#define AK4641_MODE1 0x04 +#define AK4641_MODE2 0x05 +#define AK4641_DAC 0x06 +#define AK4641_MIC 0x07 +#define AK4641_TIMER 0x08 +#define AK4641_ALC1 0x09 +#define AK4641_ALC2 0x0a +#define AK4641_PGA 0x0b +#define AK4641_LATT 0x0c +#define AK4641_RATT 0x0d +#define AK4641_VOL 0x0e +#define AK4641_STATUS 0x0f +#define AK4641_EQLO 0x10 +#define AK4641_EQMID 0x11 +#define AK4641_EQHI 0x12 +#define AK4641_BTIF 0x13 /* codec private data */ struct ak4641_priv { + struct regmap *regmap; unsigned int sysclk; int deemph; int playback_fs; @@ -38,19 +57,19 @@ struct ak4641_priv { /* * ak4641 register cache */ -static const u8 ak4641_reg[AK4641_CACHEREGNUM] = { - 0x00, 0x80, 0x00, 0x80, - 0x02, 0x00, 0x11, 0x05, - 0x00, 0x00, 0x36, 0x10, - 0x00, 0x00, 0x57, 0x00, - 0x88, 0x88, 0x08, 0x08 +static const struct reg_default ak4641_reg_defaults[] = { + { 0, 0x00 }, { 1, 0x80 }, { 2, 0x00 }, { 3, 0x80 }, + { 4, 0x02 }, { 5, 0x00 }, { 6, 0x11 }, { 7, 0x05 }, + { 8, 0x00 }, { 9, 0x00 }, { 10, 0x36 }, { 11, 0x10 }, + { 12, 0x00 }, { 13, 0x00 }, { 14, 0x57 }, { 15, 0x00 }, + { 16, 0x88 }, { 17, 0x88 }, { 18, 0x08 }, { 19, 0x08 } }; static const int deemph_settings[] = {44100, 0, 48000, 32000}; -static int ak4641_set_deemph(struct snd_soc_codec *codec) +static int ak4641_set_deemph(struct snd_soc_component *component) { - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); int i, best = 0; for (i = 0 ; i < ARRAY_SIZE(deemph_settings); i++) { @@ -64,33 +83,33 @@ static int ak4641_set_deemph(struct snd_soc_codec *codec) best = i; } - dev_dbg(codec->dev, "Set deemphasis %d\n", best); + dev_dbg(component->dev, "Set deemphasis %d\n", best); - return snd_soc_update_bits(codec, AK4641_DAC, 0x3, best); + return snd_soc_component_update_bits(component, AK4641_DAC, 0x3, best); } static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); + int deemph = ucontrol->value.integer.value[0]; if (deemph > 1) return -EINVAL; ak4641->deemph = deemph; - return ak4641_set_deemph(codec); + return ak4641_set_deemph(component); } static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); - ucontrol->value.enumerated.item[0] = ak4641->deemph; + ucontrol->value.integer.value[0] = ak4641->deemph; return 0; }; @@ -111,14 +130,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); -static const struct soc_enum ak4641_mono_out_enum = - SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); -static const struct soc_enum ak4641_hp_out_enum = - SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); -static const struct soc_enum ak4641_mic_select_enum = - SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); -static const struct soc_enum ak4641_mic_or_dac_enum = - SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); +static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum, + AK4641_SIG1, 6, ak4641_mono_out); +static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum, + AK4641_MODE2, 2, ak4641_hp_out); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum, + AK4641_MIC, 1, ak4641_mic_select); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum, + AK4641_BTIF, 4, ak4641_mic_or_dac); static const struct snd_kcontrol_new ak4641_snd_controls[] = { SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), @@ -285,8 +304,8 @@ static const struct snd_soc_dapm_route ak4641_audio_map[] = { static int ak4641_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 ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = codec_dai->component; + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); ak4641->sysclk = freq; return 0; @@ -296,8 +315,8 @@ static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_codec *codec = dai->codec; - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *component = dai->component; + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); int rate = params_rate(params), fs = 256; u8 mode2; @@ -318,17 +337,17 @@ static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, mode2 = (0x0 << 5); break; default: - dev_err(codec->dev, "Error: unsupported fs=%d\n", fs); + dev_err(component->dev, "Error: unsupported fs=%d\n", fs); return -EINVAL; } - snd_soc_update_bits(codec, AK4641_MODE2, (0x3 << 5), mode2); + snd_soc_component_update_bits(component, AK4641_MODE2, (0x3 << 5), mode2); /* Update de-emphasis filter for the new rate */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ak4641->playback_fs = rate; - ak4641_set_deemph(codec); - }; + ak4641_set_deemph(component); + } return 0; } @@ -336,7 +355,7 @@ static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; u8 btif; int ret; @@ -358,7 +377,7 @@ static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - ret = snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif); + ret = snd_soc_component_update_bits(component, AK4641_BTIF, (0x3 << 5), btif); if (ret < 0) return ret; @@ -368,7 +387,7 @@ static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; u8 mode1 = 0; /* interface format */ @@ -383,33 +402,35 @@ static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - return snd_soc_write(codec, AK4641_MODE1, mode1); + return snd_soc_component_write(component, AK4641_MODE1, mode1); } -static int ak4641_mute(struct snd_soc_dai *dai, int mute) +static int ak4641_mute(struct snd_soc_dai *dai, int mute, int direction) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; - return snd_soc_update_bits(codec, AK4641_DAC, 0x20, mute ? 0x20 : 0); + return snd_soc_component_update_bits(component, AK4641_DAC, 0x20, mute ? 0x20 : 0); } -static int ak4641_set_bias_level(struct snd_soc_codec *codec, +static int ak4641_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - struct ak4641_platform_data *pdata = codec->dev->platform_data; + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + struct ak4641_priv *ak4641 = snd_soc_component_get_drvdata(component); + struct ak4641_platform_data *pdata = component->dev->platform_data; int ret; switch (level) { case SND_SOC_BIAS_ON: /* unmute */ - snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0); + snd_soc_component_update_bits(component, AK4641_DAC, 0x20, 0); break; case SND_SOC_BIAS_PREPARE: /* mute */ - snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); + snd_soc_component_update_bits(component, AK4641_DAC, 0x20, 0x20); break; case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) { if (pdata && gpio_is_valid(pdata->gpio_power)) gpio_set_value(pdata->gpio_power, 1); mdelay(1); @@ -417,26 +438,25 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, gpio_set_value(pdata->gpio_npdn, 1); mdelay(1); - ret = snd_soc_cache_sync(codec); + ret = regcache_sync(ak4641->regmap); if (ret) { - dev_err(codec->dev, + dev_err(component->dev, "Failed to sync cache: %d\n", ret); return ret; } } - snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0x80); - snd_soc_update_bits(codec, AK4641_PM2, 0x80, 0); + snd_soc_component_update_bits(component, AK4641_PM1, 0x80, 0x80); + snd_soc_component_update_bits(component, AK4641_PM2, 0x80, 0); break; case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0); + snd_soc_component_update_bits(component, AK4641_PM1, 0x80, 0); if (pdata && gpio_is_valid(pdata->gpio_npdn)) gpio_set_value(pdata->gpio_npdn, 0); if (pdata && gpio_is_valid(pdata->gpio_power)) gpio_set_value(pdata->gpio_power, 0); - codec->cache_sync = 1; + regcache_mark_dirty(ak4641->regmap); break; } - codec->dapm.bias_level = level; return 0; } @@ -448,15 +468,17 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec, static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = { .hw_params = ak4641_i2s_hw_params, .set_fmt = ak4641_i2s_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = { .hw_params = NULL, /* rates are controlled by BT chip */ .set_fmt = ak4641_pcm_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4641_dai[] = { @@ -478,7 +500,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = { .formats = AK4641_FORMATS, }, .ops = &ak4641_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "ak4641-voice", @@ -498,51 +520,11 @@ static struct snd_soc_dai_driver ak4641_dai[] = { .formats = AK4641_FORMATS, }, .ops = &ak4641_pcm_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; -static int ak4641_suspend(struct snd_soc_codec *codec) -{ - ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ak4641_resume(struct snd_soc_codec *codec) -{ - ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int ak4641_probe(struct snd_soc_codec *codec) -{ - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* power on device */ - ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int ak4641_remove(struct snd_soc_codec *codec) -{ - ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - - -static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { - .probe = ak4641_probe, - .remove = ak4641_remove, - .suspend = ak4641_suspend, - .resume = ak4641_resume, +static const struct snd_soc_component_driver soc_component_dev_ak4641 = { .controls = ak4641_snd_controls, .num_controls = ARRAY_SIZE(ak4641_snd_controls), .dapm_widgets = ak4641_dapm_widgets, @@ -550,15 +532,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { .dapm_routes = ak4641_audio_map, .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), .set_bias_level = ak4641_set_bias_level, - .reg_cache_size = ARRAY_SIZE(ak4641_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4641_reg, - .reg_cache_step = 1, + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; +static const struct regmap_config ak4641_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = AK4641_BTIF, + .reg_defaults = ak4641_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ak4641_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; -static int ak4641_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int ak4641_i2c_probe(struct i2c_client *i2c) { struct ak4641_platform_data *pdata = i2c->dev.platform_data; struct ak4641_priv *ak4641; @@ -569,6 +559,10 @@ static int ak4641_i2c_probe(struct i2c_client *i2c, if (!ak4641) return -ENOMEM; + ak4641->regmap = devm_regmap_init_i2c(i2c, &ak4641_regmap); + if (IS_ERR(ak4641->regmap)) + return PTR_ERR(ak4641->regmap); + if (pdata) { if (gpio_is_valid(pdata->gpio_power)) { ret = gpio_request_one(pdata->gpio_power, @@ -589,7 +583,8 @@ static int ak4641_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, ak4641); - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641, + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_ak4641, ak4641_dai, ARRAY_SIZE(ak4641_dai)); if (ret != 0) goto err_gpio2; @@ -610,12 +605,10 @@ err_out: return ret; } -static int ak4641_i2c_remove(struct i2c_client *i2c) +static void ak4641_i2c_remove(struct i2c_client *i2c) { struct ak4641_platform_data *pdata = i2c->dev.platform_data; - snd_soc_unregister_codec(&i2c->dev); - if (pdata) { if (gpio_is_valid(pdata->gpio_power)) { gpio_set_value(pdata->gpio_power, 0); @@ -624,12 +617,10 @@ static int ak4641_i2c_remove(struct i2c_client *i2c) if (gpio_is_valid(pdata->gpio_npdn)) gpio_free(pdata->gpio_npdn); } - - return 0; } static const struct i2c_device_id ak4641_i2c_id[] = { - { "ak4641", 0 }, + { "ak4641" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); @@ -637,7 +628,6 @@ MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); static struct i2c_driver ak4641_i2c_driver = { .driver = { .name = "ak4641", - .owner = THIS_MODULE, }, .probe = ak4641_i2c_probe, .remove = ak4641_i2c_remove, |
