blob: 47e20b741c51e1d6d7d7abf7892db2a3b38dbc6a [file] [log] [blame]
Takashi Iwaie3d280f2015-02-17 21:46:37 +01001/*
2 * HD-audio core stuff
3 */
4
5#ifndef __SOUND_HDAUDIO_H
6#define __SOUND_HDAUDIO_H
7
8#include <linux/device.h>
Takashi Iwaid068ebc2015-03-02 23:22:59 +01009#include <sound/hda_verbs.h>
10
Takashi Iwai7639a062015-03-03 10:07:24 +010011/* codec node id */
12typedef u16 hda_nid_t;
13
Takashi Iwaid068ebc2015-03-02 23:22:59 +010014struct hdac_bus;
15struct hdac_device;
16struct hdac_driver;
Takashi Iwai3256be62015-02-24 14:59:42 +010017struct hdac_widget_tree;
Takashi Iwaie3d280f2015-02-17 21:46:37 +010018
19/*
20 * exported bus type
21 */
22extern struct bus_type snd_hda_bus_type;
23
24/*
Takashi Iwai71fc4c72015-03-03 17:33:10 +010025 * generic arrays
26 */
27struct 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
35/*
Takashi Iwaie3d280f2015-02-17 21:46:37 +010036 * HD-audio codec base device
37 */
38struct hdac_device {
39 struct device dev;
40 int type;
Takashi Iwaid068ebc2015-03-02 23:22:59 +010041 struct hdac_bus *bus;
42 unsigned int addr; /* codec address */
43 struct list_head list; /* list point for bus codec_list */
Takashi Iwai7639a062015-03-03 10:07:24 +010044
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
Takashi Iwai05852442015-03-03 15:40:08 +010062 /* verb exec op override */
63 int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
64 unsigned int flags, unsigned int *res);
65
Takashi Iwai7639a062015-03-03 10:07:24 +010066 /* 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 */
Takashi Iwai3256be62015-02-24 14:59:42 +010072
73 /* sysfs */
74 struct hdac_widget_tree *widgets;
Takashi Iwai4d75faa02015-02-25 14:42:38 +010075
76 /* regmap */
77 struct regmap *regmap;
78 bool lazy_cache:1; /* don't wake up for writes */
Takashi Iwaie3d280f2015-02-17 21:46:37 +010079};
80
81/* device/driver type used for matching */
82enum {
83 HDA_DEV_CORE,
84 HDA_DEV_LEGACY,
85};
86
Takashi Iwai7639a062015-03-03 10:07:24 +010087/* direction */
88enum {
89 HDA_INPUT, HDA_OUTPUT
90};
91
Takashi Iwaie3d280f2015-02-17 21:46:37 +010092#define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev)
93
Takashi Iwai7639a062015-03-03 10:07:24 +010094int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
95 const char *name, unsigned int addr);
96void snd_hdac_device_exit(struct hdac_device *dev);
Takashi Iwai3256be62015-02-24 14:59:42 +010097int snd_hdac_device_register(struct hdac_device *codec);
98void snd_hdac_device_unregister(struct hdac_device *codec);
Takashi Iwai7639a062015-03-03 10:07:24 +010099
100int snd_hdac_refresh_widgets(struct hdac_device *codec);
101
102unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
103 unsigned int verb, unsigned int parm);
Takashi Iwai05852442015-03-03 15:40:08 +0100104int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd,
105 unsigned int flags, unsigned int *res);
Takashi Iwai7639a062015-03-03 10:07:24 +0100106int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
107 unsigned int verb, unsigned int parm, unsigned int *res);
108int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
109int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
110 hda_nid_t *conn_list, int max_conns);
111int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
112 hda_nid_t *start_id);
113
114#ifdef CONFIG_PM
115void snd_hdac_power_up(struct hdac_device *codec);
116void snd_hdac_power_down(struct hdac_device *codec);
117#else
118static inline void snd_hdac_power_up(struct hdac_device *codec) {}
119static inline void snd_hdac_power_down(struct hdac_device *codec) {}
120#endif
121
Takashi Iwaie3d280f2015-02-17 21:46:37 +0100122/*
123 * HD-audio codec base driver
124 */
125struct hdac_driver {
126 struct device_driver driver;
127 int type;
128 int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
Takashi Iwaid068ebc2015-03-02 23:22:59 +0100129 void (*unsol_event)(struct hdac_device *dev, unsigned int event);
Takashi Iwaie3d280f2015-02-17 21:46:37 +0100130};
131
132#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
133
Takashi Iwaid068ebc2015-03-02 23:22:59 +0100134/*
135 * HD-audio bus base driver
136 */
137struct hdac_bus_ops {
138 /* send a single command */
139 int (*command)(struct hdac_bus *bus, unsigned int cmd);
140 /* get a response from the last command */
141 int (*get_response)(struct hdac_bus *bus, unsigned int addr,
142 unsigned int *res);
143};
144
145#define HDA_UNSOL_QUEUE_SIZE 64
146
147struct hdac_bus {
148 struct device *dev;
149 const struct hdac_bus_ops *ops;
150
151 /* codec linked list */
152 struct list_head codec_list;
153 unsigned int num_codecs;
154
155 /* link caddr -> codec */
156 struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
157
158 /* unsolicited event queue */
159 u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */
160 unsigned int unsol_rp, unsol_wp;
161 struct work_struct unsol_work;
162
163 /* bit flags of powered codecs */
164 unsigned long codec_powered;
165
166 /* flags */
167 bool sync_write:1; /* sync after verb write */
168
169 /* locks */
170 struct mutex cmd_mutex;
171};
172
173int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
174 const struct hdac_bus_ops *ops);
175void snd_hdac_bus_exit(struct hdac_bus *bus);
176int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
177 unsigned int cmd, unsigned int *res);
178int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
179 unsigned int cmd, unsigned int *res);
180void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex);
181
182int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec);
183void snd_hdac_bus_remove_device(struct hdac_bus *bus,
184 struct hdac_device *codec);
185
Takashi Iwai7639a062015-03-03 10:07:24 +0100186static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
187{
188 set_bit(codec->addr, &codec->bus->codec_powered);
189}
190
191static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
192{
193 clear_bit(codec->addr, &codec->bus->codec_powered);
194}
195
Takashi Iwai71fc4c72015-03-03 17:33:10 +0100196/*
197 * generic array helpers
198 */
199void *snd_array_new(struct snd_array *array);
200void snd_array_free(struct snd_array *array);
201static inline void snd_array_init(struct snd_array *array, unsigned int size,
202 unsigned int align)
203{
204 array->elem_size = size;
205 array->alloc_align = align;
206}
207
208static inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
209{
210 return array->list + idx * array->elem_size;
211}
212
213static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
214{
215 return (unsigned long)(ptr - array->list) / array->elem_size;
216}
217
Takashi Iwaie3d280f2015-02-17 21:46:37 +0100218#endif /* __SOUND_HDAUDIO_H */