diff options
-rw-r--r-- | include/sound/hda_register.h | 152 | ||||
-rw-r--r-- | include/sound/hdaudio.h | 224 | ||||
-rw-r--r-- | sound/hda/Makefile | 2 | ||||
-rw-r--r-- | sound/hda/hdac_bus.c | 20 | ||||
-rw-r--r-- | sound/hda/hdac_controller.c | 449 | ||||
-rw-r--r-- | sound/hda/hdac_stream.c | 536 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 132 |
8 files changed, 1380 insertions, 137 deletions
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h new file mode 100644 index 000000000000..4f6d3fce6ee6 --- /dev/null +++ b/include/sound/hda_register.h | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * HD-audio controller (Azalia) registers and helpers | ||
3 | * | ||
4 | * For traditional reasons, we still use azx_ prefix here | ||
5 | */ | ||
6 | |||
7 | #ifndef __SOUND_HDA_REGISTER_H | ||
8 | #define __SOUND_HDA_REGISTER_H | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <sound/hdaudio.h> | ||
12 | |||
13 | #define AZX_REG_GCAP 0x00 | ||
14 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ | ||
15 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | ||
16 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | ||
17 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ | ||
18 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ | ||
19 | #define AZX_REG_VMIN 0x02 | ||
20 | #define AZX_REG_VMAJ 0x03 | ||
21 | #define AZX_REG_OUTPAY 0x04 | ||
22 | #define AZX_REG_INPAY 0x06 | ||
23 | #define AZX_REG_GCTL 0x08 | ||
24 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ | ||
25 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ | ||
26 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | ||
27 | #define AZX_REG_WAKEEN 0x0c | ||
28 | #define AZX_REG_STATESTS 0x0e | ||
29 | #define AZX_REG_GSTS 0x10 | ||
30 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ | ||
31 | #define AZX_REG_INTCTL 0x20 | ||
32 | #define AZX_REG_INTSTS 0x24 | ||
33 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ | ||
34 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | ||
35 | #define AZX_REG_SSYNC 0x38 | ||
36 | #define AZX_REG_CORBLBASE 0x40 | ||
37 | #define AZX_REG_CORBUBASE 0x44 | ||
38 | #define AZX_REG_CORBWP 0x48 | ||
39 | #define AZX_REG_CORBRP 0x4a | ||
40 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ | ||
41 | #define AZX_REG_CORBCTL 0x4c | ||
42 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ | ||
43 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | ||
44 | #define AZX_REG_CORBSTS 0x4d | ||
45 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ | ||
46 | #define AZX_REG_CORBSIZE 0x4e | ||
47 | |||
48 | #define AZX_REG_RIRBLBASE 0x50 | ||
49 | #define AZX_REG_RIRBUBASE 0x54 | ||
50 | #define AZX_REG_RIRBWP 0x58 | ||
51 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ | ||
52 | #define AZX_REG_RINTCNT 0x5a | ||
53 | #define AZX_REG_RIRBCTL 0x5c | ||
54 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | ||
55 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | ||
56 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | ||
57 | #define AZX_REG_RIRBSTS 0x5d | ||
58 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ | ||
59 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | ||
60 | #define AZX_REG_RIRBSIZE 0x5e | ||
61 | |||
62 | #define AZX_REG_IC 0x60 | ||
63 | #define AZX_REG_IR 0x64 | ||
64 | #define AZX_REG_IRS 0x68 | ||
65 | #define AZX_IRS_VALID (1<<1) | ||
66 | #define AZX_IRS_BUSY (1<<0) | ||
67 | |||
68 | #define AZX_REG_DPLBASE 0x70 | ||
69 | #define AZX_REG_DPUBASE 0x74 | ||
70 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | ||
71 | |||
72 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | ||
73 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | ||
74 | |||
75 | /* stream register offsets from stream base */ | ||
76 | #define AZX_REG_SD_CTL 0x00 | ||
77 | #define AZX_REG_SD_STS 0x03 | ||
78 | #define AZX_REG_SD_LPIB 0x04 | ||
79 | #define AZX_REG_SD_CBL 0x08 | ||
80 | #define AZX_REG_SD_LVI 0x0c | ||
81 | #define AZX_REG_SD_FIFOW 0x0e | ||
82 | #define AZX_REG_SD_FIFOSIZE 0x10 | ||
83 | #define AZX_REG_SD_FORMAT 0x12 | ||
84 | #define AZX_REG_SD_BDLPL 0x18 | ||
85 | #define AZX_REG_SD_BDLPU 0x1c | ||
86 | |||
87 | /* PCI space */ | ||
88 | #define AZX_PCIREG_TCSEL 0x44 | ||
89 | |||
90 | /* | ||
91 | * other constants | ||
92 | */ | ||
93 | |||
94 | /* max number of fragments - we may use more if allocating more pages for BDL */ | ||
95 | #define BDL_SIZE 4096 | ||
96 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | ||
97 | #define AZX_MAX_FRAG 32 | ||
98 | /* max buffer size - no h/w limit, you can increase as you like */ | ||
99 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | ||
100 | |||
101 | /* RIRB int mask: overrun[2], response[0] */ | ||
102 | #define RIRB_INT_RESPONSE 0x01 | ||
103 | #define RIRB_INT_OVERRUN 0x04 | ||
104 | #define RIRB_INT_MASK 0x05 | ||
105 | |||
106 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | ||
107 | #define STATESTS_INT_MASK ((1 << HDA_MAX_CODECS) - 1) | ||
108 | |||
109 | /* SD_CTL bits */ | ||
110 | #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ | ||
111 | #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ | ||
112 | #define SD_CTL_STRIPE (3 << 16) /* stripe control */ | ||
113 | #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ | ||
114 | #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ | ||
115 | #define SD_CTL_STREAM_TAG_MASK (0xf << 20) | ||
116 | #define SD_CTL_STREAM_TAG_SHIFT 20 | ||
117 | |||
118 | /* SD_CTL and SD_STS */ | ||
119 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ | ||
120 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | ||
121 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ | ||
122 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ | ||
123 | SD_INT_COMPLETE) | ||
124 | |||
125 | /* SD_STS */ | ||
126 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | ||
127 | |||
128 | /* INTCTL and INTSTS */ | ||
129 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ | ||
130 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | ||
131 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | ||
132 | |||
133 | /* below are so far hardcoded - should read registers in future */ | ||
134 | #define AZX_MAX_CORB_ENTRIES 256 | ||
135 | #define AZX_MAX_RIRB_ENTRIES 256 | ||
136 | |||
137 | /* | ||
138 | * helpers to read the stream position | ||
139 | */ | ||
140 | static inline unsigned int | ||
141 | snd_hdac_stream_get_pos_lpib(struct hdac_stream *stream) | ||
142 | { | ||
143 | return snd_hdac_stream_readl(stream, SD_LPIB); | ||
144 | } | ||
145 | |||
146 | static inline unsigned int | ||
147 | snd_hdac_stream_get_pos_posbuf(struct hdac_stream *stream) | ||
148 | { | ||
149 | return le32_to_cpu(*stream->posbuf); | ||
150 | } | ||
151 | |||
152 | #endif /* __SOUND_HDA_REGISTER_H */ | ||
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 2a8aa9dfb83d..9349ccf15a36 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h | |||
@@ -6,12 +6,17 @@ | |||
6 | #define __SOUND_HDAUDIO_H | 6 | #define __SOUND_HDAUDIO_H |
7 | 7 | ||
8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/timecounter.h> | ||
11 | #include <sound/core.h> | ||
12 | #include <sound/memalloc.h> | ||
9 | #include <sound/hda_verbs.h> | 13 | #include <sound/hda_verbs.h> |
10 | 14 | ||
11 | /* codec node id */ | 15 | /* codec node id */ |
12 | typedef u16 hda_nid_t; | 16 | typedef u16 hda_nid_t; |
13 | 17 | ||
14 | struct hdac_bus; | 18 | struct hdac_bus; |
19 | struct hdac_stream; | ||
15 | struct hdac_device; | 20 | struct hdac_device; |
16 | struct hdac_driver; | 21 | struct hdac_driver; |
17 | struct hdac_widget_tree; | 22 | struct hdac_widget_tree; |
@@ -161,7 +166,7 @@ struct hdac_driver { | |||
161 | #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) | 166 | #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) |
162 | 167 | ||
163 | /* | 168 | /* |
164 | * HD-audio bus base driver | 169 | * Bus verb operators |
165 | */ | 170 | */ |
166 | struct hdac_bus_ops { | 171 | struct hdac_bus_ops { |
167 | /* send a single command */ | 172 | /* send a single command */ |
@@ -171,11 +176,50 @@ struct hdac_bus_ops { | |||
171 | unsigned int *res); | 176 | unsigned int *res); |
172 | }; | 177 | }; |
173 | 178 | ||
179 | /* | ||
180 | * Lowlevel I/O operators | ||
181 | */ | ||
182 | struct hdac_io_ops { | ||
183 | /* mapped register accesses */ | ||
184 | void (*reg_writel)(u32 value, u32 __iomem *addr); | ||
185 | u32 (*reg_readl)(u32 __iomem *addr); | ||
186 | void (*reg_writew)(u16 value, u16 __iomem *addr); | ||
187 | u16 (*reg_readw)(u16 __iomem *addr); | ||
188 | void (*reg_writeb)(u8 value, u8 __iomem *addr); | ||
189 | u8 (*reg_readb)(u8 __iomem *addr); | ||
190 | }; | ||
191 | |||
174 | #define HDA_UNSOL_QUEUE_SIZE 64 | 192 | #define HDA_UNSOL_QUEUE_SIZE 64 |
193 | #define HDA_MAX_CODECS 8 /* limit by controller side */ | ||
194 | |||
195 | /* HD Audio class code */ | ||
196 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | ||
197 | |||
198 | /* | ||
199 | * CORB/RIRB | ||
200 | * | ||
201 | * Each CORB entry is 4byte, RIRB is 8byte | ||
202 | */ | ||
203 | struct hdac_rb { | ||
204 | __le32 *buf; /* virtual address of CORB/RIRB buffer */ | ||
205 | dma_addr_t addr; /* physical address of CORB/RIRB buffer */ | ||
206 | unsigned short rp, wp; /* RIRB read/write pointers */ | ||
207 | int cmds[HDA_MAX_CODECS]; /* number of pending requests */ | ||
208 | u32 res[HDA_MAX_CODECS]; /* last read value */ | ||
209 | }; | ||
175 | 210 | ||
211 | /* | ||
212 | * HD-audio bus base driver | ||
213 | */ | ||
176 | struct hdac_bus { | 214 | struct hdac_bus { |
177 | struct device *dev; | 215 | struct device *dev; |
178 | const struct hdac_bus_ops *ops; | 216 | const struct hdac_bus_ops *ops; |
217 | const struct hdac_io_ops *io_ops; | ||
218 | |||
219 | /* h/w resources */ | ||
220 | unsigned long addr; | ||
221 | void __iomem *remap_addr; | ||
222 | int irq; | ||
179 | 223 | ||
180 | /* codec linked list */ | 224 | /* codec linked list */ |
181 | struct list_head codec_list; | 225 | struct list_head codec_list; |
@@ -189,18 +233,45 @@ struct hdac_bus { | |||
189 | unsigned int unsol_rp, unsol_wp; | 233 | unsigned int unsol_rp, unsol_wp; |
190 | struct work_struct unsol_work; | 234 | struct work_struct unsol_work; |
191 | 235 | ||
236 | /* bit flags of detected codecs */ | ||
237 | unsigned long codec_mask; | ||
238 | |||
192 | /* bit flags of powered codecs */ | 239 | /* bit flags of powered codecs */ |
193 | unsigned long codec_powered; | 240 | unsigned long codec_powered; |
194 | 241 | ||
195 | /* flags */ | 242 | /* CORB/RIRB */ |
243 | struct hdac_rb corb; | ||
244 | struct hdac_rb rirb; | ||
245 | unsigned int last_cmd[HDA_MAX_CODECS]; /* last sent command */ | ||
246 | |||
247 | /* CORB/RIRB and position buffers */ | ||
248 | struct snd_dma_buffer rb; | ||
249 | struct snd_dma_buffer posbuf; | ||
250 | |||
251 | /* hdac_stream linked list */ | ||
252 | struct list_head stream_list; | ||
253 | |||
254 | /* operation state */ | ||
255 | bool chip_init:1; /* h/w initialized */ | ||
256 | |||
257 | /* behavior flags */ | ||
196 | bool sync_write:1; /* sync after verb write */ | 258 | bool sync_write:1; /* sync after verb write */ |
259 | bool use_posbuf:1; /* use position buffer */ | ||
260 | bool snoop:1; /* enable snooping */ | ||
261 | bool align_bdle_4k:1; /* BDLE align 4K boundary */ | ||
262 | bool reverse_assign:1; /* assign devices in reverse order */ | ||
263 | bool corbrp_self_clear:1; /* CORBRP clears itself after reset */ | ||
264 | |||
265 | int bdl_pos_adj; /* BDL position adjustment */ | ||
197 | 266 | ||
198 | /* locks */ | 267 | /* locks */ |
268 | spinlock_t reg_lock; | ||
199 | struct mutex cmd_mutex; | 269 | struct mutex cmd_mutex; |
200 | }; | 270 | }; |
201 | 271 | ||
202 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | 272 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
203 | const struct hdac_bus_ops *ops); | 273 | const struct hdac_bus_ops *ops, |
274 | const struct hdac_io_ops *io_ops); | ||
204 | void snd_hdac_bus_exit(struct hdac_bus *bus); | 275 | void snd_hdac_bus_exit(struct hdac_bus *bus); |
205 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, | 276 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, |
206 | unsigned int cmd, unsigned int *res); | 277 | unsigned int cmd, unsigned int *res); |
@@ -222,6 +293,153 @@ static inline void snd_hdac_codec_link_down(struct hdac_device *codec) | |||
222 | clear_bit(codec->addr, &codec->bus->codec_powered); | 293 | clear_bit(codec->addr, &codec->bus->codec_powered); |
223 | } | 294 | } |
224 | 295 | ||
296 | int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); | ||
297 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, | ||
298 | unsigned int *res); | ||
299 | |||
300 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); | ||
301 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus); | ||
302 | void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus); | ||
303 | void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus); | ||
304 | void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); | ||
305 | void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); | ||
306 | |||
307 | void snd_hdac_bus_update_rirb(struct hdac_bus *bus); | ||
308 | void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, | ||
309 | void (*ack)(struct hdac_bus *, | ||
310 | struct hdac_stream *)); | ||
311 | |||
312 | /* | ||
313 | * macros for easy use | ||
314 | */ | ||
315 | #define _snd_hdac_chip_write(type, chip, reg, value) \ | ||
316 | ((chip)->io_ops->reg_write ## type(value, (chip)->remap_addr + (reg))) | ||
317 | #define _snd_hdac_chip_read(type, chip, reg) \ | ||
318 | ((chip)->io_ops->reg_read ## type((chip)->remap_addr + (reg))) | ||
319 | |||
320 | /* read/write a register, pass without AZX_REG_ prefix */ | ||
321 | #define snd_hdac_chip_writel(chip, reg, value) \ | ||
322 | _snd_hdac_chip_write(l, chip, AZX_REG_ ## reg, value) | ||
323 | #define snd_hdac_chip_writew(chip, reg, value) \ | ||
324 | _snd_hdac_chip_write(w, chip, AZX_REG_ ## reg, value) | ||
325 | #define snd_hdac_chip_writeb(chip, reg, value) \ | ||
326 | _snd_hdac_chip_write(b, chip, AZX_REG_ ## reg, value) | ||
327 | #define snd_hdac_chip_readl(chip, reg) \ | ||
328 | _snd_hdac_chip_read(l, chip, AZX_REG_ ## reg) | ||
329 | #define snd_hdac_chip_readw(chip, reg) \ | ||
330 | _snd_hdac_chip_read(w, chip, AZX_REG_ ## reg) | ||
331 | #define snd_hdac_chip_readb(chip, reg) \ | ||
332 | _snd_hdac_chip_read(b, chip, AZX_REG_ ## reg) | ||
333 | |||
334 | /* update a register, pass without AZX_REG_ prefix */ | ||
335 | #define snd_hdac_chip_updatel(chip, reg, mask, val) \ | ||
336 | snd_hdac_chip_writel(chip, reg, \ | ||
337 | (snd_hdac_chip_readl(chip, reg) & ~(mask)) | (val)) | ||
338 | #define snd_hdac_chip_updatew(chip, reg, mask, val) \ | ||
339 | snd_hdac_chip_writew(chip, reg, \ | ||
340 | (snd_hdac_chip_readw(chip, reg) & ~(mask)) | (val)) | ||
341 | #define snd_hdac_chip_updateb(chip, reg, mask, val) \ | ||
342 | snd_hdac_chip_writeb(chip, reg, \ | ||
343 | (snd_hdac_chip_readb(chip, reg) & ~(mask)) | (val)) | ||
344 | |||
345 | /* | ||
346 | * HD-audio stream | ||
347 | */ | ||
348 | struct hdac_stream { | ||
349 | struct hdac_bus *bus; | ||
350 | struct snd_dma_buffer bdl; /* BDL buffer */ | ||
351 | __le32 *posbuf; /* position buffer pointer */ | ||
352 | int direction; /* playback / capture (SNDRV_PCM_STREAM_*) */ | ||
353 | |||
354 | unsigned int bufsize; /* size of the play buffer in bytes */ | ||
355 | unsigned int period_bytes; /* size of the period in bytes */ | ||
356 | unsigned int frags; /* number for period in the play buffer */ | ||
357 | unsigned int fifo_size; /* FIFO size */ | ||
358 | |||
359 | void __iomem *sd_addr; /* stream descriptor pointer */ | ||
360 | |||
361 | u32 sd_int_sta_mask; /* stream int status mask */ | ||
362 | |||
363 | /* pcm support */ | ||
364 | struct snd_pcm_substream *substream; /* assigned substream, | ||
365 | * set in PCM open | ||
366 | */ | ||
367 | unsigned int format_val; /* format value to be set in the | ||
368 | * controller and the codec | ||
369 | */ | ||
370 | unsigned char stream_tag; /* assigned stream */ | ||
371 | unsigned char index; /* stream index */ | ||
372 | int assigned_key; /* last device# key assigned to */ | ||
373 | |||
374 | bool opened:1; | ||
375 | bool running:1; | ||
376 | bool no_period_wakeup:1; | ||
377 | |||
378 | /* timestamp */ | ||
379 | unsigned long start_wallclk; /* start + minimum wallclk */ | ||
380 | unsigned long period_wallclk; /* wallclk for period */ | ||
381 | struct timecounter tc; | ||
382 | struct cyclecounter cc; | ||
383 | int delay_negative_threshold; | ||
384 | |||
385 | struct list_head list; | ||
386 | }; | ||
387 | |||
388 | void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, | ||
389 | int idx, int direction, int tag); | ||
390 | struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, | ||
391 | struct snd_pcm_substream *substream); | ||
392 | void snd_hdac_stream_release(struct hdac_stream *azx_dev); | ||
393 | |||
394 | int snd_hdac_stream_setup(struct hdac_stream *azx_dev); | ||
395 | void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev); | ||
396 | int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); | ||
397 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); | ||
398 | void snd_hdac_stream_clear(struct hdac_stream *azx_dev); | ||
399 | void snd_hdac_stream_stop(struct hdac_stream *azx_dev); | ||
400 | void snd_hdac_stream_reset(struct hdac_stream *azx_dev); | ||
401 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, | ||
402 | unsigned int streams, unsigned int reg); | ||
403 | void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, | ||
404 | unsigned int streams); | ||
405 | void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, | ||
406 | unsigned int streams); | ||
407 | /* | ||
408 | * macros for easy use | ||
409 | */ | ||
410 | #define _snd_hdac_stream_write(type, dev, reg, value) \ | ||
411 | ((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg))) | ||
412 | #define _snd_hdac_stream_read(type, dev, reg) \ | ||
413 | ((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg))) | ||
414 | |||
415 | /* read/write a register, pass without AZX_REG_ prefix */ | ||
416 | #define snd_hdac_stream_writel(dev, reg, value) \ | ||
417 | _snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) | ||
418 | #define snd_hdac_stream_writew(dev, reg, value) \ | ||
419 | _snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) | ||
420 | #define snd_hdac_stream_writeb(dev, reg, value) \ | ||
421 | _snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) | ||
422 | #define snd_hdac_stream_readl(dev, reg) \ | ||
423 | _snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) | ||
424 | #define snd_hdac_stream_readw(dev, reg) \ | ||
425 | _snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) | ||
426 | #define snd_hdac_stream_readb(dev, reg) \ | ||
427 | _snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) | ||
428 | |||
429 | /* update a register, pass without AZX_REG_ prefix */ | ||
430 | #define snd_hdac_stream_updatel(dev, reg, mask, val) \ | ||
431 | snd_hdac_stream_writel(dev, reg, \ | ||
432 | (snd_hdac_stream_readl(dev, reg) & \ | ||
433 | ~(mask)) | (val)) | ||
434 | #define snd_hdac_stream_updatew(dev, reg, mask, val) \ | ||
435 | snd_hdac_stream_writew(dev, reg, \ | ||
436 | (snd_hdac_stream_readw(dev, reg) & \ | ||
437 | ~(mask)) | (val)) | ||
438 | #define snd_hdac_stream_updateb(dev, reg, mask, val) \ | ||
439 | snd_hdac_stream_writeb(dev, reg, \ | ||
440 | (snd_hdac_stream_readb(dev, reg) & \ | ||
441 | ~(mask)) | (val)) | ||
442 | |||
225 | /* | 443 | /* |
226 | * generic array helpers | 444 | * generic array helpers |
227 | */ | 445 | */ |
diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 7a359f5b7e25..5b4bb47c16fd 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ | 1 | snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ |
2 | hdac_regmap.o array.o | 2 | hdac_regmap.o hdac_controller.o hdac_stream.o array.o |
3 | 3 | ||
4 | snd-hda-core-objs += trace.o | 4 | snd-hda-core-objs += trace.o |
5 | CFLAGS_trace.o := -I$(src) | 5 | CFLAGS_trace.o := -I$(src) |
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 8e262da74f6a..27c447e4fe5c 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c | |||
@@ -11,21 +11,36 @@ | |||
11 | 11 | ||
12 | static void process_unsol_events(struct work_struct *work); | 12 | static void process_unsol_events(struct work_struct *work); |
13 | 13 | ||
14 | static const struct hdac_bus_ops default_ops = { | ||
15 | .command = snd_hdac_bus_send_cmd, | ||
16 | .get_response = snd_hdac_bus_get_response, | ||
17 | }; | ||
18 | |||
14 | /** | 19 | /** |
15 | * snd_hdac_bus_init - initialize a HD-audio bas bus | 20 | * snd_hdac_bus_init - initialize a HD-audio bas bus |
16 | * @bus: the pointer to bus object | 21 | * @bus: the pointer to bus object |
22 | * @ops: bus verb operators | ||
23 | * @io_ops: lowlevel I/O operators | ||
17 | * | 24 | * |
18 | * Returns 0 if successful, or a negative error code. | 25 | * Returns 0 if successful, or a negative error code. |
19 | */ | 26 | */ |
20 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | 27 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
21 | const struct hdac_bus_ops *ops) | 28 | const struct hdac_bus_ops *ops, |
29 | const struct hdac_io_ops *io_ops) | ||
22 | { | 30 | { |
23 | memset(bus, 0, sizeof(*bus)); | 31 | memset(bus, 0, sizeof(*bus)); |
24 | bus->dev = dev; | 32 | bus->dev = dev; |
25 | bus->ops = ops; | 33 | if (ops) |
34 | bus->ops = ops; | ||
35 | else | ||
36 | bus->ops = &default_ops; | ||
37 | bus->io_ops = io_ops; | ||
38 | INIT_LIST_HEAD(&bus->stream_list); | ||
26 | INIT_LIST_HEAD(&bus->codec_list); | 39 | INIT_LIST_HEAD(&bus->codec_list); |
27 | INIT_WORK(&bus->unsol_work, process_unsol_events); | 40 | INIT_WORK(&bus->unsol_work, process_unsol_events); |
41 | spin_lock_init(&bus->reg_lock); | ||
28 | mutex_init(&bus->cmd_mutex); | 42 | mutex_init(&bus->cmd_mutex); |
43 | bus->irq = -1; | ||
29 | return 0; | 44 | return 0; |
30 | } | 45 | } |
31 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init); | 46 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init); |
@@ -36,6 +51,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init); | |||
36 | */ | 51 | */ |
37 | void snd_hdac_bus_exit(struct hdac_bus *bus) | 52 | void snd_hdac_bus_exit(struct hdac_bus *bus) |
38 | { | 53 | { |
54 | WARN_ON(!list_empty(&bus->stream_list)); | ||
39 | WARN_ON(!list_empty(&bus->codec_list)); | 55 | WARN_ON(!list_empty(&bus->codec_list)); |
40 | cancel_work_sync(&bus->unsol_work); | 56 | cancel_work_sync(&bus->unsol_work); |
41 | } | 57 | } |
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c new file mode 100644 index 000000000000..c0069d0b7875 --- /dev/null +++ b/sound/hda/hdac_controller.c | |||
@@ -0,0 +1,449 @@ | |||
1 | /* | ||
2 | * HD-audio controller helpers | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/export.h> | ||
8 | #include <sound/core.h> | ||
9 | #include <sound/hdaudio.h> | ||
10 | #include <sound/hda_register.h> | ||
11 | |||
12 | /* clear CORB read pointer properly */ | ||
13 | static void azx_clear_corbrp(struct hdac_bus *bus) | ||
14 | { | ||
15 | int timeout; | ||
16 | |||
17 | for (timeout = 1000; timeout > 0; timeout--) { | ||
18 | if (snd_hdac_chip_readw(bus, CORBRP) & AZX_CORBRP_RST) | ||
19 | break; | ||
20 | udelay(1); | ||
21 | } | ||
22 | if (timeout <= 0) | ||
23 | dev_err(bus->dev, "CORB reset timeout#1, CORBRP = %d\n", | ||
24 | snd_hdac_chip_readw(bus, CORBRP)); | ||
25 | |||
26 | snd_hdac_chip_writew(bus, CORBRP, 0); | ||
27 | for (timeout = 1000; timeout > 0; timeout--) { | ||
28 | if (snd_hdac_chip_readw(bus, CORBRP) == 0) | ||
29 | break; | ||
30 | udelay(1); | ||
31 | } | ||
32 | if (timeout <= 0) | ||
33 | dev_err(bus->dev, "CORB reset timeout#2, CORBRP = %d\n", | ||
34 | snd_hdac_chip_readw(bus, CORBRP)); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * snd_hdac_bus_init_cmd_io - set up CORB/RIRB buffers | ||
39 | * @bus: HD-audio core bus | ||
40 | */ | ||
41 | void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) | ||
42 | { | ||
43 | spin_lock_irq(&bus->reg_lock); | ||
44 | /* CORB set up */ | ||
45 | bus->corb.addr = bus->rb.addr; | ||
46 | bus->corb.buf = (__le32 *)bus->rb.area; | ||
47 | snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr); | ||
48 | snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr)); | ||
49 | |||
50 | /* set the corb size to 256 entries (ULI requires explicitly) */ | ||
51 | snd_hdac_chip_writeb(bus, CORBSIZE, 0x02); | ||
52 | /* set the corb write pointer to 0 */ | ||
53 | snd_hdac_chip_writew(bus, CORBWP, 0); | ||
54 | |||
55 | /* reset the corb hw read pointer */ | ||
56 | snd_hdac_chip_writew(bus, CORBRP, AZX_CORBRP_RST); | ||
57 | if (!bus->corbrp_self_clear) | ||
58 | azx_clear_corbrp(bus); | ||
59 | |||
60 | /* enable corb dma */ | ||
61 | snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN); | ||
62 | |||
63 | /* RIRB set up */ | ||
64 | bus->rirb.addr = bus->rb.addr + 2048; | ||
65 | bus->rirb.buf = (__le32 *)(bus->rb.area + 2048); | ||
66 | bus->rirb.wp = bus->rirb.rp = 0; | ||
67 | memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds)); | ||
68 | snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr); | ||
69 | snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr)); | ||
70 | |||
71 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | ||
72 | snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02); | ||
73 | /* reset the rirb hw write pointer */ | ||
74 | snd_hdac_chip_writew(bus, RIRBWP, AZX_RIRBWP_RST); | ||
75 | /* set N=1, get RIRB response interrupt for new entry */ | ||
76 | snd_hdac_chip_writew(bus, RINTCNT, 1); | ||
77 | /* enable rirb dma and response irq */ | ||
78 | snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); | ||
79 | spin_unlock_irq(&bus->reg_lock); | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io); | ||
82 | |||
83 | /** | ||
84 | * snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers | ||
85 | * @bus: HD-audio core bus | ||
86 | */ | ||
87 | void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus) | ||
88 | { | ||
89 | spin_lock_irq(&bus->reg_lock); | ||
90 | /* disable ringbuffer DMAs */ | ||
91 | snd_hdac_chip_writeb(bus, RIRBCTL, 0); | ||
92 | snd_hdac_chip_writeb(bus, CORBCTL, 0); | ||
93 | /* disable unsolicited responses */ | ||
94 | snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0); | ||
95 | spin_unlock_irq(&bus->reg_lock); | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io); | ||
98 | |||
99 | static unsigned int azx_command_addr(u32 cmd) | ||
100 | { | ||
101 | unsigned int addr = cmd >> 28; | ||
102 | |||
103 | if (snd_BUG_ON(addr >= HDA_MAX_CODECS)) | ||
104 | addr = 0; | ||
105 | return addr; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * snd_hdac_bus_send_cmd - send a command verb via CORB | ||
110 | * @bus: HD-audio core bus | ||
111 | * @val: encoded verb value to send | ||
112 | * | ||
113 | * Returns zero for success or a negative error code. | ||
114 | */ | ||
115 | int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val) | ||
116 | { | ||
117 | unsigned int addr = azx_command_addr(val); | ||
118 | unsigned int wp, rp; | ||
119 | |||
120 | spin_lock_irq(&bus->reg_lock); | ||
121 | |||
122 | bus->last_cmd[azx_command_addr(val)] = val; | ||
123 | |||
124 | /* add command to corb */ | ||
125 | wp = snd_hdac_chip_readw(bus, CORBWP); | ||
126 | if (wp == 0xffff) { | ||
127 | /* something wrong, controller likely turned to D3 */ | ||
128 | spin_unlock_irq(&bus->reg_lock); | ||
129 | return -EIO; | ||
130 | } | ||
131 | wp++; | ||
132 | wp %= AZX_MAX_CORB_ENTRIES; | ||
133 | |||
134 | rp = snd_hdac_chip_readw(bus, CORBRP); | ||
135 | if (wp == rp) { | ||
136 | /* oops, it's full */ | ||
137 | spin_unlock_irq(&bus->reg_lock); | ||
138 | return -EAGAIN; | ||
139 | } | ||
140 | |||
141 | bus->rirb.cmds[addr]++; | ||
142 | bus->corb.buf[wp] = cpu_to_le32(val); | ||
143 | snd_hdac_chip_writew(bus, CORBWP, wp); | ||
144 | |||
145 | spin_unlock_irq(&bus->reg_lock); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd); | ||
150 | |||
151 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) | ||
152 | |||
153 | /** | ||
154 | * snd_hdac_bus_update_rirb - retrieve RIRB entries | ||
155 | * @bus: HD-audio core bus | ||
156 | * | ||
157 | * Usually called from interrupt handler. | ||
158 | */ | ||
159 | void snd_hdac_bus_update_rirb(struct hdac_bus *bus) | ||
160 | { | ||
161 | unsigned int rp, wp; | ||
162 | unsigned int addr; | ||
163 | u32 res, res_ex; | ||
164 | |||
165 | wp = snd_hdac_chip_readw(bus, RIRBWP); | ||
166 | if (wp == 0xffff) { | ||
167 | /* something wrong, controller likely turned to D3 */ | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | if (wp == bus->rirb.wp) | ||
172 | return; | ||
173 | bus->rirb.wp = wp; | ||
174 | |||
175 | while (bus->rirb.rp != wp) { | ||
176 | bus->rirb.rp++; | ||
177 | bus->rirb.rp %= AZX_MAX_RIRB_ENTRIES; | ||
178 | |||
179 | rp = bus->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | ||
180 | res_ex = le32_to_cpu(bus->rirb.buf[rp + 1]); | ||
181 | res = le32_to_cpu(bus->rirb.buf[rp]); | ||
182 | addr = res_ex & 0xf; | ||
183 | if (addr >= HDA_MAX_CODECS) { | ||
184 | dev_err(bus->dev, | ||
185 | "spurious response %#x:%#x, rp = %d, wp = %d", | ||
186 | res, res_ex, bus->rirb.rp, wp); | ||
187 | snd_BUG(); | ||
188 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) | ||
189 | snd_hdac_bus_queue_event(bus, res, res_ex); | ||
190 | else if (bus->rirb.cmds[addr]) { | ||
191 | bus->rirb.res[addr] = res; | ||
192 | bus->rirb.cmds[addr]--; | ||
193 | } else { | ||
194 | dev_err_ratelimited(bus->dev, | ||
195 | "spurious response %#x:%#x, last cmd=%#08x\n", | ||
196 | res, res_ex, bus->last_cmd[addr]); | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(snd_hdac_bus_update_rirb); | ||
201 | |||
202 | /** | ||
203 | * snd_hdac_bus_get_response - receive a response via RIRB | ||
204 | * @bus: HD-audio core bus | ||
205 | * @addr: codec address | ||
206 | * @res: pointer to store the value, NULL when not needed | ||
207 | * | ||
208 | * Returns zero if a value is read, or a negative error code. | ||
209 | */ | ||
210 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, | ||
211 | unsigned int *res) | ||
212 | { | ||
213 | unsigned long timeout; | ||
214 | unsigned long loopcounter; | ||
215 | |||
216 | timeout = jiffies + msecs_to_jiffies(1000); | ||
217 | |||
218 | for (loopcounter = 0;; loopcounter++) { | ||
219 | spin_lock_irq(&bus->reg_lock); | ||
220 | if (!bus->rirb.cmds[addr]) { | ||
221 | if (res) | ||
222 | *res = bus->rirb.res[addr]; /* the last value */ | ||
223 | spin_unlock_irq(&bus->reg_lock); | ||
224 | return 0; | ||
225 | } | ||
226 | spin_unlock_irq(&bus->reg_lock); | ||
227 | if (time_after(jiffies, timeout)) | ||
228 | break; | ||
229 | if (loopcounter > 3000) | ||
230 | msleep(2); /* temporary workaround */ | ||
231 | else { | ||
232 | udelay(10); | ||
233 | cond_resched(); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | return -EIO; | ||
238 | } | ||
239 | EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response); | ||
240 | |||
241 | /* | ||
242 | * Lowlevel interface | ||
243 | */ | ||
244 | |||
245 | /** | ||
246 | * snd_hdac_bus_enter_link_reset - enter link reset | ||
247 | * @bus: HD-audio core bus | ||
248 | * | ||
249 | * Enter to the link reset state. | ||
250 | */ | ||
251 | void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus) | ||
252 | { | ||
253 | unsigned long timeout; | ||
254 | |||
255 | /* reset controller */ | ||
256 | snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, 0); | ||
257 | |||
258 | timeout = jiffies + msecs_to_jiffies(100); | ||
259 | while ((snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET) && | ||
260 | time_before(jiffies, timeout)) | ||
261 | usleep_range(500, 1000); | ||
262 | } | ||
263 | EXPORT_SYMBOL_GPL(snd_hdac_bus_enter_link_reset); | ||
264 | |||
265 | /** | ||
266 | * snd_hdac_bus_exit_link_reset - exit link reset | ||
267 | * @bus: HD-audio core bus | ||
268 | * | ||
269 | * Exit from the link reset state. | ||
270 | */ | ||
271 | void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus) | ||
272 | { | ||
273 | unsigned long timeout; | ||
274 | |||
275 | snd_hdac_chip_updateb(bus, GCTL, 0, AZX_GCTL_RESET); | ||
276 | |||
277 | timeout = jiffies + msecs_to_jiffies(100); | ||
278 | while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout)) | ||
279 | usleep_range(500, 1000); | ||
280 | } | ||
281 | EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset); | ||
282 | |||
283 | /* reset codec link */ | ||
284 | static int azx_reset(struct hdac_bus *bus, bool full_reset) | ||
285 | { | ||
286 | if (!full_reset) | ||
287 | goto skip_reset; | ||
288 | |||
289 | /* clear STATESTS */ | ||
290 | snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); | ||
291 | |||
292 | /* reset controller */ | ||
293 | snd_hdac_bus_enter_link_reset(bus); | ||
294 | |||
295 | /* delay for >= 100us for codec PLL to settle per spec | ||
296 | * Rev 0.9 section 5.5.1 | ||
297 | */ | ||
298 | usleep_range(500, 1000); | ||
299 | |||
300 | /* Bring controller out of reset */ | ||
301 | snd_hdac_bus_exit_link_reset(bus); | ||
302 | |||
303 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | ||
304 | usleep_range(1000, 1200); | ||
305 | |||
306 | skip_reset: | ||
307 | /* check to see if controller is ready */ | ||
308 | if (!snd_hdac_chip_readb(bus, GCTL)) { | ||
309 | dev_dbg(bus->dev, "azx_reset: controller not ready!\n"); | ||
310 | return -EBUSY; | ||
311 | } | ||
312 | |||
313 | /* Accept unsolicited responses */ | ||
314 | snd_hdac_chip_updatel(bus, GCTL, 0, AZX_GCTL_UNSOL); | ||
315 | |||
316 | /* detect codecs */ | ||
317 | if (!bus->codec_mask) { | ||
318 | bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); | ||
319 | dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /* enable interrupts */ | ||
326 | static void azx_int_enable(struct hdac_bus *bus) | ||
327 | { | ||
328 | /* enable controller CIE and GIE */ | ||
329 | snd_hdac_chip_updatel(bus, INTCTL, 0, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); | ||
330 | } | ||
331 | |||
332 | /* disable interrupts */ | ||
333 | static void azx_int_disable(struct hdac_bus *bus) | ||
334 | { | ||
335 | struct hdac_stream *azx_dev; | ||
336 | |||
337 | /* disable interrupts in stream descriptor */ | ||
338 | list_for_each_entry(azx_dev, &bus->stream_list, list) | ||
339 | snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); | ||
340 | |||
341 | /* disable SIE for all streams */ | ||
342 | snd_hdac_chip_writeb(bus, INTCTL, 0); | ||
343 | |||
344 | /* disable controller CIE and GIE */ | ||
345 | snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN, 0); | ||
346 | } | ||
347 | |||
348 | /* clear interrupts */ | ||
349 | static void azx_int_clear(struct hdac_bus *bus) | ||
350 | { | ||
351 | struct hdac_stream *azx_dev; | ||
352 | |||
353 | /* clear stream status */ | ||
354 | list_for_each_entry(azx_dev, &bus->stream_list, list) | ||
355 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); | ||
356 | |||
357 | /* clear STATESTS */ | ||
358 | snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); | ||
359 | |||
360 | /* clear rirb status */ | ||
361 | snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); | ||
362 | |||
363 | /* clear int status */ | ||
364 | snd_hdac_chip_writel(bus, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * snd_hdac_bus_init_chip - reset and start the controller registers | ||
369 | * @bus: HD-audio core bus | ||
370 | * @full_reset: Do full reset | ||
371 | */ | ||
372 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset) | ||
373 | { | ||
374 | if (bus->chip_init) | ||
375 | return false; | ||
376 | |||
377 | /* reset controller */ | ||
378 | azx_reset(bus, full_reset); | ||
379 | |||
380 | /* initialize interrupts */ | ||
381 | azx_int_clear(bus); | ||
382 | azx_int_enable(bus); | ||
383 | |||
384 | /* initialize the codec command I/O */ | ||
385 | snd_hdac_bus_init_cmd_io(bus); | ||
386 | |||
387 | /* program the position buffer */ | ||
388 | if (bus->use_posbuf && bus->posbuf.addr) { | ||
389 | snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); | ||
390 | snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr)); | ||
391 | } | ||
392 | |||
393 | bus->chip_init = true; | ||
394 | return true; | ||
395 | } | ||
396 | EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip); | ||
397 | |||
398 | /** | ||
399 | * snd_hdac_bus_stop_chip - disable the whole IRQ and I/Os | ||
400 | * @bus: HD-audio core bus | ||
401 | */ | ||
402 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus) | ||
403 | { | ||
404 | if (!bus->chip_init) | ||
405 | return; | ||
406 | |||
407 | /* disable interrupts */ | ||
408 | azx_int_disable(bus); | ||
409 | azx_int_clear(bus); | ||
410 | |||
411 | /* disable CORB/RIRB */ | ||
412 | snd_hdac_bus_stop_cmd_io(bus); | ||
413 | |||
414 | /* disable position buffer */ | ||
415 | if (bus->posbuf.addr) { | ||
416 | snd_hdac_chip_writel(bus, DPLBASE, 0); | ||
417 | snd_hdac_chip_writel(bus, DPUBASE, 0); | ||
418 | } | ||
419 | |||
420 | bus->chip_init = false; | ||
421 | } | ||
422 | EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip); | ||
423 | |||
424 | /** | ||
425 | * snd_hdac_bus_handle_stream_irq - interrupt handler for streams | ||
426 | * @bus: HD-audio core bus | ||
427 | * @status: INTSTS register value | ||
428 | * @ask: callback to be called for woken streams | ||
429 | */ | ||
430 | void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, | ||
431 | void (*ack)(struct hdac_bus *, | ||
432 | struct hdac_stream *)) | ||
433 | { | ||
434 | struct hdac_stream *azx_dev; | ||
435 | u8 sd_status; | ||
436 | |||
437 | list_for_each_entry(azx_dev, &bus->stream_list, list) { | ||
438 | if (status & azx_dev->sd_int_sta_mask) { | ||
439 | sd_status = snd_hdac_stream_readb(azx_dev, SD_STS); | ||
440 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); | ||
441 | if (!azx_dev->substream || !azx_dev->running || | ||
442 | !(sd_status & SD_INT_COMPLETE)) | ||
443 | continue; | ||
444 | if (ack) | ||
445 | ack(bus, azx_dev); | ||
446 | } | ||
447 | } | ||
448 | } | ||
449 | EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq); | ||
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c new file mode 100644 index 000000000000..b513a15c777f --- /dev/null +++ b/sound/hda/hdac_stream.c | |||
@@ -0,0 +1,536 @@ | |||
1 | /* | ||
2 | * HD-audio stream operations | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/export.h> | ||
8 | #include <sound/core.h> | ||
9 | #include <sound/pcm.h> | ||
10 | #include <sound/hdaudio.h> | ||
11 | #include <sound/hda_register.h> | ||
12 | |||
13 | /** | ||
14 | * snd_hdac_stream_init - initialize each stream (aka device) | ||
15 | * @bus: HD-audio core bus | ||
16 | * @azx_dev: HD-audio core stream object to initialize | ||
17 | * @idx: stream index number | ||
18 | * @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE) | ||
19 | * @tag: the tag id to assign | ||
20 | * | ||
21 | * Assign the starting bdl address to each stream (device) and initialize. | ||
22 | */ | ||
23 | void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, | ||
24 | int idx, int direction, int tag) | ||
25 | { | ||
26 | azx_dev->bus = bus; | ||
27 | if (bus->posbuf.area) | ||
28 | azx_dev->posbuf = (__le32 *)(bus->posbuf.area + idx * 8); | ||
29 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | ||
30 | azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80); | ||
31 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | ||
32 | azx_dev->sd_int_sta_mask = 1 << idx; | ||
33 | azx_dev->index = idx; | ||
34 | azx_dev->direction = direction; | ||
35 | azx_dev->stream_tag = tag; | ||
36 | list_add_tail(&azx_dev->list, &bus->stream_list); | ||
37 | } | ||
38 | EXPORT_SYMBOL_GPL(snd_hdac_stream_init); | ||
39 | |||
40 | /** | ||
41 | * snd_hdac_stream_start - start a stream | ||
42 | * @azx_dev: HD-audio core stream to start | ||
43 | * @fresh_start: false = wallclock timestamp relative to period wallclock | ||
44 | * | ||
45 | * Start a stream, set start_wallclk and set the running flag. | ||
46 | */ | ||
47 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) | ||
48 | { | ||
49 | struct hdac_bus *bus = azx_dev->bus; | ||
50 | |||
51 | azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK); | ||
52 | if (!fresh_start) | ||
53 | azx_dev->start_wallclk -= azx_dev->period_wallclk; | ||
54 | |||
55 | /* enable SIE */ | ||
56 | snd_hdac_chip_updatel(bus, INTCTL, 0, 1 << azx_dev->index); | ||
57 | /* set DMA start and interrupt mask */ | ||
58 | snd_hdac_stream_updateb(azx_dev, SD_CTL, | ||
59 | 0, SD_CTL_DMA_START | SD_INT_MASK); | ||
60 | azx_dev->running = true; | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(snd_hdac_stream_start); | ||
63 | |||
64 | /** | ||
65 | * snd_hdac_stream_clear - stop a stream DMA | ||
66 | * @azx_dev: HD-audio core stream to stop | ||
67 | */ | ||
68 | void snd_hdac_stream_clear(struct hdac_stream *azx_dev) | ||
69 | { | ||
70 | snd_hdac_stream_updateb(azx_dev, SD_CTL, | ||
71 | SD_CTL_DMA_START | SD_INT_MASK, 0); | ||
72 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | ||
73 | azx_dev->running = false; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); | ||
76 | |||
77 | /** | ||
78 | * snd_hdac_stream_stop - stop a stream | ||
79 | * @azx_dev: HD-audio core stream to stop | ||
80 | * | ||
81 | * Stop a stream DMA and disable stream interrupt | ||
82 | */ | ||
83 | void snd_hdac_stream_stop(struct hdac_stream *azx_dev) | ||
84 | { | ||
85 | snd_hdac_stream_clear(azx_dev); | ||
86 | /* disable SIE */ | ||
87 | snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0); | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(snd_hdac_stream_stop); | ||
90 | |||
91 | /** | ||
92 | * snd_hdac_stream_reset - reset a stream | ||
93 | * @azx_dev: HD-audio core stream to reset | ||
94 | */ | ||
95 | void snd_hdac_stream_reset(struct hdac_stream *azx_dev) | ||
96 | { | ||
97 | unsigned char val; | ||
98 | int timeout; | ||
99 | |||
100 | snd_hdac_stream_clear(azx_dev); | ||
101 | |||
102 | snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); | ||
103 | udelay(3); | ||
104 | timeout = 300; | ||
105 | do { | ||
106 | val = snd_hdac_stream_readb(azx_dev, SD_CTL) & | ||
107 | SD_CTL_STREAM_RESET; | ||
108 | if (val) | ||
109 | break; | ||
110 | } while (--timeout); | ||
111 | val &= ~SD_CTL_STREAM_RESET; | ||
112 | snd_hdac_stream_writeb(azx_dev, SD_CTL, val); | ||
113 | udelay(3); | ||
114 | |||
115 | timeout = 300; | ||
116 | /* waiting for hardware to report that the stream is out of reset */ | ||
117 | do { | ||
118 | val = snd_hdac_stream_readb(azx_dev, SD_CTL) & | ||
119 | SD_CTL_STREAM_RESET; | ||
120 | if (!val) | ||
121 | break; | ||
122 | } while (--timeout); | ||
123 | |||
124 | /* reset first position - may not be synced with hw at this time */ | ||
125 | if (azx_dev->posbuf) | ||
126 | *azx_dev->posbuf = 0; | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(snd_hdac_stream_reset); | ||
129 | |||
130 | /** | ||
131 | * snd_hdac_stream_setup - set up the SD for streaming | ||
132 | * @azx_dev: HD-audio core stream to set up | ||
133 | */ | ||
134 | int snd_hdac_stream_setup(struct hdac_stream *azx_dev) | ||
135 | { | ||
136 | struct hdac_bus *bus = azx_dev->bus; | ||
137 | struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; | ||
138 | unsigned int val; | ||
139 | |||
140 | /* make sure the run bit is zero for SD */ | ||
141 | snd_hdac_stream_clear(azx_dev); | ||
142 | /* program the stream_tag */ | ||
143 | val = snd_hdac_stream_readl(azx_dev, SD_CTL); | ||
144 | val = (val & ~SD_CTL_STREAM_TAG_MASK) | | ||
145 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); | ||
146 | if (!bus->snoop) | ||
147 | val |= SD_CTL_TRAFFIC_PRIO; | ||
148 | snd_hdac_stream_writel(azx_dev, SD_CTL, val); | ||
149 | |||
150 | /* program the length of samples in cyclic buffer */ | ||
151 | snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize); | ||
152 | |||
153 | /* program the stream format */ | ||
154 | /* this value needs to be the same as the one programmed */ | ||
155 | snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val); | ||
156 | |||
157 | /* program the stream LVI (last valid index) of the BDL */ | ||
158 | snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1); | ||
159 | |||
160 | /* program the BDL address */ | ||
161 | /* lower BDL address */ | ||
162 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); | ||
163 | /* upper BDL address */ | ||
164 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, | ||
165 | upper_32_bits(azx_dev->bdl.addr)); | ||
166 | |||
167 | /* enable the position buffer */ | ||
168 | if (bus->use_posbuf && bus->posbuf.addr) { | ||
169 | if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE)) | ||
170 | snd_hdac_chip_writel(bus, DPLBASE, | ||
171 | (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE); | ||
172 | } | ||
173 | |||
174 | /* set the interrupt enable bits in the descriptor control register */ | ||
175 | snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); | ||
176 | |||
177 | if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) | ||
178 | azx_dev->fifo_size = | ||
179 | snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; | ||
180 | else | ||
181 | azx_dev->fifo_size = 0; | ||
182 | |||
183 | /* when LPIB delay correction gives a small negative value, | ||
184 | * we ignore it; currently set the threshold statically to | ||
185 | * 64 frames | ||
186 | */ | ||
187 | if (runtime->period_size > 64) | ||
188 | azx_dev->delay_negative_threshold = | ||
189 | -frames_to_bytes(runtime, 64); | ||
190 | else | ||
191 | azx_dev->delay_negative_threshold = 0; | ||
192 | |||
193 | /* wallclk has 24Mhz clock source */ | ||
194 | azx_dev->period_wallclk = (((runtime->period_size * 24000) / | ||
195 | runtime->rate) * 1000); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | EXPORT_SYMBOL_GPL(snd_hdac_stream_setup); | ||
200 | |||
201 | /** | ||
202 | * snd_hdac_stream_cleanup - cleanup a stream | ||
203 | * @azx_dev: HD-audio core stream to clean up | ||
204 | */ | ||
205 | void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev) | ||
206 | { | ||
207 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
208 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
209 | snd_hdac_stream_writel(azx_dev, SD_CTL, 0); | ||
210 | azx_dev->bufsize = 0; | ||
211 | azx_dev->period_bytes = 0; | ||
212 | azx_dev->format_val = 0; | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(snd_hdac_stream_cleanup); | ||
215 | |||
216 | /** | ||
217 | * snd_hdac_stream_assign - assign a stream for the PCM | ||
218 | * @bus: HD-audio core bus | ||
219 | * @substream: PCM substream to assign | ||
220 | * | ||
221 | * Look for an unused stream for the given PCM substream, assign it | ||
222 | * and return the stream object. If no stream is free, returns NULL. | ||
223 | * The function tries to keep using the same stream object when it's used | ||
224 | * beforehand. Also, when bus->reverse_assign flag is set, the last free | ||
225 | * or matching entry is returned. This is needed for some strange codecs. | ||
226 | */ | ||
227 | struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, | ||
228 | struct snd_pcm_substream *substream) | ||
229 | { | ||
230 | struct hdac_stream *azx_dev; | ||
231 | struct hdac_stream *res = NULL; | ||
232 | |||
233 | /* make a non-zero unique key for the substream */ | ||
234 | int key = (substream->pcm->device << 16) | (substream->number << 2) | | ||
235 | (substream->stream + 1); | ||
236 | |||
237 | list_for_each_entry(azx_dev, &bus->stream_list, list) { | ||
238 | if (azx_dev->direction != substream->stream) | ||
239 | continue; | ||
240 | if (azx_dev->opened) | ||
241 | continue; | ||
242 | if (azx_dev->assigned_key == key) { | ||
243 | res = azx_dev; | ||
244 | break; | ||
245 | } | ||
246 | if (!res || bus->reverse_assign) | ||
247 | res = azx_dev; | ||
248 | } | ||
249 | if (res) { | ||
250 | spin_lock_irq(&bus->reg_lock); | ||
251 | res->opened = 1; | ||
252 | res->running = 0; | ||
253 | res->assigned_key = key; | ||
254 | res->substream = substream; | ||
255 | spin_unlock_irq(&bus->reg_lock); | ||
256 | } | ||
257 | return res; | ||
258 | } | ||
259 | EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); | ||
260 | |||
261 | /** | ||
262 | * snd_hdac_stream_release - release the assigned stream | ||
263 | * @azx_dev: HD-audio core stream to release | ||
264 | * | ||
265 | * Release the stream that has been assigned by snd_hdac_stream_assign(). | ||
266 | */ | ||
267 | void snd_hdac_stream_release(struct hdac_stream *azx_dev) | ||
268 | { | ||
269 | struct hdac_bus *bus = azx_dev->bus; | ||
270 | |||
271 | spin_lock_irq(&bus->reg_lock); | ||
272 | azx_dev->opened = 0; | ||
273 | azx_dev->running = 0; | ||
274 | azx_dev->substream = NULL; | ||
275 | spin_unlock_irq(&bus->reg_lock); | ||
276 | } | ||
277 | EXPORT_SYMBOL_GPL(snd_hdac_stream_release); | ||
278 | |||
279 | /* | ||
280 | * set up a BDL entry | ||
281 | */ | ||
282 | static int setup_bdle(struct hdac_bus *bus, | ||
283 | struct snd_dma_buffer *dmab, | ||
284 | struct hdac_stream *azx_dev, __le32 **bdlp, | ||
285 | int ofs, int size, int with_ioc) | ||
286 | { | ||
287 | __le32 *bdl = *bdlp; | ||
288 | |||
289 | while (size > 0) { | ||
290 | dma_addr_t addr; | ||
291 | int chunk; | ||
292 | |||
293 | if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) | ||
294 | return -EINVAL; | ||
295 | |||
296 | addr = snd_sgbuf_get_addr(dmab, ofs); | ||
297 | /* program the address field of the BDL entry */ | ||
298 | bdl[0] = cpu_to_le32((u32)addr); | ||
299 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | ||
300 | /* program the size field of the BDL entry */ | ||
301 | chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); | ||
302 | /* one BDLE cannot cross 4K boundary on CTHDA chips */ | ||
303 | if (bus->align_bdle_4k) { | ||
304 | u32 remain = 0x1000 - (ofs & 0xfff); | ||
305 | |||
306 | if (chunk > remain) | ||
307 | chunk = remain; | ||
308 | } | ||
309 | bdl[2] = cpu_to_le32(chunk); | ||
310 | /* program the IOC to enable interrupt | ||
311 | * only when the whole fragment is processed | ||
312 | */ | ||
313 | size -= chunk; | ||
314 | bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); | ||
315 | bdl += 4; | ||
316 | azx_dev->frags++; | ||
317 | ofs += chunk; | ||
318 | } | ||
319 | *bdlp = bdl; | ||
320 | return ofs; | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * snd_hdac_stream_setup_periods - set up BDL entries | ||
325 | * @azx_dev: HD-audio core stream to set up | ||
326 | * | ||
327 | * Set up the buffer descriptor table of the given stream based on the | ||
328 | * period and buffer sizes of the assigned PCM substream. | ||
329 | */ | ||
330 | int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev) | ||
331 | { | ||
332 | struct hdac_bus *bus = azx_dev->bus; | ||
333 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
334 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
335 | __le32 *bdl; | ||
336 | int i, ofs, periods, period_bytes; | ||
337 | int pos_adj, pos_align; | ||
338 | |||
339 | /* reset BDL address */ | ||
340 | snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); | ||
341 | snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); | ||
342 | |||
343 | period_bytes = azx_dev->period_bytes; | ||
344 | periods = azx_dev->bufsize / period_bytes; | ||
345 | |||
346 | /* program the initial BDL entries */ | ||
347 | bdl = (__le32 *)azx_dev->bdl.area; | ||
348 | ofs = 0; | ||
349 | azx_dev->frags = 0; | ||
350 | |||
351 | pos_adj = bus->bdl_pos_adj; | ||
352 | if (!azx_dev->no_period_wakeup && pos_adj > 0) { | ||
353 | pos_align = pos_adj; | ||
354 | pos_adj = (pos_adj * runtime->rate + 47999) / 48000; | ||
355 | if (!pos_adj) | ||
356 | pos_adj = pos_align; | ||
357 | else | ||
358 | pos_adj = ((pos_adj + pos_align - 1) / pos_align) * | ||
359 | pos_align; | ||
360 | pos_adj = frames_to_bytes(runtime, pos_adj); | ||
361 | if (pos_adj >= period_bytes) { | ||
362 | dev_warn(bus->dev, "Too big adjustment %d\n", | ||
363 | pos_adj); | ||
364 | pos_adj = 0; | ||
365 | } else { | ||
366 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
367 | azx_dev, | ||
368 | &bdl, ofs, pos_adj, true); | ||
369 | if (ofs < 0) | ||
370 | goto error; | ||
371 | } | ||
372 | } else | ||
373 | pos_adj = 0; | ||
374 | |||
375 | for (i = 0; i < periods; i++) { | ||
376 | if (i == periods - 1 && pos_adj) | ||
377 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
378 | azx_dev, &bdl, ofs, | ||
379 | period_bytes - pos_adj, 0); | ||
380 | else | ||
381 | ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), | ||
382 | azx_dev, &bdl, ofs, | ||
383 | period_bytes, | ||
384 | !azx_dev->no_period_wakeup); | ||
385 | if (ofs < 0) | ||
386 | goto error; | ||
387 | } | ||
388 | return 0; | ||
389 | |||
390 | error: | ||
391 | dev_err(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n", | ||
392 | azx_dev->bufsize, period_bytes); | ||
393 | return -EINVAL; | ||
394 | } | ||
395 | EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods); | ||
396 | |||
397 | static cycle_t azx_cc_read(const struct cyclecounter *cc) | ||
398 | { | ||
399 | struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc); | ||
400 | |||
401 | return snd_hdac_chip_readl(azx_dev->bus, WALLCLK); | ||
402 | } | ||
403 | |||
404 | static void azx_timecounter_init(struct hdac_stream *azx_dev, | ||
405 | bool force, cycle_t last) | ||
406 | { | ||
407 | struct timecounter *tc = &azx_dev->tc; | ||
408 | struct cyclecounter *cc = &azx_dev->cc; | ||
409 | u64 nsec; | ||
410 | |||
411 | cc->read = azx_cc_read; | ||
412 | cc->mask = CLOCKSOURCE_MASK(32); | ||
413 | |||
414 | /* | ||
415 | * Converting from 24 MHz to ns means applying a 125/3 factor. | ||
416 | * To avoid any saturation issues in intermediate operations, | ||
417 | * the 125 factor is applied first. The division is applied | ||
418 | * last after reading the timecounter value. | ||
419 | * Applying the 1/3 factor as part of the multiplication | ||
420 | * requires at least 20 bits for a decent precision, however | ||
421 | * overflows occur after about 4 hours or less, not a option. | ||
422 | */ | ||
423 | |||
424 | cc->mult = 125; /* saturation after 195 years */ | ||
425 | cc->shift = 0; | ||
426 | |||
427 | nsec = 0; /* audio time is elapsed time since trigger */ | ||
428 | timecounter_init(tc, cc, nsec); | ||
429 | if (force) { | ||
430 | /* | ||
431 | * force timecounter to use predefined value, | ||
432 | * used for synchronized starts | ||
433 | */ | ||
434 | tc->cycle_last = last; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * snd_hdac_stream_timecounter_init - initialize time counter | ||
440 | * @azx_dev: HD-audio core stream (master stream) | ||
441 | * @streams: bit flags of streams to set up | ||
442 | * | ||
443 | * Initializes the time counter of streams marked by the bit flags (each | ||
444 | * bit corresponds to the stream index). | ||
445 | * The trigger timestamp of PCM substream assigned to the given stream is | ||
446 | * updated accordingly, too. | ||
447 | */ | ||
448 | void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, | ||
449 | unsigned int streams) | ||
450 | { | ||
451 | struct hdac_bus *bus = azx_dev->bus; | ||
452 | struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; | ||
453 | struct hdac_stream *s; | ||
454 | bool inited = false; | ||
455 | cycle_t cycle_last = 0; | ||
456 | int i = 0; | ||
457 | |||
458 | list_for_each_entry(s, &bus->stream_list, list) { | ||
459 | if (streams & (1 << i)) { | ||
460 | azx_timecounter_init(s, inited, cycle_last); | ||
461 | if (!inited) { | ||
462 | inited = true; | ||
463 | cycle_last = s->tc.cycle_last; | ||
464 | } | ||
465 | } | ||
466 | i++; | ||
467 | } | ||
468 | |||
469 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); | ||
470 | runtime->trigger_tstamp_latched = true; | ||
471 | } | ||
472 | EXPORT_SYMBOL_GPL(snd_hdac_stream_timecounter_init); | ||
473 | |||
474 | /** | ||
475 | * snd_hdac_stream_sync_trigger - turn on/off stream sync register | ||
476 | * @azx_dev: HD-audio core stream (master stream) | ||
477 | * @streams: bit flags of streams to sync | ||
478 | */ | ||
479 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, | ||
480 | unsigned int streams, unsigned int reg) | ||
481 | { | ||
482 | struct hdac_bus *bus = azx_dev->bus; | ||
483 | unsigned int val; | ||
484 | |||
485 | if (!reg) | ||
486 | reg = AZX_REG_SSYNC; | ||
487 | val = _snd_hdac_chip_read(l, bus, reg); | ||
488 | if (set) | ||
489 | val |= streams; | ||
490 | else | ||
491 | val &= ~streams; | ||
492 | _snd_hdac_chip_write(l, bus, reg, val); | ||
493 | } | ||
494 | EXPORT_SYMBOL_GPL(snd_hdac_stream_sync_trigger); | ||
495 | |||
496 | /** | ||
497 | * snd_hdac_stream_sync - sync with start/strop trigger operation | ||
498 | * @azx_dev: HD-audio core stream (master stream) | ||
499 | * @start: true = start, false = stop | ||
500 | * @streams: bit flags of streams to sync | ||
501 | * | ||
502 | * For @start = true, wait until all FIFOs get ready. | ||
503 | * For @start = false, wait until all RUN bits are cleared. | ||
504 | */ | ||
505 | void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, | ||
506 | unsigned int streams) | ||
507 | { | ||
508 | struct hdac_bus *bus = azx_dev->bus; | ||
509 | int i, nwait, timeout; | ||
510 | struct hdac_stream *s; | ||
511 | |||
512 | for (timeout = 5000; timeout; timeout--) { | ||
513 | nwait = 0; | ||
514 | i = 0; | ||
515 | list_for_each_entry(s, &bus->stream_list, list) { | ||
516 | if (streams & (1 << i)) { | ||
517 | if (start) { | ||
518 | /* check FIFO gets ready */ | ||
519 | if (!(snd_hdac_stream_readb(s, SD_STS) & | ||
520 | SD_STS_FIFO_READY)) | ||
521 | nwait++; | ||
522 | } else { | ||
523 | /* check RUN bit is cleared */ | ||
524 | if (snd_hdac_stream_readb(s, SD_CTL) & | ||
525 | SD_CTL_DMA_START) | ||
526 | nwait++; | ||
527 | } | ||
528 | } | ||
529 | i++; | ||
530 | } | ||
531 | if (!nwait) | ||
532 | break; | ||
533 | cpu_relax(); | ||
534 | } | ||
535 | } | ||
536 | EXPORT_SYMBOL_GPL(snd_hdac_stream_sync); | ||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c13d5c3e1d03..b86e2f449e56 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -550,7 +550,7 @@ int snd_hda_bus_new(struct snd_card *card, | |||
550 | if (!bus) | 550 | if (!bus) |
551 | return -ENOMEM; | 551 | return -ENOMEM; |
552 | 552 | ||
553 | err = snd_hdac_bus_init(&bus->core, card->dev, &bus_ops); | 553 | err = snd_hdac_bus_init(&bus->core, card->dev, &bus_ops, NULL); |
554 | if (err < 0) { | 554 | if (err < 0) { |
555 | kfree(bus); | 555 | kfree(bus); |
556 | return err; | 556 | return err; |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index be1b7ded8d82..15a796c21b9d 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -21,135 +21,10 @@ | |||
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include "hda_codec.h" | 23 | #include "hda_codec.h" |
24 | #include <sound/hda_register.h> | ||
24 | 25 | ||
25 | /* | 26 | #define AZX_MAX_CODECS HDA_MAX_CODECS |
26 | * registers | ||
27 | */ | ||
28 | #define AZX_REG_GCAP 0x00 | ||
29 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ | ||
30 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | ||
31 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | ||
32 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ | ||
33 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ | ||
34 | #define AZX_REG_VMIN 0x02 | ||
35 | #define AZX_REG_VMAJ 0x03 | ||
36 | #define AZX_REG_OUTPAY 0x04 | ||
37 | #define AZX_REG_INPAY 0x06 | ||
38 | #define AZX_REG_GCTL 0x08 | ||
39 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ | ||
40 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ | ||
41 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | ||
42 | #define AZX_REG_WAKEEN 0x0c | ||
43 | #define AZX_REG_STATESTS 0x0e | ||
44 | #define AZX_REG_GSTS 0x10 | ||
45 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ | ||
46 | #define AZX_REG_INTCTL 0x20 | ||
47 | #define AZX_REG_INTSTS 0x24 | ||
48 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ | ||
49 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | ||
50 | #define AZX_REG_SSYNC 0x38 | ||
51 | #define AZX_REG_CORBLBASE 0x40 | ||
52 | #define AZX_REG_CORBUBASE 0x44 | ||
53 | #define AZX_REG_CORBWP 0x48 | ||
54 | #define AZX_REG_CORBRP 0x4a | ||
55 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ | ||
56 | #define AZX_REG_CORBCTL 0x4c | ||
57 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ | ||
58 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | ||
59 | #define AZX_REG_CORBSTS 0x4d | ||
60 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ | ||
61 | #define AZX_REG_CORBSIZE 0x4e | ||
62 | |||
63 | #define AZX_REG_RIRBLBASE 0x50 | ||
64 | #define AZX_REG_RIRBUBASE 0x54 | ||
65 | #define AZX_REG_RIRBWP 0x58 | ||
66 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ | ||
67 | #define AZX_REG_RINTCNT 0x5a | ||
68 | #define AZX_REG_RIRBCTL 0x5c | ||
69 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | ||
70 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | ||
71 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | ||
72 | #define AZX_REG_RIRBSTS 0x5d | ||
73 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ | ||
74 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | ||
75 | #define AZX_REG_RIRBSIZE 0x5e | ||
76 | |||
77 | #define AZX_REG_IC 0x60 | ||
78 | #define AZX_REG_IR 0x64 | ||
79 | #define AZX_REG_IRS 0x68 | ||
80 | #define AZX_IRS_VALID (1<<1) | ||
81 | #define AZX_IRS_BUSY (1<<0) | ||
82 | |||
83 | #define AZX_REG_DPLBASE 0x70 | ||
84 | #define AZX_REG_DPUBASE 0x74 | ||
85 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | ||
86 | |||
87 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | ||
88 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | ||
89 | |||
90 | /* stream register offsets from stream base */ | ||
91 | #define AZX_REG_SD_CTL 0x00 | ||
92 | #define AZX_REG_SD_STS 0x03 | ||
93 | #define AZX_REG_SD_LPIB 0x04 | ||
94 | #define AZX_REG_SD_CBL 0x08 | ||
95 | #define AZX_REG_SD_LVI 0x0c | ||
96 | #define AZX_REG_SD_FIFOW 0x0e | ||
97 | #define AZX_REG_SD_FIFOSIZE 0x10 | ||
98 | #define AZX_REG_SD_FORMAT 0x12 | ||
99 | #define AZX_REG_SD_BDLPL 0x18 | ||
100 | #define AZX_REG_SD_BDLPU 0x1c | ||
101 | |||
102 | /* PCI space */ | ||
103 | #define AZX_PCIREG_TCSEL 0x44 | ||
104 | |||
105 | /* | ||
106 | * other constants | ||
107 | */ | ||
108 | |||
109 | /* max number of fragments - we may use more if allocating more pages for BDL */ | ||
110 | #define BDL_SIZE 4096 | ||
111 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | ||
112 | #define AZX_MAX_FRAG 32 | ||
113 | /* max buffer size - no h/w limit, you can increase as you like */ | ||
114 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | ||
115 | |||
116 | /* RIRB int mask: overrun[2], response[0] */ | ||
117 | #define RIRB_INT_RESPONSE 0x01 | ||
118 | #define RIRB_INT_OVERRUN 0x04 | ||
119 | #define RIRB_INT_MASK 0x05 | ||
120 | |||
121 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | ||
122 | #define AZX_MAX_CODECS 8 | ||
123 | #define AZX_DEFAULT_CODECS 4 | 27 | #define AZX_DEFAULT_CODECS 4 |
124 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) | ||
125 | |||
126 | /* SD_CTL bits */ | ||
127 | #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ | ||
128 | #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ | ||
129 | #define SD_CTL_STRIPE (3 << 16) /* stripe control */ | ||
130 | #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ | ||
131 | #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ | ||
132 | #define SD_CTL_STREAM_TAG_MASK (0xf << 20) | ||
133 | #define SD_CTL_STREAM_TAG_SHIFT 20 | ||
134 | |||
135 | /* SD_CTL and SD_STS */ | ||
136 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ | ||
137 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | ||
138 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ | ||
139 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ | ||
140 | SD_INT_COMPLETE) | ||
141 | |||
142 | /* SD_STS */ | ||
143 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | ||
144 | |||
145 | /* INTCTL and INTSTS */ | ||
146 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ | ||
147 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | ||
148 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | ||
149 | |||
150 | /* below are so far hardcoded - should read registers in future */ | ||
151 | #define AZX_MAX_CORB_ENTRIES 256 | ||
152 | #define AZX_MAX_RIRB_ENTRIES 256 | ||
153 | 28 | ||
154 | /* driver quirks (capabilities) */ | 29 | /* driver quirks (capabilities) */ |
155 | /* bits 0-7 are used for indicating driver type */ | 30 | /* bits 0-7 are used for indicating driver type */ |
@@ -183,9 +58,6 @@ enum { | |||
183 | AZX_SNOOP_TYPE_NVIDIA, | 58 | AZX_SNOOP_TYPE_NVIDIA, |
184 | }; | 59 | }; |
185 | 60 | ||
186 | /* HD Audio class code */ | ||
187 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | ||
188 | |||
189 | struct azx_dev { | 61 | struct azx_dev { |
190 | struct snd_dma_buffer bdl; /* BDL buffer */ | 62 | struct snd_dma_buffer bdl; /* BDL buffer */ |
191 | u32 *posbuf; /* position buffer pointer */ | 63 | u32 *posbuf; /* position buffer pointer */ |