Advertisement
Guest User

nvidia>grouper-3.1diff

a guest
Nov 1st, 2015
368
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 156.40 KB | None | 0 0
  1. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
  2. index 7d5a661..4b94603 100644
  3. --- a/sound/soc/codecs/Kconfig
  4. +++ b/sound/soc/codecs/Kconfig
  5. @@ -41,6 +41,7 @@ config SND_SOC_ALL_CODECS
  6.     select SND_SOC_PCM3008
  7.     select SND_SOC_RT5639 if I2C
  8.     select SND_SOC_RT5640 if I2C
  9. +   select SND_SOC_RT5642 if I2C
  10.     select SND_SOC_SGTL5000 if I2C
  11.     select SND_SOC_SN95031 if INTEL_SCU_IPC
  12.     select SND_SOC_SPDIF
  13. @@ -223,6 +224,8 @@ config SND_SOC_RT5639
  14.  config SND_SOC_RT5640
  15.     tristate
  16.  
  17. +config SND_SOC_RT5642
  18. +   tristate
  19.  #Freescale sgtl5000 codec
  20.  config SND_SOC_SGTL5000
  21.     tristate
  22. diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
  23. index 2eaef5b..8eb8bfe 100644
  24. --- a/sound/soc/codecs/Makefile
  25. +++ b/sound/soc/codecs/Makefile
  26. @@ -90,6 +90,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
  27.  snd-soc-jz4740-codec-objs := jz4740.o
  28.  snd-soc-rt5639-objs := rt5639.o
  29.  snd-soc-rt5640-objs := rt5640.o
  30. +snd-soc-rt5640-dsp-objs := rt5640-dsp.o
  31.  
  32.  # Amp
  33.  snd-soc-lm4857-objs := lm4857.o
  34. @@ -189,6 +190,7 @@ obj-$(CONFIG_SND_SOC_WM9713)    += snd-soc-wm9713.o
  35.  obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
  36.  obj-$(CONFIG_SND_SOC_RT5639)   += snd-soc-rt5639.o
  37.  obj-$(CONFIG_SND_SOC_RT5640)   += snd-soc-rt5640.o
  38. +obj-$(CONFIG_SND_SOC_RT5642)   += snd-soc-rt5640-dsp.o
  39.  
  40.  # Amp
  41.  obj-$(CONFIG_SND_SOC_LM4857)   += snd-soc-lm4857.o
  42. diff --git a/sound/soc/codecs/rt5639.c b/sound/soc/codecs/rt5639.c
  43. index 139503e..06c8451 100644
  44. --- a/sound/soc/codecs/rt5639.c
  45. +++ b/sound/soc/codecs/rt5639.c
  46. @@ -2239,6 +2239,8 @@ static int rt5639_probe(struct snd_soc_codec *codec)
  47.     struct rt5639_priv *rt5639 = snd_soc_codec_get_drvdata(codec);
  48.     int ret;
  49.  
  50. +   codec->dapm.idle_bias_off = 1;
  51. +
  52.     ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
  53.     if (ret != 0) {
  54.         dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
  55. diff --git a/sound/soc/codecs/rt5640-dsp.c b/sound/soc/codecs/rt5640-dsp.c
  56. new file mode 100644
  57. index 0000000..e00fec5
  58. --- /dev/null
  59. +++ b/sound/soc/codecs/rt5640-dsp.c
  60. @@ -0,0 +1,1359 @@
  61. +/*
  62. + * rt5640.c  --  RT5640 ALSA SoC DSP driver
  63. + *
  64. + * Copyright 2011 Realtek Semiconductor Corp.
  65. + * Author: Johnny Hsu <johnnyhsu@realtek.com>
  66. + *
  67. + * This program is free software; you can redistribute it and/or modify
  68. + * it under the terms of the GNU General Public License version 2 as
  69. + * published by the Free Software Foundation.
  70. + */
  71. +
  72. +#include <linux/delay.h>
  73. +#include <linux/i2c.h>
  74. +#include <linux/platform_device.h>
  75. +#include <sound/soc.h>
  76. +#include <sound/soc-dapm.h>
  77. +
  78. +#define RTK_IOCTL
  79. +#ifdef RTK_IOCTL
  80. +#include <linux/spi/spi.h> //kmalloc kfree
  81. +
  82. +#include "rt56xx_ioctl.h"
  83. +#define DBG 1
  84. +#endif
  85. +
  86. +#include "rt5640.h"
  87. +#include "rt5640-dsp.h"
  88. +
  89. +
  90. +static const u16 rt5640_dsp_init[][2] = {
  91. +   {0x3fd2, 0x0038}, {0x229C, 0x0fa0}, {0x22d2, 0x8400}, {0x22ee, 0x0001},
  92. +   {0x22f2, 0x0040}, {0x22f5, 0x8000}, {0x22f6, 0x0000}, {0x22f9, 0x007f},
  93. +   {0x2310, 0x0880},
  94. +};
  95. +#define RT5640_DSP_INIT_NUM \
  96. +   (sizeof(rt5640_dsp_init) / sizeof(rt5640_dsp_init[0]))
  97. +
  98. +static const u16 rt5640_dsp_48[][2] = {
  99. +   {0x22c8, 0x0026}, {0x22fe, 0x0fa0}, {0x22ff, 0x3893}, {0x22fa, 0x2487},
  100. +   {0x2301, 0x0002},
  101. +};
  102. +#define RT5640_DSP_48_NUM (sizeof(rt5640_dsp_48) / sizeof(rt5640_dsp_48[0]))
  103. +
  104. +static const u16 rt5640_dsp_441[][2] = {
  105. +   {0x22c6, 0x0031}, {0x22c7, 0x0050}, {0x22c8, 0x0009}, {0x22fe, 0x0e5b},
  106. +   {0x22ff, 0x3c83}, {0x22fa, 0x2484}, {0x2301, 0x0001},
  107. +};
  108. +#define RT5640_DSP_441_NUM (sizeof(rt5640_dsp_441) / sizeof(rt5640_dsp_441[0]))
  109. +
  110. +static const u16 rt5640_dsp_16[][2] = {
  111. +   {0x22c8, 0x0026}, {0x22fa, 0x2484}, {0x2301, 0x0002},
  112. +};
  113. +#define RT5640_DSP_16_NUM (sizeof(rt5640_dsp_16) / sizeof(rt5640_dsp_16[0]))
  114. +
  115. +static const u16 rt5640_dsp_aec_ns_fens[][2] = {
  116. +   {0x22f8, 0x8005}, {0x2303, 0x0971}, {0x2304, 0x0312}, {0x2305, 0x0005},
  117. +   {0x2309, 0x0400}, {0x230a, 0x1b00}, {0x230c, 0x0200}, {0x230d, 0x0400},
  118. +   {0x2310, 0x0824}, {0x2325, 0x5000}, {0x2326, 0x0040}, {0x232f, 0x0080},
  119. +   {0x2332, 0x0080}, {0x2333, 0x0008}, {0x2337, 0x0002}, {0x2339, 0x0010},
  120. +   {0x2348, 0x1000}, {0x2349, 0x1000}, {0x2360, 0x0180}, {0x2361, 0x1800},
  121. +   {0x2362, 0x0180}, {0x2363, 0x0100}, {0x2364, 0x0078}, {0x2365, 0x2000},
  122. +   {0x236e, 0x1800}, {0x236f, 0x0a0a}, {0x2370, 0x0f00}, {0x2372, 0x1a00},
  123. +   {0x2373, 0x3000}, {0x2374, 0x2400}, {0x2375, 0x1800}, {0x2380, 0x7fff},
  124. +   {0x2381, 0x4000}, {0x2382, 0x0400}, {0x2383, 0x0400}, {0x2384, 0x0005},
  125. +   {0x2385, 0x0005}, {0x238c, 0x0400}, {0x238e, 0x7000}, {0x2393, 0x4444},
  126. +   {0x2394, 0x4444}, {0x2395, 0x4444}, {0x2396, 0x2000}, {0x2396, 0x3000},
  127. +   {0x2398, 0x0020}, {0x23a5, 0x0006}, {0x23a6, 0x7fff}, {0x23b3, 0x000e},
  128. +   {0x23b4, 0x000a}, {0x23b7, 0x0008}, {0x23bb, 0x1000}, {0x23bc, 0x0130},
  129. +   {0x23bd, 0x0100}, {0x23be, 0x2400}, {0x23cf, 0x0800}, {0x23d0, 0x0400},
  130. +   {0x23d1, 0xff80}, {0x23d2, 0xff80}, {0x23d3, 0x0800}, {0x23d4, 0x3e00},
  131. +   {0x23d5, 0x5000}, {0x23e7, 0x0800}, {0x23e8, 0x0e00}, {0x23e9, 0x7000},
  132. +   {0x23ea, 0x7ff0}, {0x23ed, 0x0300}, {0x22fb, 0x0000},
  133. +};
  134. +#define RT5640_DSP_AEC_NUM \
  135. +   (sizeof(rt5640_dsp_aec_ns_fens) / sizeof(rt5640_dsp_aec_ns_fens[0]))
  136. +
  137. +static const u16 rt5640_dsp_hfbf[][2] = {
  138. +   {0x22f8, 0x8004}, {0x22a0, 0x1205}, {0x22a1, 0x0f00}, {0x22a2, 0x1000},
  139. +   {0x22a3, 0x1000}, {0x22a4, 0x1000}, {0x22aa, 0x0006}, {0x22ad, 0x0060},
  140. +   {0x22ae, 0x0080}, {0x22af, 0x0000}, {0x22b0, 0x000e}, {0x22b1, 0x0010},
  141. +   {0x22b2, 0x0006}, {0x22b3, 0x0001}, {0x22b4, 0x0010}, {0x22b5, 0x0001},
  142. +   {0x22b7, 0x0005}, {0x22d8, 0x0017}, {0x22f9, 0x007f}, {0x2303, 0x0971},
  143. +   {0x2304, 0x0302}, {0x2303, 0x0971}, {0x2304, 0x4302}, {0x2305, 0x102d},
  144. +   {0x2309, 0x0400}, {0x230c, 0x0400}, {0x230d, 0x0200}, {0x232f, 0x0020},
  145. +   {0x2332, 0x0100}, {0x2333, 0x0020}, {0x2337, 0xffff}, {0x2339, 0x0010},
  146. +   {0x2348, 0x1000}, {0x2349, 0x1000}, {0x236e, 0x1800}, {0x236f, 0x1006},
  147. +   {0x2370, 0x1000}, {0x2372, 0x0200}, {0x237b, 0x001e}, {0x2380, 0x7fff},
  148. +   {0x2381, 0x4000}, {0x2382, 0x0080}, {0x2383, 0x0200}, {0x2386, 0x7f80},
  149. +   {0x2387, 0x0040}, {0x238a, 0x0280}, {0x238c, 0x6000}, {0x238e, 0x5000},
  150. +   {0x2396, 0x6a00}, {0x2397, 0x6000}, {0x2398, 0x00e0}, {0x23a5, 0x0005},
  151. +   {0x23b3, 0x000f}, {0x23b4, 0x0003}, {0x23bb, 0x2000}, {0x23bc, 0x00d0},
  152. +   {0x23bd, 0x0140}, {0x23be, 0x1000}, {0x23cf, 0x0800}, {0x23d0, 0x0400},
  153. +   {0x23d1, 0x0100}, {0x23d2, 0x0100}, {0x23d5, 0x7c00}, {0x23ed, 0x0300},
  154. +   {0x23ee, 0x3000}, {0x23ef, 0x2800}, {0x22fb, 0x0000},
  155. +};
  156. +#define RT5640_DSP_HFBF_NUM \
  157. +   (sizeof(rt5640_dsp_hfbf) / sizeof(rt5640_dsp_hfbf[0]))
  158. +
  159. +static const u16 rt5640_dsp_ffp[][2] = {
  160. +   {0x22f8, 0x8005}, {0x2303, 0x1971}, {0x2304, 0x8312}, {0x2305, 0x0005},
  161. +   {0x2309, 0x0200}, {0x230a, 0x1b00}, {0x230c, 0x0800}, {0x230d, 0x0400},
  162. +   {0x2325, 0x5000}, {0x2326, 0x0040}, {0x232f, 0x0080}, {0x2332, 0x0100},
  163. +   {0x2333, 0x0020}, {0x2337, 0x0001}, {0x2339, 0x0010}, {0x233c, 0x0040},
  164. +   {0x2348, 0x1000}, {0x2349, 0x1000}, {0x2360, 0x0180}, {0x2361, 0x1800},
  165. +   {0x2362, 0x0200}, {0x2363, 0x0200}, {0x2364, 0x0200}, {0x2365, 0x2000},
  166. +   {0x236e, 0x1000}, {0x236f, 0x0a05}, {0x2370, 0x0f00}, {0x2372, 0x1a00},
  167. +   {0x2373, 0x3000}, {0x2374, 0x2400}, {0x2375, 0x1800}, {0x2380, 0x7fff},
  168. +   {0x2381, 0x4000}, {0x2382, 0x0400}, {0x2383, 0x0400}, {0x2384, 0x0005},
  169. +   {0x2385, 0x0005}, {0x238e, 0x7000}, {0x2393, 0x4444}, {0x2394, 0x4444},
  170. +   {0x2395, 0x4444}, {0x2396, 0x2000}, {0x2397, 0x3000}, {0x2398, 0x0020},
  171. +   {0x23a5, 0x0006}, {0x23a6, 0x7fff}, {0x23b3, 0x000a}, {0x23b4, 0x0006},
  172. +   {0x23b7, 0x0008}, {0x23bb, 0x1000}, {0x23bc, 0x0130}, {0x23bd, 0x0160},
  173. +   {0x23be, 0x2400}, {0x23cf, 0x0800}, {0x23d0, 0x0400}, {0x23d1, 0xff80},
  174. +   {0x23d2, 0xff80}, {0x23d3, 0x2000}, {0x23d4, 0x5000}, {0x23d5, 0x5000},
  175. +   {0x23e7, 0x0c00}, {0x23e8, 0x1400}, {0x23e9, 0x6000}, {0x23ea, 0x7f00},
  176. +   {0x23ed, 0x0300}, {0x23ee, 0x2800}, {0x22fb, 0x0000},
  177. +};
  178. +#define RT5640_DSP_FFP_NUM (sizeof(rt5640_dsp_ffp) / sizeof(rt5640_dsp_ffp[0]))
  179. +
  180. +static const u16 rt5640_dsp_p3_tab[][3] = {
  181. +   {0x4af0, 0x1000, 0x822b}, {0x90f0, 0x1001, 0x8393},
  182. +   {0x64f0, 0x1002, 0x822b}, {0x0ff0, 0x1003, 0x26e0},
  183. +   {0x55f0, 0x1004, 0x2200}, {0xcff0, 0x1005, 0x1a7b},
  184. +   {0x5af0, 0x1006, 0x823a}, {0x90f0, 0x1007, 0x8393},
  185. +   {0x64f0, 0x1008, 0x822b}, {0x0ff0, 0x1009, 0x26e0},
  186. +   {0x03f0, 0x100a, 0x2218}, {0x0ef0, 0x100b, 0x3400},
  187. +   {0x4ff0, 0x100c, 0x195e}, {0x00f0, 0x100d, 0x0000},
  188. +   {0xf0f0, 0x100e, 0x8143}, {0x1ff0, 0x100f, 0x2788},
  189. +   {0x0ef0, 0x1010, 0x3400}, {0xe0f0, 0x1011, 0x1a26},
  190. +   {0x2cf0, 0x1012, 0x8001}, {0x0ff0, 0x1013, 0x267c},
  191. +   {0x82f0, 0x1014, 0x1a27}, {0x3cf0, 0x1015, 0x8001},
  192. +   {0x0ff0, 0x1016, 0x267c}, {0x82f0, 0x1017, 0x1a27},
  193. +   {0xeff0, 0x1018, 0x1a26}, {0x01f0, 0x1019, 0x4ff0},
  194. +   {0x5cf0, 0x101a, 0x2b81}, {0xfaf0, 0x101b, 0x2a6a},
  195. +   {0x05f0, 0x101c, 0x4011}, {0x0ff0, 0x101d, 0x278e},
  196. +   {0x0ef0, 0x101e, 0x3400}, {0xe1f0, 0x101f, 0x1997},
  197. +   {0x1ff0, 0x1020, 0x1997}, {0x03f0, 0x1021, 0x2279},
  198. +   {0xb8f0, 0x1022, 0x8206}, {0xf8f0, 0x1023, 0x0f00},
  199. +   {0xfff0, 0x1024, 0x279e}, {0x0ff0, 0x1025, 0x2272},
  200. +   {0x0ef0, 0x1026, 0x3400}, {0x3ff0, 0x1027, 0x199a},
  201. +   {0x0ff0, 0x1028, 0x2262}, {0x0ff0, 0x1029, 0x2272},
  202. +   {0x0ef0, 0x102a, 0x3400}, {0xfff0, 0x102b, 0x199a},
  203. +   {0x7ff0, 0x102c, 0x22e2}, {0x0ef0, 0x102d, 0x3400},
  204. +   {0xfff0, 0x102e, 0x19cb}, {0xfff0, 0x102f, 0x47ff},
  205. +   {0xb1f0, 0x1030, 0x80b1}, {0x5ff0, 0x1031, 0x2261},
  206. +   {0x62f0, 0x1032, 0x1903}, {0x9af0, 0x1033, 0x0d00},
  207. +   {0xcff0, 0x1034, 0x80b1}, {0x0ff0, 0x1035, 0x0e27},
  208. +   {0x8ff0, 0x1036, 0x9229}, {0x0ef0, 0x1037, 0x3400},
  209. +   {0xaff0, 0x1038, 0x19f5}, {0x81f0, 0x1039, 0x8229},
  210. +   {0x0ef0, 0x103a, 0x3400}, {0xfff0, 0x103b, 0x19f6},
  211. +   {0x5af0, 0x103c, 0x8234}, {0xeaf0, 0x103d, 0x9113},
  212. +   {0x0ef0, 0x103e, 0x3400}, {0x7ff0, 0x103f, 0x19ea},
  213. +   {0x8af0, 0x1040, 0x924d}, {0x08f0, 0x1041, 0x3400},
  214. +   {0x3ff0, 0x1042, 0x1a74}, {0x00f0, 0x1043, 0x0000},
  215. +   {0x00f0, 0x1044, 0x0000}, {0x00f0, 0x1045, 0x0c38},
  216. +   {0x0ff0, 0x1046, 0x2618}, {0xb0f0, 0x1047, 0x8148},
  217. +   {0x01f0, 0x1048, 0x3700}, {0x02f0, 0x1049, 0x3a70},
  218. +   {0x03f0, 0x104a, 0x3a78}, {0x9af0, 0x104b, 0x8229},
  219. +   {0xd6f0, 0x104c, 0x47c4}, {0x95f0, 0x104d, 0x4361},
  220. +   {0x0ff0, 0x104e, 0x2082}, {0x76f0, 0x104f, 0x626b},
  221. +   {0x0ff0, 0x1050, 0x208a}, {0x0ff0, 0x1051, 0x204a},
  222. +   {0xc9f0, 0x1052, 0x7882}, {0x75f0, 0x1053, 0x626b},
  223. +   {0x0ff0, 0x1054, 0x208a}, {0x0ff0, 0x1055, 0x204a},
  224. +   {0xcdf0, 0x1056, 0x7882}, {0x0ff0, 0x1057, 0x2630},
  225. +   {0x8af0, 0x1058, 0x2b30}, {0xf4f0, 0x1059, 0x1904},
  226. +   {0x98f0, 0x105a, 0x9229}, {0x0ef0, 0x105b, 0x3400},
  227. +   {0xeff0, 0x105c, 0x19fd}, {0xd7f0, 0x105d, 0x40cc},
  228. +   {0x0ef0, 0x105e, 0x3400}, {0xdff0, 0x105f, 0x1a44},
  229. +   {0x00f0, 0x1060, 0x0000}, {0xcef0, 0x1061, 0x1507},
  230. +   {0x90f0, 0x1062, 0x1020}, {0x5ff0, 0x1063, 0x1006},
  231. +   {0x89f0, 0x1064, 0x608f}, {0x0ff0, 0x1065, 0x0e64},
  232. +   {0x49f0, 0x1066, 0x1044}, {0xcff0, 0x1067, 0x2b28},
  233. +   {0x93f0, 0x1068, 0x2a62}, {0x5ff0, 0x1069, 0x266a},
  234. +   {0x54f0, 0x106a, 0x22a8}, {0x0af0, 0x106b, 0x0f22},
  235. +   {0xfbf0, 0x106c, 0x0f0c}, {0x5ff0, 0x106d, 0x0d00},
  236. +   {0x90f0, 0x106e, 0x1020}, {0x4ff0, 0x106f, 0x1006},
  237. +   {0x8df0, 0x1070, 0x6087}, {0x0ff0, 0x1071, 0x0e64},
  238. +   {0xb9f0, 0x1072, 0x1044}, {0xcff0, 0x1073, 0x2a63},
  239. +   {0x5ff0, 0x1074, 0x266a}, {0x54f0, 0x1075, 0x22a8},
  240. +   {0x0af0, 0x1076, 0x0f22}, {0xfbf0, 0x1077, 0x0f0c},
  241. +   {0x93f0, 0x1078, 0x2aef}, {0x0ff0, 0x1079, 0x227a},
  242. +   {0xc2f0, 0x107a, 0x1907}, {0xf5f0, 0x107b, 0x0d00},
  243. +   {0xfdf0, 0x107c, 0x7800}, {0x0ef0, 0x107d, 0x3400},
  244. +   {0xaff0, 0x107e, 0x1899},
  245. +};
  246. +#define RT5640_DSP_PATCH3_NUM \
  247. +   (sizeof(rt5640_dsp_p3_tab) / sizeof(rt5640_dsp_p3_tab[0]))
  248. +
  249. +static const u16 rt5640_dsp_p2_tab[][2] = {
  250. +   {0x3fa1, 0xe7bb}, {0x3fb1, 0x5000}, {0x3fa2, 0xa26b}, {0x3fb2, 0x500e},
  251. +   {0x3fa3, 0xa27c}, {0x3fb3, 0x2282}, {0x3fa4, 0x996e}, {0x3fb4, 0x5019},
  252. +   {0x3fa5, 0x99a2}, {0x3fb5, 0x5021}, {0x3fa6, 0x99ae}, {0x3fb6, 0x5028},
  253. +   {0x3fa7, 0x9cbb}, {0x3fb7, 0x502c}, {0x3fa8, 0x9900}, {0x3fb8, 0x1903},
  254. +   {0x3fa9, 0x9f59}, {0x3fb9, 0x502f}, {0x3faa, 0x9f6e}, {0x3fba, 0x5039},
  255. +   {0x3fab, 0x9ea2}, {0x3fbb, 0x503c}, {0x3fac, 0x9fc8}, {0x3fbc, 0x5045},
  256. +   {0x3fad, 0xa44c}, {0x3fbd, 0x505d}, {0x3fae, 0x8983}, {0x3fbe, 0x5061},
  257. +   {0x3faf, 0x95e3}, {0x3fbf, 0x5006}, {0x3fa0, 0xe742}, {0x3fb0, 0x5040},
  258. +};
  259. +#define RT5640_DSP_PATCH2_NUM \
  260. +   (sizeof(rt5640_dsp_p2_tab) / sizeof(rt5640_dsp_p2_tab[0]))
  261. +
  262. +/**
  263. + * rt5640_dsp_done - Wait until DSP is ready.
  264. + * @codec: SoC Audio Codec device.
  265. + *
  266. + * To check voice DSP status and confirm it's ready for next work.
  267. + *
  268. + * Returns 0 for success or negative error code.
  269. + */
  270. +static int rt5640_dsp_done(struct snd_soc_codec *codec)
  271. +{
  272. +   unsigned int count = 0, dsp_val;
  273. +
  274. +   dsp_val = snd_soc_read(codec, RT5640_DSP_CTRL3);
  275. +   while(dsp_val & RT5640_DSP_BUSY_MASK) {
  276. +       if(count > 10)
  277. +           return -EBUSY;
  278. +       dsp_val = snd_soc_read(codec, RT5640_DSP_CTRL3);
  279. +       count ++;      
  280. +   }
  281. +
  282. +   return 0;
  283. +}
  284. +
  285. +/**
  286. + * rt5640_dsp_write - Write DSP register.
  287. + * @codec: SoC audio codec device.
  288. + * @param: DSP parameters.
  289. +  *
  290. + * Modify voice DSP register for sound effect. The DSP can be controlled
  291. + * through DSP command format (0xfc), addr (0xc4), data (0xc5) and cmd (0xc6)
  292. + * register. It has to wait until the DSP is ready.
  293. + *
  294. + * Returns 0 for success or negative error code.
  295. + */
  296. +static int rt5640_dsp_write(struct snd_soc_codec *codec,
  297. +       struct rt5640_dsp_param *param)
  298. +{
  299. +   unsigned int dsp_val = snd_soc_read(codec, RT5640_DSP_CTRL3);
  300. +   int ret;
  301. +
  302. +   ret = rt5640_dsp_done(codec);
  303. +   if (ret < 0) {
  304. +       dev_err(codec->dev, "DSP is busy: %d\n", ret);
  305. +       goto err;
  306. +   }
  307. +   ret = snd_soc_write(codec, RT5640_DUMMY3, param->cmd_fmt);
  308. +   if (ret < 0) {
  309. +       dev_err(codec->dev, "Failed to write cmd format: %d\n", ret);
  310. +       goto err;
  311. +   }
  312. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL1, param->addr);
  313. +   if (ret < 0) {
  314. +       dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
  315. +       goto err;
  316. +   }
  317. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL2, param->data);
  318. +   if (ret < 0) {
  319. +       dev_err(codec->dev, "Failed to write DSP data reg: %d\n", ret);
  320. +       goto err;
  321. +   }
  322. +   dsp_val &= ~(RT5640_DSP_R_EN | RT5640_DSP_CMD_MASK);
  323. +   dsp_val |= RT5640_DSP_W_EN | param->cmd;
  324. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL3, dsp_val);
  325. +   if (ret < 0) {
  326. +       dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
  327. +       goto err;
  328. +   }
  329. +   mdelay(10);
  330. +   return 0;
  331. +  
  332. +err:
  333. +   return ret;
  334. +}
  335. +
  336. +/**
  337. + * rt5640_dsp_read - Read DSP register.
  338. + * @codec: SoC audio codec device.
  339. + * @reg: DSP register index.
  340. + *
  341. + * Read DSP setting value from voice DSP. The DSP can be controlled
  342. + * through DSP addr (0xc4), data (0xc5) and cmd (0xc6) register. Each
  343. + * command has to wait until the DSP is ready.
  344. + *
  345. + * Returns DSP register value or negative error code.
  346. + */
  347. +static unsigned int rt5640_dsp_read(
  348. +   struct snd_soc_codec *codec, unsigned int reg)
  349. +{
  350. +   unsigned int val_h, val_l, value;
  351. +   unsigned int dsp_val = snd_soc_read(codec, RT5640_DSP_CTRL3);
  352. +   int ret = 0;
  353. +
  354. +   ret = rt5640_dsp_done(codec);
  355. +   if (ret < 0) {
  356. +       dev_err(codec->dev, "DSP is busy: %d\n", ret);
  357. +       goto err;
  358. +   }
  359. +   ret = snd_soc_write(codec, RT5640_DUMMY3, 0);
  360. +   if (ret < 0) {
  361. +       dev_err(codec->dev, "Failed to write fc = 0: %d\n", ret);
  362. +       goto err;
  363. +   }
  364. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL1, reg);
  365. +   if (ret < 0) {
  366. +       dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
  367. +       goto err;
  368. +   }
  369. +   dsp_val &= ~(RT5640_DSP_W_EN | RT5640_DSP_CMD_MASK);
  370. +   dsp_val |= RT5640_DSP_R_EN | RT5640_DSP_CMD_MR;
  371. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL3, dsp_val);
  372. +   if (ret < 0) {
  373. +       dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
  374. +       goto err;
  375. +   }
  376. +
  377. +   /* Read DSP high byte data */
  378. +   ret = rt5640_dsp_done(codec);
  379. +   if (ret < 0) {
  380. +       dev_err(codec->dev, "DSP is busy: %d\n", ret);
  381. +       goto err;
  382. +   }
  383. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL1, RT5640_DSP_REG_DATHI);
  384. +   if (ret < 0) {
  385. +       dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
  386. +       goto err;
  387. +   }
  388. +   dsp_val &= ~(RT5640_DSP_W_EN | RT5640_DSP_CMD_MASK);
  389. +   dsp_val |= RT5640_DSP_R_EN | RT5640_DSP_CMD_RR;
  390. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL3, dsp_val);
  391. +   if (ret < 0) {
  392. +       dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
  393. +       goto err;
  394. +   }
  395. +   ret = rt5640_dsp_done(codec);
  396. +   if (ret < 0) {
  397. +       dev_err(codec->dev, "DSP is busy: %d\n", ret);
  398. +       goto err;
  399. +   }
  400. +   ret = snd_soc_read(codec, RT5640_DSP_CTRL2);
  401. +   if (ret < 0) {
  402. +       dev_err(codec->dev, "Failed to read DSP data reg: %d\n", ret);
  403. +       goto err;
  404. +   }
  405. +   val_h = ret;
  406. +
  407. +   /* Read DSP low byte data */
  408. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL1, RT5640_DSP_REG_DATLO);
  409. +   if (ret < 0) {
  410. +       dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
  411. +       goto err;
  412. +   }
  413. +   ret = snd_soc_write(codec, RT5640_DSP_CTRL3, dsp_val);
  414. +   if (ret < 0) {
  415. +       dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
  416. +       goto err;
  417. +   }
  418. +   ret = rt5640_dsp_done(codec);
  419. +   if (ret < 0) {
  420. +       dev_err(codec->dev, "DSP is busy: %d\n", ret);
  421. +       goto err;
  422. +   }
  423. +   ret = snd_soc_read(codec, RT5640_DSP_CTRL2);
  424. +   if (ret < 0) {
  425. +       dev_err(codec->dev, "Failed to read DSP data reg: %d\n", ret);
  426. +       goto err;
  427. +   }
  428. +   val_l = ret;
  429. +
  430. +   value = ((val_h & 0xff) << 8) |(val_l & 0xff);
  431. +   return value;
  432. +
  433. +err:
  434. +   return ret;
  435. +}
  436. +
  437. +static int rt5640_dsp_get(struct snd_kcontrol *kcontrol,
  438. +       struct snd_ctl_elem_value *ucontrol)
  439. +{
  440. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  441. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  442. +
  443. +   ucontrol->value.integer.value[0] = rt5640->dsp_sw;
  444. +
  445. +   return 0;
  446. +}
  447. +
  448. +static int rt5640_dsp_put(struct snd_kcontrol *kcontrol,
  449. +       struct snd_ctl_elem_value *ucontrol)
  450. +{
  451. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  452. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  453. +
  454. +   if (rt5640->dsp_sw != ucontrol->value.integer.value[0])
  455. +       rt5640->dsp_sw = ucontrol->value.integer.value[0];
  456. +
  457. +   return 0;
  458. +   }
  459. +
  460. +static int rt5640_dsp_play_bp_get(struct snd_kcontrol *kcontrol,
  461. +       struct snd_ctl_elem_value *ucontrol)
  462. +{
  463. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  464. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  465. +
  466. +   ucontrol->value.integer.value[0] = rt5640->dsp_play_pass;
  467. +
  468. +   return 0;
  469. +}
  470. +
  471. +static int rt5640_dsp_play_bp_put(struct snd_kcontrol *kcontrol,
  472. +       struct snd_ctl_elem_value *ucontrol)
  473. +{
  474. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  475. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  476. +
  477. +   if (rt5640->dsp_play_pass == ucontrol->value.integer.value[0])
  478. +       return 0;
  479. +   rt5640->dsp_play_pass = ucontrol->value.integer.value[0];
  480. +
  481. +   rt5640_conn_mux_path(codec, "DAC L2 Mux",
  482. +       rt5640->dsp_play_pass ? "IF2" : "TxDC");
  483. +   rt5640_conn_mux_path(codec, "DAC R2 Mux",
  484. +       rt5640->dsp_play_pass ? "IF2" : "TxDC");
  485. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXL",
  486. +       "DAC L1 Switch", rt5640->dsp_play_pass);
  487. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXL",
  488. +       "DAC L2 Switch", !rt5640->dsp_play_pass);
  489. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXR",
  490. +       "DAC R1 Switch", rt5640->dsp_play_pass);
  491. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXR",
  492. +       "DAC R2 Switch", !rt5640->dsp_play_pass);
  493. +
  494. +   return 0;
  495. +}
  496. +
  497. +static int rt5640_dsp_rec_bp_get(struct snd_kcontrol *kcontrol,
  498. +       struct snd_ctl_elem_value *ucontrol)
  499. +{
  500. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  501. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  502. +
  503. +   ucontrol->value.integer.value[0] = rt5640->dsp_rec_pass;
  504. +
  505. +   return 0;
  506. +}
  507. +
  508. +static int rt5640_dsp_rec_bp_put(struct snd_kcontrol *kcontrol,
  509. +       struct snd_ctl_elem_value *ucontrol)
  510. +{
  511. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  512. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  513. +
  514. +   if (rt5640->dsp_rec_pass == ucontrol->value.integer.value[0])
  515. +       return 0;
  516. +   rt5640->dsp_rec_pass = ucontrol->value.integer.value[0];
  517. +
  518. +   rt5640_conn_mux_path(codec, "IF2 ADC L Mux",
  519. +       rt5640->dsp_rec_pass ? "Mono ADC MIXL" : "TxDP");
  520. +   rt5640_conn_mux_path(codec, "IF2 ADC R Mux",
  521. +       rt5640->dsp_rec_pass ? "Mono ADC MIXR" : "TxDP");
  522. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXL",
  523. +       "ADC1 Switch", rt5640->dsp_rec_pass);
  524. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXR",
  525. +       "ADC1 Switch", rt5640->dsp_rec_pass);
  526. +   rt5640_conn_mixer_path(codec, "Mono ADC MIXL",
  527. +       "ADC1 Switch", !rt5640->dsp_rec_pass);
  528. +   rt5640_conn_mixer_path(codec, "Mono ADC MIXR",
  529. +       "ADC1 Switch", !rt5640->dsp_rec_pass);
  530. +
  531. +   return 0;
  532. +}
  533. +
  534. +static int rt5640_dac_active_get(struct snd_kcontrol *kcontrol,
  535. +       struct snd_ctl_elem_value *ucontrol)
  536. +{
  537. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  538. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  539. +   struct snd_soc_dapm_widget *w;
  540. +  
  541. +   list_for_each_entry(w, &dapm->card->widgets, list)
  542. +   {
  543. +       if (!w->sname || w->dapm != dapm)
  544. +           continue;
  545. +       if (strstr(w->sname, "Playback")) {
  546. +           pr_info("widget %s %s\n", w->name, w->sname);
  547. +           ucontrol->value.integer.value[0] = w->active;
  548. +           break;
  549. +       }
  550. +   }
  551. +   return 0;
  552. +}
  553. +
  554. +static int rt5640_dac_active_put(struct snd_kcontrol *kcontrol,
  555. +       struct snd_ctl_elem_value *ucontrol)
  556. +{
  557. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  558. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  559. +   struct snd_soc_dapm_widget *w;
  560. +  
  561. +   list_for_each_entry(w, &dapm->card->widgets, list)
  562. +   {
  563. +       if (!w->sname || w->dapm != dapm)
  564. +           continue;
  565. +       if (strstr(w->sname, "Playback")) {
  566. +           pr_info("widget %s %s\n", w->name, w->sname);
  567. +           w->active = 1;
  568. +       }
  569. +   }
  570. +   return 0;
  571. +}
  572. +
  573. +static int rt5640_adc_active_get(struct snd_kcontrol *kcontrol,
  574. +       struct snd_ctl_elem_value *ucontrol)
  575. +{
  576. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  577. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  578. +   struct snd_soc_dapm_widget *w;
  579. +  
  580. +   list_for_each_entry(w, &dapm->card->widgets, list)
  581. +   {
  582. +       if (!w->sname || w->dapm != dapm)
  583. +           continue;
  584. +       if (strstr(w->sname, "Capture")) {
  585. +           pr_info("widget %s %s\n", w->name, w->sname);
  586. +           ucontrol->value.integer.value[0] = w->active;
  587. +           break;
  588. +       }
  589. +   }
  590. +   return 0;
  591. +}
  592. +
  593. +static int rt5640_adc_active_put(struct snd_kcontrol *kcontrol,
  594. +       struct snd_ctl_elem_value *ucontrol)
  595. +{
  596. +   struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  597. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  598. +   struct snd_soc_dapm_widget *w;
  599. +  
  600. +   list_for_each_entry(w, &dapm->card->widgets, list)
  601. +   {
  602. +       if (!w->sname || w->dapm != dapm)
  603. +           continue;
  604. +       if (strstr(w->sname, "Capture")) {
  605. +           pr_info("widget %s %s\n", w->name, w->sname);
  606. +           w->active = 1;
  607. +       }
  608. +   }
  609. +   return 0;
  610. +}
  611. +
  612. +/* DSP Path Control 1 */
  613. +static const char *rt5640_src_rxdp_mode[] = {
  614. +   "Normal", "Divided by 3"};
  615. +
  616. +static const SOC_ENUM_SINGLE_DECL(
  617. +   rt5640_src_rxdp_enum, RT5640_DSP_PATH1,
  618. +   RT5640_RXDP_SRC_SFT, rt5640_src_rxdp_mode);
  619. +
  620. +static const char *rt5640_src_txdp_mode[] = {
  621. +   "Normal", "Multiplied by 3"};
  622. +
  623. +static const SOC_ENUM_SINGLE_DECL(
  624. +   rt5640_src_txdp_enum, RT5640_DSP_PATH1,
  625. +   RT5640_TXDP_SRC_SFT, rt5640_src_txdp_mode);
  626. +
  627. +/* DSP data select */
  628. +static const char *rt5640_dsp_data_select[] = {
  629. +   "Normal", "left copy to right", "right copy to left", "Swap"};
  630. +
  631. +static const SOC_ENUM_SINGLE_DECL(rt5640_rxdc_data_enum, RT5640_DSP_PATH2,
  632. +               RT5640_RXDC_SEL_SFT, rt5640_dsp_data_select);
  633. +
  634. +static const SOC_ENUM_SINGLE_DECL(rt5640_rxdp_data_enum, RT5640_DSP_PATH2,
  635. +               RT5640_RXDP_SEL_SFT, rt5640_dsp_data_select);
  636. +
  637. +static const SOC_ENUM_SINGLE_DECL(rt5640_txdc_data_enum, RT5640_DSP_PATH2,
  638. +               RT5640_TXDC_SEL_SFT, rt5640_dsp_data_select);
  639. +
  640. +static const SOC_ENUM_SINGLE_DECL(rt5640_txdp_data_enum, RT5640_DSP_PATH2,
  641. +               RT5640_TXDP_SEL_SFT, rt5640_dsp_data_select);
  642. +
  643. +/* Sound Effect */
  644. +static const char *rt5640_dsp_mode[] = {
  645. +   "Disable", "AEC+NS+FENS", "HFBF", "Far Field Pick-up"};
  646. +
  647. +static const SOC_ENUM_SINGLE_DECL(rt5640_dsp_enum, 0, 0, rt5640_dsp_mode);
  648. +
  649. +static const struct snd_kcontrol_new rt5640_dsp_snd_controls[] = {
  650. +   SOC_ENUM("RxDC input data", rt5640_rxdc_data_enum),
  651. +   SOC_ENUM("RxDP input data", rt5640_rxdp_data_enum),
  652. +   SOC_ENUM("TxDC input data", rt5640_txdc_data_enum),
  653. +   SOC_ENUM("TxDP input data", rt5640_txdp_data_enum),
  654. +   SOC_ENUM("SRC for RxDP", rt5640_src_rxdp_enum),
  655. +   SOC_ENUM("SRC for TxDP", rt5640_src_txdp_enum),
  656. +   /* AEC */
  657. +   SOC_ENUM_EXT("DSP Function Switch", rt5640_dsp_enum,
  658. +       rt5640_dsp_get, rt5640_dsp_put),
  659. +   SOC_SINGLE_EXT("DSP Playback Bypass", 0, 0, 1, 0,
  660. +       rt5640_dsp_play_bp_get, rt5640_dsp_play_bp_put),
  661. +   SOC_SINGLE_EXT("DSP Record Bypass", 0, 0, 1, 0,
  662. +       rt5640_dsp_rec_bp_get, rt5640_dsp_rec_bp_put),
  663. +   SOC_SINGLE_EXT("DAC Switch", 0, 0, 1, 0,
  664. +       rt5640_dac_active_get, rt5640_dac_active_put),
  665. +   SOC_SINGLE_EXT("ADC Switch", 0, 0, 1, 0,
  666. +       rt5640_adc_active_get, rt5640_adc_active_put),
  667. +};
  668. +
  669. +static int rt5640_dsp_patch_3(struct snd_soc_codec *codec)
  670. +{
  671. +   struct rt5640_dsp_param param;
  672. +   int ret, i;
  673. +
  674. +   param.cmd_fmt =  0x0090;
  675. +   param.addr = 0x0064;
  676. +   param.data = 0x0004;
  677. +   param.cmd =  RT5640_DSP_CMD_RW;
  678. +   ret = rt5640_dsp_write(codec, &param);
  679. +   if (ret < 0) {
  680. +       dev_err(codec->dev,
  681. +           "Fail to set DSP 3 bytes patch entrance: %d\n", ret);
  682. +       goto patch_err;
  683. +   }
  684. +
  685. +   param.cmd =  RT5640_DSP_CMD_PE;
  686. +   for(i = 0; i < RT5640_DSP_PATCH3_NUM; i++) {
  687. +       param.cmd_fmt =  rt5640_dsp_p3_tab[i][0];
  688. +       param.addr = rt5640_dsp_p3_tab[i][1];
  689. +       param.data = rt5640_dsp_p3_tab[i][2];
  690. +       ret = rt5640_dsp_write(codec, &param);
  691. +       if (ret < 0) {
  692. +           dev_err(codec->dev, "Fail to patch Dsp: %d\n", ret);
  693. +           goto patch_err;
  694. +       }
  695. +   }
  696. +
  697. +   return 0;
  698. +
  699. +patch_err:
  700. +
  701. +   return ret;
  702. +}
  703. +
  704. +static int rt5640_dsp_patch_2(struct snd_soc_codec *codec)
  705. +{
  706. +   struct rt5640_dsp_param param;
  707. +   int ret, i;
  708. +
  709. +   param.cmd_fmt =  0x0090;
  710. +   param.addr = 0x0064;
  711. +   param.data = 0x0000;
  712. +   param.cmd =  RT5640_DSP_CMD_RW;
  713. +   ret = rt5640_dsp_write(codec, &param);
  714. +   if (ret < 0) {
  715. +       dev_err(codec->dev,
  716. +           "Fail to set DSP 2 bytes patch entrance: %d\n", ret);
  717. +       goto patch_err;
  718. +   }
  719. +
  720. +   param.cmd_fmt =  0x00e0;
  721. +   param.cmd =  RT5640_DSP_CMD_MW;
  722. +   for(i = 0; i < RT5640_DSP_PATCH2_NUM; i++) {
  723. +       param.addr = rt5640_dsp_p2_tab[i][0];
  724. +       param.data = rt5640_dsp_p2_tab[i][1];
  725. +       ret = rt5640_dsp_write(codec, &param);
  726. +       if (ret < 0) {
  727. +           dev_err(codec->dev, "Fail to patch Dsp: %d\n", ret);
  728. +           goto patch_err;
  729. +       }
  730. +   }
  731. +
  732. +   return 0;
  733. +
  734. +patch_err:
  735. +
  736. +   return ret;
  737. +}
  738. +
  739. +/**
  740. + * rt5640_dsp_patch - Write DSP patch code.
  741. + *
  742. + * @codec: SoC audio codec device.
  743. + *
  744. + * Write patch codes to DSP including 3 and 2 bytes data.
  745. + *
  746. + * Returns 0 for success or negative error code.
  747. + */
  748. +static int rt5640_dsp_patch(struct snd_soc_codec *codec)
  749. +{
  750. +   int ret;
  751. +
  752. +   dev_dbg(codec->dev, "\n DSP Patch Start ......\n");
  753. +
  754. +   ret = snd_soc_update_bits(codec, RT5640_MICBIAS,
  755. +       RT5640_PWR_CLK25M_MASK, RT5640_PWR_CLK25M_PU);
  756. +   if (ret < 0)
  757. +       goto patch_err;
  758. +
  759. +   ret = snd_soc_update_bits(codec, RT5640_GLB_CLK,
  760. +       RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);
  761. +   if (ret < 0)
  762. +       goto patch_err;
  763. +
  764. +   ret = snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  765. +       RT5640_PWR_I2S_DSP, RT5640_PWR_I2S_DSP);
  766. +   if (ret < 0)
  767. +       goto patch_err;
  768. +
  769. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  770. +       RT5640_DSP_PD_PIN_MASK, RT5640_DSP_PD_PIN_HI);
  771. +   if (ret < 0) {
  772. +       dev_err(codec->dev, "Failed to power up DSP: %d\n", ret);
  773. +       goto patch_err;
  774. +   }
  775. +
  776. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  777. +       RT5640_DSP_RST_PIN_MASK, RT5640_DSP_RST_PIN_LO);
  778. +   if (ret < 0) {
  779. +       dev_err(codec->dev, "Failed to reset DSP: %d\n", ret);
  780. +       goto patch_err;
  781. +   }
  782. +
  783. +   mdelay(10);
  784. +
  785. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  786. +       RT5640_DSP_RST_PIN_MASK, RT5640_DSP_RST_PIN_HI);
  787. +   if (ret < 0) {
  788. +       dev_err(codec->dev, "Failed to recover DSP: %d\n", ret);
  789. +       goto patch_err;
  790. +   }
  791. +
  792. +   ret = rt5640_dsp_patch_3(codec);
  793. +   if (ret < 0)
  794. +       goto patch_err;
  795. +
  796. +   ret = rt5640_dsp_patch_2(codec);
  797. +   if (ret < 0)
  798. +       goto patch_err;
  799. +
  800. +   return 0;
  801. +
  802. +patch_err:
  803. +
  804. +   return ret;
  805. +}
  806. +
  807. +static void rt5640_do_dsp_patch(struct work_struct *work)
  808. +{
  809. +   struct rt5640_priv *rt5640 =
  810. +       container_of(work, struct rt5640_priv, patch_work.work);
  811. +   struct snd_soc_codec *codec = rt5640->codec;
  812. +
  813. +   if (rt5640_dsp_patch(codec) < 0)
  814. +       dev_err(codec->dev, "Patch DSP rom code Fail !!!\n");
  815. +}
  816. +
  817. +
  818. +/**
  819. + * rt5640_dsp_conf - Set DSP basic setting.
  820. + *
  821. + * @codec: SoC audio codec device.
  822. + *
  823. + * Set parameters of basic setting to DSP.
  824. + *
  825. + * Returns 0 for success or negative error code.
  826. + */
  827. +static int rt5640_dsp_conf(struct snd_soc_codec *codec)
  828. +{
  829. +   struct rt5640_dsp_param param;
  830. +   int ret, i;
  831. +
  832. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  833. +       RT5640_DSP_PD_PIN_MASK, RT5640_DSP_PD_PIN_HI);
  834. +   if (ret < 0) {
  835. +       dev_err(codec->dev, "Failed to power up DSP: %d\n", ret);
  836. +       goto conf_err;
  837. +   }
  838. +
  839. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  840. +       RT5640_DSP_RST_PIN_MASK, RT5640_DSP_RST_PIN_LO);
  841. +   if (ret < 0) {
  842. +       dev_err(codec->dev, "Failed to reset DSP: %d\n", ret);
  843. +       goto conf_err;
  844. +   }
  845. +
  846. +   mdelay(10);
  847. +
  848. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  849. +       RT5640_DSP_RST_PIN_MASK | RT5640_DSP_CLK_MASK,
  850. +       RT5640_DSP_RST_PIN_HI | RT5640_DSP_CLK_384K);
  851. +   if (ret < 0) {
  852. +       dev_err(codec->dev, "Failed to recover DSP: %d\n", ret);
  853. +       goto conf_err;
  854. +   }
  855. +
  856. +   param.cmd_fmt =  0x00e0;
  857. +   param.cmd =  RT5640_DSP_CMD_MW;
  858. +   for(i = 0; i < RT5640_DSP_INIT_NUM; i++) {
  859. +       param.addr = rt5640_dsp_init[i][0];
  860. +       param.data = rt5640_dsp_init[i][1];
  861. +       ret = rt5640_dsp_write(codec, &param);
  862. +       if (ret < 0) {
  863. +           dev_err(codec->dev, "Fail to config Dsp: %d\n", ret);
  864. +           goto conf_err;
  865. +       }
  866. +   }
  867. +
  868. +   return 0;
  869. +
  870. +conf_err:
  871. +
  872. +   return ret;
  873. +}
  874. +
  875. +/**
  876. + * rt5640_dsp_rate - Set DSP rate setting.
  877. + *
  878. + * @codec: SoC audio codec device.
  879. + * @rate: Sampling rate.
  880. + *
  881. + * Set parameters of sampling rate to DSP.
  882. + *
  883. + * Returns 0 for success or negative error code.
  884. + */
  885. +static int rt5640_dsp_rate(struct snd_soc_codec *codec, int rate)
  886. +{
  887. +   struct rt5640_dsp_param param;
  888. +   int ret, i, tab_num;
  889. +   unsigned short (*rate_tab)[2];
  890. +
  891. +   if (rate != 48000 &&  rate != 44100 && rate != 16000)
  892. +       return -EINVAL;
  893. +
  894. +   if (rate > 44100) {
  895. +       rate_tab = rt5640_dsp_48;
  896. +       tab_num = RT5640_DSP_48_NUM;
  897. +   } else {
  898. +       if (rate > 16000) {
  899. +           rate_tab = rt5640_dsp_441;
  900. +           tab_num = RT5640_DSP_441_NUM;
  901. +       } else {
  902. +           rate_tab = rt5640_dsp_16;
  903. +           tab_num = RT5640_DSP_16_NUM;
  904. +       }
  905. +   }
  906. +
  907. +   param.cmd_fmt =  0x00e0;
  908. +   param.cmd =  RT5640_DSP_CMD_MW;
  909. +   for (i = 0; i < tab_num; i++) {
  910. +       param.addr = rate_tab[i][0];
  911. +       param.data = rate_tab[i][1];
  912. +       ret = rt5640_dsp_write(codec, &param);
  913. +       if (ret < 0)
  914. +           goto rate_err;
  915. +   }
  916. +
  917. +   return 0;
  918. +
  919. +rate_err:
  920. +
  921. +   dev_err(codec->dev, "Fail to set rate %d parameters: %d\n", rate, ret);
  922. +   return ret;
  923. +}
  924. +
  925. +/**
  926. + * rt5640_dsp_set_mode - Set DSP mode parameters.
  927. + *
  928. + * @codec: SoC audio codec device.
  929. + * @mode: DSP mode.
  930. + *
  931. + * Set parameters of mode to DSP.
  932. + * There are three modes which includes " mic AEC + NS + FENS",
  933. + * "HFBF" and "Far-field pickup".
  934. + *
  935. + * Returns 0 for success or negative error code.
  936. + */
  937. +static int rt5640_dsp_set_mode(struct snd_soc_codec *codec, int mode)
  938. +{
  939. +   struct rt5640_dsp_param param;
  940. +   int ret, i, tab_num;
  941. +   unsigned short (*mode_tab)[2];
  942. +
  943. +   switch (mode) {
  944. +   case RT5640_DSP_AEC_NS_FENS:
  945. +       dev_info(codec->dev, "AEC\n");
  946. +       mode_tab = rt5640_dsp_aec_ns_fens;
  947. +       tab_num = RT5640_DSP_AEC_NUM;
  948. +       break;
  949. +
  950. +   case RT5640_DSP_HFBF:
  951. +       dev_info(codec->dev, "Beamforming\n");
  952. +       mode_tab = rt5640_dsp_hfbf;
  953. +       tab_num = RT5640_DSP_HFBF_NUM;
  954. +       break;
  955. +
  956. +   case RT5640_DSP_FFP:
  957. +       dev_info(codec->dev, "Far Field Pick-up\n");
  958. +       mode_tab = rt5640_dsp_ffp;
  959. +       tab_num = RT5640_DSP_FFP_NUM;
  960. +       break;
  961. +
  962. +   case RT5640_DSP_DIS:
  963. +   default:
  964. +       dev_info(codec->dev, "Disable\n");
  965. +       return 0;
  966. +   }
  967. +
  968. +   param.cmd_fmt =  0x00e0;
  969. +   param.cmd =  RT5640_DSP_CMD_MW;
  970. +   for (i = 0; i < tab_num; i++) {
  971. +       param.addr = mode_tab[i][0];
  972. +       param.data = mode_tab[i][1];
  973. +       ret = rt5640_dsp_write(codec, &param);
  974. +       if (ret < 0)
  975. +           goto mode_err;
  976. +   }
  977. +
  978. +   return 0;
  979. +
  980. +mode_err:
  981. +
  982. +   dev_err(codec->dev, "Fail to set mode %d parameters: %d\n", mode, ret);
  983. +   return ret;
  984. +}
  985. +
  986. +/**
  987. + * rt5640_dsp_snd_effect - Set DSP sound effect.
  988. + *
  989. + * Set parameters of sound effect to DSP.
  990. + *
  991. + * Returns 0 for success or negative error code.
  992. + */
  993. +static int rt5640_dsp_snd_effect(struct snd_soc_codec *codec)
  994. +{
  995. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  996. +   int ret;
  997. +
  998. +
  999. +
  1000. +   ret = rt5640_dsp_conf(codec);
  1001. +   if (ret < 0)
  1002. +       goto effect_err;
  1003. +
  1004. +   ret = rt5640_dsp_rate(codec, rt5640->lrck[rt5640->aif_pu] ?
  1005. +       rt5640->lrck[rt5640->aif_pu] : 44100);
  1006. +   if (ret < 0)
  1007. +       goto effect_err;
  1008. +
  1009. +   ret = rt5640_dsp_set_mode(codec, rt5640->dsp_sw);
  1010. +   if (ret < 0)
  1011. +       goto effect_err;
  1012. +
  1013. +   mdelay(20);
  1014. +
  1015. +   return 0;
  1016. +
  1017. +effect_err:
  1018. +
  1019. +   return ret;
  1020. +}
  1021. +
  1022. +static int rt5640_dsp_event(struct snd_soc_dapm_widget *w,
  1023. +           struct snd_kcontrol *k, int event)
  1024. +{
  1025. +   struct snd_soc_codec *codec = w->codec;
  1026. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  1027. +   static unsigned int power_on;
  1028. +  
  1029. +   switch (event) {
  1030. +   case SND_SOC_DAPM_POST_PMD:
  1031. +       pr_info("%s(): PMD\n", __func__);
  1032. +       if (!power_on)
  1033. +           return 0;
  1034. +       power_on--;
  1035. +       if (!power_on) {
  1036. +           snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1037. +               RT5640_PWR_I2S_DSP, 0);
  1038. +           snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  1039. +               RT5640_DSP_PD_PIN_MASK, RT5640_DSP_PD_PIN_LO);
  1040. +       }
  1041. +       break;
  1042. +
  1043. +   case SND_SOC_DAPM_PRE_PMU:
  1044. +       pr_info("%s(): PMU\n", __func__);
  1045. +       if (rt5640->dsp_sw == RT5640_DSP_DIS || 2 <= power_on)
  1046. +           return 0;
  1047. +       if (!power_on) {
  1048. +           snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1049. +               RT5640_PWR_I2S_DSP, RT5640_PWR_I2S_DSP);
  1050. +           rt5640_dsp_snd_effect(codec);
  1051. +       }
  1052. +       power_on++;
  1053. +       break;
  1054. +
  1055. +   default:
  1056. +       return 0;
  1057. +   }  
  1058. +
  1059. +   return 0;
  1060. +}
  1061. +
  1062. +static const struct snd_soc_dapm_widget rt5640_dsp_dapm_widgets[] = {
  1063. +   SND_SOC_DAPM_PGA_E("DSP Downstream", SND_SOC_NOPM,
  1064. +       0, 0, NULL, 0, rt5640_dsp_event,
  1065. +       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),
  1066. +   SND_SOC_DAPM_PGA_E("DSP Upstream", SND_SOC_NOPM,
  1067. +       0, 0, NULL, 0, rt5640_dsp_event,
  1068. +       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),
  1069. +   SND_SOC_DAPM_PGA("RxDP", SND_SOC_NOPM, 0, 0, NULL, 0),
  1070. +   SND_SOC_DAPM_PGA("RxDC", SND_SOC_NOPM, 0, 0, NULL, 0),
  1071. +   SND_SOC_DAPM_PGA("TxDC", SND_SOC_NOPM, 0, 0, NULL, 0),
  1072. +   SND_SOC_DAPM_PGA("TxDP", SND_SOC_NOPM, 0, 0, NULL, 0),
  1073. +};
  1074. +
  1075. +static const struct snd_soc_dapm_route rt5640_dsp_dapm_routes[] = {
  1076. +   {"RxDC", NULL, "Mono ADC MIXL"},
  1077. +   {"RxDC", NULL, "Mono ADC MIXR"},
  1078. +   {"RxDP", NULL, "IF2 DAC L"},
  1079. +   {"RxDP", NULL, "IF2 DAC R"},
  1080. +
  1081. +   {"DSP Downstream", NULL, "RxDP"},
  1082. +   {"TxDC", NULL, "DSP Downstream"},
  1083. +   {"DSP Upstream", NULL, "RxDC"},
  1084. +   {"TxDP", NULL, "DSP Upstream"},
  1085. +
  1086. +   {"IF2 ADC L Mux", "TxDP", "TxDP"},
  1087. +   {"IF2 ADC R Mux", "TxDP", "TxDP"},
  1088. +   {"DAC L2 Mux", "TxDC", "TxDC"},
  1089. +   {"DAC R2 Mux", "TxDC", "TxDC"},
  1090. +};
  1091. +
  1092. +/**
  1093. + * rt5640_dsp_show - Dump DSP registers.
  1094. + * @dev: codec device.
  1095. + * @attr: device attribute.
  1096. + * @buf: buffer for display.
  1097. + *
  1098. + * To show non-zero values of all DSP registers.
  1099. + *
  1100. + * Returns buffer length.
  1101. + */
  1102. +static ssize_t rt5640_dsp_show(struct device *dev,
  1103. +   struct device_attribute *attr, char *buf)
  1104. +{
  1105. +   struct i2c_client *client = to_i2c_client(dev);
  1106. +   struct rt5640_priv *rt5640 = i2c_get_clientdata(client);
  1107. +   struct snd_soc_codec *codec = rt5640->codec;
  1108. +   unsigned short (*rt5640_dsp_tab)[2];
  1109. +   unsigned int val;
  1110. +   int cnt = 0, i, tab_num;
  1111. +
  1112. +   switch (rt5640->dsp_sw) {
  1113. +   case RT5640_DSP_AEC_NS_FENS:
  1114. +       cnt += sprintf(buf, "[ RT5642 DSP 'AEC' ]\n");
  1115. +       rt5640_dsp_tab = rt5640_dsp_aec_ns_fens;
  1116. +       tab_num = RT5640_DSP_AEC_NUM;
  1117. +       break;
  1118. +
  1119. +   case RT5640_DSP_HFBF:
  1120. +       cnt += sprintf(buf, "[ RT5642 DSP 'Beamforming' ]\n");
  1121. +       rt5640_dsp_tab = rt5640_dsp_hfbf;
  1122. +       tab_num = RT5640_DSP_HFBF_NUM;
  1123. +       break;
  1124. +
  1125. +   case RT5640_DSP_FFP:
  1126. +       cnt += sprintf(buf, "[ RT5642 DSP 'Far Field Pick-up' ]\n");
  1127. +       rt5640_dsp_tab = rt5640_dsp_ffp;
  1128. +       tab_num = RT5640_DSP_FFP_NUM;
  1129. +       break;
  1130. +
  1131. +   case RT5640_DSP_DIS:
  1132. +   default:
  1133. +       cnt += sprintf(buf, "RT5642 DSP Disabled\n");
  1134. +       goto dsp_done;
  1135. +   }
  1136. +
  1137. +   for (i = 0; i < tab_num; i++) {
  1138. +       if (cnt + RT5640_DSP_REG_DISP_LEN >= PAGE_SIZE)
  1139. +           break;
  1140. +       val = rt5640_dsp_read(codec, rt5640_dsp_tab[i][0]);
  1141. +       if (!val)
  1142. +           continue;
  1143. +       cnt += snprintf(buf + cnt, RT5640_DSP_REG_DISP_LEN,
  1144. +           "%04x: %04x\n", rt5640_dsp_tab[i][0], val);
  1145. +   }
  1146. +
  1147. +dsp_done:
  1148. +
  1149. +   if (cnt >= PAGE_SIZE)
  1150. +       cnt = PAGE_SIZE - 1;
  1151. +
  1152. +   return cnt;
  1153. +}
  1154. +static DEVICE_ATTR(dsp_reg, 0444, rt5640_dsp_show, NULL);
  1155. +
  1156. +/**
  1157. + * rt5640_dsp_probe - register DSP for rt5640
  1158. + * @codec: audio codec
  1159. + *
  1160. + * To register DSP function for rt5640.
  1161. + *
  1162. + * Returns 0 for success or negative error code.
  1163. + */
  1164. +int rt5640_dsp_probe(struct snd_soc_codec *codec)
  1165. +{
  1166. +   struct rt5640_priv *rt5640;
  1167. +   int ret;
  1168. +
  1169. +   if (codec == NULL)
  1170. +       return -EINVAL;
  1171. +
  1172. +   snd_soc_add_controls(codec, rt5640_dsp_snd_controls,
  1173. +           ARRAY_SIZE(rt5640_dsp_snd_controls));
  1174. +   snd_soc_dapm_new_controls(&codec->dapm, rt5640_dsp_dapm_widgets,
  1175. +           ARRAY_SIZE(rt5640_dsp_dapm_widgets));
  1176. +   snd_soc_dapm_add_routes(&codec->dapm, rt5640_dsp_dapm_routes,
  1177. +           ARRAY_SIZE(rt5640_dsp_dapm_routes));
  1178. +
  1179. +   /* Patch DSP rom code if IC version is larger than C version */
  1180. +   //if (RT5640_VER_C != snd_soc_read(codec, RT5640_VENDOR_ID)) {
  1181. +   ret = snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1182. +       RT5640_PWR_I2S_DSP, RT5640_PWR_I2S_DSP);
  1183. +   if (ret < 0) {
  1184. +       dev_err(codec->dev,
  1185. +           "Failed to power up DSP IIS interface: %d\n", ret);
  1186. +   }
  1187. +   rt5640_dsp_conf(codec);
  1188. +   ret = rt5640_dsp_read(codec, 0x3800);
  1189. +   pr_info("DSP version code = 0x%04x\n",ret);
  1190. +   if(ret != 0x501a) {
  1191. +       rt5640 = snd_soc_codec_get_drvdata(codec);
  1192. +       INIT_DELAYED_WORK(&rt5640->patch_work, rt5640_do_dsp_patch);
  1193. +       schedule_delayed_work(&rt5640->patch_work,
  1194. +               msecs_to_jiffies(100));
  1195. +   }
  1196. +   snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1197. +       RT5640_PWR_I2S_DSP, 0);
  1198. +
  1199. +   ret = device_create_file(codec->dev, &dev_attr_dsp_reg);
  1200. +   if (ret != 0) {
  1201. +       dev_err(codec->dev,
  1202. +           "Failed to create index_reg sysfs files: %d\n", ret);
  1203. +       return ret;
  1204. +   }
  1205. +
  1206. +   return 0;
  1207. +}
  1208. +EXPORT_SYMBOL_GPL(rt5640_dsp_probe);
  1209. +
  1210. +int do_rt5640_dsp_set_mode(struct snd_soc_codec *codec, int mode) {
  1211. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  1212. +
  1213. +   if(DBG) printk("%s mode=%d\n",__func__,mode);
  1214. +
  1215. +   if(rt5640->dsp_sw == mode)
  1216. +       return 0;
  1217. +   rt5640->dsp_sw = mode;
  1218. +
  1219. +   if(rt5640->dsp_sw == RT5640_DSP_DIS) {
  1220. +       rt5640->dsp_play_pass = rt5640->dsp_rec_pass = 1;
  1221. +       snd_soc_update_bits(codec, RT5640_DSP_PATH1,
  1222. +           RT5640_RXDP_SRC_MASK | RT5640_TXDP_SRC_MASK, 0);
  1223. +       snd_soc_update_bits(codec, RT5640_ASRC_1,
  1224. +           RT5640_M1_T_MASK, RT5640_M1_T_I2S2);
  1225. +   } else {
  1226. +       rt5640->dsp_play_pass = rt5640->dsp_rec_pass = 0;
  1227. +   }
  1228. +   rt5640_conn_mux_path(codec, "SDI1 TX Mux",
  1229. +       rt5640->dsp_play_pass ? "IF1" : "IF2");
  1230. +   //Stereo DAC MIXL
  1231. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXL",
  1232. +            "DAC L1 Switch", rt5640->dsp_play_pass);
  1233. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXL",
  1234. +                "DAC L2 Switch", !rt5640->dsp_play_pass);
  1235. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXR",
  1236. +            "DAC R1 Switch", rt5640->dsp_play_pass);
  1237. +   rt5640_conn_mixer_path(codec, "Stereo DAC MIXR",
  1238. +                "DAC R2 Switch", !rt5640->dsp_play_pass);
  1239. +   //Stereo ADC MIXL
  1240. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXL", "ADC1 Switch", true);
  1241. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXR", "ADC1 Switch", true);
  1242. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXL",
  1243. +       "ADC2 Switch", rt5640->dsp_rec_pass);
  1244. +   rt5640_conn_mixer_path(codec, "Stereo ADC MIXR",
  1245. +       "ADC2 Switch", rt5640->dsp_rec_pass);
  1246. +   //Mono ADC MIXL
  1247. +   rt5640_conn_mixer_path(codec, "Mono ADC MIXL",
  1248. +       "ADC2 Switch", !rt5640->dsp_rec_pass);
  1249. +   rt5640_conn_mixer_path(codec, "Mono ADC MIXR",
  1250. +       "ADC2 Switch", !rt5640->dsp_rec_pass);
  1251. +   return 0;
  1252. +}
  1253. +
  1254. +EXPORT_SYMBOL_GPL(do_rt5640_dsp_set_mode);
  1255. +
  1256. +#ifdef RTK_IOCTL
  1257. +int rt56xx_dsp_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
  1258. +{
  1259. +   struct rt56xx_cmd rt56xx;
  1260. +   int *buf;
  1261. +   int *p;
  1262. +   int ret;
  1263. +   struct rt5640_dsp_param param;
  1264. +  
  1265. +   //int mask1 = 0, mask2 = 0;
  1266. +
  1267. +   struct rt56xx_cmd __user *_rt56xx =(struct rt56xx_cmd *)arg;
  1268. +   struct snd_soc_codec *codec = hw->private_data;
  1269. +   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  1270. +
  1271. +   if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) {
  1272. +       printk("copy_from_user faild\n");
  1273. +       return -EFAULT;
  1274. +   }
  1275. +   if(DBG) printk("rt56xx.number=%d\n",rt56xx.number);
  1276. +   buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
  1277. +   if (buf == NULL)
  1278. +       return -ENOMEM;
  1279. +   if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
  1280. +       goto err;
  1281. +   }
  1282. +  
  1283. +   ret = snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1284. +       RT5640_PWR_I2S_DSP, RT5640_PWR_I2S_DSP);
  1285. +   if (ret < 0) {
  1286. +       dev_err(codec->dev,
  1287. +           "Failed to power up DSP IIS interface: %d\n", ret);
  1288. +       goto err;
  1289. +   }
  1290. +   /*
  1291. +   ret = rt5640_dsp_conf(codec);
  1292. +   if (ret < 0)
  1293. +       goto err;
  1294. +   */
  1295. +  
  1296. +   switch (cmd) {
  1297. +   case RT_READ_CODEC_DSP_IOCTL:
  1298. +       if(DBG) printk(" case RT_READ_CODEC_DSP_IOCTL\n");
  1299. +      
  1300. +       for (p = buf; p < buf + rt56xx.number/2; p++)
  1301. +       {
  1302. +           *(p+rt56xx.number/2) = rt5640_dsp_read(codec, *p);
  1303. +       }
  1304. +       if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
  1305. +           goto err;
  1306. +          
  1307. +       break;
  1308. +   case RT_WRITE_CODEC_DSP_IOCTL:
  1309. +       if(DBG) printk(" case RT_WRITE_CODEC_DSP_IOCTL\n");
  1310. +      
  1311. +       param.cmd_fmt =  0x00e0;
  1312. +       param.cmd =  RT5640_DSP_CMD_MW;
  1313. +       p = buf;
  1314. +       param.addr = *p;
  1315. +       param.data = *(p+rt56xx.number/2);
  1316. +       if(codec == NULL)
  1317. +       {
  1318. +           printk("codec = null\n");
  1319. +           break;
  1320. +       }
  1321. +       for (p = buf; p < buf + rt56xx.number/2; p++)
  1322. +           rt5640_dsp_write(codec, &param);
  1323. +       break;
  1324. +   case RT_GET_CODEC_DSP_MODE_IOCTL:
  1325. +       if(DBG) printk("case RT_GET_CODEC_DSP_MODE_IOCTL\n");
  1326. +      
  1327. +       *buf = rt5640->dsp_sw;
  1328. +       if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
  1329. +           goto err;
  1330. +       break;
  1331. +   default:
  1332. +       printk("unsported dsp command\n");
  1333. +       break;
  1334. +   }
  1335. +
  1336. +   kfree(buf);
  1337. +   return 0;
  1338. +
  1339. +err:
  1340. +   kfree(buf);
  1341. +   return -EFAULT;
  1342. +
  1343. +}
  1344. +EXPORT_SYMBOL_GPL(rt56xx_dsp_ioctl_common);
  1345. +#endif
  1346. +
  1347. +#ifdef CONFIG_PM
  1348. +int rt5640_dsp_suspend(struct snd_soc_codec *codec, pm_message_t state)
  1349. +{
  1350. +   struct rt5640_dsp_param param;
  1351. +   int ret;
  1352. +
  1353. +   if (RT5640_VER_C == snd_soc_read(codec, RT5640_VENDOR_ID))
  1354. +       return 0;
  1355. +
  1356. +   ret = snd_soc_update_bits(codec, RT5640_PWR_DIG2,
  1357. +       RT5640_PWR_I2S_DSP, RT5640_PWR_I2S_DSP);
  1358. +   if (ret < 0) {
  1359. +       dev_err(codec->dev,
  1360. +           "Failed to power up DSP IIS interface: %d\n", ret);
  1361. +       goto rsm_err;
  1362. +   }
  1363. +
  1364. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  1365. +       RT5640_DSP_PD_PIN_MASK, RT5640_DSP_PD_PIN_HI);
  1366. +   if (ret < 0) {
  1367. +       dev_err(codec->dev, "Failed to power up DSP: %d\n", ret);
  1368. +       goto rsm_err;
  1369. +   }
  1370. +
  1371. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  1372. +       RT5640_DSP_RST_PIN_MASK, RT5640_DSP_RST_PIN_LO);
  1373. +   if (ret < 0) {
  1374. +       dev_err(codec->dev, "Failed to reset DSP: %d\n", ret);
  1375. +       goto rsm_err;
  1376. +   }
  1377. +
  1378. +   mdelay(10);
  1379. +
  1380. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  1381. +       RT5640_DSP_RST_PIN_MASK, RT5640_DSP_RST_PIN_HI);
  1382. +   if (ret < 0) {
  1383. +       dev_err(codec->dev, "Failed to recover DSP: %d\n", ret);
  1384. +       goto rsm_err;
  1385. +   }
  1386. +
  1387. +   param.cmd_fmt =  0x00e0;
  1388. +   param.addr = 0x3fd2;
  1389. +   param.data = 0x0030;
  1390. +   param.cmd =  RT5640_DSP_CMD_MW;
  1391. +   ret = rt5640_dsp_write(codec, &param);
  1392. +   if (ret < 0) {
  1393. +       dev_err(codec->dev,
  1394. +           "Failed to Power up LDO of Dsp: %d\n", ret);
  1395. +       goto rsm_err;
  1396. +   }
  1397. +
  1398. +   ret = snd_soc_update_bits(codec, RT5640_DSP_CTRL3,
  1399. +       RT5640_DSP_PD_PIN_MASK, RT5640_DSP_PD_PIN_LO);
  1400. +   if (ret < 0) {
  1401. +       dev_err(codec->dev, "Failed to power down DSP: %d\n", ret);
  1402. +       goto rsm_err;
  1403. +   }
  1404. +
  1405. +   return 0;
  1406. +
  1407. +rsm_err:
  1408. +
  1409. +   return ret;
  1410. +}
  1411. +EXPORT_SYMBOL_GPL(rt5640_dsp_suspend);
  1412. +
  1413. +int rt5640_dsp_resume(struct snd_soc_codec *codec)
  1414. +{
  1415. +   return 0;
  1416. +}
  1417. +EXPORT_SYMBOL_GPL(rt5640_dsp_resume);
  1418. +#endif
  1419. +
  1420. diff --git a/sound/soc/codecs/rt5640-dsp.h b/sound/soc/codecs/rt5640-dsp.h
  1421. new file mode 100644
  1422. index 0000000..6616267
  1423. --- /dev/null
  1424. +++ b/sound/soc/codecs/rt5640-dsp.h
  1425. @@ -0,0 +1,44 @@
  1426. +/*
  1427. + * rt5640-dsp.h  --  RT5640 ALSA SoC DSP driver
  1428. + *
  1429. + * Copyright 2011 Realtek Microelectronics
  1430. + * Author: Johnny Hsu <johnnyhsu@realtek.com>
  1431. + *
  1432. + * This program is free software; you can redistribute it and/or modify
  1433. + * it under the terms of the GNU General Public License version 2 as
  1434. + * published by the Free Software Foundation.
  1435. + */
  1436. +
  1437. +#ifndef __RT5640_DSP_H__
  1438. +#define __RT5640_DSP_H__
  1439. +
  1440. +/* Debug String Length */
  1441. +#define RT5640_DSP_REG_DISP_LEN 12
  1442. +
  1443. +enum {
  1444. +   RT5640_DSP_DIS,
  1445. +   RT5640_DSP_AEC_NS_FENS,
  1446. +   RT5640_DSP_HFBF,
  1447. +   RT5640_DSP_FFP,
  1448. +};
  1449. +
  1450. +struct rt5640_dsp_param {
  1451. +   u16 cmd_fmt;
  1452. +   u16 addr;
  1453. +   u16 data;
  1454. +   u8 cmd;
  1455. +};
  1456. +
  1457. +int rt5640_dsp_probe(struct snd_soc_codec *codec);
  1458. +int do_rt5640_dsp_set_mode(struct snd_soc_codec *codec, int mode);
  1459. +#ifdef RTK_IOCTL
  1460. +int rt56xx_dsp_ioctl_common(struct snd_hwdep *hw, struct file *file,
  1461. +   unsigned int cmd, unsigned long arg);
  1462. +#endif
  1463. +#ifdef CONFIG_PM
  1464. +int rt5640_dsp_suspend(struct snd_soc_codec *codec, pm_message_t state);
  1465. +int rt5640_dsp_resume(struct snd_soc_codec *codec);
  1466. +#endif
  1467. +
  1468. +#endif /* __RT5640_DSP_H__ */
  1469. +
  1470. diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
  1471. index e3d0af0..03b5aca 100644
  1472. --- a/sound/soc/codecs/rt5640.c
  1473. +++ b/sound/soc/codecs/rt5640.c
  1474. @@ -3,6 +3,7 @@
  1475.   *
  1476.   * Copyright 2011 Realtek Semiconductor Corp.
  1477.   * Author: Johnny Hsu <johnnyhsu@realtek.com>
  1478. + *
  1479.   * This program is free software; you can redistribute it and/or modify
  1480.   * it under the terms of the GNU General Public License version 2 as
  1481.   * published by the Free Software Foundation.
  1482. @@ -23,88 +24,266 @@
  1483.  #include <sound/soc-dapm.h>
  1484.  #include <sound/initval.h>
  1485.  #include <sound/tlv.h>
  1486. +#include <mach/board-grouper-misc.h>
  1487. +#include <mach/pinmux.h>
  1488. +#include "../board.h"
  1489. +#include "../board-grouper.h"
  1490. +
  1491. +#include <linux/input.h>
  1492. +#include <linux/debugfs.h>
  1493. +#include <linux/cdev.h>
  1494. +#include <linux/slab.h>
  1495. +#include <linux/gpio.h>
  1496. +
  1497. +#define RTK_IOCTL
  1498. +#ifdef RTK_IOCTL
  1499. +#include "rt56xx_ioctl.h"
  1500. +#define DBG 1
  1501. +#define VIRTUAL_REG_FOR_MISC_FUNC 0x99
  1502. +#endif
  1503.  
  1504. +#define AUDIO_IOC_MAGIC    0xf7
  1505. +#define AUDIO_CAPTURE_MODE _IOW(AUDIO_IOC_MAGIC, 6,int)
  1506. +#define AUDIO_STRESS_TEST  _IOW(AUDIO_IOC_MAGIC, 1,int)
  1507. +#define AUDIO_IOCTL_START_HEAVY (2)
  1508. +#define AUDIO_IOCTL_START_NORMAL (1)
  1509. +#define AUDIO_IOCTL_STOP (0)
  1510. +#define START_NORMAL (HZ/2)
  1511. +#define START_HEAVY (HZ/20)
  1512. +
  1513. +#define INPUT_SOURCE_NORMAL 100
  1514. +#define INPUT_SOURCE_VR 101
  1515. +#define OUTPUT_SOURCE_NORMAL    200
  1516. +#define OUTPUT_SOURCE_VOICE 201
  1517. +#define INPUT_SOURCE_NO_AGC 300
  1518. +#define INPUT_SOURCE_AGC 301
  1519. +#define END_RECORDING 400
  1520. +#define STOP_COMMUNICATION 401
  1521. +#define START_COMMUNICATION 402
  1522. +
  1523. +static int input_source=INPUT_SOURCE_NORMAL;
  1524. +static int output_source=OUTPUT_SOURCE_NORMAL;
  1525. +static int input_agc = INPUT_SOURCE_NO_AGC;
  1526. +
  1527. +static int poll_rate = 0;
  1528. +static struct delayed_work poll_audio_work;
  1529. +static int count_base = 1;
  1530. +static int count_100 = 0;
  1531. +static int hp_amp_count = 0;
  1532.  #include "rt5640.h"
  1533. -#if (CONFIG_SND_SOC_RT5642_MODULE | CONFIG_SND_SOC_RT5642)
  1534. +#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
  1535.  #include "rt5640-dsp.h"
  1536.  #endif
  1537.  
  1538. -#define RT5640_DEMO 1
  1539. -#define RT5640_REG_RW 1
  1540. -#define RT5640_DET_EXT_MIC 0
  1541. +#define RT5640_REG_RW 1 /* for debug */
  1542. +struct snd_soc_codec *rt5640_audio_codec = NULL;
  1543. +EXPORT_SYMBOL(rt5640_audio_codec);
  1544. +static struct rt5640_priv *rt5640_dsp = NULL;
  1545.  
  1546. -#ifdef RT5640_DEMO
  1547.  struct rt5640_init_reg {
  1548.     u8 reg;
  1549.     u16 val;
  1550.  };
  1551.  
  1552.  static struct rt5640_init_reg init_list[] = {
  1553. -   {RT5640_DUMMY1      , 0x3701},/*fa[12:13] = 1'b;fa[8~10]=1;fa[0]=1*/
  1554. -   {RT5640_DEPOP_M1    , 0x0019},/* 8e[4:3] = 11'b; 8e[0] = 1'b */
  1555. -   {RT5640_DEPOP_M2    , 0x3100},/* 8f[13] = 1'b */
  1556. -   {RT5640_ADDA_CLK1   , 0x1114},/* 73[2] = 1'b  */
  1557. -   {RT5640_MICBIAS     , 0x3030},/* 93[5:4] = 11'b */
  1558. -   {RT5640_PRIV_INDEX  , 0x003d},/* PR3d[12] = 1'b */
  1559. -   {RT5640_PRIV_DATA   , 0x3600},
  1560. -   {RT5640_CLS_D_OUT   , 0xa000},/* 8d[11] = 0'b */
  1561. -   {RT5640_PRIV_INDEX  , 0x001c},/* PR1c = 0D21'h */
  1562. -   {RT5640_PRIV_DATA   , 0x0D21},
  1563. -   {RT5640_PRIV_INDEX  , 0x001b},/* PR1B = 0D21'h */
  1564. -   {RT5640_PRIV_DATA   , 0x0000},
  1565. -   {RT5640_PRIV_INDEX  , 0x0012},/* PR12 = 0aa8'h */
  1566. +   {RT5640_DUMMY1      , 0x3701},//fa[12:13] = 1'b; fa[8~10]=1; fa[0]=1
  1567. +   {RT5640_ADDA_CLK1   , 0x1114},//73[2] = 1'b
  1568. +   {RT5640_MICBIAS     , 0x3030},//93[5:4] = 11'b
  1569. +   {RT5640_CLS_D_OUT   , 0xa000},//8d[11] = 0'b
  1570. +   {RT5640_PRIV_INDEX  , 0x003d},//PR3d[12] = 0'b; PR3d[9] = 1'b
  1571. +   {RT5640_PRIV_DATA   , 0x2600},
  1572. +   {RT5640_PRIV_INDEX  , 0x0012},//PR12 = 0aa8'h
  1573.     {RT5640_PRIV_DATA   , 0x0aa8},
  1574. -   {RT5640_PRIV_INDEX  , 0x0014},/* PR14 = 0aaa'h */
  1575. -   {RT5640_PRIV_DATA   , 0x0aaa},
  1576. -   {RT5640_PRIV_INDEX  , 0x0020},/* PR20 = 6110'h */
  1577. -   {RT5640_PRIV_DATA   , 0x6110},
  1578. -   {RT5640_PRIV_INDEX  , 0x0021},/* PR21 = e0e0'h */
  1579. -   {RT5640_PRIV_DATA   , 0xe0e0},
  1580. -   {RT5640_PRIV_INDEX  , 0x0023},/* PR23 = 1804'h */
  1581. -   {RT5640_PRIV_DATA   , 0x1804},
  1582. +   {RT5640_PRIV_INDEX  , 0x0014},//PR14 = 8aaa'h
  1583. +   {RT5640_PRIV_DATA   , 0x8aaa},
  1584. +   {RT5640_PRIV_INDEX  , 0x0020},//PR20 = 6115'h
  1585. +   {RT5640_PRIV_DATA   , 0x6115},
  1586. +   {RT5640_PRIV_INDEX  , 0x0023},//PR23 = 0804'h
  1587. +   {RT5640_PRIV_DATA   , 0x0804},
  1588.     /*playback*/
  1589. -   {RT5640_STO_DAC_MIXER   , 0x1414},/*Dig inf 1 -> Sto DAC mixer -> DACL*/
  1590. -   {RT5640_OUT_L3_MIXER    , 0x01fe},/*DACL1 -> OUTMIXL*/
  1591. -   {RT5640_OUT_R3_MIXER    , 0x01fe},/*DACR1 -> OUTMIXR */
  1592. -   {RT5640_HP_VOL      , 0x8888},/* OUTMIX -> HPVOL */
  1593. -   {RT5640_HPO_MIXER   , 0xc000},/* HPVOL -> HPOLMIX */
  1594. -/* {RT5640_HPO_MIXER   , 0xa000},// DAC1 -> HPOLMIX   */
  1595. -   {RT5640_SPK_L_MIXER , 0x0036},/* DACL1 -> SPKMIXL */
  1596. -   {RT5640_SPK_R_MIXER , 0x0036},/* DACR1 -> SPKMIXR */
  1597. -   {RT5640_SPK_VOL     , 0x8888},/* SPKMIX -> SPKVOL */
  1598. -   {RT5640_SPO_L_MIXER , 0xe800},/* SPKVOLL -> SPOLMIX */
  1599. -   {RT5640_SPO_R_MIXER , 0x2800},/* SPKVOLR -> SPORMIX */
  1600. -/* {RT5640_SPO_L_MIXER , 0xb800},//DAC -> SPOLMIX */
  1601. -/* {RT5640_SPO_R_MIXER , 0x1800},//DAC -> SPORMIX */
  1602. -/* {RT5640_I2S1_SDP    , 0xD000},//change IIS1 and IIS2 */
  1603. +   {RT5640_STO_DAC_MIXER   , 0x1414},//Dig inf 1 -> Sto DAC mixer -> DACL
  1604. +   {RT5640_OUT_L3_MIXER    , 0x01fe},//DACL1 -> OUTMIXL
  1605. +   {RT5640_OUT_R3_MIXER    , 0x01fe},//DACR1 -> OUTMIXR
  1606. +   {RT5640_HP_VOL      , 0x8888},//OUTMIX -> HPVOL
  1607. +   {RT5640_HPO_MIXER   , 0xc000},//HPVOL -> HPOLMIX
  1608. +// {RT5640_HPO_MIXER   , 0xa000},//DAC1 -> HPOLMIX
  1609. +   {RT5640_SPK_L_MIXER , 0x0036},//DACL1 -> SPKMIXL
  1610. +   {RT5640_SPK_R_MIXER , 0x0036},//DACR1 -> SPKMIXR
  1611. +   {RT5640_SPK_VOL     , 0x8a8a},//SPKMIX -> SPKVOL
  1612. +   {RT5640_SPO_L_MIXER , 0xe800},//SPKVOLL -> SPOLMIX
  1613. +   {RT5640_SPO_R_MIXER , 0x2800},//SPKVOLR -> SPORMIX
  1614. +// {RT5640_SPO_L_MIXER , 0xb800},//DAC -> SPOLMIX
  1615. +// {RT5640_SPO_R_MIXER , 0x1800},//DAC -> SPORMIX
  1616. +   {RT5640_I2S1_SDP    , 0x8000},//change IIS1 and IIS2
  1617.     /*record*/
  1618. -   {RT5640_IN1_IN2     , 0x5080},/*IN1 boost 40db & differential mode*/
  1619. -   {RT5640_IN3_IN4     , 0x0500},/*IN2 boost 40db & signal ended mode*/
  1620. -   {RT5640_REC_L2_MIXER    , 0x005f},/* enable Mic1 -> RECMIXL */
  1621. -   {RT5640_REC_R2_MIXER    , 0x005f},/* enable Mic1 -> RECMIXR */
  1622. -/* {RT5640_REC_L2_MIXER    , 0x006f},//Mic2 -> RECMIXL */
  1623. -/* {RT5640_REC_R2_MIXER    , 0x006f},//Mic2 -> RECMIXR */
  1624. -   {RT5640_STO_ADC_MIXER   , 0x3020},/* ADC -> Sto ADC mixer */
  1625. -
  1626. -#if RT5640_DET_EXT_MIC
  1627. +   {RT5640_IN1_IN2     , 0x5080},//IN1 boost 40db and differential mode
  1628. +   {RT5640_IN3_IN4     , 0x0840},//IN2 boost 52db and differential mode
  1629. +// {RT5640_REC_L2_MIXER    , 0x007d},//Mic1 -> RECMIXL
  1630. +// {RT5640_REC_R2_MIXER    , 0x007d},//Mic1 -> RECMIXR
  1631. +   {RT5640_REC_L2_MIXER    , 0x006f},//Mic2 -> RECMIXL
  1632. +   {RT5640_REC_R2_MIXER    , 0x006f},//Mic2 -> RECMIXR
  1633. +   {RT5640_STO_ADC_MIXER   , 0x1000},//ADC -> Sto ADC mixer
  1634. +#ifdef RT5640_DET_EXT_MIC
  1635.     {RT5640_MICBIAS , 0x3800},/* enable MICBIAS short current */
  1636.     {RT5640_GPIO_CTRL1  , 0x8400},/* set GPIO1 to IRQ */
  1637.     {RT5640_GPIO_CTRL3  , 0x0004},/* set GPIO1 output */
  1638.     {RT5640_IRQ_CTRL2   , 0x8000},/*set MICBIAS short current to IRQ */
  1639. -                   /*( if sticky set regBE : 8800 ) */
  1640.  #endif
  1641. -
  1642. +   {RT5640_CHARGE_PUMP , 0x0f00},
  1643. +   {RT5640_PRIV_INDEX  , 0x0090},
  1644. +   {RT5640_PRIV_DATA   , 0x2000},
  1645. +   {RT5640_PRIV_INDEX  , 0x0091},
  1646. +   {RT5640_PRIV_DATA   , 0x1000},
  1647. +   {RT5640_STO_DAC_MIXER   , 0x0404},
  1648. +   {RT5640_LOUT_MIXER  , 0x3000},
  1649. +   {RT5640_I2S1_SDP    , 0xe000},
  1650. +   {RT5640_DSP_PATH2   , 0x0000},
  1651. +   {RT5640_PRIV_INDEX      , 0x006e},
  1652. +   {RT5640_PRIV_DATA       , 0x3159},
  1653.  };
  1654.  #define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
  1655.  
  1656. +
  1657. +static void audio_codec_stress(struct work_struct *work __attribute__((unused)))
  1658. +{
  1659. +   u16 temp;
  1660. +
  1661. +   if((count_base % 2))
  1662. +       temp = snd_soc_write(rt5640_audio_codec, RT5640_OUTPUT, 0xCACA); /* write codec register 0x03 to 0xCACA */
  1663. +   else
  1664. +       temp = snd_soc_write(rt5640_audio_codec, RT5640_OUTPUT, 0xCBCB); /* write codec register 0x03 to 0xCACA */
  1665. +
  1666. +   temp = snd_soc_read(rt5640_audio_codec, RT5640_OUTPUT); /* write codec register 0x03 to 0xCACA */
  1667. +
  1668. +   if((count_base % 2)){
  1669. +       if(temp != 0xCACA)
  1670. +           printk("tegra.i2c-4:audio codec rt5642 write fail\n");
  1671. +   }else{
  1672. +       if(temp != 0xCBCB)
  1673. +           printk("tegra.i2c-4:audio codec rt5642 write fail\n");
  1674. +   }
  1675. +
  1676. +   count_base = count_base+1;
  1677. +
  1678. +   if (count_base == 100){
  1679. +       count_base = 0;
  1680. +       count_100 = count_100 + 1;
  1681. +       printk("AUDIO_CODEC: count = %d (* 100), the register 0x03h is %x\n",count_100,temp);
  1682. +   }
  1683. +
  1684. +   schedule_delayed_work(&poll_audio_work, poll_rate);
  1685. +}
  1686. +
  1687. +int rt5640_conn_mux_path(struct snd_soc_codec *codec,
  1688. +       char *widget_name, char *path_name)
  1689. +{
  1690. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  1691. +   struct snd_soc_dapm_widget *w;
  1692. +   struct snd_soc_dapm_path *path;
  1693. +   const struct snd_kcontrol_new *kcontrol;
  1694. +   struct soc_enum *em;
  1695. +   unsigned int val, mask, bitmask;
  1696. +   int i;
  1697. +   if (codec == NULL || widget_name == NULL || path_name == NULL)
  1698. +       return -EINVAL;
  1699. +   list_for_each_entry(w, &dapm->card->widgets, list)
  1700. +   {
  1701. +       if (!w->name || w->dapm != dapm)
  1702. +           continue;
  1703. +       if (!(strcmp(w->name, widget_name))) {
  1704. +           dev_info(codec->dev, "w->name=%s\n", w->name);
  1705. +           list_for_each_entry(path, &w->sources, list_sink)
  1706. +           {
  1707. +               if (!(strcmp(path->name, path_name)))
  1708. +                   path->connect = 1;
  1709. +               else
  1710. +                   path->connect = 0;
  1711. +               dev_info(codec->dev,
  1712. +                   "path->name=%s path->connect=%d\n",
  1713. +                   path->name, path->connect);
  1714. +           }
  1715. +           break;
  1716. +       }
  1717. +   }
  1718. +   snd_soc_dapm_sync(dapm);
  1719. +   kcontrol = &w->kcontrol_news[0];
  1720. +   em = (struct soc_enum *)kcontrol->private_value;
  1721. +   for (i = 0; i < em->max; i++)
  1722. +       if (!(strcmp(path_name, em->texts[i])))
  1723. +           break;
  1724. +   for (bitmask = 1; bitmask < em->max; bitmask <<= 1)
  1725. +       ;
  1726. +   val = i << em->shift_l;
  1727. +   mask = (bitmask - 1) << em->shift_l;
  1728. +   snd_soc_update_bits(codec, em->reg, mask, val);
  1729. +   return 0;
  1730. +}
  1731. +EXPORT_SYMBOL(rt5640_conn_mux_path);
  1732. +
  1733. +//*************************************************************************************************
  1734. +//EQ parameter
  1735. +//*************************************************************************************************
  1736. +enum
  1737. +{
  1738. +   NORMAL=0,
  1739. +   CLUB,
  1740. +   DANCE,
  1741. +   LIVE,
  1742. +   POP,
  1743. +   ROCK,
  1744. +   OPPO,
  1745. +   TREBLE,
  1746. +   BASS,
  1747. +   NAKASI,
  1748. +};
  1749. +
  1750. +typedef struct  _HW_EQ_PRESET
  1751. +{
  1752. +   u16     HwEqType;
  1753. +   u16     EqValue[22];
  1754. +   u16  HwEQCtrl;
  1755. +
  1756. +}HW_EQ_PRESET;
  1757. +
  1758. +
  1759. +static HW_EQ_PRESET HwEq_Preset[]={
  1760. +/*          0xA0   0xA1   0xA2   0xA3   0xA4   0xA5   0xA6   0xA7   0xA8   0xA9   0xAA   0xAB   0xAC,  0xAD   0xAE   0xAF   0xB0   0xB1   0xB2    0xB0*/
  1761. +   {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000},
  1762. +   {CLUB  ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0000,0x0000,0x0000,0x0436,0x0000,0x0000,0x0000,0x0000},0x000E},
  1763. +   {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0000,0x0000,0x0000,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F},
  1764. +   {LIVE  ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0000,0x0000,0x0000,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F},
  1765. +   {POP   ,{0x1EB5,0xFCB6,0xC1D4,0x1E5D,0x0E23,0xD92E,0x16E6,0xFCB6,0x0000,0x0969,0xF988,0x0000,0x0000,0x0000,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F},
  1766. +   {ROCK  ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0000,0x0000,0x0000,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F},
  1767. +   {OPPO  ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x000F},
  1768. +   {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699,0x0000,0x0000,0x0000},0x0020},
  1769. +   {BASS  ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0001},
  1770. +   {NAKASI,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1EF8,0x0000,0x1F77,0x00E4,0x1F79},0x0160},
  1771. +};
  1772. +
  1773. +//*************************************************************************************************
  1774. +//*************************************************************************************************
  1775. +
  1776.  static int rt5640_reg_init(struct snd_soc_codec *codec)
  1777.  {
  1778.     int i;
  1779. +
  1780.     for (i = 0; i < RT5640_INIT_REG_LEN; i++)
  1781.         snd_soc_write(codec, init_list[i].reg, init_list[i].val);
  1782. +
  1783. +   return 0;
  1784. +}
  1785. +
  1786. +static int rt5640_index_sync(struct snd_soc_codec *codec)
  1787. +{
  1788. +   int i;
  1789. +
  1790. +   for (i = 0; i < RT5640_INIT_REG_LEN; i++)
  1791. +       if (RT5640_PRIV_INDEX == init_list[i].reg ||
  1792. +           RT5640_PRIV_DATA == init_list[i].reg)
  1793. +           snd_soc_write(codec, init_list[i].reg,
  1794. +                   init_list[i].val);
  1795.     return 0;
  1796.  }
  1797. -#endif
  1798.  
  1799.  static const u16 rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
  1800.     [RT5640_RESET] = 0x000c,
  1801. @@ -134,7 +313,7 @@ static const u16 rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
  1802.     [RT5640_SPO_CLSD_RATIO] = 0x0004,
  1803.     [RT5640_MONO_MIXER] = 0xfc00,
  1804.     [RT5640_OUT_L3_MIXER] = 0x01ff,
  1805. -   [RT5640_OUT_R3_MIXER] = 0x01ff,
  1806. +   [RT5640_OUT_R3_MIXER] = 0x01ff,
  1807.     [RT5640_LOUT_MIXER] = 0xf000,
  1808.     [RT5640_PWR_ANLG1] = 0x00c0,
  1809.     [RT5640_I2S1_SDP] = 0x8000,
  1810. @@ -271,6 +450,48 @@ err:
  1811.     return ret;
  1812.  }
  1813.  
  1814. +//*************************************************************************************************
  1815. +//for EQ function
  1816. +//*************************************************************************************************
  1817. +static void rt5640_update_eqmode(struct snd_soc_codec *codec, int mode)
  1818. +{
  1819. +   u16 HwEqIndex=0;
  1820. +
  1821. +   if(mode==NORMAL)
  1822. +   {
  1823. +       /*clear EQ parameter*/
  1824. +       for(HwEqIndex=0;HwEqIndex<=0x12;HwEqIndex++)
  1825. +       {
  1826. +           rt5640_index_write(codec, HwEqIndex+0xA0, HwEq_Preset[mode].EqValue[HwEqIndex]);
  1827. +       }
  1828. +
  1829. +       snd_soc_update_bits(codec,0xb1,0x007f,0x0000);  //disable Hardware LP,BP1,BP2,BP3,HP1,HP2 block Control
  1830. +
  1831. +       //rt5640_index_update_bits(codec,0x11,0x8000,0x0000);       /*disable EQ block*/
  1832. +       snd_soc_update_bits(codec, 0xb0,0x6000,0x6000);
  1833. +       snd_soc_update_bits(codec, 0xb0,0x6000,0x0000);
  1834. +   }
  1835. +   else
  1836. +   {
  1837. +       //rt5640_index_update_bits(codec,0x11,0x8000,0x8000);   /*enable EQ block*/
  1838. +
  1839. +       snd_soc_write(codec,0xb1,HwEq_Preset[mode].HwEQCtrl);
  1840. +
  1841. +       /*Fill EQ parameter*/
  1842. +       for(HwEqIndex=0;HwEqIndex<=0x12;HwEqIndex++)
  1843. +       {
  1844. +           rt5640_index_write(codec, HwEqIndex+0xA0,HwEq_Preset[mode].EqValue[HwEqIndex]);
  1845. +       }
  1846. +       //update EQ parameter
  1847. +       //snd_soc_update_bits(codec, 0xb0,0xE000,0xE000);
  1848. +       //snd_soc_update_bits(codec, 0xb0,0x6000,0x0000); //clean the bits
  1849. +       snd_soc_write(codec, 0xb0,0x6000);
  1850. +   }
  1851. +}
  1852. +
  1853. +//*************************************************************************************************
  1854. +//*************************************************************************************************
  1855. +
  1856.  static int rt5640_volatile_register(
  1857.     struct snd_soc_codec *codec, unsigned int reg)
  1858.  {
  1859. @@ -419,41 +640,103 @@ static int rt5640_readable_register(
  1860.     }
  1861.  }
  1862.  
  1863. -int rt5640_headset_detect(struct snd_soc_codec *codec, int jack_insert)
  1864. +static void dc_calibrate(struct snd_soc_codec *codec)
  1865.  {
  1866. -   int jack_type;
  1867. +   unsigned int sclk_src;
  1868.  
  1869. -   if (jack_insert) {
  1870. -       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  1871. -           RT5640_PWR_LDO2, RT5640_PWR_LDO2);
  1872. -       snd_soc_update_bits(codec, RT5640_PWR_ANLG2,
  1873. -           RT5640_PWR_MB1, RT5640_PWR_MB1);
  1874. -       snd_soc_update_bits(codec, RT5640_MICBIAS,
  1875. -           RT5640_MIC1_OVCD_MASK | RT5640_MIC1_OVTH_MASK |
  1876. -           RT5640_PWR_CLK25M_MASK | RT5640_PWR_MB_MASK,
  1877. -           RT5640_MIC1_OVCD_EN | RT5640_MIC1_OVTH_600UA |
  1878. -           RT5640_PWR_MB_PU | RT5640_PWR_CLK25M_PU);
  1879. -       snd_soc_update_bits(codec, RT5640_DUMMY1,
  1880. -           0x1, 0x1);
  1881. -       msleep(50);
  1882. -       if (snd_soc_read(codec, RT5640_IRQ_CTRL2) & 0x8)
  1883. -           jack_type = RT5640_HEADPHO_DET;
  1884. -       else
  1885. -           jack_type = RT5640_HEADSET_DET;
  1886. -       snd_soc_update_bits(codec, RT5640_IRQ_CTRL2,
  1887. -           RT5640_MB1_OC_CLR, 0);
  1888. -   } else {
  1889. -       snd_soc_update_bits(codec, RT5640_MICBIAS,
  1890. -           RT5640_MIC1_OVCD_MASK,
  1891. -           RT5640_MIC1_OVCD_DIS);
  1892. -
  1893. -       jack_type = RT5640_NO_JACK;
  1894. -   }
  1895. +   sclk_src = snd_soc_read(codec, RT5640_GLB_CLK) &
  1896. +       RT5640_SCLK_SRC_MASK;
  1897. +
  1898. +   snd_soc_update_bits(codec, RT5640_PWR_ANLG2,
  1899. +       RT5640_PWR_MB1, RT5640_PWR_MB1);
  1900. +   snd_soc_update_bits(codec, RT5640_DEPOP_M2,
  1901. +       RT5640_DEPOP_MASK, RT5640_DEPOP_MAN);
  1902. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  1903. +       RT5640_HP_CP_MASK | RT5640_HP_SG_MASK | RT5640_HP_CB_MASK,
  1904. +       RT5640_HP_CP_PU | RT5640_HP_SG_DIS | RT5640_HP_CB_PU);
  1905.  
  1906. -   return jack_type;
  1907. +   snd_soc_update_bits(codec, RT5640_GLB_CLK,
  1908. +       RT5640_SCLK_SRC_MASK, 0x2 << RT5640_SCLK_SRC_SFT);
  1909. +
  1910. +   rt5640_index_write(codec, RT5640_HP_DCC_INT1, 0x9f00);
  1911. +   snd_soc_update_bits(codec, RT5640_PWR_ANLG2,
  1912. +       RT5640_PWR_MB1, 0);
  1913. +   snd_soc_update_bits(codec, RT5640_GLB_CLK,
  1914. +       RT5640_SCLK_SRC_MASK, sclk_src);
  1915.  }
  1916. -EXPORT_SYMBOL(rt5640_headset_detect);
  1917.  
  1918. +/**
  1919. + * rt5640_conn_mixer_path - connect mixer widget path.
  1920. + * @codec: SoC audio codec device.
  1921. + * @widget_name: widget name.
  1922. + * @path_name: path name.
  1923. + * @turn: enable or disable.
  1924. + *
  1925. + * Make mixer path connected and update register.
  1926. + *
  1927. + * Returns 0 for success or negative error code.
  1928. + */
  1929. +int rt5640_conn_mixer_path(struct snd_soc_codec *codec,
  1930. +   char *widget_name, char *path_name, bool turn)
  1931. +{
  1932. +   struct snd_soc_dapm_context *dapm = &codec->dapm;
  1933. +   struct snd_soc_dapm_widget *w;
  1934. +   struct snd_soc_dapm_path *path;
  1935. +   const struct snd_kcontrol *kcontrol;
  1936. +   struct soc_mixer_control *mc;
  1937. +   unsigned int val, mask;
  1938. +   int i, update = 0;
  1939. +
  1940. +   if (codec == NULL || widget_name == NULL || path_name == NULL)
  1941. +       return -EINVAL;
  1942. +
  1943. +   list_for_each_entry(w, &dapm->card->widgets, list)
  1944. +   {
  1945. +       if (!w->name || w->dapm != dapm)
  1946. +           continue;
  1947. +       if (!(strcmp(w->name, widget_name))) {
  1948. +           if (w->id != snd_soc_dapm_mixer)
  1949. +               return -EINVAL;
  1950. +           dev_info(codec->dev, "w->name=%s\n", w->name);
  1951. +           list_for_each_entry(path, &w->sources, list_sink)
  1952. +           {
  1953. +               if (path->name &&
  1954. +                   !(strcmp(path->name, path_name))) {
  1955. +                   path->connect = turn;
  1956. +                   dev_info(codec->dev,
  1957. +                       "path->name=%s connect=%d\n",
  1958. +                       path->name, path->connect);
  1959. +                   break;
  1960. +               }
  1961. +           }
  1962. +           update = 1;
  1963. +           break;
  1964. +       }
  1965. +   }
  1966. +
  1967. +   if (update) {
  1968. +       snd_soc_dapm_sync(dapm);
  1969. +
  1970. +       kcontrol = w->kcontrols[0];
  1971. +       for (i = 0; i < w->num_kcontrols; i++) {
  1972. +           if (!strcmp(path_name, w->kcontrol_news[i].name)) {
  1973. +               mc = (struct soc_mixer_control *)
  1974. +                   w->kcontrol_news[i].private_value;
  1975. +               mask = (1 << fls(mc->max)) - 1;
  1976. +               val = turn;
  1977. +               if (mc->invert)
  1978. +                   val = mc->max - val;
  1979. +               mask = mask << mc->shift;
  1980. +               val = val << mc->shift;
  1981. +               snd_soc_update_bits(codec, mc->reg, mask, val);
  1982. +               break;
  1983. +           }
  1984. +       }
  1985. +   }
  1986. +
  1987. +   return 0;
  1988. +}
  1989. +EXPORT_SYMBOL(rt5640_conn_mixer_path);
  1990.  static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
  1991.  static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
  1992.  static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
  1993. @@ -556,7 +839,7 @@ static const SOC_ENUM_SINGLE_DECL(
  1994.  
  1995.  /* Interface data select */
  1996.  static const char *rt5640_data_select[] = {
  1997. -   "Normal", "left copy to right", "right copy to left", "Swap"};
  1998. +   "Normal", "swap", "left copy to right", "right copy to left"};
  1999.  
  2000.  static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
  2001.                 RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
  2002. @@ -595,7 +878,8 @@ static const SOC_ENUM_SINGLE_DECL(rt5640_dmic_enum, 0, 0, rt5640_dmic_mode);
  2003.  #define REGVAL_MAX 0xffff
  2004.  static unsigned int regctl_addr;
  2005.  static int rt5640_regctl_info(struct snd_kcontrol *kcontrol,
  2006. -           struct snd_ctl_elem_info *uinfo) {
  2007. +           struct snd_ctl_elem_info *uinfo)
  2008. +{
  2009.     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  2010.     uinfo->count = 2;
  2011.     uinfo->value.integer.min = 0;
  2012. @@ -617,17 +901,13 @@ static int rt5640_regctl_put(struct snd_kcontrol *kcontrol,
  2013.  {
  2014.     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  2015.     regctl_addr = ucontrol->value.integer.value[0];
  2016. -   if (ucontrol->value.integer.value[1] <= REGVAL_MAX)
  2017. -       snd_soc_write(codec, regctl_addr,
  2018. -       ucontrol->value.integer.value[1]);
  2019. +   if(ucontrol->value.integer.value[1] <= REGVAL_MAX)
  2020. +       snd_soc_write(codec, regctl_addr, ucontrol->value.integer.value[1]);
  2021.     return 0;
  2022.  }
  2023.  #endif
  2024.  
  2025.  
  2026. -#define VOL_RESCALE_MAX_VOL 0x27 /* 39 */
  2027. -#define VOL_RESCALE_MIX_RANGE 0x1F /* 31 */
  2028. -
  2029.  static int rt5640_vol_rescale_get(struct snd_kcontrol *kcontrol,
  2030.         struct snd_ctl_elem_value *ucontrol)
  2031.  {
  2032. @@ -636,9 +916,9 @@ static int rt5640_vol_rescale_get(struct snd_kcontrol *kcontrol,
  2033.     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  2034.     unsigned int val = snd_soc_read(codec, mc->reg);
  2035.  
  2036. -   ucontrol->value.integer.value[0] = VOL_RESCALE_MAX_VOL -
  2037. +   ucontrol->value.integer.value[0] = RT5640_VOL_RSCL_MAX -
  2038.         ((val & RT5640_L_VOL_MASK) >> mc->shift);
  2039. -   ucontrol->value.integer.value[1] = VOL_RESCALE_MAX_VOL -
  2040. +   ucontrol->value.integer.value[1] = RT5640_VOL_RSCL_MAX -
  2041.         (val & RT5640_R_VOL_MASK);
  2042.  
  2043.     return 0;
  2044. @@ -652,8 +932,8 @@ static int rt5640_vol_rescale_put(struct snd_kcontrol *kcontrol,
  2045.     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  2046.     unsigned int val, val2;
  2047.  
  2048. -   val = VOL_RESCALE_MAX_VOL - ucontrol->value.integer.value[0];
  2049. -   val2 = VOL_RESCALE_MAX_VOL - ucontrol->value.integer.value[1];
  2050. +   val = RT5640_VOL_RSCL_MAX - ucontrol->value.integer.value[0];
  2051. +   val2 = RT5640_VOL_RSCL_MAX - ucontrol->value.integer.value[1];
  2052.     return snd_soc_update_bits_locked(codec, mc->reg, RT5640_L_VOL_MASK |
  2053.             RT5640_R_VOL_MASK, val << mc->shift | val2);
  2054.  }
  2055. @@ -661,18 +941,17 @@ static int rt5640_vol_rescale_put(struct snd_kcontrol *kcontrol,
  2056.  
  2057.  static const struct snd_kcontrol_new rt5640_snd_controls[] = {
  2058.     /* Speaker Output Volume */
  2059. +   SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
  2060. +       RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
  2061.     SOC_DOUBLE_EXT_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
  2062. -       RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, VOL_RESCALE_MIX_RANGE, 0,
  2063. +       RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, RT5640_VOL_RSCL_RANGE, 0,
  2064.         rt5640_vol_rescale_get, rt5640_vol_rescale_put, out_vol_tlv),
  2065. -
  2066.     /* Headphone Output Volume */
  2067.     SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
  2068.         RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
  2069. -
  2070.     SOC_DOUBLE_EXT_TLV("HP Playback Volume", RT5640_HP_VOL,
  2071. -       RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, VOL_RESCALE_MIX_RANGE, 0,
  2072. +       RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, RT5640_VOL_RSCL_RANGE, 0,
  2073.         rt5640_vol_rescale_get, rt5640_vol_rescale_put, out_vol_tlv),
  2074. -
  2075.     /* OUTPUT Control */
  2076.     SOC_DOUBLE("OUT Playback Switch", RT5640_OUTPUT,
  2077.         RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
  2078. @@ -721,6 +1000,8 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
  2079.     /* DMIC */
  2080.     SOC_ENUM_EXT("DMIC Switch", rt5640_dmic_enum,
  2081.         rt5640_dmic_get, rt5640_dmic_put),
  2082. +   SOC_ENUM("ADC IF1 SWITCH", rt5640_if1_adc_enum),
  2083. +   SOC_ENUM("DAC IF1 SWITCH", rt5640_if1_dac_enum),
  2084.  
  2085.  #ifdef RT5640_REG_RW
  2086.     {
  2087. @@ -777,7 +1058,7 @@ static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
  2088.  
  2089.     val = snd_soc_read(source->codec, RT5640_GLB_CLK);
  2090.     val &= RT5640_SCLK_SRC_MASK;
  2091. -   if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T)
  2092. +   if (val == RT5640_SCLK_SRC_PLL1)
  2093.         return 1;
  2094.     else
  2095.         return 0;
  2096. @@ -1075,9 +1356,8 @@ static const SOC_ENUM_SINGLE_DECL(
  2097.  static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux =
  2098.     SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum);
  2099.  
  2100. -static const char *rt5640_mono_adc_l2_src[] = {
  2101. -   "DMIC L1", "DMIC L2", "Mono DAC MIXL"
  2102. -};
  2103. +static const char *rt5640_mono_adc_l2_src[] =
  2104. +   {"DMIC L1", "DMIC L2", "Mono DAC MIXL"};
  2105.  
  2106.  static const SOC_ENUM_SINGLE_DECL(
  2107.     rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
  2108. @@ -1095,9 +1375,8 @@ static const SOC_ENUM_SINGLE_DECL(
  2109.  static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux =
  2110.     SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum);
  2111.  
  2112. -static const char *rt5640_mono_adc_r2_src[] = {
  2113. -   "DMIC R1", "DMIC R2", "Mono DAC MIXR"
  2114. -};
  2115. +static const char *rt5640_mono_adc_r2_src[] =
  2116. +   {"DMIC R1", "DMIC R2", "Mono DAC MIXR"};
  2117.  
  2118.  static const SOC_ENUM_SINGLE_DECL(
  2119.     rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
  2120. @@ -1163,52 +1442,283 @@ static const SOC_ENUM_SINGLE_DECL(
  2121.  static const struct snd_kcontrol_new rt5640_sdi_mux =
  2122.     SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
  2123.  
  2124. -static int spk_event(struct snd_soc_dapm_widget *w,
  2125. +static int mono_adc_mixer_event(struct snd_soc_dapm_widget *w,
  2126.     struct snd_kcontrol *kcontrol, int event)
  2127.  {
  2128.     struct snd_soc_codec *codec = w->codec;
  2129. -   static unsigned int spkl_out_enable;
  2130. -   static unsigned int spkr_out_enable;
  2131. +   unsigned int val, mask;
  2132.  
  2133.     switch (event) {
  2134.     case SND_SOC_DAPM_POST_PMU:
  2135. -       pr_info("spk_event --SND_SOC_DAPM_POST_PMU\n");
  2136. -       snd_soc_update_bits(codec, RT5640_PWR_DIG1, 0x0001, 0x0001);
  2137. -       rt5640_index_update_bits(codec, 0x1c, 0xf000, 0xf000);
  2138. -       /* rt5640_index_write(codec, 0x1c, 0xfd21); */
  2139. +       val = snd_soc_read(codec, RT5640_MONO_ADC_MIXER);
  2140. +       mask = RT5640_M_MONO_ADC_L1 | RT5640_M_MONO_ADC_L2 |
  2141. +           RT5640_M_MONO_ADC_R1 | RT5640_M_MONO_ADC_R2;
  2142. +       if ((val & mask) ^ mask)
  2143. +           snd_soc_update_bits(codec, RT5640_DUMMY1,
  2144. +           RT5640_M_MAMIX_L | RT5640_M_MAMIX_R, 0);
  2145. +       break;
  2146. +
  2147. +   case SND_SOC_DAPM_POST_PMD:
  2148. +       snd_soc_update_bits(codec, RT5640_DUMMY1,
  2149. +           RT5640_M_MAMIX_L | RT5640_M_MAMIX_R,
  2150. +           RT5640_M_MAMIX_L | RT5640_M_MAMIX_R);
  2151. +       break;
  2152. +   default:
  2153. +       return 0;
  2154. +   }
  2155. +   return 0;
  2156. +}
  2157. +static int rt5640_adc_event(struct snd_soc_dapm_widget *w,
  2158. +   struct snd_kcontrol *kcontrol, int event)
  2159. +{
  2160. +   struct snd_soc_codec *codec = w->codec;
  2161. +   switch (event) {
  2162. +   case SND_SOC_DAPM_POST_PMU:
  2163. +       usleep_range(1000, 1500);
  2164. +       rt5640_index_update_bits(codec,
  2165. +           RT5640_CHOP_DAC_ADC, 0x1000, 0x1000);
  2166. +       break;
  2167. +   case SND_SOC_DAPM_PRE_PMU:
  2168. +       snd_soc_update_bits(codec, RT5640_STO_ADC_MIXER,
  2169. +           0x5040, 0x5040);
  2170. +       break;
  2171. +   case SND_SOC_DAPM_POST_PMD:
  2172. +       rt5640_index_update_bits(codec,
  2173. +           RT5640_CHOP_DAC_ADC, 0x1000, 0x0000);
  2174. +       break;
  2175. +
  2176. +   default:
  2177. +       return 0;
  2178. +   }
  2179. +
  2180. +   return 0;
  2181. +}
  2182. +
  2183. +static int rt5640_spk_event(struct snd_soc_dapm_widget *w,
  2184. +       struct snd_kcontrol *kcontrol, int event)
  2185. +{
  2186. +   struct snd_soc_codec *codec = w->codec;
  2187. +
  2188. +   switch (event) {
  2189. +   case SND_SOC_DAPM_POST_PMU:
  2190. +       usleep_range(1000, 1500); /* depop delay */
  2191. +       snd_soc_update_bits(codec, RT5640_PWR_DIG1,
  2192. +           RT5640_PWR_CLS_D, RT5640_PWR_CLS_D);
  2193. +       rt5640_index_update_bits(codec,
  2194. +           RT5640_CLSD_INT_REG1, 0xf000, 0xf000);
  2195. +       /*Enable  DRC */
  2196. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2197. +           RT5640_DRC_AGC_P_MASK | RT5640_DRC_AGC_MASK |
  2198. +           RT5640_DRC_AGC_UPD,
  2199. +           RT5640_DRC_AGC_P_DAC | RT5640_DRC_AGC_EN |
  2200. +           RT5640_DRC_AGC_UPD);
  2201. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
  2202. +           RT5640_DRC_AGC_PRB_MASK,
  2203. +           0x0003);
  2204. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_3,
  2205. +           RT5640_DRC_AGC_TAR_MASK,
  2206. +           0x0080);
  2207. +       snd_soc_update_bits(codec, RT5640_SPK_VOL,
  2208. +           RT5640_L_MUTE | RT5640_R_MUTE, 0);
  2209. +       rt5640_update_eqmode(codec,NAKASI);
  2210. +       break;
  2211. +
  2212. +   case SND_SOC_DAPM_PRE_PMD:
  2213. +       snd_soc_update_bits(codec, RT5640_SPK_VOL,
  2214. +           RT5640_L_MUTE | RT5640_R_MUTE,
  2215. +           RT5640_L_MUTE | RT5640_R_MUTE);
  2216. +       /*Disable DRC */
  2217. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2218. +           RT5640_DRC_AGC_P_MASK | RT5640_DRC_AGC_MASK |
  2219. +           RT5640_DRC_AGC_UPD, RT5640_DRC_AGC_UPD);
  2220. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
  2221. +           RT5640_DRC_AGC_PRB_MASK,
  2222. +           0x0000);
  2223. +       snd_soc_update_bits(codec, RT5640_DRC_AGC_3,
  2224. +           RT5640_DRC_AGC_TAR_MASK,
  2225. +           0x0000);
  2226. +       rt5640_index_update_bits(codec,
  2227. +           RT5640_CLSD_INT_REG1, 0xf000, 0x0000);
  2228. +       snd_soc_update_bits(codec, RT5640_PWR_DIG1,
  2229. +           RT5640_PWR_CLS_D, 0);
  2230. +       rt5640_update_eqmode(codec,NORMAL);
  2231. +       break;
  2232. +
  2233. +   default:
  2234. +       return 0;
  2235. +   }
  2236. +
  2237. +   return 0;
  2238. +}
  2239. +
  2240. +static void rt5640_pmu_depop(struct snd_soc_codec *codec)
  2241. +{
  2242. +   if (hp_amp_count == 0) {
  2243. +       /* depop parameters */
  2244. +       snd_soc_update_bits(codec, RT5640_DEPOP_M2,
  2245. +           RT5640_DEPOP_MASK, RT5640_DEPOP_MAN);
  2246. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2247. +           RT5640_HP_CP_MASK | RT5640_HP_SG_MASK |
  2248. +                   RT5640_HP_CB_MASK,
  2249. +           RT5640_HP_CP_PU | RT5640_HP_SG_DIS | RT5640_HP_CB_PU);
  2250. +       /* headphone amp power on */
  2251. +       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2252. +           RT5640_PWR_FV1 | RT5640_PWR_FV2, 0);
  2253. +       snd_soc_update_bits(codec, RT5640_PWR_VOL,
  2254. +           RT5640_PWR_HV_L | RT5640_PWR_HV_R,
  2255. +           RT5640_PWR_HV_L | RT5640_PWR_HV_R);
  2256. +       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2257. +           RT5640_PWR_HP_L | RT5640_PWR_HP_R | RT5640_PWR_HA,
  2258. +           RT5640_PWR_HP_L | RT5640_PWR_HP_R | RT5640_PWR_HA);
  2259. +       /* wait for power to be stable to depop */
  2260. +       usleep_range(5000, 6000);
  2261. +       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2262. +           RT5640_PWR_FV1 | RT5640_PWR_FV2,
  2263. +           RT5640_PWR_FV1 | RT5640_PWR_FV2);
  2264. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2265. +           RT5640_HP_CO_MASK | RT5640_HP_SG_MASK,
  2266. +           RT5640_HP_CO_EN | RT5640_HP_SG_EN);
  2267. +       /* headphone unmute sequence */
  2268. +       snd_soc_update_bits(codec, RT5640_DEPOP_M3,
  2269. +           RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK |
  2270. +                   RT5640_CP_FQ3_MASK,
  2271. +           (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ1_SFT) |
  2272. +           (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
  2273. +           (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ3_SFT));
  2274. +       rt5640_index_write(codec, RT5640_MAMP_INT_REG2, 0xfc00);
  2275. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2276. +           RT5640_SMT_TRIG_MASK, RT5640_SMT_TRIG_EN);
  2277. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2278. +           RT5640_RSTN_MASK, RT5640_RSTN_EN);
  2279. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2280. +           RT5640_RSTN_MASK | RT5640_HP_L_SMT_MASK |
  2281. +                   RT5640_HP_R_SMT_MASK,
  2282. +           RT5640_RSTN_DIS | RT5640_HP_L_SMT_EN |
  2283. +                   RT5640_HP_R_SMT_EN);
  2284. +       snd_soc_update_bits(codec, RT5640_HP_VOL,
  2285. +           RT5640_L_MUTE | RT5640_R_MUTE, 0);
  2286. +       usleep_range(40000, 41000);
  2287. +       snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2288. +           RT5640_HP_SG_MASK | RT5640_HP_L_SMT_MASK |
  2289. +           RT5640_HP_R_SMT_MASK, RT5640_HP_SG_DIS |
  2290. +           RT5640_HP_L_SMT_DIS | RT5640_HP_R_SMT_DIS);
  2291. +   }
  2292. +   hp_amp_count++;
  2293. +}
  2294. +
  2295. +static void rt5640_pmd_depop(struct snd_soc_codec *codec)
  2296. +{
  2297. +
  2298. +   if (--hp_amp_count) {
  2299. +       hp_amp_count = 0;
  2300. +       return;
  2301. +   }
  2302. +   /* headphone mute sequence */
  2303. +   snd_soc_update_bits(codec, RT5640_DEPOP_M3,
  2304. +       RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK | RT5640_CP_FQ3_MASK,
  2305. +       (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ1_SFT) |
  2306. +       (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
  2307. +       (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ3_SFT));
  2308. +   rt5640_index_write(codec, RT5640_MAMP_INT_REG2, 0xfc00);
  2309. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2310. +       RT5640_HP_SG_MASK, RT5640_HP_SG_EN);
  2311. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2312. +       RT5640_RSTP_MASK, RT5640_RSTP_EN);
  2313. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2314. +       RT5640_RSTP_MASK | RT5640_HP_L_SMT_MASK |
  2315. +       RT5640_HP_R_SMT_MASK, RT5640_RSTP_DIS |
  2316. +       RT5640_HP_L_SMT_EN | RT5640_HP_R_SMT_EN);
  2317. +   snd_soc_update_bits(codec, RT5640_HP_VOL,
  2318. +       RT5640_L_MUTE | RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2319. +   msleep(30);
  2320. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2321. +       RT5640_HP_SG_MASK | RT5640_HP_L_SMT_MASK |
  2322. +       RT5640_HP_R_SMT_MASK, RT5640_HP_SG_DIS |
  2323. +       RT5640_HP_L_SMT_DIS | RT5640_HP_R_SMT_DIS);
  2324. +   /* headphone amp power down */
  2325. +   snd_soc_update_bits(codec, RT5640_DEPOP_M1,
  2326. +       RT5640_SMT_TRIG_MASK | RT5640_HP_CD_PD_MASK |
  2327. +       RT5640_HP_CO_MASK | RT5640_HP_CP_MASK |
  2328. +       RT5640_HP_SG_MASK | RT5640_HP_CB_MASK,
  2329. +       RT5640_SMT_TRIG_DIS | RT5640_HP_CD_PD_EN |
  2330. +       RT5640_HP_CO_DIS | RT5640_HP_CP_PD |
  2331. +       RT5640_HP_SG_EN | RT5640_HP_CB_PD);
  2332. +   snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2333. +       RT5640_PWR_HP_L | RT5640_PWR_HP_R | RT5640_PWR_HA,
  2334. +       0);
  2335. +}
  2336. +
  2337. +static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
  2338. +   struct snd_kcontrol *kcontrol, int event)
  2339. +{
  2340. +   struct snd_soc_codec *codec = w->codec;
  2341. +   unsigned int val;
  2342. +
  2343. +   switch (event) {
  2344. +   case SND_SOC_DAPM_POST_PMU:
  2345. +       val = snd_soc_read(codec,0xb1);
  2346. +       snd_soc_update_bits(codec,0xb1,0x007f,0x0000);
  2347. +       rt5640_pmu_depop(codec);
  2348. +       snd_soc_write(codec,0xb1,val);
  2349. +       snd_soc_write(codec,0xb0,0x6000);
  2350.         break;
  2351.  
  2352.     case SND_SOC_DAPM_PRE_PMD:
  2353. -       pr_info("spk_event --SND_SOC_DAPM_POST_PMD\n");
  2354. -       /* rt5640_index_write(codec, 0x1c, 0xfd00); */
  2355. -       rt5640_index_update_bits(codec, 0x1c, 0xf000, 0x0000);
  2356. -       snd_soc_update_bits(codec, RT5640_PWR_DIG1, 0x0001, 0x0000);
  2357. +       rt5640_pmd_depop(codec);
  2358. +       break;
  2359. +   default:
  2360. +       return 0;
  2361. +   }
  2362. +
  2363. +   return 0;
  2364. +}
  2365. +
  2366. +static int rt5640_mono_event(struct snd_soc_dapm_widget *w,
  2367. +   struct snd_kcontrol *kcontrol, int event)
  2368. +{
  2369. +   struct snd_soc_codec *codec = w->codec;
  2370. +
  2371. +   switch (event) {
  2372. +   case SND_SOC_DAPM_POST_PMU:
  2373. +       snd_soc_update_bits(codec, RT5640_MONO_OUT,
  2374. +               RT5640_L_MUTE, 0);
  2375. +       break;
  2376. +
  2377. +   case SND_SOC_DAPM_PRE_PMD:
  2378. +       snd_soc_update_bits(codec, RT5640_MONO_OUT,
  2379. +           RT5640_L_MUTE, RT5640_L_MUTE);
  2380.         break;
  2381.  
  2382.     default:
  2383.         return 0;
  2384.     }
  2385. +
  2386.     return 0;
  2387.  }
  2388.  
  2389. -static int hp_event(struct snd_soc_dapm_widget *w,
  2390. +static int rt5640_lout_event(struct snd_soc_dapm_widget *w,
  2391.     struct snd_kcontrol *kcontrol, int event)
  2392.  {
  2393.     struct snd_soc_codec *codec = w->codec;
  2394. -   static unsigned int hp_out_enable;
  2395.  
  2396.     switch (event) {
  2397.     case SND_SOC_DAPM_POST_PMU:
  2398. -       pr_info("hp_event --SND_SOC_DAPM_POST_PMU\n");
  2399. +       rt5640_pmu_depop(codec);
  2400. +       snd_soc_update_bits(codec, RT5640_OUTPUT,
  2401. +           RT5640_L_MUTE | RT5640_R_MUTE, 0);
  2402.         break;
  2403.  
  2404.     case SND_SOC_DAPM_PRE_PMD:
  2405. -       pr_info("hp_event --SND_SOC_DAPM_POST_PMD\n");
  2406. +       snd_soc_update_bits(codec, RT5640_OUTPUT,
  2407. +           RT5640_L_MUTE | RT5640_R_MUTE,
  2408. +           RT5640_L_MUTE | RT5640_R_MUTE);
  2409. +       rt5640_pmd_depop(codec);
  2410.         break;
  2411.  
  2412.     default:
  2413.         return 0;
  2414.     }
  2415. +
  2416.     return 0;
  2417.  }
  2418.  
  2419. @@ -1224,11 +1734,11 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2420.     SND_SOC_DAPM_MICBIAS("micbias2", RT5640_PWR_ANLG2,
  2421.             RT5640_PWR_MB2_BIT, 0),
  2422.     /* Input Lines */
  2423. -
  2424.     SND_SOC_DAPM_INPUT("MIC1"),
  2425.     SND_SOC_DAPM_INPUT("MIC2"),
  2426.     SND_SOC_DAPM_INPUT("DMIC1"),
  2427.     SND_SOC_DAPM_INPUT("DMIC2"),
  2428. +
  2429.     SND_SOC_DAPM_INPUT("IN1P"),
  2430.     SND_SOC_DAPM_INPUT("IN1N"),
  2431.     SND_SOC_DAPM_INPUT("IN2P"),
  2432. @@ -1258,10 +1768,12 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2433.     SND_SOC_DAPM_MIXER("RECMIXR", RT5640_PWR_MIXER, RT5640_PWR_RM_R_BIT, 0,
  2434.             rt5640_rec_r_mix, ARRAY_SIZE(rt5640_rec_r_mix)),
  2435.     /* ADCs */
  2436. -   SND_SOC_DAPM_ADC("ADC L", NULL, RT5640_PWR_DIG1,
  2437. -           RT5640_PWR_ADC_L_BIT, 0),
  2438. -   SND_SOC_DAPM_ADC("ADC R", NULL, RT5640_PWR_DIG1,
  2439. -           RT5640_PWR_ADC_R_BIT, 0),
  2440. +   SND_SOC_DAPM_ADC_E("ADC L", NULL, RT5640_PWR_DIG1,
  2441. +       RT5640_PWR_ADC_L_BIT, 0, rt5640_adc_event,
  2442. +       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
  2443. +   SND_SOC_DAPM_ADC_E("ADC R", NULL, RT5640_PWR_DIG1,
  2444. +       RT5640_PWR_ADC_R_BIT, 0, rt5640_adc_event,
  2445. +       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
  2446.     /* ADC Mux */
  2447.     SND_SOC_DAPM_MUX("Stereo ADC L2 Mux", SND_SOC_NOPM, 0, 0,
  2448.                 &rt5640_sto_adc_l2_mux),
  2449. @@ -1288,13 +1800,14 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2450.         rt5640_sto_adc_r_mix, ARRAY_SIZE(rt5640_sto_adc_r_mix)),
  2451.     SND_SOC_DAPM_SUPPLY("mono left filter", RT5640_PWR_DIG2,
  2452.         RT5640_PWR_ADC_MF_L_BIT, 0, NULL, 0),
  2453. -   SND_SOC_DAPM_MIXER("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
  2454. -       rt5640_mono_adc_l_mix, ARRAY_SIZE(rt5640_mono_adc_l_mix)),
  2455. +   SND_SOC_DAPM_MIXER_E("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
  2456. +       rt5640_mono_adc_l_mix, ARRAY_SIZE(rt5640_mono_adc_l_mix),
  2457. +       mono_adc_mixer_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
  2458.     SND_SOC_DAPM_SUPPLY("mono right filter", RT5640_PWR_DIG2,
  2459.         RT5640_PWR_ADC_MF_R_BIT, 0, NULL, 0),
  2460. -   SND_SOC_DAPM_MIXER("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
  2461. -       rt5640_mono_adc_r_mix, ARRAY_SIZE(rt5640_mono_adc_r_mix)),
  2462. -
  2463. +   SND_SOC_DAPM_MIXER_E("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
  2464. +       rt5640_mono_adc_r_mix, ARRAY_SIZE(rt5640_mono_adc_r_mix),
  2465. +       mono_adc_mixer_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
  2466.     /* IF2 Mux */
  2467.     SND_SOC_DAPM_MUX("IF2 ADC L Mux", SND_SOC_NOPM, 0, 0,
  2468.                 &rt5640_if2_adc_l_mux),
  2469. @@ -1320,7 +1833,7 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2470.     SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
  2471.     SND_SOC_DAPM_SUPPLY("I2S3", RT5640_PWR_DIG1,
  2472.         RT5640_PWR_I2S3_BIT, 0, NULL, 0),
  2473. -   SND_SOC_DAPM_PGA("IF3 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
  2474. +   SND_SOC_DAPM_PGA("IF3 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
  2475.     SND_SOC_DAPM_PGA("IF3 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
  2476.     SND_SOC_DAPM_PGA("IF3 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
  2477.     SND_SOC_DAPM_PGA("IF3 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
  2478. @@ -1369,6 +1882,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2479.                 &rt5640_dac_l2_mux),
  2480.     SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
  2481.                 &rt5640_dac_r2_mux),
  2482. +   SND_SOC_DAPM_PGA("DAC L2 Volume", RT5640_PWR_DIG1,
  2483. +           RT5640_PWR_DAC_L2_BIT, 0, NULL, 0),
  2484. +   SND_SOC_DAPM_PGA("DAC R2 Volume", RT5640_PWR_DIG1,
  2485. +           RT5640_PWR_DAC_R2_BIT, 0, NULL, 0),
  2486.  
  2487.     /* DAC Mixer */
  2488.     SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
  2489. @@ -1415,11 +1932,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2490.     SND_SOC_DAPM_PGA("HPOVOL R", RT5640_PWR_VOL,
  2491.         RT5640_PWR_HV_R_BIT, 0, NULL, 0),
  2492.     /* SPO/HPO/LOUT/Mono Mixer */
  2493. -   SND_SOC_DAPM_MIXER("SPOL MIX", SND_SOC_NOPM, 0,
  2494. +   SND_SOC_DAPM_MIXER("SPOL MIX",SND_SOC_NOPM, 0,
  2495.         0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)),
  2496.     SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0,
  2497.         0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)),
  2498. -
  2499.     SND_SOC_DAPM_MIXER("HPOL MIX", SND_SOC_NOPM, 0, 0,
  2500.         rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
  2501.     SND_SOC_DAPM_MIXER("HPOR MIX", SND_SOC_NOPM, 0, 0,
  2502. @@ -1429,21 +1945,17 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
  2503.     SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
  2504.         rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
  2505.  
  2506. -   SND_SOC_DAPM_SUPPLY("Improve mono amp drv", RT5640_PWR_ANLG1,
  2507. -       RT5640_PWR_MA_BIT, 0, NULL, 0),
  2508. -
  2509. -   SND_SOC_DAPM_SUPPLY("Improve HP amp drv", RT5640_PWR_ANLG1,
  2510. -   SND_SOC_NOPM, 0, hp_event, SND_SOC_DAPM_PRE_PMD |
  2511. -                   SND_SOC_DAPM_POST_PMU),
  2512. +   SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0,
  2513. +       rt5640_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
  2514.  
  2515. -   SND_SOC_DAPM_PGA("HP L amp", RT5640_PWR_ANLG1,
  2516. -       RT5640_PWR_HP_L_BIT, 0, NULL, 0),
  2517. +   SND_SOC_DAPM_PGA_S("SPK amp", 1, SND_SOC_NOPM, 0, 0,
  2518. +       rt5640_spk_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
  2519.  
  2520. -   SND_SOC_DAPM_PGA("HP R amp", RT5640_PWR_ANLG1,
  2521. -       RT5640_PWR_HP_R_BIT, 0, NULL, 0),
  2522. +   SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0,
  2523. +       rt5640_lout_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
  2524.  
  2525. -   SND_SOC_DAPM_SUPPLY("Improve SPK amp drv", RT5640_PWR_DIG1,
  2526. -       SND_SOC_NOPM, 0, spk_event,
  2527. +   SND_SOC_DAPM_PGA_S("Mono amp", 1, RT5640_PWR_ANLG1,
  2528. +       RT5640_PWR_MA_BIT, 0, rt5640_mono_event,
  2529.         SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
  2530.  
  2531.     /* Output Lines */
  2532. @@ -1655,28 +2167,30 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
  2533.     {"DAC L2 Mux", "IF2", "IF2 DAC L"},
  2534.     {"DAC L2 Mux", "IF3", "IF3 DAC L"},
  2535.     {"DAC L2 Mux", "Base L/R", "Audio DSP"},
  2536. +   {"DAC L2 Volume", NULL, "DAC L2 Mux"},
  2537.  
  2538.     {"DAC R2 Mux", "IF2", "IF2 DAC R"},
  2539.     {"DAC R2 Mux", "IF3", "IF3 DAC R"},
  2540. +   {"DAC R2 Volume", NULL, "DAC R2 Mux"},
  2541.  
  2542.     {"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
  2543. -   {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
  2544. +   {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume"},
  2545.     {"Stereo DAC MIXL", "ANC Switch", "ANC"},
  2546.     {"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
  2547. -   {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
  2548. +   {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume"},
  2549.     {"Stereo DAC MIXR", "ANC Switch", "ANC"},
  2550.  
  2551.     {"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
  2552. -   {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
  2553. -   {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
  2554. +   {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume"},
  2555. +   {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume"},
  2556.     {"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
  2557. -   {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
  2558. -   {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
  2559. +   {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume"},
  2560. +   {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume"},
  2561.  
  2562.     {"DIG MIXL", "DAC L1 Switch", "DAC MIXL"},
  2563. -   {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
  2564. +   {"DIG MIXL", "DAC L2 Switch", "DAC L2 Volume"},
  2565.     {"DIG MIXR", "DAC R1 Switch", "DAC MIXR"},
  2566. -   {"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
  2567. +   {"DIG MIXR", "DAC R2 Switch", "DAC R2 Volume"},
  2568.  
  2569.     {"DAC L1", NULL, "Stereo DAC MIXL"},
  2570.     {"DAC L1", NULL, "PLL1", check_sysclk1_source},
  2571. @@ -1749,39 +2263,32 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
  2572.     {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
  2573.     {"Mono MIX", "BST1 Switch", "BST1"},
  2574.  
  2575. -   {"HP L amp", NULL, "HPOL MIX"},
  2576. -   {"HP R amp", NULL, "HPOR MIX"},
  2577. -
  2578. -/* {"HP L amp", NULL, "Improve HP amp drv"},
  2579. -   {"HP R amp", NULL, "Improve HP amp drv"}, */
  2580. -
  2581. -   {"SPOLP", NULL, "SPOL MIX"},
  2582. -   {"SPOLN", NULL, "SPOL MIX"},
  2583. -   {"SPORP", NULL, "SPOR MIX"},
  2584. -   {"SPORN", NULL, "SPOR MIX"},
  2585. -
  2586. -   {"SPOLP", NULL, "Improve SPK amp drv"},
  2587. -   {"SPOLN", NULL, "Improve SPK amp drv"},
  2588. -   {"SPORP", NULL, "Improve SPK amp drv"},
  2589. -   {"SPORN", NULL, "Improve SPK amp drv"},
  2590. -
  2591. -   {"HPOL", NULL, "Improve HP amp drv"},
  2592. -   {"HPOR", NULL, "Improve HP amp drv"},
  2593. -
  2594. -   {"HPOL", NULL, "HP L amp"},
  2595. -   {"HPOR", NULL, "HP R amp"},
  2596. -   {"LOUTL", NULL, "LOUT MIX"},
  2597. -   {"LOUTR", NULL, "LOUT MIX"},
  2598. -   {"MonoP", NULL, "Mono MIX"},
  2599. -   {"MonoN", NULL, "Mono MIX"},
  2600. -   {"MonoP", NULL, "Improve mono amp drv"},
  2601. +   {"SPK amp", NULL, "SPOL MIX"},
  2602. +   {"SPK amp", NULL, "SPOR MIX"},
  2603. +   {"SPOLP", NULL, "SPK amp"},
  2604. +   {"SPOLN", NULL, "SPK amp"},
  2605. +   {"SPORP", NULL, "SPK amp"},
  2606. +   {"SPORN", NULL, "SPK amp"},
  2607. +
  2608. +   {"HP amp", NULL, "HPOL MIX"},
  2609. +   {"HP amp", NULL, "HPOR MIX"},
  2610. +   {"HPOL", NULL, "HP amp"},
  2611. +   {"HPOR", NULL, "HP amp"},
  2612. +
  2613. +   {"LOUT amp", NULL, "LOUT MIX"},
  2614. +   {"LOUTL", NULL, "LOUT amp"},
  2615. +   {"LOUTR", NULL, "LOUT amp"},
  2616. +
  2617. +   {"Mono amp", NULL, "Mono MIX"},
  2618. +   {"MonoP", NULL, "Mono amp"},
  2619. +   {"MonoN", NULL, "Mono amp"},
  2620.  };
  2621.  
  2622.  static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
  2623.  {
  2624.     int ret = 0, val = snd_soc_read(codec, RT5640_I2S1_SDP);
  2625.  
  2626. -   if (codec == NULL)
  2627. +   if(codec == NULL)
  2628.         return -EINVAL;
  2629.  
  2630.     val = (val & RT5640_I2S_IF_MASK) >> RT5640_I2S_IF_SFT;
  2631. @@ -1808,9 +2315,8 @@ static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
  2632.             ret |= RT5640_U_IF3;
  2633.         break;
  2634.  
  2635. -#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
  2636. -           CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
  2637. -
  2638. +#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
  2639. +    defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
  2640.     case RT5640_AIF3:
  2641.         if (val == RT5640_IF_312 || val == RT5640_IF_321)
  2642.             ret |= RT5640_U_IF1;
  2643. @@ -1834,7 +2340,7 @@ static int get_clk_info(int sclk, int rate)
  2644.  {
  2645.     int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
  2646.  
  2647. -   if (sclk <= 0 || rate <= 0)
  2648. +   if(sclk <= 0 || rate <= 0)
  2649.         return -EINVAL;
  2650.  
  2651.     rate = rate << 8;
  2652. @@ -1895,7 +2401,7 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
  2653.         return -EINVAL;
  2654.     }
  2655.     if (dai_sel & RT5640_U_IF1) {
  2656. -       mask_clk = RT5640_I2S_BCLK_MS1_MASK | RT5640_I2S_PD1_MASK;
  2657. +       mask_clk = RT5640_I2S_BCLK_MS1_MASK | RT5640_I2S_PD1_MASK;
  2658.         val_clk = bclk_ms << RT5640_I2S_BCLK_MS1_SFT |
  2659.             pre_div << RT5640_I2S_PD1_SFT;
  2660.         snd_soc_update_bits(codec, RT5640_I2S1_SDP,
  2661. @@ -1910,8 +2416,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
  2662.             RT5640_I2S_DL_MASK, val_len);
  2663.         snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk);
  2664.     }
  2665. -#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
  2666. -           CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
  2667. +#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
  2668. +    defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
  2669.     if (dai_sel & RT5640_U_IF3) {
  2670.         mask_clk = RT5640_I2S_BCLK_MS3_MASK | RT5640_I2S_PD3_MASK;
  2671.         val_clk = bclk_ms << RT5640_I2S_BCLK_MS3_SFT |
  2672. @@ -1973,7 +2479,7 @@ static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  2673.         reg_val |= RT5640_I2S_DF_PCM_A;
  2674.         break;
  2675.     case SND_SOC_DAIFMT_DSP_B:
  2676. -       reg_val  |= RT5640_I2S_DF_PCM_B;
  2677. +       reg_val |= RT5640_I2S_DF_PCM_B;
  2678.         break;
  2679.     default:
  2680.         return -EINVAL;
  2681. @@ -1994,8 +2500,8 @@ static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  2682.             RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
  2683.             RT5640_I2S_DF_MASK, reg_val);
  2684.     }
  2685. -#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
  2686. -           CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
  2687. +#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
  2688. +    defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
  2689.     if (dai_sel & RT5640_U_IF3) {
  2690.         snd_soc_update_bits(codec, RT5640_I2S3_SDP,
  2691.             RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
  2692. @@ -2022,9 +2528,6 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
  2693.     case RT5640_SCLK_S_PLL1:
  2694.         reg_val |= RT5640_SCLK_SRC_PLL1;
  2695.         break;
  2696. -   case RT5640_SCLK_S_PLL1_TK:
  2697. -       reg_val |= RT5640_SCLK_SRC_PLL1T;
  2698. -       break;
  2699.     case RT5640_SCLK_S_RCCLK:
  2700.         reg_val |= RT5640_SCLK_SRC_RCCLK;
  2701.         break;
  2702. @@ -2038,6 +2541,7 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
  2703.     rt5640->sysclk_src = clk_id;
  2704.  
  2705.     dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
  2706. +
  2707.     return 0;
  2708.  }
  2709.  
  2710. @@ -2077,7 +2581,7 @@ static int rt5640_pll_calc(const unsigned int freq_in,
  2711.             if (red < red_t) {
  2712.                 n = n_t;
  2713.                 m = m_t;
  2714. -               if (red == 0)
  2715. +               if(red == 0)
  2716.                     goto code_find;
  2717.                 red_t = red;
  2718.             }
  2719. @@ -2088,7 +2592,7 @@ static int rt5640_pll_calc(const unsigned int freq_in,
  2720.  code_find:
  2721.  
  2722.     pll_code->m_bp = bypass;
  2723. -   pll_code->m_code = m;
  2724. +   pll_code->m_code= m;
  2725.     pll_code->n_code = n;
  2726.     pll_code->k_code = 2;
  2727.     return 0;
  2728. @@ -2123,12 +2627,9 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
  2729.         break;
  2730.     case RT5640_PLL1_S_BCLK1:
  2731.     case RT5640_PLL1_S_BCLK2:
  2732. -
  2733. -#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
  2734. -           CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
  2735. -
  2736. +#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
  2737. +    defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
  2738.     case RT5640_PLL1_S_BCLK3:
  2739. -
  2740.  #endif
  2741.         dai_sel = get_sdp_info(codec, dai->id);
  2742.         if (dai_sel < 0) {
  2743. @@ -2163,11 +2664,16 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
  2744.     dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code.m_bp,
  2745.         (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code);
  2746.  
  2747. -   snd_soc_write(codec, RT5640_PLL_CTRL1,
  2748. -       pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code);
  2749. -   snd_soc_write(codec, RT5640_PLL_CTRL2,
  2750. -       (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT |
  2751. -       pll_code.m_bp << RT5640_PLL_M_BP_SFT);
  2752. +   {
  2753. +       int val;
  2754. +
  2755. +       val = (pll_code.n_code << RT5640_PLL_N_SFT) | pll_code.k_code;
  2756. +       snd_soc_write(codec, RT5640_PLL_CTRL1, val);
  2757. +
  2758. +       val = (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT;
  2759. +       val |= (pll_code.m_bp << RT5640_PLL_M_BP_SFT);
  2760. +       snd_soc_write(codec, RT5640_PLL_CTRL2, val);
  2761. +   }
  2762.  
  2763.     rt5640->pll_in = freq_in;
  2764.     rt5640->pll_out = freq_out;
  2765. @@ -2197,12 +2703,13 @@ static ssize_t rt5640_index_show(struct device *dev,
  2766.  
  2767.     cnt += sprintf(buf, "RT5640 index register\n");
  2768.     for (i = 0; i < 0xb4; i++) {
  2769. -       if (cnt + 9 >= PAGE_SIZE - 1)
  2770. +       if (cnt + RT5640_REG_DISP_LEN >= PAGE_SIZE)
  2771.             break;
  2772.         val = rt5640_index_read(codec, i);
  2773.         if (!val)
  2774.             continue;
  2775. -       cnt += snprintf(buf + cnt, 10, "%02x: %04x\n", i, val);
  2776. +       cnt += snprintf(buf + cnt, RT5640_REG_DISP_LEN,
  2777. +               "%02x: %04x\n", i, val);
  2778.     }
  2779.  
  2780.     if (cnt >= PAGE_SIZE)
  2781. @@ -2217,69 +2724,40 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
  2782.  {
  2783.     switch (level) {
  2784.     case SND_SOC_BIAS_ON:
  2785. -#ifdef RT5640_DEMO
  2786. -       snd_soc_update_bits(codec, RT5640_SPK_VOL,
  2787. -           RT5640_L_MUTE | RT5640_R_MUTE, 0);
  2788. -       snd_soc_update_bits(codec, RT5640_HP_VOL,
  2789. -           RT5640_L_MUTE | RT5640_R_MUTE, 0);
  2790.         break;
  2791. -#endif
  2792. -   case SND_SOC_BIAS_PREPARE:
  2793. -#ifdef RT5640_DEMO
  2794. -       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2795. -           RT5640_PWR_VREF1 | RT5640_PWR_MB |
  2796. -           RT5640_PWR_BG | RT5640_PWR_VREF2,
  2797. -           RT5640_PWR_VREF1 | RT5640_PWR_MB |
  2798. -           RT5640_PWR_BG | RT5640_PWR_VREF2);
  2799. -       msleep(100);
  2800. -
  2801. -       snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2802. -           RT5640_PWR_FV1 | RT5640_PWR_FV2,
  2803. -           RT5640_PWR_FV1 | RT5640_PWR_FV2);
  2804.  
  2805. +   case SND_SOC_BIAS_PREPARE:
  2806.         snd_soc_update_bits(codec, RT5640_PWR_ANLG2,
  2807.             RT5640_PWR_MB1 | RT5640_PWR_MB2,
  2808.             RT5640_PWR_MB1 | RT5640_PWR_MB2);
  2809. -#endif
  2810.         break;
  2811.  
  2812.     case SND_SOC_BIAS_STANDBY:
  2813. -#ifdef RT5640_DEMO
  2814. -       snd_soc_update_bits(codec, RT5640_SPK_VOL, RT5640_L_MUTE |
  2815. -           RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2816. -       snd_soc_update_bits(codec, RT5640_HP_VOL, RT5640_L_MUTE |
  2817. -           RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2818. -
  2819.         snd_soc_update_bits(codec, RT5640_PWR_ANLG2,
  2820. -           RT5640_PWR_MB1 | RT5640_PWR_MB2,
  2821. -           0);
  2822. -#endif
  2823. +           RT5640_PWR_MB1 | RT5640_PWR_MB2, 0);
  2824.         if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
  2825.             snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2826.                 RT5640_PWR_VREF1 | RT5640_PWR_MB |
  2827.                 RT5640_PWR_BG | RT5640_PWR_VREF2,
  2828.                 RT5640_PWR_VREF1 | RT5640_PWR_MB |
  2829.                 RT5640_PWR_BG | RT5640_PWR_VREF2);
  2830. -           msleep(10);
  2831. +           /*
  2832. +            * wait 10ms to
  2833. +            * make 1st and 2nd reference voltages stable
  2834. +            */
  2835. +           usleep_range(10000, 15000);
  2836.             snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  2837.                 RT5640_PWR_FV1 | RT5640_PWR_FV2,
  2838.                 RT5640_PWR_FV1 | RT5640_PWR_FV2);
  2839.             codec->cache_only = false;
  2840.             snd_soc_cache_sync(codec);
  2841. +           rt5640_index_sync(codec);
  2842.         }
  2843.         break;
  2844.  
  2845.     case SND_SOC_BIAS_OFF:
  2846. -#ifdef RT5640_DEMO
  2847. -       snd_soc_update_bits(codec, RT5640_SPK_VOL, RT5640_L_MUTE |
  2848. -           RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2849. -       snd_soc_update_bits(codec, RT5640_HP_VOL, RT5640_L_MUTE |
  2850. -           RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2851. -       snd_soc_update_bits(codec, RT5640_OUTPUT, RT5640_L_MUTE |
  2852. -           RT5640_R_MUTE, RT5640_L_MUTE | RT5640_R_MUTE);
  2853. -       snd_soc_update_bits(codec, RT5640_MONO_OUT,
  2854. -           RT5640_L_MUTE, RT5640_L_MUTE);
  2855. -#endif
  2856. +       snd_soc_write(codec, RT5640_DEPOP_M1, 0x0004);
  2857. +       snd_soc_write(codec, RT5640_DEPOP_M2, 0x1100);
  2858.         snd_soc_write(codec, RT5640_PWR_DIG1, 0x0000);
  2859.         snd_soc_write(codec, RT5640_PWR_DIG2, 0x0000);
  2860.         snd_soc_write(codec, RT5640_PWR_VOL, 0x0000);
  2861. @@ -2296,11 +2774,540 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
  2862.     return 0;
  2863.  }
  2864.  
  2865. +#ifdef RTK_IOCTL
  2866. +int set_drc_agc_enable(struct snd_soc_codec *codec, int enable, int path)
  2867. +{
  2868. +   return snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2869. +       RT5640_DRC_AGC_P_MASK | RT5640_DRC_AGC_MASK | RT5640_DRC_AGC_UPD,
  2870. +       enable << RT5640_DRC_AGC_SFT | path << RT5640_DRC_AGC_P_SFT |
  2871. +       1 << RT5640_DRC_AGC_UPD_BIT );
  2872. +}
  2873. +
  2874. +int set_drc_agc_parameters(struct snd_soc_codec *codec, int attack_rate, int sample_rate,
  2875. +   int recovery_rate, int limit_level)
  2876. +{
  2877. +   int ret;
  2878. +
  2879. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_3,
  2880. +       RT5640_DRC_AGC_TAR_MASK, limit_level << RT5640_DRC_AGC_TAR_SFT);
  2881. +
  2882. +   if (ret < 0)
  2883. +       return ret;
  2884. +
  2885. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2886. +       RT5640_DRC_AGC_AR_MASK | RT5640_DRC_AGC_R_MASK |
  2887. +       RT5640_DRC_AGC_UPD | RT5640_DRC_AGC_RC_MASK,
  2888. +       attack_rate << RT5640_DRC_AGC_AR_SFT |
  2889. +       sample_rate << RT5640_DRC_AGC_R_SFT |
  2890. +       recovery_rate << RT5640_DRC_AGC_RC_SFT |
  2891. +       1 << RT5640_DRC_AGC_UPD_BIT );
  2892. +
  2893. +   return ret;
  2894. +}
  2895. +
  2896. +int set_digital_boost_gain(struct snd_soc_codec *codec, int post_gain, int pre_gain)
  2897. +{
  2898. +   int ret;
  2899. +
  2900. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
  2901. +       RT5640_DRC_AGC_POB_MASK | RT5640_DRC_AGC_PRB_MASK,
  2902. +       post_gain << RT5640_DRC_AGC_POB_SFT |
  2903. +       pre_gain << RT5640_DRC_AGC_PRB_SFT);
  2904. +
  2905. +   if (ret < 0)
  2906. +       return ret;
  2907. +
  2908. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2909. +       RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
  2910. +
  2911. +   return ret;
  2912. +}
  2913. +
  2914. +int set_noise_gate(struct snd_soc_codec *codec, int noise_gate_en, int noise_gate_hold_en,
  2915. +   int compression_gain, int noise_gate_th)
  2916. +{
  2917. +   int ret;
  2918. +
  2919. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_3,
  2920. +       RT5640_DRC_AGC_NGB_MASK | RT5640_DRC_AGC_NG_SFT |
  2921. +       RT5640_DRC_AGC_NGH_MASK | RT5640_DRC_AGC_NGT_MASK,
  2922. +       noise_gate_en << RT5640_DRC_AGC_NG_SFT |
  2923. +       noise_gate_hold_en << RT5640_DRC_AGC_NGH_SFT |
  2924. +       compression_gain << RT5640_DRC_AGC_NGB_SFT |
  2925. +       noise_gate_th << RT5640_DRC_AGC_NGT_SFT);
  2926. +
  2927. +   if (ret < 0)
  2928. +       return ret;
  2929. +
  2930. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2931. +       RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
  2932. +
  2933. +   return ret;
  2934. +}
  2935. +
  2936. +int set_drc_agc_compression(struct snd_soc_codec *codec, int compression_en, int compression_ratio)
  2937. +{
  2938. +   int ret;
  2939. +
  2940. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
  2941. +       RT5640_DRC_AGC_CP_MASK | RT5640_DRC_AGC_CPR_MASK,
  2942. +       compression_en << RT5640_DRC_AGC_CP_SFT |
  2943. +       compression_ratio << RT5640_DRC_AGC_CPR_SFT);
  2944. +
  2945. +   if (ret < 0)
  2946. +       return ret;
  2947. +
  2948. +   ret = snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
  2949. +       RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
  2950. +
  2951. +   return ret;
  2952. +}
  2953. +
  2954. +//flove083011
  2955. +#if defined(CONFIG_SND_HWDEP)
  2956. +#define RT_CE_CODEC_HWDEP_NAME "rt56xx hwdep "
  2957. +
  2958. +static int rt56xx_hwdep_open(struct snd_hwdep *hw, struct file *file)
  2959. +{
  2960. +   printk("enter %s\n", __func__);
  2961. +   return 0;
  2962. +}
  2963. +
  2964. +static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file)
  2965. +{
  2966. +   printk("enter %s\n", __func__);
  2967. +   return 0;
  2968. +}
  2969. +
  2970. +
  2971. +static int rt56xx_hwdep_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
  2972. +{
  2973. +   struct rt56xx_cmd rt56xx;
  2974. +#if 0
  2975. +   struct rt56xx_reg *buf;
  2976. +   struct rt56xx_reg *p;
  2977. +#else
  2978. +   //struct rt56xx_arg *buf;
  2979. +   int *buf;
  2980. +   //struct rt56xx_arg *p;
  2981. +   int *p;
  2982. +#endif
  2983. +   int mask1 = 0, mask2 = 0;
  2984. +
  2985. +
  2986. +   struct rt56xx_cmd __user *_rt56xx =(struct rt56xx_cmd *)arg;
  2987. +   struct snd_soc_codec *codec = hw->private_data;
  2988. +
  2989. +   if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) {
  2990. +       printk("copy_from_user faild\n");
  2991. +       return -EFAULT;
  2992. +   }
  2993. +   if(DBG) printk("rt56xx.number=%d\n",rt56xx.number);
  2994. +   buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
  2995. +   if (buf == NULL)
  2996. +       return -ENOMEM;
  2997. +   if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
  2998. +       goto err;
  2999. +   }
  3000. +
  3001. +   switch (cmd) {
  3002. +       case RT_READ_CODEC_REG_IOCTL:
  3003. +           if(DBG) printk(" case RT_READ_CODEC_REG_IOCTL\n");
  3004. +
  3005. +           for (p = buf; p < buf + rt56xx.number/2; p++)
  3006. +           {
  3007. +               *(p+rt56xx.number/2) = snd_soc_read(codec, *p);
  3008. +           }
  3009. +           if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
  3010. +               goto err;
  3011. +
  3012. +           break;
  3013. +       case RT_WRITE_CODEC_REG_IOCTL:
  3014. +           if(DBG) printk(" case RT_WRITE_CODEC_REG_IOCTL\n");
  3015. +
  3016. +           for (p = buf; p < buf + rt56xx.number/2; p++)
  3017. +               snd_soc_write(codec, *p, *(p+rt56xx.number/2));
  3018. +           break;
  3019. +       case RT_READ_CODEC_INDEX_IOCTL:
  3020. +           if(DBG) printk(" case RT_READ_CODEC_INDEX_IOCTL\n");
  3021. +
  3022. +           for (p = buf; p < buf + rt56xx.number/2; p++)
  3023. +           {
  3024. +               *(p+rt56xx.number/2) = rt5640_index_read(codec, *p);
  3025. +           }
  3026. +           if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
  3027. +               goto err;
  3028. +
  3029. +           break;
  3030. +       case RT_WRITE_CODEC_INDEX_IOCTL:
  3031. +           if(DBG) printk(" case RT_WRITE_CODEC_INDEX_IOCTL\n");
  3032. +
  3033. +           for (p = buf; p < buf + rt56xx.number/2; p++)
  3034. +               rt5640_index_write(codec, *p, *(p+rt56xx.number/2));
  3035. +           break;
  3036. +       case RT_SET_CODEC_HWEQ_IOCTL: {
  3037. +           u16 virtual_reg;
  3038. +           int rt5640_eq_mode;
  3039. +
  3040. +           printk(" case RT_SET_CODEC_HWEQ_IOCTL\n");
  3041. +
  3042. +           virtual_reg = snd_soc_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);
  3043. +           rt5640_eq_mode=(virtual_reg&0x00f0)>>4;
  3044. +
  3045. +           if ( rt5640_eq_mode == *buf)
  3046. +               break;
  3047. +
  3048. +           rt5640_update_eqmode(codec, *buf);
  3049. +
  3050. +           virtual_reg &= 0xff0f;
  3051. +           virtual_reg |= (*buf<<4);
  3052. +           snd_soc_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, virtual_reg);
  3053. +       }
  3054. +           break;
  3055. +       case RT_GET_CODEC_ID:
  3056. +           if(DBG) printk(" case RT_GET_CODEC_ID\n");
  3057. +
  3058. +           *buf = snd_soc_read(codec, RT5640_VENDOR_ID2);
  3059. +
  3060. +           if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
  3061. +               goto err;
  3062. +
  3063. +           break;
  3064. +       case RT_SET_CODEC_SPK_VOL_IOCTL:
  3065. +           if(DBG) printk("case RT_SET_CODEC_SPK_VOL_IOCTL\n");
  3066. +           snd_soc_update_bits(codec, RT5640_SPK_VOL,
  3067. +               RT5640_L_VOL_MASK | RT5640_R_VOL_MASK,
  3068. +               *(buf)<<RT5640_L_VOL_SFT | *(buf)<<RT5640_R_VOL_SFT);
  3069. +           break;
  3070. +       case RT_SET_CODEC_MIC_GAIN_IOCTL:
  3071. +           if(DBG) printk("case RT_SET_CODEC_MIC_GAIN_IOCTL\n");
  3072. +           snd_soc_update_bits(codec, RT5640_IN1_IN2,
  3073. +               RT5640_BST_MASK1,
  3074. +               *(buf)<<RT5640_BST_SFT1);
  3075. +           snd_soc_update_bits(codec, RT5640_IN3_IN4,
  3076. +               RT5640_BST_MASK2,
  3077. +               *(buf)<<RT5640_BST_SFT2);
  3078. +           break;
  3079. +       case RT_SET_CODEC_3D_SPK_IOCTL:
  3080. +           if(DBG) printk("case RT_SET_CODEC_3D_SPK_IOCTL\n");
  3081. +
  3082. +           if(rt56xx.number < 4)
  3083. +               break;
  3084. +           mask1 = 0;
  3085. +           if(*buf != -1)
  3086. +               mask1 |= RT5640_3D_SPK_MASK;
  3087. +           if(*(buf+1) != -1)
  3088. +               mask1 |= RT5640_3D_SPK_M_MASK;
  3089. +           if(*(buf+2) != -1)
  3090. +               mask1 |= RT5640_3D_SPK_CG_MASK;
  3091. +           if(*(buf+3) != -1)
  3092. +               mask1 |= RT5640_3D_SPK_SG_MASK;
  3093. +
  3094. +           rt5640_index_update_bits(codec, RT5640_3D_SPK, mask1,
  3095. +               *(buf)<<RT5640_3D_SPK_SFT | *(buf+1)<<RT5640_3D_SPK_M_SFT |
  3096. +               *(buf+2)<<RT5640_3D_SPK_CG_SFT | *(buf+3)<<RT5640_3D_SPK_SG_SFT);
  3097. +           break;
  3098. +       case RT_SET_CODEC_MP3PLUS_IOCTL:
  3099. +           if(DBG) printk("case RT_SET_CODEC_MP3PLUS_IOCTL\n");
  3100. +
  3101. +           if(rt56xx.number < 5)
  3102. +               break;
  3103. +           mask1 = mask2 = 0;
  3104. +           if(*buf != -1)
  3105. +               mask1 |= RT5640_M_MP3_MASK;
  3106. +           if(*(buf+1) != -1)
  3107. +               mask1 |= RT5640_EG_MP3_MASK;
  3108. +           if(*(buf+2) != -1)
  3109. +               mask2 |= RT5640_OG_MP3_MASK;
  3110. +           if(*(buf+3) != -1)
  3111. +               mask2 |= RT5640_HG_MP3_MASK;
  3112. +           if(*(buf+4) != -1)
  3113. +               mask2 |= RT5640_MP3_WT_MASK;
  3114. +
  3115. +           snd_soc_update_bits(codec, RT5640_MP3_PLUS1, mask1,
  3116. +               *(buf)<<RT5640_M_MP3_SFT | *(buf+1)<<RT5640_EG_MP3_SFT);
  3117. +
  3118. +
  3119. +           snd_soc_update_bits(codec, RT5640_MP3_PLUS2, mask2,
  3120. +               *(buf+2)<<RT5640_OG_MP3_SFT | *(buf+3)<<RT5640_HG_MP3_SFT |
  3121. +               *(buf+4)<<RT5640_MP3_WT_SFT);
  3122. +           break;
  3123. +       case RT_SET_CODEC_3D_HEADPHONE_IOCTL:
  3124. +           if(DBG) printk("case RT_SET_CODEC_3D_HEADPHONE_IOCTL\n");
  3125. +
  3126. +           if(rt56xx.number < 4)
  3127. +               break;
  3128. +           mask1 = 0;
  3129. +           if(*buf != -1)
  3130. +               mask1 |= RT5640_3D_HP_MASK;
  3131. +           if(*(buf+1) != -1)
  3132. +               mask1 |= RT5640_3D_BT_MASK;
  3133. +           if(*(buf+2) != -1)
  3134. +               mask1 |= RT5640_3D_1F_MIX_MASK;
  3135. +           if(*(buf+3) != -1)
  3136. +               mask1 |= RT5640_3D_HP_M_MASK;
  3137. +
  3138. +           snd_soc_update_bits(codec, RT5640_3D_HP, mask1,
  3139. +               *(buf)<<RT5640_3D_HP_SFT | *(buf+1)<<RT5640_3D_BT_SFT |
  3140. +               *(buf+2)<<RT5640_3D_1F_MIX_SFT | *(buf+3)<<RT5640_3D_HP_M_SFT);
  3141. +
  3142. +           if(*(buf+4) != -1)
  3143. +               rt5640_index_update_bits(codec, 0x59, 0x1f, *(buf+4) );
  3144. +           break;
  3145. +       case RT_SET_CODEC_BASS_BACK_IOCTL:
  3146. +           if(DBG) printk("case RT_SET_CODEC_BASSBACK_IOCTL\n");
  3147. +
  3148. +           if(rt56xx.number < 3)
  3149. +               break;
  3150. +           mask1 = 0;
  3151. +           if(*buf != -1)
  3152. +               mask1 |= RT5640_BB_MASK;
  3153. +           if(*(buf+1) != -1)
  3154. +               mask1 |= RT5640_BB_CT_MASK;
  3155. +           if(*(buf+2) != -1)
  3156. +               mask1 |= RT5640_G_BB_BST_MASK;
  3157. +
  3158. +           snd_soc_update_bits(codec, RT5640_BASE_BACK, mask1,
  3159. +               *(buf)<<RT5640_BB_SFT | *(buf+1)<<RT5640_BB_CT_SFT |
  3160. +               *(buf+2)<<RT5640_G_BB_BST_SFT );
  3161. +           break;
  3162. +       case RT_SET_CODEC_DIPOLE_SPK_IOCTL:
  3163. +           if(DBG) printk("case RT_SET_CODEC_DIPOLE_SPK_IOCTL\n");
  3164. +
  3165. +           if(rt56xx.number < 2)
  3166. +               break;
  3167. +           mask1 = 0;
  3168. +           if(*buf != -1)
  3169. +               mask1 |= RT5640_DP_SPK_MASK;
  3170. +           if(*(buf+1) != -1)
  3171. +               mask1 |= RT5640_DP_ATT_MASK;
  3172. +
  3173. +           rt5640_index_update_bits(codec, RT5640_DIP_SPK_INF, mask1,
  3174. +               *(buf)<<RT5640_DP_SPK_SFT | *(buf+1)<<RT5640_DP_ATT_SFT );
  3175. +           break;
  3176. +       case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL:
  3177. +           if(DBG) printk("case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL\n");
  3178. +
  3179. +           if(rt56xx.number < 2)
  3180. +               break;
  3181. +           set_drc_agc_enable(codec, *(buf), *(buf+1));
  3182. +           break;
  3183. +       case RT_SET_CODEC_DRC_AGC_PAR_IOCTL:
  3184. +           if(DBG) printk("case RT_SET_CODEC_DRC_AGC_PAR_IOCTL\n");
  3185. +           if(rt56xx.number < 4)
  3186. +               break;
  3187. +           set_drc_agc_parameters(codec, *(buf), *(buf+1), *(buf+2), *(buf+3));
  3188. +           break;
  3189. +       case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL:
  3190. +           if(DBG) printk("case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL\n");
  3191. +           if(rt56xx.number < 2)
  3192. +               break;
  3193. +
  3194. +           set_digital_boost_gain(codec, *(buf), *(buf+1));
  3195. +           break;
  3196. +       case RT_SET_CODEC_NOISE_GATE_IOCTL:
  3197. +           if(DBG) printk("case RT_SET_CODEC_NOISE_GATE_IOCTL\n");
  3198. +           if(rt56xx.number < 4)
  3199. +               break;
  3200. +           set_noise_gate(codec, *(buf), *(buf+1), *(buf+2), *(buf+3));
  3201. +           break;
  3202. +       case RT_SET_CODEC_DRC_AGC_COMP_IOCTL:
  3203. +           if(DBG) printk("case RT_SET_CODEC_DRC_AGC_COMP_IOCTL\n");
  3204. +           if(rt56xx.number < 2)
  3205. +               break;
  3206. +
  3207. +           set_drc_agc_compression(codec, *(buf), *(buf+1));
  3208. +           break;
  3209. +       case RT_SET_CODEC_WNR_ENABLE_IOCTL:
  3210. +           if(DBG) printk("case RT_SET_CODEC_WNR_ENABLE_IOCTL\n");
  3211. +
  3212. +           rt5640_index_update_bits(codec, RT5640_WND_1, RT5640_WND_MASK,
  3213. +               *(buf)<<RT5640_WND_SFT );
  3214. +           break;
  3215. +       case RT_SET_CODEC_DSP_MODE_IOCTL:
  3216. +           if(DBG) printk("case RT_SET_CODEC_DSP_MODE_IOCTL\n");
  3217. +           do_rt5640_dsp_set_mode(codec,*(buf));
  3218. +           break;
  3219. +
  3220. +       case RT_GET_CODEC_HWEQ_IOCTL:
  3221. +       case RT_GET_CODEC_SPK_VOL_IOCTL:
  3222. +       case RT_GET_CODEC_MIC_GAIN_IOCTL:
  3223. +       case RT_GET_CODEC_3D_SPK_IOCTL:
  3224. +       case RT_GET_CODEC_MP3PLUS_IOCTL:
  3225. +       case RT_GET_CODEC_3D_HEADPHONE_IOCTL:
  3226. +       case RT_GET_CODEC_BASS_BACK_IOCTL:
  3227. +       case RT_GET_CODEC_DIPOLE_SPK_IOCTL:
  3228. +       case RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL:
  3229. +       case RT_GET_CODEC_NOISE_GATE_IOCTL:
  3230. +       case RT_GET_CODEC_DRC_AGC_COMP_IOCTL:
  3231. +       default:
  3232. +           printk("default\n");
  3233. +           break;
  3234. +   }
  3235. +
  3236. +   kfree(buf);
  3237. +   return 0;
  3238. +
  3239. +err:
  3240. +   kfree(buf);
  3241. +   return -EFAULT;
  3242. +
  3243. +}
  3244. +
  3245. +static int rt56xx_codec_dump_reg(struct snd_hwdep *hw, struct file *file, unsigned long arg)
  3246. +{
  3247. +   struct rt56xx_cmd rt56xx;
  3248. +   struct rt56xx_cmd __user *_rt56xx =(struct rt56xx_cmd *)arg;
  3249. +   int *buf;
  3250. +   struct snd_soc_codec *codec = hw->private_data;
  3251. +   int number = RT5640_VENDOR_ID2 + 1;
  3252. +   int i;
  3253. +
  3254. +   printk(KERN_DEBUG "enter %s, number = %d\n", __func__, number);
  3255. +   if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))
  3256. +       return -EFAULT;
  3257. +
  3258. +   buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL);
  3259. +   if (buf == NULL)
  3260. +       return -ENOMEM;
  3261. +
  3262. +   for (i = 0; i < number/2; i++)
  3263. +   {
  3264. +       buf[i] = i << 1;
  3265. +       buf[i+number/2] = codec->read(codec, buf[i]);
  3266. +   }
  3267. +   if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * i))
  3268. +       goto err;
  3269. +   rt56xx.number = number;
  3270. +   if (copy_to_user(_rt56xx, &rt56xx, sizeof(rt56xx)))
  3271. +       goto err;
  3272. +   kfree(buf);
  3273. +   return 0;
  3274. +err:
  3275. +   kfree(buf);
  3276. +   return -EFAULT;
  3277. +
  3278. +}
  3279. +
  3280. +static int rt56xx_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
  3281. +{
  3282. +
  3283. +   printk("***********************rt56xx_hwdep_ioctl cmd=%x,arg=%lx**********************\n",cmd,arg);
  3284. +#if 0
  3285. +   if (cmd == RT_READ_ALL_CODEC_REG_IOCTL)
  3286. +   {
  3287. +       return rt56xx_codec_dump_reg(hw, file, arg);
  3288. +   }
  3289. +   else
  3290. +   {
  3291. +       return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg);
  3292. +   }
  3293. +#else
  3294. +   switch (cmd) {
  3295. +   case RT_READ_ALL_CODEC_REG_IOCTL:
  3296. +       return rt56xx_codec_dump_reg(hw, file, arg);
  3297. +   case AUDIO_CAPTURE_MODE:
  3298. +       switch(arg){
  3299. +           case INPUT_SOURCE_NORMAL:
  3300. +           case INPUT_SOURCE_VR:
  3301. +               printk("AUDIO_CODEC: Capture mode [%s]\n",
  3302. +               arg == INPUT_SOURCE_NORMAL ? "NORMAL" : "VR");
  3303. +               input_source=arg;
  3304. +               if(arg == INPUT_SOURCE_VR){
  3305. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_AEC_NS_FENS);
  3306. +               }else{
  3307. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_DIS);
  3308. +               }
  3309. +               break;
  3310. +           case INPUT_SOURCE_AGC:
  3311. +           case INPUT_SOURCE_NO_AGC:
  3312. +               printk("AUDIO_CODEC: Capture mode [%s]\n",
  3313. +               arg == INPUT_SOURCE_AGC ? "AGC" : "NON-AGC");
  3314. +               input_agc = arg;
  3315. +               if(arg == INPUT_SOURCE_AGC){
  3316. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_AEC_NS_FENS);
  3317. +               }else{
  3318. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_DIS);
  3319. +               }
  3320. +               break;
  3321. +           case OUTPUT_SOURCE_NORMAL:
  3322. +           case OUTPUT_SOURCE_VOICE:
  3323. +                            printk("AUDIO_CODEC: Capture mode [%s]\n",
  3324. +               arg == OUTPUT_SOURCE_NORMAL ? "NORMAL" : "VOICE");
  3325. +               output_source=arg;
  3326. +               if(arg == OUTPUT_SOURCE_VOICE){
  3327. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_AEC_NS_FENS);
  3328. +               }
  3329. +               break;
  3330. +           case END_RECORDING:
  3331. +               do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_DIS);
  3332. +               break;
  3333. +           case START_COMMUNICATION:
  3334. +                            printk("AUDIO_CODEC: Capture mode [%s]\n",
  3335. +               arg == START_COMMUNICATION ? "COMMUNICATION" : "NORMAL");
  3336. +               if(arg == START_COMMUNICATION){
  3337. +                   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_AEC_NS_FENS);
  3338. +               }
  3339. +               break;
  3340. +           case STOP_COMMUNICATION:
  3341. +               do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_DIS);
  3342. +               break;
  3343. +           default:
  3344. +               break;
  3345. +           }
  3346. +       break;
  3347. +   case AUDIO_STRESS_TEST:
  3348. +       printk("AUDIO_CODEC: AUDIO_STRESS_TEST: %lu (1: Start, 0: Stop)\n",arg);
  3349. +           if(arg==AUDIO_IOCTL_START_HEAVY){
  3350. +               poll_rate = START_HEAVY;
  3351. +               schedule_delayed_work(&poll_audio_work, poll_rate);
  3352. +           }else if(arg==AUDIO_IOCTL_START_NORMAL){
  3353. +               poll_rate = START_NORMAL;
  3354. +               schedule_delayed_work(&poll_audio_work,poll_rate);
  3355. +           }else if(arg==AUDIO_IOCTL_STOP){
  3356. +               cancel_delayed_work_sync(&poll_audio_work);
  3357. +           }
  3358. +
  3359. +           break;
  3360. +#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
  3361. +   case RT_READ_CODEC_DSP_IOCTL:
  3362. +   case RT_WRITE_CODEC_DSP_IOCTL:
  3363. +   case RT_GET_CODEC_DSP_MODE_IOCTL:
  3364. +       return rt56xx_dsp_ioctl_common(hw, file, cmd, arg);
  3365. +#endif
  3366. +   default:
  3367. +       return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg);
  3368. +#endif
  3369. +   }
  3370. +
  3371. +   return -EINVAL;
  3372. +}
  3373. +
  3374. +static int realtek_ce_init_hwdep(struct snd_soc_codec *codec)
  3375. +{
  3376. +   struct snd_hwdep *hw;
  3377. +   struct snd_card *card = codec->card->snd_card;
  3378. +   int err;
  3379. +
  3380. +   if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0)
  3381. +       return err;
  3382. +
  3383. +   strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME);
  3384. +   hw->private_data = codec;
  3385. +   hw->ops.open = rt56xx_hwdep_open;
  3386. +   hw->ops.release = rt56xx_hwdep_release;
  3387. +   hw->ops.ioctl = rt56xx_hwdep_ioctl;
  3388. +   return 0;
  3389. +}
  3390. +#endif
  3391. +#endif
  3392. +
  3393.  static int rt5640_probe(struct snd_soc_codec *codec)
  3394.  {
  3395.     struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
  3396.     int ret;
  3397. -   u16 val;
  3398. +
  3399. +   codec->dapm.idle_bias_off = 1;
  3400.  
  3401.     ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
  3402.     if (ret != 0) {
  3403. @@ -2308,20 +3315,14 @@ static int rt5640_probe(struct snd_soc_codec *codec)
  3404.         return ret;
  3405.     }
  3406.  
  3407. -   val = snd_soc_read(codec, RT5640_RESET);
  3408. -   if (val != rt5640_reg[RT5640_RESET]) {
  3409. -       dev_err(codec->dev,
  3410. -           "Device with ID register %x is not a rt5640\n", val);
  3411. -       return -ENODEV;
  3412. -   }
  3413. -
  3414.     rt5640_reset(codec);
  3415.     snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  3416.         RT5640_PWR_VREF1 | RT5640_PWR_MB |
  3417.         RT5640_PWR_BG | RT5640_PWR_VREF2,
  3418.         RT5640_PWR_VREF1 | RT5640_PWR_MB |
  3419.         RT5640_PWR_BG | RT5640_PWR_VREF2);
  3420. -   msleep(100);
  3421. +   /* need wait 10ms to make 1st and 2nd reference voltage stable */
  3422. +   usleep_range(10000, 15000);
  3423.     snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
  3424.         RT5640_PWR_FV1 | RT5640_PWR_FV2,
  3425.         RT5640_PWR_FV1 | RT5640_PWR_FV2);
  3426. @@ -2340,21 +3341,14 @@ static int rt5640_probe(struct snd_soc_codec *codec)
  3427.             RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING);
  3428.     }
  3429.  
  3430. -#ifdef RT5640_DEMO
  3431.     rt5640_reg_init(codec);
  3432. -#endif
  3433. -
  3434. -
  3435. -#if (CONFIG_SND_SOC_RT5642_MODULE | CONFIG_SND_SOC_RT5642)
  3436. -   rt5640_register_dsp(codec);
  3437. -#endif
  3438. -
  3439. +   dc_calibrate(codec);
  3440.     codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
  3441. -
  3442. -   snd_soc_add_controls(codec, rt5640_snd_controls,
  3443. -       ARRAY_SIZE(rt5640_snd_controls));
  3444. -
  3445.     rt5640->codec = codec;
  3446. +   rt5640_audio_codec = codec;
  3447. +   rt5640_dsp = rt5640;
  3448. +   rt5640->dsp_sw = RT5640_DSP_AEC_NS_FENS;
  3449. +
  3450.     ret = device_create_file(codec->dev, &dev_attr_index_reg);
  3451.     if (ret != 0) {
  3452.         dev_err(codec->dev,
  3453. @@ -2362,30 +3356,73 @@ static int rt5640_probe(struct snd_soc_codec *codec)
  3454.         return ret;
  3455.     }
  3456.  
  3457. +   snd_soc_add_controls(codec, rt5640_snd_controls,ARRAY_SIZE(rt5640_snd_controls));
  3458. +   snd_soc_dapm_new_controls(&codec->dapm, rt5640_dapm_widgets,
  3459. +           ARRAY_SIZE(rt5640_dapm_widgets));
  3460. +   snd_soc_dapm_add_routes(&codec->dapm, rt5640_dapm_routes,
  3461. +           ARRAY_SIZE(rt5640_dapm_routes));
  3462. +#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
  3463. +   rt5640_dsp_probe(codec);
  3464. +#endif
  3465. +
  3466. +#ifdef RTK_IOCTL
  3467. +#if defined(CONFIG_SND_HWDEP)
  3468. +   printk("************************realtek_ce_init_hwdep*************************************\n");
  3469. +   realtek_ce_init_hwdep(codec);
  3470. +#endif
  3471. +#endif
  3472. +   do_rt5640_dsp_set_mode(rt5640_audio_codec,RT5640_DSP_DIS);
  3473.     return 0;
  3474.  }
  3475.  
  3476.  static int rt5640_remove(struct snd_soc_codec *codec)
  3477.  {
  3478.     rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
  3479. -   rt5640_reset(codec);
  3480. -   snd_soc_write(codec, RT5640_PWR_ANLG1, 0);
  3481. -
  3482.     return 0;
  3483.  }
  3484. +
  3485.  #ifdef CONFIG_PM
  3486.  static int rt5640_suspend(struct snd_soc_codec *codec, pm_message_t state)
  3487.  {
  3488. -   rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
  3489. -   snd_soc_write(codec, RT5640_PWR_ANLG1, 0);
  3490. +   int ret =0;
  3491. +   printk("rt5640_suspend+\n");
  3492. +#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
  3493. +   /* After opening LDO of DSP, then close LDO of codec.
  3494. +    * (1) DSP LDO power on
  3495. +    * (2) DSP core power off
  3496. +    * (3) DSP IIS interface power off
  3497. +    * (4) Toggle pin of codec LDO1 to power off
  3498. +    */
  3499. +   rt5640_dsp_suspend(codec, state);
  3500. +#endif
  3501.  
  3502. +   snd_soc_update_bits(codec, RT5640_SPK_VOL,
  3503. +           RT5640_L_MUTE | RT5640_R_MUTE,
  3504. +           RT5640_L_MUTE | RT5640_R_MUTE);
  3505. +   rt5640_index_update_bits(codec,
  3506. +           RT5640_CLSD_INT_REG1, 0xf000, 0x0000);
  3507. +   rt5640_pmd_depop(codec);
  3508. +   rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
  3509. +   tegra_gpio_enable(TEGRA_GPIO_PW4);
  3510. +   ret = gpio_request(TEGRA_GPIO_PW4, "audio_mclk");
  3511. +   if (ret < 0)
  3512. +       pr_err("%s: gpio_request failed for gpio %s\n",__func__, "AUDIO_MCLK");
  3513. +   gpio_direction_output(TEGRA_GPIO_PW4, 0);
  3514. +   gpio_free(TEGRA_GPIO_PW4);
  3515. +   printk("rt5640_suspend-\n");
  3516.     return 0;
  3517.  }
  3518.  
  3519.  static int rt5640_resume(struct snd_soc_codec *codec)
  3520.  {
  3521. +   printk("rt5640_resume+\n");
  3522. +   tegra_gpio_disable(TEGRA_GPIO_PW4);
  3523.     rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  3524. -
  3525. +#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
  3526. +   /* After opening LDO of codec, then close LDO of DSP. */
  3527. +   rt5640_dsp_resume(codec);
  3528. +#endif
  3529. +   printk("rt5640_resume-\n");
  3530.     return 0;
  3531.  }
  3532.  #else
  3533. @@ -2444,8 +3481,8 @@ struct snd_soc_dai_driver rt5640_dai[] = {
  3534.         },
  3535.         .ops = &rt5640_aif_dai_ops,
  3536.     },
  3537. -#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
  3538. -           CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
  3539. +#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
  3540. +    defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
  3541.     {
  3542.         .name = "rt5640-aif3",
  3543.         .id = RT5640_AIF3,
  3544. @@ -2480,10 +3517,12 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
  3545.     .volatile_register = rt5640_volatile_register,
  3546.     .readable_register = rt5640_readable_register,
  3547.     .reg_cache_step = 1,
  3548. -   .dapm_widgets = rt5640_dapm_widgets,
  3549. -   .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets),
  3550. -   .dapm_routes = rt5640_dapm_routes,
  3551. -   .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes),
  3552. +   //.controls = rt5640_snd_controls,
  3553. +   //.num_controls = ARRAY_SIZE(rt5640_snd_controls),
  3554. +   //.dapm_widgets = rt5640_dapm_widgets,
  3555. +   //.num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets),
  3556. +   //.dapm_routes = rt5640_dapm_routes,
  3557. +   //.num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes),
  3558.  };
  3559.  
  3560.  static const struct i2c_device_id rt5640_i2c_id[] = {
  3561. @@ -2492,12 +3531,14 @@ static const struct i2c_device_id rt5640_i2c_id[] = {
  3562.  };
  3563.  MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
  3564.  
  3565. -static int rt5640_i2c_probe(struct i2c_client *i2c,
  3566. +static int __devinit rt5640_i2c_probe(struct i2c_client *i2c,
  3567.             const struct i2c_device_id *id)
  3568.  {
  3569.     struct rt5640_priv *rt5640;
  3570.     int ret;
  3571.  
  3572. +   printk("%s\n", __func__);
  3573. +
  3574.     rt5640 = kzalloc(sizeof(struct rt5640_priv), GFP_KERNEL);
  3575.     if (NULL == rt5640)
  3576.         return -ENOMEM;
  3577. @@ -2508,17 +3549,29 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
  3578.             rt5640_dai, ARRAY_SIZE(rt5640_dai));
  3579.     if (ret < 0)
  3580.         kfree(rt5640);
  3581. +   INIT_DELAYED_WORK(&poll_audio_work, audio_codec_stress);
  3582.  
  3583.     return ret;
  3584.  }
  3585.  
  3586. -static __devexit int rt5640_i2c_remove(struct i2c_client *i2c)
  3587. +static int __devexit rt5640_i2c_remove(struct i2c_client *i2c)
  3588.  {
  3589.     snd_soc_unregister_codec(&i2c->dev);
  3590.     kfree(i2c_get_clientdata(i2c));
  3591.     return 0;
  3592.  }
  3593.  
  3594. +static void rt5640_i2c_shutdown(struct i2c_client *client)
  3595. +{
  3596. +   struct rt5640_priv *rt5640 = i2c_get_clientdata(client);
  3597. +   struct snd_soc_codec *codec = rt5640->codec;
  3598. +
  3599. +   if (codec != NULL)
  3600. +       rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
  3601. +
  3602. +   return;
  3603. +}
  3604. +
  3605.  struct i2c_driver rt5640_i2c_driver = {
  3606.     .driver = {
  3607.         .name = "rt5640",
  3608. @@ -2526,11 +3579,13 @@ struct i2c_driver rt5640_i2c_driver = {
  3609.     },
  3610.     .probe = rt5640_i2c_probe,
  3611.     .remove   = __devexit_p(rt5640_i2c_remove),
  3612. +   .shutdown = rt5640_i2c_shutdown,
  3613.     .id_table = rt5640_i2c_id,
  3614.  };
  3615.  
  3616.  static int __init rt5640_modinit(void)
  3617.  {
  3618. +   printk("%s\n", __func__);
  3619.     return i2c_add_driver(&rt5640_i2c_driver);
  3620.  }
  3621.  module_init(rt5640_modinit);
  3622. diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
  3623. index d6920f0..7e84c1b 100644
  3624. --- a/sound/soc/codecs/rt5640.h
  3625. +++ b/sound/soc/codecs/rt5640.h
  3626. @@ -144,6 +144,11 @@
  3627.  
  3628.  
  3629.  /* Index of Codec Private Register definition */
  3630. +#define RT5640_BIAS_CUR1           0x12
  3631. +#define RT5640_BIAS_CUR3           0x14
  3632. +#define RT5640_CLSD_INT_REG1           0x1c
  3633. +#define RT5640_MAMP_INT_REG2           0x37
  3634. +#define RT5640_CHOP_DAC_ADC            0x3d
  3635.  #define RT5640_3D_SPK              0x63
  3636.  #define RT5640_WND_1               0x6c
  3637.  #define RT5640_WND_2               0x6d
  3638. @@ -152,6 +157,7 @@
  3639.  #define RT5640_WND_5               0x70
  3640.  #define RT5640_WND_8               0x73
  3641.  #define RT5640_DIP_SPK_INF         0x75
  3642. +#define RT5640_HP_DCC_INT1         0x77
  3643.  #define RT5640_EQ_BW_LOP           0xa0
  3644.  #define RT5640_EQ_GN_LOP           0xa1
  3645.  #define RT5640_EQ_FC_BP1           0xa2
  3646. @@ -191,7 +197,9 @@
  3647.  
  3648.  /* IN1 and IN2 Control (0x0d) */
  3649.  /* IN3 and IN4 Control (0x0e) */
  3650. +#define RT5640_BST_MASK1           (0xf<<12)
  3651.  #define RT5640_BST_SFT1                12
  3652. +#define RT5640_BST_MASK2           (0xf<<8)
  3653.  #define RT5640_BST_SFT2                8
  3654.  #define RT5640_IN_DF1              (0x1 << 7)
  3655.  #define RT5640_IN_SFT1             7
  3656. @@ -977,8 +985,7 @@
  3657.  #define RT5640_SCLK_SRC_SFT            14
  3658.  #define RT5640_SCLK_SRC_MCLK           (0x0 << 14)
  3659.  #define RT5640_SCLK_SRC_PLL1           (0x1 << 14)
  3660. -#define RT5640_SCLK_SRC_PLL1T          (0x2 << 14)
  3661. -#define RT5640_SCLK_SRC_RCCLK          (0x3 << 14) /* 15MHz */
  3662. +#define RT5640_SCLK_SRC_RCCLK          (0x2 << 14) /* 15MHz */
  3663.  #define RT5640_PLL1_SRC_MASK           (0x3 << 12)
  3664.  #define RT5640_PLL1_SRC_SFT            12
  3665.  #define RT5640_PLL1_SRC_MCLK           (0x0 << 12)
  3666. @@ -1205,6 +1212,14 @@
  3667.  #define RT5640_CP_FQ2_SFT          4
  3668.  #define RT5640_CP_FQ3_MASK         (0x7)
  3669.  #define RT5640_CP_FQ3_SFT          0
  3670. +#define RT5640_CP_FQ_1_5_KHZ           0
  3671. +#define RT5640_CP_FQ_3_KHZ         1
  3672. +#define RT5640_CP_FQ_6_KHZ         2
  3673. +#define RT5640_CP_FQ_12_KHZ            3
  3674. +#define RT5640_CP_FQ_24_KHZ            4
  3675. +#define RT5640_CP_FQ_48_KHZ            5
  3676. +#define RT5640_CP_FQ_96_KHZ            6
  3677. +#define RT5640_CP_FQ_192_KHZ           7
  3678.  
  3679.  /* HPOUT charge pump (0x91) */
  3680.  #define RT5640_OSW_L_MASK          (0x1 << 11)
  3681. @@ -1699,15 +1714,15 @@
  3682.  #define RT5640_DSP_RST_PIN_LO          (0x0 << 10)
  3683.  #define RT5640_DSP_RST_PIN_HI          (0x1 << 10)
  3684.  #define RT5640_DSP_R_EN                (0x1 << 9)
  3685. -#define RT5640_DSP_R_EN_BIT            9
  3686.  #define RT5640_DSP_W_EN            (0x1 << 8)
  3687. -#define RT5640_DSP_W_EN_BIT            8
  3688.  #define RT5640_DSP_CMD_MASK            (0xff)
  3689. -#define RT5640_DSP_CMD_SFT         0
  3690. -#define RT5640_DSP_CMD_MW          (0x3B)  /* Memory Write */
  3691. +#define RT5640_DSP_CMD_PE          (0x0d)  /* Patch Entry */
  3692. +#define RT5640_DSP_CMD_MW          (0x3b)  /* Memory Write */
  3693.  #define RT5640_DSP_CMD_MR          (0x37)  /* Memory Read */
  3694.  #define RT5640_DSP_CMD_RR          (0x60)  /* Register Read */
  3695.  #define RT5640_DSP_CMD_RW          (0x68)  /* Register Write */
  3696. +#define RT5640_DSP_REG_DATHI           (0x26)  /* High Data Addr */
  3697. +#define RT5640_DSP_REG_DATLO           (0x25)  /* Low Data Addr */
  3698.  
  3699.  /* Programmable Register Array Control 1 (0xc8) */
  3700.  #define RT5640_REG_SEQ_MASK            (0xf << 12)
  3701. @@ -2019,24 +2034,35 @@ enum {
  3702.  #define RT5640_EQ_PST_VOL_MASK     (0xffff)
  3703.  #define RT5640_EQ_PST_VOL_SFT          0
  3704.  
  3705. -#define RT5640_NO_JACK     BIT(0)
  3706. -#define RT5640_HEADSET_DET BIT(1)
  3707. -#define RT5640_HEADPHO_DET BIT(2)
  3708. +#define RT5640_M_MAMIX_L           (0x1 << 13)
  3709. +#define RT5640_M_MAMIX_R           (0x1 << 12)
  3710. +/* Vendor ID (0xfd) */
  3711. +#define RT5640_VER_C               0x2
  3712. +#define RT5640_VER_D               0x3
  3713.  
  3714. -int rt5640_headset_detect(struct snd_soc_codec *codec, int jack_insert);
  3715. +
  3716. +
  3717. +
  3718. +/* Volume Rescale */
  3719. +#define RT5640_VOL_RSCL_MAX 0x27
  3720. +#define RT5640_VOL_RSCL_RANGE 0x1F
  3721. +/* Debug String Length */
  3722. +#define RT5640_REG_DISP_LEN 10
  3723.  
  3724.  /* System Clock Source */
  3725. -#define RT5640_SCLK_S_MCLK 0
  3726. -#define RT5640_SCLK_S_PLL1 1
  3727. -#define RT5640_SCLK_S_PLL1_TK 2
  3728. -#define RT5640_SCLK_S_RCCLK 3
  3729. +enum {
  3730. +   RT5640_SCLK_S_MCLK,
  3731. +   RT5640_SCLK_S_PLL1,
  3732. +   RT5640_SCLK_S_RCCLK,
  3733. +};
  3734.  
  3735.  /* PLL1 Source */
  3736. -#define RT5640_PLL1_S_MCLK 0
  3737. -#define RT5640_PLL1_S_BCLK1 1
  3738. -#define RT5640_PLL1_S_BCLK2 2
  3739. -#define RT5640_PLL1_S_BCLK3 3
  3740. -
  3741. +enum {
  3742. +   RT5640_PLL1_S_MCLK,
  3743. +   RT5640_PLL1_S_BCLK1,
  3744. +   RT5640_PLL1_S_BCLK2,
  3745. +   RT5640_PLL1_S_BCLK3,
  3746. +};
  3747.  
  3748.  enum {
  3749.     RT5640_AIF1,
  3750. @@ -2045,11 +2071,9 @@ enum {
  3751.     RT5640_AIFS,
  3752.  };
  3753.  
  3754. -enum {
  3755. -   RT5640_U_IF1 = 0x1,
  3756. -   RT5640_U_IF2 = 0x2,
  3757. -   RT5640_U_IF3 = 0x4,
  3758. -};
  3759. +#define RT5640_U_IF1 (0x1)
  3760. +#define RT5640_U_IF2 (0x1 << 1)
  3761. +#define RT5640_U_IF3 (0x1 << 2)
  3762.  
  3763.  enum {
  3764.     RT5640_IF_123,
  3765. @@ -2078,6 +2102,7 @@ struct rt5640_pll_code {
  3766.  
  3767.  struct rt5640_priv {
  3768.     struct snd_soc_codec *codec;
  3769. +   struct delayed_work patch_work;
  3770.  
  3771.     int aif_pu;
  3772.     int sysclk;
  3773. @@ -2091,8 +2116,14 @@ struct rt5640_priv {
  3774.     int pll_out;
  3775.  
  3776.     int dmic_en;
  3777. -   int dsp_sw;
  3778. +   int dsp_sw; /* expected parameter setting */
  3779. +   bool dsp_play_pass;
  3780. +   bool dsp_rec_pass;
  3781.  };
  3782.  
  3783. +int rt5640_conn_mux_path(struct snd_soc_codec *codec,
  3784. +       char *widget_name, char *path_name);
  3785. +int rt5640_conn_mixer_path(struct snd_soc_codec *codec,
  3786. +       char *widget_name, char *path_name, bool enable);
  3787.  
  3788.  #endif /* __RT5640_H__ */
  3789. diff --git a/sound/soc/codecs/rt56xx_ioctl.h b/sound/soc/codecs/rt56xx_ioctl.h
  3790. new file mode 100644
  3791. index 0000000..2b8f9f0
  3792. --- /dev/null
  3793. +++ b/sound/soc/codecs/rt56xx_ioctl.h
  3794. @@ -0,0 +1,50 @@
  3795. +#include <sound/hwdep.h>
  3796. +#include <linux/ioctl.h>
  3797. +
  3798. +struct rt56xx_cmd
  3799. +{
  3800. +   size_t number;
  3801. +   int __user *buf;
  3802. +};
  3803. +
  3804. +enum
  3805. +{
  3806. +   RT_READ_CODEC_REG_IOCTL = _IOR('R', 0x01, struct rt56xx_cmd),
  3807. +   RT_WRITE_CODEC_REG_IOCTL = _IOW('R', 0x01, struct rt56xx_cmd),
  3808. +   RT_READ_ALL_CODEC_REG_IOCTL = _IOR('R', 0x02, struct rt56xx_cmd),
  3809. +   RT_READ_CODEC_INDEX_IOCTL = _IOR('R', 0x03, struct rt56xx_cmd),
  3810. +   RT_WRITE_CODEC_INDEX_IOCTL = _IOW('R', 0x03, struct rt56xx_cmd),
  3811. +   RT_READ_CODEC_DSP_IOCTL = _IOR('R', 0x04, struct rt56xx_cmd),
  3812. +   RT_WRITE_CODEC_DSP_IOCTL = _IOW('R', 0x04, struct rt56xx_cmd),
  3813. +   RT_SET_CODEC_HWEQ_IOCTL = _IOW('R', 0x05, struct rt56xx_cmd),
  3814. +   RT_GET_CODEC_HWEQ_IOCTL = _IOR('R', 0x05, struct rt56xx_cmd),
  3815. +   RT_SET_CODEC_SPK_VOL_IOCTL = _IOW('R', 0x06, struct rt56xx_cmd),
  3816. +   RT_GET_CODEC_SPK_VOL_IOCTL = _IOR('R', 0x06, struct rt56xx_cmd),
  3817. +   RT_SET_CODEC_MIC_GAIN_IOCTL = _IOW('R', 0x07, struct rt56xx_cmd),
  3818. +   RT_GET_CODEC_MIC_GAIN_IOCTL = _IOR('R', 0x07, struct rt56xx_cmd),
  3819. +   RT_SET_CODEC_3D_SPK_IOCTL = _IOW('R', 0x08, struct rt56xx_cmd),
  3820. +   RT_GET_CODEC_3D_SPK_IOCTL = _IOR('R', 0x08, struct rt56xx_cmd),
  3821. +   RT_SET_CODEC_MP3PLUS_IOCTL = _IOW('R', 0x09, struct rt56xx_cmd),
  3822. +   RT_GET_CODEC_MP3PLUS_IOCTL = _IOR('R', 0x09, struct rt56xx_cmd),
  3823. +   RT_SET_CODEC_3D_HEADPHONE_IOCTL = _IOW('R', 0x0A, struct rt56xx_cmd),
  3824. +   RT_GET_CODEC_3D_HEADPHONE_IOCTL = _IOR('R', 0x0A, struct rt56xx_cmd),
  3825. +   RT_SET_CODEC_BASS_BACK_IOCTL = _IOW('R', 0x0B, struct rt56xx_cmd),
  3826. +   RT_GET_CODEC_BASS_BACK_IOCTL = _IOR('R', 0x0B, struct rt56xx_cmd),
  3827. +   RT_SET_CODEC_DIPOLE_SPK_IOCTL = _IOW('R', 0x0C, struct rt56xx_cmd),
  3828. +   RT_GET_CODEC_DIPOLE_SPK_IOCTL = _IOR('R', 0x0C, struct rt56xx_cmd),
  3829. +   RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL = _IOW('R', 0x0D, struct rt56xx_cmd),
  3830. +   RT_GET_CODEC_DRC_AGC_ENABLE_IOCTL = _IOR('R', 0x0D, struct rt56xx_cmd),
  3831. +   RT_SET_CODEC_DSP_MODE_IOCTL = _IOW('R', 0x0E, struct rt56xx_cmd),
  3832. +   RT_GET_CODEC_DSP_MODE_IOCTL = _IOR('R', 0x0E, struct rt56xx_cmd),
  3833. +   RT_SET_CODEC_WNR_ENABLE_IOCTL = _IOW('R', 0x0F, struct rt56xx_cmd),
  3834. +   RT_GET_CODEC_WNR_ENABLE_IOCTL = _IOR('R', 0x0F, struct rt56xx_cmd),
  3835. +   RT_SET_CODEC_DRC_AGC_PAR_IOCTL = _IOW('R', 0x10, struct rt56xx_cmd),
  3836. +   RT_GET_CODEC_DRC_AGC_PAR_IOCTL = _IOR('R', 0x10, struct rt56xx_cmd),
  3837. +   RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL = _IOW('R', 0x11, struct rt56xx_cmd),
  3838. +   RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL = _IOR('R', 0x11, struct rt56xx_cmd),
  3839. +   RT_SET_CODEC_NOISE_GATE_IOCTL = _IOW('R', 0x12, struct rt56xx_cmd),
  3840. +   RT_GET_CODEC_NOISE_GATE_IOCTL = _IOR('R', 0x12, struct rt56xx_cmd),
  3841. +   RT_SET_CODEC_DRC_AGC_COMP_IOCTL = _IOW('R', 0x13, struct rt56xx_cmd),
  3842. +   RT_GET_CODEC_DRC_AGC_COMP_IOCTL = _IOR('R', 0x13, struct rt56xx_cmd),
  3843. +   RT_GET_CODEC_ID = _IOR('R', 0x30, struct rt56xx_cmd),
  3844. +};
  3845. diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
  3846. index 2a8b4f1..1217aaa 100644
  3847. --- a/sound/soc/tegra/Kconfig
  3848. +++ b/sound/soc/tegra/Kconfig
  3849. @@ -200,6 +200,8 @@ config SND_SOC_TEGRA_RT5640
  3850.     select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
  3851.     select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
  3852.     select SND_SOC_RT5640
  3853. +   select SND_SOC_RT5642
  3854. +   select SND_HWDEP
  3855.     select SND_SOC_SPDIF
  3856.     select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
  3857.     help
  3858. @@ -228,3 +230,6 @@ config SND_SOC_TEGRA_MAX98095
  3859.       Say Y or M here if you want to add support for SoC audio on Tegra
  3860.       boards using the MAX98095 codec. Currently, only supported board is
  3861.       Cardhu.
  3862. +config HEADSET_FUNCTION
  3863. +    tristate "Headset detection function"
  3864. +    default n
  3865. diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
  3866. index d546046..adf7588 100644
  3867. --- a/sound/soc/tegra/Makefile
  3868. +++ b/sound/soc/tegra/Makefile
  3869. @@ -38,4 +38,5 @@ obj-$(CONFIG_SND_SOC_TEGRA_MAX98088) += snd-soc-tegra-max98088.o
  3870.  obj-$(CONFIG_SND_SOC_TEGRA_TLV320AIC326X) += snd-soc-tegra-aic326x.o
  3871.  obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
  3872.  obj-$(CONFIG_SND_SOC_TEGRA_MAX98095) += snd-soc-tegra-max98095.o
  3873. +obj-$(CONFIG_HEADSET_FUNCTION) += headset.o
  3874.  obj-$(CONFIG_SND_SOC_TEGRA_P1852) += snd-soc-tegra-p1852.o
  3875. diff --git a/sound/soc/tegra/headset.c b/sound/soc/tegra/headset.c
  3876. new file mode 100644
  3877. index 0000000..368d0cd
  3878. --- /dev/null
  3879. +++ b/sound/soc/tegra/headset.c
  3880. @@ -0,0 +1,627 @@
  3881. +/*
  3882. + *  Headset device detection driver.
  3883. + *
  3884. + * Copyright (C) 2011 ASUSTek Corporation.
  3885. + *
  3886. + * Authors:
  3887. + *  Jason Cheng <jason4_cheng@asus.com>
  3888. + *
  3889. + * This software is licensed under the terms of the GNU General Public
  3890. + * License version 2, as published by the Free Software Foundation, and
  3891. + * may be copied, distributed, and modified under those terms.
  3892. + *
  3893. + * This program is distributed in the hope that it will be useful,
  3894. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3895. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3896. + * GNU General Public License for more details.
  3897. + *
  3898. + */
  3899. +#include <linux/module.h>
  3900. +#include <linux/fs.h>
  3901. +#include <linux/interrupt.h>
  3902. +#include <linux/workqueue.h>
  3903. +#include <linux/irq.h>
  3904. +#include <linux/delay.h>
  3905. +#include <linux/types.h>
  3906. +#include <linux/input.h>
  3907. +#include <linux/mutex.h>
  3908. +#include <linux/errno.h>
  3909. +#include <linux/err.h>
  3910. +#include <linux/hrtimer.h>
  3911. +#include <linux/timer.h>
  3912. +#include <linux/switch.h>
  3913. +#include <linux/input.h>
  3914. +#include <linux/slab.h>
  3915. +#include <asm/gpio.h>
  3916. +#include <asm/uaccess.h>
  3917. +#include <asm/string.h>
  3918. +#include <sound/soc.h>
  3919. +#include "../gpio-names.h"
  3920. +#include "../codecs/rt5640.h"
  3921. +#include <mach/board-grouper-misc.h>
  3922. +#include <mach/pinmux.h>
  3923. +#include "../board.h"
  3924. +#include "../board-grouper.h"
  3925. +MODULE_DESCRIPTION("Headset detection driver");
  3926. +MODULE_LICENSE("GPL");
  3927. +
  3928. +#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io)       \
  3929. +        {                                                       \
  3930. +                .pingroup       = TEGRA_PINGROUP_##_pingroup,   \
  3931. +                .func           = TEGRA_MUX_##_mux,             \
  3932. +                .pupd           = TEGRA_PUPD_##_pupd,           \
  3933. +                .tristate       = TEGRA_TRI_##_tri,             \
  3934. +                .io             = TEGRA_PIN_##_io,              \
  3935. +                .lock           = TEGRA_PIN_LOCK_DEFAULT,       \
  3936. +                .od             = TEGRA_PIN_OD_DEFAULT,         \
  3937. +                .ioreset        = TEGRA_PIN_IO_RESET_DEFAULT,   \
  3938. +        }
  3939. +
  3940. +/*----------------------------------------------------------------------------
  3941. +** FUNCTION DECLARATION
  3942. +**----------------------------------------------------------------------------*/
  3943. +static int   __init        headset_init(void);
  3944. +static void __exit    headset_exit(void);
  3945. +static irqreturn_t     detect_irq_handler(int irq, void *dev_id);
  3946. +static void        detection_work(struct work_struct *work);
  3947. +static int                 jack_config_gpio(void);
  3948. +static irqreturn_t     lineout_irq_handler(int irq, void *dev_id);
  3949. +static void        lineout_work_queue(struct work_struct *work);
  3950. +static void        dock_work_queue(struct work_struct *work);
  3951. +static int                 lineout_config_gpio(u32 project_info);
  3952. +static void        detection_work(struct work_struct *work);
  3953. +static int                 btn_config_gpio(void);
  3954. +static int                      switch_config_gpio(void);
  3955. +int            hs_micbias_power(int on);
  3956. +static irqreturn_t dockin_irq_handler(int irq, void *dev_id);
  3957. +static void        set_dock_switches(void);
  3958. +/*----------------------------------------------------------------------------
  3959. +** GLOBAL VARIABLES
  3960. +**----------------------------------------------------------------------------*/
  3961. +#define JACK_GPIO      (TEGRA_GPIO_PW2)
  3962. +#define LINEOUT_GPIO_NAKASI    (TEGRA_GPIO_PW3)
  3963. +#define LINEOUT_GPIO_BACH  (TEGRA_GPIO_PX6)
  3964. +#define HOOK_GPIO      (TEGRA_GPIO_PX2)
  3965. +#define UART_HEADPHONE_SWITCH (TEGRA_GPIO_PS2)
  3966. +#define ON (1)
  3967. +#define OFF    (0)
  3968. +
  3969. +enum{
  3970. +   NO_DEVICE = 0,
  3971. +   HEADSET_WITH_MIC = 1,
  3972. +   HEADSET_WITHOUT_MIC = 2,
  3973. +};
  3974. +
  3975. +struct headset_data {
  3976. +   struct switch_dev sdev;
  3977. +   struct input_dev *input;
  3978. +   unsigned int irq;
  3979. +   struct hrtimer timer;
  3980. +   ktime_t debouncing_time;
  3981. +};
  3982. +
  3983. +static struct headset_data *hs_data;
  3984. +bool headset_alive = false;
  3985. +EXPORT_SYMBOL(headset_alive);
  3986. +bool lineout_alive;
  3987. +EXPORT_SYMBOL(lineout_alive);
  3988. +
  3989. +static struct workqueue_struct *g_detection_work_queue;
  3990. +static DECLARE_WORK(g_detection_work, detection_work);
  3991. +
  3992. +extern struct snd_soc_codec *rt5640_audio_codec;
  3993. +struct work_struct headset_work;
  3994. +struct work_struct lineout_work;
  3995. +struct work_struct dock_work;
  3996. +static bool UART_enable = false;
  3997. +static unsigned int revision;
  3998. +static u32 lineout_gpio;
  3999. +static int gpio_dock_in = 0;
  4000. +
  4001. +static struct switch_dev dock_switch = {
  4002. +   .name = "dock",
  4003. +};
  4004. +
  4005. +static struct switch_dev audio_switch = {
  4006. +   .name = "usb_audio",
  4007. +};
  4008. +
  4009. +static ssize_t headset_name_show(struct switch_dev *sdev, char *buf)
  4010. +{
  4011. +   switch (switch_get_state(&hs_data->sdev)){
  4012. +   case NO_DEVICE:{
  4013. +       return sprintf(buf, "%s\n", "No Device");
  4014. +       }
  4015. +   case HEADSET_WITH_MIC:{
  4016. +       return sprintf(buf, "%s\n", "HEADSET");
  4017. +       }
  4018. +   case HEADSET_WITHOUT_MIC:{
  4019. +       return sprintf(buf, "%s\n", "HEADPHONE");
  4020. +       }
  4021. +   }
  4022. +   return -EINVAL;
  4023. +}
  4024. +
  4025. +static ssize_t headset_state_show(struct switch_dev *sdev, char *buf)
  4026. +{
  4027. +   switch (switch_get_state(&hs_data->sdev)){
  4028. +   case NO_DEVICE:
  4029. +       return sprintf(buf, "%d\n", 0);
  4030. +   case HEADSET_WITH_MIC:
  4031. +       return sprintf(buf, "%d\n", 1);
  4032. +   case HEADSET_WITHOUT_MIC:
  4033. +       return sprintf(buf, "%d\n", 2);
  4034. +   }
  4035. +   return -EINVAL;
  4036. +}
  4037. +
  4038. +static void tristate_uart(void)
  4039. +{
  4040. +        enum tegra_pingroup pingroup = TEGRA_PINGROUP_ULPI_DATA0;
  4041. +        enum tegra_pullupdown pupd = TEGRA_PUPD_PULL_DOWN;
  4042. +        enum tegra_pin_io io = TEGRA_PIN_INPUT;
  4043. +   enum tegra_tristate tristate = TEGRA_TRI_TRISTATE;
  4044. +
  4045. +        tegra_pinmux_set_pullupdown(pingroup, pupd);
  4046. +        tegra_pinmux_set_tristate(pingroup, tristate);
  4047. +}
  4048. +
  4049. +
  4050. +static void pulldown_uart(void)
  4051. +{
  4052. +   enum tegra_pingroup pingroupTx = TEGRA_PINGROUP_ULPI_DATA0;
  4053. +   enum tegra_pingroup pingroupRx = TEGRA_PINGROUP_ULPI_DATA1;
  4054. +        enum tegra_pullupdown pupd = TEGRA_PUPD_PULL_DOWN;
  4055. +        enum tegra_pin_io io = TEGRA_PIN_INPUT;
  4056. +
  4057. +   tegra_pinmux_set_pullupdown(pingroupTx, pupd);
  4058. +   tegra_pinmux_set_io(pingroupTx, io);
  4059. +//        tegra_pinmux_set_pullupdown(pingroupRx, pupd);
  4060. +  //      tegra_pinmux_set_io(pingroupRx, io);
  4061. +}
  4062. +
  4063. +
  4064. +static void normal_uart(void)
  4065. +{
  4066. +   struct tegra_pingroup_config debug_uart [] = {
  4067. +        DEFAULT_PINMUX(ULPI_DATA0,      UARTA,          NORMAL,     NORMAL,     OUTPUT),
  4068. +        };
  4069. +        tegra_pinmux_config_table(debug_uart, ARRAY_SIZE(debug_uart));
  4070. +
  4071. +   //     tegra_pinmux_set_pullupdown(pingroupRx, pupd);
  4072. +    //    tegra_pinmux_set_io(pingroupRx, ioIn);
  4073. +
  4074. +}
  4075. +
  4076. +
  4077. +static void enable_uart(void)
  4078. +{
  4079. +   struct tegra_pingroup_config debug_uart [] = {
  4080. +        DEFAULT_PINMUX(ULPI_DATA0,      ULPI,          NORMAL,    NORMAL,   OUTPUT),
  4081. +        };
  4082. +        tegra_pinmux_config_table(debug_uart, ARRAY_SIZE(debug_uart));
  4083. +}
  4084. +
  4085. +
  4086. +static void disable_uart(void)
  4087. +{
  4088. +   struct tegra_pingroup_config debug_uart [] = {
  4089. +   DEFAULT_PINMUX(ULPI_DATA0,      ULPI,          PULL_UP,    TRISTATE,   OUTPUT),
  4090. +   };
  4091. +   tegra_pinmux_config_table(debug_uart, ARRAY_SIZE(debug_uart));
  4092. +}
  4093. +static void insert_headset(void)
  4094. +{
  4095. +        struct snd_soc_dapm_context *dapm;
  4096. +
  4097. +        dapm = &rt5640_audio_codec->dapm;
  4098. +
  4099. +   if(gpio_get_value(lineout_gpio) == 0 && UART_enable){
  4100. +                printk("%s: debug board\n", __func__);
  4101. +                switch_set_state(&hs_data->sdev, NO_DEVICE);
  4102. +                hs_micbias_power(OFF);
  4103. +                headset_alive = false;
  4104. +       gpio_direction_output(UART_HEADPHONE_SWITCH, 0);
  4105. +       normal_uart();
  4106. +   }else if(gpio_get_value(HOOK_GPIO)){
  4107. +       printk("%s: headphone\n", __func__);
  4108. +       switch_set_state(&hs_data->sdev, HEADSET_WITHOUT_MIC);
  4109. +       hs_micbias_power(OFF);
  4110. +       pulldown_uart();
  4111. +       gpio_direction_output(UART_HEADPHONE_SWITCH, 1);
  4112. +       headset_alive = false;
  4113. +   }else{
  4114. +       printk("%s: headset\n", __func__);
  4115. +       switch_set_state(&hs_data->sdev, HEADSET_WITHOUT_MIC);
  4116. +       hs_micbias_power(ON);
  4117. +       pulldown_uart();
  4118. +       gpio_direction_output(UART_HEADPHONE_SWITCH, 1);
  4119. +       headset_alive = true;
  4120. +   }
  4121. +   hs_data->debouncing_time = ktime_set(0, 100000000);  /* 100 ms */
  4122. +}
  4123. +static void remove_headset(void)
  4124. +{
  4125. +   switch_set_state(&hs_data->sdev, NO_DEVICE);
  4126. +   hs_data->debouncing_time = ktime_set(0, 100000000);  /* 100 ms */
  4127. +   headset_alive = false;
  4128. +   tristate_uart();
  4129. +   gpio_direction_output(UART_HEADPHONE_SWITCH, 0);
  4130. +}
  4131. +
  4132. +static void detection_work(struct work_struct *work)
  4133. +{
  4134. +   unsigned long irq_flags;
  4135. +   int cable_in1;
  4136. +   int mic_in = 0;
  4137. +   hs_micbias_power(ON);
  4138. +   /* Disable headset interrupt while detecting.*/
  4139. +   local_irq_save(irq_flags);
  4140. +   disable_irq(hs_data->irq);
  4141. +   local_irq_restore(irq_flags);
  4142. +
  4143. +   /* Delay 1000ms for pin stable. */
  4144. +   msleep(1000);
  4145. +
  4146. +   /* Restore IRQs */
  4147. +   local_irq_save(irq_flags);
  4148. +   enable_irq(hs_data->irq);
  4149. +   local_irq_restore(irq_flags);
  4150. +
  4151. +   if (gpio_get_value(JACK_GPIO) != 0) {
  4152. +       /* Headset not plugged in */
  4153. +
  4154. +//     if (switch_get_state(&hs_data->sdev) == HEADSET_WITH_MIC ||
  4155. +//         switch_get_state(&hs_data->sdev) == HEADSET_WITHOUT_MIC)
  4156. +           remove_headset();
  4157. +       goto closed_micbias;
  4158. +   }
  4159. +
  4160. +   cable_in1 = gpio_get_value(JACK_GPIO);
  4161. +   mic_in  = gpio_get_value(HOOK_GPIO);
  4162. +   if (cable_in1 == 0) {
  4163. +       printk("HOOK_GPIO value: %d\n", mic_in);
  4164. +       if(switch_get_state(&hs_data->sdev) == NO_DEVICE)
  4165. +           insert_headset();
  4166. +       else if ( mic_in == 1)
  4167. +           goto closed_micbias;
  4168. +   } else{
  4169. +       printk("HEADSET: Jack-in GPIO is low, but not a headset \n");
  4170. +       goto closed_micbias;
  4171. +   }
  4172. +   return;
  4173. +
  4174. +closed_micbias:
  4175. +   hs_micbias_power(OFF);
  4176. +   return;
  4177. +}
  4178. +
  4179. +static enum hrtimer_restart detect_event_timer_func(struct hrtimer *data)
  4180. +{
  4181. +   queue_work(g_detection_work_queue, &g_detection_work);
  4182. +   return HRTIMER_NORESTART;
  4183. +}
  4184. +
  4185. +/**********************************************************
  4186. +**  Function: Jack detection-in gpio configuration function
  4187. +**  Parameter: none
  4188. +**  Return value: if sucess, then returns 0
  4189. +**
  4190. +************************************************************/
  4191. +static int jack_config_gpio()
  4192. +{
  4193. +   int ret;
  4194. +
  4195. +   printk("HEADSET: Config Jack-in detection gpio\n");
  4196. +   hs_micbias_power(ON);
  4197. +   tegra_gpio_enable(JACK_GPIO);
  4198. +   ret = gpio_request(JACK_GPIO, "h2w_detect");
  4199. +   ret = gpio_direction_input(JACK_GPIO);
  4200. +
  4201. +   hs_data->irq = gpio_to_irq(JACK_GPIO);
  4202. +   ret = request_irq(hs_data->irq, detect_irq_handler,
  4203. +             IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "h2w_detect", NULL);
  4204. +
  4205. +   ret = irq_set_irq_wake(hs_data->irq, 1);
  4206. +   msleep(1);
  4207. +   if (gpio_get_value(JACK_GPIO) == 0){
  4208. +       insert_headset();
  4209. +   }else {
  4210. +       hs_micbias_power(OFF);
  4211. +       headset_alive = false;
  4212. +       switch_set_state(&hs_data->sdev, NO_DEVICE);
  4213. +       remove_headset();
  4214. +   }
  4215. +
  4216. +   return 0;
  4217. +}
  4218. +
  4219. +/**********************************************************
  4220. +**  Function: Headset Hook Key Detection interrupt handler
  4221. +**  Parameter: irq
  4222. +**  Return value: IRQ_HANDLED
  4223. +**  High: Hook button pressed
  4224. +************************************************************/
  4225. +static int btn_config_gpio()
  4226. +{
  4227. +   int ret;
  4228. +
  4229. +   printk("HEADSET: Config Headset Button detection gpio\n");
  4230. +
  4231. +   tegra_gpio_enable(HOOK_GPIO);
  4232. +   ret = gpio_request(HOOK_GPIO, "btn_INT");
  4233. +   ret = gpio_direction_input(HOOK_GPIO);
  4234. +
  4235. +   return 0;
  4236. +}
  4237. +
  4238. +static void lineout_work_queue(struct work_struct *work)
  4239. +{
  4240. +   msleep(300);
  4241. +
  4242. +   if (gpio_get_value(lineout_gpio) == 0){
  4243. +       printk("LINEOUT: LineOut inserted\n");
  4244. +       lineout_alive = true;
  4245. +   }else if(gpio_get_value(lineout_gpio)){
  4246. +       printk("LINEOUT: LineOut removed\n");
  4247. +       lineout_alive = false;
  4248. +   }
  4249. +
  4250. +}
  4251. +
  4252. +static void set_dock_switches(void)
  4253. +{
  4254. +   bool docked = !gpio_get_value(gpio_dock_in);
  4255. +
  4256. +   /* LE desk dock == 3, undocked == 0. */
  4257. +   switch_set_state(&dock_switch, docked ? 3 : 0);
  4258. +
  4259. +   /*
  4260. +    * Analog audio == 1, no audio == 0.
  4261. +    * Note that because we cannot detect the presence of a 3.5mm jack
  4262. +    * in the dock's audio socket, when docked, audio is always on.
  4263. +    */
  4264. +   switch_set_state(&audio_switch, docked ? 1 : 0);
  4265. +}
  4266. +
  4267. +static void dock_work_queue(struct work_struct *work)
  4268. +{
  4269. +   set_dock_switches();
  4270. +}
  4271. +
  4272. +/**********************************************************
  4273. +**  Function: LineOut Detection configuration function
  4274. +**  Parameter: none
  4275. +**  Return value: IRQ_HANDLED
  4276. +**
  4277. +************************************************************/
  4278. +static int lineout_config_gpio(u32 project_info)
  4279. +{
  4280. +   int ret;
  4281. +
  4282. +   printk("HEADSET: Config LineOut detection gpio\n");
  4283. +   if(project_info == GROUPER_PROJECT_BACH)
  4284. +       lineout_gpio = LINEOUT_GPIO_BACH;
  4285. +   else if(project_info == GROUPER_PROJECT_NAKASI)
  4286. +       lineout_gpio = LINEOUT_GPIO_NAKASI;
  4287. +   tegra_gpio_enable(lineout_gpio);
  4288. +   ret = gpio_request(lineout_gpio, "lineout_int");
  4289. +   ret = gpio_direction_input(lineout_gpio);
  4290. +#if 0
  4291. +   ret = request_irq(gpio_to_irq(LINEOUT_GPIO), &lineout_irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "lineout_int", 0);
  4292. +#endif
  4293. +   if (gpio_get_value(lineout_gpio) == 0)
  4294. +       lineout_alive = true;
  4295. +   else
  4296. +       lineout_alive = false;
  4297. +
  4298. +   return 0;
  4299. +}
  4300. +
  4301. +static int switch_config_gpio()
  4302. +{
  4303. +        int ret;
  4304. +
  4305. +        printk("HEADSET: Config uart<->headphone gpio\n");
  4306. +
  4307. +        tegra_gpio_enable(UART_HEADPHONE_SWITCH);
  4308. +        ret = gpio_request(UART_HEADPHONE_SWITCH, "uart_headphone_switch");
  4309. +
  4310. +        return 0;
  4311. +}
  4312. +
  4313. +static int dockin_config_gpio()
  4314. +{
  4315. +   int ret = 0;
  4316. +   int irq_num = 0;
  4317. +
  4318. +   irq_num = gpio_to_irq(gpio_dock_in);
  4319. +   ret = request_irq(irq_num, dockin_irq_handler,
  4320. +       IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING | IRQF_SHARED, "dock_detect", hs_data);
  4321. +   if(ret < 0)
  4322. +       printk("%s: request irq fail errno = %d\n", __func__, ret);
  4323. +
  4324. +        return ret;
  4325. +}
  4326. +
  4327. +static irqreturn_t dockin_irq_handler(int irq, void *dev_id)
  4328. +{
  4329. +   schedule_work(&dock_work);
  4330. +
  4331. +        return IRQ_HANDLED;
  4332. +}
  4333. +
  4334. +/**********************************************************
  4335. +**  Function: LineOut detection interrupt handler
  4336. +**  Parameter: dedicated irq
  4337. +**  Return value: if sucess, then returns IRQ_HANDLED
  4338. +**
  4339. +************************************************************/
  4340. +static irqreturn_t lineout_irq_handler(int irq, void *dev_id)
  4341. +{
  4342. +   schedule_work(&lineout_work);
  4343. +   return IRQ_HANDLED;
  4344. +}
  4345. +
  4346. +/**********************************************************
  4347. +**  Function: Headset jack-in detection interrupt handler
  4348. +**  Parameter: dedicated irq
  4349. +**  Return value: if sucess, then returns IRQ_HANDLED
  4350. +**
  4351. +************************************************************/
  4352. +static irqreturn_t detect_irq_handler(int irq, void *dev_id)
  4353. +{
  4354. +   int value1, value2;
  4355. +   int retry_limit = 10;
  4356. +
  4357. +   do {
  4358. +       value1 = gpio_get_value(JACK_GPIO);
  4359. +       irq_set_irq_type(hs_data->irq, value1 ?
  4360. +               IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
  4361. +       value2 = gpio_get_value(JACK_GPIO);
  4362. +   }while (value1 != value2 && retry_limit-- > 0);
  4363. +
  4364. +   if ((switch_get_state(&hs_data->sdev) == NO_DEVICE) ^ value2){
  4365. +       hrtimer_start(&hs_data->timer, hs_data->debouncing_time, HRTIMER_MODE_REL);
  4366. +   }
  4367. +
  4368. +   return IRQ_HANDLED;
  4369. +}
  4370. +
  4371. +static int codec_micbias_power(int on)
  4372. +{
  4373. +   if(on){
  4374. +       //for ALC5642
  4375. +       if(rt5640_audio_codec == NULL){
  4376. +           printk("%s: No rt5640_audio_codec - set micbias on fail\n", __func__);
  4377. +           return 0;
  4378. +       }
  4379. +#if 0
  4380. +       snd_soc_update_bits(rt5640_audio_codec, RT5640_PWR_ANLG1, RT5640_PWR_LDO2, RT5640_PWR_LDO2); /* Enable LDO2 */
  4381. +       snd_soc_update_bits(rt5640_audio_codec, RT5640_PWR_ANLG2, RT5640_PWR_MB1, RT5640_PWR_MB1); /*Enable MicBias1 */
  4382. +       //for ALC5642
  4383. +#endif
  4384. +   }else{
  4385. +       //for ALC5642
  4386. +       if(rt5640_audio_codec == NULL){
  4387. +           printk("%s: No rt5640_audio_codec - set micbias off fail\n", __func__);
  4388. +           return 0;
  4389. +       }
  4390. +       snd_soc_update_bits(rt5640_audio_codec, RT5640_PWR_ANLG2, RT5640_PWR_MB1, 0); /* Disable MicBias1 */
  4391. +       snd_soc_update_bits(rt5640_audio_codec, RT5640_PWR_ANLG1, RT5640_PWR_LDO2, 0); /* Disable LDO2 */
  4392. +       //for ALC5642
  4393. +   }
  4394. +   return 0;
  4395. +}
  4396. +
  4397. +
  4398. +int hs_micbias_power(int on)
  4399. +{
  4400. +   static int nLastVregStatus = -1;
  4401. +
  4402. +   if(on && nLastVregStatus!=ON){
  4403. +       printk("HEADSET: Turn on micbias power\n");
  4404. +       nLastVregStatus = ON;
  4405. +       codec_micbias_power(ON);
  4406. +   }
  4407. +   else if(!on && nLastVregStatus!=OFF){
  4408. +       printk("HEADSET: Turn off micbias power\n");
  4409. +       nLastVregStatus = OFF;
  4410. +       codec_micbias_power(OFF);
  4411. +   }
  4412. +   return 0;
  4413. +}
  4414. +EXPORT_SYMBOL(hs_micbias_power);
  4415. +
  4416. +/**********************************************************
  4417. +**  Function: Headset driver init function
  4418. +**  Parameter: none
  4419. +**  Return value: none
  4420. +**
  4421. +************************************************************/
  4422. +static int __init headset_init(void)
  4423. +{
  4424. +   u32 project_info = grouper_get_project_id();
  4425. +   u32 pmic_id = grouper_query_pmic_id();
  4426. +
  4427. +   printk(KERN_INFO "%s+ #####\n", __func__);
  4428. +   int ret;
  4429. +
  4430. +   printk("HEADSET: Headset detection init\n");
  4431. +
  4432. +   if (project_info == GROUPER_PROJECT_BACH)
  4433. +       gpio_dock_in = TEGRA_GPIO_PO5;
  4434. +   else
  4435. +       gpio_dock_in = TEGRA_GPIO_PU4;
  4436. +
  4437. +   if(project_info == GROUPER_PROJECT_BACH ||
  4438. +       (project_info == GROUPER_PROJECT_NAKASI && pmic_id ==GROUPER_PMIC_TI))
  4439. +       UART_enable = true;
  4440. +
  4441. +   revision = grouper_query_pcba_revision();
  4442. +
  4443. +   hs_data = kzalloc(sizeof(struct headset_data), GFP_KERNEL);
  4444. +   if (!hs_data)
  4445. +       return -ENOMEM;
  4446. +
  4447. +   hs_data->debouncing_time = ktime_set(0, 100000000);  /* 100 ms */
  4448. +   hs_data->sdev.name = "h2w";
  4449. +   hs_data->sdev.print_name = headset_name_show;
  4450. +   hs_data->sdev.print_state = headset_state_show;
  4451. +
  4452. +   ret = switch_dev_register(&hs_data->sdev);
  4453. +   if (ret < 0)
  4454. +       goto err_switch_dev_register;
  4455. +
  4456. +   WARN_ON(switch_dev_register(&dock_switch));
  4457. +   WARN_ON(switch_dev_register(&audio_switch));
  4458. +   /* Make sure dock switches are correct at boot */
  4459. +   set_dock_switches();
  4460. +
  4461. +   g_detection_work_queue = create_workqueue("detection");
  4462. +
  4463. +   hrtimer_init(&hs_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  4464. +   hs_data->timer.function = detect_event_timer_func;
  4465. +
  4466. +   printk("HEADSET: Headset detection mode\n");
  4467. +   lineout_config_gpio(project_info);
  4468. +   btn_config_gpio();/*Config hook detection GPIO*/
  4469. +   switch_config_gpio(); /*Config uart and headphone switch*/
  4470. +   jack_config_gpio();/*Config jack detection GPIO*/
  4471. +   INIT_WORK(&lineout_work, lineout_work_queue);
  4472. +   INIT_WORK(&dock_work, dock_work_queue);
  4473. +   dockin_config_gpio();
  4474. +
  4475. +   printk(KERN_INFO "%s- #####\n", __func__);
  4476. +   return 0;
  4477. +
  4478. +err_switch_dev_register:
  4479. +   printk(KERN_ERR "Headset: Failed to register driver\n");
  4480. +
  4481. +   return ret;
  4482. +}
  4483. +
  4484. +/**********************************************************
  4485. +**  Function: Headset driver exit function
  4486. +**  Parameter: none
  4487. +**  Return value: none
  4488. +**
  4489. +************************************************************/
  4490. +static void __exit headset_exit(void)
  4491. +{
  4492. +   printk("HEADSET: Headset exit\n");
  4493. +   if (switch_get_state(&hs_data->sdev))
  4494. +       remove_headset();
  4495. +   gpio_free(JACK_GPIO);
  4496. +   gpio_free(HOOK_GPIO);
  4497. +   gpio_free(lineout_gpio);
  4498. +
  4499. +   free_irq(hs_data->irq, 0);
  4500. +   destroy_workqueue(g_detection_work_queue);
  4501. +   switch_dev_unregister(&hs_data->sdev);
  4502. +   switch_dev_unregister(&dock_switch);
  4503. +   switch_dev_unregister(&audio_switch);
  4504. +}
  4505. +
  4506. +module_init(headset_init);
  4507. +module_exit(headset_exit);
  4508. diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
  4509. index f277d28..7186f3d 100644
  4510. --- a/sound/soc/tegra/tegra_pcm.c
  4511. +++ b/sound/soc/tegra/tegra_pcm.c
  4512. @@ -2,7 +2,7 @@
  4513.   * tegra_pcm.c - Tegra PCM driver
  4514.   *
  4515.   * Author: Stephen Warren <swarren@nvidia.com>
  4516. - * Copyright (C) 2010 - NVIDIA, Inc.
  4517. + * Copyright (C) 2010-2012 - NVIDIA, Inc.
  4518.   *
  4519.   * Based on code copyright/by:
  4520.   *
  4521. @@ -29,6 +29,7 @@
  4522.   *
  4523.   */
  4524.  
  4525. +#include <asm/mach-types.h>
  4526.  #include <linux/module.h>
  4527.  #include <linux/dma-mapping.h>
  4528.  #include <linux/slab.h>
  4529. @@ -41,6 +42,9 @@
  4530.  
  4531.  #define DRV_NAME "tegra-pcm-audio"
  4532.  
  4533. +#define PERIOD_BYTES_MAX   (PAGE_SIZE * 2)
  4534. +#define PERIODS_MAX        64
  4535. +
  4536.  static const struct snd_pcm_hardware tegra_pcm_hardware = {
  4537.     .info           = SNDRV_PCM_INFO_MMAP |
  4538.                   SNDRV_PCM_INFO_MMAP_VALID |
  4539. @@ -51,10 +55,10 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
  4540.     .channels_min       = 1,
  4541.     .channels_max       = 2,
  4542.     .period_bytes_min   = 128,
  4543. -   .period_bytes_max   = PAGE_SIZE,
  4544. +   .period_bytes_max   = PERIOD_BYTES_MAX,
  4545.     .periods_min        = 2,
  4546. -   .periods_max        = 8,
  4547. -   .buffer_bytes_max   = PAGE_SIZE * 8,
  4548. +   .periods_max        = PERIODS_MAX,
  4549. +   .buffer_bytes_max   = PERIOD_BYTES_MAX * PERIODS_MAX,
  4550.     .fifo_size      = 4,
  4551.  };
  4552.  
  4553. @@ -262,8 +266,11 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  4554.         spin_lock_irqsave(&prtd->lock, flags);
  4555.         prtd->running = 0;
  4556.         spin_unlock_irqrestore(&prtd->lock, flags);
  4557. -       tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
  4558. -       tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
  4559. +       tegra_dma_cancel(prtd->dma_chan);
  4560. +       if (prtd->dma_req[0].status == -TEGRA_DMA_REQ_ERROR_ABORTED)
  4561. +           prtd->dma_req[0].complete(&prtd->dma_req[0]);
  4562. +       if (prtd->dma_req[1].status == -TEGRA_DMA_REQ_ERROR_ABORTED)
  4563. +           prtd->dma_req[1].complete(&prtd->dma_req[1]);
  4564.         break;
  4565.     default:
  4566.         return -EINVAL;
  4567. @@ -386,10 +393,19 @@ static void tegra_pcm_free(struct snd_pcm *pcm)
  4568.     tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
  4569.  }
  4570.  
  4571. +static int tegra_pcm_probe(struct snd_soc_platform *platform)
  4572. +{
  4573. +   if(machine_is_kai() || machine_is_grouper())
  4574. +       platform->dapm.idle_bias_off = 1;
  4575. +
  4576. +   return 0;
  4577. +}
  4578. +
  4579.  struct snd_soc_platform_driver tegra_pcm_platform = {
  4580.     .ops        = &tegra_pcm_ops,
  4581.     .pcm_new    = tegra_pcm_new,
  4582.     .pcm_free   = tegra_pcm_free,
  4583. +   .probe      = tegra_pcm_probe,
  4584.  };
  4585.  
  4586.  static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev)
  4587. diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
  4588. index 268228e..1fff7ec 100644
  4589. --- a/sound/soc/tegra/tegra_rt5640.c
  4590. +++ b/sound/soc/tegra/tegra_rt5640.c
  4591. @@ -69,6 +69,8 @@ struct tegra_rt5640 {
  4592.  #ifdef CONFIG_SWITCH
  4593.     int jack_status;
  4594.  #endif
  4595. +   enum snd_soc_bias_level bias_level;
  4596. +   volatile int clock_enabled;
  4597.  };
  4598.  
  4599.  static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
  4600. @@ -277,11 +279,14 @@ static int tegra_rt5640_jack_notifier(struct notifier_block *self,
  4601.     struct snd_soc_codec *codec = jack->codec;
  4602.     struct snd_soc_card *card = codec->card;
  4603.     struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
  4604. +   struct tegra_rt5640_platform_data *pdata = machine->pdata;
  4605.     enum headset_state state = BIT_NO_HEADSET;
  4606.     unsigned char status_jack;
  4607. -
  4608. +#if 0
  4609.     if (jack == &tegra_rt5640_hp_jack) {
  4610.         if (action) {
  4611. +           /* Enable ext mic; enable signal is active-low */
  4612. +           gpio_direction_output(pdata->gpio_ext_mic_en, 0);
  4613.             if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
  4614.                 status_jack = rt5639_headset_detect(codec, 1);
  4615.             else if (!strncmp(machine->pdata->codec_name, "rt5640",
  4616. @@ -302,6 +307,8 @@ static int tegra_rt5640_jack_notifier(struct notifier_block *self,
  4617.                             SND_JACK_MICROPHONE;
  4618.             }
  4619.         } else {
  4620. +           /* Disable ext mic; enable signal is active-low */
  4621. +           gpio_direction_output(pdata->gpio_ext_mic_en, 1);
  4622.             if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
  4623.                 rt5639_headset_detect(codec, 0);
  4624.             else if (!strncmp(machine->pdata->codec_name, "rt5640",
  4625. @@ -312,7 +319,7 @@ static int tegra_rt5640_jack_notifier(struct notifier_block *self,
  4626.             machine->jack_status &= ~SND_JACK_MICROPHONE;
  4627.         }
  4628.     }
  4629. -
  4630. +#endif
  4631.     switch (machine->jack_status) {
  4632.     case SND_JACK_HEADPHONE:
  4633.         state = BIT_HEADSET_NO_MIC;
  4634. @@ -427,10 +434,11 @@ static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
  4635.  }
  4636.  
  4637.  static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
  4638. -   SND_SOC_DAPM_SPK("Int Spk", tegra_rt5640_event_int_spk),
  4639. -   SND_SOC_DAPM_HP("Headphone Jack", tegra_rt5640_event_hp),
  4640. -   SND_SOC_DAPM_MIC("Mic Jack", tegra_rt5640_event_ext_mic),
  4641. -   SND_SOC_DAPM_MIC("Int Mic", tegra_rt5640_event_int_mic),
  4642. +   SND_SOC_DAPM_SPK("Int Spk", NULL),
  4643. +   SND_SOC_DAPM_HP("Headphone Jack", NULL),
  4644. +   SND_SOC_DAPM_MIC("Mic Jack", NULL),
  4645. +   SND_SOC_DAPM_MIC("Int Mic", NULL),
  4646. +   SND_SOC_DAPM_SPK("AUX", NULL),
  4647.  };
  4648.  
  4649.  static const struct snd_soc_dapm_route cardhu_audio_map[] = {
  4650. @@ -440,11 +448,12 @@ static const struct snd_soc_dapm_route cardhu_audio_map[] = {
  4651.     {"Int Spk", NULL, "SPORN"},
  4652.     {"Int Spk", NULL, "SPOLP"},
  4653.     {"Int Spk", NULL, "SPOLN"},
  4654. -   {"micbias1", NULL, "Mic Jack"},
  4655. -   {"IN1P", NULL, "micbias1"},
  4656. -   {"IN1N", NULL, "micbias1"},
  4657. -   {"micbias1", NULL, "Int Mic"},
  4658. -   {"IN2P", NULL, "micbias1"},
  4659. +   {"DMIC L1", NULL, "Int Mic"},
  4660. +   {"DMIC R1", NULL, "Int Mic"},
  4661. +   {"micbias2", NULL, "Mic Jack"},
  4662. +   {"MIC2", NULL, "micbias2"},
  4663. +   {"AUX", NULL, "LOUTL"},
  4664. +   {"AUX", NULL, "LOUTR"},
  4665.  };
  4666.  
  4667.  static const struct snd_kcontrol_new cardhu_controls[] = {
  4668. @@ -452,6 +461,7 @@ static const struct snd_kcontrol_new cardhu_controls[] = {
  4669.     SOC_DAPM_PIN_SWITCH("Headphone Jack"),
  4670.     SOC_DAPM_PIN_SWITCH("Mic Jack"),
  4671.     SOC_DAPM_PIN_SWITCH("Int Mic"),
  4672. +   SOC_DAPM_PIN_SWITCH("AUX"),
  4673.  };
  4674.  
  4675.  static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
  4676. @@ -463,69 +473,18 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
  4677.     struct tegra_rt5640_platform_data *pdata = machine->pdata;
  4678.     int ret;
  4679.  
  4680. -   if (gpio_is_valid(pdata->gpio_spkr_en)) {
  4681. -       ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
  4682. -       if (ret) {
  4683. -           dev_err(card->dev, "cannot get spkr_en gpio\n");
  4684. -           return ret;
  4685. -       }
  4686. -       machine->gpio_requested |= GPIO_SPKR_EN;
  4687.  
  4688. -       gpio_direction_output(pdata->gpio_spkr_en, 0);
  4689. -   }
  4690.  
  4691. -   if (gpio_is_valid(pdata->gpio_hp_mute)) {
  4692. -       ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
  4693. -       if (ret) {
  4694. -           dev_err(card->dev, "cannot get hp_mute gpio\n");
  4695. -           return ret;
  4696. -       }
  4697. -       machine->gpio_requested |= GPIO_HP_MUTE;
  4698.  
  4699. -       gpio_direction_output(pdata->gpio_hp_mute, 0);
  4700. -   }
  4701.  
  4702. -   if (gpio_is_valid(pdata->gpio_int_mic_en)) {
  4703. -       ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
  4704. -       if (ret) {
  4705. -           dev_err(card->dev, "cannot get int_mic_en gpio\n");
  4706. -           return ret;
  4707. -       }
  4708. -       machine->gpio_requested |= GPIO_INT_MIC_EN;
  4709.  
  4710.         /* Disable int mic; enable signal is active-high */
  4711. -       gpio_direction_output(pdata->gpio_int_mic_en, 0);
  4712. -   }
  4713.  
  4714. -   if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
  4715. -       ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
  4716. -       if (ret) {
  4717. -           dev_err(card->dev, "cannot get ext_mic_en gpio\n");
  4718. -           return ret;
  4719. -       }
  4720. -       machine->gpio_requested |= GPIO_EXT_MIC_EN;
  4721.  
  4722. -       /* Enable ext mic; enable signal is active-low */
  4723. -       gpio_direction_output(pdata->gpio_ext_mic_en, 0);
  4724. -   }
  4725.  
  4726. -   if (gpio_is_valid(pdata->gpio_hp_det)) {
  4727. -       tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
  4728. -       snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
  4729. -               &tegra_rt5640_hp_jack);
  4730. -#ifndef CONFIG_SWITCH
  4731. -       snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
  4732. -                   ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
  4733. -                   tegra_rt5640_hp_jack_pins);
  4734. -#else
  4735. -       snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
  4736. -                   &tegra_rt5640_jack_detect_nb);
  4737. -#endif
  4738. -       snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
  4739. -                   1,
  4740. -                   &tegra_rt5640_hp_jack_gpio);
  4741. -       machine->gpio_requested |= GPIO_HP_DET;
  4742. -   }
  4743. +
  4744. +   machine->bias_level = SND_SOC_BIAS_STANDBY;
  4745. +   machine->clock_enabled = 1;
  4746.  
  4747.     ret = snd_soc_add_controls(codec, cardhu_controls,
  4748.             ARRAY_SIZE(cardhu_controls));
  4749. @@ -540,7 +499,11 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
  4750.     /* FIXME: Calculate automatically based on DAPM routes? */
  4751.     snd_soc_dapm_nc_pin(dapm, "LOUTL");
  4752.     snd_soc_dapm_nc_pin(dapm, "LOUTR");
  4753. -
  4754. +   snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
  4755. +   snd_soc_dapm_disable_pin(dapm, "Int Spk");
  4756. +   snd_soc_dapm_disable_pin(dapm, "Mic Jack");
  4757. +   snd_soc_dapm_disable_pin(dapm, "Int Mic");
  4758. +   snd_soc_dapm_disable_pin(dapm, "AUX");
  4759.     snd_soc_dapm_sync(dapm);
  4760.  
  4761.     return 0;
  4762. @@ -571,16 +534,49 @@ static struct snd_soc_dai_link tegra_rt5640_dai[] = {
  4763.         .stream_name = "BT SCO PCM",
  4764.         .codec_name = "spdif-dit.1",
  4765.         .platform_name = "tegra-pcm-audio",
  4766. -       .cpu_dai_name = "tegra30-i2s.4",
  4767. +       .cpu_dai_name = "tegra30-i2s.3",
  4768.         .codec_dai_name = "dit-hifi",
  4769.         .ops = &tegra_rt5640_bt_sco_ops,
  4770.     },
  4771.  };
  4772.  
  4773. +static int tegra_rt5640_set_bias_level(struct snd_soc_card *card,
  4774. +   struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  4775. +{
  4776. +   struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
  4777. +
  4778. +   if (machine->bias_level == SND_SOC_BIAS_OFF &&
  4779. +       level != SND_SOC_BIAS_OFF && (!machine->clock_enabled)) {
  4780. +       machine->clock_enabled = 1;
  4781. +       tegra_asoc_utils_clk_enable(&machine->util_data);
  4782. +       machine->bias_level = level;
  4783. +   }
  4784. +
  4785. +   return 0;
  4786. +}
  4787. +
  4788. +static int tegra_rt5640_set_bias_level_post(struct snd_soc_card *card,
  4789. +   struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  4790. +{
  4791. +   struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
  4792. +
  4793. +   if (machine->bias_level != SND_SOC_BIAS_OFF &&
  4794. +       level == SND_SOC_BIAS_OFF && machine->clock_enabled) {
  4795. +       machine->clock_enabled = 0;
  4796. +       tegra_asoc_utils_clk_disable(&machine->util_data);
  4797. +   }
  4798. +
  4799. +   machine->bias_level = level;
  4800. +
  4801. +   return 0 ;
  4802. +}
  4803. +
  4804.  static struct snd_soc_card snd_soc_tegra_rt5640 = {
  4805.     .name = "tegra-rt5640",
  4806.     .dai_link = tegra_rt5640_dai,
  4807.     .num_links = ARRAY_SIZE(tegra_rt5640_dai),
  4808. +   .set_bias_level = tegra_rt5640_set_bias_level,
  4809. +   .set_bias_level_post = tegra_rt5640_set_bias_level_post,
  4810.  };
  4811.  
  4812.  static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
  4813. @@ -613,37 +609,19 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
  4814.     if (ret)
  4815.         goto err_free_machine;
  4816.  
  4817. -   machine->cdc_en = regulator_get(NULL, "cdc_en");
  4818. -   if (WARN_ON(IS_ERR(machine->cdc_en))) {
  4819. -       dev_err(&pdev->dev, "Couldn't get regulator cdc_en: %ld\n",
  4820. -                       PTR_ERR(machine->cdc_en));
  4821. -       machine->cdc_en = 0;
  4822. -   } else {
  4823. -       regulator_enable(machine->cdc_en);
  4824. -   }
  4825.  
  4826. -   machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
  4827. -   if (IS_ERR(machine->spk_reg)) {
  4828. -       dev_info(&pdev->dev, "No speaker regulator found\n");
  4829. -       machine->spk_reg = 0;
  4830. -   }
  4831.  
  4832. -#ifdef CONFIG_SWITCH
  4833.     /* Addd h2w swith class support */
  4834. -   ret = switch_dev_register(&tegra_rt5640_headset_switch);
  4835. -   if (ret < 0)
  4836. -       goto err_fini_utils;
  4837. -#endif
  4838.  
  4839.     card->dev = &pdev->dev;
  4840.     platform_set_drvdata(pdev, card);
  4841.     snd_soc_card_set_drvdata(card, machine);
  4842. -
  4843. +   card->dapm.idle_bias_off = 1;
  4844.     ret = snd_soc_register_card(card);
  4845.     if (ret) {
  4846.         dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
  4847.             ret);
  4848. -       goto err_unregister_switch;
  4849. +       goto err_fini_utils;
  4850.     }
  4851.  
  4852.     if (!card->instantiated) {
  4853. @@ -657,11 +635,7 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
  4854.  
  4855.  err_unregister_card:
  4856.     snd_soc_unregister_card(card);
  4857. -err_unregister_switch:
  4858. -#ifdef CONFIG_SWITCH
  4859. -   switch_dev_unregister(&tegra_rt5640_headset_switch);
  4860.  err_fini_utils:
  4861. -#endif
  4862.     tegra_asoc_utils_fini(&machine->util_data);
  4863.  err_free_machine:
  4864.     kfree(machine);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement