Merge branch 'asoc-5.3' into asoc-linus
authorMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:42 +0000 (10:31 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:42 +0000 (10:31 +0100)
33 files changed:
arch/arm/mach-omap1/board-ams-delta.c
include/sound/soc-dapm.h
sound/soc/amd/Kconfig
sound/soc/atmel/mchp-i2s-mcc.c
sound/soc/codecs/cs4349.c
sound/soc/codecs/es8316.c
sound/soc/codecs/es8328.c
sound/soc/codecs/hdac_hda.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/rt1011.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-audmux.c
sound/soc/intel/baytrail/sst-baytrail-pcm.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/intel/common/sst-ipc.c
sound/soc/intel/skylake/skl-debug.c
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/mediatek/common/mtk-afe-fe-dai.c
sound/soc/meson/Kconfig
sound/soc/meson/axg-tdm-formatter.c
sound/soc/rockchip/rockchip_max98090.c
sound/soc/sh/rcar/adg.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/hda.c
sound/soc/sunxi/sun4i-i2s.c
sound/soc/ti/ams-delta.c
sound/soc/ti/davinci-i2s.c
sound/soc/uniphier/aio-cpu.c
sound/soc/uniphier/aio.h

index e47a6fb..a2aa7a1 100644 (file)
@@ -246,8 +246,8 @@ static struct platform_device latch2_gpio_device = {
 #define LATCH2_PIN_SCARD_CMDVCC                11
 #define LATCH2_PIN_MODEM_NRESET                12
 #define LATCH2_PIN_MODEM_CODEC         13
-#define LATCH2_PIN_AUDIO_MUTE          14
-#define LATCH2_PIN_HOOKFLASH           15
+#define LATCH2_PIN_HANDSFREE_MUTE      14
+#define LATCH2_PIN_HANDSET_MUTE                15
 
 static struct regulator_consumer_supply modem_nreset_consumers[] = {
        REGULATOR_SUPPLY("RESET#", "serial8250.1"),
@@ -476,6 +476,10 @@ static struct gpiod_lookup_table ams_delta_audio_gpio_table = {
                            "hook_switch", 0),
                GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
                            "modem_codec", 0),
+               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSFREE_MUTE,
+                           "handsfree_mute", 0),
+               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSET_MUTE,
+                           "handset_mute", 0),
                { },
        },
 };
@@ -590,8 +594,6 @@ static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
 static struct gpiod_hog ams_delta_gpio_hogs[] = {
        GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
                 GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
-       GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_AUDIO_MUTE, "audio_mute",
-                GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
        {},
 };
 
index c00a0b8..8a90816 100644 (file)
@@ -402,6 +402,9 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 struct snd_soc_dapm_widget *snd_soc_dapm_new_control(
                struct snd_soc_dapm_context *dapm,
                const struct snd_soc_dapm_widget *widget);
+struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked(
+               struct snd_soc_dapm_context *dapm,
+               const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
                                 struct snd_soc_dai *dai);
 int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
index 9ca9214..5f40517 100644 (file)
@@ -10,7 +10,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
        select SND_SOC_MAX98357A
        select SND_SOC_ADAU7002
        select REGULATOR
-       depends on SND_SOC_AMD_ACP && I2C
+       depends on SND_SOC_AMD_ACP && I2C && GPIOLIB
        help
         This option enables machine driver for DA7219 and MAX9835.
 
index 8649588..ab7d5f9 100644 (file)
@@ -670,8 +670,13 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
        }
 
        ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra);
-       if (ret < 0)
+       if (ret < 0) {
+               if (dev->gclk_use) {
+                       clk_unprepare(dev->gclk);
+                       dev->gclk_use = 0;
+               }
                return ret;
+       }
        return regmap_write(dev->regmap, MCHP_I2SMCC_MRB, mrb);
 }
 
@@ -686,31 +691,37 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream,
                err = wait_event_interruptible_timeout(dev->wq_txrdy,
                                                       dev->tx_rdy,
                                                       msecs_to_jiffies(500));
+               if (err == 0) {
+                       dev_warn_once(dev->dev,
+                                     "Timeout waiting for Tx ready\n");
+                       regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+                                    MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+                       dev->tx_rdy = 1;
+               }
        } else {
                err = wait_event_interruptible_timeout(dev->wq_rxrdy,
                                                       dev->rx_rdy,
                                                       msecs_to_jiffies(500));
-       }
-
-       if (err == 0) {
-               u32 idra;
-
-               dev_warn_once(dev->dev, "Timeout waiting for %s\n",
-                             is_playback ? "Tx ready" : "Rx ready");
-               if (is_playback)
-                       idra = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels);
-               else
-                       idra = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels);
-               regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
+               if (err == 0) {
+                       dev_warn_once(dev->dev,
+                                     "Timeout waiting for Rx ready\n");
+                       regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+                                    MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+                       dev->rx_rdy = 1;
+               }
        }
 
        if (!mchp_i2s_mcc_is_running(dev)) {
                regmap_write(dev->regmap, MCHP_I2SMCC_CR, MCHP_I2SMCC_CR_CKDIS);
 
                if (dev->gclk_running) {
-                       clk_disable_unprepare(dev->gclk);
+                       clk_disable(dev->gclk);
                        dev->gclk_running = 0;
                }
+               if (dev->gclk_use) {
+                       clk_unprepare(dev->gclk);
+                       dev->gclk_use = 0;
+               }
        }
 
        return 0;
