b07f7c9f2d63bc4bd13253e6ba87340b4cdd8377
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.10 / 950-0390-Allo-boss2-driver.patch
1 From 5eba3bb8b48060a5ddf143c1aa69840a90dd9162 Mon Sep 17 00:00:00 2001
2 From: Sudeep <sudeepkumar@cem-solutions.net>
3 Date: Fri, 23 Oct 2020 15:47:17 +0530
4 Subject: [PATCH] Allo boss2 driver
5
6 Signed-off-by: Sudeep <sudeepkumar@cem-solutions.net>
7 ---
8 sound/soc/bcm/Kconfig | 9 +
9 sound/soc/bcm/Makefile | 2 +
10 sound/soc/bcm/allo-boss2-dac.c | 1133 ++++++++++++++++++++++++++++++++
11 3 files changed, 1144 insertions(+)
12 create mode 100644 sound/soc/bcm/allo-boss2-dac.c
13
14 --- a/sound/soc/bcm/Kconfig
15 +++ b/sound/soc/bcm/Kconfig
16 @@ -267,6 +267,15 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC
17 help
18 Say Y or M if you want to add support for Allo Boss DAC.
19
20 +config SND_BCM2708_SOC_ALLO_BOSS2_DAC
21 + tristate "Support for Allo Boss2 DAC"
22 + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
23 + depends on I2C
24 + select REGMAP_I2C
25 + select SND_AUDIO_GRAPH_CARD
26 + help
27 + Say Y or M if you want to add support for Allo Boss2 DAC.
28 +
29 config SND_BCM2708_SOC_ALLO_DIGIONE
30 tristate "Support for Allo DigiOne"
31 depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
32 --- a/sound/soc/bcm/Makefile
33 +++ b/sound/soc/bcm/Makefile
34 @@ -38,6 +38,7 @@ snd-soc-digidac1-soundcard-objs := digid
35 snd-soc-dionaudio-loco-objs := dionaudio_loco.o
36 snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
37 snd-soc-allo-boss-dac-objs := allo-boss-dac.o
38 +snd-soc-allo-boss2-dac-objs := allo-boss2-dac.o
39 snd-soc-allo-piano-dac-objs := allo-piano-dac.o
40 snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o
41 snd-soc-allo-katana-codec-objs := allo-katana-codec.o
42 @@ -68,6 +69,7 @@ obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) +=
43 obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o
44 obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o
45 obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += snd-soc-allo-boss-dac.o
46 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS2_DAC) += snd-soc-allo-boss2-dac.o
47 obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
48 obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o
49 obj-$(CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC) += snd-soc-allo-katana-codec.o
50 --- /dev/null
51 +++ b/sound/soc/bcm/allo-boss2-dac.c
52 @@ -0,0 +1,1133 @@
53 +/*
54 + * Driver for the ALLO KATANA CODEC
55 + *
56 + * Author: Jaikumar <sudeepkumar@cem-solutions.net>
57 + * Copyright 2018
58 + *
59 + * This program is free software; you can redistribute it and/or
60 + * modify it under the terms of the GNU General Public License
61 + * version 2 as published by the Free Software Foundation.
62 + *
63 + * This program is distributed in the hope that it will be useful, but
64 + * WITHOUT ANY WARRANTY; without even the implied warranty of
65 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
66 + * General Public License for more details.
67 + */
68 +
69 +#include <linux/module.h>
70 +#include <linux/moduleparam.h>
71 +#include <linux/kernel.h>
72 +#include <linux/init.h>
73 +#include <linux/delay.h>
74 +#include <linux/gpio.h>
75 +#include <linux/gpio/consumer.h>
76 +#include <linux/platform_device.h>
77 +#include <linux/pm.h>
78 +#include <linux/i2c.h>
79 +#include <linux/of_device.h>
80 +#include <linux/regmap.h>
81 +#include <linux/slab.h>
82 +#include <sound/core.h>
83 +#include <sound/pcm.h>
84 +#include <sound/pcm_params.h>
85 +#include <sound/soc.h>
86 +#include <sound/soc-dapm.h>
87 +#include <sound/initval.h>
88 +#include <sound/tlv.h>
89 +#include <linux/of_gpio.h>
90 +#include <linux/regulator/consumer.h>
91 +#include <linux/pm_runtime.h>
92 +#include <linux/of_irq.h>
93 +#include <linux/completion.h>
94 +#include <linux/mutex.h>
95 +#include <linux/workqueue.h>
96 +#include <sound/jack.h>
97 +
98 +#include "../codecs/cs43130.h"
99 +
100 +#include <linux/clk.h>
101 +#include <linux/gcd.h>
102 +#define DEBUG
103 +
104 +#define CS43130_DSD_EN_MASK 0x10
105 +#define CS43130_PDN_DONE_INT_MASK 0x00
106 +
107 +static struct gpio_desc *snd_allo_clk44gpio;
108 +static struct gpio_desc *snd_allo_clk48gpio;
109 +
110 +struct cs43130_priv {
111 + struct snd_soc_component *component;
112 + struct regmap *regmap;
113 + struct regulator_bulk_data supplies[CS43130_NUM_SUPPLIES];
114 + struct gpio_desc *reset_gpio;
115 + unsigned int dev_id; /* codec device ID */
116 + int xtal_ibias;
117 + /* shared by both DAIs */
118 + struct mutex clk_mutex;
119 + int clk_req;
120 + bool pll_bypass;
121 + struct completion xtal_rdy;
122 + struct completion pll_rdy;
123 + unsigned int mclk;
124 + unsigned int mclk_int;
125 + int mclk_int_src;
126 +
127 + /* DAI specific */
128 + struct cs43130_dai dais[CS43130_DAI_ID_MAX];
129 +
130 + /* HP load specific */
131 + bool dc_meas;
132 + bool ac_meas;
133 + bool hpload_done;
134 + struct completion hpload_evt;
135 + unsigned int hpload_stat;
136 + u16 hpload_dc[2];
137 + u16 dc_threshold[CS43130_DC_THRESHOLD];
138 + u16 ac_freq[CS43130_AC_FREQ];
139 + u16 hpload_ac[CS43130_AC_FREQ][2];
140 + struct workqueue_struct *wq;
141 + struct work_struct work;
142 + struct snd_soc_jack jack;
143 +};
144 +
145 +static const struct reg_default cs43130_reg_defaults[] = {
146 + {CS43130_SYS_CLK_CTL_1, 0x06},
147 + {CS43130_SP_SRATE, 0x01},
148 + {CS43130_SP_BITSIZE, 0x05},
149 + {CS43130_PAD_INT_CFG, 0x03},
150 + {CS43130_PWDN_CTL, 0xFE},
151 + {CS43130_CRYSTAL_SET, 0x04},
152 + {CS43130_PLL_SET_1, 0x00},
153 + {CS43130_PLL_SET_2, 0x00},
154 + {CS43130_PLL_SET_3, 0x00},
155 + {CS43130_PLL_SET_4, 0x00},
156 + {CS43130_PLL_SET_5, 0x40},
157 + {CS43130_PLL_SET_6, 0x10},
158 + {CS43130_PLL_SET_7, 0x80},
159 + {CS43130_PLL_SET_8, 0x03},
160 + {CS43130_PLL_SET_9, 0x02},
161 + {CS43130_PLL_SET_10, 0x02},
162 + {CS43130_CLKOUT_CTL, 0x00},
163 + {CS43130_ASP_NUM_1, 0x01},
164 + {CS43130_ASP_NUM_2, 0x00},
165 + {CS43130_ASP_DEN_1, 0x08},
166 + {CS43130_ASP_DEN_2, 0x00},
167 + {CS43130_ASP_LRCK_HI_TIME_1, 0x1F},
168 + {CS43130_ASP_LRCK_HI_TIME_2, 0x00},
169 + {CS43130_ASP_LRCK_PERIOD_1, 0x3F},
170 + {CS43130_ASP_LRCK_PERIOD_2, 0x00},
171 + {CS43130_ASP_CLOCK_CONF, 0x0C},
172 + {CS43130_ASP_FRAME_CONF, 0x0A},
173 + {CS43130_XSP_NUM_1, 0x01},
174 + {CS43130_XSP_NUM_2, 0x00},
175 + {CS43130_XSP_DEN_1, 0x02},
176 + {CS43130_XSP_DEN_2, 0x00},
177 + {CS43130_XSP_LRCK_HI_TIME_1, 0x1F},
178 + {CS43130_XSP_LRCK_HI_TIME_2, 0x00},
179 + {CS43130_XSP_LRCK_PERIOD_1, 0x3F},
180 + {CS43130_XSP_LRCK_PERIOD_2, 0x00},
181 + {CS43130_XSP_CLOCK_CONF, 0x0C},
182 + {CS43130_XSP_FRAME_CONF, 0x0A},
183 + {CS43130_ASP_CH_1_LOC, 0x00},
184 + {CS43130_ASP_CH_2_LOC, 0x00},
185 + {CS43130_ASP_CH_1_SZ_EN, 0x06},
186 + {CS43130_ASP_CH_2_SZ_EN, 0x0E},
187 + {CS43130_XSP_CH_1_LOC, 0x00},
188 + {CS43130_XSP_CH_2_LOC, 0x00},
189 + {CS43130_XSP_CH_1_SZ_EN, 0x06},
190 + {CS43130_XSP_CH_2_SZ_EN, 0x0E},
191 + {CS43130_DSD_VOL_B, 0x78},
192 + {CS43130_DSD_VOL_A, 0x78},
193 + {CS43130_DSD_PATH_CTL_1, 0xA8},
194 + {CS43130_DSD_INT_CFG, 0x00},
195 + {CS43130_DSD_PATH_CTL_2, 0x02},
196 + {CS43130_DSD_PCM_MIX_CTL, 0x00},
197 + {CS43130_DSD_PATH_CTL_3, 0x40},
198 + {CS43130_HP_OUT_CTL_1, 0x30},
199 + {CS43130_PCM_FILT_OPT, 0x02},
200 + {CS43130_PCM_VOL_B, 0x78},
201 + {CS43130_PCM_VOL_A, 0x78},
202 + {CS43130_PCM_PATH_CTL_1, 0xA8},
203 + {CS43130_PCM_PATH_CTL_2, 0x00},
204 + {CS43130_CLASS_H_CTL, 0x1E},
205 + {CS43130_HP_DETECT, 0x04},
206 + {CS43130_HP_LOAD_1, 0x00},
207 + {CS43130_HP_MEAS_LOAD_1, 0x00},
208 + {CS43130_HP_MEAS_LOAD_2, 0x00},
209 + {CS43130_INT_MASK_1, 0xFF},
210 + {CS43130_INT_MASK_2, 0xFF},
211 + {CS43130_INT_MASK_3, 0xFF},
212 + {CS43130_INT_MASK_4, 0xFF},
213 + {CS43130_INT_MASK_5, 0xFF},
214 +};
215 +static bool cs43130_volatile_register(struct device *dev, unsigned int reg)
216 +{
217 + switch (reg) {
218 + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
219 + case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2:
220 + case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2:
221 + return true;
222 + default:
223 + return false;
224 + }
225 +}
226 +
227 +static const char * const pcm_spd_texts[] = {
228 + "Fast",
229 + "Slow",
230 +};
231 +
232 +static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7,
233 + pcm_spd_texts);
234 +
235 +static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
236 +
237 +static const struct snd_kcontrol_new cs43130_controls[] = {
238 + SOC_DOUBLE_R_TLV("Master Playback Volume", CS43130_PCM_VOL_B,
239 + CS43130_PCM_VOL_A, 0, 255, 1, master_tlv),
240 + SOC_DOUBLE("Master Playback Switch", CS43130_PCM_PATH_CTL_1,
241 + 0, 1, 1, 1),
242 + SOC_DOUBLE_R_TLV("Digital Playback Volume", CS43130_DSD_VOL_B,
243 + CS43130_DSD_VOL_A, 0, 255, 1, master_tlv),
244 + SOC_DOUBLE("Digital Playback Switch", CS43130_DSD_PATH_CTL_1,
245 + 0, 1, 1, 1),
246 + SOC_SINGLE("HV_Enable", CS43130_HP_OUT_CTL_1, 0, 1, 0),
247 + SOC_ENUM("PCM Filter Speed", pcm_spd_enum),
248 + SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0),
249 + SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0),
250 + SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0),
251 + SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0),
252 +};
253 +
254 +static bool cs43130_readable_register(struct device *dev, unsigned int reg)
255 +{
256 + switch (reg) {
257 + case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1:
258 + case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG:
259 + case CS43130_PWDN_CTL:
260 + case CS43130_CRYSTAL_SET:
261 + case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5:
262 + case CS43130_PLL_SET_6:
263 + case CS43130_PLL_SET_7:
264 + case CS43130_PLL_SET_8:
265 + case CS43130_PLL_SET_9:
266 + case CS43130_PLL_SET_10:
267 + case CS43130_CLKOUT_CTL:
268 + case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF:
269 + case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF:
270 + case CS43130_ASP_CH_1_LOC:
271 + case CS43130_ASP_CH_2_LOC:
272 + case CS43130_ASP_CH_1_SZ_EN:
273 + case CS43130_ASP_CH_2_SZ_EN:
274 + case CS43130_XSP_CH_1_LOC:
275 + case CS43130_XSP_CH_2_LOC:
276 + case CS43130_XSP_CH_1_SZ_EN:
277 + case CS43130_XSP_CH_2_SZ_EN:
278 + case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3:
279 + case CS43130_HP_OUT_CTL_1:
280 + case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2:
281 + case CS43130_CLASS_H_CTL:
282 + case CS43130_HP_DETECT:
283 + case CS43130_HP_STATUS:
284 + case CS43130_HP_LOAD_1:
285 + case CS43130_HP_MEAS_LOAD_1:
286 + case CS43130_HP_MEAS_LOAD_2:
287 + case CS43130_HP_DC_STAT_1:
288 + case CS43130_HP_DC_STAT_2:
289 + case CS43130_HP_AC_STAT_1:
290 + case CS43130_HP_AC_STAT_2:
291 + case CS43130_HP_LOAD_STAT:
292 + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
293 + case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5:
294 + return true;
295 + default:
296 + return false;
297 + }
298 +}
299 +static bool cs43130_precious_register(struct device *dev, unsigned int reg)
300 +{
301 + switch (reg) {
302 + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
303 + return true;
304 + default:
305 + return false;
306 + }
307 +}
308 +static int cs43130_pcm_pdn(struct snd_soc_component *component)
309 +{
310 + struct cs43130_priv *cs43130 =
311 + snd_soc_component_get_drvdata(component);
312 + int ret;
313 + unsigned int reg, pdn_int;
314 +
315 + regmap_write(cs43130->regmap, CS43130_DSD_PATH_CTL_2, 0x02);
316 + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
317 + CS43130_PDN_DONE_INT_MASK, 0);
318 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
319 + CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
320 + usleep_range(10, 50);
321 + ret = regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, &reg);
322 + pdn_int = reg & 0xFE;
323 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
324 + CS43130_PDN_ASP_MASK, 1 << CS43130_PDN_ASP_SHIFT);
325 + return 0;
326 +
327 +}
328 +static int cs43130_pwr_up_asp_dac(struct snd_soc_component *component)
329 +{
330 + struct cs43130_priv *cs43130 =
331 + snd_soc_component_get_drvdata(component);
332 +
333 + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
334 + CS43130_ASP_3ST_MASK, 0);
335 + regmap_write(cs43130->regmap, CS43130_DXD1, 0x99);
336 + regmap_write(cs43130->regmap, CS43130_DXD13, 0x20);
337 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
338 + CS43130_PDN_ASP_MASK, 0);
339 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
340 + CS43130_PDN_HP_MASK, 0);
341 + usleep_range(10000, 12000);
342 + regmap_write(cs43130->regmap, CS43130_DXD1, 0x00);
343 + regmap_write(cs43130->regmap, CS43130_DXD13, 0x00);
344 + return 0;
345 +}
346 +static int cs43130_change_clksrc(struct snd_soc_component *component,
347 + enum cs43130_mclk_src_sel src)
348 +{
349 + int ret;
350 + struct cs43130_priv *cs43130 =
351 + snd_soc_component_get_drvdata(component);
352 + int mclk_int_decoded;
353 +
354 + if (src == cs43130->mclk_int_src) {
355 + /* clk source has not changed */
356 + return 0;
357 + }
358 + switch (cs43130->mclk_int) {
359 + case CS43130_MCLK_22M:
360 + mclk_int_decoded = CS43130_MCLK_22P5;
361 + break;
362 + case CS43130_MCLK_24M:
363 + mclk_int_decoded = CS43130_MCLK_24P5;
364 + break;
365 + default:
366 + dev_err(component->dev, "Invalid MCLK INT freq: %u\n",
367 + cs43130->mclk_int);
368 + return -EINVAL;
369 + }
370 +
371 + switch (src) {
372 + case CS43130_MCLK_SRC_EXT:
373 + cs43130->pll_bypass = true;
374 + cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT;
375 + if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {
376 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
377 + CS43130_PDN_XTAL_MASK,
378 + 1 << CS43130_PDN_XTAL_SHIFT);
379 + } else {
380 + reinit_completion(&cs43130->xtal_rdy);
381 + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
382 + CS43130_XTAL_RDY_INT_MASK, 0);
383 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
384 + CS43130_PDN_XTAL_MASK, 0);
385 + ret = wait_for_completion_timeout(&cs43130->xtal_rdy,
386 + msecs_to_jiffies(100));
387 + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
388 + CS43130_XTAL_RDY_INT_MASK,
389 + 1 << CS43130_XTAL_RDY_INT_SHIFT);
390 + if (ret == 0) {
391 + dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n");
392 + return -ETIMEDOUT;
393 + }
394 + }
395 + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
396 + CS43130_MCLK_SRC_SEL_MASK,
397 + src << CS43130_MCLK_SRC_SEL_SHIFT);
398 + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
399 + CS43130_MCLK_INT_MASK,
400 + mclk_int_decoded << CS43130_MCLK_INT_SHIFT);
401 + usleep_range(150, 200);
402 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
403 + CS43130_PDN_PLL_MASK,
404 + 1 << CS43130_PDN_PLL_SHIFT);
405 + break;
406 + case CS43130_MCLK_SRC_RCO:
407 + cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
408 +
409 + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
410 + CS43130_MCLK_SRC_SEL_MASK,
411 + src << CS43130_MCLK_SRC_SEL_SHIFT);
412 + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
413 + CS43130_MCLK_INT_MASK,
414 + CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT);
415 + usleep_range(150, 200);
416 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
417 + CS43130_PDN_XTAL_MASK,
418 + 1 << CS43130_PDN_XTAL_SHIFT);
419 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
420 + CS43130_PDN_PLL_MASK,
421 + 1 << CS43130_PDN_PLL_SHIFT);
422 + break;
423 + default:
424 + dev_err(component->dev, "Invalid MCLK source value\n");
425 + return -EINVAL;
426 + }
427 +
428 + return 0;
429 +}
430 +static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = {
431 + {8, CS43130_SP_BIT_SIZE_8, CS43130_CH_BIT_SIZE_8},
432 + {16, CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16},
433 + {24, CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24},
434 + {32, CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32},
435 +};
436 +
437 +static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table(
438 + unsigned int bitwidth)
439 +{
440 + int i;
441 +
442 + for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) {
443 + if (cs43130_bitwidth_table[i].bitwidth == bitwidth)
444 + return &cs43130_bitwidth_table[i];
445 + }
446 +
447 + return NULL;
448 +}
449 +static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai,
450 + struct regmap *regmap)
451 +{
452 + const struct cs43130_bitwidth_map *bw_map;
453 +
454 + bw_map = cs43130_get_bitwidth_table(bitwidth_dai);
455 + if (!bw_map)
456 + return -EINVAL;
457 +
458 + switch (dai_id) {
459 + case CS43130_ASP_PCM_DAI:
460 + case CS43130_ASP_DOP_DAI:
461 + regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN,
462 + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
463 + regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN,
464 + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
465 + regmap_update_bits(regmap, CS43130_SP_BITSIZE,
466 + CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit);
467 + break;
468 + case CS43130_XSP_DOP_DAI:
469 + regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN,
470 + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
471 + regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN,
472 + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
473 + regmap_update_bits(regmap, CS43130_SP_BITSIZE,
474 + CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit <<
475 + CS43130_XSP_BITSIZE_SHIFT);
476 + break;
477 + default:
478 + return -EINVAL;
479 + }
480 +
481 + return 0;
482 +}
483 +static const struct cs43130_rate_map cs43130_rate_table[] = {
484 + {32000, CS43130_ASP_SPRATE_32K},
485 + {44100, CS43130_ASP_SPRATE_44_1K},
486 + {48000, CS43130_ASP_SPRATE_48K},
487 + {88200, CS43130_ASP_SPRATE_88_2K},
488 + {96000, CS43130_ASP_SPRATE_96K},
489 + {176400, CS43130_ASP_SPRATE_176_4K},
490 + {192000, CS43130_ASP_SPRATE_192K},
491 + {352800, CS43130_ASP_SPRATE_352_8K},
492 + {384000, CS43130_ASP_SPRATE_384K},
493 +};
494 +
495 +static const struct cs43130_rate_map *cs43130_get_rate_table(int fs)
496 +{
497 + int i;
498 +
499 + for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) {
500 + if (cs43130_rate_table[i].fs == fs)
501 + return &cs43130_rate_table[i];
502 + }
503 +
504 + return NULL;
505 +}
506 +
507 +static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs,
508 + const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table)
509 +{
510 + int i;
511 +
512 + for (i = 0; i < len_clk_gen_table; i++) {
513 + if (clk_gen_table[i].mclk_int == mclk_int &&
514 + clk_gen_table[i].fs == fs)
515 + return &clk_gen_table[i];
516 + }
517 + return NULL;
518 +}
519 +
520 +static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
521 + struct snd_pcm_hw_params *params,
522 + struct cs43130_priv *cs43130)
523 +{
524 + u16 frm_size;
525 + u16 hi_size;
526 + u8 frm_delay;
527 + u8 frm_phase;
528 + u8 frm_data;
529 + u8 sclk_edge;
530 + u8 lrck_edge;
531 + u8 clk_data;
532 + u8 loc_ch1;
533 + u8 loc_ch2;
534 + u8 dai_mode_val;
535 + const struct cs43130_clk_gen *clk_gen;
536 +
537 + switch (cs43130->dais[dai_id].dai_format) {
538 + case SND_SOC_DAIFMT_I2S:
539 + hi_size = bitwidth_sclk;
540 + frm_delay = 2;
541 + frm_phase = 0;
542 + break;
543 + case SND_SOC_DAIFMT_LEFT_J:
544 + hi_size = bitwidth_sclk;
545 + frm_delay = 2;
546 + frm_phase = 1;
547 + break;
548 + case SND_SOC_DAIFMT_DSP_A:
549 + hi_size = 1;
550 + frm_delay = 2;
551 + frm_phase = 1;
552 + break;
553 + case SND_SOC_DAIFMT_DSP_B:
554 + hi_size = 1;
555 + frm_delay = 0;
556 + frm_phase = 1;
557 + break;
558 + default:
559 + return -EINVAL;
560 + }
561 + switch (cs43130->dais[dai_id].dai_mode) {
562 + case SND_SOC_DAIFMT_CBS_CFS:
563 + dai_mode_val = 0;
564 + break;
565 + case SND_SOC_DAIFMT_CBM_CFM:
566 + dai_mode_val = 1;
567 + break;
568 + default:
569 + return -EINVAL;
570 + }
571 +
572 + frm_size = bitwidth_sclk * params_channels(params);
573 + sclk_edge = 1;
574 + lrck_edge = 0;
575 + loc_ch1 = 0;
576 + loc_ch2 = bitwidth_sclk * (params_channels(params) - 1);
577 +
578 + frm_data = frm_delay & CS43130_SP_FSD_MASK;
579 + frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK;
580 +
581 + clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK;
582 + clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) &
583 + CS43130_SP_LCPOL_OUT_MASK;
584 + clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) &
585 + CS43130_SP_SCPOL_IN_MASK;
586 + clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) &
587 + CS43130_SP_SCPOL_OUT_MASK;
588 + clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) &
589 + CS43130_SP_MODE_MASK;
590 + switch (dai_id) {
591 + case CS43130_ASP_PCM_DAI:
592 + case CS43130_ASP_DOP_DAI:
593 + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1,
594 + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
595 + CS43130_SP_LCPR_LSB_DATA_SHIFT);
596 + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2,
597 + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
598 + CS43130_SP_LCPR_MSB_DATA_SHIFT);
599 + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1,
600 + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
601 + CS43130_SP_LCHI_LSB_DATA_SHIFT);
602 + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2,
603 + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
604 + CS43130_SP_LCHI_MSB_DATA_SHIFT);
605 + regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data);
606 + regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1);
607 + regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2);
608 + regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN,
609 + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
610 + regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN,
611 + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
612 + regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data);
613 + break;
614 + case CS43130_XSP_DOP_DAI:
615 + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1,
616 + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
617 + CS43130_SP_LCPR_LSB_DATA_SHIFT);
618 + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2,
619 + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
620 + CS43130_SP_LCPR_MSB_DATA_SHIFT);
621 + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1,
622 + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
623 + CS43130_SP_LCHI_LSB_DATA_SHIFT);
624 + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2,
625 + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
626 + CS43130_SP_LCHI_MSB_DATA_SHIFT);
627 + regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data);
628 + regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1);
629 + regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2);
630 + regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN,
631 + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
632 + regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN,
633 + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
634 + regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data);
635 + break;
636 + default:
637 + return -EINVAL;
638 + }
639 + switch (frm_size) {
640 + case 16:
641 + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
642 + params_rate(params),
643 + cs43130_16_clk_gen,
644 + ARRAY_SIZE(cs43130_16_clk_gen));
645 + break;
646 + case 32:
647 + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
648 + params_rate(params),
649 + cs43130_32_clk_gen,
650 + ARRAY_SIZE(cs43130_32_clk_gen));
651 + break;
652 + case 48:
653 + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
654 + params_rate(params),
655 + cs43130_48_clk_gen,
656 + ARRAY_SIZE(cs43130_48_clk_gen));
657 + break;
658 + case 64:
659 + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
660 + params_rate(params),
661 + cs43130_64_clk_gen,
662 + ARRAY_SIZE(cs43130_64_clk_gen));
663 + break;
664 + default:
665 + return -EINVAL;
666 + }
667 + if (!clk_gen)
668 + return -EINVAL;
669 + switch (dai_id) {
670 + case CS43130_ASP_PCM_DAI:
671 + case CS43130_ASP_DOP_DAI:
672 + regmap_write(cs43130->regmap, CS43130_ASP_DEN_1,
673 + (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >>
674 + CS43130_SP_M_LSB_DATA_SHIFT);
675 + regmap_write(cs43130->regmap, CS43130_ASP_DEN_2,
676 + (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >>
677 + CS43130_SP_M_MSB_DATA_SHIFT);
678 + regmap_write(cs43130->regmap, CS43130_ASP_NUM_1,
679 + (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >>
680 + CS43130_SP_N_LSB_DATA_SHIFT);
681 + regmap_write(cs43130->regmap, CS43130_ASP_NUM_2,
682 + (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >>
683 + CS43130_SP_N_MSB_DATA_SHIFT);
684 + break;
685 + case CS43130_XSP_DOP_DAI:
686 + regmap_write(cs43130->regmap, CS43130_XSP_DEN_1,
687 + (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >>
688 + CS43130_SP_M_LSB_DATA_SHIFT);
689 + regmap_write(cs43130->regmap, CS43130_XSP_DEN_2,
690 + (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >>
691 + CS43130_SP_M_MSB_DATA_SHIFT);
692 + regmap_write(cs43130->regmap, CS43130_XSP_NUM_1,
693 + (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >>
694 + CS43130_SP_N_LSB_DATA_SHIFT);
695 + regmap_write(cs43130->regmap, CS43130_XSP_NUM_2,
696 + (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >>
697 + CS43130_SP_N_MSB_DATA_SHIFT);
698 + break;
699 + default:
700 + return -EINVAL;
701 + }
702 + return 0;
703 +}
704 +
705 +static int cs43130_hw_params(struct snd_pcm_substream *substream,
706 + struct snd_pcm_hw_params *params,
707 + struct snd_soc_dai *dai)
708 +{
709 + struct snd_soc_component *component = dai->component;
710 + struct cs43130_priv *cs43130 =
711 + snd_soc_component_get_drvdata(component);
712 + const struct cs43130_rate_map *rate_map;
713 + unsigned int sclk = cs43130->dais[dai->id].sclk;
714 + unsigned int bitwidth_sclk;
715 + unsigned int bitwidth_dai = (unsigned int)(params_width(params));
716 + unsigned int dop_rate = (unsigned int)(params_rate(params));
717 + unsigned int required_clk, ret;
718 + u8 dsd_speed;
719 +
720 + cs43130->pll_bypass = true;
721 + cs43130_pcm_pdn(component);
722 + mutex_lock(&cs43130->clk_mutex);
723 + if (!cs43130->clk_req) {
724 + /* no DAI is currently using clk */
725 + if (!(CS43130_MCLK_22M % params_rate(params))) {
726 + required_clk = CS43130_MCLK_22M;
727 + cs43130->mclk_int = CS43130_MCLK_22M;
728 + gpiod_set_value_cansleep(snd_allo_clk44gpio, 1);
729 + gpiod_set_value_cansleep(snd_allo_clk48gpio, 0);
730 + usleep_range(13500, 14000);
731 + } else {
732 + required_clk = CS43130_MCLK_24M;
733 + cs43130->mclk_int = CS43130_MCLK_24M;
734 + gpiod_set_value_cansleep(snd_allo_clk48gpio, 1);
735 + gpiod_set_value_cansleep(snd_allo_clk44gpio, 0);
736 + usleep_range(13500, 14000);
737 + }
738 + if (cs43130->pll_bypass)
739 + cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
740 + else
741 + cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
742 + }
743 +
744 + cs43130->clk_req++;
745 + mutex_unlock(&cs43130->clk_mutex);
746 +
747 + switch (dai->id) {
748 + case CS43130_ASP_DOP_DAI:
749 + case CS43130_XSP_DOP_DAI:
750 + /* DoP bitwidth is always 24-bit */
751 + bitwidth_dai = 24;
752 + sclk = params_rate(params) * bitwidth_dai *
753 + params_channels(params);
754 +
755 + switch (params_rate(params)) {
756 + case 176400:
757 + dsd_speed = 0;
758 + break;
759 + case 352800:
760 + dsd_speed = 1;
761 + break;
762 + default:
763 + dev_err(component->dev, "Rate(%u) not supported\n",
764 + params_rate(params));
765 + return -EINVAL;
766 + }
767 +
768 + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
769 + CS43130_DSD_SPEED_MASK,
770 + dsd_speed << CS43130_DSD_SPEED_SHIFT);
771 + break;
772 + case CS43130_ASP_PCM_DAI:
773 + rate_map = cs43130_get_rate_table(params_rate(params));
774 + if (!rate_map)
775 + return -EINVAL;
776 +
777 + regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val);
778 + if ((dop_rate == 176400) && (bitwidth_dai == 24)) {
779 + dsd_speed = 0;
780 + regmap_update_bits(cs43130->regmap,
781 + CS43130_DSD_PATH_CTL_2,
782 + CS43130_DSD_SPEED_MASK,
783 + dsd_speed << CS43130_DSD_SPEED_SHIFT);
784 + regmap_update_bits(cs43130->regmap,
785 + CS43130_DSD_PATH_CTL_2,
786 + CS43130_DSD_SRC_MASK,
787 + CS43130_DSD_SRC_ASP <<
788 + CS43130_DSD_SRC_SHIFT);
789 + regmap_update_bits(cs43130->regmap,
790 + CS43130_DSD_PATH_CTL_2,
791 + CS43130_DSD_EN_MASK, 0x01 <<
792 + CS43130_DSD_EN_SHIFT);
793 + }
794 + break;
795 + default:
796 + dev_err(component->dev, "Invalid DAI (%d)\n", dai->id);
797 + return -EINVAL;
798 + }
799 +
800 + switch (dai->id) {
801 + case CS43130_ASP_DOP_DAI:
802 + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
803 + CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP <<
804 + CS43130_DSD_SRC_SHIFT);
805 + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
806 + CS43130_DSD_EN_MASK, 0x01 <<
807 + CS43130_DSD_EN_SHIFT);
808 + break;
809 + case CS43130_XSP_DOP_DAI:
810 + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
811 + CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP <<
812 + CS43130_DSD_SRC_SHIFT);
813 + break;
814 + }
815 + if (!sclk && cs43130->dais[dai->id].dai_mode ==
816 + SND_SOC_DAIFMT_CBM_CFM) {
817 + /* Calculate SCLK in master mode if unassigned */
818 + sclk = params_rate(params) * bitwidth_dai *
819 + params_channels(params);
820 + }
821 + if (!sclk) {
822 + /* at this point, SCLK must be set */
823 + dev_err(component->dev, "SCLK freq is not set\n");
824 + return -EINVAL;
825 + }
826 +
827 + bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);
828 + if (bitwidth_sclk < bitwidth_dai) {
829 + dev_err(component->dev, "Format not supported: SCLK freq is too low\n");
830 + return -EINVAL;
831 + }
832 +
833 + dev_dbg(component->dev,
834 + "sclk = %u, fs = %d, bitwidth_dai = %u\n",
835 + sclk, params_rate(params), bitwidth_dai);
836 +
837 + dev_dbg(component->dev,
838 + "bitwidth_sclk = %u, num_ch = %u\n",
839 + bitwidth_sclk, params_channels(params));
840 +
841 + cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap);
842 + cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130);
843 + ret = cs43130_pwr_up_asp_dac(component);
844 + return 0;
845 +}
846 +
847 +static int cs43130_hw_free(struct snd_pcm_substream *substream,
848 + struct snd_soc_dai *dai)
849 +{
850 + struct snd_soc_component *component = dai->component;
851 + struct cs43130_priv *cs43130 =
852 + snd_soc_component_get_drvdata(component);
853 +
854 + mutex_lock(&cs43130->clk_mutex);
855 + cs43130->clk_req--;
856 + if (!cs43130->clk_req) {
857 + /* no DAI is currently using clk */
858 + cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);
859 + cs43130_pcm_pdn(component);
860 + }
861 + mutex_unlock(&cs43130->clk_mutex);
862 +
863 + return 0;
864 +}
865 +
866 +static const unsigned int cs43130_asp_src_rates[] = {
867 + 32000, 44100, 48000, 88200, 96000, 176400, 192000
868 +};
869 +
870 +static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = {
871 + .count = ARRAY_SIZE(cs43130_asp_src_rates),
872 + .list = cs43130_asp_src_rates,
873 +};
874 +
875 +static int cs43130_pcm_startup(struct snd_pcm_substream *substream,
876 + struct snd_soc_dai *dai)
877 +{
878 + return snd_pcm_hw_constraint_list(substream->runtime, 0,
879 + SNDRV_PCM_HW_PARAM_RATE,
880 + &cs43130_asp_constraints);
881 +}
882 +
883 +static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
884 +{
885 + struct snd_soc_component *component = codec_dai->component;
886 + struct cs43130_priv *cs43130 =
887 + snd_soc_component_get_drvdata(component);
888 +
889 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
890 + case SND_SOC_DAIFMT_CBS_CFS:
891 + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;
892 + break;
893 + case SND_SOC_DAIFMT_CBM_CFM:
894 + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;
895 + break;
896 + default:
897 + dev_err(component->dev, "unsupported mode\n");
898 + return -EINVAL;
899 + }
900 +
901 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
902 + case SND_SOC_DAIFMT_I2S:
903 + cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S;
904 + break;
905 + case SND_SOC_DAIFMT_LEFT_J:
906 + cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J;
907 + break;
908 + default:
909 + dev_err(component->dev,
910 + "unsupported audio format\n");
911 + return -EINVAL;
912 + }
913 +
914 + dev_dbg(component->dev, "dai_id = %d, dai_mode = %u, dai_format = %u\n",
915 + codec_dai->id,
916 + cs43130->dais[codec_dai->id].dai_mode,
917 + cs43130->dais[codec_dai->id].dai_format);
918 +
919 + return 0;
920 +}
921 +
922 +static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,
923 + int clk_id, unsigned int freq, int dir)
924 +{
925 + struct snd_soc_component *component = codec_dai->component;
926 + struct cs43130_priv *cs43130 =
927 + snd_soc_component_get_drvdata(component);
928 +
929 + cs43130->dais[codec_dai->id].sclk = freq;
930 + dev_dbg(component->dev, "dai_id = %d, sclk = %u\n", codec_dai->id,
931 + cs43130->dais[codec_dai->id].sclk);
932 +
933 + return 0;
934 +}
935 +
936 +static int cs43130_component_set_sysclk(struct snd_soc_component *component,
937 + int clk_id, int source,
938 + unsigned int freq, int dir)
939 +{
940 + struct cs43130_priv *cs43130 =
941 + snd_soc_component_get_drvdata(component);
942 +
943 + dev_dbg(component->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n",
944 + clk_id, source, freq, dir);
945 +
946 + switch (freq) {
947 + case CS43130_MCLK_22M:
948 + case CS43130_MCLK_24M:
949 + cs43130->mclk = freq;
950 + break;
951 + default:
952 + dev_err(component->dev, "Invalid MCLK INT freq: %u\n", freq);
953 + return -EINVAL;
954 + }
955 +
956 + if (source == CS43130_MCLK_SRC_EXT) {
957 + cs43130->pll_bypass = true;
958 + } else {
959 + dev_err(component->dev, "Invalid MCLK source\n");
960 + return -EINVAL;
961 + }
962 +
963 + return 0;
964 +}
965 +static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = {
966 + 24,
967 + 43,
968 + 93,
969 + 200,
970 + 431,
971 + 928,
972 + 2000,
973 + 4309,
974 + 9283,
975 + 20000,
976 +};
977 +static const struct snd_soc_dai_ops cs43130_dai_ops = {
978 + .startup = cs43130_pcm_startup,
979 + .hw_params = cs43130_hw_params,
980 + .hw_free = cs43130_hw_free,
981 + .set_sysclk = cs43130_set_sysclk,
982 + .set_fmt = cs43130_pcm_set_fmt,
983 +};
984 +
985 +static struct snd_soc_dai_driver cs43130_codec_dai = {
986 + .name = "allo-cs43130",
987 + .playback = {
988 + .stream_name = "Playback",
989 + .channels_min = 2,
990 + .channels_max = 2,
991 + .rates = SNDRV_PCM_RATE_CONTINUOUS,
992 + .rate_min = 44100,
993 + .rate_max = 192000,
994 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
995 + SNDRV_PCM_FMTBIT_S24_LE |
996 + SNDRV_PCM_FMTBIT_S32_LE
997 +
998 + },
999 + .ops = &cs43130_dai_ops,
1000 +};
1001 +
1002 +static struct snd_soc_component_driver cs43130_component_driver = {
1003 + .idle_bias_on = true,
1004 + .controls = cs43130_controls,
1005 + .num_controls = ARRAY_SIZE(cs43130_controls),
1006 + .set_sysclk = cs43130_component_set_sysclk,
1007 + .idle_bias_on = 1,
1008 + .use_pmdown_time = 1,
1009 + .endianness = 1,
1010 + .non_legacy_dai_naming = 1,
1011 +};
1012 +
1013 +static const struct regmap_config cs43130_regmap = {
1014 + .reg_bits = 24,
1015 + .pad_bits = 8,
1016 + .val_bits = 8,
1017 +
1018 + .max_register = CS43130_LASTREG,
1019 + .reg_defaults = cs43130_reg_defaults,
1020 + .num_reg_defaults = ARRAY_SIZE(cs43130_reg_defaults),
1021 + .readable_reg = cs43130_readable_register,
1022 + .precious_reg = cs43130_precious_register,
1023 + .volatile_reg = cs43130_volatile_register,
1024 + .cache_type = REGCACHE_RBTREE,
1025 + /* needed for regcache_sync */
1026 + .use_single_read = true,
1027 + .use_single_write = true,
1028 +};
1029 +
1030 +static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
1031 + 50,
1032 + 120,
1033 +};
1034 +
1035 +static int cs43130_handle_device_data(struct i2c_client *i2c_client,
1036 + struct cs43130_priv *cs43130)
1037 +{
1038 + struct device_node *np = i2c_client->dev.of_node;
1039 + unsigned int val;
1040 + int i;
1041 +
1042 + if (of_property_read_u32(np, "cirrus,xtal-ibias", &val) < 0) {
1043 + /* Crystal is unused. System clock is used for external MCLK */
1044 + cs43130->xtal_ibias = CS43130_XTAL_UNUSED;
1045 + return 0;
1046 + }
1047 +
1048 + switch (val) {
1049 + case 1:
1050 + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA;
1051 + break;
1052 + case 2:
1053 + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA;
1054 + break;
1055 + case 3:
1056 + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA;
1057 + break;
1058 + default:
1059 + dev_err(&i2c_client->dev,
1060 + "Invalid cirrus,xtal-ibias value: %d\n", val);
1061 + return -EINVAL;
1062 + }
1063 +
1064 + cs43130->dc_meas = of_property_read_bool(np, "cirrus,dc-measure");
1065 + cs43130->ac_meas = of_property_read_bool(np, "cirrus,ac-measure");
1066 +
1067 + if (of_property_read_u16_array(np, "cirrus,ac-freq", cs43130->ac_freq,
1068 + CS43130_AC_FREQ) < 0) {
1069 + for (i = 0; i < CS43130_AC_FREQ; i++)
1070 + cs43130->ac_freq[i] = cs43130_ac_freq[i];
1071 + }
1072 +
1073 + if (of_property_read_u16_array(np, "cirrus,dc-threshold",
1074 + cs43130->dc_threshold,
1075 + CS43130_DC_THRESHOLD) < 0) {
1076 + for (i = 0; i < CS43130_DC_THRESHOLD; i++)
1077 + cs43130->dc_threshold[i] = cs43130_dc_threshold[i];
1078 + }
1079 +
1080 + return 0;
1081 +}
1082 +
1083 +
1084 +static int allo_cs43130_component_probe(struct i2c_client *i2c,
1085 + const struct i2c_device_id *id)
1086 +{
1087 + struct regmap *regmap;
1088 + struct regmap_config config = cs43130_regmap;
1089 + struct device *dev = &i2c->dev;
1090 + struct cs43130_priv *cs43130;
1091 + unsigned int devid = 0;
1092 + unsigned int reg;
1093 + int ret;
1094 +
1095 + regmap = devm_regmap_init_i2c(i2c, &config);
1096 + if (IS_ERR(regmap))
1097 + return PTR_ERR(regmap);
1098 +
1099 + cs43130 = devm_kzalloc(dev, sizeof(struct cs43130_priv),
1100 + GFP_KERNEL);
1101 + if (!cs43130)
1102 + return -ENOMEM;
1103 +
1104 + dev_set_drvdata(dev, cs43130);
1105 + cs43130->regmap = regmap;
1106 +
1107 + if (i2c->dev.of_node) {
1108 + ret = cs43130_handle_device_data(i2c, cs43130);
1109 + if (ret != 0)
1110 + return ret;
1111 + }
1112 + usleep_range(2000, 2050);
1113 +
1114 + ret = regmap_read(cs43130->regmap, CS43130_DEVID_AB, &reg);
1115 + devid = (reg & 0xFF) << 12;
1116 + ret = regmap_read(cs43130->regmap, CS43130_DEVID_CD, &reg);
1117 + devid |= (reg & 0xFF) << 4;
1118 + ret = regmap_read(cs43130->regmap, CS43130_DEVID_E, &reg);
1119 + devid |= (reg & 0xF0) >> 4;
1120 + if (devid != CS43198_CHIP_ID) {
1121 + dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret);
1122 + return ret;
1123 + }
1124 +
1125 + cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
1126 + msleep(20);
1127 +
1128 + ret = snd_soc_register_component(dev, &cs43130_component_driver,
1129 + &cs43130_codec_dai, 1);
1130 + if (ret != 0) {
1131 + dev_err(dev, "failed to register codec: %d\n", ret);
1132 + return ret;
1133 + }
1134 + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
1135 + CS43130_ASP_3ST_MASK, 0);
1136 + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
1137 + CS43130_XSP_3ST_MASK, 1);
1138 + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
1139 + CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
1140 + msleep(20);
1141 + regmap_write(cs43130->regmap, CS43130_CLASS_H_CTL, 0x06);
1142 + snd_allo_clk44gpio = devm_gpiod_get(dev, "clock44", GPIOD_OUT_HIGH);
1143 + if (IS_ERR(snd_allo_clk44gpio))
1144 + dev_err(dev, "devm_gpiod_get() failed\n");
1145 +
1146 + snd_allo_clk48gpio = devm_gpiod_get(dev, "clock48", GPIOD_OUT_LOW);
1147 + if (IS_ERR(snd_allo_clk48gpio))
1148 + dev_err(dev, "devm_gpiod_get() failed\n");
1149 +
1150 + return 0;
1151 +}
1152 +
1153 +static int allo_cs43130_component_remove(struct i2c_client *i2c)
1154 +{
1155 + snd_soc_unregister_component(&i2c->dev);
1156 + return 0;
1157 +}
1158 +
1159 +static const struct i2c_device_id allo_cs43130_component_id[] = {
1160 + { "allo-cs43198", },
1161 + { }
1162 +};
1163 +MODULE_DEVICE_TABLE(i2c, allo_cs43130_component_id);
1164 +
1165 +static const struct of_device_id allo_cs43130_codec_of_match[] = {
1166 + { .compatible = "allo,allo-cs43198", },
1167 + { }
1168 +};
1169 +MODULE_DEVICE_TABLE(of, allo_cs43130_codec_of_match);
1170 +
1171 +static struct i2c_driver allo_cs43130_component_driver = {
1172 + .probe = allo_cs43130_component_probe,
1173 + .remove = allo_cs43130_component_remove,
1174 + .id_table = allo_cs43130_component_id,
1175 + .driver = {
1176 + .name = "allo-cs43198",
1177 + .of_match_table = allo_cs43130_codec_of_match,
1178 + },
1179 +};
1180 +
1181 +module_i2c_driver(allo_cs43130_component_driver);
1182 +
1183 +MODULE_DESCRIPTION("ASoC Allo Boss2 Codec Driver");
1184 +MODULE_AUTHOR("Sudeepkumar <sudeepkumar@cem-solutions.net>");
1185 +MODULE_LICENSE("GPL v2");