apq8074.c 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697
  1. /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/clk.h>
  13. #include <linux/delay.h>
  14. #include <linux/gpio.h>
  15. #include <linux/of_gpio.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/slab.h>
  18. #include <linux/mfd/pm8xxx/pm8921.h>
  19. #include <linux/qpnp/clkdiv.h>
  20. #include <linux/regulator/consumer.h>
  21. #include <linux/io.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 <sound/q6afe-v2.h>
  28. #include <sound/q6core.h>
  29. #include <sound/pcm_params.h>
  30. #include <asm/mach-types.h>
  31. #include <mach/subsystem_notif.h>
  32. #include <mach/socinfo.h>
  33. #include "qdsp6v2/msm-pcm-routing-v2.h"
  34. #include "../codecs/wcd9xxx-common.h"
  35. #include "../codecs/wcd9320.h"
  36. #define DRV_NAME "apq8074-asoc-taiko"
  37. #define APQ8074_SPK_ON 1
  38. #define APQ8074_SPK_OFF 0
  39. #define MSM_SLIM_0_RX_MAX_CHANNELS 2
  40. #define MSM_SLIM_0_TX_MAX_CHANNELS 4
  41. #define BTSCO_RATE_8KHZ 8000
  42. #define BTSCO_RATE_16KHZ 16000
  43. static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
  44. static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
  45. #define SAMPLING_RATE_48KHZ 48000
  46. #define SAMPLING_RATE_96KHZ 96000
  47. #define SAMPLING_RATE_192KHZ 192000
  48. static int apq8074_auxpcm_rate = 8000;
  49. #define LO_1_SPK_AMP 0x1
  50. #define LO_3_SPK_AMP 0x2
  51. #define LO_2_SPK_AMP 0x4
  52. #define LO_4_SPK_AMP 0x8
  53. #define LPAIF_OFFSET 0xFE000000
  54. #define LPAIF_PRI_MODE_MUXSEL (LPAIF_OFFSET + 0x2B000)
  55. #define LPAIF_SEC_MODE_MUXSEL (LPAIF_OFFSET + 0x2C000)
  56. #define LPAIF_TER_MODE_MUXSEL (LPAIF_OFFSET + 0x2D000)
  57. #define LPAIF_QUAD_MODE_MUXSEL (LPAIF_OFFSET + 0x2E000)
  58. #define I2S_PCM_SEL 1
  59. #define I2S_PCM_SEL_OFFSET 1
  60. #define WCD9XXX_MBHC_DEF_BUTTONS 8
  61. #define WCD9XXX_MBHC_DEF_RLOADS 5
  62. #define TAIKO_EXT_CLK_RATE 9600000
  63. /* It takes about 13ms for Class-D PAs to ramp-up */
  64. #define EXT_CLASS_D_EN_DELAY 13000
  65. #define EXT_CLASS_D_DIS_DELAY 3000
  66. #define EXT_CLASS_D_DELAY_DELTA 2000
  67. /* It takes about 13ms for Class-AB PAs to ramp-up */
  68. #define EXT_CLASS_AB_EN_DELAY 10000
  69. #define EXT_CLASS_AB_DIS_DELAY 1000
  70. #define EXT_CLASS_AB_DELAY_DELTA 1000
  71. #define NUM_OF_AUXPCM_GPIOS 4
  72. static void *adsp_state_notifier;
  73. #define ADSP_STATE_READY_TIMEOUT_MS 3000
  74. static inline int param_is_mask(int p)
  75. {
  76. return ((p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
  77. (p <= SNDRV_PCM_HW_PARAM_LAST_MASK));
  78. }
  79. static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
  80. {
  81. return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
  82. }
  83. static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
  84. {
  85. if (bit >= SNDRV_MASK_MAX)
  86. return;
  87. if (param_is_mask(n)) {
  88. struct snd_mask *m = param_to_mask(p, n);
  89. m->bits[0] = 0;
  90. m->bits[1] = 0;
  91. m->bits[bit >> 5] |= (1 << (bit & 31));
  92. }
  93. }
  94. static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
  95. static const struct soc_enum apq8074_auxpcm_enum[] = {
  96. SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
  97. };
  98. static void *def_taiko_mbhc_cal(void);
  99. static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  100. bool dapm);
  101. static struct wcd9xxx_mbhc_config mbhc_cfg = {
  102. .read_fw_bin = false,
  103. .calibration = NULL,
  104. .micbias = MBHC_MICBIAS2,
  105. .mclk_cb_fn = msm_snd_enable_codec_ext_clk,
  106. .mclk_rate = TAIKO_EXT_CLK_RATE,
  107. .gpio = 0,
  108. .gpio_irq = 0,
  109. .gpio_level_insert = 1,
  110. .detect_extn_cable = false,
  111. .insert_detect = true,
  112. .swap_gnd_mic = NULL,
  113. };
  114. struct msm_auxpcm_gpio {
  115. unsigned gpio_no;
  116. const char *gpio_name;
  117. };
  118. struct msm_auxpcm_ctrl {
  119. struct msm_auxpcm_gpio *pin_data;
  120. u32 cnt;
  121. };
  122. struct apq8074_asoc_mach_data {
  123. int mclk_gpio;
  124. u32 mclk_freq;
  125. int us_euro_gpio;
  126. struct msm_auxpcm_ctrl *pri_auxpcm_ctrl;
  127. };
  128. #define GPIO_NAME_INDEX 0
  129. #define DT_PARSE_INDEX 1
  130. static char *msm_prim_auxpcm_gpio_name[][2] = {
  131. {"PRIM_AUXPCM_CLK", "qcom,prim-auxpcm-gpio-clk"},
  132. {"PRIM_AUXPCM_SYNC", "qcom,prim-auxpcm-gpio-sync"},
  133. {"PRIM_AUXPCM_DIN", "qcom,prim-auxpcm-gpio-din"},
  134. {"PRIM_AUXPCM_DOUT", "qcom,prim-auxpcm-gpio-dout"},
  135. };
  136. static void *lpaif_pri_muxsel_virt_addr;
  137. struct apq8074_liquid_dock_dev {
  138. int dock_plug_gpio;
  139. int dock_plug_irq;
  140. struct snd_soc_dapm_context *dapm;
  141. struct work_struct irq_work;
  142. };
  143. static struct apq8074_liquid_dock_dev *apq8074_liquid_dock_dev;
  144. static int dock_plug_det = -1;
  145. /* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
  146. enum {
  147. SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
  148. SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
  149. SLIM_2_RX_1 = 147, /* HDMI RX */
  150. SLIM_3_RX_1 = 148, /* In-call recording RX */
  151. SLIM_3_RX_2 = 149, /* In-call recording RX */
  152. SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
  153. };
  154. static struct platform_device *spdev;
  155. static struct regulator *ext_spk_amp_regulator;
  156. static int ext_spk_amp_gpio = -1;
  157. static int ext_ult_spk_amp_gpio = -1;
  158. static int apq8074_spk_control = 1;
  159. static int apq8074_ext_spk_pamp;
  160. static int msm_slim_0_rx_ch = 1;
  161. static int msm_slim_0_tx_ch = 1;
  162. static int msm_btsco_rate = BTSCO_RATE_8KHZ;
  163. static int msm_btsco_ch = 1;
  164. static int msm_hdmi_rx_ch = 2;
  165. static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
  166. static int msm_proxy_rx_ch = 2;
  167. static struct mutex cdc_mclk_mutex;
  168. static struct clk *codec_clk;
  169. static int clk_users;
  170. static atomic_t prim_auxpcm_rsc_ref;
  171. static int apq8074_liquid_ext_spk_power_amp_init(void)
  172. {
  173. int ret = 0;
  174. ext_spk_amp_gpio = of_get_named_gpio(spdev->dev.of_node,
  175. "qcom,ext-spk-amp-gpio", 0);
  176. if (ext_spk_amp_gpio >= 0) {
  177. ret = gpio_request(ext_spk_amp_gpio, "ext_spk_amp_gpio");
  178. if (ret) {
  179. pr_err("%s: gpio_request failed for ext_spk_amp_gpio.\n",
  180. __func__);
  181. return -EINVAL;
  182. }
  183. gpio_direction_output(ext_spk_amp_gpio, 0);
  184. if (ext_spk_amp_regulator == NULL) {
  185. ext_spk_amp_regulator = regulator_get(&spdev->dev,
  186. "qcom,ext-spk-amp");
  187. if (IS_ERR(ext_spk_amp_regulator)) {
  188. pr_err("%s: Cannot get regulator %s.\n",
  189. __func__, "qcom,ext-spk-amp");
  190. gpio_free(ext_spk_amp_gpio);
  191. return PTR_ERR(ext_spk_amp_regulator);
  192. }
  193. }
  194. }
  195. ext_ult_spk_amp_gpio = of_get_named_gpio(spdev->dev.of_node,
  196. "qcom,ext-ult-spk-amp-gpio", 0);
  197. if (ext_ult_spk_amp_gpio >= 0) {
  198. ret = gpio_request(ext_ult_spk_amp_gpio,
  199. "ext_ult_spk_amp_gpio");
  200. if (ret) {
  201. pr_err("%s: gpio_request failed for ext-ult_spk-amp-gpio.\n",
  202. __func__);
  203. return -EINVAL;
  204. }
  205. gpio_direction_output(ext_ult_spk_amp_gpio, 0);
  206. }
  207. return 0;
  208. }
  209. static void apq8074_liquid_ext_ult_spk_power_amp_enable(u32 on)
  210. {
  211. if (on) {
  212. regulator_enable(ext_spk_amp_regulator);
  213. gpio_direction_output(ext_ult_spk_amp_gpio, 1);
  214. /* time takes enable the external power class AB amplifier */
  215. usleep_range(EXT_CLASS_AB_EN_DELAY,
  216. EXT_CLASS_AB_EN_DELAY + EXT_CLASS_AB_DELAY_DELTA);
  217. } else {
  218. gpio_direction_output(ext_ult_spk_amp_gpio, 0);
  219. regulator_disable(ext_spk_amp_regulator);
  220. /* time takes disable the external power class AB amplifier */
  221. usleep_range(EXT_CLASS_AB_DIS_DELAY,
  222. EXT_CLASS_AB_DIS_DELAY + EXT_CLASS_AB_DELAY_DELTA);
  223. }
  224. pr_debug("%s: %s external ultrasound SPKR_DRV PAs.\n", __func__,
  225. on ? "Enable" : "Disable");
  226. }
  227. static void apq8074_liquid_ext_spk_power_amp_enable(u32 on)
  228. {
  229. if (on) {
  230. regulator_enable(ext_spk_amp_regulator);
  231. gpio_direction_output(ext_spk_amp_gpio, on);
  232. /*time takes enable the external power amplifier*/
  233. usleep_range(EXT_CLASS_D_EN_DELAY,
  234. EXT_CLASS_D_EN_DELAY + EXT_CLASS_D_DELAY_DELTA);
  235. } else {
  236. gpio_direction_output(ext_spk_amp_gpio, on);
  237. regulator_disable(ext_spk_amp_regulator);
  238. /*time takes disable the external power amplifier*/
  239. usleep_range(EXT_CLASS_D_DIS_DELAY,
  240. EXT_CLASS_D_DIS_DELAY + EXT_CLASS_D_DELAY_DELTA);
  241. }
  242. pr_debug("%s: %s external speaker PAs.\n", __func__,
  243. on ? "Enable" : "Disable");
  244. }
  245. static void apq8074_liquid_docking_irq_work(struct work_struct *work)
  246. {
  247. struct apq8074_liquid_dock_dev *dock_dev =
  248. container_of(work,
  249. struct apq8074_liquid_dock_dev,
  250. irq_work);
  251. struct snd_soc_dapm_context *dapm = dock_dev->dapm;
  252. mutex_lock(&dapm->codec->mutex);
  253. dock_plug_det =
  254. gpio_get_value(dock_dev->dock_plug_gpio);
  255. if (0 == dock_plug_det) {
  256. if ((apq8074_ext_spk_pamp & LO_1_SPK_AMP) &&
  257. (apq8074_ext_spk_pamp & LO_3_SPK_AMP) &&
  258. (apq8074_ext_spk_pamp & LO_2_SPK_AMP) &&
  259. (apq8074_ext_spk_pamp & LO_4_SPK_AMP))
  260. apq8074_liquid_ext_spk_power_amp_enable(1);
  261. } else {
  262. if ((apq8074_ext_spk_pamp & LO_1_SPK_AMP) &&
  263. (apq8074_ext_spk_pamp & LO_3_SPK_AMP) &&
  264. (apq8074_ext_spk_pamp & LO_2_SPK_AMP) &&
  265. (apq8074_ext_spk_pamp & LO_4_SPK_AMP))
  266. apq8074_liquid_ext_spk_power_amp_enable(0);
  267. }
  268. mutex_unlock(&dapm->codec->mutex);
  269. }
  270. static irqreturn_t apq8074_liquid_docking_irq_handler(int irq, void *dev)
  271. {
  272. struct apq8074_liquid_dock_dev *dock_dev = dev;
  273. /* switch speakers should not run in interrupt context */
  274. schedule_work(&dock_dev->irq_work);
  275. return IRQ_HANDLED;
  276. }
  277. static int apq8074_liquid_init_docking(struct snd_soc_dapm_context *dapm)
  278. {
  279. int ret = 0;
  280. int dock_plug_gpio = 0;
  281. /* plug in docking speaker+plug in device OR unplug one of them */
  282. u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
  283. dock_plug_det = 0;
  284. dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node,
  285. "qcom,dock-plug-det-irq", 0);
  286. if (dock_plug_gpio >= 0) {
  287. apq8074_liquid_dock_dev =
  288. kzalloc(sizeof(*apq8074_liquid_dock_dev), GFP_KERNEL);
  289. if (!apq8074_liquid_dock_dev) {
  290. pr_err("apq8074_liquid_dock_dev alloc fail.\n");
  291. return -ENOMEM;
  292. }
  293. apq8074_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio;
  294. ret = gpio_request(apq8074_liquid_dock_dev->dock_plug_gpio,
  295. "dock-plug-det-irq");
  296. if (ret) {
  297. pr_err("%s:failed request apq8074_liquid_dock_plug_gpio.\n",
  298. __func__);
  299. return -EINVAL;
  300. }
  301. dock_plug_det =
  302. gpio_get_value(apq8074_liquid_dock_dev->dock_plug_gpio);
  303. apq8074_liquid_dock_dev->dock_plug_irq =
  304. gpio_to_irq(apq8074_liquid_dock_dev->dock_plug_gpio);
  305. apq8074_liquid_dock_dev->dapm = dapm;
  306. INIT_WORK(
  307. &apq8074_liquid_dock_dev->irq_work,
  308. apq8074_liquid_docking_irq_work);
  309. ret = request_irq(apq8074_liquid_dock_dev->dock_plug_irq,
  310. apq8074_liquid_docking_irq_handler,
  311. dock_plug_irq_flags,
  312. "liquid_dock_plug_irq",
  313. apq8074_liquid_dock_dev);
  314. }
  315. return 0;
  316. }
  317. static int apq8074_liquid_ext_spk_power_amp_on(u32 spk)
  318. {
  319. int rc;
  320. if (spk & (LO_1_SPK_AMP | LO_3_SPK_AMP | LO_2_SPK_AMP | LO_4_SPK_AMP)) {
  321. pr_debug("%s: External speakers are already on. spk = 0x%x\n",
  322. __func__, spk);
  323. apq8074_ext_spk_pamp |= spk;
  324. if ((apq8074_ext_spk_pamp & LO_1_SPK_AMP) &&
  325. (apq8074_ext_spk_pamp & LO_3_SPK_AMP) &&
  326. (apq8074_ext_spk_pamp & LO_2_SPK_AMP) &&
  327. (apq8074_ext_spk_pamp & LO_4_SPK_AMP))
  328. if (ext_spk_amp_gpio >= 0 &&
  329. dock_plug_det == 0)
  330. apq8074_liquid_ext_spk_power_amp_enable(1);
  331. rc = 0;
  332. } else {
  333. pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
  334. __func__, spk);
  335. rc = -EINVAL;
  336. }
  337. return rc;
  338. }
  339. static void apq8074_ext_spk_power_amp_on(u32 spk)
  340. {
  341. if (gpio_is_valid(ext_spk_amp_gpio))
  342. apq8074_liquid_ext_spk_power_amp_on(spk);
  343. }
  344. static void apq8074_liquid_ext_spk_power_amp_off(u32 spk)
  345. {
  346. if (spk & (LO_1_SPK_AMP |
  347. LO_3_SPK_AMP |
  348. LO_2_SPK_AMP |
  349. LO_4_SPK_AMP)) {
  350. pr_debug("%s Left and right speakers case spk = 0x%08x",
  351. __func__, spk);
  352. if (!apq8074_ext_spk_pamp) {
  353. if (ext_spk_amp_gpio >= 0 &&
  354. dock_plug_det == 0)
  355. apq8074_liquid_ext_spk_power_amp_enable(0);
  356. apq8074_ext_spk_pamp = 0;
  357. }
  358. } else {
  359. pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
  360. __func__, spk);
  361. return;
  362. }
  363. }
  364. static void apq8074_ext_spk_power_amp_off(u32 spk)
  365. {
  366. if (gpio_is_valid(ext_spk_amp_gpio))
  367. apq8074_liquid_ext_spk_power_amp_off(spk);
  368. }
  369. static void apq8074_ext_control(struct snd_soc_codec *codec)
  370. {
  371. struct snd_soc_dapm_context *dapm = &codec->dapm;
  372. mutex_lock(&dapm->codec->mutex);
  373. pr_debug("%s: apq8074_spk_control = %d", __func__, apq8074_spk_control);
  374. if (apq8074_spk_control == APQ8074_SPK_ON) {
  375. snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
  376. snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
  377. snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
  378. snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
  379. } else {
  380. snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
  381. snd_soc_dapm_disable_pin(dapm, "Lineout_3 amp");
  382. snd_soc_dapm_disable_pin(dapm, "Lineout_2 amp");
  383. snd_soc_dapm_disable_pin(dapm, "Lineout_4 amp");
  384. }
  385. snd_soc_dapm_sync(dapm);
  386. mutex_unlock(&dapm->codec->mutex);
  387. }
  388. static int apq8074_get_spk(struct snd_kcontrol *kcontrol,
  389. struct snd_ctl_elem_value *ucontrol)
  390. {
  391. pr_debug("%s: apq8074_spk_control = %d", __func__, apq8074_spk_control);
  392. ucontrol->value.integer.value[0] = apq8074_spk_control;
  393. return 0;
  394. }
  395. static int apq8074_set_spk(struct snd_kcontrol *kcontrol,
  396. struct snd_ctl_elem_value *ucontrol)
  397. {
  398. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  399. pr_debug("%s()\n", __func__);
  400. if (apq8074_spk_control == ucontrol->value.integer.value[0])
  401. return 0;
  402. apq8074_spk_control = ucontrol->value.integer.value[0];
  403. apq8074_ext_control(codec);
  404. return 1;
  405. }
  406. static int msm_ext_spkramp_event(struct snd_soc_dapm_widget *w,
  407. struct snd_kcontrol *k, int event)
  408. {
  409. pr_debug("%s()\n", __func__);
  410. if (SND_SOC_DAPM_EVENT_ON(event)) {
  411. if (!strncmp(w->name, "Lineout_1 amp", 14))
  412. apq8074_ext_spk_power_amp_on(LO_1_SPK_AMP);
  413. else if (!strncmp(w->name, "Lineout_3 amp", 14))
  414. apq8074_ext_spk_power_amp_on(LO_3_SPK_AMP);
  415. else if (!strncmp(w->name, "Lineout_2 amp", 14))
  416. apq8074_ext_spk_power_amp_on(LO_2_SPK_AMP);
  417. else if (!strncmp(w->name, "Lineout_4 amp", 14))
  418. apq8074_ext_spk_power_amp_on(LO_4_SPK_AMP);
  419. else {
  420. pr_err("%s() Invalid Speaker Widget = %s\n",
  421. __func__, w->name);
  422. return -EINVAL;
  423. }
  424. } else {
  425. if (!strncmp(w->name, "Lineout_1 amp", 14))
  426. apq8074_ext_spk_power_amp_off(LO_1_SPK_AMP);
  427. else if (!strncmp(w->name, "Lineout_3 amp", 14))
  428. apq8074_ext_spk_power_amp_off(LO_3_SPK_AMP);
  429. else if (!strncmp(w->name, "Lineout_2 amp", 14))
  430. apq8074_ext_spk_power_amp_off(LO_2_SPK_AMP);
  431. else if (!strncmp(w->name, "Lineout_4 amp", 14))
  432. apq8074_ext_spk_power_amp_off(LO_4_SPK_AMP);
  433. else {
  434. pr_err("%s() Invalid Speaker Widget = %s\n",
  435. __func__, w->name);
  436. return -EINVAL;
  437. }
  438. }
  439. return 0;
  440. }
  441. static int msm_ext_spkramp_ultrasound_event(struct snd_soc_dapm_widget *w,
  442. struct snd_kcontrol *k, int event)
  443. {
  444. pr_debug("%s()\n", __func__);
  445. if (!strncmp(w->name, "SPK_ultrasound amp", 19)) {
  446. if (!gpio_is_valid(ext_ult_spk_amp_gpio)) {
  447. pr_err("%s: ext_ult_spk_amp_gpio isn't configured\n",
  448. __func__);
  449. return -EINVAL;
  450. }
  451. if (SND_SOC_DAPM_EVENT_ON(event))
  452. apq8074_liquid_ext_ult_spk_power_amp_enable(1);
  453. else
  454. apq8074_liquid_ext_ult_spk_power_amp_enable(0);
  455. } else {
  456. pr_err("%s() Invalid Speaker Widget = %s\n",
  457. __func__, w->name);
  458. return -EINVAL;
  459. }
  460. return 0;
  461. }
  462. static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
  463. bool dapm)
  464. {
  465. int ret = 0;
  466. pr_debug("%s: enable = %d clk_users = %d\n",
  467. __func__, enable, clk_users);
  468. mutex_lock(&cdc_mclk_mutex);
  469. if (enable) {
  470. if (!codec_clk) {
  471. dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
  472. __func__);
  473. ret = -EINVAL;
  474. goto exit;
  475. }
  476. clk_users++;
  477. if (clk_users != 1)
  478. goto exit;
  479. if (codec_clk) {
  480. clk_set_rate(codec_clk, TAIKO_EXT_CLK_RATE);
  481. clk_prepare_enable(codec_clk);
  482. taiko_mclk_enable(codec, 1, dapm);
  483. } else {
  484. pr_err("%s: Error setting Taiko MCLK\n", __func__);
  485. clk_users--;
  486. goto exit;
  487. }
  488. } else {
  489. if (clk_users > 0) {
  490. clk_users--;
  491. if (clk_users == 0) {
  492. taiko_mclk_enable(codec, 0, dapm);
  493. clk_disable_unprepare(codec_clk);
  494. }
  495. } else {
  496. pr_err("%s: Error releasing Taiko MCLK\n", __func__);
  497. ret = -EINVAL;
  498. goto exit;
  499. }
  500. }
  501. exit:
  502. mutex_unlock(&cdc_mclk_mutex);
  503. return ret;
  504. }
  505. static int apq8074_mclk_event(struct snd_soc_dapm_widget *w,
  506. struct snd_kcontrol *kcontrol, int event)
  507. {
  508. pr_debug("%s: event = %d\n", __func__, event);
  509. switch (event) {
  510. case SND_SOC_DAPM_PRE_PMU:
  511. return msm_snd_enable_codec_ext_clk(w->codec, 1, true);
  512. case SND_SOC_DAPM_POST_PMD:
  513. return msm_snd_enable_codec_ext_clk(w->codec, 0, true);
  514. }
  515. return 0;
  516. }
  517. static const struct snd_soc_dapm_widget apq8074_dapm_widgets[] = {
  518. SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
  519. apq8074_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  520. SND_SOC_DAPM_SPK("Lineout_1 amp", msm_ext_spkramp_event),
  521. SND_SOC_DAPM_SPK("Lineout_3 amp", msm_ext_spkramp_event),
  522. SND_SOC_DAPM_SPK("Lineout_2 amp", msm_ext_spkramp_event),
  523. SND_SOC_DAPM_SPK("Lineout_4 amp", msm_ext_spkramp_event),
  524. SND_SOC_DAPM_SPK("SPK_ultrasound amp",
  525. msm_ext_spkramp_ultrasound_event),
  526. SND_SOC_DAPM_MIC("Handset Mic", NULL),
  527. SND_SOC_DAPM_MIC("Headset Mic", NULL),
  528. SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
  529. SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
  530. SND_SOC_DAPM_MIC("Analog Mic4", NULL),
  531. SND_SOC_DAPM_MIC("Analog Mic6", NULL),
  532. SND_SOC_DAPM_MIC("Analog Mic7", NULL),
  533. SND_SOC_DAPM_MIC("Digital Mic1", NULL),
  534. SND_SOC_DAPM_MIC("Digital Mic2", NULL),
  535. SND_SOC_DAPM_MIC("Digital Mic3", NULL),
  536. SND_SOC_DAPM_MIC("Digital Mic4", NULL),
  537. SND_SOC_DAPM_MIC("Digital Mic5", NULL),
  538. SND_SOC_DAPM_MIC("Digital Mic6", NULL),
  539. };
  540. static const char *const spk_function[] = {"Off", "On"};
  541. static const char *const slim0_rx_ch_text[] = {"One", "Two"};
  542. static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four",
  543. "Five"};
  544. static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
  545. "Six", "Seven", "Eight"};
  546. static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE"};
  547. static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
  548. "KHZ_192"};
  549. static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
  550. "Five", "Six", "Seven", "Eight"};
  551. static const char *const btsco_rate_text[] = {"8000", "16000"};
  552. static const struct soc_enum msm_btsco_enum[] = {
  553. SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
  554. };
  555. static int slim0_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
  556. struct snd_ctl_elem_value *ucontrol)
  557. {
  558. int sample_rate_val = 0;
  559. switch (slim0_rx_sample_rate) {
  560. case SAMPLING_RATE_192KHZ:
  561. sample_rate_val = 2;
  562. break;
  563. case SAMPLING_RATE_96KHZ:
  564. sample_rate_val = 1;
  565. break;
  566. case SAMPLING_RATE_48KHZ:
  567. default:
  568. sample_rate_val = 0;
  569. break;
  570. }
  571. ucontrol->value.integer.value[0] = sample_rate_val;
  572. pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
  573. slim0_rx_sample_rate);
  574. return 0;
  575. }
  576. static int slim0_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
  577. struct snd_ctl_elem_value *ucontrol)
  578. {
  579. pr_debug("%s: ucontrol value = %ld\n", __func__,
  580. ucontrol->value.integer.value[0]);
  581. switch (ucontrol->value.integer.value[0]) {
  582. case 2:
  583. slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
  584. break;
  585. case 1:
  586. slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
  587. break;
  588. case 0:
  589. default:
  590. slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
  591. }
  592. pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
  593. slim0_rx_sample_rate);
  594. return 0;
  595. }
  596. static int slim0_rx_bit_format_get(struct snd_kcontrol *kcontrol,
  597. struct snd_ctl_elem_value *ucontrol)
  598. {
  599. switch (slim0_rx_bit_format) {
  600. case SNDRV_PCM_FORMAT_S24_LE:
  601. ucontrol->value.integer.value[0] = 1;
  602. break;
  603. case SNDRV_PCM_FORMAT_S16_LE:
  604. default:
  605. ucontrol->value.integer.value[0] = 0;
  606. break;
  607. }
  608. pr_debug("%s: slim0_rx_bit_format = %d, ucontrol value = %ld\n",
  609. __func__, slim0_rx_bit_format,
  610. ucontrol->value.integer.value[0]);
  611. return 0;
  612. }
  613. static int slim0_rx_bit_format_put(struct snd_kcontrol *kcontrol,
  614. struct snd_ctl_elem_value *ucontrol)
  615. {
  616. switch (ucontrol->value.integer.value[0]) {
  617. case 1:
  618. slim0_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
  619. break;
  620. case 0:
  621. default:
  622. slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
  623. break;
  624. }
  625. return 0;
  626. }
  627. static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
  628. struct snd_ctl_elem_value *ucontrol)
  629. {
  630. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  631. msm_slim_0_rx_ch);
  632. ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
  633. return 0;
  634. }
  635. static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
  636. struct snd_ctl_elem_value *ucontrol)
  637. {
  638. msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
  639. pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
  640. msm_slim_0_rx_ch);
  641. return 1;
  642. }
  643. static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
  644. struct snd_ctl_elem_value *ucontrol)
  645. {
  646. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
  647. msm_slim_0_tx_ch);
  648. ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
  649. return 0;
  650. }
  651. static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
  652. struct snd_ctl_elem_value *ucontrol)
  653. {
  654. msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
  655. pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__, msm_slim_0_tx_ch);
  656. return 1;
  657. }
  658. static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
  659. struct snd_ctl_elem_value *ucontrol)
  660. {
  661. pr_debug("%s: msm_btsco_rate = %d", __func__, msm_btsco_rate);
  662. ucontrol->value.integer.value[0] = msm_btsco_rate;
  663. return 0;
  664. }
  665. static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
  666. struct snd_ctl_elem_value *ucontrol)
  667. {
  668. switch (ucontrol->value.integer.value[0]) {
  669. case 0:
  670. msm_btsco_rate = BTSCO_RATE_8KHZ;
  671. break;
  672. case 1:
  673. msm_btsco_rate = BTSCO_RATE_16KHZ;
  674. break;
  675. default:
  676. msm_btsco_rate = BTSCO_RATE_8KHZ;
  677. break;
  678. }
  679. pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
  680. return 0;
  681. }
  682. static int hdmi_rx_bit_format_get(struct snd_kcontrol *kcontrol,
  683. struct snd_ctl_elem_value *ucontrol)
  684. {
  685. switch (hdmi_rx_bit_format) {
  686. case SNDRV_PCM_FORMAT_S24_LE:
  687. ucontrol->value.integer.value[0] = 1;
  688. break;
  689. case SNDRV_PCM_FORMAT_S16_LE:
  690. default:
  691. ucontrol->value.integer.value[0] = 0;
  692. break;
  693. }
  694. pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
  695. __func__, hdmi_rx_bit_format,
  696. ucontrol->value.integer.value[0]);
  697. return 0;
  698. }
  699. static int hdmi_rx_bit_format_put(struct snd_kcontrol *kcontrol,
  700. struct snd_ctl_elem_value *ucontrol)
  701. {
  702. switch (ucontrol->value.integer.value[0]) {
  703. case 1:
  704. hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
  705. break;
  706. case 0:
  707. default:
  708. hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
  709. break;
  710. }
  711. pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
  712. __func__, hdmi_rx_bit_format,
  713. ucontrol->value.integer.value[0]);
  714. return 0;
  715. }
  716. static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
  717. struct snd_ctl_elem_value *ucontrol)
  718. {
  719. pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
  720. msm_hdmi_rx_ch);
  721. ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
  722. return 0;
  723. }
  724. static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
  725. struct snd_ctl_elem_value *ucontrol)
  726. {
  727. msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
  728. if (msm_hdmi_rx_ch > 8) {
  729. pr_err("%s: channels exceeded 8.Limiting to max channels-8\n",
  730. __func__);
  731. msm_hdmi_rx_ch = 8;
  732. }
  733. pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__, msm_hdmi_rx_ch);
  734. return 1;
  735. }
  736. static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
  737. SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
  738. msm_btsco_rate_get, msm_btsco_rate_put),
  739. };
  740. static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  741. struct snd_pcm_hw_params *params)
  742. {
  743. struct snd_interval *rate = hw_param_interval(params,
  744. SNDRV_PCM_HW_PARAM_RATE);
  745. struct snd_interval *channels = hw_param_interval(params,
  746. SNDRV_PCM_HW_PARAM_CHANNELS);
  747. rate->min = rate->max = msm_btsco_rate;
  748. channels->min = channels->max = msm_btsco_ch;
  749. return 0;
  750. }
  751. static int apq8074_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
  752. struct snd_ctl_elem_value *ucontrol)
  753. {
  754. ucontrol->value.integer.value[0] = apq8074_auxpcm_rate;
  755. return 0;
  756. }
  757. static int apq8074_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
  758. struct snd_ctl_elem_value *ucontrol)
  759. {
  760. switch (ucontrol->value.integer.value[0]) {
  761. case 0:
  762. apq8074_auxpcm_rate = 8000;
  763. break;
  764. case 1:
  765. apq8074_auxpcm_rate = 16000;
  766. break;
  767. default:
  768. apq8074_auxpcm_rate = 8000;
  769. break;
  770. }
  771. return 0;
  772. }
  773. static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
  774. struct snd_ctl_elem_value *ucontrol)
  775. {
  776. pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
  777. msm_proxy_rx_ch);
  778. ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
  779. return 0;
  780. }
  781. static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
  782. struct snd_ctl_elem_value *ucontrol)
  783. {
  784. msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
  785. pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
  786. msm_proxy_rx_ch);
  787. return 1;
  788. }
  789. static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
  790. struct snd_pcm_hw_params *params)
  791. {
  792. struct snd_interval *rate =
  793. hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  794. struct snd_interval *channels =
  795. hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  796. rate->min = rate->max = apq8074_auxpcm_rate;
  797. channels->min = channels->max = 1;
  798. return 0;
  799. }
  800. static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  801. struct snd_pcm_hw_params *params)
  802. {
  803. struct snd_interval *rate = hw_param_interval(params,
  804. SNDRV_PCM_HW_PARAM_RATE);
  805. struct snd_interval *channels = hw_param_interval(params,
  806. SNDRV_PCM_HW_PARAM_CHANNELS);
  807. pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
  808. if (channels->max < 2)
  809. channels->min = channels->max = 2;
  810. channels->min = channels->max = msm_proxy_rx_ch;
  811. rate->min = rate->max = 48000;
  812. return 0;
  813. }
  814. static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  815. struct snd_pcm_hw_params *params)
  816. {
  817. struct snd_interval *rate = hw_param_interval(params,
  818. SNDRV_PCM_HW_PARAM_RATE);
  819. rate->min = rate->max = 48000;
  820. return 0;
  821. }
  822. static int apq8074_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  823. struct snd_pcm_hw_params *params)
  824. {
  825. struct snd_interval *rate = hw_param_interval(params,
  826. SNDRV_PCM_HW_PARAM_RATE);
  827. struct snd_interval *channels = hw_param_interval(params,
  828. SNDRV_PCM_HW_PARAM_CHANNELS);
  829. pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
  830. channels->min, channels->max);
  831. param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
  832. hdmi_rx_bit_format);
  833. if (channels->max < 2)
  834. channels->min = channels->max = 2;
  835. rate->min = rate->max = 48000;
  836. channels->min = channels->max = msm_hdmi_rx_ch;
  837. return 0;
  838. }
  839. static int msm_aux_pcm_get_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
  840. {
  841. struct msm_auxpcm_gpio *pin_data = NULL;
  842. int ret = 0;
  843. int i;
  844. int j;
  845. pin_data = auxpcm_ctrl->pin_data;
  846. for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
  847. ret = gpio_request(pin_data->gpio_no,
  848. pin_data->gpio_name);
  849. pr_debug("%s: gpio = %d, gpio name = %s\n"
  850. "ret = %d\n", __func__,
  851. pin_data->gpio_no,
  852. pin_data->gpio_name,
  853. ret);
  854. if (ret) {
  855. pr_err("%s: Failed to request gpio %d\n",
  856. __func__, pin_data->gpio_no);
  857. /* Release all GPIOs on failure */
  858. for (j = i; j >= 0; j--)
  859. gpio_free(pin_data->gpio_no);
  860. return ret;
  861. }
  862. }
  863. return 0;
  864. }
  865. static int msm_aux_pcm_free_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
  866. {
  867. struct msm_auxpcm_gpio *pin_data = NULL;
  868. int i;
  869. int ret = 0;
  870. if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
  871. pr_err("%s: Ctrl pointers are NULL\n", __func__);
  872. ret = -EINVAL;
  873. goto err;
  874. }
  875. pin_data = auxpcm_ctrl->pin_data;
  876. for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
  877. gpio_free(pin_data->gpio_no);
  878. pr_debug("%s: gpio = %d, gpio_name = %s\n",
  879. __func__, pin_data->gpio_no,
  880. pin_data->gpio_name);
  881. }
  882. err:
  883. return ret;
  884. }
  885. static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
  886. {
  887. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  888. struct snd_soc_card *card = rtd->card;
  889. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  890. struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
  891. int ret = 0;
  892. pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
  893. __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
  894. auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
  895. if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
  896. pr_err("%s: Ctrl pointers are NULL\n", __func__);
  897. ret = -EINVAL;
  898. goto err;
  899. }
  900. if (atomic_inc_return(&prim_auxpcm_rsc_ref) == 1) {
  901. if (lpaif_pri_muxsel_virt_addr != NULL)
  902. iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
  903. lpaif_pri_muxsel_virt_addr);
  904. else
  905. pr_err("%s lpaif_pri_muxsel_virt_addr is NULL\n",
  906. __func__);
  907. ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
  908. }
  909. if (ret < 0) {
  910. pr_err("%s: Aux PCM GPIO request failed\n", __func__);
  911. return -EINVAL;
  912. }
  913. err:
  914. return ret;
  915. }
  916. static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
  917. {
  918. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  919. struct snd_soc_card *card = rtd->card;
  920. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  921. struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
  922. pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
  923. __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
  924. auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
  925. if (atomic_dec_return(&prim_auxpcm_rsc_ref) == 0)
  926. msm_aux_pcm_free_gpios(auxpcm_ctrl);
  927. }
  928. static struct snd_soc_ops msm_auxpcm_be_ops = {
  929. .startup = msm_prim_auxpcm_startup,
  930. .shutdown = msm_prim_auxpcm_shutdown,
  931. };
  932. static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  933. struct snd_pcm_hw_params *params)
  934. {
  935. struct snd_interval *rate = hw_param_interval(params,
  936. SNDRV_PCM_HW_PARAM_RATE);
  937. struct snd_interval *channels =
  938. hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  939. pr_debug("%s()\n", __func__);
  940. param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
  941. slim0_rx_bit_format);
  942. rate->min = rate->max = slim0_rx_sample_rate;
  943. channels->min = channels->max = msm_slim_0_rx_ch;
  944. pr_debug("%s: format = %d, rate = %d, channels = %d\n",
  945. __func__, params_format(params), params_rate(params),
  946. msm_slim_0_rx_ch);
  947. return 0;
  948. }
  949. static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  950. struct snd_pcm_hw_params *params)
  951. {
  952. struct snd_interval *rate = hw_param_interval(params,
  953. SNDRV_PCM_HW_PARAM_RATE);
  954. struct snd_interval *channels = hw_param_interval(params,
  955. SNDRV_PCM_HW_PARAM_CHANNELS);
  956. pr_debug("%s()\n", __func__);
  957. rate->min = rate->max = 48000;
  958. channels->min = channels->max = msm_slim_0_tx_ch;
  959. return 0;
  960. }
  961. static int msm_slim_5_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  962. struct snd_pcm_hw_params *params)
  963. {
  964. int rc;
  965. void *config;
  966. struct snd_soc_codec *codec = rtd->codec;
  967. struct snd_interval *rate =
  968. hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  969. struct snd_interval *channels =
  970. hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  971. pr_debug("%s enter\n", __func__);
  972. rate->min = rate->max = 16000;
  973. channels->min = channels->max = 1;
  974. config = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_PORT_CONFIG);
  975. rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG, config,
  976. SLIMBUS_5_TX);
  977. if (rc) {
  978. pr_err("%s: Failed to set slimbus slave port config %d\n",
  979. __func__, rc);
  980. return rc;
  981. }
  982. return 0;
  983. }
  984. static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  985. struct snd_pcm_hw_params *params)
  986. {
  987. struct snd_interval *rate = hw_param_interval(params,
  988. SNDRV_PCM_HW_PARAM_RATE);
  989. pr_debug("%s()\n", __func__);
  990. rate->min = rate->max = 48000;
  991. return 0;
  992. }
  993. static const struct soc_enum msm_snd_enum[] = {
  994. SOC_ENUM_SINGLE_EXT(2, spk_function),
  995. SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
  996. SOC_ENUM_SINGLE_EXT(5, slim0_tx_ch_text),
  997. SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
  998. SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
  999. SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
  1000. SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
  1001. };
  1002. static const struct snd_kcontrol_new msm_snd_controls[] = {
  1003. SOC_ENUM_EXT("Speaker Function", msm_snd_enum[0], apq8074_get_spk,
  1004. apq8074_set_spk),
  1005. SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
  1006. msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
  1007. SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
  1008. msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
  1009. SOC_ENUM_EXT("AUX PCM SampleRate", apq8074_auxpcm_enum[0],
  1010. apq8074_auxpcm_rate_get, apq8074_auxpcm_rate_put),
  1011. SOC_ENUM_EXT("HDMI_RX Channels", msm_snd_enum[3],
  1012. msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
  1013. SOC_ENUM_EXT("SLIM_0_RX Format", msm_snd_enum[4],
  1014. slim0_rx_bit_format_get, slim0_rx_bit_format_put),
  1015. SOC_ENUM_EXT("SLIM_0_RX SampleRate", msm_snd_enum[5],
  1016. slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
  1017. SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
  1018. hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
  1019. SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[6],
  1020. msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
  1021. };
  1022. static bool apq8074_swap_gnd_mic(struct snd_soc_codec *codec)
  1023. {
  1024. struct snd_soc_card *card = codec->card;
  1025. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  1026. int value = gpio_get_value_cansleep(pdata->us_euro_gpio);
  1027. pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
  1028. gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
  1029. return true;
  1030. }
  1031. static int msm_afe_set_config(struct snd_soc_codec *codec)
  1032. {
  1033. int rc;
  1034. void *config_data;
  1035. pr_debug("%s: enter\n", __func__);
  1036. config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
  1037. rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
  1038. if (rc) {
  1039. pr_err("%s: Failed to set codec registers config %d\n",
  1040. __func__, rc);
  1041. return rc;
  1042. }
  1043. config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
  1044. rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
  1045. if (rc) {
  1046. pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
  1047. rc);
  1048. return rc;
  1049. }
  1050. return 0;
  1051. }
  1052. static void msm_afe_clear_config(void)
  1053. {
  1054. afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
  1055. afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
  1056. }
  1057. static int msm8974_adsp_state_callback(struct notifier_block *nb,
  1058. unsigned long value, void *priv)
  1059. {
  1060. if (value == SUBSYS_BEFORE_SHUTDOWN) {
  1061. pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
  1062. __func__);
  1063. msm_afe_clear_config();
  1064. } else if (value == SUBSYS_AFTER_POWERUP) {
  1065. pr_debug("%s: ADSP is up\n", __func__);
  1066. }
  1067. return NOTIFY_OK;
  1068. }
  1069. static struct notifier_block adsp_state_notifier_block = {
  1070. .notifier_call = msm8974_adsp_state_callback,
  1071. .priority = -INT_MAX,
  1072. };
  1073. static int msm8974_taiko_codec_up(struct snd_soc_codec *codec)
  1074. {
  1075. int err;
  1076. unsigned long timeout;
  1077. int adsp_ready = 0;
  1078. timeout = jiffies +
  1079. msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
  1080. do {
  1081. if (!q6core_is_adsp_ready()) {
  1082. pr_err("%s: ADSP Audio isn't ready\n", __func__);
  1083. } else {
  1084. pr_debug("%s: ADSP Audio is ready\n", __func__);
  1085. adsp_ready = 1;
  1086. break;
  1087. }
  1088. } while (time_after(timeout, jiffies));
  1089. if (!adsp_ready) {
  1090. pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
  1091. return -ETIMEDOUT;
  1092. }
  1093. err = msm_afe_set_config(codec);
  1094. if (err)
  1095. pr_err("%s: Failed to set AFE config. err %d\n",
  1096. __func__, err);
  1097. return err;
  1098. }
  1099. static int apq8074_taiko_event_cb(struct snd_soc_codec *codec,
  1100. enum wcd9xxx_codec_event codec_event)
  1101. {
  1102. switch (codec_event) {
  1103. case WCD9XXX_CODEC_EVENT_CODEC_UP:
  1104. return msm8974_taiko_codec_up(codec);
  1105. break;
  1106. default:
  1107. pr_err("%s: UnSupported codec event %d\n",
  1108. __func__, codec_event);
  1109. return -EINVAL;
  1110. }
  1111. }
  1112. static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
  1113. {
  1114. int err;
  1115. void *config_data;
  1116. struct snd_soc_codec *codec = rtd->codec;
  1117. struct snd_soc_dapm_context *dapm = &codec->dapm;
  1118. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1119. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1120. /* Taiko SLIMBUS configuration
  1121. * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
  1122. * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
  1123. * TX14, TX15, TX16
  1124. */
  1125. unsigned int rx_ch[TAIKO_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
  1126. 151, 152, 153, 154, 155, 156};
  1127. unsigned int tx_ch[TAIKO_TX_MAX] = {128, 129, 130, 131, 132, 133,
  1128. 134, 135, 136, 137, 138, 139,
  1129. 140, 141, 142, 143};
  1130. pr_info("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
  1131. rtd->pmdown_time = 0;
  1132. err = snd_soc_add_codec_controls(codec, msm_snd_controls,
  1133. ARRAY_SIZE(msm_snd_controls));
  1134. if (err < 0)
  1135. return err;
  1136. err = apq8074_liquid_ext_spk_power_amp_init();
  1137. if (err) {
  1138. pr_err("%s: LiQUID 8974 CLASS_D PAs init failed (%d)\n",
  1139. __func__, err);
  1140. return err;
  1141. }
  1142. err = apq8074_liquid_init_docking(dapm);
  1143. if (err) {
  1144. pr_err("%s: LiQUID 8974 init Docking stat IRQ failed (%d)\n",
  1145. __func__, err);
  1146. return err;
  1147. }
  1148. snd_soc_dapm_new_controls(dapm, apq8074_dapm_widgets,
  1149. ARRAY_SIZE(apq8074_dapm_widgets));
  1150. snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
  1151. snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
  1152. snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
  1153. snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
  1154. snd_soc_dapm_sync(dapm);
  1155. codec_clk = clk_get(cpu_dai->dev, "osr_clk");
  1156. snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
  1157. tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
  1158. err = msm_afe_set_config(codec);
  1159. if (err) {
  1160. pr_err("%s: Failed to set AFE config %d\n", __func__, err);
  1161. goto out;
  1162. }
  1163. config_data = taiko_get_afe_config(codec, AFE_AANC_VERSION);
  1164. err = afe_set_config(AFE_AANC_VERSION, config_data, 0);
  1165. if (err) {
  1166. pr_err("%s: Failed to set aanc version %d\n",
  1167. __func__, err);
  1168. goto out;
  1169. }
  1170. config_data = taiko_get_afe_config(codec,
  1171. AFE_CDC_CLIP_REGISTERS_CONFIG);
  1172. if (config_data) {
  1173. err = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
  1174. config_data, 0);
  1175. if (err) {
  1176. pr_err("%s: Failed to set clip registers %d\n",
  1177. __func__, err);
  1178. return err;
  1179. }
  1180. }
  1181. config_data = taiko_get_afe_config(codec, AFE_CLIP_BANK_SEL);
  1182. if (config_data) {
  1183. err = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
  1184. if (err) {
  1185. pr_err("%s: Failed to set AFE bank selection %d\n",
  1186. __func__, err);
  1187. return err;
  1188. }
  1189. }
  1190. /* start mbhc */
  1191. mbhc_cfg.calibration = def_taiko_mbhc_cal();
  1192. if (mbhc_cfg.calibration) {
  1193. err = taiko_hs_detect(codec, &mbhc_cfg);
  1194. if (err)
  1195. goto out;
  1196. } else {
  1197. err = -ENOMEM;
  1198. goto out;
  1199. }
  1200. adsp_state_notifier =
  1201. subsys_notif_register_notifier("adsp",
  1202. &adsp_state_notifier_block);
  1203. if (!adsp_state_notifier) {
  1204. pr_err("%s: Failed to register adsp state notifier\n",
  1205. __func__);
  1206. err = -EFAULT;
  1207. taiko_hs_detect_exit(codec);
  1208. goto out;
  1209. }
  1210. taiko_event_register(apq8074_taiko_event_cb, rtd->codec);
  1211. return 0;
  1212. out:
  1213. clk_put(codec_clk);
  1214. return err;
  1215. }
  1216. static int apq8074_snd_startup(struct snd_pcm_substream *substream)
  1217. {
  1218. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1219. substream->name, substream->stream);
  1220. return 0;
  1221. }
  1222. static void *def_taiko_mbhc_cal(void)
  1223. {
  1224. void *taiko_cal;
  1225. struct wcd9xxx_mbhc_btn_detect_cfg *btn_cfg;
  1226. u16 *btn_low, *btn_high;
  1227. u8 *n_ready, *n_cic, *gain;
  1228. taiko_cal = kzalloc(WCD9XXX_MBHC_CAL_SIZE(WCD9XXX_MBHC_DEF_BUTTONS,
  1229. WCD9XXX_MBHC_DEF_RLOADS),
  1230. GFP_KERNEL);
  1231. if (!taiko_cal) {
  1232. pr_err("%s: out of memory\n", __func__);
  1233. return NULL;
  1234. }
  1235. #define S(X, Y) ((WCD9XXX_MBHC_CAL_GENERAL_PTR(taiko_cal)->X) = (Y))
  1236. S(t_ldoh, 100);
  1237. S(t_bg_fast_settle, 100);
  1238. S(t_shutdown_plug_rem, 255);
  1239. S(mbhc_nsa, 4);
  1240. S(mbhc_navg, 4);
  1241. #undef S
  1242. #define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_DET_PTR(taiko_cal)->X) = (Y))
  1243. S(mic_current, TAIKO_PID_MIC_5_UA);
  1244. S(hph_current, TAIKO_PID_MIC_5_UA);
  1245. S(t_mic_pid, 100);
  1246. S(t_ins_complete, 250);
  1247. S(t_ins_retry, 200);
  1248. #undef S
  1249. #define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(taiko_cal)->X) = (Y))
  1250. S(v_no_mic, 30);
  1251. S(v_hs_max, 2400);
  1252. #undef S
  1253. #define S(X, Y) ((WCD9XXX_MBHC_CAL_BTN_DET_PTR(taiko_cal)->X) = (Y))
  1254. S(c[0], 62);
  1255. S(c[1], 124);
  1256. S(nc, 1);
  1257. S(n_meas, 3);
  1258. S(mbhc_nsc, 11);
  1259. S(n_btn_meas, 1);
  1260. S(n_btn_con, 2);
  1261. S(num_btn, WCD9XXX_MBHC_DEF_BUTTONS);
  1262. S(v_btn_press_delta_sta, 100);
  1263. S(v_btn_press_delta_cic, 50);
  1264. #undef S
  1265. btn_cfg = WCD9XXX_MBHC_CAL_BTN_DET_PTR(taiko_cal);
  1266. btn_low = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_V_BTN_LOW);
  1267. btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
  1268. MBHC_BTN_DET_V_BTN_HIGH);
  1269. btn_low[0] = -50;
  1270. btn_high[0] = 20;
  1271. btn_low[1] = 21;
  1272. btn_high[1] = 61;
  1273. btn_low[2] = 62;
  1274. btn_high[2] = 104;
  1275. btn_low[3] = 105;
  1276. btn_high[3] = 148;
  1277. btn_low[4] = 149;
  1278. btn_high[4] = 189;
  1279. btn_low[5] = 190;
  1280. btn_high[5] = 228;
  1281. btn_low[6] = 229;
  1282. btn_high[6] = 269;
  1283. btn_low[7] = 270;
  1284. btn_high[7] = 500;
  1285. n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
  1286. n_ready[0] = 80;
  1287. n_ready[1] = 68;
  1288. n_cic = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_CIC);
  1289. n_cic[0] = 60;
  1290. n_cic[1] = 47;
  1291. gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_GAIN);
  1292. gain[0] = 11;
  1293. gain[1] = 9;
  1294. return taiko_cal;
  1295. }
  1296. static int msm_snd_hw_params(struct snd_pcm_substream *substream,
  1297. struct snd_pcm_hw_params *params)
  1298. {
  1299. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1300. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1301. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1302. int ret = 0;
  1303. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  1304. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  1305. unsigned int user_set_tx_ch = 0;
  1306. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1307. pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch);
  1308. ret = snd_soc_dai_get_channel_map(codec_dai,
  1309. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1310. if (ret < 0) {
  1311. pr_err("%s: failed to get codec chan map\n", __func__);
  1312. goto end;
  1313. }
  1314. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  1315. msm_slim_0_rx_ch, rx_ch);
  1316. if (ret < 0) {
  1317. pr_err("%s: failed to set cpu chan map\n", __func__);
  1318. goto end;
  1319. }
  1320. } else {
  1321. pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
  1322. codec_dai->name, codec_dai->id, user_set_tx_ch);
  1323. ret = snd_soc_dai_get_channel_map(codec_dai,
  1324. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1325. if (ret < 0) {
  1326. pr_err("%s: failed to get codec chan map\n", __func__);
  1327. goto end;
  1328. }
  1329. /* For tabla_tx1 case */
  1330. if (codec_dai->id == 1)
  1331. user_set_tx_ch = msm_slim_0_tx_ch;
  1332. /* For tabla_tx2 case */
  1333. else if (codec_dai->id == 3)
  1334. user_set_tx_ch = params_channels(params);
  1335. else
  1336. user_set_tx_ch = tx_ch_cnt;
  1337. pr_debug("%s: msm_slim_0_tx_ch(%d)user_set_tx_ch(%d)tx_ch_cnt(%d)\n",
  1338. __func__, msm_slim_0_tx_ch, user_set_tx_ch, tx_ch_cnt);
  1339. ret = snd_soc_dai_set_channel_map(cpu_dai,
  1340. user_set_tx_ch, tx_ch, 0 , 0);
  1341. if (ret < 0) {
  1342. pr_err("%s: failed to set cpu chan map\n", __func__);
  1343. goto end;
  1344. }
  1345. }
  1346. end:
  1347. return ret;
  1348. }
  1349. static void apq8074_snd_shudown(struct snd_pcm_substream *substream)
  1350. {
  1351. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  1352. substream->name, substream->stream);
  1353. }
  1354. static struct snd_soc_ops apq8074_be_ops = {
  1355. .startup = apq8074_snd_startup,
  1356. .hw_params = msm_snd_hw_params,
  1357. .shutdown = apq8074_snd_shudown,
  1358. };
  1359. static int apq8074_slimbus_2_hw_params(struct snd_pcm_substream *substream,
  1360. struct snd_pcm_hw_params *params)
  1361. {
  1362. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  1363. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  1364. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  1365. int ret = 0;
  1366. unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  1367. unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
  1368. unsigned int num_tx_ch = 0;
  1369. unsigned int num_rx_ch = 0;
  1370. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  1371. num_rx_ch = params_channels(params);
  1372. pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
  1373. codec_dai->name, codec_dai->id, num_rx_ch);
  1374. ret = snd_soc_dai_get_channel_map(codec_dai,
  1375. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1376. if (ret < 0) {
  1377. pr_err("%s: failed to get codec chan map\n", __func__);
  1378. goto end;
  1379. }
  1380. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
  1381. num_rx_ch, rx_ch);
  1382. if (ret < 0) {
  1383. pr_err("%s: failed to set cpu chan map\n", __func__);
  1384. goto end;
  1385. }
  1386. } else {
  1387. num_tx_ch = params_channels(params);
  1388. pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
  1389. codec_dai->name, codec_dai->id, num_tx_ch);
  1390. ret = snd_soc_dai_get_channel_map(codec_dai,
  1391. &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
  1392. if (ret < 0) {
  1393. pr_err("%s: failed to get codec chan map\n", __func__);
  1394. goto end;
  1395. }
  1396. ret = snd_soc_dai_set_channel_map(cpu_dai,
  1397. num_tx_ch, tx_ch, 0 , 0);
  1398. if (ret < 0) {
  1399. pr_err("%s: failed to set cpu chan map\n", __func__);
  1400. goto end;
  1401. }
  1402. }
  1403. end:
  1404. return ret;
  1405. }
  1406. static struct snd_soc_ops apq8074_slimbus_2_be_ops = {
  1407. .startup = apq8074_snd_startup,
  1408. .hw_params = apq8074_slimbus_2_hw_params,
  1409. .shutdown = apq8074_snd_shudown,
  1410. };
  1411. /* Digital audio interface glue - connects codec <---> CPU */
  1412. static struct snd_soc_dai_link apq8074_common_dai_links[] = {
  1413. /* FrontEnd DAI Links */
  1414. {
  1415. .name = "MSM8974 Media1",
  1416. .stream_name = "MultiMedia1",
  1417. .cpu_dai_name = "MultiMedia1",
  1418. .platform_name = "msm-pcm-dsp.0",
  1419. .dynamic = 1,
  1420. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1421. SND_SOC_DPCM_TRIGGER_POST},
  1422. .codec_dai_name = "snd-soc-dummy-dai",
  1423. .codec_name = "snd-soc-dummy",
  1424. .ignore_suspend = 1,
  1425. /* this dainlink has playback support */
  1426. .ignore_pmdown_time = 1,
  1427. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
  1428. },
  1429. {
  1430. .name = "MSM8974 Media2",
  1431. .stream_name = "MultiMedia2",
  1432. .cpu_dai_name = "MultiMedia2",
  1433. .platform_name = "msm-pcm-dsp.0",
  1434. .dynamic = 1,
  1435. .codec_dai_name = "snd-soc-dummy-dai",
  1436. .codec_name = "snd-soc-dummy",
  1437. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1438. SND_SOC_DPCM_TRIGGER_POST},
  1439. .ignore_suspend = 1,
  1440. /* this dainlink has playback support */
  1441. .ignore_pmdown_time = 1,
  1442. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
  1443. },
  1444. {
  1445. .name = "Circuit-Switch Voice",
  1446. .stream_name = "CS-Voice",
  1447. .cpu_dai_name = "CS-VOICE",
  1448. .platform_name = "msm-pcm-voice",
  1449. .dynamic = 1,
  1450. .codec_dai_name = "snd-soc-dummy-dai",
  1451. .codec_name = "snd-soc-dummy",
  1452. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1453. SND_SOC_DPCM_TRIGGER_POST},
  1454. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1455. .ignore_suspend = 1,
  1456. /* this dainlink has playback support */
  1457. .ignore_pmdown_time = 1,
  1458. .be_id = MSM_FRONTEND_DAI_CS_VOICE,
  1459. },
  1460. {
  1461. .name = "MSM VoIP",
  1462. .stream_name = "VoIP",
  1463. .cpu_dai_name = "VoIP",
  1464. .platform_name = "msm-voip-dsp",
  1465. .dynamic = 1,
  1466. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1467. SND_SOC_DPCM_TRIGGER_POST},
  1468. .codec_dai_name = "snd-soc-dummy-dai",
  1469. .codec_name = "snd-soc-dummy",
  1470. .ignore_suspend = 1,
  1471. /* this dainlink has playback support */
  1472. .ignore_pmdown_time = 1,
  1473. .be_id = MSM_FRONTEND_DAI_VOIP,
  1474. },
  1475. {
  1476. .name = "MSM8974 LPA",
  1477. .stream_name = "LPA",
  1478. .cpu_dai_name = "MultiMedia3",
  1479. .platform_name = "msm-pcm-lpa",
  1480. .dynamic = 1,
  1481. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1482. SND_SOC_DPCM_TRIGGER_POST},
  1483. .codec_dai_name = "snd-soc-dummy-dai",
  1484. .codec_name = "snd-soc-dummy",
  1485. .ignore_suspend = 1,
  1486. /* this dainlink has playback support */
  1487. .ignore_pmdown_time = 1,
  1488. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
  1489. },
  1490. /* Hostless PCM purpose */
  1491. {
  1492. .name = "SLIMBUS_0 Hostless",
  1493. .stream_name = "SLIMBUS_0 Hostless",
  1494. .cpu_dai_name = "SLIMBUS0_HOSTLESS",
  1495. .platform_name = "msm-pcm-hostless",
  1496. .dynamic = 1,
  1497. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1498. SND_SOC_DPCM_TRIGGER_POST},
  1499. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1500. .ignore_suspend = 1,
  1501. .ignore_pmdown_time = 1, /* dai link has playback support */
  1502. .codec_dai_name = "snd-soc-dummy-dai",
  1503. .codec_name = "snd-soc-dummy",
  1504. },
  1505. {
  1506. .name = "INT_FM Hostless",
  1507. .stream_name = "INT_FM Hostless",
  1508. .cpu_dai_name = "INT_FM_HOSTLESS",
  1509. .platform_name = "msm-pcm-hostless",
  1510. .dynamic = 1,
  1511. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1512. SND_SOC_DPCM_TRIGGER_POST},
  1513. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1514. .ignore_suspend = 1,
  1515. /* this dainlink has playback support */
  1516. .ignore_pmdown_time = 1,
  1517. .codec_dai_name = "snd-soc-dummy-dai",
  1518. .codec_name = "snd-soc-dummy",
  1519. },
  1520. {
  1521. .name = "MSM AFE-PCM RX",
  1522. .stream_name = "AFE-PROXY RX",
  1523. .cpu_dai_name = "msm-dai-q6-dev.241",
  1524. .codec_name = "msm-stub-codec.1",
  1525. .codec_dai_name = "msm-stub-rx",
  1526. .platform_name = "msm-pcm-afe",
  1527. .ignore_suspend = 1,
  1528. /* this dainlink has playback support */
  1529. .ignore_pmdown_time = 1,
  1530. },
  1531. {
  1532. .name = "MSM AFE-PCM TX",
  1533. .stream_name = "AFE-PROXY TX",
  1534. .cpu_dai_name = "msm-dai-q6-dev.240",
  1535. .codec_name = "msm-stub-codec.1",
  1536. .codec_dai_name = "msm-stub-tx",
  1537. .platform_name = "msm-pcm-afe",
  1538. .ignore_suspend = 1,
  1539. },
  1540. {
  1541. .name = "MSM8974 Compr",
  1542. .stream_name = "COMPR",
  1543. .cpu_dai_name = "MultiMedia4",
  1544. .platform_name = "msm-compress-dsp",
  1545. .dynamic = 1,
  1546. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1547. SND_SOC_DPCM_TRIGGER_POST},
  1548. .codec_dai_name = "snd-soc-dummy-dai",
  1549. .codec_name = "snd-soc-dummy",
  1550. .ignore_suspend = 1,
  1551. .ignore_pmdown_time = 1,
  1552. /* this dainlink has playback support */
  1553. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
  1554. },
  1555. {
  1556. .name = "AUXPCM Hostless",
  1557. .stream_name = "AUXPCM Hostless",
  1558. .cpu_dai_name = "AUXPCM_HOSTLESS",
  1559. .platform_name = "msm-pcm-hostless",
  1560. .dynamic = 1,
  1561. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1562. SND_SOC_DPCM_TRIGGER_POST},
  1563. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1564. .ignore_suspend = 1,
  1565. /* this dainlink has playback support */
  1566. .ignore_pmdown_time = 1,
  1567. .codec_dai_name = "snd-soc-dummy-dai",
  1568. .codec_name = "snd-soc-dummy",
  1569. },
  1570. {
  1571. .name = "SLIMBUS_1 Hostless",
  1572. .stream_name = "SLIMBUS_1 Hostless",
  1573. .cpu_dai_name = "SLIMBUS1_HOSTLESS",
  1574. .platform_name = "msm-pcm-hostless",
  1575. .dynamic = 1,
  1576. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1577. SND_SOC_DPCM_TRIGGER_POST},
  1578. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1579. .ignore_suspend = 1,
  1580. .ignore_pmdown_time = 1, /* dai link has playback support */
  1581. .codec_dai_name = "snd-soc-dummy-dai",
  1582. .codec_name = "snd-soc-dummy",
  1583. },
  1584. {
  1585. .name = "SLIMBUS_3 Hostless",
  1586. .stream_name = "SLIMBUS_3 Hostless",
  1587. .cpu_dai_name = "SLIMBUS3_HOSTLESS",
  1588. .platform_name = "msm-pcm-hostless",
  1589. .dynamic = 1,
  1590. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1591. SND_SOC_DPCM_TRIGGER_POST},
  1592. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1593. .ignore_suspend = 1,
  1594. .ignore_pmdown_time = 1, /* dai link has playback support */
  1595. .codec_dai_name = "snd-soc-dummy-dai",
  1596. .codec_name = "snd-soc-dummy",
  1597. },
  1598. {
  1599. .name = "SLIMBUS_4 Hostless",
  1600. .stream_name = "SLIMBUS_4 Hostless",
  1601. .cpu_dai_name = "SLIMBUS4_HOSTLESS",
  1602. .platform_name = "msm-pcm-hostless",
  1603. .dynamic = 1,
  1604. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1605. SND_SOC_DPCM_TRIGGER_POST},
  1606. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1607. .ignore_suspend = 1,
  1608. .ignore_pmdown_time = 1, /* dai link has playback support */
  1609. .codec_dai_name = "snd-soc-dummy-dai",
  1610. .codec_name = "snd-soc-dummy",
  1611. },
  1612. {
  1613. .name = "VoLTE",
  1614. .stream_name = "VoLTE",
  1615. .cpu_dai_name = "VoLTE",
  1616. .platform_name = "msm-pcm-voice",
  1617. .dynamic = 1,
  1618. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1619. SND_SOC_DPCM_TRIGGER_POST},
  1620. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1621. .ignore_suspend = 1,
  1622. /* this dainlink has playback support */
  1623. .ignore_pmdown_time = 1,
  1624. .codec_dai_name = "snd-soc-dummy-dai",
  1625. .codec_name = "snd-soc-dummy",
  1626. .be_id = MSM_FRONTEND_DAI_VOLTE,
  1627. },
  1628. {
  1629. .name = "MSM8974 LowLatency",
  1630. .stream_name = "MultiMedia5",
  1631. .cpu_dai_name = "MultiMedia5",
  1632. .platform_name = "msm-pcm-dsp.1",
  1633. .dynamic = 1,
  1634. .codec_dai_name = "snd-soc-dummy-dai",
  1635. .codec_name = "snd-soc-dummy",
  1636. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1637. SND_SOC_DPCM_TRIGGER_POST},
  1638. .ignore_suspend = 1,
  1639. /* this dainlink has playback support */
  1640. .ignore_pmdown_time = 1,
  1641. .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
  1642. },
  1643. /* LSM FE */
  1644. {
  1645. .name = "Listen 1 Audio Service",
  1646. .stream_name = "Listen 1 Audio Service",
  1647. .cpu_dai_name = "LSM1",
  1648. .platform_name = "msm-lsm-client",
  1649. .dynamic = 1,
  1650. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1651. SND_SOC_DPCM_TRIGGER_POST },
  1652. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1653. .ignore_suspend = 1,
  1654. .ignore_pmdown_time = 1,
  1655. .codec_dai_name = "snd-soc-dummy-dai",
  1656. .codec_name = "snd-soc-dummy",
  1657. .be_id = MSM_FRONTEND_DAI_LSM1,
  1658. },
  1659. {
  1660. .name = "Listen 2 Audio Service",
  1661. .stream_name = "Listen 2 Audio Service",
  1662. .cpu_dai_name = "LSM2",
  1663. .platform_name = "msm-lsm-client",
  1664. .dynamic = 1,
  1665. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1666. SND_SOC_DPCM_TRIGGER_POST },
  1667. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1668. .ignore_suspend = 1,
  1669. .ignore_pmdown_time = 1,
  1670. .codec_dai_name = "snd-soc-dummy-dai",
  1671. .codec_name = "snd-soc-dummy",
  1672. .be_id = MSM_FRONTEND_DAI_LSM2,
  1673. },
  1674. {
  1675. .name = "Listen 3 Audio Service",
  1676. .stream_name = "Listen 3 Audio Service",
  1677. .cpu_dai_name = "LSM3",
  1678. .platform_name = "msm-lsm-client",
  1679. .dynamic = 1,
  1680. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1681. SND_SOC_DPCM_TRIGGER_POST },
  1682. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1683. .ignore_suspend = 1,
  1684. .ignore_pmdown_time = 1,
  1685. .codec_dai_name = "snd-soc-dummy-dai",
  1686. .codec_name = "snd-soc-dummy",
  1687. .be_id = MSM_FRONTEND_DAI_LSM3,
  1688. },
  1689. {
  1690. .name = "Listen 4 Audio Service",
  1691. .stream_name = "Listen 4 Audio Service",
  1692. .cpu_dai_name = "LSM4",
  1693. .platform_name = "msm-lsm-client",
  1694. .dynamic = 1,
  1695. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1696. SND_SOC_DPCM_TRIGGER_POST },
  1697. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1698. .ignore_suspend = 1,
  1699. .ignore_pmdown_time = 1,
  1700. .codec_dai_name = "snd-soc-dummy-dai",
  1701. .codec_name = "snd-soc-dummy",
  1702. .be_id = MSM_FRONTEND_DAI_LSM4,
  1703. },
  1704. {
  1705. .name = "Listen 5 Audio Service",
  1706. .stream_name = "Listen 5 Audio Service",
  1707. .cpu_dai_name = "LSM5",
  1708. .platform_name = "msm-lsm-client",
  1709. .dynamic = 1,
  1710. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1711. SND_SOC_DPCM_TRIGGER_POST },
  1712. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1713. .ignore_suspend = 1,
  1714. .ignore_pmdown_time = 1,
  1715. .codec_dai_name = "snd-soc-dummy-dai",
  1716. .codec_name = "snd-soc-dummy",
  1717. .be_id = MSM_FRONTEND_DAI_LSM5,
  1718. },
  1719. {
  1720. .name = "Listen 6 Audio Service",
  1721. .stream_name = "Listen 6 Audio Service",
  1722. .cpu_dai_name = "LSM6",
  1723. .platform_name = "msm-lsm-client",
  1724. .dynamic = 1,
  1725. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1726. SND_SOC_DPCM_TRIGGER_POST },
  1727. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1728. .ignore_suspend = 1,
  1729. .ignore_pmdown_time = 1,
  1730. .codec_dai_name = "snd-soc-dummy-dai",
  1731. .codec_name = "snd-soc-dummy",
  1732. .be_id = MSM_FRONTEND_DAI_LSM6,
  1733. },
  1734. {
  1735. .name = "Listen 7 Audio Service",
  1736. .stream_name = "Listen 7 Audio Service",
  1737. .cpu_dai_name = "LSM7",
  1738. .platform_name = "msm-lsm-client",
  1739. .dynamic = 1,
  1740. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1741. SND_SOC_DPCM_TRIGGER_POST },
  1742. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1743. .ignore_suspend = 1,
  1744. .ignore_pmdown_time = 1,
  1745. .codec_dai_name = "snd-soc-dummy-dai",
  1746. .codec_name = "snd-soc-dummy",
  1747. .be_id = MSM_FRONTEND_DAI_LSM7,
  1748. },
  1749. {
  1750. .name = "Listen 8 Audio Service",
  1751. .stream_name = "Listen 8 Audio Service",
  1752. .cpu_dai_name = "LSM8",
  1753. .platform_name = "msm-lsm-client",
  1754. .dynamic = 1,
  1755. .trigger = { SND_SOC_DPCM_TRIGGER_POST,
  1756. SND_SOC_DPCM_TRIGGER_POST },
  1757. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1758. .ignore_suspend = 1,
  1759. .ignore_pmdown_time = 1,
  1760. .codec_dai_name = "snd-soc-dummy-dai",
  1761. .codec_name = "snd-soc-dummy",
  1762. .be_id = MSM_FRONTEND_DAI_LSM8,
  1763. },
  1764. /* Backend BT/FM DAI Links */
  1765. {
  1766. .name = LPASS_BE_INT_BT_SCO_RX,
  1767. .stream_name = "Internal BT-SCO Playback",
  1768. .cpu_dai_name = "msm-dai-q6-dev.12288",
  1769. .platform_name = "msm-pcm-routing",
  1770. .codec_name = "msm-stub-codec.1",
  1771. .codec_dai_name = "msm-stub-rx",
  1772. .no_pcm = 1,
  1773. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
  1774. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  1775. /* this dainlink has playback support */
  1776. .ignore_pmdown_time = 1,
  1777. .ignore_suspend = 1,
  1778. },
  1779. {
  1780. .name = LPASS_BE_INT_BT_SCO_TX,
  1781. .stream_name = "Internal BT-SCO Capture",
  1782. .cpu_dai_name = "msm-dai-q6-dev.12289",
  1783. .platform_name = "msm-pcm-routing",
  1784. .codec_name = "msm-stub-codec.1",
  1785. .codec_dai_name = "msm-stub-tx",
  1786. .no_pcm = 1,
  1787. .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
  1788. .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
  1789. .ignore_suspend = 1,
  1790. },
  1791. {
  1792. .name = LPASS_BE_INT_FM_RX,
  1793. .stream_name = "Internal FM Playback",
  1794. .cpu_dai_name = "msm-dai-q6-dev.12292",
  1795. .platform_name = "msm-pcm-routing",
  1796. .codec_name = "msm-stub-codec.1",
  1797. .codec_dai_name = "msm-stub-rx",
  1798. .no_pcm = 1,
  1799. .be_id = MSM_BACKEND_DAI_INT_FM_RX,
  1800. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1801. /* this dainlink has playback support */
  1802. .ignore_pmdown_time = 1,
  1803. .ignore_suspend = 1,
  1804. },
  1805. {
  1806. .name = LPASS_BE_INT_FM_TX,
  1807. .stream_name = "Internal FM Capture",
  1808. .cpu_dai_name = "msm-dai-q6-dev.12293",
  1809. .platform_name = "msm-pcm-routing",
  1810. .codec_name = "msm-stub-codec.1",
  1811. .codec_dai_name = "msm-stub-tx",
  1812. .no_pcm = 1,
  1813. .be_id = MSM_BACKEND_DAI_INT_FM_TX,
  1814. .be_hw_params_fixup = msm_be_hw_params_fixup,
  1815. .ignore_suspend = 1,
  1816. },
  1817. /* Backend AFE DAI Links */
  1818. {
  1819. .name = LPASS_BE_AFE_PCM_RX,
  1820. .stream_name = "AFE Playback",
  1821. .cpu_dai_name = "msm-dai-q6-dev.224",
  1822. .platform_name = "msm-pcm-routing",
  1823. .codec_name = "msm-stub-codec.1",
  1824. .codec_dai_name = "msm-stub-rx",
  1825. .no_pcm = 1,
  1826. .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
  1827. .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
  1828. /* this dainlink has playback support */
  1829. .ignore_pmdown_time = 1,
  1830. .ignore_suspend = 1,
  1831. },
  1832. {
  1833. .name = LPASS_BE_AFE_PCM_TX,
  1834. .stream_name = "AFE Capture",
  1835. .cpu_dai_name = "msm-dai-q6-dev.225",
  1836. .platform_name = "msm-pcm-routing",
  1837. .codec_name = "msm-stub-codec.1",
  1838. .codec_dai_name = "msm-stub-tx",
  1839. .no_pcm = 1,
  1840. .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
  1841. .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
  1842. .ignore_suspend = 1,
  1843. },
  1844. /* HDMI Hostless */
  1845. {
  1846. .name = "HDMI_RX_HOSTLESS",
  1847. .stream_name = "HDMI_RX_HOSTLESS",
  1848. .cpu_dai_name = "HDMI_HOSTLESS",
  1849. .platform_name = "msm-pcm-hostless",
  1850. .dynamic = 1,
  1851. .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  1852. SND_SOC_DPCM_TRIGGER_POST},
  1853. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1854. .ignore_suspend = 1,
  1855. .ignore_pmdown_time = 1,
  1856. .codec_dai_name = "snd-soc-dummy-dai",
  1857. .codec_name = "snd-soc-dummy",
  1858. },
  1859. /* AUX PCM Backend DAI Links */
  1860. {
  1861. .name = LPASS_BE_AUXPCM_RX,
  1862. .stream_name = "AUX PCM Playback",
  1863. .cpu_dai_name = "msm-dai-q6-auxpcm.1",
  1864. .platform_name = "msm-pcm-routing",
  1865. .codec_name = "msm-stub-codec.1",
  1866. .codec_dai_name = "msm-stub-rx",
  1867. .no_pcm = 1,
  1868. .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
  1869. .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
  1870. .ops = &msm_auxpcm_be_ops,
  1871. .ignore_pmdown_time = 1,
  1872. .ignore_suspend = 1,
  1873. /* this dainlink has playback support */
  1874. },
  1875. {
  1876. .name = LPASS_BE_AUXPCM_TX,
  1877. .stream_name = "AUX PCM Capture",
  1878. .cpu_dai_name = "msm-dai-q6-auxpcm.1",
  1879. .platform_name = "msm-pcm-routing",
  1880. .codec_name = "msm-stub-codec.1",
  1881. .codec_dai_name = "msm-stub-tx",
  1882. .no_pcm = 1,
  1883. .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
  1884. .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
  1885. .ops = &msm_auxpcm_be_ops,
  1886. .ignore_suspend = 1,
  1887. },
  1888. /* Backend DAI Links */
  1889. {
  1890. .name = LPASS_BE_SLIMBUS_0_RX,
  1891. .stream_name = "Slimbus Playback",
  1892. .cpu_dai_name = "msm-dai-q6-dev.16384",
  1893. .platform_name = "msm-pcm-routing",
  1894. .codec_name = "taiko_codec",
  1895. .codec_dai_name = "taiko_rx1",
  1896. .no_pcm = 1,
  1897. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
  1898. .init = &msm_audrx_init,
  1899. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1900. .ops = &apq8074_be_ops,
  1901. .ignore_pmdown_time = 1, /* dai link has playback support */
  1902. .ignore_suspend = 1,
  1903. },
  1904. {
  1905. .name = LPASS_BE_SLIMBUS_0_TX,
  1906. .stream_name = "Slimbus Capture",
  1907. .cpu_dai_name = "msm-dai-q6-dev.16385",
  1908. .platform_name = "msm-pcm-routing",
  1909. .codec_name = "taiko_codec",
  1910. .codec_dai_name = "taiko_tx1",
  1911. .no_pcm = 1,
  1912. .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
  1913. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1914. .ops = &apq8074_be_ops,
  1915. .ignore_suspend = 1,
  1916. },
  1917. {
  1918. .name = LPASS_BE_SLIMBUS_1_RX,
  1919. .stream_name = "Slimbus1 Playback",
  1920. .cpu_dai_name = "msm-dai-q6-dev.16386",
  1921. .platform_name = "msm-pcm-routing",
  1922. .codec_name = "taiko_codec",
  1923. .codec_dai_name = "taiko_rx1",
  1924. .no_pcm = 1,
  1925. .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
  1926. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1927. .ops = &apq8074_be_ops,
  1928. /* dai link has playback support */
  1929. .ignore_pmdown_time = 1,
  1930. .ignore_suspend = 1,
  1931. },
  1932. {
  1933. .name = LPASS_BE_SLIMBUS_1_TX,
  1934. .stream_name = "Slimbus1 Capture",
  1935. .cpu_dai_name = "msm-dai-q6-dev.16387",
  1936. .platform_name = "msm-pcm-routing",
  1937. .codec_name = "taiko_codec",
  1938. .codec_dai_name = "taiko_tx1",
  1939. .no_pcm = 1,
  1940. .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
  1941. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1942. .ops = &apq8074_be_ops,
  1943. .ignore_suspend = 1,
  1944. },
  1945. {
  1946. .name = LPASS_BE_SLIMBUS_3_RX,
  1947. .stream_name = "Slimbus3 Playback",
  1948. .cpu_dai_name = "msm-dai-q6-dev.16390",
  1949. .platform_name = "msm-pcm-routing",
  1950. .codec_name = "taiko_codec",
  1951. .codec_dai_name = "taiko_rx1",
  1952. .no_pcm = 1,
  1953. .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
  1954. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1955. .ops = &apq8074_be_ops,
  1956. /* dai link has playback support */
  1957. .ignore_pmdown_time = 1,
  1958. .ignore_suspend = 1,
  1959. },
  1960. {
  1961. .name = LPASS_BE_SLIMBUS_3_TX,
  1962. .stream_name = "Slimbus3 Capture",
  1963. .cpu_dai_name = "msm-dai-q6-dev.16391",
  1964. .platform_name = "msm-pcm-routing",
  1965. .codec_name = "taiko_codec",
  1966. .codec_dai_name = "taiko_tx1",
  1967. .no_pcm = 1,
  1968. .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
  1969. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1970. .ops = &apq8074_be_ops,
  1971. .ignore_suspend = 1,
  1972. },
  1973. {
  1974. .name = LPASS_BE_SLIMBUS_4_RX,
  1975. .stream_name = "Slimbus4 Playback",
  1976. .cpu_dai_name = "msm-dai-q6-dev.16392",
  1977. .platform_name = "msm-pcm-routing",
  1978. .codec_name = "taiko_codec",
  1979. .codec_dai_name = "taiko_rx1",
  1980. .no_pcm = 1,
  1981. .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
  1982. .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
  1983. .ops = &apq8074_be_ops,
  1984. /* dai link has playback support */
  1985. .ignore_pmdown_time = 1,
  1986. .ignore_suspend = 1,
  1987. },
  1988. {
  1989. .name = LPASS_BE_SLIMBUS_4_TX,
  1990. .stream_name = "Slimbus4 Capture",
  1991. .cpu_dai_name = "msm-dai-q6-dev.16393",
  1992. .platform_name = "msm-pcm-hostless",
  1993. .codec_name = "taiko_codec",
  1994. .codec_dai_name = "taiko_vifeedback",
  1995. .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
  1996. .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
  1997. .ops = &apq8074_be_ops,
  1998. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  1999. .ignore_suspend = 1,
  2000. },
  2001. /* Incall Record Uplink BACK END DAI Link */
  2002. {
  2003. .name = LPASS_BE_INCALL_RECORD_TX,
  2004. .stream_name = "Voice Uplink Capture",
  2005. .cpu_dai_name = "msm-dai-q6-dev.32772",
  2006. .platform_name = "msm-pcm-routing",
  2007. .codec_name = "msm-stub-codec.1",
  2008. .codec_dai_name = "msm-stub-tx",
  2009. .no_pcm = 1,
  2010. .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
  2011. .be_hw_params_fixup = msm_be_hw_params_fixup,
  2012. .ignore_suspend = 1,
  2013. },
  2014. /* Incall Record Downlink BACK END DAI Link */
  2015. {
  2016. .name = LPASS_BE_INCALL_RECORD_RX,
  2017. .stream_name = "Voice Downlink Capture",
  2018. .cpu_dai_name = "msm-dai-q6-dev.32771",
  2019. .platform_name = "msm-pcm-routing",
  2020. .codec_name = "msm-stub-codec.1",
  2021. .codec_dai_name = "msm-stub-tx",
  2022. .no_pcm = 1,
  2023. .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
  2024. .be_hw_params_fixup = msm_be_hw_params_fixup,
  2025. .ignore_suspend = 1,
  2026. },
  2027. /* MAD BE */
  2028. {
  2029. .name = LPASS_BE_SLIMBUS_5_TX,
  2030. .stream_name = "Slimbus5 Capture",
  2031. .cpu_dai_name = "msm-dai-q6-dev.16395",
  2032. .platform_name = "msm-pcm-routing",
  2033. .codec_name = "taiko_codec",
  2034. .codec_dai_name = "taiko_mad1",
  2035. .no_pcm = 1,
  2036. .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
  2037. .be_hw_params_fixup = msm_slim_5_tx_be_hw_params_fixup,
  2038. .ops = &apq8074_be_ops,
  2039. },
  2040. /* Incall Music BACK END DAI Link */
  2041. {
  2042. .name = LPASS_BE_VOICE_PLAYBACK_TX,
  2043. .stream_name = "Voice Farend Playback",
  2044. .cpu_dai_name = "msm-dai-q6-dev.32773",
  2045. .platform_name = "msm-pcm-routing",
  2046. .codec_name = "msm-stub-codec.1",
  2047. .codec_dai_name = "msm-stub-rx",
  2048. .no_pcm = 1,
  2049. .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
  2050. .be_hw_params_fixup = msm_be_hw_params_fixup,
  2051. .ignore_suspend = 1,
  2052. },
  2053. /* Ultrasound RX Back End DAI Link */
  2054. {
  2055. .name = "SLIMBUS_2 Hostless Playback",
  2056. .stream_name = "SLIMBUS_2 Hostless Playback",
  2057. .cpu_dai_name = "msm-dai-q6-dev.16388",
  2058. .platform_name = "msm-pcm-hostless",
  2059. .codec_name = "taiko_codec",
  2060. .codec_dai_name = "taiko_rx2",
  2061. .ignore_suspend = 1,
  2062. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2063. .ops = &apq8074_slimbus_2_be_ops,
  2064. },
  2065. /* Ultrasound TX Back End DAI Link */
  2066. {
  2067. .name = "SLIMBUS_2 Hostless Capture",
  2068. .stream_name = "SLIMBUS_2 Hostless Capture",
  2069. .cpu_dai_name = "msm-dai-q6-dev.16389",
  2070. .platform_name = "msm-pcm-hostless",
  2071. .codec_name = "taiko_codec",
  2072. .codec_dai_name = "taiko_tx2",
  2073. .ignore_suspend = 1,
  2074. .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
  2075. .ops = &apq8074_slimbus_2_be_ops,
  2076. },
  2077. };
  2078. static struct snd_soc_dai_link apq8074_hdmi_dai_link[] = {
  2079. /* HDMI BACK END DAI Link */
  2080. {
  2081. .name = LPASS_BE_HDMI,
  2082. .stream_name = "HDMI Playback",
  2083. .cpu_dai_name = "msm-dai-q6-hdmi.8",
  2084. .platform_name = "msm-pcm-routing",
  2085. .codec_name = "msm-hdmi-audio-codec-rx",
  2086. .codec_dai_name = "msm_hdmi_audio_codec_rx_dai",
  2087. .no_pcm = 1,
  2088. .be_id = MSM_BACKEND_DAI_HDMI_RX,
  2089. .be_hw_params_fixup = apq8074_hdmi_be_hw_params_fixup,
  2090. .ignore_pmdown_time = 1,
  2091. .ignore_suspend = 1,
  2092. },
  2093. };
  2094. static struct snd_soc_dai_link apq8074_dai_links[
  2095. ARRAY_SIZE(apq8074_common_dai_links) +
  2096. ARRAY_SIZE(apq8074_hdmi_dai_link)];
  2097. struct snd_soc_card snd_soc_card_apq8074 = {
  2098. .name = "apq8074-taiko-snd-card",
  2099. };
  2100. static int apq8074_dtparse_auxpcm(struct platform_device *pdev,
  2101. struct msm_auxpcm_ctrl **auxpcm_ctrl,
  2102. char *msm_auxpcm_gpio_name[][2])
  2103. {
  2104. int ret = 0;
  2105. int i = 0;
  2106. struct msm_auxpcm_gpio *pin_data = NULL;
  2107. struct msm_auxpcm_ctrl *ctrl;
  2108. unsigned int gpio_no[NUM_OF_AUXPCM_GPIOS];
  2109. enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
  2110. int auxpcm_cnt = 0;
  2111. pin_data = devm_kzalloc(&pdev->dev, (ARRAY_SIZE(gpio_no) *
  2112. sizeof(struct msm_auxpcm_gpio)),
  2113. GFP_KERNEL);
  2114. if (!pin_data) {
  2115. dev_err(&pdev->dev, "No memory for gpio\n");
  2116. ret = -ENOMEM;
  2117. goto err;
  2118. }
  2119. for (i = 0; i < ARRAY_SIZE(gpio_no); i++) {
  2120. gpio_no[i] = of_get_named_gpio_flags(pdev->dev.of_node,
  2121. msm_auxpcm_gpio_name[i][DT_PARSE_INDEX],
  2122. 0, &flags);
  2123. if (gpio_no[i] > 0) {
  2124. pin_data[i].gpio_name =
  2125. msm_auxpcm_gpio_name[auxpcm_cnt][GPIO_NAME_INDEX];
  2126. pin_data[i].gpio_no = gpio_no[i];
  2127. dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
  2128. "0x%x\n", __func__,
  2129. pin_data[i].gpio_name,
  2130. pin_data[i].gpio_no);
  2131. auxpcm_cnt++;
  2132. } else {
  2133. dev_err(&pdev->dev, "%s:Invalid AUXPCM GPIO[%s]= %x\n",
  2134. __func__,
  2135. msm_auxpcm_gpio_name[i][GPIO_NAME_INDEX],
  2136. gpio_no[i]);
  2137. ret = -ENODEV;
  2138. goto err;
  2139. }
  2140. }
  2141. ctrl = devm_kzalloc(&pdev->dev,
  2142. sizeof(struct msm_auxpcm_ctrl), GFP_KERNEL);
  2143. if (!ctrl) {
  2144. dev_err(&pdev->dev, "No memory for gpio\n");
  2145. ret = -ENOMEM;
  2146. goto err;
  2147. }
  2148. ctrl->pin_data = pin_data;
  2149. ctrl->cnt = auxpcm_cnt;
  2150. *auxpcm_ctrl = ctrl;
  2151. return ret;
  2152. err:
  2153. if (pin_data)
  2154. devm_kfree(&pdev->dev, pin_data);
  2155. return ret;
  2156. }
  2157. static int apq8074_prepare_codec_mclk(struct snd_soc_card *card)
  2158. {
  2159. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  2160. int ret;
  2161. if (pdata->mclk_gpio) {
  2162. ret = gpio_request(pdata->mclk_gpio, "TAIKO_CODEC_PMIC_MCLK");
  2163. if (ret) {
  2164. dev_err(card->dev,
  2165. "%s: Failed to request taiko mclk gpio %d\n",
  2166. __func__, pdata->mclk_gpio);
  2167. return ret;
  2168. }
  2169. }
  2170. return 0;
  2171. }
  2172. static int apq8074_prepare_us_euro(struct snd_soc_card *card)
  2173. {
  2174. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  2175. int ret;
  2176. if (pdata->us_euro_gpio) {
  2177. dev_dbg(card->dev, "%s : us_euro gpio request %d", __func__,
  2178. pdata->us_euro_gpio);
  2179. ret = gpio_request(pdata->us_euro_gpio, "TAIKO_CODEC_US_EURO");
  2180. if (ret) {
  2181. dev_err(card->dev,
  2182. "%s: Failed to request taiko US/EURO gpio %d error %d\n",
  2183. __func__, pdata->us_euro_gpio, ret);
  2184. return ret;
  2185. }
  2186. }
  2187. return 0;
  2188. }
  2189. static __devinit int apq8074_asoc_machine_probe(struct platform_device *pdev)
  2190. {
  2191. struct snd_soc_card *card = &snd_soc_card_apq8074;
  2192. struct apq8074_asoc_mach_data *pdata;
  2193. int ret;
  2194. const char *auxpcm_pri_gpio_set = NULL;
  2195. if (!pdev->dev.of_node) {
  2196. dev_err(&pdev->dev, "No platform supplied from device tree\n");
  2197. return -EINVAL;
  2198. }
  2199. pdata = devm_kzalloc(&pdev->dev,
  2200. sizeof(struct apq8074_asoc_mach_data), GFP_KERNEL);
  2201. if (!pdata) {
  2202. dev_err(&pdev->dev, "Can't allocate apq8074_asoc_mach_data\n");
  2203. return -ENOMEM;
  2204. }
  2205. /* Parse AUXPCM info from DT */
  2206. ret = apq8074_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
  2207. msm_prim_auxpcm_gpio_name);
  2208. if (ret) {
  2209. dev_err(&pdev->dev,
  2210. "%s: Auxpcm pin data parse failed\n", __func__);
  2211. goto err;
  2212. }
  2213. card->dev = &pdev->dev;
  2214. platform_set_drvdata(pdev, card);
  2215. snd_soc_card_set_drvdata(card, pdata);
  2216. ret = snd_soc_of_parse_card_name(card, "qcom,model");
  2217. if (ret)
  2218. goto err;
  2219. ret = snd_soc_of_parse_audio_routing(card,
  2220. "qcom,audio-routing");
  2221. if (ret)
  2222. goto err;
  2223. ret = of_property_read_u32(pdev->dev.of_node,
  2224. "qcom,taiko-mclk-clk-freq", &pdata->mclk_freq);
  2225. if (ret) {
  2226. dev_err(&pdev->dev, "Looking up %s property in node %s failed",
  2227. "qcom,taiko-mclk-clk-freq",
  2228. pdev->dev.of_node->full_name);
  2229. goto err;
  2230. }
  2231. if (pdata->mclk_freq != 9600000) {
  2232. dev_err(&pdev->dev, "unsupported taiko mclk freq %u\n",
  2233. pdata->mclk_freq);
  2234. ret = -EINVAL;
  2235. goto err;
  2236. }
  2237. pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
  2238. "qcom,cdc-mclk-gpios", 0);
  2239. if (pdata->mclk_gpio < 0) {
  2240. dev_err(&pdev->dev,
  2241. "Looking up %s property in node %s failed %d\n",
  2242. "qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
  2243. pdata->mclk_gpio);
  2244. ret = -ENODEV;
  2245. goto err;
  2246. }
  2247. ret = apq8074_prepare_codec_mclk(card);
  2248. if (ret)
  2249. goto err;
  2250. if (of_property_read_bool(pdev->dev.of_node, "qcom,hdmi-audio-rx")) {
  2251. dev_info(&pdev->dev, "%s(): hdmi audio support present\n",
  2252. __func__);
  2253. memcpy(apq8074_dai_links, apq8074_common_dai_links,
  2254. sizeof(apq8074_common_dai_links));
  2255. memcpy(apq8074_dai_links + ARRAY_SIZE(apq8074_common_dai_links),
  2256. apq8074_hdmi_dai_link, sizeof(apq8074_hdmi_dai_link));
  2257. card->dai_link = apq8074_dai_links;
  2258. card->num_links = ARRAY_SIZE(apq8074_dai_links);
  2259. } else {
  2260. dev_info(&pdev->dev, "%s(): No hdmi audio support\n", __func__);
  2261. card->dai_link = apq8074_common_dai_links;
  2262. card->num_links = ARRAY_SIZE(apq8074_common_dai_links);
  2263. }
  2264. pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
  2265. "qcom,us-euro-gpios", 0);
  2266. if (pdata->us_euro_gpio < 0) {
  2267. dev_err(&pdev->dev, "Looking up %s property in node %s failed",
  2268. "qcom,us-euro-gpios",
  2269. pdev->dev.of_node->full_name);
  2270. } else {
  2271. dev_dbg(&pdev->dev, "%s detected %d",
  2272. "qcom,us-euro-gpios", pdata->us_euro_gpio);
  2273. mbhc_cfg.swap_gnd_mic = apq8074_swap_gnd_mic;
  2274. }
  2275. ret = apq8074_prepare_us_euro(card);
  2276. if (ret)
  2277. dev_err(&pdev->dev, "apq8074_prepare_us_euro failed (%d)\n",
  2278. ret);
  2279. mutex_init(&cdc_mclk_mutex);
  2280. atomic_set(&prim_auxpcm_rsc_ref, 0);
  2281. spdev = pdev;
  2282. ext_spk_amp_regulator = NULL;
  2283. apq8074_liquid_dock_dev = NULL;
  2284. ret = snd_soc_register_card(card);
  2285. if (ret) {
  2286. dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
  2287. ret);
  2288. goto err;
  2289. }
  2290. ret = of_property_read_string(pdev->dev.of_node,
  2291. "qcom,prim-auxpcm-gpio-set", &auxpcm_pri_gpio_set);
  2292. if (ret) {
  2293. dev_err(&pdev->dev, "Looking up %s property in node %s failed",
  2294. "qcom,prim-auxpcm-gpio-set",
  2295. pdev->dev.of_node->full_name);
  2296. goto err;
  2297. }
  2298. if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
  2299. lpaif_pri_muxsel_virt_addr =
  2300. ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
  2301. } else if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-tert")) {
  2302. lpaif_pri_muxsel_virt_addr =
  2303. ioremap(LPAIF_TER_MODE_MUXSEL, 4);
  2304. } else {
  2305. dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
  2306. auxpcm_pri_gpio_set);
  2307. ret = -EINVAL;
  2308. goto err;
  2309. }
  2310. if (lpaif_pri_muxsel_virt_addr == NULL) {
  2311. pr_err("%s Pri muxsel virt addr is null\n", __func__);
  2312. ret = -EINVAL;
  2313. goto err;
  2314. }
  2315. return 0;
  2316. err:
  2317. if (pdata->mclk_gpio > 0) {
  2318. dev_dbg(&pdev->dev, "%s free gpio %d\n",
  2319. __func__, pdata->mclk_gpio);
  2320. gpio_free(pdata->mclk_gpio);
  2321. pdata->mclk_gpio = 0;
  2322. }
  2323. if (pdata->us_euro_gpio > 0) {
  2324. dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
  2325. __func__, pdata->us_euro_gpio);
  2326. gpio_free(pdata->us_euro_gpio);
  2327. pdata->us_euro_gpio = 0;
  2328. }
  2329. devm_kfree(&pdev->dev, pdata);
  2330. return ret;
  2331. }
  2332. static int __devexit apq8074_asoc_machine_remove(struct platform_device *pdev)
  2333. {
  2334. struct snd_soc_card *card = platform_get_drvdata(pdev);
  2335. struct apq8074_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
  2336. if (ext_spk_amp_regulator)
  2337. regulator_put(ext_spk_amp_regulator);
  2338. if (gpio_is_valid(ext_ult_spk_amp_gpio))
  2339. gpio_free(ext_ult_spk_amp_gpio);
  2340. gpio_free(pdata->mclk_gpio);
  2341. gpio_free(pdata->us_euro_gpio);
  2342. if (gpio_is_valid(ext_spk_amp_gpio))
  2343. gpio_free(ext_spk_amp_gpio);
  2344. if (apq8074_liquid_dock_dev != NULL) {
  2345. if (apq8074_liquid_dock_dev->dock_plug_gpio)
  2346. gpio_free(apq8074_liquid_dock_dev->dock_plug_gpio);
  2347. if (apq8074_liquid_dock_dev->dock_plug_irq)
  2348. free_irq(apq8074_liquid_dock_dev->dock_plug_irq,
  2349. apq8074_liquid_dock_dev);
  2350. kfree(apq8074_liquid_dock_dev);
  2351. apq8074_liquid_dock_dev = NULL;
  2352. }
  2353. iounmap(lpaif_pri_muxsel_virt_addr);
  2354. snd_soc_unregister_card(card);
  2355. return 0;
  2356. }
  2357. static const struct of_device_id apq8074_asoc_machine_of_match[] = {
  2358. { .compatible = "qcom,apq8074-audio-taiko", },
  2359. {},
  2360. };
  2361. static struct platform_driver apq8074_asoc_machine_driver = {
  2362. .driver = {
  2363. .name = DRV_NAME,
  2364. .owner = THIS_MODULE,
  2365. .pm = &snd_soc_pm_ops,
  2366. .of_match_table = apq8074_asoc_machine_of_match,
  2367. },
  2368. .probe = apq8074_asoc_machine_probe,
  2369. .remove = __devexit_p(apq8074_asoc_machine_remove),
  2370. };
  2371. module_platform_driver(apq8074_asoc_machine_driver);
  2372. MODULE_DESCRIPTION("ALSA SoC msm");
  2373. MODULE_LICENSE("GPL v2");
  2374. MODULE_ALIAS("platform:" DRV_NAME);
  2375. MODULE_DEVICE_TABLE(of, apq8074_asoc_machine_of_match);