cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wm8741.c (18037B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * wm8741.c  --  WM8741 ALSA SoC Audio driver
      4 *
      5 * Copyright 2010-1 Wolfson Microelectronics plc
      6 *
      7 * Author: Ian Lartey <ian@opensource.wolfsonmicro.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/moduleparam.h>
     12#include <linux/init.h>
     13#include <linux/delay.h>
     14#include <linux/pm.h>
     15#include <linux/i2c.h>
     16#include <linux/spi/spi.h>
     17#include <linux/regmap.h>
     18#include <linux/regulator/consumer.h>
     19#include <linux/slab.h>
     20#include <linux/of_device.h>
     21#include <sound/core.h>
     22#include <sound/pcm.h>
     23#include <sound/pcm_params.h>
     24#include <sound/soc.h>
     25#include <sound/initval.h>
     26#include <sound/tlv.h>
     27
     28#include "wm8741.h"
     29
     30#define WM8741_NUM_SUPPLIES 2
     31static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
     32	"AVDD",
     33	"DVDD",
     34};
     35
     36/* codec private data */
     37struct wm8741_priv {
     38	struct wm8741_platform_data pdata;
     39	struct regmap *regmap;
     40	struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
     41	unsigned int sysclk;
     42	const struct snd_pcm_hw_constraint_list *sysclk_constraints;
     43};
     44
     45static const struct reg_default wm8741_reg_defaults[] = {
     46	{  0, 0x0000 },     /* R0  - DACLLSB Attenuation */
     47	{  1, 0x0000 },     /* R1  - DACLMSB Attenuation */
     48	{  2, 0x0000 },     /* R2  - DACRLSB Attenuation */
     49	{  3, 0x0000 },     /* R3  - DACRMSB Attenuation */
     50	{  4, 0x0000 },     /* R4  - Volume Control */
     51	{  5, 0x000A },     /* R5  - Format Control */
     52	{  6, 0x0000 },     /* R6  - Filter Control */
     53	{  7, 0x0000 },     /* R7  - Mode Control 1 */
     54	{  8, 0x0002 },     /* R8  - Mode Control 2 */
     55	{ 32, 0x0002 },     /* R32 - ADDITONAL_CONTROL_1 */
     56};
     57
     58static int wm8741_reset(struct snd_soc_component *component)
     59{
     60	return snd_soc_component_write(component, WM8741_RESET, 0);
     61}
     62
     63static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0);
     64static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0);
     65
     66static const struct snd_kcontrol_new wm8741_snd_controls_stereo[] = {
     67SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
     68		 WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine),
     69SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION,
     70		 WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv),
     71};
     72
     73static const struct snd_kcontrol_new wm8741_snd_controls_mono_left[] = {
     74SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
     75		 1, 255, 1, dac_tlv_fine),
     76SOC_SINGLE_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION,
     77		 0, 511, 1, dac_tlv),
     78};
     79
     80static const struct snd_kcontrol_new wm8741_snd_controls_mono_right[] = {
     81SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACRLSB_ATTENUATION,
     82		1, 255, 1, dac_tlv_fine),
     83SOC_SINGLE_TLV("Playback Volume", WM8741_DACRMSB_ATTENUATION,
     84		0, 511, 1, dac_tlv),
     85};
     86
     87static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = {
     88SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0),
     89SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0),
     90SND_SOC_DAPM_OUTPUT("VOUTLP"),
     91SND_SOC_DAPM_OUTPUT("VOUTLN"),
     92SND_SOC_DAPM_OUTPUT("VOUTRP"),
     93SND_SOC_DAPM_OUTPUT("VOUTRN"),
     94};
     95
     96static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
     97	{ "VOUTLP", NULL, "DACL" },
     98	{ "VOUTLN", NULL, "DACL" },
     99	{ "VOUTRP", NULL, "DACR" },
    100	{ "VOUTRN", NULL, "DACR" },
    101};
    102
    103static const unsigned int rates_11289[] = {
    104	44100, 88200,
    105};
    106
    107static const struct snd_pcm_hw_constraint_list constraints_11289 = {
    108	.count	= ARRAY_SIZE(rates_11289),
    109	.list	= rates_11289,
    110};
    111
    112static const unsigned int rates_12288[] = {
    113	32000, 48000, 96000,
    114};
    115
    116static const struct snd_pcm_hw_constraint_list constraints_12288 = {
    117	.count	= ARRAY_SIZE(rates_12288),
    118	.list	= rates_12288,
    119};
    120
    121static const unsigned int rates_16384[] = {
    122	32000,
    123};
    124
    125static const struct snd_pcm_hw_constraint_list constraints_16384 = {
    126	.count	= ARRAY_SIZE(rates_16384),
    127	.list	= rates_16384,
    128};
    129
    130static const unsigned int rates_16934[] = {
    131	44100, 88200,
    132};
    133
    134static const struct snd_pcm_hw_constraint_list constraints_16934 = {
    135	.count	= ARRAY_SIZE(rates_16934),
    136	.list	= rates_16934,
    137};
    138
    139static const unsigned int rates_18432[] = {
    140	48000, 96000,
    141};
    142
    143static const struct snd_pcm_hw_constraint_list constraints_18432 = {
    144	.count	= ARRAY_SIZE(rates_18432),
    145	.list	= rates_18432,
    146};
    147
    148static const unsigned int rates_22579[] = {
    149	44100, 88200, 176400
    150};
    151
    152static const struct snd_pcm_hw_constraint_list constraints_22579 = {
    153	.count	= ARRAY_SIZE(rates_22579),
    154	.list	= rates_22579,
    155};
    156
    157static const unsigned int rates_24576[] = {
    158	32000, 48000, 96000, 192000
    159};
    160
    161static const struct snd_pcm_hw_constraint_list constraints_24576 = {
    162	.count	= ARRAY_SIZE(rates_24576),
    163	.list	= rates_24576,
    164};
    165
    166static const unsigned int rates_36864[] = {
    167	48000, 96000, 192000
    168};
    169
    170static const struct snd_pcm_hw_constraint_list constraints_36864 = {
    171	.count	= ARRAY_SIZE(rates_36864),
    172	.list	= rates_36864,
    173};
    174
    175static int wm8741_startup(struct snd_pcm_substream *substream,
    176			  struct snd_soc_dai *dai)
    177{
    178	struct snd_soc_component *component = dai->component;
    179	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    180
    181	if (wm8741->sysclk)
    182		snd_pcm_hw_constraint_list(substream->runtime, 0,
    183				SNDRV_PCM_HW_PARAM_RATE,
    184				wm8741->sysclk_constraints);
    185
    186	return 0;
    187}
    188
    189static int wm8741_hw_params(struct snd_pcm_substream *substream,
    190			    struct snd_pcm_hw_params *params,
    191			    struct snd_soc_dai *dai)
    192{
    193	struct snd_soc_component *component = dai->component;
    194	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    195	unsigned int iface, mode;
    196	int i;
    197
    198	/* The set of sample rates that can be supported depends on the
    199	 * MCLK supplied to the CODEC - enforce this.
    200	 */
    201	if (!wm8741->sysclk) {
    202		dev_err(component->dev,
    203			"No MCLK configured, call set_sysclk() on init or in hw_params\n");
    204		return -EINVAL;
    205	}
    206
    207	/* Find a supported LRCLK rate */
    208	for (i = 0; i < wm8741->sysclk_constraints->count; i++) {
    209		if (wm8741->sysclk_constraints->list[i] == params_rate(params))
    210			break;
    211	}
    212
    213	if (i == wm8741->sysclk_constraints->count) {
    214		dev_err(component->dev, "LRCLK %d unsupported with MCLK %d\n",
    215			params_rate(params), wm8741->sysclk);
    216		return -EINVAL;
    217	}
    218
    219	/* bit size */
    220	switch (params_width(params)) {
    221	case 16:
    222		iface = 0x0;
    223		break;
    224	case 20:
    225		iface = 0x1;
    226		break;
    227	case 24:
    228		iface = 0x2;
    229		break;
    230	case 32:
    231		iface = 0x3;
    232		break;
    233	default:
    234		dev_dbg(component->dev, "wm8741_hw_params:    Unsupported bit size param = %d",
    235			params_width(params));
    236		return -EINVAL;
    237	}
    238
    239	/* oversampling rate */
    240	if (params_rate(params) > 96000)
    241		mode = 0x40;
    242	else if (params_rate(params) > 48000)
    243		mode = 0x20;
    244	else
    245		mode = 0x00;
    246
    247	dev_dbg(component->dev, "wm8741_hw_params:    bit size param = %d, rate param = %d",
    248		params_width(params), params_rate(params));
    249
    250	snd_soc_component_update_bits(component, WM8741_FORMAT_CONTROL, WM8741_IWL_MASK,
    251			    iface);
    252	snd_soc_component_update_bits(component, WM8741_MODE_CONTROL_1, WM8741_OSR_MASK,
    253			    mode);
    254
    255	return 0;
    256}
    257
    258static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
    259		int clk_id, unsigned int freq, int dir)
    260{
    261	struct snd_soc_component *component = codec_dai->component;
    262	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    263
    264	dev_dbg(component->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
    265
    266	switch (freq) {
    267	case 0:
    268		wm8741->sysclk_constraints = NULL;
    269		break;
    270	case 11289600:
    271		wm8741->sysclk_constraints = &constraints_11289;
    272		break;
    273	case 12288000:
    274		wm8741->sysclk_constraints = &constraints_12288;
    275		break;
    276	case 16384000:
    277		wm8741->sysclk_constraints = &constraints_16384;
    278		break;
    279	case 16934400:
    280		wm8741->sysclk_constraints = &constraints_16934;
    281		break;
    282	case 18432000:
    283		wm8741->sysclk_constraints = &constraints_18432;
    284		break;
    285	case 22579200:
    286	case 33868800:
    287		wm8741->sysclk_constraints = &constraints_22579;
    288		break;
    289	case 24576000:
    290		wm8741->sysclk_constraints = &constraints_24576;
    291		break;
    292	case 36864000:
    293		wm8741->sysclk_constraints = &constraints_36864;
    294		break;
    295	default:
    296		return -EINVAL;
    297	}
    298
    299	wm8741->sysclk = freq;
    300	return 0;
    301}
    302
    303static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
    304		unsigned int fmt)
    305{
    306	struct snd_soc_component *component = codec_dai->component;
    307	unsigned int iface;
    308
    309	/* check master/slave audio interface */
    310	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    311	case SND_SOC_DAIFMT_CBS_CFS:
    312		break;
    313	default:
    314		return -EINVAL;
    315	}
    316
    317	/* interface format */
    318	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    319	case SND_SOC_DAIFMT_I2S:
    320		iface = 0x08;
    321		break;
    322	case SND_SOC_DAIFMT_RIGHT_J:
    323		iface = 0x00;
    324		break;
    325	case SND_SOC_DAIFMT_LEFT_J:
    326		iface = 0x04;
    327		break;
    328	case SND_SOC_DAIFMT_DSP_A:
    329		iface = 0x0C;
    330		break;
    331	case SND_SOC_DAIFMT_DSP_B:
    332		iface = 0x1C;
    333		break;
    334	default:
    335		return -EINVAL;
    336	}
    337
    338	/* clock inversion */
    339	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    340	case SND_SOC_DAIFMT_NB_NF:
    341		break;
    342	case SND_SOC_DAIFMT_NB_IF:
    343		iface |= 0x10;
    344		break;
    345	case SND_SOC_DAIFMT_IB_NF:
    346		iface |= 0x20;
    347		break;
    348	case SND_SOC_DAIFMT_IB_IF:
    349		iface |= 0x30;
    350		break;
    351	default:
    352		return -EINVAL;
    353	}
    354
    355
    356	dev_dbg(component->dev, "wm8741_set_dai_fmt:    Format=%x, Clock Inv=%x\n",
    357				fmt & SND_SOC_DAIFMT_FORMAT_MASK,
    358				((fmt & SND_SOC_DAIFMT_INV_MASK)));
    359
    360	snd_soc_component_update_bits(component, WM8741_FORMAT_CONTROL,
    361			    WM8741_BCP_MASK | WM8741_LRP_MASK | WM8741_FMT_MASK,
    362			    iface);
    363
    364	return 0;
    365}
    366
    367static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute, int direction)
    368{
    369	struct snd_soc_component *component = codec_dai->component;
    370
    371	snd_soc_component_update_bits(component, WM8741_VOLUME_CONTROL,
    372			WM8741_SOFT_MASK, !!mute << WM8741_SOFT_SHIFT);
    373	return 0;
    374}
    375
    376#define WM8741_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
    377			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
    378			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
    379			SNDRV_PCM_RATE_192000)
    380
    381#define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
    382			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
    383
    384static const struct snd_soc_dai_ops wm8741_dai_ops = {
    385	.startup	= wm8741_startup,
    386	.hw_params	= wm8741_hw_params,
    387	.set_sysclk	= wm8741_set_dai_sysclk,
    388	.set_fmt	= wm8741_set_dai_fmt,
    389	.mute_stream	= wm8741_mute,
    390	.no_capture_mute = 1,
    391};
    392
    393static struct snd_soc_dai_driver wm8741_dai = {
    394	.name = "wm8741",
    395	.playback = {
    396		.stream_name = "Playback",
    397		.channels_min = 2,
    398		.channels_max = 2,
    399		.rates = WM8741_RATES,
    400		.formats = WM8741_FORMATS,
    401	},
    402	.ops = &wm8741_dai_ops,
    403};
    404
    405#ifdef CONFIG_PM
    406static int wm8741_resume(struct snd_soc_component *component)
    407{
    408	snd_soc_component_cache_sync(component);
    409	return 0;
    410}
    411#else
    412#define wm8741_resume NULL
    413#endif
    414
    415static int wm8741_configure(struct snd_soc_component *component)
    416{
    417	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    418
    419	/* Configure differential mode */
    420	switch (wm8741->pdata.diff_mode) {
    421	case WM8741_DIFF_MODE_STEREO:
    422	case WM8741_DIFF_MODE_STEREO_REVERSED:
    423	case WM8741_DIFF_MODE_MONO_LEFT:
    424	case WM8741_DIFF_MODE_MONO_RIGHT:
    425		snd_soc_component_update_bits(component, WM8741_MODE_CONTROL_2,
    426				WM8741_DIFF_MASK,
    427				wm8741->pdata.diff_mode << WM8741_DIFF_SHIFT);
    428		break;
    429	default:
    430		return -EINVAL;
    431	}
    432
    433	/* Change some default settings - latch VU */
    434	snd_soc_component_update_bits(component, WM8741_DACLLSB_ATTENUATION,
    435			WM8741_UPDATELL, WM8741_UPDATELL);
    436	snd_soc_component_update_bits(component, WM8741_DACLMSB_ATTENUATION,
    437			WM8741_UPDATELM, WM8741_UPDATELM);
    438	snd_soc_component_update_bits(component, WM8741_DACRLSB_ATTENUATION,
    439			WM8741_UPDATERL, WM8741_UPDATERL);
    440	snd_soc_component_update_bits(component, WM8741_DACRMSB_ATTENUATION,
    441			WM8741_UPDATERM, WM8741_UPDATERM);
    442
    443	return 0;
    444}
    445
    446static int wm8741_add_controls(struct snd_soc_component *component)
    447{
    448	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    449
    450	switch (wm8741->pdata.diff_mode) {
    451	case WM8741_DIFF_MODE_STEREO:
    452	case WM8741_DIFF_MODE_STEREO_REVERSED:
    453		snd_soc_add_component_controls(component,
    454				wm8741_snd_controls_stereo,
    455				ARRAY_SIZE(wm8741_snd_controls_stereo));
    456		break;
    457	case WM8741_DIFF_MODE_MONO_LEFT:
    458		snd_soc_add_component_controls(component,
    459				wm8741_snd_controls_mono_left,
    460				ARRAY_SIZE(wm8741_snd_controls_mono_left));
    461		break;
    462	case WM8741_DIFF_MODE_MONO_RIGHT:
    463		snd_soc_add_component_controls(component,
    464				wm8741_snd_controls_mono_right,
    465				ARRAY_SIZE(wm8741_snd_controls_mono_right));
    466		break;
    467	default:
    468		return -EINVAL;
    469	}
    470
    471	return 0;
    472}
    473
    474static int wm8741_probe(struct snd_soc_component *component)
    475{
    476	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    477	int ret = 0;
    478
    479	ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
    480				    wm8741->supplies);
    481	if (ret != 0) {
    482		dev_err(component->dev, "Failed to enable supplies: %d\n", ret);
    483		goto err_get;
    484	}
    485
    486	ret = wm8741_reset(component);
    487	if (ret < 0) {
    488		dev_err(component->dev, "Failed to issue reset\n");
    489		goto err_enable;
    490	}
    491
    492	ret = wm8741_configure(component);
    493	if (ret < 0) {
    494		dev_err(component->dev, "Failed to change default settings\n");
    495		goto err_enable;
    496	}
    497
    498	ret = wm8741_add_controls(component);
    499	if (ret < 0) {
    500		dev_err(component->dev, "Failed to add controls\n");
    501		goto err_enable;
    502	}
    503
    504	dev_dbg(component->dev, "Successful registration\n");
    505	return ret;
    506
    507err_enable:
    508	regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
    509err_get:
    510	return ret;
    511}
    512
    513static void wm8741_remove(struct snd_soc_component *component)
    514{
    515	struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
    516
    517	regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
    518}
    519
    520static const struct snd_soc_component_driver soc_component_dev_wm8741 = {
    521	.probe			= wm8741_probe,
    522	.remove			= wm8741_remove,
    523	.resume			= wm8741_resume,
    524	.dapm_widgets		= wm8741_dapm_widgets,
    525	.num_dapm_widgets	= ARRAY_SIZE(wm8741_dapm_widgets),
    526	.dapm_routes		= wm8741_dapm_routes,
    527	.num_dapm_routes	= ARRAY_SIZE(wm8741_dapm_routes),
    528	.idle_bias_on		= 1,
    529	.use_pmdown_time	= 1,
    530	.endianness		= 1,
    531	.non_legacy_dai_naming	= 1,
    532};
    533
    534static const struct of_device_id wm8741_of_match[] = {
    535	{ .compatible = "wlf,wm8741", },
    536	{ }
    537};
    538MODULE_DEVICE_TABLE(of, wm8741_of_match);
    539
    540static const struct regmap_config wm8741_regmap = {
    541	.reg_bits = 7,
    542	.val_bits = 9,
    543	.max_register = WM8741_MAX_REGISTER,
    544
    545	.reg_defaults = wm8741_reg_defaults,
    546	.num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults),
    547	.cache_type = REGCACHE_RBTREE,
    548};
    549
    550static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741)
    551{
    552	const struct wm8741_platform_data *pdata = dev_get_platdata(dev);
    553	u32 diff_mode;
    554
    555	if (dev->of_node) {
    556		if (of_property_read_u32(dev->of_node, "diff-mode", &diff_mode)
    557				>= 0)
    558			wm8741->pdata.diff_mode = diff_mode;
    559	} else {
    560		if (pdata != NULL)
    561			memcpy(&wm8741->pdata, pdata, sizeof(wm8741->pdata));
    562	}
    563
    564	return 0;
    565}
    566
    567#if IS_ENABLED(CONFIG_I2C)
    568static int wm8741_i2c_probe(struct i2c_client *i2c)
    569{
    570	struct wm8741_priv *wm8741;
    571	int ret, i;
    572
    573	wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv),
    574			      GFP_KERNEL);
    575	if (wm8741 == NULL)
    576		return -ENOMEM;
    577
    578	for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
    579		wm8741->supplies[i].supply = wm8741_supply_names[i];
    580
    581	ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
    582				      wm8741->supplies);
    583	if (ret != 0) {
    584		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
    585		return ret;
    586	}
    587
    588	wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap);
    589	if (IS_ERR(wm8741->regmap)) {
    590		ret = PTR_ERR(wm8741->regmap);
    591		dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
    592		return ret;
    593	}
    594
    595	ret = wm8741_set_pdata(&i2c->dev, wm8741);
    596	if (ret != 0) {
    597		dev_err(&i2c->dev, "Failed to set pdata: %d\n", ret);
    598		return ret;
    599	}
    600
    601	i2c_set_clientdata(i2c, wm8741);
    602
    603	ret = devm_snd_soc_register_component(&i2c->dev,
    604				     &soc_component_dev_wm8741, &wm8741_dai, 1);
    605
    606	return ret;
    607}
    608
    609static const struct i2c_device_id wm8741_i2c_id[] = {
    610	{ "wm8741", 0 },
    611	{ }
    612};
    613MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
    614
    615static struct i2c_driver wm8741_i2c_driver = {
    616	.driver = {
    617		.name = "wm8741",
    618		.of_match_table = wm8741_of_match,
    619	},
    620	.probe_new = wm8741_i2c_probe,
    621	.id_table = wm8741_i2c_id,
    622};
    623#endif
    624
    625#if defined(CONFIG_SPI_MASTER)
    626static int wm8741_spi_probe(struct spi_device *spi)
    627{
    628	struct wm8741_priv *wm8741;
    629	int ret, i;
    630
    631	wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv),
    632			     GFP_KERNEL);
    633	if (wm8741 == NULL)
    634		return -ENOMEM;
    635
    636	for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
    637		wm8741->supplies[i].supply = wm8741_supply_names[i];
    638
    639	ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies),
    640				      wm8741->supplies);
    641	if (ret != 0) {
    642		dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
    643		return ret;
    644	}
    645
    646	wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap);
    647	if (IS_ERR(wm8741->regmap)) {
    648		ret = PTR_ERR(wm8741->regmap);
    649		dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
    650		return ret;
    651	}
    652
    653	ret = wm8741_set_pdata(&spi->dev, wm8741);
    654	if (ret != 0) {
    655		dev_err(&spi->dev, "Failed to set pdata: %d\n", ret);
    656		return ret;
    657	}
    658
    659	spi_set_drvdata(spi, wm8741);
    660
    661	ret = devm_snd_soc_register_component(&spi->dev,
    662			&soc_component_dev_wm8741, &wm8741_dai, 1);
    663	return ret;
    664}
    665
    666static struct spi_driver wm8741_spi_driver = {
    667	.driver = {
    668		.name	= "wm8741",
    669		.of_match_table = wm8741_of_match,
    670	},
    671	.probe		= wm8741_spi_probe,
    672};
    673#endif /* CONFIG_SPI_MASTER */
    674
    675static int __init wm8741_modinit(void)
    676{
    677	int ret = 0;
    678
    679#if IS_ENABLED(CONFIG_I2C)
    680	ret = i2c_add_driver(&wm8741_i2c_driver);
    681	if (ret != 0)
    682		pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
    683#endif
    684#if defined(CONFIG_SPI_MASTER)
    685	ret = spi_register_driver(&wm8741_spi_driver);
    686	if (ret != 0) {
    687		printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n",
    688		       ret);
    689	}
    690#endif
    691
    692	return ret;
    693}
    694module_init(wm8741_modinit);
    695
    696static void __exit wm8741_exit(void)
    697{
    698#if defined(CONFIG_SPI_MASTER)
    699	spi_unregister_driver(&wm8741_spi_driver);
    700#endif
    701#if IS_ENABLED(CONFIG_I2C)
    702	i2c_del_driver(&wm8741_i2c_driver);
    703#endif
    704}
    705module_exit(wm8741_exit);
    706
    707MODULE_DESCRIPTION("ASoC WM8741 driver");
    708MODULE_AUTHOR("Ian Lartey <ian@opensource.wolfsonmicro.com>");
    709MODULE_LICENSE("GPL");