Merge remote-tracking branch 'asoc/topic/arizona' into asoc-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 9 Dec 2012 15:22:00 +0000 (00:22 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 9 Dec 2012 15:22:00 +0000 (00:22 +0900)
12 files changed:
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/arizona-haptics.c [new file with mode: 0644]
drivers/mfd/arizona-core.c
include/linux/mfd/arizona/core.h
include/linux/mfd/arizona/pdata.h
sound/soc/codecs/Kconfig
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm_adsp.c

index 7c0f1ecfdd7a3ff88fed02671e1cf0fba5847b24..104a7c3153c0c4ce5fd695403bfb8a263da992d7 100644 (file)
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
          To compile this driver as a module, choose M here: the
          module will be called ad714x-spi.
 
+config INPUT_ARIZONA_HAPTICS
+       tristate "Arizona haptics support"
+       depends on MFD_ARIZONA && SND_SOC
+       select INPUT_FF_MEMLESS
+       help
+         Say Y to enable support for the haptics module in Arizona CODECs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called arizona-haptics.
+
 config INPUT_BMA150
        tristate "BMA150/SMB380 acceleration sensor support"
        depends on I2C
index 83fe6f5b77d120e9b3194325f0fc83879a474a0a..5ea769eda999ff1fa35954bdc6bf467c22ebbf99 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X)           += adxl34x.o
 obj-$(CONFIG_INPUT_ADXL34X_I2C)                += adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)                += adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)             += apanel.o
