13333cb71SPaul Handrigan /* 23333cb71SPaul Handrigan * cs35l33.c -- CS35L33 ALSA SoC audio driver 33333cb71SPaul Handrigan * 43333cb71SPaul Handrigan * Copyright 2016 Cirrus Logic, Inc. 53333cb71SPaul Handrigan * 63333cb71SPaul Handrigan * Author: Paul Handrigan <paul.handrigan@cirrus.com> 73333cb71SPaul Handrigan * 83333cb71SPaul Handrigan * This program is free software; you can redistribute it and/or modify 93333cb71SPaul Handrigan * it under the terms of the GNU General Public License version 2 as 103333cb71SPaul Handrigan * published by the Free Software Foundation. 113333cb71SPaul Handrigan * 123333cb71SPaul Handrigan */ 133333cb71SPaul Handrigan #include <linux/module.h> 143333cb71SPaul Handrigan #include <linux/moduleparam.h> 153333cb71SPaul Handrigan #include <linux/kernel.h> 163333cb71SPaul Handrigan #include <linux/init.h> 173333cb71SPaul Handrigan #include <linux/delay.h> 183333cb71SPaul Handrigan #include <linux/i2c.h> 193333cb71SPaul Handrigan #include <linux/slab.h> 203333cb71SPaul Handrigan #include <linux/workqueue.h> 213333cb71SPaul Handrigan #include <linux/platform_device.h> 223333cb71SPaul Handrigan #include <sound/core.h> 233333cb71SPaul Handrigan #include <sound/pcm.h> 243333cb71SPaul Handrigan #include <sound/pcm_params.h> 253333cb71SPaul Handrigan #include <sound/soc.h> 263333cb71SPaul Handrigan #include <sound/soc-dapm.h> 273333cb71SPaul Handrigan #include <sound/initval.h> 283333cb71SPaul Handrigan #include <sound/tlv.h> 293333cb71SPaul Handrigan #include <linux/gpio.h> 303333cb71SPaul Handrigan #include <linux/gpio/consumer.h> 313333cb71SPaul Handrigan #include <sound/cs35l33.h> 323333cb71SPaul Handrigan #include <linux/pm_runtime.h> 333333cb71SPaul Handrigan #include <linux/regulator/consumer.h> 343333cb71SPaul Handrigan #include <linux/regulator/machine.h> 353333cb71SPaul Handrigan #include <linux/of_gpio.h> 363333cb71SPaul Handrigan #include <linux/of.h> 373333cb71SPaul Handrigan #include <linux/of_device.h> 383333cb71SPaul Handrigan #include <linux/of_irq.h> 393333cb71SPaul Handrigan 403333cb71SPaul Handrigan #include "cs35l33.h" 413333cb71SPaul Handrigan 423333cb71SPaul Handrigan #define CS35L33_BOOT_DELAY 50 433333cb71SPaul Handrigan 443333cb71SPaul Handrigan struct cs35l33_private { 45cefcf594SKuninori Morimoto struct snd_soc_component *component; 463333cb71SPaul Handrigan struct cs35l33_pdata pdata; 473333cb71SPaul Handrigan struct regmap *regmap; 483333cb71SPaul Handrigan struct gpio_desc *reset_gpio; 493333cb71SPaul Handrigan bool amp_cal; 503333cb71SPaul Handrigan int mclk_int; 513333cb71SPaul Handrigan struct regulator_bulk_data core_supplies[2]; 523333cb71SPaul Handrigan int num_core_supplies; 533333cb71SPaul Handrigan bool is_tdm_mode; 543333cb71SPaul Handrigan bool enable_soft_ramp; 553333cb71SPaul Handrigan }; 563333cb71SPaul Handrigan 573333cb71SPaul Handrigan static const struct reg_default cs35l33_reg[] = { 583333cb71SPaul Handrigan {CS35L33_PWRCTL1, 0x85}, 593333cb71SPaul Handrigan {CS35L33_PWRCTL2, 0xFE}, 603333cb71SPaul Handrigan {CS35L33_CLK_CTL, 0x0C}, 613333cb71SPaul Handrigan {CS35L33_BST_PEAK_CTL, 0x90}, 623333cb71SPaul Handrigan {CS35L33_PROTECT_CTL, 0x55}, 633333cb71SPaul Handrigan {CS35L33_BST_CTL1, 0x00}, 643333cb71SPaul Handrigan {CS35L33_BST_CTL2, 0x01}, 653333cb71SPaul Handrigan {CS35L33_ADSP_CTL, 0x00}, 663333cb71SPaul Handrigan {CS35L33_ADC_CTL, 0xC8}, 673333cb71SPaul Handrigan {CS35L33_DAC_CTL, 0x14}, 683333cb71SPaul Handrigan {CS35L33_DIG_VOL_CTL, 0x00}, 693333cb71SPaul Handrigan {CS35L33_CLASSD_CTL, 0x04}, 703333cb71SPaul Handrigan {CS35L33_AMP_CTL, 0x90}, 713333cb71SPaul Handrigan {CS35L33_INT_MASK_1, 0xFF}, 723333cb71SPaul Handrigan {CS35L33_INT_MASK_2, 0xFF}, 733333cb71SPaul Handrigan {CS35L33_DIAG_LOCK, 0x00}, 743333cb71SPaul Handrigan {CS35L33_DIAG_CTRL_1, 0x40}, 753333cb71SPaul Handrigan {CS35L33_DIAG_CTRL_2, 0x00}, 763333cb71SPaul Handrigan {CS35L33_HG_MEMLDO_CTL, 0x62}, 773333cb71SPaul Handrigan {CS35L33_HG_REL_RATE, 0x03}, 783333cb71SPaul Handrigan {CS35L33_LDO_DEL, 0x12}, 793333cb71SPaul Handrigan {CS35L33_HG_HEAD, 0x0A}, 803333cb71SPaul Handrigan {CS35L33_HG_EN, 0x05}, 813333cb71SPaul Handrigan {CS35L33_TX_VMON, 0x00}, 823333cb71SPaul Handrigan {CS35L33_TX_IMON, 0x03}, 833333cb71SPaul Handrigan {CS35L33_TX_VPMON, 0x02}, 843333cb71SPaul Handrigan {CS35L33_TX_VBSTMON, 0x05}, 853333cb71SPaul Handrigan {CS35L33_TX_FLAG, 0x06}, 863333cb71SPaul Handrigan {CS35L33_TX_EN1, 0x00}, 873333cb71SPaul Handrigan {CS35L33_TX_EN2, 0x00}, 883333cb71SPaul Handrigan {CS35L33_TX_EN3, 0x00}, 893333cb71SPaul Handrigan {CS35L33_TX_EN4, 0x00}, 903333cb71SPaul Handrigan {CS35L33_RX_AUD, 0x40}, 913333cb71SPaul Handrigan {CS35L33_RX_SPLY, 0x03}, 923333cb71SPaul Handrigan {CS35L33_RX_ALIVE, 0x04}, 933333cb71SPaul Handrigan {CS35L33_BST_CTL4, 0x63}, 943333cb71SPaul Handrigan }; 953333cb71SPaul Handrigan 963333cb71SPaul Handrigan static const struct reg_sequence cs35l33_patch[] = { 973333cb71SPaul Handrigan { 0x00, 0x99, 0 }, 983333cb71SPaul Handrigan { 0x59, 0x02, 0 }, 993333cb71SPaul Handrigan { 0x52, 0x30, 0 }, 1003333cb71SPaul Handrigan { 0x39, 0x45, 0 }, 1013333cb71SPaul Handrigan { 0x57, 0x30, 0 }, 1023333cb71SPaul Handrigan { 0x2C, 0x68, 0 }, 1033333cb71SPaul Handrigan { 0x00, 0x00, 0 }, 1043333cb71SPaul Handrigan }; 1053333cb71SPaul Handrigan 1063333cb71SPaul Handrigan static bool cs35l33_volatile_register(struct device *dev, unsigned int reg) 1073333cb71SPaul Handrigan { 1083333cb71SPaul Handrigan switch (reg) { 1093333cb71SPaul Handrigan case CS35L33_DEVID_AB: 1103333cb71SPaul Handrigan case CS35L33_DEVID_CD: 1113333cb71SPaul Handrigan case CS35L33_DEVID_E: 1123333cb71SPaul Handrigan case CS35L33_REV_ID: 1133333cb71SPaul Handrigan case CS35L33_INT_STATUS_1: 1143333cb71SPaul Handrigan case CS35L33_INT_STATUS_2: 1153333cb71SPaul Handrigan case CS35L33_HG_STATUS: 1163333cb71SPaul Handrigan return true; 1173333cb71SPaul Handrigan default: 1183333cb71SPaul Handrigan return false; 1193333cb71SPaul Handrigan } 1203333cb71SPaul Handrigan } 1213333cb71SPaul Handrigan 1223333cb71SPaul Handrigan static bool cs35l33_writeable_register(struct device *dev, unsigned int reg) 1233333cb71SPaul Handrigan { 1243333cb71SPaul Handrigan switch (reg) { 1253333cb71SPaul Handrigan /* these are read only registers */ 1263333cb71SPaul Handrigan case CS35L33_DEVID_AB: 1273333cb71SPaul Handrigan case CS35L33_DEVID_CD: 1283333cb71SPaul Handrigan case CS35L33_DEVID_E: 1293333cb71SPaul Handrigan case CS35L33_REV_ID: 1303333cb71SPaul Handrigan case CS35L33_INT_STATUS_1: 1313333cb71SPaul Handrigan case CS35L33_INT_STATUS_2: 1323333cb71SPaul Handrigan case CS35L33_HG_STATUS: 1333333cb71SPaul Handrigan return false; 1343333cb71SPaul Handrigan default: 1353333cb71SPaul Handrigan return true; 1363333cb71SPaul Handrigan } 1373333cb71SPaul Handrigan } 1383333cb71SPaul Handrigan 1393333cb71SPaul Handrigan static bool cs35l33_readable_register(struct device *dev, unsigned int reg) 1403333cb71SPaul Handrigan { 1413333cb71SPaul Handrigan switch (reg) { 1423333cb71SPaul Handrigan case CS35L33_DEVID_AB: 1433333cb71SPaul Handrigan case CS35L33_DEVID_CD: 1443333cb71SPaul Handrigan case CS35L33_DEVID_E: 1453333cb71SPaul Handrigan case CS35L33_REV_ID: 1463333cb71SPaul Handrigan case CS35L33_PWRCTL1: 1473333cb71SPaul Handrigan case CS35L33_PWRCTL2: 1483333cb71SPaul Handrigan case CS35L33_CLK_CTL: 1493333cb71SPaul Handrigan case CS35L33_BST_PEAK_CTL: 1503333cb71SPaul Handrigan case CS35L33_PROTECT_CTL: 1513333cb71SPaul Handrigan case CS35L33_BST_CTL1: 1523333cb71SPaul Handrigan case CS35L33_BST_CTL2: 1533333cb71SPaul Handrigan case CS35L33_ADSP_CTL: 1543333cb71SPaul Handrigan case CS35L33_ADC_CTL: 1553333cb71SPaul Handrigan case CS35L33_DAC_CTL: 1563333cb71SPaul Handrigan case CS35L33_DIG_VOL_CTL: 1573333cb71SPaul Handrigan case CS35L33_CLASSD_CTL: 1583333cb71SPaul Handrigan case CS35L33_AMP_CTL: 1593333cb71SPaul Handrigan case CS35L33_INT_MASK_1: 1603333cb71SPaul Handrigan case CS35L33_INT_MASK_2: 1613333cb71SPaul Handrigan case CS35L33_INT_STATUS_1: 1623333cb71SPaul Handrigan case CS35L33_INT_STATUS_2: 1633333cb71SPaul Handrigan case CS35L33_DIAG_LOCK: 1643333cb71SPaul Handrigan case CS35L33_DIAG_CTRL_1: 1653333cb71SPaul Handrigan case CS35L33_DIAG_CTRL_2: 1663333cb71SPaul Handrigan case CS35L33_HG_MEMLDO_CTL: 1673333cb71SPaul Handrigan case CS35L33_HG_REL_RATE: 1683333cb71SPaul Handrigan case CS35L33_LDO_DEL: 1693333cb71SPaul Handrigan case CS35L33_HG_HEAD: 1703333cb71SPaul Handrigan case CS35L33_HG_EN: 1713333cb71SPaul Handrigan case CS35L33_TX_VMON: 1723333cb71SPaul Handrigan case CS35L33_TX_IMON: 1733333cb71SPaul Handrigan case CS35L33_TX_VPMON: 1743333cb71SPaul Handrigan case CS35L33_TX_VBSTMON: 1753333cb71SPaul Handrigan case CS35L33_TX_FLAG: 1763333cb71SPaul Handrigan case CS35L33_TX_EN1: 1773333cb71SPaul Handrigan case CS35L33_TX_EN2: 1783333cb71SPaul Handrigan case CS35L33_TX_EN3: 1793333cb71SPaul Handrigan case CS35L33_TX_EN4: 1803333cb71SPaul Handrigan case CS35L33_RX_AUD: 1813333cb71SPaul Handrigan case CS35L33_RX_SPLY: 1823333cb71SPaul Handrigan case CS35L33_RX_ALIVE: 1833333cb71SPaul Handrigan case CS35L33_BST_CTL4: 1843333cb71SPaul Handrigan return true; 1853333cb71SPaul Handrigan default: 1863333cb71SPaul Handrigan return false; 1873333cb71SPaul Handrigan } 1883333cb71SPaul Handrigan } 1893333cb71SPaul Handrigan 1903333cb71SPaul Handrigan static DECLARE_TLV_DB_SCALE(classd_ctl_tlv, 900, 100, 0); 1913333cb71SPaul Handrigan static DECLARE_TLV_DB_SCALE(dac_tlv, -10200, 50, 0); 1923333cb71SPaul Handrigan 1933333cb71SPaul Handrigan static const struct snd_kcontrol_new cs35l33_snd_controls[] = { 1943333cb71SPaul Handrigan 1953333cb71SPaul Handrigan SOC_SINGLE_TLV("SPK Amp Volume", CS35L33_AMP_CTL, 1963333cb71SPaul Handrigan 4, 0x09, 0, classd_ctl_tlv), 1973333cb71SPaul Handrigan SOC_SINGLE_SX_TLV("DAC Volume", CS35L33_DIG_VOL_CTL, 1983333cb71SPaul Handrigan 0, 0x34, 0xE4, dac_tlv), 1993333cb71SPaul Handrigan }; 2003333cb71SPaul Handrigan 2013333cb71SPaul Handrigan static int cs35l33_spkrdrv_event(struct snd_soc_dapm_widget *w, 2023333cb71SPaul Handrigan struct snd_kcontrol *kcontrol, int event) 2033333cb71SPaul Handrigan { 204cefcf594SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 205cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 2063333cb71SPaul Handrigan 2073333cb71SPaul Handrigan switch (event) { 2083333cb71SPaul Handrigan case SND_SOC_DAPM_POST_PMU: 2093333cb71SPaul Handrigan if (!priv->amp_cal) { 2103333cb71SPaul Handrigan usleep_range(8000, 9000); 2113333cb71SPaul Handrigan priv->amp_cal = true; 2123333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLASSD_CTL, 2133333cb71SPaul Handrigan CS35L33_AMP_CAL, 0); 214cefcf594SKuninori Morimoto dev_dbg(component->dev, "Amp calibration done\n"); 2153333cb71SPaul Handrigan } 216cefcf594SKuninori Morimoto dev_dbg(component->dev, "Amp turned on\n"); 2173333cb71SPaul Handrigan break; 2183333cb71SPaul Handrigan case SND_SOC_DAPM_POST_PMD: 219cefcf594SKuninori Morimoto dev_dbg(component->dev, "Amp turned off\n"); 2203333cb71SPaul Handrigan break; 2213333cb71SPaul Handrigan default: 222cefcf594SKuninori Morimoto dev_err(component->dev, "Invalid event = 0x%x\n", event); 2233333cb71SPaul Handrigan break; 2243333cb71SPaul Handrigan } 2253333cb71SPaul Handrigan 2263333cb71SPaul Handrigan return 0; 2273333cb71SPaul Handrigan } 2283333cb71SPaul Handrigan 2293333cb71SPaul Handrigan static int cs35l33_sdin_event(struct snd_soc_dapm_widget *w, 2303333cb71SPaul Handrigan struct snd_kcontrol *kcontrol, int event) 2313333cb71SPaul Handrigan { 232cefcf594SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 233cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 2343333cb71SPaul Handrigan unsigned int val; 2353333cb71SPaul Handrigan 2363333cb71SPaul Handrigan switch (event) { 2373333cb71SPaul Handrigan case SND_SOC_DAPM_PRE_PMU: 2383333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 2393333cb71SPaul Handrigan CS35L33_PDN_BST, 0); 2403333cb71SPaul Handrigan val = priv->is_tdm_mode ? 0 : CS35L33_PDN_TDM; 2413333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 2423333cb71SPaul Handrigan CS35L33_PDN_TDM, val); 243cefcf594SKuninori Morimoto dev_dbg(component->dev, "BST turned on\n"); 2443333cb71SPaul Handrigan break; 2453333cb71SPaul Handrigan case SND_SOC_DAPM_POST_PMU: 246cefcf594SKuninori Morimoto dev_dbg(component->dev, "SDIN turned on\n"); 2473333cb71SPaul Handrigan if (!priv->amp_cal) { 2483333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLASSD_CTL, 2493333cb71SPaul Handrigan CS35L33_AMP_CAL, CS35L33_AMP_CAL); 250cefcf594SKuninori Morimoto dev_dbg(component->dev, "Amp calibration started\n"); 2513333cb71SPaul Handrigan usleep_range(10000, 11000); 2523333cb71SPaul Handrigan } 2533333cb71SPaul Handrigan break; 2543333cb71SPaul Handrigan case SND_SOC_DAPM_POST_PMD: 2553333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 2563333cb71SPaul Handrigan CS35L33_PDN_TDM, CS35L33_PDN_TDM); 2573333cb71SPaul Handrigan usleep_range(4000, 4100); 2583333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 2593333cb71SPaul Handrigan CS35L33_PDN_BST, CS35L33_PDN_BST); 260cefcf594SKuninori Morimoto dev_dbg(component->dev, "BST and SDIN turned off\n"); 2613333cb71SPaul Handrigan break; 2623333cb71SPaul Handrigan default: 263cefcf594SKuninori Morimoto dev_err(component->dev, "Invalid event = 0x%x\n", event); 2643333cb71SPaul Handrigan 2653333cb71SPaul Handrigan } 2663333cb71SPaul Handrigan 2673333cb71SPaul Handrigan return 0; 2683333cb71SPaul Handrigan } 2693333cb71SPaul Handrigan 2703333cb71SPaul Handrigan static int cs35l33_sdout_event(struct snd_soc_dapm_widget *w, 2713333cb71SPaul Handrigan struct snd_kcontrol *kcontrol, int event) 2723333cb71SPaul Handrigan { 273cefcf594SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 274cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 2753333cb71SPaul Handrigan unsigned int mask = CS35L33_SDOUT_3ST_I2S | CS35L33_PDN_TDM; 2763333cb71SPaul Handrigan unsigned int mask2 = CS35L33_SDOUT_3ST_TDM; 2773333cb71SPaul Handrigan unsigned int val, val2; 2783333cb71SPaul Handrigan 2793333cb71SPaul Handrigan switch (event) { 2803333cb71SPaul Handrigan case SND_SOC_DAPM_PRE_PMU: 2813333cb71SPaul Handrigan if (priv->is_tdm_mode) { 2823333cb71SPaul Handrigan /* set sdout_3st_i2s and reset pdn_tdm */ 2833333cb71SPaul Handrigan val = CS35L33_SDOUT_3ST_I2S; 2843333cb71SPaul Handrigan /* reset sdout_3st_tdm */ 2853333cb71SPaul Handrigan val2 = 0; 2863333cb71SPaul Handrigan } else { 2873333cb71SPaul Handrigan /* reset sdout_3st_i2s and set pdn_tdm */ 2883333cb71SPaul Handrigan val = CS35L33_PDN_TDM; 2893333cb71SPaul Handrigan /* set sdout_3st_tdm */ 2903333cb71SPaul Handrigan val2 = CS35L33_SDOUT_3ST_TDM; 2913333cb71SPaul Handrigan } 292cefcf594SKuninori Morimoto dev_dbg(component->dev, "SDOUT turned on\n"); 2933333cb71SPaul Handrigan break; 2943333cb71SPaul Handrigan case SND_SOC_DAPM_PRE_PMD: 2953333cb71SPaul Handrigan val = CS35L33_SDOUT_3ST_I2S | CS35L33_PDN_TDM; 2963333cb71SPaul Handrigan val2 = CS35L33_SDOUT_3ST_TDM; 297cefcf594SKuninori Morimoto dev_dbg(component->dev, "SDOUT turned off\n"); 2983333cb71SPaul Handrigan break; 2993333cb71SPaul Handrigan default: 300cefcf594SKuninori Morimoto dev_err(component->dev, "Invalid event = 0x%x\n", event); 3013333cb71SPaul Handrigan return 0; 3023333cb71SPaul Handrigan } 3033333cb71SPaul Handrigan 3043333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 3053333cb71SPaul Handrigan mask, val); 3063333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 3073333cb71SPaul Handrigan mask2, val2); 3083333cb71SPaul Handrigan 3093333cb71SPaul Handrigan return 0; 3103333cb71SPaul Handrigan } 3113333cb71SPaul Handrigan 3123333cb71SPaul Handrigan static const struct snd_soc_dapm_widget cs35l33_dapm_widgets[] = { 3133333cb71SPaul Handrigan 3143333cb71SPaul Handrigan SND_SOC_DAPM_OUTPUT("SPK"), 3153333cb71SPaul Handrigan SND_SOC_DAPM_OUT_DRV_E("SPKDRV", CS35L33_PWRCTL1, 7, 1, NULL, 0, 3163333cb71SPaul Handrigan cs35l33_spkrdrv_event, 3173333cb71SPaul Handrigan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 3183333cb71SPaul Handrigan SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L33_PWRCTL2, 3193333cb71SPaul Handrigan 2, 1, cs35l33_sdin_event, SND_SOC_DAPM_PRE_PMU | 3203333cb71SPaul Handrigan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 3213333cb71SPaul Handrigan 3223333cb71SPaul Handrigan SND_SOC_DAPM_INPUT("MON"), 3233333cb71SPaul Handrigan 3243333cb71SPaul Handrigan SND_SOC_DAPM_ADC("VMON", NULL, 3253333cb71SPaul Handrigan CS35L33_PWRCTL2, CS35L33_PDN_VMON_SHIFT, 1), 3263333cb71SPaul Handrigan SND_SOC_DAPM_ADC("IMON", NULL, 3273333cb71SPaul Handrigan CS35L33_PWRCTL2, CS35L33_PDN_IMON_SHIFT, 1), 3283333cb71SPaul Handrigan SND_SOC_DAPM_ADC("VPMON", NULL, 3293333cb71SPaul Handrigan CS35L33_PWRCTL2, CS35L33_PDN_VPMON_SHIFT, 1), 3303333cb71SPaul Handrigan SND_SOC_DAPM_ADC("VBSTMON", NULL, 3313333cb71SPaul Handrigan CS35L33_PWRCTL2, CS35L33_PDN_VBSTMON_SHIFT, 1), 3323333cb71SPaul Handrigan 3333333cb71SPaul Handrigan SND_SOC_DAPM_AIF_OUT_E("SDOUT", NULL, 0, SND_SOC_NOPM, 0, 0, 3343333cb71SPaul Handrigan cs35l33_sdout_event, SND_SOC_DAPM_PRE_PMU | 3353333cb71SPaul Handrigan SND_SOC_DAPM_PRE_PMD), 3363333cb71SPaul Handrigan }; 3373333cb71SPaul Handrigan 3383333cb71SPaul Handrigan static const struct snd_soc_dapm_route cs35l33_audio_map[] = { 3393333cb71SPaul Handrigan {"SDIN", NULL, "CS35L33 Playback"}, 3403333cb71SPaul Handrigan {"SPKDRV", NULL, "SDIN"}, 3413333cb71SPaul Handrigan {"SPK", NULL, "SPKDRV"}, 3423333cb71SPaul Handrigan 3433333cb71SPaul Handrigan {"VMON", NULL, "MON"}, 3443333cb71SPaul Handrigan {"IMON", NULL, "MON"}, 3453333cb71SPaul Handrigan 3463333cb71SPaul Handrigan {"SDOUT", NULL, "VMON"}, 3473333cb71SPaul Handrigan {"SDOUT", NULL, "IMON"}, 3483333cb71SPaul Handrigan {"CS35L33 Capture", NULL, "SDOUT"}, 3493333cb71SPaul Handrigan }; 3503333cb71SPaul Handrigan 3513333cb71SPaul Handrigan static const struct snd_soc_dapm_route cs35l33_vphg_auto_route[] = { 3523333cb71SPaul Handrigan {"SPKDRV", NULL, "VPMON"}, 3533333cb71SPaul Handrigan {"VPMON", NULL, "CS35L33 Playback"}, 3543333cb71SPaul Handrigan }; 3553333cb71SPaul Handrigan 3563333cb71SPaul Handrigan static const struct snd_soc_dapm_route cs35l33_vp_vbst_mon_route[] = { 3573333cb71SPaul Handrigan {"SDOUT", NULL, "VPMON"}, 3583333cb71SPaul Handrigan {"VPMON", NULL, "MON"}, 3593333cb71SPaul Handrigan {"SDOUT", NULL, "VBSTMON"}, 3603333cb71SPaul Handrigan {"VBSTMON", NULL, "MON"}, 3613333cb71SPaul Handrigan }; 3623333cb71SPaul Handrigan 363cefcf594SKuninori Morimoto static int cs35l33_set_bias_level(struct snd_soc_component *component, 3643333cb71SPaul Handrigan enum snd_soc_bias_level level) 3653333cb71SPaul Handrigan { 3663333cb71SPaul Handrigan unsigned int val; 367cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 3683333cb71SPaul Handrigan 3693333cb71SPaul Handrigan switch (level) { 3703333cb71SPaul Handrigan case SND_SOC_BIAS_ON: 3713333cb71SPaul Handrigan break; 3723333cb71SPaul Handrigan case SND_SOC_BIAS_PREPARE: 3733333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 3743333cb71SPaul Handrigan CS35L33_PDN_ALL, 0); 3753333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 3763333cb71SPaul Handrigan CS35L33_MCLKDIS, 0); 3773333cb71SPaul Handrigan break; 3783333cb71SPaul Handrigan case SND_SOC_BIAS_STANDBY: 3793333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL1, 3803333cb71SPaul Handrigan CS35L33_PDN_ALL, CS35L33_PDN_ALL); 3813333cb71SPaul Handrigan regmap_read(priv->regmap, CS35L33_INT_STATUS_2, &val); 3823333cb71SPaul Handrigan usleep_range(1000, 1100); 3833333cb71SPaul Handrigan if (val & CS35L33_PDN_DONE) 3843333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 3853333cb71SPaul Handrigan CS35L33_MCLKDIS, CS35L33_MCLKDIS); 3863333cb71SPaul Handrigan break; 3873333cb71SPaul Handrigan case SND_SOC_BIAS_OFF: 3883333cb71SPaul Handrigan break; 3893333cb71SPaul Handrigan default: 3903333cb71SPaul Handrigan return -EINVAL; 3913333cb71SPaul Handrigan } 3923333cb71SPaul Handrigan 3933333cb71SPaul Handrigan return 0; 3943333cb71SPaul Handrigan } 3953333cb71SPaul Handrigan 3963333cb71SPaul Handrigan struct cs35l33_mclk_div { 3973333cb71SPaul Handrigan int mclk; 3983333cb71SPaul Handrigan int srate; 3993333cb71SPaul Handrigan u8 adsp_rate; 4003333cb71SPaul Handrigan u8 int_fs_ratio; 4013333cb71SPaul Handrigan }; 4023333cb71SPaul Handrigan 4033333cb71SPaul Handrigan static const struct cs35l33_mclk_div cs35l33_mclk_coeffs[] = { 4043333cb71SPaul Handrigan /* MCLK, Sample Rate, adsp_rate, int_fs_ratio */ 4053333cb71SPaul Handrigan {5644800, 11025, 0x4, CS35L33_INT_FS_RATE}, 4063333cb71SPaul Handrigan {5644800, 22050, 0x8, CS35L33_INT_FS_RATE}, 4073333cb71SPaul Handrigan {5644800, 44100, 0xC, CS35L33_INT_FS_RATE}, 4083333cb71SPaul Handrigan 4093333cb71SPaul Handrigan {6000000, 8000, 0x1, 0}, 4103333cb71SPaul Handrigan {6000000, 11025, 0x2, 0}, 4113333cb71SPaul Handrigan {6000000, 11029, 0x3, 0}, 4123333cb71SPaul Handrigan {6000000, 12000, 0x4, 0}, 4133333cb71SPaul Handrigan {6000000, 16000, 0x5, 0}, 4143333cb71SPaul Handrigan {6000000, 22050, 0x6, 0}, 4153333cb71SPaul Handrigan {6000000, 22059, 0x7, 0}, 4163333cb71SPaul Handrigan {6000000, 24000, 0x8, 0}, 4173333cb71SPaul Handrigan {6000000, 32000, 0x9, 0}, 4183333cb71SPaul Handrigan {6000000, 44100, 0xA, 0}, 4193333cb71SPaul Handrigan {6000000, 44118, 0xB, 0}, 4203333cb71SPaul Handrigan {6000000, 48000, 0xC, 0}, 4213333cb71SPaul Handrigan 4223333cb71SPaul Handrigan {6144000, 8000, 0x1, CS35L33_INT_FS_RATE}, 4233333cb71SPaul Handrigan {6144000, 12000, 0x4, CS35L33_INT_FS_RATE}, 4243333cb71SPaul Handrigan {6144000, 16000, 0x5, CS35L33_INT_FS_RATE}, 4253333cb71SPaul Handrigan {6144000, 24000, 0x8, CS35L33_INT_FS_RATE}, 4263333cb71SPaul Handrigan {6144000, 32000, 0x9, CS35L33_INT_FS_RATE}, 4273333cb71SPaul Handrigan {6144000, 48000, 0xC, CS35L33_INT_FS_RATE}, 4283333cb71SPaul Handrigan }; 4293333cb71SPaul Handrigan 4303333cb71SPaul Handrigan static int cs35l33_get_mclk_coeff(int mclk, int srate) 4313333cb71SPaul Handrigan { 4323333cb71SPaul Handrigan int i; 4333333cb71SPaul Handrigan 4343333cb71SPaul Handrigan for (i = 0; i < ARRAY_SIZE(cs35l33_mclk_coeffs); i++) { 4353333cb71SPaul Handrigan if (cs35l33_mclk_coeffs[i].mclk == mclk && 4363333cb71SPaul Handrigan cs35l33_mclk_coeffs[i].srate == srate) 4373333cb71SPaul Handrigan return i; 4383333cb71SPaul Handrigan } 4393333cb71SPaul Handrigan return -EINVAL; 4403333cb71SPaul Handrigan } 4413333cb71SPaul Handrigan 4423333cb71SPaul Handrigan static int cs35l33_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 4433333cb71SPaul Handrigan { 444cefcf594SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 445cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 4463333cb71SPaul Handrigan 4473333cb71SPaul Handrigan switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 4483333cb71SPaul Handrigan case SND_SOC_DAIFMT_CBM_CFM: 4493333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, 4503333cb71SPaul Handrigan CS35L33_MS_MASK, CS35L33_MS_MASK); 451cefcf594SKuninori Morimoto dev_dbg(component->dev, "Audio port in master mode\n"); 4523333cb71SPaul Handrigan break; 4533333cb71SPaul Handrigan case SND_SOC_DAIFMT_CBS_CFS: 4543333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, 4553333cb71SPaul Handrigan CS35L33_MS_MASK, 0); 456cefcf594SKuninori Morimoto dev_dbg(component->dev, "Audio port in slave mode\n"); 4573333cb71SPaul Handrigan break; 4583333cb71SPaul Handrigan default: 4593333cb71SPaul Handrigan return -EINVAL; 4603333cb71SPaul Handrigan } 4613333cb71SPaul Handrigan 4623333cb71SPaul Handrigan switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 4633333cb71SPaul Handrigan case SND_SOC_DAIFMT_DSP_A: 4643333cb71SPaul Handrigan /* 4653333cb71SPaul Handrigan * tdm mode in cs35l33 resembles dsp-a mode very 4663333cb71SPaul Handrigan * closely, it is dsp-a with fsync shifted left by half bclk 4673333cb71SPaul Handrigan */ 4683333cb71SPaul Handrigan priv->is_tdm_mode = true; 469cefcf594SKuninori Morimoto dev_dbg(component->dev, "Audio port in TDM mode\n"); 4703333cb71SPaul Handrigan break; 4713333cb71SPaul Handrigan case SND_SOC_DAIFMT_I2S: 4723333cb71SPaul Handrigan priv->is_tdm_mode = false; 473cefcf594SKuninori Morimoto dev_dbg(component->dev, "Audio port in I2S mode\n"); 4743333cb71SPaul Handrigan break; 4753333cb71SPaul Handrigan default: 4763333cb71SPaul Handrigan return -EINVAL; 4773333cb71SPaul Handrigan } 4783333cb71SPaul Handrigan 4793333cb71SPaul Handrigan return 0; 4803333cb71SPaul Handrigan } 4813333cb71SPaul Handrigan 4823333cb71SPaul Handrigan static int cs35l33_pcm_hw_params(struct snd_pcm_substream *substream, 4833333cb71SPaul Handrigan struct snd_pcm_hw_params *params, 4843333cb71SPaul Handrigan struct snd_soc_dai *dai) 4853333cb71SPaul Handrigan { 486cefcf594SKuninori Morimoto struct snd_soc_component *component = dai->component; 487cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 4883333cb71SPaul Handrigan int sample_size = params_width(params); 4893333cb71SPaul Handrigan int coeff = cs35l33_get_mclk_coeff(priv->mclk_int, params_rate(params)); 4903333cb71SPaul Handrigan 4913333cb71SPaul Handrigan if (coeff < 0) 4923333cb71SPaul Handrigan return coeff; 4933333cb71SPaul Handrigan 4943333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 4953333cb71SPaul Handrigan CS35L33_ADSP_FS | CS35L33_INT_FS_RATE, 4963333cb71SPaul Handrigan cs35l33_mclk_coeffs[coeff].int_fs_ratio 4973333cb71SPaul Handrigan | cs35l33_mclk_coeffs[coeff].adsp_rate); 4983333cb71SPaul Handrigan 4993333cb71SPaul Handrigan if (priv->is_tdm_mode) { 5003333cb71SPaul Handrigan sample_size = (sample_size / 8) - 1; 5013333cb71SPaul Handrigan if (sample_size > 2) 5023333cb71SPaul Handrigan sample_size = 2; 5033333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_RX_AUD, 5043333cb71SPaul Handrigan CS35L33_AUDIN_RX_DEPTH, 5053333cb71SPaul Handrigan sample_size << CS35L33_AUDIN_RX_DEPTH_SHIFT); 5063333cb71SPaul Handrigan } 5073333cb71SPaul Handrigan 508cefcf594SKuninori Morimoto dev_dbg(component->dev, "sample rate=%d, bits per sample=%d\n", 5093333cb71SPaul Handrigan params_rate(params), params_width(params)); 5103333cb71SPaul Handrigan 5113333cb71SPaul Handrigan return 0; 5123333cb71SPaul Handrigan } 5133333cb71SPaul Handrigan 5143333cb71SPaul Handrigan static const unsigned int cs35l33_src_rates[] = { 5153333cb71SPaul Handrigan 8000, 11025, 11029, 12000, 16000, 22050, 5163333cb71SPaul Handrigan 22059, 24000, 32000, 44100, 44118, 48000 5173333cb71SPaul Handrigan }; 5183333cb71SPaul Handrigan 5193333cb71SPaul Handrigan static const struct snd_pcm_hw_constraint_list cs35l33_constraints = { 5203333cb71SPaul Handrigan .count = ARRAY_SIZE(cs35l33_src_rates), 5213333cb71SPaul Handrigan .list = cs35l33_src_rates, 5223333cb71SPaul Handrigan }; 5233333cb71SPaul Handrigan 5243333cb71SPaul Handrigan static int cs35l33_pcm_startup(struct snd_pcm_substream *substream, 5253333cb71SPaul Handrigan struct snd_soc_dai *dai) 5263333cb71SPaul Handrigan { 5273333cb71SPaul Handrigan snd_pcm_hw_constraint_list(substream->runtime, 0, 5283333cb71SPaul Handrigan SNDRV_PCM_HW_PARAM_RATE, 5293333cb71SPaul Handrigan &cs35l33_constraints); 5303333cb71SPaul Handrigan return 0; 5313333cb71SPaul Handrigan } 5323333cb71SPaul Handrigan 5333333cb71SPaul Handrigan static int cs35l33_set_tristate(struct snd_soc_dai *dai, int tristate) 5343333cb71SPaul Handrigan { 535cefcf594SKuninori Morimoto struct snd_soc_component *component = dai->component; 536cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 5373333cb71SPaul Handrigan 5383333cb71SPaul Handrigan if (tristate) { 5393333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 5403333cb71SPaul Handrigan CS35L33_SDOUT_3ST_I2S, CS35L33_SDOUT_3ST_I2S); 5413333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 5423333cb71SPaul Handrigan CS35L33_SDOUT_3ST_TDM, CS35L33_SDOUT_3ST_TDM); 5433333cb71SPaul Handrigan } else { 5443333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_PWRCTL2, 5453333cb71SPaul Handrigan CS35L33_SDOUT_3ST_I2S, 0); 5463333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_CLK_CTL, 5473333cb71SPaul Handrigan CS35L33_SDOUT_3ST_TDM, 0); 5483333cb71SPaul Handrigan } 5493333cb71SPaul Handrigan 5503333cb71SPaul Handrigan return 0; 5513333cb71SPaul Handrigan } 5523333cb71SPaul Handrigan 5533333cb71SPaul Handrigan static int cs35l33_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 5543333cb71SPaul Handrigan unsigned int rx_mask, int slots, int slot_width) 5553333cb71SPaul Handrigan { 556cefcf594SKuninori Morimoto struct snd_soc_component *component = dai->component; 557cefcf594SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 558cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 5593333cb71SPaul Handrigan unsigned int reg, bit_pos, i; 5603333cb71SPaul Handrigan int slot, slot_num; 5613333cb71SPaul Handrigan 5623333cb71SPaul Handrigan if (slot_width != 8) 5633333cb71SPaul Handrigan return -EINVAL; 5643333cb71SPaul Handrigan 5653333cb71SPaul Handrigan /* scan rx_mask for aud slot */ 5663333cb71SPaul Handrigan slot = ffs(rx_mask) - 1; 5673333cb71SPaul Handrigan if (slot >= 0) { 5683333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_RX_AUD, 5693333cb71SPaul Handrigan CS35L33_X_LOC, slot); 570cefcf594SKuninori Morimoto dev_dbg(component->dev, "Audio starts from slots %d", slot); 5713333cb71SPaul Handrigan } 5723333cb71SPaul Handrigan 5733333cb71SPaul Handrigan /* 5743333cb71SPaul Handrigan * scan tx_mask: vmon(2 slots); imon (2 slots); 5753333cb71SPaul Handrigan * vpmon (1 slot) vbstmon (1 slot) 5763333cb71SPaul Handrigan */ 5773333cb71SPaul Handrigan slot = ffs(tx_mask) - 1; 5783333cb71SPaul Handrigan slot_num = 0; 5793333cb71SPaul Handrigan 5803333cb71SPaul Handrigan for (i = 0; i < 2 ; i++) { 5813333cb71SPaul Handrigan /* disable vpmon/vbstmon: enable later if set in tx_mask */ 5823333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_TX_VPMON + i, 5833333cb71SPaul Handrigan CS35L33_X_STATE | CS35L33_X_LOC, CS35L33_X_STATE 5843333cb71SPaul Handrigan | CS35L33_X_LOC); 5853333cb71SPaul Handrigan } 5863333cb71SPaul Handrigan 5873333cb71SPaul Handrigan /* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/ 5883333cb71SPaul Handrigan snd_soc_dapm_del_routes(dapm, cs35l33_vp_vbst_mon_route, 5893333cb71SPaul Handrigan ARRAY_SIZE(cs35l33_vp_vbst_mon_route)); 5903333cb71SPaul Handrigan 5913333cb71SPaul Handrigan while (slot >= 0) { 5923333cb71SPaul Handrigan /* configure VMON_TX_LOC */ 5933333cb71SPaul Handrigan if (slot_num == 0) { 5943333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_TX_VMON, 5953333cb71SPaul Handrigan CS35L33_X_STATE | CS35L33_X_LOC, slot); 596cefcf594SKuninori Morimoto dev_dbg(component->dev, "VMON enabled in slots %d-%d", 5973333cb71SPaul Handrigan slot, slot + 1); 5983333cb71SPaul Handrigan } 5993333cb71SPaul Handrigan 6003333cb71SPaul Handrigan /* configure IMON_TX_LOC */ 6013333cb71SPaul Handrigan if (slot_num == 3) { 6023333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_TX_IMON, 6033333cb71SPaul Handrigan CS35L33_X_STATE | CS35L33_X_LOC, slot); 604cefcf594SKuninori Morimoto dev_dbg(component->dev, "IMON enabled in slots %d-%d", 6053333cb71SPaul Handrigan slot, slot + 1); 6063333cb71SPaul Handrigan } 6073333cb71SPaul Handrigan 6083333cb71SPaul Handrigan /* configure VPMON_TX_LOC */ 6093333cb71SPaul Handrigan if (slot_num == 4) { 6103333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_TX_VPMON, 6113333cb71SPaul Handrigan CS35L33_X_STATE | CS35L33_X_LOC, slot); 6123333cb71SPaul Handrigan snd_soc_dapm_add_routes(dapm, 6133333cb71SPaul Handrigan &cs35l33_vp_vbst_mon_route[0], 2); 614cefcf594SKuninori Morimoto dev_dbg(component->dev, "VPMON enabled in slots %d", slot); 6153333cb71SPaul Handrigan } 6163333cb71SPaul Handrigan 6173333cb71SPaul Handrigan /* configure VBSTMON_TX_LOC */ 6183333cb71SPaul Handrigan if (slot_num == 5) { 6193333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_TX_VBSTMON, 6203333cb71SPaul Handrigan CS35L33_X_STATE | CS35L33_X_LOC, slot); 6213333cb71SPaul Handrigan snd_soc_dapm_add_routes(dapm, 6223333cb71SPaul Handrigan &cs35l33_vp_vbst_mon_route[2], 2); 623cefcf594SKuninori Morimoto dev_dbg(component->dev, 6243333cb71SPaul Handrigan "VBSTMON enabled in slots %d", slot); 6253333cb71SPaul Handrigan } 6263333cb71SPaul Handrigan 6273333cb71SPaul Handrigan /* Enable the relevant tx slot */ 6283333cb71SPaul Handrigan reg = CS35L33_TX_EN4 - (slot/8); 6293333cb71SPaul Handrigan bit_pos = slot - ((slot / 8) * (8)); 6303333cb71SPaul Handrigan regmap_update_bits(priv->regmap, reg, 6313333cb71SPaul Handrigan 1 << bit_pos, 1 << bit_pos); 6323333cb71SPaul Handrigan 6333333cb71SPaul Handrigan tx_mask &= ~(1 << slot); 6343333cb71SPaul Handrigan slot = ffs(tx_mask) - 1; 6353333cb71SPaul Handrigan slot_num++; 6363333cb71SPaul Handrigan } 6373333cb71SPaul Handrigan 6383333cb71SPaul Handrigan return 0; 6393333cb71SPaul Handrigan } 6403333cb71SPaul Handrigan 641cefcf594SKuninori Morimoto static int cs35l33_component_set_sysclk(struct snd_soc_component *component, 6423333cb71SPaul Handrigan int clk_id, int source, unsigned int freq, int dir) 6433333cb71SPaul Handrigan { 644cefcf594SKuninori Morimoto struct cs35l33_private *cs35l33 = snd_soc_component_get_drvdata(component); 6453333cb71SPaul Handrigan 6463333cb71SPaul Handrigan switch (freq) { 6473333cb71SPaul Handrigan case CS35L33_MCLK_5644: 6483333cb71SPaul Handrigan case CS35L33_MCLK_6: 6493333cb71SPaul Handrigan case CS35L33_MCLK_6144: 6503333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 6513333cb71SPaul Handrigan CS35L33_MCLKDIV2, 0); 6523333cb71SPaul Handrigan cs35l33->mclk_int = freq; 6533333cb71SPaul Handrigan break; 6543333cb71SPaul Handrigan case CS35L33_MCLK_11289: 6553333cb71SPaul Handrigan case CS35L33_MCLK_12: 6563333cb71SPaul Handrigan case CS35L33_MCLK_12288: 6573333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 6583333cb71SPaul Handrigan CS35L33_MCLKDIV2, CS35L33_MCLKDIV2); 6593333cb71SPaul Handrigan cs35l33->mclk_int = freq/2; 6603333cb71SPaul Handrigan break; 6613333cb71SPaul Handrigan default: 6623333cb71SPaul Handrigan cs35l33->mclk_int = 0; 6633333cb71SPaul Handrigan return -EINVAL; 6643333cb71SPaul Handrigan } 6653333cb71SPaul Handrigan 666cefcf594SKuninori Morimoto dev_dbg(component->dev, "external mclk freq=%d, internal mclk freq=%d\n", 6673333cb71SPaul Handrigan freq, cs35l33->mclk_int); 6683333cb71SPaul Handrigan 6693333cb71SPaul Handrigan return 0; 6703333cb71SPaul Handrigan } 6713333cb71SPaul Handrigan 6723333cb71SPaul Handrigan static const struct snd_soc_dai_ops cs35l33_ops = { 6733333cb71SPaul Handrigan .startup = cs35l33_pcm_startup, 6743333cb71SPaul Handrigan .set_tristate = cs35l33_set_tristate, 6753333cb71SPaul Handrigan .set_fmt = cs35l33_set_dai_fmt, 6763333cb71SPaul Handrigan .hw_params = cs35l33_pcm_hw_params, 6773333cb71SPaul Handrigan .set_tdm_slot = cs35l33_set_tdm_slot, 6783333cb71SPaul Handrigan }; 6793333cb71SPaul Handrigan 6803333cb71SPaul Handrigan static struct snd_soc_dai_driver cs35l33_dai = { 6813333cb71SPaul Handrigan .name = "cs35l33-dai", 6823333cb71SPaul Handrigan .id = 0, 6833333cb71SPaul Handrigan .playback = { 6843333cb71SPaul Handrigan .stream_name = "CS35L33 Playback", 6853333cb71SPaul Handrigan .channels_min = 1, 6863333cb71SPaul Handrigan .channels_max = 1, 6873333cb71SPaul Handrigan .rates = CS35L33_RATES, 6883333cb71SPaul Handrigan .formats = CS35L33_FORMATS, 6893333cb71SPaul Handrigan }, 6903333cb71SPaul Handrigan .capture = { 6913333cb71SPaul Handrigan .stream_name = "CS35L33 Capture", 6923333cb71SPaul Handrigan .channels_min = 2, 6933333cb71SPaul Handrigan .channels_max = 2, 6943333cb71SPaul Handrigan .rates = CS35L33_RATES, 6953333cb71SPaul Handrigan .formats = CS35L33_FORMATS, 6963333cb71SPaul Handrigan }, 6973333cb71SPaul Handrigan .ops = &cs35l33_ops, 6983333cb71SPaul Handrigan .symmetric_rates = 1, 6993333cb71SPaul Handrigan }; 7003333cb71SPaul Handrigan 701cefcf594SKuninori Morimoto static int cs35l33_set_hg_data(struct snd_soc_component *component, 7023333cb71SPaul Handrigan struct cs35l33_pdata *pdata) 7033333cb71SPaul Handrigan { 7043333cb71SPaul Handrigan struct cs35l33_hg *hg_config = &pdata->hg_config; 705cefcf594SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 706cefcf594SKuninori Morimoto struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); 7073333cb71SPaul Handrigan 7083333cb71SPaul Handrigan if (hg_config->enable_hg_algo) { 7093333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 7103333cb71SPaul Handrigan CS35L33_MEM_DEPTH_MASK, 7113333cb71SPaul Handrigan hg_config->mem_depth << CS35L33_MEM_DEPTH_SHIFT); 7123333cb71SPaul Handrigan regmap_write(priv->regmap, CS35L33_HG_REL_RATE, 7133333cb71SPaul Handrigan hg_config->release_rate); 7143333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_HEAD, 7153333cb71SPaul Handrigan CS35L33_HD_RM_MASK, 7163333cb71SPaul Handrigan hg_config->hd_rm << CS35L33_HD_RM_SHIFT); 7173333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 7183333cb71SPaul Handrigan CS35L33_LDO_THLD_MASK, 7193333cb71SPaul Handrigan hg_config->ldo_thld << CS35L33_LDO_THLD_SHIFT); 7203333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL, 7213333cb71SPaul Handrigan CS35L33_LDO_DISABLE_MASK, 7223333cb71SPaul Handrigan hg_config->ldo_path_disable << 7233333cb71SPaul Handrigan CS35L33_LDO_DISABLE_SHIFT); 7243333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 7253333cb71SPaul Handrigan CS35L33_LDO_ENTRY_DELAY_MASK, 7263333cb71SPaul Handrigan hg_config->ldo_entry_delay << 7273333cb71SPaul Handrigan CS35L33_LDO_ENTRY_DELAY_SHIFT); 7283333cb71SPaul Handrigan if (hg_config->vp_hg_auto) { 7293333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_EN, 7303333cb71SPaul Handrigan CS35L33_VP_HG_AUTO_MASK, 7313333cb71SPaul Handrigan CS35L33_VP_HG_AUTO_MASK); 7323333cb71SPaul Handrigan snd_soc_dapm_add_routes(dapm, cs35l33_vphg_auto_route, 7333333cb71SPaul Handrigan ARRAY_SIZE(cs35l33_vphg_auto_route)); 7343333cb71SPaul Handrigan } 7353333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_EN, 7363333cb71SPaul Handrigan CS35L33_VP_HG_MASK, 7373333cb71SPaul Handrigan hg_config->vp_hg << CS35L33_VP_HG_SHIFT); 7383333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 7393333cb71SPaul Handrigan CS35L33_VP_HG_RATE_MASK, 7403333cb71SPaul Handrigan hg_config->vp_hg_rate << CS35L33_VP_HG_RATE_SHIFT); 7413333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_LDO_DEL, 7423333cb71SPaul Handrigan CS35L33_VP_HG_VA_MASK, 7433333cb71SPaul Handrigan hg_config->vp_hg_va << CS35L33_VP_HG_VA_SHIFT); 7443333cb71SPaul Handrigan regmap_update_bits(priv->regmap, CS35L33_HG_EN, 7453333cb71SPaul Handrigan CS35L33_CLASS_HG_EN_MASK, CS35L33_CLASS_HG_EN_MASK); 7463333cb71SPaul Handrigan } 7473333cb71SPaul Handrigan return 0; 7483333cb71SPaul Handrigan } 7493333cb71SPaul Handrigan 750cefcf594SKuninori Morimoto static int cs35l33_set_bst_ipk(struct snd_soc_component *component, unsigned int bst) 7513333cb71SPaul Handrigan { 752cefcf594SKuninori Morimoto struct cs35l33_private *cs35l33 = snd_soc_component_get_drvdata(component); 7533333cb71SPaul Handrigan int ret = 0, steps = 0; 7543333cb71SPaul Handrigan 7553333cb71SPaul Handrigan /* Boost current in uA */ 7563333cb71SPaul Handrigan if (bst > 3600000 || bst < 1850000) { 757cefcf594SKuninori Morimoto dev_err(component->dev, "Invalid boost current %d\n", bst); 7583333cb71SPaul Handrigan ret = -EINVAL; 7593333cb71SPaul Handrigan goto err; 7603333cb71SPaul Handrigan } 7613333cb71SPaul Handrigan 7623333cb71SPaul Handrigan if (bst % 15625) { 763cefcf594SKuninori Morimoto dev_err(component->dev, "Current not a multiple of 15625uA (%d)\n", 7643333cb71SPaul Handrigan bst); 7653333cb71SPaul Handrigan ret = -EINVAL; 7663333cb71SPaul Handrigan goto err; 7673333cb71SPaul Handrigan } 7683333cb71SPaul Handrigan 7693333cb71SPaul Handrigan while (bst > 1850000) { 7703333cb71SPaul Handrigan bst -= 15625; 7713333cb71SPaul Handrigan steps++; 7723333cb71SPaul Handrigan } 7733333cb71SPaul Handrigan 7743333cb71SPaul Handrigan regmap_write(cs35l33->regmap, CS35L33_BST_PEAK_CTL, 7753333cb71SPaul Handrigan steps+0x70); 7763333cb71SPaul Handrigan 7773333cb71SPaul Handrigan err: 7783333cb71SPaul Handrigan return ret; 7793333cb71SPaul Handrigan } 7803333cb71SPaul Handrigan 781cefcf594SKuninori Morimoto static int cs35l33_probe(struct snd_soc_component *component) 7823333cb71SPaul Handrigan { 783cefcf594SKuninori Morimoto struct cs35l33_private *cs35l33 = snd_soc_component_get_drvdata(component); 7843333cb71SPaul Handrigan 785cefcf594SKuninori Morimoto cs35l33->component = component; 786cefcf594SKuninori Morimoto pm_runtime_get_sync(component->dev); 7873333cb71SPaul Handrigan 7883333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_PROTECT_CTL, 7893333cb71SPaul Handrigan CS35L33_ALIVE_WD_DIS, 0x8); 7903333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_BST_CTL2, 7913333cb71SPaul Handrigan CS35L33_ALIVE_WD_DIS2, 7923333cb71SPaul Handrigan CS35L33_ALIVE_WD_DIS2); 7933333cb71SPaul Handrigan 7943333cb71SPaul Handrigan /* Set Platform Data */ 7953333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_BST_CTL1, 7963333cb71SPaul Handrigan CS35L33_BST_CTL_MASK, cs35l33->pdata.boost_ctl); 7973333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_CLASSD_CTL, 7983333cb71SPaul Handrigan CS35L33_AMP_DRV_SEL_MASK, 7993333cb71SPaul Handrigan cs35l33->pdata.amp_drv_sel << CS35L33_AMP_DRV_SEL_SHIFT); 8003333cb71SPaul Handrigan 8013333cb71SPaul Handrigan if (cs35l33->pdata.boost_ipk) 802cefcf594SKuninori Morimoto cs35l33_set_bst_ipk(component, cs35l33->pdata.boost_ipk); 8033333cb71SPaul Handrigan 8043333cb71SPaul Handrigan if (cs35l33->enable_soft_ramp) { 805cefcf594SKuninori Morimoto snd_soc_component_update_bits(component, CS35L33_DAC_CTL, 8063333cb71SPaul Handrigan CS35L33_DIGSFT, CS35L33_DIGSFT); 807cefcf594SKuninori Morimoto snd_soc_component_update_bits(component, CS35L33_DAC_CTL, 8083333cb71SPaul Handrigan CS35L33_DSR_RATE, cs35l33->pdata.ramp_rate); 8093333cb71SPaul Handrigan } else { 810cefcf594SKuninori Morimoto snd_soc_component_update_bits(component, CS35L33_DAC_CTL, 8113333cb71SPaul Handrigan CS35L33_DIGSFT, 0); 8123333cb71SPaul Handrigan } 8133333cb71SPaul Handrigan 8143333cb71SPaul Handrigan /* update IMON scaling rate if different from default of 0x8 */ 8153333cb71SPaul Handrigan if (cs35l33->pdata.imon_adc_scale != 0x8) 816cefcf594SKuninori Morimoto snd_soc_component_update_bits(component, CS35L33_ADC_CTL, 8173333cb71SPaul Handrigan CS35L33_IMON_SCALE, cs35l33->pdata.imon_adc_scale); 8183333cb71SPaul Handrigan 819cefcf594SKuninori Morimoto cs35l33_set_hg_data(component, &(cs35l33->pdata)); 8203333cb71SPaul Handrigan 8213333cb71SPaul Handrigan /* 8223333cb71SPaul Handrigan * unmask important interrupts that causes the chip to enter 8233333cb71SPaul Handrigan * speaker safe mode and hence deserves user attention 8243333cb71SPaul Handrigan */ 8253333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_INT_MASK_1, 8263333cb71SPaul Handrigan CS35L33_M_OTE | CS35L33_M_OTW | CS35L33_M_AMP_SHORT | 8273333cb71SPaul Handrigan CS35L33_M_CAL_ERR, 0); 8283333cb71SPaul Handrigan 829cefcf594SKuninori Morimoto pm_runtime_put_sync(component->dev); 8303333cb71SPaul Handrigan 8313333cb71SPaul Handrigan return 0; 8323333cb71SPaul Handrigan } 8333333cb71SPaul Handrigan 834cefcf594SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_cs35l33 = { 8353333cb71SPaul Handrigan .probe = cs35l33_probe, 8363333cb71SPaul Handrigan .set_bias_level = cs35l33_set_bias_level, 837cefcf594SKuninori Morimoto .set_sysclk = cs35l33_component_set_sysclk, 838133987d6SKuninori Morimoto .controls = cs35l33_snd_controls, 839133987d6SKuninori Morimoto .num_controls = ARRAY_SIZE(cs35l33_snd_controls), 8403333cb71SPaul Handrigan .dapm_widgets = cs35l33_dapm_widgets, 8413333cb71SPaul Handrigan .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), 8423333cb71SPaul Handrigan .dapm_routes = cs35l33_audio_map, 8433333cb71SPaul Handrigan .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), 844cefcf594SKuninori Morimoto .use_pmdown_time = 1, 845cefcf594SKuninori Morimoto .endianness = 1, 846cefcf594SKuninori Morimoto .non_legacy_dai_naming = 1, 8473333cb71SPaul Handrigan }; 8483333cb71SPaul Handrigan 8493333cb71SPaul Handrigan static const struct regmap_config cs35l33_regmap = { 8503333cb71SPaul Handrigan .reg_bits = 8, 8513333cb71SPaul Handrigan .val_bits = 8, 8523333cb71SPaul Handrigan 8533333cb71SPaul Handrigan .max_register = CS35L33_MAX_REGISTER, 8543333cb71SPaul Handrigan .reg_defaults = cs35l33_reg, 8553333cb71SPaul Handrigan .num_reg_defaults = ARRAY_SIZE(cs35l33_reg), 8563333cb71SPaul Handrigan .volatile_reg = cs35l33_volatile_register, 8573333cb71SPaul Handrigan .readable_reg = cs35l33_readable_register, 8583333cb71SPaul Handrigan .writeable_reg = cs35l33_writeable_register, 8593333cb71SPaul Handrigan .cache_type = REGCACHE_RBTREE, 8603333cb71SPaul Handrigan .use_single_rw = true, 8613333cb71SPaul Handrigan }; 8623333cb71SPaul Handrigan 86320f12f2cSArnd Bergmann static int __maybe_unused cs35l33_runtime_resume(struct device *dev) 8643333cb71SPaul Handrigan { 8653333cb71SPaul Handrigan struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); 8663333cb71SPaul Handrigan int ret; 8673333cb71SPaul Handrigan 8683333cb71SPaul Handrigan dev_dbg(dev, "%s\n", __func__); 8693333cb71SPaul Handrigan 8703333cb71SPaul Handrigan gpiod_set_value_cansleep(cs35l33->reset_gpio, 0); 8713333cb71SPaul Handrigan 8723333cb71SPaul Handrigan ret = regulator_bulk_enable(cs35l33->num_core_supplies, 8733333cb71SPaul Handrigan cs35l33->core_supplies); 8743333cb71SPaul Handrigan if (ret != 0) { 8753333cb71SPaul Handrigan dev_err(dev, "Failed to enable core supplies: %d\n", ret); 8763333cb71SPaul Handrigan return ret; 8773333cb71SPaul Handrigan } 8783333cb71SPaul Handrigan 8793333cb71SPaul Handrigan regcache_cache_only(cs35l33->regmap, false); 8803333cb71SPaul Handrigan 8813333cb71SPaul Handrigan gpiod_set_value_cansleep(cs35l33->reset_gpio, 1); 8823333cb71SPaul Handrigan 8833333cb71SPaul Handrigan msleep(CS35L33_BOOT_DELAY); 8843333cb71SPaul Handrigan 8853333cb71SPaul Handrigan ret = regcache_sync(cs35l33->regmap); 8863333cb71SPaul Handrigan if (ret != 0) { 8873333cb71SPaul Handrigan dev_err(dev, "Failed to restore register cache\n"); 8883333cb71SPaul Handrigan goto err; 8893333cb71SPaul Handrigan } 8903333cb71SPaul Handrigan 8913333cb71SPaul Handrigan return 0; 8923333cb71SPaul Handrigan 8933333cb71SPaul Handrigan err: 8943333cb71SPaul Handrigan regcache_cache_only(cs35l33->regmap, true); 8953333cb71SPaul Handrigan regulator_bulk_disable(cs35l33->num_core_supplies, 8963333cb71SPaul Handrigan cs35l33->core_supplies); 8973333cb71SPaul Handrigan 8983333cb71SPaul Handrigan return ret; 8993333cb71SPaul Handrigan } 9003333cb71SPaul Handrigan 90120f12f2cSArnd Bergmann static int __maybe_unused cs35l33_runtime_suspend(struct device *dev) 9023333cb71SPaul Handrigan { 9033333cb71SPaul Handrigan struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); 9043333cb71SPaul Handrigan 9053333cb71SPaul Handrigan dev_dbg(dev, "%s\n", __func__); 9063333cb71SPaul Handrigan 9073333cb71SPaul Handrigan /* redo the calibration in next power up */ 9083333cb71SPaul Handrigan cs35l33->amp_cal = false; 9093333cb71SPaul Handrigan 9103333cb71SPaul Handrigan regcache_cache_only(cs35l33->regmap, true); 9113333cb71SPaul Handrigan regcache_mark_dirty(cs35l33->regmap); 9123333cb71SPaul Handrigan regulator_bulk_disable(cs35l33->num_core_supplies, 9133333cb71SPaul Handrigan cs35l33->core_supplies); 9143333cb71SPaul Handrigan 9153333cb71SPaul Handrigan return 0; 9163333cb71SPaul Handrigan } 9173333cb71SPaul Handrigan 9183333cb71SPaul Handrigan static const struct dev_pm_ops cs35l33_pm_ops = { 9193333cb71SPaul Handrigan SET_RUNTIME_PM_OPS(cs35l33_runtime_suspend, 9203333cb71SPaul Handrigan cs35l33_runtime_resume, 9213333cb71SPaul Handrigan NULL) 9223333cb71SPaul Handrigan }; 9233333cb71SPaul Handrigan 9243333cb71SPaul Handrigan static int cs35l33_get_hg_data(const struct device_node *np, 9253333cb71SPaul Handrigan struct cs35l33_pdata *pdata) 9263333cb71SPaul Handrigan { 9273333cb71SPaul Handrigan struct device_node *hg; 9283333cb71SPaul Handrigan struct cs35l33_hg *hg_config = &pdata->hg_config; 9293333cb71SPaul Handrigan u32 val32; 9303333cb71SPaul Handrigan 9313333cb71SPaul Handrigan hg = of_get_child_by_name(np, "cirrus,hg-algo"); 9323333cb71SPaul Handrigan hg_config->enable_hg_algo = hg ? true : false; 9333333cb71SPaul Handrigan 9343333cb71SPaul Handrigan if (hg_config->enable_hg_algo) { 9353333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,mem-depth", &val32) >= 0) 9363333cb71SPaul Handrigan hg_config->mem_depth = val32; 9373333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,release-rate", 9383333cb71SPaul Handrigan &val32) >= 0) 9393333cb71SPaul Handrigan hg_config->release_rate = val32; 9403333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,ldo-thld", &val32) >= 0) 9413333cb71SPaul Handrigan hg_config->ldo_thld = val32; 9423333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,ldo-path-disable", 9433333cb71SPaul Handrigan &val32) >= 0) 9443333cb71SPaul Handrigan hg_config->ldo_path_disable = val32; 9453333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,ldo-entry-delay", 9463333cb71SPaul Handrigan &val32) >= 0) 9473333cb71SPaul Handrigan hg_config->ldo_entry_delay = val32; 9483333cb71SPaul Handrigan 9493333cb71SPaul Handrigan hg_config->vp_hg_auto = of_property_read_bool(hg, 9503333cb71SPaul Handrigan "cirrus,vp-hg-auto"); 9513333cb71SPaul Handrigan 9523333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,vp-hg", &val32) >= 0) 9533333cb71SPaul Handrigan hg_config->vp_hg = val32; 9543333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,vp-hg-rate", &val32) >= 0) 9553333cb71SPaul Handrigan hg_config->vp_hg_rate = val32; 9563333cb71SPaul Handrigan if (of_property_read_u32(hg, "cirrus,vp-hg-va", &val32) >= 0) 9573333cb71SPaul Handrigan hg_config->vp_hg_va = val32; 9583333cb71SPaul Handrigan } 9593333cb71SPaul Handrigan 9603333cb71SPaul Handrigan of_node_put(hg); 9613333cb71SPaul Handrigan 9623333cb71SPaul Handrigan return 0; 9633333cb71SPaul Handrigan } 9643333cb71SPaul Handrigan 9653333cb71SPaul Handrigan static irqreturn_t cs35l33_irq_thread(int irq, void *data) 9663333cb71SPaul Handrigan { 9673333cb71SPaul Handrigan struct cs35l33_private *cs35l33 = data; 968cefcf594SKuninori Morimoto struct snd_soc_component *component = cs35l33->component; 9693333cb71SPaul Handrigan unsigned int sticky_val1, sticky_val2, current_val, mask1, mask2; 9703333cb71SPaul Handrigan 9713333cb71SPaul Handrigan regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_2, 9723333cb71SPaul Handrigan &sticky_val2); 9733333cb71SPaul Handrigan regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_1, 9743333cb71SPaul Handrigan &sticky_val1); 9753333cb71SPaul Handrigan regmap_read(cs35l33->regmap, CS35L33_INT_MASK_2, &mask2); 9763333cb71SPaul Handrigan regmap_read(cs35l33->regmap, CS35L33_INT_MASK_1, &mask1); 9773333cb71SPaul Handrigan 9783333cb71SPaul Handrigan /* Check to see if the unmasked bits are active, 9793333cb71SPaul Handrigan * if not then exit. 9803333cb71SPaul Handrigan */ 9813333cb71SPaul Handrigan if (!(sticky_val1 & ~mask1) && !(sticky_val2 & ~mask2)) 9823333cb71SPaul Handrigan return IRQ_NONE; 9833333cb71SPaul Handrigan 9843333cb71SPaul Handrigan regmap_read(cs35l33->regmap, CS35L33_INT_STATUS_1, 9853333cb71SPaul Handrigan ¤t_val); 9863333cb71SPaul Handrigan 9873333cb71SPaul Handrigan /* handle the interrupts */ 9883333cb71SPaul Handrigan 9893333cb71SPaul Handrigan if (sticky_val1 & CS35L33_AMP_SHORT) { 990cefcf594SKuninori Morimoto dev_crit(component->dev, "Amp short error\n"); 9913333cb71SPaul Handrigan if (!(current_val & CS35L33_AMP_SHORT)) { 992cefcf594SKuninori Morimoto dev_dbg(component->dev, 9933333cb71SPaul Handrigan "Amp short error release\n"); 9943333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 9953333cb71SPaul Handrigan CS35L33_AMP_CTL, 9963333cb71SPaul Handrigan CS35L33_AMP_SHORT_RLS, 0); 9973333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 9983333cb71SPaul Handrigan CS35L33_AMP_CTL, 9993333cb71SPaul Handrigan CS35L33_AMP_SHORT_RLS, 10003333cb71SPaul Handrigan CS35L33_AMP_SHORT_RLS); 10013333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10023333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_AMP_SHORT_RLS, 10033333cb71SPaul Handrigan 0); 10043333cb71SPaul Handrigan } 10053333cb71SPaul Handrigan } 10063333cb71SPaul Handrigan 10073333cb71SPaul Handrigan if (sticky_val1 & CS35L33_CAL_ERR) { 1008cefcf594SKuninori Morimoto dev_err(component->dev, "Cal error\n"); 10093333cb71SPaul Handrigan 10103333cb71SPaul Handrigan /* redo the calibration in next power up */ 10113333cb71SPaul Handrigan cs35l33->amp_cal = false; 10123333cb71SPaul Handrigan 10133333cb71SPaul Handrigan if (!(current_val & CS35L33_CAL_ERR)) { 1014cefcf594SKuninori Morimoto dev_dbg(component->dev, "Cal error release\n"); 10153333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10163333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 10173333cb71SPaul Handrigan 0); 10183333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10193333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 10203333cb71SPaul Handrigan CS35L33_CAL_ERR_RLS); 10213333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10223333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_CAL_ERR_RLS, 10233333cb71SPaul Handrigan 0); 10243333cb71SPaul Handrigan } 10253333cb71SPaul Handrigan } 10263333cb71SPaul Handrigan 10273333cb71SPaul Handrigan if (sticky_val1 & CS35L33_OTE) { 1028cefcf594SKuninori Morimoto dev_crit(component->dev, "Over temperature error\n"); 10293333cb71SPaul Handrigan if (!(current_val & CS35L33_OTE)) { 1030cefcf594SKuninori Morimoto dev_dbg(component->dev, 10313333cb71SPaul Handrigan "Over temperature error release\n"); 10323333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10333333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTE_RLS, 0); 10343333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10353333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTE_RLS, 10363333cb71SPaul Handrigan CS35L33_OTE_RLS); 10373333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10383333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTE_RLS, 0); 10393333cb71SPaul Handrigan } 10403333cb71SPaul Handrigan } 10413333cb71SPaul Handrigan 10423333cb71SPaul Handrigan if (sticky_val1 & CS35L33_OTW) { 1043cefcf594SKuninori Morimoto dev_err(component->dev, "Over temperature warning\n"); 10443333cb71SPaul Handrigan if (!(current_val & CS35L33_OTW)) { 1045cefcf594SKuninori Morimoto dev_dbg(component->dev, 10463333cb71SPaul Handrigan "Over temperature warning release\n"); 10473333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10483333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTW_RLS, 0); 10493333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10503333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTW_RLS, 10513333cb71SPaul Handrigan CS35L33_OTW_RLS); 10523333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, 10533333cb71SPaul Handrigan CS35L33_AMP_CTL, CS35L33_OTW_RLS, 0); 10543333cb71SPaul Handrigan } 10553333cb71SPaul Handrigan } 10563333cb71SPaul Handrigan if (CS35L33_ALIVE_ERR & sticky_val1) 1057cefcf594SKuninori Morimoto dev_err(component->dev, "ERROR: ADSPCLK Interrupt\n"); 10583333cb71SPaul Handrigan 10593333cb71SPaul Handrigan if (CS35L33_MCLK_ERR & sticky_val1) 1060cefcf594SKuninori Morimoto dev_err(component->dev, "ERROR: MCLK Interrupt\n"); 10613333cb71SPaul Handrigan 10623333cb71SPaul Handrigan if (CS35L33_VMON_OVFL & sticky_val2) 1063cefcf594SKuninori Morimoto dev_err(component->dev, 10643333cb71SPaul Handrigan "ERROR: VMON Overflow Interrupt\n"); 10653333cb71SPaul Handrigan 10663333cb71SPaul Handrigan if (CS35L33_IMON_OVFL & sticky_val2) 1067cefcf594SKuninori Morimoto dev_err(component->dev, 10683333cb71SPaul Handrigan "ERROR: IMON Overflow Interrupt\n"); 10693333cb71SPaul Handrigan 10703333cb71SPaul Handrigan if (CS35L33_VPMON_OVFL & sticky_val2) 1071cefcf594SKuninori Morimoto dev_err(component->dev, 10723333cb71SPaul Handrigan "ERROR: VPMON Overflow Interrupt\n"); 10733333cb71SPaul Handrigan 10743333cb71SPaul Handrigan return IRQ_HANDLED; 10753333cb71SPaul Handrigan } 10763333cb71SPaul Handrigan 10773333cb71SPaul Handrigan static const char * const cs35l33_core_supplies[] = { 10783333cb71SPaul Handrigan "VA", 10793333cb71SPaul Handrigan "VP", 10803333cb71SPaul Handrigan }; 10813333cb71SPaul Handrigan 10823333cb71SPaul Handrigan static int cs35l33_of_get_pdata(struct device *dev, 10833333cb71SPaul Handrigan struct cs35l33_private *cs35l33) 10843333cb71SPaul Handrigan { 10853333cb71SPaul Handrigan struct device_node *np = dev->of_node; 10863333cb71SPaul Handrigan struct cs35l33_pdata *pdata = &cs35l33->pdata; 10873333cb71SPaul Handrigan u32 val32; 10883333cb71SPaul Handrigan 10893333cb71SPaul Handrigan if (!np) 10903333cb71SPaul Handrigan return 0; 10913333cb71SPaul Handrigan 10923333cb71SPaul Handrigan if (of_property_read_u32(np, "cirrus,boost-ctl", &val32) >= 0) { 10933333cb71SPaul Handrigan pdata->boost_ctl = val32; 10943333cb71SPaul Handrigan pdata->amp_drv_sel = 1; 10953333cb71SPaul Handrigan } 10963333cb71SPaul Handrigan 10973333cb71SPaul Handrigan if (of_property_read_u32(np, "cirrus,ramp-rate", &val32) >= 0) { 10983333cb71SPaul Handrigan pdata->ramp_rate = val32; 10993333cb71SPaul Handrigan cs35l33->enable_soft_ramp = true; 11003333cb71SPaul Handrigan } 11013333cb71SPaul Handrigan 11023333cb71SPaul Handrigan if (of_property_read_u32(np, "cirrus,boost-ipk", &val32) >= 0) 11033333cb71SPaul Handrigan pdata->boost_ipk = val32; 11043333cb71SPaul Handrigan 11053333cb71SPaul Handrigan if (of_property_read_u32(np, "cirrus,imon-adc-scale", &val32) >= 0) { 11063333cb71SPaul Handrigan if ((val32 == 0x0) || (val32 == 0x7) || (val32 == 0x6)) 11073333cb71SPaul Handrigan pdata->imon_adc_scale = val32; 11083333cb71SPaul Handrigan else 11093333cb71SPaul Handrigan /* use default value */ 11103333cb71SPaul Handrigan pdata->imon_adc_scale = 0x8; 11113333cb71SPaul Handrigan } else { 11123333cb71SPaul Handrigan /* use default value */ 11133333cb71SPaul Handrigan pdata->imon_adc_scale = 0x8; 11143333cb71SPaul Handrigan } 11153333cb71SPaul Handrigan 11163333cb71SPaul Handrigan cs35l33_get_hg_data(np, pdata); 11173333cb71SPaul Handrigan 11183333cb71SPaul Handrigan return 0; 11193333cb71SPaul Handrigan } 11203333cb71SPaul Handrigan 11213333cb71SPaul Handrigan static int cs35l33_i2c_probe(struct i2c_client *i2c_client, 11223333cb71SPaul Handrigan const struct i2c_device_id *id) 11233333cb71SPaul Handrigan { 11243333cb71SPaul Handrigan struct cs35l33_private *cs35l33; 11253333cb71SPaul Handrigan struct cs35l33_pdata *pdata = dev_get_platdata(&i2c_client->dev); 11263333cb71SPaul Handrigan int ret, devid, i; 11273333cb71SPaul Handrigan unsigned int reg; 11283333cb71SPaul Handrigan 11293333cb71SPaul Handrigan cs35l33 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l33_private), 11303333cb71SPaul Handrigan GFP_KERNEL); 11313333cb71SPaul Handrigan if (!cs35l33) 11323333cb71SPaul Handrigan return -ENOMEM; 11333333cb71SPaul Handrigan 11343333cb71SPaul Handrigan i2c_set_clientdata(i2c_client, cs35l33); 11353333cb71SPaul Handrigan cs35l33->regmap = devm_regmap_init_i2c(i2c_client, &cs35l33_regmap); 11363333cb71SPaul Handrigan if (IS_ERR(cs35l33->regmap)) { 11373333cb71SPaul Handrigan ret = PTR_ERR(cs35l33->regmap); 11383333cb71SPaul Handrigan dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 11393333cb71SPaul Handrigan return ret; 11403333cb71SPaul Handrigan } 11413333cb71SPaul Handrigan 11423333cb71SPaul Handrigan regcache_cache_only(cs35l33->regmap, true); 11433333cb71SPaul Handrigan 11443333cb71SPaul Handrigan for (i = 0; i < ARRAY_SIZE(cs35l33_core_supplies); i++) 11453333cb71SPaul Handrigan cs35l33->core_supplies[i].supply 11463333cb71SPaul Handrigan = cs35l33_core_supplies[i]; 11473333cb71SPaul Handrigan cs35l33->num_core_supplies = ARRAY_SIZE(cs35l33_core_supplies); 11483333cb71SPaul Handrigan 11493333cb71SPaul Handrigan ret = devm_regulator_bulk_get(&i2c_client->dev, 11503333cb71SPaul Handrigan cs35l33->num_core_supplies, 11513333cb71SPaul Handrigan cs35l33->core_supplies); 11523333cb71SPaul Handrigan if (ret != 0) { 11533333cb71SPaul Handrigan dev_err(&i2c_client->dev, 11543333cb71SPaul Handrigan "Failed to request core supplies: %d\n", 11553333cb71SPaul Handrigan ret); 11563333cb71SPaul Handrigan return ret; 11573333cb71SPaul Handrigan } 11583333cb71SPaul Handrigan 11593333cb71SPaul Handrigan if (pdata) { 11603333cb71SPaul Handrigan cs35l33->pdata = *pdata; 11613333cb71SPaul Handrigan } else { 11623333cb71SPaul Handrigan cs35l33_of_get_pdata(&i2c_client->dev, cs35l33); 11633333cb71SPaul Handrigan pdata = &cs35l33->pdata; 11643333cb71SPaul Handrigan } 11653333cb71SPaul Handrigan 11663333cb71SPaul Handrigan ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq, NULL, 11673333cb71SPaul Handrigan cs35l33_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW, 11683333cb71SPaul Handrigan "cs35l33", cs35l33); 11693333cb71SPaul Handrigan if (ret != 0) 11703333cb71SPaul Handrigan dev_warn(&i2c_client->dev, "Failed to request IRQ: %d\n", ret); 11713333cb71SPaul Handrigan 11723333cb71SPaul Handrigan /* We could issue !RST or skip it based on AMP topology */ 11733333cb71SPaul Handrigan cs35l33->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, 11743333cb71SPaul Handrigan "reset-gpios", GPIOD_OUT_HIGH); 1175410fe39cSAxel Lin if (IS_ERR(cs35l33->reset_gpio)) { 11763333cb71SPaul Handrigan dev_err(&i2c_client->dev, "%s ERROR: Can't get reset GPIO\n", 11773333cb71SPaul Handrigan __func__); 11783333cb71SPaul Handrigan return PTR_ERR(cs35l33->reset_gpio); 11793333cb71SPaul Handrigan } 11803333cb71SPaul Handrigan 11813333cb71SPaul Handrigan ret = regulator_bulk_enable(cs35l33->num_core_supplies, 11823333cb71SPaul Handrigan cs35l33->core_supplies); 11833333cb71SPaul Handrigan if (ret != 0) { 11843333cb71SPaul Handrigan dev_err(&i2c_client->dev, 11853333cb71SPaul Handrigan "Failed to enable core supplies: %d\n", 11863333cb71SPaul Handrigan ret); 1187beefe4a9SAxel Lin return ret; 11883333cb71SPaul Handrigan } 11893333cb71SPaul Handrigan 11903333cb71SPaul Handrigan gpiod_set_value_cansleep(cs35l33->reset_gpio, 1); 11913333cb71SPaul Handrigan 11923333cb71SPaul Handrigan msleep(CS35L33_BOOT_DELAY); 11933333cb71SPaul Handrigan regcache_cache_only(cs35l33->regmap, false); 11943333cb71SPaul Handrigan 11953333cb71SPaul Handrigan /* initialize codec */ 11963333cb71SPaul Handrigan ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_AB, ®); 11973333cb71SPaul Handrigan devid = (reg & 0xFF) << 12; 11983333cb71SPaul Handrigan ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_CD, ®); 11993333cb71SPaul Handrigan devid |= (reg & 0xFF) << 4; 12003333cb71SPaul Handrigan ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_E, ®); 12013333cb71SPaul Handrigan devid |= (reg & 0xF0) >> 4; 12023333cb71SPaul Handrigan 12033333cb71SPaul Handrigan if (devid != CS35L33_CHIP_ID) { 12043333cb71SPaul Handrigan dev_err(&i2c_client->dev, 12053333cb71SPaul Handrigan "CS35L33 Device ID (%X). Expected ID %X\n", 12063333cb71SPaul Handrigan devid, CS35L33_CHIP_ID); 12073333cb71SPaul Handrigan goto err_enable; 12083333cb71SPaul Handrigan } 12093333cb71SPaul Handrigan 12103333cb71SPaul Handrigan ret = regmap_read(cs35l33->regmap, CS35L33_REV_ID, ®); 12113333cb71SPaul Handrigan if (ret < 0) { 12123333cb71SPaul Handrigan dev_err(&i2c_client->dev, "Get Revision ID failed\n"); 12133333cb71SPaul Handrigan goto err_enable; 12143333cb71SPaul Handrigan } 12153333cb71SPaul Handrigan 12163333cb71SPaul Handrigan dev_info(&i2c_client->dev, 12175d78b027SAxel Lin "Cirrus Logic CS35L33, Revision: %02X\n", reg & 0xFF); 12183333cb71SPaul Handrigan 12193333cb71SPaul Handrigan ret = regmap_register_patch(cs35l33->regmap, 12203333cb71SPaul Handrigan cs35l33_patch, ARRAY_SIZE(cs35l33_patch)); 12213333cb71SPaul Handrigan if (ret < 0) { 12223333cb71SPaul Handrigan dev_err(&i2c_client->dev, 12233333cb71SPaul Handrigan "Error in applying regmap patch: %d\n", ret); 12243333cb71SPaul Handrigan goto err_enable; 12253333cb71SPaul Handrigan } 12263333cb71SPaul Handrigan 12273333cb71SPaul Handrigan /* disable mclk and tdm */ 12283333cb71SPaul Handrigan regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL, 12293333cb71SPaul Handrigan CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM, 12303333cb71SPaul Handrigan CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM); 12313333cb71SPaul Handrigan 12323333cb71SPaul Handrigan pm_runtime_set_autosuspend_delay(&i2c_client->dev, 100); 12333333cb71SPaul Handrigan pm_runtime_use_autosuspend(&i2c_client->dev); 12343333cb71SPaul Handrigan pm_runtime_set_active(&i2c_client->dev); 12353333cb71SPaul Handrigan pm_runtime_enable(&i2c_client->dev); 12363333cb71SPaul Handrigan 1237cefcf594SKuninori Morimoto ret = devm_snd_soc_register_component(&i2c_client->dev, 1238cefcf594SKuninori Morimoto &soc_component_dev_cs35l33, &cs35l33_dai, 1); 12393333cb71SPaul Handrigan if (ret < 0) { 1240cefcf594SKuninori Morimoto dev_err(&i2c_client->dev, "%s: Register component failed\n", 12413333cb71SPaul Handrigan __func__); 1242beefe4a9SAxel Lin goto err_enable; 12433333cb71SPaul Handrigan } 12443333cb71SPaul Handrigan 12453333cb71SPaul Handrigan return 0; 12463333cb71SPaul Handrigan 12473333cb71SPaul Handrigan err_enable: 12483333cb71SPaul Handrigan regulator_bulk_disable(cs35l33->num_core_supplies, 12493333cb71SPaul Handrigan cs35l33->core_supplies); 12503333cb71SPaul Handrigan 12513333cb71SPaul Handrigan return ret; 12523333cb71SPaul Handrigan } 12533333cb71SPaul Handrigan 12543333cb71SPaul Handrigan static int cs35l33_i2c_remove(struct i2c_client *client) 12553333cb71SPaul Handrigan { 12563333cb71SPaul Handrigan struct cs35l33_private *cs35l33 = i2c_get_clientdata(client); 12573333cb71SPaul Handrigan 12583333cb71SPaul Handrigan gpiod_set_value_cansleep(cs35l33->reset_gpio, 0); 12593333cb71SPaul Handrigan 12603333cb71SPaul Handrigan pm_runtime_disable(&client->dev); 12613333cb71SPaul Handrigan regulator_bulk_disable(cs35l33->num_core_supplies, 12623333cb71SPaul Handrigan cs35l33->core_supplies); 12633333cb71SPaul Handrigan 12643333cb71SPaul Handrigan return 0; 12653333cb71SPaul Handrigan } 12663333cb71SPaul Handrigan 12673333cb71SPaul Handrigan static const struct of_device_id cs35l33_of_match[] = { 12683333cb71SPaul Handrigan { .compatible = "cirrus,cs35l33", }, 12693333cb71SPaul Handrigan {}, 12703333cb71SPaul Handrigan }; 12713333cb71SPaul Handrigan MODULE_DEVICE_TABLE(of, cs35l33_of_match); 12723333cb71SPaul Handrigan 12733333cb71SPaul Handrigan static const struct i2c_device_id cs35l33_id[] = { 12743333cb71SPaul Handrigan {"cs35l33", 0}, 12753333cb71SPaul Handrigan {} 12763333cb71SPaul Handrigan }; 12773333cb71SPaul Handrigan 12783333cb71SPaul Handrigan MODULE_DEVICE_TABLE(i2c, cs35l33_id); 12793333cb71SPaul Handrigan 12803333cb71SPaul Handrigan static struct i2c_driver cs35l33_i2c_driver = { 12813333cb71SPaul Handrigan .driver = { 12823333cb71SPaul Handrigan .name = "cs35l33", 12833333cb71SPaul Handrigan .pm = &cs35l33_pm_ops, 12843333cb71SPaul Handrigan .of_match_table = cs35l33_of_match, 12853333cb71SPaul Handrigan 12863333cb71SPaul Handrigan }, 12873333cb71SPaul Handrigan .id_table = cs35l33_id, 12883333cb71SPaul Handrigan .probe = cs35l33_i2c_probe, 12893333cb71SPaul Handrigan .remove = cs35l33_i2c_remove, 12903333cb71SPaul Handrigan 12913333cb71SPaul Handrigan }; 12923333cb71SPaul Handrigan module_i2c_driver(cs35l33_i2c_driver); 12933333cb71SPaul Handrigan 12943333cb71SPaul Handrigan MODULE_DESCRIPTION("ASoC CS35L33 driver"); 12953333cb71SPaul Handrigan MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>"); 12963333cb71SPaul Handrigan MODULE_LICENSE("GPL"); 1297