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; | |
4d75faa0 TI |
75 | |
76 | /* regmap */ | |
77 | struct regmap *regmap; | |
5e56bcea | 78 | struct snd_array vendor_verbs; |
4d75faa0 | 79 | bool lazy_cache:1; /* don't wake up for writes */ |
faa75f8a | 80 | bool caps_overwriting:1; /* caps overwrite being in process */ |
40ba66a7 | 81 | bool cache_coef:1; /* cache COEF read/write too */ |
e3d280fc TI |
82 | }; |
83 | ||
84 | /* device/driver type used for matching */ | |
85 | enum { | |
86 | HDA_DEV_CORE, | |
87 | HDA_DEV_LEGACY, | |
88 | }; | |
89 | ||
7639a06c TI |
90 | /* direction */ |
91 | enum { | |
92 | HDA_INPUT, HDA_OUTPUT | |
93 | }; | |
94 | ||
e3d280fc TI |
95 | #define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev) |
96 | ||
7639a06c TI |
97 | int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus, |
98 | const char *name, unsigned int addr); | |
99 | void snd_hdac_device_exit(struct hdac_device *dev); | |
3256be65 TI |
100 | int snd_hdac_device_register(struct hdac_device *codec); |
101 | void snd_hdac_device_unregister(struct hdac_device *codec); | |
7639a06c TI |
102 | |
103 | int snd_hdac_refresh_widgets(struct hdac_device *codec); | |
104 | ||
105 | unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, | |
106 | unsigned int verb, unsigned int parm); | |
05852448 TI |
107 | int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, |
108 | unsigned int flags, unsigned int *res); | |
7639a06c TI |
109 | int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, |
110 | unsigned int verb, unsigned int parm, unsigned int *res); | |
01ed3c06 TI |
111 | int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, |
112 | unsigned int *res); | |
9ba17b4d TI |
113 | int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, |
114 | int parm); | |
faa75f8a TI |
115 | int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid, |
116 | unsigned int parm, unsigned int val); | |
7639a06c TI |
117 | int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, |
118 | hda_nid_t *conn_list, int max_conns); | |
119 | int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, | |
120 | hda_nid_t *start_id); | |
121 | ||
01ed3c06 TI |
122 | /** |
123 | * snd_hdac_read_parm - read a codec parameter | |
124 | * @codec: the codec object | |
125 | * @nid: NID to read a parameter | |
126 | * @parm: parameter to read | |
127 | * | |
128 | * Returns -1 for error. If you need to distinguish the error more | |
129 | * strictly, use _snd_hdac_read_parm() directly. | |
130 | */ | |
131 | static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, | |
132 | int parm) | |
133 | { | |
134 | unsigned int val; | |
135 | ||
136 | return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val; | |
137 | } | |
138 | ||
7639a06c TI |
139 | #ifdef CONFIG_PM |
140 | void snd_hdac_power_up(struct hdac_device *codec); | |
141 | void snd_hdac_power_down(struct hdac_device *codec); | |
c3aeda62 TI |
142 | void snd_hdac_power_up_pm(struct hdac_device *codec); |
143 | void snd_hdac_power_down_pm(struct hdac_device *codec); | |
7639a06c TI |
144 | #else |
145 | static inline void snd_hdac_power_up(struct hdac_device *codec) {} | |
146 | static inline void snd_hdac_power_down(struct hdac_device *codec) {} | |
c3aeda62 TI |
147 | static inline void snd_hdac_power_up_pm(struct hdac_device *codec) {} |
148 | static inline void snd_hdac_power_down_pm(struct hdac_device *codec) {} | |
7639a06c TI |
149 | #endif |
150 | ||
e3d280fc TI |
151 | /* |
152 | * HD-audio codec base driver | |
153 | */ | |
154 | struct hdac_driver { | |
155 | struct device_driver driver; | |
156 | int type; | |
157 | int (*match)(struct hdac_device *dev, struct hdac_driver *drv); | |
d068ebc2 | 158 | void (*unsol_event)(struct hdac_device *dev, unsigned int event); |
e3d280fc TI |
159 | }; |
160 | ||
161 | #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) | |
162 | ||
d068ebc2 TI |
163 | /* |
164 | * HD-audio bus base driver | |
165 | */ | |
166 | struct hdac_bus_ops { | |
167 | /* send a single command */ | |
168 | int (*command)(struct hdac_bus *bus, unsigned int cmd); | |
169 | /* get a response from the last command */ | |
170 | int (*get_response)(struct hdac_bus *bus, unsigned int addr, | |
171 | unsigned int *res); | |
172 | }; | |
173 | ||
174 | #define HDA_UNSOL_QUEUE_SIZE 64 | |
175 | ||
176 | struct hdac_bus { | |
177 | struct device *dev; | |
178 | const struct hdac_bus_ops *ops; | |
179 | ||
180 | /* codec linked list */ | |
181 | struct list_head codec_list; | |
182 | unsigned int num_codecs; | |
183 | ||
184 | /* link caddr -> codec */ | |
185 | struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; | |
186 | ||
187 | /* unsolicited event queue */ | |
188 | u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */ | |
189 | unsigned int unsol_rp, unsol_wp; | |
190 | struct work_struct unsol_work; | |
191 | ||
192 | /* bit flags of powered codecs */ | |
193 | unsigned long codec_powered; | |
194 | ||
195 | /* flags */ | |
196 | bool sync_write:1; /* sync after verb write */ | |
197 | ||
198 | /* locks */ | |
199 | struct mutex cmd_mutex; | |
200 | }; | |
201 | ||
202 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | |
203 | const struct hdac_bus_ops *ops); | |
204 | void snd_hdac_bus_exit(struct hdac_bus *bus); | |
205 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, | |
206 | unsigned int cmd, unsigned int *res); | |
207 | int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, | |
208 | unsigned int cmd, unsigned int *res); | |
209 | void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); | |
210 | ||
211 | int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); | |
212 | void snd_hdac_bus_remove_device(struct hdac_bus *bus, | |
213 | struct hdac_device *codec); | |
214 | ||
7639a06c TI |
215 | static inline void snd_hdac_codec_link_up(struct hdac_device *codec) |
216 | { | |
217 | set_bit(codec->addr, &codec->bus->codec_powered); | |
218 | } | |
219 | ||
220 | static inline void snd_hdac_codec_link_down(struct hdac_device *codec) | |
221 | { | |
222 | clear_bit(codec->addr, &codec->bus->codec_powered); | |
223 | } | |
224 | ||
71fc4c7e TI |
225 | /* |
226 | * generic array helpers | |
227 | */ | |
228 | void *snd_array_new(struct snd_array *array); | |
229 | void snd_array_free(struct snd_array *array); | |
230 | static inline void snd_array_init(struct snd_array *array, unsigned int size, | |
231 | unsigned int align) | |
232 | { | |
233 | array->elem_size = size; | |
234 | array->alloc_align = align; | |
235 | } | |
236 | ||
237 | static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) | |
238 | { | |
239 | return array->list + idx * array->elem_size; | |
240 | } | |
241 | ||
242 | static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) | |
243 | { | |
244 | return (unsigned long)(ptr - array->list) / array->elem_size; | |
245 | } | |
246 | ||
e3d280fc | 247 | #endif /* __SOUND_HDAUDIO_H */ |