layout.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. /*
  2. * Apple Onboard Audio driver -- layout/machine id fabric
  3. *
  4. * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
  5. *
  6. * GPL v2, can be found in COPYING.
  7. *
  8. *
  9. * This fabric module looks for sound codecs based on the
  10. * layout-id or device-id property in the device tree.
  11. */
  12. #include <asm/prom.h>
  13. #include <linux/list.h>
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #include "../aoa.h"
  17. #include "../soundbus/soundbus.h"
  18. MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
  19. MODULE_LICENSE("GPL");
  20. MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa");
  21. #define MAX_CODECS_PER_BUS 2
  22. /* These are the connections the layout fabric
  23. * knows about. It doesn't really care about the
  24. * input ones, but I thought I'd separate them
  25. * to give them proper names. The thing is that
  26. * Apple usually will distinguish the active output
  27. * by GPIOs, while the active input is set directly
  28. * on the codec. Hence we here tell the codec what
  29. * we think is connected. This information is hard-
  30. * coded below ... */
  31. #define CC_SPEAKERS (1<<0)
  32. #define CC_HEADPHONE (1<<1)
  33. #define CC_LINEOUT (1<<2)
  34. #define CC_DIGITALOUT (1<<3)
  35. #define CC_LINEIN (1<<4)
  36. #define CC_MICROPHONE (1<<5)
  37. #define CC_DIGITALIN (1<<6)
  38. /* pretty bogus but users complain...
  39. * This is a flag saying that the LINEOUT
  40. * should be renamed to HEADPHONE.
  41. * be careful with input detection! */
  42. #define CC_LINEOUT_LABELLED_HEADPHONE (1<<7)
  43. struct codec_connection {
  44. /* CC_ flags from above */
  45. int connected;
  46. /* codec dependent bit to be set in the aoa_codec.connected field.
  47. * This intentionally doesn't have any generic flags because the
  48. * fabric has to know the codec anyway and all codecs might have
  49. * different connectors */
  50. int codec_bit;
  51. };
  52. struct codec_connect_info {
  53. char *name;
  54. struct codec_connection *connections;
  55. };
  56. #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)
  57. struct layout {
  58. unsigned int layout_id, device_id;
  59. struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
  60. int flags;
  61. /* if busname is not assigned, we use 'Master' below,
  62. * so that our layout table doesn't need to be filled
  63. * too much.
  64. * We only assign these two if we expect to find more
  65. * than one soundbus, i.e. on those machines with
  66. * multiple layout-ids */
  67. char *busname;
  68. int pcmid;
  69. };
  70. MODULE_ALIAS("sound-layout-36");
  71. MODULE_ALIAS("sound-layout-41");
  72. MODULE_ALIAS("sound-layout-45");
  73. MODULE_ALIAS("sound-layout-47");
  74. MODULE_ALIAS("sound-layout-48");
  75. MODULE_ALIAS("sound-layout-49");
  76. MODULE_ALIAS("sound-layout-50");
  77. MODULE_ALIAS("sound-layout-51");
  78. MODULE_ALIAS("sound-layout-56");
  79. MODULE_ALIAS("sound-layout-57");
  80. MODULE_ALIAS("sound-layout-58");
  81. MODULE_ALIAS("sound-layout-60");
  82. MODULE_ALIAS("sound-layout-61");
  83. MODULE_ALIAS("sound-layout-62");
  84. MODULE_ALIAS("sound-layout-64");
  85. MODULE_ALIAS("sound-layout-65");
  86. MODULE_ALIAS("sound-layout-66");
  87. MODULE_ALIAS("sound-layout-67");
  88. MODULE_ALIAS("sound-layout-68");
  89. MODULE_ALIAS("sound-layout-69");
  90. MODULE_ALIAS("sound-layout-70");
  91. MODULE_ALIAS("sound-layout-72");
  92. MODULE_ALIAS("sound-layout-76");
  93. MODULE_ALIAS("sound-layout-80");
  94. MODULE_ALIAS("sound-layout-82");
  95. MODULE_ALIAS("sound-layout-84");
  96. MODULE_ALIAS("sound-layout-86");
  97. MODULE_ALIAS("sound-layout-90");
  98. MODULE_ALIAS("sound-layout-92");
  99. MODULE_ALIAS("sound-layout-94");
  100. MODULE_ALIAS("sound-layout-96");
  101. MODULE_ALIAS("sound-layout-98");
  102. MODULE_ALIAS("sound-layout-100");
  103. MODULE_ALIAS("aoa-device-id-14");
  104. MODULE_ALIAS("aoa-device-id-22");
  105. MODULE_ALIAS("aoa-device-id-35");
  106. MODULE_ALIAS("aoa-device-id-44");
  107. /* onyx with all but microphone connected */
  108. static struct codec_connection onyx_connections_nomic[] = {
  109. {
  110. .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
  111. .codec_bit = 0,
  112. },
  113. {
  114. .connected = CC_DIGITALOUT,
  115. .codec_bit = 1,
  116. },
  117. {
  118. .connected = CC_LINEIN,
  119. .codec_bit = 2,
  120. },
  121. {} /* terminate array by .connected == 0 */
  122. };
  123. /* onyx on machines without headphone */
  124. static struct codec_connection onyx_connections_noheadphones[] = {
  125. {
  126. .connected = CC_SPEAKERS | CC_LINEOUT |
  127. CC_LINEOUT_LABELLED_HEADPHONE,
  128. .codec_bit = 0,
  129. },
  130. {
  131. .connected = CC_DIGITALOUT,
  132. .codec_bit = 1,
  133. },
  134. /* FIXME: are these correct? probably not for all the machines
  135. * below ... If not this will need separating. */
  136. {
  137. .connected = CC_LINEIN,
  138. .codec_bit = 2,
  139. },
  140. {
  141. .connected = CC_MICROPHONE,
  142. .codec_bit = 3,
  143. },
  144. {} /* terminate array by .connected == 0 */
  145. };
  146. /* onyx on machines with real line-out */
  147. static struct codec_connection onyx_connections_reallineout[] = {
  148. {
  149. .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
  150. .codec_bit = 0,
  151. },
  152. {
  153. .connected = CC_DIGITALOUT,
  154. .codec_bit = 1,
  155. },
  156. {
  157. .connected = CC_LINEIN,
  158. .codec_bit = 2,
  159. },
  160. {} /* terminate array by .connected == 0 */
  161. };
  162. /* tas on machines without line out */
  163. static struct codec_connection tas_connections_nolineout[] = {
  164. {
  165. .connected = CC_SPEAKERS | CC_HEADPHONE,
  166. .codec_bit = 0,
  167. },
  168. {
  169. .connected = CC_LINEIN,
  170. .codec_bit = 2,
  171. },
  172. {
  173. .connected = CC_MICROPHONE,
  174. .codec_bit = 3,
  175. },
  176. {} /* terminate array by .connected == 0 */
  177. };
  178. /* tas on machines with neither line out nor line in */
  179. static struct codec_connection tas_connections_noline[] = {
  180. {
  181. .connected = CC_SPEAKERS | CC_HEADPHONE,
  182. .codec_bit = 0,
  183. },
  184. {
  185. .connected = CC_MICROPHONE,
  186. .codec_bit = 3,
  187. },
  188. {} /* terminate array by .connected == 0 */
  189. };
  190. /* tas on machines without microphone */
  191. static struct codec_connection tas_connections_nomic[] = {
  192. {
  193. .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
  194. .codec_bit = 0,
  195. },
  196. {
  197. .connected = CC_LINEIN,
  198. .codec_bit = 2,
  199. },
  200. {} /* terminate array by .connected == 0 */
  201. };
  202. /* tas on machines with everything connected */
  203. static struct codec_connection tas_connections_all[] = {
  204. {
  205. .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
  206. .codec_bit = 0,
  207. },
  208. {
  209. .connected = CC_LINEIN,
  210. .codec_bit = 2,
  211. },
  212. {
  213. .connected = CC_MICROPHONE,
  214. .codec_bit = 3,
  215. },
  216. {} /* terminate array by .connected == 0 */
  217. };
  218. static struct codec_connection toonie_connections[] = {
  219. {
  220. .connected = CC_SPEAKERS | CC_HEADPHONE,
  221. .codec_bit = 0,
  222. },
  223. {} /* terminate array by .connected == 0 */
  224. };
  225. static struct codec_connection topaz_input[] = {
  226. {
  227. .connected = CC_DIGITALIN,
  228. .codec_bit = 0,
  229. },
  230. {} /* terminate array by .connected == 0 */
  231. };
  232. static struct codec_connection topaz_output[] = {
  233. {
  234. .connected = CC_DIGITALOUT,
  235. .codec_bit = 1,
  236. },
  237. {} /* terminate array by .connected == 0 */
  238. };
  239. static struct codec_connection topaz_inout[] = {
  240. {
  241. .connected = CC_DIGITALIN,
  242. .codec_bit = 0,
  243. },
  244. {
  245. .connected = CC_DIGITALOUT,
  246. .codec_bit = 1,
  247. },
  248. {} /* terminate array by .connected == 0 */
  249. };
  250. static struct layout layouts[] = {
  251. /* last PowerBooks (15" Oct 2005) */
  252. { .layout_id = 82,
  253. .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
  254. .codecs[0] = {
  255. .name = "onyx",
  256. .connections = onyx_connections_noheadphones,
  257. },
  258. .codecs[1] = {
  259. .name = "topaz",
  260. .connections = topaz_input,
  261. },
  262. },
  263. /* PowerMac9,1 */
  264. { .layout_id = 60,
  265. .codecs[0] = {
  266. .name = "onyx",
  267. .connections = onyx_connections_reallineout,
  268. },
  269. },
  270. /* PowerMac9,1 */
  271. { .layout_id = 61,
  272. .codecs[0] = {
  273. .name = "topaz",
  274. .connections = topaz_input,
  275. },
  276. },
  277. /* PowerBook5,7 */
  278. { .layout_id = 64,
  279. .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
  280. .codecs[0] = {
  281. .name = "onyx",
  282. .connections = onyx_connections_noheadphones,
  283. },
  284. },
  285. /* PowerBook5,7 */
  286. { .layout_id = 65,
  287. .codecs[0] = {
  288. .name = "topaz",
  289. .connections = topaz_input,
  290. },
  291. },
  292. /* PowerBook5,9 [17" Oct 2005] */
  293. { .layout_id = 84,
  294. .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
  295. .codecs[0] = {
  296. .name = "onyx",
  297. .connections = onyx_connections_noheadphones,
  298. },
  299. .codecs[1] = {
  300. .name = "topaz",
  301. .connections = topaz_input,
  302. },
  303. },
  304. /* PowerMac8,1 */
  305. { .layout_id = 45,
  306. .codecs[0] = {
  307. .name = "onyx",
  308. .connections = onyx_connections_noheadphones,
  309. },
  310. .codecs[1] = {
  311. .name = "topaz",
  312. .connections = topaz_input,
  313. },
  314. },
  315. /* Quad PowerMac (analog in, analog/digital out) */
  316. { .layout_id = 68,
  317. .codecs[0] = {
  318. .name = "onyx",
  319. .connections = onyx_connections_nomic,
  320. },
  321. },
  322. /* Quad PowerMac (digital in) */
  323. { .layout_id = 69,
  324. .codecs[0] = {
  325. .name = "topaz",
  326. .connections = topaz_input,
  327. },
  328. .busname = "digital in", .pcmid = 1 },
  329. /* Early 2005 PowerBook (PowerBook 5,6) */
  330. { .layout_id = 70,
  331. .codecs[0] = {
  332. .name = "tas",
  333. .connections = tas_connections_nolineout,
  334. },
  335. },
  336. /* PowerBook 5,4 */
  337. { .layout_id = 51,
  338. .codecs[0] = {
  339. .name = "tas",
  340. .connections = tas_connections_nolineout,
  341. },
  342. },
  343. /* PowerBook6,5 */
  344. { .device_id = 44,
  345. .codecs[0] = {
  346. .name = "tas",
  347. .connections = tas_connections_all,
  348. },
  349. },
  350. /* PowerBook6,7 */
  351. { .layout_id = 80,
  352. .codecs[0] = {
  353. .name = "tas",
  354. .connections = tas_connections_noline,
  355. },
  356. },
  357. /* PowerBook6,8 */
  358. { .layout_id = 72,
  359. .codecs[0] = {
  360. .name = "tas",
  361. .connections = tas_connections_nolineout,
  362. },
  363. },
  364. /* PowerMac8,2 */
  365. { .layout_id = 86,
  366. .codecs[0] = {
  367. .name = "onyx",
  368. .connections = onyx_connections_nomic,
  369. },
  370. .codecs[1] = {
  371. .name = "topaz",
  372. .connections = topaz_input,
  373. },
  374. },
  375. /* PowerBook6,7 */
  376. { .layout_id = 92,
  377. .codecs[0] = {
  378. .name = "tas",
  379. .connections = tas_connections_nolineout,
  380. },
  381. },
  382. /* PowerMac10,1 (Mac Mini) */
  383. { .layout_id = 58,
  384. .codecs[0] = {
  385. .name = "toonie",
  386. .connections = toonie_connections,
  387. },
  388. },
  389. {
  390. .layout_id = 96,
  391. .codecs[0] = {
  392. .name = "onyx",
  393. .connections = onyx_connections_noheadphones,
  394. },
  395. },
  396. /* unknown, untested, but this comes from Apple */
  397. { .layout_id = 41,
  398. .codecs[0] = {
  399. .name = "tas",
  400. .connections = tas_connections_all,
  401. },
  402. },
  403. { .layout_id = 36,
  404. .codecs[0] = {
  405. .name = "tas",
  406. .connections = tas_connections_nomic,
  407. },
  408. .codecs[1] = {
  409. .name = "topaz",
  410. .connections = topaz_inout,
  411. },
  412. },
  413. { .layout_id = 47,
  414. .codecs[0] = {
  415. .name = "onyx",
  416. .connections = onyx_connections_noheadphones,
  417. },
  418. },
  419. { .layout_id = 48,
  420. .codecs[0] = {
  421. .name = "topaz",
  422. .connections = topaz_input,
  423. },
  424. },
  425. { .layout_id = 49,
  426. .codecs[0] = {
  427. .name = "onyx",
  428. .connections = onyx_connections_nomic,
  429. },
  430. },
  431. { .layout_id = 50,
  432. .codecs[0] = {
  433. .name = "topaz",
  434. .connections = topaz_input,
  435. },
  436. },
  437. { .layout_id = 56,
  438. .codecs[0] = {
  439. .name = "onyx",
  440. .connections = onyx_connections_noheadphones,
  441. },
  442. },
  443. { .layout_id = 57,
  444. .codecs[0] = {
  445. .name = "topaz",
  446. .connections = topaz_input,
  447. },
  448. },
  449. { .layout_id = 62,
  450. .codecs[0] = {
  451. .name = "onyx",
  452. .connections = onyx_connections_noheadphones,
  453. },
  454. .codecs[1] = {
  455. .name = "topaz",
  456. .connections = topaz_output,
  457. },
  458. },
  459. { .layout_id = 66,
  460. .codecs[0] = {
  461. .name = "onyx",
  462. .connections = onyx_connections_noheadphones,
  463. },
  464. },
  465. { .layout_id = 67,
  466. .codecs[0] = {
  467. .name = "topaz",
  468. .connections = topaz_input,
  469. },
  470. },
  471. { .layout_id = 76,
  472. .codecs[0] = {
  473. .name = "tas",
  474. .connections = tas_connections_nomic,
  475. },
  476. .codecs[1] = {
  477. .name = "topaz",
  478. .connections = topaz_inout,
  479. },
  480. },
  481. { .layout_id = 90,
  482. .codecs[0] = {
  483. .name = "tas",
  484. .connections = tas_connections_noline,
  485. },
  486. },
  487. { .layout_id = 94,
  488. .codecs[0] = {
  489. .name = "onyx",
  490. /* but it has an external mic?? how to select? */
  491. .connections = onyx_connections_noheadphones,
  492. },
  493. },
  494. { .layout_id = 98,
  495. .codecs[0] = {
  496. .name = "toonie",
  497. .connections = toonie_connections,
  498. },
  499. },
  500. { .layout_id = 100,
  501. .codecs[0] = {
  502. .name = "topaz",
  503. .connections = topaz_input,
  504. },
  505. .codecs[1] = {
  506. .name = "onyx",
  507. .connections = onyx_connections_noheadphones,
  508. },
  509. },
  510. /* PowerMac3,4 */
  511. { .device_id = 14,
  512. .codecs[0] = {
  513. .name = "tas",
  514. .connections = tas_connections_noline,
  515. },
  516. },
  517. /* PowerMac3,6 */
  518. { .device_id = 22,
  519. .codecs[0] = {
  520. .name = "tas",
  521. .connections = tas_connections_all,
  522. },
  523. },
  524. /* PowerBook5,2 */
  525. { .device_id = 35,
  526. .codecs[0] = {
  527. .name = "tas",
  528. .connections = tas_connections_all,
  529. },
  530. },
  531. {}
  532. };
  533. static struct layout *find_layout_by_id(unsigned int id)
  534. {
  535. struct layout *l;
  536. l = layouts;
  537. while (l->codecs[0].name) {
  538. if (l->layout_id == id)
  539. return l;
  540. l++;
  541. }
  542. return NULL;
  543. }
  544. static struct layout *find_layout_by_device(unsigned int id)
  545. {
  546. struct layout *l;
  547. l = layouts;
  548. while (l->codecs[0].name) {
  549. if (l->device_id == id)
  550. return l;
  551. l++;
  552. }
  553. return NULL;
  554. }
  555. static void use_layout(struct layout *l)
  556. {
  557. int i;
  558. for (i=0; i<MAX_CODECS_PER_BUS; i++) {
  559. if (l->codecs[i].name) {
  560. request_module("snd-aoa-codec-%s", l->codecs[i].name);
  561. }
  562. }
  563. /* now we wait for the codecs to call us back */
  564. }
  565. struct layout_dev;
  566. struct layout_dev_ptr {
  567. struct layout_dev *ptr;
  568. };
  569. struct layout_dev {
  570. struct list_head list;
  571. struct soundbus_dev *sdev;
  572. struct device_node *sound;
  573. struct aoa_codec *codecs[MAX_CODECS_PER_BUS];
  574. struct layout *layout;
  575. struct gpio_runtime gpio;
  576. /* we need these for headphone/lineout detection */
  577. struct snd_kcontrol *headphone_ctrl;
  578. struct snd_kcontrol *lineout_ctrl;
  579. struct snd_kcontrol *speaker_ctrl;
  580. struct snd_kcontrol *master_ctrl;
  581. struct snd_kcontrol *headphone_detected_ctrl;
  582. struct snd_kcontrol *lineout_detected_ctrl;
  583. struct layout_dev_ptr selfptr_headphone;
  584. struct layout_dev_ptr selfptr_lineout;
  585. u32 have_lineout_detect:1,
  586. have_headphone_detect:1,
  587. switch_on_headphone:1,
  588. switch_on_lineout:1;
  589. };
  590. static LIST_HEAD(layouts_list);
  591. static int layouts_list_items;
  592. /* this can go away but only if we allow multiple cards,
  593. * make the fabric handle all the card stuff, etc... */
  594. static struct layout_dev *layout_device;
  595. #define control_info snd_ctl_boolean_mono_info
  596. #define AMP_CONTROL(n, description) \
  597. static int n##_control_get(struct snd_kcontrol *kcontrol, \
  598. struct snd_ctl_elem_value *ucontrol) \
  599. { \
  600. struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \
  601. if (gpio->methods && gpio->methods->get_##n) \
  602. ucontrol->value.integer.value[0] = \
  603. gpio->methods->get_##n(gpio); \
  604. return 0; \
  605. } \
  606. static int n##_control_put(struct snd_kcontrol *kcontrol, \
  607. struct snd_ctl_elem_value *ucontrol) \
  608. { \
  609. struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \
  610. if (gpio->methods && gpio->methods->set_##n) \
  611. gpio->methods->set_##n(gpio, \
  612. !!ucontrol->value.integer.value[0]); \
  613. return 1; \
  614. } \
  615. static struct snd_kcontrol_new n##_ctl = { \
  616. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  617. .name = description, \
  618. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
  619. .info = control_info, \
  620. .get = n##_control_get, \
  621. .put = n##_control_put, \
  622. }
  623. AMP_CONTROL(headphone, "Headphone Switch");
  624. AMP_CONTROL(speakers, "Speakers Switch");
  625. AMP_CONTROL(lineout, "Line-Out Switch");
  626. AMP_CONTROL(master, "Master Switch");
  627. static int detect_choice_get(struct snd_kcontrol *kcontrol,
  628. struct snd_ctl_elem_value *ucontrol)
  629. {
  630. struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
  631. switch (kcontrol->private_value) {
  632. case 0:
  633. ucontrol->value.integer.value[0] = ldev->switch_on_headphone;
  634. break;
  635. case 1:
  636. ucontrol->value.integer.value[0] = ldev->switch_on_lineout;
  637. break;
  638. default:
  639. return -ENODEV;
  640. }
  641. return 0;
  642. }
  643. static int detect_choice_put(struct snd_kcontrol *kcontrol,
  644. struct snd_ctl_elem_value *ucontrol)
  645. {
  646. struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
  647. switch (kcontrol->private_value) {
  648. case 0:
  649. ldev->switch_on_headphone = !!ucontrol->value.integer.value[0];
  650. break;
  651. case 1:
  652. ldev->switch_on_lineout = !!ucontrol->value.integer.value[0];
  653. break;
  654. default:
  655. return -ENODEV;
  656. }
  657. return 1;
  658. }
  659. static struct snd_kcontrol_new headphone_detect_choice = {
  660. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  661. .name = "Headphone Detect Autoswitch",
  662. .info = control_info,
  663. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  664. .get = detect_choice_get,
  665. .put = detect_choice_put,
  666. .private_value = 0,
  667. };
  668. static struct snd_kcontrol_new lineout_detect_choice = {
  669. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  670. .name = "Line-Out Detect Autoswitch",
  671. .info = control_info,
  672. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  673. .get = detect_choice_get,
  674. .put = detect_choice_put,
  675. .private_value = 1,
  676. };
  677. static int detected_get(struct snd_kcontrol *kcontrol,
  678. struct snd_ctl_elem_value *ucontrol)
  679. {
  680. struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
  681. int v;
  682. switch (kcontrol->private_value) {
  683. case 0:
  684. v = ldev->gpio.methods->get_detect(&ldev->gpio,
  685. AOA_NOTIFY_HEADPHONE);
  686. break;
  687. case 1:
  688. v = ldev->gpio.methods->get_detect(&ldev->gpio,
  689. AOA_NOTIFY_LINE_OUT);
  690. break;
  691. default:
  692. return -ENODEV;
  693. }
  694. ucontrol->value.integer.value[0] = v;
  695. return 0;
  696. }
  697. static struct snd_kcontrol_new headphone_detected = {
  698. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  699. .name = "Headphone Detected",
  700. .info = control_info,
  701. .access = SNDRV_CTL_ELEM_ACCESS_READ,
  702. .get = detected_get,
  703. .private_value = 0,
  704. };
  705. static struct snd_kcontrol_new lineout_detected = {
  706. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  707. .name = "Line-Out Detected",
  708. .info = control_info,
  709. .access = SNDRV_CTL_ELEM_ACCESS_READ,
  710. .get = detected_get,
  711. .private_value = 1,
  712. };
  713. static int check_codec(struct aoa_codec *codec,
  714. struct layout_dev *ldev,
  715. struct codec_connect_info *cci)
  716. {
  717. const u32 *ref;
  718. char propname[32];
  719. struct codec_connection *cc;
  720. /* if the codec has a 'codec' node, we require a reference */
  721. if (codec->node && (strcmp(codec->node->name, "codec") == 0)) {
  722. snprintf(propname, sizeof(propname),
  723. "platform-%s-codec-ref", codec->name);
  724. ref = of_get_property(ldev->sound, propname, NULL);
  725. if (!ref) {
  726. printk(KERN_INFO "snd-aoa-fabric-layout: "
  727. "required property %s not present\n", propname);
  728. return -ENODEV;
  729. }
  730. if (*ref != codec->node->phandle) {
  731. printk(KERN_INFO "snd-aoa-fabric-layout: "
  732. "%s doesn't match!\n", propname);
  733. return -ENODEV;
  734. }
  735. } else {
  736. if (layouts_list_items != 1) {
  737. printk(KERN_INFO "snd-aoa-fabric-layout: "
  738. "more than one soundbus, but no references.\n");
  739. return -ENODEV;
  740. }
  741. }
  742. codec->soundbus_dev = ldev->sdev;
  743. codec->gpio = &ldev->gpio;
  744. cc = cci->connections;
  745. if (!cc)
  746. return -EINVAL;
  747. printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n");
  748. codec->connected = 0;
  749. codec->fabric_data = cc;
  750. while (cc->connected) {
  751. codec->connected |= 1<<cc->codec_bit;
  752. cc++;
  753. }
  754. return 0;
  755. }
  756. static int layout_found_codec(struct aoa_codec *codec)
  757. {
  758. struct layout_dev *ldev;
  759. int i;
  760. list_for_each_entry(ldev, &layouts_list, list) {
  761. for (i=0; i<MAX_CODECS_PER_BUS; i++) {
  762. if (!ldev->layout->codecs[i].name)
  763. continue;
  764. if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) {
  765. if (check_codec(codec,
  766. ldev,
  767. &ldev->layout->codecs[i]) == 0)
  768. return 0;
  769. }
  770. }
  771. }
  772. return -ENODEV;
  773. }
  774. static void layout_remove_codec(struct aoa_codec *codec)
  775. {
  776. int i;
  777. /* here remove the codec from the layout dev's
  778. * codec reference */
  779. codec->soundbus_dev = NULL;
  780. codec->gpio = NULL;
  781. for (i=0; i<MAX_CODECS_PER_BUS; i++) {
  782. }
  783. }
  784. static void layout_notify(void *data)
  785. {
  786. struct layout_dev_ptr *dptr = data;
  787. struct layout_dev *ldev;
  788. int v, update;
  789. struct snd_kcontrol *detected, *c;
  790. struct snd_card *card = aoa_get_card();
  791. ldev = dptr->ptr;
  792. if (data == &ldev->selfptr_headphone) {
  793. v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE);
  794. detected = ldev->headphone_detected_ctrl;
  795. update = ldev->switch_on_headphone;
  796. if (update) {
  797. ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
  798. ldev->gpio.methods->set_headphone(&ldev->gpio, v);
  799. ldev->gpio.methods->set_lineout(&ldev->gpio, 0);
  800. }
  801. } else if (data == &ldev->selfptr_lineout) {
  802. v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT);
  803. detected = ldev->lineout_detected_ctrl;
  804. update = ldev->switch_on_lineout;
  805. if (update) {
  806. ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
  807. ldev->gpio.methods->set_headphone(&ldev->gpio, 0);
  808. ldev->gpio.methods->set_lineout(&ldev->gpio, v);
  809. }
  810. } else
  811. return;
  812. if (detected)
  813. snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id);
  814. if (update) {
  815. c = ldev->headphone_ctrl;
  816. if (c)
  817. snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
  818. c = ldev->speaker_ctrl;
  819. if (c)
  820. snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
  821. c = ldev->lineout_ctrl;
  822. if (c)
  823. snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
  824. }
  825. }
  826. static void layout_attached_codec(struct aoa_codec *codec)
  827. {
  828. struct codec_connection *cc;
  829. struct snd_kcontrol *ctl;
  830. int headphones, lineout;
  831. struct layout_dev *ldev = layout_device;
  832. /* need to add this codec to our codec array! */
  833. cc = codec->fabric_data;
  834. headphones = codec->gpio->methods->get_detect(codec->gpio,
  835. AOA_NOTIFY_HEADPHONE);
  836. lineout = codec->gpio->methods->get_detect(codec->gpio,
  837. AOA_NOTIFY_LINE_OUT);
  838. if (codec->gpio->methods->set_master) {
  839. ctl = snd_ctl_new1(&master_ctl, codec->gpio);
  840. ldev->master_ctrl = ctl;
  841. aoa_snd_ctl_add(ctl);
  842. }
  843. while (cc->connected) {
  844. if (cc->connected & CC_SPEAKERS) {
  845. if (headphones <= 0 && lineout <= 0)
  846. ldev->gpio.methods->set_speakers(codec->gpio, 1);
  847. ctl = snd_ctl_new1(&speakers_ctl, codec->gpio);
  848. ldev->speaker_ctrl = ctl;
  849. aoa_snd_ctl_add(ctl);
  850. }
  851. if (cc->connected & CC_HEADPHONE) {
  852. if (headphones == 1)
  853. ldev->gpio.methods->set_headphone(codec->gpio, 1);
  854. ctl = snd_ctl_new1(&headphone_ctl, codec->gpio);
  855. ldev->headphone_ctrl = ctl;
  856. aoa_snd_ctl_add(ctl);
  857. ldev->have_headphone_detect =
  858. !ldev->gpio.methods
  859. ->set_notify(&ldev->gpio,
  860. AOA_NOTIFY_HEADPHONE,
  861. layout_notify,
  862. &ldev->selfptr_headphone);
  863. if (ldev->have_headphone_detect) {
  864. ctl = snd_ctl_new1(&headphone_detect_choice,
  865. ldev);
  866. aoa_snd_ctl_add(ctl);
  867. ctl = snd_ctl_new1(&headphone_detected,
  868. ldev);
  869. ldev->headphone_detected_ctrl = ctl;
  870. aoa_snd_ctl_add(ctl);
  871. }
  872. }
  873. if (cc->connected & CC_LINEOUT) {
  874. if (lineout == 1)
  875. ldev->gpio.methods->set_lineout(codec->gpio, 1);
  876. ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
  877. if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
  878. strlcpy(ctl->id.name,
  879. "Headphone Switch", sizeof(ctl->id.name));
  880. ldev->lineout_ctrl = ctl;
  881. aoa_snd_ctl_add(ctl);
  882. ldev->have_lineout_detect =
  883. !ldev->gpio.methods
  884. ->set_notify(&ldev->gpio,
  885. AOA_NOTIFY_LINE_OUT,
  886. layout_notify,
  887. &ldev->selfptr_lineout);
  888. if (ldev->have_lineout_detect) {
  889. ctl = snd_ctl_new1(&lineout_detect_choice,
  890. ldev);
  891. if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
  892. strlcpy(ctl->id.name,
  893. "Headphone Detect Autoswitch",
  894. sizeof(ctl->id.name));
  895. aoa_snd_ctl_add(ctl);
  896. ctl = snd_ctl_new1(&lineout_detected,
  897. ldev);
  898. if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
  899. strlcpy(ctl->id.name,
  900. "Headphone Detected",
  901. sizeof(ctl->id.name));
  902. ldev->lineout_detected_ctrl = ctl;
  903. aoa_snd_ctl_add(ctl);
  904. }
  905. }
  906. cc++;
  907. }
  908. /* now update initial state */
  909. if (ldev->have_headphone_detect)
  910. layout_notify(&ldev->selfptr_headphone);
  911. if (ldev->have_lineout_detect)
  912. layout_notify(&ldev->selfptr_lineout);
  913. }
  914. static struct aoa_fabric layout_fabric = {
  915. .name = "SoundByLayout",
  916. .owner = THIS_MODULE,
  917. .found_codec = layout_found_codec,
  918. .remove_codec = layout_remove_codec,
  919. .attached_codec = layout_attached_codec,
  920. };
  921. static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
  922. {
  923. struct device_node *sound = NULL;
  924. const unsigned int *id;
  925. struct layout *layout = NULL;
  926. struct layout_dev *ldev = NULL;
  927. int err;
  928. /* hm, currently we can only have one ... */
  929. if (layout_device)
  930. return -ENODEV;
  931. /* by breaking out we keep a reference */
  932. while ((sound = of_get_next_child(sdev->ofdev.dev.of_node, sound))) {
  933. if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
  934. break;
  935. }
  936. if (!sound)
  937. return -ENODEV;
  938. id = of_get_property(sound, "layout-id", NULL);
  939. if (id) {
  940. layout = find_layout_by_id(*id);
  941. } else {
  942. id = of_get_property(sound, "device-id", NULL);
  943. if (id)
  944. layout = find_layout_by_device(*id);
  945. }
  946. if (!layout) {
  947. printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
  948. goto outnodev;
  949. }
  950. ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL);
  951. if (!ldev)
  952. goto outnodev;
  953. layout_device = ldev;
  954. ldev->sdev = sdev;
  955. ldev->sound = sound;
  956. ldev->layout = layout;
  957. ldev->gpio.node = sound->parent;
  958. switch (layout->layout_id) {
  959. case 0: /* anything with device_id, not layout_id */
  960. case 41: /* that unknown machine no one seems to have */
  961. case 51: /* PowerBook5,4 */
  962. case 58: /* Mac Mini */
  963. ldev->gpio.methods = ftr_gpio_methods;
  964. printk(KERN_DEBUG
  965. "snd-aoa-fabric-layout: Using direct GPIOs\n");
  966. break;
  967. default:
  968. ldev->gpio.methods = pmf_gpio_methods;
  969. printk(KERN_DEBUG
  970. "snd-aoa-fabric-layout: Using PMF GPIOs\n");
  971. }
  972. ldev->selfptr_headphone.ptr = ldev;
  973. ldev->selfptr_lineout.ptr = ldev;
  974. dev_set_drvdata(&sdev->ofdev.dev, ldev);
  975. list_add(&ldev->list, &layouts_list);
  976. layouts_list_items++;
  977. /* assign these before registering ourselves, so
  978. * callbacks that are done during registration
  979. * already have the values */
  980. sdev->pcmid = ldev->layout->pcmid;
  981. if (ldev->layout->busname) {
  982. sdev->pcmname = ldev->layout->busname;
  983. } else {
  984. sdev->pcmname = "Master";
  985. }
  986. ldev->gpio.methods->init(&ldev->gpio);
  987. err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev);
  988. if (err && err != -EALREADY) {
  989. printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
  990. " another fabric is active!\n");
  991. goto outlistdel;
  992. }
  993. use_layout(layout);
  994. ldev->switch_on_headphone = 1;
  995. ldev->switch_on_lineout = 1;
  996. return 0;
  997. outlistdel:
  998. /* we won't be using these then... */
  999. ldev->gpio.methods->exit(&ldev->gpio);
  1000. /* reset if we didn't use it */
  1001. sdev->pcmname = NULL;
  1002. sdev->pcmid = -1;
  1003. list_del(&ldev->list);
  1004. layouts_list_items--;
  1005. kfree(ldev);
  1006. outnodev:
  1007. of_node_put(sound);
  1008. layout_device = NULL;
  1009. return -ENODEV;
  1010. }
  1011. static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
  1012. {
  1013. struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
  1014. int i;
  1015. for (i=0; i<MAX_CODECS_PER_BUS; i++) {
  1016. if (ldev->codecs[i]) {
  1017. aoa_fabric_unlink_codec(ldev->codecs[i]);
  1018. }
  1019. ldev->codecs[i] = NULL;
  1020. }
  1021. list_del(&ldev->list);
  1022. layouts_list_items--;
  1023. of_node_put(ldev->sound);
  1024. ldev->gpio.methods->set_notify(&ldev->gpio,
  1025. AOA_NOTIFY_HEADPHONE,
  1026. NULL,
  1027. NULL);
  1028. ldev->gpio.methods->set_notify(&ldev->gpio,
  1029. AOA_NOTIFY_LINE_OUT,
  1030. NULL,
  1031. NULL);
  1032. ldev->gpio.methods->exit(&ldev->gpio);
  1033. layout_device = NULL;
  1034. kfree(ldev);
  1035. sdev->pcmid = -1;
  1036. sdev->pcmname = NULL;
  1037. return 0;
  1038. }
  1039. #ifdef CONFIG_PM
  1040. static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state)
  1041. {
  1042. struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
  1043. if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
  1044. ldev->gpio.methods->all_amps_off(&ldev->gpio);
  1045. return 0;
  1046. }
  1047. static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
  1048. {
  1049. struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
  1050. if (ldev->gpio.methods && ldev->gpio.methods->all_amps_restore)
  1051. ldev->gpio.methods->all_amps_restore(&ldev->gpio);
  1052. return 0;
  1053. }
  1054. #endif
  1055. static struct soundbus_driver aoa_soundbus_driver = {
  1056. .name = "snd_aoa_soundbus_drv",
  1057. .owner = THIS_MODULE,
  1058. .probe = aoa_fabric_layout_probe,
  1059. .remove = aoa_fabric_layout_remove,
  1060. #ifdef CONFIG_PM
  1061. .suspend = aoa_fabric_layout_suspend,
  1062. .resume = aoa_fabric_layout_resume,
  1063. #endif
  1064. .driver = {
  1065. .owner = THIS_MODULE,
  1066. }
  1067. };
  1068. static int __init aoa_fabric_layout_init(void)
  1069. {
  1070. int err;
  1071. err = soundbus_register_driver(&aoa_soundbus_driver);
  1072. if (err)
  1073. return err;
  1074. return 0;
  1075. }
  1076. static void __exit aoa_fabric_layout_exit(void)
  1077. {
  1078. soundbus_unregister_driver(&aoa_soundbus_driver);
  1079. aoa_fabric_unregister(&layout_fabric);
  1080. }
  1081. module_init(aoa_fabric_layout_init);
  1082. module_exit(aoa_fabric_layout_exit);