apq8064-i2s.c 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707
  1. /* Copyright (c) 2012, 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 <linux/pm_runtime.h>
  21. #include <linux/slimbus/slimbus.h>
  22. #include <sound/core.h>
  23. #include <sound/soc.h>
  24. #include <sound/soc-dapm.h>
  25. #include <sound/pcm.h>
  26. #include <sound/jack.h>
  27. #include <asm/mach-types.h>
  28. #include <mach/socinfo.h>
  29. #include "msm-pcm-routing.h"
  30. #include "../codecs/wcd9310.h"
  31. /* 8064 machine driver */
  32. #define PM8921_GPIO_BASE NR_GPIO_IRQS
  33. #define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
  34. #define MSM8064_SPK_ON 1
  35. #define MSM8064_SPK_OFF 0
  36. #define MSM_SLIM_0_RX_MAX_CHANNELS 2
  37. #define MSM_SLIM_0_TX_MAX_CHANNELS 4
  38. #define BTSCO_RATE_8KHZ 8000
  39. #define BTSCO_RATE_16KHZ 16000
  40. #define BOTTOM_SPK_AMP_POS 0x1
  41. #define BOTTOM_SPK_AMP_NEG 0x2
  42. #define TOP_SPK_AMP_POS 0x4
  43. #define TOP_SPK_AMP_NEG 0x8
  44. #define TOP_SPK_AMP 0x10
  45. #define GPIO_AUX_PCM_DOUT 43
  46. #define GPIO_AUX_PCM_DIN 44
  47. #define GPIO_AUX_PCM_SYNC 45
  48. #define GPIO_AUX_PCM_CLK 46
  49. #define TABLA_EXT_CLK_RATE 12288000
  50. #define TABLA_MBHC_DEF_BUTTONS 8
  51. #define TABLA_MBHC_DEF_RLOADS 5
  52. #define JACK_DETECT_GPIO 38
  53. /* MCLK selection GPIOs from PMIC */
  54. #define PM_GPIO_MCLK_MDM 27
  55. #define PM_GPIO_MCLK_APQ 41
  56. /* SPKR I2S Configuration */
  57. #define GPIO_SPKR_I2S_MCLK 39
  58. #define GPIO_SPKR_I2S_SCK 40
  59. #define GPIO_SPKR_I2S_DOUT 41
  60. #define GPIO_SPKR_I2S_WS 42
  61. /* MIC I2S Configuration */
  62. #define GPIO_MIC_I2S_MCLK 34
  63. #define GPIO_MIC_I2S_SCK 35
  64. #define GPIO_MIC_I2S_WS 36
  65. #define GPIO_MIC_I2S_DIN0 37
  66. #define GPIO_MIC_I2S_DIN1 38
  67. /* MI2S Configuration */
  68. #define GPIO_MI2S_WS 27
  69. #define GPIO_MI2S_SCK 28
  70. #define GPIO_MI2S_SD3 29
  71. #define GPIO_MI2S_SD2 30
  72. #define GPIO_MI2S_SD1 31
  73. #define GPIO_MI2S_SD0 32
  74. #define GPIO_MI2S_MCLK 33
  75. struct request_gpio {
  76. unsigned gpio_no;
  77. char *gpio_name;
  78. };
  79. /* SD0 as RX and SD3 as TX. SD1 and SD2 are unused */
  80. static struct request_gpio mi2s_gpio[] = {
  81. {
  82. .gpio_no = GPIO_MI2S_WS,
  83. .gpio_name = "MI2S_WS",
  84. },
  85. {
  86. .gpio_no = GPIO_MI2S_SCK,
  87. .gpio_name = "MI2S_SCK",
  88. },
  89. {
  90. .gpio_no = GPIO_MI2S_SD3,
  91. .gpio_name = "MI2S_SD3",
  92. },
  93. {
  94. .gpio_no = GPIO_MI2S_SD0,
  95. .gpio_name = "MI2S_SD0",
  96. },
  97. {
  98. .gpio_no = GPIO_MI2S_MCLK,
  99. .gpio_name = "MI2S_MCLK",
  100. },
  101. };
  102. /* I2S RX is slave so MCLK is not needed */
  103. static struct request_gpio spkr_i2s_gpio[] = {
  104. {
  105. .gpio_no = GPIO_SPKR_I2S_WS,
  106. .gpio_name = "SPKR_I2S_WS",
  107. },
  108. {
  109. .gpio_no = GPIO_SPKR_I2S_SCK,
  110. .gpio_name = "SPKR_I2S_SCK",
  111. },
  112. {
  113. .gpio_no = GPIO_SPKR_I2S_DOUT,
  114. .gpio_name = "SPKR_I2S_DOUT",
  115. },
  116. };
  117. /* I2S TX is slave so MCLK is not needed. DIN1 is not used */
  118. static struct request_gpio mic_i2s_gpio[] = {
  119. {
  120. .gpio_no = GPIO_MIC_I2S_WS,
  121. .gpio_name = "MIC_I2S_WS",
  122. },
  123. {
  124. .gpio_no = GPIO_MIC_I2S_SCK,
  125. .gpio_name = "MIC_I2S_SCK",
  126. },
  127. {
  128. .gpio_no = GPIO_MIC_I2S_DIN0,
  129. .gpio_name = "MIC_I2S_DIN",
  130. },
  131. };
  132. /* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
  133. enum {
  134. SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
  135. SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
  136. SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
  137. SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
  138. SLIM_3_TX_1 = 153, /* HDMI RX */
  139. SLIM_3_TX_2 = 154, /* HDMI RX */
  140. SLIM_4_TX_1 = 148, /* In-call recording RX */
  141. SLIM_4_TX_2 = 149, /* In-call recording RX */
  142. SLIM_4_RX_1 = 150, /* In-call music delivery TX */
  143. };
  144. enum {
  145. INCALL_REC_MONO,
  146. INCALL_REC_STEREO,
  147. };
  148. static u32 mdm_mclk_gpio = PM8921_GPIO_PM_TO_SYS(PM_GPIO_MCLK_MDM);
  149. static u32 apq_mclk_gpio = PM8921_GPIO_PM_TO_SYS(PM_GPIO_MCLK_APQ);
  150. static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
  151. static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
  152. static int msm_spk_control;
  153. static int msm_ext_bottom_spk_pamp;
  154. static int msm_ext_top_spk_pamp;
  155. static int msm_slim_0_rx_ch = 1;
  156. static int msm_slim_0_tx_ch = 1;
  157. static int msm_slim_3_rx_ch = 1;
  158. static struct clk *i2s_rx_bit_clk;
  159. static struct clk *i2s_tx_bit_clk;
  160. static struct clk *mi2s_bit_clk;
  161. static int msm_i2s_rx_ch = 1;
  162. static int msm_i2s_tx_ch = 1;
  163. static int msm_mi2s_rx_ch = 1;
  164. static int msm_mi2s_tx_ch = 1;
  165. /* MI2S TX and RX share the same control block*/
  166. static atomic_t mi2s_rsc_ref;
  167. static int msm_btsco_rate = BTSCO_RATE_8KHZ;
  168. static int msm_btsco_ch = 1;
  169. static int rec_mode = INCALL_REC_MONO;
  170. static struct clk *codec_clk;
  171. static int clk_users;
  172. static struct snd_soc_jack hs_jack;
  173. static struct snd_soc_jack button_jack;
  174. static atomic_t auxpcm_rsc_ref;
  175. static int apq8064_i2s_hs_detect_use_gpio = -1;
  176. module_param(apq8064_i2s_hs_detect_use_gpio, int, 0444);
  177. MODULE_PARM_DESC(apq8064_i2s_hs_detect_use_gpio, "Use GPIO for headset detection");
  178. static bool apq8064_i2s_hs_detect_use_firmware;
  179. module_param(apq8064_i2s_hs_detect_use_firmware, bool, 0444);
  180. MODULE_PARM_DESC(apq8064_i2s_hs_detect_use_firmware,
  181. "Use firmware for headset detection");
  182. static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  183. bool dapm);
  184. static struct tabla_mbhc_config mbhc_cfg = {
  185. .headset_jack = &hs_jack,
  186. .button_jack = &button_jack,
  187. .read_fw_bin = false,
  188. .calibration = NULL,
  189. .micbias = TABLA_MICBIAS2,
  190. .mclk_cb_fn = msm_enable_codec_ext_clk,
  191. .mclk_rate = TABLA_EXT_CLK_RATE,
  192. .gpio = 0,
  193. .gpio_irq = 0,
  194. .gpio_level_insert = 1,
  195. };
  196. static struct mutex cdc_mclk_mutex;
  197. static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
  198. {
  199. int ret = 0;
  200. struct pm_gpio param = {
  201. .direction = PM_GPIO_DIR_OUT,
  202. .output_buffer = PM_GPIO_OUT_BUF_CMOS,
  203. .output_value = 1,
  204. .pull = PM_GPIO_PULL_NO,
  205. .vin_sel = PM_GPIO_VIN_S4,
  206. .out_strength = PM_GPIO_STRENGTH_MED,
  207. .
  208. function = PM_GPIO_FUNC_NORMAL,
  209. };
  210. if (spk_amp_gpio == bottom_spk_pamp_gpio) {
  211. ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
  212. if (ret) {
  213. pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
  214. __func__, bottom_spk_pamp_gpio);
  215. return;
  216. }
  217. ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
  218. if (ret)
  219. pr_err("%s: Failed to configure Bottom Spk Ampl gpio %u\n",
  220. __func__, bottom_spk_pamp_gpio);
  221. else {
  222. pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
  223. gpio_direction_output(bottom_spk_pamp_gpio, 1);
  224. }
  225. } else if (spk_amp_gpio == top_spk_pamp_gpio) {
  226. ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
  227. if (ret) {
  228. pr_err("%s: Error requesting GPIO %d\n", __func__,
  229. top_spk_pamp_gpio);
  230. return;
  231. }
  232. ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
  233. if (ret)
  234. pr_err("%s: Failed to configure Top Spk Ampl gpio %u\n",
  235. __func__, top_spk_pamp_gpio);
  236. else {
  237. pr_debug("%s: enable Top spkr amp gpio\n", __func__);
  238. gpio_direction_output(top_spk_pamp_gpio, 1);
  239. }
  240. } else {
  241. pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO gpio = %u\n",
  242. __func__, spk_amp_gpio);
  243. return;
  244. }
  245. }
  246. static void msm_ext_spk_power_amp_on(u32 spk)
  247. {
  248. if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
  249. if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
  250. (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
  251. pr_debug("%s() External Bottom Speaker Ampl already turned on\n"
  252. "spk = 0x%08x\n", __func__, spk);
  253. return;
  254. }
  255. msm_ext_bottom_spk_pamp |= spk;
  256. if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
  257. (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
  258. msm_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
  259. pr_debug("%s: slepping 4 ms after turning on external\n"
  260. "Bottom Speaker Ampl\n", __func__);
  261. usleep_range(4000, 4000);
  262. }
  263. } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
  264. pr_debug("%s():top_spk_amp_state = 0x%x spk_event = 0x%x\n",
  265. __func__, msm_ext_top_spk_pamp, spk);
  266. if (((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
  267. (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
  268. (msm_ext_top_spk_pamp & TOP_SPK_AMP)) {
  269. pr_debug("%s() External Top Speaker Ampl already turned on\n"
  270. "spk = 0x%08x\n", __func__, spk);
  271. return;
  272. }
  273. msm_ext_top_spk_pamp |= spk;
  274. if (((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
  275. (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
  276. (msm_ext_top_spk_pamp & TOP_SPK_AMP)) {
  277. msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
  278. pr_debug("%s: sleeping 4 ms after turning on\n"
  279. "external Top Speaker Ampl\n", __func__);
  280. usleep_range(4000, 4000);
  281. }
  282. } else {
  283. pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
  284. __func__, spk);
  285. return;
  286. }
  287. }
  288. static void msm_ext_spk_power_amp_off(u32 spk)
  289. {
  290. if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
  291. if (!msm_ext_bottom_spk_pamp)
  292. return;
  293. gpio_direction_output(bottom_spk_pamp_gpio, 0);
  294. gpio_free(bottom_spk_pamp_gpio);
  295. msm_ext_bottom_spk_pamp = 0;
  296. pr_debug("%s: sleeping 4 ms after turning off external Bottom\n"
  297. "Speaker Ampl\n", __func__);
  298. usleep_range(4000, 4000);
  299. } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
  300. pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
  301. __func__, msm_ext_top_spk_pamp, spk);
  302. if (!msm_ext_top_spk_pamp)
  303. return;
  304. if ((spk & TOP_SPK_AMP_POS) || (spk & TOP_SPK_AMP_NEG)) {
  305. msm_ext_top_spk_pamp &= (~(TOP_SPK_AMP_POS |
  306. TOP_SPK_AMP_NEG));
  307. } else if (spk & TOP_SPK_AMP) {
  308. msm_ext_top_spk_pamp &= ~TOP_SPK_AMP;
  309. }
  310. if (msm_ext_top_spk_pamp)
  311. return;
  312. gpio_direction_output(top_spk_pamp_gpio, 0);
  313. gpio_free(top_spk_pamp_gpio);
  314. msm_ext_top_spk_pamp = 0;
  315. pr_debug("%s: sleeping 4 ms after ext Top Spek Ampl is off\n",
  316. __func__);
  317. usleep_range(4000, 4000);
  318. } else {
  319. pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
  320. __func__, spk);
  321. return;
  322. }
  323. }
  324. static void msm_ext_control(struct snd_soc_codec *codec)
  325. {
  326. struct snd_soc_dapm_context *dapm = &codec->dapm;
  327. pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
  328. if (msm_spk_control == MSM8064_SPK_ON) {
  329. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
  330. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
  331. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
  332. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
  333. } else {
  334. snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
  335. snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
  336. snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
  337. snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
  338. }
  339. snd_soc_dapm_sync(dapm);
  340. }
  341. static int msm_get_spk(struct snd_kcontrol *kcontrol,
  342. struct snd_ctl_elem_value *ucontrol)
  343. {
  344. pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
  345. ucontrol->value.integer.value[0] = msm_spk_control;
  346. return 0;
  347. }
  348. static int msm_set_spk(struct snd_kcontrol *kcontrol,
  349. struct snd_ctl_elem_value *ucontrol)
  350. {
  351. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  352. pr_debug("%s()\n", __func__);
  353. if (msm_spk_control == ucontrol->value.integer.value[0])
  354. return 0;
  355. msm_spk_control = ucontrol->value.integer.value[0];
  356. msm_ext_control(codec);
  357. return 1;
  358. }
  359. static int msm_spkramp_event(struct snd_soc_dapm_widget *w,
  360. struct snd_kcontrol *k, int event)
  361. {
  362. pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
  363. if (SND_SOC_DAPM_EVENT_ON(event)) {
  364. if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
  365. msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
  366. else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
  367. msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
  368. else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
  369. msm_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
  370. else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
  371. msm_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
  372. else if (!strncmp(w->name, "Ext Spk Top", 12))
  373. msm_ext_spk_power_amp_on(TOP_SPK_AMP);
  374. else {
  375. pr_err("%s() Invalid Speaker Widget = %s\n",
  376. __func__, w->name);
  377. return -EINVAL;
  378. }
  379. } else {
  380. if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
  381. msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
  382. else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
  383. msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
  384. else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
  385. msm_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
  386. else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
  387. msm_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
  388. else if (!strncmp(w->name, "Ext Spk Top", 12))
  389. msm_ext_spk_power_amp_off(TOP_SPK_AMP);
  390. else {
  391. pr_err("%s() Invalid Speaker Widget = %s\n",
  392. __func__, w->name);
  393. return -EINVAL;
  394. }
  395. }
  396. return 0;
  397. }
  398. static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  399. bool dapm)
  400. {
  401. int r = 0;
  402. pr_debug("%s: enable = %d\n", __func__, enable);
  403. mutex_lock(&cdc_mclk_mutex);
  404. if (enable) {
  405. clk_users++;
  406. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  407. if (clk_users == 1) {
  408. if (codec_clk) {
  409. /*
  410. * For MBHC calc, the MCLK is from APQ side
  411. * so APQ has control of the MCLK at this point
  412. */
  413. clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
  414. clk_prepare_enable(codec_clk);
  415. tabla_mclk_enable(codec, 1, dapm);
  416. } else {
  417. pr_err("%s: Error setting Tabla MCLK\n",
  418. __func__);
  419. clk_users--;
  420. r = -EINVAL;
  421. }
  422. }
  423. } else {
  424. if (clk_users > 0) {
  425. clk_users--;
  426. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  427. if (clk_users == 0) {
  428. pr_debug("%s: disabling MCLK. clk_users = %d\n",
  429. __func__, clk_users);
  430. tabla_mclk_enable(codec, 0, dapm);
  431. /*
  432. * For MBHC calc, the MCLK is from APQ side
  433. * so APQ has control of the MCLK at this point
  434. */
  435. clk_disable_unprepare(codec_clk);
  436. }
  437. } else {
  438. pr_err("%s: Error releasing Tabla MCLK\n", __func__);
  439. r = -EINVAL;
  440. }
  441. }
  442. mutex_unlock(&cdc_mclk_mutex);
  443. return r;
  444. }
  445. static int msm_mclk_event(struct snd_soc_dapm_widget *w,
  446. struct snd_kcontrol *kcontrol, int event)
  447. {
  448. pr_debug("%s: event = %d\n", __func__, event);
  449. switch (event) {
  450. case SND_SOC_DAPM_PRE_PMU:
  451. clk_users++;
  452. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  453. if (clk_users != 1)
  454. return 0;
  455. if (codec_clk) {
  456. /*
  457. * Since the MCLK is from MDM side so APQ side
  458. * has no control of the MCLK at this point
  459. */
  460. /*clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
  461. clk_prepare_enable(codec_clk); */
  462. tabla_mclk_enable(w->codec, 1, true);
  463. } else {
  464. pr_err("%s: Error setting Tabla MCLK\n", __func__);
  465. clk_users--;
  466. return -EINVAL;
  467. }
  468. break;
  469. case SND_SOC_DAPM_POST_PMD:
  470. pr_debug("%s: clk_users = %d\n", __func__, clk_users);
  471. if (clk_users == 0)
  472. return 0;
  473. clk_users--;
  474. if (!clk_users) {
  475. pr_debug("%s: disabling MCLK. clk_users = %d\n",
  476. __func__, clk_users);
  477. tabla_mclk_enable(w->codec, 0, true);
  478. /*
  479. * Since the MCLK is from MDM side so APQ side
  480. * has no control of the MCLK at this point
  481. */
  482. /* clk_disable_unprepare(codec_clk); */
  483. }
  484. break;
  485. }
  486. return 0;
  487. }
  488. static const struct snd_soc_dapm_widget apq8064_dapm_widgets[] = {
  489. SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
  490. msm_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  491. SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm_spkramp_event),
  492. SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm_spkramp_event),
  493. SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm_spkramp_event),
  494. SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm_spkramp_event),
  495. SND_SOC_DAPM_SPK("Ext Spk Top", msm_spkramp_event),
  496. /************ Analog MICs ************/
  497. /**
  498. * Analog mic7 (Front Top) on Liquid.
  499. * Used as Handset mic on CDP.
  500. */
  501. SND_SOC_DAPM_MIC("Analog mic7", NULL),
  502. SND_SOC_DAPM_MIC("Headset Mic", NULL),
  503. SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
  504. SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
  505. /*********** Digital Mics ***************/
  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 apq8064_common_audio_map[] = {
  514. {"RX_BIAS", NULL, "MCLK"},
  515. {"LDO_H", NULL, "MCLK"},
  516. {"HEADPHONE", NULL, "LDO_H"},
  517. /* Speaker path */
  518. {"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
  519. {"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
  520. {"Ext Spk Top Pos", NULL, "LINEOUT2"},
  521. {"Ext Spk Top Neg", NULL, "LINEOUT4"},
  522. {"Ext Spk Top", NULL, "LINEOUT5"},
  523. /************ Analog MIC Paths ************/
  524. /* Headset Mic */
  525. {"AMIC2", NULL, "MIC BIAS2 External"},
  526. {"MIC BIAS2 External", NULL, "Headset Mic"},
  527. /* Headset ANC microphones */
  528. {"AMIC3", NULL, "MIC BIAS3 Internal1"},
  529. {"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
  530. {"AMIC4", NULL, "MIC BIAS1 Internal2"},
  531. {"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
  532. };
  533. static const struct snd_soc_dapm_route apq8064_mtp_audio_map[] = {
  534. /************ Digital MIC Paths ************/
  535. /*
  536. * Digital Mic1 (Front bottom Left) on MTP.
  537. * Conncted to DMIC1 Input on Tabla codec.
  538. */
  539. {"DMIC1", NULL, "MIC BIAS1 External"},
  540. {"MIC BIAS1 External", NULL, "Digital Mic1"},
  541. /**
  542. * Digital Mic2 (Front bottom right) on MTP.
  543. * Conncted to DMIC2 Input on Tabla codec.
  544. */
  545. {"DMIC2", NULL, "MIC BIAS1 External"},
  546. {"MIC BIAS1 External", NULL, "Digital Mic2"},
  547. /**
  548. * Digital Mic3 (Back bottom) on MTP.
  549. * Conncted to DMIC3 Input on Tabla codec.
  550. */
  551. {"DMIC3", NULL, "MIC BIAS3 External"},
  552. {"MIC BIAS3 External", NULL, "Digital Mic3"},
  553. /**
  554. * Digital Mic4 (Back top) on MTP.
  555. * Conncted to DMIC4 Input on Tabla codec.
  556. */
  557. {"DMIC4", NULL, "MIC BIAS3 External"},
  558. {"MIC BIAS3 External", NULL, "Digital Mic4"},
  559. /**
  560. * Digital Mic5 (Top front Mic) on MTP.
  561. * Conncted to DMIC6 Input on Tabla codec.
  562. */
  563. {"DMIC6", NULL, "MIC BIAS4 External"},
  564. {"MIC BIAS4 External", NULL, "Digital Mic5"},
  565. };
  566. static const struct snd_soc_dapm_route apq8064_liquid_cdp_audio_map[] = {
  567. /************ Analog MIC Paths ************/
  568. /**
  569. * Analog mic7 (Front Top Mic) on Liquid.
  570. * Used as Handset mic on CDP.
  571. * Not there on MTP.
  572. */
  573. {"AMIC1", NULL, "MIC BIAS1 External"},
  574. {"MIC BIAS1 External", NULL, "Analog mic7"},
  575. /************ Digital MIC Paths ************/
  576. /**
  577. * The digital Mic routes are setup considering
  578. * Liquid as default device.
  579. */
  580. /**
  581. * Digital Mic1 (Front bottom left corner) on Liquid.
  582. * Digital Mic2 (Front bottom right) on MTP.
  583. * Digital Mic GM1 on CDP mainboard.
  584. * Conncted to DMIC2 Input on Tabla codec.
  585. */
  586. {"DMIC2", NULL, "MIC BIAS1 External"},
  587. {"MIC BIAS1 External", NULL, "Digital Mic1"},
  588. /**
  589. * Digital Mic2 (Front left side) on Liquid.
  590. * Digital Mic GM2 on CDP mainboard.
  591. * Not there on MTP.
  592. * Conncted to DMIC3 Input on Tabla codec.
  593. */
  594. {"DMIC3", NULL, "MIC BIAS3 External"},
  595. {"MIC BIAS3 External", NULL, "Digital Mic2"},
  596. /**
  597. * Digital Mic3. Front bottom left of middle on Liquid.
  598. * Digital Mic5 (Top front Mic) on MTP.
  599. * Digital Mic GM5 on CDP mainboard.
  600. * Conncted to DMIC6 Input on Tabla codec.
  601. */
  602. {"DMIC6", NULL, "MIC BIAS4 External"},
  603. {"MIC BIAS4 External", NULL, "Digital Mic3"},
  604. /**
  605. * Digital Mic4. Back bottom on Liquid.
  606. * Digital Mic GM3 on CDP mainboard.
  607. * Top Front Mic on MTP.
  608. * Conncted to DMIC5 Input on Tabla codec.
  609. */
  610. {"DMIC5", NULL, "MIC BIAS4 External"},
  611. {"MIC BIAS4 External", NULL, "Digital Mic4"},
  612. /**
  613. * Digital Mic5. Front bottom right of middle on Liquid.
  614. * Digital Mic GM6 on CDP mainboard.
  615. * Not there on MTP.
  616. * Conncted to DMIC4 Input on Tabla codec.
  617. */
  618. {"DMIC4", NULL, "MIC BIAS3 External"},
  619. {"MIC BIAS3 External", NULL, "Digital Mic5"},
  620. /* Digital Mic6 (Front bottom right corner) on Liquid.
  621. * Digital Mic1 (Front bottom Left) on MTP.
  622. * Digital Mic GM4 on CDP.
  623. * Conncted to DMIC1 Input on Tabla codec.
  624. */
  625. {"DMIC1", NULL, "MIC BIAS1 External"},
  626. {"MIC BIAS1 External", NULL, "Digital Mic6"},
  627. };
  628. static const char * const spk_function[] = {"Off", "On"};
  629. static const char * const rx_ch_text[] = {"One", "Two"};
  630. static const char * const tx_ch_text[] = {"One", "Two", "Three", "Four"};
  631. static const struct soc_enum msm_enum[] = {
  632. SOC_ENUM_SINGLE_EXT(2, spk_function),
  633. SOC_ENUM_SINGLE_EXT(2, rx_ch_text),
  634. SOC_ENUM_SINGLE_EXT(4, tx_ch_text),
  635. };
  636. static const char * const btsco_rate_text[] = {"8000", "16000"};
  637. static const struct soc_enum msm_btsco_enum[] = {
  638. SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
  639. };
  640. static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
  641. struct snd_ctl_elem_value *ucontrol)
  642. {
  643. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  644. msm_slim_0_rx_ch);
  645. ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
  646. return 0;
  647. }
  648. static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
  649. struct snd_ctl_elem_value *ucontrol)
  650. {
  651. msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
  652. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  653. msm_slim_0_rx_ch);
  654. return 1;
  655. }
  656. static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
  657. struct snd_ctl_elem_value *ucontrol)
  658. {
  659. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
  660. msm_slim_0_tx_ch);
  661. ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
  662. return 0;
  663. }
  664. static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
  665. struct snd_ctl_elem_value *ucontrol)
  666. {
  667. msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
  668. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
  669. msm_slim_0_tx_ch);
  670. return 1;
  671. }
  672. static int msm_slim_3_rx_ch_get(struct snd_kcontrol *kcontrol,
  673. struct snd_ctl_elem_value *ucontrol)
  674. {
  675. pr_debug("%s: msm_slim_3_rx_ch = %d\n", __func__,
  676. msm_slim_3_rx_ch);
  677. ucontrol->value.integer.value[0] = msm_slim_3_rx_ch - 1;
  678. return 0;
  679. }
  680. static int msm_slim_3_rx_ch_put(struct snd_kcontrol *kcontrol,
  681. struct snd_ctl_elem_value *ucontrol)
  682. {
  683. msm_slim_3_rx_ch = ucontrol->value.integer.value[0] + 1;
  684. pr_debug("%s: msm_slim_3_rx_ch = %d\n", __func__,
  685. msm_slim_3_rx_ch);
  686. return 1;
  687. }
  688. static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
  689. struct snd_ctl_elem_value *ucontrol)
  690. {
  691. pr_debug("%s: msm_btsco_rate = %d", __func__,
  692. msm_btsco_rate);
  693. ucontrol->value.integer.value[0] = msm_btsco_rate;
  694. return 0;
  695. }
  696. static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
  697. struct snd_ctl_elem_value *ucontrol)
  698. {
  699. switch (ucontrol->value.integer.value[0]) {
  700. case 8000:
  701. msm_btsco_rate = BTSCO_RATE_8KHZ;
  702. break;
  703. case 16000:
  704. msm_btsco_rate = BTSCO_RATE_16KHZ;
  705. break;
  706. default:
  707. msm_btsco_rate = BTSCO_RATE_8KHZ;
  708. break;
  709. }
  710. pr_debug("%s: msm_btsco_rate = %d\n", __func__,
  711. msm_btsco_rate);
  712. return 0;
  713. }
  714. static int msm_incall_rec_mode_get(struct snd_kcontrol *kcontrol,
  715. struct snd_ctl_elem_value *ucontrol)
  716. {
  717. ucontrol->value.integer.value[0] = rec_mode;
  718. return 0;
  719. }
  720. static int msm_incall_rec_mode_put(struct snd_kcontrol *kcontrol,
  721. struct snd_ctl_elem_value *ucontrol)
  722. {
  723. rec_mode = ucontrol->value.integer.value[0];
  724. pr_debug("%s: rec_mode:%d\n", __func__, rec_mode);
  725. return 0;
  726. }
  727. static const struct snd_kcontrol_new tabla_msm_controls[] = {
  728. SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
  729. msm_set_spk),
  730. SOC_ENUM_EXT("SLIM_0_RX Channels", msm_enum[1],
  731. msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
  732. SOC_ENUM_EXT("SLIM_0_TX Channels", msm_enum[2],
  733. msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
  734. SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
  735. msm_btsco_rate_get, msm_btsco_rate_put),
  736. SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
  737. msm_incall_rec_mode_get, msm_incall_rec_mode_put),
  738. SOC_ENUM_EXT("SLIM_3_RX Channels", msm_enum[1],
  739. msm_slim_3_rx_ch_get, msm_slim_3_rx_ch_put),
  740. };
  741. static int msm_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
  742. struct snd_ctl_elem_value *ucontrol)
  743. {
  744. pr_debug("%s: msm_mi2s_rx_ch = %d\n", __func__,
  745. msm_mi2s_rx_ch);
  746. ucontrol->value.integer.value[0] = msm_mi2s_rx_ch - 1;
  747. return 0;
  748. }
  749. static int msm_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
  750. struct snd_ctl_elem_value *ucontrol)
  751. {
  752. msm_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
  753. pr_debug("%s: msm_mi2s_rx_ch = %d\n", __func__,
  754. msm_mi2s_rx_ch);
  755. return 1;
  756. }
  757. static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
  758. struct snd_ctl_elem_value *ucontrol)
  759. {
  760. pr_debug("%s: msm_mi2s_tx_ch = %d\n", __func__,
  761. msm_mi2s_tx_ch);
  762. ucontrol->value.integer.value[0] = msm_mi2s_tx_ch - 1;
  763. return 0;
  764. }
  765. static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
  766. struct snd_ctl_elem_value *ucontrol)
  767. {
  768. msm_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
  769. pr_debug("%s: msm_mi2s_tx_ch = %d\n", __func__,
  770. msm_mi2s_tx_ch);
  771. return 1;
  772. }
  773. static int msm_mi2s_get_spk(struct snd_kcontrol *kcontrol,
  774. struct snd_ctl_elem_value *ucontrol)
  775. {
  776. pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
  777. ucontrol->value.integer.value[0] = msm_spk_control;
  778. return 0;
  779. }
  780. static int msm_mi2s_set_spk(struct snd_kcontrol *kcontrol,
  781. struct snd_ctl_elem_value *ucontrol)
  782. {
  783. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  784. pr_debug("%s()\n", __func__);
  785. if (msm_spk_control == ucontrol->value.integer.value[0])
  786. return 0;
  787. msm_spk_control = ucontrol->value.integer.value[0];
  788. msm_ext_control(codec);
  789. return 1;
  790. }
  791. static int msm_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  792. struct snd_pcm_hw_params *params)
  793. {
  794. struct snd_interval *channels = hw_param_interval(params,
  795. SNDRV_PCM_HW_PARAM_CHANNELS);
  796. pr_debug("%s(): channels = %d\n", __func__, msm_mi2s_rx_ch);
  797. channels->min = channels->max = msm_mi2s_rx_ch;
  798. return 0;
  799. }
  800. static int msm_mi2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  801. struct snd_pcm_hw_params *params)
  802. {
  803. struct snd_interval *channels = hw_param_interval(params,
  804. SNDRV_PCM_HW_PARAM_CHANNELS);
  805. pr_debug("%s(): channels = %d\n", __func__, msm_mi2s_tx_ch);
  806. channels->min = channels->max = msm_mi2s_tx_ch;
  807. return 0;
  808. }
  809. static int msm_i2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  810. struct snd_pcm_hw_params *params)
  811. {
  812. struct snd_interval *channels = hw_param_interval(params,
  813. SNDRV_PCM_HW_PARAM_CHANNELS);
  814. pr_debug("%s(): channels = %d\n", __func__, msm_i2s_rx_ch);
  815. channels->min = channels->max = msm_i2s_rx_ch;
  816. return 0;
  817. }
  818. static int msm_i2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  819. struct snd_pcm_hw_params *params)
  820. {
  821. struct snd_interval *channels = hw_param_interval(params,
  822. SNDRV_PCM_HW_PARAM_CHANNELS);
  823. pr_debug("%s(): channels = %d\n", __func__, msm_i2s_tx_ch);
  824. channels->min = channels->max = msm_i2s_tx_ch;
  825. return 0;
  826. }
  827. static const struct snd_kcontrol_new tabla_msm_mi2s_controls[] = {
  828. SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_mi2s_get_spk,
  829. msm_mi2s_set_spk),
  830. SOC_ENUM_EXT("MI2S_RX Channels", msm_enum[1],
  831. msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
  832. SOC_ENUM_EXT("MI2S_TX Channels", msm_enum[2],
  833. msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
  834. SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
  835. msm_btsco_rate_get, msm_btsco_rate_put),
  836. SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
  837. msm_incall_rec_mode_get, msm_incall_rec_mode_put),
  838. };
  839. static int msm_mi2s_audrx_init(struct snd_soc_pcm_runtime *rtd)
  840. {
  841. int ret;
  842. uint32_t revision;
  843. struct snd_soc_codec *codec = rtd->codec;
  844. struct snd_soc_dapm_context *dapm = &codec->dapm;
  845. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  846. struct pm_gpio param = {
  847. .direction = PM_GPIO_DIR_OUT,
  848. .output_buffer = PM_GPIO_OUT_BUF_CMOS,
  849. .output_value = 1,
  850. .pull = PM_GPIO_PULL_NO,
  851. .vin_sel = PM_GPIO_VIN_S4,
  852. .out_strength = PM_GPIO_STRENGTH_MED,
  853. .function = PM_GPIO_FUNC_NORMAL,
  854. };
  855. pr_debug("%s(), dev_name(%s)\n", __func__, dev_name(cpu_dai->dev));
  856. ret = gpio_request(GPIO_MI2S_MCLK, "MI2S_MCLK");
  857. if (ret)
  858. pr_err("%s: Failed to request gpio %d\n", __func__,
  859. GPIO_MI2S_MCLK);
  860. /* APQ provides the mclk to codec */
  861. ret = gpio_request(mdm_mclk_gpio, "MDM_MCLK_SWITCH");
  862. if (ret) {
  863. pr_err("%s: Failed to request gpio %d\n", __func__,
  864. mdm_mclk_gpio);
  865. return ret;
  866. }
  867. ret = pm8xxx_gpio_config(mdm_mclk_gpio, &param);
  868. if (ret)
  869. pr_err("%s: Failed to configure gpio %d\n", __func__,
  870. mdm_mclk_gpio);
  871. else
  872. gpio_direction_output(mdm_mclk_gpio, 0);
  873. pr_debug("%s: Config mdm_mclk_gpio\n", __func__);
  874. ret = gpio_request(apq_mclk_gpio, "APQ_MCLK_SWITCH");
  875. if (ret) {
  876. pr_err("%s: Failed to request gpio %d\n", __func__,
  877. apq_mclk_gpio);
  878. return ret;
  879. }
  880. ret = pm8xxx_gpio_config(apq_mclk_gpio, &param);
  881. if (ret)
  882. pr_err("%s: Failed to configure gpio %d\n", __func__,
  883. apq_mclk_gpio);
  884. else
  885. gpio_direction_output(apq_mclk_gpio, 1);
  886. pr_debug("%s: Config apq_mclk_gpio\n", __func__);
  887. snd_soc_dapm_new_controls(dapm, apq8064_dapm_widgets,
  888. ARRAY_SIZE(apq8064_dapm_widgets));
  889. snd_soc_dapm_add_routes(dapm, apq8064_common_audio_map,
  890. ARRAY_SIZE(apq8064_common_audio_map));
  891. if (machine_is_apq8064_mtp()) {
  892. snd_soc_dapm_add_routes(dapm, apq8064_mtp_audio_map,
  893. ARRAY_SIZE(apq8064_mtp_audio_map));
  894. } else {
  895. snd_soc_dapm_add_routes(dapm, apq8064_liquid_cdp_audio_map,
  896. ARRAY_SIZE(apq8064_liquid_cdp_audio_map));
  897. }
  898. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
  899. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
  900. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
  901. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
  902. snd_soc_dapm_sync(dapm);
  903. ret = snd_soc_jack_new(codec, "Headset Jack",
  904. (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
  905. SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
  906. &hs_jack);
  907. if (ret) {
  908. pr_err("failed to create new jack\n");
  909. return ret;
  910. }
  911. ret = snd_soc_jack_new(codec, "Button Jack",
  912. TABLA_JACK_BUTTON_MASK, &button_jack);
  913. if (ret) {
  914. pr_err("failed to create new jack\n");
  915. return ret;
  916. }
  917. /* Get the MCLK from MI2S block for MBHC calibration */
  918. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  919. pr_debug("%s: Device name is %s\n", __func__, dev_name(cpu_dai->dev));
  920. /* APQ8064 Rev 1.1 CDP and Liquid have mechanical switch */
  921. revision = socinfo_get_version();
  922. if (apq8064_i2s_hs_detect_use_gpio != -1) {
  923. if (apq8064_i2s_hs_detect_use_gpio == 1)
  924. pr_debug("%s: MBHC mechanical is enabled by request\n",
  925. __func__);
  926. else if (apq8064_i2s_hs_detect_use_gpio == 0)
  927. pr_debug("%s: MBHC mechanical is disabled by request\n",
  928. __func__);
  929. else
  930. pr_warn("%s: Invalid hs_detect_use_gpio %d\n", __func__,
  931. apq8064_i2s_hs_detect_use_gpio);
  932. } else if (SOCINFO_VERSION_MAJOR(revision) == 0) {
  933. pr_warn("%s: Unknown HW revision detected %d.%d\n", __func__,
  934. SOCINFO_VERSION_MAJOR(revision),
  935. SOCINFO_VERSION_MINOR(revision));
  936. } else if ((SOCINFO_VERSION_MAJOR(revision) == 1 &&
  937. SOCINFO_VERSION_MINOR(revision) >= 1 &&
  938. (machine_is_apq8064_cdp() ||
  939. machine_is_apq8064_liquid())) ||
  940. SOCINFO_VERSION_MAJOR(revision) > 1) {
  941. pr_debug("%s: MBHC mechanical switch available APQ8064 detected\n",
  942. __func__);
  943. apq8064_i2s_hs_detect_use_gpio = 1;
  944. }
  945. if (apq8064_i2s_hs_detect_use_gpio == 1) {
  946. pr_debug("%s: Using MBHC mechanical switch\n", __func__);
  947. mbhc_cfg.gpio = JACK_DETECT_GPIO;
  948. mbhc_cfg.gpio_irq = gpio_to_irq(JACK_DETECT_GPIO);
  949. ret = gpio_request(mbhc_cfg.gpio, "MBHC_HS_DETECT");
  950. if (ret < 0) {
  951. pr_err("%s: gpio_request %d failed %d\n", __func__,
  952. mbhc_cfg.gpio, ret);
  953. return ret;
  954. }
  955. gpio_direction_input(JACK_DETECT_GPIO);
  956. } else
  957. pr_debug("%s: Not using MBHC mechanical switch\n", __func__);
  958. mbhc_cfg.read_fw_bin = apq8064_i2s_hs_detect_use_firmware;
  959. ret = tabla_hs_detect(codec, &mbhc_cfg);
  960. /* MDM provides the mclk to codec */
  961. gpio_direction_output(apq_mclk_gpio, 0);
  962. gpio_direction_output(mdm_mclk_gpio, 1);
  963. pr_debug("%s: Clock switch to MDM\n", __func__);
  964. /* Should we add code to put back codec clock?*/
  965. gpio_free(GPIO_MI2S_MCLK);
  966. pr_debug("%s: Free MCLK GPIO\n", __func__);
  967. return ret;
  968. }
  969. static int msm_mi2s_free_gpios(void)
  970. {
  971. int i;
  972. for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++)
  973. gpio_free(mi2s_gpio[i].gpio_no);
  974. return 0;
  975. }
  976. static void msm_mi2s_shutdown(struct snd_pcm_substream *substream)
  977. {
  978. if (atomic_dec_return(&mi2s_rsc_ref) == 0) {
  979. pr_debug("%s: free mi2s resources\n", __func__);
  980. if (mi2s_bit_clk) {
  981. clk_disable_unprepare(mi2s_bit_clk);
  982. clk_put(mi2s_bit_clk);
  983. mi2s_bit_clk = NULL;
  984. }
  985. msm_mi2s_free_gpios();
  986. }
  987. }
  988. static int msm_configure_mi2s_gpio(void)
  989. {
  990. int rtn;
  991. int i;
  992. int j;
  993. for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++) {
  994. rtn = gpio_request(mi2s_gpio[i].gpio_no,
  995. mi2s_gpio[i].gpio_name);
  996. pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
  997. __func__,
  998. mi2s_gpio[i].gpio_no,
  999. mi2s_gpio[i].gpio_name,
  1000. rtn);
  1001. if (rtn) {
  1002. pr_err("%s: Failed to request gpio %d\n",
  1003. __func__,
  1004. mi2s_gpio[i].gpio_no);
  1005. for (j = i; j >= 0; j--)
  1006. gpio_free(mi2s_gpio[j].gpio_no);
  1007. goto err;
  1008. }
  1009. }
  1010. err:
  1011. return rtn;
  1012. }
  1013. static int msm_mi2s_startup(struct snd_pcm_substream *substream)
  1014. {
  1015. int ret = 0;
  1016. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1017. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1018. pr_debug("%s: dai name %s %p\n", __func__, cpu_dai->name, cpu_dai->dev);
  1019. if (atomic_inc_return(&mi2s_rsc_ref) == 1) {
  1020. pr_debug("%s: acquire mi2s resources\n", __func__);
  1021. msm_configure_mi2s_gpio();
  1022. pr_debug("%s: APQ is MI2S slave\n", __func__);
  1023. mi2s_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  1024. if (IS_ERR(mi2s_bit_clk))
  1025. return PTR_ERR(mi2s_bit_clk);
  1026. clk_set_rate(mi2s_bit_clk, 0);
  1027. ret = clk_prepare_enable(mi2s_bit_clk);
  1028. if (IS_ERR_VALUE(ret)) {
  1029. pr_err("Unable to enable mi2s_bit_clk\n");
  1030. clk_put(mi2s_bit_clk);
  1031. return ret;
  1032. }
  1033. ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
  1034. if (IS_ERR_VALUE(ret))
  1035. pr_err("set format for CPU dai failed\n");
  1036. }
  1037. return ret;
  1038. }
  1039. static int msm_i2s_rx_free_gpios(void)
  1040. {
  1041. int i;
  1042. for (i = 0; i < ARRAY_SIZE(spkr_i2s_gpio); i++)
  1043. gpio_free(spkr_i2s_gpio[i].gpio_no);
  1044. return 0;
  1045. }
  1046. static int msm_i2s_tx_free_gpios(void)
  1047. {
  1048. int i;
  1049. for (i = 0; i < ARRAY_SIZE(mic_i2s_gpio); i++)
  1050. gpio_free(mic_i2s_gpio[i].gpio_no);
  1051. return 0;
  1052. }
  1053. static void msm_i2s_shutdown(struct snd_pcm_substream *substream)
  1054. {
  1055. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1056. pr_debug("%s: free i2s rx resources\n", __func__);
  1057. if (i2s_rx_bit_clk) {
  1058. clk_disable_unprepare(i2s_rx_bit_clk);
  1059. clk_put(i2s_rx_bit_clk);
  1060. i2s_rx_bit_clk = NULL;
  1061. }
  1062. msm_i2s_rx_free_gpios();
  1063. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  1064. pr_debug("%s: free i2s tx resources\n", __func__);
  1065. if (i2s_tx_bit_clk) {
  1066. clk_disable_unprepare(i2s_tx_bit_clk);
  1067. clk_put(i2s_tx_bit_clk);
  1068. i2s_tx_bit_clk = NULL;
  1069. }
  1070. msm_i2s_tx_free_gpios();
  1071. }
  1072. }
  1073. static int msm_configure_i2s_rx_gpio(void)
  1074. {
  1075. int rtn;
  1076. int i;
  1077. int j;
  1078. for (i = 0; i < ARRAY_SIZE(spkr_i2s_gpio); i++) {
  1079. rtn = gpio_request(spkr_i2s_gpio[i].gpio_no,
  1080. spkr_i2s_gpio[i].gpio_name);
  1081. pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
  1082. __func__,
  1083. spkr_i2s_gpio[i].gpio_no,
  1084. spkr_i2s_gpio[i].gpio_name,
  1085. rtn);
  1086. if (rtn) {
  1087. pr_err("%s: Failed to request gpio %d\n",
  1088. __func__,
  1089. spkr_i2s_gpio[i].gpio_no);
  1090. for (j = i; j >= 0; j--)
  1091. gpio_free(spkr_i2s_gpio[j].gpio_no);
  1092. goto err;
  1093. }
  1094. }
  1095. err:
  1096. return rtn;
  1097. }
  1098. static int msm_configure_i2s_tx_gpio(void)
  1099. {
  1100. int rtn;
  1101. int i;
  1102. int j;
  1103. for (i = 0; i < ARRAY_SIZE(mic_i2s_gpio); i++) {
  1104. rtn = gpio_request(mic_i2s_gpio[i].gpio_no,
  1105. mic_i2s_gpio[i].gpio_name);
  1106. pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
  1107. __func__,
  1108. mic_i2s_gpio[i].gpio_no,
  1109. mic_i2s_gpio[i].gpio_name,
  1110. rtn);
  1111. if (rtn) {
  1112. pr_err("%s: Failed to request gpio %d\n",
  1113. __func__,
  1114. mic_i2s_gpio[i].gpio_no);
  1115. for (j = i; j >= 0; j--)
  1116. gpio_free(mic_i2s_gpio[j].gpio_no);
  1117. goto err;
  1118. }
  1119. }
  1120. err:
  1121. return rtn;
  1122. }
  1123. static int msm_i2s_startup(struct snd_pcm_substream *substream)
  1124. {
  1125. int ret = 0;
  1126. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1127. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1128. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1129. msm_configure_i2s_rx_gpio();
  1130. i2s_rx_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  1131. if (IS_ERR(i2s_rx_bit_clk)) {
  1132. pr_err("Failed to get i2s bit_clk\n");
  1133. return PTR_ERR(i2s_rx_bit_clk);
  1134. }
  1135. clk_set_rate(i2s_rx_bit_clk, 0);
  1136. ret = clk_prepare_enable(i2s_rx_bit_clk);
  1137. if (IS_ERR_VALUE(ret)) {
  1138. pr_err("Unable to enable i2s_rx_bit_clk\n");
  1139. clk_put(i2s_rx_bit_clk);
  1140. return ret;
  1141. }
  1142. ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
  1143. if (IS_ERR_VALUE(ret))
  1144. pr_err("set format for CPU dai failed\n");
  1145. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  1146. msm_configure_i2s_tx_gpio();
  1147. i2s_tx_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
  1148. if (IS_ERR(i2s_tx_bit_clk)) {
  1149. pr_err("Failed to get i2s_tx_bit_clk\n");
  1150. return PTR_ERR(i2s_tx_bit_clk);
  1151. }
  1152. clk_set_rate(i2s_tx_bit_clk, 0);
  1153. ret = clk_prepare_enable(i2s_tx_bit_clk);
  1154. if (ret != 0) {
  1155. pr_err("Unable to enable i2s_tx_bit_clk\n");
  1156. clk_put(i2s_tx_bit_clk);
  1157. return ret;
  1158. }
  1159. ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
  1160. if (IS_ERR_VALUE(ret))
  1161. pr_err("set format for CPU dai failed\n");
  1162. }
  1163. pr_debug("%s: ret = %d\n", __func__, ret);
  1164. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1165. substream->name, substream->stream);
  1166. return ret;
  1167. }
  1168. static void *def_tabla_mbhc_cal(void)
  1169. {
  1170. void *tabla_cal;
  1171. struct tabla_mbhc_btn_detect_cfg *btn_cfg;
  1172. u16 *btn_low, *btn_high;
  1173. u8 *n_ready, *n_cic, *gain;
  1174. tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
  1175. TABLA_MBHC_DEF_RLOADS),
  1176. GFP_KERNEL);
  1177. if (!tabla_cal) {
  1178. pr_err("%s: out of memory\n", __func__);
  1179. return NULL;
  1180. }
  1181. #define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
  1182. S(t_ldoh, 100);
  1183. S(t_bg_fast_settle, 100);
  1184. S(t_shutdown_plug_rem, 255);
  1185. S(mbhc_nsa, 4);
  1186. S(mbhc_navg, 4);
  1187. #undef S
  1188. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
  1189. S(mic_current, TABLA_PID_MIC_5_UA);
  1190. S(hph_current, TABLA_PID_MIC_5_UA);
  1191. S(t_mic_pid, 100);
  1192. S(t_ins_complete, 250);
  1193. S(t_ins_retry, 200);
  1194. #undef S
  1195. #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
  1196. S(v_no_mic, 30);
  1197. S(v_hs_max, 1550);
  1198. #undef S
  1199. #define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
  1200. S(c[0], 62);
  1201. S(c[1], 124);
  1202. S(nc, 1);
  1203. S(n_meas, 3);
  1204. S(mbhc_nsc, 11);
  1205. S(n_btn_meas, 1);
  1206. S(n_btn_con, 2);
  1207. S(num_btn, TABLA_MBHC_DEF_BUTTONS);
  1208. S(v_btn_press_delta_sta, 100);
  1209. S(v_btn_press_delta_cic, 50);
  1210. #undef S
  1211. btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
  1212. btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
  1213. btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
  1214. btn_low[0] = -50;
  1215. btn_high[0] = 10;
  1216. btn_low[1] = 11;
  1217. btn_high[1] = 38;
  1218. btn_low[2] = 39;
  1219. btn_high[2] = 64;
  1220. btn_low[3] = 65;
  1221. btn_high[3] = 91;
  1222. btn_low[4] = 92;
  1223. btn_high[4] = 115;
  1224. btn_low[5] = 116;
  1225. btn_high[5] = 141;
  1226. btn_low[6] = 142;
  1227. btn_high[6] = 163;
  1228. btn_low[7] = 164;
  1229. btn_high[7] = 250;
  1230. n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
  1231. n_ready[0] = 48;
  1232. n_ready[1] = 38;
  1233. n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
  1234. n_cic[0] = 60;
  1235. n_cic[1] = 47;
  1236. gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
  1237. gain[0] = 11;
  1238. gain[1] = 9;
  1239. return tabla_cal;
  1240. }
  1241. static int msm_hw_params(struct snd_pcm_substream *substream,
  1242. struct snd_pcm_hw_params *params)
  1243. {
  1244. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1245. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1246. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1247. int ret = 0;
  1248. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  1249. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  1250. unsigned int num_tx_ch = 0;
  1251. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1252. pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch);
  1253. ret = snd_soc_dai_get_channel_map(codec_dai,
  1254. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1255. if (ret < 0) {
  1256. pr_err("%s: failed to get codec chan map\n", __func__);
  1257. goto end;
  1258. }
  1259. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  1260. msm_slim_0_rx_ch, rx_ch);
  1261. if (ret < 0) {
  1262. pr_err("%s: failed to set cpu chan map\n", __func__);
  1263. goto end;
  1264. }
  1265. ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
  1266. msm_slim_0_rx_ch, rx_ch);
  1267. if (ret < 0) {
  1268. pr_err("%s: failed to set codec channel map\n",
  1269. __func__);
  1270. goto end;
  1271. }
  1272. } else {
  1273. if (codec_dai->id == 2)
  1274. num_tx_ch = msm_slim_0_tx_ch;
  1275. else if (codec_dai->id == 5) {
  1276. /* DAI 5 is used for external EC reference from codec.
  1277. * Since Rx is fed as reference for EC, the config of
  1278. * this DAI is based on that of the Rx path.
  1279. */
  1280. num_tx_ch = msm_slim_0_rx_ch;
  1281. }
  1282. pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
  1283. codec_dai->name, codec_dai->id, num_tx_ch);
  1284. ret = snd_soc_dai_get_channel_map(codec_dai,
  1285. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1286. if (ret < 0) {
  1287. pr_err("%s: failed to get codec chan map\n", __func__);
  1288. goto end;
  1289. }
  1290. ret = snd_soc_dai_set_channel_map(cpu_dai,
  1291. num_tx_ch, tx_ch, 0 , 0);
  1292. if (ret < 0) {
  1293. pr_err("%s: failed to set cpu chan map\n", __func__);
  1294. goto end;
  1295. }
  1296. ret = snd_soc_dai_set_channel_map(codec_dai,
  1297. num_tx_ch, tx_ch, 0, 0);
  1298. if (ret < 0) {
  1299. pr_err("%s: failed to set codec channel map\n",
  1300. __func__);
  1301. goto end;
  1302. }
  1303. }
  1304. end:
  1305. return ret;
  1306. }
  1307. static int msm_stubrx_init(struct snd_soc_pcm_runtime *rtd)
  1308. {
  1309. rtd->pmdown_time = 0;
  1310. return 0;
  1311. }
  1312. static int msm_slimbus_2_hw_params(struct snd_pcm_substream *substream,
  1313. struct snd_pcm_hw_params *params)
  1314. {
  1315. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1316. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1317. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1318. int ret = 0;
  1319. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  1320. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  1321. unsigned int num_tx_ch = 0;
  1322. unsigned int num_rx_ch = 0;
  1323. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1324. num_rx_ch = params_channels(params);
  1325. pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
  1326. codec_dai->name, codec_dai->id, num_rx_ch);
  1327. ret = snd_soc_dai_get_channel_map(codec_dai,
  1328. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1329. if (ret < 0) {
  1330. pr_err("%s: failed to get codec chan map\n", __func__);
  1331. goto end;
  1332. }
  1333. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  1334. num_rx_ch, rx_ch);
  1335. if (ret < 0) {
  1336. pr_err("%s: failed to set cpu chan map\n", __func__);
  1337. goto end;
  1338. }
  1339. ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
  1340. num_rx_ch, rx_ch);
  1341. if (ret < 0) {
  1342. pr_err("%s: failed to set codec channel map\n",
  1343. __func__);
  1344. goto end;
  1345. }
  1346. } else {
  1347. num_tx_ch = params_channels(params);
  1348. pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
  1349. codec_dai->name, codec_dai->id, num_tx_ch);
  1350. ret = snd_soc_dai_get_channel_map(codec_dai,
  1351. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1352. if (ret < 0) {
  1353. pr_err("%s: failed to get codec chan map\n", __func__);
  1354. goto end;
  1355. }
  1356. ret = snd_soc_dai_set_channel_map(cpu_dai,
  1357. num_tx_ch, tx_ch, 0 , 0);
  1358. if (ret < 0) {
  1359. pr_err("%s: failed to set cpu chan map\n", __func__);
  1360. goto end;
  1361. }
  1362. ret = snd_soc_dai_set_channel_map(codec_dai,
  1363. num_tx_ch, tx_ch, 0, 0);
  1364. if (ret < 0) {
  1365. pr_err("%s: failed to set codec channel map\n",
  1366. __func__);
  1367. goto end;
  1368. }
  1369. }
  1370. end:
  1371. return ret;
  1372. }
  1373. static int msm_slimbus_1_hw_params(struct snd_pcm_substream *substream,
  1374. struct snd_pcm_hw_params *params)
  1375. {
  1376. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1377. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1378. int ret = 0;
  1379. unsigned int rx_ch = SLIM_1_RX_1, tx_ch = SLIM_1_TX_1;
  1380. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1381. pr_debug("%s: APQ BT/USB TX -> SLIMBUS_1_RX -> MDM TX shared ch %d\n",
  1382. __func__, rx_ch);
  1383. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
  1384. if (ret < 0) {
  1385. pr_err("%s: Erorr %d setting SLIM_1 RX channel map\n",
  1386. __func__, ret);
  1387. goto end;
  1388. }
  1389. } else {
  1390. pr_debug("%s: MDM RX -> SLIMBUS_1_TX -> APQ BT/USB Rx shared ch %d\n",
  1391. __func__, tx_ch);
  1392. ret = snd_soc_dai_set_channel_map(cpu_dai, 1, &tx_ch, 0, 0);
  1393. if (ret < 0) {
  1394. pr_err("%s: Erorr %d setting SLIM_1 TX channel map\n",
  1395. __func__, ret);
  1396. goto end;
  1397. }
  1398. }
  1399. end:
  1400. return ret;
  1401. }
  1402. static int msm_slimbus_3_hw_params(struct snd_pcm_substream *substream,
  1403. struct snd_pcm_hw_params *params)
  1404. {
  1405. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1406. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1407. int ret = 0;
  1408. unsigned int rx_ch[2] = {SLIM_3_RX_1, SLIM_3_RX_2};
  1409. unsigned int tx_ch[2] = {SLIM_3_TX_1, SLIM_3_TX_2};
  1410. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1411. pr_debug("%s: slim_3_rx_ch %d, sch %d %d\n",
  1412. __func__, msm_slim_3_rx_ch,
  1413. rx_ch[0], rx_ch[1]);
  1414. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  1415. msm_slim_3_rx_ch, rx_ch);
  1416. if (ret < 0) {
  1417. pr_err("%s: Erorr %d setting SLIM_3 RX channel map\n",
  1418. __func__, ret);
  1419. goto end;
  1420. }
  1421. } else {
  1422. pr_debug("%s: MDM RX -> SLIMBUS_3_TX -> APQ HDMI ch: %d, %d\n",
  1423. __func__, tx_ch[0], tx_ch[1]);
  1424. ret = snd_soc_dai_set_channel_map(cpu_dai, 2, tx_ch, 0, 0);
  1425. if (ret < 0) {
  1426. pr_err("%s: Erorr %d setting SLIM_3 TX channel map\n",
  1427. __func__, ret);
  1428. goto end;
  1429. }
  1430. }
  1431. end:
  1432. return ret;
  1433. }
  1434. static int msm_slimbus_4_hw_params(struct snd_pcm_substream *substream,
  1435. struct snd_pcm_hw_params *params)
  1436. {
  1437. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1438. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1439. int ret = 0;
  1440. unsigned int rx_ch = SLIM_4_RX_1, tx_ch[2];
  1441. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1442. pr_debug("%s: APQ Incall Playback SLIMBUS_4_RX -> MDM TX shared ch %d\n",
  1443. __func__, rx_ch);
  1444. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
  1445. if (ret < 0) {
  1446. pr_err("%s: Erorr %d setting SLIM_4 RX channel map\n",
  1447. __func__, ret);
  1448. }
  1449. } else {
  1450. if (rec_mode == INCALL_REC_STEREO) {
  1451. tx_ch[0] = SLIM_4_TX_1;
  1452. tx_ch[1] = SLIM_4_TX_2;
  1453. ret = snd_soc_dai_set_channel_map(cpu_dai, 2,
  1454. tx_ch, 0, 0);
  1455. } else {
  1456. tx_ch[0] = SLIM_4_TX_1;
  1457. ret = snd_soc_dai_set_channel_map(cpu_dai, 1,
  1458. tx_ch, 0, 0);
  1459. }
  1460. pr_debug("%s: Incall Record shared tx_ch[0]:%d, tx_ch[1]:%d\n",
  1461. __func__, tx_ch[0], tx_ch[1]);
  1462. if (ret < 0) {
  1463. pr_err("%s: Erorr %d setting SLIM_4 TX channel map\n",
  1464. __func__, ret);
  1465. }
  1466. }
  1467. return ret;
  1468. }
  1469. static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
  1470. {
  1471. int err;
  1472. uint32_t revision;
  1473. struct snd_soc_codec *codec = rtd->codec;
  1474. struct snd_soc_dapm_context *dapm = &codec->dapm;
  1475. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1476. pr_debug("%s(), dev_name(%s)\n", __func__, dev_name(cpu_dai->dev));
  1477. /*if (machine_is_msm_liquid()) {
  1478. top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
  1479. bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
  1480. }*/
  1481. snd_soc_dapm_new_controls(dapm, apq8064_dapm_widgets,
  1482. ARRAY_SIZE(apq8064_dapm_widgets));
  1483. snd_soc_dapm_add_routes(dapm, apq8064_common_audio_map,
  1484. ARRAY_SIZE(apq8064_common_audio_map));
  1485. if (machine_is_apq8064_mtp()) {
  1486. snd_soc_dapm_add_routes(dapm, apq8064_mtp_audio_map,
  1487. ARRAY_SIZE(apq8064_mtp_audio_map));
  1488. } else {
  1489. snd_soc_dapm_add_routes(dapm, apq8064_liquid_cdp_audio_map,
  1490. ARRAY_SIZE(apq8064_liquid_cdp_audio_map));
  1491. }
  1492. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
  1493. snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
  1494. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
  1495. snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
  1496. snd_soc_dapm_sync(dapm);
  1497. err = snd_soc_jack_new(codec, "Headset Jack",
  1498. (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
  1499. SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
  1500. &hs_jack);
  1501. if (err) {
  1502. pr_err("failed to create new jack\n");
  1503. return err;
  1504. }
  1505. err = snd_soc_jack_new(codec, "Button Jack",
  1506. TABLA_JACK_BUTTON_MASK, &button_jack);
  1507. if (err) {
  1508. pr_err("failed to create new jack\n");
  1509. return err;
  1510. }
  1511. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  1512. /* APQ8064 Rev 1.1 CDP and Liquid have mechanical switch */
  1513. revision = socinfo_get_version();
  1514. if (apq8064_i2s_hs_detect_use_gpio != -1) {
  1515. if (apq8064_i2s_hs_detect_use_gpio == 1)
  1516. pr_debug("%s: MBHC mechanical is enabled by request\n",
  1517. __func__);
  1518. else if (apq8064_i2s_hs_detect_use_gpio == 0)
  1519. pr_debug("%s: MBHC mechanical is disabled by request\n",
  1520. __func__);
  1521. else
  1522. pr_warn("%s: Invalid hs_detect_use_gpio %d\n", __func__,
  1523. apq8064_i2s_hs_detect_use_gpio);
  1524. } else if (SOCINFO_VERSION_MAJOR(revision) == 0) {
  1525. pr_warn("%s: Unknown HW revision detected %d.%d\n", __func__,
  1526. SOCINFO_VERSION_MAJOR(revision),
  1527. SOCINFO_VERSION_MINOR(revision));
  1528. } else if ((SOCINFO_VERSION_MAJOR(revision) == 1 &&
  1529. SOCINFO_VERSION_MINOR(revision) >= 1 &&
  1530. (machine_is_apq8064_cdp() ||
  1531. machine_is_apq8064_liquid())) ||
  1532. SOCINFO_VERSION_MAJOR(revision) > 1) {
  1533. pr_debug("%s: MBHC mechanical switch available APQ8064 detected\n",
  1534. __func__);
  1535. apq8064_i2s_hs_detect_use_gpio = 1;
  1536. }
  1537. if (apq8064_i2s_hs_detect_use_gpio == 1) {
  1538. pr_debug("%s: Using MBHC mechanical switch\n", __func__);
  1539. mbhc_cfg.gpio = JACK_DETECT_GPIO;
  1540. mbhc_cfg.gpio_irq = gpio_to_irq(JACK_DETECT_GPIO);
  1541. err = gpio_request(mbhc_cfg.gpio, "MBHC_HS_DETECT");
  1542. if (err < 0) {
  1543. pr_err("%s: gpio_request %d failed %d\n", __func__,
  1544. mbhc_cfg.gpio, err);
  1545. return err;
  1546. }
  1547. gpio_direction_input(JACK_DETECT_GPIO);
  1548. } else
  1549. pr_debug("%s: Not using MBHC mechanical switch\n", __func__);
  1550. mbhc_cfg.read_fw_bin = apq8064_i2s_hs_detect_use_firmware;
  1551. err = tabla_hs_detect(codec, &mbhc_cfg);
  1552. return err;
  1553. }
  1554. static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1555. struct snd_pcm_hw_params *params)
  1556. {
  1557. struct snd_interval *rate = hw_param_interval(params,
  1558. SNDRV_PCM_HW_PARAM_RATE);
  1559. struct snd_interval *channels = hw_param_interval(params,
  1560. SNDRV_PCM_HW_PARAM_CHANNELS);
  1561. pr_debug("%s()\n", __func__);
  1562. rate->min = rate->max = 48000;
  1563. channels->min = channels->max = msm_slim_0_rx_ch;
  1564. return 0;
  1565. }
  1566. static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1567. struct snd_pcm_hw_params *params)
  1568. {
  1569. struct snd_interval *rate = hw_param_interval(params,
  1570. SNDRV_PCM_HW_PARAM_RATE);
  1571. struct snd_interval *channels = hw_param_interval(params,
  1572. SNDRV_PCM_HW_PARAM_CHANNELS);
  1573. pr_debug("%s()\n", __func__);
  1574. rate->min = rate->max = 48000;
  1575. channels->min = channels->max = msm_slim_0_tx_ch;
  1576. return 0;
  1577. }
  1578. static int msm_slim_3_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1579. struct snd_pcm_hw_params *params)
  1580. {
  1581. struct snd_interval *rate = hw_param_interval(params,
  1582. SNDRV_PCM_HW_PARAM_RATE);
  1583. struct snd_interval *channels = hw_param_interval(params,
  1584. SNDRV_PCM_HW_PARAM_CHANNELS);
  1585. pr_debug("%s()\n", __func__);
  1586. rate->min = rate->max = 48000;
  1587. channels->min = channels->max = msm_slim_3_rx_ch;
  1588. return 0;
  1589. }
  1590. static int msm_slim_3_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1591. struct snd_pcm_hw_params *params)
  1592. {
  1593. struct snd_interval *rate = hw_param_interval(params,
  1594. SNDRV_PCM_HW_PARAM_RATE);
  1595. struct snd_interval *channels = hw_param_interval(params,
  1596. SNDRV_PCM_HW_PARAM_CHANNELS);
  1597. pr_debug("%s()\n", __func__);
  1598. rate->min = rate->max = 48000;
  1599. channels->min = channels->max = 2;
  1600. return 0;
  1601. }
  1602. static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1603. struct snd_pcm_hw_params *params)
  1604. {
  1605. struct snd_interval *rate = hw_param_interval(params,
  1606. SNDRV_PCM_HW_PARAM_RATE);
  1607. pr_debug("%s()\n", __func__);
  1608. rate->min = rate->max = 48000;
  1609. return 0;
  1610. }
  1611. static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1612. struct snd_pcm_hw_params *params)
  1613. {
  1614. struct snd_interval *rate = hw_param_interval(params,
  1615. SNDRV_PCM_HW_PARAM_RATE);
  1616. struct snd_interval *channels = hw_param_interval(params,
  1617. SNDRV_PCM_HW_PARAM_CHANNELS);
  1618. pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
  1619. channels->min, channels->max);
  1620. rate->min = rate->max = 48000;
  1621. return 0;
  1622. }
  1623. static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1624. struct snd_pcm_hw_params *params)
  1625. {
  1626. struct snd_interval *rate = hw_param_interval(params,
  1627. SNDRV_PCM_HW_PARAM_RATE);
  1628. struct snd_interval *channels = hw_param_interval(params,
  1629. SNDRV_PCM_HW_PARAM_CHANNELS);
  1630. rate->min = rate->max = msm_btsco_rate;
  1631. channels->min = channels->max = msm_btsco_ch;
  1632. return 0;
  1633. }
  1634. static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1635. struct snd_pcm_hw_params *params)
  1636. {
  1637. struct snd_interval *rate = hw_param_interval(params,
  1638. SNDRV_PCM_HW_PARAM_RATE);
  1639. struct snd_interval *channels = hw_param_interval(params,
  1640. SNDRV_PCM_HW_PARAM_CHANNELS);
  1641. /* PCM only supports mono output with 8khz sample rate */
  1642. rate->min = rate->max = 8000;
  1643. channels->min = channels->max = 1;
  1644. return 0;
  1645. }
  1646. static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  1647. struct snd_pcm_hw_params *params)
  1648. {
  1649. struct snd_interval *rate = hw_param_interval(params,
  1650. SNDRV_PCM_HW_PARAM_RATE);
  1651. pr_debug("%s()\n", __func__);
  1652. rate->min = rate->max = 48000;
  1653. return 0;
  1654. }
  1655. static int msm_aux_pcm_get_gpios(void)
  1656. {
  1657. return 0;
  1658. }
  1659. static int msm_aux_pcm_free_gpios(void)
  1660. {
  1661. return 0;
  1662. }
  1663. static int msm_startup(struct snd_pcm_substream *substream)
  1664. {
  1665. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1666. pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
  1667. __func__, rtd->dai_link->stream_name,
  1668. rtd->dai_link->cpu_dai_name,
  1669. rtd->dai_link->codec_dai_name);
  1670. return 0;
  1671. }
  1672. static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
  1673. {
  1674. int ret = 0;
  1675. pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
  1676. __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
  1677. if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
  1678. ret = msm_aux_pcm_get_gpios();
  1679. if (ret < 0) {
  1680. pr_err("%s: Aux PCM GPIO request failed\n", __func__);
  1681. return -EINVAL;
  1682. }
  1683. return 0;
  1684. }
  1685. static int msm_slimbus_1_startup(struct snd_pcm_substream *substream)
  1686. {
  1687. struct slim_controller *slim = slim_busnum_to_ctrl(1);
  1688. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1689. substream->name, substream->stream);
  1690. if (slim != NULL)
  1691. pm_runtime_get_sync(slim->dev.parent);
  1692. return 0;
  1693. }
  1694. static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
  1695. {
  1696. pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
  1697. __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
  1698. if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
  1699. msm_aux_pcm_free_gpios();
  1700. }
  1701. static void msm_shutdown(struct snd_pcm_substream *substream)
  1702. {
  1703. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1704. pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
  1705. __func__, rtd->dai_link->stream_name,
  1706. rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
  1707. }
  1708. static void msm_slimbus_1_shutdown(struct snd_pcm_substream *substream)
  1709. {
  1710. struct slim_controller *slim = slim_busnum_to_ctrl(1);
  1711. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1712. substream->name, substream->stream);
  1713. if (slim != NULL) {
  1714. pm_runtime_mark_last_busy(slim->dev.parent);
  1715. pm_runtime_put(slim->dev.parent);
  1716. }
  1717. }
  1718. static struct snd_soc_ops msm_be_ops = {
  1719. .startup = msm_startup,
  1720. .hw_params = msm_hw_params,
  1721. .shutdown = msm_shutdown,
  1722. };
  1723. static struct snd_soc_ops msm_auxpcm_be_ops = {
  1724. .startup = msm_auxpcm_startup,
  1725. .shutdown = msm_auxpcm_shutdown,
  1726. };
  1727. static struct snd_soc_ops msm_slimbus_1_be_ops = {
  1728. .startup = msm_slimbus_1_startup,
  1729. .hw_params = msm_slimbus_1_hw_params,
  1730. .shutdown = msm_slimbus_1_shutdown,
  1731. };
  1732. static struct snd_soc_ops msm_slimbus_3_be_ops = {
  1733. .startup = msm_startup,
  1734. .hw_params = msm_slimbus_3_hw_params,
  1735. .shutdown = msm_shutdown,
  1736. };
  1737. static struct snd_soc_ops msm_slimbus_4_be_ops = {
  1738. .startup = msm_startup,
  1739. .hw_params = msm_slimbus_4_hw_params,
  1740. .shutdown = msm_shutdown,
  1741. };
  1742. static struct snd_soc_ops msm_slimbus_2_be_ops = {
  1743. .startup = msm_startup,
  1744. .hw_params = msm_slimbus_2_hw_params,
  1745. .shutdown = msm_shutdown,
  1746. };
  1747. static struct snd_soc_ops msm_mi2s_be_ops = {
  1748. .startup = msm_mi2s_startup,
  1749. .shutdown = msm_mi2s_shutdown,
  1750. };
  1751. static struct snd_soc_ops msm_i2s_be_ops = {
  1752. .startup = msm_i2s_startup,
  1753. .shutdown = msm_i2s_shutdown,
  1754. };
  1755. static struct snd_soc_dai_link msm_dai_delta_mi2s[] = {
  1756. /* Backend DAI Links */
  1757. {
  1758. .name = LPASS_BE_MI2S_RX,
  1759. .stream_name = "MI2S Playback",
  1760. .cpu_dai_name = "msm-dai-q6-mi2s",
  1761. .platform_name = "msm-pcm-routing",
  1762. .codec_name = "tabla_codec",
  1763. .codec_dai_name = "tabla_i2s_rx1",
  1764. .no_pcm = 1,
  1765. .be_id = MSM_BACKEND_DAI_MI2S_RX,
  1766. .init = &msm_mi2s_audrx_init,
  1767. .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
  1768. .ops = &msm_mi2s_be_ops,
  1769. .ignore_pmdown_time = 1, /* Playback support */
  1770. },
  1771. {
  1772. .name = LPASS_BE_MI2S_TX,
  1773. .stream_name = "MI2S Capture",
  1774. .cpu_dai_name = "msm-dai-q6-mi2s",
  1775. .platform_name = "msm-pcm-routing",
  1776. .codec_name = "tabla_codec",
  1777. .codec_dai_name = "tabla_i2s_tx1",
  1778. .no_pcm = 1,
  1779. .be_id = MSM_BACKEND_DAI_MI2S_TX,
  1780. .be_hw_params_fixup = msm_mi2s_tx_be_hw_params_fixup,
  1781. .ops = &msm_mi2s_be_ops,
  1782. },
  1783. {
  1784. .name = LPASS_BE_PRI_I2S_RX,
  1785. .stream_name = "Primary I2S Playback",
  1786. .cpu_dai_name = "msm-dai-q6.0",
  1787. .platform_name = "msm-pcm-routing",
  1788. .codec_name = "msm-stub-codec.1",
  1789. .codec_dai_name = "msm-stub-rx",
  1790. .no_pcm = 1,
  1791. .be_id = MSM_BACKEND_DAI_PRI_I2S_RX,
  1792. .be_hw_params_fixup = msm_i2s_rx_be_hw_params_fixup,
  1793. .ops = &msm_i2s_be_ops,
  1794. },
  1795. {
  1796. .name = LPASS_BE_PRI_I2S_TX,
  1797. .stream_name = "Primary I2S Capture",
  1798. .cpu_dai_name = "msm-dai-q6.1",
  1799. .platform_name = "msm-pcm-routing",
  1800. .codec_name = "msm-stub-codec.1",
  1801. .codec_dai_name = "msm-stub-tx",
  1802. .no_pcm = 1,
  1803. .be_id = MSM_BACKEND_DAI_PRI_I2S_TX,
  1804. .be_hw_params_fixup = msm_i2s_tx_be_hw_params_fixup,
  1805. .ops = &msm_i2s_be_ops,
  1806. },
  1807. };
  1808. static struct snd_soc_dai_link msm_dai_delta_slim[] = {
  1809. /* Hostless PMC purpose */
  1810. {
  1811. .name = "SLIMBUS_0 Hostless",
  1812. .stream_name = "SLIMBUS_0 Hostless",
  1813. .cpu_dai_name = "SLIMBUS0_HOSTLESS",
  1814. .platform_name = "msm-pcm-hostless",
  1815. .dynamic = 1,
  1816. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1817. SND_SOC_DPCM_TRIGGER_POST},
  1818. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1819. .ignore_suspend = 1,
  1820. .ignore_pmdown_time = 1, /* Playback support */
  1821. .codec_dai_name = "snd-soc-dummy-dai",
  1822. .codec_name = "snd-soc-dummy",
  1823. /* .be_id = do not care */
  1824. },
  1825. /* Backend DAI Links */
  1826. {
  1827. .name = LPASS_BE_SLIMBUS_0_RX,
  1828. .stream_name = "Slimbus Playback",
  1829. .cpu_dai_name = "msm-dai-q6.16384",
  1830. .platform_name = "msm-pcm-routing",
  1831. .codec_name = "tabla_codec",
  1832. .codec_dai_name = "tabla_rx1",
  1833. .no_pcm = 1,
  1834. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
  1835. .init = &msm_audrx_init,
  1836. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1837. .ops = &msm_be_ops,
  1838. .ignore_pmdown_time = 1, /* Playback support */
  1839. },
  1840. {
  1841. .name = LPASS_BE_SLIMBUS_0_TX,
  1842. .stream_name = "Slimbus Capture",
  1843. .cpu_dai_name = "msm-dai-q6.16385",
  1844. .platform_name = "msm-pcm-routing",
  1845. .codec_name = "tabla_codec",
  1846. .codec_dai_name = "tabla_tx1",
  1847. .no_pcm = 1,
  1848. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
  1849. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1850. .ops = &msm_be_ops,
  1851. },
  1852. {
  1853. .name = LPASS_BE_STUB_RX,
  1854. .stream_name = "Stub Playback",
  1855. .cpu_dai_name = "msm-dai-stub",
  1856. .platform_name = "msm-pcm-routing",
  1857. .codec_name = "tabla_codec",
  1858. .codec_dai_name = "tabla_rx2",
  1859. .no_pcm = 1,
  1860. .be_id = MSM_BACKEND_DAI_EXTPROC_RX,
  1861. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1862. .init = &msm_stubrx_init,
  1863. .ops = &msm_be_ops,
  1864. .ignore_pmdown_time = 1, /* Playback support */
  1865. },
  1866. {
  1867. .name = LPASS_BE_STUB_TX,
  1868. .stream_name = "Stub Capture",
  1869. .cpu_dai_name = "msm-dai-stub",
  1870. .platform_name = "msm-pcm-routing",
  1871. .codec_name = "tabla_codec",
  1872. .codec_dai_name = "tabla_tx1",
  1873. .no_pcm = 1,
  1874. .be_id = MSM_BACKEND_DAI_EXTPROC_TX,
  1875. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1876. .ops = &msm_be_ops,
  1877. },
  1878. {
  1879. .name = LPASS_BE_SLIMBUS_1_RX,
  1880. .stream_name = "Slimbus1 Playback",
  1881. .cpu_dai_name = "msm-dai-q6.16386",
  1882. .platform_name = "msm-pcm-routing",
  1883. .codec_name = "msm-stub-codec.1",
  1884. .codec_dai_name = "msm-stub-rx",
  1885. .no_pcm = 1,
  1886. .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
  1887. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  1888. .ops = &msm_slimbus_1_be_ops,
  1889. .ignore_pmdown_time = 1, /* Playback support */
  1890. },
  1891. {
  1892. .name = LPASS_BE_SLIMBUS_1_TX,
  1893. .stream_name = "Slimbus1 Capture",
  1894. .cpu_dai_name = "msm-dai-q6.16387",
  1895. .platform_name = "msm-pcm-routing",
  1896. .codec_name = "msm-stub-codec.1",
  1897. .codec_dai_name = "msm-stub-tx",
  1898. .no_pcm = 1,
  1899. .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
  1900. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  1901. .ops = &msm_slimbus_1_be_ops,
  1902. },
  1903. /* Ultrasound TX Back End DAI Link */
  1904. {
  1905. .name = "SLIMBUS_2 Hostless Capture",
  1906. .stream_name = "SLIMBUS_2 Hostless Capture",
  1907. .cpu_dai_name = "msm-dai-q6.16389",
  1908. .platform_name = "msm-pcm-hostless",
  1909. .codec_name = "tabla_codec",
  1910. .codec_dai_name = "tabla_tx2",
  1911. .ignore_suspend = 1,
  1912. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1913. .ops = &msm_slimbus_2_be_ops,
  1914. },
  1915. /* Ultrasound RX Back End DAI Link */
  1916. {
  1917. .name = "SLIMBUS_2 Hostless Playback",
  1918. .stream_name = "SLIMBUS_2 Hostless Playback",
  1919. .cpu_dai_name = "msm-dai-q6.16388",
  1920. .platform_name = "msm-pcm-hostless",
  1921. .codec_name = "tabla_codec",
  1922. .codec_dai_name = "tabla_rx3",
  1923. .ignore_suspend = 1,
  1924. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1925. .ops = &msm_slimbus_2_be_ops,
  1926. },
  1927. /* Incall Music Back End DAI Link */
  1928. {
  1929. .name = LPASS_BE_SLIMBUS_4_RX,
  1930. .stream_name = "Slimbus4 Playback",
  1931. .cpu_dai_name = "msm-dai-q6.16392",
  1932. .platform_name = "msm-pcm-routing",
  1933. .codec_name = "msm-stub-codec.1",
  1934. .codec_dai_name = "msm-stub-rx",
  1935. .no_pcm = 1,
  1936. .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
  1937. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1938. .ops = &msm_slimbus_4_be_ops,
  1939. .ignore_pmdown_time = 1, /* Playback support */
  1940. },
  1941. /* Incall Record Back End DAI Link */
  1942. {
  1943. .name = LPASS_BE_SLIMBUS_4_TX,
  1944. .stream_name = "Slimbus4 Capture",
  1945. .cpu_dai_name = "msm-dai-q6.16393",
  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_SLIMBUS_4_TX,
  1951. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1952. .ops = &msm_slimbus_4_be_ops,
  1953. },
  1954. {
  1955. .name = LPASS_BE_STUB_1_TX,
  1956. .stream_name = "Stub1 Capture",
  1957. .cpu_dai_name = "msm-dai-stub",
  1958. .platform_name = "msm-pcm-routing",
  1959. .codec_name = "tabla_codec",
  1960. .codec_dai_name = "tabla_tx3",
  1961. .no_pcm = 1,
  1962. .be_id = MSM_BACKEND_DAI_EXTPROC_EC_TX,
  1963. /* This BE is used for external EC reference from codec. Since
  1964. * Rx is fed as reference for EC, the config of this DAI is
  1965. * based on that of the Rx path.
  1966. */
  1967. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1968. .ops = &msm_be_ops,
  1969. },
  1970. {
  1971. .name = LPASS_BE_SLIMBUS_3_RX,
  1972. .stream_name = "Slimbus3 Playback",
  1973. .cpu_dai_name = "msm-dai-q6.16390",
  1974. .platform_name = "msm-pcm-routing",
  1975. .codec_name = "msm-stub-codec.1",
  1976. .codec_dai_name = "msm-stub-rx",
  1977. .no_pcm = 1,
  1978. .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
  1979. .be_hw_params_fixup = msm_slim_3_rx_be_hw_params_fixup,
  1980. .ops = &msm_slimbus_3_be_ops,
  1981. .ignore_pmdown_time = 1, /* Playback support */
  1982. },
  1983. {
  1984. .name = LPASS_BE_SLIMBUS_3_TX,
  1985. .stream_name = "Slimbus3 Capture",
  1986. .cpu_dai_name = "msm-dai-q6.16391",
  1987. .platform_name = "msm-pcm-routing",
  1988. .codec_name = "msm-stub-codec.1",
  1989. .codec_dai_name = "msm-stub-tx",
  1990. .no_pcm = 1,
  1991. .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
  1992. .be_hw_params_fixup = msm_slim_3_tx_be_hw_params_fixup,
  1993. .ops = &msm_slimbus_3_be_ops,
  1994. },
  1995. };
  1996. /* Digital audio interface glue - connects codec <---> CPU */
  1997. static struct snd_soc_dai_link msm_dai[] = {
  1998. /* FrontEnd DAI Links */
  1999. {
  2000. /*
  2001. * In APQ8064 I2S platform, there is no playback support
  2002. * only voice call is supported so there is no even system
  2003. * tone or dialing tone which is by design because I2S clock
  2004. * is provided by MDM which matches voice call sample rate
  2005. * 8kHz or 16kHz while system tone is 48kHz. We disable the
  2006. * playback by feeding the audio to AUX PCM port.
  2007. */
  2008. .name = "MSM8960 Media1",
  2009. .stream_name = "MultiMedia1",
  2010. .cpu_dai_name = "MultiMedia1",
  2011. .platform_name = "msm-pcm-dsp",
  2012. .dynamic = 1,
  2013. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2014. SND_SOC_DPCM_TRIGGER_POST},
  2015. .codec_dai_name = "snd-soc-dummy-dai",
  2016. .codec_name = "snd-soc-dummy",
  2017. .ignore_suspend = 1,
  2018. .ignore_pmdown_time = 1, /* Playback support */
  2019. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
  2020. },
  2021. {
  2022. .name = "MSM8960 Media2",
  2023. .stream_name = "MultiMedia2",
  2024. .cpu_dai_name = "MultiMedia2",
  2025. .platform_name = "msm-multi-ch-pcm-dsp",
  2026. .dynamic = 1,
  2027. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2028. SND_SOC_DPCM_TRIGGER_POST},
  2029. .codec_dai_name = "snd-soc-dummy-dai",
  2030. .codec_name = "snd-soc-dummy",
  2031. .ignore_suspend = 1,
  2032. .ignore_pmdown_time = 1, /* Playback support */
  2033. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
  2034. },
  2035. {
  2036. .name = "Circuit-Switch Voice",
  2037. .stream_name = "CS-Voice",
  2038. .cpu_dai_name = "CS-VOICE",
  2039. .platform_name = "msm-pcm-voice",
  2040. .dynamic = 1,
  2041. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2042. SND_SOC_DPCM_TRIGGER_POST},
  2043. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2044. .ignore_suspend = 1,
  2045. .codec_dai_name = "snd-soc-dummy-dai",
  2046. .codec_name = "snd-soc-dummy",
  2047. .ignore_suspend = 1,
  2048. .ignore_pmdown_time = 1, /* Playback support */
  2049. .be_id = MSM_FRONTEND_DAI_CS_VOICE,
  2050. },
  2051. {
  2052. .name = "MSM VoIP",
  2053. .stream_name = "VoIP",
  2054. .cpu_dai_name = "VoIP",
  2055. .platform_name = "msm-voip-dsp",
  2056. .dynamic = 1,
  2057. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2058. SND_SOC_DPCM_TRIGGER_POST},
  2059. .codec_dai_name = "snd-soc-dummy-dai",
  2060. .codec_name = "snd-soc-dummy",
  2061. .ignore_suspend = 1,
  2062. .ignore_pmdown_time = 1, /* Playback support */
  2063. .be_id = MSM_FRONTEND_DAI_VOIP,
  2064. },
  2065. {
  2066. .name = "MSM8960 LPA",
  2067. .stream_name = "LPA",
  2068. .cpu_dai_name = "MultiMedia3",
  2069. .platform_name = "msm-pcm-lpa",
  2070. .dynamic = 1,
  2071. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2072. SND_SOC_DPCM_TRIGGER_POST},
  2073. .codec_dai_name = "snd-soc-dummy-dai",
  2074. .codec_name = "snd-soc-dummy",
  2075. .ignore_suspend = 1,
  2076. .ignore_pmdown_time = 1, /* Playback support */
  2077. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
  2078. },
  2079. {
  2080. .name = "INT_FM Hostless",
  2081. .stream_name = "INT_FM Hostless",
  2082. .cpu_dai_name = "INT_FM_HOSTLESS",
  2083. .platform_name = "msm-pcm-hostless",
  2084. .dynamic = 1,
  2085. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2086. SND_SOC_DPCM_TRIGGER_POST},
  2087. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2088. .ignore_suspend = 1,
  2089. .ignore_pmdown_time = 1, /* Playback support */
  2090. .codec_dai_name = "snd-soc-dummy-dai",
  2091. .codec_name = "snd-soc-dummy",
  2092. /* .be_id = do not care */
  2093. },
  2094. {
  2095. .name = "MSM AFE-PCM RX",
  2096. .stream_name = "AFE-PROXY RX",
  2097. .cpu_dai_name = "msm-dai-q6.241",
  2098. .codec_name = "msm-stub-codec.1",
  2099. .codec_dai_name = "msm-stub-rx",
  2100. .platform_name = "msm-pcm-afe",
  2101. .ignore_suspend = 1,
  2102. .ignore_pmdown_time = 1, /* Playback support */
  2103. },
  2104. {
  2105. .name = "MSM AFE-PCM TX",
  2106. .stream_name = "AFE-PROXY TX",
  2107. .cpu_dai_name = "msm-dai-q6.240",
  2108. .codec_name = "msm-stub-codec.1",
  2109. .codec_dai_name = "msm-stub-tx",
  2110. .platform_name = "msm-pcm-afe",
  2111. .ignore_suspend = 1,
  2112. },
  2113. {
  2114. .name = "MSM8960 Compr",
  2115. .stream_name = "COMPR",
  2116. .cpu_dai_name = "MultiMedia4",
  2117. .platform_name = "msm-compr-dsp",
  2118. .dynamic = 1,
  2119. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2120. SND_SOC_DPCM_TRIGGER_POST},
  2121. .codec_dai_name = "snd-soc-dummy-dai",
  2122. .codec_name = "snd-soc-dummy",
  2123. .ignore_suspend = 1,
  2124. .ignore_pmdown_time = 1, /* Playback support */
  2125. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
  2126. },
  2127. {
  2128. .name = "AUXPCM Hostless",
  2129. .stream_name = "AUXPCM Hostless",
  2130. .cpu_dai_name = "AUXPCM_HOSTLESS",
  2131. .platform_name = "msm-pcm-hostless",
  2132. .dynamic = 1,
  2133. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2134. SND_SOC_DPCM_TRIGGER_POST},
  2135. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2136. .ignore_suspend = 1,
  2137. .ignore_pmdown_time = 1, /* Playback support */
  2138. .codec_dai_name = "snd-soc-dummy-dai",
  2139. .codec_name = "snd-soc-dummy",
  2140. },
  2141. /* HDMI Hostless */
  2142. {
  2143. .name = "HDMI_RX_HOSTLESS",
  2144. .stream_name = "HDMI_RX_HOSTLESS",
  2145. .cpu_dai_name = "HDMI_HOSTLESS",
  2146. .platform_name = "msm-pcm-hostless",
  2147. .dynamic = 1,
  2148. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2149. SND_SOC_DPCM_TRIGGER_POST},
  2150. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2151. .codec_dai_name = "snd-soc-dummy-dai",
  2152. .codec_name = "snd-soc-dummy",
  2153. .ignore_suspend = 1,
  2154. .ignore_pmdown_time = 1, /* Playback support */
  2155. },
  2156. {
  2157. .name = "Voice Stub",
  2158. .stream_name = "Voice Stub",
  2159. .cpu_dai_name = "VOICE_STUB",
  2160. .platform_name = "msm-pcm-hostless",
  2161. .dynamic = 1,
  2162. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  2163. SND_SOC_DPCM_TRIGGER_POST},
  2164. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2165. .ignore_suspend = 1,
  2166. .ignore_pmdown_time = 1, /* Playback support */
  2167. .codec_dai_name = "snd-soc-dummy-dai",
  2168. .codec_name = "snd-soc-dummy",
  2169. },
  2170. /* Backend BT/FM DAI Links */
  2171. {
  2172. .name = LPASS_BE_INT_BT_SCO_RX,
  2173. .stream_name = "Internal BT-SCO Playback",
  2174. .cpu_dai_name = "msm-dai-q6.12288",
  2175. .platform_name = "msm-pcm-routing",
  2176. .codec_name = "msm-stub-codec.1",
  2177. .codec_dai_name = "msm-stub-rx",
  2178. .no_pcm = 1,
  2179. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
  2180. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  2181. .ignore_pmdown_time = 1, /* Playback support */
  2182. },
  2183. {
  2184. .name = LPASS_BE_INT_BT_SCO_TX,
  2185. .stream_name = "Internal BT-SCO Capture",
  2186. .cpu_dai_name = "msm-dai-q6.12289",
  2187. .platform_name = "msm-pcm-routing",
  2188. .codec_name = "msm-stub-codec.1",
  2189. .codec_dai_name = "msm-stub-tx",
  2190. .no_pcm = 1,
  2191. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
  2192. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  2193. },
  2194. {
  2195. .name = LPASS_BE_INT_FM_RX,
  2196. .stream_name = "Internal FM Playback",
  2197. .cpu_dai_name = "msm-dai-q6.12292",
  2198. .platform_name = "msm-pcm-routing",
  2199. .codec_name = "msm-stub-codec.1",
  2200. .codec_dai_name = "msm-stub-rx",
  2201. .no_pcm = 1,
  2202. .be_id = MSM_BACKEND_DAI_INT_FM_RX,
  2203. .be_hw_params_fixup = msm_be_hw_params_fixup,
  2204. .ignore_pmdown_time = 1, /* Playback support */
  2205. },
  2206. {
  2207. .name = LPASS_BE_INT_FM_TX,
  2208. .stream_name = "Internal FM Capture",
  2209. .cpu_dai_name = "msm-dai-q6.12293",
  2210. .platform_name = "msm-pcm-routing",
  2211. .codec_name = "msm-stub-codec.1",
  2212. .codec_dai_name = "msm-stub-tx",
  2213. .no_pcm = 1,
  2214. .be_id = MSM_BACKEND_DAI_INT_FM_TX,
  2215. .be_hw_params_fixup = msm_be_hw_params_fixup,
  2216. },
  2217. /* HDMI BACK END DAI Link */
  2218. {
  2219. .name = LPASS_BE_HDMI,
  2220. .stream_name = "HDMI Playback",
  2221. .cpu_dai_name = "msm-dai-q6-hdmi.8",
  2222. .platform_name = "msm-pcm-routing",
  2223. .codec_name = "msm-stub-codec.1",
  2224. .codec_dai_name = "msm-stub-rx",
  2225. .no_pcm = 1,
  2226. .be_id = MSM_BACKEND_DAI_HDMI_RX,
  2227. .be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
  2228. },
  2229. /* Backend AFE DAI Links */
  2230. {
  2231. .name = LPASS_BE_AFE_PCM_RX,
  2232. .stream_name = "AFE Playback",
  2233. .cpu_dai_name = "msm-dai-q6.224",
  2234. .platform_name = "msm-pcm-routing",
  2235. .codec_name = "msm-stub-codec.1",
  2236. .codec_dai_name = "msm-stub-rx",
  2237. .no_pcm = 1,
  2238. .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
  2239. .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
  2240. .ignore_pmdown_time = 1, /* Playback support */
  2241. },
  2242. {
  2243. .name = LPASS_BE_AFE_PCM_TX,
  2244. .stream_name = "AFE Capture",
  2245. .cpu_dai_name = "msm-dai-q6.225",
  2246. .platform_name = "msm-pcm-routing",
  2247. .codec_name = "msm-stub-codec.1",
  2248. .codec_dai_name = "msm-stub-tx",
  2249. .no_pcm = 1,
  2250. .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
  2251. .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
  2252. },
  2253. /* AUX PCM Backend DAI Links */
  2254. {
  2255. .name = LPASS_BE_AUXPCM_RX,
  2256. .stream_name = "AUX PCM Playback",
  2257. .cpu_dai_name = "msm-dai-q6.2",
  2258. .platform_name = "msm-pcm-routing",
  2259. .codec_name = "msm-stub-codec.1",
  2260. .codec_dai_name = "msm-stub-rx",
  2261. .no_pcm = 1,
  2262. .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
  2263. .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
  2264. .ops = &msm_auxpcm_be_ops,
  2265. .ignore_pmdown_time = 1, /* Playback support */
  2266. },
  2267. {
  2268. .name = LPASS_BE_AUXPCM_TX,
  2269. .stream_name = "AUX PCM Capture",
  2270. .cpu_dai_name = "msm-dai-q6.3",
  2271. .platform_name = "msm-pcm-routing",
  2272. .codec_name = "msm-stub-codec.1",
  2273. .codec_dai_name = "msm-stub-tx",
  2274. .no_pcm = 1,
  2275. .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
  2276. .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
  2277. .ops = &msm_auxpcm_be_ops,
  2278. },
  2279. };
  2280. /* Digital audio interface glue - connects codec <---> CPU */
  2281. static struct snd_soc_dai_link msm_mi2s_dai[
  2282. ARRAY_SIZE(msm_dai) +
  2283. ARRAY_SIZE(msm_dai_delta_mi2s)];
  2284. static struct snd_soc_dai_link msm_slim_dai[
  2285. ARRAY_SIZE(msm_dai) +
  2286. ARRAY_SIZE(msm_dai_delta_slim)];
  2287. static struct snd_soc_card snd_soc_card_msm = {
  2288. .name = "apq8064-tabla-snd-card",
  2289. };
  2290. static struct platform_device *msm_snd_device;
  2291. static int __init msm_audio_init(void)
  2292. {
  2293. int ret;
  2294. u32 version = socinfo_get_platform_version();
  2295. if (!machine_is_apq8064_mtp() ||
  2296. (SOCINFO_VERSION_MINOR(version) != 1)) {
  2297. pr_info("%s: Not APQ8064 in I2S mode\n", __func__);
  2298. return -ENODEV;
  2299. }
  2300. mutex_init(&cdc_mclk_mutex);
  2301. pr_debug("%s: APQ8064 is in I2S mode\n", __func__);
  2302. mbhc_cfg.calibration = def_tabla_mbhc_cal();
  2303. if (!mbhc_cfg.calibration) {
  2304. pr_err("Calibration data allocation failed\n");
  2305. return -ENOMEM;
  2306. }
  2307. msm_snd_device = platform_device_alloc("soc-audio", 0);
  2308. if (!msm_snd_device) {
  2309. pr_err("Platform device allocation failed\n");
  2310. kfree(mbhc_cfg.calibration);
  2311. return -ENOMEM;
  2312. }
  2313. if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
  2314. memcpy(msm_slim_dai, msm_dai, sizeof(msm_dai));
  2315. memcpy(msm_slim_dai + ARRAY_SIZE(msm_dai),
  2316. msm_dai_delta_slim, sizeof(msm_dai_delta_slim));
  2317. snd_soc_card_msm.dai_link = msm_slim_dai;
  2318. snd_soc_card_msm.num_links = ARRAY_SIZE(msm_slim_dai);
  2319. snd_soc_card_msm.controls = tabla_msm_controls;
  2320. snd_soc_card_msm.num_controls =
  2321. ARRAY_SIZE(tabla_msm_controls);
  2322. pr_info("%s: Load Slimbus Dai\n", __func__);
  2323. } else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) {
  2324. memcpy(msm_mi2s_dai, msm_dai, sizeof(msm_dai));
  2325. memcpy(msm_mi2s_dai + ARRAY_SIZE(msm_dai),
  2326. msm_dai_delta_mi2s, sizeof(msm_dai_delta_mi2s));
  2327. snd_soc_card_msm.dai_link = msm_mi2s_dai;
  2328. snd_soc_card_msm.num_links = ARRAY_SIZE(msm_mi2s_dai);
  2329. snd_soc_card_msm.controls = tabla_msm_mi2s_controls;
  2330. snd_soc_card_msm.num_controls =
  2331. ARRAY_SIZE(tabla_msm_mi2s_controls);
  2332. pr_info("%s: Load MI2S\n", __func__);
  2333. }
  2334. platform_set_drvdata(msm_snd_device, &snd_soc_card_msm);
  2335. ret = platform_device_add(msm_snd_device);
  2336. if (ret) {
  2337. platform_device_put(msm_snd_device);
  2338. kfree(mbhc_cfg.calibration);
  2339. return ret;
  2340. }
  2341. atomic_set(&mi2s_rsc_ref, 0);
  2342. atomic_set(&auxpcm_rsc_ref, 0);
  2343. return ret;
  2344. }
  2345. module_init(msm_audio_init);
  2346. static void __exit msm_audio_exit(void)
  2347. {
  2348. if (!soc_class_is_apq8064() || socinfo_get_id() == 130) {
  2349. pr_err("%s: Not the right machine type\n", __func__);
  2350. return ;
  2351. }
  2352. platform_device_unregister(msm_snd_device);
  2353. if (mbhc_cfg.gpio)
  2354. gpio_free(mbhc_cfg.gpio);
  2355. kfree(mbhc_cfg.calibration);
  2356. mutex_destroy(&cdc_mclk_mutex);
  2357. }
  2358. module_exit(msm_audio_exit);
  2359. MODULE_DESCRIPTION("ALSA SoC msm");
  2360. MODULE_LICENSE("GPL v2");