ASoC: twl6040: Update twl IO macro
[deliverable/linux.git] / sound / soc / codecs / twl6040.c
index 0dd2d539726408c8e498795bfe8aa489731b196f..d33d2b4769f3b1ec02c281d7f67ca9011c34c26a 100644 (file)
@@ -34,7 +34,6 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
 #define TWL6040_RATES   (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 #define TWL6040_FORMATS         (SNDRV_PCM_FMTBIT_S32_LE)
 
+struct twl6040_jack_data {
+       struct snd_soc_jack *jack;
+       int report;
+};
+
 /* codec private data */
 struct twl6040_data {
        int audpwron;
@@ -53,6 +57,11 @@ struct twl6040_data {
        unsigned int sysclk;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
        struct completion ready;
+       struct twl6040_jack_data hs_jack;
+       struct snd_soc_codec *codec;
+       struct workqueue_struct *workqueue;
+       struct delayed_work delayed_work;
+       struct mutex mutex;
 };
 
 /*
@@ -201,7 +210,7 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg);
+       twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
        twl6040_write_reg_cache(codec, reg, value);
 
        return value;
@@ -217,7 +226,7 @@ static int twl6040_write(struct snd_soc_codec *codec,
                return -EIO;
 
        twl6040_write_reg_cache(codec, reg, value);
-       return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
+       return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
 }
 
 static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
@@ -382,6 +391,47 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+void twl6040_hs_jack_report(struct snd_soc_codec *codec,
+                               struct snd_soc_jack *jack, int report)
+{
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+       int status;
+
+       mutex_lock(&priv->mutex);
+
+       /* Sync status */
+       status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
+       if (status & TWL6040_PLUGCOMP)
+               snd_soc_jack_report(jack, report, report);
+       else
+               snd_soc_jack_report(jack, 0, report);
+
+       mutex_unlock(&priv->mutex);
+}
+
+void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
+                               struct snd_soc_jack *jack, int report)
+{
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+       struct twl6040_jack_data *hs_jack = &priv->hs_jack;
+
+       hs_jack->jack = jack;
+       hs_jack->report = report;
+
+       twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
+}
+EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
+
+static void twl6040_accessory_work(struct work_struct *work)
+{
+       struct twl6040_data *priv = container_of(work,
+                                       struct twl6040_data, delayed_work.work);
+       struct snd_soc_codec *codec = priv->codec;
+       struct twl6040_jack_data *hs_jack = &priv->hs_jack;
+
+       twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
+}
+
 /* audio interrupt handler */
 static irqreturn_t twl6040_naudint_handler(int irq, void *data)
 {
@@ -389,7 +439,7 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        u8 intid;
 
-       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
+       twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
 
        switch (intid) {
        case TWL6040_THINT:
@@ -397,6 +447,9 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
                break;
        case TWL6040_PLUGINT:
        case TWL6040_UNPLUGINT:
+               queue_delayed_work(priv->workqueue, &priv->delayed_work,
+                                                       msecs_to_jiffies(200));
+               break;
        case TWL6040_HOOKINT:
                break;
        case TWL6040_HFINT:
@@ -662,7 +715,7 @@ static int twl6040_power_up_completion(struct snd_soc_codec *codec,
                                msecs_to_jiffies(48));
 
        if (!time_left) {
-               twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid,
+               twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
                                                        TWL6040_REG_INTID);
                if (!(intid & TWL6040_READYINT)) {
                        dev_err(codec->dev, "timeout waiting for READYINT\n");
@@ -1024,6 +1077,8 @@ static int twl6040_probe(struct snd_soc_codec *codec)
                return -ENOMEM;
        snd_soc_codec_set_drvdata(codec, priv);
 
+       priv->codec = codec;
+
        if (twl_codec) {
                audpwron = twl_codec->audpwron_gpio;
                naudint = twl_codec->naudint_irq;
@@ -1034,6 +1089,14 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
        priv->audpwron = audpwron;
        priv->naudint = naudint;
+       priv->workqueue = create_singlethread_workqueue("twl6040-codec");
+
+       if (!priv->workqueue)
+               goto work_err;
+
+       INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
+
+       mutex_init(&priv->mutex);
 
        init_completion(&priv->ready);
 
@@ -1090,6 +1153,8 @@ gpio2_err:
        if (gpio_is_valid(audpwron))
                gpio_free(audpwron);
 gpio1_err:
+       destroy_workqueue(priv->workqueue);
+work_err:
        kfree(priv);
        return ret;
 }
@@ -1108,6 +1173,7 @@ static int twl6040_remove(struct snd_soc_codec *codec)
        if (naudint)
                free_irq(naudint, codec);
 
+       destroy_workqueue(priv->workqueue);
        kfree(priv);
 
        return 0;
This page took 0.032015 seconds and 5 git commands to generate.