162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * MAX98504 ALSA SoC Audio driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2013 - 2014 Maxim Integrated Products 662306a36Sopenharmony_ci * Copyright 2016 Samsung Electronics Co., Ltd. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/i2c.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <sound/soc.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "max98504.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const char * const max98504_supply_names[] = { 2062306a36Sopenharmony_ci "DVDD", 2162306a36Sopenharmony_ci "DIOVDD", 2262306a36Sopenharmony_ci "PVDD", 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci#define MAX98504_NUM_SUPPLIES ARRAY_SIZE(max98504_supply_names) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct max98504_priv { 2762306a36Sopenharmony_ci struct regmap *regmap; 2862306a36Sopenharmony_ci struct regulator_bulk_data supplies[MAX98504_NUM_SUPPLIES]; 2962306a36Sopenharmony_ci unsigned int pcm_rx_channels; 3062306a36Sopenharmony_ci bool brownout_enable; 3162306a36Sopenharmony_ci unsigned int brownout_threshold; 3262306a36Sopenharmony_ci unsigned int brownout_attenuation; 3362306a36Sopenharmony_ci unsigned int brownout_attack_hold; 3462306a36Sopenharmony_ci unsigned int brownout_timed_hold; 3562306a36Sopenharmony_ci unsigned int brownout_release_rate; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic struct reg_default max98504_reg_defaults[] = { 3962306a36Sopenharmony_ci { 0x01, 0}, 4062306a36Sopenharmony_ci { 0x02, 0}, 4162306a36Sopenharmony_ci { 0x03, 0}, 4262306a36Sopenharmony_ci { 0x04, 0}, 4362306a36Sopenharmony_ci { 0x10, 0}, 4462306a36Sopenharmony_ci { 0x11, 0}, 4562306a36Sopenharmony_ci { 0x12, 0}, 4662306a36Sopenharmony_ci { 0x13, 0}, 4762306a36Sopenharmony_ci { 0x14, 0}, 4862306a36Sopenharmony_ci { 0x15, 0}, 4962306a36Sopenharmony_ci { 0x16, 0}, 5062306a36Sopenharmony_ci { 0x17, 0}, 5162306a36Sopenharmony_ci { 0x18, 0}, 5262306a36Sopenharmony_ci { 0x19, 0}, 5362306a36Sopenharmony_ci { 0x1A, 0}, 5462306a36Sopenharmony_ci { 0x20, 0}, 5562306a36Sopenharmony_ci { 0x21, 0}, 5662306a36Sopenharmony_ci { 0x22, 0}, 5762306a36Sopenharmony_ci { 0x23, 0}, 5862306a36Sopenharmony_ci { 0x24, 0}, 5962306a36Sopenharmony_ci { 0x25, 0}, 6062306a36Sopenharmony_ci { 0x26, 0}, 6162306a36Sopenharmony_ci { 0x27, 0}, 6262306a36Sopenharmony_ci { 0x28, 0}, 6362306a36Sopenharmony_ci { 0x30, 0}, 6462306a36Sopenharmony_ci { 0x31, 0}, 6562306a36Sopenharmony_ci { 0x32, 0}, 6662306a36Sopenharmony_ci { 0x33, 0}, 6762306a36Sopenharmony_ci { 0x34, 0}, 6862306a36Sopenharmony_ci { 0x35, 0}, 6962306a36Sopenharmony_ci { 0x36, 0}, 7062306a36Sopenharmony_ci { 0x37, 0}, 7162306a36Sopenharmony_ci { 0x38, 0}, 7262306a36Sopenharmony_ci { 0x39, 0}, 7362306a36Sopenharmony_ci { 0x40, 0}, 7462306a36Sopenharmony_ci { 0x41, 0}, 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic bool max98504_volatile_register(struct device *dev, unsigned int reg) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci switch (reg) { 8062306a36Sopenharmony_ci case MAX98504_INTERRUPT_STATUS: 8162306a36Sopenharmony_ci case MAX98504_INTERRUPT_FLAGS: 8262306a36Sopenharmony_ci case MAX98504_INTERRUPT_FLAG_CLEARS: 8362306a36Sopenharmony_ci case MAX98504_WATCHDOG_CLEAR: 8462306a36Sopenharmony_ci case MAX98504_GLOBAL_ENABLE: 8562306a36Sopenharmony_ci case MAX98504_SOFTWARE_RESET: 8662306a36Sopenharmony_ci return true; 8762306a36Sopenharmony_ci default: 8862306a36Sopenharmony_ci return false; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic bool max98504_readable_register(struct device *dev, unsigned int reg) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci switch (reg) { 9562306a36Sopenharmony_ci case MAX98504_SOFTWARE_RESET: 9662306a36Sopenharmony_ci case MAX98504_WATCHDOG_CLEAR: 9762306a36Sopenharmony_ci case MAX98504_INTERRUPT_FLAG_CLEARS: 9862306a36Sopenharmony_ci return false; 9962306a36Sopenharmony_ci default: 10062306a36Sopenharmony_ci return true; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int max98504_pcm_rx_ev(struct snd_soc_dapm_widget *w, 10562306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); 10862306a36Sopenharmony_ci struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci switch (event) { 11162306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 11262306a36Sopenharmony_ci regmap_write(max98504->regmap, MAX98504_PCM_RX_ENABLE, 11362306a36Sopenharmony_ci max98504->pcm_rx_channels); 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 11662306a36Sopenharmony_ci regmap_write(max98504->regmap, MAX98504_PCM_RX_ENABLE, 0); 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return 0; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic int max98504_component_probe(struct snd_soc_component *c) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c); 12662306a36Sopenharmony_ci struct regmap *map = max98504->regmap; 12762306a36Sopenharmony_ci int ret; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci ret = regulator_bulk_enable(MAX98504_NUM_SUPPLIES, max98504->supplies); 13062306a36Sopenharmony_ci if (ret < 0) 13162306a36Sopenharmony_ci return ret; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci regmap_write(map, MAX98504_SOFTWARE_RESET, 0x1); 13462306a36Sopenharmony_ci msleep(20); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (!max98504->brownout_enable) 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci regmap_write(map, MAX98504_PVDD_BROWNOUT_ENABLE, 0x1); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_1, 14262306a36Sopenharmony_ci (max98504->brownout_threshold & 0x1f) << 3 | 14362306a36Sopenharmony_ci (max98504->brownout_attenuation & 0x3)); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_2, 14662306a36Sopenharmony_ci max98504->brownout_attack_hold & 0xff); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_3, 14962306a36Sopenharmony_ci max98504->brownout_timed_hold & 0xff); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_4, 15262306a36Sopenharmony_ci max98504->brownout_release_rate & 0xff); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return 0; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic void max98504_component_remove(struct snd_soc_component *c) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci regulator_bulk_disable(MAX98504_NUM_SUPPLIES, max98504->supplies); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const char *spk_source_mux_text[] = { 16562306a36Sopenharmony_ci "PCM Monomix", "Analog In", "PDM Left", "PDM Right" 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const struct soc_enum spk_source_mux_enum = 16962306a36Sopenharmony_ci SOC_ENUM_SINGLE(MAX98504_SPEAKER_SOURCE_SELECT, 17062306a36Sopenharmony_ci 0, ARRAY_SIZE(spk_source_mux_text), 17162306a36Sopenharmony_ci spk_source_mux_text); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic const struct snd_kcontrol_new spk_source_mux = 17462306a36Sopenharmony_ci SOC_DAPM_ENUM("SPK Source", spk_source_mux_enum); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98504_dapm_routes[] = { 17762306a36Sopenharmony_ci { "SPKOUT", NULL, "Global Enable" }, 17862306a36Sopenharmony_ci { "SPK Source", "PCM Monomix", "DAC PCM" }, 17962306a36Sopenharmony_ci { "SPK Source", "Analog In", "AIN" }, 18062306a36Sopenharmony_ci { "SPK Source", "PDM Left", "DAC PDM" }, 18162306a36Sopenharmony_ci { "SPK Source", "PDM Right", "DAC PDM" }, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98504_dapm_widgets[] = { 18562306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Global Enable", MAX98504_GLOBAL_ENABLE, 18662306a36Sopenharmony_ci 0, 0, NULL, 0), 18762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN"), 18862306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF2OUTL", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), 18962306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF2OUTR", "AIF2 Capture", 1, SND_SOC_NOPM, 0, 0), 19062306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("DAC PCM", NULL, SND_SOC_NOPM, 0, 0, 19162306a36Sopenharmony_ci max98504_pcm_rx_ev, 19262306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 19362306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC PDM", NULL, MAX98504_PDM_RX_ENABLE, 0, 0), 19462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("SPK Source", SND_SOC_NOPM, 0, 0, &spk_source_mux), 19562306a36Sopenharmony_ci SND_SOC_DAPM_REG(snd_soc_dapm_spk, "SPKOUT", 19662306a36Sopenharmony_ci MAX98504_SPEAKER_ENABLE, 0, 1, 1, 0), 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic int max98504_set_tdm_slot(struct snd_soc_dai *dai, 20062306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 20162306a36Sopenharmony_ci int slots, int slot_width) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct max98504_priv *max98504 = snd_soc_dai_get_drvdata(dai); 20462306a36Sopenharmony_ci struct regmap *map = max98504->regmap; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci switch (dai->id) { 20862306a36Sopenharmony_ci case MAX98504_DAI_ID_PCM: 20962306a36Sopenharmony_ci regmap_write(map, MAX98504_PCM_TX_ENABLE, tx_mask); 21062306a36Sopenharmony_ci max98504->pcm_rx_channels = rx_mask; 21162306a36Sopenharmony_ci break; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci case MAX98504_DAI_ID_PDM: 21462306a36Sopenharmony_ci regmap_write(map, MAX98504_PDM_TX_ENABLE, tx_mask); 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci default: 21762306a36Sopenharmony_ci WARN_ON(1); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_cistatic int max98504_set_channel_map(struct snd_soc_dai *dai, 22362306a36Sopenharmony_ci unsigned int tx_num, unsigned int *tx_slot, 22462306a36Sopenharmony_ci unsigned int rx_num, unsigned int *rx_slot) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci struct max98504_priv *max98504 = snd_soc_dai_get_drvdata(dai); 22762306a36Sopenharmony_ci struct regmap *map = max98504->regmap; 22862306a36Sopenharmony_ci unsigned int i, sources = 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci for (i = 0; i < tx_num; i++) 23162306a36Sopenharmony_ci if (tx_slot[i]) 23262306a36Sopenharmony_ci sources |= (1 << i); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci switch (dai->id) { 23562306a36Sopenharmony_ci case MAX98504_DAI_ID_PCM: 23662306a36Sopenharmony_ci regmap_write(map, MAX98504_PCM_TX_CHANNEL_SOURCES, 23762306a36Sopenharmony_ci sources); 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci case MAX98504_DAI_ID_PDM: 24162306a36Sopenharmony_ci regmap_write(map, MAX98504_PDM_TX_CONTROL, sources); 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci default: 24462306a36Sopenharmony_ci WARN_ON(1); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci regmap_write(map, MAX98504_MEASUREMENT_ENABLE, sources ? 0x3 : 0x01); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98504_dai_ops = { 25362306a36Sopenharmony_ci .set_tdm_slot = max98504_set_tdm_slot, 25462306a36Sopenharmony_ci .set_channel_map = max98504_set_channel_map, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci#define MAX98504_FORMATS (SNDRV_PCM_FMTBIT_S8|SNDRV_PCM_FMTBIT_S16_LE|\ 25862306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE|SNDRV_PCM_FMTBIT_S32_LE) 25962306a36Sopenharmony_ci#define MAX98504_PDM_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\ 26062306a36Sopenharmony_ci SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|\ 26162306a36Sopenharmony_ci SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_88200|\ 26262306a36Sopenharmony_ci SNDRV_PCM_RATE_96000) 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98504_dai[] = { 26562306a36Sopenharmony_ci /* TODO: Add the PCM interface definitions */ 26662306a36Sopenharmony_ci { 26762306a36Sopenharmony_ci .name = "max98504-aif2", 26862306a36Sopenharmony_ci .id = MAX98504_DAI_ID_PDM, 26962306a36Sopenharmony_ci .playback = { 27062306a36Sopenharmony_ci .stream_name = "AIF2 Playback", 27162306a36Sopenharmony_ci .channels_min = 1, 27262306a36Sopenharmony_ci .channels_max = 2, 27362306a36Sopenharmony_ci .rates = MAX98504_PDM_RATES, 27462306a36Sopenharmony_ci .formats = MAX98504_FORMATS, 27562306a36Sopenharmony_ci }, 27662306a36Sopenharmony_ci .capture = { 27762306a36Sopenharmony_ci .stream_name = "AIF2 Capture", 27862306a36Sopenharmony_ci .channels_min = 1, 27962306a36Sopenharmony_ci .channels_max = 2, 28062306a36Sopenharmony_ci .rates = MAX98504_PDM_RATES, 28162306a36Sopenharmony_ci .formats = MAX98504_FORMATS, 28262306a36Sopenharmony_ci }, 28362306a36Sopenharmony_ci .ops = &max98504_dai_ops, 28462306a36Sopenharmony_ci }, 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic const struct snd_soc_component_driver max98504_component_driver = { 28862306a36Sopenharmony_ci .probe = max98504_component_probe, 28962306a36Sopenharmony_ci .remove = max98504_component_remove, 29062306a36Sopenharmony_ci .dapm_widgets = max98504_dapm_widgets, 29162306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98504_dapm_widgets), 29262306a36Sopenharmony_ci .dapm_routes = max98504_dapm_routes, 29362306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98504_dapm_routes), 29462306a36Sopenharmony_ci .endianness = 1, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct regmap_config max98504_regmap = { 29862306a36Sopenharmony_ci .reg_bits = 16, 29962306a36Sopenharmony_ci .val_bits = 8, 30062306a36Sopenharmony_ci .max_register = MAX98504_MAX_REGISTER, 30162306a36Sopenharmony_ci .reg_defaults = max98504_reg_defaults, 30262306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98504_reg_defaults), 30362306a36Sopenharmony_ci .volatile_reg = max98504_volatile_register, 30462306a36Sopenharmony_ci .readable_reg = max98504_readable_register, 30562306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic int max98504_i2c_probe(struct i2c_client *client) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct device *dev = &client->dev; 31162306a36Sopenharmony_ci struct device_node *node = dev->of_node; 31262306a36Sopenharmony_ci struct max98504_priv *max98504; 31362306a36Sopenharmony_ci int i, ret; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci max98504 = devm_kzalloc(dev, sizeof(*max98504), GFP_KERNEL); 31662306a36Sopenharmony_ci if (!max98504) 31762306a36Sopenharmony_ci return -ENOMEM; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (node) { 32062306a36Sopenharmony_ci if (!of_property_read_u32(node, "maxim,brownout-threshold", 32162306a36Sopenharmony_ci &max98504->brownout_threshold)) 32262306a36Sopenharmony_ci max98504->brownout_enable = true; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci of_property_read_u32(node, "maxim,brownout-attenuation", 32562306a36Sopenharmony_ci &max98504->brownout_attenuation); 32662306a36Sopenharmony_ci of_property_read_u32(node, "maxim,brownout-attack-hold-ms", 32762306a36Sopenharmony_ci &max98504->brownout_attack_hold); 32862306a36Sopenharmony_ci of_property_read_u32(node, "maxim,brownout-timed-hold-ms", 32962306a36Sopenharmony_ci &max98504->brownout_timed_hold); 33062306a36Sopenharmony_ci of_property_read_u32(node, "maxim,brownout-release-rate-ms", 33162306a36Sopenharmony_ci &max98504->brownout_release_rate); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci max98504->regmap = devm_regmap_init_i2c(client, &max98504_regmap); 33562306a36Sopenharmony_ci if (IS_ERR(max98504->regmap)) { 33662306a36Sopenharmony_ci ret = PTR_ERR(max98504->regmap); 33762306a36Sopenharmony_ci dev_err(&client->dev, "regmap initialization failed: %d\n", ret); 33862306a36Sopenharmony_ci return ret; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci for (i = 0; i < MAX98504_NUM_SUPPLIES; i++) 34262306a36Sopenharmony_ci max98504->supplies[i].supply = max98504_supply_names[i]; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci ret = devm_regulator_bulk_get(dev, MAX98504_NUM_SUPPLIES, 34562306a36Sopenharmony_ci max98504->supplies); 34662306a36Sopenharmony_ci if (ret < 0) 34762306a36Sopenharmony_ci return ret; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci i2c_set_clientdata(client, max98504); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, &max98504_component_driver, 35262306a36Sopenharmony_ci max98504_dai, ARRAY_SIZE(max98504_dai)); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci#ifdef CONFIG_OF 35662306a36Sopenharmony_cistatic const struct of_device_id max98504_of_match[] = { 35762306a36Sopenharmony_ci { .compatible = "maxim,max98504" }, 35862306a36Sopenharmony_ci { }, 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98504_of_match); 36162306a36Sopenharmony_ci#endif 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic const struct i2c_device_id max98504_i2c_id[] = { 36462306a36Sopenharmony_ci { "max98504" }, 36562306a36Sopenharmony_ci { } 36662306a36Sopenharmony_ci}; 36762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98504_i2c_id); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic struct i2c_driver max98504_i2c_driver = { 37062306a36Sopenharmony_ci .driver = { 37162306a36Sopenharmony_ci .name = "max98504", 37262306a36Sopenharmony_ci .of_match_table = of_match_ptr(max98504_of_match), 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci .probe = max98504_i2c_probe, 37562306a36Sopenharmony_ci .id_table = max98504_i2c_id, 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_cimodule_i2c_driver(max98504_i2c_driver); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC MAX98504 driver"); 38062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 381