diff options
Diffstat (limited to 'sound/soc/codecs/si476x.c')
| -rw-r--r-- | sound/soc/codecs/si476x.c | 142 |
1 files changed, 57 insertions, 85 deletions
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 73e205c892a0..d87141ba8438 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips * @@ -5,22 +6,13 @@ * Copyright (C) 2013 Andrey Smirnov * * Author: Andrey Smirnov <andrew.smirnov@gmail.com> - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * */ #include <linux/module.h> #include <linux/slab.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <linux/regmap.h> #include <sound/soc.h> #include <sound/initval.h> @@ -60,55 +52,24 @@ enum si476x_pcm_format { SI476X_PCM_FORMAT_S24_LE = 6, }; -static unsigned int si476x_codec_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - int err; - unsigned int val; - struct si476x_core *core = codec->control_data; - - si476x_core_lock(core); - if (!si476x_core_is_powered_up(core)) - regcache_cache_only(core->regmap, true); - - err = regmap_read(core->regmap, reg, &val); - - if (!si476x_core_is_powered_up(core)) - regcache_cache_only(core->regmap, false); - si476x_core_unlock(core); - - if (err < 0) - return err; - - return val; -} - -static int si476x_codec_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val) -{ - int err; - struct si476x_core *core = codec->control_data; - - si476x_core_lock(core); - if (!si476x_core_is_powered_up(core)) - regcache_cache_only(core->regmap, true); - - err = regmap_write(core->regmap, reg, val); - - if (!si476x_core_is_powered_up(core)) - regcache_cache_only(core->regmap, false); - si476x_core_unlock(core); +static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = { +SND_SOC_DAPM_OUTPUT("LOUT"), +SND_SOC_DAPM_OUTPUT("ROUT"), +}; - return err; -} +static const struct snd_soc_dapm_route si476x_dapm_routes[] = { + { "Capture", NULL, "LOUT" }, + { "Capture", NULL, "ROUT" }, +}; static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { + struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev); int err; u16 format = 0; - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -168,11 +129,16 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, + si476x_core_lock(core); + + err = snd_soc_component_update_bits(codec_dai->component, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK, format); + + si476x_core_unlock(core); + if (err < 0) { - dev_err(codec_dai->codec->dev, "Failed to set output format\n"); + dev_err(codec_dai->component->dev, "Failed to set output format\n"); return err; } @@ -183,57 +149,57 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev); int rate, width, err; rate = params_rate(params); if (rate < 32000 || rate > 48000) { - dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate); + dev_err(dai->component->dev, "Rate: %d is not supported\n", rate); return -EINVAL; } - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: + switch (params_width(params)) { + case 8: width = SI476X_PCM_FORMAT_S8; break; - case SNDRV_PCM_FORMAT_S16_LE: + case 16: width = SI476X_PCM_FORMAT_S16_LE; break; - case SNDRV_PCM_FORMAT_S20_3LE: + case 20: width = SI476X_PCM_FORMAT_S20_3LE; break; - case SNDRV_PCM_FORMAT_S24_LE: + case 24: width = SI476X_PCM_FORMAT_S24_LE; break; default: return -EINVAL; } - err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE, + si476x_core_lock(core); + + err = snd_soc_component_write(dai->component, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE, rate); if (err < 0) { - dev_err(dai->codec->dev, "Failed to set sample rate\n"); - return err; + dev_err(dai->component->dev, "Failed to set sample rate\n"); + goto out; } - err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, + err = snd_soc_component_update_bits(dai->component, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); if (err < 0) { - dev_err(dai->codec->dev, "Failed to set output width\n"); - return err; + dev_err(dai->component->dev, "Failed to set output width\n"); + goto out; } - return 0; -} +out: + si476x_core_unlock(core); -static int si476x_codec_probe(struct snd_soc_codec *codec) -{ - codec->control_data = i2c_mfd_cell_to_core(codec->dev); - return 0; + return err; } -static struct snd_soc_dai_ops si476x_dai_ops = { +static const struct snd_soc_dai_ops si476x_dai_ops = { .hw_params = si476x_codec_hw_params, .set_fmt = si476x_codec_set_dai_fmt, }; @@ -256,33 +222,39 @@ static struct snd_soc_dai_driver si476x_dai = { .ops = &si476x_dai_ops, }; -static struct snd_soc_codec_driver soc_codec_dev_si476x = { - .probe = si476x_codec_probe, - .read = si476x_codec_read, - .write = si476x_codec_write, +static int si476x_probe(struct snd_soc_component *component) +{ + snd_soc_component_init_regmap(component, + dev_get_regmap(component->dev->parent, NULL)); + + return 0; +} + +static const struct snd_soc_component_driver soc_component_dev_si476x = { + .probe = si476x_probe, + .dapm_widgets = si476x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), + .dapm_routes = si476x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; static int si476x_platform_probe(struct platform_device *pdev) { - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x, + return devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_si476x, &si476x_dai, 1); } -static int si476x_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - MODULE_ALIAS("platform:si476x-codec"); static struct platform_driver si476x_platform_driver = { .driver = { .name = "si476x-codec", - .owner = THIS_MODULE, }, .probe = si476x_platform_probe, - .remove = si476x_platform_remove, }; module_platform_driver(si476x_platform_driver); |
