1261 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system4 *5 * Copyright: 2014 Raumfeld GmbH6 * Author: Sven Brandau <info@brandau.biz>7 *8 * based on code from:9 * Raumfeld GmbH10 * Johannes Stezenbach <js@sig21.net>11 * Wolfson Microelectronics PLC.12 * Mark Brown <broonie@opensource.wolfsonmicro.com>13 * Freescale Semiconductor, Inc.14 * Timur Tabi <timur@freescale.com>15 */16 17#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__18 19#include <linux/module.h>20#include <linux/moduleparam.h>21#include <linux/init.h>22#include <linux/delay.h>23#include <linux/pm.h>24#include <linux/i2c.h>25#include <linux/of.h>26#include <linux/regmap.h>27#include <linux/regulator/consumer.h>28#include <linux/gpio/consumer.h>29#include <linux/slab.h>30#include <sound/core.h>31#include <sound/pcm.h>32#include <sound/pcm_params.h>33#include <sound/soc.h>34#include <sound/soc-dapm.h>35#include <sound/initval.h>36#include <sound/tlv.h>37 38#include <sound/sta350.h>39#include "sta350.h"40 41#define STA350_RATES (SNDRV_PCM_RATE_32000 | \42 SNDRV_PCM_RATE_44100 | \43 SNDRV_PCM_RATE_48000 | \44 SNDRV_PCM_RATE_88200 | \45 SNDRV_PCM_RATE_96000 | \46 SNDRV_PCM_RATE_176400 | \47 SNDRV_PCM_RATE_192000)48 49#define STA350_FORMATS \50 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \51 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE | \52 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)53 54/* Power-up register defaults */55static const struct reg_default sta350_regs[] = {56 { 0x0, 0x63 },57 { 0x1, 0x80 },58 { 0x2, 0xdf },59 { 0x3, 0x40 },60 { 0x4, 0xc2 },61 { 0x5, 0x5c },62 { 0x6, 0x00 },63 { 0x7, 0xff },64 { 0x8, 0x60 },65 { 0x9, 0x60 },66 { 0xa, 0x60 },67 { 0xb, 0x00 },68 { 0xc, 0x00 },69 { 0xd, 0x00 },70 { 0xe, 0x00 },71 { 0xf, 0x40 },72 { 0x10, 0x80 },73 { 0x11, 0x77 },74 { 0x12, 0x6a },75 { 0x13, 0x69 },76 { 0x14, 0x6a },77 { 0x15, 0x69 },78 { 0x16, 0x00 },79 { 0x17, 0x00 },80 { 0x18, 0x00 },81 { 0x19, 0x00 },82 { 0x1a, 0x00 },83 { 0x1b, 0x00 },84 { 0x1c, 0x00 },85 { 0x1d, 0x00 },86 { 0x1e, 0x00 },87 { 0x1f, 0x00 },88 { 0x20, 0x00 },89 { 0x21, 0x00 },90 { 0x22, 0x00 },91 { 0x23, 0x00 },92 { 0x24, 0x00 },93 { 0x25, 0x00 },94 { 0x26, 0x00 },95 { 0x27, 0x2a },96 { 0x28, 0xc0 },97 { 0x29, 0xf3 },98 { 0x2a, 0x33 },99 { 0x2b, 0x00 },100 { 0x2c, 0x0c },101 { 0x31, 0x00 },102 { 0x36, 0x00 },103 { 0x37, 0x00 },104 { 0x38, 0x00 },105 { 0x39, 0x01 },106 { 0x3a, 0xee },107 { 0x3b, 0xff },108 { 0x3c, 0x7e },109 { 0x3d, 0xc0 },110 { 0x3e, 0x26 },111 { 0x3f, 0x00 },112 { 0x48, 0x00 },113 { 0x49, 0x00 },114 { 0x4a, 0x00 },115 { 0x4b, 0x04 },116 { 0x4c, 0x00 },117};118 119static const struct regmap_range sta350_write_regs_range[] = {120 regmap_reg_range(STA350_CONFA, STA350_AUTO2),121 regmap_reg_range(STA350_C1CFG, STA350_FDRC2),122 regmap_reg_range(STA350_EQCFG, STA350_EVOLRES),123 regmap_reg_range(STA350_NSHAPE, STA350_MISC2),124};125 126static const struct regmap_range sta350_read_regs_range[] = {127 regmap_reg_range(STA350_CONFA, STA350_AUTO2),128 regmap_reg_range(STA350_C1CFG, STA350_STATUS),129 regmap_reg_range(STA350_EQCFG, STA350_EVOLRES),130 regmap_reg_range(STA350_NSHAPE, STA350_MISC2),131};132 133static const struct regmap_range sta350_volatile_regs_range[] = {134 regmap_reg_range(STA350_CFADDR2, STA350_CFUD),135 regmap_reg_range(STA350_STATUS, STA350_STATUS),136};137 138static const struct regmap_access_table sta350_write_regs = {139 .yes_ranges = sta350_write_regs_range,140 .n_yes_ranges = ARRAY_SIZE(sta350_write_regs_range),141};142 143static const struct regmap_access_table sta350_read_regs = {144 .yes_ranges = sta350_read_regs_range,145 .n_yes_ranges = ARRAY_SIZE(sta350_read_regs_range),146};147 148static const struct regmap_access_table sta350_volatile_regs = {149 .yes_ranges = sta350_volatile_regs_range,150 .n_yes_ranges = ARRAY_SIZE(sta350_volatile_regs_range),151};152 153/* regulator power supply names */154static const char * const sta350_supply_names[] = {155 "vdd-dig", /* digital supply, 3.3V */156 "vdd-pll", /* pll supply, 3.3V */157 "vcc" /* power amp supply, 5V - 26V */158};159 160/* codec private data */161struct sta350_priv {162 struct regmap *regmap;163 struct regulator_bulk_data supplies[ARRAY_SIZE(sta350_supply_names)];164 struct sta350_platform_data *pdata;165 166 unsigned int mclk;167 unsigned int format;168 169 u32 coef_shadow[STA350_COEF_COUNT];170 int shutdown;171 172 struct gpio_desc *gpiod_nreset;173 struct gpio_desc *gpiod_power_down;174 175 struct mutex coeff_lock;176};177 178static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12750, 50, 1);179static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);180static const DECLARE_TLV_DB_SCALE(tone_tlv, -1200, 200, 0);181 182static const char * const sta350_drc_ac[] = {183 "Anti-Clipping", "Dynamic Range Compression"184};185static const char * const sta350_auto_gc_mode[] = {186 "User", "AC no clipping", "AC limited clipping (10%)",187 "DRC nighttime listening mode"188};189static const char * const sta350_auto_xo_mode[] = {190 "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz",191 "200Hz", "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz",192 "340Hz", "360Hz"193};194static const char * const sta350_binary_output[] = {195 "FFX 3-state output - normal operation", "Binary output"196};197static const char * const sta350_limiter_select[] = {198 "Limiter Disabled", "Limiter #1", "Limiter #2"199};200static const char * const sta350_limiter_attack_rate[] = {201 "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",202 "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",203 "0.0645", "0.0564", "0.0501", "0.0451"204};205static const char * const sta350_limiter_release_rate[] = {206 "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",207 "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",208 "0.0134", "0.0117", "0.0110", "0.0104"209};210static const char * const sta350_noise_shaper_type[] = {211 "Third order", "Fourth order"212};213 214static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_attack_tlv,215 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),216 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),217);218 219static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_release_tlv,220 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),221 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),222 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),223 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),224 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),225);226 227static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_attack_tlv,228 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),229 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),230 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),231);232 233static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_release_tlv,234 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),235 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),236 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),237 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),238 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),239);240 241static SOC_ENUM_SINGLE_DECL(sta350_drc_ac_enum,242 STA350_CONFD, STA350_CONFD_DRC_SHIFT,243 sta350_drc_ac);244static SOC_ENUM_SINGLE_DECL(sta350_noise_shaper_enum,245 STA350_CONFE, STA350_CONFE_NSBW_SHIFT,246 sta350_noise_shaper_type);247static SOC_ENUM_SINGLE_DECL(sta350_auto_gc_enum,248 STA350_AUTO1, STA350_AUTO1_AMGC_SHIFT,249 sta350_auto_gc_mode);250static SOC_ENUM_SINGLE_DECL(sta350_auto_xo_enum,251 STA350_AUTO2, STA350_AUTO2_XO_SHIFT,252 sta350_auto_xo_mode);253static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch1_enum,254 STA350_C1CFG, STA350_CxCFG_BO_SHIFT,255 sta350_binary_output);256static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch2_enum,257 STA350_C2CFG, STA350_CxCFG_BO_SHIFT,258 sta350_binary_output);259static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch3_enum,260 STA350_C3CFG, STA350_CxCFG_BO_SHIFT,261 sta350_binary_output);262static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch1_enum,263 STA350_C1CFG, STA350_CxCFG_LS_SHIFT,264 sta350_limiter_select);265static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch2_enum,266 STA350_C2CFG, STA350_CxCFG_LS_SHIFT,267 sta350_limiter_select);268static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch3_enum,269 STA350_C3CFG, STA350_CxCFG_LS_SHIFT,270 sta350_limiter_select);271static SOC_ENUM_SINGLE_DECL(sta350_limiter1_attack_rate_enum,272 STA350_L1AR, STA350_LxA_SHIFT,273 sta350_limiter_attack_rate);274static SOC_ENUM_SINGLE_DECL(sta350_limiter2_attack_rate_enum,275 STA350_L2AR, STA350_LxA_SHIFT,276 sta350_limiter_attack_rate);277static SOC_ENUM_SINGLE_DECL(sta350_limiter1_release_rate_enum,278 STA350_L1AR, STA350_LxR_SHIFT,279 sta350_limiter_release_rate);280static SOC_ENUM_SINGLE_DECL(sta350_limiter2_release_rate_enum,281 STA350_L2AR, STA350_LxR_SHIFT,282 sta350_limiter_release_rate);283 284/*285 * byte array controls for setting biquad, mixer, scaling coefficients;286 * for biquads all five coefficients need to be set in one go,287 * mixer and pre/postscale coefs can be set individually;288 * each coef is 24bit, the bytes are ordered in the same way289 * as given in the STA350 data sheet (big endian; b1, b2, a1, a2, b0)290 */291 292static int sta350_coefficient_info(struct snd_kcontrol *kcontrol,293 struct snd_ctl_elem_info *uinfo)294{295 int numcoef = kcontrol->private_value >> 16;296 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;297 uinfo->count = 3 * numcoef;298 return 0;299}300 301static int sta350_coefficient_get(struct snd_kcontrol *kcontrol,302 struct snd_ctl_elem_value *ucontrol)303{304 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);305 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);306 int numcoef = kcontrol->private_value >> 16;307 int index = kcontrol->private_value & 0xffff;308 unsigned int cfud, val;309 int i, ret = 0;310 311 mutex_lock(&sta350->coeff_lock);312 313 /* preserve reserved bits in STA350_CFUD */314 regmap_read(sta350->regmap, STA350_CFUD, &cfud);315 cfud &= 0xf0;316 /*317 * chip documentation does not say if the bits are self clearing,318 * so do it explicitly319 */320 regmap_write(sta350->regmap, STA350_CFUD, cfud);321 322 regmap_write(sta350->regmap, STA350_CFADDR2, index);323 if (numcoef == 1) {324 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x04);325 } else if (numcoef == 5) {326 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x08);327 } else {328 ret = -EINVAL;329 goto exit_unlock;330 }331 332 for (i = 0; i < 3 * numcoef; i++) {333 regmap_read(sta350->regmap, STA350_B1CF1 + i, &val);334 ucontrol->value.bytes.data[i] = val;335 }336 337exit_unlock:338 mutex_unlock(&sta350->coeff_lock);339 340 return ret;341}342 343static int sta350_coefficient_put(struct snd_kcontrol *kcontrol,344 struct snd_ctl_elem_value *ucontrol)345{346 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);347 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);348 int numcoef = kcontrol->private_value >> 16;349 int index = kcontrol->private_value & 0xffff;350 unsigned int cfud;351 int i;352 353 /* preserve reserved bits in STA350_CFUD */354 regmap_read(sta350->regmap, STA350_CFUD, &cfud);355 cfud &= 0xf0;356 /*357 * chip documentation does not say if the bits are self clearing,358 * so do it explicitly359 */360 regmap_write(sta350->regmap, STA350_CFUD, cfud);361 362 regmap_write(sta350->regmap, STA350_CFADDR2, index);363 for (i = 0; i < numcoef && (index + i < STA350_COEF_COUNT); i++)364 sta350->coef_shadow[index + i] =365 (ucontrol->value.bytes.data[3 * i] << 16)366 | (ucontrol->value.bytes.data[3 * i + 1] << 8)367 | (ucontrol->value.bytes.data[3 * i + 2]);368 for (i = 0; i < 3 * numcoef; i++)369 regmap_write(sta350->regmap, STA350_B1CF1 + i,370 ucontrol->value.bytes.data[i]);371 if (numcoef == 1)372 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);373 else if (numcoef == 5)374 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x02);375 else376 return -EINVAL;377 378 return 0;379}380 381static int sta350_sync_coef_shadow(struct snd_soc_component *component)382{383 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);384 unsigned int cfud;385 int i;386 387 /* preserve reserved bits in STA350_CFUD */388 regmap_read(sta350->regmap, STA350_CFUD, &cfud);389 cfud &= 0xf0;390 391 for (i = 0; i < STA350_COEF_COUNT; i++) {392 regmap_write(sta350->regmap, STA350_CFADDR2, i);393 regmap_write(sta350->regmap, STA350_B1CF1,394 (sta350->coef_shadow[i] >> 16) & 0xff);395 regmap_write(sta350->regmap, STA350_B1CF2,396 (sta350->coef_shadow[i] >> 8) & 0xff);397 regmap_write(sta350->regmap, STA350_B1CF3,398 (sta350->coef_shadow[i]) & 0xff);399 /*400 * chip documentation does not say if the bits are401 * self-clearing, so do it explicitly402 */403 regmap_write(sta350->regmap, STA350_CFUD, cfud);404 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);405 }406 return 0;407}408 409static int sta350_cache_sync(struct snd_soc_component *component)410{411 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);412 unsigned int mute;413 int rc;414 415 /* mute during register sync */416 regmap_read(sta350->regmap, STA350_CFUD, &mute);417 regmap_write(sta350->regmap, STA350_MMUTE, mute | STA350_MMUTE_MMUTE);418 sta350_sync_coef_shadow(component);419 rc = regcache_sync(sta350->regmap);420 regmap_write(sta350->regmap, STA350_MMUTE, mute);421 return rc;422}423 424#define SINGLE_COEF(xname, index) \425{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \426 .info = sta350_coefficient_info, \427 .get = sta350_coefficient_get,\428 .put = sta350_coefficient_put, \429 .private_value = index | (1 << 16) }430 431#define BIQUAD_COEFS(xname, index) \432{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \433 .info = sta350_coefficient_info, \434 .get = sta350_coefficient_get,\435 .put = sta350_coefficient_put, \436 .private_value = index | (5 << 16) }437 438static const struct snd_kcontrol_new sta350_snd_controls[] = {439SOC_SINGLE_TLV("Master Volume", STA350_MVOL, 0, 0xff, 1, mvol_tlv),440/* VOL */441SOC_SINGLE_TLV("Ch1 Volume", STA350_C1VOL, 0, 0xff, 1, chvol_tlv),442SOC_SINGLE_TLV("Ch2 Volume", STA350_C2VOL, 0, 0xff, 1, chvol_tlv),443SOC_SINGLE_TLV("Ch3 Volume", STA350_C3VOL, 0, 0xff, 1, chvol_tlv),444/* CONFD */445SOC_SINGLE("High Pass Filter Bypass Switch",446 STA350_CONFD, STA350_CONFD_HPB_SHIFT, 1, 1),447SOC_SINGLE("De-emphasis Filter Switch",448 STA350_CONFD, STA350_CONFD_DEMP_SHIFT, 1, 0),449SOC_SINGLE("DSP Bypass Switch",450 STA350_CONFD, STA350_CONFD_DSPB_SHIFT, 1, 0),451SOC_SINGLE("Post-scale Link Switch",452 STA350_CONFD, STA350_CONFD_PSL_SHIFT, 1, 0),453SOC_SINGLE("Biquad Coefficient Link Switch",454 STA350_CONFD, STA350_CONFD_BQL_SHIFT, 1, 0),455SOC_ENUM("Compressor/Limiter Switch", sta350_drc_ac_enum),456SOC_ENUM("Noise Shaper Bandwidth", sta350_noise_shaper_enum),457SOC_SINGLE("Zero-detect Mute Enable Switch",458 STA350_CONFD, STA350_CONFD_ZDE_SHIFT, 1, 0),459SOC_SINGLE("Submix Mode Switch",460 STA350_CONFD, STA350_CONFD_SME_SHIFT, 1, 0),461/* CONFE */462SOC_SINGLE("Zero Cross Switch", STA350_CONFE, STA350_CONFE_ZCE_SHIFT, 1, 0),463SOC_SINGLE("Soft Ramp Switch", STA350_CONFE, STA350_CONFE_SVE_SHIFT, 1, 0),464/* MUTE */465SOC_SINGLE("Master Switch", STA350_MMUTE, STA350_MMUTE_MMUTE_SHIFT, 1, 1),466SOC_SINGLE("Ch1 Switch", STA350_MMUTE, STA350_MMUTE_C1M_SHIFT, 1, 1),467SOC_SINGLE("Ch2 Switch", STA350_MMUTE, STA350_MMUTE_C2M_SHIFT, 1, 1),468SOC_SINGLE("Ch3 Switch", STA350_MMUTE, STA350_MMUTE_C3M_SHIFT, 1, 1),469/* AUTOx */470SOC_ENUM("Automode GC", sta350_auto_gc_enum),471SOC_ENUM("Automode XO", sta350_auto_xo_enum),472/* CxCFG */473SOC_SINGLE("Ch1 Tone Control Bypass Switch",474 STA350_C1CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),475SOC_SINGLE("Ch2 Tone Control Bypass Switch",476 STA350_C2CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),477SOC_SINGLE("Ch1 EQ Bypass Switch",478 STA350_C1CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),479SOC_SINGLE("Ch2 EQ Bypass Switch",480 STA350_C2CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),481SOC_SINGLE("Ch1 Master Volume Bypass Switch",482 STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),483SOC_SINGLE("Ch2 Master Volume Bypass Switch",484 STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),485SOC_SINGLE("Ch3 Master Volume Bypass Switch",486 STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),487SOC_ENUM("Ch1 Binary Output Select", sta350_binary_output_ch1_enum),488SOC_ENUM("Ch2 Binary Output Select", sta350_binary_output_ch2_enum),489SOC_ENUM("Ch3 Binary Output Select", sta350_binary_output_ch3_enum),490SOC_ENUM("Ch1 Limiter Select", sta350_limiter_ch1_enum),491SOC_ENUM("Ch2 Limiter Select", sta350_limiter_ch2_enum),492SOC_ENUM("Ch3 Limiter Select", sta350_limiter_ch3_enum),493/* TONE */494SOC_SINGLE_RANGE_TLV("Bass Tone Control Volume",495 STA350_TONE, STA350_TONE_BTC_SHIFT, 1, 13, 0, tone_tlv),496SOC_SINGLE_RANGE_TLV("Treble Tone Control Volume",497 STA350_TONE, STA350_TONE_TTC_SHIFT, 1, 13, 0, tone_tlv),498SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta350_limiter1_attack_rate_enum),499SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta350_limiter2_attack_rate_enum),500SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta350_limiter1_release_rate_enum),501SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta350_limiter2_release_rate_enum),502 503/*504 * depending on mode, the attack/release thresholds have505 * two different enum definitions; provide both506 */507SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)",508 STA350_L1ATRT, STA350_LxA_SHIFT,509 16, 0, sta350_limiter_ac_attack_tlv),510SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)",511 STA350_L2ATRT, STA350_LxA_SHIFT,512 16, 0, sta350_limiter_ac_attack_tlv),513SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)",514 STA350_L1ATRT, STA350_LxR_SHIFT,515 16, 0, sta350_limiter_ac_release_tlv),516SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)",517 STA350_L2ATRT, STA350_LxR_SHIFT,518 16, 0, sta350_limiter_ac_release_tlv),519SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)",520 STA350_L1ATRT, STA350_LxA_SHIFT,521 16, 0, sta350_limiter_drc_attack_tlv),522SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)",523 STA350_L2ATRT, STA350_LxA_SHIFT,524 16, 0, sta350_limiter_drc_attack_tlv),525SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)",526 STA350_L1ATRT, STA350_LxR_SHIFT,527 16, 0, sta350_limiter_drc_release_tlv),528SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)",529 STA350_L2ATRT, STA350_LxR_SHIFT,530 16, 0, sta350_limiter_drc_release_tlv),531 532BIQUAD_COEFS("Ch1 - Biquad 1", 0),533BIQUAD_COEFS("Ch1 - Biquad 2", 5),534BIQUAD_COEFS("Ch1 - Biquad 3", 10),535BIQUAD_COEFS("Ch1 - Biquad 4", 15),536BIQUAD_COEFS("Ch2 - Biquad 1", 20),537BIQUAD_COEFS("Ch2 - Biquad 2", 25),538BIQUAD_COEFS("Ch2 - Biquad 3", 30),539BIQUAD_COEFS("Ch2 - Biquad 4", 35),540BIQUAD_COEFS("High-pass", 40),541BIQUAD_COEFS("Low-pass", 45),542SINGLE_COEF("Ch1 - Prescale", 50),543SINGLE_COEF("Ch2 - Prescale", 51),544SINGLE_COEF("Ch1 - Postscale", 52),545SINGLE_COEF("Ch2 - Postscale", 53),546SINGLE_COEF("Ch3 - Postscale", 54),547SINGLE_COEF("Thermal warning - Postscale", 55),548SINGLE_COEF("Ch1 - Mix 1", 56),549SINGLE_COEF("Ch1 - Mix 2", 57),550SINGLE_COEF("Ch2 - Mix 1", 58),551SINGLE_COEF("Ch2 - Mix 2", 59),552SINGLE_COEF("Ch3 - Mix 1", 60),553SINGLE_COEF("Ch3 - Mix 2", 61),554};555 556static const struct snd_soc_dapm_widget sta350_dapm_widgets[] = {557SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),558SND_SOC_DAPM_OUTPUT("LEFT"),559SND_SOC_DAPM_OUTPUT("RIGHT"),560SND_SOC_DAPM_OUTPUT("SUB"),561};562 563static const struct snd_soc_dapm_route sta350_dapm_routes[] = {564 { "LEFT", NULL, "DAC" },565 { "RIGHT", NULL, "DAC" },566 { "SUB", NULL, "DAC" },567 { "DAC", NULL, "Playback" },568};569 570/* MCLK interpolation ratio per fs */571static struct {572 int fs;573 int ir;574} interpolation_ratios[] = {575 { 32000, 0 },576 { 44100, 0 },577 { 48000, 0 },578 { 88200, 1 },579 { 96000, 1 },580 { 176400, 2 },581 { 192000, 2 },582};583 584/* MCLK to fs clock ratios */585static int mcs_ratio_table[3][6] = {586 { 768, 512, 384, 256, 128, 576 },587 { 384, 256, 192, 128, 64, 0 },588 { 192, 128, 96, 64, 32, 0 },589};590 591/**592 * sta350_set_dai_sysclk - configure MCLK593 * @codec_dai: the codec DAI594 * @clk_id: the clock ID (ignored)595 * @freq: the MCLK input frequency596 * @dir: the clock direction (ignored)597 *598 * The value of MCLK is used to determine which sample rates are supported599 * by the STA350, based on the mcs_ratio_table.600 *601 * This function must be called by the machine driver's 'startup' function,602 * otherwise the list of supported sample rates will not be available in603 * time for ALSA.604 */605static int sta350_set_dai_sysclk(struct snd_soc_dai *codec_dai,606 int clk_id, unsigned int freq, int dir)607{608 struct snd_soc_component *component = codec_dai->component;609 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);610 611 dev_dbg(component->dev, "mclk=%u\n", freq);612 sta350->mclk = freq;613 614 return 0;615}616 617/**618 * sta350_set_dai_fmt - configure the codec for the selected audio format619 * @codec_dai: the codec DAI620 * @fmt: a SND_SOC_DAIFMT_x value indicating the data format621 *622 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the623 * codec accordingly.624 */625static int sta350_set_dai_fmt(struct snd_soc_dai *codec_dai,626 unsigned int fmt)627{628 struct snd_soc_component *component = codec_dai->component;629 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);630 unsigned int confb = 0;631 632 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {633 case SND_SOC_DAIFMT_CBC_CFC:634 break;635 default:636 return -EINVAL;637 }638 639 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {640 case SND_SOC_DAIFMT_I2S:641 case SND_SOC_DAIFMT_RIGHT_J:642 case SND_SOC_DAIFMT_LEFT_J:643 sta350->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;644 break;645 default:646 return -EINVAL;647 }648 649 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {650 case SND_SOC_DAIFMT_NB_NF:651 confb |= STA350_CONFB_C2IM;652 break;653 case SND_SOC_DAIFMT_NB_IF:654 confb |= STA350_CONFB_C1IM;655 break;656 default:657 return -EINVAL;658 }659 660 return regmap_update_bits(sta350->regmap, STA350_CONFB,661 STA350_CONFB_C1IM | STA350_CONFB_C2IM, confb);662}663 664/**665 * sta350_hw_params - program the STA350 with the given hardware parameters.666 * @substream: the audio stream667 * @params: the hardware parameters to set668 * @dai: the SOC DAI (ignored)669 *670 * This function programs the hardware with the values provided.671 * Specifically, the sample rate and the data format.672 */673static int sta350_hw_params(struct snd_pcm_substream *substream,674 struct snd_pcm_hw_params *params,675 struct snd_soc_dai *dai)676{677 struct snd_soc_component *component = dai->component;678 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);679 int i, mcs = -EINVAL, ir = -EINVAL;680 unsigned int confa, confb;681 unsigned int rate, ratio;682 int ret;683 684 if (!sta350->mclk) {685 dev_err(component->dev,686 "sta350->mclk is unset. Unable to determine ratio\n");687 return -EIO;688 }689 690 rate = params_rate(params);691 ratio = sta350->mclk / rate;692 dev_dbg(component->dev, "rate: %u, ratio: %u\n", rate, ratio);693 694 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {695 if (interpolation_ratios[i].fs == rate) {696 ir = interpolation_ratios[i].ir;697 break;698 }699 }700 701 if (ir < 0) {702 dev_err(component->dev, "Unsupported samplerate: %u\n", rate);703 return -EINVAL;704 }705 706 for (i = 0; i < 6; i++) {707 if (mcs_ratio_table[ir][i] == ratio) {708 mcs = i;709 break;710 }711 }712 713 if (mcs < 0) {714 dev_err(component->dev, "Unresolvable ratio: %u\n", ratio);715 return -EINVAL;716 }717 718 confa = (ir << STA350_CONFA_IR_SHIFT) |719 (mcs << STA350_CONFA_MCS_SHIFT);720 confb = 0;721 722 switch (params_width(params)) {723 case 24:724 dev_dbg(component->dev, "24bit\n");725 fallthrough;726 case 32:727 dev_dbg(component->dev, "24bit or 32bit\n");728 switch (sta350->format) {729 case SND_SOC_DAIFMT_I2S:730 confb |= 0x0;731 break;732 case SND_SOC_DAIFMT_LEFT_J:733 confb |= 0x1;734 break;735 case SND_SOC_DAIFMT_RIGHT_J:736 confb |= 0x2;737 break;738 }739 740 break;741 case 20:742 dev_dbg(component->dev, "20bit\n");743 switch (sta350->format) {744 case SND_SOC_DAIFMT_I2S:745 confb |= 0x4;746 break;747 case SND_SOC_DAIFMT_LEFT_J:748 confb |= 0x5;749 break;750 case SND_SOC_DAIFMT_RIGHT_J:751 confb |= 0x6;752 break;753 }754 755 break;756 case 18:757 dev_dbg(component->dev, "18bit\n");758 switch (sta350->format) {759 case SND_SOC_DAIFMT_I2S:760 confb |= 0x8;761 break;762 case SND_SOC_DAIFMT_LEFT_J:763 confb |= 0x9;764 break;765 case SND_SOC_DAIFMT_RIGHT_J:766 confb |= 0xa;767 break;768 }769 770 break;771 case 16:772 dev_dbg(component->dev, "16bit\n");773 switch (sta350->format) {774 case SND_SOC_DAIFMT_I2S:775 confb |= 0x0;776 break;777 case SND_SOC_DAIFMT_LEFT_J:778 confb |= 0xd;779 break;780 case SND_SOC_DAIFMT_RIGHT_J:781 confb |= 0xe;782 break;783 }784 785 break;786 default:787 return -EINVAL;788 }789 790 ret = regmap_update_bits(sta350->regmap, STA350_CONFA,791 STA350_CONFA_MCS_MASK | STA350_CONFA_IR_MASK,792 confa);793 if (ret < 0)794 return ret;795 796 ret = regmap_update_bits(sta350->regmap, STA350_CONFB,797 STA350_CONFB_SAI_MASK | STA350_CONFB_SAIFB,798 confb);799 if (ret < 0)800 return ret;801 802 return 0;803}804 805static int sta350_startup_sequence(struct sta350_priv *sta350)806{807 if (sta350->gpiod_power_down)808 gpiod_set_value(sta350->gpiod_power_down, 1);809 810 if (sta350->gpiod_nreset) {811 gpiod_set_value(sta350->gpiod_nreset, 0);812 mdelay(1);813 gpiod_set_value(sta350->gpiod_nreset, 1);814 mdelay(1);815 }816 817 return 0;818}819 820/**821 * sta350_set_bias_level - DAPM callback822 * @component: the component device823 * @level: DAPM power level824 *825 * This is called by ALSA to put the component into low power mode826 * or to wake it up. If the component is powered off completely827 * all registers must be restored after power on.828 */829static int sta350_set_bias_level(struct snd_soc_component *component,830 enum snd_soc_bias_level level)831{832 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);833 int ret;834 835 dev_dbg(component->dev, "level = %d\n", level);836 switch (level) {837 case SND_SOC_BIAS_ON:838 break;839 840 case SND_SOC_BIAS_PREPARE:841 /* Full power on */842 regmap_update_bits(sta350->regmap, STA350_CONFF,843 STA350_CONFF_PWDN | STA350_CONFF_EAPD,844 STA350_CONFF_PWDN | STA350_CONFF_EAPD);845 break;846 847 case SND_SOC_BIAS_STANDBY:848 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {849 ret = regulator_bulk_enable(850 ARRAY_SIZE(sta350->supplies),851 sta350->supplies);852 if (ret < 0) {853 dev_err(component->dev,854 "Failed to enable supplies: %d\n",855 ret);856 return ret;857 }858 sta350_startup_sequence(sta350);859 sta350_cache_sync(component);860 }861 862 /* Power down */863 regmap_update_bits(sta350->regmap, STA350_CONFF,864 STA350_CONFF_PWDN | STA350_CONFF_EAPD,865 0);866 867 break;868 869 case SND_SOC_BIAS_OFF:870 /* The chip runs through the power down sequence for us */871 regmap_update_bits(sta350->regmap, STA350_CONFF,872 STA350_CONFF_PWDN | STA350_CONFF_EAPD, 0);873 874 /* power down: low */875 if (sta350->gpiod_power_down)876 gpiod_set_value(sta350->gpiod_power_down, 0);877 878 if (sta350->gpiod_nreset)879 gpiod_set_value(sta350->gpiod_nreset, 0);880 881 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies),882 sta350->supplies);883 break;884 }885 return 0;886}887 888static const struct snd_soc_dai_ops sta350_dai_ops = {889 .hw_params = sta350_hw_params,890 .set_sysclk = sta350_set_dai_sysclk,891 .set_fmt = sta350_set_dai_fmt,892};893 894static struct snd_soc_dai_driver sta350_dai = {895 .name = "sta350-hifi",896 .playback = {897 .stream_name = "Playback",898 .channels_min = 2,899 .channels_max = 2,900 .rates = STA350_RATES,901 .formats = STA350_FORMATS,902 },903 .ops = &sta350_dai_ops,904};905 906static int sta350_probe(struct snd_soc_component *component)907{908 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);909 struct sta350_platform_data *pdata = sta350->pdata;910 int i, ret = 0, thermal = 0;911 912 ret = regulator_bulk_enable(ARRAY_SIZE(sta350->supplies),913 sta350->supplies);914 if (ret < 0) {915 dev_err(component->dev, "Failed to enable supplies: %d\n", ret);916 return ret;917 }918 919 ret = sta350_startup_sequence(sta350);920 if (ret < 0) {921 dev_err(component->dev, "Failed to startup device\n");922 return ret;923 }924 925 /* CONFA */926 if (!pdata->thermal_warning_recovery)927 thermal |= STA350_CONFA_TWAB;928 if (!pdata->thermal_warning_adjustment)929 thermal |= STA350_CONFA_TWRB;930 if (!pdata->fault_detect_recovery)931 thermal |= STA350_CONFA_FDRB;932 regmap_update_bits(sta350->regmap, STA350_CONFA,933 STA350_CONFA_TWAB | STA350_CONFA_TWRB |934 STA350_CONFA_FDRB,935 thermal);936 937 /* CONFC */938 regmap_update_bits(sta350->regmap, STA350_CONFC,939 STA350_CONFC_OM_MASK,940 pdata->ffx_power_output_mode941 << STA350_CONFC_OM_SHIFT);942 regmap_update_bits(sta350->regmap, STA350_CONFC,943 STA350_CONFC_CSZ_MASK,944 pdata->drop_compensation_ns945 << STA350_CONFC_CSZ_SHIFT);946 regmap_update_bits(sta350->regmap,947 STA350_CONFC,948 STA350_CONFC_OCRB,949 pdata->oc_warning_adjustment ?950 STA350_CONFC_OCRB : 0);951 952 /* CONFE */953 regmap_update_bits(sta350->regmap, STA350_CONFE,954 STA350_CONFE_MPCV,955 pdata->max_power_use_mpcc ?956 STA350_CONFE_MPCV : 0);957 regmap_update_bits(sta350->regmap, STA350_CONFE,958 STA350_CONFE_MPC,959 pdata->max_power_correction ?960 STA350_CONFE_MPC : 0);961 regmap_update_bits(sta350->regmap, STA350_CONFE,962 STA350_CONFE_AME,963 pdata->am_reduction_mode ?964 STA350_CONFE_AME : 0);965 regmap_update_bits(sta350->regmap, STA350_CONFE,966 STA350_CONFE_PWMS,967 pdata->odd_pwm_speed_mode ?968 STA350_CONFE_PWMS : 0);969 regmap_update_bits(sta350->regmap, STA350_CONFE,970 STA350_CONFE_DCCV,971 pdata->distortion_compensation ?972 STA350_CONFE_DCCV : 0);973 /* CONFF */974 regmap_update_bits(sta350->regmap, STA350_CONFF,975 STA350_CONFF_IDE,976 pdata->invalid_input_detect_mute ?977 STA350_CONFF_IDE : 0);978 regmap_update_bits(sta350->regmap, STA350_CONFF,979 STA350_CONFF_OCFG_MASK,980 pdata->output_conf981 << STA350_CONFF_OCFG_SHIFT);982 983 /* channel to output mapping */984 regmap_update_bits(sta350->regmap, STA350_C1CFG,985 STA350_CxCFG_OM_MASK,986 pdata->ch1_output_mapping987 << STA350_CxCFG_OM_SHIFT);988 regmap_update_bits(sta350->regmap, STA350_C2CFG,989 STA350_CxCFG_OM_MASK,990 pdata->ch2_output_mapping991 << STA350_CxCFG_OM_SHIFT);992 regmap_update_bits(sta350->regmap, STA350_C3CFG,993 STA350_CxCFG_OM_MASK,994 pdata->ch3_output_mapping995 << STA350_CxCFG_OM_SHIFT);996 997 /* miscellaneous registers */998 regmap_update_bits(sta350->regmap, STA350_MISC1,999 STA350_MISC1_CPWMEN,1000 pdata->activate_mute_output ?1001 STA350_MISC1_CPWMEN : 0);1002 regmap_update_bits(sta350->regmap, STA350_MISC1,1003 STA350_MISC1_BRIDGOFF,1004 pdata->bridge_immediate_off ?1005 STA350_MISC1_BRIDGOFF : 0);1006 regmap_update_bits(sta350->regmap, STA350_MISC1,1007 STA350_MISC1_NSHHPEN,1008 pdata->noise_shape_dc_cut ?1009 STA350_MISC1_NSHHPEN : 0);1010 regmap_update_bits(sta350->regmap, STA350_MISC1,1011 STA350_MISC1_RPDNEN,1012 pdata->powerdown_master_vol ?1013 STA350_MISC1_RPDNEN: 0);1014 1015 regmap_update_bits(sta350->regmap, STA350_MISC2,1016 STA350_MISC2_PNDLSL_MASK,1017 pdata->powerdown_delay_divider1018 << STA350_MISC2_PNDLSL_SHIFT);1019 1020 /* initialize coefficient shadow RAM with reset values */1021 for (i = 4; i <= 49; i += 5)1022 sta350->coef_shadow[i] = 0x400000;1023 for (i = 50; i <= 54; i++)1024 sta350->coef_shadow[i] = 0x7fffff;1025 sta350->coef_shadow[55] = 0x5a9df7;1026 sta350->coef_shadow[56] = 0x7fffff;1027 sta350->coef_shadow[59] = 0x7fffff;1028 sta350->coef_shadow[60] = 0x400000;1029 sta350->coef_shadow[61] = 0x400000;1030 1031 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);1032 /* Bias level configuration will have done an extra enable */1033 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);1034 1035 return 0;1036}1037 1038static void sta350_remove(struct snd_soc_component *component)1039{1040 struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component);1041 1042 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);1043}1044 1045static const struct snd_soc_component_driver sta350_component = {1046 .probe = sta350_probe,1047 .remove = sta350_remove,1048 .set_bias_level = sta350_set_bias_level,1049 .controls = sta350_snd_controls,1050 .num_controls = ARRAY_SIZE(sta350_snd_controls),1051 .dapm_widgets = sta350_dapm_widgets,1052 .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets),1053 .dapm_routes = sta350_dapm_routes,1054 .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes),1055 .suspend_bias_off = 1,1056 .idle_bias_on = 1,1057 .use_pmdown_time = 1,1058 .endianness = 1,1059};1060 1061static const struct regmap_config sta350_regmap = {1062 .reg_bits = 8,1063 .val_bits = 8,1064 .max_register = STA350_MISC2,1065 .reg_defaults = sta350_regs,1066 .num_reg_defaults = ARRAY_SIZE(sta350_regs),1067 .cache_type = REGCACHE_MAPLE,1068 .wr_table = &sta350_write_regs,1069 .rd_table = &sta350_read_regs,1070 .volatile_table = &sta350_volatile_regs,1071};1072 1073#ifdef CONFIG_OF1074static const struct of_device_id st350_dt_ids[] = {1075 { .compatible = "st,sta350", },1076 { }1077};1078MODULE_DEVICE_TABLE(of, st350_dt_ids);1079 1080static const char * const sta350_ffx_modes[] = {1081 [STA350_FFX_PM_DROP_COMP] = "drop-compensation",1082 [STA350_FFX_PM_TAPERED_COMP] = "tapered-compensation",1083 [STA350_FFX_PM_FULL_POWER] = "full-power-mode",1084 [STA350_FFX_PM_VARIABLE_DROP_COMP] = "variable-drop-compensation",1085};1086 1087static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350)1088{1089 struct device_node *np = dev->of_node;1090 struct sta350_platform_data *pdata;1091 const char *ffx_power_mode;1092 u16 tmp;1093 u8 tmp8;1094 1095 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);1096 if (!pdata)1097 return -ENOMEM;1098 1099 of_property_read_u8(np, "st,output-conf",1100 &pdata->output_conf);1101 of_property_read_u8(np, "st,ch1-output-mapping",1102 &pdata->ch1_output_mapping);1103 of_property_read_u8(np, "st,ch2-output-mapping",1104 &pdata->ch2_output_mapping);1105 of_property_read_u8(np, "st,ch3-output-mapping",1106 &pdata->ch3_output_mapping);1107 1108 pdata->thermal_warning_recovery =1109 of_property_read_bool(np, "st,thermal-warning-recovery");1110 pdata->thermal_warning_adjustment =1111 of_property_read_bool(np, "st,thermal-warning-adjustment");1112 pdata->fault_detect_recovery =1113 of_property_read_bool(np, "st,fault-detect-recovery");1114 1115 pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP;1116 if (!of_property_read_string(np, "st,ffx-power-output-mode",1117 &ffx_power_mode)) {1118 int i, mode = -EINVAL;1119 1120 for (i = 0; i < ARRAY_SIZE(sta350_ffx_modes); i++)1121 if (!strcasecmp(ffx_power_mode, sta350_ffx_modes[i]))1122 mode = i;1123 1124 if (mode < 0)1125 dev_warn(dev, "Unsupported ffx output mode: %s\n",1126 ffx_power_mode);1127 else1128 pdata->ffx_power_output_mode = mode;1129 }1130 1131 tmp = 140;1132 of_property_read_u16(np, "st,drop-compensation-ns", &tmp);1133 pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20;1134 1135 pdata->oc_warning_adjustment =1136 of_property_read_bool(np, "st,overcurrent-warning-adjustment");1137 1138 /* CONFE */1139 pdata->max_power_use_mpcc =1140 of_property_read_bool(np, "st,max-power-use-mpcc");1141 pdata->max_power_correction =1142 of_property_read_bool(np, "st,max-power-correction");1143 pdata->am_reduction_mode =1144 of_property_read_bool(np, "st,am-reduction-mode");1145 pdata->odd_pwm_speed_mode =1146 of_property_read_bool(np, "st,odd-pwm-speed-mode");1147 pdata->distortion_compensation =1148 of_property_read_bool(np, "st,distortion-compensation");1149 1150 /* CONFF */1151 pdata->invalid_input_detect_mute =1152 of_property_read_bool(np, "st,invalid-input-detect-mute");1153 1154 /* MISC */1155 pdata->activate_mute_output =1156 of_property_read_bool(np, "st,activate-mute-output");1157 pdata->bridge_immediate_off =1158 of_property_read_bool(np, "st,bridge-immediate-off");1159 pdata->noise_shape_dc_cut =1160 of_property_read_bool(np, "st,noise-shape-dc-cut");1161 pdata->powerdown_master_vol =1162 of_property_read_bool(np, "st,powerdown-master-volume");1163 1164 if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) {1165 if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128)1166 pdata->powerdown_delay_divider = ilog2(tmp8);1167 else1168 dev_warn(dev, "Unsupported powerdown delay divider %d\n",1169 tmp8);1170 }1171 1172 sta350->pdata = pdata;1173 1174 return 0;1175}1176#endif1177 1178static int sta350_i2c_probe(struct i2c_client *i2c)1179{1180 struct device *dev = &i2c->dev;1181 struct sta350_priv *sta350;1182 int ret, i;1183 1184 sta350 = devm_kzalloc(dev, sizeof(struct sta350_priv), GFP_KERNEL);1185 if (!sta350)1186 return -ENOMEM;1187 1188 mutex_init(&sta350->coeff_lock);1189 sta350->pdata = dev_get_platdata(dev);1190 1191#ifdef CONFIG_OF1192 if (dev->of_node) {1193 ret = sta350_probe_dt(dev, sta350);1194 if (ret < 0)1195 return ret;1196 }1197#endif1198 1199 /* GPIOs */1200 sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset",1201 GPIOD_OUT_LOW);1202 if (IS_ERR(sta350->gpiod_nreset))1203 return PTR_ERR(sta350->gpiod_nreset);1204 1205 sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down",1206 GPIOD_OUT_LOW);1207 if (IS_ERR(sta350->gpiod_power_down))1208 return PTR_ERR(sta350->gpiod_power_down);1209 1210 /* regulators */1211 for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)1212 sta350->supplies[i].supply = sta350_supply_names[i];1213 1214 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies),1215 sta350->supplies);1216 if (ret < 0) {1217 dev_err(dev, "Failed to request supplies: %d\n", ret);1218 return ret;1219 }1220 1221 sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap);1222 if (IS_ERR(sta350->regmap)) {1223 ret = PTR_ERR(sta350->regmap);1224 dev_err(dev, "Failed to init regmap: %d\n", ret);1225 return ret;1226 }1227 1228 i2c_set_clientdata(i2c, sta350);1229 1230 ret = devm_snd_soc_register_component(dev, &sta350_component, &sta350_dai, 1);1231 if (ret < 0)1232 dev_err(dev, "Failed to register component (%d)\n", ret);1233 1234 return ret;1235}1236 1237static void sta350_i2c_remove(struct i2c_client *client)1238{}1239 1240static const struct i2c_device_id sta350_i2c_id[] = {1241 { "sta350" },1242 { }1243};1244MODULE_DEVICE_TABLE(i2c, sta350_i2c_id);1245 1246static struct i2c_driver sta350_i2c_driver = {1247 .driver = {1248 .name = "sta350",1249 .of_match_table = of_match_ptr(st350_dt_ids),1250 },1251 .probe = sta350_i2c_probe,1252 .remove = sta350_i2c_remove,1253 .id_table = sta350_i2c_id,1254};1255 1256module_i2c_driver(sta350_i2c_driver);1257 1258MODULE_DESCRIPTION("ASoC STA350 driver");1259MODULE_AUTHOR("Sven Brandau <info@brandau.biz>");1260MODULE_LICENSE("GPL");1261