@@ -809,6 +820,8 @@ static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai)
 
        init_waitqueue_head(&dev->wq_txrdy);
        init_waitqueue_head(&dev->wq_rxrdy);
+       dev->tx_rdy = 1;
+       dev->rx_rdy = 1;
 
        snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
 
index 09716fa..3381209 100644 (file)
@@ -378,6 +378,7 @@ static struct i2c_driver cs4349_i2c_driver = {
        .driver = {
                .name           = "cs4349",
                .of_match_table = cs4349_of_match,
+               .pm = &cs4349_runtime_pm,
        },
        .id_table       = cs4349_i2c_id,
        .probe          = cs4349_i2c_probe,
index 6db002c..ed2959d 100644 (file)
@@ -51,7 +51,10 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
-static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
+       0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
+       8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
+);
 
 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
        0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
@@ -89,7 +92,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = {
        SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
                       4, 0, 3, 1, hpout_vol_tlv),
        SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
-                      0, 4, 7, 0, hpmixer_gain_tlv),
+                      4, 0, 11, 0, hpmixer_gain_tlv),
 
        SOC_ENUM("Playback Polarity", dacpol),
        SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
index 822a25a..69b81e7 100644 (file)
@@ -228,7 +228,7 @@ static const struct soc_enum es8328_rline_enum =
                              ARRAY_SIZE(es8328_line_texts),
                              es8328_line_texts);
 static const struct snd_kcontrol_new es8328_right_line_controls =
-       SOC_DAPM_ENUM("Route", es8328_lline_enum);
+       SOC_DAPM_ENUM("Route", es8328_rline_enum);
 
 /* Left Mixer */
 static const struct snd_kcontrol_new es8328_left_mixer_controls[] = {
index 7d49402..91242b6 100644 (file)
@@ -495,6 +495,10 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev)
 
 static int hdac_hda_dev_remove(struct hdac_device *hdev)
 {
+       struct hdac_hda_priv *hda_pvt;
+
+       hda_pvt = dev_get_drvdata(&hdev->dev);
+       cancel_delayed_work_sync(&hda_pvt->codec.jackpoll_work);
        return 0;
 }
 
