summaryrefslogtreecommitdiffstats
path: root/include/sound
diff options
context:
space:
mode:
Diffstat (limited to 'include/sound')
-rw-r--r--include/sound/control.h2
-rw-r--r--include/sound/core.h4
-rw-r--r--include/sound/emux_synth.h2
-rw-r--r--include/sound/hda_i915.h36
-rw-r--r--include/sound/hda_register.h244
-rw-r--r--include/sound/hdaudio.h309
-rw-r--r--include/sound/hdaudio_ext.h132
-rw-r--r--include/sound/info.h37
-rw-r--r--include/sound/jack.h13
-rw-r--r--include/sound/pcm.h5
-rw-r--r--include/sound/pcm_drm_eld.h6
-rw-r--r--include/sound/pcm_iec958.h9
12 files changed, 773 insertions, 26 deletions
diff --git a/include/sound/control.h b/include/sound/control.h
index 95aad6d3fd1a..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, int idx, void *private_data);
+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);
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);
diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h
index fb81f3722b6a..a0a40b74bf13 100644
--- a/include/sound/emux_synth.h
+++ b/include/sound/emux_synth.h
@@ -125,7 +125,7 @@ struct snd_emux {
struct snd_util_memhdr *memhdr; /* memory chunk information */
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_PROC_FS
struct snd_info_entry *proc;
#endif
diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h
new file mode 100644
index 000000000000..adb5ba5cbd9d
--- /dev/null
+++ b/include/sound/hda_i915.h
@@ -0,0 +1,36 @@
+/*
+ * HD-Audio helpers to sync with i915 driver
+ */
+#ifndef __SOUND_HDA_I915_H
+#define __SOUND_HDA_I915_H
+
+#ifdef CONFIG_SND_HDA_I915
+int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
+int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
+int snd_hdac_get_display_clk(struct hdac_bus *bus);
+int snd_hdac_i915_init(struct hdac_bus *bus);
+int snd_hdac_i915_exit(struct hdac_bus *bus);
+#else
+static int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
+{
+ return 0;
+}
+static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
+{
+ return 0;
+}
+static inline int snd_hdac_get_display_clk(struct hdac_bus *bus)
+{
+ return 0;
+}
+static inline int snd_hdac_i915_init(struct hdac_bus *bus)
+{
+ return -ENODEV;
+}
+static inline int snd_hdac_i915_exit(struct hdac_bus *bus)
+{
+ return 0;
+}
+#endif
+
+#endif /* __SOUND_HDA_I915_H */
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
new file mode 100644
index 000000000000..ae995e523ff8
--- /dev/null
+++ b/include/sound/hda_register.h
@@ -0,0 +1,244 @@
+/*
+ * 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_GCAP2 0x12
+#define AZX_REG_LLCH 0x14
+#define AZX_REG_OUTSTRMPAY 0x18
+#define AZX_REG_INSTRMPAY 0x1A
+#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_FIFOL 0x14
+#define AZX_REG_SD_BDLPL 0x18
+#define AZX_REG_SD_BDLPU 0x1c
+
+/* Haswell/Broadwell display HD-A controller Extended Mode registers */
+#define AZX_REG_HSW_EM4 0x100c
+#define AZX_REG_HSW_EM5 0x1010
+
+/* 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
+
+/* Capability header Structure */
+#define AZX_REG_CAP_HDR 0x0
+#define AZX_CAP_HDR_VER_OFF 28
+#define AZX_CAP_HDR_VER_MASK (0xF << AZX_CAP_HDR_VER_OFF)
+#define AZX_CAP_HDR_ID_OFF 16
+#define AZX_CAP_HDR_ID_MASK (0xFFF << AZX_CAP_HDR_ID_OFF)
+#define AZX_CAP_HDR_NXT_PTR_MASK 0xFFFF
+
+/* registers of Software Position Based FIFO Capability Structure */
+#define AZX_SPB_CAP_ID 0x4
+#define AZX_REG_SPB_BASE_ADDR 0x700
+#define AZX_REG_SPB_SPBFCH 0x00
+#define AZX_REG_SPB_SPBFCCTL 0x04
+/* Base used to calculate the iterating register offset */
+#define AZX_SPB_BASE 0x08
+/* Interval used to calculate the iterating register offset */
+#define AZX_SPB_INTERVAL 0x08
+
+/* registers of Global Time Synchronization Capability Structure */
+#define AZX_GTS_CAP_ID 0x1
+#define AZX_REG_GTS_GTSCH 0x00
+#define AZX_REG_GTS_GTSCD 0x04
+#define AZX_REG_GTS_GTSCTLAC 0x0C
+#define AZX_GTS_BASE 0x20
+#define AZX_GTS_INTERVAL 0x20
+
+/* registers for Processing Pipe Capability Structure */
+#define AZX_PP_CAP_ID 0x3
+#define AZX_REG_PP_PPCH 0x10
+#define AZX_REG_PP_PPCTL 0x04
+#define AZX_PPCTL_PIE (1<<31)
+#define AZX_PPCTL_GPROCEN (1<<30)
+/* _X_ = dma engine # and cannot * exceed 29 (per spec max 30 dma engines) */
+#define AZX_PPCTL_PROCEN(_X_) (1<<(_X_))
+
+#define AZX_REG_PP_PPSTS 0x08
+
+#define AZX_PPHC_BASE 0x10
+#define AZX_PPHC_INTERVAL 0x10
+
+#define AZX_REG_PPHCLLPL 0x0
+#define AZX_REG_PPHCLLPU 0x4
+#define AZX_REG_PPHCLDPL 0x8
+#define AZX_REG_PPHCLDPU 0xC
+
+#define AZX_PPLC_BASE 0x10
+#define AZX_PPLC_MULTI 0x10
+#define AZX_PPLC_INTERVAL 0x10
+
+#define AZX_REG_PPLCCTL 0x0
+#define AZX_PPLCCTL_STRM_BITS 4
+#define AZX_PPLCCTL_STRM_SHIFT 20
+#define AZX_REG_MASK(bit_num, offset) \
+ (((1 << (bit_num)) - 1) << (offset))
+#define AZX_PPLCCTL_STRM_MASK \
+ AZX_REG_MASK(AZX_PPLCCTL_STRM_BITS, AZX_PPLCCTL_STRM_SHIFT)
+#define AZX_PPLCCTL_RUN (1<<1)
+#define AZX_PPLCCTL_STRST (1<<0)
+
+#define AZX_REG_PPLCFMT 0x4
+#define AZX_REG_PPLCLLPL 0x8
+#define AZX_REG_PPLCLLPU 0xC
+
+/* registers for Multiple Links Capability Structure */
+#define AZX_ML_CAP_ID 0x2
+#define AZX_REG_ML_MLCH 0x00
+#define AZX_REG_ML_MLCD 0x04
+#define AZX_ML_BASE 0x40
+#define AZX_ML_INTERVAL 0x40
+
+#define AZX_REG_ML_LCAP 0x00
+#define AZX_REG_ML_LCTL 0x04
+#define AZX_REG_ML_LOSIDV 0x08
+#define AZX_REG_ML_LSDIID 0x0C
+#define AZX_REG_ML_LPSOO 0x10
+#define AZX_REG_ML_LPSIO 0x12
+#define AZX_REG_ML_LWALFC 0x18
+#define AZX_REG_ML_LOUTPAY 0x20
+#define AZX_REG_ML_LINPAY 0x30
+
+#define AZX_MLCTL_SPA (1<<16)
+#define AZX_MLCTL_CPA 23
+
+/*
+ * 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..4caf1fde8a4f 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -6,12 +6,18 @@
#define __SOUND_HDAUDIO_H
#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/timecounter.h>
+#include <sound/core.h>
+#include <sound/memalloc.h>
#include <sound/hda_verbs.h>
+#include <drm/i915_component.h>
/* codec node id */
typedef u16 hda_nid_t;
struct hdac_bus;
+struct hdac_stream;
struct hdac_device;
struct hdac_driver;
struct hdac_widget_tree;
@@ -22,6 +28,16 @@ struct hdac_widget_tree;
extern struct bus_type snd_hda_bus_type;
/*
+ * HDA device table
+ */
+struct hda_device_id {
+ __u32 vendor_id;
+ __u32 rev_id;
+ const char *name;
+ unsigned long driver_data;
+};
+
+/*
* generic arrays
*/
struct snd_array {
@@ -69,6 +85,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;
@@ -85,6 +102,7 @@ struct hdac_device {
enum {
HDA_DEV_CORE,
HDA_DEV_LEGACY,
+ HDA_DEV_ASOC,
};
/* direction */
@@ -118,6 +136,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
@@ -154,14 +181,18 @@ static inline void snd_hdac_power_down_pm(struct hdac_device *codec) {}
struct hdac_driver {
struct device_driver driver;
int type;
+ const struct hda_device_id *id_table;
int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
void (*unsol_event)(struct hdac_device *dev, unsigned int event);
};
#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
+const struct hda_device_id *
+hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv);
+
/*
- * HD-audio bus base driver
+ * Bus verb operators
*/
struct hdac_bus_ops {
/* send a single command */
@@ -169,13 +200,59 @@ 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);
+};
+
+/*
+ * 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);
+ /* 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
+#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 +266,49 @@ 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;
+
+ /* i915 component interface */
+ struct i915_audio_component *audio_component;
+ int i915_power_refcount;
};
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 +330,201 @@ 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);
+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);
+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 *));
+
+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
+ */
+#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 prepared:1;
+ bool no_period_wakeup:1;
+ bool locked: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;
+#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,
+ 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);
+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);
+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))
+
+#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
*/
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
new file mode 100644
index 000000000000..0f89df1511dc
--- /dev/null
+++ b/include/sound/hdaudio_ext.h
@@ -0,0 +1,132 @@
+#ifndef __SOUND_HDAUDIO_EXT_H
+#define __SOUND_HDAUDIO_EXT_H
+
+#include <sound/hdaudio.h>
+
+/**
+ * hdac_ext_bus: HDAC extended bus for extended HDA caps
+ *
+ * @bus: hdac bus
+ * @num_streams: streams supported
+ * @ppcap: pp capabilities pointer
+ * @spbcap: SPIB capabilities pointer
+ * @mlcap: MultiLink capabilities pointer
+ * @gtscap: gts capabilities pointer
+ * @hlink_list: link list of HDA links
+ */
+struct hdac_ext_bus {
+ struct hdac_bus bus;
+ int num_streams;
+ int idx;
+
+ void __iomem *ppcap;
+ void __iomem *spbcap;
+ void __iomem *mlcap;
+ void __iomem *gtscap;
+
+ struct list_head hlink_list;
+};
+
+int snd_hdac_ext_bus_init(struct hdac_ext_bus *sbus, struct device *dev,
+ const struct hdac_bus_ops *ops,
+ const struct hdac_io_ops *io_ops);
+
+void snd_hdac_ext_bus_exit(struct hdac_ext_bus *sbus);
+int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *sbus, int addr);
+void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev);
+
+#define ebus_to_hbus(ebus) (&(ebus)->bus)
+#define hbus_to_ebus(_bus) \
+ container_of(_bus, struct hdac_ext_bus, bus)
+
+int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *sbus);
+void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable);
+void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable);
+
+void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *chip,
+ bool enable, int index);
+
+int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *bus);
+struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *bus,
+ const char *codec_name);
+
+enum hdac_ext_stream_type {
+ HDAC_EXT_STREAM_TYPE_COUPLED = 0,
+ HDAC_EXT_STREAM_TYPE_HOST,
+ HDAC_EXT_STREAM_TYPE_LINK
+};
+
+/**
+ * hdac_ext_stream: HDAC extended stream for extended HDA caps
+ *
+ * @hstream: hdac_stream
+ * @pphc_addr: processing pipe host stream pointer
+ * @pplc_addr: processing pipe link stream pointer
+ * @decoupled: stream host and link is decoupled
+ * @link_locked: link is locked
+ * @link_prepared: link is prepared
+ * link_substream: link substream
+ */
+struct hdac_ext_stream {
+ struct hdac_stream hstream;
+
+ void __iomem *pphc_addr;
+ void __iomem *pplc_addr;
+
+ bool decoupled:1;
+ bool link_locked:1;
+ bool link_prepared;
+
+ struct snd_pcm_substream *link_substream;
+};
+
+#define hdac_stream(s) (&(s)->hstream)
+#define stream_to_hdac_ext_stream(s) \
+ container_of(s, struct hdac_ext_stream, hstream)
+
+void snd_hdac_ext_stream_init(struct hdac_ext_bus *bus,
+ struct hdac_ext_stream *stream, int idx,
+ int direction, int tag);
+int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx,
+ int num_stream, int dir);
+void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus);
+void snd_hdac_link_free_all(struct hdac_ext_bus *ebus);
+struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *bus,
+ struct snd_pcm_substream *substream,
+ int type);
+void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type);
+void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *bus,
+ struct hdac_ext_stream *azx_dev, bool decouple);
+void snd_hdac_ext_stop_streams(struct hdac_ext_bus *sbus);
+
+void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hstream);
+void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hstream);
+void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hstream);
+int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *stream, int fmt);
+
+struct hdac_ext_link {
+ struct hdac_bus *bus;
+ int index;
+ void __iomem *ml_addr; /* link output stream reg pointer */
+ u32 lcaps; /* link capablities */
+ u16 lsdiid; /* link sdi identifier */
+ struct list_head list;
+};
+
+int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link);
+int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link);
+void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
+ int stream);
+void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
+ int stream);
+
+/* update register macro */
+#define snd_hdac_updatel(addr, reg, mask, val) \
+ writel(((readl(addr + reg) & ~(mask)) | (val)), \
+ addr + reg)
+
+#define snd_hdac_updatew(addr, reg, mask, val) \
+ writew(((readw(addr + reg) & ~(mask)) | (val)), \
+ addr + reg)
+
+#endif /* __SOUND_HDAUDIO_EXT_H */
diff --git a/include/sound/info.h b/include/sound/info.h
index 9ca1a493d370..67390ee846aa 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -23,6 +23,8 @@
*/
#include <linux/poll.h>
+#include <linux/seq_file.h>
+#include <sound/core.h>
/* buffer for information */
struct snd_info_buffer {
@@ -90,16 +92,14 @@ struct snd_info_entry {
struct list_head list;
};
-#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
+#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_SND_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
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_PROC_FS
extern struct snd_info_entry *snd_seq_root;
#ifdef CONFIG_SND_OSSEMUL
@@ -110,8 +110,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);
@@ -135,8 +145,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,
@@ -175,7 +189,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
@@ -184,7 +197,7 @@ static inline int snd_info_check_reserved_words(const char *str) { return 1; }
* OSS info part
*/
-#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
+#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_SND_PROC_FS)
#define SNDRV_OSS_INFO_DEV_AUDIO 0
#define SNDRV_OSS_INFO_DEV_SYNTH 1
@@ -197,6 +210,6 @@ static inline int snd_info_check_reserved_words(const char *str) { return 1; }
int snd_oss_info_register(int dev, int num, char *string);
#define snd_oss_info_unregister(dev, num) snd_oss_info_register(dev, num, NULL)
-#endif /* CONFIG_SND_OSSEMUL && CONFIG_PROC_FS */
+#endif /* CONFIG_SND_OSSEMUL && CONFIG_SND_PROC_FS */
#endif /* __SOUND_INFO_H */
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 218235030ebc..23bede121c78 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;
@@ -85,7 +87,8 @@ 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,
int keytype);
@@ -93,9 +96,13 @@ 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)
+ struct snd_jack **jack, bool initial_kctl, bool phantom_jack)
+{
+ return 0;
+}
+
+static inline int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask)
{
return 0;
}
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 0cb7f3f5df7b..691e7ee0a510 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;
};
@@ -273,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;
};
diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
new file mode 100644
index 000000000000..93357b25d2e2
--- /dev/null
+++ b/include/sound/pcm_drm_eld.h
@@ -0,0 +1,6 @@
+#ifndef __SOUND_PCM_DRM_ELD_H
+#define __SOUND_PCM_DRM_ELD_H
+
+int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
+
+#endif
diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
new file mode 100644
index 000000000000..0eed397aca8e
--- /dev/null
+++ b/include/sound/pcm_iec958.h
@@ -0,0 +1,9 @@
+#ifndef __SOUND_PCM_IEC958_H
+#define __SOUND_PCM_IEC958_H
+
+#include <linux/types.h>
+
+int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+ size_t len);
+
+#endif