layout.c 27 KB

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