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