aml_m3_codec.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. #include <linux/module.h>
  2. #include <linux/moduleparam.h>
  3. #include <linux/init.h>
  4. #include <linux/delay.h>
  5. #include <linux/pm.h>
  6. #include <linux/i2c.h>
  7. #include <linux/slab.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/regulator/consumer.h>
  10. #include <linux/spi/spi.h>
  11. #include <sound/core.h>
  12. #include <sound/pcm.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. #include <sound/soc-dapm.h>
  16. #include <sound/initval.h>
  17. #include <sound/tlv.h>
  18. #include <mach/am_regs.h>
  19. #include "aml_audio_hw.h"
  20. static struct snd_soc_codec *aml_m3_codec;
  21. static int (*is_hp_pluged)(void) = NULL;
  22. static void (*mute_spk)(struct snd_soc_codec* codec, int flag) = NULL;
  23. /* codec private data */
  24. struct aml_m3_codec_priv {
  25. struct snd_soc_codec codec;
  26. u16 reg_cache[ADAC_MAXREG];
  27. unsigned int sysclk;
  28. };
  29. u16 aml_m3_reg[ADAC_MAXREG] = {0};
  30. unsigned long aml_rate_table[] = {
  31. 8000, 11025, 12000, 16000, 22050, 24000, 32000,
  32. 44100, 48000, 88200, 96000, 192000
  33. };
  34. void latch_ (struct snd_soc_codec* codec)
  35. {
  36. int latch;
  37. latch = 1;
  38. snd_soc_write(codec, ADAC_LATCH, latch);
  39. latch = 0;
  40. snd_soc_write(codec, ADAC_LATCH, latch);
  41. }
  42. typedef enum {
  43. AML_PWR_DOWN,
  44. AML_PWR_UP,
  45. AML_PWR_KEEP,
  46. } AML_PATH_SET_TYPE;
  47. void aml_reset_path(struct snd_soc_codec* codec, AML_PATH_SET_TYPE type)
  48. {
  49. unsigned int pwr_reg2 = snd_soc_read(codec, ADAC_POWER_CTRL_REG2);
  50. latch_(codec);
  51. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, pwr_reg2&(~(1<<7)));
  52. latch_(codec);
  53. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, pwr_reg2|(1<<7));
  54. latch_(codec);
  55. if (AML_PWR_DOWN == type)
  56. {
  57. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, pwr_reg2&(~(1<<7)));
  58. latch_(codec);
  59. }
  60. if (AML_PWR_KEEP == type)
  61. {
  62. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, pwr_reg2);
  63. latch_(codec);
  64. }
  65. }
  66. void aml_m3_reset(struct snd_soc_codec* codec, bool first_time)
  67. {
  68. unsigned long data32;
  69. if (first_time)
  70. {
  71. //audio_set_clk(AUDIO_CLK_FREQ_48,0);
  72. audio_set_clk(AUDIO_CLK_FREQ_192,0);
  73. set_acodec_source(AIU_I2SOUT_TO_DAC); // 0=no clock to CODEC; 1=pcmout to DAC; 2=Aiu I2S out to DAC.
  74. // --------------------------------------------------------
  75. // Configure audio DAC control interface
  76. // --------------------------------------------------------
  77. data32 = 0;
  78. data32 |= 0 << 15; // [15] audac_soft_reset_n
  79. data32 |= 0 << 14; // [14] audac_reset_ctrl: 0=use audac_reset_n pulse from reset module; 1=use audac_soft_reset_n.
  80. data32 |= 0 << 9; // [9] delay_rd_en
  81. data32 |= 0 << 8; // [8] audac_reg_clk_inv
  82. data32 |= 0x55 << 1; // [7:1] audac_i2caddr
  83. data32 |= 0 << 0; // [0] audac_intfsel: 0=use host bus; 1=use I2C.
  84. WRITE_MPEG_REG(AIU_AUDAC_CTRL0, data32);
  85. WRITE_MPEG_REG( HHI_AUD_PLL_CNTL, READ_MPEG_REG(HHI_AUD_PLL_CNTL) & ~(1 << 15));
  86. WRITE_MPEG_REG_BITS(HHI_AUD_CLK_CNTL, 1, 23, 1);
  87. WRITE_MPEG_REG(AUDIN_SOURCE_SEL, (1<<0)); // select audio codec output as I2S source
  88. msleep(100);
  89. // Enable APB3 fail on error
  90. data32 = 0;
  91. data32 |= 1 << 15; // [15] err_en
  92. data32 |= 255 << 0; // [11:0] max_err
  93. WRITE_MPEG_REG(AIU_AUDAC_CTRL1, data32);
  94. // Check read back data
  95. data32 = READ_MPEG_REG(AIU_AUDAC_CTRL0);
  96. if (data32 != (0x55 << 1)) {
  97. printk("audiocodec init error: AIU_AUDAC_CTRL0 = %lx\n", data32);
  98. }
  99. data32 = READ_MPEG_REG(AIU_AUDAC_CTRL1);
  100. if (data32 != 0x80ff) {
  101. printk("audiocodec init error: AIU_AUDAC_CTRL1 = %lx\n", data32);
  102. }
  103. wr_regbank (0, // rstdpz: active low.
  104. 0, // mclksel[3:0]: master clock freq sel. 0=256Fs, 1=384Fs, ...
  105. 8, // i2sfsadc[3:0]: sample freq sel. 0=8kHz, 1=11.025k, 2=12k, 3=16k, 4=22.05k, 5=24k, 6=32k, 7=44.1k, 8=48k, 9=88.2k, 10=96k, 11=192k, >11=Rsrv.
  106. 8, // i2sfsdac[3:0]: sample freq sel. 0=8kHz, 1=11.025k, 2=12k, 3=16k, 4=22.05k, 5=24k, 6=32k, 7=44.1k, 8=48k, 9=88.2k, 10=96k, 11=192k, >11=Rsrv.
  107. 1, // i2ssplit: 0=single mode, 1=dual mode.
  108. 1, // i2smode[2:0]: Data format sel. 0=Right justify, 1=I2S, 2=Left justify, 3=Burst1, 4=Burst2, 5=Mono burst1, 6=Mono burst2, 7=Rsrv.
  109. 1, // pdauxdrvrz: 0=power down active, 1=normal.
  110. 1, // pdauxdrvlz: 0=power down active, 1=normal.
  111. 1, // pdhsdrvrz: 0=power down active, 1=normal.
  112. 1, // pdhsdrvlz: 0=power down active, 1=normal.
  113. 1, // pdlsdrvz: 0=power down active, 1=normal.
  114. 1, // pddacrz: 0=power down active, 1=normal.
  115. 1, // pddaclz: 0=power down active, 1=normal.
  116. 0, // pdz: 0=power down active, 1=normal.
  117. 1, // pdmbiasz: 0=power down active, 1=normal.
  118. 1, // pdvcmbufz: 0=power down active, 1=normal.
  119. 1, // pdrpgaz: 0=power down active, 1=normal.
  120. 1, // pdlpgaz: 0=power down active, 1=normal.
  121. 1, // pdadcrz: 0=power down active, 1=normal.
  122. 1, // pdadclz: 0=power down active, 1=normal.
  123. 0, // hsmute[1:0]: bit[1] Analog playback right channel mute, bit[0] Analog playback left channel mute.
  124. 0, // recmute[1:0]: bit[1] Digital record right channel mute, bit[0] Digital record left channel mute.
  125. 0, // micmute[1:0]: bit[1] Input PGA right channel mute, bit[0] Input PGA left channel mute.
  126. 0, // lmmute[1:0]: bit[1] Digital playback right channel mute, bit[0] Digital playback left channel mute.
  127. 0, // lsmute: loud speaker mute.
  128. 0, // lmmix: Playback digital mixer sel.
  129. 0, // recmix: Record digital mixer sel.
  130. 0, // ctr[1:0]: test mode sel. 0=Normal, 1=Digital filter loopback, 2=Digital filter bypass, 3=Digital audio I/F loopback.
  131. 1, // enhp: Record channel high pass filter enable.
  132. 0x5454, // lmvol[15:0]: Digital playback volumn control, [15:8] control right channel, [7:0] control left channel.
  133. // 0=-126dB, 1=-124.5dB, ..., 0x53=-1.5dB, 0x54=0dB, >=0x55 Rsrv.
  134. 0x2828, // hsvol[15:0]: Analog playback headset volumn control, [15:8] control right channel, [7:0] control left channel.
  135. // 0=-40dB, 1=-39dB, ..., 0x28=0dB, ..., 0x2e=6dB, >=0x2f Rsrv.
  136. 0, // pbmix[15:0]: Playback channel mixing sel. [15:8] control right channel, [7:0] control left channel.
  137. // 0=Left(Right) digital source only, 1=Analog source only, 2=Analog + left(right) digital,
  138. // 3=Right(Left) digital sourcd only, 4=Left(Right) digital + right(left) digital, 5=Analog + right(left) digital,
  139. // 6=Analog + left(right) digital + right(left) digital, >=7 Rsrv.
  140. 0x0001, // lsmix[15:0]
  141. 0x1212, // micvol[15:0]: Input PGA volume control. [15:8] control right channel, [7:0] control left channel.
  142. // 0=-6dB, 1=-4.5dB, ..., 4=0dB, ..., 0x11=19.5dB, 0x12=21dB, >=0x13 Rsrv.
  143. 0x1111, // recvol[15:0]: Digital record channel master volume control. [15:8] control right channel, [7:0] control left channel.
  144. // 0=30dB, 1=28.5dB, ..., 0x13=1.5dB, 0x14=0dB, 0x15=-1.5dB, ..., 0x54=-96dB, >=0x55 Rsrv.
  145. 0x0101); // recsel[15:0]: Input PGA selection. [15:8] control right channel, [7:0] control left channel.
  146. // 0x01=input1, 0x03=input2, 0x05=input3, 0x09=input4,
  147. // 0x11=input5, 0x21=input6, 0x41=input7, 0x81=input8, others=Rsrv.
  148. adac_power_up_mode_2();
  149. adac_startup_seq();
  150. udelay(10);
  151. if(is_hp_pluged && is_hp_pluged()) {
  152. data32 = snd_soc_read(codec, ADAC_MUTE_CTRL_REG1);
  153. data32 &= ~0xc0;
  154. snd_soc_write(codec, ADAC_MUTE_CTRL_REG1, data32); //unmute HP
  155. if(mute_spk)
  156. mute_spk(codec, 1);
  157. latch_(codec);
  158. }
  159. else {
  160. data32 = snd_soc_read(codec, ADAC_MUTE_CTRL_REG1);
  161. data32 |= 0xc0;
  162. snd_soc_write(codec, ADAC_MUTE_CTRL_REG1, data32);//mute HP
  163. if(mute_spk)
  164. mute_spk(codec, 0);
  165. latch_(codec);
  166. }
  167. /* snd_soc_write(codec, ADAC_RESET, (0<<1));
  168. snd_soc_write(codec, ADAC_RESET, (0<<1));
  169. snd_soc_write(codec, ADAC_RESET, (0<<1));
  170. snd_soc_write(codec, ADAC_RESET, (0<<1));
  171. snd_soc_write(codec, ADAC_RESET, (0<<1));
  172. msleep(100);
  173. snd_soc_write(codec,ADAC_CLOCK, 0); // 256fs
  174. snd_soc_write(codec, ADAC_I2S_CONFIG_REG1, (7<<4)|7); // samplerate for ADC&DAC
  175. snd_soc_write(codec, ADAC_I2S_CONFIG_REG2, 1|(1<<3)); // I2S | split
  176. snd_soc_write(codec, ADAC_MUTE_CTRL_REG1,0);
  177. snd_soc_write(codec, ADAC_MUTE_CTRL_REG2, 0);
  178. snd_soc_write(codec,ADAC_DAC_ADC_MIXER, 0);
  179. snd_soc_write(codec,ADAC_PLAYBACK_VOL_CTRL_LSB, 0x54);
  180. snd_soc_write(codec,ADAC_PLAYBACK_VOL_CTRL_MSB, 0x54);
  181. snd_soc_write(codec,ADAC_STEREO_HS_VOL_CTRL_LSB, 0x28);
  182. snd_soc_write(codec,ADAC_STEREO_HS_VOL_CTRL_MSB, 0x28);
  183. snd_soc_write(codec, ADAC_PLAYBACK_MIX_CTRL_LSB, 0);
  184. snd_soc_write(codec, ADAC_PLAYBACK_MIX_CTRL_MSB, 0);
  185. snd_soc_write(codec, ADAC_STEREO_PGA_VOL_LSB, 4);
  186. snd_soc_write(codec, ADAC_STEREO_PGA_VOL_MSB, 4);
  187. snd_soc_write(codec, ADAC_RECVOL_CTRL_LSB, 0x14);
  188. snd_soc_write(codec, ADAC_RECVOL_CTRL_MSB, 0x14);
  189. snd_soc_write(codec, ADAC_REC_CH_SEL_LSB, 1|(1<<(1-1)));// 1|(1<<(channel-1))
  190. snd_soc_write(codec, ADAC_REC_CH_SEL_MSB, 1|(1<<(1-1)));// 1|(1<<(channel-1))
  191. snd_soc_write(codec, ADAC_POWER_CTRL_REG1, 0xf7);
  192. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0x2f);
  193. snd_soc_write(codec, ADAC_LS_MIX_CTRL_LSB, 1);
  194. snd_soc_write(codec, ADAC_LS_MIX_CTRL_MSB, 0);
  195. aml_reset_path(codec, AML_PWR_UP);
  196. aml_reset_path(codec, AML_PWR_DOWN);
  197. */
  198. }
  199. else
  200. {
  201. snd_soc_write(codec, ADAC_LS_MIX_CTRL_LSB, 1);
  202. snd_soc_write(codec, ADAC_LS_MIX_CTRL_MSB, 0);
  203. aml_reset_path(codec, AML_PWR_UP);
  204. latch_(codec);
  205. snd_soc_write(codec, ADAC_RESET, (0<<1));
  206. latch_(codec);
  207. latch_(codec);
  208. latch_(codec);
  209. snd_soc_write(codec, ADAC_RESET, (1<<1));
  210. latch_(codec);
  211. latch_(codec);
  212. }
  213. msleep(200);
  214. }
  215. int audio_dac_set(unsigned freq)
  216. {
  217. return 0;
  218. }
  219. static int post_reset(struct snd_soc_dapm_widget *w,
  220. struct snd_kcontrol *kcontrol, int event)
  221. {
  222. struct snd_soc_codec *codec = w->codec;
  223. if (SND_SOC_DAPM_POST_PMU == event)
  224. {
  225. aml_m3_reset(codec,false);
  226. }
  227. else if (SND_SOC_DAPM_POST_PMD == event && codec->active == 0)
  228. aml_reset_path(codec, AML_PWR_DOWN);
  229. return 0;
  230. }
  231. static int aml_switch_get_enum(struct snd_kcontrol *kcontrol,
  232. struct snd_ctl_elem_value *ucontrol)
  233. {
  234. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  235. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  236. struct snd_soc_dapm_widget *w;
  237. //struct snd_soc_dapm_context * dapm = &codec->dapm;
  238. char *lname = NULL;
  239. char *rname = NULL;
  240. switch (e->reg)
  241. {
  242. case ADAC_POWER_CTRL_REG1:
  243. if (6 == e->shift_l)
  244. {
  245. lname = "LINEOUTL";
  246. rname = "LINEOUTR";
  247. }
  248. else if (4 == e->shift_l)
  249. {
  250. lname = "HP_L";
  251. rname = "HP_R";
  252. }
  253. else if (2 == e->shift_l)
  254. {
  255. lname = "SPEAKER";
  256. }
  257. break;
  258. case ADAC_POWER_CTRL_REG2:
  259. if (2 == e->shift_l)
  260. {
  261. lname = "LINEINL";
  262. rname = "LINEINR";
  263. }
  264. break;
  265. default:
  266. break;
  267. }
  268. list_for_each_entry(w, &codec->card->widgets, list) {
  269. if (lname && !strcmp(lname, w->name))
  270. ucontrol->value.enumerated.item[0] = w->connected;
  271. if (rname && !strcmp(rname, w->name))
  272. ucontrol->value.enumerated.item[0] = w->connected;
  273. }
  274. return 0;
  275. }
  276. static int aml_switch_put_enum(struct snd_kcontrol *kcontrol,
  277. struct snd_ctl_elem_value *ucontrol)
  278. {
  279. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  280. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  281. struct snd_soc_dapm_widget *w;
  282. char *lname = NULL;
  283. char *rname = NULL;
  284. unsigned int pwr_reg;
  285. switch (e->reg)
  286. {
  287. case ADAC_POWER_CTRL_REG1:
  288. if (6 == e->shift_l)
  289. {
  290. lname = "LINEOUTL";
  291. rname = "LINEOUTR";
  292. }
  293. else if (4 == e->shift_l)
  294. {
  295. lname = "HP_L";
  296. rname = "HP_R";
  297. }
  298. else if (2 == e->shift_l)
  299. {
  300. lname = "SPEAKER";
  301. }
  302. break;
  303. case ADAC_POWER_CTRL_REG2:
  304. if (2 == e->shift_l)
  305. {
  306. lname = "LINEINL";
  307. rname = "LINEINR";
  308. }
  309. break;
  310. default:
  311. break;
  312. }
  313. pwr_reg = snd_soc_read(codec, e->reg);
  314. if(ucontrol->value.enumerated.item[0] == 0){
  315. snd_soc_write(codec, e->reg, (pwr_reg&(~(0x1<<(e->shift_l)|0x1<<(e->shift_r)))));
  316. }
  317. else{
  318. snd_soc_write(codec, e->reg, (pwr_reg|(0x1<<(e->shift_l)|0x1<<(e->shift_r))));
  319. }
  320. list_for_each_entry(w, &codec->card->widgets, list) {
  321. if (lname && !strcmp(lname, w->name))
  322. {
  323. w->connected = ucontrol->value.enumerated.item[0];
  324. printk("%s:connect=%d\n",w->name,w->connected);
  325. }
  326. if (rname && !strcmp(rname, w->name))
  327. {
  328. w->connected = ucontrol->value.enumerated.item[0];
  329. printk("%s:connect=%d\n",w->name,w->connected);
  330. }
  331. }
  332. return 0;
  333. }
  334. static int aml_put_volsw_2r(struct snd_kcontrol *kcontrol,
  335. struct snd_ctl_elem_value *ucontrol)
  336. {
  337. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  338. int err = snd_soc_put_volsw_2r(kcontrol, ucontrol);
  339. if (err < 0)
  340. return err;
  341. aml_reset_path(codec, AML_PWR_KEEP);
  342. return 0;
  343. }
  344. static int aml_ai_source_get_enum(struct snd_kcontrol *kcontrol,
  345. struct snd_ctl_elem_value *ucontrol)
  346. {
  347. //struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  348. //struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  349. if (READ_MPEG_REG(AUDIN_SOURCE_SEL) == 0)
  350. WRITE_MPEG_REG(AUDIN_SOURCE_SEL, (1<<0)); // select audio codec output as I2S source
  351. if (READ_MPEG_REG(AUDIN_SOURCE_SEL) == 1)
  352. ucontrol->value.enumerated.item[0] = 0;// linein
  353. else
  354. ucontrol->value.enumerated.item[0] = 1;//hdmi
  355. return 0;
  356. }
  357. static int aml_ai_source_put_enum(struct snd_kcontrol *kcontrol,
  358. struct snd_ctl_elem_value *ucontrol)
  359. {
  360. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  361. //struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  362. if (ucontrol->value.enumerated.item[0] == 0)
  363. WRITE_MPEG_REG(AUDIN_SOURCE_SEL, (1<<0)); // select audio codec output as I2S source
  364. else
  365. WRITE_MPEG_REG(AUDIN_SOURCE_SEL, (1<<4) | (2 << 0)); // Select HDMI RX output as AUDIN source
  366. snd_soc_write(codec, ADAC_RESET, (0<<1));
  367. latch_(codec);
  368. snd_soc_write(codec, ADAC_RESET, (1<<1));
  369. latch_(codec);
  370. return 0;
  371. }
  372. void aml_linein_start(void)
  373. {
  374. // power up adc
  375. unsigned int pwr_reg2 = snd_soc_read(aml_m3_codec, ADAC_POWER_CTRL_REG2);
  376. snd_soc_write(aml_m3_codec, ADAC_POWER_CTRL_REG2, pwr_reg2|0xF);
  377. latch_(aml_m3_codec);
  378. // power up codec
  379. aml_reset_path(aml_m3_codec, AML_PWR_UP);
  380. snd_soc_write(aml_m3_codec, ADAC_RESET, (0<<1));
  381. latch_(aml_m3_codec);
  382. snd_soc_write(aml_m3_codec, ADAC_RESET, (1<<1));
  383. latch_(aml_m3_codec);
  384. }
  385. void aml_linein_stop(void)
  386. {
  387. // power down adc
  388. unsigned int pwr_reg2 = snd_soc_read(aml_m3_codec, ADAC_POWER_CTRL_REG2);
  389. snd_soc_write(aml_m3_codec, ADAC_POWER_CTRL_REG2, pwr_reg2&(~0xF));
  390. latch_(aml_m3_codec);
  391. // power down codec
  392. if (aml_m3_codec->active == 0)
  393. aml_reset_path(aml_m3_codec, AML_PWR_DOWN);
  394. }
  395. static const DECLARE_TLV_DB_SCALE(lineout_volume, -12600, 150, 0);
  396. static const DECLARE_TLV_DB_SCALE(hs_volume, -4000, 100, 0);
  397. static const DECLARE_TLV_DB_SCALE(linein_volume, -9600, 150, 0);
  398. static const char *left_linein_texts[] = {
  399. "Left Line In 1", "Left Line In 2", "Left Line In 3", "Left Line In 4",
  400. "Left Line In 5", "Left Line In 6", "Left Line In 7", "Left Line In 8"
  401. };
  402. static const char *right_linein_texts[] = {
  403. "Right Line In 1", "Right Line In 2", "Right Line In 3", "Right Line In 4",
  404. "Right Line In 5", "Right Line In 6", "Right Line In 7", "Right Line In 8"
  405. };
  406. static const unsigned int linein_values[] = {
  407. 1|(1<<(1-1)),
  408. 1|(1<<(2-1)),
  409. 1|(1<<(3-1)),
  410. 1|(1<<(4-1)),
  411. 1|(1<<(5-1)),
  412. 1|(1<<(6-1)),
  413. 1|(1<<(7-1)),
  414. 1|(1<<(8-1))
  415. };
  416. static const char *iis_split_texts[] = {
  417. "iis_not_split", "iis_split"
  418. };
  419. static const unsigned int iis_split_values[] = {
  420. 0,
  421. 1
  422. };
  423. static const SOC_VALUE_ENUM_SINGLE_DECL(left_linein_select, ADAC_REC_CH_SEL_LSB,
  424. 0, 0xff, left_linein_texts, linein_values);
  425. static const SOC_VALUE_ENUM_SINGLE_DECL(right_linein_select, ADAC_REC_CH_SEL_MSB,
  426. 0, 0xff, right_linein_texts, linein_values);
  427. static const SOC_VALUE_ENUM_SINGLE_DECL(iis_split_select, ADAC_I2S_CONFIG_REG2,
  428. 3, 0xff, iis_split_texts, iis_split_values);
  429. static const char *switch_op_modes_texts[] = {
  430. "OFF", "ON"
  431. };
  432. static const struct soc_enum lineout_op_modes_enum =
  433. SOC_ENUM_DOUBLE(ADAC_POWER_CTRL_REG1, 6, 7,
  434. ARRAY_SIZE(switch_op_modes_texts),
  435. switch_op_modes_texts);
  436. static const struct soc_enum hp_op_modes_enum =
  437. SOC_ENUM_DOUBLE(ADAC_POWER_CTRL_REG1, 4, 5,
  438. ARRAY_SIZE(switch_op_modes_texts),
  439. switch_op_modes_texts);
  440. static const struct soc_enum linein_op_modes_enum =
  441. SOC_ENUM_DOUBLE(ADAC_POWER_CTRL_REG2, 2, 2,
  442. ARRAY_SIZE(switch_op_modes_texts),
  443. switch_op_modes_texts);
  444. static const struct soc_enum sp_op_modes_enum =
  445. SOC_ENUM_DOUBLE(ADAC_POWER_CTRL_REG1, 2, 3,
  446. ARRAY_SIZE(switch_op_modes_texts),
  447. switch_op_modes_texts);
  448. static const char *audio_in_source_texts[] = {
  449. "LINEIN", "HDMI"
  450. };
  451. static const struct soc_enum audio_in_source_enum =
  452. SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
  453. ARRAY_SIZE(audio_in_source_texts),
  454. audio_in_source_texts);
  455. static const struct snd_kcontrol_new amlm3_snd_controls[] = {
  456. SOC_DOUBLE_R_EXT_TLV("LINEOUT Playback Volume", ADAC_PLAYBACK_VOL_CTRL_LSB, ADAC_PLAYBACK_VOL_CTRL_MSB,
  457. 0, 84, 0, snd_soc_get_volsw_2r, aml_put_volsw_2r, lineout_volume),
  458. SOC_DOUBLE_R_EXT_TLV("HeadSet Playback Volume", ADAC_STEREO_HS_VOL_CTRL_LSB, ADAC_STEREO_HS_VOL_CTRL_MSB,
  459. 0, 46, 0, snd_soc_get_volsw_2r, aml_put_volsw_2r, hs_volume),
  460. SOC_DOUBLE_R_EXT_TLV("LINEIN Capture Volume", ADAC_RECVOL_CTRL_LSB, ADAC_RECVOL_CTRL_MSB,
  461. 0, 84, 1, snd_soc_get_volsw_2r, aml_put_volsw_2r, linein_volume),
  462. SOC_VALUE_ENUM("Left LINEIN Select",left_linein_select),
  463. SOC_VALUE_ENUM("Right LINEIN Select",right_linein_select),
  464. SOC_VALUE_ENUM("IIS Split Select", iis_split_select),
  465. SOC_ENUM_EXT("LOUT Playback Switch", lineout_op_modes_enum,
  466. aml_switch_get_enum,aml_switch_put_enum),
  467. SOC_ENUM_EXT("HP Playback Switch", hp_op_modes_enum,
  468. aml_switch_get_enum,aml_switch_put_enum),
  469. SOC_ENUM_EXT("LIN Capture Switch", linein_op_modes_enum,
  470. aml_switch_get_enum,aml_switch_put_enum),
  471. SOC_ENUM_EXT("SP Playback Switch", sp_op_modes_enum,
  472. aml_switch_get_enum,aml_switch_put_enum),
  473. SOC_ENUM_EXT("Audio In Source", audio_in_source_enum,
  474. aml_ai_source_get_enum,aml_ai_source_put_enum),
  475. };
  476. static const struct snd_kcontrol_new lineoutl_switch_controls =
  477. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG1, 0, 1, 1);
  478. static const struct snd_kcontrol_new lineoutr_switch_controls =
  479. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG1, 1, 1, 1);
  480. static const struct snd_kcontrol_new hsl_switch_controls =
  481. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG1, 6, 1, 1);
  482. static const struct snd_kcontrol_new hsr_switch_controls =
  483. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG1, 7, 1, 1);
  484. static const struct snd_kcontrol_new spk_switch_controls =
  485. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG2, 2, 1, 1);
  486. static const struct snd_kcontrol_new lineinl_switch_controls =
  487. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG2, 4, 1, 1);
  488. static const struct snd_kcontrol_new lineinr_switch_controls =
  489. SOC_DAPM_SINGLE("Switch", ADAC_MUTE_CTRL_REG2, 5, 1, 1);
  490. static const struct snd_soc_dapm_widget aml_m3_dapm_widgets[] = {
  491. SND_SOC_DAPM_OUTPUT("LINEOUTL"),
  492. SND_SOC_DAPM_OUTPUT("LINEOUTR"),
  493. SND_SOC_DAPM_OUTPUT("HP_L"),
  494. SND_SOC_DAPM_OUTPUT("HP_R"),
  495. SND_SOC_DAPM_OUTPUT("SPEAKER"),
  496. SND_SOC_DAPM_INPUT("LINEINL"),
  497. SND_SOC_DAPM_INPUT("LINEINR"),
  498. SND_SOC_DAPM_DAC("DACL", "Left DAC Playback", ADAC_POWER_CTRL_REG1, 0, 0),
  499. SND_SOC_DAPM_DAC("DACR", "Right DAC Playback", ADAC_POWER_CTRL_REG1, 1, 0),
  500. SND_SOC_DAPM_ADC("ADCL", "Left ADC Capture", ADAC_POWER_CTRL_REG2, 0, 0),
  501. SND_SOC_DAPM_ADC("ADCR", "Right ADC Capture", ADAC_POWER_CTRL_REG2, 1, 0),
  502. SND_SOC_DAPM_SWITCH("LINEOUTL Switch", ADAC_POWER_CTRL_REG1, 6, 0,
  503. &lineoutl_switch_controls),
  504. SND_SOC_DAPM_SWITCH("LINEOUTR Switch", ADAC_POWER_CTRL_REG1, 7, 0,
  505. &lineoutr_switch_controls),
  506. SND_SOC_DAPM_SWITCH("HP_L Switch", ADAC_POWER_CTRL_REG1, 4, 0,
  507. &hsl_switch_controls),
  508. SND_SOC_DAPM_SWITCH("HP_R Switch", ADAC_POWER_CTRL_REG1, 5, 0,
  509. &hsr_switch_controls),
  510. SND_SOC_DAPM_SWITCH("SPEAKER Switch", ADAC_POWER_CTRL_REG1, 2, 0,
  511. &spk_switch_controls),
  512. SND_SOC_DAPM_SWITCH("LINEINL Switch", ADAC_POWER_CTRL_REG2, 2, 0,
  513. &lineinl_switch_controls),
  514. SND_SOC_DAPM_SWITCH("LINEINR Switch", ADAC_POWER_CTRL_REG2, 3, 0,
  515. &lineinr_switch_controls),
  516. SND_SOC_DAPM_POST("RESET", post_reset),
  517. //SND_SOC_DAPM_PGA("HSL", ADAC_POWER_CTRL_REG1, 4, 0, NULL, 0),
  518. //SND_SOC_DAPM_PGA("HSR", ADAC_POWER_CTRL_REG1, 5, 0, NULL, 0),
  519. //SND_SOC_DAPM_PGA("PDZ", ADAC_POWER_CTRL_REG2, 7, 0, NULL, 0),
  520. SND_SOC_DAPM_MICBIAS("MICBIAS", ADAC_POWER_CTRL_REG2, 5, 0)
  521. };
  522. /* Target, Path, Source */
  523. static const struct snd_soc_dapm_route aml_m3_audio_map[] = {
  524. {"LINEOUTL", NULL, "LINEOUTL Switch"},
  525. {"LINEOUTL Switch", NULL, "DACL"},
  526. {"LINEOUTR", NULL, "LINEOUTR Switch"},
  527. {"LINEOUTR Switch", NULL, "DACR"},
  528. {"HP_L", NULL, "HP_L Switch"},
  529. {"HP_L Switch", NULL, "DACL"},
  530. {"HP_R", NULL, "HP_R Switch"},
  531. {"HP_R Switch", NULL, "DACR"},
  532. {"SPEAKER", NULL, "SPEAKER Switch"},
  533. {"SPEAKER Switch", NULL, "DACL"},
  534. {"SPEAKER Switch", NULL, "DACR"},
  535. {"ADCL", NULL, "LINEINL Switch"},
  536. {"LINEINL Switch", NULL, "LINEINL"},
  537. {"ADCR", NULL, "LINEINR Switch"},
  538. {"LINEINR Switch", NULL, "LINEINR"},
  539. };
  540. static int aml_m3_write(struct snd_soc_codec *codec, unsigned int reg,
  541. unsigned int value)
  542. {
  543. u16 *reg_cache = codec->reg_cache;
  544. //printk("***Entered %s:%s:\nWriting reg is %#x; value=%#x\n",__FILE__,__func__, reg, value);
  545. if (reg >= codec->reg_size/sizeof(u16))
  546. return -EINVAL;
  547. WRITE_APB_REG((APB_BASE+(reg<<2)), value);
  548. reg_cache[reg] = value;
  549. //printk("Read back reg is %#x value=%#x\n", reg, READ_APB_REG(APB_BASE+(reg<<2)));
  550. return 0;
  551. }
  552. static unsigned int aml_m3_read(struct snd_soc_codec *codec,
  553. unsigned int reg)
  554. {
  555. //u16 *reg_cache = codec->reg_cache;
  556. if (reg >= codec->reg_size/sizeof(u16))
  557. return -EINVAL;
  558. return READ_APB_REG(APB_BASE+(reg<<2));
  559. //return reg_cache[reg];
  560. }
  561. static int aml_m3_codec_hw_params(struct snd_pcm_substream *substream,
  562. struct snd_pcm_hw_params *params,
  563. struct snd_soc_dai *dai)
  564. {
  565. struct snd_soc_codec *codec = dai->codec;
  566. unsigned int i2sfs;
  567. unsigned long rate = params_rate(params);
  568. int rate_idx = 0;
  569. for (rate_idx = 0; rate_idx < ARRAY_SIZE(aml_rate_table); rate_idx++)
  570. if (aml_rate_table[rate_idx] == rate)
  571. break;
  572. if (ARRAY_SIZE(aml_rate_table) == rate_idx)
  573. rate_idx = 0;
  574. i2sfs = snd_soc_read(codec, ADAC_I2S_CONFIG_REG1);
  575. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  576. snd_soc_write(codec, ADAC_I2S_CONFIG_REG1, (i2sfs&0x0f)|(rate_idx<<4));
  577. else
  578. snd_soc_write(codec, ADAC_I2S_CONFIG_REG1, (i2sfs&0xf0)|rate_idx);
  579. aml_reset_path(codec, AML_PWR_KEEP);
  580. return 0;
  581. }
  582. static int aml_m3_codec_pcm_prepare(struct snd_pcm_substream *substream,
  583. struct snd_soc_dai *dai)
  584. {
  585. //struct snd_soc_codec *codec = dai->codec;
  586. /* set active */
  587. // TODO
  588. return 0;
  589. }
  590. static void aml_m3_codec_shutdown(struct snd_pcm_substream *substream,
  591. struct snd_soc_dai *dai)
  592. {
  593. struct snd_soc_codec *codec = dai->codec;
  594. /* deactivate */
  595. if (!codec->active) {
  596. udelay(50);
  597. // TODO
  598. }
  599. }
  600. static int aml_m3_codec_mute(struct snd_soc_dai *dai, int mute)
  601. {
  602. struct snd_soc_codec *codec = dai->codec;
  603. u16 reg;
  604. // TODO
  605. reg = snd_soc_read(codec, ADAC_MUTE_CTRL_REG1);
  606. if(mute){
  607. reg |= 3;
  608. }
  609. else{
  610. reg &= ~3;
  611. }
  612. printk("aml_m3_codec_mute mute=%d\n",mute);
  613. // snd_soc_write(codec, ADAC_MUTE_CTRL_REG1, reg);
  614. return 0;
  615. }
  616. static int aml_m3_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  617. int clk_id, unsigned int freq, int dir)
  618. {
  619. //struct snd_soc_codec *codec = codec_dai->codec;
  620. unsigned long data = 0;
  621. switch (freq) {
  622. case 32000:
  623. data = 6;
  624. break;
  625. case 44100:
  626. data = 7;
  627. break;
  628. case 48000:
  629. data = 8;
  630. break;
  631. case 96000:
  632. data = 10;
  633. break;
  634. default:
  635. data = 6;
  636. break;
  637. }
  638. //snd_soc_write(codec,ADAC_CLOCK, 0);
  639. //snd_soc_write(codec,ADAC_I2S_CONFIG_REG1, data);
  640. return 0;
  641. }
  642. static int aml_m3_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
  643. unsigned int fmt)
  644. {
  645. //struct snd_soc_codec *codec = codec_dai->codec;
  646. u16 iface = 0;
  647. /* set master/slave audio interface */
  648. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  649. case SND_SOC_DAIFMT_CBM_CFM:
  650. iface |= 0x0040;
  651. break;
  652. case SND_SOC_DAIFMT_CBS_CFS:
  653. break;
  654. default:
  655. return -EINVAL;
  656. }
  657. /* interface format */
  658. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  659. case SND_SOC_DAIFMT_I2S:
  660. iface |= 0x0002;
  661. break;
  662. case SND_SOC_DAIFMT_RIGHT_J:
  663. break;
  664. case SND_SOC_DAIFMT_LEFT_J:
  665. iface |= 0x0001;
  666. break;
  667. case SND_SOC_DAIFMT_DSP_A:
  668. iface |= 0x0003;
  669. break;
  670. case SND_SOC_DAIFMT_DSP_B:
  671. iface |= 0x0013;
  672. break;
  673. default:
  674. return -EINVAL;
  675. }
  676. /* clock inversion */
  677. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  678. case SND_SOC_DAIFMT_NB_NF:
  679. break;
  680. case SND_SOC_DAIFMT_IB_IF:
  681. iface |= 0x0090;
  682. break;
  683. case SND_SOC_DAIFMT_IB_NF:
  684. iface |= 0x0080;
  685. break;
  686. case SND_SOC_DAIFMT_NB_IF:
  687. iface |= 0x0010;
  688. break;
  689. default:
  690. return -EINVAL;
  691. }
  692. /* set iface */
  693. // TODO
  694. return 0;
  695. }
  696. #define AML_RATES SNDRV_PCM_RATE_8000_96000
  697. #define AML_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
  698. SNDRV_PCM_FMTBIT_S24_LE)
  699. static struct snd_soc_dai_ops aml_m3_codec_dai_ops = {
  700. .prepare = aml_m3_codec_pcm_prepare,
  701. .hw_params = aml_m3_codec_hw_params,
  702. .shutdown = aml_m3_codec_shutdown,
  703. .digital_mute = aml_m3_codec_mute,
  704. .set_sysclk = aml_m3_codec_set_dai_sysclk,
  705. .set_fmt = aml_m3_codec_set_dai_fmt,
  706. };
  707. struct snd_soc_dai_driver aml_m3_codec_dai = {
  708. .name = "AML-M3",
  709. .playback = {
  710. .stream_name = "Playback",
  711. .channels_min = 1,
  712. .channels_max = 2,
  713. .rates = AML_RATES,
  714. .formats = AML_FORMATS,},
  715. .capture = {
  716. .stream_name = "Capture",
  717. .channels_min = 1,
  718. .channels_max = 2,
  719. .rates = AML_RATES,
  720. .formats = AML_FORMATS,},
  721. .ops = &aml_m3_codec_dai_ops,
  722. .symmetric_rates = 1,
  723. };
  724. EXPORT_SYMBOL_GPL(aml_m3_codec_dai);
  725. static int aml_m3_set_bias_level(struct snd_soc_codec *codec,
  726. enum snd_soc_bias_level level)
  727. {
  728. switch (level) {
  729. case SND_SOC_BIAS_ON:
  730. break;
  731. case SND_SOC_BIAS_PREPARE:
  732. break;
  733. case SND_SOC_BIAS_STANDBY:
  734. break;
  735. case SND_SOC_BIAS_OFF:
  736. break;
  737. default:
  738. break;
  739. }
  740. codec->dapm.bias_level = level;
  741. return 0;
  742. }
  743. static int aml_m3_soc_probe(struct snd_soc_codec *codec){
  744. struct snd_soc_dapm_context *dapm = &codec->dapm;
  745. aml_m3_reset(codec, true);
  746. aml_m3_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  747. snd_soc_add_controls(codec, amlm3_snd_controls,
  748. ARRAY_SIZE(amlm3_snd_controls));
  749. snd_soc_dapm_new_controls(dapm, aml_m3_dapm_widgets,
  750. ARRAY_SIZE(aml_m3_dapm_widgets));
  751. snd_soc_dapm_add_routes(dapm, aml_m3_audio_map, ARRAY_SIZE(aml_m3_audio_map));
  752. aml_m3_codec = codec;
  753. return 0;
  754. }
  755. static int aml_m3_soc_remove(struct snd_soc_codec *codec){
  756. return 0;
  757. }
  758. static int aml_m3_soc_suspend(struct snd_soc_codec *codec, pm_message_t state){
  759. printk("aml_m3_codec_suspend\n");
  760. WRITE_MPEG_REG( HHI_GCLK_MPEG1, READ_MPEG_REG(HHI_GCLK_MPEG1)&~(1 << 2));
  761. aml_reset_path(codec, AML_PWR_DOWN);
  762. return 0;
  763. }
  764. static int aml_m3_soc_resume(struct snd_soc_codec *codec){
  765. printk("aml_m3_codec resume\n");
  766. WRITE_MPEG_REG( HHI_GCLK_MPEG1, READ_MPEG_REG(HHI_GCLK_MPEG1)|(1 << 2));
  767. aml_m3_reset(codec, true);
  768. return 0;
  769. }
  770. static struct snd_soc_codec_driver soc_codec_dev_m3 = {
  771. .probe = aml_m3_soc_probe,
  772. .remove = aml_m3_soc_remove,
  773. .suspend = aml_m3_soc_suspend,
  774. .resume = aml_m3_soc_resume,
  775. .read = aml_m3_read,
  776. .write = aml_m3_write,
  777. .set_bias_level = aml_m3_set_bias_level,
  778. .reg_cache_size = ARRAY_SIZE(aml_m3_reg),
  779. .reg_word_size = sizeof(u16),
  780. .reg_cache_step = 2,
  781. .reg_cache_default = aml_m3_reg,
  782. .dapm_widgets = aml_m3_dapm_widgets,
  783. .num_dapm_widgets = ARRAY_SIZE(aml_m3_dapm_widgets),
  784. .dapm_routes = aml_m3_audio_map,
  785. .num_dapm_routes = ARRAY_SIZE(aml_m3_audio_map),
  786. };
  787. static int aml_m3_codec_platform_probe(struct platform_device *pdev)
  788. {
  789. return snd_soc_register_codec(&pdev->dev,
  790. &soc_codec_dev_m3, &aml_m3_codec_dai, 1);
  791. }
  792. static int __exit aml_m3_codec_platform_remove(struct platform_device *pdev)
  793. {
  794. snd_soc_unregister_codec(&pdev->dev);
  795. return 0;
  796. }
  797. static struct platform_driver aml_m3_codec_platform_driver = {
  798. .driver = {
  799. .name = "aml_m3_codec",
  800. .owner = THIS_MODULE,
  801. },
  802. .probe = aml_m3_codec_platform_probe,
  803. .remove = __exit_p(aml_m3_codec_platform_remove),
  804. };
  805. static int __init aml_m3_codec_modinit(void)
  806. {
  807. return platform_driver_register(&aml_m3_codec_platform_driver);
  808. }
  809. static void __exit aml_m3_codec_exit(void)
  810. {
  811. platform_driver_unregister(&aml_m3_codec_platform_driver);
  812. }
  813. module_init(aml_m3_codec_modinit);
  814. module_exit(aml_m3_codec_exit);
  815. MODULE_DESCRIPTION("ASoC AML M3 codec driver");
  816. MODULE_AUTHOR("AMLogic Inc.");
  817. MODULE_LICENSE("GPL");