Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Support for CS42L83 on Apple machines

Merge series from Martin Povišer <povik+lin@cutebit.org>:

there's a CS42L83 headphone jack codec found in Apple computers (in the
recent 'Apple Silicon' ones as well as in earlier models, one example
[1]). The part isn't publicly documented, but it appears almost
identical to CS42L42, for which we have a driver in kernel. This series
adapts the CS42L42 driver to the new part, and makes one change in
anticipation of a machine driver for the Apple computers.

Patch 1 adds new compatible to the cs42l42 schema.

Patches 2 to 7 are taken from Richard's recent series [2] adding
soundwire support to cs42l42. They are useful refactorings to build on
in the later patches, and also this way our work doesn't diverge.
(I fixed missing free_irq path in cs42l42_init, did
s/Soundwire/SoundWire/ in changelogs, rebased.)

Patch 8 exports some regmap-related symbols from cs42l42.c so they can
be used to create cs42l83 regmap in cs42l83-i2c.c later.

Patch 9 is the cs42l83 support proper.

Patch 10 implements 'set_bclk_ratio' on the cs42l42 core. This will be
called by the upcoming ASoC machine driver for 'Apple Silicon' Macs.
(We have touched on this change to be made in earlier discussion, see
[3] and replies.)

Patch 11 brings cs42l42-i2c.c in sync with cs42l83-i2c.c on
dev_err_probe() usage.

+529 -126
+1
Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
··· 19 19 compatible: 20 20 enum: 21 21 - cirrus,cs42l42 22 + - cirrus,cs42l83 22 23 23 24 reg: 24 25 description:
+1
MAINTAINERS
··· 1913 1913 S: Maintained 1914 1914 F: Documentation/devicetree/bindings/sound/apple,* 1915 1915 F: sound/soc/apple/* 1916 + F: sound/soc/codecs/cs42l83-i2c.c 1916 1917 1917 1918 ARM/ARTPEC MACHINE SUPPORT 1918 1919 M: Jesper Nilsson <jesper.nilsson@axis.com>
+1
include/sound/cs42l42.h
··· 40 40 #define CS42L42_PAGE_30 0x3000 41 41 42 42 #define CS42L42_CHIP_ID 0x42A42 43 + #define CS42L83_CHIP_ID 0x42A83 43 44 44 45 /* Page 0x10 Global Registers */ 45 46 #define CS42L42_DEVID_AB (CS42L42_PAGE_10 + 0x01)
+14 -1
sound/soc/codecs/Kconfig
··· 692 692 Enable support for Cirrus Logic CS35L45 smart speaker amplifier 693 693 with I2C control. 694 694 695 + config SND_SOC_CS42L42_CORE 696 + tristate 697 + 695 698 config SND_SOC_CS42L42 696 - tristate "Cirrus Logic CS42L42 CODEC" 699 + tristate "Cirrus Logic CS42L42 CODEC (I2C)" 697 700 depends on I2C 701 + select REGMAP 702 + select REGMAP_I2C 703 + select SND_SOC_CS42L42_CORE 698 704 699 705 config SND_SOC_CS42L51 700 706 tristate ··· 721 715 config SND_SOC_CS42L73 722 716 tristate "Cirrus Logic CS42L73 CODEC" 723 717 depends on I2C 718 + 719 + config SND_SOC_CS42L83 720 + tristate "Cirrus Logic CS42L83 CODEC" 721 + depends on I2C 722 + select REGMAP 723 + select REGMAP_I2C 724 + select SND_SOC_CS42L42_CORE 724 725 725 726 config SND_SOC_CS4234 726 727 tristate "Cirrus Logic CS4234 CODEC"
+5 -1
sound/soc/codecs/Makefile
··· 65 65 snd-soc-cs35l45-spi-objs := cs35l45-spi.o 66 66 snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o 67 67 snd-soc-cs42l42-objs := cs42l42.o 68 + snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o 68 69 snd-soc-cs42l51-objs := cs42l51.o 69 70 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o 70 71 snd-soc-cs42l52-objs := cs42l52.o 71 72 snd-soc-cs42l56-objs := cs42l56.o 72 73 snd-soc-cs42l73-objs := cs42l73.o 74 + snd-soc-cs42l83-i2c-objs := cs42l83-i2c.o 73 75 snd-soc-cs4234-objs := cs4234.o 74 76 snd-soc-cs4265-objs := cs4265.o 75 77 snd-soc-cs4270-objs := cs4270.o ··· 424 422 obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o 425 423 obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o 426 424 obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o 427 - obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42.o 425 + obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o 426 + obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o 428 427 obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 429 428 obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o 430 429 obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o 431 430 obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o 432 431 obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o 432 + obj-$(CONFIG_SND_SOC_CS42L83) += snd-soc-cs42l83-i2c.o 433 433 obj-$(CONFIG_SND_SOC_CS4234) += snd-soc-cs4234.o 434 434 obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o 435 435 obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
+106
sound/soc/codecs/cs42l42-i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * cs42l42-i2c.c -- CS42L42 ALSA SoC audio driver for I2C 4 + * 5 + * Copyright 2016, 2022 Cirrus Logic, Inc. 6 + */ 7 + 8 + #include <linux/i2c.h> 9 + #include <linux/module.h> 10 + #include <linux/regmap.h> 11 + #include <linux/slab.h> 12 + #include <linux/types.h> 13 + 14 + #include "cs42l42.h" 15 + 16 + static int cs42l42_i2c_probe(struct i2c_client *i2c_client) 17 + { 18 + struct device *dev = &i2c_client->dev; 19 + struct cs42l42_private *cs42l42; 20 + struct regmap *regmap; 21 + int ret; 22 + 23 + cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL); 24 + if (!cs42l42) 25 + return -ENOMEM; 26 + 27 + regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap); 28 + if (IS_ERR(regmap)) 29 + return dev_err_probe(&i2c_client->dev, PTR_ERR(regmap), 30 + "regmap_init() failed\n"); 31 + 32 + cs42l42->devid = CS42L42_CHIP_ID; 33 + cs42l42->dev = dev; 34 + cs42l42->regmap = regmap; 35 + cs42l42->irq = i2c_client->irq; 36 + 37 + ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai); 38 + if (ret) 39 + return ret; 40 + 41 + return cs42l42_init(cs42l42); 42 + } 43 + 44 + static int cs42l42_i2c_remove(struct i2c_client *i2c_client) 45 + { 46 + struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev); 47 + 48 + cs42l42_common_remove(cs42l42); 49 + 50 + return 0; 51 + } 52 + 53 + static int __maybe_unused cs42l42_i2c_resume(struct device *dev) 54 + { 55 + int ret; 56 + 57 + ret = cs42l42_resume(dev); 58 + if (ret) 59 + return ret; 60 + 61 + cs42l42_resume_restore(dev); 62 + 63 + return 0; 64 + } 65 + 66 + static const struct dev_pm_ops cs42l42_i2c_pm_ops = { 67 + SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume) 68 + }; 69 + 70 + static const struct of_device_id __maybe_unused cs42l42_of_match[] = { 71 + { .compatible = "cirrus,cs42l42", }, 72 + {} 73 + }; 74 + MODULE_DEVICE_TABLE(of, cs42l42_of_match); 75 + 76 + static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = { 77 + {"10134242", 0,}, 78 + {} 79 + }; 80 + MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match); 81 + 82 + static const struct i2c_device_id cs42l42_id[] = { 83 + {"cs42l42", 0}, 84 + {} 85 + }; 86 + 87 + MODULE_DEVICE_TABLE(i2c, cs42l42_id); 88 + 89 + static struct i2c_driver cs42l42_i2c_driver = { 90 + .driver = { 91 + .name = "cs42l42", 92 + .pm = &cs42l42_i2c_pm_ops, 93 + .of_match_table = of_match_ptr(cs42l42_of_match), 94 + .acpi_match_table = ACPI_PTR(cs42l42_acpi_match), 95 + }, 96 + .id_table = cs42l42_id, 97 + .probe_new = cs42l42_i2c_probe, 98 + .remove = cs42l42_i2c_remove, 99 + }; 100 + 101 + module_i2c_driver(cs42l42_i2c_driver); 102 + 103 + MODULE_DESCRIPTION("ASoC CS42L42 I2C driver"); 104 + MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 105 + MODULE_LICENSE("GPL"); 106 + MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
+136 -123
sound/soc/codecs/cs42l42.c
··· 15 15 #include <linux/types.h> 16 16 #include <linux/init.h> 17 17 #include <linux/delay.h> 18 - #include <linux/i2c.h> 19 18 #include <linux/gpio.h> 20 19 #include <linux/regmap.h> 21 20 #include <linux/slab.h> ··· 171 172 { CS42L42_ASP_RX_DAI1_CH2_BIT_LSB, 0x00 }, 172 173 }; 173 174 174 - static bool cs42l42_readable_register(struct device *dev, unsigned int reg) 175 + bool cs42l42_readable_register(struct device *dev, unsigned int reg) 175 176 { 176 177 switch (reg) { 177 178 case CS42L42_PAGE_REGISTER: ··· 330 331 return false; 331 332 } 332 333 } 334 + EXPORT_SYMBOL_NS_GPL(cs42l42_readable_register, SND_SOC_CS42L42_CORE); 333 335 334 - static bool cs42l42_volatile_register(struct device *dev, unsigned int reg) 336 + bool cs42l42_volatile_register(struct device *dev, unsigned int reg) 335 337 { 336 338 switch (reg) { 337 339 case CS42L42_DEVID_AB: ··· 363 363 return false; 364 364 } 365 365 } 366 + EXPORT_SYMBOL_NS_GPL(cs42l42_volatile_register, SND_SOC_CS42L42_CORE); 366 367 367 - static const struct regmap_range_cfg cs42l42_page_range = { 368 + const struct regmap_range_cfg cs42l42_page_range = { 368 369 .name = "Pages", 369 370 .range_min = 0, 370 371 .range_max = CS42L42_MAX_REGISTER, ··· 375 374 .window_start = 0, 376 375 .window_len = 256, 377 376 }; 377 + EXPORT_SYMBOL_NS_GPL(cs42l42_page_range, SND_SOC_CS42L42_CORE); 378 378 379 - static const struct regmap_config cs42l42_regmap = { 379 + const struct regmap_config cs42l42_regmap = { 380 380 .reg_bits = 8, 381 381 .val_bits = 8, 382 382 ··· 395 393 .use_single_read = true, 396 394 .use_single_write = true, 397 395 }; 396 + EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, SND_SOC_CS42L42_CORE); 398 397 399 398 static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true); 400 399 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true); ··· 582 579 return 0; 583 580 } 584 581 585 - static const struct snd_soc_component_driver soc_component_dev_cs42l42 = { 582 + const struct snd_soc_component_driver cs42l42_soc_component = { 586 583 .set_jack = cs42l42_set_jack, 587 584 .dapm_widgets = cs42l42_dapm_widgets, 588 585 .num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets), ··· 593 590 .idle_bias_on = 1, 594 591 .endianness = 1, 595 592 }; 593 + EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE); 596 594 597 595 /* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */ 598 596 static const struct reg_sequence cs42l42_to_sclk_seq[] = { ··· 651 647 { 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1} 652 648 }; 653 649 654 - static int cs42l42_pll_config(struct snd_soc_component *component) 650 + static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk) 655 651 { 656 652 struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); 657 653 int i; 658 - u32 clk; 659 654 u32 fsync; 660 - 661 - if (!cs42l42->sclk) 662 - clk = cs42l42->bclk; 663 - else 664 - clk = cs42l42->sclk; 665 655 666 656 /* Don't reconfigure if there is an audio stream running */ 667 657 if (cs42l42->stream_use) { ··· 893 895 unsigned int width = (params_width(params) / 8) - 1; 894 896 unsigned int slot_width = 0; 895 897 unsigned int val = 0; 898 + unsigned int bclk; 896 899 int ret; 897 900 898 901 cs42l42->srate = params_rate(params); 899 902 900 - /* 901 - * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being 902 - * more than assumed (which would result in overclocking). 903 - */ 904 - if (params_width(params) == 24) 905 - slot_width = 32; 903 + if (cs42l42->bclk_ratio) { 904 + /* machine driver has set the BCLK/samp-rate ratio */ 905 + bclk = cs42l42->bclk_ratio * params_rate(params); 906 + } else if (cs42l42->sclk) { 907 + /* machine driver has set the SCLK */ 908 + bclk = cs42l42->sclk; 909 + } else { 910 + /* 911 + * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being 912 + * more than assumed (which would result in overclocking). 913 + */ 914 + if (params_width(params) == 24) 915 + slot_width = 32; 906 916 907 - /* I2S frame always has multiple of 2 channels */ 908 - cs42l42->bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2); 917 + /* I2S frame always has multiple of 2 channels */ 918 + bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2); 919 + } 909 920 910 921 switch (substream->stream) { 911 922 case SNDRV_PCM_STREAM_CAPTURE: ··· 954 947 break; 955 948 } 956 949 957 - ret = cs42l42_pll_config(component); 950 + ret = cs42l42_pll_config(component, bclk); 958 951 if (ret) 959 952 return ret; 960 953 ··· 985 978 dev_err(component->dev, "SCLK %u not supported\n", freq); 986 979 987 980 return -EINVAL; 981 + } 982 + 983 + static int cs42l42_set_bclk_ratio(struct snd_soc_dai *dai, 984 + unsigned int bclk_ratio) 985 + { 986 + struct snd_soc_component *component = dai->component; 987 + struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); 988 + 989 + cs42l42->bclk_ratio = bclk_ratio; 990 + 991 + return 0; 988 992 } 989 993 990 994 static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ··· 1101 1083 .hw_params = cs42l42_pcm_hw_params, 1102 1084 .set_fmt = cs42l42_set_dai_fmt, 1103 1085 .set_sysclk = cs42l42_set_sysclk, 1086 + .set_bclk_ratio = cs42l42_set_bclk_ratio, 1104 1087 .mute_stream = cs42l42_mute_stream, 1105 1088 }; 1106 1089 1107 - static struct snd_soc_dai_driver cs42l42_dai = { 1090 + struct snd_soc_dai_driver cs42l42_dai = { 1108 1091 .name = "cs42l42", 1109 1092 .playback = { 1110 1093 .stream_name = "Playback", ··· 1125 1106 .symmetric_sample_bits = 1, 1126 1107 .ops = &cs42l42_ops, 1127 1108 }; 1109 + EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE); 1128 1110 1129 1111 static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42) 1130 1112 { ··· 1646 1626 unsigned int i; 1647 1627 1648 1628 mutex_lock(&cs42l42->irq_lock); 1649 - if (cs42l42->suspended) { 1629 + if (cs42l42->suspended || !cs42l42->init_done) { 1650 1630 mutex_unlock(&cs42l42->irq_lock); 1651 1631 return IRQ_NONE; 1652 1632 } ··· 2121 2101 REG_SEQ0(CS42L42_PWR_CTL1, 0xFF) 2122 2102 }; 2123 2103 2124 - static int __maybe_unused cs42l42_suspend(struct device *dev) 2104 + int cs42l42_suspend(struct device *dev) 2125 2105 { 2126 2106 struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); 2127 2107 unsigned int reg; ··· 2181 2161 return 0; 2182 2162 2183 2163 } 2164 + EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, SND_SOC_CS42L42_CORE); 2184 2165 2185 - static int __maybe_unused cs42l42_resume(struct device *dev) 2166 + int cs42l42_resume(struct device *dev) 2186 2167 { 2187 2168 struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); 2188 2169 int ret; ··· 2205 2184 gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); 2206 2185 usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); 2207 2186 2187 + dev_dbg(dev, "System resume powered up\n"); 2188 + 2189 + return 0; 2190 + } 2191 + EXPORT_SYMBOL_NS_GPL(cs42l42_resume, SND_SOC_CS42L42_CORE); 2192 + 2193 + void cs42l42_resume_restore(struct device *dev) 2194 + { 2195 + struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); 2196 + 2208 2197 regcache_cache_only(cs42l42->regmap, false); 2209 2198 regcache_mark_dirty(cs42l42->regmap); 2210 2199 ··· 2227 2196 mutex_unlock(&cs42l42->irq_lock); 2228 2197 2229 2198 dev_dbg(dev, "System resumed\n"); 2199 + } 2200 + EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, SND_SOC_CS42L42_CORE); 2201 + 2202 + static int __maybe_unused cs42l42_i2c_resume(struct device *dev) 2203 + { 2204 + int ret; 2205 + 2206 + ret = cs42l42_resume(dev); 2207 + if (ret) 2208 + return ret; 2209 + 2210 + cs42l42_resume_restore(dev); 2230 2211 2231 2212 return 0; 2232 2213 } 2233 2214 2234 - static int cs42l42_i2c_probe(struct i2c_client *i2c_client) 2215 + int cs42l42_common_probe(struct cs42l42_private *cs42l42, 2216 + const struct snd_soc_component_driver *component_drv, 2217 + struct snd_soc_dai_driver *dai) 2235 2218 { 2236 - struct cs42l42_private *cs42l42; 2237 - int ret, i, devid; 2238 - unsigned int reg; 2219 + int ret, i; 2239 2220 2240 - cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private), 2241 - GFP_KERNEL); 2242 - if (!cs42l42) 2243 - return -ENOMEM; 2244 - 2245 - cs42l42->dev = &i2c_client->dev; 2246 - i2c_set_clientdata(i2c_client, cs42l42); 2221 + dev_set_drvdata(cs42l42->dev, cs42l42); 2247 2222 mutex_init(&cs42l42->irq_lock); 2248 - 2249 - cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap); 2250 - if (IS_ERR(cs42l42->regmap)) { 2251 - ret = PTR_ERR(cs42l42->regmap); 2252 - dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 2253 - return ret; 2254 - } 2255 2223 2256 2224 BUILD_BUG_ON(ARRAY_SIZE(cs42l42_supply_names) != ARRAY_SIZE(cs42l42->supplies)); 2257 2225 for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++) 2258 2226 cs42l42->supplies[i].supply = cs42l42_supply_names[i]; 2259 2227 2260 - ret = devm_regulator_bulk_get(&i2c_client->dev, 2228 + ret = devm_regulator_bulk_get(cs42l42->dev, 2261 2229 ARRAY_SIZE(cs42l42->supplies), 2262 2230 cs42l42->supplies); 2263 2231 if (ret != 0) { 2264 - dev_err(&i2c_client->dev, 2232 + dev_err(cs42l42->dev, 2265 2233 "Failed to request supplies: %d\n", ret); 2266 2234 return ret; 2267 2235 } ··· 2268 2238 ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies), 2269 2239 cs42l42->supplies); 2270 2240 if (ret != 0) { 2271 - dev_err(&i2c_client->dev, 2241 + dev_err(cs42l42->dev, 2272 2242 "Failed to enable supplies: %d\n", ret); 2273 2243 return ret; 2274 2244 } 2275 2245 2276 2246 /* Reset the Device */ 2277 - cs42l42->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, 2247 + cs42l42->reset_gpio = devm_gpiod_get_optional(cs42l42->dev, 2278 2248 "reset", GPIOD_OUT_LOW); 2279 2249 if (IS_ERR(cs42l42->reset_gpio)) { 2280 2250 ret = PTR_ERR(cs42l42->reset_gpio); ··· 2282 2252 } 2283 2253 2284 2254 if (cs42l42->reset_gpio) { 2285 - dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); 2255 + dev_dbg(cs42l42->dev, "Found reset GPIO\n"); 2286 2256 gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); 2287 2257 } 2288 2258 usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); 2289 2259 2290 2260 /* Request IRQ if one was specified */ 2291 - if (i2c_client->irq) { 2292 - ret = request_threaded_irq(i2c_client->irq, 2261 + if (cs42l42->irq) { 2262 + ret = request_threaded_irq(cs42l42->irq, 2293 2263 NULL, cs42l42_irq_thread, 2294 2264 IRQF_ONESHOT | IRQF_TRIGGER_LOW, 2295 2265 "cs42l42", cs42l42); 2296 2266 if (ret) { 2297 - dev_err_probe(&i2c_client->dev, ret, 2298 - "Failed to request IRQ\n"); 2267 + dev_err_probe(cs42l42->dev, ret, 2268 + "Failed to request IRQ\n"); 2299 2269 goto err_disable_noirq; 2300 2270 } 2301 2271 } 2272 + 2273 + /* Register codec now so it can EPROBE_DEFER */ 2274 + ret = devm_snd_soc_register_component(cs42l42->dev, component_drv, dai, 1); 2275 + if (ret < 0) 2276 + goto err; 2277 + 2278 + return 0; 2279 + 2280 + err: 2281 + if (cs42l42->irq) 2282 + free_irq(cs42l42->irq, cs42l42); 2283 + 2284 + err_disable_noirq: 2285 + gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); 2286 + err_disable_noreset: 2287 + regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies); 2288 + 2289 + return ret; 2290 + } 2291 + EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, SND_SOC_CS42L42_CORE); 2292 + 2293 + int cs42l42_init(struct cs42l42_private *cs42l42) 2294 + { 2295 + unsigned int reg; 2296 + int devid, ret; 2302 2297 2303 2298 /* initialize codec */ 2304 2299 devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB); 2305 2300 if (devid < 0) { 2306 2301 ret = devid; 2307 - dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret); 2302 + dev_err(cs42l42->dev, "Failed to read device ID: %d\n", ret); 2308 2303 goto err_disable; 2309 2304 } 2310 2305 2311 - if (devid != CS42L42_CHIP_ID) { 2306 + if (devid != cs42l42->devid) { 2312 2307 ret = -ENODEV; 2313 - dev_err(&i2c_client->dev, 2314 - "CS42L42 Device ID (%X). Expected %X\n", 2315 - devid, CS42L42_CHIP_ID); 2308 + dev_err(cs42l42->dev, 2309 + "CS42L%x Device ID (%X). Expected %X\n", 2310 + cs42l42->devid & 0xff, devid, cs42l42->devid); 2316 2311 goto err_disable; 2317 2312 } 2318 2313 2319 2314 ret = regmap_read(cs42l42->regmap, CS42L42_REVID, &reg); 2320 2315 if (ret < 0) { 2321 - dev_err(&i2c_client->dev, "Get Revision ID failed\n"); 2316 + dev_err(cs42l42->dev, "Get Revision ID failed\n"); 2322 2317 goto err_shutdown; 2323 2318 } 2324 2319 2325 - dev_info(&i2c_client->dev, 2326 - "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF); 2320 + dev_info(cs42l42->dev, 2321 + "Cirrus Logic CS42L%x, Revision: %02X\n", 2322 + cs42l42->devid & 0xff, reg & 0xFF); 2327 2323 2328 2324 /* Power up the codec */ 2329 2325 regmap_update_bits(cs42l42->regmap, CS42L42_PWR_CTL1, ··· 2368 2312 (1 << CS42L42_ADC_PDN_SHIFT) | 2369 2313 (0 << CS42L42_PDN_ALL_SHIFT)); 2370 2314 2371 - ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42); 2315 + ret = cs42l42_handle_device_data(cs42l42->dev, cs42l42); 2372 2316 if (ret != 0) 2373 2317 goto err_shutdown; 2374 2318 2375 2319 /* Setup headset detection */ 2376 2320 cs42l42_setup_hs_type_detect(cs42l42); 2377 2321 2322 + /* 2323 + * Set init_done before unmasking interrupts so any triggered 2324 + * immediately will be handled. 2325 + */ 2326 + cs42l42->init_done = true; 2327 + 2378 2328 /* Mask/Unmask Interrupts */ 2379 2329 cs42l42_set_interrupt_masks(cs42l42); 2380 - 2381 - /* Register codec for machine driver */ 2382 - ret = devm_snd_soc_register_component(&i2c_client->dev, 2383 - &soc_component_dev_cs42l42, &cs42l42_dai, 1); 2384 - if (ret < 0) 2385 - goto err_shutdown; 2386 2330 2387 2331 return 0; 2388 2332 ··· 2392 2336 regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff); 2393 2337 2394 2338 err_disable: 2395 - if (i2c_client->irq) 2396 - free_irq(i2c_client->irq, cs42l42); 2339 + if (cs42l42->irq) 2340 + free_irq(cs42l42->irq, cs42l42); 2397 2341 2398 - err_disable_noirq: 2399 2342 gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); 2400 - err_disable_noreset: 2401 2343 regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), 2402 2344 cs42l42->supplies); 2403 2345 return ret; 2404 2346 } 2347 + EXPORT_SYMBOL_NS_GPL(cs42l42_init, SND_SOC_CS42L42_CORE); 2405 2348 2406 - static int cs42l42_i2c_remove(struct i2c_client *i2c_client) 2349 + void cs42l42_common_remove(struct cs42l42_private *cs42l42) 2407 2350 { 2408 - struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client); 2409 - 2410 - if (i2c_client->irq) 2411 - free_irq(i2c_client->irq, cs42l42); 2351 + if (cs42l42->irq) 2352 + free_irq(cs42l42->irq, cs42l42); 2412 2353 2413 2354 /* 2414 2355 * The driver might not have control of reset and power supplies, 2415 2356 * so ensure that the chip internals are powered down. 2416 2357 */ 2417 - regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff); 2418 - regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff); 2419 - regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff); 2358 + if (cs42l42->init_done) { 2359 + regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff); 2360 + regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff); 2361 + regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff); 2362 + } 2420 2363 2421 2364 gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); 2422 2365 regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies); 2423 - 2424 - return 0; 2425 2366 } 2426 - 2427 - static const struct dev_pm_ops cs42l42_pm_ops = { 2428 - SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_resume) 2429 - }; 2430 - 2431 - #ifdef CONFIG_OF 2432 - static const struct of_device_id cs42l42_of_match[] = { 2433 - { .compatible = "cirrus,cs42l42", }, 2434 - {} 2435 - }; 2436 - MODULE_DEVICE_TABLE(of, cs42l42_of_match); 2437 - #endif 2438 - 2439 - #ifdef CONFIG_ACPI 2440 - static const struct acpi_device_id cs42l42_acpi_match[] = { 2441 - {"10134242", 0,}, 2442 - {} 2443 - }; 2444 - MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match); 2445 - #endif 2446 - 2447 - static const struct i2c_device_id cs42l42_id[] = { 2448 - {"cs42l42", 0}, 2449 - {} 2450 - }; 2451 - 2452 - MODULE_DEVICE_TABLE(i2c, cs42l42_id); 2453 - 2454 - static struct i2c_driver cs42l42_i2c_driver = { 2455 - .driver = { 2456 - .name = "cs42l42", 2457 - .pm = &cs42l42_pm_ops, 2458 - .of_match_table = of_match_ptr(cs42l42_of_match), 2459 - .acpi_match_table = ACPI_PTR(cs42l42_acpi_match), 2460 - }, 2461 - .id_table = cs42l42_id, 2462 - .probe_new = cs42l42_i2c_probe, 2463 - .remove = cs42l42_i2c_remove, 2464 - }; 2465 - 2466 - module_i2c_driver(cs42l42_i2c_driver); 2367 + EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE); 2467 2368 2468 2369 MODULE_DESCRIPTION("ASoC CS42L42 driver"); 2469 2370 MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
+23 -1
sound/soc/codecs/cs42l42.h
··· 20 20 #include <linux/regulator/consumer.h> 21 21 #include <sound/jack.h> 22 22 #include <sound/cs42l42.h> 23 + #include <sound/soc-component.h> 24 + #include <sound/soc-dai.h> 23 25 24 26 struct cs42l42_private { 25 27 struct regmap *regmap; ··· 31 29 struct completion pdn_done; 32 30 struct snd_soc_jack *jack; 33 31 struct mutex irq_lock; 32 + int devid; 33 + int irq; 34 34 int pll_config; 35 - int bclk; 36 35 u32 sclk; 36 + u32 bclk_ratio; 37 37 u32 srate; 38 38 u8 plug_state; 39 39 u8 hs_type; ··· 51 47 u8 stream_use; 52 48 bool hp_adc_up_pending; 53 49 bool suspended; 50 + bool init_done; 54 51 }; 52 + 53 + extern const struct regmap_range_cfg cs42l42_page_range; 54 + extern const struct regmap_config cs42l42_regmap; 55 + extern const struct snd_soc_component_driver cs42l42_soc_component; 56 + extern struct snd_soc_dai_driver cs42l42_dai; 57 + 58 + bool cs42l42_readable_register(struct device *dev, unsigned int reg); 59 + bool cs42l42_volatile_register(struct device *dev, unsigned int reg); 60 + 61 + int cs42l42_suspend(struct device *dev); 62 + int cs42l42_resume(struct device *dev); 63 + void cs42l42_resume_restore(struct device *dev); 64 + int cs42l42_common_probe(struct cs42l42_private *cs42l42, 65 + const struct snd_soc_component_driver *component_drv, 66 + struct snd_soc_dai_driver *dai); 67 + int cs42l42_init(struct cs42l42_private *cs42l42); 68 + void cs42l42_common_remove(struct cs42l42_private *cs42l42); 55 69 56 70 #endif /* __CS42L42_H__ */
+242
sound/soc/codecs/cs42l83-i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * cs42l83-i2c.c -- CS42L83 ALSA SoC audio driver for I2C 4 + * 5 + * Based on cs42l42-i2c.c: 6 + * Copyright 2016, 2022 Cirrus Logic, Inc. 7 + */ 8 + 9 + #include <linux/i2c.h> 10 + #include <linux/module.h> 11 + #include <linux/regmap.h> 12 + #include <linux/slab.h> 13 + #include <linux/types.h> 14 + 15 + #include "cs42l42.h" 16 + 17 + static const struct reg_default cs42l83_reg_defaults[] = { 18 + { CS42L42_FRZ_CTL, 0x00 }, 19 + { CS42L42_SRC_CTL, 0x10 }, 20 + { CS42L42_MCLK_CTL, 0x00 }, /* <- only deviation from CS42L42 */ 21 + { CS42L42_SFTRAMP_RATE, 0xA4 }, 22 + { CS42L42_SLOW_START_ENABLE, 0x70 }, 23 + { CS42L42_I2C_DEBOUNCE, 0x88 }, 24 + { CS42L42_I2C_STRETCH, 0x03 }, 25 + { CS42L42_I2C_TIMEOUT, 0xB7 }, 26 + { CS42L42_PWR_CTL1, 0xFF }, 27 + { CS42L42_PWR_CTL2, 0x84 }, 28 + { CS42L42_PWR_CTL3, 0x20 }, 29 + { CS42L42_RSENSE_CTL1, 0x40 }, 30 + { CS42L42_RSENSE_CTL2, 0x00 }, 31 + { CS42L42_OSC_SWITCH, 0x00 }, 32 + { CS42L42_RSENSE_CTL3, 0x1B }, 33 + { CS42L42_TSENSE_CTL, 0x1B }, 34 + { CS42L42_TSRS_INT_DISABLE, 0x00 }, 35 + { CS42L42_HSDET_CTL1, 0x77 }, 36 + { CS42L42_HSDET_CTL2, 0x00 }, 37 + { CS42L42_HS_SWITCH_CTL, 0xF3 }, 38 + { CS42L42_HS_CLAMP_DISABLE, 0x00 }, 39 + { CS42L42_MCLK_SRC_SEL, 0x00 }, 40 + { CS42L42_SPDIF_CLK_CFG, 0x00 }, 41 + { CS42L42_FSYNC_PW_LOWER, 0x00 }, 42 + { CS42L42_FSYNC_PW_UPPER, 0x00 }, 43 + { CS42L42_FSYNC_P_LOWER, 0xF9 }, 44 + { CS42L42_FSYNC_P_UPPER, 0x00 }, 45 + { CS42L42_ASP_CLK_CFG, 0x00 }, 46 + { CS42L42_ASP_FRM_CFG, 0x10 }, 47 + { CS42L42_FS_RATE_EN, 0x00 }, 48 + { CS42L42_IN_ASRC_CLK, 0x00 }, 49 + { CS42L42_OUT_ASRC_CLK, 0x00 }, 50 + { CS42L42_PLL_DIV_CFG1, 0x00 }, 51 + { CS42L42_ADC_OVFL_INT_MASK, 0x01 }, 52 + { CS42L42_MIXER_INT_MASK, 0x0F }, 53 + { CS42L42_SRC_INT_MASK, 0x0F }, 54 + { CS42L42_ASP_RX_INT_MASK, 0x1F }, 55 + { CS42L42_ASP_TX_INT_MASK, 0x0F }, 56 + { CS42L42_CODEC_INT_MASK, 0x03 }, 57 + { CS42L42_SRCPL_INT_MASK, 0x7F }, 58 + { CS42L42_VPMON_INT_MASK, 0x01 }, 59 + { CS42L42_PLL_LOCK_INT_MASK, 0x01 }, 60 + { CS42L42_TSRS_PLUG_INT_MASK, 0x0F }, 61 + { CS42L42_PLL_CTL1, 0x00 }, 62 + { CS42L42_PLL_DIV_FRAC0, 0x00 }, 63 + { CS42L42_PLL_DIV_FRAC1, 0x00 }, 64 + { CS42L42_PLL_DIV_FRAC2, 0x00 }, 65 + { CS42L42_PLL_DIV_INT, 0x40 }, 66 + { CS42L42_PLL_CTL3, 0x10 }, 67 + { CS42L42_PLL_CAL_RATIO, 0x80 }, 68 + { CS42L42_PLL_CTL4, 0x03 }, 69 + { CS42L42_LOAD_DET_EN, 0x00 }, 70 + { CS42L42_HSBIAS_SC_AUTOCTL, 0x03 }, 71 + { CS42L42_WAKE_CTL, 0xC0 }, 72 + { CS42L42_ADC_DISABLE_MUTE, 0x00 }, 73 + { CS42L42_TIPSENSE_CTL, 0x02 }, 74 + { CS42L42_MISC_DET_CTL, 0x03 }, 75 + { CS42L42_MIC_DET_CTL1, 0x1F }, 76 + { CS42L42_MIC_DET_CTL2, 0x2F }, 77 + { CS42L42_DET_INT1_MASK, 0xE0 }, 78 + { CS42L42_DET_INT2_MASK, 0xFF }, 79 + { CS42L42_HS_BIAS_CTL, 0xC2 }, 80 + { CS42L42_ADC_CTL, 0x00 }, 81 + { CS42L42_ADC_VOLUME, 0x00 }, 82 + { CS42L42_ADC_WNF_HPF_CTL, 0x71 }, 83 + { CS42L42_DAC_CTL1, 0x00 }, 84 + { CS42L42_DAC_CTL2, 0x02 }, 85 + { CS42L42_HP_CTL, 0x0D }, 86 + { CS42L42_CLASSH_CTL, 0x07 }, 87 + { CS42L42_MIXER_CHA_VOL, 0x3F }, 88 + { CS42L42_MIXER_ADC_VOL, 0x3F }, 89 + { CS42L42_MIXER_CHB_VOL, 0x3F }, 90 + { CS42L42_EQ_COEF_IN0, 0x00 }, 91 + { CS42L42_EQ_COEF_IN1, 0x00 }, 92 + { CS42L42_EQ_COEF_IN2, 0x00 }, 93 + { CS42L42_EQ_COEF_IN3, 0x00 }, 94 + { CS42L42_EQ_COEF_RW, 0x00 }, 95 + { CS42L42_EQ_COEF_OUT0, 0x00 }, 96 + { CS42L42_EQ_COEF_OUT1, 0x00 }, 97 + { CS42L42_EQ_COEF_OUT2, 0x00 }, 98 + { CS42L42_EQ_COEF_OUT3, 0x00 }, 99 + { CS42L42_EQ_INIT_STAT, 0x00 }, 100 + { CS42L42_EQ_START_FILT, 0x00 }, 101 + { CS42L42_EQ_MUTE_CTL, 0x00 }, 102 + { CS42L42_SP_RX_CH_SEL, 0x04 }, 103 + { CS42L42_SP_RX_ISOC_CTL, 0x04 }, 104 + { CS42L42_SP_RX_FS, 0x8C }, 105 + { CS42l42_SPDIF_CH_SEL, 0x0E }, 106 + { CS42L42_SP_TX_ISOC_CTL, 0x04 }, 107 + { CS42L42_SP_TX_FS, 0xCC }, 108 + { CS42L42_SPDIF_SW_CTL1, 0x3F }, 109 + { CS42L42_SRC_SDIN_FS, 0x40 }, 110 + { CS42L42_SRC_SDOUT_FS, 0x40 }, 111 + { CS42L42_SPDIF_CTL1, 0x01 }, 112 + { CS42L42_SPDIF_CTL2, 0x00 }, 113 + { CS42L42_SPDIF_CTL3, 0x00 }, 114 + { CS42L42_SPDIF_CTL4, 0x42 }, 115 + { CS42L42_ASP_TX_SZ_EN, 0x00 }, 116 + { CS42L42_ASP_TX_CH_EN, 0x00 }, 117 + { CS42L42_ASP_TX_CH_AP_RES, 0x0F }, 118 + { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 }, 119 + { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 }, 120 + { CS42L42_ASP_TX_HIZ_DLY_CFG, 0x00 }, 121 + { CS42L42_ASP_TX_CH2_BIT_MSB, 0x00 }, 122 + { CS42L42_ASP_TX_CH2_BIT_LSB, 0x00 }, 123 + { CS42L42_ASP_RX_DAI0_EN, 0x00 }, 124 + { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x03 }, 125 + { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 }, 126 + { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 }, 127 + { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x03 }, 128 + { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 }, 129 + { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x00 }, 130 + { CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x03 }, 131 + { CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 }, 132 + { CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x00 }, 133 + { CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x03 }, 134 + { CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 }, 135 + { CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0x00 }, 136 + { CS42L42_ASP_RX_DAI1_CH1_AP_RES, 0x03 }, 137 + { CS42L42_ASP_RX_DAI1_CH1_BIT_MSB, 0x00 }, 138 + { CS42L42_ASP_RX_DAI1_CH1_BIT_LSB, 0x00 }, 139 + { CS42L42_ASP_RX_DAI1_CH2_AP_RES, 0x03 }, 140 + { CS42L42_ASP_RX_DAI1_CH2_BIT_MSB, 0x00 }, 141 + { CS42L42_ASP_RX_DAI1_CH2_BIT_LSB, 0x00 }, 142 + }; 143 + 144 + /* 145 + * This is all the same as for CS42L42 but we 146 + * replace the on-reset register defaults. 147 + */ 148 + const struct regmap_config cs42l83_regmap = { 149 + .reg_bits = 8, 150 + .val_bits = 8, 151 + 152 + .readable_reg = cs42l42_readable_register, 153 + .volatile_reg = cs42l42_volatile_register, 154 + 155 + .ranges = &cs42l42_page_range, 156 + .num_ranges = 1, 157 + 158 + .max_register = CS42L42_MAX_REGISTER, 159 + .reg_defaults = cs42l83_reg_defaults, 160 + .num_reg_defaults = ARRAY_SIZE(cs42l83_reg_defaults), 161 + .cache_type = REGCACHE_RBTREE, 162 + 163 + .use_single_read = true, 164 + .use_single_write = true, 165 + }; 166 + 167 + static int cs42l83_i2c_probe(struct i2c_client *i2c_client) 168 + { 169 + struct device *dev = &i2c_client->dev; 170 + struct cs42l42_private *cs42l83; 171 + struct regmap *regmap; 172 + int ret; 173 + 174 + cs42l83 = devm_kzalloc(dev, sizeof(*cs42l83), GFP_KERNEL); 175 + if (!cs42l83) 176 + return -ENOMEM; 177 + 178 + regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap); 179 + if (IS_ERR(regmap)) 180 + return dev_err_probe(&i2c_client->dev, PTR_ERR(regmap), 181 + "regmap_init() failed\n"); 182 + 183 + cs42l83->devid = CS42L83_CHIP_ID; 184 + cs42l83->dev = dev; 185 + cs42l83->regmap = regmap; 186 + cs42l83->irq = i2c_client->irq; 187 + 188 + ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai); 189 + if (ret) 190 + return ret; 191 + 192 + return cs42l42_init(cs42l83); 193 + } 194 + 195 + static int cs42l83_i2c_remove(struct i2c_client *i2c_client) 196 + { 197 + struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev); 198 + 199 + cs42l42_common_remove(cs42l83); 200 + 201 + return 0; 202 + } 203 + 204 + static int __maybe_unused cs42l83_i2c_resume(struct device *dev) 205 + { 206 + int ret; 207 + 208 + ret = cs42l42_resume(dev); 209 + if (ret) 210 + return ret; 211 + 212 + cs42l42_resume_restore(dev); 213 + 214 + return 0; 215 + } 216 + 217 + static const struct dev_pm_ops cs42l83_i2c_pm_ops = { 218 + SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume) 219 + }; 220 + 221 + static const struct of_device_id __maybe_unused cs42l83_of_match[] = { 222 + { .compatible = "cirrus,cs42l83", }, 223 + {} 224 + }; 225 + MODULE_DEVICE_TABLE(of, cs42l83_of_match); 226 + 227 + static struct i2c_driver cs42l83_i2c_driver = { 228 + .driver = { 229 + .name = "cs42l83", 230 + .pm = &cs42l83_i2c_pm_ops, 231 + .of_match_table = of_match_ptr(cs42l83_of_match), 232 + }, 233 + .probe_new = cs42l83_i2c_probe, 234 + .remove = cs42l83_i2c_remove, 235 + }; 236 + 237 + module_i2c_driver(cs42l83_i2c_driver); 238 + 239 + MODULE_DESCRIPTION("ASoC CS42L83 I2C driver"); 240 + MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>"); 241 + MODULE_LICENSE("GPL"); 242 + MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);