+obj-$(CONFIG_INPUT_ARIZONA_HAPTICS)    += arizona-haptics.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)                += ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)         += atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)                += bfin_rotary.o
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
new file mode 100644 (file)
index 0000000..7a04f54
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Arizona haptics driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_haptics {
+       struct arizona *arizona;
+       struct input_dev *input_dev;
+       struct work_struct work;
+
+       struct mutex mutex;
+       u8 intensity;
+};
+
+static void arizona_haptics_work(struct work_struct *work)
+{
+       struct arizona_haptics *haptics = container_of(work,
+                                                      struct arizona_haptics,
+                                                      work);
+       struct arizona *arizona = haptics->arizona;
+       struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
+       int ret;
+
+       if (!haptics->arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return;
+       }
+
+       if (haptics->intensity) {
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_PHASE_2_INTENSITY,
+                                        ARIZONA_PHASE2_INTENSITY_MASK,
+                                        haptics->intensity);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to set intensity: %d\n",
+                               ret);
+                       return;
+               }
+
+               /* This enable sequence will be a noop if already enabled */
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start haptics: %d\n",
+                               ret);
+                       return;
+               }
+
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+       } else {
+               /* This disable sequence will be a noop if already enabled */
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to stop haptics: %d\n",
+                               ret);
+                       return;
+               }
+       }
+}
+
+static int arizona_haptics_play(struct input_dev *input, void *data,
+                               struct ff_effect *effect)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct arizona *arizona = haptics->arizona;
+
+       if (!arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return -EBUSY;
+       }
+
+       if (effect->u.rumble.strong_magnitude) {
+               /* Scale the magnitude into the range the device supports */
+               if (arizona->pdata.hap_act) {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 9;
+                       if (effect->direction < 0x8000)
+                               haptics->intensity += 0x7f;
+               } else {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 8;
+               }
+       } else {
+               haptics->intensity = 0;
+       }
+
+       schedule_work(&haptics->work);
+
+       return 0;
+}
+
+static void arizona_haptics_close(struct input_dev *input)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
+
+       cancel_work_sync(&haptics->work);
+
+       mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       if (haptics->arizona->dapm)
+               snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+
+       mutex_unlock(dapm_mutex);
+}
+
+static int arizona_haptics_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct arizona_haptics *haptics;
+       int ret;
+
+       haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+       if (!haptics)
+               return -ENOMEM;
+
+       haptics->arizona = arizona;
+
+       ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
+                                ARIZONA_HAP_ACT, arizona->pdata.hap_act);
+       if (ret != 0) {
+               dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
+                       ret);
+               return ret;
+       }
+
+       INIT_WORK(&haptics->work, arizona_haptics_work);
+
+       haptics->input_dev = input_allocate_device();
+       if (haptics->input_dev == NULL) {
+               dev_err(arizona->dev, "Failed to allocate input device\n");
+               return -ENOMEM;
+       }
+
+       input_set_drvdata(haptics->input_dev, haptics);
+
+       haptics->input_dev->name = "arizona:haptics";
+       haptics->input_dev->dev.parent = pdev->dev.parent;
+       haptics->input_dev->close = arizona_haptics_close;
+       __set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
+
+       ret = input_ff_create_memless(haptics->input_dev, NULL,
+                                     arizona_haptics_play);
+       if (ret < 0) {
+               dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+                       ret);
+               goto err_ialloc;
+       }
+
+       ret = input_register_device(haptics->input_dev);
+       if (ret < 0) {
+               dev_err(arizona->dev, "couldn't register input device: %d\n",
+                       ret);
+               goto err_iff;
+       }
+
+       platform_set_drvdata(pdev, haptics);
+
+       return 0;
+
+err_iff:
+       if (haptics->input_dev)
+               input_ff_destroy(haptics->input_dev);
+err_ialloc:
+       input_free_device(haptics->input_dev);
+
+       return ret;
+}
+
+static int arizona_haptics_remove(struct platform_device *pdev)
+{
+       struct arizona_haptics *haptics = platform_get_drvdata(pdev);
+
+       input_unregister_device(haptics->input_dev);
+
+       return 0;
+}
+
+static struct platform_driver arizona_haptics_driver = {
+       .probe          = arizona_haptics_probe,
+       .remove         = arizona_haptics_remove,
+       .driver         = {
+               .name   = "arizona-haptics",
+               .owner  = THIS_MODULE,
+       },
+};
+module_platform_driver(arizona_haptics_driver);
+
+MODULE_ALIAS("platform:arizona-haptics");
+MODULE_DESCRIPTION("Arizona haptics driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 1b48f2094806c75fa8914657978f1b7bf814ae93..75619711a9e7904000f89b30769a084b4094a27a 100644 (file)
@@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
 static struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5102-codec" },
@@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = {
 static struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5110-codec" },
index dd231ac0bb1fd8ac678d475404bc95ebaa104cec..a580363a7d29723e6656cbed8d9d94b4b1801bea 100644 (file)
@@ -78,6 +78,8 @@ enum arizona_type {
 
 #define ARIZONA_NUM_IRQ                   50
 
+struct snd_soc_dapm_context;
+
 struct arizona {
        struct regmap *regmap;
        struct device *dev;
@@ -98,6 +100,8 @@ struct arizona {
 
        struct mutex clk_lock;
        int clk32k_ref;
+
+       struct snd_soc_dapm_context *dapm;
 };
 
 int arizona_clk32k_enable(struct arizona *arizona);
index 7ab442905a57b209b10c042cf141ac2b2ba2275e..8b1d1daaae16c27e59d037f46899a1f6c631acc4 100644 (file)
@@ -62,6 +62,9 @@
 
 #define ARIZONA_MAX_OUTPUT 6
 
+#define ARIZONA_HAP_ACT_ERM 0
+#define ARIZONA_HAP_ACT_LRA 2
+
 #define ARIZONA_MAX_PDM_SPK 2
 
 struct regulator_init_data;
@@ -114,6 +117,9 @@ struct arizona_pdata {
 
        /** PDM speaker format */
        unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
+
+       /** Haptic actuator type */
+       unsigned int hap_act;
 };
 
 #endif
index f866e18e7876849d5f86d393db28ba2d2d19553e..80799639814e1f668a63ea0b871f38474a1a69ef 100644 (file)
@@ -148,7 +148,9 @@ config SND_SOC_WM_HUBS
 
 config SND_SOC_WM_ADSP
        tristate
+       default y if SND_SOC_WM5102=y
        default y if SND_SOC_WM2200=y
+       default m if SND_SOC_WM5102=m
        default m if SND_SOC_WM2200=m
 
 config SND_SOC_AB8500_CODEC
index 054967d8bac2f6d089214e390b1bd6ce416f64b2..adf397b9d0e650eb19768e7bc6c592352014a595 100644 (file)
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
 
+static const char *arizona_vol_ramp_text[] = {
+       "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+       "15ms/6dB", "30ms/6dB",
+};
+
+const struct soc_enum arizona_in_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
+
+const struct soc_enum arizona_in_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
+
+const struct soc_enum arizona_out_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
+
+const struct soc_enum arizona_out_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
+
 static const char *arizona_lhpf_mode_text[] = {
        "Low-pass", "High-pass"
 };
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
        case 49152000:
                val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
                break;
+       case 67737600:
+       case 73728000:
+               val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 90316800:
+       case 98304000:
+               val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 135475200:
+       case 147456000:
+               val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
        default:
                return -EINVAL;
        }
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
                return -EBUSY;
        }
 
+       dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
+               arizona_dai_clk_str(clk_id));
+
        memset(&routes, 0, sizeof(routes));
        routes[0].sink = dai->driver->capture.stream_name;
        routes[1].sink = dai->driver->playback.stream_name;
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
        routes[1].source = arizona_dai_clk_str(clk_id);
        snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
 
+       dai_priv->clk = clk_id;
+
        return snd_soc_dapm_sync(&codec->dapm);
 }
 
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
        bool ena;
        int ret;
 
