linux/sound/soc/codecs/ak4104.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * AK4104 ALSA SoC (ASoC) driver
   4 *
   5 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/slab.h>
  10#include <linux/spi/spi.h>
  11#include <linux/of_device.h>
  12#include <linux/gpio/consumer.h>
  13#include <linux/regulator/consumer.h>
  14#include <sound/asoundef.h>
  15#include <sound/core.h>
  16#include <sound/soc.h>
  17#include <sound/initval.h>
  18
  19/* AK4104 registers addresses */
  20#define AK4104_REG_CONTROL1             0x00
  21#define AK4104_REG_RESERVED             0x01
  22#define AK4104_REG_CONTROL2             0x02
  23#define AK4104_REG_TX                   0x03
  24#define AK4104_REG_CHN_STATUS(x)        ((x) + 0x04)
  25#define AK4104_NUM_REGS                 10
  26
  27#define AK4104_REG_MASK                 0x1f
  28#define AK4104_READ                     0xc0
  29#define AK4104_WRITE                    0xe0
  30#define AK4104_RESERVED_VAL             0x5b
  31
  32/* Bit masks for AK4104 registers */
  33#define AK4104_CONTROL1_RSTN            (1 << 0)
  34#define AK4104_CONTROL1_PW              (1 << 1)
  35#define AK4104_CONTROL1_DIF0            (1 << 2)
  36#define AK4104_CONTROL1_DIF1            (1 << 3)
  37
  38#define AK4104_CONTROL2_SEL0            (1 << 0)
  39#define AK4104_CONTROL2_SEL1            (1 << 1)
  40#define AK4104_CONTROL2_MODE            (1 << 2)
  41
  42#define AK4104_TX_TXE                   (1 << 0)
  43#define AK4104_TX_V                     (1 << 1)
  44
  45struct ak4104_private {
  46        struct regmap *regmap;
  47        struct regulator *regulator;
  48};
  49
  50static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
  51SND_SOC_DAPM_PGA("TXE", AK4104_REG_TX, AK4104_TX_TXE, 0, NULL, 0),
  52
  53SND_SOC_DAPM_OUTPUT("TX"),
  54};
  55
  56static const struct snd_soc_dapm_route ak4104_dapm_routes[] = {
  57        { "TXE", NULL, "Playback" },
  58        { "TX", NULL, "TXE" },
  59};
  60
  61static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
  62                              unsigned int format)
  63{
  64        struct snd_soc_component *component = codec_dai->component;
  65        struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
  66        int val = 0;
  67        int ret;
  68
  69        /* set DAI format */
  70        switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
  71        case SND_SOC_DAIFMT_RIGHT_J:
  72                break;
  73        case SND_SOC_DAIFMT_LEFT_J:
  74                val |= AK4104_CONTROL1_DIF0;
  75                break;
  76        case SND_SOC_DAIFMT_I2S:
  77                val |= AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1;
  78                break;
  79        default:
  80                dev_err(component->dev, "invalid dai format\n");
  81                return -EINVAL;
  82        }
  83
  84        /* This device can only be slave */
  85        if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
  86                return -EINVAL;
  87
  88        ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
  89                                 AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
  90                                 val);
  91        if (ret < 0)
  92                return ret;
  93
  94        return 0;
  95}
  96
  97static int ak4104_hw_params(struct snd_pcm_substream *substream,
  98                            struct snd_pcm_hw_params *params,
  99                            struct snd_soc_dai *dai)
 100{
 101        struct snd_soc_component *component = dai->component;
 102        struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
 103        int ret, val = 0;
 104
 105        /* set the IEC958 bits: consumer mode, no copyright bit */
 106        val |= IEC958_AES0_CON_NOT_COPYRIGHT;
 107        regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val);
 108
 109        val = 0;
 110
 111        switch (params_rate(params)) {
 112        case 22050:
 113                val |= IEC958_AES3_CON_FS_22050;
 114                break;
 115        case 24000:
 116                val |= IEC958_AES3_CON_FS_24000;
 117                break;
 118        case 32000:
 119                val |= IEC958_AES3_CON_FS_32000;
 120                break;
 121        case 44100:
 122                val |= IEC958_AES3_CON_FS_44100;
 123                break;
 124        case 48000:
 125                val |= IEC958_AES3_CON_FS_48000;
 126                break;
 127        case 88200:
 128                val |= IEC958_AES3_CON_FS_88200;
 129                break;
 130        case 96000:
 131                val |= IEC958_AES3_CON_FS_96000;
 132                break;
 133        case 176400:
 134                val |= IEC958_AES3_CON_FS_176400;
 135                break;
 136        case 192000:
 137                val |= IEC958_AES3_CON_FS_192000;
 138                break;
 139        default:
 140                dev_err(component->dev, "unsupported sampling rate\n");
 141                return -EINVAL;
 142        }
 143
 144        ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val);
 145        if (ret < 0)
 146                return ret;
 147
 148        return 0;
 149}
 150
 151static const struct snd_soc_dai_ops ak4101_dai_ops = {
 152        .hw_params = ak4104_hw_params,
 153        .set_fmt = ak4104_set_dai_fmt,
 154};
 155
 156static struct snd_soc_dai_driver ak4104_dai = {
 157        .name = "ak4104-hifi",
 158        .playback = {
 159                .stream_name = "Playback",
 160                .channels_min = 2,
 161                .channels_max = 2,
 162                .rates = SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 163                         SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 164                         SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
 165                         SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
 166                .formats = SNDRV_PCM_FMTBIT_S16_LE  |
 167                           SNDRV_PCM_FMTBIT_S24_3LE |
 168                           SNDRV_PCM_FMTBIT_S24_LE
 169        },
 170        .ops = &ak4101_dai_ops,
 171};
 172
 173static int ak4104_probe(struct snd_soc_component *component)
 174{
 175        struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
 176        int ret;
 177
 178        ret = regulator_enable(ak4104->regulator);
 179        if (ret < 0) {
 180                dev_err(component->dev, "Unable to enable regulator: %d\n", ret);
 181                return ret;
 182        }
 183
 184        /* set power-up and non-reset bits */
 185        ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
 186                                 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
 187                                 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
 188        if (ret < 0)
 189                goto exit_disable_regulator;
 190
 191        /* enable transmitter */
 192        ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
 193                                 AK4104_TX_TXE, AK4104_TX_TXE);
 194        if (ret < 0)
 195                goto exit_disable_regulator;
 196
 197        return 0;
 198
 199exit_disable_regulator:
 200        regulator_disable(ak4104->regulator);
 201        return ret;
 202}
 203
 204static void ak4104_remove(struct snd_soc_component *component)
 205{
 206        struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
 207
 208        regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
 209                           AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
 210        regulator_disable(ak4104->regulator);
 211}
 212
 213#ifdef CONFIG_PM
 214static int ak4104_soc_suspend(struct snd_soc_component *component)
 215{
 216        struct ak4104_private *priv = snd_soc_component_get_drvdata(component);
 217
 218        regulator_disable(priv->regulator);
 219
 220        return 0;
 221}
 222
 223static int ak4104_soc_resume(struct snd_soc_component *component)
 224{
 225        struct ak4104_private *priv = snd_soc_component_get_drvdata(component);
 226        int ret;
 227
 228        ret = regulator_enable(priv->regulator);
 229        if (ret < 0)
 230                return ret;
 231
 232        return 0;
 233}
 234#else
 235#define ak4104_soc_suspend      NULL
 236#define ak4104_soc_resume       NULL
 237#endif /* CONFIG_PM */
 238
 239static const struct snd_soc_component_driver soc_component_device_ak4104 = {
 240        .probe                  = ak4104_probe,
 241        .remove                 = ak4104_remove,
 242        .suspend                = ak4104_soc_suspend,
 243        .resume                 = ak4104_soc_resume,
 244        .dapm_widgets           = ak4104_dapm_widgets,
 245        .num_dapm_widgets       = ARRAY_SIZE(ak4104_dapm_widgets),
 246        .dapm_routes            = ak4104_dapm_routes,
 247        .num_dapm_routes        = ARRAY_SIZE(ak4104_dapm_routes),
 248        .idle_bias_on           = 1,
 249        .use_pmdown_time        = 1,
 250        .endianness             = 1,
 251        .non_legacy_dai_naming  = 1,
 252};
 253
 254static const struct regmap_config ak4104_regmap = {
 255        .reg_bits = 8,
 256        .val_bits = 8,
 257
 258        .max_register = AK4104_NUM_REGS - 1,
 259        .read_flag_mask = AK4104_READ,
 260        .write_flag_mask = AK4104_WRITE,
 261
 262        .cache_type = REGCACHE_RBTREE,
 263};
 264
 265static int ak4104_spi_probe(struct spi_device *spi)
 266{
 267        struct ak4104_private *ak4104;
 268        struct gpio_desc *reset_gpiod;
 269        unsigned int val;
 270        int ret;
 271
 272        spi->bits_per_word = 8;
 273        spi->mode = SPI_MODE_0;
 274        ret = spi_setup(spi);
 275        if (ret < 0)
 276                return ret;
 277
 278        ak4104 = devm_kzalloc(&spi->dev, sizeof(struct ak4104_private),
 279                              GFP_KERNEL);
 280        if (ak4104 == NULL)
 281                return -ENOMEM;
 282
 283        ak4104->regulator = devm_regulator_get(&spi->dev, "vdd");
 284        if (IS_ERR(ak4104->regulator)) {
 285                ret = PTR_ERR(ak4104->regulator);
 286                dev_err(&spi->dev, "Unable to get Vdd regulator: %d\n", ret);
 287                return ret;
 288        }
 289
 290        ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
 291        if (IS_ERR(ak4104->regmap)) {
 292                ret = PTR_ERR(ak4104->regmap);
 293                return ret;
 294        }
 295
 296        reset_gpiod = devm_gpiod_get_optional(&spi->dev, "reset",
 297                                              GPIOD_OUT_HIGH);
 298        if (IS_ERR(reset_gpiod) &&
 299            PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
 300                return -EPROBE_DEFER;
 301
 302        /* read the 'reserved' register - according to the datasheet, it
 303         * should contain 0x5b. Not a good way to verify the presence of
 304         * the device, but there is no hardware ID register. */
 305        ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
 306        if (ret != 0)
 307                return ret;
 308        if (val != AK4104_RESERVED_VAL)
 309                return -ENODEV;
 310
 311        spi_set_drvdata(spi, ak4104);
 312
 313        ret = devm_snd_soc_register_component(&spi->dev,
 314                        &soc_component_device_ak4104, &ak4104_dai, 1);
 315        return ret;
 316}
 317
 318static const struct of_device_id ak4104_of_match[] = {
 319        { .compatible = "asahi-kasei,ak4104", },
 320        { }
 321};
 322MODULE_DEVICE_TABLE(of, ak4104_of_match);
 323
 324static const struct spi_device_id ak4104_id_table[] = {
 325        { "ak4104", 0 },
 326        { }
 327};
 328MODULE_DEVICE_TABLE(spi, ak4104_id_table);
 329
 330static struct spi_driver ak4104_spi_driver = {
 331        .driver  = {
 332                .name   = "ak4104",
 333                .of_match_table = ak4104_of_match,
 334        },
 335        .id_table = ak4104_id_table,
 336        .probe  = ak4104_spi_probe,
 337};
 338
 339module_spi_driver(ak4104_spi_driver);
 340
 341MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 342MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
 343MODULE_LICENSE("GPL");
 344
 345