index 2991895..18c173e 100644 (file)
@@ -88,8 +88,10 @@ struct hdac_hdmi_port {
        hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
        struct hdac_hdmi_eld eld;
        const char *jack_pin;
+       bool is_connect;
        struct snd_soc_dapm_context *dapm;
        const char *output_pin;
+       struct work_struct dapm_work;
 };
 
 struct hdac_hdmi_pcm {
@@ -163,11 +165,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
 {
        struct hdac_device *hdev = port->pin->hdev;
 
-       if (is_connect)
-               snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
-       else
-               snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
-
+       port->is_connect = is_connect;
        if (is_connect) {
                /*
                 * Report Jack connect event when a device is connected
@@ -193,10 +191,32 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
                if (pcm->jack_event > 0)
                        pcm->jack_event--;
        }
+}
 
+static void hdac_hdmi_port_dapm_update(struct hdac_hdmi_port *port)
+{
+       if (port->is_connect)
+               snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
+       else
+               snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
        snd_soc_dapm_sync(port->dapm);
 }
 
+static void hdac_hdmi_jack_dapm_work(struct work_struct *work)
+{
+       struct hdac_hdmi_port *port;
+
+       port = container_of(work, struct hdac_hdmi_port, dapm_work);
+       hdac_hdmi_port_dapm_update(port);
+}
+
+static void hdac_hdmi_jack_report_sync(struct hdac_hdmi_pcm *pcm,
+               struct hdac_hdmi_port *port, bool is_connect)
+{
+       hdac_hdmi_jack_report(pcm, port, is_connect);
+       hdac_hdmi_port_dapm_update(port);
+}
+
 /* MST supported verbs */
 /*
  * Get the no devices that can be connected to a port on the Pin widget.
@@ -904,7 +924,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
                list_for_each_entry_safe(p, p_next, &pcm->port_list, head) {
                        if (p == port && p->id == port->id &&
                                        p->pin == port->pin) {
-                               hdac_hdmi_jack_report(pcm, port, false);
+                               hdac_hdmi_jack_report_sync(pcm, port, false);
                                list_del(&p->head);
                        }
                }
@@ -918,7 +938,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
                if (!strcmp(cvt_name, pcm->cvt->name)) {
                        list_add_tail(&port->head, &pcm->port_list);
                        if (port->eld.monitor_present && port->eld.eld_valid) {
-                               hdac_hdmi_jack_report(pcm, port, true);
+                               hdac_hdmi_jack_report_sync(pcm, port, true);
                                mutex_unlock(&hdmi->pin_mutex);
                                return ret;
                        }
@@ -1281,16 +1301,20 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
                 * report jack here. It will be done in usermode mux
                 * control select.
                 */
-               if (pcm)
+               if (pcm) {
                        hdac_hdmi_jack_report(pcm, port, false);
+                       schedule_work(&port->dapm_work);
+               }
 
                mutex_unlock(&hdmi->pin_mutex);
                return;
        }
 
        if (port->eld.monitor_present && port->eld.eld_valid) {
-               if (pcm)
+               if (pcm) {
                        hdac_hdmi_jack_report(pcm, port, true);
+                       schedule_work(&port->dapm_work);
+               }
 
                print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
                          port->eld.eld_buffer, port->eld.eld_size, false);
@@ -1319,6 +1343,7 @@ static int hdac_hdmi_add_ports(struct hdac_device *hdev,
        for (i = 0; i < max_ports; i++) {
                ports[i].id = i;
                ports[i].pin = pin;
+               INIT_WORK(&ports[i].dapm_work, hdac_hdmi_jack_dapm_work);
        }
        pin->ports = ports;
        pin->num_ports = max_ports;
@@ -2083,8 +2108,20 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
        return ret;
 }
 
+static void clear_dapm_works(struct hdac_device *hdev)
+{
+       struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
+       struct hdac_hdmi_pin *pin;
+       int i;
+
+       list_for_each_entry(pin, &hdmi->pin_list, head)
+               for (i = 0; i < pin->num_ports; i++)
+                       cancel_work_sync(&pin->ports[i].dapm_work);
+}
+
 static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
 {
+       clear_dapm_works(hdev);
        snd_hdac_display_power(hdev->bus, hdev->addr, false);
 
        return 0;
@@ -2103,6 +2140,8 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
        if (!bus)
                return 0;
 
+       clear_dapm_works(hdev);
+
        /*
         * Power down afg.
         * codec_read is preferred over codec_write to set the power state.
index 0a6ff13..ed28250 100644 (file)
@@ -1619,14 +1619,18 @@ static int rt1011_hw_params(struct snd_pcm_substream *substream,
 static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_component *component = dai->component;
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
        unsigned int reg_val = 0, reg_bclk_inv = 0;
+       int ret = 0;
 
+       snd_soc_dapm_mutex_lock(dapm);
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                reg_val |= RT1011_I2S_TDM_MS_S;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -1636,7 +1640,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                reg_bclk_inv |= RT1011_TDM_INV_BCLK;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1652,7 +1656,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                reg_val |= RT1011_I2S_TDM_DF_PCM_B;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
        switch (dai->id) {
@@ -1667,9 +1671,11 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                break;
        default:
                dev_err(component->dev, "Invalid dai->id: %d\n", dai->id);
-               return -EINVAL;
+               ret = -EINVAL;
        }
-       return 0;
+
+       snd_soc_dapm_mutex_unlock(dapm);
+       return ret;
 }
 
 static int rt1011_set_component_sysclk(struct snd_soc_component *component,
@@ -1788,8 +1794,12 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
        struct snd_soc_component *component = dai->component;
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
        unsigned int val = 0, tdm_en = 0;
+       int ret = 0;
 
+       snd_soc_dapm_mutex_lock(dapm);
        if (rx_mask || tx_mask)
                tdm_en = RT1011_TDM_I2S_DOCK_EN_1;
 
@@ -1809,7 +1819,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
        case 2:
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
        switch (slot_width) {
@@ -1828,7 +1838,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
        case 16:
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
        snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
@@ -1845,7 +1855,8 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
                RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
                RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
 
-       return 0;
+       snd_soc_dapm_mutex_unlock(dapm);
+       return ret;
 }
 
 static int rt1011_probe(struct snd_soc_component *component)
index 0c246fb..7a3f9fb 100644 (file)
@@ -167,7 +167,7 @@ SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0),
 SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0),
 SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0),
 SOC_ENUM("3D Low Cut-off", low_3d),
-SOC_ENUM("3D High Cut-off", low_3d),
+SOC_ENUM("3D High Cut-off", high_3d),
 SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv),
 
 SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0),
index 5ebdd1d..bcb3c9d 100644 (file)
@@ -545,18 +545,6 @@ static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
 static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 
-static const char *input_mode_text[] = {
-       "Single-Ended", "Differential Line", "Differential Mic"
-};
-
-static SOC_ENUM_SINGLE_DECL(lin_mode,
-                           WM8904_ANALOGUE_LEFT_INPUT_1, 0,
-                           input_mode_text);
-
-static SOC_ENUM_SINGLE_DECL(rin_mode,
-                           WM8904_ANALOGUE_RIGHT_INPUT_1, 0,
-                           input_mode_text);
-
 static const char *hpf_mode_text[] = {
        "Hi-fi", "Voice 1", "Voice 2", "Voice 3"
 };
@@ -591,9 +579,6 @@ static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
 SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
                 WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
 
-SOC_ENUM("Left Capture Mode", lin_mode),
-SOC_ENUM("Right Capture Mode", rin_mode),
-
 /* No TLV since it depends on mode */
 SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0,
             WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0),
@@ -852,6 +837,10 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static const char *input_mode_text[] = {
+       "Single-Ended", "Differential Line", "Differential Mic"
+};
+
 static const char *lin_text[] = {
        "IN1L", "IN2L", "IN3L"
 };
@@ -866,7 +855,14 @@ static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4,
                            lin_text);
 
 static const struct snd_kcontrol_new lin_inv_mux =
-       SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum);
+       SOC_DAPM_ENUM("Left Capture Inverting Mux", lin_inv_enum);
+
+static SOC_ENUM_SINGLE_DECL(lin_mode_enum,
+                           WM8904_ANALOGUE_LEFT_INPUT_1, 0,
+                           input_mode_text);
+
+static const struct snd_kcontrol_new lin_mode =
+       SOC_DAPM_ENUM("Left Capture Mode", lin_mode_enum);
 
 static const char *rin_text[] = {
        "IN1R", "IN2R", "IN3R"
@@ -882,7 +878,14 @@ static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4,
                            rin_text);
 
 static const struct snd_kcontrol_new rin_inv_mux =
