1/*
2 * cs35l32.c -- CS35L32 ALSA SoC audio driver
3 *
4 * Copyright 2014 CirrusLogic, Inc.
5 *
6 * Author: Brian Austin <brian.austin@cirrus.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/version.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/i2c.h>
21#include <linux/gpio.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/platform_device.h>
25#include <linux/regulator/consumer.h>
26#include <linux/gpio/consumer.h>
27#include <linux/of_device.h>
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/initval.h>
34#include <sound/tlv.h>
35#include <dt-bindings/sound/cs35l32.h>
36
37#include "cs35l32.h"
38
39#define CS35L32_NUM_SUPPLIES 2
40static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = {
41	"VA",
42	"VP",
43};
44
45struct  cs35l32_private {
46	struct regmap *regmap;
47	struct snd_soc_codec *codec;
48	struct regulator_bulk_data supplies[CS35L32_NUM_SUPPLIES];
49	struct cs35l32_platform_data pdata;
50	struct gpio_desc *reset_gpio;
51};
52
53static const struct reg_default cs35l32_reg_defaults[] = {
54
55	{ 0x06, 0x04 }, /* Power Ctl 1 */
56	{ 0x07, 0xE8 }, /* Power Ctl 2 */
57	{ 0x08, 0x40 }, /* Clock Ctl */
58	{ 0x09, 0x20 }, /* Low Battery Threshold */
59	{ 0x0A, 0x00 }, /* Voltage Monitor [RO] */
60	{ 0x0B, 0x40 }, /* Conv Peak Curr Protection CTL */
61	{ 0x0C, 0x07 }, /* IMON Scaling */
62	{ 0x0D, 0x03 }, /* Audio/LED Pwr Manager */
63	{ 0x0F, 0x20 }, /* Serial Port Control */
64	{ 0x10, 0x14 }, /* Class D Amp CTL */
65	{ 0x11, 0x00 }, /* Protection Release CTL */
66	{ 0x12, 0xFF }, /* Interrupt Mask 1 */
67	{ 0x13, 0xFF }, /* Interrupt Mask 2 */
68	{ 0x14, 0xFF }, /* Interrupt Mask 3 */
69	{ 0x19, 0x00 }, /* LED Flash Mode Current */
70	{ 0x1A, 0x00 }, /* LED Movie Mode Current */
71	{ 0x1B, 0x20 }, /* LED Flash Timer */
72	{ 0x1C, 0x00 }, /* LED Flash Inhibit Current */
73};
74
75static bool cs35l32_readable_register(struct device *dev, unsigned int reg)
76{
77	switch (reg) {
78	case CS35L32_DEVID_AB:
79	case CS35L32_DEVID_CD:
80	case CS35L32_DEVID_E:
81	case CS35L32_FAB_ID:
82	case CS35L32_REV_ID:
83	case CS35L32_PWRCTL1:
84	case CS35L32_PWRCTL2:
85	case CS35L32_CLK_CTL:
86	case CS35L32_BATT_THRESHOLD:
87	case CS35L32_VMON:
88	case CS35L32_BST_CPCP_CTL:
89	case CS35L32_IMON_SCALING:
90	case CS35L32_AUDIO_LED_MNGR:
91	case CS35L32_ADSP_CTL:
92	case CS35L32_CLASSD_CTL:
93	case CS35L32_PROTECT_CTL:
94	case CS35L32_INT_MASK_1:
95	case CS35L32_INT_MASK_2:
96	case CS35L32_INT_MASK_3:
97	case CS35L32_INT_STATUS_1:
98	case CS35L32_INT_STATUS_2:
99	case CS35L32_INT_STATUS_3:
100	case CS35L32_LED_STATUS:
101	case CS35L32_FLASH_MODE:
102	case CS35L32_MOVIE_MODE:
103	case CS35L32_FLASH_TIMER:
104	case CS35L32_FLASH_INHIBIT:
105		return true;
106	default:
107		return false;
108	}
109}
110
111static bool cs35l32_volatile_register(struct device *dev, unsigned int reg)
112{
113	switch (reg) {
114	case CS35L32_DEVID_AB:
115	case CS35L32_DEVID_CD:
116	case CS35L32_DEVID_E:
117	case CS35L32_FAB_ID:
118	case CS35L32_REV_ID:
119	case CS35L32_INT_STATUS_1:
120	case CS35L32_INT_STATUS_2:
121	case CS35L32_INT_STATUS_3:
122	case CS35L32_LED_STATUS:
123		return true;
124	default:
125		return false;
126	}
127}
128
129static bool cs35l32_precious_register(struct device *dev, unsigned int reg)
130{
131	switch (reg) {
132	case CS35L32_INT_STATUS_1:
133	case CS35L32_INT_STATUS_2:
134	case CS35L32_INT_STATUS_3:
135	case CS35L32_LED_STATUS:
136		return true;
137	default:
138		return false;
139	}
140}
141
142static DECLARE_TLV_DB_SCALE(classd_ctl_tlv, 900, 300, 0);
143
144static const struct snd_kcontrol_new imon_ctl =
145	SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 6, 1, 1);
146
147static const struct snd_kcontrol_new vmon_ctl =
148	SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 7, 1, 1);
149
150static const struct snd_kcontrol_new vpmon_ctl =
151	SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 5, 1, 1);
152
153static const struct snd_kcontrol_new cs35l32_snd_controls[] = {
154	SOC_SINGLE_TLV("Speaker Volume", CS35L32_CLASSD_CTL,
155		       3, 0x04, 1, classd_ctl_tlv),
156	SOC_SINGLE("Zero Cross Switch", CS35L32_CLASSD_CTL, 2, 1, 0),
157	SOC_SINGLE("Gain Manager Switch", CS35L32_AUDIO_LED_MNGR, 3, 1, 0),
158};
159
160static const struct snd_soc_dapm_widget cs35l32_dapm_widgets[] = {
161
162	SND_SOC_DAPM_SUPPLY("BOOST", CS35L32_PWRCTL1, 2, 1, NULL, 0),
163	SND_SOC_DAPM_OUT_DRV("Speaker", CS35L32_PWRCTL1, 7, 1, NULL, 0),
164
165	SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L32_PWRCTL2, 3, 1),
166
167	SND_SOC_DAPM_INPUT("VP"),
168	SND_SOC_DAPM_INPUT("ISENSE"),
169	SND_SOC_DAPM_INPUT("VSENSE"),
170
171	SND_SOC_DAPM_SWITCH("VMON ADC", CS35L32_PWRCTL2, 7, 1, &vmon_ctl),
172	SND_SOC_DAPM_SWITCH("IMON ADC", CS35L32_PWRCTL2, 6, 1, &imon_ctl),
173	SND_SOC_DAPM_SWITCH("VPMON ADC", CS35L32_PWRCTL2, 5, 1, &vpmon_ctl),
174};
175
176static const struct snd_soc_dapm_route cs35l32_audio_map[] = {
177
178	{"Speaker", NULL, "BOOST"},
179
180	{"VMON ADC", NULL, "VSENSE"},
181	{"IMON ADC", NULL, "ISENSE"},
182	{"VPMON ADC", NULL, "VP"},
183
184	{"SDOUT", "Switch", "VMON ADC"},
185	{"SDOUT",  "Switch", "IMON ADC"},
186	{"SDOUT", "Switch", "VPMON ADC"},
187
188	{"Capture", NULL, "SDOUT"},
189};
190
191static int cs35l32_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
192{
193	struct snd_soc_codec *codec = codec_dai->codec;
194
195	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
196	case SND_SOC_DAIFMT_CBM_CFM:
197		snd_soc_update_bits(codec, CS35L32_ADSP_CTL,
198				    CS35L32_ADSP_MASTER_MASK,
199				CS35L32_ADSP_MASTER_MASK);
200		break;
201	case SND_SOC_DAIFMT_CBS_CFS:
202		snd_soc_update_bits(codec, CS35L32_ADSP_CTL,
203				    CS35L32_ADSP_MASTER_MASK, 0);
204		break;
205	default:
206		return -EINVAL;
207	}
208
209	return 0;
210}
211
212static int cs35l32_set_tristate(struct snd_soc_dai *dai, int tristate)
213{
214	struct snd_soc_codec *codec = dai->codec;
215
216	return snd_soc_update_bits(codec, CS35L32_PWRCTL2,
217					CS35L32_SDOUT_3ST, tristate << 3);
218}
219
220static const struct snd_soc_dai_ops cs35l32_ops = {
221	.set_fmt = cs35l32_set_dai_fmt,
222	.set_tristate = cs35l32_set_tristate,
223};
224
225static struct snd_soc_dai_driver cs35l32_dai[] = {
226	{
227		.name = "cs35l32-monitor",
228		.id = 0,
229		.capture = {
230			.stream_name = "Capture",
231			.channels_min = 2,
232			.channels_max = 2,
233			.rates = CS35L32_RATES,
234			.formats = CS35L32_FORMATS,
235		},
236		.ops = &cs35l32_ops,
237		.symmetric_rates = 1,
238	}
239};
240
241static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec,
242			      int clk_id, int source, unsigned int freq, int dir)
243{
244	unsigned int val;
245
246	switch (freq) {
247	case 6000000:
248		val = CS35L32_MCLK_RATIO;
249		break;
250	case 12000000:
251		val = CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO;
252		break;
253	case 6144000:
254		val = 0;
255		break;
256	case 12288000:
257		val = CS35L32_MCLK_DIV2_MASK;
258		break;
259	default:
260		return -EINVAL;
261	}
262
263	return snd_soc_update_bits(codec, CS35L32_CLK_CTL,
264			CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val);
265}
266
267static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
268	.set_sysclk = cs35l32_codec_set_sysclk,
269
270	.dapm_widgets = cs35l32_dapm_widgets,
271	.num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets),
272	.dapm_routes = cs35l32_audio_map,
273	.num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map),
274
275	.controls = cs35l32_snd_controls,
276	.num_controls = ARRAY_SIZE(cs35l32_snd_controls),
277};
278
279/* Current and threshold powerup sequence Pg37 in datasheet */
280static const struct reg_default cs35l32_monitor_patch[] = {
281
282	{ 0x00, 0x99 },
283	{ 0x48, 0x17 },
284	{ 0x49, 0x56 },
285	{ 0x43, 0x01 },
286	{ 0x3B, 0x62 },
287	{ 0x3C, 0x80 },
288	{ 0x00, 0x00 },
289};
290
291static const struct regmap_config cs35l32_regmap = {
292	.reg_bits = 8,
293	.val_bits = 8,
294
295	.max_register = CS35L32_MAX_REGISTER,
296	.reg_defaults = cs35l32_reg_defaults,
297	.num_reg_defaults = ARRAY_SIZE(cs35l32_reg_defaults),
298	.volatile_reg = cs35l32_volatile_register,
299	.readable_reg = cs35l32_readable_register,
300	.precious_reg = cs35l32_precious_register,
301	.cache_type = REGCACHE_RBTREE,
302};
303
304static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
305				    struct cs35l32_platform_data *pdata)
306{
307	struct device_node *np = i2c_client->dev.of_node;
308	unsigned int val;
309
310	if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0)
311		pdata->sdout_share = val;
312
313	of_property_read_u32(np, "cirrus,boost-manager", &val);
314	switch (val) {
315	case CS35L32_BOOST_MGR_AUTO:
316	case CS35L32_BOOST_MGR_AUTO_AUDIO:
317	case CS35L32_BOOST_MGR_BYPASS:
318	case CS35L32_BOOST_MGR_FIXED:
319		pdata->boost_mng = val;
320		break;
321	default:
322		dev_err(&i2c_client->dev,
323			"Wrong cirrus,boost-manager DT value %d\n", val);
324		pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS;
325	}
326
327	of_property_read_u32(np, "cirrus,sdout-datacfg", &val);
328	switch (val) {
329	case CS35L32_DATA_CFG_LR_VP:
330	case CS35L32_DATA_CFG_LR_STAT:
331	case CS35L32_DATA_CFG_LR:
332	case CS35L32_DATA_CFG_LR_VPSTAT:
333		pdata->sdout_datacfg = val;
334		break;
335	default:
336		dev_err(&i2c_client->dev,
337			"Wrong cirrus,sdout-datacfg DT value %d\n", val);
338		pdata->sdout_datacfg = CS35L32_DATA_CFG_LR;
339	}
340
341	of_property_read_u32(np, "cirrus,battery-threshold", &val);
342	switch (val) {
343	case CS35L32_BATT_THRESH_3_1V:
344	case CS35L32_BATT_THRESH_3_2V:
345	case CS35L32_BATT_THRESH_3_3V:
346	case CS35L32_BATT_THRESH_3_4V:
347		pdata->batt_thresh = val;
348		break;
349	default:
350		dev_err(&i2c_client->dev,
351			"Wrong cirrus,battery-threshold DT value %d\n", val);
352		pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V;
353	}
354
355	of_property_read_u32(np, "cirrus,battery-recovery", &val);
356	switch (val) {
357	case CS35L32_BATT_RECOV_3_1V:
358	case CS35L32_BATT_RECOV_3_2V:
359	case CS35L32_BATT_RECOV_3_3V:
360	case CS35L32_BATT_RECOV_3_4V:
361	case CS35L32_BATT_RECOV_3_5V:
362	case CS35L32_BATT_RECOV_3_6V:
363		pdata->batt_recov = val;
364		break;
365	default:
366		dev_err(&i2c_client->dev,
367			"Wrong cirrus,battery-recovery DT value %d\n", val);
368		pdata->batt_recov = CS35L32_BATT_RECOV_3_4V;
369	}
370
371	return 0;
372}
373
374static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
375				       const struct i2c_device_id *id)
376{
377	struct cs35l32_private *cs35l32;
378	struct cs35l32_platform_data *pdata =
379		dev_get_platdata(&i2c_client->dev);
380	int ret, i;
381	unsigned int devid = 0;
382	unsigned int reg;
383
384
385	cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l32_private),
386			       GFP_KERNEL);
387	if (!cs35l32) {
388		dev_err(&i2c_client->dev, "could not allocate codec\n");
389		return -ENOMEM;
390	}
391
392	i2c_set_clientdata(i2c_client, cs35l32);
393
394	cs35l32->regmap = devm_regmap_init_i2c(i2c_client, &cs35l32_regmap);
395	if (IS_ERR(cs35l32->regmap)) {
396		ret = PTR_ERR(cs35l32->regmap);
397		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
398		return ret;
399	}
400
401	if (pdata) {
402		cs35l32->pdata = *pdata;
403	} else {
404		pdata = devm_kzalloc(&i2c_client->dev,
405				     sizeof(struct cs35l32_platform_data),
406				GFP_KERNEL);
407		if (!pdata) {
408			dev_err(&i2c_client->dev, "could not allocate pdata\n");
409			return -ENOMEM;
410		}
411		if (i2c_client->dev.of_node) {
412			ret = cs35l32_handle_of_data(i2c_client,
413						     &cs35l32->pdata);
414			if (ret != 0)
415				return ret;
416		}
417	}
418
419	for (i = 0; i < ARRAY_SIZE(cs35l32->supplies); i++)
420		cs35l32->supplies[i].supply = cs35l32_supply_names[i];
421
422	ret = devm_regulator_bulk_get(&i2c_client->dev,
423				      ARRAY_SIZE(cs35l32->supplies),
424				      cs35l32->supplies);
425	if (ret != 0) {
426		dev_err(&i2c_client->dev,
427			"Failed to request supplies: %d\n", ret);
428		return ret;
429	}
430
431	ret = regulator_bulk_enable(ARRAY_SIZE(cs35l32->supplies),
432				    cs35l32->supplies);
433	if (ret != 0) {
434		dev_err(&i2c_client->dev,
435			"Failed to enable supplies: %d\n", ret);
436		return ret;
437	}
438
439	/* Reset the Device */
440	cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
441		"reset", GPIOD_OUT_LOW);
442	if (IS_ERR(cs35l32->reset_gpio))
443		return PTR_ERR(cs35l32->reset_gpio);
444
445	if (cs35l32->reset_gpio)
446		gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
447
448	/* initialize codec */
449	ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg);
450	devid = (reg & 0xFF) << 12;
451
452	ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_CD, &reg);
453	devid |= (reg & 0xFF) << 4;
454
455	ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_E, &reg);
456	devid |= (reg & 0xF0) >> 4;
457
458	if (devid != CS35L32_CHIP_ID) {
459		ret = -ENODEV;
460		dev_err(&i2c_client->dev,
461			"CS35L32 Device ID (%X). Expected %X\n",
462			devid, CS35L32_CHIP_ID);
463		return ret;
464	}
465
466	ret = regmap_read(cs35l32->regmap, CS35L32_REV_ID, &reg);
467	if (ret < 0) {
468		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
469		return ret;
470	}
471
472	ret = regmap_register_patch(cs35l32->regmap, cs35l32_monitor_patch,
473				    ARRAY_SIZE(cs35l32_monitor_patch));
474	if (ret < 0) {
475		dev_err(&i2c_client->dev, "Failed to apply errata patch\n");
476		return ret;
477	}
478
479	dev_info(&i2c_client->dev,
480		 "Cirrus Logic CS35L32, Revision: %02X\n", reg & 0xFF);
481
482	/* Setup VBOOST Management */
483	if (cs35l32->pdata.boost_mng)
484		regmap_update_bits(cs35l32->regmap, CS35L32_AUDIO_LED_MNGR,
485				   CS35L32_BOOST_MASK,
486				cs35l32->pdata.boost_mng);
487
488	/* Setup ADSP Format Config */
489	if (cs35l32->pdata.sdout_share)
490		regmap_update_bits(cs35l32->regmap, CS35L32_ADSP_CTL,
491				    CS35L32_ADSP_SHARE_MASK,
492				cs35l32->pdata.sdout_share << 3);
493
494	/* Setup ADSP Data Configuration */
495	if (cs35l32->pdata.sdout_datacfg)
496		regmap_update_bits(cs35l32->regmap, CS35L32_ADSP_CTL,
497				   CS35L32_ADSP_DATACFG_MASK,
498				cs35l32->pdata.sdout_datacfg << 4);
499
500	/* Setup Low Battery Recovery  */
501	if (cs35l32->pdata.batt_recov)
502		regmap_update_bits(cs35l32->regmap, CS35L32_BATT_THRESHOLD,
503				   CS35L32_BATT_REC_MASK,
504				cs35l32->pdata.batt_recov << 1);
505
506	/* Setup Low Battery Threshold */
507	if (cs35l32->pdata.batt_thresh)
508		regmap_update_bits(cs35l32->regmap, CS35L32_BATT_THRESHOLD,
509				   CS35L32_BATT_THRESH_MASK,
510				cs35l32->pdata.batt_thresh << 4);
511
512	/* Power down the AMP */
513	regmap_update_bits(cs35l32->regmap, CS35L32_PWRCTL1, CS35L32_PDN_AMP,
514			    CS35L32_PDN_AMP);
515
516	/* Clear MCLK Error Bit since we don't have the clock yet */
517	ret = regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, &reg);
518
519	ret =  snd_soc_register_codec(&i2c_client->dev,
520			&soc_codec_dev_cs35l32, cs35l32_dai,
521			ARRAY_SIZE(cs35l32_dai));
522	if (ret < 0)
523		goto err_disable;
524
525	return 0;
526
527err_disable:
528	regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies),
529			       cs35l32->supplies);
530	return ret;
531}
532
533static int cs35l32_i2c_remove(struct i2c_client *i2c_client)
534{
535	struct cs35l32_private *cs35l32 = i2c_get_clientdata(i2c_client);
536
537	snd_soc_unregister_codec(&i2c_client->dev);
538
539	/* Hold down reset */
540	if (cs35l32->reset_gpio)
541		gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
542
543	return 0;
544}
545
546#ifdef CONFIG_PM
547static int cs35l32_runtime_suspend(struct device *dev)
548{
549	struct cs35l32_private *cs35l32 = dev_get_drvdata(dev);
550
551	regcache_cache_only(cs35l32->regmap, true);
552	regcache_mark_dirty(cs35l32->regmap);
553
554	/* Hold down reset */
555	if (cs35l32->reset_gpio)
556		gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
557
558	/* remove power */
559	regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies),
560			       cs35l32->supplies);
561
562	return 0;
563}
564
565static int cs35l32_runtime_resume(struct device *dev)
566{
567	struct cs35l32_private *cs35l32 = dev_get_drvdata(dev);
568	int ret;
569
570	/* Enable power */
571	ret = regulator_bulk_enable(ARRAY_SIZE(cs35l32->supplies),
572				    cs35l32->supplies);
573	if (ret != 0) {
574		dev_err(dev, "Failed to enable supplies: %d\n",
575			ret);
576		return ret;
577	}
578
579	if (cs35l32->reset_gpio)
580		gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
581
582	regcache_cache_only(cs35l32->regmap, false);
583	regcache_sync(cs35l32->regmap);
584
585	return 0;
586}
587#endif
588
589static const struct dev_pm_ops cs35l32_runtime_pm = {
590	SET_RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume,
591			   NULL)
592};
593
594static const struct of_device_id cs35l32_of_match[] = {
595	{ .compatible = "cirrus,cs35l32", },
596	{},
597};
598MODULE_DEVICE_TABLE(of, cs35l32_of_match);
599
600
601static const struct i2c_device_id cs35l32_id[] = {
602	{"cs35l32", 0},
603	{}
604};
605
606MODULE_DEVICE_TABLE(i2c, cs35l32_id);
607
608static struct i2c_driver cs35l32_i2c_driver = {
609	.driver = {
610		   .name = "cs35l32",
611		   .owner = THIS_MODULE,
612		   .pm = &cs35l32_runtime_pm,
613		   .of_match_table = cs35l32_of_match,
614		   },
615	.id_table = cs35l32_id,
616	.probe = cs35l32_i2c_probe,
617	.remove = cs35l32_i2c_remove,
618};
619
620module_i2c_driver(cs35l32_i2c_driver);
621
622MODULE_DESCRIPTION("ASoC CS35L32 driver");
623MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
624MODULE_LICENSE("GPL");
625