aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-04-14 06:15:47 -0400
committerTakashi Iwai <tiwai@suse.de>2015-04-16 01:27:58 -0400
commit14752412721c61d9ac1e8d8fb51d7148cb15f85b (patch)
treea66845e59854c2a01b107695b69ebf05e692776c
parentcad372f1be5ef7cf14b980e679fbf30430dc241f (diff)
ALSA: hda - Add the controller helper codes to hda-core module
This patch adds the controller helper codes to hda-core library. The I/O access ops are added to the bus ops. The CORB/RIRB, the basic attributes like irq# and iomap address, some locks and the list of streams are added to the bus object, together with the stream object and its helpers. Currently the codes are just copied from the legacy driver, so you can find duplicated codes in both directories. Only constants are removed from the original hda_controller.h. More integration work will follow in the later patches. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/hda_register.h152
-rw-r--r--include/sound/hdaudio.h224
-rw-r--r--sound/hda/Makefile2
-rw-r--r--sound/hda/hdac_bus.c20
-rw-r--r--sound/hda/hdac_controller.c449
-rw-r--r--sound/hda/hdac_stream.c536
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_controller.h132
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 */
73enum { 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 */
140static inline unsigned int
141snd_hdac_stream_get_pos_lpib(struct hdac_stream *stream)
142{
143 return snd_hdac_stream_readl(stream, SD_LPIB);
144}
145
146static inline unsigned int
147snd_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 */
12typedef u16 hda_nid_t; 16typedef u16 hda_nid_t;
13 17
14struct hdac_bus; 18struct hdac_bus;
19struct hdac_stream;
15struct hdac_device; 20struct hdac_device;
16struct hdac_driver; 21struct hdac_driver;
17struct hdac_widget_tree; 22struct 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 */
166struct hdac_bus_ops { 171struct 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 */
182struct 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 */
203struct 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 */
176struct hdac_bus { 214struct 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
202int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, 272int 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);
204void snd_hdac_bus_exit(struct hdac_bus *bus); 275void snd_hdac_bus_exit(struct hdac_bus *bus);
205int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, 276int 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
296int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
297int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
298 unsigned int *res);
299
300bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset);
301void snd_hdac_bus_stop_chip(struct hdac_bus *bus);
302void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus);
303void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
304void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
305void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
306
307void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
308void 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 */
348struct 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
388void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
389 int idx, int direction, int tag);
390struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
391 struct snd_pcm_substream *substream);
392void snd_hdac_stream_release(struct hdac_stream *azx_dev);
393
394int snd_hdac_stream_setup(struct hdac_stream *azx_dev);
395void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev);
396int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
397void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start);
398void snd_hdac_stream_clear(struct hdac_stream *azx_dev);
399void snd_hdac_stream_stop(struct hdac_stream *azx_dev);
400void snd_hdac_stream_reset(struct hdac_stream *azx_dev);
401void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
402 unsigned int streams, unsigned int reg);
403void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
404 unsigned int streams);
405void 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 @@
1snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ 1snd-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
4snd-hda-core-objs += trace.o 4snd-hda-core-objs += trace.o
5CFLAGS_trace.o := -I$(src) 5CFLAGS_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
12static void process_unsol_events(struct work_struct *work); 12static void process_unsol_events(struct work_struct *work);
13 13
14static 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 */
20int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, 27int 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}
31EXPORT_SYMBOL_GPL(snd_hdac_bus_init); 46EXPORT_SYMBOL_GPL(snd_hdac_bus_init);
@@ -36,6 +51,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init);
36 */ 51 */
37void snd_hdac_bus_exit(struct hdac_bus *bus) 52void 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 */
13static 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 */
41void 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}
81EXPORT_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 */
87void 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}
97EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io);
98
99static 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 */
115int 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}
149EXPORT_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 */
159void 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}
200EXPORT_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 */
210int 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}
239EXPORT_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 */
251void 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}
263EXPORT_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 */
271void 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}
281EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset);
282
283/* reset codec link */
284static 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 */
326static 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 */
333static 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 */
349static 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 */
372bool 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}
396EXPORT_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 */
402void 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}
422EXPORT_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 */
430void 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}
449EXPORT_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 */
23void 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}
38EXPORT_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 */
47void 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}
62EXPORT_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 */
68void 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}
75EXPORT_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 */
83void 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}
89EXPORT_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 */
95void 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}
128EXPORT_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 */
134int 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}
199EXPORT_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 */
205void 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}
214EXPORT_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 */
227struct 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}
259EXPORT_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 */
267void 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}
277EXPORT_SYMBOL_GPL(snd_hdac_stream_release);
278
279/*
280 * set up a BDL entry
281 */
282static 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 */
330int 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}
395EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods);
396
397static 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
404static 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 */
448void 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}
472EXPORT_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 */
479void 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}
494EXPORT_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 */
505void 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}
536EXPORT_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 */
88enum { 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
189struct azx_dev { 61struct 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 */