📄 snd-aoa-fabric-layout.c
字号:
/* * Apple Onboard Audio driver -- layout fabric * * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> * * GPL v2, can be found in COPYING. * * * This fabric module looks for sound codecs * based on the layout-id property in the device tree. * */#include <asm/prom.h>#include <linux/list.h>#include <linux/module.h>#include "../aoa.h"#include "../soundbus/soundbus.h"MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa");#define MAX_CODECS_PER_BUS 2/* These are the connections the layout fabric * knows about. It doesn't really care about the * input ones, but I thought I'd separate them * to give them proper names. The thing is that * Apple usually will distinguish the active output * by GPIOs, while the active input is set directly * on the codec. Hence we here tell the codec what * we think is connected. This information is hard- * coded below ... */#define CC_SPEAKERS (1<<0)#define CC_HEADPHONE (1<<1)#define CC_LINEOUT (1<<2)#define CC_DIGITALOUT (1<<3)#define CC_LINEIN (1<<4)#define CC_MICROPHONE (1<<5)#define CC_DIGITALIN (1<<6)/* pretty bogus but users complain... * This is a flag saying that the LINEOUT * should be renamed to HEADPHONE. * be careful with input detection! */#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7)struct codec_connection { /* CC_ flags from above */ int connected; /* codec dependent bit to be set in the aoa_codec.connected field. * This intentionally doesn't have any generic flags because the * fabric has to know the codec anyway and all codecs might have * different connectors */ int codec_bit;};struct codec_connect_info { char *name; struct codec_connection *connections;};#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)struct layout { unsigned int layout_id; struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; int flags; /* if busname is not assigned, we use 'Master' below, * so that our layout table doesn't need to be filled * too much. * We only assign these two if we expect to find more * than one soundbus, i.e. on those machines with * multiple layout-ids */ char *busname; int pcmid;};MODULE_ALIAS("sound-layout-36");MODULE_ALIAS("sound-layout-41");MODULE_ALIAS("sound-layout-45");MODULE_ALIAS("sound-layout-47");MODULE_ALIAS("sound-layout-48");MODULE_ALIAS("sound-layout-49");MODULE_ALIAS("sound-layout-50");MODULE_ALIAS("sound-layout-51");MODULE_ALIAS("sound-layout-56");MODULE_ALIAS("sound-layout-57");MODULE_ALIAS("sound-layout-58");MODULE_ALIAS("sound-layout-60");MODULE_ALIAS("sound-layout-61");MODULE_ALIAS("sound-layout-62");MODULE_ALIAS("sound-layout-64");MODULE_ALIAS("sound-layout-65");MODULE_ALIAS("sound-layout-66");MODULE_ALIAS("sound-layout-67");MODULE_ALIAS("sound-layout-68");MODULE_ALIAS("sound-layout-69");MODULE_ALIAS("sound-layout-70");MODULE_ALIAS("sound-layout-72");MODULE_ALIAS("sound-layout-76");MODULE_ALIAS("sound-layout-80");MODULE_ALIAS("sound-layout-82");MODULE_ALIAS("sound-layout-84");MODULE_ALIAS("sound-layout-86");MODULE_ALIAS("sound-layout-90");MODULE_ALIAS("sound-layout-92");MODULE_ALIAS("sound-layout-94");MODULE_ALIAS("sound-layout-96");MODULE_ALIAS("sound-layout-98");MODULE_ALIAS("sound-layout-100");/* onyx with all but microphone connected */static struct codec_connection onyx_connections_nomic[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, .codec_bit = 0, }, { .connected = CC_DIGITALOUT, .codec_bit = 1, }, { .connected = CC_LINEIN, .codec_bit = 2, }, {} /* terminate array by .connected == 0 */};/* onyx on machines without headphone */static struct codec_connection onyx_connections_noheadphones[] = { { .connected = CC_SPEAKERS | CC_LINEOUT | CC_LINEOUT_LABELLED_HEADPHONE, .codec_bit = 0, }, { .connected = CC_DIGITALOUT, .codec_bit = 1, }, /* FIXME: are these correct? probably not for all the machines * below ... If not this will need separating. */ { .connected = CC_LINEIN, .codec_bit = 2, }, { .connected = CC_MICROPHONE, .codec_bit = 3, }, {} /* terminate array by .connected == 0 */};/* onyx on machines with real line-out */static struct codec_connection onyx_connections_reallineout[] = { { .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, .codec_bit = 0, }, { .connected = CC_DIGITALOUT, .codec_bit = 1, }, { .connected = CC_LINEIN, .codec_bit = 2, }, {} /* terminate array by .connected == 0 */};/* tas on machines without line out */static struct codec_connection tas_connections_nolineout[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE, .codec_bit = 0, }, { .connected = CC_LINEIN, .codec_bit = 2, }, { .connected = CC_MICROPHONE, .codec_bit = 3, }, {} /* terminate array by .connected == 0 */};/* tas on machines with neither line out nor line in */static struct codec_connection tas_connections_noline[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE, .codec_bit = 0, }, { .connected = CC_MICROPHONE, .codec_bit = 3, }, {} /* terminate array by .connected == 0 */};/* tas on machines without microphone */static struct codec_connection tas_connections_nomic[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, .codec_bit = 0, }, { .connected = CC_LINEIN, .codec_bit = 2, }, {} /* terminate array by .connected == 0 */};/* tas on machines with everything connected */static struct codec_connection tas_connections_all[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, .codec_bit = 0, }, { .connected = CC_LINEIN, .codec_bit = 2, }, { .connected = CC_MICROPHONE, .codec_bit = 3, }, {} /* terminate array by .connected == 0 */};static struct codec_connection toonie_connections[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE, .codec_bit = 0, }, {} /* terminate array by .connected == 0 */};static struct codec_connection topaz_input[] = { { .connected = CC_DIGITALIN, .codec_bit = 0, }, {} /* terminate array by .connected == 0 */};static struct codec_connection topaz_output[] = { { .connected = CC_DIGITALOUT, .codec_bit = 1, }, {} /* terminate array by .connected == 0 */};static struct codec_connection topaz_inout[] = { { .connected = CC_DIGITALIN, .codec_bit = 0, }, { .connected = CC_DIGITALOUT, .codec_bit = 1, }, {} /* terminate array by .connected == 0 */};static struct layout layouts[] = { /* last PowerBooks (15" Oct 2005) */ { .layout_id = 82, .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, .codecs[1] = { .name = "topaz", .connections = topaz_input, }, }, /* PowerMac9,1 */ { .layout_id = 60, .codecs[0] = { .name = "onyx", .connections = onyx_connections_reallineout, }, }, /* PowerMac9,1 */ { .layout_id = 61, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, /* PowerBook5,7 */ { .layout_id = 64, .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, /* PowerBook5,7 */ { .layout_id = 65, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, /* PowerBook5,9 [17" Oct 2005] */ { .layout_id = 84, .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, .codecs[1] = { .name = "topaz", .connections = topaz_input, }, }, /* PowerMac8,1 */ { .layout_id = 45, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, .codecs[1] = { .name = "topaz", .connections = topaz_input, }, }, /* Quad PowerMac (analog in, analog/digital out) */ { .layout_id = 68, .codecs[0] = { .name = "onyx", .connections = onyx_connections_nomic, }, }, /* Quad PowerMac (digital in) */ { .layout_id = 69, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, .busname = "digital in", .pcmid = 1 }, /* Early 2005 PowerBook (PowerBook 5,6) */ { .layout_id = 70, .codecs[0] = { .name = "tas", .connections = tas_connections_nolineout, }, }, /* PowerBook 5,4 */ { .layout_id = 51, .codecs[0] = { .name = "tas", .connections = tas_connections_nolineout, }, }, /* PowerBook6,7 */ { .layout_id = 80, .codecs[0] = { .name = "tas", .connections = tas_connections_noline, }, }, /* PowerBook6,8 */ { .layout_id = 72, .codecs[0] = { .name = "tas", .connections = tas_connections_nolineout, }, }, /* PowerMac8,2 */ { .layout_id = 86, .codecs[0] = { .name = "onyx", .connections = onyx_connections_nomic, }, .codecs[1] = { .name = "topaz", .connections = topaz_input, }, }, /* PowerBook6,7 */ { .layout_id = 92, .codecs[0] = { .name = "tas", .connections = tas_connections_nolineout, }, }, /* PowerMac10,1 (Mac Mini) */ { .layout_id = 58, .codecs[0] = { .name = "toonie", .connections = toonie_connections, }, }, { .layout_id = 96, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, /* unknown, untested, but this comes from Apple */ { .layout_id = 41, .codecs[0] = { .name = "tas", .connections = tas_connections_all, }, }, { .layout_id = 36, .codecs[0] = { .name = "tas", .connections = tas_connections_nomic, }, .codecs[1] = { .name = "topaz", .connections = topaz_inout, }, }, { .layout_id = 47, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, { .layout_id = 48, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, { .layout_id = 49, .codecs[0] = { .name = "onyx", .connections = onyx_connections_nomic, }, }, { .layout_id = 50, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, { .layout_id = 56, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, { .layout_id = 57, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, { .layout_id = 62, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, .codecs[1] = { .name = "topaz", .connections = topaz_output, }, }, { .layout_id = 66, .codecs[0] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, { .layout_id = 67, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, }, { .layout_id = 76, .codecs[0] = { .name = "tas", .connections = tas_connections_nomic, }, .codecs[1] = { .name = "topaz", .connections = topaz_inout, }, }, { .layout_id = 90, .codecs[0] = { .name = "tas", .connections = tas_connections_noline, }, }, { .layout_id = 94, .codecs[0] = { .name = "onyx", /* but it has an external mic?? how to select? */ .connections = onyx_connections_noheadphones, }, }, { .layout_id = 98, .codecs[0] = { .name = "toonie", .connections = toonie_connections, }, }, { .layout_id = 100, .codecs[0] = { .name = "topaz", .connections = topaz_input, }, .codecs[1] = { .name = "onyx", .connections = onyx_connections_noheadphones, }, }, {}};static struct layout *find_layout_by_id(unsigned int id){ struct layout *l; l = layouts; while (l->layout_id) { if (l->layout_id == id) return l; l++; } return NULL;}static void use_layout(struct layout *l){ int i; for (i=0; i<MAX_CODECS_PER_BUS; i++) { if (l->codecs[i].name) { request_module("snd-aoa-codec-%s", l->codecs[i].name); } } /* now we wait for the codecs to call us back */}struct layout_dev;struct layout_dev_ptr { struct layout_dev *ptr;};struct layout_dev { struct list_head list; struct soundbus_dev *sdev; struct device_node *sound; struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; struct layout *layout; struct gpio_runtime gpio;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -