blob: b81b4bec6f050b2e824dbda300faf55aadb5e3d3 [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 Iwaie3d280f2015-02-17 21:46:37 +010017
18/*
19 * exported bus type
20 */
21extern struct bus_type snd_hda_bus_type;
22
23/*
24 * HD-audio codec base device
25 */
26struct hdac_device {
27 struct device dev;
28 int type;
Takashi Iwaid068ebc2015-03-02 23:22:59 +010029 struct hdac_bus *bus;
30 unsigned int addr; /* codec address */
31 struct list_head list; /* list point for bus codec_list */
Takashi Iwai7639a062015-03-03 10:07:24 +010032
33 hda_nid_t afg; /* AFG node id */
34 hda_nid_t mfg; /* MFG node id */
35
36 /* ids */
37 unsigned int vendor_id;
38 unsigned int subsystem_id;
39 unsigned int revision_id;
40 unsigned int afg_function_id;
41 unsigned int mfg_function_id;
42 unsigned int afg_unsol:1;
43 unsigned int mfg_unsol:1;
44
45 unsigned int power_caps; /* FG power caps */
46
47 const char *vendor_name; /* codec vendor name */
48 const char *chip_name; /* codec chip name */
49
50 /* widgets */
51 unsigned int num_nodes;
52 hda_nid_t start_nid, end_nid;
53
54 /* misc flags */
55 atomic_t in_pm; /* suspend/resume being performed */
Takashi Iwaie3d280f2015-02-17 21:46:37 +010056};
57
58/* device/driver type used for matching */
59enum {
60 HDA_DEV_CORE,
61 HDA_DEV_LEGACY,
62};
63
Takashi Iwai7639a062015-03-03 10:07:24 +010064/* direction */
65enum {
66 HDA_INPUT, HDA_OUTPUT
67};
68
Takashi Iwaie3d280f2015-02-17 21:46:37 +010069#define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev)
70
Takashi Iwai7639a062015-03-03 10:07:24 +010071int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
72 const char *name, unsigned int addr);
73void snd_hdac_device_exit(struct hdac_device *dev);
74
75int snd_hdac_refresh_widgets(struct hdac_device *codec);
76
77unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
78 unsigned int verb, unsigned int parm);
79int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
80 unsigned int verb, unsigned int parm, unsigned int *res);
81int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
82int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
83 hda_nid_t *conn_list, int max_conns);
84int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
85 hda_nid_t *start_id);
86
87#ifdef CONFIG_PM
88void snd_hdac_power_up(struct hdac_device *codec);
89void snd_hdac_power_down(struct hdac_device *codec);
90#else
91static inline void snd_hdac_power_up(struct hdac_device *codec) {}
92static inline void snd_hdac_power_down(struct hdac_device *codec) {}
93#endif
94
Takashi Iwaie3d280f2015-02-17 21:46:37 +010095/*
96 * HD-audio codec base driver
97 */
98struct hdac_driver {
99 struct device_driver driver;
100 int type;
101 int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
Takashi Iwaid068ebc2015-03-02 23:22:59 +0100102 void (*unsol_event)(struct hdac_device *dev, unsigned int event);
Takashi Iwaie3d280f2015-02-17 21:46:37 +0100103};
104
105#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
106
Takashi Iwaid068ebc2015-03-02 23:22:59 +0100107/*
108 * HD-audio bus base driver
109 */
110struct hdac_bus_ops {
111 /* send a single command */
112 int (*command)(struct hdac_bus *bus, unsigned int cmd);
113 /* get a response from the last command */
114 int (*get_response)(struct hdac_bus *bus, unsigned int addr,
115 unsigned int *res);
116};
117
118#define HDA_UNSOL_QUEUE_SIZE 64
119
120struct hdac_bus {
121 struct device *dev;
122 const struct hdac_bus_ops *ops;
123
124 /* codec linked list */
125 struct list_head codec_list;
126 unsigned int num_codecs;
127
128 /* link caddr -> codec */
129 struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
130
131 /* unsolicited event queue */
132 u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */
133 unsigned int unsol_rp, unsol_wp;
134 struct work_struct unsol_work;
135
136 /* bit flags of powered codecs */
137 unsigned long codec_powered;
138
139 /* flags */
140 bool sync_write:1; /* sync after verb write */
141
142 /* locks */
143 struct mutex cmd_mutex;
144};
145
146int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
147 const struct hdac_bus_ops *ops);
148void snd_hdac_bus_exit(struct hdac_bus *bus);
149int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
150 unsigned int cmd, unsigned int *res);
151int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
152 unsigned int cmd, unsigned int *res);
153void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex);
154
155int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec);
156void snd_hdac_bus_remove_device(struct hdac_bus *bus,
157 struct hdac_device *codec);
158
Takashi Iwai7639a062015-03-03 10:07:24 +0100159static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
160{
161 set_bit(codec->addr, &codec->bus->codec_powered);
162}
163
164static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
165{
166 clear_bit(codec->addr, &codec->bus->codec_powered);
167}
168
Takashi Iwaie3d280f2015-02-17 21:46:37 +0100169#endif /* __SOUND_HDAUDIO_H */