From 14752412721c61d9ac1e8d8fb51d7148cb15f85b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2015 12:15:47 +0200 Subject: 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 --- include/sound/hda_register.h | 152 +++++++++++++++++++++++++++++ include/sound/hdaudio.h | 224 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 include/sound/hda_register.h (limited to 'include') 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 @@ +/* + * 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 +#include + +#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/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 @@ #define __SOUND_HDAUDIO_H #include +#include +#include +#include +#include #include /* codec node id */ typedef u16 hda_nid_t; struct hdac_bus; +struct hdac_stream; struct hdac_device; struct hdac_driver; struct hdac_widget_tree; @@ -161,7 +166,7 @@ struct hdac_driver { #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) /* - * HD-audio bus base driver + * Bus verb operators */ struct hdac_bus_ops { /* send a single command */ @@ -171,11 +176,50 @@ struct hdac_bus_ops { unsigned int *res); }; +/* + * Lowlevel I/O operators + */ +struct hdac_io_ops { + /* mapped register accesses */ + void (*reg_writel)(u32 value, u32 __iomem *addr); + u32 (*reg_readl)(u32 __iomem *addr); + void (*reg_writew)(u16 value, u16 __iomem *addr); + u16 (*reg_readw)(u16 __iomem *addr); + void (*reg_writeb)(u8 value, u8 __iomem *addr); + u8 (*reg_readb)(u8 __iomem *addr); +}; + #define HDA_UNSOL_QUEUE_SIZE 64 +#define HDA_MAX_CODECS 8 /* limit by controller side */ + +/* HD Audio class code */ +#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 + +/* + * CORB/RIRB + * + * Each CORB entry is 4byte, RIRB is 8byte + */ +struct hdac_rb { + __le32 *buf; /* virtual address of CORB/RIRB buffer */ + dma_addr_t addr; /* physical address of CORB/RIRB buffer */ + unsigned short rp, wp; /* RIRB read/write pointers */ + int cmds[HDA_MAX_CODECS]; /* number of pending requests */ + u32 res[HDA_MAX_CODECS]; /* last read value */ +}; +/* + * HD-audio bus base driver + */ struct hdac_bus { struct device *dev; const struct hdac_bus_ops *ops; + const struct hdac_io_ops *io_ops; + + /* h/w resources */ + unsigned long addr; + void __iomem *remap_addr; + int irq; /* codec linked list */ struct list_head codec_list; @@ -189,18 +233,45 @@ struct hdac_bus { unsigned int unsol_rp, unsol_wp; struct work_struct unsol_work; + /* bit flags of detected codecs */ + unsigned long codec_mask; + /* bit flags of powered codecs */ unsigned long codec_powered; - /* flags */ + /* CORB/RIRB */ + struct hdac_rb corb; + struct hdac_rb rirb; + unsigned int last_cmd[HDA_MAX_CODECS]; /* last sent command */ + + /* CORB/RIRB and position buffers */ + struct snd_dma_buffer rb; + struct snd_dma_buffer posbuf; + + /* hdac_stream linked list */ + struct list_head stream_list; + + /* operation state */ + bool chip_init:1; /* h/w initialized */ + + /* behavior flags */ bool sync_write:1; /* sync after verb write */ + bool use_posbuf:1; /* use position buffer */ + bool snoop:1; /* enable snooping */ + bool align_bdle_4k:1; /* BDLE align 4K boundary */ + bool reverse_assign:1; /* assign devices in reverse order */ + bool corbrp_self_clear:1; /* CORBRP clears itself after reset */ + + int bdl_pos_adj; /* BDL position adjustment */ /* locks */ + spinlock_t reg_lock; struct mutex cmd_mutex; }; int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_bus_ops *ops); + const struct hdac_bus_ops *ops, + const struct hdac_io_ops *io_ops); void snd_hdac_bus_exit(struct hdac_bus *bus); int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res); @@ -222,6 +293,153 @@ static inline void snd_hdac_codec_link_down(struct hdac_device *codec) clear_bit(codec->addr, &codec->bus->codec_powered); } +int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); +int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, + unsigned int *res); + +bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); +void snd_hdac_bus_stop_chip(struct hdac_bus *bus); +void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus); +void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus); +void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); +void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); + +void snd_hdac_bus_update_rirb(struct hdac_bus *bus); +void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, + void (*ack)(struct hdac_bus *, + struct hdac_stream *)); + +/* + * macros for easy use + */ +#define _snd_hdac_chip_write(type, chip, reg, value) \ + ((chip)->io_ops->reg_write ## type(value, (chip)->remap_addr + (reg))) +#define _snd_hdac_chip_read(type, chip, reg) \ + ((chip)->io_ops->reg_read ## type((chip)->remap_addr + (reg))) + +/* read/write a register, pass without AZX_REG_ prefix */ +#define snd_hdac_chip_writel(chip, reg, value) \ + _snd_hdac_chip_write(l, chip, AZX_REG_ ## reg, value) +#define snd_hdac_chip_writew(chip, reg, value) \ + _snd_hdac_chip_write(w, chip, AZX_REG_ ## reg, value) +#define snd_hdac_chip_writeb(chip, reg, value) \ + _snd_hdac_chip_write(b, chip, AZX_REG_ ## reg, value) +#define snd_hdac_chip_readl(chip, reg) \ + _snd_hdac_chip_read(l, chip, AZX_REG_ ## reg) +#define snd_hdac_chip_readw(chip, reg) \ + _snd_hdac_chip_read(w, chip, AZX_REG_ ## reg) +#define snd_hdac_chip_readb(chip, reg) \ + _snd_hdac_chip_read(b, chip, AZX_REG_ ## reg) + +/* update a register, pass without AZX_REG_ prefix */ +#define snd_hdac_chip_updatel(chip, reg, mask, val) \ + snd_hdac_chip_writel(chip, reg, \ + (snd_hdac_chip_readl(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_chip_updatew(chip, reg, mask, val) \ + snd_hdac_chip_writew(chip, reg, \ + (snd_hdac_chip_readw(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_chip_updateb(chip, reg, mask, val) \ + snd_hdac_chip_writeb(chip, reg, \ + (snd_hdac_chip_readb(chip, reg) & ~(mask)) | (val)) + +/* + * HD-audio stream + */ +struct hdac_stream { + struct hdac_bus *bus; + struct snd_dma_buffer bdl; /* BDL buffer */ + __le32 *posbuf; /* position buffer pointer */ + int direction; /* playback / capture (SNDRV_PCM_STREAM_*) */ + + unsigned int bufsize; /* size of the play buffer in bytes */ + unsigned int period_bytes; /* size of the period in bytes */ + unsigned int frags; /* number for period in the play buffer */ + unsigned int fifo_size; /* FIFO size */ + + void __iomem *sd_addr; /* stream descriptor pointer */ + + u32 sd_int_sta_mask; /* stream int status mask */ + + /* pcm support */ + struct snd_pcm_substream *substream; /* assigned substream, + * set in PCM open + */ + unsigned int format_val; /* format value to be set in the + * controller and the codec + */ + unsigned char stream_tag; /* assigned stream */ + unsigned char index; /* stream index */ + int assigned_key; /* last device# key assigned to */ + + bool opened:1; + bool running:1; + bool no_period_wakeup:1; + + /* timestamp */ + unsigned long start_wallclk; /* start + minimum wallclk */ + unsigned long period_wallclk; /* wallclk for period */ + struct timecounter tc; + struct cyclecounter cc; + int delay_negative_threshold; + + struct list_head list; +}; + +void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, + int idx, int direction, int tag); +struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, + struct snd_pcm_substream *substream); +void snd_hdac_stream_release(struct hdac_stream *azx_dev); + +int snd_hdac_stream_setup(struct hdac_stream *azx_dev); +void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev); +int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); +void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); +void snd_hdac_stream_clear(struct hdac_stream *azx_dev); +void snd_hdac_stream_stop(struct hdac_stream *azx_dev); +void snd_hdac_stream_reset(struct hdac_stream *azx_dev); +void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, + unsigned int streams, unsigned int reg); +void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, + unsigned int streams); +void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, + unsigned int streams); +/* + * macros for easy use + */ +#define _snd_hdac_stream_write(type, dev, reg, value) \ + ((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg))) +#define _snd_hdac_stream_read(type, dev, reg) \ + ((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg))) + +/* read/write a register, pass without AZX_REG_ prefix */ +#define snd_hdac_stream_writel(dev, reg, value) \ + _snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) +#define snd_hdac_stream_writew(dev, reg, value) \ + _snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) +#define snd_hdac_stream_writeb(dev, reg, value) \ + _snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) +#define snd_hdac_stream_readl(dev, reg) \ + _snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) +#define snd_hdac_stream_readw(dev, reg) \ + _snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) +#define snd_hdac_stream_readb(dev, reg) \ + _snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) + +/* update a register, pass without AZX_REG_ prefix */ +#define snd_hdac_stream_updatel(dev, reg, mask, val) \ + snd_hdac_stream_writel(dev, reg, \ + (snd_hdac_stream_readl(dev, reg) & \ + ~(mask)) | (val)) +#define snd_hdac_stream_updatew(dev, reg, mask, val) \ + snd_hdac_stream_writew(dev, reg, \ + (snd_hdac_stream_readw(dev, reg) & \ + ~(mask)) | (val)) +#define snd_hdac_stream_updateb(dev, reg, mask, val) \ + snd_hdac_stream_writeb(dev, reg, \ + (snd_hdac_stream_readb(dev, reg) & \ + ~(mask)) | (val)) + /* * generic array helpers */ -- cgit v1.2.3 From 8f3f600b52b100f254fc16a60af1261d2e4dc239 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2015 12:53:28 +0200 Subject: ALSA: hda - Add DSP loader to core library code Copied from the legacy driver code, no transition done yet. Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 9349ccf15a36..69f27bc49eb4 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -187,6 +187,11 @@ struct hdac_io_ops { u16 (*reg_readw)(u16 __iomem *addr); void (*reg_writeb)(u8 value, u8 __iomem *addr); u8 (*reg_readb)(u8 __iomem *addr); + /* Allocation ops */ + int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size, + struct snd_dma_buffer *buf); + void (*dma_free_pages)(struct hdac_bus *bus, + struct snd_dma_buffer *buf); }; #define HDA_UNSOL_QUEUE_SIZE 64 @@ -374,6 +379,7 @@ struct hdac_stream { bool opened:1; bool running:1; bool no_period_wakeup:1; + bool locked:1; /* timestamp */ unsigned long start_wallclk; /* start + minimum wallclk */ @@ -383,6 +389,10 @@ struct hdac_stream { int delay_negative_threshold; struct list_head list; +#ifdef CONFIG_SND_HDA_DSP_LOADER + /* DSP access mutex */ + struct mutex dsp_mutex; +#endif }; void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, @@ -440,6 +450,42 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, (snd_hdac_stream_readb(dev, reg) & \ ~(mask)) | (val)) +#ifdef CONFIG_SND_HDA_DSP_LOADER +/* DSP lock helpers */ +#define snd_hdac_dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) +#define snd_hdac_dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) +#define snd_hdac_dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) +#define snd_hdac_stream_is_locked(dev) ((dev)->locked) +/* DSP loader helpers */ +int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, + unsigned int byte_size, struct snd_dma_buffer *bufp); +void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start); +void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, + struct snd_dma_buffer *dmab); +#else /* CONFIG_SND_HDA_DSP_LOADER */ +#define snd_hdac_dsp_lock_init(dev) do {} while (0) +#define snd_hdac_dsp_lock(dev) do {} while (0) +#define snd_hdac_dsp_unlock(dev) do {} while (0) +#define snd_hdac_stream_is_locked(dev) 0 + +static inline int +snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, + unsigned int byte_size, struct snd_dma_buffer *bufp) +{ + return 0; +} + +static inline void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start) +{ +} + +static inline void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, + struct snd_dma_buffer *dmab) +{ +} +#endif /* CONFIG_SND_HDA_DSP_LOADER */ + + /* * generic array helpers */ -- cgit v1.2.3 From 304dad30388d017544bc2e90fe4fefcca94263d3 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Sun, 12 Apr 2015 18:06:13 +0530 Subject: ALSA: hda - moved alloc/free stream pages function to controller library Moved azx_alloc_stream_pages and azx_free_stream_pages to controller library. Signed-off-by: Jeeja KP Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 69f27bc49eb4..59d21848a472 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -314,6 +314,9 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, void (*ack)(struct hdac_bus *, struct hdac_stream *)); +int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); +void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); + /* * macros for easy use */ -- cgit v1.2.3 From b7d023e11434131e5a7ceb4be33c3afa2c855e89 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Apr 2015 08:19:06 +0200 Subject: ALSA: hda - Move PCM format and rate handling code to core library Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 59d21848a472..15bc039de78d 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -123,6 +123,15 @@ int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, hda_nid_t *start_id); +unsigned int snd_hdac_calc_stream_format(unsigned int rate, + unsigned int channels, + unsigned int format, + unsigned int maxbps, + unsigned short spdif_ctls); +int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, + u32 *ratesp, u64 *formatsp, unsigned int *bpsp); +bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid, + unsigned int format); /** * snd_hdac_read_parm - read a codec parameter -- cgit v1.2.3 From 6d23c8f5440e33cb854e394d38b8c19315f21428 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Apr 2015 13:34:30 +0200 Subject: ALSA: hda - Move prepared flag into struct hdac_stream This flag seems used commonly, so deserves to be located there. Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 15bc039de78d..dbeb195eb4e8 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -390,6 +390,7 @@ struct hdac_stream { bool opened:1; bool running:1; + bool prepared:1; bool no_period_wakeup:1; bool locked:1; -- cgit v1.2.3 From c1cc18b1ca01530a40ace0c9ec48124ff1340125 Mon Sep 17 00:00:00 2001 From: Ramesh Babu Date: Fri, 17 Apr 2015 17:58:57 +0530 Subject: ALSA: hda - add ASoC device type for hda core Add HDA_DEV_ASOC device/driver type to support ASoC HDA drivers. Signed-off-by: Ramesh Babu Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index dbeb195eb4e8..d05931fc6f28 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -90,6 +90,7 @@ struct hdac_device { enum { HDA_DEV_CORE, HDA_DEV_LEGACY, + HDA_DEV_ASOC, }; /* direction */ -- cgit v1.2.3 From 86f6501bf4c13e805e48497aaffab86ad7a98c44 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Fri, 17 Apr 2015 17:58:58 +0530 Subject: ALSA: hda - add generic functions to set hdac stream params This will be used by hda controller driver to setup stream params in prepare. This function will setup the bdl and periods. Signed-off-by: Jeeja KP Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index d05931fc6f28..6a2e030c836c 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -418,6 +418,8 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev); int snd_hdac_stream_setup(struct hdac_stream *azx_dev); void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev); int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); +int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, + unsigned int format_val); void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); void snd_hdac_stream_clear(struct hdac_stream *azx_dev); void snd_hdac_stream_stop(struct hdac_stream *azx_dev); -- cgit v1.2.3 From 4adb7bcbcb69d3bee0ed72de83adaee27daccdd8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Apr 2015 16:10:22 +0200 Subject: ALSA: core: Use seq_file for text proc file reads seq_file is _the_ standard interface for simple text proc files. Though, we still need to support the binary proc files and the text file write, and also we need to manage the device disconnection gracefully. Thus this patch just replaces the text file read code with seq_file while keeping the rest intact. snd_iprintf() helper function is now a macro to expand itself to seq_printf() to be compatible with the existing code. The seq_file object is stored to the unused entry->rbuffer->buffer pointer. When the output size is expected to be large (greater than PAGE_SIZE), the driver should set entry->size field beforehand. Then the given size will be preallocated and the multiple show calls can be avoided. Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/info.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/info.h b/include/sound/info.h index 9ca1a493d370..ff8962ebece5 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -23,6 +23,7 @@ */ #include +#include /* buffer for information */ struct snd_info_buffer { @@ -110,8 +111,18 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer); static inline void snd_card_info_read_oss(struct snd_info_buffer *buffer) {} #endif -__printf(2, 3) -int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...); +/** + * snd_iprintf - printf on the procfs buffer + * @buf: the procfs buffer + * @fmt: the printf format + * + * Outputs the string on the procfs buffer just like printf(). + * + * Return: zero for success, or a negative error code. + */ +#define snd_iprintf(buf, fmt, args...) \ + seq_printf((struct seq_file *)(buf)->buffer, fmt, ##args) + int snd_info_init(void); int snd_info_done(void); @@ -175,7 +186,6 @@ static inline int snd_card_proc_new(struct snd_card *card, const char *name, static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)), void *private_data, void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {} - static inline int snd_info_check_reserved_words(const char *str) { return 1; } #endif -- cgit v1.2.3 From c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Apr 2015 18:26:38 +0200 Subject: ALSA: core: Remove child proc file elements recursively This patch changes the way to manage the resource release of proc files: namely, let snd_info_free_entry() freeing the whole children. This makes it us possible to drop the snd_device_*() management. Then snd_card_proc_new() becomes merely a wrapper to snd_info_create_card_entry(). Together with this change, now you need to call snd_info_free_entry() for a proc entry created via snd_card_proc_new(), while it was freed via snd_device_free() beforehand. Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/info.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/info.h b/include/sound/info.h index ff8962ebece5..3e2fda3c75ee 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -24,6 +24,7 @@ #include #include +#include /* buffer for information */ struct snd_info_buffer { @@ -146,8 +147,12 @@ void snd_info_card_id_change(struct snd_card *card); int snd_info_register(struct snd_info_entry *entry); /* for card drivers */ -int snd_card_proc_new(struct snd_card *card, const char *name, - struct snd_info_entry **entryp); +static inline int snd_card_proc_new(struct snd_card *card, const char *name, + struct snd_info_entry **entryp) +{ + *entryp = snd_info_create_card_entry(card, name, card->proc_root); + return *entryp ? 0 : -ENOMEM; +} static inline void snd_info_set_text_ops(struct snd_info_entry *entry, void *private_data, -- cgit v1.2.3 From b046d244e2290e3d114af2e91503ee3d08fc605a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Apr 2015 21:33:41 +0200 Subject: ALSA: core: Remove superfluous exit calls for proc entries Since each proc entry is freed automatically by the parent, we don't have to take care of its life cycle any longer. This allows us to reduce a few more lines of codes. Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/core.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index b12931f513f4..cdfecafff0f4 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -224,16 +224,13 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type); #endif int snd_minor_info_init(void); -int snd_minor_info_done(void); /* sound_oss.c */ #ifdef CONFIG_SND_OSSEMUL int snd_minor_info_oss_init(void); -int snd_minor_info_oss_done(void); #else static inline int snd_minor_info_oss_init(void) { return 0; } -static inline int snd_minor_info_oss_done(void) { return 0; } #endif /* memory.c */ @@ -262,7 +259,6 @@ int snd_card_free_when_closed(struct snd_card *card); void snd_card_set_id(struct snd_card *card, const char *id); int snd_card_register(struct snd_card *card); int snd_card_info_init(void); -int snd_card_info_done(void); int snd_card_add_dev_attr(struct snd_card *card, const struct attribute_group *group); int snd_component_add(struct snd_card *card, const char *component); -- cgit v1.2.3 From a0dca822e923e605dbdc2f6ed4fcd96b74df9258 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 23 Apr 2015 10:56:21 +0200 Subject: ALSA: core: Clean up OSS proc file management A few minor cleanups: - Move the call of snd_info_minor_register() into snd_info_init() so that we can call all proc-related stuff in a shot - Add missing __init prefix to snd_info_minor_register() - Return an error properly from snd_oss_info_register() - Drop snd_info_minor_unregister() that is superfluous now Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/info.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/info.h b/include/sound/info.h index 3e2fda3c75ee..16269951bafc 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -94,10 +94,8 @@ struct snd_info_entry { #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) int snd_info_minor_register(void); -int snd_info_minor_unregister(void); #else -#define snd_info_minor_register() /* NOP */ -#define snd_info_minor_unregister() /* NOP */ +#define snd_info_minor_register() 0 #endif -- cgit v1.2.3 From d16efa0626bfd11157d4a622a24aaae98435f26d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 12:20:28 +0200 Subject: ALSA: Close holes in struct snd_pcm_hw_rule On a 64-bit system there are two 32-bit holes due to the alignment of 64-bit fields. Reordering things slightly gets rid of those holes, reducing the size of the struct by 17% percent of its original size. Signed-off-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 0cb7f3f5df7b..d632809d9425 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -224,9 +224,10 @@ typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule { unsigned int cond; - snd_pcm_hw_rule_func_t func; int var; int deps[4]; + + snd_pcm_hw_rule_func_t func; void *private; }; -- cgit v1.2.3 From 782e50e0b38ff284dead13265f1c3e04004e507d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 12:20:29 +0200 Subject: ALSA: Close holes in struct snd_pcm_constraint_list On a 64-bit system there is a 32-bit hole in struct snd_pcm_constraint_list and then 32-bit padding at the end. Reordering things slightly gets rid of the hole and padding, reducing the size of the struct by 50% from its original size. Signed-off-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index d632809d9425..691e7ee0a510 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -274,8 +274,8 @@ struct snd_pcm_hw_constraint_ratdens { }; struct snd_pcm_hw_constraint_list { - unsigned int count; const unsigned int *list; + unsigned int count; unsigned int mask; }; -- cgit v1.2.3 From acde50a7bf1fd6ae0baa4402f0a02c4b1bd4c990 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 12:44:25 +0200 Subject: ASoC: dmaengine_pcm: Make FLAG_NO_RESIDUE internal Whether residue can be reported or not is not a property of the audio controller but of the DMA controller. The FLAG_NO_RESIDUE was initially added when the DMAengine framework had no support for describing the residue reporting capabilities of the controller. Support for this was added quite a while ago and recently the DMAengine framework started to complain if a driver does not describe its capabilities and a lot of patches have been merged that add support for this where it was missing. So it should be safe to assume that driver on actively used platforms properly implement the DMA capabilities API. This patch makes the FLAG_NO_RESIDUE internal and no longer allows audio controller drivers to manually set the flag. If a DMA driver against expectations does not support reporting its capabilities for now the generic DMAengine PCM driver will now emit a warning and simply assume that residue reporting is not supported. In the future this might be changed to aborting with an error. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include') diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index eb73a3a39ec2..f86ef5ea9b01 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -90,11 +90,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data( * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. */ #define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) -/* - * The platforms dmaengine driver does not support reporting the amount of - * bytes that are still left to transfer. - */ -#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2) /* * The PCM is half duplex and the DMA channel is shared between capture and * playback. -- cgit v1.2.3 From 9058cbe1eed29381f84dec9f96980f5a4ea1025f Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 27 Apr 2015 21:20:56 +0800 Subject: ALSA: jack: implement kctl creating for jack devices Currently the ALSA jack core registers only input devices for each jack registered. These jack input devices are not readable by userspace devices that run as non root. This patch series will implement kctls inside the core jack part, including kctls creating, status changing report, for both HD-Audio and ASoC jack. This allows non root userspace to read jack status and act on it. This patch adds a new API called snd_jack_add_new_kctl(), which will create a kcontrol, add it to the card, and also attach it to the jack kctl list. This patch also initialises the jack kctl list after jack is newed, and reports kctl status when jack insertion/removal events occur. snd_jack_new() is updated in the following patches to also support creating phantom jacks and jack kcontrols. We then remove these duplicated features from HDA jack and have jack kctls handled by core throughout HDA and ASoC. Signed-off-by: Liam Girdwood Modified-by: Jie Yang Signed-off-by: Jie Yang Reveiwed-by: Mark Brown Signed-off-by: Takashi Iwai --- include/sound/jack.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/jack.h b/include/sound/jack.h index 218235030ebc..433b13b89125 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -73,6 +73,8 @@ enum snd_jack_types { struct snd_jack { struct input_dev *input_dev; + struct list_head kctl_list; + struct snd_card *card; int registered; int type; const char *id; @@ -86,6 +88,7 @@ struct snd_jack { int snd_jack_new(struct snd_card *card, const char *id, int type, struct snd_jack **jack); +int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask); void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, int keytype); @@ -93,13 +96,17 @@ int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, void snd_jack_report(struct snd_jack *jack, int status); #else - static inline int snd_jack_new(struct snd_card *card, const char *id, int type, struct snd_jack **jack) { return 0; } +static inline int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask) +{ + return 0; +} + static inline void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) { -- cgit v1.2.3 From b8dd086674cfbfc246a5b9d7d7ff37f62350a878 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 27 Apr 2015 21:20:57 +0800 Subject: ALSA: Jack: handle jack embedded kcontrol creating within ctljack This patch adds a static method get_available_index() to allocate the index of new jack kcontrols and also adds jack_kctl_name_gen() which is used to ensure compatibility with jack naming by removing " Jack" from some incorrectly passed names. Signed-off-by: Jie Yang Signed-off-by: Takashi Iwai --- include/sound/control.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/control.h b/include/sound/control.h index 95aad6d3fd1a..f50e2e918ceb 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -252,7 +252,7 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); * Helper functions for jack-detection controls */ struct snd_kcontrol * -snd_kctl_jack_new(const char *name, int idx, void *private_data); +snd_kctl_jack_new(const char *name, void *private_data, struct snd_card *card); void snd_kctl_jack_report(struct snd_card *card, struct snd_kcontrol *kctl, bool status); -- cgit v1.2.3 From 4e3f0dc65883cac95807549b2f7a3ac183686bcb Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 27 Apr 2015 21:20:58 +0800 Subject: ALSA: jack: extend snd_jack_new to support phantom jack Dont create input devices for phantom jacks. Here, we extend snd_jack_new() to support phantom jack creating: pass in a bool param for [non-]phantom flag, and a bool param initial_jack to indicate whether we need to create a kctl at this stage. We can also add a kctl to the jack after its created meaning we can now integrate the HDA and ASoC jacks. Signed-off-by: Jie Yang Signed-off-by: Takashi Iwai --- include/sound/jack.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/jack.h b/include/sound/jack.h index 433b13b89125..23bede121c78 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -87,7 +87,7 @@ struct snd_jack { #ifdef CONFIG_SND_JACK int snd_jack_new(struct snd_card *card, const char *id, int type, - struct snd_jack **jack); + struct snd_jack **jack, bool initial_kctl, bool phantom_jack); int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask); void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, @@ -97,7 +97,7 @@ void snd_jack_report(struct snd_jack *jack, int status); #else static inline int snd_jack_new(struct snd_card *card, const char *id, int type, - struct snd_jack **jack) + struct snd_jack **jack, bool initial_kctl, bool phantom_jack) { return 0; } -- cgit v1.2.3 From 2ba2dfa1fcc7ce5d2bf1716ec3d32b6fa0882e68 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 27 Apr 2015 21:20:59 +0800 Subject: ALSA: hda - Update to use the new jack kctls method Jack snd_kcontrols can now be created during snd_jack_new() or by later calling snd_jack_add_new_kctls(). This patch creates the jacks during the initialisation stage for both phantom and non phantom jacks. Signed-off-by: Jie Yang Signed-off-by: Takashi Iwai --- include/sound/control.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/control.h b/include/sound/control.h index f50e2e918ceb..21d047f229a1 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -252,7 +252,7 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); * Helper functions for jack-detection controls */ struct snd_kcontrol * -snd_kctl_jack_new(const char *name, void *private_data, struct snd_card *card); +snd_kctl_jack_new(const char *name, struct snd_card *card); void snd_kctl_jack_report(struct snd_card *card, struct snd_kcontrol *kctl, bool status); -- cgit v1.2.3 From 2dc0f16b83b43fd1f86a2358d46f46488230c6c8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 21 Apr 2015 07:02:34 +0000 Subject: ASoC: soc.h: tidyup struct snd_soc_dai_link definition order Current struct snd_soc_dai_link has many members, but definition order was random. Especially, bool / bit field are defined randomly. This patch tidyups these definition order to calculate data alignment easy. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index fcb312b3f258..38757fe7a3d8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -949,6 +949,24 @@ struct snd_soc_dai_link { enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */ + /* codec/machine specific init - e.g. add machine controls */ + int (*init)(struct snd_soc_pcm_runtime *rtd); + + /* optional hw_params re-writing for BE and FE sync */ + int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + + /* machine stream operations */ + const struct snd_soc_ops *ops; + const struct snd_soc_compr_ops *compr_ops; + + /* For unidirectional dai links */ + bool playback_only; + bool capture_only; + + /* Mark this pcm with non atomic ops */ + bool nonatomic; + /* Keep DAI active over suspend */ unsigned int ignore_suspend:1; @@ -957,9 +975,6 @@ struct snd_soc_dai_link { unsigned int symmetric_channels:1; unsigned int symmetric_samplebits:1; - /* Mark this pcm with non atomic ops */ - bool nonatomic; - /* Do not create a PCM for this DAI link (Backend link) */ unsigned int no_pcm:1; @@ -972,21 +987,6 @@ struct snd_soc_dai_link { /* pmdown_time is ignored at stop */ unsigned int ignore_pmdown_time:1; - - /* codec/machine specific init - e.g. add machine controls */ - int (*init)(struct snd_soc_pcm_runtime *rtd); - - /* optional hw_params re-writing for BE and FE sync */ - int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params); - - /* machine stream operations */ - const struct snd_soc_ops *ops; - const struct snd_soc_compr_ops *compr_ops; - - /* For unidirectional dai links */ - bool playback_only; - bool capture_only; }; struct snd_soc_codec_conf { -- cgit v1.2.3 From 39ed68c8cd3aff417603a95d0594308598b9f469 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 22:13:22 +0200 Subject: ASoC: Add helper function getting CODEC's DAPM context The DAPM context in the snd_soc_codec struct is redundant and scheduled to be replaced by the DAPM context in the snd_soc_component struct. This patch introduces a new helper function snd_soc_codec_get_dapm() which should be used for getting the DAPM context for a CODEC rather then directly accessing the dapm field. Once there are no more direct users of the dapm field left it is possible to transparently switch all drivers to the component DAPM context by updating snd_soc_codec_get_dapm() function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index fcb312b3f258..2f742009da4b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -807,7 +807,7 @@ struct snd_soc_codec { /* component */ struct snd_soc_component component; - /* dapm */ + /* Don't access this directly, use snd_soc_codec_get_dapm() */ struct snd_soc_dapm_context dapm; #ifdef CONFIG_DEBUG_FS @@ -1269,6 +1269,18 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( return component->dapm_ptr; } +/** + * snd_soc_codec_get_dapm() - Returns the DAPM context for the CODEC + * @codec: The CODEC for which to get the DAPM context + * + * Note: Use this function instead of directly accessing the CODEC's dapm field + */ +static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm( + struct snd_soc_codec *codec) +{ + return &codec->dapm; +} + /** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol -- cgit v1.2.3 From fa880775ab0d5a8d540972f7b6800fad1af16b75 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 22:13:23 +0200 Subject: ASoC: Add helper functions bias level management Currently drivers are responsible for managing the bias_level field of their DAPM context. The DAPM state itself is managed by the DAPM core though and the core has certain expectations on how and when the bias_level field should be updated. If drivers don't adhere to these undefined behavior can occur. This patch adds a few helper functions for manipulating the DAPM context state, each function with a description on when it should be used and what its effects are. This will also help us to move more of the bias_level management from drivers to the DAPM core. For convenience also add snd_soc_codec_* wrappers around these helpers. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 34 ++++++++++++++++++++++++++++++++++ include/sound/soc.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0bc83647d3fa..70216d20e897 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -444,6 +444,9 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( struct snd_kcontrol *kcontrol); +int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); + /* dapm widget types */ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ @@ -623,4 +626,35 @@ struct snd_soc_dapm_stats { int neighbour_checks; }; +/** + * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level + * @dapm: The DAPM context to initialize + * @level: The DAPM level to initialize to + * + * This function only sets the driver internal state of the DAPM level and will + * not modify the state of the device. Hence it should not be used during normal + * operation, but only to synchronize the internal state to the device state. + * E.g. during driver probe to set the DAPM level to the one corresponding with + * the power-on reset state of the device. + * + * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). + */ +static inline void snd_soc_dapm_init_bias_level( + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) +{ + dapm->bias_level = level; +} + +/** + * snd_soc_dapm_get_bias_level() - Get current DAPM bias level + * @dapm: The context for which to get the bias level + * + * Returns: The current bias level of the passed DAPM context. + */ +static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level( + struct snd_soc_dapm_context *dapm) +{ + return dapm->bias_level; +} + #endif diff --git a/include/sound/soc.h b/include/sound/soc.h index 2f742009da4b..7781bfe85c5d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1281,6 +1281,46 @@ static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm( return &codec->dapm; } +/** + * snd_soc_dapm_init_bias_level() - Initialize CODEC DAPM bias level + * @dapm: The CODEC for which to initialize the DAPM bias level + * @level: The DAPM level to initialize to + * + * Initializes the CODEC DAPM bias level. See snd_soc_dapm_init_bias_level(). + */ +static inline void snd_soc_codec_init_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + snd_soc_dapm_init_bias_level(snd_soc_codec_get_dapm(codec), level); +} + +/** + * snd_soc_dapm_get_bias_level() - Get current CODEC DAPM bias level + * @codec: The CODEC for which to get the DAPM bias level + * + * Returns: The current DAPM bias level of the CODEC. + */ +static inline enum snd_soc_bias_level snd_soc_codec_get_bias_level( + struct snd_soc_codec *codec) +{ + return snd_soc_dapm_get_bias_level(snd_soc_codec_get_dapm(codec)); +} + +/** + * snd_soc_codec_force_bias_level() - Set the CODEC DAPM bias level + * @codec: The CODEC for which to set the level + * @level: The level to set to + * + * Forces the CODEC bias level to a specific state. See + * snd_soc_dapm_force_bias_level(). + */ +static inline int snd_soc_codec_force_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + return snd_soc_dapm_force_bias_level(snd_soc_codec_get_dapm(codec), + level); +} + /** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol -- cgit v1.2.3 From a5e7e07c264bb76d0b7c782766989c491833de05 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 29 Apr 2015 17:43:20 +0800 Subject: ALSA: hda - allow a codec to control the link power A flag "link_power_control" is added to indicate whether a codec needs to control the link power. And a new bus ops link_power() is defined for the codec to request to enable/disable the link power. Signed-off-by: Mengdong Lin Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 6a2e030c836c..b97c59eab7ab 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -74,6 +74,7 @@ struct hdac_device { /* misc flags */ atomic_t in_pm; /* suspend/resume being performed */ + bool link_power_control:1; /* sysfs */ struct hdac_widget_tree *widgets; @@ -184,6 +185,8 @@ struct hdac_bus_ops { /* get a response from the last command */ int (*get_response)(struct hdac_bus *bus, unsigned int addr, unsigned int *res); + /* control the link power */ + int (*link_power)(struct hdac_bus *bus, bool enable); }; /* @@ -311,6 +314,7 @@ static inline void snd_hdac_codec_link_down(struct hdac_device *codec) int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res); +int snd_hdac_link_power(struct hdac_device *codec, bool enable); bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); void snd_hdac_bus_stop_chip(struct hdac_bus *bus); -- cgit v1.2.3 From 632f3ab95fe2ffebf09969a57ab21be409ed7dcc Mon Sep 17 00:00:00 2001 From: "Lu, Han" Date: Tue, 5 May 2015 09:05:47 +0800 Subject: drm/i915/audio: add codec wakeup override enabled/disable callback Add support for enabling codec wakeup override signal to allow re-enumeration of the controller on SKL after resume from low power state. In SKL, HDMI/DP codec and PCH HD Audio Controller are in different power wells, so it's necessary to reset display audio codecs when power well on, otherwise display audio codecs will disappear when resume from low power state. Reset steps when power on: enable codec wakeup -> azx_init_chip() -> disable codec wakeup v3 by Jani: Simplify to only support toggling the appropriate chicken bit. v4 by Han: add explanation and specify the hw swquence. Signed-off-by: Lu, Han Signed-off-by: Jani Nikula Acked-by: Daniel Vetter Signed-off-by: Takashi Iwai --- include/drm/i915_component.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h index 3e2f22e5bf3c..c9a8b64aa33b 100644 --- a/include/drm/i915_component.h +++ b/include/drm/i915_component.h @@ -31,6 +31,7 @@ struct i915_audio_component { struct module *owner; void (*get_power)(struct device *); void (*put_power)(struct device *); + void (*codec_wake_override)(struct device *, bool enable); int (*get_cdclk_freq)(struct device *); } *ops; }; -- cgit v1.2.3 From 5967cb3d87802908fe5ab96aa0b417606bf4ca3b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 1 May 2015 12:37:23 +0100 Subject: ASoC: Correct typo in SOC_VALUE_ENUM_SINGLE macro xnitmes is clearly intended to be xnitems, but all other macros just refer to this as xitems, so change it to that. Signed-off-by: Charles Keepax Reviewed-by: Lars-Peter Clausen Tested-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 7781bfe85c5d..b257a09a98d1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -190,8 +190,8 @@ #define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) +#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \ + SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xitems, xtexts, xvalues) #define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ -- cgit v1.2.3 From 561ed680b764b288feeb74a24e1d9fb3da98ec7b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 1 May 2015 12:37:26 +0100 Subject: ASoC: dapm: Add support for autodisable mux controls Commit 57295073b6ac ("ASoC: dapm: Implement mixer input auto-disable") added support for autodisable controls, controls whose values are only written to the hardware when their respective widgets are powered up. But it only added support for controls based on the mixer abstraction. This patch add support for mux controls (DAPM controls based on the enum abstraction) to be auto-disabled as well. As each mux can only have a single control, there is no need to tie the autodisable widget to the inputs (as is done for the mixer controls) it can be tided directly to the mux widget itself. Note that it is assumed that the first entry in a autodisable mux control will always represent the off state for the mux and is what the mux will be set to whilst it is disabled. Signed-off-by: Charles Keepax Reviewed-by: Lars-Peter Clausen Tested-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index b257a09a98d1..2f2e59e1513e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -192,6 +192,10 @@ .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} #define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xitems, xtexts, xvalues) +#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \ +{ .reg = xreg, .shift_l = xshift, .shift_r = xshift, \ + .mask = xmask, .items = xitems, .texts = xtexts, \ + .values = xvalues, .autodisable = 1} #define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ @@ -312,6 +316,11 @@ ARRAY_SIZE(xtexts), xtexts, xvalues) #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) + +#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ + const struct soc_enum name = SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, \ + xshift, xmask, ARRAY_SIZE(xtexts), xtexts, xvalues) + #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) @@ -1188,6 +1197,7 @@ struct soc_enum { unsigned int mask; const char * const *texts; const unsigned int *values; + unsigned int autodisable:1; }; /** -- cgit v1.2.3 From d714f97c5b8c4c5da56b89a7289acb3f12ef7abb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 1 May 2015 18:02:43 +0200 Subject: ASoC: dapm: Add demux support A demux is conceptually similar to a mux. Where a mux has multiple input and one output and selects one of the inputs to be connected to the output, the demux has one input and multiple outputs and selects one of the outputs to which the input gets connected. This similarity makes it straight forward to support them in DAPM using the existing mux support, we only need to swap sinks and sources when initially setting up the paths. The only slightly tricky part is that there can only be one control per path. Since mixers/muxes are at the sink of a path and a demux is at the source and both types want a control it is not possible to directly connect a demux output to a mixer/mux input. The patch adds some sanity checks to make sure that this does not happen. Drivers who want to model hardware which directly connects a demux output to a mixer/mux input can do this by inserting a dummy widget between the two. E.g.: { "Dummy", "Demux Control", "Demux" }, { "Mixer", "Mixer Control", "Dummy" }, Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 70216d20e897..96c5e0ec81d1 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -107,6 +107,10 @@ struct device; { .id = snd_soc_dapm_mux, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} +#define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \ +{ .id = snd_soc_dapm_demux, .name = wname, \ + SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ + .kcontrol_news = wcontrols, .num_kcontrols = 1} /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ @@ -452,6 +456,7 @@ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ + snd_soc_dapm_demux, /* connects the input to one of multiple outputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ -- cgit v1.2.3 From ac4fc3eeb79e06499779db99937522526e863ab6 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 5 May 2015 21:42:01 +0800 Subject: ASoC: rt5645: remove unused field in pdata We can know if dmic is used by reading the value of dmic1_data_pin and dmic2_data_pin. Also IRQ must be used if codec JD or button detection function is used. So, dmic_en and en_jd_func can be remove from platform data. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- include/sound/rt5645.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 120d9610054e..652cb9e4afe5 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h @@ -15,7 +15,6 @@ struct rt5645_platform_data { /* IN2 can optionally be differential */ bool in2_diff; - bool dmic_en; unsigned int dmic1_data_pin; /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ unsigned int dmic2_data_pin; @@ -24,8 +23,6 @@ struct rt5645_platform_data { unsigned int hp_det_gpio; bool gpio_hp_det_active_high; - /* true if codec's jd function is used */ - bool en_jd_func; unsigned int jd_mode; }; -- cgit v1.2.3 From 45a110a1377d9f7afbbf53e351b72cf813ac426e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 11 May 2015 13:50:30 +0100 Subject: ASoC: dapm: Add cache to speed up adding of routes Some CODECs have a significant number of DAPM routes and for each route, when it is added to the card, the entire card widget list must be searched. When adding routes it is very likely, however, that adjacent routes will require adjacent widgets. For example all the routes for a mux are likely added in a block and the sink widget will be the same each time and it is also quite likely that the source widgets are sequential located in the widget list. This patch adds a cache to the DAPM context, this cache will hold the source and sink widgets from the last call to snd_soc_dapm_add_route for that context. A small search of the widget list will be made from those points for both the sink and source. Currently this search only checks both the last widget and the one adjacent to it. On wm8280 which has approximately 500 widgets and 30000 routes (one of the largest CODECs in mainline), the number of paths that hit the cache is 24000, which significantly improves probe time. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 96c5e0ec81d1..b9170e2bc5ab 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -593,6 +593,10 @@ struct snd_soc_dapm_update { int val; }; +struct snd_soc_dapm_wcache { + struct snd_soc_dapm_widget *widget; +}; + /* DAPM context */ struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; @@ -614,6 +618,9 @@ struct snd_soc_dapm_context { int (*set_bias_level)(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); + struct snd_soc_dapm_wcache path_sink_cache; + struct snd_soc_dapm_wcache path_source_cache; + #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_dapm; #endif -- cgit v1.2.3 From 98d8fc6c5d3652e91c61d78941e0fa6f94771d67 Mon Sep 17 00:00:00 2001