*/
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
        struct mutex lock;
        const struct ak4613_interface *iface;
        struct snd_pcm_hw_constraint_list constraint;
+       struct work_struct dummy_write_work;
+       struct snd_soc_component *component;
+       unsigned int rate;
        unsigned int sysclk;
 
        unsigned int fmt;
        default:
                return -EINVAL;
        }
+       priv->rate = rate;
 
        /*
         * FIXME
        return 0;
 }
 
+static void ak4613_dummy_write(struct work_struct *work)
+{
+       struct ak4613_priv *priv = container_of(work,
+                                               struct ak4613_priv,
+                                               dummy_write_work);
+       struct snd_soc_component *component = priv->component;
+       unsigned int mgmt1;
+       unsigned int mgmt3;
+
+       /*
+        * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks
+        *
+        * Note
+        *
+        * To avoid extra delay, we want to avoid preemption here,
+        * but we can't. Because it uses I2C access which is using IRQ
+        * and sleep. Thus, delay might be more than 5 LR clocks
+        * see also
+        *      ak4613_dai_trigger()
+        */
+       udelay(5000000 / priv->rate);
+
+       snd_soc_component_read(component, PW_MGMT1, &mgmt1);
+       snd_soc_component_read(component, PW_MGMT3, &mgmt3);
+
+       snd_soc_component_write(component, PW_MGMT1, mgmt1);
+       snd_soc_component_write(component, PW_MGMT3, mgmt3);
+}
+
+static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+                             struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       /*
+        * FIXME
+        *
+        * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks
+        * from Power Down Release. Otherwise, Playback volume will be 0dB.
+        * To avoid complex multiple delay/dummy_write method from
+        * ak4613_set_bias_level() / SND_SOC_DAPM_DAC_E("DACx", ...),
+        * call it once here.
+        *
+        * But, unfortunately, we can't "write" here because here is atomic
+        * context (It uses I2C access for writing).
+        * Thus, use schedule_work() to switching to normal context
+        * immediately.
+        *
+        * Note
+        *
+        * Calling ak4613_dummy_write() function might be delayed.
+        * In such case, ak4613 volume might be temporarily 0dB when
+        * beggining of playback.
+        * see also
+        *      ak4613_dummy_write()
+        */
+
+       if ((cmd != SNDRV_PCM_TRIGGER_START) &&
+           (cmd != SNDRV_PCM_TRIGGER_RESUME))
+               return 0;
+
+       if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+               return  0;
+
+       priv->component = &codec->component;
+       schedule_work(&priv->dummy_write_work);
+
+       return 0;
+}
+
 static const struct snd_soc_dai_ops ak4613_dai_ops = {
        .startup        = ak4613_dai_startup,
        .shutdown       = ak4613_dai_shutdown,
        .set_sysclk     = ak4613_dai_set_sysclk,
        .set_fmt        = ak4613_dai_set_fmt,
+       .trigger        = ak4613_dai_trigger,
        .hw_params      = ak4613_dai_hw_params,
 };
 
        priv->iface             = NULL;
        priv->cnt               = 0;
        priv->sysclk            = 0;
+       INIT_WORK(&priv->dummy_write_work, ak4613_dummy_write);
 
        mutex_init(&priv->lock);