mpq8064.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876
  1. /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/clk.h>
  13. #include <linux/delay.h>
  14. #include <linux/gpio.h>
  15. #include <linux/mfd/pm8xxx/pm8921.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/gpio.h>
  18. #include <linux/mfd/pm8xxx/pm8921.h>
  19. #include <linux/slab.h>
  20. #include <sound/core.h>
  21. #include <sound/soc.h>
  22. #include <sound/soc-dapm.h>
  23. #include <sound/pcm.h>
  24. #include <sound/jack.h>
  25. #include <sound/pcm_params.h>
  26. #include <asm/mach-types.h>
  27. #include <mach/socinfo.h>
  28. #include "msm-pcm-routing.h"
  29. #include "../codecs/wcd9310.h"
  30. /* 8064 machine driver */
  31. #define PM8921_MPP_BASE (PM8921_GPIO_BASE + PM8921_NR_GPIOS)
  32. #define PM8821_NR_MPPS (4)
  33. #define PM8821_MPP_BASE (PM8921_MPP_BASE + PM8921_NR_MPPS)
  34. #define PM8921_GPIO_BASE NR_GPIO_IRQS
  35. #define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
  36. #define GPIO_EXPANDER_IRQ_BASE (TABLA_INTERRUPT_BASE + \
  37. NR_TABLA_IRQS)
  38. #define GPIO_EXPANDER_GPIO_BASE (PM8821_MPP_BASE + PM8821_NR_MPPS)
  39. #define GPIO_EPM_EXPANDER_BASE GPIO_EXPANDER_GPIO_BASE
  40. #define SX150X_EPM_NR_GPIOS 16
  41. #define SX150X_EPM_NR_IRQS 8
  42. #define SX150X_EXP1_GPIO_BASE (GPIO_EPM_EXPANDER_BASE + \
  43. SX150X_EPM_NR_GPIOS)
  44. #define SX150X_EXP1_IRQ_BASE (GPIO_EXPANDER_IRQ_BASE + \
  45. SX150X_EPM_NR_IRQS)
  46. #define SX150X_EXP1_NR_IRQS 16
  47. #define SX150X_EXP1_NR_GPIOS 16
  48. #define SX150X_EXP2_GPIO_BASE (SX150X_EXP1_GPIO_BASE + \
  49. SX150X_EXP1_NR_GPIOS)
  50. #define SX150X_EXP2_IRQ_BASE (SX150X_EXP1_IRQ_BASE + SX150X_EXP1_NR_IRQS)
  51. #define SX150X_EXP2_NR_IRQS 8
  52. #define SX150X_EXP2_NR_GPIOS 8
  53. #define SX150X_EXP3_GPIO_BASE (SX150X_EXP2_GPIO_BASE + \
  54. SX150X_EXP2_NR_GPIOS)
  55. #define SX150X_EXP3_IRQ_BASE (SX150X_EXP2_IRQ_BASE + SX150X_EXP2_NR_IRQS)
  56. #define SX150X_EXP3_NR_IRQS 8
  57. #define SX150X_EXP3_NR_GPIOS 8
  58. #define SX150X_EXP4_GPIO_BASE (SX150X_EXP3_GPIO_BASE + \
  59. SX150X_EXP3_NR_GPIOS)
  60. #define SX150X_EXP4_IRQ_BASE (SX150X_EXP3_IRQ_BASE + SX150X_EXP3_NR_IRQS)
  61. #define SX150X_EXP4_NR_IRQS 16
  62. #define SX150X_EXP4_NR_GPIOS 16
  63. #define SX150X_GPIO(_expander, _pin) (SX150X_EXP##_expander##_GPIO_BASE + _pin)
  64. enum {
  65. SX150X_EPM,
  66. SX150X_EXP1,
  67. SX150X_EXP2,
  68. SX150X_EXP3,
  69. SX150X_EXP4,
  70. };
  71. #define MPQ8064_SPK_ON 1
  72. #define MPQ8064_SPK_OFF 0
  73. #define MSM_SLIM_0_RX_MAX_CHANNELS 2
  74. #define MSM_SLIM_0_TX_MAX_CHANNELS 4
  75. #define BOTTOM_SPK_AMP_POS 0x1
  76. #define BOTTOM_SPK_AMP_NEG 0x2
  77. #define TOP_SPK_AMP_POS 0x4
  78. #define TOP_SPK_AMP_NEG 0x8
  79. #define GPIO_AUX_PCM_DOUT 43
  80. #define GPIO_AUX_PCM_DIN 44
  81. #define GPIO_AUX_PCM_SYNC 45
  82. #define GPIO_AUX_PCM_CLK 46
  83. #define TABLA_EXT_CLK_RATE 12288000
  84. #define TABLA_MBHC_DEF_BUTTONS 8
  85. #define TABLA_MBHC_DEF_RLOADS 5
  86. #define GPIO_SEC_I2S_RX_SCK 47
  87. #define GPIO_SEC_I2S_RX_WS 48
  88. #define GPIO_SEC_I2S_RX_DOUT 49
  89. #define GPIO_SEC_I2S_RX_MCLK 50
  90. #define I2S_MCLK_RATE 12288000
  91. #define GPIO_MI2S_WS 27
  92. #define GPIO_MI2S_SCLK 28
  93. #define GPIO_MI2S_DOUT3 29
  94. #define GPIO_MI2S_DOUT2 30
  95. #define GPIO_MI2S_DOUT1 31
  96. #define GPIO_MI2S_DOUT0 32
  97. #define GPIO_MI2S_MCLK 33
  98. static struct clk *sec_i2s_rx_osr_clk;
  99. static struct clk *sec_i2s_rx_bit_clk;
  100. struct request_gpio {
  101. unsigned gpio_no;
  102. char *gpio_name;
  103. };
  104. static struct request_gpio sec_i2s_rx_gpio[] = {
  105. {
  106. .gpio_no = GPIO_SEC_I2S_RX_MCLK,
  107. .gpio_name = "SEC_I2S_RX_MCLK",
  108. },
  109. {
  110. .gpio_no = GPIO_SEC_I2S_RX_SCK,
  111. .gpio_name = "SEC_I2S_RX_SCK",
  112. },
  113. {
  114. .gpio_no = GPIO_SEC_I2S_RX_WS,
  115. .gpio_name = "SEC_I2S_RX_WS",
  116. },
  117. {
  118. .gpio_no = GPIO_SEC_I2S_RX_DOUT,
  119. .gpio_name = "SEC_I2S_RX_DOUT",
  120. },
  121. };
  122. static struct request_gpio mi2s_gpio[] = {
  123. {
  124. .gpio_no = GPIO_MI2S_WS,
  125. .gpio_name = "MI2S_WS",
  126. },
  127. {
  128. .gpio_no = GPIO_MI2S_SCLK,
  129. .gpio_name = "MI2S_SCLK",
  130. },
  131. {
  132. .gpio_no = GPIO_MI2S_DOUT3,
  133. .gpio_name = "MI2S_DOUT3",
  134. },
  135. {
  136. .gpio_no = GPIO_MI2S_DOUT2,
  137. .gpio_name = "MI2S_DOUT2",
  138. },
  139. {
  140. .gpio_no = GPIO_MI2S_DOUT1,
  141. .gpio_name = "MI2S_DOUT1",
  142. },
  143. {
  144. .gpio_no = GPIO_MI2S_DOUT0,
  145. .gpio_name = "MI2S_DOUT0",
  146. },
  147. {
  148. .gpio_no = GPIO_MI2S_MCLK,
  149. .gpio_name = "MI2S_MCLK",
  150. },
  151. };
  152. static struct clk *mi2s_bit_clk;
  153. static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
  154. static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
  155. static int msm_spk_control;
  156. static int msm_ext_bottom_spk_pamp;
  157. static int msm_ext_top_spk_pamp;
  158. static int msm_slim_0_rx_ch = 1;
  159. static int msm_slim_0_tx_ch = 1;
  160. static int msm_hdmi_rx_ch = 8;
  161. static int mi2s_rate_variable;
  162. static int hdmi_rate_variable;
  163. static struct clk *codec_clk;
  164. static int clk_users;
  165. static struct snd_soc_jack hs_jack;
  166. static struct snd_soc_jack button_jack;
  167. static int detect_dtv_platform;
  168. static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  169. bool dapm);
  170. static struct tabla_mbhc_config mbhc_cfg = {
  171. .headset_jack = &hs_jack,
  172. .button_jack = &button_jack,
  173. .read_fw_bin = false,
  174. .calibration = NULL,
  175. .micbias = TABLA_MICBIAS2,
  176. .mclk_cb_fn = msm_enable_codec_ext_clk,
  177. .mclk_rate = TABLA_EXT_CLK_RATE,
  178. .gpio = 0, /* MBHC GPIO is not configured */
  179. .gpio_irq = 0,
  180. .gpio_level_insert = 1,
  181. };
  182. static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
  183. {
  184. int ret = 0;
  185. struct pm_gpio param = {
  186. .direction = PM_GPIO_DIR_OUT,
  187. .output_buffer = PM_GPIO_OUT_BUF_CMOS,
  188. .output_value = 1,
  189. .pull = PM_GPIO_PULL_NO,
  190. .vin_sel = PM_GPIO_VIN_S4,
  191. .out_strength = PM_GPIO_STRENGTH_MED,
  192. .
  193. function = PM_GPIO_FUNC_NORMAL,
  194. };
  195. if (spk_amp_gpio == bottom_spk_pamp_gpio) {
  196. ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
  197. if (ret) {
  198. pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
  199. __func__, bottom_spk_pamp_gpio);
  200. return;
  201. }
  202. ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
  203. if (ret)
  204. pr_err("%s: Failed to configure Bottom Spk Ampl"
  205. " gpio %u\n", __func__, bottom_spk_pamp_gpio);
  206. else {
  207. pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
  208. gpio_direction_output(bottom_spk_pamp_gpio, 1);
  209. }
  210. } else if (spk_amp_gpio == top_spk_pamp_gpio) {
  211. ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
  212. if (ret) {
  213. pr_err("%s: Error requesting GPIO %d\n", __func__,
  214. top_spk_pamp_gpio);
  215. return;
  216. }
  217. ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
  218. if (ret)
  219. pr_err("%s: Failed to configure Top Spk Ampl"
  220. " gpio %u\n", __func__, top_spk_pamp_gpio);
  221. else {
  222. pr_debug("%s: enable Top spkr amp gpio\n", __func__);
  223. gpio_direction_output(top_spk_pamp_gpio, 1);
  224. }
  225. } else {
  226. pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
  227. " gpio = %u\n", __func__, spk_amp_gpio);
  228. return;
  229. }
  230. }
  231. static void msm_ext_spk_power_amp_on(u32 spk)
  232. {
  233. if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
  234. if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
  235. (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
  236. pr_debug("%s() External Bottom Speaker Ampl already "
  237. "turned on. spk = 0x%08x\n", __func__, spk);
  238. return;
  239. }
  240. msm_ext_bottom_spk_pamp |= spk;
  241. if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
  242. (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
  243. msm_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
  244. pr_debug("%s: slepping 4 ms after turning on external "
  245. " Bottom Speaker Ampl\n", __func__);
  246. usleep_range(4000, 4000);
  247. }
  248. } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
  249. if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
  250. (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
  251. pr_debug("%s() External Top Speaker Ampl already"
  252. "turned on. spk = 0x%08x\n", __func__, spk);
  253. return;
  254. }
  255. msm_ext_top_spk_pamp |= spk;
  256. if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
  257. (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
  258. msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
  259. pr_debug("%s: sleeping 4 ms after turning on "
  260. " external Top Speaker Ampl\n", __func__);
  261. usleep_range(4000, 4000);
  262. }
  263. } else {
  264. pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
  265. __func__, spk);
  266. return;
  267. }
  268. }
  269. static void msm_ext_spk_power_amp_off(u32 spk)
  270. {
  271. if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
  272. if (!msm_ext_bottom_spk_pamp)
  273. return;
  274. gpio_direction_output(bottom_spk_pamp_gpio, 0);
  275. gpio_free(bottom_spk_pamp_gpio);
  276. msm_ext_bottom_spk_pamp = 0;
  277. pr_debug("%s: sleeping 4 ms after turning off external Bottom"
  278. " Speaker Ampl\n", __func__);
  279. usleep_range(4000, 4000);
  280. } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
  281. if (!msm_ext_top_spk_pamp)
  282. return;
  283. gpio_direction_output(top_spk_pamp_gpio, 0);
  284. gpio_free(top_spk_pamp_gpio);
  285. msm_ext_top_spk_pamp = 0;
  286. pr_debug("%s: sleeping 4 ms after turning off external Top"
  287. " Spkaker Ampl\n", __func__);
  288. usleep_range(4000, 4000);
  289. } else {
  290. pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
  291. __func__, spk);
  292. return;
  293. }
  294. }
  295. static void msm_ext_control(struct snd_soc_codec *codec)
  296. {
  297. struct snd_soc_dapm_context *dapm = &codec->dapm;
  298. pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
  299. if (msm_spk_control == MPQ8064_SPK_ON) {
  300. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
  301. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
  302. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
  303. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
  304. } else {
  305. snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
  306. snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
  307. snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
  308. snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
  309. }
  310. snd_soc_dapm_sync(dapm);
  311. }
  312. static int msm_get_spk(struct snd_kcontrol *kcontrol,
  313. struct snd_ctl_elem_value *ucontrol)
  314. {
  315. pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
  316. ucontrol->value.integer.value[0] = msm_spk_control;
  317. return 0;
  318. }
  319. static int msm_set_spk(struct snd_kcontrol *kcontrol,
  320. struct snd_ctl_elem_value *ucontrol)
  321. {
  322. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  323. pr_debug("%s()\n", __func__);
  324. if (msm_spk_control == ucontrol->value.integer.value[0])
  325. return 0;
  326. msm_spk_control = ucontrol->value.integer.value[0];
  327. msm_ext_control(codec);
  328. return 1;
  329. }
  330. static int msm_spkramp_event(struct snd_soc_dapm_widget *w,
  331. struct snd_kcontrol *k, int event)
  332. {
  333. pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
  334. if (SND_SOC_DAPM_EVENT_ON(event)) {
  335. if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
  336. msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
  337. else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
  338. msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
  339. else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
  340. msm_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
  341. else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
  342. msm_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
  343. else {
  344. pr_err("%s() Invalid Speaker Widget = %s\n",
  345. __func__, w->name);
  346. return -EINVAL;
  347. }
  348. } else {
  349. if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
  350. msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
  351. else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
  352. msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
  353. else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
  354. msm_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
  355. else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
  356. msm_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
  357. else {
  358. pr_err("%s() Invalid Speaker Widget = %s\n",
  359. __func__, w->name);
  360. return -EINVAL;
  361. }
  362. }
  363. return 0;
  364. }
  365. static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  366. bool dapm)
  367. {
  368. pr_debug("%s: enable = %d\n", __func__, enable);
  369. if (enable) {
  370. clk_users++;
  371. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  372. if (clk_users != 1)
  373. return 0;
  374. if (codec_clk) {
  375. clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
  376. clk_prepare_enable(codec_clk);
  377. tabla_mclk_enable(codec, 1, dapm);
  378. } else {
  379. pr_err("%s: Error setting Tabla MCLK\n", __func__);
  380. clk_users--;
  381. return -EINVAL;
  382. }
  383. } else {
  384. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  385. if (clk_users == 0)
  386. return 0;
  387. clk_users--;
  388. if (!clk_users) {
  389. pr_debug("%s: disabling MCLK. clk_users = %d\n",
  390. __func__, clk_users);
  391. clk_disable_unprepare(codec_clk);
  392. tabla_mclk_enable(codec, 0, dapm);
  393. }
  394. }
  395. return 0;
  396. }
  397. static int msm_mclk_event(struct snd_soc_dapm_widget *w,
  398. struct snd_kcontrol *kcontrol, int event)
  399. {
  400. pr_debug("%s: event = %d\n", __func__, event);
  401. switch (event) {
  402. case SND_SOC_DAPM_PRE_PMU:
  403. clk_users++;
  404. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  405. if (clk_users != 1)
  406. return 0;
  407. if (codec_clk) {
  408. clk_set_rate(codec_clk, 12288000);
  409. clk_prepare_enable(codec_clk);
  410. tabla_mclk_enable(w->codec, 1, true);
  411. } else {
  412. pr_err("%s: Error setting Tabla MCLK\n", __func__);
  413. clk_users--;
  414. return -EINVAL;
  415. }
  416. break;
  417. case SND_SOC_DAPM_POST_PMD:
  418. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  419. if (clk_users == 0)
  420. return 0;
  421. clk_users--;
  422. if (!clk_users) {
  423. pr_debug("%s: disabling MCLK. clk_users = %d\n",
  424. __func__, clk_users);
  425. clk_disable_unprepare(codec_clk);
  426. tabla_mclk_enable(w->codec, 0, true);
  427. }
  428. break;
  429. }
  430. return 0;
  431. }
  432. static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
  433. SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
  434. msm_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  435. SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm_spkramp_event),
  436. SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm_spkramp_event),
  437. SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm_spkramp_event),
  438. SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm_spkramp_event),
  439. SND_SOC_DAPM_MIC("Handset Mic", NULL),
  440. SND_SOC_DAPM_MIC("Headset Mic", NULL),
  441. SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
  442. SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
  443. };
  444. static const struct snd_soc_dapm_route common_audio_map[] = {
  445. {"RX_BIAS", NULL, "MCLK"},
  446. {"LDO_H", NULL, "MCLK"},
  447. /* Speaker path */
  448. {"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
  449. {"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
  450. {"Ext Spk Top Pos", NULL, "LINEOUT2"},
  451. {"Ext Spk Top Neg", NULL, "LINEOUT4"},
  452. /* Microphone path */
  453. {"AMIC1", NULL, "MIC BIAS1 Internal1"},
  454. {"MIC BIAS1 Internal1", NULL, "Handset Mic"},
  455. {"AMIC2", NULL, "MIC BIAS2 External"},
  456. {"MIC BIAS2 External", NULL, "Headset Mic"},
  457. /**
  458. * AMIC3 and AMIC4 inputs are connected to ANC microphones
  459. * These mics are biased differently on CDP and FLUID
  460. * routing entries below are based on bias arrangement
  461. * on FLUID.
  462. */
  463. {"AMIC3", NULL, "MIC BIAS3 Internal1"},
  464. {"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
  465. {"AMIC4", NULL, "MIC BIAS1 Internal2"},
  466. {"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
  467. {"HEADPHONE", NULL, "LDO_H"},
  468. };
  469. static const char *spk_function[] = {"Off", "On"};
  470. static const char *slim0_rx_ch_text[] = {"One", "Two"};
  471. static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
  472. static const char * const hdmi_rx_ch_text[] = {"Two", "Three", "Four",
  473. "Five", "Six", "Seven", "Eight"};
  474. static const char * const mi2s_rate[] = {"Default", "Variable"};
  475. static const char * const hdmi_rate[] = {"Default", "Variable"};
  476. static const struct soc_enum msm_enum[] = {
  477. SOC_ENUM_SINGLE_EXT(2, spk_function),
  478. SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
  479. SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
  480. SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
  481. SOC_ENUM_SINGLE_EXT(2, mi2s_rate),
  482. SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
  483. };
  484. static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
  485. struct snd_ctl_elem_value *ucontrol)
  486. {
  487. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  488. msm_slim_0_rx_ch);
  489. ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
  490. return 0;
  491. }
  492. static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
  493. struct snd_ctl_elem_value *ucontrol)
  494. {
  495. msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
  496. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  497. msm_slim_0_rx_ch);
  498. return 1;
  499. }
  500. static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
  501. struct snd_ctl_elem_value *ucontrol)
  502. {
  503. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
  504. msm_slim_0_tx_ch);
  505. ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
  506. return 0;
  507. }
  508. static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
  509. struct snd_ctl_elem_value *ucontrol)
  510. {
  511. msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
  512. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
  513. msm_slim_0_tx_ch);
  514. return 1;
  515. }
  516. static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
  517. struct snd_ctl_elem_value *ucontrol)
  518. {
  519. pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
  520. msm_hdmi_rx_ch);
  521. ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
  522. return 0;
  523. }
  524. static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
  525. struct snd_ctl_elem_value *ucontrol)
  526. {
  527. msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
  528. pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
  529. msm_hdmi_rx_ch);
  530. return 1;
  531. }
  532. static int msm_mi2s_rate_put(struct snd_kcontrol *kcontrol,
  533. struct snd_ctl_elem_value *ucontrol)
  534. {
  535. mi2s_rate_variable = ucontrol->value.integer.value[0];
  536. pr_debug("%s: mi2s_rate_variable = %d\n", __func__, mi2s_rate_variable);
  537. return 0;
  538. }
  539. static int msm_mi2s_rate_get(struct snd_kcontrol *kcontrol,
  540. struct snd_ctl_elem_value *ucontrol)
  541. {
  542. ucontrol->value.integer.value[0] = mi2s_rate_variable;
  543. return 0;
  544. }
  545. static int msm_hdmi_rate_put(struct snd_kcontrol *kcontrol,
  546. struct snd_ctl_elem_value *ucontrol)
  547. {
  548. hdmi_rate_variable = ucontrol->value.integer.value[0];
  549. pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
  550. return 0;
  551. }
  552. static int msm_hdmi_rate_get(struct snd_kcontrol *kcontrol,
  553. struct snd_ctl_elem_value *ucontrol)
  554. {
  555. ucontrol->value.integer.value[0] = hdmi_rate_variable;
  556. return 0;
  557. }
  558. static const struct snd_kcontrol_new tabla_msm_controls[] = {
  559. SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
  560. msm_set_spk),
  561. SOC_ENUM_EXT("SLIM_0_RX Channels", msm_enum[1],
  562. msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
  563. SOC_ENUM_EXT("SLIM_0_TX Channels", msm_enum[2],
  564. msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
  565. SOC_ENUM_EXT("HDMI_RX Channels", msm_enum[3],
  566. msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
  567. SOC_ENUM_EXT("SEC RX Rate", msm_enum[4],
  568. msm_mi2s_rate_get,
  569. msm_mi2s_rate_put),
  570. SOC_ENUM_EXT("HDMI RX Rate", msm_enum[5],
  571. msm_hdmi_rate_get,
  572. msm_hdmi_rate_put),
  573. };
  574. static void *def_tabla_mbhc_cal(void)
  575. {
  576. void *tabla_cal;
  577. struct tabla_mbhc_btn_detect_cfg *btn_cfg;
  578. u16 *btn_low, *btn_high;
  579. u8 *n_ready, *n_cic, *gain;
  580. tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
  581. TABLA_MBHC_DEF_RLOADS),
  582. GFP_KERNEL);
  583. if (!tabla_cal) {
  584. pr_err("%s: out of memory\n", __func__);
  585. return NULL;
  586. }
  587. #define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
  588. S(t_ldoh, 100);
  589. S(t_bg_fast_settle, 100);
  590. S(t_shutdown_plug_rem, 255);
  591. S(mbhc_nsa, 4);
  592. S(mbhc_navg, 4);
  593. #undef S
  594. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
  595. S(mic_current, TABLA_PID_MIC_5_UA);
  596. S(hph_current, TABLA_PID_MIC_5_UA);
  597. S(t_mic_pid, 100);
  598. S(t_ins_complete, 250);
  599. S(t_ins_retry, 200);
  600. #undef S
  601. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
  602. S(v_no_mic, 30);
  603. S(v_hs_max, 2400);
  604. #undef S
  605. #define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
  606. S(c[0], 62);
  607. S(c[1], 124);
  608. S(nc, 1);
  609. S(n_meas, 3);
  610. S(mbhc_nsc, 11);
  611. S(n_btn_meas, 1);
  612. S(n_btn_con, 2);
  613. S(num_btn, TABLA_MBHC_DEF_BUTTONS);
  614. S(v_btn_press_delta_sta, 100);
  615. S(v_btn_press_delta_cic, 50);
  616. #undef S
  617. btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
  618. btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
  619. btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
  620. btn_low[0] = -50;
  621. btn_high[0] = 20;
  622. btn_low[1] = 21;
  623. btn_high[1] = 62;
  624. btn_low[2] = 62;
  625. btn_high[2] = 104;
  626. btn_low[3] = 105;
  627. btn_high[3] = 143;
  628. btn_low[4] = 144;
  629. btn_high[4] = 181;
  630. btn_low[5] = 182;
  631. btn_high[5] = 218;
  632. btn_low[6] = 219;
  633. btn_high[6] = 254;
  634. btn_low[7] = 255;
  635. btn_high[7] = 330;
  636. n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
  637. n_ready[0] = 80;
  638. n_ready[1] = 68;
  639. n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
  640. n_cic[0] = 60;
  641. n_cic[1] = 47;
  642. gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
  643. gain[0] = 11;
  644. gain[1] = 9;
  645. return tabla_cal;
  646. }
  647. static int msm_hw_params(struct snd_pcm_substream *substream,
  648. struct snd_pcm_hw_params *params)
  649. {
  650. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  651. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  652. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  653. int ret = 0;
  654. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  655. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  656. pr_debug("%s: ch=%d\n", __func__,
  657. msm_slim_0_rx_ch);
  658. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  659. ret = snd_soc_dai_get_channel_map(codec_dai,
  660. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  661. if (ret < 0) {
  662. pr_err("%s: failed to get codec chan map\n", __func__);
  663. goto end;
  664. }
  665. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  666. msm_slim_0_rx_ch, rx_ch);
  667. if (ret < 0) {
  668. pr_err("%s: failed to set cpu chan map\n", __func__);
  669. goto end;
  670. }
  671. } else {
  672. ret = snd_soc_dai_get_channel_map(codec_dai,
  673. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  674. if (ret < 0) {
  675. pr_err("%s: failed to get codec chan map\n", __func__);
  676. goto end;
  677. }
  678. ret = snd_soc_dai_set_channel_map(cpu_dai,
  679. msm_slim_0_tx_ch, tx_ch, 0 , 0);
  680. if (ret < 0) {
  681. pr_err("%s: failed to set cpu chan map\n", __func__);
  682. goto end;
  683. }
  684. }
  685. end:
  686. return ret;
  687. }
  688. static int mpq_dtv_amp_power_up(void)
  689. {
  690. int ret;
  691. pr_debug("%s()\n", __func__);
  692. ret = gpio_request(SX150X_GPIO(1, 14),
  693. "DTV AMP Sleep");
  694. if (ret) {
  695. pr_err("%s: DTV AMP Sleep GPIO request returns %d\n",
  696. __func__, ret);
  697. return ret;
  698. }
  699. ret = gpio_direction_output(SX150X_GPIO(1, 14), 0);
  700. if (ret) {
  701. pr_err("%s: DTV AMP Sleep GPIO set output returns %d\n",
  702. __func__, ret);
  703. return ret;
  704. }
  705. ret = gpio_request(SX150X_GPIO(1, 13),
  706. "DTV AMP Mute");
  707. if (ret) {
  708. pr_err("%s: DTV AMP Mute GPIO request returns %d\n",
  709. __func__, ret);
  710. return ret;
  711. }
  712. ret = gpio_direction_output(SX150X_GPIO(1, 13), 0);
  713. if (ret) {
  714. pr_err("%s: DTV AMP Mute GPIO set output returns %d\n",
  715. __func__, ret);
  716. return ret;
  717. }
  718. return ret;
  719. }
  720. static int mpq_dtv_amp_power_down(void)
  721. {
  722. int ret;
  723. pr_debug("%s()\n", __func__);
  724. ret = gpio_direction_output(SX150X_GPIO(1, 14), 1);
  725. if (ret) {
  726. pr_err("%s: DTV AMP Sleep GPIO set output failed\n", __func__);
  727. return ret;
  728. }
  729. gpio_free(SX150X_GPIO(1, 14));
  730. ret = gpio_direction_output(SX150X_GPIO(1, 13), 1);
  731. if (ret) {
  732. pr_err("%s: DTV AMP Mute GPIO set output failed\n", __func__);
  733. return ret;
  734. }
  735. gpio_free(SX150X_GPIO(1, 13));
  736. return ret;
  737. }
  738. static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
  739. {
  740. int err;
  741. struct snd_soc_codec *codec = rtd->codec;
  742. struct snd_soc_dapm_context *dapm = &codec->dapm;
  743. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  744. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  745. unsigned int rx_ch[TABLA_RX_MAX] = {138, 139, 140, 141, 142, 143, 144};
  746. unsigned int tx_ch[TABLA_TX_MAX] = {128, 129, 130, 131, 132, 133, 134,
  747. 135, 136, 137};
  748. pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
  749. snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
  750. ARRAY_SIZE(msm_dapm_widgets));
  751. snd_soc_dapm_add_routes(dapm, common_audio_map,
  752. ARRAY_SIZE(common_audio_map));
  753. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
  754. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
  755. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
  756. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
  757. snd_soc_dapm_sync(dapm);
  758. err = snd_soc_jack_new(codec, "Headset Jack",
  759. (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
  760. &hs_jack);
  761. if (err) {
  762. pr_err("failed to create new jack\n");
  763. return err;
  764. }
  765. err = snd_soc_jack_new(codec, "Button Jack",
  766. TABLA_JACK_BUTTON_MASK, &button_jack);
  767. if (err) {
  768. pr_err("failed to create new jack\n");
  769. return err;
  770. }
  771. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  772. err = tabla_hs_detect(codec, &mbhc_cfg);
  773. snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
  774. tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
  775. if (detect_dtv_platform) {
  776. err = gpio_request(SX150X_GPIO(1, 11),
  777. "DTV AMP Gain0");
  778. if (err) {
  779. pr_err("%s: DTV AMP Gain0 request returns %d\n",
  780. __func__, err);
  781. return err;
  782. }
  783. err = gpio_direction_output(SX150X_GPIO(1, 11), 0);
  784. if (err) {
  785. pr_err("%s: DTV AMP Gain0 set output returns %d\n",
  786. __func__, err);
  787. return err;
  788. }
  789. gpio_free(SX150X_GPIO(1, 11));
  790. err = gpio_request(SX150X_GPIO(1, 12),
  791. "DTV AMP Gain1");
  792. if (err) {
  793. pr_err("%s: DTV AMP Gain0 request returns %d\n",
  794. __func__, err);
  795. return err;
  796. }
  797. err = gpio_direction_output(SX150X_GPIO(1, 12), 0);
  798. if (err) {
  799. pr_err("%s: DTV AMP Gain1 set output returns %d\n",
  800. __func__, err);
  801. return err;
  802. }
  803. gpio_free(SX150X_GPIO(1, 12));
  804. err = gpio_request(SX150X_GPIO(1, 15),
  805. "DTV AMP Status");
  806. if (err) {
  807. pr_err("%s: DTV AMP Status request returns %d\n",
  808. __func__, err);
  809. return err;
  810. }
  811. err = gpio_direction_input(SX150X_GPIO(1, 15));
  812. if (err) {
  813. pr_err("%s: DTV AMP Status set output returns %d\n",
  814. __func__, err);
  815. return err;
  816. }
  817. err = mpq_dtv_amp_power_down();
  818. if (err) {
  819. pr_err("%s: DTV AMP Status set output returns %d\n",
  820. __func__, err);
  821. return err;
  822. }
  823. }
  824. return err;
  825. }
  826. static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  827. struct snd_pcm_hw_params *params)
  828. {
  829. struct snd_interval *rate = hw_param_interval(params,
  830. SNDRV_PCM_HW_PARAM_RATE);
  831. struct snd_interval *channels = hw_param_interval(params,
  832. SNDRV_PCM_HW_PARAM_CHANNELS);
  833. pr_debug("%s()\n", __func__);
  834. rate->min = rate->max = 48000;
  835. channels->min = channels->max = msm_slim_0_rx_ch;
  836. return 0;
  837. }
  838. static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  839. struct snd_pcm_hw_params *params)
  840. {
  841. struct snd_interval *rate = hw_param_interval(params,
  842. SNDRV_PCM_HW_PARAM_RATE);
  843. struct snd_interval *channels = hw_param_interval(params,
  844. SNDRV_PCM_HW_PARAM_CHANNELS);
  845. pr_debug("%s()\n", __func__);
  846. rate->min = rate->max = 48000;
  847. channels->min = channels->max = msm_slim_0_tx_ch;
  848. return 0;
  849. }
  850. static int mpq8064_proxy_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
  851. struct snd_pcm_hw_params *params)
  852. {
  853. struct snd_interval *rate = hw_param_interval(params,
  854. SNDRV_PCM_HW_PARAM_RATE);
  855. struct snd_interval *channels = hw_param_interval(params,
  856. SNDRV_PCM_HW_PARAM_CHANNELS);
  857. pr_debug("%s ()\n", __func__);
  858. rate->min = rate->max = 48000;
  859. channels->min = channels->max = 2;
  860. return 0;
  861. }
  862. static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  863. struct snd_pcm_hw_params *params)
  864. {
  865. struct snd_interval *rate = hw_param_interval(params,
  866. SNDRV_PCM_HW_PARAM_RATE);
  867. struct snd_interval *channels = hw_param_interval(params,
  868. SNDRV_PCM_HW_PARAM_CHANNELS);
  869. pr_debug("%s mi2s_rate_variable = %d\n", __func__, mi2s_rate_variable);
  870. /*Configure the sample rate as 48000 KHz for the LPCM playback*/
  871. if (!mi2s_rate_variable)
  872. rate->min = rate->max = 48000;
  873. channels->min = channels->max = 2;
  874. return 0;
  875. }
  876. static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  877. struct snd_pcm_hw_params *params)
  878. {
  879. struct snd_interval *rate = hw_param_interval(params,
  880. SNDRV_PCM_HW_PARAM_RATE);
  881. pr_debug("%s()\n", __func__);
  882. rate->min = rate->max = 48000;
  883. return 0;
  884. }
  885. static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  886. struct snd_pcm_hw_params *params)
  887. {
  888. struct snd_interval *rate = hw_param_interval(params,
  889. SNDRV_PCM_HW_PARAM_RATE);
  890. struct snd_interval *channels = hw_param_interval(params,
  891. SNDRV_PCM_HW_PARAM_CHANNELS);
  892. pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
  893. channels->min, channels->max);
  894. /*Configure the sample rate as 48000 KHz for the LPCM playback*/
  895. if (!hdmi_rate_variable)
  896. rate->min = rate->max = 48000;
  897. channels->min = channels->max = msm_hdmi_rx_ch;
  898. return 0;
  899. }
  900. static int msm_mi2s_free_gpios(void)
  901. {
  902. int i;
  903. for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++)
  904. gpio_free(mi2s_gpio[i].gpio_no);
  905. return 0;
  906. }
  907. static void msm_mi2s_shutdown(struct snd_pcm_substream *substream)
  908. {
  909. if (mi2s_bit_clk) {
  910. clk_disable_unprepare(mi2s_bit_clk);
  911. clk_put(mi2s_bit_clk);
  912. mi2s_bit_clk = NULL;
  913. }
  914. }
  915. static int configure_mi2s_gpio(void)
  916. {
  917. int rtn;
  918. int i;
  919. int j;
  920. for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++) {
  921. rtn = gpio_request(mi2s_gpio[i].gpio_no,
  922. mi2s_gpio[i].gpio_name);
  923. pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
  924. __func__,
  925. mi2s_gpio[i].gpio_no,
  926. mi2s_gpio[i].gpio_name,
  927. rtn);
  928. if (rtn) {
  929. pr_err("%s: Failed to request gpio %d\n",
  930. __func__,
  931. mi2s_gpio[i].gpio_no);
  932. for (j = i; j >= 0; j--)
  933. gpio_free(mi2s_gpio[j].gpio_no);
  934. goto err;
  935. }
  936. }
  937. err:
  938. return rtn;
  939. }
  940. static int msm_mi2s_startup(struct snd_pcm_substream *substream)
  941. {
  942. int ret = 0;
  943. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  944. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  945. mi2s_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  946. if (IS_ERR(mi2s_bit_clk))
  947. return PTR_ERR(mi2s_bit_clk);
  948. clk_set_rate(mi2s_bit_clk, 0);
  949. ret = clk_prepare_enable(mi2s_bit_clk);
  950. if (IS_ERR_VALUE(ret)) {
  951. pr_err("Unable to enable mi2s_bit_clk\n");
  952. clk_put(mi2s_bit_clk);
  953. return ret;
  954. }
  955. ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
  956. if (IS_ERR_VALUE(ret))
  957. pr_err("set format for CPU dai failed\n");
  958. return ret;
  959. }
  960. static int mpq8064_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
  961. struct snd_pcm_hw_params *params)
  962. {
  963. struct snd_interval *rate = hw_param_interval(params,
  964. SNDRV_PCM_HW_PARAM_RATE);
  965. struct snd_interval *channels = hw_param_interval(params,
  966. SNDRV_PCM_HW_PARAM_CHANNELS);
  967. /* PCM only supports mono output with 8khz sample rate */
  968. rate->min = rate->max = 8000;
  969. channels->min = channels->max = 1;
  970. return 0;
  971. }
  972. static int mpq8064_aux_pcm_get_gpios(void)
  973. {
  974. int ret = 0;
  975. pr_debug("%s\n", __func__);
  976. ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
  977. if (ret < 0) {
  978. pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
  979. __func__, GPIO_AUX_PCM_DOUT);
  980. goto fail_dout;
  981. }
  982. ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
  983. if (ret < 0) {
  984. pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
  985. __func__, GPIO_AUX_PCM_DIN);
  986. goto fail_din;
  987. }
  988. ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
  989. if (ret < 0) {
  990. pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
  991. __func__, GPIO_AUX_PCM_SYNC);
  992. goto fail_sync;
  993. }
  994. ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
  995. if (ret < 0) {
  996. pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
  997. __func__, GPIO_AUX_PCM_CLK);
  998. goto fail_clk;
  999. }
  1000. return 0;
  1001. fail_clk:
  1002. gpio_free(GPIO_AUX_PCM_SYNC);
  1003. fail_sync:
  1004. gpio_free(GPIO_AUX_PCM_DIN);
  1005. fail_din:
  1006. gpio_free(GPIO_AUX_PCM_DOUT);
  1007. fail_dout:
  1008. return ret;
  1009. }
  1010. static int mpq8064_aux_pcm_free_gpios(void)
  1011. {
  1012. gpio_free(GPIO_AUX_PCM_DIN);
  1013. gpio_free(GPIO_AUX_PCM_DOUT);
  1014. gpio_free(GPIO_AUX_PCM_SYNC);
  1015. gpio_free(GPIO_AUX_PCM_CLK);
  1016. return 0;
  1017. }
  1018. static int msm_startup(struct snd_pcm_substream *substream)
  1019. {
  1020. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1021. substream->name, substream->stream);
  1022. if (detect_dtv_platform)
  1023. mpq_dtv_amp_power_up();
  1024. return 0;
  1025. }
  1026. static void msm_shutdown(struct snd_pcm_substream *substream)
  1027. {
  1028. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1029. substream->name, substream->stream);
  1030. if (detect_dtv_platform)
  1031. mpq_dtv_amp_power_down();
  1032. }
  1033. static int mpq8064_auxpcm_startup(struct snd_pcm_substream *substream)
  1034. {
  1035. int ret = 0;
  1036. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1037. ret = mpq8064_aux_pcm_get_gpios();
  1038. if (ret < 0) {
  1039. pr_err("%s: Aux PCM GPIO request failed\n", __func__);
  1040. return -EINVAL;
  1041. }
  1042. return 0;
  1043. }
  1044. static void mpq8064_auxpcm_shutdown(struct snd_pcm_substream *substream)
  1045. {
  1046. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1047. mpq8064_aux_pcm_free_gpios();
  1048. }
  1049. static struct snd_soc_ops msm_be_ops = {
  1050. .startup = msm_startup,
  1051. .hw_params = msm_hw_params,
  1052. .shutdown = msm_shutdown,
  1053. };
  1054. static struct snd_soc_ops mpq8064_auxpcm_be_ops = {
  1055. .startup = mpq8064_auxpcm_startup,
  1056. .shutdown = mpq8064_auxpcm_shutdown,
  1057. };
  1058. static int mpq8064_sec_i2s_rx_free_gpios(void)
  1059. {
  1060. int i;
  1061. for (i = 0; i < ARRAY_SIZE(sec_i2s_rx_gpio); i++)
  1062. gpio_free(sec_i2s_rx_gpio[i].gpio_no);
  1063. return 0;
  1064. }
  1065. static int mpq8064_sec_i2s_rx_hw_params(struct snd_pcm_substream *substream,
  1066. struct snd_pcm_hw_params *params)
  1067. {
  1068. int rate = params_rate(params);
  1069. int bit_clk_set = 0;
  1070. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1071. switch (params_format(params)) {
  1072. case SNDRV_PCM_FORMAT_S16_LE:
  1073. bit_clk_set = I2S_MCLK_RATE/(rate * 2 * 16);
  1074. clk_set_rate(sec_i2s_rx_bit_clk, bit_clk_set);
  1075. break;
  1076. case SNDRV_PCM_FORMAT_S24_LE:
  1077. bit_clk_set = I2S_MCLK_RATE/(rate * 2 * 24);
  1078. clk_set_rate(sec_i2s_rx_bit_clk, bit_clk_set);
  1079. break;
  1080. default:
  1081. pr_err("wrong format\n");
  1082. break;
  1083. }
  1084. }
  1085. return 0;
  1086. }
  1087. static void mpq8064_sec_i2s_rx_shutdown(struct snd_pcm_substream *substream)
  1088. {
  1089. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1090. if (sec_i2s_rx_bit_clk) {
  1091. clk_disable_unprepare(sec_i2s_rx_bit_clk);
  1092. clk_put(sec_i2s_rx_bit_clk);
  1093. sec_i2s_rx_bit_clk = NULL;
  1094. }
  1095. if (sec_i2s_rx_osr_clk) {
  1096. clk_disable_unprepare(sec_i2s_rx_osr_clk);
  1097. clk_put(sec_i2s_rx_osr_clk);
  1098. sec_i2s_rx_osr_clk = NULL;
  1099. }
  1100. }
  1101. pr_info("%s(): substream = %s stream = %d\n", __func__,
  1102. substream->name, substream->stream);
  1103. }
  1104. static int configure_sec_i2s_rx_gpio(void)
  1105. {
  1106. int rtn;
  1107. int i;
  1108. int j;
  1109. for (i = 0; i < ARRAY_SIZE(sec_i2s_rx_gpio); i++) {
  1110. rtn = gpio_request(sec_i2s_rx_gpio[i].gpio_no,
  1111. sec_i2s_rx_gpio[i].gpio_name);
  1112. pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
  1113. __func__,
  1114. sec_i2s_rx_gpio[i].gpio_no,
  1115. sec_i2s_rx_gpio[i].gpio_name,
  1116. rtn);
  1117. if (rtn) {
  1118. pr_err("%s: Failed to request gpio %d\n",
  1119. __func__,
  1120. sec_i2s_rx_gpio[i].gpio_no);
  1121. for (j = i; j >= 0; j--)
  1122. gpio_free(sec_i2s_rx_gpio[j].gpio_no);
  1123. goto err;
  1124. }
  1125. }
  1126. err:
  1127. return rtn;
  1128. }
  1129. static int mpq8064_sec_i2s_rx_startup(struct snd_pcm_substream *substream)
  1130. {
  1131. int ret = 0;
  1132. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1133. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1134. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1135. sec_i2s_rx_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
  1136. if (IS_ERR(sec_i2s_rx_osr_clk)) {
  1137. pr_err("Failed to get sec_i2s_rx_osr_clk\n");
  1138. return PTR_ERR(sec_i2s_rx_osr_clk);
  1139. }
  1140. clk_set_rate(sec_i2s_rx_osr_clk, I2S_MCLK_RATE);
  1141. clk_prepare_enable(sec_i2s_rx_osr_clk);
  1142. sec_i2s_rx_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  1143. if (IS_ERR(sec_i2s_rx_bit_clk)) {
  1144. pr_err("Failed to get sec i2s osr_clk\n");
  1145. clk_disable_unprepare(sec_i2s_rx_osr_clk);
  1146. clk_put(sec_i2s_rx_osr_clk);
  1147. return PTR_ERR(sec_i2s_rx_bit_clk);
  1148. }
  1149. clk_set_rate(sec_i2s_rx_bit_clk, 1);
  1150. ret = clk_prepare_enable(sec_i2s_rx_bit_clk);
  1151. if (ret != 0) {
  1152. pr_err("Unable to enable sec i2s rx_bit_clk\n");
  1153. clk_put(sec_i2s_rx_bit_clk);
  1154. clk_disable_unprepare(sec_i2s_rx_osr_clk);
  1155. clk_put(sec_i2s_rx_osr_clk);
  1156. return ret;
  1157. }
  1158. ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
  1159. if (ret < 0)
  1160. pr_err("set format for codec dai failed\n");
  1161. }
  1162. pr_debug("%s: ret = %d\n", __func__, ret);
  1163. pr_info("%s(): substream = %s stream = %d\n", __func__,
  1164. substream->name, substream->stream);
  1165. return ret;
  1166. }
  1167. static struct snd_soc_ops mpq8064_sec_i2s_rx_be_ops = {
  1168. .startup = mpq8064_sec_i2s_rx_startup,
  1169. .shutdown = mpq8064_sec_i2s_rx_shutdown,
  1170. .hw_params = mpq8064_sec_i2s_rx_hw_params,
  1171. };
  1172. static struct snd_soc_ops msm_mi2s_tx_be_ops = {
  1173. .startup = msm_mi2s_startup,
  1174. .shutdown = msm_mi2s_shutdown,
  1175. };
  1176. /* Digital audio interface glue - connects codec <---> CPU */
  1177. static struct snd_soc_dai_link msm_dai[] = {
  1178. /* FrontEnd DAI Links */
  1179. {
  1180. .name = "MSM8960 Media1",
  1181. .stream_name = "MultiMedia1",
  1182. .cpu_dai_name = "MultiMedia1",
  1183. .platform_name = "msm-pcm-dsp",
  1184. .dynamic = 1,
  1185. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1186. SND_SOC_DPCM_TRIGGER_POST},
  1187. .codec_dai_name = "snd-soc-dummy-dai",
  1188. .codec_name = "snd-soc-dummy",
  1189. .ignore_suspend = 1,
  1190. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1191. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
  1192. },
  1193. {
  1194. .name = "MSM8960 Media2",
  1195. .stream_name = "MultiMedia2",
  1196. .cpu_dai_name = "MultiMedia2",
  1197. .platform_name = "msm-multi-ch-pcm-dsp",
  1198. .dynamic = 1,
  1199. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1200. SND_SOC_DPCM_TRIGGER_POST},
  1201. .codec_dai_name = "snd-soc-dummy-dai",
  1202. .codec_name = "snd-soc-dummy",
  1203. .ignore_suspend = 1,
  1204. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1205. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
  1206. },
  1207. {
  1208. .name = "Circuit-Switch Voice",
  1209. .stream_name = "CS-Voice",
  1210. .cpu_dai_name = "CS-VOICE",
  1211. .platform_name = "msm-pcm-voice",
  1212. .dynamic = 1,
  1213. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1214. SND_SOC_DPCM_TRIGGER_POST},
  1215. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1216. .ignore_suspend = 1,
  1217. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1218. .codec_dai_name = "snd-soc-dummy-dai",
  1219. .codec_name = "snd-soc-dummy",
  1220. .be_id = MSM_FRONTEND_DAI_CS_VOICE,
  1221. },
  1222. {
  1223. .name = "MSM VoIP",
  1224. .stream_name = "VoIP",
  1225. .cpu_dai_name = "VoIP",
  1226. .platform_name = "msm-voip-dsp",
  1227. .dynamic = 1,
  1228. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1229. SND_SOC_DPCM_TRIGGER_POST},
  1230. .codec_dai_name = "snd-soc-dummy-dai",
  1231. .codec_name = "snd-soc-dummy",
  1232. .ignore_suspend = 1,
  1233. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1234. .be_id = MSM_FRONTEND_DAI_VOIP,
  1235. },
  1236. {
  1237. .name = "MSM8960 Media3",
  1238. .stream_name = "MultiMedia3",
  1239. .cpu_dai_name = "MultiMedia3",
  1240. .platform_name = "msm-multi-ch-pcm-dsp",
  1241. .dynamic = 1,
  1242. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1243. SND_SOC_DPCM_TRIGGER_POST},
  1244. .codec_dai_name = "snd-soc-dummy-dai",
  1245. .codec_name = "snd-soc-dummy",
  1246. .ignore_suspend = 1,
  1247. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1248. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
  1249. },
  1250. /* Hostless PMC purpose */
  1251. {
  1252. .name = "SLIMBUS_0 Hostless",
  1253. .stream_name = "SLIMBUS_0 Hostless",
  1254. .cpu_dai_name = "SLIMBUS0_HOSTLESS",
  1255. .platform_name = "msm-pcm-hostless",
  1256. .dynamic = 1,
  1257. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1258. SND_SOC_DPCM_TRIGGER_POST},
  1259. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1260. .ignore_suspend = 1,
  1261. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1262. .codec_dai_name = "snd-soc-dummy-dai",
  1263. .codec_name = "snd-soc-dummy",
  1264. },
  1265. {
  1266. .name = "INT_FM Hostless",
  1267. .stream_name = "INT_FM Hostless",
  1268. .cpu_dai_name = "INT_FM_HOSTLESS",
  1269. .platform_name = "msm-pcm-hostless",
  1270. .dynamic = 1,
  1271. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1272. SND_SOC_DPCM_TRIGGER_POST},
  1273. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1274. .ignore_suspend = 1,
  1275. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1276. .codec_dai_name = "snd-soc-dummy-dai",
  1277. .codec_name = "snd-soc-dummy",
  1278. },
  1279. {
  1280. .name = "MSM AFE-PCM RX",
  1281. .stream_name = "AFE-PROXY RX",
  1282. .cpu_dai_name = "msm-dai-q6.241",
  1283. .codec_name = "msm-stub-codec.1",
  1284. .codec_dai_name = "msm-stub-rx",
  1285. .platform_name = "msm-pcm-afe",
  1286. .ignore_suspend = 1,
  1287. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1288. },
  1289. {
  1290. .name = "MSM AFE-PCM TX",
  1291. .stream_name = "AFE-PROXY TX",
  1292. .cpu_dai_name = "msm-dai-q6.240",
  1293. .codec_name = "msm-stub-codec.1",
  1294. .codec_dai_name = "msm-stub-tx",
  1295. .platform_name = "msm-pcm-afe",
  1296. .ignore_suspend = 1,
  1297. },
  1298. {
  1299. .name = "MSM8960 Compr1",
  1300. .stream_name = "COMPR1",
  1301. .cpu_dai_name = "MultiMedia4",
  1302. .platform_name = "msm-compr-dsp",
  1303. .dynamic = 1,
  1304. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1305. SND_SOC_DPCM_TRIGGER_POST},
  1306. .codec_dai_name = "snd-soc-dummy-dai",
  1307. .codec_name = "snd-soc-dummy",
  1308. .ignore_suspend = 1,
  1309. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1310. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
  1311. },
  1312. {
  1313. .name = "Voice Stub",
  1314. .stream_name = "Voice Stub",
  1315. .cpu_dai_name = "VOICE_STUB",
  1316. .platform_name = "msm-pcm-hostless",
  1317. .dynamic = 1,
  1318. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1319. SND_SOC_DPCM_TRIGGER_POST},
  1320. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1321. .ignore_suspend = 1,
  1322. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1323. .codec_dai_name = "snd-soc-dummy-dai",
  1324. .codec_name = "snd-soc-dummy",
  1325. },
  1326. /* HDMI Hostless */
  1327. {
  1328. .name = "HDMI_RX_HOSTLESS",
  1329. .stream_name = "HDMI_RX_HOSTLESS",
  1330. .cpu_dai_name = "HDMI_HOSTLESS",
  1331. .platform_name = "msm-pcm-hostless",
  1332. .dynamic = 1,
  1333. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1334. SND_SOC_DPCM_TRIGGER_POST},
  1335. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1336. .ignore_suspend = 1,
  1337. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1338. .codec_dai_name = "snd-soc-dummy-dai",
  1339. .codec_name = "snd-soc-dummy",
  1340. },
  1341. /* MI2S TX Hostless */
  1342. {
  1343. .name = "MI2S_TX Hostless",
  1344. .stream_name = "MI2S_TX Hostless",
  1345. .cpu_dai_name = "MI2S_TX_HOSTLESS",
  1346. .platform_name = "msm-pcm-hostless",
  1347. .dynamic = 1,
  1348. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1349. SND_SOC_DPCM_TRIGGER_POST},
  1350. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1351. .ignore_suspend = 1,
  1352. .codec_dai_name = "snd-soc-dummy-dai",
  1353. .codec_name = "snd-soc-dummy",
  1354. },
  1355. /* Secondary I2S RX Hostless */
  1356. {
  1357. .name = "SEC_I2S_RX Hostless",
  1358. .stream_name = "SEC_I2S_RX Hostless",
  1359. .cpu_dai_name = "SEC_I2S_RX_HOSTLESS",
  1360. .platform_name = "msm-pcm-hostless",
  1361. .dynamic = 1,
  1362. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1363. SND_SOC_DPCM_TRIGGER_POST},
  1364. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1365. .ignore_suspend = 1,
  1366. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1367. .codec_dai_name = "snd-soc-dummy-dai",
  1368. .codec_name = "snd-soc-dummy",
  1369. },
  1370. {
  1371. .name = "MSM8960 Media5",
  1372. .stream_name = "MultiMedia5",
  1373. .cpu_dai_name = "MultiMedia5",
  1374. .platform_name = "msm-multi-ch-pcm-dsp",
  1375. .dynamic = 1,
  1376. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1377. SND_SOC_DPCM_TRIGGER_POST},
  1378. .codec_dai_name = "snd-soc-dummy-dai",
  1379. .codec_name = "snd-soc-dummy",
  1380. .ignore_suspend = 1,
  1381. .ignore_pmdown_time = 1, /* this dailink has playback support */
  1382. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5
  1383. },
  1384. {
  1385. .name = "MSM8960 Media6",
  1386. .stream_name = "MultiMedia6",
  1387. .cpu_dai_name = "MultiMedia6",
  1388. .platform_name = "msm-multi-ch-pcm-dsp",
  1389. .dynamic = 1,
  1390. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1391. SND_SOC_DPCM_TRIGGER_POST},
  1392. .codec_dai_name = "snd-soc-dummy-dai",
  1393. .codec_name = "snd-soc-dummy",
  1394. .ignore_suspend = 1,
  1395. .ignore_pmdown_time = 1, /* this dailink has playback support */
  1396. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
  1397. },
  1398. {
  1399. .name = "MSM8960 Compr2",
  1400. .stream_name = "COMPR2",
  1401. .cpu_dai_name = "MultiMedia7",
  1402. .platform_name = "msm-compr-dsp",
  1403. .dynamic = 1,
  1404. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1405. SND_SOC_DPCM_TRIGGER_POST},
  1406. .codec_dai_name = "snd-soc-dummy-dai",
  1407. .codec_name = "snd-soc-dummy",
  1408. .ignore_suspend = 1,
  1409. .ignore_pmdown_time = 1, /* this dailink has playback support */
  1410. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
  1411. },
  1412. {
  1413. .name = "MSM8960 Compr3",
  1414. .stream_name = "COMPR3",
  1415. .cpu_dai_name = "MultiMedia8",
  1416. .platform_name = "msm-compr-dsp",
  1417. .dynamic = 1,
  1418. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1419. SND_SOC_DPCM_TRIGGER_POST},
  1420. .codec_dai_name = "snd-soc-dummy-dai",
  1421. .codec_name = "snd-soc-dummy",
  1422. .ignore_suspend = 1,
  1423. .ignore_pmdown_time = 1, /* this dailink has playback support */
  1424. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
  1425. },
  1426. {
  1427. .name = "AUXPCM Hostless",
  1428. .stream_name = "AUXPCM Hostless",
  1429. .cpu_dai_name = "AUXPCM_HOSTLESS",
  1430. .platform_name = "msm-pcm-hostless",
  1431. .dynamic = 1,
  1432. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1433. SND_SOC_DPCM_TRIGGER_POST},
  1434. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1435. .ignore_suspend = 1,
  1436. .ignore_pmdown_time = 1, /* dainlink has playback support */
  1437. .codec_dai_name = "snd-soc-dummy-dai",
  1438. .codec_name = "snd-soc-dummy",
  1439. },
  1440. {
  1441. .name = "MSM8960 Pseudo",
  1442. .stream_name = "Pseudo",
  1443. .cpu_dai_name = "Pseudo",
  1444. .dynamic = 1,
  1445. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1446. SND_SOC_DPCM_TRIGGER_POST},
  1447. .codec_dai_name = "snd-soc-dummy-dai",
  1448. .codec_name = "snd-soc-dummy",
  1449. .ignore_suspend = 1,
  1450. .ignore_pmdown_time = 1,
  1451. .be_id = MSM_FRONTEND_DAI_PSEUDO,
  1452. },
  1453. /* Backend DAI Links */
  1454. {
  1455. .name = LPASS_BE_SLIMBUS_0_RX,
  1456. .stream_name = "Slimbus Playback",
  1457. .cpu_dai_name = "msm-dai-q6.16384",
  1458. .platform_name = "msm-pcm-routing",
  1459. .codec_name = "tabla_codec",
  1460. .codec_dai_name = "tabla_rx1",
  1461. .no_pcm = 1,
  1462. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
  1463. .init = &msm_audrx_init,
  1464. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1465. .ops = &msm_be_ops,
  1466. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1467. },
  1468. {
  1469. .name = LPASS_BE_SLIMBUS_0_TX,
  1470. .stream_name = "Slimbus Capture",
  1471. .cpu_dai_name = "msm-dai-q6.16385",
  1472. .platform_name = "msm-pcm-routing",
  1473. .codec_name = "tabla_codec",
  1474. .codec_dai_name = "tabla_tx1",
  1475. .no_pcm = 1,
  1476. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
  1477. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1478. .ops = &msm_be_ops,
  1479. },
  1480. {
  1481. .name = LPASS_BE_SEC_I2S_RX,
  1482. .stream_name = "Secondary I2S Playback",
  1483. .cpu_dai_name = "msm-dai-q6.4",
  1484. .platform_name = "msm-pcm-routing",
  1485. .codec_name = "cs8427-spdif.5-0014",
  1486. .codec_dai_name = "spdif_rx",
  1487. .no_pcm = 1,
  1488. .be_id = MSM_BACKEND_DAI_SEC_I2S_RX,
  1489. .be_hw_params_fixup = msm_be_i2s_hw_params_fixup,
  1490. .ops = &mpq8064_sec_i2s_rx_be_ops,
  1491. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1492. },
  1493. {
  1494. .name = LPASS_BE_INT_FM_RX,
  1495. .stream_name = "Internal FM Playback",
  1496. .cpu_dai_name = "msm-dai-q6.12292",
  1497. .platform_name = "msm-pcm-routing",
  1498. .codec_name = "msm-stub-codec.1",
  1499. .codec_dai_name = "msm-stub-rx",
  1500. .no_pcm = 1,
  1501. .be_id = MSM_BACKEND_DAI_INT_FM_RX,
  1502. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1503. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1504. },
  1505. {
  1506. .name = LPASS_BE_INT_FM_TX,
  1507. .stream_name = "Internal FM Capture",
  1508. .cpu_dai_name = "msm-dai-q6.12293",
  1509. .platform_name = "msm-pcm-routing",
  1510. .codec_name = "msm-stub-codec.1",
  1511. .codec_dai_name = "msm-stub-tx",
  1512. .no_pcm = 1,
  1513. .be_id = MSM_BACKEND_DAI_INT_FM_TX,
  1514. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1515. },
  1516. /* HDMI BACK END DAI Link */
  1517. {
  1518. .name = LPASS_BE_HDMI,
  1519. .stream_name = "HDMI Playback",
  1520. .cpu_dai_name = "msm-dai-q6-hdmi.8",
  1521. .platform_name = "msm-pcm-routing",
  1522. .codec_name = "msm-stub-codec.1",
  1523. .codec_dai_name = "msm-stub-rx",
  1524. .no_pcm = 1,
  1525. .be_id = MSM_BACKEND_DAI_HDMI_RX,
  1526. .be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
  1527. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1528. },
  1529. {
  1530. .name = LPASS_BE_MI2S_TX,
  1531. .stream_name = "MI2S Capture",
  1532. .cpu_dai_name = "msm-dai-q6-mi2s",
  1533. .platform_name = "msm-pcm-routing",
  1534. .codec_name = "msm-stub-codec.1",
  1535. .codec_dai_name = "msm-stub-tx",
  1536. .no_pcm = 1,
  1537. .be_id = MSM_BACKEND_DAI_MI2S_TX,
  1538. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1539. .ops = &msm_mi2s_tx_be_ops,
  1540. },
  1541. /* Backend AFE DAI Links */
  1542. {
  1543. .name = LPASS_BE_AFE_PCM_RX,
  1544. .stream_name = "AFE Playback",
  1545. .cpu_dai_name = "msm-dai-q6.224",
  1546. .platform_name = "msm-pcm-routing",
  1547. .codec_name = "msm-stub-codec.1",
  1548. .codec_dai_name = "msm-stub-rx",
  1549. .no_pcm = 1,
  1550. .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
  1551. .be_hw_params_fixup = mpq8064_proxy_be_params_fixup,
  1552. .ignore_pmdown_time = 1, /* this dainlink has playback support */
  1553. },
  1554. {
  1555. .name = LPASS_BE_AFE_PCM_TX,
  1556. .stream_name = "AFE Capture",
  1557. .cpu_dai_name = "msm-dai-q6.225",
  1558. .platform_name = "msm-pcm-routing",
  1559. .codec_name = "msm-stub-codec.1",
  1560. .codec_dai_name = "msm-stub-tx",
  1561. .no_pcm = 1,
  1562. .be_hw_params_fixup = mpq8064_proxy_be_params_fixup,
  1563. .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
  1564. },
  1565. /* AUX PCM Backend DAI Links */
  1566. {
  1567. .name = LPASS_BE_AUXPCM_RX,
  1568. .stream_name = "AUX PCM Playback",
  1569. .cpu_dai_name = "msm-dai-q6.2",
  1570. .platform_name = "msm-pcm-routing",
  1571. .codec_name = "msm-stub-codec.1",
  1572. .codec_dai_name = "msm-stub-rx",
  1573. .no_pcm = 1,
  1574. .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
  1575. .be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
  1576. .ops = &mpq8064_auxpcm_be_ops,
  1577. .ignore_pmdown_time = 1,
  1578. },
  1579. {
  1580. .name = LPASS_BE_AUXPCM_TX,
  1581. .stream_name = "AUX PCM Capture",
  1582. .cpu_dai_name = "msm-dai-q6.3",
  1583. .platform_name = "msm-pcm-routing",
  1584. .codec_name = "msm-stub-codec.1",
  1585. .codec_dai_name = "msm-stub-tx",
  1586. .no_pcm = 1,
  1587. .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
  1588. .be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
  1589. },
  1590. {
  1591. .name = LPASS_BE_PSEUDO,
  1592. .stream_name = "PSEUDO Playback",
  1593. .cpu_dai_name = "msm-dai-q6.32769",
  1594. .platform_name = "msm-pcm-routing",
  1595. .codec_name = "snd-soc-dummy",
  1596. .codec_dai_name = "snd-soc-dummy-dai",
  1597. .no_pcm = 1,
  1598. .be_id = MSM_BACKEND_DAI_PSEUDO_PORT,
  1599. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1600. .ignore_pmdown_time = 1,
  1601. },
  1602. };
  1603. static struct snd_soc_card snd_soc_card_msm = {
  1604. .name = "mpq8064-tabla-snd-card",
  1605. .dai_link = msm_dai,
  1606. .num_links = ARRAY_SIZE(msm_dai),
  1607. .controls = tabla_msm_controls,
  1608. .num_controls = ARRAY_SIZE(tabla_msm_controls),
  1609. };
  1610. static struct platform_device *msm_snd_device;
  1611. static int __init msm_audio_init(void)
  1612. {
  1613. int ret;
  1614. if (socinfo_get_id() != 130) {
  1615. pr_err("%s: Not the right machine type\n", __func__);
  1616. return -ENODEV;
  1617. }
  1618. if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
  1619. bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(16);
  1620. if (machine_is_mpq8064_dtv())
  1621. detect_dtv_platform = 1;
  1622. pr_info("MPQ8064: detect_dtv_platform is %d\n", detect_dtv_platform);
  1623. mbhc_cfg.calibration = def_tabla_mbhc_cal();
  1624. if (!mbhc_cfg.calibration) {
  1625. pr_err("Calibration data allocation failed\n");
  1626. return -ENOMEM;
  1627. }
  1628. msm_snd_device = platform_device_alloc("soc-audio", 0);
  1629. if (!msm_snd_device) {
  1630. pr_err("Platform device allocation failed\n");
  1631. kfree(mbhc_cfg.calibration);
  1632. return -ENOMEM;
  1633. }
  1634. platform_set_drvdata(msm_snd_device, &snd_soc_card_msm);
  1635. ret = platform_device_add(msm_snd_device);
  1636. if (ret) {
  1637. platform_device_put(msm_snd_device);
  1638. kfree(mbhc_cfg.calibration);
  1639. return ret;
  1640. }
  1641. configure_sec_i2s_rx_gpio();
  1642. configure_mi2s_gpio();
  1643. return ret;
  1644. }
  1645. module_init(msm_audio_init);
  1646. static void __exit msm_audio_exit(void)
  1647. {
  1648. if (socinfo_get_id() != 130) {
  1649. pr_err("%s: Not the right machine type\n", __func__);
  1650. return ;
  1651. }
  1652. mpq8064_sec_i2s_rx_free_gpios();
  1653. msm_mi2s_free_gpios();
  1654. platform_device_unregister(msm_snd_device);
  1655. kfree(mbhc_cfg.calibration);
  1656. }
  1657. module_exit(msm_audio_exit);
  1658. MODULE_DESCRIPTION("ALSA SoC mpq8064");
  1659. MODULE_LICENSE("GPL v2");