-       SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum);
+       SOC_DAPM_ENUM("Right Capture Inverting Mux", rin_inv_enum);
+
+static SOC_ENUM_SINGLE_DECL(rin_mode_enum,
+                           WM8904_ANALOGUE_RIGHT_INPUT_1, 0,
+                           input_mode_text);
+
+static const struct snd_kcontrol_new rin_mode =
+       SOC_DAPM_ENUM("Right Capture Mode", rin_mode_enum);
 
 static const char *aif_text[] = {
        "Left", "Right"
@@ -932,9 +935,11 @@ SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
 SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux),
 SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
                 &lin_inv_mux),
+SND_SOC_DAPM_MUX("Left Capture Mode", SND_SOC_NOPM, 0, 0, &lin_mode),
 SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rin_mux),
 SND_SOC_DAPM_MUX("Right Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
                 &rin_inv_mux),
+SND_SOC_DAPM_MUX("Right Capture Mode", SND_SOC_NOPM, 0, 0, &rin_mode),
 
 SND_SOC_DAPM_PGA("Left Capture PGA", WM8904_POWER_MANAGEMENT_0, 1, 0,
                 NULL, 0),
@@ -1057,6 +1062,12 @@ static const struct snd_soc_dapm_route adc_intercon[] = {
        { "Left Capture Inverting Mux", "IN2L", "IN2L" },
        { "Left Capture Inverting Mux", "IN3L", "IN3L" },
 
+       { "Left Capture Mode", "Single-Ended", "Left Capture Inverting Mux" },
+       { "Left Capture Mode", "Differential Line", "Left Capture Mux" },
+       { "Left Capture Mode", "Differential Line", "Left Capture Inverting Mux" },
+       { "Left Capture Mode", "Differential Mic", "Left Capture Mux" },
+       { "Left Capture Mode", "Differential Mic", "Left Capture Inverting Mux" },
+
        { "Right Capture Mux", "IN1R", "IN1R" },
        { "Right Capture Mux", "IN2R", "IN2R" },
        { "Right Capture Mux", "IN3R", "IN3R" },
@@ -1065,11 +1076,14 @@ static const struct snd_soc_dapm_route adc_intercon[] = {
        { "Right Capture Inverting Mux", "IN2R", "IN2R" },
        { "Right Capture Inverting Mux", "IN3R", "IN3R" },
 
-       { "Left Capture PGA", NULL, "Left Capture Mux" },
-       { "Left Capture PGA", NULL, "Left Capture Inverting Mux" },
+       { "Right Capture Mode", "Single-Ended", "Right Capture Inverting Mux" },
+       { "Right Capture Mode", "Differential Line", "Right Capture Mux" },
+       { "Right Capture Mode", "Differential Line", "Right Capture Inverting Mux" },
+       { "Right Capture Mode", "Differential Mic", "Right Capture Mux" },
+       { "Right Capture Mode", "Differential Mic", "Right Capture Inverting Mux" },
 
-       { "Right Capture PGA", NULL, "Right Capture Mux" },
-       { "Right Capture PGA", NULL, "Right Capture Inverting Mux" },
+       { "Left Capture PGA", NULL, "Left Capture Mode" },
+       { "Right Capture PGA", NULL, "Right Capture Mode" },
 
        { "AIFOUTL Mux", "Left", "ADCL" },
        { "AIFOUTL Mux", "Right", "ADCR" },
index fa862af..085855f 100644 (file)
@@ -799,15 +799,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        u32 wl = SSI_SxCCR_WL(sample_size);
        int ret;
 
-       /*
-        * SSI is properly configured if it is enabled and running in
-        * the synchronous mode; Note that AC97 mode is an exception
-        * that should set separate configurations for STCCR and SRCCR
-        * despite running in the synchronous mode.
-        */
-       if (ssi->streams && ssi->synchronous)
-               return 0;
-
        if (fsl_ssi_is_i2s_master(ssi)) {
                ret = fsl_ssi_set_bclk(substream, dai, hw_params);
                if (ret)
@@ -823,6 +814,15 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
+       /*
+        * SSI is properly configured if it is enabled and running in
+        * the synchronous mode; Note that AC97 mode is an exception
+        * that should set separate configurations for STCCR and SRCCR
+        * despite running in the synchronous mode.
+        */
+       if (ssi->streams && ssi->synchronous)
+               return 0;
+
        if (!fsl_ssi_is_ac97(ssi)) {
                /*
                 * Keep the ssi->i2s_net intact while having a local variable
index b2351cd..16ede3b 100644 (file)
@@ -23,6 +23,8 @@
 
 static struct clk *audmux_clk;
 static void __iomem *audmux_base;
+static u32 *regcache;
+static u32 reg_max;
 
 #define IMX_AUDMUX_V2_PTCR(x)          ((x) * 8)
 #define IMX_AUDMUX_V2_PDCR(x)          ((x) * 8 + 4)
@@ -317,8 +319,23 @@ static int imx_audmux_probe(struct platform_device *pdev)
        if (of_id)
                pdev->id_entry = of_id->data;
        audmux_type = pdev->id_entry->driver_data;
-       if (audmux_type == IMX31_AUDMUX)
+
+       switch (audmux_type) {
+       case IMX31_AUDMUX:
                audmux_debugfs_init();
+               reg_max = 14;
+               break;
+       case IMX21_AUDMUX:
+               reg_max = 6;
+               break;
+       default:
+               dev_err(&pdev->dev, "unsupported version!\n");
+               return -EINVAL;
+       }
+
+       regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL);
+       if (!regcache)
+               return -ENOMEM;
 
        if (of_id)
                imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
@@ -334,12 +351,47 @@ static int imx_audmux_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int imx_audmux_suspend(struct device *dev)
+{
+       int i;
+
+       clk_prepare_enable(audmux_clk);
+
+       for (i = 0; i < reg_max; i++)
+               regcache[i] = readl(audmux_base + i * 4);
+
+       clk_disable_unprepare(audmux_clk);
+
+       return 0;
+}
+
+static int imx_audmux_resume(struct device *dev)
+{
+       int i;
+
+       clk_prepare_enable(audmux_clk);
+
+       for (i = 0; i < reg_max; i++)
+               writel(regcache[i], audmux_base + i * 4);
+
+       clk_disable_unprepare(audmux_clk);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops imx_audmux_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume)
+};
+
 static struct platform_driver imx_audmux_driver = {
        .probe          = imx_audmux_probe,
        .remove         = imx_audmux_remove,
        .id_table       = imx_audmux_ids,
        .driver = {
                .name   = DRIVER_NAME,
+               .pm = &imx_audmux_pm,
                .of_match_table = imx_audmux_dt_ids,
        }
 };
index 9cbc982..54f2ee3 100644 (file)
@@ -193,6 +193,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
                pdata->restore_stream = false;
+               /* fallthrough */
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                sst_byt_stream_pause(byt, pcm_data->stream);
                break;
index 33eb725..83b978e 100644 (file)
@@ -400,6 +400,20 @@ static struct snd_soc_card snd_soc_card_cht = {
 
 static const struct dmi_system_id cht_max98090_quirk_table[] = {
        {
+               /* Banjo model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Banjo"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Candy model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Candy"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
                /* Clapper model Chromebook */
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Clapper"),
@@ -407,6 +421,27 @@ static const struct dmi_system_id cht_max98090_quirk_table[] = {
                .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
        },
        {
+               /* Cyan model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Enguarde model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Enguarde"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Glimmer model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
                /* Gnawty model Chromebook (Acer Chromebook CB3-111) */
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Gnawty"),
@@ -414,12 +449,75 @@ static const struct dmi_system_id cht_max98090_quirk_table[] = {
                .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
        },
        {
+               /* Heli model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Heli"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Kip model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Kip"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Ninja model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Ninja"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Orco model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Orco"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Quawks model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Quawks"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Rambi model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Rambi"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Squawks model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Squawks"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
+               /* Sumo model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Sumo"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {
                /* Swanky model Chromebook (Toshiba Chromebook 2) */
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Swanky"),
                },
                .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
        },
+       {
+               /* Winky model Chromebook */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Winky"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
        {}
 };
 
index daeaa39..0b12d61 100644 (file)
@@ -309,6 +309,7 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_SPK("Spk", NULL),
+       SND_SOC_DAPM_MIC("SoC DMIC", NULL),
 };
 
 static const struct snd_soc_dapm_route sof_map[] = {
@@ -319,6 +320,9 @@ static const struct snd_soc_dapm_route sof_map[] = {
        /* other jacks */
        { "IN1P", NULL, "Headset Mic" },
 
+       /* digital mics */
+       {"DMic", NULL, "SoC DMIC"},
+
 };
 
 static const struct snd_soc_dapm_route speaker_map[] = {
index ef5b66a..3a66121 100644 (file)
@@ -222,6 +222,8 @@ struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
 
        if (ipc->ops.reply_msg_match != NULL)
                header = ipc->ops.reply_msg_match(header, &mask);
+       else
+               mask = (u64)-1;
 
        if (list_empty(&ipc->rx_list)) {
                dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
index b9b4a72..b28a9c2 100644 (file)
@@ -188,7 +188,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
        memset(d->fw_read_buff, 0, FW_REG_BUF);
 
        if (w0_stat_sz > 0)
-               __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
+               __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
 
        for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
                ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
index 1132109..e01815c 100644 (file)
@@ -225,7 +225,7 @@ int skl_nhlt_update_topology_bin(struct skl *skl)
        struct hdac_bus *bus = skl_to_bus(skl);
        struct device *dev = bus->dev;
 
-       dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n",
+       dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n",
                nhlt->header.oem_id, nhlt->header.oem_table_id,
                nhlt->header.oem_revision);
 
index d165634..10ea4fd 100644 (file)
@@ -241,7 +241,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
        struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
        struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
        int hd_audio = 0;
-       int hd_align = 1;
+       int hd_align = 0;
 
        /* set hd mode */
        switch (substream->runtime->format) {
@@ -254,7 +254,6 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
                hd_audio = 1;
-               hd_align = 0;
                break;
        default:
                dev_err(afe->dev, "%s() error: unsupported format %d\n",
index 63b38c1..2e36761 100644 (file)
@@ -87,6 +87,7 @@ config SND_MESON_AXG_PDM
 
 config SND_MESON_G12A_TOHDMITX
        tristate "Amlogic G12A To HDMI TX Control Support"
+       select REGMAP_MMIO
        imply SND_SOC_HDMI_CODEC
        help
          Select Y or M to add support for HDMI audio on the g12a SoC
index 2e49820..1a0bf9d 100644 (file)
@@ -327,7 +327,7 @@ int axg_tdm_formatter_probe(struct platform_device *pdev)
        }
 
        /* Formatter dedicated reset line */
-       formatter->reset = reset_control_get_optional_exclusive(dev, NULL);
+       formatter->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
        if (IS_ERR(formatter->reset)) {
                ret = PTR_ERR(formatter->reset);
                if (ret != -EPROBE_DEFER)
index 782e534..d54f672 100644 (file)
@@ -138,8 +138,19 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int rk_aif1_startup(struct snd_pcm_substream *substream)
+{
+       /*
+        * Set period size to 240 because pl330 has issue
+        * dealing with larger period in stress testing.
+        */
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 240, 240);
+}
+
 static const struct snd_soc_ops rk_aif1_ops = {
        .hw_params = rk_aif1_hw_params,
+       .startup = rk_aif1_startup,
 };
 
 SND_SOC_DAILINK_DEFS(hifi,
index fce4e05..b9aacf3 100644 (file)
@@ -30,6 +30,7 @@ struct rsnd_adg {
        struct clk *clkout[CLKOUTMAX];
        struct clk_onecell_data onecell;
        struct rsnd_mod mod;
+       int clk_rate[CLKMAX];
        u32 flags;
        u32 ckr;
        u32 rbga;
@@ -114,9 +115,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
        unsigned int val, en;
        unsigned int min, diff;
        unsigned int sel_rate[] = {
-               clk_get_rate(adg->clk[CLKA]),   /* 0000: CLKA */
-               clk_get_rate(adg->clk[CLKB]),   /* 0001: CLKB */
-               clk_get_rate(adg->clk[CLKC]),   /* 0010: CLKC */
+               adg->clk_rate[CLKA],    /* 0000: CLKA */
+               adg->clk_rate[CLKB],    /* 0001: CLKB */
+               adg->clk_rate[CLKC],    /* 0010: CLKC */
                adg->rbga_rate_for_441khz,      /* 0011: RBGA */
                adg->rbgb_rate_for_48khz,       /* 0100: RBGB */
        };
@@ -302,7 +303,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
         * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
         */
        for_each_rsnd_clk(clk, adg, i) {
-               if (rate == clk_get_rate(clk))
+               if (rate == adg->clk_rate[i])
                        return sel_table[i];
        }
 
@@ -369,10 +370,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
 
        for_each_rsnd_clk(clk, adg, i) {
                ret = 0;
-               if (enable)
+               if (enable) {
                        ret = clk_prepare_enable(clk);
-               else
+
+                       /*
+                        * We shouldn't use clk_get_rate() under
+                        * atomic context. Let's keep it when
+                        * rsnd_adg_clk_enable() was called
+                        */
+                       adg->clk_rate[i] = clk_get_rate(adg->clk[i]);
+               } else {
                        clk_disable_unprepare(clk);
+               }
 
                if (ret < 0)
                        dev_warn(dev, "can't use clk %d\n", i);
index 748f5f6..5552c66 100644 (file)
@@ -306,6 +306,12 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
 
                if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i]))
                        pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE;
+
+               if (rtd->pcm->streams[i].pcm->name[0] == '\0') {
+                       strscpy_pad(rtd->pcm->streams[i].pcm->name,
+                                   rtd->pcm->streams[i].pcm->id,
+                                   sizeof(rtd->pcm->streams[i].pcm->name));
+               }
        }
 
        return 0;
index dc463f1..2eca85c 100644 (file)
@@ -80,12 +80,6 @@ struct soc_tplg {
 
 static int soc_tplg_process_headers(struct soc_tplg *tplg);
 static void soc_tplg_complete(struct soc_tplg *tplg);
-struct snd_soc_dapm_widget *
-snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
-                        const struct snd_soc_dapm_widget *widget);
-struct snd_soc_dapm_widget *
-snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
-                        const struct snd_soc_dapm_widget *widget);
 static void soc_tplg_denum_remove_texts(struct soc_enum *se);
 static void soc_tplg_denum_remove_values(struct soc_enum *se);
 
index 7f66539..ae50839 100644 (file)
@@ -329,10 +329,23 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        if (bus->ppcap)
                dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+       /* init i915 and HDMI codecs */
+       ret = hda_codec_i915_init(sdev);
+       if (ret < 0) {
+               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
+               return ret;
+       }
+#endif
+
+       /* Init HDA controller after i915 init */
        ret = hda_dsp_ctrl_init_chip(sdev, true);
        if (ret < 0) {
                dev_err(bus->dev, "error: init chip failed with ret: %d\n",
                        ret);
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+               hda_codec_i915_exit(sdev);
+#endif
                return ret;
        }
 
@@ -340,13 +353,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(bus);
 
-       /* init i915 and HDMI codecs */
-       ret = hda_codec_i915_init(sdev);
-       if (ret < 0) {
-               dev_err(sdev->dev, "error: no HDMI audio devices found\n");
-               return ret;
-       }
-
        /* codec detection */
        if (!bus->codec_mask) {
                dev_info(bus->dev, "no hda codecs found!\n");
index 7fa5c61..85c3b2c 100644 (file)
@@ -1148,11 +1148,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
                        goto err_pm_disable;
        }
 
-       ret = devm_snd_soc_register_component(&pdev->dev,
-                                             &sun4i_i2s_component,
-                                             &sun4i_i2s_dai, 1);
+       ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s);
        if (ret) {
-               dev_err(&pdev->dev, "Could not register DAI\n");
+               dev_err(&pdev->dev, "Could not initialise regmap fields\n");
                goto err_suspend;
        }
 
@@ -1162,9 +1160,11 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
                goto err_suspend;
        }
 
-       ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s);
+       ret = devm_snd_soc_register_component(&pdev->dev,
+                                             &sun4i_i2s_component,
+                                             &sun4i_i2s_dai, 1);
        if (ret) {
-               dev_err(&pdev->dev, "Could not initialise regmap fields\n");
+               dev_err(&pdev->dev, "Could not register DAI\n");
                goto err_suspend;
        }
 
index dee8fc7..8e2fb81 100644 (file)
 #include "omap-mcbsp.h"
 #include "../codecs/cx20442.h"
 
+static struct gpio_desc *handset_mute;
+static struct gpio_desc *handsfree_mute;
+
+static int ams_delta_event_handset(struct snd_soc_dapm_widget *w,
+                                  struct snd_kcontrol *k, int event)
+{
+       gpiod_set_value_cansleep(handset_mute, !SND_SOC_DAPM_EVENT_ON(event));
+       return 0;
+}
+
+static int ams_delta_event_handsfree(struct snd_soc_dapm_widget *w,
+                                    struct snd_kcontrol *k, int event)
+{
+       gpiod_set_value_cansleep(handsfree_mute, !SND_SOC_DAPM_EVENT_ON(event));
+       return 0;
+}
+
 /* Board specific DAPM widgets */
 static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
        /* Handset */
        SND_SOC_DAPM_MIC("Mouthpiece", NULL),
-       SND_SOC_DAPM_HP("Earpiece", NULL),
+       SND_SOC_DAPM_HP("Earpiece", ams_delta_event_handset),
        /* Handsfree/Speakerphone */
        SND_SOC_DAPM_MIC("Microphone", NULL),
-       SND_SOC_DAPM_SPK("Speaker", NULL),
+       SND_SOC_DAPM_SPK("Speaker", ams_delta_event_handsfree),
 };
 
 /* How they are connected to codec pins */
@@ -542,6 +559,16 @@ static int ams_delta_probe(struct platform_device *pdev)
 
        card->dev = &pdev->dev;
 
+       handset_mute = devm_gpiod_get(card->dev, "handset_mute",
+                                     GPIOD_OUT_HIGH);
+       if (IS_ERR(handset_mute))
+               return PTR_ERR(handset_mute);
+
+       handsfree_mute = devm_gpiod_get(card->dev, "handsfree_mute",
+                                       GPIOD_OUT_HIGH);
+       if (IS_ERR(handsfree_mute))
+               return PTR_ERR(handsfree_mute);
+
        ret = snd_soc_register_card(card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
index 92c1bdc..27afdbb 100644 (file)
@@ -187,57 +187,9 @@ static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
 static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
                struct snd_pcm_substream *substream)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        u32 spcr;
        u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
-       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-       if (spcr & mask) {
-               /* start off disabled */
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
-                               spcr & ~mask);
-               toggle_clock(dev, playback);
-       }
-       if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
-                       DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
-               /* Start the sample generator */
-               spcr |= DAVINCI_MCBSP_SPCR_GRST;
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
-       }
-
-       if (playback) {
-               /* Stop the DMA to avoid data loss */
-               /* while the transmitter is out of reset to handle XSYNCERR */
-               if (component->driver->ops->trigger) {
-                       int ret = component->driver->ops->trigger(substream,
-                               SNDRV_PCM_TRIGGER_STOP);
-                       if (ret < 0)
-                               printk(KERN_DEBUG "Playback DMA stop failed\n");
-               }
-
-               /* Enable the transmitter */
-               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               spcr |= DAVINCI_MCBSP_SPCR_XRST;
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
-
-               /* wait for any unexpected frame sync error to occur */
-               udelay(100);
-
-               /* Disable the transmitter to clear any outstanding XSYNCERR */
-               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
-               toggle_clock(dev, playback);
-
-               /* Restart the DMA */
-               if (component->driver->ops->trigger) {
-                       int ret = component->driver->ops->trigger(substream,
-                               SNDRV_PCM_TRIGGER_START);
-                       if (ret < 0)
-                               printk(KERN_DEBUG "Playback DMA start failed\n");
-               }
-       }
 
        /* Enable transmitter or receiver */
        spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -575,7 +527,41 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
 {
        struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       u32 spcr;
+       u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
+
        davinci_mcbsp_stop(dev, playback);
+
+       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       if (spcr & mask) {
+               /* start off disabled */
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
+                                       spcr & ~mask);
+               toggle_clock(dev, playback);
+       }
+       if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
+                       DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
+               /* Start the sample generator */
+               spcr |= DAVINCI_MCBSP_SPCR_GRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+       }
+
+       if (playback) {
+               /* Enable the transmitter */
+               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+               spcr |= DAVINCI_MCBSP_SPCR_XRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+
+               /* wait for any unexpected frame sync error to occur */
+               udelay(100);
+
+               /* Disable the transmitter to clear any outstanding XSYNCERR */
+               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+               spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+               toggle_clock(dev, playback);
+       }
+
        return 0;
 }
 
