soc-dapm.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539
  1. /*
  2. * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
  3. *
  4. * Copyright 2005 Wolfson Microelectronics PLC.
  5. * Author: Liam Girdwood
  6. * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * Features:
  14. * o Changes power status of internal codec blocks depending on the
  15. * dynamic configuration of codec internal audio paths and active
  16. * DAC's/ADC's.
  17. * o Platform power domain - can support external components i.e. amps and
  18. * mic/meadphone insertion events.
  19. * o Automatic Mic Bias support
  20. * o Jack insertion power event initiation - e.g. hp insertion will enable
  21. * sinks, dacs, etc
  22. * o Delayed powerdown of audio susbsystem to reduce pops between a quick
  23. * device reopen.
  24. *
  25. * Todo:
  26. * o DAPM power change sequencing - allow for configurable per
  27. * codec sequences.
  28. * o Support for analogue bias optimisation.
  29. * o Support for reduced codec oversampling rates.
  30. * o Support for reduced codec bias currents.
  31. */
  32. #include <linux/module.h>
  33. #include <linux/moduleparam.h>
  34. #include <linux/init.h>
  35. #include <linux/delay.h>
  36. #include <linux/pm.h>
  37. #include <linux/bitops.h>
  38. #include <linux/platform_device.h>
  39. #include <linux/jiffies.h>
  40. #include <sound/core.h>
  41. #include <sound/pcm.h>
  42. #include <sound/pcm_params.h>
  43. #include <sound/soc-dapm.h>
  44. #include <sound/initval.h>
  45. /* debug */
  46. #ifdef DEBUG
  47. #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
  48. #else
  49. #define dump_dapm(codec, action)
  50. #endif
  51. /* dapm power sequences - make this per codec in the future */
  52. static int dapm_up_seq[] = {
  53. snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
  54. snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
  55. snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
  56. };
  57. static int dapm_down_seq[] = {
  58. snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
  59. snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
  60. snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
  61. };
  62. static int dapm_status = 1;
  63. module_param(dapm_status, int, 0);
  64. MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
  65. static unsigned int pop_time;
  66. static void pop_wait(void)
  67. {
  68. if (pop_time)
  69. schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
  70. }
  71. static void pop_dbg(const char *fmt, ...)
  72. {
  73. va_list args;
  74. va_start(args, fmt);
  75. if (pop_time) {
  76. vprintk(fmt, args);
  77. pop_wait();
  78. }
  79. va_end(args);
  80. }
  81. /* create a new dapm widget */
  82. static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
  83. const struct snd_soc_dapm_widget *_widget)
  84. {
  85. return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
  86. }
  87. /* set up initial codec paths */
  88. static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
  89. struct snd_soc_dapm_path *p, int i)
  90. {
  91. switch (w->id) {
  92. case snd_soc_dapm_switch:
  93. case snd_soc_dapm_mixer: {
  94. int val;
  95. struct soc_mixer_control *mc = (struct soc_mixer_control *)
  96. w->kcontrols[i].private_value;
  97. uint reg = mc->reg;
  98. uint shift = mc->shift;
  99. int max = mc->max;
  100. uint mask = (1 << fls(max)) - 1;
  101. uint invert = mc->invert;
  102. val = snd_soc_read(w->codec, reg);
  103. val = (val >> shift) & mask;
  104. if ((invert && !val) || (!invert && val))
  105. p->connect = 1;
  106. else
  107. p->connect = 0;
  108. }
  109. break;
  110. case snd_soc_dapm_mux: {
  111. struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
  112. int val, item, bitmask;
  113. for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
  114. ;
  115. val = snd_soc_read(w->codec, e->reg);
  116. item = (val >> e->shift_l) & (bitmask - 1);
  117. p->connect = 0;
  118. for (i = 0; i < e->max; i++) {
  119. if (!(strcmp(p->name, e->texts[i])) && item == i)
  120. p->connect = 1;
  121. }
  122. }
  123. break;
  124. /* does not effect routing - always connected */
  125. case snd_soc_dapm_pga:
  126. case snd_soc_dapm_output:
  127. case snd_soc_dapm_adc:
  128. case snd_soc_dapm_input:
  129. case snd_soc_dapm_dac:
  130. case snd_soc_dapm_micbias:
  131. case snd_soc_dapm_vmid:
  132. p->connect = 1;
  133. break;
  134. /* does effect routing - dynamically connected */
  135. case snd_soc_dapm_hp:
  136. case snd_soc_dapm_mic:
  137. case snd_soc_dapm_spk:
  138. case snd_soc_dapm_line:
  139. case snd_soc_dapm_pre:
  140. case snd_soc_dapm_post:
  141. p->connect = 0;
  142. break;
  143. }
  144. }
  145. /* connect mux widget to it's interconnecting audio paths */
  146. static int dapm_connect_mux(struct snd_soc_codec *codec,
  147. struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
  148. struct snd_soc_dapm_path *path, const char *control_name,
  149. const struct snd_kcontrol_new *kcontrol)
  150. {
  151. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  152. int i;
  153. for (i = 0; i < e->max; i++) {
  154. if (!(strcmp(control_name, e->texts[i]))) {
  155. list_add(&path->list, &codec->dapm_paths);
  156. list_add(&path->list_sink, &dest->sources);
  157. list_add(&path->list_source, &src->sinks);
  158. path->name = (char*)e->texts[i];
  159. dapm_set_path_status(dest, path, 0);
  160. return 0;
  161. }
  162. }
  163. return -ENODEV;
  164. }
  165. /* connect mixer widget to it's interconnecting audio paths */
  166. static int dapm_connect_mixer(struct snd_soc_codec *codec,
  167. struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
  168. struct snd_soc_dapm_path *path, const char *control_name)
  169. {
  170. int i;
  171. /* search for mixer kcontrol */
  172. for (i = 0; i < dest->num_kcontrols; i++) {
  173. if (!strcmp(control_name, dest->kcontrols[i].name)) {
  174. list_add(&path->list, &codec->dapm_paths);
  175. list_add(&path->list_sink, &dest->sources);
  176. list_add(&path->list_source, &src->sinks);
  177. path->name = dest->kcontrols[i].name;
  178. dapm_set_path_status(dest, path, i);
  179. return 0;
  180. }
  181. }
  182. return -ENODEV;
  183. }
  184. /* update dapm codec register bits */
  185. static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
  186. {
  187. int change, power;
  188. unsigned short old, new;
  189. struct snd_soc_codec *codec = widget->codec;
  190. /* check for valid widgets */
  191. if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
  192. widget->id == snd_soc_dapm_output ||
  193. widget->id == snd_soc_dapm_hp ||
  194. widget->id == snd_soc_dapm_mic ||
  195. widget->id == snd_soc_dapm_line ||
  196. widget->id == snd_soc_dapm_spk)
  197. return 0;
  198. power = widget->power;
  199. if (widget->invert)
  200. power = (power ? 0:1);
  201. old = snd_soc_read(codec, widget->reg);
  202. new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
  203. change = old != new;
  204. if (change) {
  205. pop_dbg("pop test %s : %s in %d ms\n", widget->name,
  206. widget->power ? "on" : "off", pop_time);
  207. snd_soc_write(codec, widget->reg, new);
  208. pop_wait();
  209. }
  210. pr_debug("reg %x old %x new %x change %d\n", widget->reg,
  211. old, new, change);
  212. return change;
  213. }
  214. /* ramps the volume up or down to minimise pops before or after a
  215. * DAPM power event */
  216. static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
  217. {
  218. const struct snd_kcontrol_new *k = widget->kcontrols;
  219. if (widget->muted && !power)
  220. return 0;
  221. if (!widget->muted && power)
  222. return 0;
  223. if (widget->num_kcontrols && k) {
  224. struct soc_mixer_control *mc =
  225. (struct soc_mixer_control *)k->private_value;
  226. uint reg = mc->reg;
  227. uint shift = mc->shift;
  228. int max = mc->max;
  229. uint mask = (1 << fls(max)) - 1;
  230. uint invert = mc->invert;
  231. if (power) {
  232. int i;
  233. /* power up has happended, increase volume to last level */
  234. if (invert) {
  235. for (i = max; i > widget->saved_value; i--)
  236. snd_soc_update_bits(widget->codec, reg, mask, i);
  237. } else {
  238. for (i = 0; i < widget->saved_value; i++)
  239. snd_soc_update_bits(widget->codec, reg, mask, i);
  240. }
  241. widget->muted = 0;
  242. } else {
  243. /* power down is about to occur, decrease volume to mute */
  244. int val = snd_soc_read(widget->codec, reg);
  245. int i = widget->saved_value = (val >> shift) & mask;
  246. if (invert) {
  247. for (; i < mask; i++)
  248. snd_soc_update_bits(widget->codec, reg, mask, i);
  249. } else {
  250. for (; i > 0; i--)
  251. snd_soc_update_bits(widget->codec, reg, mask, i);
  252. }
  253. widget->muted = 1;
  254. }
  255. }
  256. return 0;
  257. }
  258. /* create new dapm mixer control */
  259. static int dapm_new_mixer(struct snd_soc_codec *codec,
  260. struct snd_soc_dapm_widget *w)
  261. {
  262. int i, ret = 0;
  263. char name[32];
  264. struct snd_soc_dapm_path *path;
  265. /* add kcontrol */
  266. for (i = 0; i < w->num_kcontrols; i++) {
  267. /* match name */
  268. list_for_each_entry(path, &w->sources, list_sink) {
  269. /* mixer/mux paths name must match control name */
  270. if (path->name != (char*)w->kcontrols[i].name)
  271. continue;
  272. /* add dapm control with long name */
  273. snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
  274. path->long_name = kstrdup (name, GFP_KERNEL);
  275. if (path->long_name == NULL)
  276. return -ENOMEM;
  277. path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
  278. path->long_name);
  279. ret = snd_ctl_add(codec->card, path->kcontrol);
  280. if (ret < 0) {
  281. printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
  282. path->long_name);
  283. kfree(path->long_name);
  284. path->long_name = NULL;
  285. return ret;
  286. }
  287. }
  288. }
  289. return ret;
  290. }
  291. /* create new dapm mux control */
  292. static int dapm_new_mux(struct snd_soc_codec *codec,
  293. struct snd_soc_dapm_widget *w)
  294. {
  295. struct snd_soc_dapm_path *path = NULL;
  296. struct snd_kcontrol *kcontrol;
  297. int ret = 0;
  298. if (!w->num_kcontrols) {
  299. printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
  300. return -EINVAL;
  301. }
  302. kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
  303. ret = snd_ctl_add(codec->card, kcontrol);
  304. if (ret < 0)
  305. goto err;
  306. list_for_each_entry(path, &w->sources, list_sink)
  307. path->kcontrol = kcontrol;
  308. return ret;
  309. err:
  310. printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
  311. return ret;
  312. }
  313. /* create new dapm volume control */
  314. static int dapm_new_pga(struct snd_soc_codec *codec,
  315. struct snd_soc_dapm_widget *w)
  316. {
  317. struct snd_kcontrol *kcontrol;
  318. int ret = 0;
  319. if (!w->num_kcontrols)
  320. return -EINVAL;
  321. kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
  322. ret = snd_ctl_add(codec->card, kcontrol);
  323. if (ret < 0) {
  324. printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
  325. return ret;
  326. }
  327. return ret;
  328. }
  329. /* reset 'walked' bit for each dapm path */
  330. static inline void dapm_clear_walk(struct snd_soc_codec *codec)
  331. {
  332. struct snd_soc_dapm_path *p;
  333. list_for_each_entry(p, &codec->dapm_paths, list)
  334. p->walked = 0;
  335. }
  336. /*
  337. * Recursively check for a completed path to an active or physically connected
  338. * output widget. Returns number of complete paths.
  339. */
  340. static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
  341. {
  342. struct snd_soc_dapm_path *path;
  343. int con = 0;
  344. if (widget->id == snd_soc_dapm_adc && widget->active)
  345. return 1;
  346. if (widget->connected) {
  347. /* connected pin ? */
  348. if (widget->id == snd_soc_dapm_output && !widget->ext)
  349. return 1;
  350. /* connected jack or spk ? */
  351. if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
  352. widget->id == snd_soc_dapm_line)
  353. return 1;
  354. }
  355. list_for_each_entry(path, &widget->sinks, list_source) {
  356. if (path->walked)
  357. continue;
  358. if (path->sink && path->connect) {
  359. path->walked = 1;
  360. con += is_connected_output_ep(path->sink);
  361. }
  362. }
  363. return con;
  364. }
  365. /*
  366. * Recursively check for a completed path to an active or physically connected
  367. * input widget. Returns number of complete paths.
  368. */
  369. static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
  370. {
  371. struct snd_soc_dapm_path *path;
  372. int con = 0;
  373. /* active stream ? */
  374. if (widget->id == snd_soc_dapm_dac && widget->active)
  375. return 1;
  376. if (widget->connected) {
  377. /* connected pin ? */
  378. if (widget->id == snd_soc_dapm_input && !widget->ext)
  379. return 1;
  380. /* connected VMID/Bias for lower pops */
  381. if (widget->id == snd_soc_dapm_vmid)
  382. return 1;
  383. /* connected jack ? */
  384. if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
  385. return 1;
  386. }
  387. list_for_each_entry(path, &widget->sources, list_sink) {
  388. if (path->walked)
  389. continue;
  390. if (path->source && path->connect) {
  391. path->walked = 1;
  392. con += is_connected_input_ep(path->source);
  393. }
  394. }
  395. return con;
  396. }
  397. /*
  398. * Handler for generic register modifier widget.
  399. */
  400. int dapm_reg_event(struct snd_soc_dapm_widget *w,
  401. struct snd_kcontrol *kcontrol, int event)
  402. {
  403. unsigned int val;
  404. if (SND_SOC_DAPM_EVENT_ON(event))
  405. val = w->on_val;
  406. else
  407. val = w->off_val;
  408. snd_soc_update_bits(w->codec, -(w->reg + 1),
  409. w->mask << w->shift, val << w->shift);
  410. return 0;
  411. }
  412. EXPORT_SYMBOL_GPL(dapm_reg_event);
  413. /*
  414. * Scan each dapm widget for complete audio path.
  415. * A complete path is a route that has valid endpoints i.e.:-
  416. *
  417. * o DAC to output pin.
  418. * o Input Pin to ADC.
  419. * o Input pin to Output pin (bypass, sidetone)
  420. * o DAC to ADC (loopback).
  421. */
  422. static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
  423. {
  424. struct snd_soc_dapm_widget *w;
  425. int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
  426. /* do we have a sequenced stream event */
  427. if (event == SND_SOC_DAPM_STREAM_START) {
  428. c = ARRAY_SIZE(dapm_up_seq);
  429. seq = dapm_up_seq;
  430. } else if (event == SND_SOC_DAPM_STREAM_STOP) {
  431. c = ARRAY_SIZE(dapm_down_seq);
  432. seq = dapm_down_seq;
  433. }
  434. for(i = 0; i < c; i++) {
  435. list_for_each_entry(w, &codec->dapm_widgets, list) {
  436. /* is widget in stream order */
  437. if (seq && seq[i] && w->id != seq[i])
  438. continue;
  439. /* vmid - no action */
  440. if (w->id == snd_soc_dapm_vmid)
  441. continue;
  442. /* active ADC */
  443. if (w->id == snd_soc_dapm_adc && w->active) {
  444. in = is_connected_input_ep(w);
  445. dapm_clear_walk(w->codec);
  446. w->power = (in != 0) ? 1 : 0;
  447. dapm_update_bits(w);
  448. continue;
  449. }
  450. /* active DAC */
  451. if (w->id == snd_soc_dapm_dac && w->active) {
  452. out = is_connected_output_ep(w);
  453. dapm_clear_walk(w->codec);
  454. w->power = (out != 0) ? 1 : 0;
  455. dapm_update_bits(w);
  456. continue;
  457. }
  458. /* pre and post event widgets */
  459. if (w->id == snd_soc_dapm_pre) {
  460. if (!w->event)
  461. continue;
  462. if (event == SND_SOC_DAPM_STREAM_START) {
  463. ret = w->event(w,
  464. NULL, SND_SOC_DAPM_PRE_PMU);
  465. if (ret < 0)
  466. return ret;
  467. } else if (event == SND_SOC_DAPM_STREAM_STOP) {
  468. ret = w->event(w,
  469. NULL, SND_SOC_DAPM_PRE_PMD);
  470. if (ret < 0)
  471. return ret;
  472. }
  473. continue;
  474. }
  475. if (w->id == snd_soc_dapm_post) {
  476. if (!w->event)
  477. continue;
  478. if (event == SND_SOC_DAPM_STREAM_START) {
  479. ret = w->event(w,
  480. NULL, SND_SOC_DAPM_POST_PMU);
  481. if (ret < 0)
  482. return ret;
  483. } else if (event == SND_SOC_DAPM_STREAM_STOP) {
  484. ret = w->event(w,
  485. NULL, SND_SOC_DAPM_POST_PMD);
  486. if (ret < 0)
  487. return ret;
  488. }
  489. continue;
  490. }
  491. /* all other widgets */
  492. in = is_connected_input_ep(w);
  493. dapm_clear_walk(w->codec);
  494. out = is_connected_output_ep(w);
  495. dapm_clear_walk(w->codec);
  496. power = (out != 0 && in != 0) ? 1 : 0;
  497. power_change = (w->power == power) ? 0: 1;
  498. w->power = power;
  499. if (!power_change)
  500. continue;
  501. /* call any power change event handlers */
  502. if (w->event)
  503. pr_debug("power %s event for %s flags %x\n",
  504. w->power ? "on" : "off",
  505. w->name, w->event_flags);
  506. /* power up pre event */
  507. if (power && w->event &&
  508. (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
  509. ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
  510. if (ret < 0)
  511. return ret;
  512. }
  513. /* power down pre event */
  514. if (!power && w->event &&
  515. (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
  516. ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
  517. if (ret < 0)
  518. return ret;
  519. }
  520. /* Lower PGA volume to reduce pops */
  521. if (w->id == snd_soc_dapm_pga && !power)
  522. dapm_set_pga(w, power);
  523. dapm_update_bits(w);
  524. /* Raise PGA volume to reduce pops */
  525. if (w->id == snd_soc_dapm_pga && power)
  526. dapm_set_pga(w, power);
  527. /* power up post event */
  528. if (power && w->event &&
  529. (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
  530. ret = w->event(w,
  531. NULL, SND_SOC_DAPM_POST_PMU);
  532. if (ret < 0)
  533. return ret;
  534. }
  535. /* power down post event */
  536. if (!power && w->event &&
  537. (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
  538. ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
  539. if (ret < 0)
  540. return ret;
  541. }
  542. }
  543. }
  544. return ret;
  545. }
  546. #ifdef DEBUG
  547. static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
  548. {
  549. struct snd_soc_dapm_widget *w;
  550. struct snd_soc_dapm_path *p = NULL;
  551. int in, out;
  552. printk("DAPM %s %s\n", codec->name, action);
  553. list_for_each_entry(w, &codec->dapm_widgets, list) {
  554. /* only display widgets that effect routing */
  555. switch (w->id) {
  556. case snd_soc_dapm_pre:
  557. case snd_soc_dapm_post:
  558. case snd_soc_dapm_vmid:
  559. continue;
  560. case snd_soc_dapm_mux:
  561. case snd_soc_dapm_output:
  562. case snd_soc_dapm_input:
  563. case snd_soc_dapm_switch:
  564. case snd_soc_dapm_hp:
  565. case snd_soc_dapm_mic:
  566. case snd_soc_dapm_spk:
  567. case snd_soc_dapm_line:
  568. case snd_soc_dapm_micbias:
  569. case snd_soc_dapm_dac:
  570. case snd_soc_dapm_adc:
  571. case snd_soc_dapm_pga:
  572. case snd_soc_dapm_mixer:
  573. if (w->name) {
  574. in = is_connected_input_ep(w);
  575. dapm_clear_walk(w->codec);
  576. out = is_connected_output_ep(w);
  577. dapm_clear_walk(w->codec);
  578. printk("%s: %s in %d out %d\n", w->name,
  579. w->power ? "On":"Off",in, out);
  580. list_for_each_entry(p, &w->sources, list_sink) {
  581. if (p->connect)
  582. printk(" in %s %s\n", p->name ? p->name : "static",
  583. p->source->name);
  584. }
  585. list_for_each_entry(p, &w->sinks, list_source) {
  586. if (p->connect)
  587. printk(" out %s %s\n", p->name ? p->name : "static",
  588. p->sink->name);
  589. }
  590. }
  591. break;
  592. }
  593. }
  594. }
  595. #endif
  596. /* test and update the power status of a mux widget */
  597. static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
  598. struct snd_kcontrol *kcontrol, int mask,
  599. int val, struct soc_enum* e)
  600. {
  601. struct snd_soc_dapm_path *path;
  602. int found = 0;
  603. if (widget->id != snd_soc_dapm_mux)
  604. return -ENODEV;
  605. if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
  606. return 0;
  607. /* find dapm widget path assoc with kcontrol */
  608. list_for_each_entry(path, &widget->codec->dapm_paths, list) {
  609. if (path->kcontrol != kcontrol)
  610. continue;
  611. if (!path->name || ! e->texts[val])
  612. continue;
  613. found = 1;
  614. /* we now need to match the string in the enum to the path */
  615. if (!(strcmp(path->name, e->texts[val])))
  616. path->connect = 1; /* new connection */
  617. else
  618. path->connect = 0; /* old connection must be powered down */
  619. }
  620. if (found) {
  621. dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
  622. dump_dapm(widget->codec, "mux power update");
  623. }
  624. return 0;
  625. }
  626. /* test and update the power status of a mixer or switch widget */
  627. static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
  628. struct snd_kcontrol *kcontrol, int reg,
  629. int val_mask, int val, int invert)
  630. {
  631. struct snd_soc_dapm_path *path;
  632. int found = 0;
  633. if (widget->id != snd_soc_dapm_mixer &&
  634. widget->id != snd_soc_dapm_switch)
  635. return -ENODEV;
  636. if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
  637. return 0;
  638. /* find dapm widget path assoc with kcontrol */
  639. list_for_each_entry(path, &widget->codec->dapm_paths, list) {
  640. if (path->kcontrol != kcontrol)
  641. continue;
  642. /* found, now check type */
  643. found = 1;
  644. if (val)
  645. /* new connection */
  646. path->connect = invert ? 0:1;
  647. else
  648. /* old connection must be powered down */
  649. path->connect = invert ? 1:0;
  650. break;
  651. }
  652. if (found) {
  653. dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
  654. dump_dapm(widget->codec, "mixer power update");
  655. }
  656. return 0;
  657. }
  658. /* show dapm widget status in sys fs */
  659. static ssize_t dapm_widget_show(struct device *dev,
  660. struct device_attribute *attr, char *buf)
  661. {
  662. struct snd_soc_device *devdata = dev_get_drvdata(dev);
  663. struct snd_soc_codec *codec = devdata->codec;
  664. struct snd_soc_dapm_widget *w;
  665. int count = 0;
  666. char *state = "not set";
  667. list_for_each_entry(w, &codec->dapm_widgets, list) {
  668. /* only display widgets that burnm power */
  669. switch (w->id) {
  670. case snd_soc_dapm_hp:
  671. case snd_soc_dapm_mic:
  672. case snd_soc_dapm_spk:
  673. case snd_soc_dapm_line:
  674. case snd_soc_dapm_micbias:
  675. case snd_soc_dapm_dac:
  676. case snd_soc_dapm_adc:
  677. case snd_soc_dapm_pga:
  678. case snd_soc_dapm_mixer:
  679. if (w->name)
  680. count += sprintf(buf + count, "%s: %s\n",
  681. w->name, w->power ? "On":"Off");
  682. break;
  683. default:
  684. break;
  685. }
  686. }
  687. switch (codec->bias_level) {
  688. case SND_SOC_BIAS_ON:
  689. state = "On";
  690. break;
  691. case SND_SOC_BIAS_PREPARE:
  692. state = "Prepare";
  693. break;
  694. case SND_SOC_BIAS_STANDBY:
  695. state = "Standby";
  696. break;
  697. case SND_SOC_BIAS_OFF:
  698. state = "Off";
  699. break;
  700. }
  701. count += sprintf(buf + count, "PM State: %s\n", state);
  702. return count;
  703. }
  704. static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
  705. /* pop/click delay times */
  706. static ssize_t dapm_pop_time_show(struct device *dev,
  707. struct device_attribute *attr, char *buf)
  708. {
  709. return sprintf(buf, "%d\n", pop_time);
  710. }
  711. static ssize_t dapm_pop_time_store(struct device *dev,
  712. struct device_attribute *attr,
  713. const char *buf, size_t count)
  714. {
  715. unsigned long val;
  716. if (strict_strtoul(buf, 10, &val) >= 0)
  717. pop_time = val;
  718. else
  719. printk(KERN_ERR "Unable to parse pop_time setting\n");
  720. return count;
  721. }
  722. static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show,
  723. dapm_pop_time_store);
  724. int snd_soc_dapm_sys_add(struct device *dev)
  725. {
  726. int ret = 0;
  727. if (dapm_status) {
  728. ret = device_create_file(dev, &dev_attr_dapm_widget);
  729. if (ret == 0)
  730. ret = device_create_file(dev, &dev_attr_dapm_pop_time);
  731. }
  732. return ret;
  733. }
  734. static void snd_soc_dapm_sys_remove(struct device *dev)
  735. {
  736. if (dapm_status) {
  737. device_remove_file(dev, &dev_attr_dapm_pop_time);
  738. device_remove_file(dev, &dev_attr_dapm_widget);
  739. }
  740. }
  741. /* free all dapm widgets and resources */
  742. static void dapm_free_widgets(struct snd_soc_codec *codec)
  743. {
  744. struct snd_soc_dapm_widget *w, *next_w;
  745. struct snd_soc_dapm_path *p, *next_p;
  746. list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
  747. list_del(&w->list);
  748. kfree(w);
  749. }
  750. list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
  751. list_del(&p->list);
  752. kfree(p->long_name);
  753. kfree(p);
  754. }
  755. }
  756. static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
  757. char *pin, int status)
  758. {
  759. struct snd_soc_dapm_widget *w;
  760. list_for_each_entry(w, &codec->dapm_widgets, list) {
  761. if (!strcmp(w->name, pin)) {
  762. pr_debug("dapm: %s: pin %s\n", codec->name, pin);
  763. w->connected = status;
  764. return 0;
  765. }
  766. }
  767. pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
  768. return -EINVAL;
  769. }
  770. /**
  771. * snd_soc_dapm_sync - scan and power dapm paths
  772. * @codec: audio codec
  773. *
  774. * Walks all dapm audio paths and powers widgets according to their
  775. * stream or path usage.
  776. *
  777. * Returns 0 for success.
  778. */
  779. int snd_soc_dapm_sync(struct snd_soc_codec *codec)
  780. {
  781. int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
  782. dump_dapm(codec, "sync");
  783. return ret;
  784. }
  785. EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
  786. static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
  787. const char *sink, const char *control, const char *source)
  788. {
  789. struct snd_soc_dapm_path *path;
  790. struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
  791. int ret = 0;
  792. /* find src and dest widgets */
  793. list_for_each_entry(w, &codec->dapm_widgets, list) {
  794. if (!wsink && !(strcmp(w->name, sink))) {
  795. wsink = w;
  796. continue;
  797. }
  798. if (!wsource && !(strcmp(w->name, source))) {
  799. wsource = w;
  800. }
  801. }
  802. if (wsource == NULL || wsink == NULL)
  803. return -ENODEV;
  804. path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
  805. if (!path)
  806. return -ENOMEM;
  807. path->source = wsource;
  808. path->sink = wsink;
  809. INIT_LIST_HEAD(&path->list);
  810. INIT_LIST_HEAD(&path->list_source);
  811. INIT_LIST_HEAD(&path->list_sink);
  812. /* check for external widgets */
  813. if (wsink->id == snd_soc_dapm_input) {
  814. if (wsource->id == snd_soc_dapm_micbias ||
  815. wsource->id == snd_soc_dapm_mic ||
  816. wsink->id == snd_soc_dapm_line ||
  817. wsink->id == snd_soc_dapm_output)
  818. wsink->ext = 1;
  819. }
  820. if (wsource->id == snd_soc_dapm_output) {
  821. if (wsink->id == snd_soc_dapm_spk ||
  822. wsink->id == snd_soc_dapm_hp ||
  823. wsink->id == snd_soc_dapm_line ||
  824. wsink->id == snd_soc_dapm_input)
  825. wsource->ext = 1;
  826. }
  827. /* connect static paths */
  828. if (control == NULL) {
  829. list_add(&path->list, &codec->dapm_paths);
  830. list_add(&path->list_sink, &wsink->sources);
  831. list_add(&path->list_source, &wsource->sinks);
  832. path->connect = 1;
  833. return 0;
  834. }
  835. /* connect dynamic paths */
  836. switch(wsink->id) {
  837. case snd_soc_dapm_adc:
  838. case snd_soc_dapm_dac:
  839. case snd_soc_dapm_pga:
  840. case snd_soc_dapm_input:
  841. case snd_soc_dapm_output:
  842. case snd_soc_dapm_micbias:
  843. case snd_soc_dapm_vmid:
  844. case snd_soc_dapm_pre:
  845. case snd_soc_dapm_post:
  846. list_add(&path->list, &codec->dapm_paths);
  847. list_add(&path->list_sink, &wsink->sources);
  848. list_add(&path->list_source, &wsource->sinks);
  849. path->connect = 1;
  850. return 0;
  851. case snd_soc_dapm_mux:
  852. ret = dapm_connect_mux(codec, wsource, wsink, path, control,
  853. &wsink->kcontrols[0]);
  854. if (ret != 0)
  855. goto err;
  856. break;
  857. case snd_soc_dapm_switch:
  858. case snd_soc_dapm_mixer:
  859. ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
  860. if (ret != 0)
  861. goto err;
  862. break;
  863. case snd_soc_dapm_hp:
  864. case snd_soc_dapm_mic:
  865. case snd_soc_dapm_line:
  866. case snd_soc_dapm_spk:
  867. list_add(&path->list, &codec->dapm_paths);
  868. list_add(&path->list_sink, &wsink->sources);
  869. list_add(&path->list_source, &wsource->sinks);
  870. path->connect = 0;
  871. return 0;
  872. }
  873. return 0;
  874. err:
  875. printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
  876. control, sink);
  877. kfree(path);
  878. return ret;
  879. }
  880. /**
  881. * snd_soc_dapm_connect_input - connect dapm widgets
  882. * @codec: audio codec
  883. * @sink: name of target widget
  884. * @control: mixer control name
  885. * @source: name of source name
  886. *
  887. * Connects 2 dapm widgets together via a named audio path. The sink is
  888. * the widget receiving the audio signal, whilst the source is the sender
  889. * of the audio signal.
  890. *
  891. * This function has been deprecated in favour of snd_soc_dapm_add_routes().
  892. *
  893. * Returns 0 for success else error.
  894. */
  895. int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
  896. const char *control, const char *source)
  897. {
  898. return snd_soc_dapm_add_route(codec, sink, control, source);
  899. }
  900. EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
  901. /**
  902. * snd_soc_dapm_add_routes - Add routes between DAPM widgets
  903. * @codec: codec
  904. * @route: audio routes
  905. * @num: number of routes
  906. *
  907. * Connects 2 dapm widgets together via a named audio path. The sink is
  908. * the widget receiving the audio signal, whilst the source is the sender
  909. * of the audio signal.
  910. *
  911. * Returns 0 for success else error. On error all resources can be freed
  912. * with a call to snd_soc_card_free().
  913. */
  914. int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
  915. const struct snd_soc_dapm_route *route, int num)
  916. {
  917. int i, ret;
  918. for (i = 0; i < num; i++) {
  919. ret = snd_soc_dapm_add_route(codec, route->sink,
  920. route->control, route->source);
  921. if (ret < 0) {
  922. printk(KERN_ERR "Failed to add route %s->%s\n",
  923. route->source,
  924. route->sink);
  925. return ret;
  926. }
  927. route++;
  928. }
  929. return 0;
  930. }
  931. EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
  932. /**
  933. * snd_soc_dapm_new_widgets - add new dapm widgets
  934. * @codec: audio codec
  935. *
  936. * Checks the codec for any new dapm widgets and creates them if found.
  937. *
  938. * Returns 0 for success.
  939. */
  940. int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
  941. {
  942. struct snd_soc_dapm_widget *w;
  943. list_for_each_entry(w, &codec->dapm_widgets, list)
  944. {
  945. if (w->new)
  946. continue;
  947. switch(w->id) {
  948. case snd_soc_dapm_switch:
  949. case snd_soc_dapm_mixer:
  950. dapm_new_mixer(codec, w);
  951. break;
  952. case snd_soc_dapm_mux:
  953. dapm_new_mux(codec, w);
  954. break;
  955. case snd_soc_dapm_adc:
  956. case snd_soc_dapm_dac:
  957. case snd_soc_dapm_pga:
  958. dapm_new_pga(codec, w);
  959. break;
  960. case snd_soc_dapm_input:
  961. case snd_soc_dapm_output:
  962. case snd_soc_dapm_micbias:
  963. case snd_soc_dapm_spk:
  964. case snd_soc_dapm_hp:
  965. case snd_soc_dapm_mic:
  966. case snd_soc_dapm_line:
  967. case snd_soc_dapm_vmid:
  968. case snd_soc_dapm_pre:
  969. case snd_soc_dapm_post:
  970. break;
  971. }
  972. w->new = 1;
  973. }
  974. dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
  975. return 0;
  976. }
  977. EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
  978. /**
  979. * snd_soc_dapm_get_volsw - dapm mixer get callback
  980. * @kcontrol: mixer control
  981. * @uinfo: control element information
  982. *
  983. * Callback to get the value of a dapm mixer control.
  984. *
  985. * Returns 0 for success.
  986. */
  987. int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
  988. struct snd_ctl_elem_value *ucontrol)
  989. {
  990. struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
  991. struct soc_mixer_control *mc =
  992. (struct soc_mixer_control *)kcontrol->private_value;
  993. uint reg = mc->reg;
  994. uint shift = mc->shift;
  995. uint rshift = mc->rshift;
  996. int max = mc->max;
  997. uint invert = mc->invert;
  998. uint mask = (1 << fls(max)) - 1;
  999. /* return the saved value if we are powered down */
  1000. if (widget->id == snd_soc_dapm_pga && !widget->power) {
  1001. ucontrol->value.integer.value[0] = widget->saved_value;
  1002. return 0;
  1003. }
  1004. ucontrol->value.integer.value[0] =
  1005. (snd_soc_read(widget->codec, reg) >> shift) & mask;
  1006. if (shift != rshift)
  1007. ucontrol->value.integer.value[1] =
  1008. (snd_soc_read(widget->codec, reg) >> rshift) & mask;
  1009. if (invert) {
  1010. ucontrol->value.integer.value[0] =
  1011. max - ucontrol->value.integer.value[0];
  1012. if (shift != rshift)
  1013. ucontrol->value.integer.value[1] =
  1014. max - ucontrol->value.integer.value[1];
  1015. }
  1016. return 0;
  1017. }
  1018. EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
  1019. /**
  1020. * snd_soc_dapm_put_volsw - dapm mixer set callback
  1021. * @kcontrol: mixer control
  1022. * @uinfo: control element information
  1023. *
  1024. * Callback to set the value of a dapm mixer control.
  1025. *
  1026. * Returns 0 for success.
  1027. */
  1028. int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
  1029. struct snd_ctl_elem_value *ucontrol)
  1030. {
  1031. struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
  1032. struct soc_mixer_control *mc =
  1033. (struct soc_mixer_control *)kcontrol->private_value;
  1034. uint reg = mc->reg;
  1035. uint shift = mc->shift;
  1036. uint rshift = mc->rshift;
  1037. int max = mc->max;
  1038. uint mask = (1 << fls(max)) - 1;
  1039. uint invert = mc->invert;
  1040. unsigned short val, val2, val_mask;
  1041. int ret;
  1042. val = (ucontrol->value.integer.value[0] & mask);
  1043. if (invert)
  1044. val = max - val;
  1045. val_mask = mask << shift;
  1046. val = val << shift;
  1047. if (shift != rshift) {
  1048. val2 = (ucontrol->value.integer.value[1] & mask);
  1049. if (invert)
  1050. val2 = max - val2;
  1051. val_mask |= mask << rshift;
  1052. val |= val2 << rshift;
  1053. }
  1054. mutex_lock(&widget->codec->mutex);
  1055. widget->value = val;
  1056. /* save volume value if the widget is powered down */
  1057. if (widget->id == snd_soc_dapm_pga && !widget->power) {
  1058. widget->saved_value = val;
  1059. mutex_unlock(&widget->codec->mutex);
  1060. return 1;
  1061. }
  1062. dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
  1063. if (widget->event) {
  1064. if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
  1065. ret = widget->event(widget, kcontrol,
  1066. SND_SOC_DAPM_PRE_REG);
  1067. if (ret < 0) {
  1068. ret = 1;
  1069. goto out;
  1070. }
  1071. }
  1072. ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
  1073. if (widget->event_flags & SND_SOC_DAPM_POST_REG)
  1074. ret = widget->event(widget, kcontrol,
  1075. SND_SOC_DAPM_POST_REG);
  1076. } else
  1077. ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
  1078. out:
  1079. mutex_unlock(&widget->codec->mutex);
  1080. return ret;
  1081. }
  1082. EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
  1083. /**
  1084. * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
  1085. * @kcontrol: mixer control
  1086. * @uinfo: control element information
  1087. *
  1088. * Callback to get the value of a dapm enumerated double mixer control.
  1089. *
  1090. * Returns 0 for success.
  1091. */
  1092. int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
  1093. struct snd_ctl_elem_value *ucontrol)
  1094. {
  1095. struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
  1096. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  1097. unsigned short val, bitmask;
  1098. for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
  1099. ;
  1100. val = snd_soc_read(widget->codec, e->reg);
  1101. ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
  1102. if (e->shift_l != e->shift_r)
  1103. ucontrol->value.enumerated.item[1] =
  1104. (val >> e->shift_r) & (bitmask - 1);
  1105. return 0;
  1106. }
  1107. EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
  1108. /**
  1109. * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
  1110. * @kcontrol: mixer control
  1111. * @uinfo: control element information
  1112. *
  1113. * Callback to set the value of a dapm enumerated double mixer control.
  1114. *
  1115. * Returns 0 for success.
  1116. */
  1117. int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
  1118. struct snd_ctl_elem_value *ucontrol)
  1119. {
  1120. struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
  1121. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  1122. unsigned short val, mux;
  1123. unsigned short mask, bitmask;
  1124. int ret = 0;
  1125. for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
  1126. ;
  1127. if (ucontrol->value.enumerated.item[0] > e->max - 1)
  1128. return -EINVAL;
  1129. mux = ucontrol->value.enumerated.item[0];
  1130. val = mux << e->shift_l;
  1131. mask = (bitmask - 1) << e->shift_l;
  1132. if (e->shift_l != e->shift_r) {
  1133. if (ucontrol->value.enumerated.item[1] > e->max - 1)
  1134. return -EINVAL;
  1135. val |= ucontrol->value.enumerated.item[1] << e->shift_r;
  1136. mask |= (bitmask - 1) << e->shift_r;
  1137. }
  1138. mutex_lock(&widget->codec->mutex);
  1139. widget->value = val;
  1140. dapm_mux_update_power(widget, kcontrol, mask, mux, e);
  1141. if (widget->event) {
  1142. if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
  1143. ret = widget->event(widget,
  1144. kcontrol, SND_SOC_DAPM_PRE_REG);
  1145. if (ret < 0)
  1146. goto out;
  1147. }
  1148. ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
  1149. if (widget->event_flags & SND_SOC_DAPM_POST_REG)
  1150. ret = widget->event(widget,
  1151. kcontrol, SND_SOC_DAPM_POST_REG);
  1152. } else
  1153. ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
  1154. out:
  1155. mutex_unlock(&widget->codec->mutex);
  1156. return ret;
  1157. }
  1158. EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
  1159. /**
  1160. * snd_soc_dapm_new_control - create new dapm control
  1161. * @codec: audio codec
  1162. * @widget: widget template
  1163. *
  1164. * Creates a new dapm control based upon the template.
  1165. *
  1166. * Returns 0 for success else error.
  1167. */
  1168. int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
  1169. const struct snd_soc_dapm_widget *widget)
  1170. {
  1171. struct snd_soc_dapm_widget *w;
  1172. if ((w = dapm_cnew_widget(widget)) == NULL)
  1173. return -ENOMEM;
  1174. w->codec = codec;
  1175. INIT_LIST_HEAD(&w->sources);
  1176. INIT_LIST_HEAD(&w->sinks);
  1177. INIT_LIST_HEAD(&w->list);
  1178. list_add(&w->list, &codec->dapm_widgets);
  1179. /* machine layer set ups unconnected pins and insertions */
  1180. w->connected = 1;
  1181. return 0;
  1182. }
  1183. EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
  1184. /**
  1185. * snd_soc_dapm_new_controls - create new dapm controls
  1186. * @codec: audio codec
  1187. * @widget: widget array
  1188. * @num: number of widgets
  1189. *
  1190. * Creates new DAPM controls based upon the templates.
  1191. *
  1192. * Returns 0 for success else error.
  1193. */
  1194. int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
  1195. const struct snd_soc_dapm_widget *widget,
  1196. int num)
  1197. {
  1198. int i, ret;
  1199. for (i = 0; i < num; i++) {
  1200. ret = snd_soc_dapm_new_control(codec, widget);
  1201. if (ret < 0)
  1202. return ret;
  1203. widget++;
  1204. }
  1205. return 0;
  1206. }
  1207. EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
  1208. /**
  1209. * snd_soc_dapm_stream_event - send a stream event to the dapm core
  1210. * @codec: audio codec
  1211. * @stream: stream name
  1212. * @event: stream event
  1213. *
  1214. * Sends a stream event to the dapm core. The core then makes any
  1215. * necessary widget power changes.
  1216. *
  1217. * Returns 0 for success else error.
  1218. */
  1219. int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
  1220. char *stream, int event)
  1221. {
  1222. struct snd_soc_dapm_widget *w;
  1223. if (stream == NULL)
  1224. return 0;
  1225. mutex_lock(&codec->mutex);
  1226. list_for_each_entry(w, &codec->dapm_widgets, list)
  1227. {
  1228. if (!w->sname)
  1229. continue;
  1230. pr_debug("widget %s\n %s stream %s event %d\n",
  1231. w->name, w->sname, stream, event);
  1232. if (strstr(w->sname, stream)) {
  1233. switch(event) {
  1234. case SND_SOC_DAPM_STREAM_START:
  1235. w->active = 1;
  1236. break;
  1237. case SND_SOC_DAPM_STREAM_STOP:
  1238. w->active = 0;
  1239. break;
  1240. case SND_SOC_DAPM_STREAM_SUSPEND:
  1241. if (w->active)
  1242. w->suspend = 1;
  1243. w->active = 0;
  1244. break;
  1245. case SND_SOC_DAPM_STREAM_RESUME:
  1246. if (w->suspend) {
  1247. w->active = 1;
  1248. w->suspend = 0;
  1249. }
  1250. break;
  1251. case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
  1252. break;
  1253. case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
  1254. break;
  1255. }
  1256. }
  1257. }
  1258. mutex_unlock(&codec->mutex);
  1259. dapm_power_widgets(codec, event);
  1260. dump_dapm(codec, __func__);
  1261. return 0;
  1262. }
  1263. EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
  1264. /**
  1265. * snd_soc_dapm_set_bias_level - set the bias level for the system
  1266. * @socdev: audio device
  1267. * @level: level to configure
  1268. *
  1269. * Configure the bias (power) levels for the SoC audio device.
  1270. *
  1271. * Returns 0 for success else error.
  1272. */
  1273. int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
  1274. enum snd_soc_bias_level level)
  1275. {
  1276. struct snd_soc_codec *codec = socdev->codec;
  1277. struct snd_soc_machine *machine = socdev->machine;
  1278. int ret = 0;
  1279. if (machine->set_bias_level)
  1280. ret = machine->set_bias_level(machine, level);
  1281. if (ret == 0 && codec->set_bias_level)
  1282. ret = codec->set_bias_level(codec, level);
  1283. return ret;
  1284. }
  1285. /**
  1286. * snd_soc_dapm_enable_pin - enable pin.
  1287. * @snd_soc_codec: SoC codec
  1288. * @pin: pin name
  1289. *
  1290. * Enables input/output pin and it's parents or children widgets iff there is
  1291. * a valid audio route and active audio stream.
  1292. * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  1293. * do any widget power switching.
  1294. */
  1295. int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
  1296. {
  1297. return snd_soc_dapm_set_pin(codec, pin, 1);
  1298. }
  1299. EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
  1300. /**
  1301. * snd_soc_dapm_disable_pin - disable pin.
  1302. * @codec: SoC codec
  1303. * @pin: pin name
  1304. *
  1305. * Disables input/output pin and it's parents or children widgets.
  1306. * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  1307. * do any widget power switching.
  1308. */
  1309. int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
  1310. {
  1311. return snd_soc_dapm_set_pin(codec, pin, 0);
  1312. }
  1313. EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
  1314. /**
  1315. * snd_soc_dapm_get_pin_status - get audio pin status
  1316. * @codec: audio codec
  1317. * @pin: audio signal pin endpoint (or start point)
  1318. *
  1319. * Get audio pin status - connected or disconnected.
  1320. *
  1321. * Returns 1 for connected otherwise 0.
  1322. */
  1323. int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
  1324. {
  1325. struct snd_soc_dapm_widget *w;
  1326. list_for_each_entry(w, &codec->dapm_widgets, list) {
  1327. if (!strcmp(w->name, pin))
  1328. return w->connected;
  1329. }
  1330. return 0;
  1331. }
  1332. EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
  1333. /**
  1334. * snd_soc_dapm_free - free dapm resources
  1335. * @socdev: SoC device
  1336. *
  1337. * Free all dapm widgets and resources.
  1338. */
  1339. void snd_soc_dapm_free(struct snd_soc_device *socdev)
  1340. {
  1341. struct snd_soc_codec *codec = socdev->codec;
  1342. snd_soc_dapm_sys_remove(socdev->dev);
  1343. dapm_free_widgets(codec);
  1344. }
  1345. EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
  1346. /* Module information */
  1347. MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
  1348. MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
  1349. MODULE_LICENSE("GPL");