aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-04-27 16:25:22 +0200
committerTakashi Iwai <tiwai@suse.de>2015-04-27 16:25:22 +0200
commit111d9bf773cfcf2c6af4a036b067bc3f59bea03b (patch)
tree33135ba53622fdd89b56d942a81e7cc9e7497434
parentdf5e4d7c8a40a5976b0559fc1d4dbd8780460311 (diff)
downloadhda-emu-111d9bf773cfcf2c6af4a036b067bc3f59bea03b.tar.gz
Support for 4.2+ kernel code
Now hda controller code was split, and bus_ops was dropped. It requires more wrappers in linux/*.h and sound/*.h files, as well as the adaption of builds of hda-emu.c. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--configure.ac11
-rw-r--r--hda-emu.c56
-rw-r--r--include/linux/clocksource.h6
-rw-r--r--include/linux/interrupt.h0
-rw-r--r--include/linux/io.h0
-rw-r--r--include/linux/timecounter.h30
-rw-r--r--include/sound/core.h2
-rw-r--r--include/sound/hda_register.h152
-rw-r--r--include/sound/memalloc.h1
-rw-r--r--include/sound/pcm.h16
-rw-r--r--include/wrapper.h12
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/hdac_stream.c5
13 files changed, 289 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 29ae021..f58a184 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,6 +189,17 @@ if test "$NEW_HDA_INFRA" = "yes"; then
AC_DEFINE(NEW_HDA_INFRA)
fi
+AC_MSG_CHECKING(for hda_bus_ops)
+if grep -q 'struct hda_bus_ops ' hda/hda_codec.h; then
+ AC_MSG_RESULT(yes)
+ HAVE_BUS_OPS=yes
+else
+ AC_MSG_RESULT(no)
+fi
+if test "$HAVE_BUS_OPS" = "yes"; then
+ AC_DEFINE(HAVE_BUS_OPS)
+fi
+
AC_MSG_CHECKING(for old bus callbacks)
ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Iinclude"
diff --git a/hda-emu.c b/hda-emu.c
index c480914..e425de8 100644
--- a/hda-emu.c
+++ b/hda-emu.c
@@ -43,6 +43,15 @@
#include "hda/hda_beep.h"
#endif
+/* fixup for 4.2+ kernels */
+#ifdef NEW_HDA_INFRA
+#ifndef HAVE_BUS_OPS
+#define snd_hda_calc_stream_format snd_hdac_calc_stream_format
+#undef STREAM_FORMAT_WITH_CODEC
+#define HAVE_HDA_ATTACH_PCM 1
+#endif
+#endif
+
#ifndef HAVE_POWER_SAVE
#define snd_hda_power_up(x)
#define snd_hda_power_down(x)
@@ -61,6 +70,11 @@ static struct snd_card card = {
static struct xhda_codec proc;
static struct hda_bus *bus;
+#ifdef NEW_HDA_INFRA
+#ifndef HAVE_BUS_OPS
+static struct hda_bus _bus;
+#endif
+#endif
static struct hda_codec *_codec;
@@ -879,7 +893,9 @@ void hda_test_pcm(int id, int op, int subid,
static int attach_pcm(struct hda_bus *bus, struct hda_codec *codec,
struct hda_pcm *cpcm)
{
+#ifdef HAVE_HDA_ATTACH_PCM
int i, s;
+#endif
if (cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams) {
@@ -1309,11 +1325,37 @@ static FILE *file_open(const char *fname)
}
#ifdef NEW_HDA_INFRA
+#ifdef HAVE_BUS_OPS
static struct hda_bus_ops bus_ops = {
.command = cmd_send,
.get_response = resp_get_caddr,
.attach_pcm = attach_pcm,
};
+#else
+int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
+{
+ return cmd_send(NULL, val);
+}
+
+int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
+ unsigned int *res)
+{
+ if (res)
+ *res = resp_get(NULL);
+ return 0;
+}
+
+void snd_hda_bus_reset(struct hda_bus *bus)
+{
+ snd_hda_bus_reset_codecs(bus);
+}
+
+int snd_hda_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
+ struct hda_pcm *cpcm)
+{
+ return attach_pcm(bus, codec, cpcm);
+}
+#endif /* HAVE_BUS_OPS */
#else /* !NEW_HDA_INFRA */
static void setup_bus_template(struct hda_bus_template *temp)
{
@@ -1493,10 +1535,16 @@ int main(int argc, char **argv)
gather_codec_hooks();
#ifdef NEW_HDA_INFRA
+#ifdef HAVE_BUS_OPS
err = snd_hda_bus_new(&card, &bus);
-#else
+#else /* HAVE_BUS_OPS */
+ err = snd_hdac_bus_init(&_bus.core, NULL, NULL, NULL);
+ bus = &_bus;
+ mutex_init(&bus->prepare_mutex);
+#endif /* HAVE_BUS_OPS */
+#else /* NEW_HDA_INFRA */
err = snd_hda_bus_new(&card, &temp, &bus);
-#endif
+#endif /* NEW_HDA_INFRA */
if (err < 0) {
hda_log(HDA_LOG_ERR, "cannot create snd_hda_bus\n");
return 1;
@@ -1504,8 +1552,10 @@ int main(int argc, char **argv)
#ifdef NEW_HDA_INFRA
bus->pci = &mypci;
- bus->ops = bus_ops;
bus->modelname = opt_model;
+#ifdef HAVE_BUS_OPS
+ bus->ops = bus_ops;
+#endif
#endif /* NEW_HDA_INFRA */
ignore_invalid_ftype = 1;
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
new file mode 100644
index 0000000..e9ce23b
--- /dev/null
+++ b/include/linux/clocksource.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_CLOCKSOURCE_H
+#define _LINUX_CLOCKSOURCE_H
+
+#define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1)
+
+#endif
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/linux/interrupt.h
diff --git a/include/linux/io.h b/include/linux/io.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/linux/io.h
diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h
new file mode 100644
index 0000000..621a98c
--- /dev/null
+++ b/include/linux/timecounter.h
@@ -0,0 +1,30 @@
+#ifndef _LINUX_TIMECOUNTER_H
+#define _LINUX_TIMECOUNTER_H
+
+struct cyclecounter {
+ cycle_t (*read)(const struct cyclecounter *cc);
+ cycle_t mask;
+ u32 mult;
+ u32 shift;
+};
+
+struct timecounter {
+ const struct cyclecounter *cc;
+ cycle_t cycle_last;
+ u64 nsec;
+ u64 mask;
+ u64 frac;
+};
+
+static inline void timecounter_init(struct timecounter *tc,
+ const struct cyclecounter *cc,
+ u64 start_tstamp)
+{
+ tc->cc = cc;
+ tc->cycle_last = cc->read(cc);
+ tc->nsec = start_tstamp;
+ tc->mask = (1ULL << cc->shift) - 1;
+ tc->frac = 0;
+}
+
+#endif /* _LINUX_TIMECOUNTER_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 56a64da..e556765 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -34,6 +34,8 @@ struct snd_info_entry;
extern struct class *sound_class;
+static inline void snd_info_free_entry(struct snd_info_entry *entry) {}
+
struct snd_card {
int number; /* number of soundcard (index to
snd_cards) */
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
new file mode 100644
index 0000000..4f6d3fc
--- /dev/null
+++ b/include/sound/hda_register.h
@@ -0,0 +1,152 @@
+/*
+ * HD-audio controller (Azalia) registers and helpers
+ *
+ * For traditional reasons, we still use azx_ prefix here
+ */
+
+#ifndef __SOUND_HDA_REGISTER_H
+#define __SOUND_HDA_REGISTER_H
+
+#include <linux/io.h>
+#include <sound/hdaudio.h>
+
+#define AZX_REG_GCAP 0x00
+#define AZX_GCAP_64OK (1 << 0) /* 64bit address support */
+#define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */
+#define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */
+#define AZX_GCAP_ISS (15 << 8) /* # of input streams */
+#define AZX_GCAP_OSS (15 << 12) /* # of output streams */
+#define AZX_REG_VMIN 0x02
+#define AZX_REG_VMAJ 0x03
+#define AZX_REG_OUTPAY 0x04
+#define AZX_REG_INPAY 0x06
+#define AZX_REG_GCTL 0x08
+#define AZX_GCTL_RESET (1 << 0) /* controller reset */
+#define AZX_GCTL_FCNTRL (1 << 1) /* flush control */
+#define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */
+#define AZX_REG_WAKEEN 0x0c
+#define AZX_REG_STATESTS 0x0e
+#define AZX_REG_GSTS 0x10
+#define AZX_GSTS_FSTS (1 << 1) /* flush status */
+#define AZX_REG_INTCTL 0x20
+#define AZX_REG_INTSTS 0x24
+#define AZX_REG_WALLCLK 0x30 /* 24Mhz source */
+#define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */
+#define AZX_REG_SSYNC 0x38
+#define AZX_REG_CORBLBASE 0x40
+#define AZX_REG_CORBUBASE 0x44
+#define AZX_REG_CORBWP 0x48
+#define AZX_REG_CORBRP 0x4a
+#define AZX_CORBRP_RST (1 << 15) /* read pointer reset */
+#define AZX_REG_CORBCTL 0x4c
+#define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */
+#define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */
+#define AZX_REG_CORBSTS 0x4d
+#define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */
+#define AZX_REG_CORBSIZE 0x4e
+
+#define AZX_REG_RIRBLBASE 0x50
+#define AZX_REG_RIRBUBASE 0x54
+#define AZX_REG_RIRBWP 0x58
+#define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */
+#define AZX_REG_RINTCNT 0x5a
+#define AZX_REG_RIRBCTL 0x5c
+#define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */
+#define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */
+#define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */
+#define AZX_REG_RIRBSTS 0x5d
+#define AZX_RBSTS_IRQ (1 << 0) /* response irq */
+#define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */
+#define AZX_REG_RIRBSIZE 0x5e
+
+#define AZX_REG_IC 0x60
+#define AZX_REG_IR 0x64
+#define AZX_REG_IRS 0x68
+#define AZX_IRS_VALID (1<<1)
+#define AZX_IRS_BUSY (1<<0)
+
+#define AZX_REG_DPLBASE 0x70
+#define AZX_REG_DPUBASE 0x74
+#define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */
+
+/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+
+/* stream register offsets from stream base */
+#define AZX_REG_SD_CTL 0x00
+#define AZX_REG_SD_STS 0x03
+#define AZX_REG_SD_LPIB 0x04
+#define AZX_REG_SD_CBL 0x08
+#define AZX_REG_SD_LVI 0x0c
+#define AZX_REG_SD_FIFOW 0x0e
+#define AZX_REG_SD_FIFOSIZE 0x10
+#define AZX_REG_SD_FORMAT 0x12
+#define AZX_REG_SD_BDLPL 0x18
+#define AZX_REG_SD_BDLPU 0x1c
+
+/* PCI space */
+#define AZX_PCIREG_TCSEL 0x44
+
+/*
+ * other constants
+ */
+
+/* max number of fragments - we may use more if allocating more pages for BDL */
+#define BDL_SIZE 4096
+#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
+#define AZX_MAX_FRAG 32
+/* max buffer size - no h/w limit, you can increase as you like */
+#define AZX_MAX_BUF_SIZE (1024*1024*1024)
+
+/* RIRB int mask: overrun[2], response[0] */
+#define RIRB_INT_RESPONSE 0x01
+#define RIRB_INT_OVERRUN 0x04
+#define RIRB_INT_MASK 0x05
+
+/* STATESTS int mask: S3,SD2,SD1,SD0 */
+#define STATESTS_INT_MASK ((1 << HDA_MAX_CODECS) - 1)
+
+/* SD_CTL bits */
+#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
+#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */
+#define SD_CTL_STRIPE (3 << 16) /* stripe control */
+#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */
+#define SD_CTL_DIR (1 << 19) /* bi-directional stream */
+#define SD_CTL_STREAM_TAG_MASK (0xf << 20)
+#define SD_CTL_STREAM_TAG_SHIFT 20
+
+/* SD_CTL and SD_STS */
+#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */
+#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */
+#define SD_INT_COMPLETE 0x04 /* completion interrupt */
+#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\
+ SD_INT_COMPLETE)
+
+/* SD_STS */
+#define SD_STS_FIFO_READY 0x20 /* FIFO ready */
+
+/* INTCTL and INTSTS */
+#define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */
+#define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
+#define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
+
+/* below are so far hardcoded - should read registers in future */
+#define AZX_MAX_CORB_ENTRIES 256
+#define AZX_MAX_RIRB_ENTRIES 256
+
+/*
+ * helpers to read the stream position
+ */
+static inline unsigned int
+snd_hdac_stream_get_pos_lpib(struct hdac_stream *stream)
+{
+ return snd_hdac_stream_readl(stream, SD_LPIB);
+}
+
+static inline unsigned int
+snd_hdac_stream_get_pos_posbuf(struct hdac_stream *stream)
+{
+ return le32_to_cpu(*stream->posbuf);
+}
+
+#endif /* __SOUND_HDA_REGISTER_H */
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
new file mode 100644
index 0000000..7890823
--- /dev/null
+++ b/include/sound/memalloc.h
@@ -0,0 +1 @@
+#include <sound/pcm.h>
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index c060488..aa95a32 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -30,6 +30,8 @@ struct snd_pcm_hardware {
};
struct snd_pcm_runtime {
+ struct timespec trigger_tstamp; /* trigger timestamp */
+ bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */
snd_pcm_access_t access; /* access mode */
snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */
snd_pcm_subformat_t subformat; /* subformat */
@@ -45,6 +47,7 @@ struct snd_pcm_runtime {
unsigned int info;
unsigned int rate_num;
unsigned int rate_den;
+ unsigned int no_period_wakeup: 1;
/* -- mmap -- */
struct snd_pcm_mmap_status *status;
@@ -316,4 +319,17 @@ struct snd_dma_buffer {
#define snd_pcm_suspend_all(pcm)
+static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size)
+{
+ return size * runtime->frame_bits / 8;
+}
+
+/* XXX just for compilation, not really working */
+#define snd_sgbuf_get_addr(dmab, offset) 0
+#define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size)
+#define snd_pcm_get_dma_buf(substream) NULL
+#define snd_pcm_lib_buffer_bytes(substream) 0
+#define snd_pcm_lib_period_bytes(substream) 0
+#define snd_pcm_gettime(runtime, tv) /* nop */
+
#endif /* __SOUND_PCM_H */
diff --git a/include/wrapper.h b/include/wrapper.h
index 685f729..5ed1674 100644
--- a/include/wrapper.h
+++ b/include/wrapper.h
@@ -128,6 +128,15 @@ typedef int8_t __s8;
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
+typedef u32 __le32;
+typedef u32 __be32;
+
+#define le32_to_cpu(x) (x)
+#define cpu_to_le32(x) (x)
+#define upper_32_bits(x) ((u32)((x) >> 32))
+
+typedef unsigned long cycle_t;
+
typedef _Bool bool;
#define true 1
#define false 0
@@ -138,6 +147,7 @@ typedef unsigned long dma_addr_t;
#define __user
#define __bitwise
+#define __iomem
typedef int pm_message_t;
#define PMSG_SUSPEND 0
@@ -322,4 +332,6 @@ module_exit(__driver##_exit);
/* attributes */
#define __printf(a, b) __attribute__((format(printf, a, b)))
+#define cpu_relax()
+
#endif /* __HDA_WRAPPER_H */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 738af69..4ec9ad0 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,4 +1,4 @@
noinst_LIBRARIES = libhdacore.a
libhdacore_a_SOURCES = hda_bus_type.c hdac_bus.c hdac_device.c hdac_sysfs.c \
- hdac_regmap.c array.c
+ hdac_regmap.c array.c hdac_stream.c
INCLUDES = -I$(top_srcdir)/include
diff --git a/lib/hdac_stream.c b/lib/hdac_stream.c
new file mode 100644
index 0000000..e7f08df
--- /dev/null
+++ b/lib/hdac_stream.c
@@ -0,0 +1,5 @@
+#ifdef NEW_HDA_INFRA
+#ifndef HAVE_BUS_OPS
+#include "../dist/sound/hda/hdac_stream.c"
+#endif
+#endif