1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
286ed3669SMark Brown /*
386ed3669SMark Brown * wm9081.c -- WM9081 ALSA SoC Audio driver
486ed3669SMark Brown *
586ed3669SMark Brown * Author: Mark Brown
686ed3669SMark Brown *
7656baaebSMark Brown * Copyright 2009-12 Wolfson Microelectronics plc
886ed3669SMark Brown */
986ed3669SMark Brown
1086ed3669SMark Brown #include <linux/module.h>
1186ed3669SMark Brown #include <linux/moduleparam.h>
1286ed3669SMark Brown #include <linux/init.h>
1386ed3669SMark Brown #include <linux/delay.h>
143ee845acSMark Brown #include <linux/device.h>
1586ed3669SMark Brown #include <linux/pm.h>
1686ed3669SMark Brown #include <linux/i2c.h>
177cfa467bSMark Brown #include <linux/regmap.h>
185a0e3ad6STejun Heo #include <linux/slab.h>
1986ed3669SMark Brown #include <sound/core.h>
2086ed3669SMark Brown #include <sound/pcm.h>
2186ed3669SMark Brown #include <sound/pcm_params.h>
2286ed3669SMark Brown #include <sound/soc.h>
2386ed3669SMark Brown #include <sound/initval.h>
2486ed3669SMark Brown #include <sound/tlv.h>
2586ed3669SMark Brown
2686ed3669SMark Brown #include <sound/wm9081.h>
2786ed3669SMark Brown #include "wm9081.h"
2886ed3669SMark Brown
29c418a84aSAxel Lin static const struct reg_default wm9081_reg[] = {
307cfa467bSMark Brown { 2, 0x00B9 }, /* R2 - Analogue Lineout */
317cfa467bSMark Brown { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */
327cfa467bSMark Brown { 4, 0x0001 }, /* R4 - VMID Control */
337cfa467bSMark Brown { 5, 0x0068 }, /* R5 - Bias Control 1 */
347cfa467bSMark Brown { 7, 0x0000 }, /* R7 - Analogue Mixer */
357cfa467bSMark Brown { 8, 0x0000 }, /* R8 - Anti Pop Control */
367cfa467bSMark Brown { 9, 0x01DB }, /* R9 - Analogue Speaker 1 */
377cfa467bSMark Brown { 10, 0x0018 }, /* R10 - Analogue Speaker 2 */
387cfa467bSMark Brown { 11, 0x0180 }, /* R11 - Power Management */
397cfa467bSMark Brown { 12, 0x0000 }, /* R12 - Clock Control 1 */
407cfa467bSMark Brown { 13, 0x0038 }, /* R13 - Clock Control 2 */
417cfa467bSMark Brown { 14, 0x4000 }, /* R14 - Clock Control 3 */
427cfa467bSMark Brown { 16, 0x0000 }, /* R16 - FLL Control 1 */
437cfa467bSMark Brown { 17, 0x0200 }, /* R17 - FLL Control 2 */
447cfa467bSMark Brown { 18, 0x0000 }, /* R18 - FLL Control 3 */
457cfa467bSMark Brown { 19, 0x0204 }, /* R19 - FLL Control 4 */
467cfa467bSMark Brown { 20, 0x0000 }, /* R20 - FLL Control 5 */
477cfa467bSMark Brown { 22, 0x0000 }, /* R22 - Audio Interface 1 */
487cfa467bSMark Brown { 23, 0x0002 }, /* R23 - Audio Interface 2 */
497cfa467bSMark Brown { 24, 0x0008 }, /* R24 - Audio Interface 3 */
507cfa467bSMark Brown { 25, 0x0022 }, /* R25 - Audio Interface 4 */
517cfa467bSMark Brown { 27, 0x0006 }, /* R27 - Interrupt Status Mask */
527cfa467bSMark Brown { 28, 0x0000 }, /* R28 - Interrupt Polarity */
537cfa467bSMark Brown { 29, 0x0000 }, /* R29 - Interrupt Control */
547cfa467bSMark Brown { 30, 0x00C0 }, /* R30 - DAC Digital 1 */
557cfa467bSMark Brown { 31, 0x0008 }, /* R31 - DAC Digital 2 */
567cfa467bSMark Brown { 32, 0x09AF }, /* R32 - DRC 1 */
577cfa467bSMark Brown { 33, 0x4201 }, /* R33 - DRC 2 */
587cfa467bSMark Brown { 34, 0x0000 }, /* R34 - DRC 3 */
597cfa467bSMark Brown { 35, 0x0000 }, /* R35 - DRC 4 */
607cfa467bSMark Brown { 38, 0x0000 }, /* R38 - Write Sequencer 1 */
617cfa467bSMark Brown { 39, 0x0000 }, /* R39 - Write Sequencer 2 */
627cfa467bSMark Brown { 40, 0x0002 }, /* R40 - MW Slave 1 */
637cfa467bSMark Brown { 42, 0x0000 }, /* R42 - EQ 1 */
647cfa467bSMark Brown { 43, 0x0000 }, /* R43 - EQ 2 */
657cfa467bSMark Brown { 44, 0x0FCA }, /* R44 - EQ 3 */
667cfa467bSMark Brown { 45, 0x0400 }, /* R45 - EQ 4 */
677cfa467bSMark Brown { 46, 0x00B8 }, /* R46 - EQ 5 */
687cfa467bSMark Brown { 47, 0x1EB5 }, /* R47 - EQ 6 */
697cfa467bSMark Brown { 48, 0xF145 }, /* R48 - EQ 7 */
707cfa467bSMark Brown { 49, 0x0B75 }, /* R49 - EQ 8 */
717cfa467bSMark Brown { 50, 0x01C5 }, /* R50 - EQ 9 */
727cfa467bSMark Brown { 51, 0x169E }, /* R51 - EQ 10 */
737cfa467bSMark Brown { 52, 0xF829 }, /* R52 - EQ 11 */
747cfa467bSMark Brown { 53, 0x07AD }, /* R53 - EQ 12 */
757cfa467bSMark Brown { 54, 0x1103 }, /* R54 - EQ 13 */
767cfa467bSMark Brown { 55, 0x1C58 }, /* R55 - EQ 14 */
777cfa467bSMark Brown { 56, 0xF373 }, /* R56 - EQ 15 */
787cfa467bSMark Brown { 57, 0x0A54 }, /* R57 - EQ 16 */
797cfa467bSMark Brown { 58, 0x0558 }, /* R58 - EQ 17 */
807cfa467bSMark Brown { 59, 0x0564 }, /* R59 - EQ 18 */
817cfa467bSMark Brown { 60, 0x0559 }, /* R60 - EQ 19 */
827cfa467bSMark Brown { 61, 0x4000 }, /* R61 - EQ 20 */
8386ed3669SMark Brown };
8486ed3669SMark Brown
8586ed3669SMark Brown static struct {
8686ed3669SMark Brown int ratio;
8786ed3669SMark Brown int clk_sys_rate;
8886ed3669SMark Brown } clk_sys_rates[] = {
8986ed3669SMark Brown { 64, 0 },
9086ed3669SMark Brown { 128, 1 },
9186ed3669SMark Brown { 192, 2 },
9286ed3669SMark Brown { 256, 3 },
9386ed3669SMark Brown { 384, 4 },
9486ed3669SMark Brown { 512, 5 },
9586ed3669SMark Brown { 768, 6 },
9686ed3669SMark Brown { 1024, 7 },
9786ed3669SMark Brown { 1408, 8 },
9886ed3669SMark Brown { 1536, 9 },
9986ed3669SMark Brown };
10086ed3669SMark Brown
10186ed3669SMark Brown static struct {
10286ed3669SMark Brown int rate;
10386ed3669SMark Brown int sample_rate;
10486ed3669SMark Brown } sample_rates[] = {
10586ed3669SMark Brown { 8000, 0 },
10686ed3669SMark Brown { 11025, 1 },
10786ed3669SMark Brown { 12000, 2 },
10886ed3669SMark Brown { 16000, 3 },
10986ed3669SMark Brown { 22050, 4 },
11086ed3669SMark Brown { 24000, 5 },
11186ed3669SMark Brown { 32000, 6 },
11286ed3669SMark Brown { 44100, 7 },
11386ed3669SMark Brown { 48000, 8 },
11486ed3669SMark Brown { 88200, 9 },
11586ed3669SMark Brown { 96000, 10 },
11686ed3669SMark Brown };
11786ed3669SMark Brown
11886ed3669SMark Brown static struct {
11986ed3669SMark Brown int div; /* *10 due to .5s */
12086ed3669SMark Brown int bclk_div;
12186ed3669SMark Brown } bclk_divs[] = {
12286ed3669SMark Brown { 10, 0 },
12386ed3669SMark Brown { 15, 1 },
12486ed3669SMark Brown { 20, 2 },
12586ed3669SMark Brown { 30, 3 },
12686ed3669SMark Brown { 40, 4 },
12786ed3669SMark Brown { 50, 5 },
12886ed3669SMark Brown { 55, 6 },
12986ed3669SMark Brown { 60, 7 },
13086ed3669SMark Brown { 80, 8 },
13186ed3669SMark Brown { 100, 9 },
13286ed3669SMark Brown { 110, 10 },
13386ed3669SMark Brown { 120, 11 },
13486ed3669SMark Brown { 160, 12 },
13586ed3669SMark Brown { 200, 13 },
13686ed3669SMark Brown { 220, 14 },
13786ed3669SMark Brown { 240, 15 },
13886ed3669SMark Brown { 250, 16 },
13986ed3669SMark Brown { 300, 17 },
14086ed3669SMark Brown { 320, 18 },
14186ed3669SMark Brown { 440, 19 },
14286ed3669SMark Brown { 480, 20 },
14386ed3669SMark Brown };
14486ed3669SMark Brown
14586ed3669SMark Brown struct wm9081_priv {
1467cfa467bSMark Brown struct regmap *regmap;
14786ed3669SMark Brown int sysclk_source;
14886ed3669SMark Brown int mclk_rate;
14986ed3669SMark Brown int sysclk_rate;
15086ed3669SMark Brown int fs;
15186ed3669SMark Brown int bclk;
15286ed3669SMark Brown int master;
15386ed3669SMark Brown int fll_fref;
15486ed3669SMark Brown int fll_fout;
155e0026beaSMark Brown int tdm_width;
1564a5f7bdaSMark Brown struct wm9081_pdata pdata;
15786ed3669SMark Brown };
15886ed3669SMark Brown
wm9081_volatile_register(struct device * dev,unsigned int reg)1597cfa467bSMark Brown static bool wm9081_volatile_register(struct device *dev, unsigned int reg)
16086ed3669SMark Brown {
16186ed3669SMark Brown switch (reg) {
1628d50e447SMark Brown case WM9081_SOFTWARE_RESET:
163f8faadb6SMark Brown case WM9081_INTERRUPT_STATUS:
1647cfa467bSMark Brown return true;
16586ed3669SMark Brown default:
1667cfa467bSMark Brown return false;
16786ed3669SMark Brown }
16886ed3669SMark Brown }
16986ed3669SMark Brown
wm9081_readable_register(struct device * dev,unsigned int reg)1707cfa467bSMark Brown static bool wm9081_readable_register(struct device *dev, unsigned int reg)
17186ed3669SMark Brown {
1727cfa467bSMark Brown switch (reg) {
1737cfa467bSMark Brown case WM9081_SOFTWARE_RESET:
1747cfa467bSMark Brown case WM9081_ANALOGUE_LINEOUT:
1757cfa467bSMark Brown case WM9081_ANALOGUE_SPEAKER_PGA:
1767cfa467bSMark Brown case WM9081_VMID_CONTROL:
1777cfa467bSMark Brown case WM9081_BIAS_CONTROL_1:
1787cfa467bSMark Brown case WM9081_ANALOGUE_MIXER:
1797cfa467bSMark Brown case WM9081_ANTI_POP_CONTROL:
1807cfa467bSMark Brown case WM9081_ANALOGUE_SPEAKER_1:
1817cfa467bSMark Brown case WM9081_ANALOGUE_SPEAKER_2:
1827cfa467bSMark Brown case WM9081_POWER_MANAGEMENT:
1837cfa467bSMark Brown case WM9081_CLOCK_CONTROL_1:
1847cfa467bSMark Brown case WM9081_CLOCK_CONTROL_2:
1857cfa467bSMark Brown case WM9081_CLOCK_CONTROL_3:
1867cfa467bSMark Brown case WM9081_FLL_CONTROL_1:
1877cfa467bSMark Brown case WM9081_FLL_CONTROL_2:
1887cfa467bSMark Brown case WM9081_FLL_CONTROL_3:
1897cfa467bSMark Brown case WM9081_FLL_CONTROL_4:
1907cfa467bSMark Brown case WM9081_FLL_CONTROL_5:
1917cfa467bSMark Brown case WM9081_AUDIO_INTERFACE_1:
1927cfa467bSMark Brown case WM9081_AUDIO_INTERFACE_2:
1937cfa467bSMark Brown case WM9081_AUDIO_INTERFACE_3:
1947cfa467bSMark Brown case WM9081_AUDIO_INTERFACE_4:
1957cfa467bSMark Brown case WM9081_INTERRUPT_STATUS:
1967cfa467bSMark Brown case WM9081_INTERRUPT_STATUS_MASK:
1977cfa467bSMark Brown case WM9081_INTERRUPT_POLARITY:
1987cfa467bSMark Brown case WM9081_INTERRUPT_CONTROL:
1997cfa467bSMark Brown case WM9081_DAC_DIGITAL_1:
2007cfa467bSMark Brown case WM9081_DAC_DIGITAL_2:
2017cfa467bSMark Brown case WM9081_DRC_1:
2027cfa467bSMark Brown case WM9081_DRC_2:
2037cfa467bSMark Brown case WM9081_DRC_3:
2047cfa467bSMark Brown case WM9081_DRC_4:
2057cfa467bSMark Brown case WM9081_WRITE_SEQUENCER_1:
2067cfa467bSMark Brown case WM9081_WRITE_SEQUENCER_2:
2077cfa467bSMark Brown case WM9081_MW_SLAVE_1:
2087cfa467bSMark Brown case WM9081_EQ_1:
2097cfa467bSMark Brown case WM9081_EQ_2:
2107cfa467bSMark Brown case WM9081_EQ_3:
2117cfa467bSMark Brown case WM9081_EQ_4:
2127cfa467bSMark Brown case WM9081_EQ_5:
2137cfa467bSMark Brown case WM9081_EQ_6:
2147cfa467bSMark Brown case WM9081_EQ_7:
2157cfa467bSMark Brown case WM9081_EQ_8:
2167cfa467bSMark Brown case WM9081_EQ_9:
2177cfa467bSMark Brown case WM9081_EQ_10:
2187cfa467bSMark Brown case WM9081_EQ_11:
2197cfa467bSMark Brown case WM9081_EQ_12:
2207cfa467bSMark Brown case WM9081_EQ_13:
2217cfa467bSMark Brown case WM9081_EQ_14:
2227cfa467bSMark Brown case WM9081_EQ_15:
2237cfa467bSMark Brown case WM9081_EQ_16:
2247cfa467bSMark Brown case WM9081_EQ_17:
2257cfa467bSMark Brown case WM9081_EQ_18:
2267cfa467bSMark Brown case WM9081_EQ_19:
2277cfa467bSMark Brown case WM9081_EQ_20:
2287cfa467bSMark Brown return true;
2297cfa467bSMark Brown default:
2307cfa467bSMark Brown return false;
2317cfa467bSMark Brown }
2327cfa467bSMark Brown }
2337cfa467bSMark Brown
wm9081_reset(struct regmap * map)2347cfa467bSMark Brown static int wm9081_reset(struct regmap *map)
2357cfa467bSMark Brown {
2367cfa467bSMark Brown return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081);
23786ed3669SMark Brown }
23886ed3669SMark Brown
23986ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
24086ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
24186ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
2425d9a5e60SLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(drc_max_tlv,
24386ed3669SMark Brown 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
24486ed3669SMark Brown 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
24586ed3669SMark Brown 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
2465d9a5e60SLars-Peter Clausen 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0)
2475d9a5e60SLars-Peter Clausen );
24886ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
24986ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
25086ed3669SMark Brown
25186ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
25286ed3669SMark Brown
25386ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0);
25486ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
25586ed3669SMark Brown static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
25686ed3669SMark Brown
25786ed3669SMark Brown static const char *drc_high_text[] = {
25886ed3669SMark Brown "1",
25986ed3669SMark Brown "1/2",
26086ed3669SMark Brown "1/4",
26186ed3669SMark Brown "1/8",
26286ed3669SMark Brown "1/16",
26386ed3669SMark Brown "0",
26486ed3669SMark Brown };
26586ed3669SMark Brown
266aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text);
26786ed3669SMark Brown
26886ed3669SMark Brown static const char *drc_low_text[] = {
26986ed3669SMark Brown "1",
27086ed3669SMark Brown "1/2",
27186ed3669SMark Brown "1/4",
27286ed3669SMark Brown "1/8",
27386ed3669SMark Brown "0",
27486ed3669SMark Brown };
27586ed3669SMark Brown
276aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text);
27786ed3669SMark Brown
27886ed3669SMark Brown static const char *drc_atk_text[] = {
27986ed3669SMark Brown "181us",
28086ed3669SMark Brown "181us",
28186ed3669SMark Brown "363us",
28286ed3669SMark Brown "726us",
28386ed3669SMark Brown "1.45ms",
28486ed3669SMark Brown "2.9ms",
28586ed3669SMark Brown "5.8ms",
28686ed3669SMark Brown "11.6ms",
28786ed3669SMark Brown "23.2ms",
28886ed3669SMark Brown "46.4ms",
28986ed3669SMark Brown "92.8ms",
29086ed3669SMark Brown "185.6ms",
29186ed3669SMark Brown };
29286ed3669SMark Brown
293aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text);
29486ed3669SMark Brown
29586ed3669SMark Brown static const char *drc_dcy_text[] = {
29686ed3669SMark Brown "186ms",
29786ed3669SMark Brown "372ms",
29886ed3669SMark Brown "743ms",
29986ed3669SMark Brown "1.49s",
30086ed3669SMark Brown "2.97s",
30186ed3669SMark Brown "5.94s",
30286ed3669SMark Brown "11.89s",
30386ed3669SMark Brown "23.78s",
30486ed3669SMark Brown "47.56s",
30586ed3669SMark Brown };
30686ed3669SMark Brown
307aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text);
30886ed3669SMark Brown
30986ed3669SMark Brown static const char *drc_qr_dcy_text[] = {
31086ed3669SMark Brown "0.725ms",
31186ed3669SMark Brown "1.45ms",
31286ed3669SMark Brown "5.8ms",
31386ed3669SMark Brown };
31486ed3669SMark Brown
315aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text);
31686ed3669SMark Brown
31786ed3669SMark Brown static const char *dac_deemph_text[] = {
31886ed3669SMark Brown "None",
31986ed3669SMark Brown "32kHz",
32086ed3669SMark Brown "44.1kHz",
32186ed3669SMark Brown "48kHz",
32286ed3669SMark Brown };
32386ed3669SMark Brown
324aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1,
325aedbfd96STakashi Iwai dac_deemph_text);
32686ed3669SMark Brown
32786ed3669SMark Brown static const char *speaker_mode_text[] = {
32886ed3669SMark Brown "Class D",
32986ed3669SMark Brown "Class AB",
33086ed3669SMark Brown };
33186ed3669SMark Brown
332aedbfd96STakashi Iwai static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6,
333aedbfd96STakashi Iwai speaker_mode_text);
33486ed3669SMark Brown
speaker_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)33586ed3669SMark Brown static int speaker_mode_get(struct snd_kcontrol *kcontrol,
33686ed3669SMark Brown struct snd_ctl_elem_value *ucontrol)
33786ed3669SMark Brown {
33848c33876SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
33986ed3669SMark Brown unsigned int reg;
34086ed3669SMark Brown
3416d75dfc3SKuninori Morimoto reg = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2);
34286ed3669SMark Brown if (reg & WM9081_SPK_MODE)
34339a79fe1STakashi Iwai ucontrol->value.enumerated.item[0] = 1;
34486ed3669SMark Brown else
34539a79fe1STakashi Iwai ucontrol->value.enumerated.item[0] = 0;
34686ed3669SMark Brown
34786ed3669SMark Brown return 0;
34886ed3669SMark Brown }
34986ed3669SMark Brown
35086ed3669SMark Brown /*
35186ed3669SMark Brown * Stop any attempts to change speaker mode while the speaker is enabled.
35286ed3669SMark Brown *
35325985edcSLucas De Marchi * We also have some special anti-pop controls dependent on speaker
35486ed3669SMark Brown * mode which must be changed along with the mode.
35586ed3669SMark Brown */
speaker_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)35686ed3669SMark Brown static int speaker_mode_put(struct snd_kcontrol *kcontrol,
35786ed3669SMark Brown struct snd_ctl_elem_value *ucontrol)
35886ed3669SMark Brown {
35948c33876SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3606d75dfc3SKuninori Morimoto unsigned int reg_pwr = snd_soc_component_read(component, WM9081_POWER_MANAGEMENT);
3616d75dfc3SKuninori Morimoto unsigned int reg2 = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2);
36286ed3669SMark Brown
36386ed3669SMark Brown /* Are we changing anything? */
36439a79fe1STakashi Iwai if (ucontrol->value.enumerated.item[0] ==
36586ed3669SMark Brown ((reg2 & WM9081_SPK_MODE) != 0))
36686ed3669SMark Brown return 0;
36786ed3669SMark Brown
36886ed3669SMark Brown /* Don't try to change modes while enabled */
36986ed3669SMark Brown if (reg_pwr & WM9081_SPK_ENA)
37086ed3669SMark Brown return -EINVAL;
37186ed3669SMark Brown
37239a79fe1STakashi Iwai if (ucontrol->value.enumerated.item[0]) {
37386ed3669SMark Brown /* Class AB */
37486ed3669SMark Brown reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
37586ed3669SMark Brown reg2 |= WM9081_SPK_MODE;
37686ed3669SMark Brown } else {
37786ed3669SMark Brown /* Class D */
37886ed3669SMark Brown reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL;
37986ed3669SMark Brown reg2 &= ~WM9081_SPK_MODE;
38086ed3669SMark Brown }
38186ed3669SMark Brown
38248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_ANALOGUE_SPEAKER_2, reg2);
38386ed3669SMark Brown
38486ed3669SMark Brown return 0;
38586ed3669SMark Brown }
38686ed3669SMark Brown
38786ed3669SMark Brown static const struct snd_kcontrol_new wm9081_snd_controls[] = {
38886ed3669SMark Brown SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv),
38986ed3669SMark Brown SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv),
39086ed3669SMark Brown
39186ed3669SMark Brown SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv),
39286ed3669SMark Brown
39386ed3669SMark Brown SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1),
39486ed3669SMark Brown SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0),
39586ed3669SMark Brown SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv),
39686ed3669SMark Brown
39786ed3669SMark Brown SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0),
39886ed3669SMark Brown SOC_ENUM("DRC High Slope", drc_high),
39986ed3669SMark Brown SOC_ENUM("DRC Low Slope", drc_low),
40086ed3669SMark Brown SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv),
40186ed3669SMark Brown SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv),
40286ed3669SMark Brown SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv),
40386ed3669SMark Brown SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv),
40486ed3669SMark Brown SOC_ENUM("DRC Attack", drc_atk),
40586ed3669SMark Brown SOC_ENUM("DRC Decay", drc_dcy),
40686ed3669SMark Brown SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0),
40786ed3669SMark Brown SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv),
40886ed3669SMark Brown SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy),
40986ed3669SMark Brown SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv),
41086ed3669SMark Brown
41186ed3669SMark Brown SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0),
41286ed3669SMark Brown
41386ed3669SMark Brown SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0),
41486ed3669SMark Brown SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0),
41586ed3669SMark Brown SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1),
41686ed3669SMark Brown SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0),
41786ed3669SMark Brown SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0,
41886ed3669SMark Brown out_tlv),
41986ed3669SMark Brown SOC_ENUM("DAC Deemphasis", dac_deemph),
42086ed3669SMark Brown SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put),
42186ed3669SMark Brown };
42286ed3669SMark Brown
42386ed3669SMark Brown static const struct snd_kcontrol_new wm9081_eq_controls[] = {
42486ed3669SMark Brown SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv),
42586ed3669SMark Brown SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv),
42686ed3669SMark Brown SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv),
42786ed3669SMark Brown SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv),
42886ed3669SMark Brown SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv),
42986ed3669SMark Brown };
43086ed3669SMark Brown
43186ed3669SMark Brown static const struct snd_kcontrol_new mixer[] = {
43286ed3669SMark Brown SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0),
43386ed3669SMark Brown SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
43486ed3669SMark Brown SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
43586ed3669SMark Brown };
43686ed3669SMark Brown
43786ed3669SMark Brown struct _fll_div {
43886ed3669SMark Brown u16 fll_fratio;
43986ed3669SMark Brown u16 fll_outdiv;
44086ed3669SMark Brown u16 fll_clk_ref_div;
44186ed3669SMark Brown u16 n;
44286ed3669SMark Brown u16 k;
44386ed3669SMark Brown };
44486ed3669SMark Brown
44586ed3669SMark Brown /* The size in bits of the FLL divide multiplied by 10
44686ed3669SMark Brown * to allow rounding later */
44786ed3669SMark Brown #define FIXED_FLL_SIZE ((1 << 16) * 10)
44886ed3669SMark Brown
44986ed3669SMark Brown static struct {
45086ed3669SMark Brown unsigned int min;
45186ed3669SMark Brown unsigned int max;
45286ed3669SMark Brown u16 fll_fratio;
45386ed3669SMark Brown int ratio;
45486ed3669SMark Brown } fll_fratios[] = {
45586ed3669SMark Brown { 0, 64000, 4, 16 },
45686ed3669SMark Brown { 64000, 128000, 3, 8 },
45786ed3669SMark Brown { 128000, 256000, 2, 4 },
45886ed3669SMark Brown { 256000, 1000000, 1, 2 },
45986ed3669SMark Brown { 1000000, 13500000, 0, 1 },
46086ed3669SMark Brown };
46186ed3669SMark Brown
fll_factors(struct _fll_div * fll_div,unsigned int Fref,unsigned int Fout)46286ed3669SMark Brown static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
46386ed3669SMark Brown unsigned int Fout)
46486ed3669SMark Brown {
46586ed3669SMark Brown u64 Kpart;
46686ed3669SMark Brown unsigned int K, Ndiv, Nmod, target;
46786ed3669SMark Brown unsigned int div;
46886ed3669SMark Brown int i;
46986ed3669SMark Brown
47086ed3669SMark Brown /* Fref must be <=13.5MHz */
47186ed3669SMark Brown div = 1;
47286ed3669SMark Brown while ((Fref / div) > 13500000) {
47386ed3669SMark Brown div *= 2;
47486ed3669SMark Brown
47586ed3669SMark Brown if (div > 8) {
47686ed3669SMark Brown pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
47786ed3669SMark Brown Fref);
47886ed3669SMark Brown return -EINVAL;
47986ed3669SMark Brown }
48086ed3669SMark Brown }
48186ed3669SMark Brown fll_div->fll_clk_ref_div = div / 2;
48286ed3669SMark Brown
48386ed3669SMark Brown pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
48486ed3669SMark Brown
48586ed3669SMark Brown /* Apply the division for our remaining calculations */
48686ed3669SMark Brown Fref /= div;
48786ed3669SMark Brown
48886ed3669SMark Brown /* Fvco should be 90-100MHz; don't check the upper bound */
48986ed3669SMark Brown div = 0;
49086ed3669SMark Brown target = Fout * 2;
49186ed3669SMark Brown while (target < 90000000) {
49286ed3669SMark Brown div++;
49386ed3669SMark Brown target *= 2;
49486ed3669SMark Brown if (div > 7) {
49586ed3669SMark Brown pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
49686ed3669SMark Brown Fout);
49786ed3669SMark Brown return -EINVAL;
49886ed3669SMark Brown }
49986ed3669SMark Brown }
50086ed3669SMark Brown fll_div->fll_outdiv = div;
50186ed3669SMark Brown
50286ed3669SMark Brown pr_debug("Fvco=%dHz\n", target);
50386ed3669SMark Brown
50425985edcSLucas De Marchi /* Find an appropriate FLL_FRATIO and factor it out of the target */
50586ed3669SMark Brown for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
50686ed3669SMark Brown if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
50786ed3669SMark Brown fll_div->fll_fratio = fll_fratios[i].fll_fratio;
50886ed3669SMark Brown target /= fll_fratios[i].ratio;
50986ed3669SMark Brown break;
51086ed3669SMark Brown }
51186ed3669SMark Brown }
51286ed3669SMark Brown if (i == ARRAY_SIZE(fll_fratios)) {
51386ed3669SMark Brown pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
51486ed3669SMark Brown return -EINVAL;
51586ed3669SMark Brown }
51686ed3669SMark Brown
51786ed3669SMark Brown /* Now, calculate N.K */
51886ed3669SMark Brown Ndiv = target / Fref;
51986ed3669SMark Brown
52086ed3669SMark Brown fll_div->n = Ndiv;
52186ed3669SMark Brown Nmod = target % Fref;
52286ed3669SMark Brown pr_debug("Nmod=%d\n", Nmod);
52386ed3669SMark Brown
52486ed3669SMark Brown /* Calculate fractional part - scale up so we can round. */
52586ed3669SMark Brown Kpart = FIXED_FLL_SIZE * (long long)Nmod;
52686ed3669SMark Brown
52786ed3669SMark Brown do_div(Kpart, Fref);
52886ed3669SMark Brown
52986ed3669SMark Brown K = Kpart & 0xFFFFFFFF;
53086ed3669SMark Brown
53186ed3669SMark Brown if ((K % 10) >= 5)
53286ed3669SMark Brown K += 5;
53386ed3669SMark Brown
53486ed3669SMark Brown /* Move down to proper range now rounding is done */
53586ed3669SMark Brown fll_div->k = K / 10;
53686ed3669SMark Brown
53786ed3669SMark Brown pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
53886ed3669SMark Brown fll_div->n, fll_div->k,
53986ed3669SMark Brown fll_div->fll_fratio, fll_div->fll_outdiv,
54086ed3669SMark Brown fll_div->fll_clk_ref_div);
54186ed3669SMark Brown
54286ed3669SMark Brown return 0;
54386ed3669SMark Brown }
54486ed3669SMark Brown
wm9081_set_fll(struct snd_soc_component * component,int fll_id,unsigned int Fref,unsigned int Fout)54548c33876SKuninori Morimoto static int wm9081_set_fll(struct snd_soc_component *component, int fll_id,
54686ed3669SMark Brown unsigned int Fref, unsigned int Fout)
54786ed3669SMark Brown {
54848c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
54986ed3669SMark Brown u16 reg1, reg4, reg5;
55086ed3669SMark Brown struct _fll_div fll_div;
55186ed3669SMark Brown int ret;
55286ed3669SMark Brown int clk_sys_reg;
55386ed3669SMark Brown
55486ed3669SMark Brown /* Any change? */
55586ed3669SMark Brown if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout)
55686ed3669SMark Brown return 0;
55786ed3669SMark Brown
55886ed3669SMark Brown /* Disable the FLL */
55986ed3669SMark Brown if (Fout == 0) {
56048c33876SKuninori Morimoto dev_dbg(component->dev, "FLL disabled\n");
56186ed3669SMark Brown wm9081->fll_fref = 0;
56286ed3669SMark Brown wm9081->fll_fout = 0;
56386ed3669SMark Brown
56486ed3669SMark Brown return 0;
56586ed3669SMark Brown }
56686ed3669SMark Brown
56786ed3669SMark Brown ret = fll_factors(&fll_div, Fref, Fout);
56886ed3669SMark Brown if (ret != 0)
56986ed3669SMark Brown return ret;
57086ed3669SMark Brown
5716d75dfc3SKuninori Morimoto reg5 = snd_soc_component_read(component, WM9081_FLL_CONTROL_5);
57286ed3669SMark Brown reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
57386ed3669SMark Brown
57486ed3669SMark Brown switch (fll_id) {
57586ed3669SMark Brown case WM9081_SYSCLK_FLL_MCLK:
57686ed3669SMark Brown reg5 |= 0x1;
57786ed3669SMark Brown break;
57886ed3669SMark Brown
57986ed3669SMark Brown default:
58048c33876SKuninori Morimoto dev_err(component->dev, "Unknown FLL ID %d\n", fll_id);
58186ed3669SMark Brown return -EINVAL;
58286ed3669SMark Brown }
58386ed3669SMark Brown
58486ed3669SMark Brown /* Disable CLK_SYS while we reconfigure */
5856d75dfc3SKuninori Morimoto clk_sys_reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3);
58686ed3669SMark Brown if (clk_sys_reg & WM9081_CLK_SYS_ENA)
58748c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_CLOCK_CONTROL_3,
58886ed3669SMark Brown clk_sys_reg & ~WM9081_CLK_SYS_ENA);
58986ed3669SMark Brown
59086ed3669SMark Brown /* Any FLL configuration change requires that the FLL be
59186ed3669SMark Brown * disabled first. */
5926d75dfc3SKuninori Morimoto reg1 = snd_soc_component_read(component, WM9081_FLL_CONTROL_1);
59386ed3669SMark Brown reg1 &= ~WM9081_FLL_ENA;
59448c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_1, reg1);
59586ed3669SMark Brown
59686ed3669SMark Brown /* Apply the configuration */
59786ed3669SMark Brown if (fll_div.k)
59886ed3669SMark Brown reg1 |= WM9081_FLL_FRAC_MASK;
59986ed3669SMark Brown else
60086ed3669SMark Brown reg1 &= ~WM9081_FLL_FRAC_MASK;
60148c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_1, reg1);
60286ed3669SMark Brown
60348c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_2,
60486ed3669SMark Brown (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
60586ed3669SMark Brown (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
60648c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_3, fll_div.k);
60786ed3669SMark Brown
6086d75dfc3SKuninori Morimoto reg4 = snd_soc_component_read(component, WM9081_FLL_CONTROL_4);
60986ed3669SMark Brown reg4 &= ~WM9081_FLL_N_MASK;
61086ed3669SMark Brown reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
61148c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_4, reg4);
61286ed3669SMark Brown
61386ed3669SMark Brown reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
61486ed3669SMark Brown reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
61548c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_5, reg5);
61686ed3669SMark Brown
617249c5156SMario Becroft /* Set gain to the recommended value */
61848c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_FLL_CONTROL_4,
619249c5156SMario Becroft WM9081_FLL_GAIN_MASK, 0);
620249c5156SMario Becroft
62186ed3669SMark Brown /* Enable the FLL */
62248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
62386ed3669SMark Brown
62486ed3669SMark Brown /* Then bring CLK_SYS up again if it was disabled */
62586ed3669SMark Brown if (clk_sys_reg & WM9081_CLK_SYS_ENA)
62648c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
62786ed3669SMark Brown
62848c33876SKuninori Morimoto dev_dbg(component->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
62986ed3669SMark Brown
63086ed3669SMark Brown wm9081->fll_fref = Fref;
63186ed3669SMark Brown wm9081->fll_fout = Fout;
63286ed3669SMark Brown
63386ed3669SMark Brown return 0;
63486ed3669SMark Brown }
63586ed3669SMark Brown
configure_clock(struct snd_soc_component * component)63648c33876SKuninori Morimoto static int configure_clock(struct snd_soc_component *component)
63786ed3669SMark Brown {
63848c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
63986ed3669SMark Brown int new_sysclk, i, target;
64086ed3669SMark Brown unsigned int reg;
64186ed3669SMark Brown int ret = 0;
64286ed3669SMark Brown int mclkdiv = 0;
64386ed3669SMark Brown int fll = 0;
64486ed3669SMark Brown
64586ed3669SMark Brown switch (wm9081->sysclk_source) {
64686ed3669SMark Brown case WM9081_SYSCLK_MCLK:
64786ed3669SMark Brown if (wm9081->mclk_rate > 12225000) {
64886ed3669SMark Brown mclkdiv = 1;
64986ed3669SMark Brown wm9081->sysclk_rate = wm9081->mclk_rate / 2;
65086ed3669SMark Brown } else {
65186ed3669SMark Brown wm9081->sysclk_rate = wm9081->mclk_rate;
65286ed3669SMark Brown }
65348c33876SKuninori Morimoto wm9081_set_fll(component, WM9081_SYSCLK_FLL_MCLK, 0, 0);
65486ed3669SMark Brown break;
65586ed3669SMark Brown
65686ed3669SMark Brown case WM9081_SYSCLK_FLL_MCLK:
65786ed3669SMark Brown /* If we have a sample rate calculate a CLK_SYS that
65886ed3669SMark Brown * gives us a suitable DAC configuration, plus BCLK.
65986ed3669SMark Brown * Ideally we would check to see if we can clock
66086ed3669SMark Brown * directly from MCLK and only use the FLL if this is
66186ed3669SMark Brown * not the case, though care must be taken with free
66286ed3669SMark Brown * running mode.
66386ed3669SMark Brown */
66486ed3669SMark Brown if (wm9081->master && wm9081->bclk) {
66586ed3669SMark Brown /* Make sure we can generate CLK_SYS and BCLK
66686ed3669SMark Brown * and that we've got 3MHz for optimal
66786ed3669SMark Brown * performance. */
66886ed3669SMark Brown for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
66986ed3669SMark Brown target = wm9081->fs * clk_sys_rates[i].ratio;
6700154724dSMark Brown new_sysclk = target;
67186ed3669SMark Brown if (target >= wm9081->bclk &&
67286ed3669SMark Brown target > 3000000)
6730154724dSMark Brown break;
67486ed3669SMark Brown }
6754b75e947SMark Brown
6764b75e947SMark Brown if (i == ARRAY_SIZE(clk_sys_rates))
6774b75e947SMark Brown return -EINVAL;
6784b75e947SMark Brown
67986ed3669SMark Brown } else if (wm9081->fs) {
68086ed3669SMark Brown for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
68186ed3669SMark Brown new_sysclk = clk_sys_rates[i].ratio
68286ed3669SMark Brown * wm9081->fs;
68386ed3669SMark Brown if (new_sysclk > 3000000)
68486ed3669SMark Brown break;
68586ed3669SMark Brown }
6864b75e947SMark Brown
6874b75e947SMark Brown if (i == ARRAY_SIZE(clk_sys_rates))
6884b75e947SMark Brown return -EINVAL;
6894b75e947SMark Brown
69086ed3669SMark Brown } else {
69186ed3669SMark Brown new_sysclk = 12288000;
69286ed3669SMark Brown }
69386ed3669SMark Brown
69448c33876SKuninori Morimoto ret = wm9081_set_fll(component, WM9081_SYSCLK_FLL_MCLK,
69586ed3669SMark Brown wm9081->mclk_rate, new_sysclk);
69686ed3669SMark Brown if (ret == 0) {
69786ed3669SMark Brown wm9081->sysclk_rate = new_sysclk;
69886ed3669SMark Brown
69986ed3669SMark Brown /* Switch SYSCLK over to FLL */
70086ed3669SMark Brown fll = 1;
70186ed3669SMark Brown } else {
70286ed3669SMark Brown wm9081->sysclk_rate = wm9081->mclk_rate;
70386ed3669SMark Brown }
70486ed3669SMark Brown break;
70586ed3669SMark Brown
70686ed3669SMark Brown default:
70786ed3669SMark Brown return -EINVAL;
70886ed3669SMark Brown }
70986ed3669SMark Brown
7106d75dfc3SKuninori Morimoto reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_1);
71186ed3669SMark Brown if (mclkdiv)
71286ed3669SMark Brown reg |= WM9081_MCLKDIV2;
71386ed3669SMark Brown else
71486ed3669SMark Brown reg &= ~WM9081_MCLKDIV2;
71548c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_CLOCK_CONTROL_1, reg);
71686ed3669SMark Brown
7176d75dfc3SKuninori Morimoto reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3);
71886ed3669SMark Brown if (fll)
71986ed3669SMark Brown reg |= WM9081_CLK_SRC_SEL;
72086ed3669SMark Brown else
72186ed3669SMark Brown reg &= ~WM9081_CLK_SRC_SEL;
72248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_CLOCK_CONTROL_3, reg);
72386ed3669SMark Brown
72448c33876SKuninori Morimoto dev_dbg(component->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
72586ed3669SMark Brown
72686ed3669SMark Brown return ret;
72786ed3669SMark Brown }
72886ed3669SMark Brown
clk_sys_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)72986ed3669SMark Brown static int clk_sys_event(struct snd_soc_dapm_widget *w,
73086ed3669SMark Brown struct snd_kcontrol *kcontrol, int event)
73186ed3669SMark Brown {
73248c33876SKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
73348c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
73486ed3669SMark Brown
73586ed3669SMark Brown /* This should be done on init() for bypass paths */
73686ed3669SMark Brown switch (wm9081->sysclk_source) {
73786ed3669SMark Brown case WM9081_SYSCLK_MCLK:
73848c33876SKuninori Morimoto dev_dbg(component->dev, "Using %dHz MCLK\n", wm9081->mclk_rate);
73986ed3669SMark Brown break;
74086ed3669SMark Brown case WM9081_SYSCLK_FLL_MCLK:
74148c33876SKuninori Morimoto dev_dbg(component->dev, "Using %dHz MCLK with FLL\n",
74286ed3669SMark Brown wm9081->mclk_rate);
74386ed3669SMark Brown break;
74486ed3669SMark Brown default:
74548c33876SKuninori Morimoto dev_err(component->dev, "System clock not configured\n");
74686ed3669SMark Brown return -EINVAL;
74786ed3669SMark Brown }
74886ed3669SMark Brown
74986ed3669SMark Brown switch (event) {
75086ed3669SMark Brown case SND_SOC_DAPM_PRE_PMU:
75148c33876SKuninori Morimoto configure_clock(component);
75286ed3669SMark Brown break;
75386ed3669SMark Brown
75486ed3669SMark Brown case SND_SOC_DAPM_POST_PMD:
75586ed3669SMark Brown /* Disable the FLL if it's running */
75648c33876SKuninori Morimoto wm9081_set_fll(component, 0, 0, 0);
75786ed3669SMark Brown break;
75886ed3669SMark Brown }
75986ed3669SMark Brown
76086ed3669SMark Brown return 0;
76186ed3669SMark Brown }
76286ed3669SMark Brown
76386ed3669SMark Brown static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
76486ed3669SMark Brown SND_SOC_DAPM_INPUT("IN1"),
76586ed3669SMark Brown SND_SOC_DAPM_INPUT("IN2"),
76686ed3669SMark Brown
7670fb7d0c3SMark Brown SND_SOC_DAPM_DAC("DAC", NULL, WM9081_POWER_MANAGEMENT, 0, 0),
76886ed3669SMark Brown
76986ed3669SMark Brown SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
77086ed3669SMark Brown mixer, ARRAY_SIZE(mixer)),
77186ed3669SMark Brown
77286ed3669SMark Brown SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
77386ed3669SMark Brown
774378a90f4SMark Brown SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0),
7754e8e78e3SMark Brown SND_SOC_DAPM_OUT_DRV("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0),
77686ed3669SMark Brown
77786ed3669SMark Brown SND_SOC_DAPM_OUTPUT("LINEOUT"),
77886ed3669SMark Brown SND_SOC_DAPM_OUTPUT("SPKN"),
77986ed3669SMark Brown SND_SOC_DAPM_OUTPUT("SPKP"),
78086ed3669SMark Brown
78186ed3669SMark Brown SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
78286ed3669SMark Brown SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
78386ed3669SMark Brown SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
78486ed3669SMark Brown SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
785a04e0c86SMark Brown SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0),
78686ed3669SMark Brown };
78786ed3669SMark Brown
78886ed3669SMark Brown
789149c7b44SMark Brown static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
79086ed3669SMark Brown { "DAC", NULL, "CLK_SYS" },
79186ed3669SMark Brown { "DAC", NULL, "CLK_DSP" },
7920fb7d0c3SMark Brown { "DAC", NULL, "AIF" },
79386ed3669SMark Brown
79486ed3669SMark Brown { "Mixer", "IN1 Switch", "IN1" },
79586ed3669SMark Brown { "Mixer", "IN2 Switch", "IN2" },
79686ed3669SMark Brown { "Mixer", "Playback Switch", "DAC" },
79786ed3669SMark Brown
79886ed3669SMark Brown { "LINEOUT PGA", NULL, "Mixer" },
79986ed3669SMark Brown { "LINEOUT PGA", NULL, "TOCLK" },
80086ed3669SMark Brown { "LINEOUT PGA", NULL, "CLK_SYS" },
80186ed3669SMark Brown
80286ed3669SMark Brown { "LINEOUT", NULL, "LINEOUT PGA" },
80386ed3669SMark Brown
80486ed3669SMark Brown { "Speaker PGA", NULL, "Mixer" },
80586ed3669SMark Brown { "Speaker PGA", NULL, "TOCLK" },
80686ed3669SMark Brown { "Speaker PGA", NULL, "CLK_SYS" },
80786ed3669SMark Brown
808378a90f4SMark Brown { "Speaker", NULL, "Speaker PGA" },
809a04e0c86SMark Brown { "Speaker", NULL, "TSENSE" },
810378a90f4SMark Brown
811378a90f4SMark Brown { "SPKN", NULL, "Speaker" },
812378a90f4SMark Brown { "SPKP", NULL, "Speaker" },
81386ed3669SMark Brown };
81486ed3669SMark Brown
wm9081_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)81548c33876SKuninori Morimoto static int wm9081_set_bias_level(struct snd_soc_component *component,
81686ed3669SMark Brown enum snd_soc_bias_level level)
81786ed3669SMark Brown {
81848c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
819da157875SMark Brown
82086ed3669SMark Brown switch (level) {
82186ed3669SMark Brown case SND_SOC_BIAS_ON:
82286ed3669SMark Brown break;
82386ed3669SMark Brown
82486ed3669SMark Brown case SND_SOC_BIAS_PREPARE:
82586ed3669SMark Brown /* VMID=2*40k */
82648c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_VMID_CONTROL,
827b4027358SAxel Lin WM9081_VMID_SEL_MASK, 0x2);
82886ed3669SMark Brown
82986ed3669SMark Brown /* Normal bias current */
83048c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_BIAS_CONTROL_1,
831b4027358SAxel Lin WM9081_STBY_BIAS_ENA, 0);
83286ed3669SMark Brown break;
83386ed3669SMark Brown
83486ed3669SMark Brown case SND_SOC_BIAS_STANDBY:
83586ed3669SMark Brown /* Initial cold start */
83648c33876SKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
837da157875SMark Brown regcache_cache_only(wm9081->regmap, false);
838da157875SMark Brown regcache_sync(wm9081->regmap);
839da157875SMark Brown
84086ed3669SMark Brown /* Disable LINEOUT discharge */
84148c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_ANTI_POP_CONTROL,
842b4027358SAxel Lin WM9081_LINEOUT_DISCH, 0);
84386ed3669SMark Brown
84486ed3669SMark Brown /* Select startup bias source */
84548c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_BIAS_CONTROL_1,
846b4027358SAxel Lin WM9081_BIAS_SRC | WM9081_BIAS_ENA,
847b4027358SAxel Lin WM9081_BIAS_SRC | WM9081_BIAS_ENA);
84886ed3669SMark Brown
84986ed3669SMark Brown /* VMID 2*4k; Soft VMID ramp enable */
85048c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_VMID_CONTROL,
851b4027358SAxel Lin WM9081_VMID_RAMP |
852b4027358SAxel Lin WM9081_VMID_SEL_MASK,
853b4027358SAxel Lin WM9081_VMID_RAMP | 0x6);
85486ed3669SMark Brown
85586ed3669SMark Brown mdelay(100);
85686ed3669SMark Brown
85786ed3669SMark Brown /* Normal bias enable & soft start off */
85848c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_VMID_CONTROL,
859b4027358SAxel Lin WM9081_VMID_RAMP, 0);
86086ed3669SMark Brown
86186ed3669SMark Brown /* Standard bias source */
86248c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_BIAS_CONTROL_1,
863b4027358SAxel Lin WM9081_BIAS_SRC, 0);
86486ed3669SMark Brown }
86586ed3669SMark Brown
86686ed3669SMark Brown /* VMID 2*240k */
86748c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_VMID_CONTROL,
868b4027358SAxel Lin WM9081_VMID_SEL_MASK, 0x04);
86986ed3669SMark Brown
87086ed3669SMark Brown /* Standby bias current on */
87148c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_BIAS_CONTROL_1,
872b4027358SAxel Lin WM9081_STBY_BIAS_ENA,
873b4027358SAxel Lin WM9081_STBY_BIAS_ENA);
87486ed3669SMark Brown break;
87586ed3669SMark Brown
87686ed3669SMark Brown case SND_SOC_BIAS_OFF:
877adf46362SAxel Lin /* Startup bias source and disable bias */
87848c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_BIAS_CONTROL_1,
879b4027358SAxel Lin WM9081_BIAS_SRC | WM9081_BIAS_ENA,
880b4027358SAxel Lin WM9081_BIAS_SRC);
88186ed3669SMark Brown
882adf46362SAxel Lin /* Disable VMID with soft ramping */
88348c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_VMID_CONTROL,
884b4027358SAxel Lin WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK,
885b4027358SAxel Lin WM9081_VMID_RAMP);
88686ed3669SMark Brown
88786ed3669SMark Brown /* Actively discharge LINEOUT */
88848c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_ANTI_POP_CONTROL,
889b4027358SAxel Lin WM9081_LINEOUT_DISCH,
890b4027358SAxel Lin WM9081_LINEOUT_DISCH);
891da157875SMark Brown
892da157875SMark Brown regcache_cache_only(wm9081->regmap, true);
89386ed3669SMark Brown break;
89486ed3669SMark Brown }
89586ed3669SMark Brown
89686ed3669SMark Brown return 0;
89786ed3669SMark Brown }
89886ed3669SMark Brown
wm9081_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)89986ed3669SMark Brown static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
90086ed3669SMark Brown unsigned int fmt)
90186ed3669SMark Brown {
90248c33876SKuninori Morimoto struct snd_soc_component *component = dai->component;
90348c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
9046d75dfc3SKuninori Morimoto unsigned int aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2);
90586ed3669SMark Brown
90686ed3669SMark Brown aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
90786ed3669SMark Brown WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
90886ed3669SMark Brown
90986ed3669SMark Brown switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
91086ed3669SMark Brown case SND_SOC_DAIFMT_CBS_CFS:
91186ed3669SMark Brown wm9081->master = 0;
91286ed3669SMark Brown break;
91386ed3669SMark Brown case SND_SOC_DAIFMT_CBS_CFM:
91486ed3669SMark Brown aif2 |= WM9081_LRCLK_DIR;
91586ed3669SMark Brown wm9081->master = 1;
91686ed3669SMark Brown break;
91786ed3669SMark Brown case SND_SOC_DAIFMT_CBM_CFS:
91886ed3669SMark Brown aif2 |= WM9081_BCLK_DIR;
91986ed3669SMark Brown wm9081->master = 1;
92086ed3669SMark Brown break;
92186ed3669SMark Brown case SND_SOC_DAIFMT_CBM_CFM:
92286ed3669SMark Brown aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
92386ed3669SMark Brown wm9081->master = 1;
92486ed3669SMark Brown break;
92586ed3669SMark Brown default:
92686ed3669SMark Brown return -EINVAL;
92786ed3669SMark Brown }
92886ed3669SMark Brown
92986ed3669SMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
93086ed3669SMark Brown case SND_SOC_DAIFMT_DSP_B:
93186ed3669SMark Brown aif2 |= WM9081_AIF_LRCLK_INV;
9323e146b55SGustavo A. R. Silva fallthrough;
93386ed3669SMark Brown case SND_SOC_DAIFMT_DSP_A:
93486ed3669SMark Brown aif2 |= 0x3;
93586ed3669SMark Brown break;
93686ed3669SMark Brown case SND_SOC_DAIFMT_I2S:
93786ed3669SMark Brown aif2 |= 0x2;
93886ed3669SMark Brown break;
93986ed3669SMark Brown case SND_SOC_DAIFMT_RIGHT_J:
94086ed3669SMark Brown break;
94186ed3669SMark Brown case SND_SOC_DAIFMT_LEFT_J:
94286ed3669SMark Brown aif2 |= 0x1;
94386ed3669SMark Brown break;
94486ed3669SMark Brown default:
94586ed3669SMark Brown return -EINVAL;
94686ed3669SMark Brown }
94786ed3669SMark Brown
94886ed3669SMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
94986ed3669SMark Brown case SND_SOC_DAIFMT_DSP_A:
95086ed3669SMark Brown case SND_SOC_DAIFMT_DSP_B:
95186ed3669SMark Brown /* frame inversion not valid for DSP modes */
95286ed3669SMark Brown switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
95386ed3669SMark Brown case SND_SOC_DAIFMT_NB_NF:
95486ed3669SMark Brown break;
95586ed3669SMark Brown case SND_SOC_DAIFMT_IB_NF:
95686ed3669SMark Brown aif2 |= WM9081_AIF_BCLK_INV;
95786ed3669SMark Brown break;
95886ed3669SMark Brown default:
95986ed3669SMark Brown return -EINVAL;
96086ed3669SMark Brown }
96186ed3669SMark Brown break;
96286ed3669SMark Brown
96386ed3669SMark Brown case SND_SOC_DAIFMT_I2S:
96486ed3669SMark Brown case SND_SOC_DAIFMT_RIGHT_J:
96586ed3669SMark Brown case SND_SOC_DAIFMT_LEFT_J:
96686ed3669SMark Brown switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
96786ed3669SMark Brown case SND_SOC_DAIFMT_NB_NF:
96886ed3669SMark Brown break;
96986ed3669SMark Brown case SND_SOC_DAIFMT_IB_IF:
97086ed3669SMark Brown aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
97186ed3669SMark Brown break;
97286ed3669SMark Brown case SND_SOC_DAIFMT_IB_NF:
97386ed3669SMark Brown aif2 |= WM9081_AIF_BCLK_INV;
97486ed3669SMark Brown break;
97586ed3669SMark Brown case SND_SOC_DAIFMT_NB_IF:
97686ed3669SMark Brown aif2 |= WM9081_AIF_LRCLK_INV;
97786ed3669SMark Brown break;
97886ed3669SMark Brown default:
97986ed3669SMark Brown return -EINVAL;
98086ed3669SMark Brown }
98186ed3669SMark Brown break;
98286ed3669SMark Brown default:
98386ed3669SMark Brown return -EINVAL;
98486ed3669SMark Brown }
98586ed3669SMark Brown
98648c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_AUDIO_INTERFACE_2, aif2);
98786ed3669SMark Brown
98886ed3669SMark Brown return 0;
98986ed3669SMark Brown }
99086ed3669SMark Brown
wm9081_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)99186ed3669SMark Brown static int wm9081_hw_params(struct snd_pcm_substream *substream,
99286ed3669SMark Brown struct snd_pcm_hw_params *params,
99386ed3669SMark Brown struct snd_soc_dai *dai)
99486ed3669SMark Brown {
99548c33876SKuninori Morimoto struct snd_soc_component *component = dai->component;
99648c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
99786ed3669SMark Brown int ret, i, best, best_val, cur_val;
99886ed3669SMark Brown unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
99986ed3669SMark Brown
10006d75dfc3SKuninori Morimoto clk_ctrl2 = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_2);
100186ed3669SMark Brown clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
100286ed3669SMark Brown
10036d75dfc3SKuninori Morimoto aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1);
100486ed3669SMark Brown
10056d75dfc3SKuninori Morimoto aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2);
100686ed3669SMark Brown aif2 &= ~WM9081_AIF_WL_MASK;
100786ed3669SMark Brown
10086d75dfc3SKuninori Morimoto aif3 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_3);
100986ed3669SMark Brown aif3 &= ~WM9081_BCLK_DIV_MASK;
101086ed3669SMark Brown
10116d75dfc3SKuninori Morimoto aif4 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_4);
101286ed3669SMark Brown aif4 &= ~WM9081_LRCLK_RATE_MASK;
101386ed3669SMark Brown
101486ed3669SMark Brown wm9081->fs = params_rate(params);
1015e0026beaSMark Brown
1016e0026beaSMark Brown if (wm9081->tdm_width) {
1017e0026beaSMark Brown /* If TDM is set up then that fixes our BCLK. */
1018e0026beaSMark Brown int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
1019e0026beaSMark Brown WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
1020e0026beaSMark Brown
1021e0026beaSMark Brown wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots;
1022e0026beaSMark Brown } else {
1023e0026beaSMark Brown /* Otherwise work out a BCLK from the sample size */
102486ed3669SMark Brown wm9081->bclk = 2 * wm9081->fs;
1025e0026beaSMark Brown
10269572696dSMark Brown switch (params_width(params)) {
10279572696dSMark Brown case 16:
102886ed3669SMark Brown wm9081->bclk *= 16;
102986ed3669SMark Brown break;
10309572696dSMark Brown case 20:
103186ed3669SMark Brown wm9081->bclk *= 20;
103286ed3669SMark Brown aif2 |= 0x4;
103386ed3669SMark Brown break;
10349572696dSMark Brown case 24:
103586ed3669SMark Brown wm9081->bclk *= 24;
103686ed3669SMark Brown aif2 |= 0x8;
103786ed3669SMark Brown break;
10389572696dSMark Brown case 32:
103986ed3669SMark Brown wm9081->bclk *= 32;
104086ed3669SMark Brown aif2 |= 0xc;
104186ed3669SMark Brown break;
104286ed3669SMark Brown default:
104386ed3669SMark Brown return -EINVAL;
104486ed3669SMark Brown }
104586ed3669SMark Brown }
104686ed3669SMark Brown
104748c33876SKuninori Morimoto dev_dbg(component->dev, "Target BCLK is %dHz\n", wm9081->bclk);
104886ed3669SMark Brown
104948c33876SKuninori Morimoto ret = configure_clock(component);
105086ed3669SMark Brown if (ret != 0)
105186ed3669SMark Brown return ret;
105286ed3669SMark Brown
105386ed3669SMark Brown /* Select nearest CLK_SYS_RATE */
105486ed3669SMark Brown best = 0;
105586ed3669SMark Brown best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio)
105686ed3669SMark Brown - wm9081->fs);
105786ed3669SMark Brown for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
105886ed3669SMark Brown cur_val = abs((wm9081->sysclk_rate /
1059a419aef8SJoe Perches clk_sys_rates[i].ratio) - wm9081->fs);
106086ed3669SMark Brown if (cur_val < best_val) {
106186ed3669SMark Brown best = i;
106286ed3669SMark Brown best_val = cur_val;
106386ed3669SMark Brown }
106486ed3669SMark Brown }
106548c33876SKuninori Morimoto dev_dbg(component->dev, "Selected CLK_SYS_RATIO of %d\n",
106686ed3669SMark Brown clk_sys_rates[best].ratio);
106786ed3669SMark Brown clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate
106886ed3669SMark Brown << WM9081_CLK_SYS_RATE_SHIFT);
106986ed3669SMark Brown
107086ed3669SMark Brown /* SAMPLE_RATE */
107186ed3669SMark Brown best = 0;
107286ed3669SMark Brown best_val = abs(wm9081->fs - sample_rates[0].rate);
107386ed3669SMark Brown for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
107486ed3669SMark Brown /* Closest match */
107586ed3669SMark Brown cur_val = abs(wm9081->fs - sample_rates[i].rate);
107686ed3669SMark Brown if (cur_val < best_val) {
107786ed3669SMark Brown best = i;
107886ed3669SMark Brown best_val = cur_val;
107986ed3669SMark Brown }
108086ed3669SMark Brown }
108148c33876SKuninori Morimoto dev_dbg(component->dev, "Selected SAMPLE_RATE of %dHz\n",
108286ed3669SMark Brown sample_rates[best].rate);
10830154724dSMark Brown clk_ctrl2 |= (sample_rates[best].sample_rate
10840154724dSMark Brown << WM9081_SAMPLE_RATE_SHIFT);
108586ed3669SMark Brown
108686ed3669SMark Brown /* BCLK_DIV */
108786ed3669SMark Brown best = 0;
108886ed3669SMark Brown best_val = INT_MAX;
108986ed3669SMark Brown for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
109086ed3669SMark Brown cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div)
109186ed3669SMark Brown - wm9081->bclk;
109286ed3669SMark Brown if (cur_val < 0) /* Table is sorted */
109386ed3669SMark Brown break;
109486ed3669SMark Brown if (cur_val < best_val) {
109586ed3669SMark Brown best = i;
109686ed3669SMark Brown best_val = cur_val;
109786ed3669SMark Brown }
109886ed3669SMark Brown }
109986ed3669SMark Brown wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div;
110048c33876SKuninori Morimoto dev_dbg(component->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
110186ed3669SMark Brown bclk_divs[best].div, wm9081->bclk);
110286ed3669SMark Brown aif3 |= bclk_divs[best].bclk_div;
110386ed3669SMark Brown
110486ed3669SMark Brown /* LRCLK is a simple fraction of BCLK */
110548c33876SKuninori Morimoto dev_dbg(component->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs);
110686ed3669SMark Brown aif4 |= wm9081->bclk / wm9081->fs;
110786ed3669SMark Brown
110886ed3669SMark Brown /* Apply a ReTune Mobile configuration if it's in use */
11094a5f7bdaSMark Brown if (wm9081->pdata.num_retune_configs) {
11104a5f7bdaSMark Brown struct wm9081_pdata *pdata = &wm9081->pdata;
111186ed3669SMark Brown struct wm9081_retune_mobile_setting *s;
111286ed3669SMark Brown int eq1;
111386ed3669SMark Brown
111486ed3669SMark Brown best = 0;
11154a5f7bdaSMark Brown best_val = abs(pdata->retune_configs[0].rate - wm9081->fs);
11164a5f7bdaSMark Brown for (i = 0; i < pdata->num_retune_configs; i++) {
11174a5f7bdaSMark Brown cur_val = abs(pdata->retune_configs[i].rate -
11184a5f7bdaSMark Brown wm9081->fs);
111986ed3669SMark Brown if (cur_val < best_val) {
112086ed3669SMark Brown best_val = cur_val;
112186ed3669SMark Brown best = i;
112286ed3669SMark Brown }
112386ed3669SMark Brown }
11244a5f7bdaSMark Brown s = &pdata->retune_configs[best];
112586ed3669SMark Brown
112648c33876SKuninori Morimoto dev_dbg(component->dev, "ReTune Mobile %s tuned for %dHz\n",
112786ed3669SMark Brown s->name, s->rate);
112886ed3669SMark Brown
112986ed3669SMark Brown /* If the EQ is enabled then disable it while we write out */
11306d75dfc3SKuninori Morimoto eq1 = snd_soc_component_read(component, WM9081_EQ_1) & WM9081_EQ_ENA;
113186ed3669SMark Brown if (eq1 & WM9081_EQ_ENA)
113248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_EQ_1, 0);
113386ed3669SMark Brown
113486ed3669SMark Brown /* Write out the other values */
113586ed3669SMark Brown for (i = 1; i < ARRAY_SIZE(s->config); i++)
113648c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_EQ_1 + i, s->config[i]);
113786ed3669SMark Brown
113886ed3669SMark Brown eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
113948c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_EQ_1, eq1);
114086ed3669SMark Brown }
114186ed3669SMark Brown
114248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
114348c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_AUDIO_INTERFACE_2, aif2);
114448c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_AUDIO_INTERFACE_3, aif3);
114548c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_AUDIO_INTERFACE_4, aif4);
114686ed3669SMark Brown
114786ed3669SMark Brown return 0;
114886ed3669SMark Brown }
114986ed3669SMark Brown
wm9081_mute(struct snd_soc_dai * codec_dai,int mute,int direction)115026d3c16eSKuninori Morimoto static int wm9081_mute(struct snd_soc_dai *codec_dai, int mute, int direction)
115186ed3669SMark Brown {
115248c33876SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
115386ed3669SMark Brown unsigned int reg;
115486ed3669SMark Brown
11556d75dfc3SKuninori Morimoto reg = snd_soc_component_read(component, WM9081_DAC_DIGITAL_2);
115686ed3669SMark Brown
115786ed3669SMark Brown if (mute)
115886ed3669SMark Brown reg |= WM9081_DAC_MUTE;
115986ed3669SMark Brown else
116086ed3669SMark Brown reg &= ~WM9081_DAC_MUTE;
116186ed3669SMark Brown
116248c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_DAC_DIGITAL_2, reg);
116386ed3669SMark Brown
116486ed3669SMark Brown return 0;
116586ed3669SMark Brown }
116686ed3669SMark Brown
wm9081_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)116748c33876SKuninori Morimoto static int wm9081_set_sysclk(struct snd_soc_component *component, int clk_id,
1168da1c6ea6SMark Brown int source, unsigned int freq, int dir)
116986ed3669SMark Brown {
117048c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
117186ed3669SMark Brown
117286ed3669SMark Brown switch (clk_id) {
117386ed3669SMark Brown case WM9081_SYSCLK_MCLK:
117486ed3669SMark Brown case WM9081_SYSCLK_FLL_MCLK:
117586ed3669SMark Brown wm9081->sysclk_source = clk_id;
117686ed3669SMark Brown wm9081->mclk_rate = freq;
117786ed3669SMark Brown break;
117886ed3669SMark Brown
117986ed3669SMark Brown default:
118086ed3669SMark Brown return -EINVAL;
118186ed3669SMark Brown }
118286ed3669SMark Brown
118386ed3669SMark Brown return 0;
118486ed3669SMark Brown }
118586ed3669SMark Brown
wm9081_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)118686ed3669SMark Brown static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
1187a5479e38SDaniel Ribeiro unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
118886ed3669SMark Brown {
118948c33876SKuninori Morimoto struct snd_soc_component *component = dai->component;
119048c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
11916d75dfc3SKuninori Morimoto unsigned int aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1);
119286ed3669SMark Brown
119386ed3669SMark Brown aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
119486ed3669SMark Brown
1195e0026beaSMark Brown if (slots < 0 || slots > 4)
119686ed3669SMark Brown return -EINVAL;
119786ed3669SMark Brown
1198e0026beaSMark Brown wm9081->tdm_width = slot_width;
1199e0026beaSMark Brown
1200e0026beaSMark Brown if (slots == 0)
1201e0026beaSMark Brown slots = 1;
1202e0026beaSMark Brown
120386ed3669SMark Brown aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
120486ed3669SMark Brown
1205a5479e38SDaniel Ribeiro switch (rx_mask) {
120686ed3669SMark Brown case 1:
120786ed3669SMark Brown break;
120886ed3669SMark Brown case 2:
120986ed3669SMark Brown aif1 |= 0x10;
121086ed3669SMark Brown break;
121186ed3669SMark Brown case 4:
121286ed3669SMark Brown aif1 |= 0x20;
121386ed3669SMark Brown break;
121486ed3669SMark Brown case 8:
121586ed3669SMark Brown aif1 |= 0x30;
121686ed3669SMark Brown break;
121786ed3669SMark Brown default:
121886ed3669SMark Brown return -EINVAL;
121986ed3669SMark Brown }
122086ed3669SMark Brown
122148c33876SKuninori Morimoto snd_soc_component_write(component, WM9081_AUDIO_INTERFACE_1, aif1);
122286ed3669SMark Brown
122386ed3669SMark Brown return 0;
122486ed3669SMark Brown }
122586ed3669SMark Brown
122686ed3669SMark Brown #define WM9081_RATES SNDRV_PCM_RATE_8000_96000
122786ed3669SMark Brown
122886ed3669SMark Brown #define WM9081_FORMATS \
122986ed3669SMark Brown (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
123086ed3669SMark Brown SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
123186ed3669SMark Brown
123285e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops wm9081_dai_ops = {
123386ed3669SMark Brown .hw_params = wm9081_hw_params,
123486ed3669SMark Brown .set_fmt = wm9081_set_dai_fmt,
123526d3c16eSKuninori Morimoto .mute_stream = wm9081_mute,
123686ed3669SMark Brown .set_tdm_slot = wm9081_set_tdm_slot,
123726d3c16eSKuninori Morimoto .no_capture_mute = 1,
123886ed3669SMark Brown };
123986ed3669SMark Brown
124086ed3669SMark Brown /* We report two channels because the CODEC processes a stereo signal, even
124186ed3669SMark Brown * though it is only capable of handling a mono output.
124286ed3669SMark Brown */
1243f0fba2adSLiam Girdwood static struct snd_soc_dai_driver wm9081_dai = {
1244f0fba2adSLiam Girdwood .name = "wm9081-hifi",
124586ed3669SMark Brown .playback = {
12460fb7d0c3SMark Brown .stream_name = "AIF",
124786ed3669SMark Brown .channels_min = 1,
124886ed3669SMark Brown .channels_max = 2,
124986ed3669SMark Brown .rates = WM9081_RATES,
125086ed3669SMark Brown .formats = WM9081_FORMATS,
125186ed3669SMark Brown },
125286ed3669SMark Brown .ops = &wm9081_dai_ops,
125386ed3669SMark Brown };
125486ed3669SMark Brown
wm9081_probe(struct snd_soc_component * component)125548c33876SKuninori Morimoto static int wm9081_probe(struct snd_soc_component *component)
125686ed3669SMark Brown {
125748c33876SKuninori Morimoto struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component);
125886ed3669SMark Brown
1259f0fba2adSLiam Girdwood /* Enable zero cross by default */
126048c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_ANALOGUE_LINEOUT,
1261b4027358SAxel Lin WM9081_LINEOUTZC, WM9081_LINEOUTZC);
126248c33876SKuninori Morimoto snd_soc_component_update_bits(component, WM9081_ANALOGUE_SPEAKER_PGA,
1263b4027358SAxel Lin WM9081_SPKPGAZC, WM9081_SPKPGAZC);
1264f0fba2adSLiam Girdwood
12654a5f7bdaSMark Brown if (!wm9081->pdata.num_retune_configs) {
126648c33876SKuninori Morimoto dev_dbg(component->dev,
126786ed3669SMark Brown "No ReTune Mobile data, using normal EQ\n");
126848c33876SKuninori Morimoto snd_soc_add_component_controls(component, wm9081_eq_controls,
126986ed3669SMark Brown ARRAY_SIZE(wm9081_eq_controls));
127086ed3669SMark Brown }
127186ed3669SMark Brown
12725d6be5aaSXiubo Li return 0;
127386ed3669SMark Brown }
127486ed3669SMark Brown
127548c33876SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_wm9081 = {
127686ed3669SMark Brown .probe = wm9081_probe,
127763d24b79SMark Brown .set_sysclk = wm9081_set_sysclk,
1278f0fba2adSLiam Girdwood .set_bias_level = wm9081_set_bias_level,
1279680fa1f8SMark Brown .controls = wm9081_snd_controls,
1280680fa1f8SMark Brown .num_controls = ARRAY_SIZE(wm9081_snd_controls),
1281149c7b44SMark Brown .dapm_widgets = wm9081_dapm_widgets,
1282149c7b44SMark Brown .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets),
1283149c7b44SMark Brown .dapm_routes = wm9081_audio_paths,
1284149c7b44SMark Brown .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
128548c33876SKuninori Morimoto .use_pmdown_time = 1,
128648c33876SKuninori Morimoto .endianness = 1,
128786ed3669SMark Brown };
128886ed3669SMark Brown
12897cfa467bSMark Brown static const struct regmap_config wm9081_regmap = {
12907cfa467bSMark Brown .reg_bits = 8,
12917cfa467bSMark Brown .val_bits = 16,
12927cfa467bSMark Brown
12937cfa467bSMark Brown .max_register = WM9081_MAX_REGISTER,
12947cfa467bSMark Brown .reg_defaults = wm9081_reg,
12957cfa467bSMark Brown .num_reg_defaults = ARRAY_SIZE(wm9081_reg),
12967cfa467bSMark Brown .volatile_reg = wm9081_volatile_register,
12977cfa467bSMark Brown .readable_reg = wm9081_readable_register,
1298*1a37aa41SMark Brown .cache_type = REGCACHE_MAPLE,
12997cfa467bSMark Brown };
13007cfa467bSMark Brown
wm9081_i2c_probe(struct i2c_client * i2c)130197b0b6e3SStephen Kitt static int wm9081_i2c_probe(struct i2c_client *i2c)
130286ed3669SMark Brown {
130386ed3669SMark Brown struct wm9081_priv *wm9081;
13047cfa467bSMark Brown unsigned int reg;
1305f0fba2adSLiam Girdwood int ret;
130686ed3669SMark Brown
1307897f7847SMark Brown wm9081 = devm_kzalloc(&i2c->dev, sizeof(struct wm9081_priv),
1308897f7847SMark Brown GFP_KERNEL);
130986ed3669SMark Brown if (wm9081 == NULL)
131086ed3669SMark Brown return -ENOMEM;
131186ed3669SMark Brown
131286ed3669SMark Brown i2c_set_clientdata(i2c, wm9081);
13137cfa467bSMark Brown
1314a5710c01SSachin Kamat wm9081->regmap = devm_regmap_init_i2c(i2c, &wm9081_regmap);
13157cfa467bSMark Brown if (IS_ERR(wm9081->regmap)) {
13167cfa467bSMark Brown ret = PTR_ERR(wm9081->regmap);
13177cfa467bSMark Brown dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
1318a5710c01SSachin Kamat return ret;
13197cfa467bSMark Brown }
13207cfa467bSMark Brown
13217cfa467bSMark Brown ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, ®);
13227cfa467bSMark Brown if (ret != 0) {
13237cfa467bSMark Brown dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
1324a5710c01SSachin Kamat return ret;
13257cfa467bSMark Brown }
13267cfa467bSMark Brown if (reg != 0x9081) {
13277cfa467bSMark Brown dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1328a5710c01SSachin Kamat return -EINVAL;
13297cfa467bSMark Brown }
13307cfa467bSMark Brown
13317cfa467bSMark Brown ret = wm9081_reset(wm9081->regmap);
13327cfa467bSMark Brown if (ret < 0) {
13337cfa467bSMark Brown dev_err(&i2c->dev, "Failed to issue reset\n");
1334a5710c01SSachin Kamat return ret;
13357cfa467bSMark Brown }
133686ed3669SMark Brown
13373ee845acSMark Brown if (dev_get_platdata(&i2c->dev))
13384a5f7bdaSMark Brown memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
13394a5f7bdaSMark Brown sizeof(wm9081->pdata));
13403ee845acSMark Brown
134168fcde97SMark Brown reg = 0;
134268fcde97SMark Brown if (wm9081->pdata.irq_high)
134368fcde97SMark Brown reg |= WM9081_IRQ_POL;
134468fcde97SMark Brown if (!wm9081->pdata.irq_cmos)
134568fcde97SMark Brown reg |= WM9081_IRQ_OP_CTRL;
134668fcde97SMark Brown regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
134768fcde97SMark Brown WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
134868fcde97SMark Brown
1349da157875SMark Brown regcache_cache_only(wm9081->regmap, true);
135068fcde97SMark Brown
135148c33876SKuninori Morimoto ret = devm_snd_soc_register_component(&i2c->dev,
135248c33876SKuninori Morimoto &soc_component_dev_wm9081, &wm9081_dai, 1);
1353f0fba2adSLiam Girdwood if (ret < 0)
1354a5710c01SSachin Kamat return ret;
13557cfa467bSMark Brown
13567cfa467bSMark Brown return 0;
135786ed3669SMark Brown }
135886ed3669SMark Brown
wm9081_i2c_remove(struct i2c_client * client)1359ed5c2f5fSUwe Kleine-König static void wm9081_i2c_remove(struct i2c_client *client)
1360ed5c2f5fSUwe Kleine-König {}
136186ed3669SMark Brown
136286ed3669SMark Brown static const struct i2c_device_id wm9081_i2c_id[] = {
136386ed3669SMark Brown { "wm9081", 0 },
136486ed3669SMark Brown { }
136586ed3669SMark Brown };
136686ed3669SMark Brown MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
136786ed3669SMark Brown
136886ed3669SMark Brown static struct i2c_driver wm9081_i2c_driver = {
136986ed3669SMark Brown .driver = {
13702031c064SMark Brown .name = "wm9081",
137186ed3669SMark Brown },
13729abcd240SUwe Kleine-König .probe = wm9081_i2c_probe,
13737a79e94eSBill Pemberton .remove = wm9081_i2c_remove,
137486ed3669SMark Brown .id_table = wm9081_i2c_id,
137586ed3669SMark Brown };
137686ed3669SMark Brown
13772dbc34d8SMark Brown module_i2c_driver(wm9081_i2c_driver);
137886ed3669SMark Brown
137986ed3669SMark Brown MODULE_DESCRIPTION("ASoC WM9081 driver");
138086ed3669SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
138186ed3669SMark Brown MODULE_LICENSE("GPL");
1382