1 // SPDX-License-Identifier: GPL-2.0-only
3 // Codec driver for Microsemi ZL38060 Connected Home Audio Processor.
5 // Copyright(c) 2020 Sven Van Asbroeck
7 // The ZL38060 is very flexible and configurable. This driver implements only a
8 // tiny subset of the chip's possible configurations:
10 // - DSP block bypassed: DAI routed straight to DACs
11 // microphone routed straight to DAI
12 // - chip's internal clock is driven by a 12 MHz external crystal
13 // - chip's DAI connected to CPU is I2S, and bit + frame clock master
14 // - chip must be strapped for "host boot": in this mode, firmware will be
15 // provided by this driver.
17 #include <linux/gpio/consumer.h>
18 #include <linux/gpio/driver.h>
19 #include <linux/property.h>
20 #include <linux/spi/spi.h>
21 #include <linux/regmap.h>
22 #include <linux/module.h>
23 #include <linux/ihex.h>
25 #include <sound/pcm_params.h>
26 #include <sound/core.h>
27 #include <sound/pcm.h>
28 #include <sound/soc.h>
30 #define DRV_NAME "zl38060"
32 #define ZL38_RATES (SNDRV_PCM_RATE_8000 |\
33 SNDRV_PCM_RATE_16000 |\
35 #define ZL38_FORMATS SNDRV_PCM_FMTBIT_S16_LE
37 #define HBI_FIRMWARE_PAGE 0xFF
38 #define ZL38_MAX_RAW_XFER 0x100
40 #define REG_TDMA_CFG_CLK 0x0262
41 #define CFG_CLK_PCLK_SHIFT 4
42 #define CFG_CLK_PCLK_MASK (0x7ff << CFG_CLK_PCLK_SHIFT)
43 #define CFG_CLK_PCLK(bits) ((bits - 1) << CFG_CLK_PCLK_SHIFT)
44 #define CFG_CLK_MASTER BIT(15)
45 #define CFG_CLK_FSRATE_MASK 0x7
46 #define CFG_CLK_FSRATE_8KHZ 0x1
47 #define CFG_CLK_FSRATE_16KHZ 0x2
48 #define CFG_CLK_FSRATE_48KHZ 0x6
50 #define REG_CLK_CFG 0x0016
51 #define CLK_CFG_SOURCE_XTAL BIT(15)
53 #define REG_CLK_STATUS 0x0014
54 #define CLK_STATUS_HWRST BIT(0)
56 #define REG_PARAM_RESULT 0x0034
57 #define PARAM_RESULT_READY 0xD3D3
59 #define REG_PG255_BASE_HI 0x000C
60 #define REG_PG255_OFFS(addr) ((HBI_FIRMWARE_PAGE << 8) | (addr & 0xFF))
61 #define REG_FWR_EXEC 0x012C
63 #define REG_CMD 0x0032
64 #define REG_HW_REV 0x0020
65 #define REG_FW_PROD 0x0022
66 #define REG_FW_REV 0x0024
68 #define REG_SEMA_FLAGS 0x0006
69 #define SEMA_FLAGS_BOOT_CMD BIT(0)
70 #define SEMA_FLAGS_APP_REBOOT BIT(1)
72 #define REG_HW_REV 0x0020
73 #define REG_FW_PROD 0x0022
74 #define REG_FW_REV 0x0024
75 #define REG_GPIO_DIR 0x02DC
76 #define REG_GPIO_DAT 0x02DA
78 #define BOOTCMD_LOAD_COMPLETE 0x000D
79 #define BOOTCMD_FW_GO 0x0008
81 #define FIRMWARE_MAJOR 2
82 #define FIRMWARE_MINOR 2
84 struct zl38_codec_priv
{
86 struct regmap
*regmap
;
87 bool is_stream_in_use
[2];
88 struct gpio_chip
*gpio_chip
;
91 static int zl38_fw_issue_command(struct regmap
*regmap
, u16 cmd
)
96 err
= regmap_read_poll_timeout(regmap
, REG_SEMA_FLAGS
, val
,
97 !(val
& SEMA_FLAGS_BOOT_CMD
), 10000,
101 err
= regmap_write(regmap
, REG_CMD
, cmd
);
104 err
= regmap_update_bits(regmap
, REG_SEMA_FLAGS
, SEMA_FLAGS_BOOT_CMD
,
105 SEMA_FLAGS_BOOT_CMD
);
109 return regmap_read_poll_timeout(regmap
, REG_CMD
, val
, !val
, 10000,
113 static int zl38_fw_go(struct regmap
*regmap
)
117 err
= zl38_fw_issue_command(regmap
, BOOTCMD_LOAD_COMPLETE
);
121 return zl38_fw_issue_command(regmap
, BOOTCMD_FW_GO
);
124 static int zl38_fw_enter_boot_mode(struct regmap
*regmap
)
129 err
= regmap_update_bits(regmap
, REG_CLK_STATUS
, CLK_STATUS_HWRST
,
134 return regmap_read_poll_timeout(regmap
, REG_PARAM_RESULT
, val
,
135 val
== PARAM_RESULT_READY
, 1000, 50000);
139 zl38_fw_send_data(struct regmap
*regmap
, u32 addr
, const void *data
, u16 len
)
141 __be32 addr_base
= cpu_to_be32(addr
& ~0xFF);
144 err
= regmap_raw_write(regmap
, REG_PG255_BASE_HI
, &addr_base
,
148 return regmap_raw_write(regmap
, REG_PG255_OFFS(addr
), data
, len
);
151 static int zl38_fw_send_xaddr(struct regmap
*regmap
, const void *data
)
153 /* execution address from ihex: 32-bit little endian.
154 * device register expects 32-bit big endian.
156 u32 addr
= le32_to_cpup(data
);
157 __be32 baddr
= cpu_to_be32(addr
);
159 return regmap_raw_write(regmap
, REG_FWR_EXEC
, &baddr
, sizeof(baddr
));
162 static int zl38_load_firmware(struct device
*dev
, struct regmap
*regmap
)
164 const struct ihex_binrec
*rec
;
165 const struct firmware
*fw
;
170 /* how to get this firmware:
171 * 1. request and download chip firmware from Microsemi
172 * (provided by Microsemi in srec format)
173 * 2. convert downloaded firmware from srec to ihex. Simple tool:
174 * https://gitlab.com/TheSven73/s3-to-irec
175 * 3. convert ihex to binary (.fw) using ihex2fw tool which is included
176 * with the Linux kernel sources
178 err
= request_ihex_firmware(&fw
, "zl38060.fw", dev
);
181 err
= zl38_fw_enter_boot_mode(regmap
);
184 rec
= (const struct ihex_binrec
*)fw
->data
;
186 addr
= be32_to_cpu(rec
->addr
);
187 len
= be16_to_cpu(rec
->len
);
189 /* regular data ihex record */
190 err
= zl38_fw_send_data(regmap
, addr
, rec
->data
, len
);
191 } else if (len
== 4) {
192 /* execution address ihex record */
193 err
= zl38_fw_send_xaddr(regmap
, rec
->data
);
200 rec
= ihex_next_binrec(rec
);
202 err
= zl38_fw_go(regmap
);
205 release_firmware(fw
);
210 static int zl38_software_reset(struct regmap
*regmap
)
215 err
= regmap_update_bits(regmap
, REG_SEMA_FLAGS
, SEMA_FLAGS_APP_REBOOT
,
216 SEMA_FLAGS_APP_REBOOT
);
220 /* wait for host bus interface to settle.
221 * Not sure if this is required: Microsemi's vendor driver does this,
222 * but the firmware manual does not mention it. Leave it in, there's
223 * little downside, apart from a slower reset.
227 return regmap_read_poll_timeout(regmap
, REG_SEMA_FLAGS
, val
,
228 !(val
& SEMA_FLAGS_APP_REBOOT
), 10000,
232 static int zl38_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
234 struct zl38_codec_priv
*priv
= snd_soc_dai_get_drvdata(dai
);
237 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
238 case SND_SOC_DAIFMT_I2S
:
239 /* firmware default is normal i2s */
245 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
246 case SND_SOC_DAIFMT_NB_NF
:
247 /* firmware default is normal bitclock and frame */
253 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
254 case SND_SOC_DAIFMT_CBM_CFM
:
255 /* always 32 bits per frame (= 16 bits/channel, 2 channels) */
256 err
= regmap_update_bits(priv
->regmap
, REG_TDMA_CFG_CLK
,
257 CFG_CLK_MASTER
| CFG_CLK_PCLK_MASK
,
258 CFG_CLK_MASTER
| CFG_CLK_PCLK(32));
269 static int zl38_hw_params(struct snd_pcm_substream
*substream
,
270 struct snd_pcm_hw_params
*params
,
271 struct snd_soc_dai
*dai
)
273 struct zl38_codec_priv
*priv
= snd_soc_dai_get_drvdata(dai
);
274 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
278 /* We cannot change hw_params while the dai is already in use - the
279 * software reset will corrupt the audio. However, this is not required,
280 * as the chip's TDM buses are fully symmetric, which mandates identical
281 * rates, channels, and samplebits for record and playback.
283 if (priv
->is_stream_in_use
[!tx
])
286 switch (params_rate(params
)) {
288 fsrate
= CFG_CLK_FSRATE_8KHZ
;
291 fsrate
= CFG_CLK_FSRATE_16KHZ
;
294 fsrate
= CFG_CLK_FSRATE_48KHZ
;
300 err
= regmap_update_bits(priv
->regmap
, REG_TDMA_CFG_CLK
,
301 CFG_CLK_FSRATE_MASK
, fsrate
);
305 /* chip requires a software reset to apply audio register changes */
306 err
= zl38_software_reset(priv
->regmap
);
311 priv
->is_stream_in_use
[tx
] = true;
316 static int zl38_hw_free(struct snd_pcm_substream
*substream
,
317 struct snd_soc_dai
*dai
)
319 struct zl38_codec_priv
*priv
= snd_soc_dai_get_drvdata(dai
);
320 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
322 priv
->is_stream_in_use
[tx
] = false;
327 /* stereo bypass with no AEC */
328 static const struct reg_sequence cp_config_stereo_bypass
[] = {
329 /* interconnects must be programmed first */
330 { 0x0210, 0x0005 }, /* DAC1 in <= I2S1-L */
331 { 0x0212, 0x0006 }, /* DAC2 in <= I2S1-R */
332 { 0x0214, 0x0001 }, /* I2S1-L in <= MIC1 */
333 { 0x0216, 0x0001 }, /* I2S1-R in <= MIC1 */
334 { 0x0224, 0x0000 }, /* AEC-S in <= n/a */
335 { 0x0226, 0x0000 }, /* AEC-R in <= n/a */
336 /* output enables must be programmed next */
337 { 0x0202, 0x000F }, /* enable I2S1 + DAC */
340 static const struct snd_soc_dai_ops zl38_dai_ops
= {
341 .set_fmt
= zl38_set_fmt
,
342 .hw_params
= zl38_hw_params
,
343 .hw_free
= zl38_hw_free
,
346 static struct snd_soc_dai_driver zl38_dai
= {
347 .name
= "zl38060-tdma",
349 .stream_name
= "Playback",
353 .formats
= ZL38_FORMATS
,
356 .stream_name
= "Capture",
360 .formats
= ZL38_FORMATS
,
362 .ops
= &zl38_dai_ops
,
363 .symmetric_rates
= 1,
364 .symmetric_samplebits
= 1,
365 .symmetric_channels
= 1,
368 static const struct snd_soc_dapm_widget zl38_dapm_widgets
[] = {
369 SND_SOC_DAPM_OUTPUT("DAC1"),
370 SND_SOC_DAPM_OUTPUT("DAC2"),
372 SND_SOC_DAPM_INPUT("DMICL"),
375 static const struct snd_soc_dapm_route zl38_dapm_routes
[] = {
376 { "DAC1", NULL
, "Playback" },
377 { "DAC2", NULL
, "Playback" },
379 { "Capture", NULL
, "DMICL" },
382 static const struct snd_soc_component_driver zl38_component_dev
= {
383 .dapm_widgets
= zl38_dapm_widgets
,
384 .num_dapm_widgets
= ARRAY_SIZE(zl38_dapm_widgets
),
385 .dapm_routes
= zl38_dapm_routes
,
386 .num_dapm_routes
= ARRAY_SIZE(zl38_dapm_routes
),
388 .non_legacy_dai_naming
= 1,
391 static void chip_gpio_set(struct gpio_chip
*c
, unsigned int offset
, int val
)
393 struct regmap
*regmap
= gpiochip_get_data(c
);
394 unsigned int mask
= BIT(offset
);
396 regmap_update_bits(regmap
, REG_GPIO_DAT
, mask
, val
? mask
: 0);
399 static int chip_gpio_get(struct gpio_chip
*c
, unsigned int offset
)
401 struct regmap
*regmap
= gpiochip_get_data(c
);
402 unsigned int mask
= BIT(offset
);
406 err
= regmap_read(regmap
, REG_GPIO_DAT
, &val
);
410 return !!(val
& mask
);
413 static int chip_direction_input(struct gpio_chip
*c
, unsigned int offset
)
415 struct regmap
*regmap
= gpiochip_get_data(c
);
416 unsigned int mask
= BIT(offset
);
418 return regmap_update_bits(regmap
, REG_GPIO_DIR
, mask
, 0);
422 chip_direction_output(struct gpio_chip
*c
, unsigned int offset
, int val
)
424 struct regmap
*regmap
= gpiochip_get_data(c
);
425 unsigned int mask
= BIT(offset
);
427 chip_gpio_set(c
, offset
, val
);
428 return regmap_update_bits(regmap
, REG_GPIO_DIR
, mask
, mask
);
431 static const struct gpio_chip template_chip
= {
432 .owner
= THIS_MODULE
,
437 .direction_input
= chip_direction_input
,
438 .direction_output
= chip_direction_output
,
439 .get
= chip_gpio_get
,
440 .set
= chip_gpio_set
,
445 static int zl38_check_revision(struct device
*dev
, struct regmap
*regmap
)
447 unsigned int hwrev
, fwprod
, fwrev
;
448 int fw_major
, fw_minor
, fw_micro
;
451 err
= regmap_read(regmap
, REG_HW_REV
, &hwrev
);
454 err
= regmap_read(regmap
, REG_FW_PROD
, &fwprod
);
457 err
= regmap_read(regmap
, REG_FW_REV
, &fwrev
);
461 fw_major
= (fwrev
>> 12) & 0xF;
462 fw_minor
= (fwrev
>> 8) & 0xF;
463 fw_micro
= fwrev
& 0xFF;
464 dev_info(dev
, "hw rev 0x%x, fw product code %d, firmware rev %d.%d.%d",
465 hwrev
& 0x1F, fwprod
, fw_major
, fw_minor
, fw_micro
);
467 if (fw_major
!= FIRMWARE_MAJOR
|| fw_minor
< FIRMWARE_MINOR
) {
468 dev_err(dev
, "unsupported firmware. driver supports %d.%d",
469 FIRMWARE_MAJOR
, FIRMWARE_MINOR
);
476 static int zl38_bus_read(void *context
,
477 const void *reg_buf
, size_t reg_size
,
478 void *val_buf
, size_t val_size
)
480 struct spi_device
*spi
= context
;
481 const u8
*reg_buf8
= reg_buf
;
486 if (reg_size
!= 2 || val_size
> ZL38_MAX_RAW_XFER
)
489 offs
= reg_buf8
[1] >> 1;
494 txbuf
[len
++] = page
== HBI_FIRMWARE_PAGE
? 0xFF : page
- 1;
496 txbuf
[len
++] = val_size
/ 2 - 1;
498 txbuf
[len
++] = offs
| 0x80;
499 txbuf
[len
++] = val_size
/ 2 - 1;
502 return spi_write_then_read(spi
, txbuf
, len
, val_buf
, val_size
);
505 static int zl38_bus_write(void *context
, const void *data
, size_t count
)
507 struct spi_device
*spi
= context
;
508 u8 buf
[4 + ZL38_MAX_RAW_XFER
];
509 size_t val_len
, len
= 0;
510 const u8
*data8
= data
;
513 if (count
> (2 + ZL38_MAX_RAW_XFER
) || count
< 4)
516 offs
= data8
[1] >> 1;
521 buf
[len
++] = page
== HBI_FIRMWARE_PAGE
? 0xFF : page
- 1;
523 buf
[len
++] = (val_len
/ 2 - 1) | 0x80;
525 buf
[len
++] = offs
| 0x80;
526 buf
[len
++] = (val_len
/ 2 - 1) | 0x80;
528 memcpy(buf
+ len
, data8
+ 2, val_len
);
531 return spi_write(spi
, buf
, len
);
534 static const struct regmap_bus zl38_regmap_bus
= {
535 .read
= zl38_bus_read
,
536 .write
= zl38_bus_write
,
537 .max_raw_write
= ZL38_MAX_RAW_XFER
,
538 .max_raw_read
= ZL38_MAX_RAW_XFER
,
541 static const struct regmap_config zl38_regmap_conf
= {
545 .use_single_read
= true,
546 .use_single_write
= true,
549 static int zl38_spi_probe(struct spi_device
*spi
)
551 struct device
*dev
= &spi
->dev
;
552 struct zl38_codec_priv
*priv
;
553 struct gpio_desc
*reset_gpio
;
556 /* get the chip to a known state by putting it in reset */
557 reset_gpio
= devm_gpiod_get_optional(dev
, "reset", GPIOD_OUT_HIGH
);
558 if (IS_ERR(reset_gpio
))
559 return PTR_ERR(reset_gpio
);
561 /* datasheet: need > 10us for a digital + analog reset */
562 usleep_range(15, 50);
563 /* take the chip out of reset */
564 gpiod_set_value_cansleep(reset_gpio
, 0);
565 /* datasheet: need > 3ms for digital section to become stable */
566 usleep_range(3000, 10000);
569 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
574 dev_set_drvdata(dev
, priv
);
575 priv
->regmap
= devm_regmap_init(dev
, &zl38_regmap_bus
, spi
,
577 if (IS_ERR(priv
->regmap
))
578 return PTR_ERR(priv
->regmap
);
580 err
= zl38_load_firmware(dev
, priv
->regmap
);
584 err
= zl38_check_revision(dev
, priv
->regmap
);
588 priv
->gpio_chip
= devm_kmemdup(dev
, &template_chip
,
589 sizeof(template_chip
), GFP_KERNEL
);
590 if (!priv
->gpio_chip
)
592 #ifdef CONFIG_OF_GPIO
593 priv
->gpio_chip
->of_node
= dev
->of_node
;
595 err
= devm_gpiochip_add_data(dev
, priv
->gpio_chip
, priv
->regmap
);
599 /* setup the cross-point switch for stereo bypass */
600 err
= regmap_multi_reg_write(priv
->regmap
, cp_config_stereo_bypass
,
601 ARRAY_SIZE(cp_config_stereo_bypass
));
604 /* setup for 12MHz crystal connected to the chip */
605 err
= regmap_update_bits(priv
->regmap
, REG_CLK_CFG
, CLK_CFG_SOURCE_XTAL
,
606 CLK_CFG_SOURCE_XTAL
);
610 return devm_snd_soc_register_component(dev
, &zl38_component_dev
,
614 static const struct of_device_id zl38_dt_ids
[] = {
615 { .compatible
= "mscc,zl38060", },
618 MODULE_DEVICE_TABLE(of
, zl38_dt_ids
);
620 static const struct spi_device_id zl38_spi_ids
[] = {
624 MODULE_DEVICE_TABLE(spi
, zl38_spi_ids
);
626 static struct spi_driver zl38060_spi_driver
= {
629 .of_match_table
= of_match_ptr(zl38_dt_ids
),
631 .probe
= zl38_spi_probe
,
632 .id_table
= zl38_spi_ids
,
634 module_spi_driver(zl38060_spi_driver
);
636 MODULE_DESCRIPTION("ASoC ZL38060 driver");
637 MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
638 MODULE_LICENSE("GPL v2");