+       if (fll->fref == Fref && fll->fout == Fout)
+               return 0;
+
        ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
        if (ret != 0) {
                arizona_fll_err(fll, "Failed to read current state: %d\n",
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                if (ena)
                        pm_runtime_put_autosuspend(arizona->dev);
 
+               fll->fref = Fref;
+               fll->fout = Fout;
+
                return 0;
        }
 
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                                   ARIZONA_FLL1_SYNC_ENA);
 
        ret = wait_for_completion_timeout(&fll->ok,
-                                         msecs_to_jiffies(25));
+                                         msecs_to_jiffies(250));
        if (ret == 0)
                arizona_fll_warn(fll, "Timed out waiting for lock\n");
 
+       fll->fref = Fref;
+       fll->fout = Fout;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
index 36ec64946120077455ab218c85aef34eaa29ef9a..41dae1ed3b714a4734448b1d3c99938af1fe9d9a 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <sound/soc.h>
 
+#include "wm_adsp.h"
+
 #define ARIZONA_CLK_SYSCLK         1
 #define ARIZONA_CLK_ASYNCCLK       2
 #define ARIZONA_CLK_OPCLK          3
 #define ARIZONA_MIXER_VOL_SHIFT                 1
 #define ARIZONA_MIXER_VOL_WIDTH                 7
 
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI  4
+#define ARIZONA_MAX_ADSP 4
 
 struct arizona;
