Commit | Line | Data |
---|---|---|
e3d280fc TI |
1 | /* |
2 | * HD-audio core stuff | |
3 | */ | |
4 | ||
5 | #ifndef __SOUND_HDAUDIO_H | |
6 | #define __SOUND_HDAUDIO_H | |
7 | ||
8 | #include <linux/device.h> | |
d068ebc2 TI |
9 | #include <sound/hda_verbs.h> |
10 | ||
7639a06c TI |
11 | /* codec node id */ |
12 | typedef u16 hda_nid_t; | |
13 | ||
d068ebc2 TI |
14 | struct hdac_bus; |
15 | struct hdac_device; | |
16 | struct hdac_driver; | |
3256be65 | 17 | struct hdac_widget_tree; |
e3d280fc TI |
18 | |
19 | /* | |
20 | * exported bus type | |
21 | */ | |
22 | extern struct bus_type snd_hda_bus_type; | |
23 | ||
71fc4c7e TI |
24 | /* |
25 | * generic arrays | |
26 | */ | |
27 | struct snd_array { | |
28 | unsigned int used; | |
29 | unsigned int alloced; | |
30 | unsigned int elem_size; | |
31 | unsigned int alloc_align; | |
32 | void *list; | |
33 | }; | |
34 | ||
e3d280fc TI |
35 | /* |
36 | * HD-audio codec base device | |
37 | */ | |
38 | struct hdac_device { | |
39 | struct device dev; | |
40 | int type; | |
d068ebc2 TI |
41 | struct hdac_bus *bus; |
42 | unsigned int addr; /* codec address */ | |
43 | struct list_head list; /* list point for bus codec_list */ | |
7639a06c TI |
44 | |
45 | hda_nid_t afg; /* AFG node id */ | |
46 | hda_nid_t mfg; /* MFG node id */ | |
47 | ||
48 | /* ids */ | |
49 | unsigned int vendor_id; | |
50 | unsigned int subsystem_id; | |
51 | unsigned int revision_id; | |
52 | unsigned int afg_function_id; | |
53 | unsigned int mfg_function_id; | |
54 | unsigned int afg_unsol:1; | |
55 | unsigned int mfg_unsol:1; | |
56 | ||
57 | unsigned int power_caps; /* FG power caps */ | |
58 | ||
59 | const char *vendor_name; /* codec vendor name */ | |
60 | const char *chip_name; /* codec chip name */ | |
61 | ||
05852448 TI |
62 | /* verb exec op override */ |
63 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, | |
64 | unsigned int flags, unsigned int *res); | |
65 | ||
7639a06c TI |
66 | /* widgets */ |
67 | unsigned int num_nodes; | |
68 | hda_nid_t start_nid, end_nid; | |
69 | ||
70 | /* misc flags */ | |
71 | atomic_t in_pm; /* suspend/resume being performed */ | |
3256be65 TI |
72 | |
73 | /* sysfs */ | |
74 | struct hdac_widget_tree *widgets; | |
e3d280fc TI |
75 | }; |
76 | ||
77 | /* device/driver type used for matching */ | |
78 | enum { | |
79 | HDA_DEV_CORE, | |
80 | HDA_DEV_LEGACY, | |
81 | }; | |
82 | ||
7639a06c TI |
83 | /* direction */ |
84 | enum { | |
85 | HDA_INPUT, HDA_OUTPUT | |
86 | }; | |
87 | ||
e3d280fc TI |
88 | #define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev) |
89 | ||
7639a06c TI |
90 | int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus, |
91 | const char *name, unsigned int addr); | |
92 | void snd_hdac_device_exit(struct hdac_device *dev); | |
3256be65 TI |
93 | int snd_hdac_device_register(struct hdac_device *codec); |
94 | void snd_hdac_device_unregister(struct hdac_device *codec); | |
7639a06c TI |
95 | |
96 | int snd_hdac_refresh_widgets(struct hdac_device *codec); | |
97 | ||
98 | unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, | |
99 | unsigned int verb, unsigned int parm); | |
05852448 TI |
100 | int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, |
101 | unsigned int flags, unsigned int *res); | |
7639a06c TI |
102 | int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, |
103 | unsigned int verb, unsigned int parm, unsigned int *res); | |
104 | int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm); | |
105 | int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, | |
106 | hda_nid_t *conn_list, int max_conns); | |
107 | int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, | |
108 | hda_nid_t *start_id); | |
109 | ||
110 | #ifdef CONFIG_PM | |
111 | void snd_hdac_power_up(struct hdac_device *codec); | |
112 | void snd_hdac_power_down(struct hdac_device *codec); | |
113 | #else | |
114 | static inline void snd_hdac_power_up(struct hdac_device *codec) {} | |
115 | static inline void snd_hdac_power_down(struct hdac_device *codec) {} | |
116 | #endif | |
117 | ||
e3d280fc TI |
118 | /* |
119 | * HD-audio codec base driver | |
120 | */ | |
121 | struct hdac_driver { | |
122 | struct device_driver driver; | |
123 | int type; | |
124 | int (*match)(struct hdac_device *dev, struct hdac_driver *drv); | |
d068ebc2 | 125 | void (*unsol_event)(struct hdac_device *dev, unsigned int event); |
e3d280fc TI |
126 | }; |
127 | ||
128 | #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) | |
129 | ||
d068ebc2 TI |
130 | /* |
131 | * HD-audio bus base driver | |
132 | */ | |
133 | struct hdac_bus_ops { | |
134 | /* send a single command */ | |
135 | int (*command)(struct hdac_bus *bus, unsigned int cmd); | |
136 | /* get a response from the last command */ | |
137 | int (*get_response)(struct hdac_bus *bus, unsigned int addr, | |
138 | unsigned int *res); | |
139 | }; | |
140 | ||
141 | #define HDA_UNSOL_QUEUE_SIZE 64 | |
142 | ||
143 | struct hdac_bus { | |
144 | struct device *dev; | |
145 | const struct hdac_bus_ops *ops; | |
146 | ||
147 | /* codec linked list */ | |
148 | struct list_head codec_list; | |
149 | unsigned int num_codecs; | |
150 | ||
151 | /* link caddr -> codec */ | |
152 | struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; | |
153 | ||
154 | /* unsolicited event queue */ | |
155 | u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */ | |
156 | unsigned int unsol_rp, unsol_wp; | |
157 | struct work_struct unsol_work; | |
158 | ||
159 | /* bit flags of powered codecs */ | |
160 | unsigned long codec_powered; | |
161 | ||
162 | /* flags */ | |
163 | bool sync_write:1; /* sync after verb write */ | |
164 | ||
165 | /* locks */ | |
166 | struct mutex cmd_mutex; | |
167 | }; | |
168 | ||
169 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | |
170 | const struct hdac_bus_ops *ops); | |
171 | void snd_hdac_bus_exit(struct hdac_bus *bus); | |
172 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, | |
173 | unsigned int cmd, unsigned int *res); | |
174 | int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, | |
175 | unsigned int cmd, unsigned int *res); | |
176 | void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); | |
177 | ||
178 | int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); | |
179 | void snd_hdac_bus_remove_device(struct hdac_bus *bus, | |
180 | struct hdac_device *codec); | |
181 | ||
7639a06c TI |
182 | static inline void snd_hdac_codec_link_up(struct hdac_device *codec) |
183 | { | |
184 | set_bit(codec->addr, &codec->bus->codec_powered); | |
185 | } | |
186 | ||
187 | static inline void snd_hdac_codec_link_down(struct hdac_device *codec) | |
188 | { | |
189 | clear_bit(codec->addr, &codec->bus->codec_powered); | |
190 | } | |
191 | ||
71fc4c7e TI |
192 | /* |
193 | * generic array helpers | |
194 | */ | |
195 | void *snd_array_new(struct snd_array *array); | |
196 | void snd_array_free(struct snd_array *array); | |
197 | static inline void snd_array_init(struct snd_array *array, unsigned int size, | |
198 | unsigned int align) | |
199 | { | |
200 | array->elem_size = size; | |
201 | array->alloc_align = align; | |
202 | } | |
203 | ||
204 | static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) | |
205 | { | |
206 | return array->list + idx * array->elem_size; | |
207 | } | |
208 | ||
209 | static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) | |
210 | { | |
211 | return (unsigned long)(ptr - array->list) / array->elem_size; | |
212 | } | |
213 | ||
e3d280fc | 214 | #endif /* __SOUND_HDAUDIO_H */ |