+static struct rk3036_reg_val_typ codec_close_list_p[] = {
+ /*S1*/{RK3036_CODEC_REG24,
+ RK3036_CR24_DAC_SOURCE_WORK
+ |RK3036_CR24_DAC_PRECHARGE
+ |RK3036_CR24_DACL_REFV_WORK
+ |RK3036_CR24_DACR_REFV_WORK
+ |RK3036_CR24_VOUTL_ZEROD_STOP
+ |RK3036_CR24_VOUTR_ZEROD_STOP},
+
+ /*S2*/{RK3036_CODEC_REG25, 0x00},
+ /*S2*/{RK3036_CODEC_REG26, 0x00},
+
+ /*S3*/{RK3036_CODEC_REG27,
+ RK3036_CR27_DACL_WORK
+ |RK3036_CR27_DACR_WORK
+ |RK3036_CR27_HPOUTL_G_MUTE
+ |RK3036_CR27_HPOUTR_G_MUTE
+ |RK3036_CR27_HPOUTL_POP_WORK
+ |RK3036_CR27_HPOUTR_POP_WORK},
+
+ /*S4*/{RK3036_CODEC_REG23,
+ RK3036_CR23_HPOUTL_WORK
+ |RK3036_CR23_HPOUTR_WORK
+ |RK3036_CR23_HPOUTL_EN_STOP
+ |RK3036_CR23_HPOUTR_EN_STOP},
+
+ /*S5*/{RK3036_CODEC_REG23,
+ RK3036_CR23_HPOUTL_INIT
+ |RK3036_CR23_HPOUTR_INIT
+ |RK3036_CR23_HPOUTL_EN_STOP
+ |RK3036_CR23_HPOUTR_EN_STOP},
+
+ /*S6*/{RK3036_CODEC_REG27,
+ RK3036_CR27_DACL_WORK
+ |RK3036_CR27_DACR_WORK
+ |RK3036_CR27_HPOUTL_G_MUTE
+ |RK3036_CR27_HPOUTR_G_MUTE
+ |RK3036_CR27_HPOUTL_POP_PRECHARGE
+ |RK3036_CR27_HPOUTR_POP_PRECHARGE},
+
+ /*S7*/{RK3036_CODEC_REG22,
+ RK3036_CR22_DACL_PATH_REFV_STOP
+ |RK3036_CR22_DACR_PATH_REFV_STOP
+ |RK3036_CR22_DACL_CLK_STOP
+ |RK3036_CR22_DACR_CLK_STOP
+ |RK3036_CR22_DACL_STOP
+ |RK3036_CR22_DACR_STOP},
+
+ /*S8*/{RK3036_CODEC_REG24,
+ RK3036_CR24_DAC_SOURCE_STOP
+ |RK3036_CR24_DAC_PRECHARGE
+ |RK3036_CR24_DACL_REFV_STOP
+ |RK3036_CR24_DACR_REFV_STOP
+ |RK3036_CR24_VOUTL_ZEROD_STOP
+ |RK3036_CR24_VOUTR_ZEROD_STOP},
+
+ /*S9*/{RK3036_CODEC_REG27,
+ RK3036_CR27_DACL_INIT
+ |RK3036_CR27_DACR_INIT
+ |RK3036_CR27_HPOUTL_G_MUTE
+ |RK3036_CR27_HPOUTR_G_MUTE
+ |RK3036_CR27_HPOUTL_POP_PRECHARGE
+ |RK3036_CR27_HPOUTR_POP_PRECHARGE},
+
+};
+#define CLOSE_LIST_LEN_P ARRAY_SIZE(codec_close_list_p)
+
+static int rk3036_codec_close_p(void)
+{
+ struct snd_soc_codec *codec = rk3036_priv->codec;
+ int i, volume = 0;
+
+ if (!rk3036_priv || !rk3036_priv->codec)
+ return -EINVAL;
+
+ for (i = 0; i < CLOSE_LIST_LEN_P; i++) {
+ if ((codec_close_list_p[i].reg ==
+ RK3036_CODEC_REG25) && (volume > 0)) {
+ snd_soc_write(codec, RK3036_CODEC_REG25, volume);
+ snd_soc_write(codec, RK3036_CODEC_REG26, volume);
+ volume++;
+ mdelay(10);
+ i--;
+ } else {
+ snd_soc_write(codec, codec_close_list_p[i].reg, codec_close_list_p[i].value);
+ mdelay(1);
+ }
+ }
+
+ return 0;
+}
+
+static int rk3036_codec_power_off(int wait_ms)
+{
+ struct snd_soc_codec *codec = rk3036_priv->codec;
+
+ if (!rk3036_priv || !rk3036_priv->codec)
+ return -EINVAL;
+
+ /* set a big current for capacitor discharge. */
+ snd_soc_write(codec, RK3036_CODEC_REG28, RK3036_CR28_YES_027I
+ |RK3036_CR28_YES_050I
+ |RK3036_CR28_YES_100I
+ |RK3036_CR28_YES_130I
+ |RK3036_CR28_YES_260I
+ |RK3036_CR28_YES_400I);
+
+ /* start discharge. */
+ snd_soc_write(codec, RK3036_CODEC_REG24, RK3036_CR24_DAC_SOURCE_STOP
+ |RK3036_CR24_DAC_DISCHARGE
+ |RK3036_CR24_DACL_REFV_STOP
+ |RK3036_CR24_DACR_REFV_STOP
+ |RK3036_CR24_VOUTL_ZEROD_STOP
+ |RK3036_CR24_VOUTR_ZEROD_STOP);
+
+ /* wait for capacitor discharge finish. */
+ mdelay(wait_ms);
+
+ return 0;
+}
+