+struct wm_adsp;
 
 struct arizona_dai_priv {
        int clk;
 };
 
 struct arizona_priv {
+       struct wm_adsp adsp[ARIZONA_MAX_ADSP];
        struct arizona *arizona;
        int sysclk;
        int asyncclk;
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        const struct snd_kcontrol_new name##_mux =      \
                SOC_DAPM_VALUE_ENUM("Route", name##_enum)
 
+#define ARIZONA_MUX_ENUMS(name, base_reg) \
+       static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg);      \
+       static ARIZONA_MUX_CTL_DECL(name)
+
 #define ARIZONA_MIXER_ENUMS(name, base_reg) \
-       static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
-       static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
-       static ARIZONA_MUX_CTL_DECL(name##_in1); \
-       static ARIZONA_MUX_CTL_DECL(name##_in2); \
-       static ARIZONA_MUX_CTL_DECL(name##_in3); \
-       static ARIZONA_MUX_CTL_DECL(name##_in4)
+       ARIZONA_MUX_ENUMS(name##_in1, base_reg);     \
+       ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
+       ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
+       ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
+
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+       ARIZONA_MUX_ENUMS(name##_aux1, base_reg);       \
+       ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8);   \
+       ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16);  \
+       ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24);  \
+       ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32);  \
+       ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
 
 #define ARIZONA_MUX(name, ctrl) \
        SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
+#define ARIZONA_MUX_WIDGETS(name, name_str) \
+       ARIZONA_MUX(name_str " Input", &name##_mux)
+
 #define ARIZONA_MIXER_WIDGETS(name, name_str)  \
        ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
        ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+       ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+       ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+       ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
+#define ARIZONA_MUX_ROUTES(name) \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Input")
+
 #define ARIZONA_MIXER_ROUTES(widget, name) \
        { widget, NULL, name " Mixer" },         \
        { name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define ARIZONA_DSP_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+       ARIZONA_MIXER_ROUTES(name, name "L"), \
+       ARIZONA_MIXER_ROUTES(name, name "R")
+
+extern const struct soc_enum arizona_in_vi_ramp;
+extern const struct soc_enum arizona_in_vd_ramp;
+
+extern const struct soc_enum arizona_out_vi_ramp;
+extern const struct soc_enum arizona_out_vd_ramp;
+
 extern const struct soc_enum arizona_lhpf1_mode;
 extern const struct soc_enum arizona_lhpf2_mode;
 extern const struct soc_enum arizona_lhpf3_mode;
@@ -146,6 +197,8 @@ struct arizona_fll {
        unsigned int vco_mult;
        struct completion lock;
        struct completion ok;
+       unsigned int fref;
+       unsigned int fout;
 
        char lock_name[ARIZONA_FLL_NAME_LEN];
        char clock_ok_name[ARIZONA_FLL_NAME_LEN];
index 7394e73fa43c0e526e7ab4e83480fb89bbf9891d..27f7e38e7ecac3984a2a454ff7f6bf5a4593a622 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "arizona.h"
 #include "wm5102.h"
+#include "wm_adsp.h"
 
 struct wm5102_priv {
        struct arizona_priv core;
@@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct wm_adsp_region wm5102_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
 static const struct reg_default wm5102_sysclk_reva_patch[] = {
        { 0x3000, 0x2225 },
        { 0x3001, 0x3a03 },
@@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
                 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -687,6 +707,14 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
+ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
 SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
           ARIZONA_OUT5_OSR_SHIFT, 1, 0),
 
@@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
                 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                    ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
 
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
 
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
 
 static const char *wm5102_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
                 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
                    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
 
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
 
@@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+WM_ADSP2("DSP1", 0),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }
 
 static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "IN3L PGA", NULL, "IN3L" },
        { "IN3R PGA", NULL, "IN3R" },
 
+       { "ASRC1L", NULL, "ASRC1L Input" },
+       { "ASRC1R", NULL, "ASRC1R Input" },
+       { "ASRC2L", NULL, "ASRC2L Input" },
+       { "ASRC2R", NULL, "ASRC2R Input" },
+
        ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
        ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
        ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
+
+       ARIZONA_DSP_ROUTES("DSP1"),
 
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
@@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 static int wm5102_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5102_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5102_DIG_VU 0x0200
@@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
        .probe = wm5102_codec_probe,
+       .remove = wm5102_codec_remove,
 
        .idle_bias_off = true,
 
@@ -1424,7 +1479,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5102_priv *wm5102;
-       int i;
+       int i, ret;
 
        wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
                              GFP_KERNEL);
@@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 
        wm5102->core.arizona = arizona;
 
+       wm5102->core.adsp[0].part = "wm5102";
+       wm5102->core.adsp[0].num = 1;
+       wm5102->core.adsp[0].type = WMFW_ADSP2;
+       wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+       wm5102->core.adsp[0].dev = arizona->dev;
+       wm5102->core.adsp[0].regmap = arizona->regmap;
+       wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+       wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
+       ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+       if (ret != 0)
+               return ret;
+
        for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
                wm5102->fll[i].vco_mult = 1;
 
index 9211e4192f710b305ca46420e0be64037a0f6967..c57dc7468300b7d8082dae3fcf266a12d20922a8 100644 (file)
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
                 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -148,6 +160,11 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
           ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
 
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
 static const char *wm5110_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
 
        { "HPOUT1L", NULL, "OUT1L" },
        { "HPOUT1R", NULL, "OUT1R" },
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 static int wm5110_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       priv->core.arizona->dapm = &codec->dapm;
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5110_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5110_DIG_VU 0x0200
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
        .probe = wm5110_codec_probe,
+       .remove = wm5110_codec_remove,
 
        .idle_bias_off = true,
 
index 7fdb68ef384e04729f514d4eb3d7c3b2c9077c98..ffc89fab96fbf4b6ccc81973f69df863132da1ec 100644 (file)
@@ -544,6 +544,28 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
+               /*
+                * For simplicity set the DSP clock rate to be the
+                * SYSCLK rate rather than making it configurable.
+                */
+               ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+                                ret);
+                       return ret;
+               }
+               val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+                       >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CLOCKING,
+                                        ADSP2_CLK_SEL_MASK, val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to set clock rate: %d\n",
+                                ret);
+                       return ret;
+               }
+
                if (dsp->dvfs) {
                        ret = regmap_read(dsp->regmap,
                                          dsp->base + ADSP2_CLOCKING, &val);
@@ -631,6 +653,17 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
 {
        int ret;
 
+       /*
+        * Disable the DSP memory by default when in reset for a small
+        * power saving.
+        */
+       ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
+                                ADSP2_MEM_ENA, 0);
+       if (ret != 0) {
+               adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
+               return ret;
+       }
+
        if (dvfs) {
                adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
                if (IS_ERR(adsp->dvfs)) {
This page took 0.04062 seconds and 5 git commands to generate.