index ee90e6c..2ae582a 100644 (file)
@@ -424,8 +424,11 @@ int uniphier_aio_dai_suspend(struct snd_soc_dai *dai)
 {
        struct uniphier_aio *aio = uniphier_priv(dai);
 
-       reset_control_assert(aio->chip->rst);
-       clk_disable_unprepare(aio->chip->clk);
+       aio->chip->num_wup_aios--;
+       if (!aio->chip->num_wup_aios) {
+               reset_control_assert(aio->chip->rst);
+               clk_disable_unprepare(aio->chip->clk);
+       }
 
        return 0;
 }
@@ -439,13 +442,15 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
        if (!aio->chip->active)
                return 0;
 
-       ret = clk_prepare_enable(aio->chip->clk);
-       if (ret)
-               return ret;
+       if (!aio->chip->num_wup_aios) {
+               ret = clk_prepare_enable(aio->chip->clk);
+               if (ret)
+                       return ret;
 
-       ret = reset_control_deassert(aio->chip->rst);
-       if (ret)
-               goto err_out_clock;
+               ret = reset_control_deassert(aio->chip->rst);
+               if (ret)
+                       goto err_out_clock;
+       }
 
        aio_iecout_set_enable(aio->chip, true);
        aio_chip_init(aio->chip);
