xref: /linux/sound/soc/codecs/zl38060.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Codec driver for Microsemi ZL38060 Connected Home Audio Processor.
4 //
5 // Copyright(c) 2020 Sven Van Asbroeck
6 
7 // The ZL38060 is very flexible and configurable. This driver implements only a
8 // tiny subset of the chip's possible configurations:
9 //
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.
16 
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>
24 
25 #include <sound/pcm_params.h>
26 #include <sound/core.h>
27 #include <sound/pcm.h>
28 #include <sound/soc.h>
29 
30 #define DRV_NAME		"zl38060"
31 
32 #define ZL38_RATES		(SNDRV_PCM_RATE_8000  |\
33 				SNDRV_PCM_RATE_16000 |\
34 				SNDRV_PCM_RATE_48000)
35 #define ZL38_FORMATS		SNDRV_PCM_FMTBIT_S16_LE
36 
37 #define HBI_FIRMWARE_PAGE	0xFF
38 #define ZL38_MAX_RAW_XFER	0x100
39 
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
49 
50 #define REG_CLK_CFG		0x0016
51 #define CLK_CFG_SOURCE_XTAL	BIT(15)
52 
53 #define REG_CLK_STATUS		0x0014
54 #define CLK_STATUS_HWRST	BIT(0)
55 
56 #define REG_PARAM_RESULT	0x0034
57 #define PARAM_RESULT_READY	0xD3D3
58 
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
62 
63 #define REG_CMD			0x0032
64 #define REG_HW_REV		0x0020
65 #define REG_FW_PROD		0x0022
66 #define REG_FW_REV		0x0024
67 
68 #define REG_SEMA_FLAGS		0x0006
69 #define SEMA_FLAGS_BOOT_CMD	BIT(0)
70 #define SEMA_FLAGS_APP_REBOOT	BIT(1)
71 
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
77 
78 #define BOOTCMD_LOAD_COMPLETE	0x000D
79 #define BOOTCMD_FW_GO		0x0008
80 
81 #define FIRMWARE_MAJOR		2
82 #define FIRMWARE_MINOR		2
83 
84 struct zl38_codec_priv {
85 	struct device *dev;
86 	struct regmap *regmap;
87 	bool is_stream_in_use[2];
88 	struct gpio_chip *gpio_chip;
89 };
90 
91 static int zl38_fw_issue_command(struct regmap *regmap, u16 cmd)
92 {
93 	unsigned int val;
94 	int err;
95 
96 	err = regmap_read_poll_timeout(regmap, REG_SEMA_FLAGS, val,
97 				       !(val & SEMA_FLAGS_BOOT_CMD), 10000,
98 				       10000 * 100);
99 	if (err)
100 		return err;
101 	err = regmap_write(regmap, REG_CMD, cmd);
102 	if (err)
103 		return err;
104 	err = regmap_update_bits(regmap, REG_SEMA_FLAGS, SEMA_FLAGS_BOOT_CMD,
105 				 SEMA_FLAGS_BOOT_CMD);
106 	if (err)
107 		return err;
108 
109 	return regmap_read_poll_timeout(regmap, REG_CMD, val, !val, 10000,
110 					10000 * 100);
111 }
112 
113 static int zl38_fw_go(struct regmap *regmap)
114 {
115 	int err;
116 
117 	err = zl38_fw_issue_command(regmap, BOOTCMD_LOAD_COMPLETE);
118 	if (err)
119 		return err;
120 
121 	return zl38_fw_issue_command(regmap, BOOTCMD_FW_GO);
122 }
123 
124 static int zl38_fw_enter_boot_mode(struct regmap *regmap)
125 {
126 	unsigned int val;
127 	int err;
128 
129 	err = regmap_update_bits(regmap, REG_CLK_STATUS, CLK_STATUS_HWRST,
130 				 CLK_STATUS_HWRST);
131 	if (err)
132 		return err;
133 
134 	return regmap_read_poll_timeout(regmap, REG_PARAM_RESULT, val,
135 					val == PARAM_RESULT_READY, 1000, 50000);
136 }
137 
138 static int
139 zl38_fw_send_data(struct regmap *regmap, u32 addr, const void *data, u16 len)
140 {
141 	__be32 addr_base = cpu_to_be32(addr & ~0xFF);
142 	int err;
143 
144 	err = regmap_raw_write(regmap, REG_PG255_BASE_HI, &addr_base,
145 			       sizeof(addr_base));
146 	if (err)
147 		return err;
148 	return regmap_raw_write(regmap, REG_PG255_OFFS(addr), data, len);
149 }
150 
151 static int zl38_fw_send_xaddr(struct regmap *regmap, const void *data)
152 {
153 	/* execution address from ihex: 32-bit little endian.
154 	 * device register expects 32-bit big endian.
155 	 */
156 	u32 addr = le32_to_cpup(data);
157 	__be32 baddr = cpu_to_be32(addr);
158 
159 	return regmap_raw_write(regmap, REG_FWR_EXEC, &baddr, sizeof(baddr));
160 }
161 
162 static int zl38_load_firmware(struct device *dev, struct regmap *regmap)
163 {
164 	const struct ihex_binrec *rec;
165 	const struct firmware *fw __free(firmware) = NULL;
166 	u32 addr;
167 	u16 len;
168 	int err;
169 
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
177 	 */
178 	err = request_ihex_firmware(&fw, "zl38060.fw", dev);
179 	if (err)
180 		return err;
181 	err = zl38_fw_enter_boot_mode(regmap);
182 	if (err)
183 		return err;
184 	rec = (const struct ihex_binrec *)fw->data;
185 	while (rec) {
186 		addr = be32_to_cpu(rec->addr);
187 		len = be16_to_cpu(rec->len);
188 		if (addr) {
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);
194 		} else {
195 			err = -EINVAL;
196 		}
197 		if (err)
198 			return err;
199 		/* next ! */
200 		rec = ihex_next_binrec(rec);
201 	}
202 
203 	return zl38_fw_go(regmap);
204 }
205 
206 
207 static int zl38_software_reset(struct regmap *regmap)
208 {
209 	unsigned int val;
210 	int err;
211 
212 	err = regmap_update_bits(regmap, REG_SEMA_FLAGS, SEMA_FLAGS_APP_REBOOT,
213 				 SEMA_FLAGS_APP_REBOOT);
214 	if (err)
215 		return err;
216 
217 	/* wait for host bus interface to settle.
218 	 * Not sure if this is required: Microsemi's vendor driver does this,
219 	 * but the firmware manual does not mention it. Leave it in, there's
220 	 * little downside, apart from a slower reset.
221 	 */
222 	msleep(50);
223 
224 	return regmap_read_poll_timeout(regmap, REG_SEMA_FLAGS, val,
225 					!(val & SEMA_FLAGS_APP_REBOOT), 10000,
226 					10000 * 100);
227 }
228 
229 static int zl38_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
230 {
231 	struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai);
232 	int err;
233 
234 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
235 	case SND_SOC_DAIFMT_I2S:
236 		/* firmware default is normal i2s */
237 		break;
238 	default:
239 		return -EINVAL;
240 	}
241 
242 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
243 	case SND_SOC_DAIFMT_NB_NF:
244 		/* firmware default is normal bitclock and frame */
245 		break;
246 	default:
247 		return -EINVAL;
248 	}
249 
250 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
251 	case SND_SOC_DAIFMT_CBP_CFP:
252 		/* always 32 bits per frame (= 16 bits/channel, 2 channels) */
253 		err = regmap_update_bits(priv->regmap, REG_TDMA_CFG_CLK,
254 					 CFG_CLK_MASTER | CFG_CLK_PCLK_MASK,
255 					 CFG_CLK_MASTER | CFG_CLK_PCLK(32));
256 		if (err)
257 			return err;
258 		break;
259 	default:
260 		return -EINVAL;
261 	}
262 
263 	return 0;
264 }
265 
266 static int zl38_hw_params(struct snd_pcm_substream *substream,
267 			  struct snd_pcm_hw_params *params,
268 			  struct snd_soc_dai *dai)
269 {
270 	struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai);
271 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
272 	unsigned int fsrate;
273 	int err;
274 
275 	/* We cannot change hw_params while the dai is already in use - the
276 	 * software reset will corrupt the audio. However, this is not required,
277 	 * as the chip's TDM buses are fully symmetric, which mandates identical
278 	 * rates, channels, and samplebits for record and playback.
279 	 */
280 	if (priv->is_stream_in_use[!tx])
281 		goto skip_setup;
282 
283 	switch (params_rate(params)) {
284 	case 8000:
285 		fsrate = CFG_CLK_FSRATE_8KHZ;
286 		break;
287 	case 16000:
288 		fsrate = CFG_CLK_FSRATE_16KHZ;
289 		break;
290 	case 48000:
291 		fsrate = CFG_CLK_FSRATE_48KHZ;
292 		break;
293 	default:
294 		return -EINVAL;
295 	}
296 
297 	err = regmap_update_bits(priv->regmap, REG_TDMA_CFG_CLK,
298 				 CFG_CLK_FSRATE_MASK, fsrate);
299 	if (err)
300 		return err;
301 
302 	/* chip requires a software reset to apply audio register changes */
303 	err = zl38_software_reset(priv->regmap);
304 	if (err)
305 		return err;
306 
307 skip_setup:
308 	priv->is_stream_in_use[tx] = true;
309 
310 	return 0;
311 }
312 
313 static int zl38_hw_free(struct snd_pcm_substream *substream,
314 			struct snd_soc_dai *dai)
315 {
316 	struct zl38_codec_priv *priv = snd_soc_dai_get_drvdata(dai);
317 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
318 
319 	priv->is_stream_in_use[tx] = false;
320 
321 	return 0;
322 }
323 
324 /* stereo bypass with no AEC */
325 static const struct reg_sequence cp_config_stereo_bypass[] = {
326 	/* interconnects must be programmed first */
327 	{ 0x0210, 0x0005 },	/* DAC1   in <= I2S1-L */
328 	{ 0x0212, 0x0006 },	/* DAC2   in <= I2S1-R */
329 	{ 0x0214, 0x0001 },	/* I2S1-L in <= MIC1   */
330 	{ 0x0216, 0x0001 },	/* I2S1-R in <= MIC1   */
331 	{ 0x0224, 0x0000 },	/* AEC-S  in <= n/a    */
332 	{ 0x0226, 0x0000 },	/* AEC-R  in <= n/a    */
333 	/* output enables must be programmed next */
334 	{ 0x0202, 0x000F },	/* enable I2S1 + DAC   */
335 };
336 
337 static const struct snd_soc_dai_ops zl38_dai_ops = {
338 	.set_fmt = zl38_set_fmt,
339 	.hw_params = zl38_hw_params,
340 	.hw_free = zl38_hw_free,
341 };
342 
343 static struct snd_soc_dai_driver zl38_dai = {
344 	.name = "zl38060-tdma",
345 	.playback = {
346 		.stream_name = "Playback",
347 		.channels_min = 2,
348 		.channels_max = 2,
349 		.rates = ZL38_RATES,
350 		.formats = ZL38_FORMATS,
351 	},
352 	.capture = {
353 		.stream_name = "Capture",
354 		.channels_min = 2,
355 		.channels_max = 2,
356 		.rates = ZL38_RATES,
357 		.formats = ZL38_FORMATS,
358 	},
359 	.ops = &zl38_dai_ops,
360 	.symmetric_rate = 1,
361 	.symmetric_sample_bits = 1,
362 	.symmetric_channels = 1,
363 };
364 
365 static const struct snd_soc_dapm_widget zl38_dapm_widgets[] = {
366 	SND_SOC_DAPM_OUTPUT("DAC1"),
367 	SND_SOC_DAPM_OUTPUT("DAC2"),
368 
369 	SND_SOC_DAPM_INPUT("DMICL"),
370 };
371 
372 static const struct snd_soc_dapm_route zl38_dapm_routes[] = {
373 	{ "DAC1",  NULL, "Playback" },
374 	{ "DAC2",  NULL, "Playback" },
375 
376 	{ "Capture",  NULL, "DMICL" },
377 };
378 
379 static const struct snd_soc_component_driver zl38_component_dev = {
380 	.dapm_widgets		= zl38_dapm_widgets,
381 	.num_dapm_widgets	= ARRAY_SIZE(zl38_dapm_widgets),
382 	.dapm_routes		= zl38_dapm_routes,
383 	.num_dapm_routes	= ARRAY_SIZE(zl38_dapm_routes),
384 	.endianness		= 1,
385 };
386 
387 static int chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val)
388 {
389 	struct regmap *regmap = gpiochip_get_data(c);
390 	unsigned int mask = BIT(offset);
391 
392 	return regmap_update_bits(regmap, REG_GPIO_DAT, mask, val ? mask : 0);
393 }
394 
395 static int chip_gpio_get(struct gpio_chip *c, unsigned int offset)
396 {
397 	struct regmap *regmap = gpiochip_get_data(c);
398 	unsigned int mask = BIT(offset);
399 	unsigned int val;
400 	int err;
401 
402 	err = regmap_read(regmap, REG_GPIO_DAT, &val);
403 	if (err)
404 		return err;
405 
406 	return !!(val & mask);
407 }
408 
409 static int chip_direction_input(struct gpio_chip *c, unsigned int offset)
410 {
411 	struct regmap *regmap = gpiochip_get_data(c);
412 	unsigned int mask = BIT(offset);
413 
414 	return regmap_update_bits(regmap, REG_GPIO_DIR, mask, 0);
415 }
416 
417 static int
418 chip_direction_output(struct gpio_chip *c, unsigned int offset, int val)
419 {
420 	struct regmap *regmap = gpiochip_get_data(c);
421 	unsigned int mask = BIT(offset);
422 	int ret;
423 
424 	ret = chip_gpio_set(c, offset, val);
425 	if (ret)
426 		return ret;
427 
428 	return regmap_update_bits(regmap, REG_GPIO_DIR, mask, mask);
429 }
430 
431 static const struct gpio_chip template_chip = {
432 	.owner = THIS_MODULE,
433 	.label = DRV_NAME,
434 
435 	.base = -1,
436 	.ngpio = 14,
437 	.direction_input = chip_direction_input,
438 	.direction_output = chip_direction_output,
439 	.get = chip_gpio_get,
440 	.set = chip_gpio_set,
441 
442 	.can_sleep = true,
443 };
444 
445 static int zl38_check_revision(struct device *dev, struct regmap *regmap)
446 {
447 	unsigned int hwrev, fwprod, fwrev;
448 	int fw_major, fw_minor, fw_micro;
449 	int err;
450 
451 	err = regmap_read(regmap, REG_HW_REV, &hwrev);
452 	if (err)
453 		return err;
454 	err = regmap_read(regmap, REG_FW_PROD, &fwprod);
455 	if (err)
456 		return err;
457 	err = regmap_read(regmap, REG_FW_REV, &fwrev);
458 	if (err)
459 		return err;
460 
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);
466 
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);
470 		return -EINVAL;
471 	}
472 
473 	return 0;
474 }
475 
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)
479 {
480 	struct spi_device *spi = context;
481 	const u8 *reg_buf8 = reg_buf;
482 	size_t len = 0;
483 	u8 offs, page;
484 	u8 txbuf[4];
485 
486 	if (reg_size != 2 || val_size > ZL38_MAX_RAW_XFER)
487 		return -EINVAL;
488 
489 	offs = reg_buf8[1] >> 1;
490 	page = reg_buf8[0];
491 
492 	if (page) {
493 		txbuf[len++] = 0xFE;
494 		txbuf[len++] = page == HBI_FIRMWARE_PAGE ? 0xFF : page - 1;
495 		txbuf[len++] = offs;
496 		txbuf[len++] = val_size / 2 - 1;
497 	} else {
498 		txbuf[len++] = offs | 0x80;
499 		txbuf[len++] = val_size / 2 - 1;
500 	}
501 
502 	return spi_write_then_read(spi, txbuf, len, val_buf, val_size);
503 }
504 
505 static int zl38_bus_write(void *context, const void *data, size_t count)
506 {
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;
511 	u8 offs, page;
512 
513 	if (count > (2 + ZL38_MAX_RAW_XFER) || count < 4)
514 		return -EINVAL;
515 	val_len = count - 2;
516 	offs = data8[1] >> 1;
517 	page = data8[0];
518 
519 	if (page) {
520 		buf[len++] = 0xFE;
521 		buf[len++] = page == HBI_FIRMWARE_PAGE ? 0xFF : page - 1;
522 		buf[len++] = offs;
523 		buf[len++] = (val_len / 2 - 1) | 0x80;
524 	} else {
525 		buf[len++] = offs | 0x80;
526 		buf[len++] = (val_len / 2 - 1) | 0x80;
527 	}
528 	memcpy(buf + len, data8 + 2, val_len);
529 	len += val_len;
530 
531 	return spi_write(spi, buf, len);
532 }
533 
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,
539 };
540 
541 static const struct regmap_config zl38_regmap_conf = {
542 	.reg_bits = 16,
543 	.val_bits = 16,
544 	.reg_stride = 2,
545 	.use_single_read = true,
546 	.use_single_write = true,
547 };
548 
549 static int zl38_spi_probe(struct spi_device *spi)
550 {
551 	struct device *dev = &spi->dev;
552 	struct zl38_codec_priv *priv;
553 	struct gpio_desc *reset_gpio;
554 	int err;
555 
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);
560 	if (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);
567 	}
568 
569 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
570 	if (!priv)
571 		return -ENOMEM;
572 
573 	priv->dev = dev;
574 	dev_set_drvdata(dev, priv);
575 	priv->regmap = devm_regmap_init(dev, &zl38_regmap_bus, spi,
576 					&zl38_regmap_conf);
577 	if (IS_ERR(priv->regmap))
578 		return PTR_ERR(priv->regmap);
579 
580 	err = zl38_load_firmware(dev, priv->regmap);
581 	if (err)
582 		return err;
583 
584 	err = zl38_check_revision(dev, priv->regmap);
585 	if (err)
586 		return err;
587 
588 	priv->gpio_chip = devm_kmemdup(dev, &template_chip,
589 				       sizeof(template_chip), GFP_KERNEL);
590 	if (!priv->gpio_chip)
591 		return -ENOMEM;
592 	priv->gpio_chip->parent = dev;
593 	err = devm_gpiochip_add_data(dev, priv->gpio_chip, priv->regmap);
594 	if (err)
595 		return err;
596 
597 	/* setup the cross-point switch for stereo bypass */
598 	err = regmap_multi_reg_write(priv->regmap, cp_config_stereo_bypass,
599 				     ARRAY_SIZE(cp_config_stereo_bypass));
600 	if (err)
601 		return err;
602 	/* setup for 12MHz crystal connected to the chip */
603 	err = regmap_update_bits(priv->regmap, REG_CLK_CFG, CLK_CFG_SOURCE_XTAL,
604 				 CLK_CFG_SOURCE_XTAL);
605 	if (err)
606 		return err;
607 
608 	return devm_snd_soc_register_component(dev, &zl38_component_dev,
609 					       &zl38_dai, 1);
610 }
611 
612 static const struct of_device_id zl38_dt_ids[] __maybe_unused = {
613 	{ .compatible = "mscc,zl38060", },
614 	{ /* sentinel */ }
615 };
616 MODULE_DEVICE_TABLE(of, zl38_dt_ids);
617 
618 static const struct spi_device_id zl38_spi_ids[] = {
619 	{ "zl38060", 0 },
620 	{ /* sentinel */ }
621 };
622 MODULE_DEVICE_TABLE(spi, zl38_spi_ids);
623 
624 static struct spi_driver zl38060_spi_driver = {
625 	.driver	= {
626 		.name = DRV_NAME,
627 		.of_match_table = of_match_ptr(zl38_dt_ids),
628 	},
629 	.probe = zl38_spi_probe,
630 	.id_table = zl38_spi_ids,
631 };
632 module_spi_driver(zl38060_spi_driver);
633 
634 MODULE_DESCRIPTION("ASoC ZL38060 driver");
635 MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
636 MODULE_LICENSE("GPL v2");
637