diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-04-27 16:25:22 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-04-27 16:25:22 +0200 |
commit | 111d9bf773cfcf2c6af4a036b067bc3f59bea03b (patch) | |
tree | 33135ba53622fdd89b56d942a81e7cc9e7497434 | |
parent | df5e4d7c8a40a5976b0559fc1d4dbd8780460311 (diff) | |
download | hda-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.ac | 11 | ||||
-rw-r--r-- | hda-emu.c | 56 | ||||
-rw-r--r-- | include/linux/clocksource.h | 6 | ||||
-rw-r--r-- | include/linux/interrupt.h | 0 | ||||
-rw-r--r-- | include/linux/io.h | 0 | ||||
-rw-r--r-- | include/linux/timecounter.h | 30 | ||||
-rw-r--r-- | include/sound/core.h | 2 | ||||
-rw-r--r-- | include/sound/hda_register.h | 152 | ||||
-rw-r--r-- | include/sound/memalloc.h | 1 | ||||
-rw-r--r-- | include/sound/pcm.h | 16 | ||||
-rw-r--r-- | include/wrapper.h | 12 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/hdac_stream.c | 5 |
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" @@ -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 |