Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
f1a77547
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
f1a77547
编写于
4月 27, 2015
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-4.2' into for-next
上级
30e5f003
8ab418d3
变更
53
展开全部
隐藏空白更改
内联
并排
Showing
53 changed file
with
2882 addition
and
2564 deletion
+2882
-2564
include/sound/core.h
include/sound/core.h
+0
-4
include/sound/hda_register.h
include/sound/hda_register.h
+152
-0
include/sound/hdaudio.h
include/sound/hdaudio.h
+283
-3
include/sound/info.h
include/sound/info.h
+21
-8
include/sound/pcm.h
include/sound/pcm.h
+3
-2
sound/core/Makefile
sound/core/Makefile
+6
-2
sound/core/info.c
sound/core/info.c
+308
-471
sound/core/info_oss.c
sound/core/info_oss.c
+7
-22
sound/core/init.c
sound/core/init.c
+7
-26
sound/core/seq/Makefile
sound/core/seq/Makefile
+2
-1
sound/core/seq/seq_info.c
sound/core/seq/seq_info.c
+14
-5
sound/core/sound.c
sound/core/sound.c
+4
-20
sound/core/sound_oss.c
sound/core/sound_oss.c
+4
-26
sound/hda/Kconfig
sound/hda/Kconfig
+3
-0
sound/hda/Makefile
sound/hda/Makefile
+1
-1
sound/hda/hdac_bus.c
sound/hda/hdac_bus.c
+18
-2
sound/hda/hdac_controller.c
sound/hda/hdac_controller.c
+507
-0
sound/hda/hdac_device.c
sound/hda/hdac_device.c
+300
-0
sound/hda/hdac_stream.c
sound/hda/hdac_stream.c
+686
-0
sound/pci/ad1889.c
sound/pci/ad1889.c
+2
-2
sound/pci/ali5451/ali5451.c
sound/pci/ali5451/ali5451.c
+2
-2
sound/pci/als300.c
sound/pci/als300.c
+2
-2
sound/pci/als4000.c
sound/pci/als4000.c
+2
-2
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0.c
+2
-2
sound/pci/aw2/aw2-alsa.c
sound/pci/aw2/aw2-alsa.c
+2
-2
sound/pci/azt3328.c
sound/pci/azt3328.c
+2
-2
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_main.c
+2
-2
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio.c
+2
-2
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k1.c
+2
-2
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/cthw20k2.c
+2
-2
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1_main.c
+2
-2
sound/pci/es1938.c
sound/pci/es1938.c
+2
-2
sound/pci/es1968.c
sound/pci/es1968.c
+2
-2
sound/pci/hda/Kconfig
sound/pci/hda/Kconfig
+0
-3
sound/pci/hda/Makefile
sound/pci/hda/Makefile
+1
-2
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.c
+10
-411
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+22
-58
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.c
+270
-1060
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_controller.h
+28
-242
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+135
-107
sound/pci/hda/hda_intel.h
sound/pci/hda/hda_intel.h
+1
-0
sound/pci/hda/hda_intel_trace.h
sound/pci/hda/hda_intel_trace.h
+2
-2
sound/pci/hda/hda_tegra.c
sound/pci/hda/hda_tegra.c
+40
-36
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_ca0132.c
+2
-5
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_hdmi.c
+1
-1
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.c
+2
-2
sound/pci/lx6464es/lx6464es.c
sound/pci/lx6464es/lx6464es.c
+1
-1
sound/pci/maestro3.c
sound/pci/maestro3.c
+2
-2
sound/pci/mixart/mixart.c
sound/pci/mixart/mixart.c
+1
-1
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr.c
+1
-1
sound/pci/sis7019.c
sound/pci/sis7019.c
+5
-5
sound/pci/sonicvibes.c
sound/pci/sonicvibes.c
+2
-2
sound/pci/trident/trident_main.c
sound/pci/trident/trident_main.c
+2
-2
未找到文件。
include/sound/core.h
浏览文件 @
f1a77547
...
...
@@ -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
);
...
...
include/sound/hda_register.h
0 → 100644
浏览文件 @
f1a77547
/*
* HD-audio controller (Azalia) registers and helpers
*
* For traditional reasons, we still use azx_ prefix here
*/
#ifndef __SOUND_HDA_REGISTER_H
#define __SOUND_HDA_REGISTER_H
#include <linux/io.h>
#include <sound/hdaudio.h>
#define AZX_REG_GCAP 0x00
#define AZX_GCAP_64OK (1 << 0)
/* 64bit address support */
#define AZX_GCAP_NSDO (3 << 1)
/* # of serial data out signals */
#define AZX_GCAP_BSS (31 << 3)
/* # of bidirectional streams */
#define AZX_GCAP_ISS (15 << 8)
/* # of input streams */
#define AZX_GCAP_OSS (15 << 12)
/* # of output streams */
#define AZX_REG_VMIN 0x02
#define AZX_REG_VMAJ 0x03
#define AZX_REG_OUTPAY 0x04
#define AZX_REG_INPAY 0x06
#define AZX_REG_GCTL 0x08
#define AZX_GCTL_RESET (1 << 0)
/* controller reset */
#define AZX_GCTL_FCNTRL (1 << 1)
/* flush control */
#define AZX_GCTL_UNSOL (1 << 8)
/* accept unsol. response enable */
#define AZX_REG_WAKEEN 0x0c
#define AZX_REG_STATESTS 0x0e
#define AZX_REG_GSTS 0x10
#define AZX_GSTS_FSTS (1 << 1)
/* flush status */
#define AZX_REG_INTCTL 0x20
#define AZX_REG_INTSTS 0x24
#define AZX_REG_WALLCLK 0x30
/* 24Mhz source */
#define AZX_REG_OLD_SSYNC 0x34
/* SSYNC for old ICH */
#define AZX_REG_SSYNC 0x38
#define AZX_REG_CORBLBASE 0x40
#define AZX_REG_CORBUBASE 0x44
#define AZX_REG_CORBWP 0x48
#define AZX_REG_CORBRP 0x4a
#define AZX_CORBRP_RST (1 << 15)
/* read pointer reset */
#define AZX_REG_CORBCTL 0x4c
#define AZX_CORBCTL_RUN (1 << 1)
/* enable DMA */
#define AZX_CORBCTL_CMEIE (1 << 0)
/* enable memory error irq */
#define AZX_REG_CORBSTS 0x4d
#define AZX_CORBSTS_CMEI (1 << 0)
/* memory error indication */
#define AZX_REG_CORBSIZE 0x4e
#define AZX_REG_RIRBLBASE 0x50
#define AZX_REG_RIRBUBASE 0x54
#define AZX_REG_RIRBWP 0x58
#define AZX_RIRBWP_RST (1 << 15)
/* write pointer reset */
#define AZX_REG_RINTCNT 0x5a
#define AZX_REG_RIRBCTL 0x5c
#define AZX_RBCTL_IRQ_EN (1 << 0)
/* enable IRQ */
#define AZX_RBCTL_DMA_EN (1 << 1)
/* enable DMA */
#define AZX_RBCTL_OVERRUN_EN (1 << 2)
/* enable overrun irq */
#define AZX_REG_RIRBSTS 0x5d
#define AZX_RBSTS_IRQ (1 << 0)
/* response irq */
#define AZX_RBSTS_OVERRUN (1 << 2)
/* overrun irq */
#define AZX_REG_RIRBSIZE 0x5e
#define AZX_REG_IC 0x60
#define AZX_REG_IR 0x64
#define AZX_REG_IRS 0x68
#define AZX_IRS_VALID (1<<1)
#define AZX_IRS_BUSY (1<<0)
#define AZX_REG_DPLBASE 0x70
#define AZX_REG_DPUBASE 0x74
#define AZX_DPLBASE_ENABLE 0x1
/* Enable position buffer */
/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
enum
{
SDI0
,
SDI1
,
SDI2
,
SDI3
,
SDO0
,
SDO1
,
SDO2
,
SDO3
};
/* stream register offsets from stream base */
#define AZX_REG_SD_CTL 0x00
#define AZX_REG_SD_STS 0x03
#define AZX_REG_SD_LPIB 0x04
#define AZX_REG_SD_CBL 0x08
#define AZX_REG_SD_LVI 0x0c
#define AZX_REG_SD_FIFOW 0x0e
#define AZX_REG_SD_FIFOSIZE 0x10
#define AZX_REG_SD_FORMAT 0x12
#define AZX_REG_SD_BDLPL 0x18
#define AZX_REG_SD_BDLPU 0x1c
/* PCI space */
#define AZX_PCIREG_TCSEL 0x44
/*
* other constants
*/
/* max number of fragments - we may use more if allocating more pages for BDL */
#define BDL_SIZE 4096
#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
#define AZX_MAX_FRAG 32
/* max buffer size - no h/w limit, you can increase as you like */
#define AZX_MAX_BUF_SIZE (1024*1024*1024)
/* RIRB int mask: overrun[2], response[0] */
#define RIRB_INT_RESPONSE 0x01
#define RIRB_INT_OVERRUN 0x04
#define RIRB_INT_MASK 0x05
/* STATESTS int mask: S3,SD2,SD1,SD0 */
#define STATESTS_INT_MASK ((1 << HDA_MAX_CODECS) - 1)
/* SD_CTL bits */
#define SD_CTL_STREAM_RESET 0x01
/* stream reset bit */
#define SD_CTL_DMA_START 0x02
/* stream DMA start bit */
#define SD_CTL_STRIPE (3 << 16)
/* stripe control */
#define SD_CTL_TRAFFIC_PRIO (1 << 18)
/* traffic priority */
#define SD_CTL_DIR (1 << 19)
/* bi-directional stream */
#define SD_CTL_STREAM_TAG_MASK (0xf << 20)
#define SD_CTL_STREAM_TAG_SHIFT 20
/* SD_CTL and SD_STS */
#define SD_INT_DESC_ERR 0x10
/* descriptor error interrupt */
#define SD_INT_FIFO_ERR 0x08
/* FIFO error interrupt */
#define SD_INT_COMPLETE 0x04
/* completion interrupt */
#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\
SD_INT_COMPLETE)
/* SD_STS */
#define SD_STS_FIFO_READY 0x20
/* FIFO ready */
/* INTCTL and INTSTS */
#define AZX_INT_ALL_STREAM 0xff
/* all stream interrupts */
#define AZX_INT_CTRL_EN 0x40000000
/* controller interrupt enable bit */
#define AZX_INT_GLOBAL_EN 0x80000000
/* global interrupt enable bit */
/* below are so far hardcoded - should read registers in future */
#define AZX_MAX_CORB_ENTRIES 256
#define AZX_MAX_RIRB_ENTRIES 256
/*
* helpers to read the stream position
*/
static
inline
unsigned
int
snd_hdac_stream_get_pos_lpib
(
struct
hdac_stream
*
stream
)
{
return
snd_hdac_stream_readl
(
stream
,
SD_LPIB
);
}
static
inline
unsigned
int
snd_hdac_stream_get_pos_posbuf
(
struct
hdac_stream
*
stream
)
{
return
le32_to_cpu
(
*
stream
->
posbuf
);
}
#endif
/* __SOUND_HDA_REGISTER_H */
include/sound/hdaudio.h
浏览文件 @
f1a77547
...
...
@@ -6,12 +6,17 @@
#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>
/* codec node id */
typedef
u16
hda_nid_t
;
struct
hdac_bus
;
struct
hdac_stream
;
struct
hdac_device
;
struct
hdac_driver
;
struct
hdac_widget_tree
;
...
...
@@ -85,6 +90,7 @@ struct hdac_device {
enum
{
HDA_DEV_CORE
,
HDA_DEV_LEGACY
,
HDA_DEV_ASOC
,
};
/* direction */
...
...
@@ -118,6 +124,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
...
...
@@ -161,7 +176,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 +186,55 @@ 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
);
/* 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 +248,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 +308,200 @@ 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
*
));
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
*/
...
...
include/sound/info.h
浏览文件 @
f1a77547
...
...
@@ -23,6 +23,8 @@
*/
#include <linux/poll.h>
#include <linux/seq_file.h>
#include <sound/core.h>
/* buffer for information */
struct
snd_info_buffer
{
...
...
@@ -92,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
...
...
@@ -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
...
...
include/sound/pcm.h
浏览文件 @
f1a77547
...
...
@@ -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
;
};
...
...
sound/core/Makefile
浏览文件 @
f1a77547
...
...
@@ -3,9 +3,13 @@
# Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-y
:=
sound.o init.o memory.o info.o control.o misc.o device.o
snd-y
:=
sound.o init.o memory.o control.o misc.o device.o
ifneq
($(CONFIG_PROC_FS),)
snd-y
+=
info.o
snd-$(CONFIG_SND_OSSEMUL)
+=
info_oss.o
endif
snd-$(CONFIG_ISA_DMA_API)
+=
isadma.o
snd-$(CONFIG_SND_OSSEMUL)
+=
sound_oss.o
info_oss.o
snd-$(CONFIG_SND_OSSEMUL)
+=
sound_oss.o
snd-$(CONFIG_SND_VMASTER)
+=
vmaster.o
snd-$(CONFIG_SND_KCTL_JACK)
+=
ctljack.o
snd-$(CONFIG_SND_JACK)
+=
jack.o
...
...
sound/core/info.c
浏览文件 @
f1a77547
此差异已折叠。
点击以展开。
sound/core/info_oss.c
浏览文件 @
f1a77547
...
...
@@ -29,15 +29,12 @@
#include <linux/utsname.h>
#include <linux/mutex.h>
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
/*
* OSS compatible part
*/
static
DEFINE_MUTEX
(
strings
);
static
char
*
snd_sndstat_strings
[
SNDRV_CARDS
][
SNDRV_OSS_INFO_DEV_COUNT
];
static
struct
snd_info_entry
*
snd_sndstat_proc_entry
;
int
snd_oss_info_register
(
int
dev
,
int
num
,
char
*
string
)
{
...
...
@@ -112,27 +109,15 @@ static void snd_sndstat_proc_read(struct snd_info_entry *entry,
snd_sndstat_show_strings
(
buffer
,
"Mixers"
,
SNDRV_OSS_INFO_DEV_MIXERS
);
}
int
snd_info_minor_register
(
void
)
int
__init
snd_info_minor_register
(
void
)
{
struct
snd_info_entry
*
entry
;
memset
(
snd_sndstat_strings
,
0
,
sizeof
(
snd_sndstat_strings
));
if
((
entry
=
snd_info_create_module_entry
(
THIS_MODULE
,
"sndstat"
,
snd_oss_root
))
!=
NULL
)
{
entry
->
c
.
text
.
read
=
snd_sndstat_proc_read
;
if
(
snd_info_register
(
entry
)
<
0
)
{
snd_info_free_entry
(
entry
);
entry
=
NULL
;
}
}
snd_sndstat_proc_entry
=
entry
;
return
0
;
entry
=
snd_info_create_module_entry
(
THIS_MODULE
,
"sndstat"
,
snd_oss_root
);
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
c
.
text
.
read
=
snd_sndstat_proc_read
;
return
snd_info_register
(
entry
);
/* freed in error path */
}
int
snd_info_minor_unregister
(
void
)
{
snd_info_free_entry
(
snd_sndstat_proc_entry
);
snd_sndstat_proc_entry
=
NULL
;
return
0
;
}
#endif
/* CONFIG_SND_OSSEMUL */
sound/core/init.c
浏览文件 @
f1a77547
...
...
@@ -783,8 +783,6 @@ int snd_card_register(struct snd_card *card)
EXPORT_SYMBOL
(
snd_card_register
);
#ifdef CONFIG_PROC_FS
static
struct
snd_info_entry
*
snd_card_info_entry
;
static
void
snd_card_info_read
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
...
...
@@ -810,7 +808,6 @@ static void snd_card_info_read(struct snd_info_entry *entry,
}
#ifdef CONFIG_SND_OSSEMUL
void
snd_card_info_read_oss
(
struct
snd_info_buffer
*
buffer
)
{
int
idx
,
count
;
...
...
@@ -832,7 +829,6 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer)
#endif
#ifdef MODULE
static
struct
snd_info_entry
*
snd_card_module_info_entry
;
static
void
snd_card_module_info_read
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
...
...
@@ -857,35 +853,20 @@ int __init snd_card_info_init(void)
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
c
.
text
.
read
=
snd_card_info_read
;
if
(
snd_info_register
(
entry
)
<
0
)
{
snd_info_free_entry
(
entry
);
return
-
ENOMEM
;
}
snd_card_info_entry
=
entry
;
if
(
snd_info_register
(
entry
)
<
0
)
return
-
ENOMEM
;
/* freed in error path */
#ifdef MODULE
entry
=
snd_info_create_module_entry
(
THIS_MODULE
,
"modules"
,
NULL
);
if
(
entry
)
{
entry
->
c
.
text
.
read
=
snd_card_module_info_read
;
if
(
snd_info_register
(
entry
)
<
0
)
snd_info_free_entry
(
entry
);
else
snd_card_module_info_entry
=
entry
;
}
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
c
.
text
.
read
=
snd_card_module_info_read
;
if
(
snd_info_register
(
entry
)
<
0
)
return
-
ENOMEM
;
/* freed in error path */
#endif
return
0
;
}
int
__exit
snd_card_info_done
(
void
)
{
snd_info_free_entry
(
snd_card_info_entry
);
#ifdef MODULE
snd_info_free_entry
(
snd_card_module_info_entry
);
#endif
return
0
;
}
#endif
/* CONFIG_PROC_FS */
/**
...
...
sound/core/seq/Makefile
浏览文件 @
f1a77547
...
...
@@ -6,7 +6,8 @@
snd-seq-device-objs
:=
seq_device.o
snd-seq-objs
:=
seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o
\
seq_fifo.o seq_prioq.o seq_timer.o
\
seq_system.o seq_ports.o seq_info.o
seq_system.o seq_ports.o
snd-seq-$(CONFIG_PROC_FS)
+=
seq_info.o
snd-seq-midi-objs
:=
seq_midi.o
snd-seq-midi-emul-objs
:=
seq_midi_emul.o
snd-seq-midi-event-objs
:=
seq_midi_event.o
...
...
sound/core/seq/seq_info.c
浏览文件 @
f1a77547
...
...
@@ -27,7 +27,6 @@
#include "seq_clientmgr.h"
#include "seq_timer.h"
#ifdef CONFIG_PROC_FS
static
struct
snd_info_entry
*
queues_entry
;
static
struct
snd_info_entry
*
clients_entry
;
static
struct
snd_info_entry
*
timer_entry
;
...
...
@@ -51,6 +50,13 @@ create_info_entry(char *name, void (*read)(struct snd_info_entry *,
return
entry
;
}
static
void
free_info_entries
(
void
)
{
snd_info_free_entry
(
queues_entry
);
snd_info_free_entry
(
clients_entry
);
snd_info_free_entry
(
timer_entry
);
}
/* create all our /proc entries */
int
__init
snd_seq_info_init
(
void
)
{
...
...
@@ -59,14 +65,17 @@ int __init snd_seq_info_init(void)
clients_entry
=
create_info_entry
(
"clients"
,
snd_seq_info_clients_read
);
timer_entry
=
create_info_entry
(
"timer"
,
snd_seq_info_timer_read
);
if
(
!
queues_entry
||
!
clients_entry
||
!
timer_entry
)
goto
error
;
return
0
;
error:
free_info_entries
();
return
-
ENOMEM
;
}
int
__exit
snd_seq_info_done
(
void
)
{
snd_info_free_entry
(
queues_entry
);
snd_info_free_entry
(
clients_entry
);
snd_info_free_entry
(
timer_entry
);
free_info_entries
();
return
0
;
}
#endif
sound/core/sound.c
浏览文件 @
f1a77547
...
...
@@ -334,9 +334,6 @@ EXPORT_SYMBOL(snd_unregister_device);
/*
* INFO PART
*/
static
struct
snd_info_entry
*
snd_minor_info_entry
;
static
const
char
*
snd_device_type_name
(
int
type
)
{
switch
(
type
)
{
...
...
@@ -389,21 +386,10 @@ int __init snd_minor_info_init(void)
struct
snd_info_entry
*
entry
;
entry
=
snd_info_create_module_entry
(
THIS_MODULE
,
"devices"
,
NULL
);
if
(
entry
)
{
entry
->
c
.
text
.
read
=
snd_minor_info_read
;
if
(
snd_info_register
(
entry
)
<
0
)
{
snd_info_free_entry
(
entry
);
entry
=
NULL
;
}
}
snd_minor_info_entry
=
entry
;
return
0
;
}
int
__exit
snd_minor_info_done
(
void
)
{
snd_info_free_entry
(
snd_minor_info_entry
);
return
0
;
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
c
.
text
.
read
=
snd_minor_info_read
;
return
snd_info_register
(
entry
);
/* freed in error path */
}
#endif
/* CONFIG_PROC_FS */
...
...
@@ -423,7 +409,6 @@ static int __init alsa_sound_init(void)
unregister_chrdev
(
major
,
"alsa"
);
return
-
ENOMEM
;
}
snd_info_minor_register
();
#ifndef MODULE
pr_info
(
"Advanced Linux Sound Architecture Driver Initialized.
\n
"
);
#endif
...
...
@@ -432,7 +417,6 @@ static int __init alsa_sound_init(void)
static
void
__exit
alsa_sound_exit
(
void
)
{
snd_info_minor_unregister
();
snd_info_done
();
unregister_chrdev
(
major
,
"alsa"
);
}
...
...
sound/core/sound_oss.c
浏览文件 @
f1a77547
...
...
@@ -19,12 +19,6 @@
*
*/
#ifdef CONFIG_SND_OSSEMUL
#if !IS_ENABLED(CONFIG_SOUND)
#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel."
#endif
#include <linux/init.h>
#include <linux/export.h>
#include <linux/slab.h>
...
...
@@ -214,9 +208,6 @@ EXPORT_SYMBOL(snd_unregister_oss_device);
*/
#ifdef CONFIG_PROC_FS
static
struct
snd_info_entry
*
snd_minor_info_oss_entry
;
static
const
char
*
snd_oss_device_type_name
(
int
type
)
{
switch
(
type
)
{
...
...
@@ -263,22 +254,9 @@ int __init snd_minor_info_oss_init(void)
struct
snd_info_entry
*
entry
;
entry
=
snd_info_create_module_entry
(
THIS_MODULE
,
"devices"
,
snd_oss_root
);
if
(
entry
)
{
entry
->
c
.
text
.
read
=
snd_minor_info_oss_read
;
if
(
snd_info_register
(
entry
)
<
0
)
{
snd_info_free_entry
(
entry
);
entry
=
NULL
;
}
}
snd_minor_info_oss_entry
=
entry
;
return
0
;
}
int
__exit
snd_minor_info_oss_done
(
void
)
{
snd_info_free_entry
(
snd_minor_info_oss_entry
);
return
0
;
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
c
.
text
.
read
=
snd_minor_info_oss_read
;
return
snd_info_register
(
entry
);
/* freed in error path */
}
#endif
/* CONFIG_PROC_FS */
#endif
/* CONFIG_SND_OSSEMUL */
sound/hda/Kconfig
浏览文件 @
f1a77547
config SND_HDA_CORE
tristate
select REGMAP
config SND_HDA_DSP_LOADER
bool
sound/hda/Makefile
浏览文件 @
f1a77547
snd-hda-core-objs
:=
hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o
\
hdac_regmap.o array.o
hdac_regmap.o
hdac_controller.o hdac_stream.o
array.o
snd-hda-core-objs
+=
trace.o
CFLAGS_trace.o
:=
-I
$(src)
...
...
sound/hda/hdac_bus.c
浏览文件 @
f1a77547
...
...
@@ -11,21 +11,36 @@
static
void
process_unsol_events
(
struct
work_struct
*
work
);
static
const
struct
hdac_bus_ops
default_ops
=
{
.
command
=
snd_hdac_bus_send_cmd
,
.
get_response
=
snd_hdac_bus_get_response
,
};
/**
* snd_hdac_bus_init - initialize a HD-audio bas bus
* @bus: the pointer to bus object
* @ops: bus verb operators
* @io_ops: lowlevel I/O operators
*
* Returns 0 if successful, or a negative error code.
*/
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
)
{
memset
(
bus
,
0
,
sizeof
(
*
bus
));
bus
->
dev
=
dev
;
bus
->
ops
=
ops
;
if
(
ops
)
bus
->
ops
=
ops
;
else
bus
->
ops
=
&
default_ops
;
bus
->
io_ops
=
io_ops
;
INIT_LIST_HEAD
(
&
bus
->
stream_list
);
INIT_LIST_HEAD
(
&
bus
->
codec_list
);
INIT_WORK
(
&
bus
->
unsol_work
,
process_unsol_events
);
spin_lock_init
(
&
bus
->
reg_lock
);
mutex_init
(
&
bus
->
cmd_mutex
);
bus
->
irq
=
-
1
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_init
);
...
...
@@ -36,6 +51,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init);
*/
void
snd_hdac_bus_exit
(
struct
hdac_bus
*
bus
)
{
WARN_ON
(
!
list_empty
(
&
bus
->
stream_list
));
WARN_ON
(
!
list_empty
(
&
bus
->
codec_list
));
cancel_work_sync
(
&
bus
->
unsol_work
);
}
...
...
sound/hda/hdac_controller.c
0 → 100644
浏览文件 @
f1a77547
/*
* HD-audio controller helpers
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <sound/core.h>
#include <sound/hdaudio.h>
#include <sound/hda_register.h>
/* clear CORB read pointer properly */
static
void
azx_clear_corbrp
(
struct
hdac_bus
*
bus
)
{
int
timeout
;
for
(
timeout
=
1000
;
timeout
>
0
;
timeout
--
)
{
if
(
snd_hdac_chip_readw
(
bus
,
CORBRP
)
&
AZX_CORBRP_RST
)
break
;
udelay
(
1
);
}
if
(
timeout
<=
0
)
dev_err
(
bus
->
dev
,
"CORB reset timeout#1, CORBRP = %d
\n
"
,
snd_hdac_chip_readw
(
bus
,
CORBRP
));
snd_hdac_chip_writew
(
bus
,
CORBRP
,
0
);
for
(
timeout
=
1000
;
timeout
>
0
;
timeout
--
)
{
if
(
snd_hdac_chip_readw
(
bus
,
CORBRP
)
==
0
)
break
;
udelay
(
1
);
}
if
(
timeout
<=
0
)
dev_err
(
bus
->
dev
,
"CORB reset timeout#2, CORBRP = %d
\n
"
,
snd_hdac_chip_readw
(
bus
,
CORBRP
));
}
/**
* snd_hdac_bus_init_cmd_io - set up CORB/RIRB buffers
* @bus: HD-audio core bus
*/
void
snd_hdac_bus_init_cmd_io
(
struct
hdac_bus
*
bus
)
{
spin_lock_irq
(
&
bus
->
reg_lock
);
/* CORB set up */
bus
->
corb
.
addr
=
bus
->
rb
.
addr
;
bus
->
corb
.
buf
=
(
__le32
*
)
bus
->
rb
.
area
;
snd_hdac_chip_writel
(
bus
,
CORBLBASE
,
(
u32
)
bus
->
corb
.
addr
);
snd_hdac_chip_writel
(
bus
,
CORBUBASE
,
upper_32_bits
(
bus
->
corb
.
addr
));
/* set the corb size to 256 entries (ULI requires explicitly) */
snd_hdac_chip_writeb
(
bus
,
CORBSIZE
,
0x02
);
/* set the corb write pointer to 0 */
snd_hdac_chip_writew
(
bus
,
CORBWP
,
0
);
/* reset the corb hw read pointer */
snd_hdac_chip_writew
(
bus
,
CORBRP
,
AZX_CORBRP_RST
);
if
(
!
bus
->
corbrp_self_clear
)
azx_clear_corbrp
(
bus
);
/* enable corb dma */
snd_hdac_chip_writeb
(
bus
,
CORBCTL
,
AZX_CORBCTL_RUN
);
/* RIRB set up */
bus
->
rirb
.
addr
=
bus
->
rb
.
addr
+
2048
;
bus
->
rirb
.
buf
=
(
__le32
*
)(
bus
->
rb
.
area
+
2048
);
bus
->
rirb
.
wp
=
bus
->
rirb
.
rp
=
0
;
memset
(
bus
->
rirb
.
cmds
,
0
,
sizeof
(
bus
->
rirb
.
cmds
));
snd_hdac_chip_writel
(
bus
,
RIRBLBASE
,
(
u32
)
bus
->
rirb
.
addr
);
snd_hdac_chip_writel
(
bus
,
RIRBUBASE
,
upper_32_bits
(
bus
->
rirb
.
addr
));
/* set the rirb size to 256 entries (ULI requires explicitly) */
snd_hdac_chip_writeb
(
bus
,
RIRBSIZE
,
0x02
);
/* reset the rirb hw write pointer */
snd_hdac_chip_writew
(
bus
,
RIRBWP
,
AZX_RIRBWP_RST
);
/* set N=1, get RIRB response interrupt for new entry */
snd_hdac_chip_writew
(
bus
,
RINTCNT
,
1
);
/* enable rirb dma and response irq */
snd_hdac_chip_writeb
(
bus
,
RIRBCTL
,
AZX_RBCTL_DMA_EN
|
AZX_RBCTL_IRQ_EN
);
spin_unlock_irq
(
&
bus
->
reg_lock
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_init_cmd_io
);
/**
* snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers
* @bus: HD-audio core bus
*/
void
snd_hdac_bus_stop_cmd_io
(
struct
hdac_bus
*
bus
)
{
spin_lock_irq
(
&
bus
->
reg_lock
);
/* disable ringbuffer DMAs */
snd_hdac_chip_writeb
(
bus
,
RIRBCTL
,
0
);
snd_hdac_chip_writeb
(
bus
,
CORBCTL
,
0
);
/* disable unsolicited responses */
snd_hdac_chip_updatel
(
bus
,
GCTL
,
AZX_GCTL_UNSOL
,
0
);
spin_unlock_irq
(
&
bus
->
reg_lock
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_stop_cmd_io
);
static
unsigned
int
azx_command_addr
(
u32
cmd
)
{
unsigned
int
addr
=
cmd
>>
28
;
if
(
snd_BUG_ON
(
addr
>=
HDA_MAX_CODECS
))
addr
=
0
;
return
addr
;
}
/**
* snd_hdac_bus_send_cmd - send a command verb via CORB
* @bus: HD-audio core bus
* @val: encoded verb value to send
*
* Returns zero for success or a negative error code.
*/
int
snd_hdac_bus_send_cmd
(
struct
hdac_bus
*
bus
,
unsigned
int
val
)
{
unsigned
int
addr
=
azx_command_addr
(
val
);
unsigned
int
wp
,
rp
;
spin_lock_irq
(
&
bus
->
reg_lock
);
bus
->
last_cmd
[
azx_command_addr
(
val
)]
=
val
;
/* add command to corb */
wp
=
snd_hdac_chip_readw
(
bus
,
CORBWP
);
if
(
wp
==
0xffff
)
{
/* something wrong, controller likely turned to D3 */
spin_unlock_irq
(
&
bus
->
reg_lock
);
return
-
EIO
;
}
wp
++
;
wp
%=
AZX_MAX_CORB_ENTRIES
;
rp
=
snd_hdac_chip_readw
(
bus
,
CORBRP
);
if
(
wp
==
rp
)
{
/* oops, it's full */
spin_unlock_irq
(
&
bus
->
reg_lock
);
return
-
EAGAIN
;
}
bus
->
rirb
.
cmds
[
addr
]
++
;
bus
->
corb
.
buf
[
wp
]
=
cpu_to_le32
(
val
);
snd_hdac_chip_writew
(
bus
,
CORBWP
,
wp
);
spin_unlock_irq
(
&
bus
->
reg_lock
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_send_cmd
);
#define AZX_RIRB_EX_UNSOL_EV (1<<4)
/**
* snd_hdac_bus_update_rirb - retrieve RIRB entries
* @bus: HD-audio core bus
*
* Usually called from interrupt handler.
*/
void
snd_hdac_bus_update_rirb
(
struct
hdac_bus
*
bus
)
{
unsigned
int
rp
,
wp
;
unsigned
int
addr
;
u32
res
,
res_ex
;
wp
=
snd_hdac_chip_readw
(
bus
,
RIRBWP
);
if
(
wp
==
0xffff
)
{
/* something wrong, controller likely turned to D3 */
return
;
}
if
(
wp
==
bus
->
rirb
.
wp
)
return
;
bus
->
rirb
.
wp
=
wp
;
while
(
bus
->
rirb
.
rp
!=
wp
)
{
bus
->
rirb
.
rp
++
;
bus
->
rirb
.
rp
%=
AZX_MAX_RIRB_ENTRIES
;
rp
=
bus
->
rirb
.
rp
<<
1
;
/* an RIRB entry is 8-bytes */
res_ex
=
le32_to_cpu
(
bus
->
rirb
.
buf
[
rp
+
1
]);
res
=
le32_to_cpu
(
bus
->
rirb
.
buf
[
rp
]);
addr
=
res_ex
&
0xf
;
if
(
addr
>=
HDA_MAX_CODECS
)
{
dev_err
(
bus
->
dev
,
"spurious response %#x:%#x, rp = %d, wp = %d"
,
res
,
res_ex
,
bus
->
rirb
.
rp
,
wp
);
snd_BUG
();
}
else
if
(
res_ex
&
AZX_RIRB_EX_UNSOL_EV
)
snd_hdac_bus_queue_event
(
bus
,
res
,
res_ex
);
else
if
(
bus
->
rirb
.
cmds
[
addr
])
{
bus
->
rirb
.
res
[
addr
]
=
res
;
bus
->
rirb
.
cmds
[
addr
]
--
;
}
else
{
dev_err_ratelimited
(
bus
->
dev
,
"spurious response %#x:%#x, last cmd=%#08x
\n
"
,
res
,
res_ex
,
bus
->
last_cmd
[
addr
]);
}
}
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_update_rirb
);
/**
* snd_hdac_bus_get_response - receive a response via RIRB
* @bus: HD-audio core bus
* @addr: codec address
* @res: pointer to store the value, NULL when not needed
*
* Returns zero if a value is read, or a negative error code.
*/
int
snd_hdac_bus_get_response
(
struct
hdac_bus
*
bus
,
unsigned
int
addr
,
unsigned
int
*
res
)
{
unsigned
long
timeout
;
unsigned
long
loopcounter
;
timeout
=
jiffies
+
msecs_to_jiffies
(
1000
);
for
(
loopcounter
=
0
;;
loopcounter
++
)
{
spin_lock_irq
(
&
bus
->
reg_lock
);
if
(
!
bus
->
rirb
.
cmds
[
addr
])
{
if
(
res
)
*
res
=
bus
->
rirb
.
res
[
addr
];
/* the last value */
spin_unlock_irq
(
&
bus
->
reg_lock
);
return
0
;
}
spin_unlock_irq
(
&
bus
->
reg_lock
);
if
(
time_after
(
jiffies
,
timeout
))
break
;
if
(
loopcounter
>
3000
)
msleep
(
2
);
/* temporary workaround */
else
{
udelay
(
10
);
cond_resched
();
}
}
return
-
EIO
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_get_response
);
/*
* Lowlevel interface
*/
/**
* snd_hdac_bus_enter_link_reset - enter link reset
* @bus: HD-audio core bus
*
* Enter to the link reset state.
*/
void
snd_hdac_bus_enter_link_reset
(
struct
hdac_bus
*
bus
)
{
unsigned
long
timeout
;
/* reset controller */
snd_hdac_chip_updatel
(
bus
,
GCTL
,
AZX_GCTL_RESET
,
0
);
timeout
=
jiffies
+
msecs_to_jiffies
(
100
);
while
((
snd_hdac_chip_readb
(
bus
,
GCTL
)
&
AZX_GCTL_RESET
)
&&
time_before
(
jiffies
,
timeout
))
usleep_range
(
500
,
1000
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_enter_link_reset
);
/**
* snd_hdac_bus_exit_link_reset - exit link reset
* @bus: HD-audio core bus
*
* Exit from the link reset state.
*/
void
snd_hdac_bus_exit_link_reset
(
struct
hdac_bus
*
bus
)
{
unsigned
long
timeout
;
snd_hdac_chip_updateb
(
bus
,
GCTL
,
0
,
AZX_GCTL_RESET
);
timeout
=
jiffies
+
msecs_to_jiffies
(
100
);
while
(
!
snd_hdac_chip_readb
(
bus
,
GCTL
)
&&
time_before
(
jiffies
,
timeout
))
usleep_range
(
500
,
1000
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_exit_link_reset
);
/* reset codec link */
static
int
azx_reset
(
struct
hdac_bus
*
bus
,
bool
full_reset
)
{
if
(
!
full_reset
)
goto
skip_reset
;
/* clear STATESTS */
snd_hdac_chip_writew
(
bus
,
STATESTS
,
STATESTS_INT_MASK
);
/* reset controller */
snd_hdac_bus_enter_link_reset
(
bus
);
/* delay for >= 100us for codec PLL to settle per spec
* Rev 0.9 section 5.5.1
*/
usleep_range
(
500
,
1000
);
/* Bring controller out of reset */
snd_hdac_bus_exit_link_reset
(
bus
);
/* Brent Chartrand said to wait >= 540us for codecs to initialize */
usleep_range
(
1000
,
1200
);
skip_reset:
/* check to see if controller is ready */
if
(
!
snd_hdac_chip_readb
(
bus
,
GCTL
))
{
dev_dbg
(
bus
->
dev
,
"azx_reset: controller not ready!
\n
"
);
return
-
EBUSY
;
}
/* Accept unsolicited responses */
snd_hdac_chip_updatel
(
bus
,
GCTL
,
0
,
AZX_GCTL_UNSOL
);
/* detect codecs */
if
(
!
bus
->
codec_mask
)
{
bus
->
codec_mask
=
snd_hdac_chip_readw
(
bus
,
STATESTS
);
dev_dbg
(
bus
->
dev
,
"codec_mask = 0x%lx
\n
"
,
bus
->
codec_mask
);
}
return
0
;
}
/* enable interrupts */
static
void
azx_int_enable
(
struct
hdac_bus
*
bus
)
{
/* enable controller CIE and GIE */
snd_hdac_chip_updatel
(
bus
,
INTCTL
,
0
,
AZX_INT_CTRL_EN
|
AZX_INT_GLOBAL_EN
);
}
/* disable interrupts */
static
void
azx_int_disable
(
struct
hdac_bus
*
bus
)
{
struct
hdac_stream
*
azx_dev
;
/* disable interrupts in stream descriptor */
list_for_each_entry
(
azx_dev
,
&
bus
->
stream_list
,
list
)
snd_hdac_stream_updateb
(
azx_dev
,
SD_CTL
,
SD_INT_MASK
,
0
);
/* disable SIE for all streams */
snd_hdac_chip_writeb
(
bus
,
INTCTL
,
0
);
/* disable controller CIE and GIE */
snd_hdac_chip_updatel
(
bus
,
INTCTL
,
AZX_INT_CTRL_EN
|
AZX_INT_GLOBAL_EN
,
0
);
}
/* clear interrupts */
static
void
azx_int_clear
(
struct
hdac_bus
*
bus
)
{
struct
hdac_stream
*
azx_dev
;
/* clear stream status */
list_for_each_entry
(
azx_dev
,
&
bus
->
stream_list
,
list
)
snd_hdac_stream_writeb
(
azx_dev
,
SD_STS
,
SD_INT_MASK
);
/* clear STATESTS */
snd_hdac_chip_writew
(
bus
,
STATESTS
,
STATESTS_INT_MASK
);
/* clear rirb status */
snd_hdac_chip_writeb
(
bus
,
RIRBSTS
,
RIRB_INT_MASK
);
/* clear int status */
snd_hdac_chip_writel
(
bus
,
INTSTS
,
AZX_INT_CTRL_EN
|
AZX_INT_ALL_STREAM
);
}
/**
* snd_hdac_bus_init_chip - reset and start the controller registers
* @bus: HD-audio core bus
* @full_reset: Do full reset
*/
bool
snd_hdac_bus_init_chip
(
struct
hdac_bus
*
bus
,
bool
full_reset
)
{
if
(
bus
->
chip_init
)
return
false
;
/* reset controller */
azx_reset
(
bus
,
full_reset
);
/* initialize interrupts */
azx_int_clear
(
bus
);
azx_int_enable
(
bus
);
/* initialize the codec command I/O */
snd_hdac_bus_init_cmd_io
(
bus
);
/* program the position buffer */
if
(
bus
->
use_posbuf
&&
bus
->
posbuf
.
addr
)
{
snd_hdac_chip_writel
(
bus
,
DPLBASE
,
(
u32
)
bus
->
posbuf
.
addr
);
snd_hdac_chip_writel
(
bus
,
DPUBASE
,
upper_32_bits
(
bus
->
posbuf
.
addr
));
}
bus
->
chip_init
=
true
;
return
true
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_init_chip
);
/**
* snd_hdac_bus_stop_chip - disable the whole IRQ and I/Os
* @bus: HD-audio core bus
*/
void
snd_hdac_bus_stop_chip
(
struct
hdac_bus
*
bus
)
{
if
(
!
bus
->
chip_init
)
return
;
/* disable interrupts */
azx_int_disable
(
bus
);
azx_int_clear
(
bus
);
/* disable CORB/RIRB */
snd_hdac_bus_stop_cmd_io
(
bus
);
/* disable position buffer */
if
(
bus
->
posbuf
.
addr
)
{
snd_hdac_chip_writel
(
bus
,
DPLBASE
,
0
);
snd_hdac_chip_writel
(
bus
,
DPUBASE
,
0
);
}
bus
->
chip_init
=
false
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_stop_chip
);
/**
* snd_hdac_bus_handle_stream_irq - interrupt handler for streams
* @bus: HD-audio core bus
* @status: INTSTS register value
* @ask: callback to be called for woken streams
*/
void
snd_hdac_bus_handle_stream_irq
(
struct
hdac_bus
*
bus
,
unsigned
int
status
,
void
(
*
ack
)(
struct
hdac_bus
*
,
struct
hdac_stream
*
))
{
struct
hdac_stream
*
azx_dev
;
u8
sd_status
;
list_for_each_entry
(
azx_dev
,
&
bus
->
stream_list
,
list
)
{
if
(
status
&
azx_dev
->
sd_int_sta_mask
)
{
sd_status
=
snd_hdac_stream_readb
(
azx_dev
,
SD_STS
);
snd_hdac_stream_writeb
(
azx_dev
,
SD_STS
,
SD_INT_MASK
);
if
(
!
azx_dev
->
substream
||
!
azx_dev
->
running
||
!
(
sd_status
&
SD_INT_COMPLETE
))
continue
;
if
(
ack
)
ack
(
bus
,
azx_dev
);
}
}
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_handle_stream_irq
);
/**
* snd_hdac_bus_alloc_stream_pages - allocate BDL and other buffers
* @bus: HD-audio core bus
*
* Call this after assigning the all streams.
* Returns zero for success, or a negative error code.
*/
int
snd_hdac_bus_alloc_stream_pages
(
struct
hdac_bus
*
bus
)
{
struct
hdac_stream
*
s
;
int
num_streams
=
0
;
int
err
;
list_for_each_entry
(
s
,
&
bus
->
stream_list
,
list
)
{
/* allocate memory for the BDL for each stream */
err
=
bus
->
io_ops
->
dma_alloc_pages
(
bus
,
SNDRV_DMA_TYPE_DEV
,
BDL_SIZE
,
&
s
->
bdl
);
num_streams
++
;
if
(
err
<
0
)
return
-
ENOMEM
;
}
if
(
WARN_ON
(
!
num_streams
))
return
-
EINVAL
;
/* allocate memory for the position buffer */
err
=
bus
->
io_ops
->
dma_alloc_pages
(
bus
,
SNDRV_DMA_TYPE_DEV
,
num_streams
*
8
,
&
bus
->
posbuf
);
if
(
err
<
0
)
return
-
ENOMEM
;
list_for_each_entry
(
s
,
&
bus
->
stream_list
,
list
)
s
->
posbuf
=
(
__le32
*
)(
bus
->
posbuf
.
area
+
s
->
index
*
8
);
/* single page (at least 4096 bytes) must suffice for both ringbuffes */
return
bus
->
io_ops
->
dma_alloc_pages
(
bus
,
SNDRV_DMA_TYPE_DEV
,
PAGE_SIZE
,
&
bus
->
rb
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_alloc_stream_pages
);
/**
* snd_hdac_bus_free_stream_pages - release BDL and other buffers
* @bus: HD-audio core bus
*/
void
snd_hdac_bus_free_stream_pages
(
struct
hdac_bus
*
bus
)
{
struct
hdac_stream
*
s
;
list_for_each_entry
(
s
,
&
bus
->
stream_list
,
list
)
{
if
(
s
->
bdl
.
area
)
bus
->
io_ops
->
dma_free_pages
(
bus
,
&
s
->
bdl
);
}
if
(
bus
->
rb
.
area
)
bus
->
io_ops
->
dma_free_pages
(
bus
,
&
bus
->
rb
);
if
(
bus
->
posbuf
.
area
)
bus
->
io_ops
->
dma_free_pages
(
bus
,
&
bus
->
posbuf
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_bus_free_stream_pages
);
sound/hda/hdac_device.c
浏览文件 @
f1a77547
...
...
@@ -10,6 +10,7 @@
#include <linux/pm_runtime.h>
#include <sound/hdaudio.h>
#include <sound/hda_regmap.h>
#include <sound/pcm.h>
#include "local.h"
static
void
setup_fg_nodes
(
struct
hdac_device
*
codec
);
...
...
@@ -597,3 +598,302 @@ static int get_codec_vendor_name(struct hdac_device *codec)
codec
->
vendor_name
=
kasprintf
(
GFP_KERNEL
,
"Generic %04x"
,
vendor_id
);
return
codec
->
vendor_name
?
0
:
-
ENOMEM
;
}
/*
* stream formats
*/
struct
hda_rate_tbl
{
unsigned
int
hz
;
unsigned
int
alsa_bits
;
unsigned
int
hda_fmt
;
};
/* rate = base * mult / div */
#define HDA_RATE(base, mult, div) \
(AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
(((div) - 1) << AC_FMT_DIV_SHIFT))
static
struct
hda_rate_tbl
rate_bits
[]
=
{
/* rate in Hz, ALSA rate bitmask, HDA format value */
/* autodetected value used in snd_hda_query_supported_pcm */
{
8000
,
SNDRV_PCM_RATE_8000
,
HDA_RATE
(
48
,
1
,
6
)
},
{
11025
,
SNDRV_PCM_RATE_11025
,
HDA_RATE
(
44
,
1
,
4
)
},
{
16000
,
SNDRV_PCM_RATE_16000
,
HDA_RATE
(
48
,
1
,
3
)
},
{
22050
,
SNDRV_PCM_RATE_22050
,
HDA_RATE
(
44
,
1
,
2
)
},
{
32000
,
SNDRV_PCM_RATE_32000
,
HDA_RATE
(
48
,
2
,
3
)
},
{
44100
,
SNDRV_PCM_RATE_44100
,
HDA_RATE
(
44
,
1
,
1
)
},
{
48000
,
SNDRV_PCM_RATE_48000
,
HDA_RATE
(
48
,
1
,
1
)
},
{
88200
,
SNDRV_PCM_RATE_88200
,
HDA_RATE
(
44
,
2
,
1
)
},
{
96000
,
SNDRV_PCM_RATE_96000
,
HDA_RATE
(
48
,
2
,
1
)
},
{
176400
,
SNDRV_PCM_RATE_176400
,
HDA_RATE
(
44
,
4
,
1
)
},
{
192000
,
SNDRV_PCM_RATE_192000
,
HDA_RATE
(
48
,
4
,
1
)
},
#define AC_PAR_PCM_RATE_BITS 11
/* up to bits 10, 384kHZ isn't supported properly */
/* not autodetected value */
{
9600
,
SNDRV_PCM_RATE_KNOT
,
HDA_RATE
(
48
,
1
,
5
)
},
{
0
}
/* terminator */
};
/**
* snd_hdac_calc_stream_format - calculate the format bitset
* @rate: the sample rate
* @channels: the number of channels
* @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
* @maxbps: the max. bps
* @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant)
*
* Calculate the format bitset from the given rate, channels and th PCM format.
*
* Return zero if invalid.
*/
unsigned
int
snd_hdac_calc_stream_format
(
unsigned
int
rate
,
unsigned
int
channels
,
unsigned
int
format
,
unsigned
int
maxbps
,
unsigned
short
spdif_ctls
)
{
int
i
;
unsigned
int
val
=
0
;
for
(
i
=
0
;
rate_bits
[
i
].
hz
;
i
++
)
if
(
rate_bits
[
i
].
hz
==
rate
)
{
val
=
rate_bits
[
i
].
hda_fmt
;
break
;
}
if
(
!
rate_bits
[
i
].
hz
)
return
0
;
if
(
channels
==
0
||
channels
>
8
)
return
0
;
val
|=
channels
-
1
;
switch
(
snd_pcm_format_width
(
format
))
{
case
8
:
val
|=
AC_FMT_BITS_8
;
break
;
case
16
:
val
|=
AC_FMT_BITS_16
;
break
;
case
20
:
case
24
:
case
32
:
if
(
maxbps
>=
32
||
format
==
SNDRV_PCM_FORMAT_FLOAT_LE
)
val
|=
AC_FMT_BITS_32
;
else
if
(
maxbps
>=
24
)
val
|=
AC_FMT_BITS_24
;
else
val
|=
AC_FMT_BITS_20
;
break
;
default:
return
0
;
}
if
(
spdif_ctls
&
AC_DIG1_NONAUDIO
)
val
|=
AC_FMT_TYPE_NON_PCM
;
return
val
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_calc_stream_format
);
static
unsigned
int
query_pcm_param
(
struct
hdac_device
*
codec
,
hda_nid_t
nid
)
{
unsigned
int
val
=
0
;
if
(
nid
!=
codec
->
afg
&&
(
get_wcaps
(
codec
,
nid
)
&
AC_WCAP_FORMAT_OVRD
))
val
=
snd_hdac_read_parm
(
codec
,
nid
,
AC_PAR_PCM
);
if
(
!
val
||
val
==
-
1
)
val
=
snd_hdac_read_parm
(
codec
,
codec
->
afg
,
AC_PAR_PCM
);
if
(
!
val
||
val
==
-
1
)
return
0
;
return
val
;
}
static
unsigned
int
query_stream_param
(
struct
hdac_device
*
codec
,
hda_nid_t
nid
)
{
unsigned
int
streams
=
snd_hdac_read_parm
(
codec
,
nid
,
AC_PAR_STREAM
);
if
(
!
streams
||
streams
==
-
1
)
streams
=
snd_hdac_read_parm
(
codec
,
codec
->
afg
,
AC_PAR_STREAM
);
if
(
!
streams
||
streams
==
-
1
)
return
0
;
return
streams
;
}
/**
* snd_hdac_query_supported_pcm - query the supported PCM rates and formats
* @codec: the codec object
* @nid: NID to query
* @ratesp: the pointer to store the detected rate bitflags
* @formatsp: the pointer to store the detected formats
* @bpsp: the pointer to store the detected format widths
*
* Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
* or @bsps argument is ignored.
*
* Returns 0 if successful, otherwise a negative error code.
*/
int
snd_hdac_query_supported_pcm
(
struct
hdac_device
*
codec
,
hda_nid_t
nid
,
u32
*
ratesp
,
u64
*
formatsp
,
unsigned
int
*
bpsp
)
{
unsigned
int
i
,
val
,
wcaps
;
wcaps
=
get_wcaps
(
codec
,
nid
);
val
=
query_pcm_param
(
codec
,
nid
);
if
(
ratesp
)
{
u32
rates
=
0
;
for
(
i
=
0
;
i
<
AC_PAR_PCM_RATE_BITS
;
i
++
)
{
if
(
val
&
(
1
<<
i
))
rates
|=
rate_bits
[
i
].
alsa_bits
;
}
if
(
rates
==
0
)
{
dev_err
(
&
codec
->
dev
,
"rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)
\n
"
,
nid
,
val
,
(
wcaps
&
AC_WCAP_FORMAT_OVRD
)
?
1
:
0
);
return
-
EIO
;
}
*
ratesp
=
rates
;
}
if
(
formatsp
||
bpsp
)
{
u64
formats
=
0
;
unsigned
int
streams
,
bps
;
streams
=
query_stream_param
(
codec
,
nid
);
if
(
!
streams
)
return
-
EIO
;
bps
=
0
;
if
(
streams
&
AC_SUPFMT_PCM
)
{
if
(
val
&
AC_SUPPCM_BITS_8
)
{
formats
|=
SNDRV_PCM_FMTBIT_U8
;
bps
=
8
;
}
if
(
val
&
AC_SUPPCM_BITS_16
)
{
formats
|=
SNDRV_PCM_FMTBIT_S16_LE
;
bps
=
16
;
}
if
(
wcaps
&
AC_WCAP_DIGITAL
)
{
if
(
val
&
AC_SUPPCM_BITS_32
)
formats
|=
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
;
if
(
val
&
(
AC_SUPPCM_BITS_20
|
AC_SUPPCM_BITS_24
))
formats
|=
SNDRV_PCM_FMTBIT_S32_LE
;
if
(
val
&
AC_SUPPCM_BITS_24
)
bps
=
24
;
else
if
(
val
&
AC_SUPPCM_BITS_20
)
bps
=
20
;
}
else
if
(
val
&
(
AC_SUPPCM_BITS_20
|
AC_SUPPCM_BITS_24
|
AC_SUPPCM_BITS_32
))
{
formats
|=
SNDRV_PCM_FMTBIT_S32_LE
;
if
(
val
&
AC_SUPPCM_BITS_32
)
bps
=
32
;
else
if
(
val
&
AC_SUPPCM_BITS_24
)
bps
=
24
;
else
if
(
val
&
AC_SUPPCM_BITS_20
)
bps
=
20
;
}
}
#if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
if (streams & AC_SUPFMT_FLOAT32) {
formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
if (!bps)
bps = 32;
}
#endif
if
(
streams
==
AC_SUPFMT_AC3
)
{
/* should be exclusive */
/* temporary hack: we have still no proper support
* for the direct AC3 stream...
*/
formats
|=
SNDRV_PCM_FMTBIT_U8
;
bps
=
8
;
}
if
(
formats
==
0
)
{
dev_err
(
&
codec
->
dev
,
"formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)
\n
"
,
nid
,
val
,
(
wcaps
&
AC_WCAP_FORMAT_OVRD
)
?
1
:
0
,
streams
);
return
-
EIO
;
}
if
(
formatsp
)
*
formatsp
=
formats
;
if
(
bpsp
)
*
bpsp
=
bps
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_query_supported_pcm
);
/**
* snd_hdac_is_supported_format - Check the validity of the format
* @codec: the codec object
* @nid: NID to check
* @format: the HD-audio format value to check
*
* Check whether the given node supports the format value.
*
* Returns true if supported, false if not.
*/
bool
snd_hdac_is_supported_format
(
struct
hdac_device
*
codec
,
hda_nid_t
nid
,
unsigned
int
format
)
{
int
i
;
unsigned
int
val
=
0
,
rate
,
stream
;
val
=
query_pcm_param
(
codec
,
nid
);
if
(
!
val
)
return
false
;
rate
=
format
&
0xff00
;
for
(
i
=
0
;
i
<
AC_PAR_PCM_RATE_BITS
;
i
++
)
if
(
rate_bits
[
i
].
hda_fmt
==
rate
)
{
if
(
val
&
(
1
<<
i
))
break
;
return
false
;
}
if
(
i
>=
AC_PAR_PCM_RATE_BITS
)
return
false
;
stream
=
query_stream_param
(
codec
,
nid
);
if
(
!
stream
)
return
false
;
if
(
stream
&
AC_SUPFMT_PCM
)
{
switch
(
format
&
0xf0
)
{
case
0x00
:
if
(
!
(
val
&
AC_SUPPCM_BITS_8
))
return
false
;
break
;
case
0x10
:
if
(
!
(
val
&
AC_SUPPCM_BITS_16
))
return
false
;
break
;
case
0x20
:
if
(
!
(
val
&
AC_SUPPCM_BITS_20
))
return
false
;
break
;
case
0x30
:
if
(
!
(
val
&
AC_SUPPCM_BITS_24
))
return
false
;
break
;
case
0x40
:
if
(
!
(
val
&
AC_SUPPCM_BITS_32
))
return
false
;
break
;
default:
return
false
;
}
}
else
{
/* FIXME: check for float32 and AC3? */
}
return
true
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_is_supported_format
);
sound/hda/hdac_stream.c
0 → 100644
浏览文件 @
f1a77547
/*
* HD-audio stream operations
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clocksource.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/hdaudio.h>
#include <sound/hda_register.h>
/**
* snd_hdac_stream_init - initialize each stream (aka device)
* @bus: HD-audio core bus
* @azx_dev: HD-audio core stream object to initialize
* @idx: stream index number
* @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE)
* @tag: the tag id to assign
*
* Assign the starting bdl address to each stream (device) and initialize.
*/
void
snd_hdac_stream_init
(
struct
hdac_bus
*
bus
,
struct
hdac_stream
*
azx_dev
,
int
idx
,
int
direction
,
int
tag
)
{
azx_dev
->
bus
=
bus
;
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev
->
sd_addr
=
bus
->
remap_addr
+
(
0x20
*
idx
+
0x80
);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
azx_dev
->
sd_int_sta_mask
=
1
<<
idx
;
azx_dev
->
index
=
idx
;
azx_dev
->
direction
=
direction
;
azx_dev
->
stream_tag
=
tag
;
snd_hdac_dsp_lock_init
(
azx_dev
);
list_add_tail
(
&
azx_dev
->
list
,
&
bus
->
stream_list
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_init
);
/**
* snd_hdac_stream_start - start a stream
* @azx_dev: HD-audio core stream to start
* @fresh_start: false = wallclock timestamp relative to period wallclock
*
* Start a stream, set start_wallclk and set the running flag.
*/
void
snd_hdac_stream_start
(
struct
hdac_stream
*
azx_dev
,
bool
fresh_start
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
azx_dev
->
start_wallclk
=
snd_hdac_chip_readl
(
bus
,
WALLCLK
);
if
(
!
fresh_start
)
azx_dev
->
start_wallclk
-=
azx_dev
->
period_wallclk
;
/* enable SIE */
snd_hdac_chip_updatel
(
bus
,
INTCTL
,
0
,
1
<<
azx_dev
->
index
);
/* set DMA start and interrupt mask */
snd_hdac_stream_updateb
(
azx_dev
,
SD_CTL
,
0
,
SD_CTL_DMA_START
|
SD_INT_MASK
);
azx_dev
->
running
=
true
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_start
);
/**
* snd_hdac_stream_clear - stop a stream DMA
* @azx_dev: HD-audio core stream to stop
*/
void
snd_hdac_stream_clear
(
struct
hdac_stream
*
azx_dev
)
{
snd_hdac_stream_updateb
(
azx_dev
,
SD_CTL
,
SD_CTL_DMA_START
|
SD_INT_MASK
,
0
);
snd_hdac_stream_writeb
(
azx_dev
,
SD_STS
,
SD_INT_MASK
);
/* to be sure */
azx_dev
->
running
=
false
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_clear
);
/**
* snd_hdac_stream_stop - stop a stream
* @azx_dev: HD-audio core stream to stop
*
* Stop a stream DMA and disable stream interrupt
*/
void
snd_hdac_stream_stop
(
struct
hdac_stream
*
azx_dev
)
{
snd_hdac_stream_clear
(
azx_dev
);
/* disable SIE */
snd_hdac_chip_updatel
(
azx_dev
->
bus
,
INTCTL
,
1
<<
azx_dev
->
index
,
0
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_stop
);
/**
* snd_hdac_stream_reset - reset a stream
* @azx_dev: HD-audio core stream to reset
*/
void
snd_hdac_stream_reset
(
struct
hdac_stream
*
azx_dev
)
{
unsigned
char
val
;
int
timeout
;
snd_hdac_stream_clear
(
azx_dev
);
snd_hdac_stream_updateb
(
azx_dev
,
SD_CTL
,
0
,
SD_CTL_STREAM_RESET
);
udelay
(
3
);
timeout
=
300
;
do
{
val
=
snd_hdac_stream_readb
(
azx_dev
,
SD_CTL
)
&
SD_CTL_STREAM_RESET
;
if
(
val
)
break
;
}
while
(
--
timeout
);
val
&=
~
SD_CTL_STREAM_RESET
;
snd_hdac_stream_writeb
(
azx_dev
,
SD_CTL
,
val
);
udelay
(
3
);
timeout
=
300
;
/* waiting for hardware to report that the stream is out of reset */
do
{
val
=
snd_hdac_stream_readb
(
azx_dev
,
SD_CTL
)
&
SD_CTL_STREAM_RESET
;
if
(
!
val
)
break
;
}
while
(
--
timeout
);
/* reset first position - may not be synced with hw at this time */
if
(
azx_dev
->
posbuf
)
*
azx_dev
->
posbuf
=
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_reset
);
/**
* snd_hdac_stream_setup - set up the SD for streaming
* @azx_dev: HD-audio core stream to set up
*/
int
snd_hdac_stream_setup
(
struct
hdac_stream
*
azx_dev
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
struct
snd_pcm_runtime
*
runtime
=
azx_dev
->
substream
->
runtime
;
unsigned
int
val
;
/* make sure the run bit is zero for SD */
snd_hdac_stream_clear
(
azx_dev
);
/* program the stream_tag */
val
=
snd_hdac_stream_readl
(
azx_dev
,
SD_CTL
);
val
=
(
val
&
~
SD_CTL_STREAM_TAG_MASK
)
|
(
azx_dev
->
stream_tag
<<
SD_CTL_STREAM_TAG_SHIFT
);
if
(
!
bus
->
snoop
)
val
|=
SD_CTL_TRAFFIC_PRIO
;
snd_hdac_stream_writel
(
azx_dev
,
SD_CTL
,
val
);
/* program the length of samples in cyclic buffer */
snd_hdac_stream_writel
(
azx_dev
,
SD_CBL
,
azx_dev
->
bufsize
);
/* program the stream format */
/* this value needs to be the same as the one programmed */
snd_hdac_stream_writew
(
azx_dev
,
SD_FORMAT
,
azx_dev
->
format_val
);
/* program the stream LVI (last valid index) of the BDL */
snd_hdac_stream_writew
(
azx_dev
,
SD_LVI
,
azx_dev
->
frags
-
1
);
/* program the BDL address */
/* lower BDL address */
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPL
,
(
u32
)
azx_dev
->
bdl
.
addr
);
/* upper BDL address */
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPU
,
upper_32_bits
(
azx_dev
->
bdl
.
addr
));
/* enable the position buffer */
if
(
bus
->
use_posbuf
&&
bus
->
posbuf
.
addr
)
{
if
(
!
(
snd_hdac_chip_readl
(
bus
,
DPLBASE
)
&
AZX_DPLBASE_ENABLE
))
snd_hdac_chip_writel
(
bus
,
DPLBASE
,
(
u32
)
bus
->
posbuf
.
addr
|
AZX_DPLBASE_ENABLE
);
}
/* set the interrupt enable bits in the descriptor control register */
snd_hdac_stream_updatel
(
azx_dev
,
SD_CTL
,
0
,
SD_INT_MASK
);
if
(
azx_dev
->
direction
==
SNDRV_PCM_STREAM_PLAYBACK
)
azx_dev
->
fifo_size
=
snd_hdac_stream_readw
(
azx_dev
,
SD_FIFOSIZE
)
+
1
;
else
azx_dev
->
fifo_size
=
0
;
/* when LPIB delay correction gives a small negative value,
* we ignore it; currently set the threshold statically to
* 64 frames
*/
if
(
runtime
->
period_size
>
64
)
azx_dev
->
delay_negative_threshold
=
-
frames_to_bytes
(
runtime
,
64
);
else
azx_dev
->
delay_negative_threshold
=
0
;
/* wallclk has 24Mhz clock source */
azx_dev
->
period_wallclk
=
(((
runtime
->
period_size
*
24000
)
/
runtime
->
rate
)
*
1000
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_setup
);
/**
* snd_hdac_stream_cleanup - cleanup a stream
* @azx_dev: HD-audio core stream to clean up
*/
void
snd_hdac_stream_cleanup
(
struct
hdac_stream
*
azx_dev
)
{
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPL
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPU
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_CTL
,
0
);
azx_dev
->
bufsize
=
0
;
azx_dev
->
period_bytes
=
0
;
azx_dev
->
format_val
=
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_cleanup
);
/**
* snd_hdac_stream_assign - assign a stream for the PCM
* @bus: HD-audio core bus
* @substream: PCM substream to assign
*
* Look for an unused stream for the given PCM substream, assign it
* and return the stream object. If no stream is free, returns NULL.
* The function tries to keep using the same stream object when it's used
* beforehand. Also, when bus->reverse_assign flag is set, the last free
* or matching entry is returned. This is needed for some strange codecs.
*/
struct
hdac_stream
*
snd_hdac_stream_assign
(
struct
hdac_bus
*
bus
,
struct
snd_pcm_substream
*
substream
)
{
struct
hdac_stream
*
azx_dev
;
struct
hdac_stream
*
res
=
NULL
;
/* make a non-zero unique key for the substream */
int
key
=
(
substream
->
pcm
->
device
<<
16
)
|
(
substream
->
number
<<
2
)
|
(
substream
->
stream
+
1
);
list_for_each_entry
(
azx_dev
,
&
bus
->
stream_list
,
list
)
{
if
(
azx_dev
->
direction
!=
substream
->
stream
)
continue
;
if
(
azx_dev
->
opened
)
continue
;
if
(
azx_dev
->
assigned_key
==
key
)
{
res
=
azx_dev
;
break
;
}
if
(
!
res
||
bus
->
reverse_assign
)
res
=
azx_dev
;
}
if
(
res
)
{
spin_lock_irq
(
&
bus
->
reg_lock
);
res
->
opened
=
1
;
res
->
running
=
0
;
res
->
assigned_key
=
key
;
res
->
substream
=
substream
;
spin_unlock_irq
(
&
bus
->
reg_lock
);
}
return
res
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_assign
);
/**
* snd_hdac_stream_release - release the assigned stream
* @azx_dev: HD-audio core stream to release
*
* Release the stream that has been assigned by snd_hdac_stream_assign().
*/
void
snd_hdac_stream_release
(
struct
hdac_stream
*
azx_dev
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
spin_lock_irq
(
&
bus
->
reg_lock
);
azx_dev
->
opened
=
0
;
azx_dev
->
running
=
0
;
azx_dev
->
substream
=
NULL
;
spin_unlock_irq
(
&
bus
->
reg_lock
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_release
);
/*
* set up a BDL entry
*/
static
int
setup_bdle
(
struct
hdac_bus
*
bus
,
struct
snd_dma_buffer
*
dmab
,
struct
hdac_stream
*
azx_dev
,
__le32
**
bdlp
,
int
ofs
,
int
size
,
int
with_ioc
)
{
__le32
*
bdl
=
*
bdlp
;
while
(
size
>
0
)
{
dma_addr_t
addr
;
int
chunk
;
if
(
azx_dev
->
frags
>=
AZX_MAX_BDL_ENTRIES
)
return
-
EINVAL
;
addr
=
snd_sgbuf_get_addr
(
dmab
,
ofs
);
/* program the address field of the BDL entry */
bdl
[
0
]
=
cpu_to_le32
((
u32
)
addr
);
bdl
[
1
]
=
cpu_to_le32
(
upper_32_bits
(
addr
));
/* program the size field of the BDL entry */
chunk
=
snd_sgbuf_get_chunk_size
(
dmab
,
ofs
,
size
);
/* one BDLE cannot cross 4K boundary on CTHDA chips */
if
(
bus
->
align_bdle_4k
)
{
u32
remain
=
0x1000
-
(
ofs
&
0xfff
);
if
(
chunk
>
remain
)
chunk
=
remain
;
}
bdl
[
2
]
=
cpu_to_le32
(
chunk
);
/* program the IOC to enable interrupt
* only when the whole fragment is processed
*/
size
-=
chunk
;
bdl
[
3
]
=
(
size
||
!
with_ioc
)
?
0
:
cpu_to_le32
(
0x01
);
bdl
+=
4
;
azx_dev
->
frags
++
;
ofs
+=
chunk
;
}
*
bdlp
=
bdl
;
return
ofs
;
}
/**
* snd_hdac_stream_setup_periods - set up BDL entries
* @azx_dev: HD-audio core stream to set up
*
* Set up the buffer descriptor table of the given stream based on the
* period and buffer sizes of the assigned PCM substream.
*/
int
snd_hdac_stream_setup_periods
(
struct
hdac_stream
*
azx_dev
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
struct
snd_pcm_substream
*
substream
=
azx_dev
->
substream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
__le32
*
bdl
;
int
i
,
ofs
,
periods
,
period_bytes
;
int
pos_adj
,
pos_align
;
/* reset BDL address */
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPL
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPU
,
0
);
period_bytes
=
azx_dev
->
period_bytes
;
periods
=
azx_dev
->
bufsize
/
period_bytes
;
/* program the initial BDL entries */
bdl
=
(
__le32
*
)
azx_dev
->
bdl
.
area
;
ofs
=
0
;
azx_dev
->
frags
=
0
;
pos_adj
=
bus
->
bdl_pos_adj
;
if
(
!
azx_dev
->
no_period_wakeup
&&
pos_adj
>
0
)
{
pos_align
=
pos_adj
;
pos_adj
=
(
pos_adj
*
runtime
->
rate
+
47999
)
/
48000
;
if
(
!
pos_adj
)
pos_adj
=
pos_align
;
else
pos_adj
=
((
pos_adj
+
pos_align
-
1
)
/
pos_align
)
*
pos_align
;
pos_adj
=
frames_to_bytes
(
runtime
,
pos_adj
);
if
(
pos_adj
>=
period_bytes
)
{
dev_warn
(
bus
->
dev
,
"Too big adjustment %d
\n
"
,
pos_adj
);
pos_adj
=
0
;
}
else
{
ofs
=
setup_bdle
(
bus
,
snd_pcm_get_dma_buf
(
substream
),
azx_dev
,
&
bdl
,
ofs
,
pos_adj
,
true
);
if
(
ofs
<
0
)
goto
error
;
}
}
else
pos_adj
=
0
;
for
(
i
=
0
;
i
<
periods
;
i
++
)
{
if
(
i
==
periods
-
1
&&
pos_adj
)
ofs
=
setup_bdle
(
bus
,
snd_pcm_get_dma_buf
(
substream
),
azx_dev
,
&
bdl
,
ofs
,
period_bytes
-
pos_adj
,
0
);
else
ofs
=
setup_bdle
(
bus
,
snd_pcm_get_dma_buf
(
substream
),
azx_dev
,
&
bdl
,
ofs
,
period_bytes
,
!
azx_dev
->
no_period_wakeup
);
if
(
ofs
<
0
)
goto
error
;
}
return
0
;
error:
dev_err
(
bus
->
dev
,
"Too many BDL entries: buffer=%d, period=%d
\n
"
,
azx_dev
->
bufsize
,
period_bytes
);
return
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_setup_periods
);
/* snd_hdac_stream_set_params - set stream parameters
* @azx_dev: HD-audio core stream for which parameters are to be set
* @format_val: format value parameter
*
* Setup the HD-audio core stream parameters from substream of the stream
* and passed format value
*/
int
snd_hdac_stream_set_params
(
struct
hdac_stream
*
azx_dev
,
unsigned
int
format_val
)
{
unsigned
int
bufsize
,
period_bytes
;
struct
snd_pcm_substream
*
substream
=
azx_dev
->
substream
;
struct
snd_pcm_runtime
*
runtime
;
int
err
;
if
(
!
substream
)
return
-
EINVAL
;
runtime
=
substream
->
runtime
;
bufsize
=
snd_pcm_lib_buffer_bytes
(
substream
);
period_bytes
=
snd_pcm_lib_period_bytes
(
substream
);
if
(
bufsize
!=
azx_dev
->
bufsize
||
period_bytes
!=
azx_dev
->
period_bytes
||
format_val
!=
azx_dev
->
format_val
||
runtime
->
no_period_wakeup
!=
azx_dev
->
no_period_wakeup
)
{
azx_dev
->
bufsize
=
bufsize
;
azx_dev
->
period_bytes
=
period_bytes
;
azx_dev
->
format_val
=
format_val
;
azx_dev
->
no_period_wakeup
=
runtime
->
no_period_wakeup
;
err
=
snd_hdac_stream_setup_periods
(
azx_dev
);
if
(
err
<
0
)
return
err
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_set_params
);
static
cycle_t
azx_cc_read
(
const
struct
cyclecounter
*
cc
)
{
struct
hdac_stream
*
azx_dev
=
container_of
(
cc
,
struct
hdac_stream
,
cc
);
return
snd_hdac_chip_readl
(
azx_dev
->
bus
,
WALLCLK
);
}
static
void
azx_timecounter_init
(
struct
hdac_stream
*
azx_dev
,
bool
force
,
cycle_t
last
)
{
struct
timecounter
*
tc
=
&
azx_dev
->
tc
;
struct
cyclecounter
*
cc
=
&
azx_dev
->
cc
;
u64
nsec
;
cc
->
read
=
azx_cc_read
;
cc
->
mask
=
CLOCKSOURCE_MASK
(
32
);
/*
* Converting from 24 MHz to ns means applying a 125/3 factor.
* To avoid any saturation issues in intermediate operations,
* the 125 factor is applied first. The division is applied
* last after reading the timecounter value.
* Applying the 1/3 factor as part of the multiplication
* requires at least 20 bits for a decent precision, however
* overflows occur after about 4 hours or less, not a option.
*/
cc
->
mult
=
125
;
/* saturation after 195 years */
cc
->
shift
=
0
;
nsec
=
0
;
/* audio time is elapsed time since trigger */
timecounter_init
(
tc
,
cc
,
nsec
);
if
(
force
)
{
/*
* force timecounter to use predefined value,
* used for synchronized starts
*/
tc
->
cycle_last
=
last
;
}
}
/**
* snd_hdac_stream_timecounter_init - initialize time counter
* @azx_dev: HD-audio core stream (master stream)
* @streams: bit flags of streams to set up
*
* Initializes the time counter of streams marked by the bit flags (each
* bit corresponds to the stream index).
* The trigger timestamp of PCM substream assigned to the given stream is
* updated accordingly, too.
*/
void
snd_hdac_stream_timecounter_init
(
struct
hdac_stream
*
azx_dev
,
unsigned
int
streams
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
struct
snd_pcm_runtime
*
runtime
=
azx_dev
->
substream
->
runtime
;
struct
hdac_stream
*
s
;
bool
inited
=
false
;
cycle_t
cycle_last
=
0
;
int
i
=
0
;
list_for_each_entry
(
s
,
&
bus
->
stream_list
,
list
)
{
if
(
streams
&
(
1
<<
i
))
{
azx_timecounter_init
(
s
,
inited
,
cycle_last
);
if
(
!
inited
)
{
inited
=
true
;
cycle_last
=
s
->
tc
.
cycle_last
;
}
}
i
++
;
}
snd_pcm_gettime
(
runtime
,
&
runtime
->
trigger_tstamp
);
runtime
->
trigger_tstamp_latched
=
true
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_timecounter_init
);
/**
* snd_hdac_stream_sync_trigger - turn on/off stream sync register
* @azx_dev: HD-audio core stream (master stream)
* @streams: bit flags of streams to sync
*/
void
snd_hdac_stream_sync_trigger
(
struct
hdac_stream
*
azx_dev
,
bool
set
,
unsigned
int
streams
,
unsigned
int
reg
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
unsigned
int
val
;
if
(
!
reg
)
reg
=
AZX_REG_SSYNC
;
val
=
_snd_hdac_chip_read
(
l
,
bus
,
reg
);
if
(
set
)
val
|=
streams
;
else
val
&=
~
streams
;
_snd_hdac_chip_write
(
l
,
bus
,
reg
,
val
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_sync_trigger
);
/**
* snd_hdac_stream_sync - sync with start/strop trigger operation
* @azx_dev: HD-audio core stream (master stream)
* @start: true = start, false = stop
* @streams: bit flags of streams to sync
*
* For @start = true, wait until all FIFOs get ready.
* For @start = false, wait until all RUN bits are cleared.
*/
void
snd_hdac_stream_sync
(
struct
hdac_stream
*
azx_dev
,
bool
start
,
unsigned
int
streams
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
int
i
,
nwait
,
timeout
;
struct
hdac_stream
*
s
;
for
(
timeout
=
5000
;
timeout
;
timeout
--
)
{
nwait
=
0
;
i
=
0
;
list_for_each_entry
(
s
,
&
bus
->
stream_list
,
list
)
{
if
(
streams
&
(
1
<<
i
))
{
if
(
start
)
{
/* check FIFO gets ready */
if
(
!
(
snd_hdac_stream_readb
(
s
,
SD_STS
)
&
SD_STS_FIFO_READY
))
nwait
++
;
}
else
{
/* check RUN bit is cleared */
if
(
snd_hdac_stream_readb
(
s
,
SD_CTL
)
&
SD_CTL_DMA_START
)
nwait
++
;
}
}
i
++
;
}
if
(
!
nwait
)
break
;
cpu_relax
();
}
}
EXPORT_SYMBOL_GPL
(
snd_hdac_stream_sync
);
#ifdef CONFIG_SND_HDA_DSP_LOADER
/**
* snd_hdac_dsp_prepare - prepare for DSP loading
* @azx_dev: HD-audio core stream used for DSP loading
* @format: HD-audio stream format
* @byte_size: data chunk byte size
* @bufp: allocated buffer
*
* Allocate the buffer for the given size and set up the given stream for
* DSP loading. Returns the stream tag (>= 0), or a negative error code.
*/
int
snd_hdac_dsp_prepare
(
struct
hdac_stream
*
azx_dev
,
unsigned
int
format
,
unsigned
int
byte_size
,
struct
snd_dma_buffer
*
bufp
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
u32
*
bdl
;
int
err
;
snd_hdac_dsp_lock
(
azx_dev
);
spin_lock_irq
(
&
bus
->
reg_lock
);
if
(
azx_dev
->
running
||
azx_dev
->
locked
)
{
spin_unlock_irq
(
&
bus
->
reg_lock
);
err
=
-
EBUSY
;
goto
unlock
;
}
azx_dev
->
locked
=
true
;
spin_unlock_irq
(
&
bus
->
reg_lock
);
err
=
bus
->
io_ops
->
dma_alloc_pages
(
bus
,
SNDRV_DMA_TYPE_DEV_SG
,
byte_size
,
bufp
);
if
(
err
<
0
)
goto
err_alloc
;
azx_dev
->
bufsize
=
byte_size
;
azx_dev
->
period_bytes
=
byte_size
;
azx_dev
->
format_val
=
format
;
snd_hdac_stream_reset
(
azx_dev
);
/* reset BDL address */
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPL
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPU
,
0
);
azx_dev
->
frags
=
0
;
bdl
=
(
u32
*
)
azx_dev
->
bdl
.
area
;
err
=
setup_bdle
(
bus
,
bufp
,
azx_dev
,
&
bdl
,
0
,
byte_size
,
0
);
if
(
err
<
0
)
goto
error
;
snd_hdac_stream_setup
(
azx_dev
);
snd_hdac_dsp_unlock
(
azx_dev
);
return
azx_dev
->
stream_tag
;
error:
bus
->
io_ops
->
dma_free_pages
(
bus
,
bufp
);
err_alloc:
spin_lock_irq
(
&
bus
->
reg_lock
);
azx_dev
->
locked
=
false
;
spin_unlock_irq
(
&
bus
->
reg_lock
);
unlock:
snd_hdac_dsp_unlock
(
azx_dev
);
return
err
;
}
EXPORT_SYMBOL_GPL
(
snd_hdac_dsp_prepare
);
/**
* snd_hdac_dsp_trigger - start / stop DSP loading
* @azx_dev: HD-audio core stream used for DSP loading
* @start: trigger start or stop
*/
void
snd_hdac_dsp_trigger
(
struct
hdac_stream
*
azx_dev
,
bool
start
)
{
if
(
start
)
snd_hdac_stream_start
(
azx_dev
,
true
);
else
snd_hdac_stream_stop
(
azx_dev
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_dsp_trigger
);
/**
* snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal
* @azx_dev: HD-audio core stream used for DSP loading
* @dmab: buffer used by DSP loading
*/
void
snd_hdac_dsp_cleanup
(
struct
hdac_stream
*
azx_dev
,
struct
snd_dma_buffer
*
dmab
)
{
struct
hdac_bus
*
bus
=
azx_dev
->
bus
;
if
(
!
dmab
->
area
||
!
azx_dev
->
locked
)
return
;
snd_hdac_dsp_lock
(
azx_dev
);
/* reset BDL address */
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPL
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_BDLPU
,
0
);
snd_hdac_stream_writel
(
azx_dev
,
SD_CTL
,
0
);
azx_dev
->
bufsize
=
0
;
azx_dev
->
period_bytes
=
0
;
azx_dev
->
format_val
=
0
;
bus
->
io_ops
->
dma_free_pages
(
bus
,
dmab
);
dmab
->
area
=
NULL
;
spin_lock_irq
(
&
bus
->
reg_lock
);
azx_dev
->
locked
=
false
;
spin_unlock_irq
(
&
bus
->
reg_lock
);
snd_hdac_dsp_unlock
(
azx_dev
);
}
EXPORT_SYMBOL_GPL
(
snd_hdac_dsp_cleanup
);
#endif
/* CONFIG_SND_HDA_DSP_LOADER */
sound/pci/ad1889.c
浏览文件 @
f1a77547
...
...
@@ -898,8 +898,8 @@ snd_ad1889_create(struct snd_card *card,
return
err
;
/* check PCI availability (32bit DMA) */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_err
(
card
->
dev
,
"error setting 32-bit DMA mask.
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/ali5451/ali5451.c
浏览文件 @
f1a77547
...
...
@@ -2105,8 +2105,8 @@ static int snd_ali_create(struct snd_card *card,
if
(
err
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 31 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
31
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
31
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
31
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
31
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 31bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/als300.c
浏览文件 @
f1a77547
...
...
@@ -658,8 +658,8 @@ static int snd_als300_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
)
{
dev_err
(
card
->
dev
,
"error setting 28bit DMA mask
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/als4000.c
浏览文件 @
f1a77547
...
...
@@ -871,8 +871,8 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
return
err
;
}
/* check, if we can restrict PCI DMA transfers to 24 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
)
{
dev_err
(
&
pci
->
dev
,
"architecture does not support 24bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/au88x0/au88x0.c
浏览文件 @
f1a77547
...
...
@@ -150,8 +150,8 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
// check PCI availability (DMA).
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_err
(
card
->
dev
,
"error to set DMA mask
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/aw2/aw2-alsa.c
浏览文件 @
f1a77547
...
...
@@ -258,8 +258,8 @@ static int snd_aw2_create(struct snd_card *card,
pci_set_master
(
pci
);
/* check PCI availability (32bit DMA) */
if
((
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
||
(
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
))
{
if
((
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
||
(
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
))
{
dev_err
(
card
->
dev
,
"Impossible to set 32bit mask DMA
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/azt3328.c
浏览文件 @
f1a77547
...
...
@@ -2420,8 +2420,8 @@ snd_azf3328_create(struct snd_card *card,
chip
->
irq
=
-
1
;
/* check if we can restrict PCI DMA transfers to 24 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 24bit PCI busmaster DMA
\n
"
);
...
...
sound/pci/ca0106/ca0106_main.c
浏览文件 @
f1a77547
...
...
@@ -1676,8 +1676,8 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
err
=
pci_enable_device
(
pci
);
if
(
err
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_err
(
card
->
dev
,
"error to set 32bit mask DMA
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
...
...
sound/pci/cs5535audio/cs5535audio.c
浏览文件 @
f1a77547
...
...
@@ -289,8 +289,8 @@ static int snd_cs5535audio_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_warn
(
card
->
dev
,
"unable to get 32bit dma
\n
"
);
err
=
-
ENXIO
;
goto
pcifail
;
...
...
sound/pci/ctxfi/cthw20k1.c
浏览文件 @
f1a77547
...
...
@@ -1910,8 +1910,8 @@ static int hw_card_start(struct hw *hw)
return
err
;
/* Set DMA transfer mask */
if
(
pci_set_dma_mask
(
pci
,
CT_XFI_DMA_MASK
)
<
0
||
pci_set_consistent_dma_mask
(
pci
,
CT_XFI_DMA_MASK
)
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
CT_XFI_DMA_MASK
)
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
CT_XFI_DMA_MASK
)
<
0
)
{
dev_err
(
hw
->
card
->
dev
,
"architecture does not support PCI busmaster DMA with mask 0x%llx
\n
"
,
CT_XFI_DMA_MASK
);
...
...
sound/pci/ctxfi/cthw20k2.c
浏览文件 @
f1a77547
...
...
@@ -2035,8 +2035,8 @@ static int hw_card_start(struct hw *hw)
return
err
;
/* Set DMA transfer mask */
if
(
pci_set_dma_mask
(
pci
,
CT_XFI_DMA_MASK
)
<
0
||
pci_set_consistent_dma_mask
(
pci
,
CT_XFI_DMA_MASK
)
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
CT_XFI_DMA_MASK
)
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
CT_XFI_DMA_MASK
)
<
0
)
{
dev_err
(
hw
->
card
->
dev
,
"architecture does not support PCI busmaster DMA with mask 0x%llx
\n
"
,
CT_XFI_DMA_MASK
);
...
...
sound/pci/emu10k1/emu10k1_main.c
浏览文件 @
f1a77547
...
...
@@ -1904,8 +1904,8 @@ int snd_emu10k1_create(struct snd_card *card,
/* set the DMA transfer mask */
emu
->
dma_mask
=
is_audigy
?
AUDIGY_DMA_MASK
:
EMU10K1_DMA_MASK
;
if
(
pci_set_dma_mask
(
pci
,
emu
->
dma_mask
)
<
0
||
pci_set_consistent_dma_mask
(
pci
,
emu
->
dma_mask
)
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
emu
->
dma_mask
)
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
emu
->
dma_mask
)
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support PCI busmaster DMA with mask 0x%lx
\n
"
,
emu
->
dma_mask
);
...
...
sound/pci/es1938.c
浏览文件 @
f1a77547
...
...
@@ -1580,8 +1580,8 @@ static int snd_es1938_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 24 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 24bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/es1968.c
浏览文件 @
f1a77547
...
...
@@ -2689,8 +2689,8 @@ static int snd_es1968_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 28bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/hda/Kconfig
浏览文件 @
f1a77547
...
...
@@ -38,9 +38,6 @@ config SND_HDA_TEGRA
if SND_HDA
config SND_HDA_DSP_LOADER
bool
config SND_HDA_PREALLOC_SIZE
int "Pre-allocated buffer size for HD-audio driver"
range 0 32768
...
...
sound/pci/hda/Makefile
浏览文件 @
f1a77547
snd-hda-intel-objs
:=
hda_intel.o
snd-hda-controller-objs
:=
hda_controller.o
snd-hda-tegra-objs
:=
hda_tegra.o
# for haswell power well
snd-hda-intel-$(CONFIG_SND_HDA_I915)
+=
hda_i915.o
snd-hda-codec-y
:=
hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
snd-hda-codec-y
+=
hda_controller.o
snd-hda-codec-$(CONFIG_PROC_FS)
+=
hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP)
+=
hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP)
+=
hda_beep.o
...
...
@@ -27,7 +27,6 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
# common driver
obj-$(CONFIG_SND_HDA)
:=
snd-hda-codec.o
obj-$(CONFIG_SND_HDA)
+=
snd-hda-controller.o
# codec drivers
obj-$(CONFIG_SND_HDA_GENERIC)
+=
snd-hda-codec-generic.o
...
...
sound/pci/hda/hda_codec.c
浏览文件 @
f1a77547
...
...
@@ -146,11 +146,11 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
bus
->
no_response_fallback
=
0
;
mutex_unlock
(
&
bus
->
core
.
cmd_mutex
);
snd_hda_power_down_pm
(
codec
);
if
(
!
codec_in_pm
(
codec
)
&&
res
&&
err
<
0
&&
bus
->
rirb_error
)
{
if
(
!
codec_in_pm
(
codec
)
&&
res
&&
err
==
-
EAGAIN
)
{
if
(
bus
->
response_reset
)
{
codec_dbg
(
codec
,
"resetting BUS due to fatal communication error
\n
"
);
bus
->
ops
.
bus_reset
(
bus
);
snd_hda_
bus_reset
(
bus
);
}
goto
again
;
}
...
...
@@ -436,9 +436,8 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid)
get_wcaps_type
(
wcaps
)
!=
AC_WID_PIN
)
return
0
;
parm
=
snd_hda_param_read
(
codec
,
nid
,
AC_PAR_DEVLIST_LEN
);
if
(
parm
==
-
1
&&
codec
->
bus
->
rirb_error
)
parm
=
0
;
if
(
_snd_hdac_read_parm
(
&
codec
->
core
,
nid
,
AC_PAR_DEVLIST_LEN
,
&
parm
))
return
0
;
/* error */
return
parm
&
AC_DEV_LIST_LEN_MASK
;
}
...
...
@@ -467,10 +466,9 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
devices
=
0
;
while
(
devices
<
dev_len
)
{
parm
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_DEVICE_LIST
,
devices
);
if
(
parm
==
-
1
&&
codec
->
bus
->
rirb_error
)
break
;
if
(
snd_hdac_read
(
&
codec
->
core
,
nid
,
AC_VERB_GET_DEVICE_LIST
,
devices
,
&
parm
))
break
;
/* error */
for
(
i
=
0
;
i
<
8
;
i
++
)
{
dev_list
[
devices
]
=
(
u8
)
parm
;
...
...
@@ -483,96 +481,6 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
return
devices
;
}
/*
* destructor
*/
static
void
snd_hda_bus_free
(
struct
hda_bus
*
bus
)
{
if
(
!
bus
)
return
;
if
(
bus
->
ops
.
private_free
)
bus
->
ops
.
private_free
(
bus
);
snd_hdac_bus_exit
(
&
bus
->
core
);
kfree
(
bus
);
}
static
int
snd_hda_bus_dev_free
(
struct
snd_device
*
device
)
{
snd_hda_bus_free
(
device
->
device_data
);
return
0
;
}
static
int
snd_hda_bus_dev_disconnect
(
struct
snd_device
*
device
)
{
struct
hda_bus
*
bus
=
device
->
device_data
;
bus
->
shutdown
=
1
;
return
0
;
}
/* hdac_bus_ops translations */
static
int
_hda_bus_command
(
struct
hdac_bus
*
_bus
,
unsigned
int
cmd
)
{
struct
hda_bus
*
bus
=
container_of
(
_bus
,
struct
hda_bus
,
core
);
return
bus
->
ops
.
command
(
bus
,
cmd
);
}
static
int
_hda_bus_get_response
(
struct
hdac_bus
*
_bus
,
unsigned
int
addr
,
unsigned
int
*
res
)
{
struct
hda_bus
*
bus
=
container_of
(
_bus
,
struct
hda_bus
,
core
);
*
res
=
bus
->
ops
.
get_response
(
bus
,
addr
);
return
bus
->
rirb_error
?
-
EIO
:
0
;
}
static
const
struct
hdac_bus_ops
bus_ops
=
{
.
command
=
_hda_bus_command
,
.
get_response
=
_hda_bus_get_response
,
};
/**
* snd_hda_bus_new - create a HDA bus
* @card: the card entry
* @busp: the pointer to store the created bus instance
*
* Returns 0 if successful, or a negative error code.
*/
int
snd_hda_bus_new
(
struct
snd_card
*
card
,
struct
hda_bus
**
busp
)
{
struct
hda_bus
*
bus
;
int
err
;
static
struct
snd_device_ops
dev_ops
=
{
.
dev_disconnect
=
snd_hda_bus_dev_disconnect
,
.
dev_free
=
snd_hda_bus_dev_free
,
};
if
(
busp
)
*
busp
=
NULL
;
bus
=
kzalloc
(
sizeof
(
*
bus
),
GFP_KERNEL
);
if
(
!
bus
)
return
-
ENOMEM
;
err
=
snd_hdac_bus_init
(
&
bus
->
core
,
card
->
dev
,
&
bus_ops
);
if
(
err
<
0
)
{
kfree
(
bus
);
return
err
;
}
bus
->
card
=
card
;
mutex_init
(
&
bus
->
prepare_mutex
);
err
=
snd_device_new
(
card
,
SNDRV_DEV_BUS
,
bus
,
&
dev_ops
);
if
(
err
<
0
)
{
snd_hda_bus_free
(
bus
);
return
err
;
}
if
(
busp
)
*
busp
=
bus
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_bus_new
);
/*
* read widget caps for each widget and store in cache
*/
...
...
@@ -3287,311 +3195,6 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
return
0
;
}
/*
* stream formats
*/
struct
hda_rate_tbl
{
unsigned
int
hz
;
unsigned
int
alsa_bits
;
unsigned
int
hda_fmt
;
};
/* rate = base * mult / div */
#define HDA_RATE(base, mult, div) \
(AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
(((div) - 1) << AC_FMT_DIV_SHIFT))
static
struct
hda_rate_tbl
rate_bits
[]
=
{
/* rate in Hz, ALSA rate bitmask, HDA format value */
/* autodetected value used in snd_hda_query_supported_pcm */
{
8000
,
SNDRV_PCM_RATE_8000
,
HDA_RATE
(
48
,
1
,
6
)
},
{
11025
,
SNDRV_PCM_RATE_11025
,
HDA_RATE
(
44
,
1
,
4
)
},
{
16000
,
SNDRV_PCM_RATE_16000
,
HDA_RATE
(
48
,
1
,
3
)
},
{
22050
,
SNDRV_PCM_RATE_22050
,
HDA_RATE
(
44
,
1
,
2
)
},
{
32000
,
SNDRV_PCM_RATE_32000
,
HDA_RATE
(
48
,
2
,
3
)
},
{
44100
,
SNDRV_PCM_RATE_44100
,
HDA_RATE
(
44
,
1
,
1
)
},
{
48000
,
SNDRV_PCM_RATE_48000
,
HDA_RATE
(
48
,
1
,
1
)
},
{
88200
,
SNDRV_PCM_RATE_88200
,
HDA_RATE
(
44
,
2
,
1
)
},
{
96000
,
SNDRV_PCM_RATE_96000
,
HDA_RATE
(
48
,
2
,
1
)
},
{
176400
,
SNDRV_PCM_RATE_176400
,
HDA_RATE
(
44
,
4
,
1
)
},
{
192000
,
SNDRV_PCM_RATE_192000
,
HDA_RATE
(
48
,
4
,
1
)
},
#define AC_PAR_PCM_RATE_BITS 11
/* up to bits 10, 384kHZ isn't supported properly */
/* not autodetected value */
{
9600
,
SNDRV_PCM_RATE_KNOT
,
HDA_RATE
(
48
,
1
,
5
)
},
{
0
}
/* terminator */
};
/**
* snd_hda_calc_stream_format - calculate format bitset
* @codec: HD-audio codec
* @rate: the sample rate
* @channels: the number of channels
* @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
* @maxbps: the max. bps
* @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant)
*
* Calculate the format bitset from the given rate, channels and th PCM format.
*
* Return zero if invalid.
*/
unsigned
int
snd_hda_calc_stream_format
(
struct
hda_codec
*
codec
,
unsigned
int
rate
,
unsigned
int
channels
,
unsigned
int
format
,
unsigned
int
maxbps
,
unsigned
short
spdif_ctls
)
{
int
i
;
unsigned
int
val
=
0
;
for
(
i
=
0
;
rate_bits
[
i
].
hz
;
i
++
)
if
(
rate_bits
[
i
].
hz
==
rate
)
{
val
=
rate_bits
[
i
].
hda_fmt
;
break
;
}
if
(
!
rate_bits
[
i
].
hz
)
{
codec_dbg
(
codec
,
"invalid rate %d
\n
"
,
rate
);
return
0
;
}
if
(
channels
==
0
||
channels
>
8
)
{
codec_dbg
(
codec
,
"invalid channels %d
\n
"
,
channels
);
return
0
;
}
val
|=
channels
-
1
;
switch
(
snd_pcm_format_width
(
format
))
{
case
8
:
val
|=
AC_FMT_BITS_8
;
break
;
case
16
:
val
|=
AC_FMT_BITS_16
;
break
;
case
20
:
case
24
:
case
32
:
if
(
maxbps
>=
32
||
format
==
SNDRV_PCM_FORMAT_FLOAT_LE
)
val
|=
AC_FMT_BITS_32
;
else
if
(
maxbps
>=
24
)
val
|=
AC_FMT_BITS_24
;
else
val
|=
AC_FMT_BITS_20
;
break
;
default:
codec_dbg
(
codec
,
"invalid format width %d
\n
"
,
snd_pcm_format_width
(
format
));
return
0
;
}
if
(
spdif_ctls
&
AC_DIG1_NONAUDIO
)
val
|=
AC_FMT_TYPE_NON_PCM
;
return
val
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_calc_stream_format
);
static
unsigned
int
query_pcm_param
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
unsigned
int
val
=
0
;
if
(
nid
!=
codec
->
core
.
afg
&&
(
get_wcaps
(
codec
,
nid
)
&
AC_WCAP_FORMAT_OVRD
))
val
=
snd_hda_param_read
(
codec
,
nid
,
AC_PAR_PCM
);
if
(
!
val
||
val
==
-
1
)
val
=
snd_hda_param_read
(
codec
,
codec
->
core
.
afg
,
AC_PAR_PCM
);
if
(
!
val
||
val
==
-
1
)
return
0
;
return
val
;
}
static
unsigned
int
query_stream_param
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
unsigned
int
streams
=
snd_hda_param_read
(
codec
,
nid
,
AC_PAR_STREAM
);
if
(
!
streams
||
streams
==
-
1
)
streams
=
snd_hda_param_read
(
codec
,
codec
->
core
.
afg
,
AC_PAR_STREAM
);
if
(
!
streams
||
streams
==
-
1
)
return
0
;
return
streams
;
}
/**
* snd_hda_query_supported_pcm - query the supported PCM rates and formats
* @codec: the HDA codec
* @nid: NID to query
* @ratesp: the pointer to store the detected rate bitflags
* @formatsp: the pointer to store the detected formats
* @bpsp: the pointer to store the detected format widths
*
* Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
* or @bsps argument is ignored.
*
* Returns 0 if successful, otherwise a negative error code.
*/
int
snd_hda_query_supported_pcm
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
u32
*
ratesp
,
u64
*
formatsp
,
unsigned
int
*
bpsp
)
{
unsigned
int
i
,
val
,
wcaps
;
wcaps
=
get_wcaps
(
codec
,
nid
);
val
=
query_pcm_param
(
codec
,
nid
);
if
(
ratesp
)
{
u32
rates
=
0
;
for
(
i
=
0
;
i
<
AC_PAR_PCM_RATE_BITS
;
i
++
)
{
if
(
val
&
(
1
<<
i
))
rates
|=
rate_bits
[
i
].
alsa_bits
;
}
if
(
rates
==
0
)
{
codec_err
(
codec
,
"rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)
\n
"
,
nid
,
val
,
(
wcaps
&
AC_WCAP_FORMAT_OVRD
)
?
1
:
0
);
return
-
EIO
;
}
*
ratesp
=
rates
;
}
if
(
formatsp
||
bpsp
)
{
u64
formats
=
0
;
unsigned
int
streams
,
bps
;
streams
=
query_stream_param
(
codec
,
nid
);
if
(
!
streams
)
return
-
EIO
;
bps
=
0
;
if
(
streams
&
AC_SUPFMT_PCM
)
{
if
(
val
&
AC_SUPPCM_BITS_8
)
{
formats
|=
SNDRV_PCM_FMTBIT_U8
;
bps
=
8
;
}
if
(
val
&
AC_SUPPCM_BITS_16
)
{
formats
|=
SNDRV_PCM_FMTBIT_S16_LE
;
bps
=
16
;
}
if
(
wcaps
&
AC_WCAP_DIGITAL
)
{
if
(
val
&
AC_SUPPCM_BITS_32
)
formats
|=
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
;
if
(
val
&
(
AC_SUPPCM_BITS_20
|
AC_SUPPCM_BITS_24
))
formats
|=
SNDRV_PCM_FMTBIT_S32_LE
;
if
(
val
&
AC_SUPPCM_BITS_24
)
bps
=
24
;
else
if
(
val
&
AC_SUPPCM_BITS_20
)
bps
=
20
;
}
else
if
(
val
&
(
AC_SUPPCM_BITS_20
|
AC_SUPPCM_BITS_24
|
AC_SUPPCM_BITS_32
))
{
formats
|=
SNDRV_PCM_FMTBIT_S32_LE
;
if
(
val
&
AC_SUPPCM_BITS_32
)
bps
=
32
;
else
if
(
val
&
AC_SUPPCM_BITS_24
)
bps
=
24
;
else
if
(
val
&
AC_SUPPCM_BITS_20
)
bps
=
20
;
}
}
#if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
if (streams & AC_SUPFMT_FLOAT32) {
formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
if (!bps)
bps = 32;
}
#endif
if
(
streams
==
AC_SUPFMT_AC3
)
{
/* should be exclusive */
/* temporary hack: we have still no proper support
* for the direct AC3 stream...
*/
formats
|=
SNDRV_PCM_FMTBIT_U8
;
bps
=
8
;
}
if
(
formats
==
0
)
{
codec_err
(
codec
,
"formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)
\n
"
,
nid
,
val
,
(
wcaps
&
AC_WCAP_FORMAT_OVRD
)
?
1
:
0
,
streams
);
return
-
EIO
;
}
if
(
formatsp
)
*
formatsp
=
formats
;
if
(
bpsp
)
*
bpsp
=
bps
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_query_supported_pcm
);
/**
* snd_hda_is_supported_format - Check the validity of the format
* @codec: HD-audio codec
* @nid: NID to check
* @format: the HD-audio format value to check
*
* Check whether the given node supports the format value.
*
* Returns 1 if supported, 0 if not.
*/
int
snd_hda_is_supported_format
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
format
)
{
int
i
;
unsigned
int
val
=
0
,
rate
,
stream
;
val
=
query_pcm_param
(
codec
,
nid
);
if
(
!
val
)
return
0
;
rate
=
format
&
0xff00
;
for
(
i
=
0
;
i
<
AC_PAR_PCM_RATE_BITS
;
i
++
)
if
(
rate_bits
[
i
].
hda_fmt
==
rate
)
{
if
(
val
&
(
1
<<
i
))
break
;
return
0
;
}
if
(
i
>=
AC_PAR_PCM_RATE_BITS
)
return
0
;
stream
=
query_stream_param
(
codec
,
nid
);
if
(
!
stream
)
return
0
;
if
(
stream
&
AC_SUPFMT_PCM
)
{
switch
(
format
&
0xf0
)
{
case
0x00
:
if
(
!
(
val
&
AC_SUPPCM_BITS_8
))
return
0
;
break
;
case
0x10
:
if
(
!
(
val
&
AC_SUPPCM_BITS_16
))
return
0
;
break
;
case
0x20
:
if
(
!
(
val
&
AC_SUPPCM_BITS_20
))
return
0
;
break
;
case
0x30
:
if
(
!
(
val
&
AC_SUPPCM_BITS_24
))
return
0
;
break
;
case
0x40
:
if
(
!
(
val
&
AC_SUPPCM_BITS_32
))
return
0
;
break
;
default:
return
0
;
}
}
else
{
/* FIXME: check for float32 and AC3? */
}
return
1
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_is_supported_format
);
/*
* PCM stuff
*/
...
...
@@ -3804,9 +3407,6 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
struct
hda_pcm
*
cpcm
;
int
dev
,
err
;
if
(
snd_BUG_ON
(
!
bus
->
ops
.
attach_pcm
))
return
-
EINVAL
;
err
=
snd_hda_codec_parse_pcms
(
codec
);
if
(
err
<
0
)
{
snd_hda_codec_reset
(
codec
);
...
...
@@ -3824,7 +3424,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
if
(
dev
<
0
)
continue
;
/* no fatal error */
cpcm
->
device
=
dev
;
err
=
bus
->
ops
.
attach_pc
m
(
bus
,
codec
,
cpcm
);
err
=
snd_hda_attach_pcm_strea
m
(
bus
,
codec
,
cpcm
);
if
(
err
<
0
)
{
codec_err
(
codec
,
"cannot attach PCM stream %d for codec #%d
\n
"
,
...
...
@@ -4494,10 +4094,10 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
EXPORT_SYMBOL_GPL
(
snd_hda_add_imux_item
);
/**
* snd_hda_bus_reset - Reset the bus
* snd_hda_bus_reset
_codecs
- Reset the bus
* @bus: HD-audio bus
*/
void
snd_hda_bus_reset
(
struct
hda_bus
*
bus
)
void
snd_hda_bus_reset
_codecs
(
struct
hda_bus
*
bus
)
{
struct
hda_codec
*
codec
;
...
...
@@ -4512,7 +4112,6 @@ void snd_hda_bus_reset(struct hda_bus *bus)
#endif
}
}
EXPORT_SYMBOL_GPL
(
snd_hda_bus_reset
);
/**
* snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
...
...
sound/pci/hda/hda_codec.h
浏览文件 @
f1a77547
...
...
@@ -40,32 +40,6 @@ struct hda_codec;
struct
hda_pcm
;
struct
hda_pcm_stream
;
/* bus operators */
struct
hda_bus_ops
{
/* send a single command */
int
(
*
command
)(
struct
hda_bus
*
bus
,
unsigned
int
cmd
);
/* get a response from the last command */
unsigned
int
(
*
get_response
)(
struct
hda_bus
*
bus
,
unsigned
int
addr
);
/* free the private data */
void
(
*
private_free
)(
struct
hda_bus
*
);
/* attach a PCM stream */
int
(
*
attach_pcm
)(
struct
hda_bus
*
bus
,
struct
hda_codec
*
codec
,
struct
hda_pcm
*
pcm
);
/* reset bus for retry verb */
void
(
*
bus_reset
)(
struct
hda_bus
*
bus
);
#ifdef CONFIG_SND_HDA_DSP_LOADER
/* prepare DSP transfer */
int
(
*
load_dsp_prepare
)(
struct
hda_bus
*
bus
,
unsigned
int
format
,
unsigned
int
byte_size
,
struct
snd_dma_buffer
*
bufp
);
/* start/stop DSP transfer */
void
(
*
load_dsp_trigger
)(
struct
hda_bus
*
bus
,
bool
start
);
/* clean up DSP transfer */
void
(
*
load_dsp_cleanup
)(
struct
hda_bus
*
bus
,
struct
snd_dma_buffer
*
dmab
);
#endif
};
/*
* codec bus
*
...
...
@@ -77,10 +51,8 @@ struct hda_bus {
struct
snd_card
*
card
;
void
*
private_data
;
struct
pci_dev
*
pci
;
const
char
*
modelname
;
struct
hda_bus_ops
ops
;
struct
mutex
prepare_mutex
;
...
...
@@ -92,7 +64,6 @@ struct hda_bus {
unsigned
int
allow_bus_reset
:
1
;
/* allow bus reset at fatal error */
/* status for codec/controller */
unsigned
int
shutdown
:
1
;
/* being unloaded */
unsigned
int
rirb_error
:
1
;
/* error in codec communication */
unsigned
int
response_reset
:
1
;
/* controller was reset */
unsigned
int
in_reset
:
1
;
/* during reset operation */
unsigned
int
no_response_fallback
:
1
;
/* don't fallback at RIRB error */
...
...
@@ -100,6 +71,9 @@ struct hda_bus {
int
primary_dig_out_type
;
/* primary digital out PCM type */
};
/* from hdac_bus to hda_bus */
#define to_hda_bus(bus) container_of(bus, struct hda_bus, core)
/*
* codec preset
*
...
...
@@ -328,7 +302,10 @@ struct hda_codec {
/*
* constructors
*/
int
snd_hda_bus_new
(
struct
snd_card
*
card
,
struct
hda_bus
**
busp
);
int
snd_hda_bus_new
(
struct
snd_card
*
card
,
const
struct
hdac_bus_ops
*
ops
,
const
struct
hdac_io_ops
*
io_ops
,
struct
hda_bus
**
busp
);
int
snd_hda_codec_new
(
struct
hda_bus
*
bus
,
struct
snd_card
*
card
,
unsigned
int
codec_addr
,
struct
hda_codec
**
codecp
);
int
snd_hda_codec_configure
(
struct
hda_codec
*
codec
);
...
...
@@ -367,8 +344,6 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
hda_nid_t
nid
,
int
recursive
);
int
snd_hda_get_devices
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
u8
*
dev_list
,
int
max_devices
);
int
snd_hda_query_supported_pcm
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
u32
*
ratesp
,
u64
*
formatsp
,
unsigned
int
*
bpsp
);
struct
hda_verb
{
hda_nid_t
nid
;
...
...
@@ -460,17 +435,17 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
int
do_now
);
#define snd_hda_codec_cleanup_stream(codec, nid) \
__snd_hda_codec_cleanup_stream(codec, nid, 0)
unsigned
int
snd_hda_calc_stream_format
(
struct
hda_codec
*
codec
,
unsigned
int
rate
,
unsigned
int
channels
,
unsigned
int
format
,
unsigned
int
maxbps
,
unsigned
short
spdif_ctls
);
int
snd_hda_is_supported_format
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
format
);
#define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, bpsp) \
snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, bpsp)
#define snd_hda_is_supported_format(codec, nid, fmt) \
snd_hdac_is_supported_format(&(codec)->core, nid, fmt)
extern
const
struct
snd_pcm_chmap_elem
snd_pcm_2_1_chmaps
[];
int
snd_hda_attach_pcm_stream
(
struct
hda_bus
*
_bus
,
struct
hda_codec
*
codec
,
struct
hda_pcm
*
cpcm
);
/*
* Misc
*/
...
...
@@ -481,6 +456,7 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
int
snd_hda_lock_devices
(
struct
hda_bus
*
bus
);
void
snd_hda_unlock_devices
(
struct
hda_bus
*
bus
);
void
snd_hda_bus_reset
(
struct
hda_bus
*
bus
);
void
snd_hda_bus_reset_codecs
(
struct
hda_bus
*
bus
);
/*
* power management
...
...
@@ -526,24 +502,12 @@ int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf);
#endif
#ifdef CONFIG_SND_HDA_DSP_LOADER
static
inline
int
snd_hda_codec_load_dsp_prepare
(
struct
hda_codec
*
codec
,
unsigned
int
format
,
unsigned
int
size
,
struct
snd_dma_buffer
*
bufp
)
{
return
codec
->
bus
->
ops
.
load_dsp_prepare
(
codec
->
bus
,
format
,
size
,
bufp
);
}
static
inline
void
snd_hda_codec_load_dsp_trigger
(
struct
hda_codec
*
codec
,
bool
start
)
{
return
codec
->
bus
->
ops
.
load_dsp_trigger
(
codec
->
bus
,
start
);
}
static
inline
void
snd_hda_codec_load_dsp_cleanup
(
struct
hda_codec
*
codec
,
struct
snd_dma_buffer
*
dmab
)
{
return
codec
->
bus
->
ops
.
load_dsp_cleanup
(
codec
->
bus
,
dmab
);
}
int
snd_hda_codec_load_dsp_prepare
(
struct
hda_codec
*
codec
,
unsigned
int
format
,
unsigned
int
size
,
struct
snd_dma_buffer
*
bufp
);
void
snd_hda_codec_load_dsp_trigger
(
struct
hda_codec
*
codec
,
bool
start
);
void
snd_hda_codec_load_dsp_cleanup
(
struct
hda_codec
*
codec
,
struct
snd_dma_buffer
*
dmab
);
#else
static
inline
int
snd_hda_codec_load_dsp_prepare
(
struct
hda_codec
*
codec
,
unsigned
int
format
,
...
...
sound/pci/hda/hda_controller.c
浏览文件 @
f1a77547
此差异已折叠。
点击以展开。
sound/pci/hda/hda_controller.h
浏览文件 @
f1a77547
...
...
@@ -21,135 +21,10 @@
#include <sound/pcm.h>
#include <sound/initval.h>
#include "hda_codec.h"
#include <sound/hda_register.h>
/*
* registers
*/
#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 AZX_MAX_CODECS 8
#define AZX_MAX_CODECS HDA_MAX_CODECS
#define AZX_DEFAULT_CODECS 4
#define STATESTS_INT_MASK ((1 << AZX_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
/* driver quirks (capabilities) */
/* bits 0-7 are used for indicating driver type */
...
...
@@ -183,40 +58,10 @@ enum {
AZX_SNOOP_TYPE_NVIDIA
,
};
/* HD Audio class code */
#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
struct
azx_dev
{
struct
snd_dma_buffer
bdl
;
/* BDL buffer */
u32
*
posbuf
;
/* position buffer pointer */
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 */
unsigned
long
start_wallclk
;
/* start + minimum wallclk */
unsigned
long
period_wallclk
;
/* wallclk for period */
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 */
unsigned
int
opened
:
1
;
unsigned
int
running
:
1
;
struct
hdac_stream
core
;
unsigned
int
irq_pending
:
1
;
unsigned
int
prepared
:
1
;
unsigned
int
locked
:
1
;
/*
* For VIA:
* A flag to ensure DMA position is 0
...
...
@@ -224,50 +69,17 @@ struct azx_dev {
*/
unsigned
int
insufficient
:
1
;
unsigned
int
wc_marked
:
1
;
unsigned
int
no_period_wakeup
:
1
;
struct
timecounter
azx_tc
;
struct
cyclecounter
azx_cc
;
int
delay_negative_threshold
;
#ifdef CONFIG_SND_HDA_DSP_LOADER
/* Allows dsp load to have sole access to the playback stream. */
struct
mutex
dsp_mutex
;
#endif
};
/* CORB/RIRB */
struct
azx_rb
{
u32
*
buf
;
/* CORB/RIRB buffer
* Each CORB entry is 4byte, RIRB is 8byte
*/
dma_addr_t
addr
;
/* physical address of CORB/RIRB buffer */
/* for RIRB */
unsigned
short
rp
,
wp
;
/* read/write pointers */
int
cmds
[
AZX_MAX_CODECS
];
/* number of pending requests */
u32
res
[
AZX_MAX_CODECS
];
/* last read value */
};
#define azx_stream(dev) (&(dev)->core)
#define stream_to_azx_dev(s) container_of(s, struct azx_dev, core)
struct
azx
;
/* Functions to read/write to hda registers. */
struct
hda_controller_ops
{
/* Register Access */
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
);
/* Disable msi if supported, PCI only */
int
(
*
disable_msi_reset_irq
)(
struct
azx
*
);
/* Allocation ops */
int
(
*
dma_alloc_pages
)(
struct
azx
*
chip
,
int
type
,
size_t
size
,
struct
snd_dma_buffer
*
buf
);
void
(
*
dma_free_pages
)(
struct
azx
*
chip
,
struct
snd_dma_buffer
*
buf
);
int
(
*
substream_alloc_pages
)(
struct
azx
*
chip
,
struct
snd_pcm_substream
*
substream
,
size_t
size
);
...
...
@@ -291,6 +103,8 @@ typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
typedef
int
(
*
azx_get_delay_callback_t
)(
struct
azx
*
,
struct
azx_dev
*
,
unsigned
int
pos
);
struct
azx
{
struct
hda_bus
bus
;
struct
snd_card
*
card
;
struct
pci_dev
*
pci
;
int
dev_index
;
...
...
@@ -312,35 +126,16 @@ struct azx {
azx_get_pos_callback_t
get_position
[
2
];
azx_get_delay_callback_t
get_delay
[
2
];
/* pci resources */
unsigned
long
addr
;
void
__iomem
*
remap_addr
;
int
irq
;
/* locks */
spinlock_t
reg_lock
;
struct
mutex
open_mutex
;
/* Prevents concurrent open/close operations */
/* streams (x num_streams) */
struct
azx_dev
*
azx_dev
;
/* PCM */
struct
list_head
pcm_list
;
/* azx_pcm list */
/* HD codec */
unsigned
short
codec_mask
;
int
codec_probe_mask
;
/* copied from probe_mask option */
struct
hda_bus
*
bus
;
unsigned
int
beep_mode
;
/* CORB/RIRB */
struct
azx_rb
corb
;
struct
azx_rb
rirb
;
/* CORB/RIRB and position buffers */
struct
snd_dma_buffer
rb
;
struct
snd_dma_buffer
posbuf
;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
const
struct
firmware
*
fw
;
#endif
...
...
@@ -349,7 +144,6 @@ struct azx {
const
int
*
bdl_pos_adj
;
int
poll_count
;
unsigned
int
running
:
1
;
unsigned
int
initialized
:
1
;
unsigned
int
single_cmd
:
1
;
unsigned
int
polling_mode
:
1
;
unsigned
int
msi
:
1
;
...
...
@@ -359,14 +153,14 @@ struct azx {
unsigned
int
region_requested
:
1
;
unsigned
int
disabled
:
1
;
/* disabled by VGA-switcher */
/* for debugging */
unsigned
int
last_cmd
[
AZX_MAX_CODECS
];
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct
azx_dev
saved_azx_dev
;
#endif
};
#define azx_bus(chip) (&(chip)->bus.core)
#define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core)
#ifdef CONFIG_X86
#define azx_snoop(chip) ((chip)->snoop)
#else
...
...
@@ -378,30 +172,17 @@ struct azx {
*/
#define azx_writel(chip, reg, value) \
((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)
)
snd_hdac_chip_writel(azx_bus(chip), reg, value
)
#define azx_readl(chip, reg) \
((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)
)
snd_hdac_chip_readl(azx_bus(chip), reg
)
#define azx_writew(chip, reg, value) \
((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)
)
snd_hdac_chip_writew(azx_bus(chip), reg, value
)
#define azx_readw(chip, reg) \
((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)
)
snd_hdac_chip_readw(azx_bus(chip), reg
)
#define azx_writeb(chip, reg, value) \
((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)
)
snd_hdac_chip_writeb(azx_bus(chip), reg, value
)
#define azx_readb(chip, reg) \
((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg))
#define azx_sd_writel(chip, dev, reg, value) \
((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readl(chip, dev, reg) \
((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_writew(chip, dev, reg, value) \
((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readw(chip, dev, reg) \
((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_writeb(chip, dev, reg, value) \
((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg))
#define azx_sd_readb(chip, dev, reg) \
((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))
snd_hdac_chip_readb(azx_bus(chip), reg)
#define azx_has_pm_runtime(chip) \
((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME)
...
...
@@ -416,22 +197,27 @@ unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
unsigned
int
azx_get_pos_posbuf
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
/* Stream control. */
void
azx_st
ream_stop
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
void
azx_st
op_all_streams
(
struct
azx
*
chip
);
/* Allocation functions. */
int
azx_alloc_stream_pages
(
struct
azx
*
chip
);
void
azx_free_stream_pages
(
struct
azx
*
chip
);
#define azx_alloc_stream_pages(chip) \
snd_hdac_bus_alloc_stream_pages(azx_bus(chip))
#define azx_free_stream_pages(chip) \
snd_hdac_bus_free_stream_pages(azx_bus(chip))
/* Low level azx interface */
void
azx_init_chip
(
struct
azx
*
chip
,
bool
full_reset
);
void
azx_stop_chip
(
struct
azx
*
chip
);
void
azx_enter_link_reset
(
struct
azx
*
chip
);
#define azx_enter_link_reset(chip) \
snd_hdac_bus_enter_link_reset(azx_bus(chip))
irqreturn_t
azx_interrupt
(
int
irq
,
void
*
dev_id
);
/* Codec interface */
int
azx_bus_create
(
struct
azx
*
chip
,
const
char
*
model
);
int
azx_bus_init
(
struct
azx
*
chip
,
const
char
*
model
,
const
struct
hdac_io_ops
*
io_ops
);
int
azx_probe_codecs
(
struct
azx
*
chip
,
unsigned
int
max_slots
);
int
azx_codec_configure
(
struct
azx
*
chip
);
int
azx_init_stream
(
struct
azx
*
chip
);
int
azx_init_streams
(
struct
azx
*
chip
);
void
azx_free_streams
(
struct
azx
*
chip
);
#endif
/* __SOUND_HDA_CONTROLLER_H */
sound/pci/hda/hda_intel.c
浏览文件 @
f1a77547
此差异已折叠。
点击以展开。
sound/pci/hda/hda_intel.h
浏览文件 @
f1a77547
...
...
@@ -34,6 +34,7 @@ struct hda_intel {
/* extra flags */
unsigned
int
irq_pending_warned
:
1
;
unsigned
int
probe_continued
:
1
;
/* VGA-switcheroo setup */
unsigned
int
use_vga_switcheroo
:
1
;
...
...
sound/pci/hda/hda_intel_trace.h
浏览文件 @
f1a77547
...
...
@@ -24,7 +24,7 @@ TRACE_EVENT(azx_pcm_trigger,
TP_fast_assign
(
__entry
->
card
=
(
chip
)
->
card
->
number
;
__entry
->
idx
=
(
dev
)
->
index
;
__entry
->
idx
=
(
dev
)
->
core
.
index
;
__entry
->
cmd
=
cmd
;
),
...
...
@@ -46,7 +46,7 @@ TRACE_EVENT(azx_get_position,
TP_fast_assign
(
__entry
->
card
=
(
chip
)
->
card
->
number
;
__entry
->
idx
=
(
dev
)
->
index
;
__entry
->
idx
=
(
dev
)
->
core
.
index
;
__entry
->
pos
=
pos
;
__entry
->
delay
=
delay
;
),
...
...
sound/pci/hda/hda_tegra.c
浏览文件 @
f1a77547
...
...
@@ -87,13 +87,13 @@ MODULE_PARM_DESC(power_save,
/*
* DMA page allocation ops.
*/
static
int
dma_alloc_pages
(
struct
azx
*
chip
,
int
type
,
size_t
size
,
static
int
dma_alloc_pages
(
struct
hdac_bus
*
bus
,
int
type
,
size_t
size
,
struct
snd_dma_buffer
*
buf
)
{
return
snd_dma_alloc_pages
(
type
,
chip
->
card
->
dev
,
size
,
buf
);
return
snd_dma_alloc_pages
(
type
,
bus
->
dev
,
size
,
buf
);
}
static
void
dma_free_pages
(
struct
azx
*
chip
,
struct
snd_dma_buffer
*
buf
)
static
void
dma_free_pages
(
struct
hdac_bus
*
bus
,
struct
snd_dma_buffer
*
buf
)
{
snd_dma_free_pages
(
buf
);
}
...
...
@@ -102,11 +102,6 @@ static int substream_alloc_pages(struct azx *chip,
struct
snd_pcm_substream
*
substream
,
size_t
size
)
{
struct
azx_dev
*
azx_dev
=
get_azx_dev
(
substream
);
azx_dev
->
bufsize
=
0
;
azx_dev
->
period_bytes
=
0
;
azx_dev
->
format_val
=
0
;
return
snd_pcm_lib_malloc_pages
(
substream
,
size
);
}
...
...
@@ -173,7 +168,7 @@ static u8 hda_tegra_readb(u8 *addr)
return
(
v
>>
shift
)
&
0xff
;
}
static
const
struct
hda
_controller_ops
hda_tegra
_ops
=
{
static
const
struct
hda
c_io_ops
hda_tegra_io
_ops
=
{
.
reg_writel
=
hda_tegra_writel
,
.
reg_readl
=
hda_tegra_readl
,
.
reg_writew
=
hda_tegra_writew
,
...
...
@@ -182,6 +177,9 @@ static const struct hda_controller_ops hda_tegra_ops = {
.
reg_readb
=
hda_tegra_readb
,
.
dma_alloc_pages
=
dma_alloc_pages
,
.
dma_free_pages
=
dma_free_pages
,
};
static
const
struct
hda_controller_ops
hda_tegra_ops
=
{
.
substream_alloc_pages
=
substream_alloc_pages
,
.
substream_free_pages
=
substream_free_pages
,
};
...
...
@@ -282,21 +280,29 @@ static const struct dev_pm_ops hda_tegra_pm = {
SET_SYSTEM_SLEEP_PM_OPS
(
hda_tegra_suspend
,
hda_tegra_resume
)
};
static
int
hda_tegra_dev_disconnect
(
struct
snd_device
*
device
)
{
struct
azx
*
chip
=
device
->
device_data
;
chip
->
bus
.
shutdown
=
1
;
return
0
;
}
/*
* destructor
*/
static
int
hda_tegra_dev_free
(
struct
snd_device
*
device
)
{
int
i
;
struct
azx
*
chip
=
device
->
device_data
;
if
(
chip
->
initialized
)
{
for
(
i
=
0
;
i
<
chip
->
num_streams
;
i
++
)
azx_stream_stop
(
chip
,
&
chip
->
azx_dev
[
i
]);
if
(
azx_bus
(
chip
)
->
chip_init
)
{
azx_stop_all_streams
(
chip
);
azx_stop_chip
(
chip
);
}
azx_free_stream_pages
(
chip
);
azx_free_streams
(
chip
);
snd_hdac_bus_exit
(
azx_bus
(
chip
));
return
0
;
}
...
...
@@ -304,6 +310,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
static
int
hda_tegra_init_chip
(
struct
azx
*
chip
,
struct
platform_device
*
pdev
)
{
struct
hda_tegra
*
hda
=
container_of
(
chip
,
struct
hda_tegra
,
chip
);
struct
hdac_bus
*
bus
=
azx_bus
(
chip
);
struct
device
*
dev
=
hda
->
dev
;
struct
resource
*
res
;
int
err
;
...
...
@@ -323,8 +330,8 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
if
(
IS_ERR
(
hda
->
regs
))
return
PTR_ERR
(
hda
->
regs
);
chip
->
remap_addr
=
hda
->
regs
+
HDA_BAR0
;
chip
->
addr
=
res
->
start
+
HDA_BAR0
;
bus
->
remap_addr
=
hda
->
regs
+
HDA_BAR0
;
bus
->
addr
=
res
->
start
+
HDA_BAR0
;
err
=
hda_tegra_enable_clocks
(
hda
);
if
(
err
)
...
...
@@ -337,6 +344,7 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
static
int
hda_tegra_first_init
(
struct
azx
*
chip
,
struct
platform_device
*
pdev
)
{
struct
hdac_bus
*
bus
=
azx_bus
(
chip
);
struct
snd_card
*
card
=
chip
->
card
;
int
err
;
unsigned
short
gcap
;
...
...
@@ -354,9 +362,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
irq_id
);
return
err
;
}
chip
->
irq
=
irq_id
;
bus
->
irq
=
irq_id
;
synchronize_irq
(
chip
->
irq
);
synchronize_irq
(
bus
->
irq
);
gcap
=
azx_readw
(
chip
,
GCAP
);
dev_dbg
(
card
->
dev
,
"chipset global capabilities = 0x%x
\n
"
,
gcap
);
...
...
@@ -374,23 +382,21 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
chip
->
capture_index_offset
=
0
;
chip
->
playback_index_offset
=
chip
->
capture_streams
;
chip
->
num_streams
=
chip
->
playback_streams
+
chip
->
capture_streams
;
chip
->
azx_dev
=
devm_kcalloc
(
card
->
dev
,
chip
->
num_streams
,
sizeof
(
*
chip
->
azx_dev
),
GFP_KERNEL
);
if
(
!
chip
->
azx_dev
)
return
-
ENOMEM
;
err
=
azx_alloc_stream_pages
(
chip
);
/* initialize streams */
err
=
azx_init_streams
(
chip
);
if
(
err
<
0
)
return
err
;
/* initialize streams */
azx_init_stream
(
chip
);
err
=
azx_alloc_stream_pages
(
chip
);
if
(
err
<
0
)
return
err
;
/* initialize chip */
azx_init_chip
(
chip
,
1
);
/* codec detection */
if
(
!
chip
->
codec_mask
)
{
if
(
!
bus
->
codec_mask
)
{
dev_err
(
card
->
dev
,
"no codecs found!
\n
"
);
return
-
ENODEV
;
}
...
...
@@ -399,7 +405,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
strcpy
(
card
->
shortname
,
"tegra-hda"
);
snprintf
(
card
->
longname
,
sizeof
(
card
->
longname
),
"%s at 0x%lx irq %i"
,
card
->
shortname
,
chip
->
addr
,
chip
->
irq
);
card
->
shortname
,
bus
->
addr
,
bus
->
irq
);
return
0
;
}
...
...
@@ -409,10 +415,10 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
*/
static
int
hda_tegra_create
(
struct
snd_card
*
card
,
unsigned
int
driver_caps
,
const
struct
hda_controller_ops
*
hda_ops
,
struct
hda_tegra
*
hda
)
{
static
struct
snd_device_ops
ops
=
{
.
dev_disconnect
=
hda_tegra_dev_disconnect
,
.
dev_free
=
hda_tegra_dev_free
,
};
struct
azx
*
chip
;
...
...
@@ -420,11 +426,9 @@ static int hda_tegra_create(struct snd_card *card,
chip
=
&
hda
->
chip
;
spin_lock_init
(
&
chip
->
reg_lock
);
mutex_init
(
&
chip
->
open_mutex
);
chip
->
card
=
card
;
chip
->
ops
=
hda_ops
;
chip
->
irq
=
-
1
;
chip
->
ops
=
&
hda_tegra_ops
;
chip
->
driver_caps
=
driver_caps
;
chip
->
driver_type
=
driver_caps
&
0xff
;
chip
->
dev_index
=
0
;
...
...
@@ -471,7 +475,11 @@ static int hda_tegra_probe(struct platform_device *pdev)
return
err
;
}
err
=
hda_tegra_create
(
card
,
driver_flags
,
&
hda_tegra_ops
,
hda
);
err
=
azx_bus_init
(
chip
,
NULL
,
&
hda_tegra_io_ops
);
if
(
err
<
0
)
goto
out_free
;
err
=
hda_tegra_create
(
card
,
driver_flags
,
hda
);
if
(
err
<
0
)
goto
out_free
;
card
->
private_data
=
chip
;
...
...
@@ -483,10 +491,6 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto
out_free
;
/* create codec instances */
err
=
azx_bus_create
(
chip
,
NULL
);
if
(
err
<
0
)
goto
out_free
;
err
=
azx_probe_codecs
(
chip
,
0
);
if
(
err
<
0
)
goto
out_free
;
...
...
@@ -500,7 +504,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto
out_free
;
chip
->
running
=
1
;
snd_hda_set_power_save
(
chip
->
bus
,
power_save
*
1000
);
snd_hda_set_power_save
(
&
chip
->
bus
,
power_save
*
1000
);
return
0
;
...
...
sound/pci/hda/patch_ca0132.c
浏览文件 @
f1a77547
...
...
@@ -2052,11 +2052,8 @@ static int dma_convert_to_hda_format(struct hda_codec *codec,
{
unsigned
int
format_val
;
format_val
=
snd_hda_calc_stream_format
(
codec
,
sample_rate
,
channels
,
SNDRV_PCM_FORMAT_S32_LE
,
32
,
0
);
format_val
=
snd_hdac_calc_stream_format
(
sample_rate
,
channels
,
SNDRV_PCM_FORMAT_S32_LE
,
32
,
0
);
if
(
hda_format
)
*
hda_format
=
(
unsigned
short
)
format_val
;
...
...
sound/pci/hda/patch_hdmi.c
浏览文件 @
f1a77547
...
...
@@ -592,7 +592,7 @@ static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
static
void
eld_proc_free
(
struct
hdmi_spec_per_pin
*
per_pin
)
{
if
(
!
per_pin
->
codec
->
bus
->
shutdown
&&
per_pin
->
proc_entry
)
{
snd_
device_free
(
per_pin
->
codec
->
card
,
per_pin
->
proc_entry
);
snd_
info_free_entry
(
per_pin
->
proc_entry
);
per_pin
->
proc_entry
=
NULL
;
}
}
...
...
sound/pci/ice1712/ice1712.c
浏览文件 @
f1a77547
...
...
@@ -2530,8 +2530,8 @@ static int snd_ice1712_create(struct snd_card *card,
if
(
err
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 28bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/lx6464es/lx6464es.c
浏览文件 @
f1a77547
...
...
@@ -981,7 +981,7 @@ static int snd_lx6464es_create(struct snd_card *card,
pci_set_master
(
pci
);
/* check if we can restrict PCI DMA transfers to 32 bits */
err
=
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
));
err
=
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
));
if
(
err
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 32bit PCI busmaster DMA
\n
"
);
...
...
sound/pci/maestro3.c
浏览文件 @
f1a77547
...
...
@@ -2537,8 +2537,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
return
-
EIO
;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
28
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
28
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 28bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/mixart/mixart.c
浏览文件 @
f1a77547
...
...
@@ -1269,7 +1269,7 @@ static int snd_mixart_probe(struct pci_dev *pci,
pci_set_master
(
pci
);
/* check if we can restrict PCI DMA transfers to 32 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_err
(
&
pci
->
dev
,
"architecture does not support 32bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/pcxhr/pcxhr.c
浏览文件 @
f1a77547
...
...
@@ -1537,7 +1537,7 @@ static int pcxhr_probe(struct pci_dev *pci,
pci_set_master
(
pci
);
/* check if we can restrict PCI DMA transfers to 32 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
32
))
<
0
)
{
dev_err
(
&
pci
->
dev
,
"architecture does not support 32bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/sis7019.c
浏览文件 @
f1a77547
...
...
@@ -383,9 +383,9 @@ static void __sis_map_silence(struct sis7019 *sis)
{
/* Helper function: must hold sis->voice_lock on entry */
if
(
!
sis
->
silence_users
)
sis
->
silence_dma_addr
=
pci_map_single
(
sis
->
pci
,
sis
->
silence_dma_addr
=
dma_map_single
(
&
sis
->
pci
->
dev
,
sis
->
suspend_state
[
0
],
4096
,
PCI_DMA_TO
DEVICE
);
4096
,
DMA_TO_
DEVICE
);
sis
->
silence_users
++
;
}
...
...
@@ -394,8 +394,8 @@ static void __sis_unmap_silence(struct sis7019 *sis)
/* Helper function: must hold sis->voice_lock on entry */
sis
->
silence_users
--
;
if
(
!
sis
->
silence_users
)
pci_unmap_single
(
sis
->
pci
,
sis
->
silence_dma_addr
,
4096
,
PCI_DMA_TO
DEVICE
);
dma_unmap_single
(
&
sis
->
pci
->
dev
,
sis
->
silence_dma_addr
,
4096
,
DMA_TO_
DEVICE
);
}
static
void
sis_free_voice
(
struct
sis7019
*
sis
,
struct
voice
*
voice
)
...
...
@@ -1325,7 +1325,7 @@ static int sis_chip_create(struct snd_card *card,
if
(
rc
)
goto
error_out
;
rc
=
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
30
));
rc
=
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
30
));
if
(
rc
<
0
)
{
dev_err
(
&
pci
->
dev
,
"architecture does not support 30-bit PCI busmaster DMA"
);
goto
error_out_enabled
;
...
...
sound/pci/sonicvibes.c
浏览文件 @
f1a77547
...
...
@@ -1259,8 +1259,8 @@ static int snd_sonicvibes_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 24 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
24
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
24
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 24bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
sound/pci/trident/trident_main.c
浏览文件 @
f1a77547
...
...
@@ -3551,8 +3551,8 @@ int snd_trident_create(struct snd_card *card,
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
/* check, if we can restrict PCI DMA transfers to 30 bits */
if
(
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
30
))
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
30
))
<
0
)
{
if
(
dma_set_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
30
))
<
0
||
dma_set_coherent_mask
(
&
pci
->
dev
,
DMA_BIT_MASK
(
30
))
<
0
)
{
dev_err
(
card
->
dev
,
"architecture does not support 30bit PCI busmaster DMA
\n
"
);
pci_disable_device
(
pci
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录