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