mdm9615.c 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442
  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/pm8018.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/slab.h>
  18. #include <linux/io.h>
  19. #include <linux/mfd/wcd9xxx/core.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 <asm/mach-types.h>
  26. #include <mach/socinfo.h>
  27. #include "msm-pcm-routing.h"
  28. #include "../codecs/wcd9310.h"
  29. #include <mach/gpiomux.h>
  30. /* 9615 machine driver */
  31. #define PM8018_GPIO_BASE NR_GPIO_IRQS
  32. #define PM8018_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8018_GPIO_BASE)
  33. #define MDM9615_SPK_ON 1
  34. #define MDM9615_SPK_OFF 0
  35. #define MDM9615_SLIM_0_RX_MAX_CHANNELS 2
  36. #define MDM9615_SLIM_0_TX_MAX_CHANNELS 4
  37. #define SAMPLE_RATE_8KHZ 8000
  38. #define SAMPLE_RATE_16KHZ 16000
  39. #define TOP_AND_BOTTOM_SPK_AMP_POS 0x1
  40. #define TOP_AND_BOTTOM_SPK_AMP_NEG 0x2
  41. #define GPIO_AUX_PCM_DOUT 23
  42. #define GPIO_AUX_PCM_DIN 22
  43. #define GPIO_AUX_PCM_SYNC 21
  44. #define GPIO_AUX_PCM_CLK 20
  45. #define GPIO_SEC_AUX_PCM_DOUT 28
  46. #define GPIO_SEC_AUX_PCM_DIN 27
  47. #define GPIO_SEC_AUX_PCM_SYNC 26
  48. #define GPIO_SEC_AUX_PCM_CLK 25
  49. #define TABLA_EXT_CLK_RATE 12288000
  50. #define TABLA_MBHC_DEF_BUTTONS 8
  51. #define TABLA_MBHC_DEF_RLOADS 5
  52. #define PM8018_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
  53. #define JACK_DETECT_GPIO 3
  54. #define JACK_DETECT_INT PM8018_GPIO_IRQ(PM8018_IRQ_BASE, JACK_DETECT_GPIO)
  55. /*
  56. * Added for I2S
  57. */
  58. #define GPIO_SPKR_I2S_MCLK 24
  59. #define GPIO_PRIM_I2S_SCK 20
  60. #define GPIO_PRIM_I2S_DOUT 23
  61. #define GPIO_PRIM_I2S_WS 21
  62. #define GPIO_PRIM_I2S_DIN 22
  63. #define GPIO_SEC_I2S_SCK 25
  64. #define GPIO_SEC_I2S_WS 26
  65. #define GPIO_SEC_I2S_DOUT 28
  66. #define GPIO_SEC_I2S_DIN 27
  67. static struct gpiomux_setting cdc_i2s_mclk = {
  68. .func = GPIOMUX_FUNC_1,
  69. .drv = GPIOMUX_DRV_8MA,
  70. .pull = GPIOMUX_PULL_NONE,
  71. };
  72. static struct gpiomux_setting cdc_i2s_sclk = {
  73. .func = GPIOMUX_FUNC_1,
  74. .drv = GPIOMUX_DRV_8MA,
  75. .pull = GPIOMUX_PULL_NONE,
  76. };
  77. static struct gpiomux_setting audio_sec_i2s[] = {
  78. /* Suspend state */
  79. {
  80. .func = GPIOMUX_FUNC_GPIO,
  81. .drv = GPIOMUX_DRV_2MA,
  82. .pull = GPIOMUX_PULL_DOWN,
  83. },
  84. /* Active state */
  85. {
  86. .func = GPIOMUX_FUNC_2,
  87. .drv = GPIOMUX_DRV_8MA,
  88. .pull = GPIOMUX_PULL_NONE,
  89. }
  90. };
  91. static struct gpiomux_setting cdc_i2s_dout = {
  92. .func = GPIOMUX_FUNC_1,
  93. .drv = GPIOMUX_DRV_8MA,
  94. .pull = GPIOMUX_PULL_NONE,
  95. };
  96. static struct gpiomux_setting cdc_i2s_ws = {
  97. .func = GPIOMUX_FUNC_1,
  98. .drv = GPIOMUX_DRV_8MA,
  99. .pull = GPIOMUX_PULL_NONE,
  100. };
  101. static struct gpiomux_setting cdc_i2s_din = {
  102. .func = GPIOMUX_FUNC_1,
  103. .drv = GPIOMUX_DRV_8MA,
  104. .pull = GPIOMUX_PULL_NONE,
  105. };
  106. static struct msm_gpiomux_config msm9615_audio_prim_i2s_codec_configs[] = {
  107. {
  108. .gpio = GPIO_SPKR_I2S_MCLK,
  109. .settings = {
  110. [GPIOMUX_SUSPENDED] = &cdc_i2s_mclk,
  111. },
  112. },
  113. {
  114. .gpio = GPIO_PRIM_I2S_SCK,
  115. .settings = {
  116. [GPIOMUX_SUSPENDED] = &cdc_i2s_sclk,
  117. },
  118. },
  119. {
  120. .gpio = GPIO_PRIM_I2S_DOUT,
  121. .settings = {
  122. [GPIOMUX_SUSPENDED] = &cdc_i2s_dout,
  123. },
  124. },
  125. {
  126. .gpio = GPIO_PRIM_I2S_WS,
  127. .settings = {
  128. [GPIOMUX_SUSPENDED] = &cdc_i2s_ws,
  129. },
  130. },
  131. {
  132. .gpio = GPIO_PRIM_I2S_DIN,
  133. .settings = {
  134. [GPIOMUX_SUSPENDED] = &cdc_i2s_din,
  135. },
  136. },
  137. };
  138. static struct msm_gpiomux_config msm9615_audio_sec_i2s_codec_configs[] = {
  139. {
  140. .gpio = GPIO_SPKR_I2S_MCLK,
  141. .settings = {
  142. [GPIOMUX_SUSPENDED] = &cdc_i2s_mclk,
  143. },
  144. },
  145. {
  146. .gpio = GPIO_SEC_I2S_SCK,
  147. .settings = {
  148. [GPIOMUX_SUSPENDED] = &audio_sec_i2s[0],
  149. [GPIOMUX_ACTIVE] = &audio_sec_i2s[1],
  150. },
  151. },
  152. {
  153. .gpio = GPIO_SEC_I2S_DOUT,
  154. .settings = {
  155. [GPIOMUX_SUSPENDED] = &audio_sec_i2s[0],
  156. [GPIOMUX_ACTIVE] = &audio_sec_i2s[1],
  157. },
  158. },
  159. {
  160. .gpio = GPIO_SEC_I2S_WS,
  161. .settings = {
  162. [GPIOMUX_SUSPENDED] = &audio_sec_i2s[0],
  163. [GPIOMUX_ACTIVE] = &audio_sec_i2s[1],
  164. },
  165. },
  166. {
  167. .gpio = GPIO_SEC_I2S_DIN,
  168. .settings = {
  169. [GPIOMUX_SUSPENDED] = &audio_sec_i2s[0],
  170. [GPIOMUX_ACTIVE] = &audio_sec_i2s[1],
  171. },
  172. },
  173. };
  174. /* Physical address for LPA CSR
  175. * LPA SIF mux registers. These are
  176. * ioremap( ) for Virtual address.
  177. */
  178. #define LPASS_CSR_BASE 0x28000000
  179. #define LPA_IF_BASE 0x28100000
  180. #define SIF_MUX_REG_BASE (LPASS_CSR_BASE + 0x00000000)
  181. #define LPA_IF_REG_BASE (LPA_IF_BASE + 0x00000000)
  182. #define LPASS_SIF_MUX_ADDR (SIF_MUX_REG_BASE + 0x00004000)
  183. #define LPAIF_SPARE_ADDR (LPA_IF_REG_BASE + 0x00000070)
  184. #define SEC_PCM_PORT_SLC_ADDR 0x00802074
  185. /* bits 2:0 should be updated with 100 to select SDC2 */
  186. #define SEC_PCM_PORT_SLC_VALUE 0x4
  187. /* SIF & SPARE MUX Values */
  188. #define MSM_SIF_FUNC_PCM 0
  189. #define MSM_SIF_FUNC_I2S_MIC 1
  190. #define MSM_SIF_FUNC_I2S_SPKR 2
  191. #define MSM_LPAIF_SPARE_DISABLE 0x0
  192. #define MSM_LPAIF_SPARE_BOTH_ENABLE 0x3
  193. /* I2S INTF CTL */
  194. #define MSM_INTF_PRIM 0
  195. #define MSM_INTF_SECN 1
  196. #define MSM_INTF_BOTH 2
  197. /* I2S Dir CTL */
  198. #define MSM_DIR_RX 0
  199. #define MSM_DIR_TX 1
  200. #define MSM_DIR_BOTH 2
  201. #define MSM_DIR_MAX 3
  202. /* I2S HW Params */
  203. #define NO_OF_BITS_PER_SAMPLE 16
  204. #define I2S_MIC_SCLK_RATE 1536000
  205. static int msm9615_i2s_rx_ch = 1;
  206. static int msm9615_i2s_tx_ch = 1;
  207. static int msm9615_i2s_spk_control;
  208. /* SIF mux bit mask & shift */
  209. #define LPASS_SIF_MUX_CTL_PRI_MUX_SEL_BMSK 0x30000
  210. #define LPASS_SIF_MUX_CTL_PRI_MUX_SEL_SHFT 0x10
  211. #define LPASS_SIF_MUX_CTL_SEC_MUX_SEL_BMSK 0x3
  212. #define LPASS_SIF_MUX_CTL_SEC_MUX_SEL_SHFT 0x0
  213. #define LPAIF_SPARE_MUX_CTL_SEC_MUX_SEL_BMSK 0x3
  214. #define LPAIF_SPARE_MUX_CTL_SEC_MUX_SEL_SHFT 0x2
  215. #define LPAIF_SPARE_MUX_CTL_PRI_MUX_SEL_BMSK 0x3
  216. #define LPAIF_SPARE_MUX_CTL_PRI_MUX_SEL_SHFT 0x0
  217. static atomic_t msm9615_auxpcm_ref;
  218. static atomic_t msm9615_sec_auxpcm_ref;
  219. struct msm_i2s_mux_ctl {
  220. const u8 sifconfig;
  221. const u8 spareconfig;
  222. };
  223. struct msm_clk {
  224. struct clk *osr_clk;
  225. struct clk *bit_clk;
  226. int clk_enable;
  227. };
  228. struct msm_i2s_clk {
  229. struct msm_clk rx_clk;
  230. struct msm_clk tx_clk;
  231. };
  232. struct msm_i2s_ctl {
  233. struct msm_i2s_clk prim_clk;
  234. struct msm_i2s_clk sec_clk;
  235. struct msm_i2s_mux_ctl mux_ctl[MSM_DIR_MAX];
  236. u8 intf_status[MSM_INTF_BOTH][MSM_DIR_BOTH];
  237. void *sif_virt_addr;
  238. void *spare_virt_addr;
  239. };
  240. static struct msm_i2s_ctl msm9x15_i2s_ctl = {
  241. {{NULL, NULL, 0}, {NULL, NULL, 0} }, /* prim_clk */
  242. {{NULL, NULL, 0}, {NULL, NULL, 0} }, /* sec_clk */
  243. /* mux_ctl */
  244. {
  245. /* Rx path only */
  246. { MSM_SIF_FUNC_I2S_SPKR, MSM_LPAIF_SPARE_DISABLE },
  247. /* Tx path only */
  248. { MSM_SIF_FUNC_I2S_MIC, MSM_LPAIF_SPARE_DISABLE },
  249. /* Rx + Tx path only */
  250. { MSM_SIF_FUNC_I2S_SPKR, MSM_LPAIF_SPARE_BOTH_ENABLE },
  251. },
  252. /* intf_status */
  253. {
  254. /* Prim I2S */
  255. {0, 0},
  256. /* Sec I2S */
  257. {0, 0}
  258. },
  259. /* sif_virt_addr */
  260. NULL,
  261. /* spare_virt_addr */
  262. NULL,
  263. };
  264. enum msm9x15_set_i2s_clk {
  265. MSM_I2S_CLK_SET_FALSE,
  266. MSM_I2S_CLK_SET_TRUE,
  267. MSM_I2S_CLK_SET_RATE0,
  268. };
  269. /*
  270. * Added for I2S
  271. */
  272. static u32 top_and_bottom_spk_pamp_gpio = PM8018_GPIO_PM_TO_SYS(5);
  273. void *sif_virt_addr;
  274. void *secpcm_portslc_virt_addr;
  275. static int mdm9615_spk_control;
  276. static int mdm9615_ext_top_and_bottom_spk_pamp;
  277. static int mdm9615_slim_0_rx_ch = 1;
  278. static int mdm9615_slim_0_tx_ch = 1;
  279. static int mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
  280. static int mdm9615_btsco_ch = 1;
  281. static int mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
  282. static struct clk *codec_clk;
  283. static int clk_users;
  284. static struct snd_soc_jack hs_jack;
  285. static struct snd_soc_jack button_jack;
  286. static struct platform_device *mdm9615_snd_device_slim;
  287. static struct platform_device *mdm9615_snd_device_i2s;
  288. static u32 sif_reg_value = 0x0000;
  289. static u32 spare_reg_value = 0x0000;
  290. static bool hs_detect_use_gpio;
  291. module_param(hs_detect_use_gpio, bool, 0444);
  292. MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
  293. static bool hs_detect_use_firmware;
  294. module_param(hs_detect_use_firmware, bool, 0444);
  295. MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
  296. static int mdm9615_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  297. bool dapm);
  298. static struct tabla_mbhc_config mbhc_cfg = {
  299. .headset_jack = &hs_jack,
  300. .button_jack = &button_jack,
  301. .read_fw_bin = false,
  302. .calibration = NULL,
  303. .micbias = TABLA_MICBIAS2,
  304. .mclk_cb_fn = mdm9615_enable_codec_ext_clk,
  305. .mclk_rate = TABLA_EXT_CLK_RATE,
  306. .gpio = 0,
  307. .gpio_irq = 0,
  308. .gpio_level_insert = 1,
  309. };
  310. static void mdm9615_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
  311. {
  312. int ret = 0;
  313. struct pm_gpio param = {
  314. .direction = PM_GPIO_DIR_OUT,
  315. .output_buffer = PM_GPIO_OUT_BUF_CMOS,
  316. .output_value = 1,
  317. .pull = PM_GPIO_PULL_NO,
  318. .vin_sel = PM_GPIO_VIN_S4,
  319. .out_strength = PM_GPIO_STRENGTH_MED,
  320. .function = PM_GPIO_FUNC_NORMAL,
  321. };
  322. if (spk_amp_gpio == top_and_bottom_spk_pamp_gpio) {
  323. ret = gpio_request(top_and_bottom_spk_pamp_gpio,
  324. "TOP_AND_BOTTOM_SPK_AMP");
  325. if (ret) {
  326. pr_err("%s: Error requesting TOP AND BOTTOM SPK AMP GPIO %u\n",
  327. __func__, top_and_bottom_spk_pamp_gpio);
  328. return;
  329. }
  330. ret = pm8xxx_gpio_config(top_and_bottom_spk_pamp_gpio, &param);
  331. if (ret)
  332. pr_err("%s: Failed to configure Top & Bottom Spk Ampl\n"
  333. "gpio %u\n", __func__,
  334. top_and_bottom_spk_pamp_gpio);
  335. else {
  336. pr_debug("%s: enable Top & Bottom spkr amp gpio\n",
  337. __func__);
  338. gpio_direction_output(top_and_bottom_spk_pamp_gpio, 1);
  339. }
  340. } else {
  341. pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
  342. " gpio = %u\n", __func__, spk_amp_gpio);
  343. return;
  344. }
  345. }
  346. static void mdm9615_ext_spk_power_amp_on(u32 spk)
  347. {
  348. if (spk & (TOP_AND_BOTTOM_SPK_AMP_POS | TOP_AND_BOTTOM_SPK_AMP_NEG)) {
  349. if ((mdm9615_ext_top_and_bottom_spk_pamp &
  350. TOP_AND_BOTTOM_SPK_AMP_POS) &&
  351. (mdm9615_ext_top_and_bottom_spk_pamp &
  352. TOP_AND_BOTTOM_SPK_AMP_NEG)) {
  353. pr_debug("%s() External Speaker Ampl already "
  354. "turned on. spk = 0x%08x\n", __func__, spk);
  355. return;
  356. }
  357. mdm9615_ext_top_and_bottom_spk_pamp |= spk;
  358. if ((mdm9615_ext_top_and_bottom_spk_pamp &
  359. TOP_AND_BOTTOM_SPK_AMP_POS) &&
  360. (mdm9615_ext_top_and_bottom_spk_pamp &
  361. TOP_AND_BOTTOM_SPK_AMP_NEG)) {
  362. mdm9615_enable_ext_spk_amp_gpio(
  363. top_and_bottom_spk_pamp_gpio);
  364. pr_debug("%s: slepping 4 ms after turning on external\n"
  365. "Speaker Ampl\n", __func__);
  366. usleep_range(4000, 4000);
  367. }
  368. } else {
  369. pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
  370. __func__, spk);
  371. return;
  372. }
  373. }
  374. static void mdm9615_ext_spk_power_amp_off(u32 spk)
  375. {
  376. if (spk & (TOP_AND_BOTTOM_SPK_AMP_POS | TOP_AND_BOTTOM_SPK_AMP_NEG)) {
  377. if (!mdm9615_ext_top_and_bottom_spk_pamp)
  378. return;
  379. gpio_direction_output(top_and_bottom_spk_pamp_gpio, 0);
  380. gpio_free(top_and_bottom_spk_pamp_gpio);
  381. mdm9615_ext_top_and_bottom_spk_pamp = 0;
  382. pr_debug("%s: sleeping 4 ms after turning off external Bottom"
  383. " Speaker Ampl\n", __func__);
  384. usleep_range(4000, 4000);
  385. } else {
  386. pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
  387. __func__, spk);
  388. return;
  389. }
  390. }
  391. static void mdm9615_ext_control(struct snd_soc_codec *codec)
  392. {
  393. struct snd_soc_dapm_context *dapm = &codec->dapm;
  394. pr_debug("%s: mdm9615_spk_control = %d", __func__, mdm9615_spk_control);
  395. if (mdm9615_spk_control == MDM9615_SPK_ON) {
  396. snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
  397. snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
  398. } else {
  399. snd_soc_dapm_disable_pin(dapm, "Ext Spk Pos");
  400. snd_soc_dapm_disable_pin(dapm, "Ext Spk Neg");
  401. }
  402. snd_soc_dapm_sync(dapm);
  403. }
  404. static int mdm9615_get_spk(struct snd_kcontrol *kcontrol,
  405. struct snd_ctl_elem_value *ucontrol)
  406. {
  407. pr_debug("%s: mdm9615_spk_control = %d", __func__, mdm9615_spk_control);
  408. ucontrol->value.integer.value[0] = mdm9615_spk_control;
  409. return 0;
  410. }
  411. static int mdm9615_set_spk(struct snd_kcontrol *kcontrol,
  412. struct snd_ctl_elem_value *ucontrol)
  413. {
  414. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  415. pr_debug("%s()\n", __func__);
  416. if (mdm9615_spk_control == ucontrol->value.integer.value[0])
  417. return 0;
  418. mdm9615_spk_control = ucontrol->value.integer.value[0];
  419. mdm9615_ext_control(codec);
  420. return 1;
  421. }
  422. static int mdm9615_spkramp_event(struct snd_soc_dapm_widget *w,
  423. struct snd_kcontrol *k, int event)
  424. {
  425. pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
  426. if (SND_SOC_DAPM_EVENT_ON(event)) {
  427. if (!strncmp(w->name, "Ext Spk Pos", 11))
  428. mdm9615_ext_spk_power_amp_on(
  429. TOP_AND_BOTTOM_SPK_AMP_POS);
  430. else if (!strncmp(w->name, "Ext Spk Neg", 11))
  431. mdm9615_ext_spk_power_amp_on(
  432. TOP_AND_BOTTOM_SPK_AMP_NEG);
  433. else {
  434. pr_err("%s() Invalid Speaker Widget = %s\n",
  435. __func__, w->name);
  436. return -EINVAL;
  437. }
  438. } else {
  439. if (!strncmp(w->name, "Ext Spk Pos", 11))
  440. mdm9615_ext_spk_power_amp_off(
  441. TOP_AND_BOTTOM_SPK_AMP_POS);
  442. else if (!strncmp(w->name, "Ext Spk Neg", 11))
  443. mdm9615_ext_spk_power_amp_off(
  444. TOP_AND_BOTTOM_SPK_AMP_NEG);
  445. else {
  446. pr_err("%s() Invalid Speaker Widget = %s\n",
  447. __func__, w->name);
  448. return -EINVAL;
  449. }
  450. }
  451. return 0;
  452. }
  453. static int mdm9615_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  454. bool dapm)
  455. {
  456. pr_debug("%s: enable = %d\n", __func__, enable);
  457. if (enable) {
  458. clk_users++;
  459. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  460. if (clk_users != 1)
  461. return 0;
  462. if (IS_ERR(codec_clk)) {
  463. pr_err("%s: Error setting Tabla MCLK\n", __func__);
  464. clk_users--;
  465. return -EINVAL;
  466. }
  467. clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
  468. clk_prepare_enable(codec_clk);
  469. tabla_mclk_enable(codec, 1, dapm);
  470. } else {
  471. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  472. if (clk_users == 0)
  473. return 0;
  474. clk_users--;
  475. if (!clk_users) {
  476. pr_debug("%s: disabling MCLK. clk_users = %d\n",
  477. __func__, clk_users);
  478. tabla_mclk_enable(codec, 0, dapm);
  479. clk_disable_unprepare(codec_clk);
  480. }
  481. }
  482. return 0;
  483. }
  484. static int mdm9615_mclk_event(struct snd_soc_dapm_widget *w,
  485. struct snd_kcontrol *kcontrol, int event)
  486. {
  487. pr_debug("%s: event = %d\n", __func__, event);
  488. switch (event) {
  489. case SND_SOC_DAPM_PRE_PMU:
  490. return mdm9615_enable_codec_ext_clk(w->codec, 1, true);
  491. case SND_SOC_DAPM_POST_PMD:
  492. return mdm9615_enable_codec_ext_clk(w->codec, 0, true);
  493. }
  494. return 0;
  495. }
  496. static const struct snd_soc_dapm_widget mdm9615_dapm_widgets[] = {
  497. SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
  498. mdm9615_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  499. SND_SOC_DAPM_SPK("Ext Spk Pos", mdm9615_spkramp_event),
  500. SND_SOC_DAPM_SPK("Ext Spk Neg", mdm9615_spkramp_event),
  501. SND_SOC_DAPM_MIC("Handset Mic", NULL),
  502. SND_SOC_DAPM_MIC("Headset Mic", NULL),
  503. SND_SOC_DAPM_MIC("Digital Mic1", NULL),
  504. SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
  505. SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
  506. SND_SOC_DAPM_MIC("Digital Mic1", NULL),
  507. SND_SOC_DAPM_MIC("Digital Mic2", NULL),
  508. SND_SOC_DAPM_MIC("Digital Mic3", NULL),
  509. SND_SOC_DAPM_MIC("Digital Mic4", NULL),
  510. SND_SOC_DAPM_MIC("Digital Mic5", NULL),
  511. SND_SOC_DAPM_MIC("Digital Mic6", NULL),
  512. };
  513. static const struct snd_soc_dapm_route common_audio_map[] = {
  514. {"RX_BIAS", NULL, "MCLK"},
  515. {"LDO_H", NULL, "MCLK"},
  516. /* Speaker path */
  517. {"Ext Spk Pos", NULL, "LINEOUT1"},
  518. {"Ext Spk Neg", NULL, "LINEOUT3"},
  519. {"Ext Spk Pos", NULL, "LINEOUT2"},
  520. {"Ext Spk Neg", NULL, "LINEOUT4"},
  521. /* Microphone path */
  522. {"AMIC1", NULL, "MIC BIAS1 External"},
  523. {"MIC BIAS1 External", NULL, "Handset Mic"},
  524. {"AMIC2", NULL, "MIC BIAS2 External"},
  525. {"MIC BIAS2 External", NULL, "Headset Mic"},
  526. /**
  527. * AMIC3 and AMIC4 inputs are connected to ANC microphones
  528. * These mics are biased differently on CDP and FLUID
  529. * routing entries below are based on bias arrangement
  530. * on FLUID.
  531. */
  532. {"AMIC3", NULL, "MIC BIAS3 Internal1"},
  533. {"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
  534. {"AMIC4", NULL, "MIC BIAS1 Internal2"},
  535. {"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
  536. {"HEADPHONE", NULL, "LDO_H"},
  537. /**
  538. * The digital Mic routes are setup considering
  539. * fluid as default device.
  540. */
  541. /**
  542. * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
  543. * Digital Mic GM5 on CDP mainboard.
  544. * Conncted to DMIC2 Input on Tabla codec.
  545. */
  546. {"DMIC2", NULL, "MIC BIAS1 External"},
  547. {"MIC BIAS1 External", NULL, "Digital Mic1"},
  548. /**
  549. * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
  550. * Digital Mic GM6 on CDP mainboard.
  551. * Conncted to DMIC1 Input on Tabla codec.
  552. */
  553. {"DMIC1", NULL, "MIC BIAS1 External"},
  554. {"MIC BIAS1 External", NULL, "Digital Mic2"},
  555. /**
  556. * Digital Mic3. Back Bottom Digital Mic on Fluid.
  557. * Digital Mic GM1 on CDP mainboard.
  558. * Conncted to DMIC4 Input on Tabla codec.
  559. */
  560. {"DMIC4", NULL, "MIC BIAS3 External"},
  561. {"MIC BIAS3 External", NULL, "Digital Mic3"},
  562. /**
  563. * Digital Mic4. Back top Digital Mic on Fluid.
  564. * Digital Mic GM2 on CDP mainboard.
  565. * Conncted to DMIC3 Input on Tabla codec.
  566. */
  567. {"DMIC3", NULL, "MIC BIAS3 External"},
  568. {"MIC BIAS3 External", NULL, "Digital Mic4"},
  569. /**
  570. * Digital Mic5. Front top Digital Mic on Fluid.
  571. * Digital Mic GM3 on CDP mainboard.
  572. * Conncted to DMIC5 Input on Tabla codec.
  573. */
  574. {"DMIC5", NULL, "MIC BIAS4 External"},
  575. {"MIC BIAS4 External", NULL, "Digital Mic5"},
  576. /* Tabla digital Mic6 - back bottom digital Mic on Liquid and
  577. * bottom mic on CDP. FLUID/MTP do not have dmic6 installed.
  578. */
  579. {"DMIC6", NULL, "MIC BIAS4 External"},
  580. {"MIC BIAS4 External", NULL, "Digital Mic6"},
  581. };
  582. static const char *spk_function[] = {"Off", "On"};
  583. static const char *slim0_rx_ch_text[] = {"One", "Two"};
  584. static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
  585. static const struct soc_enum mdm9615_enum[] = {
  586. SOC_ENUM_SINGLE_EXT(2, spk_function),
  587. SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
  588. SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
  589. };
  590. static const char *btsco_rate_text[] = {"8000", "16000"};
  591. static const struct soc_enum mdm9615_btsco_enum[] = {
  592. SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
  593. };
  594. static const char * const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
  595. static const struct soc_enum mdm9615_auxpcm_enum[] = {
  596. SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
  597. };
  598. static int mdm9615_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
  599. struct snd_ctl_elem_value *ucontrol)
  600. {
  601. pr_debug("%s: mdm9615_slim_0_rx_ch = %d\n", __func__,
  602. mdm9615_slim_0_rx_ch);
  603. ucontrol->value.integer.value[0] = mdm9615_slim_0_rx_ch - 1;
  604. return 0;
  605. }
  606. static int mdm9615_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
  607. struct snd_ctl_elem_value *ucontrol)
  608. {
  609. mdm9615_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
  610. pr_debug("%s: mdm9615_slim_0_rx_ch = %d\n", __func__,
  611. mdm9615_slim_0_rx_ch);
  612. return 1;
  613. }
  614. static int mdm9615_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
  615. struct snd_ctl_elem_value *ucontrol)
  616. {
  617. pr_debug("%s: mdm9615_slim_0_tx_ch = %d\n", __func__,
  618. mdm9615_slim_0_tx_ch);
  619. ucontrol->value.integer.value[0] = mdm9615_slim_0_tx_ch - 1;
  620. return 0;
  621. }
  622. static int mdm9615_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
  623. struct snd_ctl_elem_value *ucontrol)
  624. {
  625. mdm9615_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
  626. pr_debug("%s: mdm9615_slim_0_tx_ch = %d\n", __func__,
  627. mdm9615_slim_0_tx_ch);
  628. return 1;
  629. }
  630. static int mdm9615_btsco_rate_get(struct snd_kcontrol *kcontrol,
  631. struct snd_ctl_elem_value *ucontrol)
  632. {
  633. pr_debug("%s: mdm9615_btsco_rate = %d", __func__, mdm9615_btsco_rate);
  634. ucontrol->value.integer.value[0] = mdm9615_btsco_rate;
  635. return 0;
  636. }
  637. static int mdm9615_btsco_rate_put(struct snd_kcontrol *kcontrol,
  638. struct snd_ctl_elem_value *ucontrol)
  639. {
  640. switch (ucontrol->value.integer.value[0]) {
  641. case 8000:
  642. mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
  643. break;
  644. case 16000:
  645. mdm9615_btsco_rate = SAMPLE_RATE_16KHZ;
  646. break;
  647. default:
  648. mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
  649. break;
  650. }
  651. pr_debug("%s: mdm9615_btsco_rate = %d\n", __func__, mdm9615_btsco_rate);
  652. return 0;
  653. }
  654. static int mdm9615_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
  655. struct snd_ctl_elem_value *ucontrol)
  656. {
  657. pr_debug("%s: mdm9615_auxpcm_rate = %d", __func__,
  658. mdm9615_auxpcm_rate);
  659. ucontrol->value.integer.value[0] = mdm9615_auxpcm_rate;
  660. return 0;
  661. }
  662. static int mdm9615_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
  663. struct snd_ctl_elem_value *ucontrol)
  664. {
  665. switch (ucontrol->value.integer.value[0]) {
  666. case 0:
  667. mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
  668. break;
  669. case 1:
  670. mdm9615_auxpcm_rate = SAMPLE_RATE_16KHZ;
  671. break;
  672. default:
  673. mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
  674. break;
  675. }
  676. pr_debug("%s: mdm9615_auxpcm_rate = %d\n"
  677. "ucontrol->value.integer.value[0] = %d\n", __func__,
  678. mdm9615_auxpcm_rate,
  679. (int)ucontrol->value.integer.value[0]);
  680. return 0;
  681. }
  682. static const struct snd_kcontrol_new tabla_mdm9615_controls[] = {
  683. SOC_ENUM_EXT("Speaker Function", mdm9615_enum[0], mdm9615_get_spk,
  684. mdm9615_set_spk),
  685. SOC_ENUM_EXT("SLIM_0_RX Channels", mdm9615_enum[1],
  686. mdm9615_slim_0_rx_ch_get, mdm9615_slim_0_rx_ch_put),
  687. SOC_ENUM_EXT("SLIM_0_TX Channels", mdm9615_enum[2],
  688. mdm9615_slim_0_tx_ch_get, mdm9615_slim_0_tx_ch_put),
  689. SOC_ENUM_EXT("Internal BTSCO SampleRate", mdm9615_btsco_enum[0],
  690. mdm9615_btsco_rate_get, mdm9615_btsco_rate_put),
  691. SOC_ENUM_EXT("AUX PCM SampleRate", mdm9615_auxpcm_enum[0],
  692. mdm9615_auxpcm_rate_get, mdm9615_auxpcm_rate_put),
  693. };
  694. static void *def_tabla_mbhc_cal(void)
  695. {
  696. void *tabla_cal;
  697. struct tabla_mbhc_btn_detect_cfg *btn_cfg;
  698. u16 *btn_low, *btn_high;
  699. u8 *n_ready, *n_cic, *gain;
  700. tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
  701. TABLA_MBHC_DEF_RLOADS),
  702. GFP_KERNEL);
  703. if (!tabla_cal) {
  704. pr_err("%s: out of memory\n", __func__);
  705. return NULL;
  706. }
  707. #define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
  708. S(t_ldoh, 100);
  709. S(t_bg_fast_settle, 100);
  710. S(t_shutdown_plug_rem, 255);
  711. S(mbhc_nsa, 4);
  712. S(mbhc_navg, 4);
  713. #undef S
  714. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
  715. S(mic_current, TABLA_PID_MIC_5_UA);
  716. S(hph_current, TABLA_PID_MIC_5_UA);
  717. S(t_mic_pid, 100);
  718. S(t_ins_complete, 250);
  719. S(t_ins_retry, 200);
  720. #undef S
  721. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
  722. S(v_no_mic, 30);
  723. S(v_hs_max, 1550);
  724. #undef S
  725. #define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
  726. S(c[0], 62);
  727. S(c[1], 124);
  728. S(nc, 1);
  729. S(n_meas, 3);
  730. S(mbhc_nsc, 11);
  731. S(n_btn_meas, 1);
  732. S(n_btn_con, 2);
  733. S(num_btn, TABLA_MBHC_DEF_BUTTONS);
  734. S(v_btn_press_delta_sta, 100);
  735. S(v_btn_press_delta_cic, 50);
  736. #undef S
  737. btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
  738. btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
  739. btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
  740. btn_low[0] = -50;
  741. btn_high[0] = 10;
  742. btn_low[1] = 11;
  743. btn_high[1] = 38;
  744. btn_low[2] = 39;
  745. btn_high[2] = 64;
  746. btn_low[3] = 65;
  747. btn_high[3] = 91;
  748. btn_low[4] = 92;
  749. btn_high[4] = 115;
  750. btn_low[5] = 116;
  751. btn_high[5] = 141;
  752. btn_low[6] = 142;
  753. btn_high[6] = 163;
  754. btn_low[7] = 164;
  755. btn_high[7] = 250;
  756. n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
  757. n_ready[0] = 48;
  758. n_ready[1] = 38;
  759. n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
  760. n_cic[0] = 60;
  761. n_cic[1] = 47;
  762. gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
  763. gain[0] = 11;
  764. gain[1] = 9;
  765. return tabla_cal;
  766. }
  767. static int msm9615_i2s_set_spk(struct snd_kcontrol *kcontrol,
  768. struct snd_ctl_elem_value *ucontrol)
  769. {
  770. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  771. pr_debug("%s()\n", __func__);
  772. if (msm9615_i2s_spk_control == ucontrol->value.integer.value[0])
  773. return 0;
  774. msm9615_i2s_spk_control = ucontrol->value.integer.value[0];
  775. mdm9615_ext_control(codec);
  776. return 1;
  777. }
  778. static int mdm9615_hw_params(struct snd_pcm_substream *substream,
  779. struct snd_pcm_hw_params *params)
  780. {
  781. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  782. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  783. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  784. int ret = 0;
  785. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  786. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  787. pr_debug("%s: ch=%d\n", __func__,
  788. mdm9615_slim_0_rx_ch);
  789. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  790. ret = snd_soc_dai_get_channel_map(codec_dai,
  791. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  792. if (ret < 0) {
  793. pr_err("%s: failed to get codec chan map\n", __func__);
  794. goto end;
  795. }
  796. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  797. mdm9615_slim_0_rx_ch, rx_ch);
  798. if (ret < 0) {
  799. pr_err("%s: failed to set cpu chan map\n", __func__);
  800. goto end;
  801. }
  802. } else {
  803. ret = snd_soc_dai_get_channel_map(codec_dai,
  804. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  805. if (ret < 0) {
  806. pr_err("%s: failed to get codec chan map\n", __func__);
  807. goto end;
  808. }
  809. ret = snd_soc_dai_set_channel_map(cpu_dai,
  810. mdm9615_slim_0_tx_ch, tx_ch, 0 , 0);
  811. if (ret < 0) {
  812. pr_err("%s: failed to set cpu chan map\n", __func__);
  813. goto end;
  814. }
  815. }
  816. end:
  817. return ret;
  818. }
  819. static int msm9615_i2s_rx_ch_get(struct snd_kcontrol *kcontrol,
  820. struct snd_ctl_elem_value *ucontrol)
  821. {
  822. pr_debug("%s: msm9615_i2s_rx_ch = %d\n", __func__,
  823. msm9615_i2s_rx_ch);
  824. ucontrol->value.integer.value[0] = msm9615_i2s_rx_ch - 1;
  825. return 0;
  826. }
  827. static int msm9615_i2s_rx_ch_put(struct snd_kcontrol *kcontrol,
  828. struct snd_ctl_elem_value *ucontrol)
  829. {
  830. msm9615_i2s_rx_ch = ucontrol->value.integer.value[0] + 1;
  831. pr_debug("%s: msm9615_i2s_rx_ch = %d\n", __func__,
  832. msm9615_i2s_rx_ch);
  833. return 1;
  834. }
  835. static int msm9615_i2s_tx_ch_get(struct snd_kcontrol *kcontrol,
  836. struct snd_ctl_elem_value *ucontrol)
  837. {
  838. pr_debug("%s: msm9615_i2s_tx_ch = %d\n", __func__,
  839. msm9615_i2s_tx_ch);
  840. ucontrol->value.integer.value[0] = msm9615_i2s_tx_ch - 1;
  841. return 0;
  842. }
  843. static int msm9615_i2s_tx_ch_put(struct snd_kcontrol *kcontrol,
  844. struct snd_ctl_elem_value *ucontrol)
  845. {
  846. msm9615_i2s_tx_ch = ucontrol->value.integer.value[0] + 1;
  847. pr_debug("%s: msm9615_i2s_tx_ch = %d\n", __func__,
  848. msm9615_i2s_tx_ch);
  849. return 1;
  850. }
  851. static int msm9615_i2s_get_spk(struct snd_kcontrol *kcontrol,
  852. struct snd_ctl_elem_value *ucontrol)
  853. {
  854. pr_debug("%s: msm9615_spk_control = %d", __func__, mdm9615_spk_control);
  855. ucontrol->value.integer.value[0] = msm9615_i2s_spk_control;
  856. return 0;
  857. }
  858. static const struct snd_kcontrol_new tabla_msm9615_i2s_controls[] = {
  859. SOC_ENUM_EXT("Speaker Function", mdm9615_enum[0], msm9615_i2s_get_spk,
  860. msm9615_i2s_set_spk),
  861. SOC_ENUM_EXT("PRI_RX Channels", mdm9615_enum[1],
  862. msm9615_i2s_rx_ch_get, msm9615_i2s_rx_ch_put),
  863. SOC_ENUM_EXT("PRI_TX Channels", mdm9615_enum[2],
  864. msm9615_i2s_tx_ch_get, msm9615_i2s_tx_ch_put),
  865. SOC_ENUM_EXT("SEC_RX Channels", mdm9615_enum[3],
  866. msm9615_i2s_rx_ch_get, msm9615_i2s_rx_ch_put),
  867. SOC_ENUM_EXT("SEC_TX Channels", mdm9615_enum[4],
  868. msm9615_i2s_tx_ch_get, msm9615_i2s_tx_ch_put),
  869. };
  870. static int msm9615_i2s_audrx_init(struct snd_soc_pcm_runtime *rtd)
  871. {
  872. int err;
  873. struct snd_soc_codec *codec = rtd->codec;
  874. struct snd_soc_dapm_context *dapm = &codec->dapm;
  875. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  876. snd_soc_dapm_new_controls(dapm, mdm9615_dapm_widgets,
  877. ARRAY_SIZE(mdm9615_dapm_widgets));
  878. snd_soc_dapm_add_routes(dapm, common_audio_map,
  879. ARRAY_SIZE(common_audio_map));
  880. snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
  881. snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
  882. snd_soc_dapm_sync(dapm);
  883. err = snd_soc_jack_new(codec, "Headset Jack",
  884. (SND_JACK_HEADSET | SND_JACK_OC_HPHL|
  885. SND_JACK_OC_HPHR), &hs_jack);
  886. if (err) {
  887. pr_err("failed to create new jack\n");
  888. return err;
  889. }
  890. err = snd_soc_jack_new(codec, "Button Jack",
  891. TABLA_JACK_BUTTON_MASK, &button_jack);
  892. if (err) {
  893. pr_err("failed to create new jack\n");
  894. return err;
  895. }
  896. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  897. err = tabla_hs_detect(codec, &mbhc_cfg);
  898. msm_gpiomux_install(
  899. msm9615_audio_prim_i2s_codec_configs,
  900. ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
  901. return err;
  902. }
  903. static int msm9615_i2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  904. struct snd_pcm_hw_params *params)
  905. {
  906. struct snd_interval *rate = hw_param_interval(params,
  907. SNDRV_PCM_HW_PARAM_RATE);
  908. struct snd_interval *channels = hw_param_interval(params,
  909. SNDRV_PCM_HW_PARAM_CHANNELS);
  910. rate->min = rate->max = 48000;
  911. channels->min = channels->max = msm9615_i2s_rx_ch;
  912. return 0;
  913. }
  914. static int msm9615_i2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  915. struct snd_pcm_hw_params *params)
  916. {
  917. struct snd_interval *rate = hw_param_interval(params,
  918. SNDRV_PCM_HW_PARAM_RATE);
  919. struct snd_interval *channels = hw_param_interval(params,
  920. SNDRV_PCM_HW_PARAM_CHANNELS);
  921. rate->min = rate->max = 48000;
  922. channels->min = channels->max = msm9615_i2s_tx_ch;
  923. return 0;
  924. }
  925. static int mdm9615_i2s_free_gpios(u8 i2s_intf, u8 i2s_dir)
  926. {
  927. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  928. if (i2s_intf == MSM_INTF_PRIM) {
  929. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] == 0 &&
  930. pintf->intf_status[i2s_intf][MSM_DIR_RX] == 0) {
  931. gpio_free(GPIO_PRIM_I2S_DIN);
  932. gpio_free(GPIO_PRIM_I2S_DOUT);
  933. gpio_free(GPIO_PRIM_I2S_SCK);
  934. gpio_free(GPIO_PRIM_I2S_WS);
  935. }
  936. } else if (i2s_intf == MSM_INTF_SECN) {
  937. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] == 0 &&
  938. pintf->intf_status[i2s_intf][MSM_DIR_RX] == 0) {
  939. gpio_free(GPIO_SEC_I2S_DOUT);
  940. gpio_free(GPIO_SEC_I2S_WS);
  941. gpio_free(GPIO_SEC_I2S_DIN);
  942. gpio_free(GPIO_SEC_I2S_SCK);
  943. }
  944. }
  945. return 0;
  946. }
  947. static int msm9615_i2s_intf_dir_sel(const char *cpu_dai_name,
  948. u8 *i2s_intf, u8 *i2s_dir)
  949. {
  950. int ret = 0;
  951. if (i2s_intf == NULL || i2s_dir == NULL || cpu_dai_name == NULL) {
  952. ret = 1;
  953. goto err;
  954. }
  955. if (!strncmp(cpu_dai_name, "msm-dai-q6.0", 12)) {
  956. *i2s_intf = MSM_INTF_PRIM;
  957. *i2s_dir = MSM_DIR_RX;
  958. } else if (!strncmp(cpu_dai_name, "msm-dai-q6.1", 12)) {
  959. *i2s_intf = MSM_INTF_PRIM;
  960. *i2s_dir = MSM_DIR_TX;
  961. } else if (!strncmp(cpu_dai_name, "msm-dai-q6.4", 12)) {
  962. *i2s_intf = MSM_INTF_SECN;
  963. *i2s_dir = MSM_DIR_RX;
  964. } else if (!strncmp(cpu_dai_name, "msm-dai-q6.5", 12)) {
  965. *i2s_intf = MSM_INTF_SECN;
  966. *i2s_dir = MSM_DIR_TX;
  967. } else {
  968. pr_err("Error in I2S cpu dai name\n");
  969. ret = 1;
  970. }
  971. err:
  972. return ret;
  973. }
  974. static int msm9615_enable_i2s_gpio(u8 i2s_intf, u8 i2s_dir)
  975. {
  976. u8 ret = 0;
  977. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  978. if (i2s_intf == MSM_INTF_PRIM) {
  979. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] == 0 &&
  980. pintf->intf_status[i2s_intf][MSM_DIR_RX] == 0) {
  981. ret = gpio_request(GPIO_PRIM_I2S_DOUT,
  982. "I2S_PRIM_DOUT");
  983. if (ret) {
  984. pr_err("%s: Failed to request gpio %d\n",
  985. __func__, GPIO_PRIM_I2S_DOUT);
  986. goto err;
  987. }
  988. ret = gpio_request(GPIO_PRIM_I2S_DIN, "I2S_PRIM_DIN");
  989. if (ret) {
  990. pr_err("%s: Failed to request gpio %d\n",
  991. __func__, GPIO_PRIM_I2S_DIN);
  992. goto err;
  993. }
  994. ret = gpio_request(GPIO_PRIM_I2S_SCK, "I2S_PRIM_SCK");
  995. if (ret) {
  996. pr_err("%s: Failed to request gpio %d\n",
  997. __func__, GPIO_PRIM_I2S_SCK);
  998. goto err;
  999. }
  1000. ret = gpio_request(GPIO_PRIM_I2S_WS, "I2S_PRIM_WS");
  1001. if (ret) {
  1002. pr_err("%s: Failed to request gpio %d\n",
  1003. __func__, GPIO_PRIM_I2S_WS);
  1004. goto err;
  1005. }
  1006. }
  1007. } else if (i2s_intf == MSM_INTF_SECN) {
  1008. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] == 0 &&
  1009. pintf->intf_status[i2s_intf][MSM_DIR_RX] == 0) {
  1010. ret = gpio_request(GPIO_SEC_I2S_DIN, "I2S_SEC_DIN");
  1011. if (ret) {
  1012. pr_err("%s: Failed to request gpio %d\n",
  1013. __func__, GPIO_SEC_I2S_DIN);
  1014. goto err;
  1015. }
  1016. ret = gpio_request(GPIO_SEC_I2S_DOUT, "I2S_SEC_DOUT");
  1017. if (ret) {
  1018. pr_err("%s: Failed to request gpio %d\n",
  1019. __func__, GPIO_SEC_I2S_DOUT);
  1020. goto err;
  1021. }
  1022. ret = gpio_request(GPIO_SEC_I2S_SCK, "I2S_SEC_SCK");
  1023. if (ret) {
  1024. pr_err("%s: Failed to request gpio %d\n",
  1025. __func__, GPIO_SEC_I2S_SCK);
  1026. goto err;
  1027. }
  1028. ret = gpio_request(GPIO_SEC_I2S_WS, "I2S_SEC_WS");
  1029. if (ret) {
  1030. pr_err("%s: Failed to request gpio %d\n",
  1031. __func__, GPIO_SEC_I2S_WS);
  1032. goto err;
  1033. }
  1034. }
  1035. }
  1036. err:
  1037. return ret;
  1038. }
  1039. static int msm9615_set_i2s_osr_bit_clk(struct snd_soc_dai *cpu_dai,
  1040. u8 i2s_intf, u8 i2s_dir,
  1041. enum msm9x15_set_i2s_clk enable)
  1042. {
  1043. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1044. struct msm_i2s_clk *pclk = &pintf->prim_clk;
  1045. struct msm_clk *clk_ctl = &pclk->rx_clk;
  1046. u8 ret = 0;
  1047. pr_debug("Dev name %s Intf =%d, Dir = %d, Enable=%d\n",
  1048. cpu_dai->name, i2s_intf, i2s_dir, enable);
  1049. if (i2s_intf == MSM_INTF_PRIM)
  1050. pclk = &pintf->prim_clk;
  1051. else if (i2s_intf == MSM_INTF_SECN)
  1052. pclk = &pintf->sec_clk;
  1053. if (i2s_dir == MSM_DIR_TX)
  1054. clk_ctl = &pclk->tx_clk;
  1055. else if (i2s_dir == MSM_DIR_RX)
  1056. clk_ctl = &pclk->rx_clk;
  1057. if (enable == MSM_I2S_CLK_SET_TRUE ||
  1058. enable == MSM_I2S_CLK_SET_RATE0) {
  1059. if (clk_ctl->clk_enable != 0) {
  1060. pr_info("%s: I2S Clk is already enabled"
  1061. "clk users %d\n", __func__,
  1062. clk_ctl->clk_enable);
  1063. ret = 0;
  1064. goto err;
  1065. }
  1066. clk_ctl->osr_clk = clk_get(cpu_dai->dev, "osr_clk");
  1067. if (IS_ERR(clk_ctl->osr_clk)) {
  1068. pr_err("%s: Fail to get OSR CLK\n", __func__);
  1069. ret = -EINVAL;
  1070. goto err;
  1071. }
  1072. ret = clk_prepare(clk_ctl->osr_clk);
  1073. if (ret != 0) {
  1074. pr_err("Unable to prepare i2s_spkr_osr_clk\n");
  1075. goto err;
  1076. }
  1077. clk_set_rate(clk_ctl->osr_clk, TABLA_EXT_CLK_RATE);
  1078. ret = clk_enable(clk_ctl->osr_clk);
  1079. if (ret != 0) {
  1080. pr_err("Fail to enable i2s_spkr_osr_clk\n");
  1081. clk_unprepare(clk_ctl->osr_clk);
  1082. goto err;
  1083. }
  1084. clk_ctl->bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  1085. if (IS_ERR(clk_ctl->bit_clk)) {
  1086. pr_err("Fail to get i2s_spkr_bit_clk\n");
  1087. clk_disable(clk_ctl->osr_clk);
  1088. clk_unprepare(clk_ctl->osr_clk);
  1089. clk_put(clk_ctl->osr_clk);
  1090. ret = -EINVAL;
  1091. goto err;
  1092. }
  1093. ret = clk_prepare(clk_ctl->bit_clk);
  1094. if (ret != 0) {
  1095. clk_disable(clk_ctl->osr_clk);
  1096. clk_unprepare(clk_ctl->osr_clk);
  1097. clk_put(clk_ctl->osr_clk);
  1098. pr_err("Fail to prepare i2s_spkr_osr_clk\n");
  1099. goto err;
  1100. }
  1101. if (enable == MSM_I2S_CLK_SET_RATE0)
  1102. clk_set_rate(clk_ctl->bit_clk, 0);
  1103. else
  1104. clk_set_rate(clk_ctl->bit_clk, 8);
  1105. ret = clk_enable(clk_ctl->bit_clk);
  1106. if (ret != 0) {
  1107. clk_disable(clk_ctl->osr_clk);
  1108. clk_unprepare(clk_ctl->osr_clk);
  1109. clk_put(clk_ctl->osr_clk);
  1110. clk_unprepare(clk_ctl->bit_clk);
  1111. pr_err("Unable to enable i2s_spkr_osr_clk\n");
  1112. goto err;
  1113. }
  1114. clk_ctl->clk_enable++;
  1115. } else if (enable == MSM_I2S_CLK_SET_FALSE &&
  1116. clk_ctl->clk_enable != 0) {
  1117. clk_disable(clk_ctl->osr_clk);
  1118. clk_disable(clk_ctl->bit_clk);
  1119. clk_unprepare(clk_ctl->osr_clk);
  1120. clk_unprepare(clk_ctl->bit_clk);
  1121. clk_put(clk_ctl->bit_clk);
  1122. clk_put(clk_ctl->osr_clk);
  1123. clk_ctl->bit_clk = NULL;
  1124. clk_ctl->osr_clk = NULL;
  1125. clk_ctl->clk_enable--;
  1126. ret = 0;
  1127. }
  1128. err:
  1129. return ret;
  1130. }
  1131. static void msm9615_config_i2s_sif_mux(u8 value, u8 i2s_intf)
  1132. {
  1133. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1134. u32 sif_shadow = 0x0000;
  1135. pr_debug("%s() Value = 0x%x intf = 0x%x\n", __func__, value, i2s_intf);
  1136. if (i2s_intf == MSM_INTF_PRIM) {
  1137. sif_shadow = (sif_shadow & LPASS_SIF_MUX_CTL_PRI_MUX_SEL_BMSK) |
  1138. (value << LPASS_SIF_MUX_CTL_PRI_MUX_SEL_SHFT);
  1139. pr_debug("%s() Sif shadow = 0x%x\n", __func__, sif_shadow);
  1140. sif_reg_value =
  1141. ((sif_reg_value & LPASS_SIF_MUX_CTL_SEC_MUX_SEL_BMSK) |
  1142. sif_shadow);
  1143. }
  1144. if (i2s_intf == MSM_INTF_SECN) {
  1145. sif_shadow = (sif_shadow & LPASS_SIF_MUX_CTL_SEC_MUX_SEL_BMSK) |
  1146. (value << LPASS_SIF_MUX_CTL_SEC_MUX_SEL_SHFT);
  1147. pr_debug("%s() Sif shadow = 0x%x\n", __func__, sif_shadow);
  1148. sif_reg_value =
  1149. ((sif_reg_value & LPASS_SIF_MUX_CTL_PRI_MUX_SEL_BMSK) |
  1150. sif_shadow);
  1151. }
  1152. if (pintf->sif_virt_addr != NULL)
  1153. iowrite32(sif_reg_value, pintf->sif_virt_addr);
  1154. /* Dont read SIF register. Device crashes. */
  1155. pr_debug("%s() SIF Reg = 0x%x\n", __func__, sif_reg_value);
  1156. }
  1157. static void msm9615_config_i2s_spare_mux(u8 value, u8 i2s_intf)
  1158. {
  1159. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1160. u32 spare_shadow = 0x0000;
  1161. pr_debug("%s() Value = 0x%x intf = 0x%x\n", __func__, value, i2s_intf);
  1162. if (i2s_intf == MSM_INTF_PRIM) {
  1163. /* Configure Primary SIF */
  1164. spare_shadow =
  1165. (spare_shadow & LPAIF_SPARE_MUX_CTL_PRI_MUX_SEL_BMSK) |
  1166. (value << LPAIF_SPARE_MUX_CTL_PRI_MUX_SEL_SHFT);
  1167. pr_debug("%s() Spare shadow = 0x%x\n", __func__, spare_shadow);
  1168. spare_reg_value =
  1169. ((spare_shadow & LPAIF_SPARE_MUX_CTL_SEC_MUX_SEL_BMSK) |
  1170. spare_shadow);
  1171. }
  1172. if (i2s_intf == MSM_INTF_SECN) {
  1173. /*Secondary interface configuration*/
  1174. spare_shadow =
  1175. (spare_shadow & LPAIF_SPARE_MUX_CTL_SEC_MUX_SEL_BMSK) |
  1176. (value << LPAIF_SPARE_MUX_CTL_SEC_MUX_SEL_SHFT);
  1177. pr_debug("%s() Spare shadow = 0x%x\n", __func__, spare_shadow);
  1178. spare_reg_value =
  1179. ((spare_shadow & LPAIF_SPARE_MUX_CTL_PRI_MUX_SEL_BMSK) |
  1180. spare_shadow);
  1181. }
  1182. if (pintf->spare_virt_addr != NULL)
  1183. iowrite32(spare_reg_value, pintf->spare_virt_addr);
  1184. /* Dont read SPARE register. Device crashes. */
  1185. pr_debug("%s( ): SPARE Reg =0x%x\n", __func__, spare_reg_value);
  1186. }
  1187. static int msm9615_i2s_hw_params(struct snd_pcm_substream *substream,
  1188. struct snd_pcm_hw_params *params)
  1189. {
  1190. int rate = params_rate(params);
  1191. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1192. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1193. struct msm_i2s_clk *pclk = &pintf->prim_clk;
  1194. struct msm_clk *clk_ctl = &pclk->rx_clk;
  1195. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1196. int bit_clk_set = 0;
  1197. u8 i2s_intf, i2s_dir;
  1198. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1199. if (!msm9615_i2s_intf_dir_sel(cpu_dai->name,
  1200. &i2s_intf, &i2s_dir)) {
  1201. bit_clk_set = TABLA_EXT_CLK_RATE /
  1202. (rate * 2 * NO_OF_BITS_PER_SAMPLE);
  1203. if (bit_clk_set != 8) {
  1204. if (i2s_intf == MSM_INTF_PRIM)
  1205. pclk = &pintf->prim_clk;
  1206. else if (i2s_intf == MSM_INTF_SECN)
  1207. pclk = &pintf->sec_clk;
  1208. clk_ctl = &pclk->rx_clk;
  1209. pr_debug("%s( ): New rate = %d",
  1210. __func__, bit_clk_set);
  1211. clk_set_rate(clk_ctl->bit_clk, bit_clk_set);
  1212. }
  1213. }
  1214. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  1215. bit_clk_set = I2S_MIC_SCLK_RATE / (rate * 2 *
  1216. NO_OF_BITS_PER_SAMPLE);
  1217. /* Not required to modify TX rate.
  1218. * Speaker clock are looped back
  1219. * to Mic.
  1220. */
  1221. }
  1222. return 1;
  1223. }
  1224. static int msm9615_i2s_startup(struct snd_pcm_substream *substream)
  1225. {
  1226. u8 ret = 0;
  1227. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1228. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1229. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1230. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1231. u8 i2s_intf, i2s_dir;
  1232. if (!msm9615_i2s_intf_dir_sel(cpu_dai->name, &i2s_intf, &i2s_dir)) {
  1233. pr_debug("%s( ): cpu name = %s intf =%d dir = %d\n",
  1234. __func__, cpu_dai->name, i2s_intf, i2s_dir);
  1235. pr_debug("%s( ): Enable status Rx =%d Tx = %d\n", __func__,
  1236. pintf->intf_status[i2s_intf][MSM_DIR_RX],
  1237. pintf->intf_status[i2s_intf][MSM_DIR_TX]);
  1238. msm9615_enable_i2s_gpio(i2s_intf, i2s_dir);
  1239. if (i2s_dir == MSM_DIR_TX) {
  1240. if (pintf->intf_status[i2s_intf][MSM_DIR_RX] > 0) {
  1241. /* This means that Rx is enabled before */
  1242. ret = msm9615_set_i2s_osr_bit_clk(cpu_dai,
  1243. i2s_intf, i2s_dir,
  1244. MSM_I2S_CLK_SET_RATE0);
  1245. if (ret != 0) {
  1246. pr_err("%s: Fail enable I2S clock\n",
  1247. __func__);
  1248. return -EINVAL;
  1249. }
  1250. msm9615_config_i2s_sif_mux(
  1251. pintf->mux_ctl[MSM_DIR_BOTH].sifconfig,
  1252. i2s_intf);
  1253. msm9615_config_i2s_spare_mux(
  1254. pintf->mux_ctl[MSM_DIR_BOTH].spareconfig,
  1255. i2s_intf);
  1256. ret = snd_soc_dai_set_fmt(cpu_dai,
  1257. SND_SOC_DAIFMT_CBM_CFM);
  1258. if (ret < 0)
  1259. pr_err("set fmt cpu dai failed\n");
  1260. ret = snd_soc_dai_set_fmt(codec_dai,
  1261. SND_SOC_DAIFMT_CBS_CFS);
  1262. if (ret < 0)
  1263. pr_err("set fmt codec dai failed\n");
  1264. } else if (pintf->intf_status[i2s_intf][i2s_dir] == 0) {
  1265. /* This means that Rx is
  1266. * not enabled before.
  1267. * only Tx will be used.
  1268. */
  1269. ret = msm9615_set_i2s_osr_bit_clk(cpu_dai,
  1270. i2s_intf, i2s_dir,
  1271. MSM_I2S_CLK_SET_TRUE);
  1272. if (ret != 0) {
  1273. pr_err("%s: Fail Tx I2S clock\n",
  1274. __func__);
  1275. return -EINVAL;
  1276. }
  1277. msm9615_config_i2s_sif_mux(
  1278. pintf->mux_ctl[MSM_DIR_TX].sifconfig,
  1279. i2s_intf);
  1280. msm9615_config_i2s_spare_mux(
  1281. pintf->mux_ctl[MSM_DIR_TX].spareconfig,
  1282. i2s_intf);
  1283. ret = snd_soc_dai_set_fmt(cpu_dai,
  1284. SND_SOC_DAIFMT_CBS_CFS);
  1285. if (ret < 0)
  1286. pr_err("set fmt cpu dai failed\n");
  1287. ret = snd_soc_dai_set_fmt(codec_dai,
  1288. SND_SOC_DAIFMT_CBS_CFS);
  1289. if (ret < 0)
  1290. pr_err("set fmt codec dai failed\n");
  1291. }
  1292. } else if (i2s_dir == MSM_DIR_RX) {
  1293. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] > 0) {
  1294. pr_err("%s: Error shutdown Tx first\n",
  1295. __func__);
  1296. return -EINVAL;
  1297. } else if (pintf->intf_status[i2s_intf][i2s_dir]
  1298. == 0) {
  1299. ret = msm9615_set_i2s_osr_bit_clk(cpu_dai,
  1300. i2s_intf, i2s_dir,
  1301. MSM_I2S_CLK_SET_TRUE);
  1302. if (ret != 0) {
  1303. pr_err("%s: Fail Rx I2S clock\n",
  1304. __func__);
  1305. return -EINVAL;
  1306. }
  1307. msm9615_config_i2s_sif_mux(
  1308. pintf->mux_ctl[MSM_DIR_RX].sifconfig,
  1309. i2s_intf);
  1310. msm9615_config_i2s_spare_mux(
  1311. pintf->mux_ctl[MSM_DIR_RX].spareconfig,
  1312. i2s_intf);
  1313. ret = snd_soc_dai_set_fmt(cpu_dai,
  1314. SND_SOC_DAIFMT_CBS_CFS);
  1315. if (ret < 0)
  1316. pr_err("set fmt cpu dai failed\n");
  1317. ret = snd_soc_dai_set_fmt(codec_dai,
  1318. SND_SOC_DAIFMT_CBS_CFS);
  1319. if (ret < 0)
  1320. pr_err("set fmt codec dai failed\n");
  1321. }
  1322. }
  1323. pintf->intf_status[i2s_intf][i2s_dir]++;
  1324. } else {
  1325. pr_err("%s: Err in i2s_intf_dir_sel\n", __func__);
  1326. return -EINVAL;
  1327. }
  1328. pr_debug("Exit %s() Enable status Rx =%d Tx = %d\n", __func__,
  1329. pintf->intf_status[i2s_intf][MSM_DIR_RX],
  1330. pintf->intf_status[i2s_intf][MSM_DIR_TX]);
  1331. return ret;
  1332. }
  1333. static void msm9615_i2s_shutdown(struct snd_pcm_substream *substream)
  1334. {
  1335. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1336. struct msm_i2s_ctl *pintf = &msm9x15_i2s_ctl;
  1337. u8 i2s_intf = 0, i2s_dir = 0, ret = 0;
  1338. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1339. pr_debug("%s( ): Enable status Rx =%d Tx = %d\n",
  1340. __func__, pintf->intf_status[i2s_intf][MSM_DIR_RX],
  1341. pintf->intf_status[i2s_intf][MSM_DIR_TX]);
  1342. if (!msm9615_i2s_intf_dir_sel(cpu_dai->name, &i2s_intf, &i2s_dir)) {
  1343. pr_debug("%s( ): intf =%d dir = %d\n", __func__,
  1344. i2s_intf, i2s_dir);
  1345. if (i2s_dir == MSM_DIR_RX)
  1346. if (pintf->intf_status[i2s_intf][MSM_DIR_TX] > 0)
  1347. pr_err("%s: Shutdown Tx First then by RX\n",
  1348. __func__);
  1349. ret = msm9615_set_i2s_osr_bit_clk(cpu_dai, i2s_intf, i2s_dir,
  1350. MSM_I2S_CLK_SET_FALSE);
  1351. if (ret != 0)
  1352. pr_err("%s: Cannot disable I2S clock\n",
  1353. __func__);
  1354. pintf->intf_status[i2s_intf][i2s_dir]--;
  1355. mdm9615_i2s_free_gpios(i2s_intf, i2s_dir);
  1356. }
  1357. pr_debug("%s( ): Enable status Rx =%d Tx = %d\n", __func__,
  1358. pintf->intf_status[i2s_intf][MSM_DIR_RX],
  1359. pintf->intf_status[i2s_intf][MSM_DIR_TX]);
  1360. }
  1361. void msm9615_config_port_select(void)
  1362. {
  1363. iowrite32(SEC_PCM_PORT_SLC_VALUE, secpcm_portslc_virt_addr);
  1364. pr_debug("%s() port select after updating = 0x%x\n",
  1365. __func__, ioread32(secpcm_portslc_virt_addr));
  1366. }
  1367. static void mdm9615_install_codec_i2s_gpio(struct snd_pcm_substream *substream)
  1368. {
  1369. u8 i2s_intf, i2s_dir;
  1370. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1371. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1372. if (!msm9615_i2s_intf_dir_sel(cpu_dai->name, &i2s_intf, &i2s_dir)) {
  1373. pr_debug("%s( ): cpu name = %s intf =%d dir = %d\n",
  1374. __func__, cpu_dai->name, i2s_intf, i2s_dir);
  1375. if (i2s_intf == MSM_INTF_PRIM) {
  1376. msm_gpiomux_install(
  1377. msm9615_audio_prim_i2s_codec_configs,
  1378. ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
  1379. } else if (i2s_intf == MSM_INTF_SECN) {
  1380. msm_gpiomux_install(msm9615_audio_sec_i2s_codec_configs,
  1381. ARRAY_SIZE(msm9615_audio_sec_i2s_codec_configs));
  1382. msm9615_config_port_select();
  1383. }
  1384. }
  1385. }
  1386. static int msm9615_i2s_prepare(struct snd_pcm_substream *substream)
  1387. {
  1388. u8 ret = 0;
  1389. if (wcd9xxx_get_intf_type() < 0)
  1390. ret = -ENODEV;
  1391. else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
  1392. mdm9615_install_codec_i2s_gpio(substream);
  1393. return ret;
  1394. }
  1395. static struct snd_soc_ops msm9615_i2s_be_ops = {
  1396. .startup = msm9615_i2s_startup,
  1397. .shutdown = msm9615_i2s_shutdown,
  1398. .hw_params = msm9615_i2s_hw_params,
  1399. .prepare = msm9615_i2s_prepare,
  1400. };
  1401. static int mdm9615_audrx_init(struct snd_soc_pcm_runtime *rtd)
  1402. {
  1403. int err;
  1404. struct snd_soc_codec *codec = rtd->codec;
  1405. struct snd_soc_dapm_context *dapm = &codec->dapm;
  1406. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1407. struct pm_gpio jack_gpio_cfg = {
  1408. .direction = PM_GPIO_DIR_IN,
  1409. .pull = PM_GPIO_PULL_NO,
  1410. .function = PM_GPIO_FUNC_NORMAL,
  1411. .vin_sel = 2,
  1412. .inv_int_pol = 0,
  1413. };
  1414. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1415. /* Tabla SLIMBUS configuration
  1416. * RX1, RX2, RX3, RX4, RX5, RX6, RX7
  1417. * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10
  1418. */
  1419. unsigned int rx_ch[TABLA_RX_MAX] = {138, 139, 140, 141, 142, 143, 144};
  1420. unsigned int tx_ch[TABLA_TX_MAX] = {128, 129, 130, 131, 132, 133, 134,
  1421. 135, 136, 137};
  1422. pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
  1423. rtd->pmdown_time = 0;
  1424. snd_soc_dapm_new_controls(dapm, mdm9615_dapm_widgets,
  1425. ARRAY_SIZE(mdm9615_dapm_widgets));
  1426. snd_soc_dapm_add_routes(dapm, common_audio_map,
  1427. ARRAY_SIZE(common_audio_map));
  1428. snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
  1429. snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
  1430. snd_soc_dapm_sync(dapm);
  1431. err = snd_soc_jack_new(codec, "Headset Jack",
  1432. (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
  1433. SND_JACK_OC_HPHR),
  1434. &hs_jack);
  1435. if (err) {
  1436. pr_err("failed to create new jack\n");
  1437. return err;
  1438. }
  1439. err = snd_soc_jack_new(codec, "Button Jack",
  1440. TABLA_JACK_BUTTON_MASK, &button_jack);
  1441. if (err) {
  1442. pr_err("failed to create new jack\n");
  1443. return err;
  1444. }
  1445. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  1446. if (hs_detect_use_gpio) {
  1447. pr_debug("%s: GPIO Headset detection enabled\n", __func__);
  1448. mbhc_cfg.gpio = PM8018_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
  1449. mbhc_cfg.gpio_irq = JACK_DETECT_INT;
  1450. }
  1451. if (mbhc_cfg.gpio) {
  1452. err = pm8xxx_gpio_config(mbhc_cfg.gpio, &jack_gpio_cfg);
  1453. if (err) {
  1454. pr_err("%s: pm8xxx_gpio_config JACK_DETECT failed %d\n",
  1455. __func__, err);
  1456. return err;
  1457. }
  1458. }
  1459. mbhc_cfg.read_fw_bin = hs_detect_use_firmware;
  1460. err = tabla_hs_detect(codec, &mbhc_cfg);
  1461. snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
  1462. tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
  1463. return err;
  1464. }
  1465. static int mdm9615_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1466. struct snd_pcm_hw_params *params)
  1467. {
  1468. struct snd_interval *rate = hw_param_interval(params,
  1469. SNDRV_PCM_HW_PARAM_RATE);
  1470. struct snd_interval *channels = hw_param_interval(params,
  1471. SNDRV_PCM_HW_PARAM_CHANNELS);
  1472. pr_debug("%s()\n", __func__);
  1473. rate->min = rate->max = 48000;
  1474. channels->min = channels->max = mdm9615_slim_0_rx_ch;
  1475. return 0;
  1476. }
  1477. static int mdm9615_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1478. struct snd_pcm_hw_params *params)
  1479. {
  1480. struct snd_interval *rate = hw_param_interval(params,
  1481. SNDRV_PCM_HW_PARAM_RATE);
  1482. struct snd_interval *channels = hw_param_interval(params,
  1483. SNDRV_PCM_HW_PARAM_CHANNELS);
  1484. pr_debug("%s()\n", __func__);
  1485. rate->min = rate->max = 48000;
  1486. channels->min = channels->max = mdm9615_slim_0_tx_ch;
  1487. return 0;
  1488. }
  1489. static int mdm9615_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1490. struct snd_pcm_hw_params *params)
  1491. {
  1492. struct snd_interval *rate = hw_param_interval(params,
  1493. SNDRV_PCM_HW_PARAM_RATE);
  1494. struct snd_interval *channels = hw_param_interval(params,
  1495. SNDRV_PCM_HW_PARAM_CHANNELS);
  1496. rate->min = rate->max = mdm9615_btsco_rate;
  1497. channels->min = channels->max = mdm9615_btsco_ch;
  1498. return 0;
  1499. }
  1500. static int mdm9615_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1501. struct snd_pcm_hw_params *params)
  1502. {
  1503. struct snd_interval *rate = hw_param_interval(params,
  1504. SNDRV_PCM_HW_PARAM_RATE);
  1505. struct snd_interval *channels = hw_param_interval(params,
  1506. SNDRV_PCM_HW_PARAM_CHANNELS);
  1507. rate->min = rate->max = mdm9615_auxpcm_rate;
  1508. /* PCM only supports mono output */
  1509. channels->min = channels->max = 1;
  1510. return 0;
  1511. }
  1512. static int mdm9615_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1513. struct snd_pcm_hw_params *params)
  1514. {
  1515. struct snd_interval *rate = hw_param_interval(params,
  1516. SNDRV_PCM_HW_PARAM_RATE);
  1517. pr_debug("%s()\n", __func__);
  1518. rate->min = rate->max = 48000;
  1519. return 0;
  1520. }
  1521. static int mdm9615_aux_pcm_get_gpios(void)
  1522. {
  1523. int ret = 0;
  1524. pr_debug("%s\n", __func__);
  1525. ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
  1526. if (ret < 0) {
  1527. pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
  1528. __func__, GPIO_AUX_PCM_DOUT);
  1529. goto fail_dout;
  1530. }
  1531. ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
  1532. if (ret < 0) {
  1533. pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
  1534. __func__, GPIO_AUX_PCM_DIN);
  1535. goto fail_din;
  1536. }
  1537. ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
  1538. if (ret < 0) {
  1539. pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
  1540. __func__, GPIO_AUX_PCM_SYNC);
  1541. goto fail_sync;
  1542. }
  1543. ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
  1544. if (ret < 0) {
  1545. pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
  1546. __func__, GPIO_AUX_PCM_CLK);
  1547. goto fail_clk;
  1548. }
  1549. return 0;
  1550. fail_clk:
  1551. gpio_free(GPIO_AUX_PCM_SYNC);
  1552. fail_sync:
  1553. gpio_free(GPIO_AUX_PCM_DIN);
  1554. fail_din:
  1555. gpio_free(GPIO_AUX_PCM_DOUT);
  1556. fail_dout:
  1557. return ret;
  1558. }
  1559. static int mdm9615_aux_pcm_free_gpios(void)
  1560. {
  1561. gpio_free(GPIO_AUX_PCM_DIN);
  1562. gpio_free(GPIO_AUX_PCM_DOUT);
  1563. gpio_free(GPIO_AUX_PCM_SYNC);
  1564. gpio_free(GPIO_AUX_PCM_CLK);
  1565. return 0;
  1566. }
  1567. static int mdm9615_sec_aux_pcm_get_gpios(void)
  1568. {
  1569. int ret = 0;
  1570. pr_debug("%s\n", __func__);
  1571. ret = gpio_request(GPIO_SEC_AUX_PCM_DOUT, "SEC_AUX PCM DOUT");
  1572. if (ret < 0) {
  1573. pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM DOUT",
  1574. __func__, GPIO_SEC_AUX_PCM_DOUT);
  1575. goto fail_dout;
  1576. }
  1577. ret = gpio_request(GPIO_SEC_AUX_PCM_DIN, "SEC_AUX PCM DIN");
  1578. if (ret < 0) {
  1579. pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM DIN",
  1580. __func__, GPIO_SEC_AUX_PCM_DIN);
  1581. goto fail_din;
  1582. }
  1583. ret = gpio_request(GPIO_SEC_AUX_PCM_SYNC, "SEC_AUX PCM SYNC");
  1584. if (ret < 0) {
  1585. pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM SYNC",
  1586. __func__, GPIO_SEC_AUX_PCM_SYNC);
  1587. goto fail_sync;
  1588. }
  1589. ret = gpio_request(GPIO_SEC_AUX_PCM_CLK, "SEC_AUX PCM CLK");
  1590. if (ret < 0) {
  1591. pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM CLK",
  1592. __func__, GPIO_SEC_AUX_PCM_CLK);
  1593. goto fail_clk;
  1594. }
  1595. return 0;
  1596. fail_clk:
  1597. gpio_free(GPIO_SEC_AUX_PCM_SYNC);
  1598. fail_sync:
  1599. gpio_free(GPIO_SEC_AUX_PCM_DIN);
  1600. fail_din:
  1601. gpio_free(GPIO_SEC_AUX_PCM_DOUT);
  1602. fail_dout:
  1603. return ret;
  1604. }
  1605. static int mdm9615_sec_aux_pcm_free_gpios(void)
  1606. {
  1607. gpio_free(GPIO_SEC_AUX_PCM_DIN);
  1608. gpio_free(GPIO_SEC_AUX_PCM_DOUT);
  1609. gpio_free(GPIO_SEC_AUX_PCM_SYNC);
  1610. gpio_free(GPIO_SEC_AUX_PCM_CLK);
  1611. return 0;
  1612. }
  1613. static int mdm9615_startup(struct snd_pcm_substream *substream)
  1614. {
  1615. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1616. substream->name, substream->stream);
  1617. return 0;
  1618. }
  1619. void msm9615_config_sif_mux(u8 value)
  1620. {
  1621. u32 sif_shadow = 0x00000;
  1622. sif_shadow = (sif_shadow & LPASS_SIF_MUX_CTL_SEC_MUX_SEL_BMSK) |
  1623. (value << LPASS_SIF_MUX_CTL_SEC_MUX_SEL_SHFT);
  1624. iowrite32(sif_shadow, sif_virt_addr);
  1625. /* Dont read SIF register. Device crashes. */
  1626. pr_debug("%s() SIF Reg = 0x%x\n", __func__, sif_shadow);
  1627. }
  1628. static int mdm9615_auxpcm_startup(struct snd_pcm_substream *substream)
  1629. {
  1630. int ret = 0;
  1631. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1632. if (atomic_inc_return(&msm9615_auxpcm_ref) == 1) {
  1633. ret = mdm9615_aux_pcm_get_gpios();
  1634. if (ret < 0) {
  1635. pr_err("%s: Aux PCM GPIO request failed\n", __func__);
  1636. return -EINVAL;
  1637. }
  1638. }
  1639. return 0;
  1640. }
  1641. static void mdm9615_auxpcm_shutdown(struct snd_pcm_substream *substream)
  1642. {
  1643. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1644. if (atomic_dec_return(&msm9615_auxpcm_ref) == 0)
  1645. mdm9615_aux_pcm_free_gpios();
  1646. }
  1647. static int mdm9615_sec_auxpcm_startup(struct snd_pcm_substream *substream)
  1648. {
  1649. int ret = 0;
  1650. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1651. if (atomic_inc_return(&msm9615_sec_auxpcm_ref) == 1) {
  1652. ret = mdm9615_sec_aux_pcm_get_gpios();
  1653. if (ret < 0) {
  1654. pr_err("%s: SEC Aux PCM GPIO request failed\n",
  1655. __func__);
  1656. return -EINVAL;
  1657. }
  1658. msm9615_config_sif_mux(MSM_SIF_FUNC_PCM);
  1659. msm9615_config_port_select();
  1660. }
  1661. return 0;
  1662. }
  1663. static void mdm9615_sec_auxpcm_shutdown(struct snd_pcm_substream *substream)
  1664. {
  1665. pr_debug("%s(): substream = %s\n", __func__, substream->name);
  1666. if (atomic_dec_return(&msm9615_sec_auxpcm_ref) == 0)
  1667. mdm9615_sec_aux_pcm_free_gpios();
  1668. }
  1669. static void mdm9615_shutdown(struct snd_pcm_substream *substream)
  1670. {
  1671. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1672. substream->name, substream->stream);
  1673. }
  1674. static struct snd_soc_ops mdm9615_be_ops = {
  1675. .startup = mdm9615_startup,
  1676. .hw_params = mdm9615_hw_params,
  1677. .shutdown = mdm9615_shutdown,
  1678. };
  1679. static struct snd_soc_ops mdm9615_auxpcm_be_ops = {
  1680. .startup = mdm9615_auxpcm_startup,
  1681. .shutdown = mdm9615_auxpcm_shutdown,
  1682. };
  1683. static struct snd_soc_ops mdm9615_sec_auxpcm_be_ops = {
  1684. .startup = mdm9615_sec_auxpcm_startup,
  1685. .shutdown = mdm9615_sec_auxpcm_shutdown,
  1686. };
  1687. /* Digital audio interface glue - connects codec <---> CPU */
  1688. static struct snd_soc_dai_link mdm9615_dai_common[] = {
  1689. /* FrontEnd DAI Links */
  1690. {
  1691. .name = "MDM9615 Media1",
  1692. .stream_name = "MultiMedia1",
  1693. .cpu_dai_name = "MultiMedia1",
  1694. .platform_name = "msm-pcm-dsp",
  1695. .dynamic = 1,
  1696. .codec_dai_name = "snd-soc-dummy-dai",
  1697. .codec_name = "snd-soc-dummy",
  1698. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1699. .ignore_suspend = 1,
  1700. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
  1701. },
  1702. {
  1703. .name = "MDM9615 Media2",
  1704. .stream_name = "MultiMedia2",
  1705. .cpu_dai_name = "MultiMedia2",
  1706. .platform_name = "msm-pcm-dsp",
  1707. .dynamic = 1,
  1708. .codec_dai_name = "snd-soc-dummy-dai",
  1709. .codec_name = "snd-soc-dummy",
  1710. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1711. .ignore_suspend = 1,
  1712. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
  1713. },
  1714. {
  1715. .name = "Circuit-Switch Voice",
  1716. .stream_name = "CS-Voice",
  1717. .cpu_dai_name = "CS-VOICE",
  1718. .platform_name = "msm-pcm-voice",
  1719. .dynamic = 1,
  1720. .codec_dai_name = "snd-soc-dummy-dai",
  1721. .codec_name = "snd-soc-dummy",
  1722. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1723. .ignore_suspend = 1,
  1724. .be_id = MSM_FRONTEND_DAI_CS_VOICE,
  1725. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1726. .ignore_suspend = 1,
  1727. },
  1728. {
  1729. .name = "MSM VoIP",
  1730. .stream_name = "VoIP",
  1731. .cpu_dai_name = "VoIP",
  1732. .platform_name = "msm-voip-dsp",
  1733. .dynamic = 1,
  1734. .codec_dai_name = "snd-soc-dummy-dai",
  1735. .codec_name = "snd-soc-dummy",
  1736. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1737. .ignore_suspend = 1,
  1738. .be_id = MSM_FRONTEND_DAI_VOIP,
  1739. },
  1740. /* Hostless PMC purpose */
  1741. {
  1742. .name = "SLIMBUS_0 Hostless",
  1743. .stream_name = "SLIMBUS_0 Hostless",
  1744. .cpu_dai_name = "SLIMBUS0_HOSTLESS",
  1745. .platform_name = "msm-pcm-hostless",
  1746. .dynamic = 1,
  1747. .codec_dai_name = "snd-soc-dummy-dai",
  1748. .codec_name = "snd-soc-dummy",
  1749. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1750. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1751. .ignore_suspend = 1,
  1752. /* .be_id = do not care */
  1753. },
  1754. {
  1755. .name = "MSM AFE-PCM RX",
  1756. .stream_name = "AFE-PROXY RX",
  1757. .cpu_dai_name = "msm-dai-q6.241",
  1758. .codec_name = "msm-stub-codec.1",
  1759. .codec_dai_name = "msm-stub-rx",
  1760. .platform_name = "msm-pcm-afe",
  1761. .ignore_suspend = 1,
  1762. },
  1763. {
  1764. .name = "MSM AFE-PCM TX",
  1765. .stream_name = "AFE-PROXY TX",
  1766. .cpu_dai_name = "msm-dai-q6.240",
  1767. .codec_name = "msm-stub-codec.1",
  1768. .codec_dai_name = "msm-stub-tx",
  1769. .platform_name = "msm-pcm-afe",
  1770. .ignore_suspend = 1,
  1771. },
  1772. {
  1773. .name = "AUXPCM Hostless",
  1774. .stream_name = "AUXPCM Hostless",
  1775. .cpu_dai_name = "AUXPCM_HOSTLESS",
  1776. .platform_name = "msm-pcm-hostless",
  1777. .dynamic = 1,
  1778. .codec_dai_name = "snd-soc-dummy-dai",
  1779. .codec_name = "snd-soc-dummy",
  1780. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1781. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1782. .ignore_suspend = 1,
  1783. },
  1784. {
  1785. .name = "VoLTE",
  1786. .stream_name = "VoLTE",
  1787. .cpu_dai_name = "VoLTE",
  1788. .platform_name = "msm-pcm-voice",
  1789. .dynamic = 1,
  1790. .codec_dai_name = "snd-soc-dummy-dai",
  1791. .codec_name = "snd-soc-dummy",
  1792. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  1793. .be_id = MSM_FRONTEND_DAI_VOLTE,
  1794. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1795. .ignore_suspend = 1,
  1796. },
  1797. {
  1798. .name = "DTMF RX Hostless",
  1799. .stream_name = "DTMF RX Hostless",
  1800. .cpu_dai_name = "DTMF_RX_HOSTLESS",
  1801. .platform_name = "msm-pcm-dtmf",
  1802. .dynamic = 1,
  1803. .codec_dai_name = "snd-soc-dummy-dai",
  1804. .codec_name = "snd-soc-dummy",
  1805. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1806. SND_SOC_DPCM_TRIGGER_POST},
  1807. .ignore_suspend = 1,
  1808. .be_id = MSM_FRONTEND_DAI_DTMF_RX,
  1809. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1810. },
  1811. {
  1812. .name = "DTMF TX",
  1813. .stream_name = "DTMF TX",
  1814. .cpu_dai_name = "msm-dai-stub",
  1815. .platform_name = "msm-pcm-dtmf",
  1816. .codec_name = "msm-stub-codec.1",
  1817. .codec_dai_name = "msm-stub-tx",
  1818. .ignore_suspend = 1,
  1819. },
  1820. {
  1821. .name = "CS-VOICE HOST RX CAPTURE",
  1822. .stream_name = "CS-VOICE HOST RX CAPTURE",
  1823. .cpu_dai_name = "msm-dai-stub",
  1824. .platform_name = "msm-host-pcm-voice",
  1825. .codec_name = "msm-stub-codec.1",
  1826. .codec_dai_name = "msm-stub-tx",
  1827. .ignore_suspend = 1,
  1828. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1829. SND_SOC_DPCM_TRIGGER_POST},
  1830. },
  1831. {
  1832. .name = "CS-VOICE HOST RX PLAYBACK",
  1833. .stream_name = "CS-VOICE HOST RX PLAYBACK",
  1834. .cpu_dai_name = "msm-dai-stub",
  1835. .platform_name = "msm-host-pcm-voice",
  1836. .codec_name = "msm-stub-codec.1",
  1837. .codec_dai_name = "msm-stub-rx",
  1838. .ignore_suspend = 1,
  1839. },
  1840. {
  1841. .name = "CS-VOICE HOST TX CAPTURE",
  1842. .stream_name = "CS-VOICE HOST TX CAPTURE",
  1843. .cpu_dai_name = "msm-dai-stub",
  1844. .platform_name = "msm-host-pcm-voice",
  1845. .codec_name = "msm-stub-codec.1",
  1846. .codec_dai_name = "msm-stub-tx",
  1847. .ignore_suspend = 1,
  1848. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1849. SND_SOC_DPCM_TRIGGER_POST},
  1850. },
  1851. {
  1852. .name = "CS-VOICE HOST TX PLAYBACK",
  1853. .stream_name = "CS-VOICE HOST TX PLAYBACK",
  1854. .cpu_dai_name = "msm-dai-stub",
  1855. .platform_name = "msm-host-pcm-voice",
  1856. .codec_name = "msm-stub-codec.1",
  1857. .codec_dai_name = "msm-stub-rx",
  1858. .ignore_suspend = 1,
  1859. },
  1860. /* Backend BT DAI Links */
  1861. {
  1862. .name = LPASS_BE_INT_BT_SCO_RX,
  1863. .stream_name = "Internal BT-SCO Playback",
  1864. .cpu_dai_name = "msm-dai-q6.12288",
  1865. .platform_name = "msm-pcm-routing",
  1866. .codec_name = "msm-stub-codec.1",
  1867. .codec_dai_name = "msm-stub-rx",
  1868. .no_pcm = 1,
  1869. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
  1870. .be_hw_params_fixup = mdm9615_btsco_be_hw_params_fixup,
  1871. },
  1872. {
  1873. .name = LPASS_BE_INT_BT_SCO_TX,
  1874. .stream_name = "Internal BT-SCO Capture",
  1875. .cpu_dai_name = "msm-dai-q6.12289",
  1876. .platform_name = "msm-pcm-routing",
  1877. .codec_name = "msm-stub-codec.1",
  1878. .codec_dai_name = "msm-stub-tx",
  1879. .no_pcm = 1,
  1880. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
  1881. .be_hw_params_fixup = mdm9615_btsco_be_hw_params_fixup,
  1882. },
  1883. /* Backend AFE DAI Links */
  1884. {
  1885. .name = LPASS_BE_AFE_PCM_RX,
  1886. .stream_name = "AFE Playback",
  1887. .cpu_dai_name = "msm-dai-q6.224",
  1888. .platform_name = "msm-pcm-routing",
  1889. .codec_name = "msm-stub-codec.1",
  1890. .codec_dai_name = "msm-stub-rx",
  1891. .no_pcm = 1,
  1892. .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
  1893. },
  1894. {
  1895. .name = LPASS_BE_AFE_PCM_TX,
  1896. .stream_name = "AFE Capture",
  1897. .cpu_dai_name = "msm-dai-q6.225",
  1898. .platform_name = "msm-pcm-routing",
  1899. .codec_name = "msm-stub-codec.1",
  1900. .codec_dai_name = "msm-stub-tx",
  1901. .no_pcm = 1,
  1902. .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
  1903. },
  1904. /* AUX PCM Backend DAI Links */
  1905. {
  1906. .name = LPASS_BE_AUXPCM_RX,
  1907. .stream_name = "AUX PCM Playback",
  1908. .cpu_dai_name = "msm-dai-q6.2",
  1909. .platform_name = "msm-pcm-routing",
  1910. .codec_name = "msm-stub-codec.1",
  1911. .codec_dai_name = "msm-stub-rx",
  1912. .no_pcm = 1,
  1913. .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
  1914. .be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
  1915. .ops = &mdm9615_auxpcm_be_ops,
  1916. },
  1917. {
  1918. .name = LPASS_BE_AUXPCM_TX,
  1919. .stream_name = "AUX PCM Capture",
  1920. .cpu_dai_name = "msm-dai-q6.3",
  1921. .platform_name = "msm-pcm-routing",
  1922. .codec_name = "msm-stub-codec.1",
  1923. .codec_dai_name = "msm-stub-tx",
  1924. .no_pcm = 1,
  1925. .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
  1926. .be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
  1927. .ops = &mdm9615_auxpcm_be_ops,
  1928. },
  1929. /* SECONDARY AUX PCM Backend DAI Links */
  1930. {
  1931. .name = LPASS_BE_SEC_AUXPCM_RX,
  1932. .stream_name = "SEC AUX PCM Playback",
  1933. .cpu_dai_name = "msm-dai-q6.12",
  1934. .platform_name = "msm-pcm-routing",
  1935. .codec_name = "msm-stub-codec.1",
  1936. .codec_dai_name = "msm-stub-rx",
  1937. .no_pcm = 1,
  1938. .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
  1939. .be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
  1940. .ops = &mdm9615_sec_auxpcm_be_ops,
  1941. },
  1942. {
  1943. .name = LPASS_BE_SEC_AUXPCM_TX,
  1944. .stream_name = "SEC AUX PCM Capture",
  1945. .cpu_dai_name = "msm-dai-q6.13",
  1946. .platform_name = "msm-pcm-routing",
  1947. .codec_name = "msm-stub-codec.1",
  1948. .codec_dai_name = "msm-stub-tx",
  1949. .no_pcm = 1,
  1950. .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
  1951. .be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
  1952. .ops = &mdm9615_sec_auxpcm_be_ops,
  1953. },
  1954. /* Incall Music BACK END DAI Link */
  1955. {
  1956. .name = LPASS_BE_VOICE_PLAYBACK_TX,
  1957. .stream_name = "Voice Farend Playback",
  1958. .cpu_dai_name = "msm-dai-q6.32773",
  1959. .platform_name = "msm-pcm-routing",
  1960. .codec_name = "msm-stub-codec.1",
  1961. .codec_dai_name = "msm-stub-rx",
  1962. .no_pcm = 1,
  1963. .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
  1964. .be_hw_params_fixup = mdm9615_be_hw_params_fixup,
  1965. },
  1966. /* Incall Record Uplink BACK END DAI Link */
  1967. {
  1968. .name = LPASS_BE_INCALL_RECORD_TX,
  1969. .stream_name = "Voice Uplink Capture",
  1970. .cpu_dai_name = "msm-dai-q6.32772",
  1971. .platform_name = "msm-pcm-routing",
  1972. .codec_name = "msm-stub-codec.1",
  1973. .codec_dai_name = "msm-stub-tx",
  1974. .no_pcm = 1,
  1975. .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
  1976. .be_hw_params_fixup = mdm9615_be_hw_params_fixup,
  1977. },
  1978. /* Incall Record Downlink BACK END DAI Link */
  1979. {
  1980. .name = LPASS_BE_INCALL_RECORD_RX,
  1981. .stream_name = "Voice Downlink Capture",
  1982. .cpu_dai_name = "msm-dai-q6.32771",
  1983. .platform_name = "msm-pcm-routing",
  1984. .codec_name = "msm-stub-codec.1",
  1985. .codec_dai_name = "msm-stub-tx",
  1986. .no_pcm = 1,
  1987. .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
  1988. .be_hw_params_fixup = mdm9615_be_hw_params_fixup,
  1989. .ignore_pmdown_time = 1, /* this dailink has playback support */
  1990. },
  1991. };
  1992. static struct snd_soc_dai_link mdm9615_dai_i2s_tabla[] = {
  1993. /* Backend I2S DAI Links */
  1994. {
  1995. .name = LPASS_BE_PRI_I2S_RX,
  1996. .stream_name = "Primary I2S Playback",
  1997. .cpu_dai_name = "msm-dai-q6.0",
  1998. .platform_name = "msm-pcm-routing",
  1999. .codec_name = "tabla_codec",
  2000. .codec_dai_name = "tabla_i2s_rx1",
  2001. .no_pcm = 1,
  2002. .be_id = MSM_BACKEND_DAI_PRI_I2S_RX,
  2003. .init = &msm9615_i2s_audrx_init,
  2004. .be_hw_params_fixup = msm9615_i2s_rx_be_hw_params_fixup,
  2005. .ops = &msm9615_i2s_be_ops,
  2006. },
  2007. {
  2008. .name = LPASS_BE_PRI_I2S_TX,
  2009. .stream_name = "Primary I2S Capture",
  2010. .cpu_dai_name = "msm-dai-q6.1",
  2011. .platform_name = "msm-pcm-routing",
  2012. .codec_name = "tabla_codec",
  2013. .codec_dai_name = "tabla_i2s_tx1",
  2014. .no_pcm = 1,
  2015. .be_id = MSM_BACKEND_DAI_PRI_I2S_TX,
  2016. .be_hw_params_fixup = msm9615_i2s_tx_be_hw_params_fixup,
  2017. .ops = &msm9615_i2s_be_ops,
  2018. },
  2019. {
  2020. .name = LPASS_BE_SEC_I2S_RX,
  2021. .stream_name = "Secondary I2S Playback",
  2022. .cpu_dai_name = "msm-dai-q6.4",
  2023. .platform_name = "msm-pcm-routing",
  2024. .codec_name = "msm-stub-codec.1",
  2025. .codec_dai_name = "msm-stub-rx",
  2026. .no_pcm = 1,
  2027. .be_id = MSM_BACKEND_DAI_SEC_I2S_RX,
  2028. .be_hw_params_fixup = msm9615_i2s_rx_be_hw_params_fixup,
  2029. .ops = &msm9615_i2s_be_ops,
  2030. },
  2031. {
  2032. .name = LPASS_BE_SEC_I2S_TX,
  2033. .stream_name = "Secondary I2S Capture",
  2034. .cpu_dai_name = "msm-dai-q6.5",
  2035. .platform_name = "msm-pcm-routing",
  2036. .codec_name = "msm-stub-codec.1",
  2037. .codec_dai_name = "msm-stub-tx",
  2038. .no_pcm = 1,
  2039. .be_id = MSM_BACKEND_DAI_SEC_I2S_TX,
  2040. .be_hw_params_fixup = msm9615_i2s_tx_be_hw_params_fixup,
  2041. .ops = &msm9615_i2s_be_ops,
  2042. },
  2043. };
  2044. static struct snd_soc_dai_link mdm9615_dai_slimbus_tabla[] = {
  2045. /* Backend SlimBus DAI Links */
  2046. {
  2047. .name = LPASS_BE_SLIMBUS_0_RX,
  2048. .stream_name = "Slimbus Playback",
  2049. .cpu_dai_name = "msm-dai-q6.16384",
  2050. .platform_name = "msm-pcm-routing",
  2051. .codec_name = "tabla_codec",
  2052. .codec_dai_name = "tabla_rx1",
  2053. .no_pcm = 1,
  2054. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
  2055. .init = &mdm9615_audrx_init,
  2056. .be_hw_params_fixup = mdm9615_slim_0_rx_be_hw_params_fixup,
  2057. .ops = &mdm9615_be_ops,
  2058. },
  2059. {
  2060. .name = LPASS_BE_SLIMBUS_0_TX,
  2061. .stream_name = "Slimbus Capture",
  2062. .cpu_dai_name = "msm-dai-q6.16385",
  2063. .platform_name = "msm-pcm-routing",
  2064. .codec_name = "tabla_codec",
  2065. .codec_dai_name = "tabla_tx1",
  2066. .no_pcm = 1,
  2067. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
  2068. .be_hw_params_fixup = mdm9615_slim_0_tx_be_hw_params_fixup,
  2069. .ops = &mdm9615_be_ops,
  2070. },
  2071. };
  2072. static struct snd_soc_dai_link mdm9615_i2s_dai[
  2073. ARRAY_SIZE(mdm9615_dai_common) +
  2074. ARRAY_SIZE(mdm9615_dai_i2s_tabla)];
  2075. static struct snd_soc_dai_link mdm9615_slimbus_dai[
  2076. ARRAY_SIZE(mdm9615_dai_common) +
  2077. ARRAY_SIZE(mdm9615_dai_slimbus_tabla)];
  2078. static struct snd_soc_card snd_soc_card_mdm9615[] = {
  2079. [0] = {
  2080. .name = "mdm9615-tabla-snd-card",
  2081. .controls = tabla_mdm9615_controls,
  2082. .num_controls = ARRAY_SIZE(tabla_mdm9615_controls),
  2083. },
  2084. [1] = {
  2085. .name = "mdm9615-tabla-snd-card-i2s",
  2086. .controls = tabla_msm9615_i2s_controls,
  2087. .num_controls = ARRAY_SIZE(tabla_msm9615_i2s_controls),
  2088. },
  2089. };
  2090. static int __init mdm9615_audio_init(void)
  2091. {
  2092. int ret;
  2093. /* Set GPIO headset detection by default */
  2094. hs_detect_use_gpio = true;
  2095. if (!cpu_is_msm9615()) {
  2096. pr_err("%s: Not the right machine type\n", __func__);
  2097. return -ENODEV ;
  2098. }
  2099. mbhc_cfg.calibration = def_tabla_mbhc_cal();
  2100. if (!mbhc_cfg.calibration) {
  2101. pr_err("Calibration data allocation failed\n");
  2102. return -ENOMEM;
  2103. }
  2104. mdm9615_snd_device_slim = platform_device_alloc("soc-audio", 0);
  2105. if (!mdm9615_snd_device_slim) {
  2106. pr_err("Platform device allocation failed\n");
  2107. kfree(mbhc_cfg.calibration);
  2108. return -ENOMEM;
  2109. }
  2110. /* Install SLIM specific links */
  2111. memcpy(mdm9615_slimbus_dai, mdm9615_dai_common,
  2112. sizeof(mdm9615_dai_common));
  2113. memcpy(mdm9615_slimbus_dai + ARRAY_SIZE(mdm9615_dai_common),
  2114. mdm9615_dai_slimbus_tabla,
  2115. sizeof(mdm9615_dai_slimbus_tabla));
  2116. snd_soc_card_mdm9615[0].dai_link = mdm9615_slimbus_dai;
  2117. snd_soc_card_mdm9615[0].num_links =
  2118. ARRAY_SIZE(mdm9615_slimbus_dai);
  2119. mdm9615_snd_device_i2s = platform_device_alloc("soc-audio", 1);
  2120. if (!mdm9615_snd_device_i2s) {
  2121. pr_err("Platform device allocation failed\n");
  2122. kfree(mbhc_cfg.calibration);
  2123. return -ENOMEM;
  2124. }
  2125. pr_err("%s: Interface Type = %d\n", __func__,
  2126. wcd9xxx_get_intf_type());
  2127. /* Install I2S specific links */
  2128. memcpy(mdm9615_i2s_dai, mdm9615_dai_common,
  2129. sizeof(mdm9615_dai_common));
  2130. memcpy(mdm9615_i2s_dai + ARRAY_SIZE(mdm9615_dai_common),
  2131. mdm9615_dai_i2s_tabla,
  2132. sizeof(mdm9615_dai_i2s_tabla));
  2133. snd_soc_card_mdm9615[1].dai_link = mdm9615_i2s_dai;
  2134. snd_soc_card_mdm9615[1].num_links =
  2135. ARRAY_SIZE(mdm9615_i2s_dai);
  2136. platform_set_drvdata(mdm9615_snd_device_slim, &snd_soc_card_mdm9615[0]);
  2137. ret = platform_device_add(mdm9615_snd_device_slim);
  2138. if (ret) {
  2139. pr_err("%s Slim platform_device_add fail\n", __func__);
  2140. platform_device_put(mdm9615_snd_device_slim);
  2141. kfree(mbhc_cfg.calibration);
  2142. return ret;
  2143. }
  2144. platform_set_drvdata(mdm9615_snd_device_i2s, &snd_soc_card_mdm9615[1]);
  2145. ret = platform_device_add(mdm9615_snd_device_i2s);
  2146. if (ret) {
  2147. pr_err("%s I2S platform_device_add fail\n", __func__);
  2148. platform_device_put(mdm9615_snd_device_i2s);
  2149. kfree(mbhc_cfg.calibration);
  2150. return ret;
  2151. }
  2152. /*
  2153. * Irrespective of audio interface type get virtual address
  2154. * of LPAIF registers as it may not be guaranted that I2S
  2155. * will probed successfully in Init.
  2156. */
  2157. atomic_set(&msm9615_auxpcm_ref, 0);
  2158. atomic_set(&msm9615_sec_auxpcm_ref, 0);
  2159. msm9x15_i2s_ctl.sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
  2160. msm9x15_i2s_ctl.spare_virt_addr = ioremap(LPAIF_SPARE_ADDR, 4);
  2161. if (msm9x15_i2s_ctl.spare_virt_addr == NULL ||
  2162. msm9x15_i2s_ctl.sif_virt_addr == NULL)
  2163. pr_err("%s: SIF or Spare ptr are NULL", __func__);
  2164. sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
  2165. secpcm_portslc_virt_addr = ioremap(SEC_PCM_PORT_SLC_ADDR, 4);
  2166. return ret;
  2167. }
  2168. module_init(mdm9615_audio_init);
  2169. static void __exit mdm9615_audio_exit(void)
  2170. {
  2171. if (!cpu_is_msm9615()) {
  2172. pr_err("%s: Not the right machine type\n", __func__);
  2173. return ;
  2174. }
  2175. platform_device_unregister(mdm9615_snd_device_slim);
  2176. platform_device_unregister(mdm9615_snd_device_i2s);
  2177. kfree(mbhc_cfg.calibration);
  2178. iounmap(msm9x15_i2s_ctl.sif_virt_addr);
  2179. iounmap(msm9x15_i2s_ctl.spare_virt_addr);
  2180. iounmap(sif_virt_addr);
  2181. iounmap(secpcm_portslc_virt_addr);
  2182. }
  2183. module_exit(mdm9615_audio_exit);
  2184. MODULE_DESCRIPTION("ALSA SoC MDM9615");
  2185. MODULE_LICENSE("GPL v2");