blob: e8c5fda82e085b0a746cb57c7296a20a13cf23a2 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Daniel Macka3819342009-03-09 02:13:17 +01002/*
3 * AK4104 ALSA SoC (ASoC) driver
4 *
5 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
Daniel Macka3819342009-03-09 02:13:17 +01006 */
7
8#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09009#include <linux/slab.h>
Daniel Macka3819342009-03-09 02:13:17 +010010#include <linux/spi/spi.h>
Daniel Mack385a4c22012-11-14 18:28:39 +080011#include <linux/of_device.h>
Daniel Mackd8f2c852018-12-06 13:24:57 +010012#include <linux/gpio/consumer.h>
Daniel Mackb38d10e2014-03-27 21:42:15 +010013#include <linux/regulator/consumer.h>
Daniel Macka3819342009-03-09 02:13:17 +010014#include <sound/asoundef.h>
Daniel Mackb38d10e2014-03-27 21:42:15 +010015#include <sound/core.h>
16#include <sound/soc.h>
17#include <sound/initval.h>
Daniel Macka3819342009-03-09 02:13:17 +010018
Daniel Macka3819342009-03-09 02:13:17 +010019/* 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
Daniel Macka3819342009-03-09 02:13:17 +010045struct ak4104_private {
Mark Brown2901d6e2012-02-17 12:14:18 -080046 struct regmap *regmap;
Daniel Mackb38d10e2014-03-27 21:42:15 +010047 struct regulator *regulator;
Daniel Macka3819342009-03-09 02:13:17 +010048};
49
Mark Brown2e619262013-08-07 19:01:40 +010050static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
Mark Browna5db4d52013-08-07 19:05:47 +010051SND_SOC_DAPM_PGA("TXE", AK4104_REG_TX, AK4104_TX_TXE, 0, NULL, 0),
52
Mark Brown2e619262013-08-07 19:01:40 +010053SND_SOC_DAPM_OUTPUT("TX"),
54};
55
56static const struct snd_soc_dapm_route ak4104_dapm_routes[] = {
Mark Browna5db4d52013-08-07 19:05:47 +010057 { "TXE", NULL, "Playback" },
58 { "TX", NULL, "TXE" },
Mark Brown2e619262013-08-07 19:01:40 +010059};
60
Daniel Macka3819342009-03-09 02:13:17 +010061static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
62 unsigned int format)
63{
Kuninori Morimoto61feead2018-01-29 03:14:01 +000064 struct snd_soc_component *component = codec_dai->component;
65 struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
Daniel Macka3819342009-03-09 02:13:17 +010066 int val = 0;
Mark Brown2901d6e2012-02-17 12:14:18 -080067 int ret;
Daniel Macka3819342009-03-09 02:13:17 +010068
Daniel Macka3819342009-03-09 02:13:17 +010069 /* 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:
Kuninori Morimoto61feead2018-01-29 03:14:01 +000080 dev_err(component->dev, "invalid dai format\n");
Daniel Macka3819342009-03-09 02:13:17 +010081 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
Daniel Mackb0ec7612013-03-06 22:22:15 +010088 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
89 AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
90 val);
Mark Brownafad95f2012-02-17 12:04:41 -080091 if (ret < 0)
92 return ret;
93
94 return 0;
Daniel Macka3819342009-03-09 02:13:17 +010095}
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{
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000101 struct snd_soc_component *component = dai->component;
102 struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
Daniel Mackb692a432013-03-06 22:22:16 +0100103 int ret, val = 0;
Daniel Macka3819342009-03-09 02:13:17 +0100104
105 /* set the IEC958 bits: consumer mode, no copyright bit */
106 val |= IEC958_AES0_CON_NOT_COPYRIGHT;
Daniel Mackb0ec7612013-03-06 22:22:15 +0100107 regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val);
Daniel Macka3819342009-03-09 02:13:17 +0100108
109 val = 0;
110
111 switch (params_rate(params)) {
Daniel Mack08201de2012-10-07 17:51:23 +0200112 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;
Daniel Macka3819342009-03-09 02:13:17 +0100121 case 44100:
122 val |= IEC958_AES3_CON_FS_44100;
123 break;
124 case 48000:
125 val |= IEC958_AES3_CON_FS_48000;
126 break;
Daniel Mack08201de2012-10-07 17:51:23 +0200127 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;
Daniel Macka3819342009-03-09 02:13:17 +0100138 break;
139 default:
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000140 dev_err(component->dev, "unsupported sampling rate\n");
Daniel Macka3819342009-03-09 02:13:17 +0100141 return -EINVAL;
142 }
143
Daniel Mackb692a432013-03-06 22:22:16 +0100144 ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val);
145 if (ret < 0)
146 return ret;
147
Daniel Mackb692a432013-03-06 22:22:16 +0100148 return 0;
149}
150
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100151static const struct snd_soc_dai_ops ak4101_dai_ops = {
Mark Brown65ec1cd2009-03-11 16:51:31 +0000152 .hw_params = ak4104_hw_params,
153 .set_fmt = ak4104_set_dai_fmt,
154};
155
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000156static struct snd_soc_dai_driver ak4104_dai = {
157 .name = "ak4104-hifi",
Daniel Macka3819342009-03-09 02:13:17 +0100158 .playback = {
159 .stream_name = "Playback",
160 .channels_min = 2,
161 .channels_max = 2,
Vishal Thankic14c59f2016-09-26 15:34:19 +0200162 .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,
Daniel Macka3819342009-03-09 02:13:17 +0100166 .formats = SNDRV_PCM_FMTBIT_S16_LE |
167 SNDRV_PCM_FMTBIT_S24_3LE |
168 SNDRV_PCM_FMTBIT_S24_LE
169 },
Mark Brown65ec1cd2009-03-11 16:51:31 +0000170 .ops = &ak4101_dai_ops,
Daniel Macka3819342009-03-09 02:13:17 +0100171};
172
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000173static int ak4104_probe(struct snd_soc_component *component)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000174{
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000175 struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
Mark Brown2901d6e2012-02-17 12:14:18 -0800176 int ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000177
Daniel Mackb38d10e2014-03-27 21:42:15 +0100178 ret = regulator_enable(ak4104->regulator);
179 if (ret < 0) {
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000180 dev_err(component->dev, "Unable to enable regulator: %d\n", ret);
Daniel Mackb38d10e2014-03-27 21:42:15 +0100181 return ret;
182 }
183
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000184 /* set power-up and non-reset bits */
Daniel Mackb0ec7612013-03-06 22:22:15 +0100185 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
186 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
187 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000188 if (ret < 0)
Daniel Mackb38d10e2014-03-27 21:42:15 +0100189 goto exit_disable_regulator;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000190
191 /* enable transmitter */
Daniel Mackb0ec7612013-03-06 22:22:15 +0100192 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
193 AK4104_TX_TXE, AK4104_TX_TXE);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000194 if (ret < 0)
Daniel Mackb38d10e2014-03-27 21:42:15 +0100195 goto exit_disable_regulator;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000196
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000197 return 0;
Daniel Mackb38d10e2014-03-27 21:42:15 +0100198
199exit_disable_regulator:
200 regulator_disable(ak4104->regulator);
201 return ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000202}
203
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000204static void ak4104_remove(struct snd_soc_component *component)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000205{
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000206 struct ak4104_private *ak4104 = snd_soc_component_get_drvdata(component);
Daniel Mackb0ec7612013-03-06 22:22:15 +0100207
208 regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
209 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
Daniel Mackb38d10e2014-03-27 21:42:15 +0100210 regulator_disable(ak4104->regulator);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000211}
212
Daniel Mackb38d10e2014-03-27 21:42:15 +0100213#ifdef CONFIG_PM
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000214static int ak4104_soc_suspend(struct snd_soc_component *component)
Daniel Mackb38d10e2014-03-27 21:42:15 +0100215{
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000216 struct ak4104_private *priv = snd_soc_component_get_drvdata(component);
Daniel Mackb38d10e2014-03-27 21:42:15 +0100217
218 regulator_disable(priv->regulator);
219
220 return 0;
221}
222
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000223static int ak4104_soc_resume(struct snd_soc_component *component)
Daniel Mackb38d10e2014-03-27 21:42:15 +0100224{
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000225 struct ak4104_private *priv = snd_soc_component_get_drvdata(component);
Daniel Mackb38d10e2014-03-27 21:42:15 +0100226 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
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000239static 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,
Mark Brown2901d6e2012-02-17 12:14:18 -0800252};
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,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000263};
Daniel Macka3819342009-03-09 02:13:17 +0100264
265static int ak4104_spi_probe(struct spi_device *spi)
266{
Daniel Macka3819342009-03-09 02:13:17 +0100267 struct ak4104_private *ak4104;
Daniel Mackd8f2c852018-12-06 13:24:57 +0100268 struct gpio_desc *reset_gpiod;
Mark Brown2901d6e2012-02-17 12:14:18 -0800269 unsigned int val;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000270 int ret;
Daniel Macka3819342009-03-09 02:13:17 +0100271
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
Axel Lin3922d512011-12-20 14:37:12 +0800278 ak4104 = devm_kzalloc(&spi->dev, sizeof(struct ak4104_private),
279 GFP_KERNEL);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000280 if (ak4104 == NULL)
Daniel Macka3819342009-03-09 02:13:17 +0100281 return -ENOMEM;
Daniel Macka3819342009-03-09 02:13:17 +0100282
Daniel Mackb38d10e2014-03-27 21:42:15 +0100283 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
Tushar Beheraa273cd12012-11-22 09:38:36 +0530290 ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
Mark Brown2901d6e2012-02-17 12:14:18 -0800291 if (IS_ERR(ak4104->regmap)) {
292 ret = PTR_ERR(ak4104->regmap);
293 return ret;
294 }
295
Daniel Mackd8f2c852018-12-06 13:24:57 +0100296 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;
Daniel Mack385a4c22012-11-14 18:28:39 +0800301
Mark Brown2901d6e2012-02-17 12:14:18 -0800302 /* 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)
Tushar Beheraa273cd12012-11-22 09:38:36 +0530307 return ret;
308 if (val != AK4104_RESERVED_VAL)
309 return -ENODEV;
Mark Brown2901d6e2012-02-17 12:14:18 -0800310
Daniel Macka3819342009-03-09 02:13:17 +0100311 spi_set_drvdata(spi, ak4104);
Daniel Macka3819342009-03-09 02:13:17 +0100312
Kuninori Morimoto61feead2018-01-29 03:14:01 +0000313 ret = devm_snd_soc_register_component(&spi->dev,
314 &soc_component_device_ak4104, &ak4104_dai, 1);
Daniel Macka3819342009-03-09 02:13:17 +0100315 return ret;
316}
317
Daniel Mackac5dbea2012-10-07 17:51:24 +0200318static const struct of_device_id ak4104_of_match[] = {
319 { .compatible = "asahi-kasei,ak4104", },
320 { }
321};
322MODULE_DEVICE_TABLE(of, ak4104_of_match);
323
Daniel Mack193b2f62013-09-16 18:14:20 +0200324static const struct spi_device_id ak4104_id_table[] = {
325 { "ak4104", 0 },
326 { }
327};
328MODULE_DEVICE_TABLE(spi, ak4104_id_table);
329
Daniel Macka3819342009-03-09 02:13:17 +0100330static struct spi_driver ak4104_spi_driver = {
331 .driver = {
Daniel Mack193b2f62013-09-16 18:14:20 +0200332 .name = "ak4104",
Daniel Mackac5dbea2012-10-07 17:51:24 +0200333 .of_match_table = ak4104_of_match,
Daniel Macka3819342009-03-09 02:13:17 +0100334 },
Daniel Mack193b2f62013-09-16 18:14:20 +0200335 .id_table = ak4104_id_table,
Daniel Macka3819342009-03-09 02:13:17 +0100336 .probe = ak4104_spi_probe,
Daniel Macka3819342009-03-09 02:13:17 +0100337};
338
Mark Brown38d78ba2012-02-16 22:50:35 -0800339module_spi_driver(ak4104_spi_driver);
Daniel Macka3819342009-03-09 02:13:17 +0100340
341MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
342MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
343MODULE_LICENSE("GPL");
344