@@ -458,7 +463,7 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
 
                ret = aio_init(sub);
                if (ret)
-                       goto err_out_clock;
+                       goto err_out_reset;
 
                if (!sub->setting)
                        continue;
@@ -466,11 +471,16 @@ int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
                aio_port_reset(sub);
                aio_src_reset(sub);
        }
+       aio->chip->num_wup_aios++;
 
        return 0;
 
+err_out_reset:
+       if (!aio->chip->num_wup_aios)
+               reset_control_assert(aio->chip->rst);
 err_out_clock:
-       clk_disable_unprepare(aio->chip->clk);
+       if (!aio->chip->num_wup_aios)
+               clk_disable_unprepare(aio->chip->clk);
 
        return ret;
 }
@@ -619,6 +629,7 @@ int uniphier_aio_probe(struct platform_device *pdev)
                return PTR_ERR(chip->rst);
 
        chip->num_aios = chip->chip_spec->num_dais;
+       chip->num_wup_aios = chip->num_aios;
        chip->aios = devm_kcalloc(dev,
                                  chip->num_aios, sizeof(struct uniphier_aio),
                                  GFP_KERNEL);
index ca6ccba..a7ff7e5 100644 (file)
@@ -285,6 +285,7 @@ struct uniphier_aio_chip {
 
        struct uniphier_aio *aios;
        int num_aios;
+       int num_wup_aios;
        struct uniphier_aio_pll *plls;
        int num_plls;