1056 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * wm8580.c -- WM8580 and WM8581 ALSA Soc Audio driver4 *5 * Copyright 2008-12 Wolfson Microelectronics PLC.6 *7 * Notes:8 * The WM8580 is a multichannel codec with S/PDIF support, featuring six9 * DAC channels and two ADC channels.10 *11 * The WM8581 is a multichannel codec with S/PDIF support, featuring eight12 * DAC channels and two ADC channels.13 *14 * Currently only the primary audio interface is supported - S/PDIF and15 * the secondary audio interfaces are not.16 */17 18#include <linux/mod_devicetable.h>19#include <linux/module.h>20#include <linux/moduleparam.h>21#include <linux/kernel.h>22#include <linux/init.h>23#include <linux/delay.h>24#include <linux/pm.h>25#include <linux/i2c.h>26#include <linux/regmap.h>27#include <linux/regulator/consumer.h>28#include <linux/slab.h>29 30#include <sound/core.h>31#include <sound/pcm.h>32#include <sound/pcm_params.h>33#include <sound/soc.h>34#include <sound/tlv.h>35#include <sound/initval.h>36#include <asm/div64.h>37 38#include "wm8580.h"39 40/* WM8580 register space */41#define WM8580_PLLA1 0x0042#define WM8580_PLLA2 0x0143#define WM8580_PLLA3 0x0244#define WM8580_PLLA4 0x0345#define WM8580_PLLB1 0x0446#define WM8580_PLLB2 0x0547#define WM8580_PLLB3 0x0648#define WM8580_PLLB4 0x0749#define WM8580_CLKSEL 0x0850#define WM8580_PAIF1 0x0951#define WM8580_PAIF2 0x0A52#define WM8580_SAIF1 0x0B53#define WM8580_PAIF3 0x0C54#define WM8580_PAIF4 0x0D55#define WM8580_SAIF2 0x0E56#define WM8580_DAC_CONTROL1 0x0F57#define WM8580_DAC_CONTROL2 0x1058#define WM8580_DAC_CONTROL3 0x1159#define WM8580_DAC_CONTROL4 0x1260#define WM8580_DAC_CONTROL5 0x1361#define WM8580_DIGITAL_ATTENUATION_DACL1 0x1462#define WM8580_DIGITAL_ATTENUATION_DACR1 0x1563#define WM8580_DIGITAL_ATTENUATION_DACL2 0x1664#define WM8580_DIGITAL_ATTENUATION_DACR2 0x1765#define WM8580_DIGITAL_ATTENUATION_DACL3 0x1866#define WM8580_DIGITAL_ATTENUATION_DACR3 0x1967#define WM8581_DIGITAL_ATTENUATION_DACL4 0x1A68#define WM8581_DIGITAL_ATTENUATION_DACR4 0x1B69#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C70#define WM8580_ADC_CONTROL1 0x1D71#define WM8580_SPDTXCHAN0 0x1E72#define WM8580_SPDTXCHAN1 0x1F73#define WM8580_SPDTXCHAN2 0x2074#define WM8580_SPDTXCHAN3 0x2175#define WM8580_SPDTXCHAN4 0x2276#define WM8580_SPDTXCHAN5 0x2377#define WM8580_SPDMODE 0x2478#define WM8580_INTMASK 0x2579#define WM8580_GPO1 0x2680#define WM8580_GPO2 0x2781#define WM8580_GPO3 0x2882#define WM8580_GPO4 0x2983#define WM8580_GPO5 0x2A84#define WM8580_INTSTAT 0x2B85#define WM8580_SPDRXCHAN1 0x2C86#define WM8580_SPDRXCHAN2 0x2D87#define WM8580_SPDRXCHAN3 0x2E88#define WM8580_SPDRXCHAN4 0x2F89#define WM8580_SPDRXCHAN5 0x3090#define WM8580_SPDSTAT 0x3191#define WM8580_PWRDN1 0x3292#define WM8580_PWRDN2 0x3393#define WM8580_READBACK 0x3494#define WM8580_RESET 0x3595 96#define WM8580_MAX_REGISTER 0x3597 98#define WM8580_DACOSR 0x4099 100/* PLLB4 (register 7h) */101#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60102#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20103#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40104#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60105 106#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180107#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080108#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100109#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180110 111/* CLKSEL (register 8h) */112#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03113#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01114#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02115 116/* AIF control 1 (registers 9h-bh) */117#define WM8580_AIF_RATE_MASK 0x7118#define WM8580_AIF_BCLKSEL_MASK 0x18119 120#define WM8580_AIF_MS 0x20121 122#define WM8580_AIF_CLKSRC_MASK 0xc0123#define WM8580_AIF_CLKSRC_PLLA 0x40124#define WM8580_AIF_CLKSRC_PLLB 0x40125#define WM8580_AIF_CLKSRC_MCLK 0xc0126 127/* AIF control 2 (registers ch-eh) */128#define WM8580_AIF_FMT_MASK 0x03129#define WM8580_AIF_FMT_RIGHTJ 0x00130#define WM8580_AIF_FMT_LEFTJ 0x01131#define WM8580_AIF_FMT_I2S 0x02132#define WM8580_AIF_FMT_DSP 0x03133 134#define WM8580_AIF_LENGTH_MASK 0x0c135#define WM8580_AIF_LENGTH_16 0x00136#define WM8580_AIF_LENGTH_20 0x04137#define WM8580_AIF_LENGTH_24 0x08138#define WM8580_AIF_LENGTH_32 0x0c139 140#define WM8580_AIF_LRP 0x10141#define WM8580_AIF_BCP 0x20142 143/* Powerdown Register 1 (register 32h) */144#define WM8580_PWRDN1_PWDN 0x001145#define WM8580_PWRDN1_ALLDACPD 0x040146 147/* Powerdown Register 2 (register 33h) */148#define WM8580_PWRDN2_OSSCPD 0x001149#define WM8580_PWRDN2_PLLAPD 0x002150#define WM8580_PWRDN2_PLLBPD 0x004151#define WM8580_PWRDN2_SPDIFPD 0x008152#define WM8580_PWRDN2_SPDIFTXD 0x010153#define WM8580_PWRDN2_SPDIFRXD 0x020154 155#define WM8580_DAC_CONTROL5_MUTEALL 0x10156 157/*158 * wm8580 register cache159 * We can't read the WM8580 register space when we160 * are using 2 wire for device control, so we cache them instead.161 */162static const struct reg_default wm8580_reg_defaults[] = {163 { 0, 0x0121 },164 { 1, 0x017e },165 { 2, 0x007d },166 { 3, 0x0014 },167 { 4, 0x0121 },168 { 5, 0x017e },169 { 6, 0x007d },170 { 7, 0x0194 },171 { 8, 0x0010 },172 { 9, 0x0002 },173 { 10, 0x0002 },174 { 11, 0x00c2 },175 { 12, 0x0182 },176 { 13, 0x0082 },177 { 14, 0x000a },178 { 15, 0x0024 },179 { 16, 0x0009 },180 { 17, 0x0000 },181 { 18, 0x00ff },182 { 19, 0x0000 },183 { 20, 0x00ff },184 { 21, 0x00ff },185 { 22, 0x00ff },186 { 23, 0x00ff },187 { 24, 0x00ff },188 { 25, 0x00ff },189 { 26, 0x00ff },190 { 27, 0x00ff },191 { 28, 0x01f0 },192 { 29, 0x0040 },193 { 30, 0x0000 },194 { 31, 0x0000 },195 { 32, 0x0000 },196 { 33, 0x0000 },197 { 34, 0x0031 },198 { 35, 0x000b },199 { 36, 0x0039 },200 { 37, 0x0000 },201 { 38, 0x0010 },202 { 39, 0x0032 },203 { 40, 0x0054 },204 { 41, 0x0076 },205 { 42, 0x0098 },206 { 43, 0x0000 },207 { 44, 0x0000 },208 { 45, 0x0000 },209 { 46, 0x0000 },210 { 47, 0x0000 },211 { 48, 0x0000 },212 { 49, 0x0000 },213 { 50, 0x005e },214 { 51, 0x003e },215 { 52, 0x0000 },216};217 218static bool wm8580_volatile(struct device *dev, unsigned int reg)219{220 switch (reg) {221 case WM8580_RESET:222 return true;223 default:224 return false;225 }226}227 228struct pll_state {229 unsigned int in;230 unsigned int out;231};232 233#define WM8580_NUM_SUPPLIES 3234static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {235 "AVDD",236 "DVDD",237 "PVDD",238};239 240struct wm8580_driver_data {241 int num_dacs;242};243 244/* codec private data */245struct wm8580_priv {246 struct regmap *regmap;247 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];248 struct pll_state a;249 struct pll_state b;250 const struct wm8580_driver_data *drvdata;251 int sysclk[2];252};253 254static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);255 256static int wm8580_out_vu(struct snd_kcontrol *kcontrol,257 struct snd_ctl_elem_value *ucontrol)258{259 struct soc_mixer_control *mc =260 (struct soc_mixer_control *)kcontrol->private_value;261 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);262 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);263 unsigned int reg = mc->reg;264 unsigned int reg2 = mc->rreg;265 int ret;266 267 /* Clear the register cache VU so we write without VU set */268 regcache_cache_only(wm8580->regmap, true);269 regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000);270 regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000);271 regcache_cache_only(wm8580->regmap, false);272 273 ret = snd_soc_put_volsw(kcontrol, ucontrol);274 if (ret < 0)275 return ret;276 277 /* Now write again with the volume update bit set */278 snd_soc_component_update_bits(component, reg, 0x100, 0x100);279 snd_soc_component_update_bits(component, reg2, 0x100, 0x100);280 281 return 0;282}283 284static const struct snd_kcontrol_new wm8580_snd_controls[] = {285SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",286 WM8580_DIGITAL_ATTENUATION_DACL1,287 WM8580_DIGITAL_ATTENUATION_DACR1,288 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),289SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",290 WM8580_DIGITAL_ATTENUATION_DACL2,291 WM8580_DIGITAL_ATTENUATION_DACR2,292 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),293SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",294 WM8580_DIGITAL_ATTENUATION_DACL3,295 WM8580_DIGITAL_ATTENUATION_DACR3,296 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),297 298SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),299SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),300SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0),301 302SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4, 0, 1, 1, 0),303SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0),304SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0),305 306SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0),307SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),308SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),309SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),310 311SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),312SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),313};314 315static const struct snd_kcontrol_new wm8581_snd_controls[] = {316SOC_DOUBLE_R_EXT_TLV("DAC4 Playback Volume",317 WM8581_DIGITAL_ATTENUATION_DACL4,318 WM8581_DIGITAL_ATTENUATION_DACR4,319 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),320 321SOC_SINGLE("DAC4 Deemphasis Switch", WM8580_DAC_CONTROL3, 3, 1, 0),322 323SOC_DOUBLE("DAC4 Invert Switch", WM8580_DAC_CONTROL4, 8, 7, 1, 0),324 325SOC_SINGLE("DAC4 Switch", WM8580_DAC_CONTROL5, 3, 1, 1),326};327 328static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {329SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),330SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),331SND_SOC_DAPM_DAC("DAC3", "Playback", WM8580_PWRDN1, 4, 1),332 333SND_SOC_DAPM_OUTPUT("VOUT1L"),334SND_SOC_DAPM_OUTPUT("VOUT1R"),335SND_SOC_DAPM_OUTPUT("VOUT2L"),336SND_SOC_DAPM_OUTPUT("VOUT2R"),337SND_SOC_DAPM_OUTPUT("VOUT3L"),338SND_SOC_DAPM_OUTPUT("VOUT3R"),339 340SND_SOC_DAPM_ADC("ADC", "Capture", WM8580_PWRDN1, 1, 1),341 342SND_SOC_DAPM_INPUT("AINL"),343SND_SOC_DAPM_INPUT("AINR"),344};345 346static const struct snd_soc_dapm_widget wm8581_dapm_widgets[] = {347SND_SOC_DAPM_DAC("DAC4", "Playback", WM8580_PWRDN1, 5, 1),348 349SND_SOC_DAPM_OUTPUT("VOUT4L"),350SND_SOC_DAPM_OUTPUT("VOUT4R"),351};352 353static const struct snd_soc_dapm_route wm8580_dapm_routes[] = {354 { "VOUT1L", NULL, "DAC1" },355 { "VOUT1R", NULL, "DAC1" },356 357 { "VOUT2L", NULL, "DAC2" },358 { "VOUT2R", NULL, "DAC2" },359 360 { "VOUT3L", NULL, "DAC3" },361 { "VOUT3R", NULL, "DAC3" },362 363 { "ADC", NULL, "AINL" },364 { "ADC", NULL, "AINR" },365};366 367static const struct snd_soc_dapm_route wm8581_dapm_routes[] = {368 { "VOUT4L", NULL, "DAC4" },369 { "VOUT4R", NULL, "DAC4" },370};371 372/* PLL divisors */373struct _pll_div {374 u32 prescale:1;375 u32 postscale:1;376 u32 freqmode:2;377 u32 n:4;378 u32 k:24;379};380 381/* The size in bits of the pll divide */382#define FIXED_PLL_SIZE (1 << 22)383 384/* PLL rate to output rate divisions */385static struct {386 unsigned int div;387 unsigned int freqmode;388 unsigned int postscale;389} post_table[] = {390 { 2, 0, 0 },391 { 4, 0, 1 },392 { 4, 1, 0 },393 { 8, 1, 1 },394 { 8, 2, 0 },395 { 16, 2, 1 },396 { 12, 3, 0 },397 { 24, 3, 1 }398};399 400static int pll_factors(struct _pll_div *pll_div, unsigned int target,401 unsigned int source)402{403 u64 Kpart;404 unsigned int K, Ndiv, Nmod;405 int i;406 407 pr_debug("wm8580: PLL %uHz->%uHz\n", source, target);408 409 /* Scale the output frequency up; the PLL should run in the410 * region of 90-100MHz.411 */412 for (i = 0; i < ARRAY_SIZE(post_table); i++) {413 if (target * post_table[i].div >= 90000000 &&414 target * post_table[i].div <= 100000000) {415 pll_div->freqmode = post_table[i].freqmode;416 pll_div->postscale = post_table[i].postscale;417 target *= post_table[i].div;418 break;419 }420 }421 422 if (i == ARRAY_SIZE(post_table)) {423 printk(KERN_ERR "wm8580: Unable to scale output frequency "424 "%u\n", target);425 return -EINVAL;426 }427 428 Ndiv = target / source;429 430 if (Ndiv < 5) {431 source /= 2;432 pll_div->prescale = 1;433 Ndiv = target / source;434 } else435 pll_div->prescale = 0;436 437 if ((Ndiv < 5) || (Ndiv > 13)) {438 printk(KERN_ERR439 "WM8580 N=%u outside supported range\n", Ndiv);440 return -EINVAL;441 }442 443 pll_div->n = Ndiv;444 Nmod = target % source;445 Kpart = FIXED_PLL_SIZE * (long long)Nmod;446 447 do_div(Kpart, source);448 449 K = Kpart & 0xFFFFFFFF;450 451 pll_div->k = K;452 453 pr_debug("PLL %x.%x prescale %d freqmode %d postscale %d\n",454 pll_div->n, pll_div->k, pll_div->prescale, pll_div->freqmode,455 pll_div->postscale);456 457 return 0;458}459 460static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,461 int source, unsigned int freq_in, unsigned int freq_out)462{463 int offset;464 struct snd_soc_component *component = codec_dai->component;465 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);466 struct pll_state *state;467 struct _pll_div pll_div;468 unsigned int reg;469 unsigned int pwr_mask;470 int ret;471 472 /* GCC isn't able to work out the ifs below for initialising/using473 * pll_div so suppress warnings.474 */475 memset(&pll_div, 0, sizeof(pll_div));476 477 switch (pll_id) {478 case WM8580_PLLA:479 state = &wm8580->a;480 offset = 0;481 pwr_mask = WM8580_PWRDN2_PLLAPD;482 break;483 case WM8580_PLLB:484 state = &wm8580->b;485 offset = 4;486 pwr_mask = WM8580_PWRDN2_PLLBPD;487 break;488 default:489 return -ENODEV;490 }491 492 if (freq_in && freq_out) {493 ret = pll_factors(&pll_div, freq_out, freq_in);494 if (ret != 0)495 return ret;496 }497 498 state->in = freq_in;499 state->out = freq_out;500 501 /* Always disable the PLL - it is not safe to leave it running502 * while reprogramming it.503 */504 snd_soc_component_update_bits(component, WM8580_PWRDN2, pwr_mask, pwr_mask);505 506 if (!freq_in || !freq_out)507 return 0;508 509 snd_soc_component_write(component, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);510 snd_soc_component_write(component, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff);511 snd_soc_component_write(component, WM8580_PLLA3 + offset,512 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));513 514 reg = snd_soc_component_read(component, WM8580_PLLA4 + offset);515 reg &= ~0x1b;516 reg |= pll_div.prescale | pll_div.postscale << 1 |517 pll_div.freqmode << 3;518 519 snd_soc_component_write(component, WM8580_PLLA4 + offset, reg);520 521 /* All done, turn it on */522 snd_soc_component_update_bits(component, WM8580_PWRDN2, pwr_mask, 0);523 524 return 0;525}526 527static const int wm8580_sysclk_ratios[] = {528 128, 192, 256, 384, 512, 768, 1152,529};530 531/*532 * Set PCM DAI bit size and sample rate.533 */534static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,535 struct snd_pcm_hw_params *params,536 struct snd_soc_dai *dai)537{538 struct snd_soc_component *component = dai->component;539 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);540 u16 paifa = 0;541 u16 paifb = 0;542 int i, ratio, osr;543 544 /* bit size */545 switch (params_width(params)) {546 case 16:547 paifa |= 0x8;548 break;549 case 20:550 paifa |= 0x0;551 paifb |= WM8580_AIF_LENGTH_20;552 break;553 case 24:554 paifa |= 0x0;555 paifb |= WM8580_AIF_LENGTH_24;556 break;557 case 32:558 paifa |= 0x0;559 paifb |= WM8580_AIF_LENGTH_32;560 break;561 default:562 return -EINVAL;563 }564 565 /* Look up the SYSCLK ratio; accept only exact matches */566 ratio = wm8580->sysclk[dai->driver->id] / params_rate(params);567 for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)568 if (ratio == wm8580_sysclk_ratios[i])569 break;570 if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {571 dev_err(component->dev, "Invalid clock ratio %d/%d\n",572 wm8580->sysclk[dai->driver->id], params_rate(params));573 return -EINVAL;574 }575 paifa |= i;576 dev_dbg(component->dev, "Running at %dfs with %dHz clock\n",577 wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);578 579 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {580 switch (ratio) {581 case 128:582 case 192:583 osr = WM8580_DACOSR;584 dev_dbg(component->dev, "Selecting 64x OSR\n");585 break;586 default:587 osr = 0;588 dev_dbg(component->dev, "Selecting 128x OSR\n");589 break;590 }591 592 snd_soc_component_update_bits(component, WM8580_PAIF3, WM8580_DACOSR, osr);593 }594 595 snd_soc_component_update_bits(component, WM8580_PAIF1 + dai->driver->id,596 WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK,597 paifa);598 snd_soc_component_update_bits(component, WM8580_PAIF3 + dai->driver->id,599 WM8580_AIF_LENGTH_MASK, paifb);600 return 0;601}602 603static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,604 unsigned int fmt)605{606 struct snd_soc_component *component = codec_dai->component;607 unsigned int aifa;608 unsigned int aifb;609 int can_invert_lrclk;610 611 aifa = snd_soc_component_read(component, WM8580_PAIF1 + codec_dai->driver->id);612 aifb = snd_soc_component_read(component, WM8580_PAIF3 + codec_dai->driver->id);613 614 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);615 616 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {617 case SND_SOC_DAIFMT_CBS_CFS:618 aifa &= ~WM8580_AIF_MS;619 break;620 case SND_SOC_DAIFMT_CBM_CFM:621 aifa |= WM8580_AIF_MS;622 break;623 default:624 return -EINVAL;625 }626 627 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {628 case SND_SOC_DAIFMT_I2S:629 can_invert_lrclk = 1;630 aifb |= WM8580_AIF_FMT_I2S;631 break;632 case SND_SOC_DAIFMT_RIGHT_J:633 can_invert_lrclk = 1;634 aifb |= WM8580_AIF_FMT_RIGHTJ;635 break;636 case SND_SOC_DAIFMT_LEFT_J:637 can_invert_lrclk = 1;638 aifb |= WM8580_AIF_FMT_LEFTJ;639 break;640 case SND_SOC_DAIFMT_DSP_A:641 can_invert_lrclk = 0;642 aifb |= WM8580_AIF_FMT_DSP;643 break;644 case SND_SOC_DAIFMT_DSP_B:645 can_invert_lrclk = 0;646 aifb |= WM8580_AIF_FMT_DSP;647 aifb |= WM8580_AIF_LRP;648 break;649 default:650 return -EINVAL;651 }652 653 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {654 case SND_SOC_DAIFMT_NB_NF:655 break;656 657 case SND_SOC_DAIFMT_IB_IF:658 if (!can_invert_lrclk)659 return -EINVAL;660 aifb |= WM8580_AIF_BCP;661 aifb |= WM8580_AIF_LRP;662 break;663 664 case SND_SOC_DAIFMT_IB_NF:665 aifb |= WM8580_AIF_BCP;666 break;667 668 case SND_SOC_DAIFMT_NB_IF:669 if (!can_invert_lrclk)670 return -EINVAL;671 aifb |= WM8580_AIF_LRP;672 break;673 674 default:675 return -EINVAL;676 }677 678 snd_soc_component_write(component, WM8580_PAIF1 + codec_dai->driver->id, aifa);679 snd_soc_component_write(component, WM8580_PAIF3 + codec_dai->driver->id, aifb);680 681 return 0;682}683 684static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,685 int div_id, int div)686{687 struct snd_soc_component *component = codec_dai->component;688 unsigned int reg;689 690 switch (div_id) {691 case WM8580_MCLK:692 reg = snd_soc_component_read(component, WM8580_PLLB4);693 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;694 695 switch (div) {696 case WM8580_CLKSRC_MCLK:697 /* Input */698 break;699 700 case WM8580_CLKSRC_PLLA:701 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLA;702 break;703 case WM8580_CLKSRC_PLLB:704 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLB;705 break;706 707 case WM8580_CLKSRC_OSC:708 reg |= WM8580_PLLB4_MCLKOUTSRC_OSC;709 break;710 711 default:712 return -EINVAL;713 }714 snd_soc_component_write(component, WM8580_PLLB4, reg);715 break;716 717 case WM8580_CLKOUTSRC:718 reg = snd_soc_component_read(component, WM8580_PLLB4);719 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;720 721 switch (div) {722 case WM8580_CLKSRC_NONE:723 break;724 725 case WM8580_CLKSRC_PLLA:726 reg |= WM8580_PLLB4_CLKOUTSRC_PLLACLK;727 break;728 729 case WM8580_CLKSRC_PLLB:730 reg |= WM8580_PLLB4_CLKOUTSRC_PLLBCLK;731 break;732 733 case WM8580_CLKSRC_OSC:734 reg |= WM8580_PLLB4_CLKOUTSRC_OSCCLK;735 break;736 737 default:738 return -EINVAL;739 }740 snd_soc_component_write(component, WM8580_PLLB4, reg);741 break;742 743 default:744 return -EINVAL;745 }746 747 return 0;748}749 750static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,751 unsigned int freq, int dir)752{753 struct snd_soc_component *component = dai->component;754 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);755 int ret, sel, sel_mask, sel_shift;756 757 switch (dai->driver->id) {758 case WM8580_DAI_PAIFRX:759 sel_mask = 0x3;760 sel_shift = 0;761 break;762 763 case WM8580_DAI_PAIFTX:764 sel_mask = 0xc;765 sel_shift = 2;766 break;767 768 default:769 WARN(1, "Unknown DAI driver ID\n");770 return -EINVAL;771 }772 773 switch (clk_id) {774 case WM8580_CLKSRC_ADCMCLK:775 if (dai->driver->id != WM8580_DAI_PAIFTX)776 return -EINVAL;777 sel = 0 << sel_shift;778 break;779 case WM8580_CLKSRC_PLLA:780 sel = 1 << sel_shift;781 break;782 case WM8580_CLKSRC_PLLB:783 sel = 2 << sel_shift;784 break;785 case WM8580_CLKSRC_MCLK:786 sel = 3 << sel_shift;787 break;788 default:789 dev_err(component->dev, "Unknown clock %d\n", clk_id);790 return -EINVAL;791 }792 793 /* We really should validate PLL settings but not yet */794 wm8580->sysclk[dai->driver->id] = freq;795 796 ret = snd_soc_component_update_bits(component, WM8580_CLKSEL, sel_mask, sel);797 if (ret < 0)798 return ret;799 800 return 0;801}802 803static int wm8580_mute(struct snd_soc_dai *codec_dai, int mute, int direction)804{805 struct snd_soc_component *component = codec_dai->component;806 unsigned int reg;807 808 reg = snd_soc_component_read(component, WM8580_DAC_CONTROL5);809 810 if (mute)811 reg |= WM8580_DAC_CONTROL5_MUTEALL;812 else813 reg &= ~WM8580_DAC_CONTROL5_MUTEALL;814 815 snd_soc_component_write(component, WM8580_DAC_CONTROL5, reg);816 817 return 0;818}819 820static int wm8580_set_bias_level(struct snd_soc_component *component,821 enum snd_soc_bias_level level)822{823 switch (level) {824 case SND_SOC_BIAS_ON:825 case SND_SOC_BIAS_PREPARE:826 break;827 828 case SND_SOC_BIAS_STANDBY:829 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {830 /* Power up and get individual control of the DACs */831 snd_soc_component_update_bits(component, WM8580_PWRDN1,832 WM8580_PWRDN1_PWDN |833 WM8580_PWRDN1_ALLDACPD, 0);834 835 /* Make VMID high impedance */836 snd_soc_component_update_bits(component, WM8580_ADC_CONTROL1,837 0x100, 0);838 }839 break;840 841 case SND_SOC_BIAS_OFF:842 snd_soc_component_update_bits(component, WM8580_PWRDN1,843 WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN);844 break;845 }846 return 0;847}848 849static int wm8580_playback_startup(struct snd_pcm_substream *substream,850 struct snd_soc_dai *dai)851{852 struct snd_soc_component *component = dai->component;853 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);854 855 return snd_pcm_hw_constraint_minmax(substream->runtime,856 SNDRV_PCM_HW_PARAM_CHANNELS, 1, wm8580->drvdata->num_dacs * 2);857}858 859#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\860 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)861 862static const struct snd_soc_dai_ops wm8580_dai_ops_playback = {863 .startup = wm8580_playback_startup,864 .set_sysclk = wm8580_set_sysclk,865 .hw_params = wm8580_paif_hw_params,866 .set_fmt = wm8580_set_paif_dai_fmt,867 .set_clkdiv = wm8580_set_dai_clkdiv,868 .set_pll = wm8580_set_dai_pll,869 .mute_stream = wm8580_mute,870 .no_capture_mute = 1,871};872 873static const struct snd_soc_dai_ops wm8580_dai_ops_capture = {874 .set_sysclk = wm8580_set_sysclk,875 .hw_params = wm8580_paif_hw_params,876 .set_fmt = wm8580_set_paif_dai_fmt,877 .set_clkdiv = wm8580_set_dai_clkdiv,878 .set_pll = wm8580_set_dai_pll,879};880 881static struct snd_soc_dai_driver wm8580_dai[] = {882 {883 .name = "wm8580-hifi-playback",884 .id = WM8580_DAI_PAIFRX,885 .playback = {886 .stream_name = "Playback",887 .channels_min = 1,888 .rates = SNDRV_PCM_RATE_8000_192000,889 .formats = WM8580_FORMATS,890 },891 .ops = &wm8580_dai_ops_playback,892 },893 {894 .name = "wm8580-hifi-capture",895 .id = WM8580_DAI_PAIFTX,896 .capture = {897 .stream_name = "Capture",898 .channels_min = 2,899 .channels_max = 2,900 .rates = SNDRV_PCM_RATE_8000_192000,901 .formats = WM8580_FORMATS,902 },903 .ops = &wm8580_dai_ops_capture,904 },905};906 907static int wm8580_probe(struct snd_soc_component *component)908{909 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);910 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);911 int ret = 0;912 913 switch (wm8580->drvdata->num_dacs) {914 case 4:915 snd_soc_add_component_controls(component, wm8581_snd_controls,916 ARRAY_SIZE(wm8581_snd_controls));917 snd_soc_dapm_new_controls(dapm, wm8581_dapm_widgets,918 ARRAY_SIZE(wm8581_dapm_widgets));919 snd_soc_dapm_add_routes(dapm, wm8581_dapm_routes,920 ARRAY_SIZE(wm8581_dapm_routes));921 break;922 default:923 break;924 }925 926 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),927 wm8580->supplies);928 if (ret != 0) {929 dev_err(component->dev, "Failed to enable supplies: %d\n", ret);930 goto err_regulator_get;931 }932 933 /* Get the codec into a known state */934 ret = snd_soc_component_write(component, WM8580_RESET, 0);935 if (ret != 0) {936 dev_err(component->dev, "Failed to reset component: %d\n", ret);937 goto err_regulator_enable;938 }939 940 return 0;941 942err_regulator_enable:943 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);944err_regulator_get:945 return ret;946}947 948/* power down chip */949static void wm8580_remove(struct snd_soc_component *component)950{951 struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);952 953 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);954}955 956static const struct snd_soc_component_driver soc_component_dev_wm8580 = {957 .probe = wm8580_probe,958 .remove = wm8580_remove,959 .set_bias_level = wm8580_set_bias_level,960 .controls = wm8580_snd_controls,961 .num_controls = ARRAY_SIZE(wm8580_snd_controls),962 .dapm_widgets = wm8580_dapm_widgets,963 .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets),964 .dapm_routes = wm8580_dapm_routes,965 .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes),966 .idle_bias_on = 1,967 .use_pmdown_time = 1,968 .endianness = 1,969};970 971static const struct regmap_config wm8580_regmap = {972 .reg_bits = 7,973 .val_bits = 9,974 .max_register = WM8580_MAX_REGISTER,975 976 .reg_defaults = wm8580_reg_defaults,977 .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults),978 .cache_type = REGCACHE_MAPLE,979 980 .volatile_reg = wm8580_volatile,981};982 983static const struct wm8580_driver_data wm8580_data = {984 .num_dacs = 3,985};986 987static const struct wm8580_driver_data wm8581_data = {988 .num_dacs = 4,989};990 991static int wm8580_i2c_probe(struct i2c_client *i2c)992{993 struct wm8580_priv *wm8580;994 int ret, i;995 996 wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv),997 GFP_KERNEL);998 if (wm8580 == NULL)999 return -ENOMEM;1000 1001 wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap);1002 if (IS_ERR(wm8580->regmap))1003 return PTR_ERR(wm8580->regmap);1004 1005 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)1006 wm8580->supplies[i].supply = wm8580_supply_names[i];1007 1008 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies),1009 wm8580->supplies);1010 if (ret != 0) {1011 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);1012 return ret;1013 }1014 1015 i2c_set_clientdata(i2c, wm8580);1016 1017 wm8580->drvdata = i2c_get_match_data(i2c);1018 if (!wm8580->drvdata)1019 return dev_err_probe(&i2c->dev, -EINVAL, "failed to find driver data\n");1020 1021 ret = devm_snd_soc_register_component(&i2c->dev,1022 &soc_component_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai));1023 1024 return ret;1025}1026 1027static const struct of_device_id wm8580_of_match[] = {1028 { .compatible = "wlf,wm8580", .data = &wm8580_data },1029 { .compatible = "wlf,wm8581", .data = &wm8581_data },1030 { }1031};1032MODULE_DEVICE_TABLE(of, wm8580_of_match);1033 1034static const struct i2c_device_id wm8580_i2c_id[] = {1035 { "wm8580", (kernel_ulong_t)&wm8580_data },1036 { "wm8581", (kernel_ulong_t)&wm8581_data },1037 { }1038};1039MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);1040 1041static struct i2c_driver wm8580_i2c_driver = {1042 .driver = {1043 .name = "wm8580",1044 .of_match_table = wm8580_of_match,1045 },1046 .probe = wm8580_i2c_probe,1047 .id_table = wm8580_i2c_id,1048};1049 1050module_i2c_driver(wm8580_i2c_driver);1051 1052MODULE_DESCRIPTION("ASoC WM8580 driver");1053MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");1054MODULE_AUTHOR("Matt Flax <flatmax@flatmax.org>");1055MODULE_LICENSE("GPL");1056