162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for ADAU1701 SigmaDSP processor 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc. 662306a36Sopenharmony_ci * Author: Lars-Peter Clausen <lars@metafoo.de> 762306a36Sopenharmony_ci * based on an inital version by Cliff Cai <cliff.cai@analog.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/of_device.h> 1762306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1862306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1962306a36Sopenharmony_ci#include <linux/regmap.h> 2062306a36Sopenharmony_ci#include <sound/core.h> 2162306a36Sopenharmony_ci#include <sound/pcm.h> 2262306a36Sopenharmony_ci#include <sound/pcm_params.h> 2362306a36Sopenharmony_ci#include <sound/soc.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <asm/unaligned.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "sigmadsp.h" 2862306a36Sopenharmony_ci#include "adau1701.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i)) 3162306a36Sopenharmony_ci#define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i)) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define ADAU1701_DSPCTRL 0x081c 3462306a36Sopenharmony_ci#define ADAU1701_SEROCTL 0x081e 3562306a36Sopenharmony_ci#define ADAU1701_SERICTL 0x081f 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define ADAU1701_AUXNPOW 0x0822 3862306a36Sopenharmony_ci#define ADAU1701_PINCONF_0 0x0820 3962306a36Sopenharmony_ci#define ADAU1701_PINCONF_1 0x0821 4062306a36Sopenharmony_ci#define ADAU1701_AUXNPOW 0x0822 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define ADAU1701_OSCIPOW 0x0826 4362306a36Sopenharmony_ci#define ADAU1701_DACSET 0x0827 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define ADAU1701_MAX_REGISTER 0x0828 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_CR (1 << 2) 4862306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_DAM (1 << 3) 4962306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_ADM (1 << 4) 5062306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_IST (1 << 5) 5162306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_SR_48 0x00 5262306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_SR_96 0x01 5362306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_SR_192 0x02 5462306a36Sopenharmony_ci#define ADAU1701_DSPCTRL_SR_MASK 0x03 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define ADAU1701_SEROCTL_INV_LRCLK 0x2000 5762306a36Sopenharmony_ci#define ADAU1701_SEROCTL_INV_BCLK 0x1000 5862306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MASTER 0x0800 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OBF16 0x0000 6162306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OBF8 0x0200 6262306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OBF4 0x0400 6362306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OBF2 0x0600 6462306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OBF_MASK 0x0600 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OLF1024 0x0000 6762306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OLF512 0x0080 6862306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OLF256 0x0100 6962306a36Sopenharmony_ci#define ADAU1701_SEROCTL_OLF_MASK 0x0180 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY1 0x0000 7262306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY0 0x0004 7362306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY8 0x0008 7462306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY12 0x000c 7562306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY16 0x0010 7662306a36Sopenharmony_ci#define ADAU1701_SEROCTL_MSB_DEALY_MASK 0x001c 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 7962306a36Sopenharmony_ci#define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 8062306a36Sopenharmony_ci#define ADAU1701_SEROCTL_WORD_LEN_16 0x0002 8162306a36Sopenharmony_ci#define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define ADAU1701_AUXNPOW_VBPD 0x40 8462306a36Sopenharmony_ci#define ADAU1701_AUXNPOW_VRPD 0x20 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define ADAU1701_SERICTL_I2S 0 8762306a36Sopenharmony_ci#define ADAU1701_SERICTL_LEFTJ 1 8862306a36Sopenharmony_ci#define ADAU1701_SERICTL_TDM 2 8962306a36Sopenharmony_ci#define ADAU1701_SERICTL_RIGHTJ_24 3 9062306a36Sopenharmony_ci#define ADAU1701_SERICTL_RIGHTJ_20 4 9162306a36Sopenharmony_ci#define ADAU1701_SERICTL_RIGHTJ_18 5 9262306a36Sopenharmony_ci#define ADAU1701_SERICTL_RIGHTJ_16 6 9362306a36Sopenharmony_ci#define ADAU1701_SERICTL_MODE_MASK 7 9462306a36Sopenharmony_ci#define ADAU1701_SERICTL_INV_BCLK BIT(3) 9562306a36Sopenharmony_ci#define ADAU1701_SERICTL_INV_LRCLK BIT(4) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define ADAU1701_OSCIPOW_OPD 0x04 9862306a36Sopenharmony_ci#define ADAU1701_DACSET_DACINIT 1 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define ADAU1707_CLKDIV_UNSET (-1U) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define ADAU1701_FIRMWARE "adau1701.bin" 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic const char * const supply_names[] = { 10562306a36Sopenharmony_ci "dvdd", "avdd" 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistruct adau1701 { 10962306a36Sopenharmony_ci struct gpio_desc *gpio_nreset; 11062306a36Sopenharmony_ci struct gpio_descs *gpio_pll_mode; 11162306a36Sopenharmony_ci unsigned int dai_fmt; 11262306a36Sopenharmony_ci unsigned int pll_clkdiv; 11362306a36Sopenharmony_ci unsigned int sysclk; 11462306a36Sopenharmony_ci struct regmap *regmap; 11562306a36Sopenharmony_ci struct i2c_client *client; 11662306a36Sopenharmony_ci u8 pin_config[12]; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci struct sigmadsp *sigmadsp; 11962306a36Sopenharmony_ci struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic const struct snd_kcontrol_new adau1701_controls[] = { 12362306a36Sopenharmony_ci SOC_SINGLE("Master Capture Switch", ADAU1701_DSPCTRL, 4, 1, 0), 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget adau1701_dapm_widgets[] = { 12762306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC0", "Playback", ADAU1701_AUXNPOW, 3, 1), 12862306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC1", "Playback", ADAU1701_AUXNPOW, 2, 1), 12962306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC2", "Playback", ADAU1701_AUXNPOW, 1, 1), 13062306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC3", "Playback", ADAU1701_AUXNPOW, 0, 1), 13162306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC", "Capture", ADAU1701_AUXNPOW, 7, 1), 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT0"), 13462306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT1"), 13562306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT2"), 13662306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT3"), 13762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("IN0"), 13862306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("IN1"), 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic const struct snd_soc_dapm_route adau1701_dapm_routes[] = { 14262306a36Sopenharmony_ci { "OUT0", NULL, "DAC0" }, 14362306a36Sopenharmony_ci { "OUT1", NULL, "DAC1" }, 14462306a36Sopenharmony_ci { "OUT2", NULL, "DAC2" }, 14562306a36Sopenharmony_ci { "OUT3", NULL, "DAC3" }, 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci { "ADC", NULL, "IN0" }, 14862306a36Sopenharmony_ci { "ADC", NULL, "IN1" }, 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic unsigned int adau1701_register_size(struct device *dev, 15262306a36Sopenharmony_ci unsigned int reg) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci switch (reg) { 15562306a36Sopenharmony_ci case ADAU1701_PINCONF_0: 15662306a36Sopenharmony_ci case ADAU1701_PINCONF_1: 15762306a36Sopenharmony_ci return 3; 15862306a36Sopenharmony_ci case ADAU1701_DSPCTRL: 15962306a36Sopenharmony_ci case ADAU1701_SEROCTL: 16062306a36Sopenharmony_ci case ADAU1701_AUXNPOW: 16162306a36Sopenharmony_ci case ADAU1701_OSCIPOW: 16262306a36Sopenharmony_ci case ADAU1701_DACSET: 16362306a36Sopenharmony_ci return 2; 16462306a36Sopenharmony_ci case ADAU1701_SERICTL: 16562306a36Sopenharmony_ci return 1; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci dev_err(dev, "Unsupported register address: %d\n", reg); 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic bool adau1701_volatile_reg(struct device *dev, unsigned int reg) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci switch (reg) { 17562306a36Sopenharmony_ci case ADAU1701_DACSET: 17662306a36Sopenharmony_ci case ADAU1701_DSPCTRL: 17762306a36Sopenharmony_ci return true; 17862306a36Sopenharmony_ci default: 17962306a36Sopenharmony_ci return false; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int adau1701_reg_write(void *context, unsigned int reg, 18462306a36Sopenharmony_ci unsigned int value) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct i2c_client *client = context; 18762306a36Sopenharmony_ci unsigned int i; 18862306a36Sopenharmony_ci unsigned int size; 18962306a36Sopenharmony_ci uint8_t buf[5]; 19062306a36Sopenharmony_ci int ret; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci size = adau1701_register_size(&client->dev, reg); 19362306a36Sopenharmony_ci if (size == 0) 19462306a36Sopenharmony_ci return -EINVAL; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci buf[0] = reg >> 8; 19762306a36Sopenharmony_ci buf[1] = reg & 0xff; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci for (i = size + 1; i >= 2; --i) { 20062306a36Sopenharmony_ci buf[i] = value; 20162306a36Sopenharmony_ci value >>= 8; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci ret = i2c_master_send(client, buf, size + 2); 20562306a36Sopenharmony_ci if (ret == size + 2) 20662306a36Sopenharmony_ci return 0; 20762306a36Sopenharmony_ci else if (ret < 0) 20862306a36Sopenharmony_ci return ret; 20962306a36Sopenharmony_ci else 21062306a36Sopenharmony_ci return -EIO; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic int adau1701_reg_read(void *context, unsigned int reg, 21462306a36Sopenharmony_ci unsigned int *value) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci int ret; 21762306a36Sopenharmony_ci unsigned int i; 21862306a36Sopenharmony_ci unsigned int size; 21962306a36Sopenharmony_ci uint8_t send_buf[2], recv_buf[3]; 22062306a36Sopenharmony_ci struct i2c_client *client = context; 22162306a36Sopenharmony_ci struct i2c_msg msgs[2]; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci size = adau1701_register_size(&client->dev, reg); 22462306a36Sopenharmony_ci if (size == 0) 22562306a36Sopenharmony_ci return -EINVAL; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci send_buf[0] = reg >> 8; 22862306a36Sopenharmony_ci send_buf[1] = reg & 0xff; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci msgs[0].addr = client->addr; 23162306a36Sopenharmony_ci msgs[0].len = sizeof(send_buf); 23262306a36Sopenharmony_ci msgs[0].buf = send_buf; 23362306a36Sopenharmony_ci msgs[0].flags = 0; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci msgs[1].addr = client->addr; 23662306a36Sopenharmony_ci msgs[1].len = size; 23762306a36Sopenharmony_ci msgs[1].buf = recv_buf; 23862306a36Sopenharmony_ci msgs[1].flags = I2C_M_RD; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 24162306a36Sopenharmony_ci if (ret < 0) 24262306a36Sopenharmony_ci return ret; 24362306a36Sopenharmony_ci else if (ret != ARRAY_SIZE(msgs)) 24462306a36Sopenharmony_ci return -EIO; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci *value = 0; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci for (i = 0; i < size; i++) { 24962306a36Sopenharmony_ci *value <<= 8; 25062306a36Sopenharmony_ci *value |= recv_buf[i]; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int adau1701_safeload(struct sigmadsp *sigmadsp, unsigned int addr, 25762306a36Sopenharmony_ci const uint8_t bytes[], size_t len) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct i2c_client *client = to_i2c_client(sigmadsp->dev); 26062306a36Sopenharmony_ci struct adau1701 *adau1701 = i2c_get_clientdata(client); 26162306a36Sopenharmony_ci unsigned int val; 26262306a36Sopenharmony_ci unsigned int i; 26362306a36Sopenharmony_ci uint8_t buf[10]; 26462306a36Sopenharmony_ci int ret; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci ret = regmap_read(adau1701->regmap, ADAU1701_DSPCTRL, &val); 26762306a36Sopenharmony_ci if (ret) 26862306a36Sopenharmony_ci return ret; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (val & ADAU1701_DSPCTRL_IST) 27162306a36Sopenharmony_ci msleep(50); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci for (i = 0; i < len / 4; i++) { 27462306a36Sopenharmony_ci put_unaligned_le16(ADAU1701_SAFELOAD_DATA(i), buf); 27562306a36Sopenharmony_ci buf[2] = 0x00; 27662306a36Sopenharmony_ci memcpy(buf + 3, bytes + i * 4, 4); 27762306a36Sopenharmony_ci ret = i2c_master_send(client, buf, 7); 27862306a36Sopenharmony_ci if (ret < 0) 27962306a36Sopenharmony_ci return ret; 28062306a36Sopenharmony_ci else if (ret != 7) 28162306a36Sopenharmony_ci return -EIO; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci put_unaligned_le16(ADAU1701_SAFELOAD_ADDR(i), buf); 28462306a36Sopenharmony_ci put_unaligned_le16(addr + i, buf + 2); 28562306a36Sopenharmony_ci ret = i2c_master_send(client, buf, 4); 28662306a36Sopenharmony_ci if (ret < 0) 28762306a36Sopenharmony_ci return ret; 28862306a36Sopenharmony_ci else if (ret != 4) 28962306a36Sopenharmony_ci return -EIO; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, 29362306a36Sopenharmony_ci ADAU1701_DSPCTRL_IST, ADAU1701_DSPCTRL_IST); 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic const struct sigmadsp_ops adau1701_sigmadsp_ops = { 29762306a36Sopenharmony_ci .safeload = adau1701_safeload, 29862306a36Sopenharmony_ci}; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int adau1701_reset(struct snd_soc_component *component, unsigned int clkdiv, 30162306a36Sopenharmony_ci unsigned int rate) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 30462306a36Sopenharmony_ci int ret; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci DECLARE_BITMAP(values, 2); 30762306a36Sopenharmony_ci sigmadsp_reset(adau1701->sigmadsp); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (clkdiv != ADAU1707_CLKDIV_UNSET && adau1701->gpio_pll_mode) { 31062306a36Sopenharmony_ci switch (clkdiv) { 31162306a36Sopenharmony_ci case 64: 31262306a36Sopenharmony_ci __assign_bit(0, values, 0); 31362306a36Sopenharmony_ci __assign_bit(1, values, 0); 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci case 256: 31662306a36Sopenharmony_ci __assign_bit(0, values, 0); 31762306a36Sopenharmony_ci __assign_bit(1, values, 1); 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci case 384: 32062306a36Sopenharmony_ci __assign_bit(0, values, 1); 32162306a36Sopenharmony_ci __assign_bit(1, values, 0); 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case 0: /* fallback */ 32462306a36Sopenharmony_ci case 512: 32562306a36Sopenharmony_ci __assign_bit(0, values, 1); 32662306a36Sopenharmony_ci __assign_bit(1, values, 1); 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci gpiod_set_array_value_cansleep(adau1701->gpio_pll_mode->ndescs, 33062306a36Sopenharmony_ci adau1701->gpio_pll_mode->desc, adau1701->gpio_pll_mode->info, 33162306a36Sopenharmony_ci values); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci adau1701->pll_clkdiv = clkdiv; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (adau1701->gpio_nreset) { 33762306a36Sopenharmony_ci gpiod_set_value_cansleep(adau1701->gpio_nreset, 0); 33862306a36Sopenharmony_ci /* minimum reset time is 20ns */ 33962306a36Sopenharmony_ci udelay(1); 34062306a36Sopenharmony_ci gpiod_set_value_cansleep(adau1701->gpio_nreset, 1); 34162306a36Sopenharmony_ci /* power-up time may be as long as 85ms */ 34262306a36Sopenharmony_ci mdelay(85); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * Postpone the firmware download to a point in time when we 34762306a36Sopenharmony_ci * know the correct PLL setup 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci if (clkdiv != ADAU1707_CLKDIV_UNSET) { 35062306a36Sopenharmony_ci ret = sigmadsp_setup(adau1701->sigmadsp, rate); 35162306a36Sopenharmony_ci if (ret) { 35262306a36Sopenharmony_ci dev_warn(component->dev, "Failed to load firmware\n"); 35362306a36Sopenharmony_ci return ret; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci regmap_write(adau1701->regmap, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); 35862306a36Sopenharmony_ci regmap_write(adau1701->regmap, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci regcache_mark_dirty(adau1701->regmap); 36162306a36Sopenharmony_ci regcache_sync(adau1701->regmap); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int adau1701_set_capture_pcm_format(struct snd_soc_component *component, 36762306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 37062306a36Sopenharmony_ci unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; 37162306a36Sopenharmony_ci unsigned int val; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci switch (params_width(params)) { 37462306a36Sopenharmony_ci case 16: 37562306a36Sopenharmony_ci val = ADAU1701_SEROCTL_WORD_LEN_16; 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci case 20: 37862306a36Sopenharmony_ci val = ADAU1701_SEROCTL_WORD_LEN_20; 37962306a36Sopenharmony_ci break; 38062306a36Sopenharmony_ci case 24: 38162306a36Sopenharmony_ci val = ADAU1701_SEROCTL_WORD_LEN_24; 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci default: 38462306a36Sopenharmony_ci return -EINVAL; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { 38862306a36Sopenharmony_ci switch (params_width(params)) { 38962306a36Sopenharmony_ci case 16: 39062306a36Sopenharmony_ci val |= ADAU1701_SEROCTL_MSB_DEALY16; 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case 20: 39362306a36Sopenharmony_ci val |= ADAU1701_SEROCTL_MSB_DEALY12; 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci case 24: 39662306a36Sopenharmony_ci val |= ADAU1701_SEROCTL_MSB_DEALY8; 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, mask, val); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic int adau1701_set_playback_pcm_format(struct snd_soc_component *component, 40862306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 41162306a36Sopenharmony_ci unsigned int val; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) 41462306a36Sopenharmony_ci return 0; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci switch (params_width(params)) { 41762306a36Sopenharmony_ci case 16: 41862306a36Sopenharmony_ci val = ADAU1701_SERICTL_RIGHTJ_16; 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci case 20: 42162306a36Sopenharmony_ci val = ADAU1701_SERICTL_RIGHTJ_20; 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci case 24: 42462306a36Sopenharmony_ci val = ADAU1701_SERICTL_RIGHTJ_24; 42562306a36Sopenharmony_ci break; 42662306a36Sopenharmony_ci default: 42762306a36Sopenharmony_ci return -EINVAL; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_SERICTL, 43162306a36Sopenharmony_ci ADAU1701_SERICTL_MODE_MASK, val); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci return 0; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int adau1701_hw_params(struct snd_pcm_substream *substream, 43762306a36Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 44062306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 44162306a36Sopenharmony_ci unsigned int clkdiv = adau1701->sysclk / params_rate(params); 44262306a36Sopenharmony_ci unsigned int val; 44362306a36Sopenharmony_ci int ret; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* 44662306a36Sopenharmony_ci * If the mclk/lrclk ratio changes, the chip needs updated PLL 44762306a36Sopenharmony_ci * mode GPIO settings, and a full reset cycle, including a new 44862306a36Sopenharmony_ci * firmware upload. 44962306a36Sopenharmony_ci */ 45062306a36Sopenharmony_ci if (clkdiv != adau1701->pll_clkdiv) { 45162306a36Sopenharmony_ci ret = adau1701_reset(component, clkdiv, params_rate(params)); 45262306a36Sopenharmony_ci if (ret < 0) 45362306a36Sopenharmony_ci return ret; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci switch (params_rate(params)) { 45762306a36Sopenharmony_ci case 192000: 45862306a36Sopenharmony_ci val = ADAU1701_DSPCTRL_SR_192; 45962306a36Sopenharmony_ci break; 46062306a36Sopenharmony_ci case 96000: 46162306a36Sopenharmony_ci val = ADAU1701_DSPCTRL_SR_96; 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci case 48000: 46462306a36Sopenharmony_ci val = ADAU1701_DSPCTRL_SR_48; 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci default: 46762306a36Sopenharmony_ci return -EINVAL; 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, 47162306a36Sopenharmony_ci ADAU1701_DSPCTRL_SR_MASK, val); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 47462306a36Sopenharmony_ci return adau1701_set_playback_pcm_format(component, params); 47562306a36Sopenharmony_ci else 47662306a36Sopenharmony_ci return adau1701_set_capture_pcm_format(component, params); 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, 48062306a36Sopenharmony_ci unsigned int fmt) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 48362306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 48462306a36Sopenharmony_ci unsigned int serictl = 0x00, seroctl = 0x00; 48562306a36Sopenharmony_ci bool invert_lrclk; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 48862306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFP: 48962306a36Sopenharmony_ci /* master, 64-bits per sample, 1 frame per sample */ 49062306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 49162306a36Sopenharmony_ci | ADAU1701_SEROCTL_OLF1024; 49262306a36Sopenharmony_ci break; 49362306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci default: 49662306a36Sopenharmony_ci return -EINVAL; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci /* clock inversion */ 50062306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 50162306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 50262306a36Sopenharmony_ci invert_lrclk = false; 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 50562306a36Sopenharmony_ci invert_lrclk = true; 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 50862306a36Sopenharmony_ci invert_lrclk = false; 50962306a36Sopenharmony_ci serictl |= ADAU1701_SERICTL_INV_BCLK; 51062306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_INV_BCLK; 51162306a36Sopenharmony_ci break; 51262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 51362306a36Sopenharmony_ci invert_lrclk = true; 51462306a36Sopenharmony_ci serictl |= ADAU1701_SERICTL_INV_BCLK; 51562306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_INV_BCLK; 51662306a36Sopenharmony_ci break; 51762306a36Sopenharmony_ci default: 51862306a36Sopenharmony_ci return -EINVAL; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 52262306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 52562306a36Sopenharmony_ci serictl |= ADAU1701_SERICTL_LEFTJ; 52662306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_MSB_DEALY0; 52762306a36Sopenharmony_ci invert_lrclk = !invert_lrclk; 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 53062306a36Sopenharmony_ci serictl |= ADAU1701_SERICTL_RIGHTJ_24; 53162306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_MSB_DEALY8; 53262306a36Sopenharmony_ci invert_lrclk = !invert_lrclk; 53362306a36Sopenharmony_ci break; 53462306a36Sopenharmony_ci default: 53562306a36Sopenharmony_ci return -EINVAL; 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (invert_lrclk) { 53962306a36Sopenharmony_ci seroctl |= ADAU1701_SEROCTL_INV_LRCLK; 54062306a36Sopenharmony_ci serictl |= ADAU1701_SERICTL_INV_LRCLK; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl); 54662306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, 54762306a36Sopenharmony_ci ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci return 0; 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_cistatic int adau1701_set_bias_level(struct snd_soc_component *component, 55362306a36Sopenharmony_ci enum snd_soc_bias_level level) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; 55662306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci switch (level) { 55962306a36Sopenharmony_ci case SND_SOC_BIAS_ON: 56062306a36Sopenharmony_ci break; 56162306a36Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 56262306a36Sopenharmony_ci break; 56362306a36Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 56462306a36Sopenharmony_ci /* Enable VREF and VREF buffer */ 56562306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, 56662306a36Sopenharmony_ci ADAU1701_AUXNPOW, mask, 0x00); 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case SND_SOC_BIAS_OFF: 56962306a36Sopenharmony_ci /* Disable VREF and VREF buffer */ 57062306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, 57162306a36Sopenharmony_ci ADAU1701_AUXNPOW, mask, mask); 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return 0; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic int adau1701_mute_stream(struct snd_soc_dai *dai, int mute, int direction) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 58162306a36Sopenharmony_ci unsigned int mask = ADAU1701_DSPCTRL_DAM; 58262306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 58362306a36Sopenharmony_ci unsigned int val; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (mute) 58662306a36Sopenharmony_ci val = 0; 58762306a36Sopenharmony_ci else 58862306a36Sopenharmony_ci val = mask; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, mask, val); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci return 0; 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic int adau1701_set_sysclk(struct snd_soc_component *component, int clk_id, 59662306a36Sopenharmony_ci int source, unsigned int freq, int dir) 59762306a36Sopenharmony_ci{ 59862306a36Sopenharmony_ci unsigned int val; 59962306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci switch (clk_id) { 60262306a36Sopenharmony_ci case ADAU1701_CLK_SRC_OSC: 60362306a36Sopenharmony_ci val = 0x0; 60462306a36Sopenharmony_ci break; 60562306a36Sopenharmony_ci case ADAU1701_CLK_SRC_MCLK: 60662306a36Sopenharmony_ci val = ADAU1701_OSCIPOW_OPD; 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci default: 60962306a36Sopenharmony_ci return -EINVAL; 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci regmap_update_bits(adau1701->regmap, ADAU1701_OSCIPOW, 61362306a36Sopenharmony_ci ADAU1701_OSCIPOW_OPD, val); 61462306a36Sopenharmony_ci adau1701->sysclk = freq; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci return 0; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic int adau1701_startup(struct snd_pcm_substream *substream, 62062306a36Sopenharmony_ci struct snd_soc_dai *dai) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(dai->component); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci return sigmadsp_restrict_params(adau1701->sigmadsp, substream); 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci#define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ 62862306a36Sopenharmony_ci SNDRV_PCM_RATE_192000) 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci#define ADAU1701_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 63162306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE) 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic const struct snd_soc_dai_ops adau1701_dai_ops = { 63462306a36Sopenharmony_ci .set_fmt = adau1701_set_dai_fmt, 63562306a36Sopenharmony_ci .hw_params = adau1701_hw_params, 63662306a36Sopenharmony_ci .mute_stream = adau1701_mute_stream, 63762306a36Sopenharmony_ci .startup = adau1701_startup, 63862306a36Sopenharmony_ci .no_capture_mute = 1, 63962306a36Sopenharmony_ci}; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic struct snd_soc_dai_driver adau1701_dai = { 64262306a36Sopenharmony_ci .name = "adau1701", 64362306a36Sopenharmony_ci .playback = { 64462306a36Sopenharmony_ci .stream_name = "Playback", 64562306a36Sopenharmony_ci .channels_min = 2, 64662306a36Sopenharmony_ci .channels_max = 8, 64762306a36Sopenharmony_ci .rates = ADAU1701_RATES, 64862306a36Sopenharmony_ci .formats = ADAU1701_FORMATS, 64962306a36Sopenharmony_ci }, 65062306a36Sopenharmony_ci .capture = { 65162306a36Sopenharmony_ci .stream_name = "Capture", 65262306a36Sopenharmony_ci .channels_min = 2, 65362306a36Sopenharmony_ci .channels_max = 8, 65462306a36Sopenharmony_ci .rates = ADAU1701_RATES, 65562306a36Sopenharmony_ci .formats = ADAU1701_FORMATS, 65662306a36Sopenharmony_ci }, 65762306a36Sopenharmony_ci .ops = &adau1701_dai_ops, 65862306a36Sopenharmony_ci .symmetric_rate = 1, 65962306a36Sopenharmony_ci}; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci#ifdef CONFIG_OF 66262306a36Sopenharmony_cistatic const struct of_device_id adau1701_dt_ids[] = { 66362306a36Sopenharmony_ci { .compatible = "adi,adau1701", }, 66462306a36Sopenharmony_ci { } 66562306a36Sopenharmony_ci}; 66662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, adau1701_dt_ids); 66762306a36Sopenharmony_ci#endif 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic int adau1701_probe(struct snd_soc_component *component) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci int i, ret; 67262306a36Sopenharmony_ci unsigned int val; 67362306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci ret = sigmadsp_attach(adau1701->sigmadsp, component); 67662306a36Sopenharmony_ci if (ret) 67762306a36Sopenharmony_ci return ret; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), 68062306a36Sopenharmony_ci adau1701->supplies); 68162306a36Sopenharmony_ci if (ret < 0) { 68262306a36Sopenharmony_ci dev_err(component->dev, "Failed to enable regulators: %d\n", ret); 68362306a36Sopenharmony_ci return ret; 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* 68762306a36Sopenharmony_ci * Let the pll_clkdiv variable default to something that won't happen 68862306a36Sopenharmony_ci * at runtime. That way, we can postpone the firmware download from 68962306a36Sopenharmony_ci * adau1701_reset() to a point in time when we know the correct PLL 69062306a36Sopenharmony_ci * mode parameters. 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ci adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci /* initalize with pre-configured pll mode settings */ 69562306a36Sopenharmony_ci ret = adau1701_reset(component, adau1701->pll_clkdiv, 0); 69662306a36Sopenharmony_ci if (ret < 0) 69762306a36Sopenharmony_ci goto exit_regulators_disable; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* set up pin config */ 70062306a36Sopenharmony_ci val = 0; 70162306a36Sopenharmony_ci for (i = 0; i < 6; i++) 70262306a36Sopenharmony_ci val |= adau1701->pin_config[i] << (i * 4); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci regmap_write(adau1701->regmap, ADAU1701_PINCONF_0, val); 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci val = 0; 70762306a36Sopenharmony_ci for (i = 0; i < 6; i++) 70862306a36Sopenharmony_ci val |= adau1701->pin_config[i + 6] << (i * 4); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci return 0; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ciexit_regulators_disable: 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); 71762306a36Sopenharmony_ci return ret; 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic void adau1701_remove(struct snd_soc_component *component) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (adau1701->gpio_nreset) 72562306a36Sopenharmony_ci gpiod_set_value_cansleep(adau1701->gpio_nreset, 0); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci#ifdef CONFIG_PM 73162306a36Sopenharmony_cistatic int adau1701_suspend(struct snd_soc_component *component) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), 73662306a36Sopenharmony_ci adau1701->supplies); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci return 0; 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_cistatic int adau1701_resume(struct snd_soc_component *component) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci struct adau1701 *adau1701 = snd_soc_component_get_drvdata(component); 74462306a36Sopenharmony_ci int ret; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), 74762306a36Sopenharmony_ci adau1701->supplies); 74862306a36Sopenharmony_ci if (ret < 0) { 74962306a36Sopenharmony_ci dev_err(component->dev, "Failed to enable regulators: %d\n", ret); 75062306a36Sopenharmony_ci return ret; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci return adau1701_reset(component, adau1701->pll_clkdiv, 0); 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci#else 75662306a36Sopenharmony_ci#define adau1701_resume NULL 75762306a36Sopenharmony_ci#define adau1701_suspend NULL 75862306a36Sopenharmony_ci#endif /* CONFIG_PM */ 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic const struct snd_soc_component_driver adau1701_component_drv = { 76162306a36Sopenharmony_ci .probe = adau1701_probe, 76262306a36Sopenharmony_ci .remove = adau1701_remove, 76362306a36Sopenharmony_ci .resume = adau1701_resume, 76462306a36Sopenharmony_ci .suspend = adau1701_suspend, 76562306a36Sopenharmony_ci .set_bias_level = adau1701_set_bias_level, 76662306a36Sopenharmony_ci .controls = adau1701_controls, 76762306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(adau1701_controls), 76862306a36Sopenharmony_ci .dapm_widgets = adau1701_dapm_widgets, 76962306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), 77062306a36Sopenharmony_ci .dapm_routes = adau1701_dapm_routes, 77162306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), 77262306a36Sopenharmony_ci .set_sysclk = adau1701_set_sysclk, 77362306a36Sopenharmony_ci .use_pmdown_time = 1, 77462306a36Sopenharmony_ci .endianness = 1, 77562306a36Sopenharmony_ci}; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cistatic const struct regmap_config adau1701_regmap = { 77862306a36Sopenharmony_ci .reg_bits = 16, 77962306a36Sopenharmony_ci .val_bits = 32, 78062306a36Sopenharmony_ci .max_register = ADAU1701_MAX_REGISTER, 78162306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 78262306a36Sopenharmony_ci .volatile_reg = adau1701_volatile_reg, 78362306a36Sopenharmony_ci .reg_write = adau1701_reg_write, 78462306a36Sopenharmony_ci .reg_read = adau1701_reg_read, 78562306a36Sopenharmony_ci}; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic int adau1701_i2c_probe(struct i2c_client *client) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct adau1701 *adau1701; 79062306a36Sopenharmony_ci struct device *dev = &client->dev; 79162306a36Sopenharmony_ci int ret, i; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); 79462306a36Sopenharmony_ci if (!adau1701) 79562306a36Sopenharmony_ci return -ENOMEM; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(supply_names); i++) 79862306a36Sopenharmony_ci adau1701->supplies[i].supply = supply_names[i]; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(adau1701->supplies), 80162306a36Sopenharmony_ci adau1701->supplies); 80262306a36Sopenharmony_ci if (ret < 0) { 80362306a36Sopenharmony_ci dev_err(dev, "Failed to get regulators: %d\n", ret); 80462306a36Sopenharmony_ci return ret; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), 80862306a36Sopenharmony_ci adau1701->supplies); 80962306a36Sopenharmony_ci if (ret < 0) { 81062306a36Sopenharmony_ci dev_err(dev, "Failed to enable regulators: %d\n", ret); 81162306a36Sopenharmony_ci return ret; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci adau1701->client = client; 81562306a36Sopenharmony_ci adau1701->regmap = devm_regmap_init(dev, NULL, client, 81662306a36Sopenharmony_ci &adau1701_regmap); 81762306a36Sopenharmony_ci if (IS_ERR(adau1701->regmap)) { 81862306a36Sopenharmony_ci ret = PTR_ERR(adau1701->regmap); 81962306a36Sopenharmony_ci goto exit_regulators_disable; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (dev->of_node) { 82462306a36Sopenharmony_ci of_property_read_u32(dev->of_node, "adi,pll-clkdiv", 82562306a36Sopenharmony_ci &adau1701->pll_clkdiv); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci of_property_read_u8_array(dev->of_node, "adi,pin-config", 82862306a36Sopenharmony_ci adau1701->pin_config, 82962306a36Sopenharmony_ci ARRAY_SIZE(adau1701->pin_config)); 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci adau1701->gpio_nreset = devm_gpiod_get_optional(dev, "reset", GPIOD_IN); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci if (IS_ERR(adau1701->gpio_nreset)) { 83562306a36Sopenharmony_ci ret = PTR_ERR(adau1701->gpio_nreset); 83662306a36Sopenharmony_ci goto exit_regulators_disable; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci adau1701->gpio_pll_mode = devm_gpiod_get_array_optional(dev, "adi,pll-mode", GPIOD_OUT_LOW); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (IS_ERR(adau1701->gpio_pll_mode)) { 84262306a36Sopenharmony_ci ret = PTR_ERR(adau1701->gpio_pll_mode); 84362306a36Sopenharmony_ci goto exit_regulators_disable; 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci i2c_set_clientdata(client, adau1701); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, 84962306a36Sopenharmony_ci &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); 85062306a36Sopenharmony_ci if (IS_ERR(adau1701->sigmadsp)) { 85162306a36Sopenharmony_ci ret = PTR_ERR(adau1701->sigmadsp); 85262306a36Sopenharmony_ci goto exit_regulators_disable; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&client->dev, 85662306a36Sopenharmony_ci &adau1701_component_drv, 85762306a36Sopenharmony_ci &adau1701_dai, 1); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ciexit_regulators_disable: 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); 86262306a36Sopenharmony_ci return ret; 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistatic const struct i2c_device_id adau1701_i2c_id[] = { 86662306a36Sopenharmony_ci { "adau1401", 0 }, 86762306a36Sopenharmony_ci { "adau1401a", 0 }, 86862306a36Sopenharmony_ci { "adau1701", 0 }, 86962306a36Sopenharmony_ci { "adau1702", 0 }, 87062306a36Sopenharmony_ci { } 87162306a36Sopenharmony_ci}; 87262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_cistatic struct i2c_driver adau1701_i2c_driver = { 87562306a36Sopenharmony_ci .driver = { 87662306a36Sopenharmony_ci .name = "adau1701", 87762306a36Sopenharmony_ci .of_match_table = of_match_ptr(adau1701_dt_ids), 87862306a36Sopenharmony_ci }, 87962306a36Sopenharmony_ci .probe = adau1701_i2c_probe, 88062306a36Sopenharmony_ci .id_table = adau1701_i2c_id, 88162306a36Sopenharmony_ci}; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cimodule_i2c_driver(adau1701_i2c_driver); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); 88662306a36Sopenharmony_ciMODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); 88762306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 88862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 889