Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
84526820
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
84526820
编写于
7月 01, 2014
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/hda-cleanup' into for-next
上级
e8750940
fb1d8ac2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
422 addition
and
394 deletion
+422
-394
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_auto_parser.c
+0
-2
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.c
+70
-130
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_controller.h
+6
-3
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+251
-70
sound/pci/hda/hda_priv.h
sound/pci/hda/hda_priv.h
+93
-160
sound/pci/hda/hda_tegra.c
sound/pci/hda/hda_tegra.c
+2
-29
未找到文件。
sound/pci/hda/hda_auto_parser.c
浏览文件 @
84526820
...
...
@@ -17,8 +17,6 @@
#include "hda_local.h"
#include "hda_auto_parser.h"
#define SFX "hda_codec: "
/*
* Helper for automatic pin configuration
*/
...
...
sound/pci/hda/hda_controller.c
浏览文件 @
84526820
...
...
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_priv.h"
...
...
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
upper_32_bits
(
azx_dev
->
bdl
.
addr
));
/* enable the position buffer */
if
(
chip
->
position_fix
[
0
]
!=
POS_FIX_LPIB
||
chip
->
position_fix
[
1
]
!=
POS_FIX_LPIB
)
{
if
(
!
(
azx_readl
(
chip
,
DPLBASE
)
&
ICH6
_DPLBASE_ENABLE
))
if
(
chip
->
get_position
[
0
]
!=
azx_get_pos_lpib
||
chip
->
get_position
[
1
]
!=
azx_get_pos_lpib
)
{
if
(
!
(
azx_readl
(
chip
,
DPLBASE
)
&
AZX
_DPLBASE_ENABLE
))
azx_writel
(
chip
,
DPLBASE
,
(
u32
)
chip
->
posbuf
.
addr
|
ICH6
_DPLBASE_ENABLE
);
(
u32
)
chip
->
posbuf
.
addr
|
AZX
_DPLBASE_ENABLE
);
}
/* set the interrupt enable bits in the descriptor control register */
...
...
@@ -673,125 +674,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return
0
;
}
/* get the current DMA position with correction on VIA chips */
static
unsigned
int
azx_via_get_position
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
unsigned
int
azx_get_pos_lpib
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
{
unsigned
int
link_pos
,
mini_pos
,
bound_pos
;
unsigned
int
mod_link_pos
,
mod_dma_pos
,
mod_mini_pos
;
unsigned
int
fifo_size
;
link_pos
=
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
if
(
azx_dev
->
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
/* Playback, no problem using link position */
return
link_pos
;
}
/* Capture */
/* For new chipset,
* use mod to get the DMA position just like old chipset
*/
mod_dma_pos
=
le32_to_cpu
(
*
azx_dev
->
posbuf
);
mod_dma_pos
%=
azx_dev
->
period_bytes
;
/* azx_dev->fifo_size can't get FIFO size of in stream.
* Get from base address + offset.
*/
fifo_size
=
readw
(
chip
->
remap_addr
+
VIA_IN_STREAM0_FIFO_SIZE_OFFSET
);
if
(
azx_dev
->
insufficient
)
{
/* Link position never gather than FIFO size */
if
(
link_pos
<=
fifo_size
)
return
0
;
azx_dev
->
insufficient
=
0
;
}
if
(
link_pos
<=
fifo_size
)
mini_pos
=
azx_dev
->
bufsize
+
link_pos
-
fifo_size
;
else
mini_pos
=
link_pos
-
fifo_size
;
/* Find nearest previous boudary */
mod_mini_pos
=
mini_pos
%
azx_dev
->
period_bytes
;
mod_link_pos
=
link_pos
%
azx_dev
->
period_bytes
;
if
(
mod_link_pos
>=
fifo_size
)
bound_pos
=
link_pos
-
mod_link_pos
;
else
if
(
mod_dma_pos
>=
mod_mini_pos
)
bound_pos
=
mini_pos
-
mod_mini_pos
;
else
{
bound_pos
=
mini_pos
-
mod_mini_pos
+
azx_dev
->
period_bytes
;
if
(
bound_pos
>=
azx_dev
->
bufsize
)
bound_pos
=
0
;
}
return
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
}
EXPORT_SYMBOL_GPL
(
azx_get_pos_lpib
);
/* Calculate real DMA position we want */
return
bound_pos
+
mod_dma_pos
;
unsigned
int
azx_get_pos_posbuf
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
{
return
le32_to_cpu
(
*
azx_dev
->
posbuf
);
}
EXPORT_SYMBOL_GPL
(
azx_get_pos_posbuf
);
unsigned
int
azx_get_position
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
,
bool
with_check
)
struct
azx_dev
*
azx_dev
)
{
struct
snd_pcm_substream
*
substream
=
azx_dev
->
substream
;
struct
azx_pcm
*
apcm
=
snd_pcm_substream_chip
(
substream
);
unsigned
int
pos
;
int
stream
=
substream
->
stream
;
struct
hda_pcm_stream
*
hinfo
=
apcm
->
hinfo
[
stream
];
int
delay
=
0
;
switch
(
chip
->
position_fix
[
stream
])
{
case
POS_FIX_LPIB
:
/* read LPIB */
pos
=
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
break
;
case
POS_FIX_VIACOMBO
:
pos
=
azx_via_get_position
(
chip
,
azx_dev
);
break
;
default:
/* use the position buffer */
pos
=
le32_to_cpu
(
*
azx_dev
->
posbuf
);
if
(
with_check
&&
chip
->
position_fix
[
stream
]
==
POS_FIX_AUTO
)
{
if
(
!
pos
||
pos
==
(
u32
)
-
1
)
{
dev_info
(
chip
->
card
->
dev
,
"Invalid position buffer, using LPIB read method instead.
\n
"
);
chip
->
position_fix
[
stream
]
=
POS_FIX_LPIB
;
pos
=
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
}
else
chip
->
position_fix
[
stream
]
=
POS_FIX_POSBUF
;
}
break
;
}
if
(
chip
->
get_position
[
stream
])
pos
=
chip
->
get_position
[
stream
](
chip
,
azx_dev
);
else
/* use the position buffer as default */
pos
=
azx_get_pos_posbuf
(
chip
,
azx_dev
);
if
(
pos
>=
azx_dev
->
bufsize
)
pos
=
0
;
/* calculate runtime delay from LPIB */
if
(
substream
->
runtime
&&
chip
->
position_fix
[
stream
]
==
POS_FIX_POSBUF
&&
(
chip
->
driver_caps
&
AZX_DCAPS_COUNT_LPIB_DELAY
))
{
unsigned
int
lpib_pos
=
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
delay
=
pos
-
lpib_pos
;
else
delay
=
lpib_pos
-
pos
;
if
(
delay
<
0
)
{
if
(
delay
>=
azx_dev
->
delay_negative_threshold
)
delay
=
0
;
else
delay
+=
azx_dev
->
bufsize
;
}
if
(
delay
>=
azx_dev
->
period_bytes
)
{
dev_info
(
chip
->
card
->
dev
,
"Unstable LPIB (%d >= %d); disabling LPIB delay counting
\n
"
,
delay
,
azx_dev
->
period_bytes
);
delay
=
0
;
chip
->
driver_caps
&=
~
AZX_DCAPS_COUNT_LPIB_DELAY
;
}
delay
=
bytes_to_frames
(
substream
->
runtime
,
delay
);
}
if
(
substream
->
runtime
)
{
struct
azx_pcm
*
apcm
=
snd_pcm_substream_chip
(
substream
);
struct
hda_pcm_stream
*
hinfo
=
apcm
->
hinfo
[
stream
];
if
(
chip
->
get_delay
[
stream
])
delay
+=
chip
->
get_delay
[
stream
](
chip
,
azx_dev
,
pos
);
if
(
hinfo
->
ops
.
get_delay
)
delay
+=
hinfo
->
ops
.
get_delay
(
hinfo
,
apcm
->
codec
,
substream
);
...
...
@@ -809,7 +725,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
struct
azx
*
chip
=
apcm
->
chip
;
struct
azx_dev
*
azx_dev
=
get_azx_dev
(
substream
);
return
bytes_to_frames
(
substream
->
runtime
,
azx_get_position
(
chip
,
azx_dev
,
false
));
azx_get_position
(
chip
,
azx_dev
));
}
static
int
azx_get_wallclock_tstamp
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -1059,10 +975,10 @@ static void azx_init_cmd_io(struct azx *chip)
azx_writew
(
chip
,
CORBWP
,
0
);
/* reset the corb hw read pointer */
azx_writew
(
chip
,
CORBRP
,
ICH6
_CORBRP_RST
);
azx_writew
(
chip
,
CORBRP
,
AZX
_CORBRP_RST
);
if
(
!
(
chip
->
driver_caps
&
AZX_DCAPS_CORBRP_SELF_CLEAR
))
{
for
(
timeout
=
1000
;
timeout
>
0
;
timeout
--
)
{
if
((
azx_readw
(
chip
,
CORBRP
)
&
ICH6_CORBRP_RST
)
==
ICH6
_CORBRP_RST
)
if
((
azx_readw
(
chip
,
CORBRP
)
&
AZX_CORBRP_RST
)
==
AZX
_CORBRP_RST
)
break
;
udelay
(
1
);
}
...
...
@@ -1082,7 +998,7 @@ static void azx_init_cmd_io(struct azx *chip)
}
/* enable corb dma */
azx_writeb
(
chip
,
CORBCTL
,
ICH6
_CORBCTL_RUN
);
azx_writeb
(
chip
,
CORBCTL
,
AZX
_CORBCTL_RUN
);
/* RIRB set up */
chip
->
rirb
.
addr
=
chip
->
rb
.
addr
+
2048
;
...
...
@@ -1095,14 +1011,14 @@ static void azx_init_cmd_io(struct azx *chip)
/* set the rirb size to 256 entries (ULI requires explicitly) */
azx_writeb
(
chip
,
RIRBSIZE
,
0x02
);
/* reset the rirb hw write pointer */
azx_writew
(
chip
,
RIRBWP
,
ICH6
_RIRBWP_RST
);
azx_writew
(
chip
,
RIRBWP
,
AZX
_RIRBWP_RST
);
/* set N=1, get RIRB response interrupt for new entry */
if
(
chip
->
driver_caps
&
AZX_DCAPS_CTX_WORKAROUND
)
azx_writew
(
chip
,
RINTCNT
,
0xc0
);
else
azx_writew
(
chip
,
RINTCNT
,
1
);
/* enable rirb dma and response irq */
azx_writeb
(
chip
,
RIRBCTL
,
ICH6_RBCTL_DMA_EN
|
ICH6
_RBCTL_IRQ_EN
);
azx_writeb
(
chip
,
RIRBCTL
,
AZX_RBCTL_DMA_EN
|
AZX
_RBCTL_IRQ_EN
);
spin_unlock_irq
(
&
chip
->
reg_lock
);
}
EXPORT_SYMBOL_GPL
(
azx_init_cmd_io
);
...
...
@@ -1146,7 +1062,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
return
-
EIO
;
}
wp
++
;
wp
%=
ICH6
_MAX_CORB_ENTRIES
;
wp
%=
AZX
_MAX_CORB_ENTRIES
;
rp
=
azx_readw
(
chip
,
CORBRP
);
if
(
wp
==
rp
)
{
...
...
@@ -1164,7 +1080,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
return
0
;
}
#define
ICH6
_RIRB_EX_UNSOL_EV (1<<4)
#define
AZX
_RIRB_EX_UNSOL_EV (1<<4)
/* retrieve RIRB entry - called from interrupt handler */
static
void
azx_update_rirb
(
struct
azx
*
chip
)
...
...
@@ -1185,7 +1101,7 @@ static void azx_update_rirb(struct azx *chip)
while
(
chip
->
rirb
.
rp
!=
wp
)
{
chip
->
rirb
.
rp
++
;
chip
->
rirb
.
rp
%=
ICH6
_MAX_RIRB_ENTRIES
;
chip
->
rirb
.
rp
%=
AZX
_MAX_RIRB_ENTRIES
;
rp
=
chip
->
rirb
.
rp
<<
1
;
/* an RIRB entry is 8-bytes */
res_ex
=
le32_to_cpu
(
chip
->
rirb
.
buf
[
rp
+
1
]);
...
...
@@ -1196,8 +1112,7 @@ static void azx_update_rirb(struct azx *chip)
res
,
res_ex
,
chip
->
rirb
.
rp
,
wp
);
snd_BUG
();
}
else
if
(
res_ex
&
ICH6_RIRB_EX_UNSOL_EV
)
}
else
if
(
res_ex
&
AZX_RIRB_EX_UNSOL_EV
)
snd_hda_queue_unsol_event
(
chip
->
bus
,
res
,
res_ex
);
else
if
(
chip
->
rirb
.
cmds
[
addr
])
{
chip
->
rirb
.
res
[
addr
]
=
res
;
...
...
@@ -1305,7 +1220,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
/* release CORB/RIRB */
azx_free_cmd_io
(
chip
);
/* disable unsolicited responses */
azx_writel
(
chip
,
GCTL
,
azx_readl
(
chip
,
GCTL
)
&
~
ICH6
_GCTL_UNSOL
);
azx_writel
(
chip
,
GCTL
,
azx_readl
(
chip
,
GCTL
)
&
~
AZX
_GCTL_UNSOL
);
return
-
1
;
}
...
...
@@ -1326,7 +1241,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
while
(
timeout
--
)
{
/* check IRV busy bit */
if
(
azx_readw
(
chip
,
IRS
)
&
ICH6
_IRS_VALID
)
{
if
(
azx_readw
(
chip
,
IRS
)
&
AZX
_IRS_VALID
)
{
/* reuse rirb.res as the response return value */
chip
->
rirb
.
res
[
addr
]
=
azx_readl
(
chip
,
IR
);
return
0
;
...
...
@@ -1350,13 +1265,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
bus
->
rirb_error
=
0
;
while
(
timeout
--
)
{
/* check ICB busy bit */
if
(
!
((
azx_readw
(
chip
,
IRS
)
&
ICH6
_IRS_BUSY
)))
{
if
(
!
((
azx_readw
(
chip
,
IRS
)
&
AZX
_IRS_BUSY
)))
{
/* Clear IRV valid bit */
azx_writew
(
chip
,
IRS
,
azx_readw
(
chip
,
IRS
)
|
ICH6
_IRS_VALID
);
AZX
_IRS_VALID
);
azx_writel
(
chip
,
IC
,
val
);
azx_writew
(
chip
,
IRS
,
azx_readw
(
chip
,
IRS
)
|
ICH6
_IRS_BUSY
);
AZX
_IRS_BUSY
);
return
azx_single_wait_for_response
(
chip
,
addr
);
}
udelay
(
1
);
...
...
@@ -1585,10 +1500,10 @@ void azx_enter_link_reset(struct azx *chip)
unsigned
long
timeout
;
/* reset controller */
azx_writel
(
chip
,
GCTL
,
azx_readl
(
chip
,
GCTL
)
&
~
ICH6
_GCTL_RESET
);
azx_writel
(
chip
,
GCTL
,
azx_readl
(
chip
,
GCTL
)
&
~
AZX
_GCTL_RESET
);
timeout
=
jiffies
+
msecs_to_jiffies
(
100
);
while
((
azx_readb
(
chip
,
GCTL
)
&
ICH6
_GCTL_RESET
)
&&
while
((
azx_readb
(
chip
,
GCTL
)
&
AZX
_GCTL_RESET
)
&&
time_before
(
jiffies
,
timeout
))
usleep_range
(
500
,
1000
);
}
...
...
@@ -1599,7 +1514,7 @@ static void azx_exit_link_reset(struct azx *chip)
{
unsigned
long
timeout
;
azx_writeb
(
chip
,
GCTL
,
azx_readb
(
chip
,
GCTL
)
|
ICH6
_GCTL_RESET
);
azx_writeb
(
chip
,
GCTL
,
azx_readb
(
chip
,
GCTL
)
|
AZX
_GCTL_RESET
);
timeout
=
jiffies
+
msecs_to_jiffies
(
100
);
while
(
!
azx_readb
(
chip
,
GCTL
)
&&
...
...
@@ -1640,7 +1555,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
/* Accept unsolicited responses */
if
(
!
chip
->
single_cmd
)
azx_writel
(
chip
,
GCTL
,
azx_readl
(
chip
,
GCTL
)
|
ICH6
_GCTL_UNSOL
);
AZX
_GCTL_UNSOL
);
/* detect codecs */
if
(
!
chip
->
codec_mask
)
{
...
...
@@ -1657,7 +1572,7 @@ static void azx_int_enable(struct azx *chip)
{
/* enable controller CIE and GIE */
azx_writel
(
chip
,
INTCTL
,
azx_readl
(
chip
,
INTCTL
)
|
ICH6_INT_CTRL_EN
|
ICH6
_INT_GLOBAL_EN
);
AZX_INT_CTRL_EN
|
AZX
_INT_GLOBAL_EN
);
}
/* disable interrupts */
...
...
@@ -1678,7 +1593,7 @@ static void azx_int_disable(struct azx *chip)
/* disable controller CIE and GIE */
azx_writel
(
chip
,
INTCTL
,
azx_readl
(
chip
,
INTCTL
)
&
~
(
ICH6_INT_CTRL_EN
|
ICH6
_INT_GLOBAL_EN
));
~
(
AZX_INT_CTRL_EN
|
AZX
_INT_GLOBAL_EN
));
}
/* clear interrupts */
...
...
@@ -1699,7 +1614,7 @@ static void azx_int_clear(struct azx *chip)
azx_writeb
(
chip
,
RIRBSTS
,
RIRB_INT_MASK
);
/* clear int status */
azx_writel
(
chip
,
INTSTS
,
ICH6_INT_CTRL_EN
|
ICH6
_INT_ALL_STREAM
);
azx_writel
(
chip
,
INTSTS
,
AZX_INT_CTRL_EN
|
AZX
_INT_ALL_STREAM
);
}
/*
...
...
@@ -2031,5 +1946,30 @@ int azx_init_stream(struct azx *chip)
}
EXPORT_SYMBOL_GPL
(
azx_init_stream
);
/*
* reboot notifier for hang-up problem at power-down
*/
static
int
azx_halt
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
buf
)
{
struct
azx
*
chip
=
container_of
(
nb
,
struct
azx
,
reboot_notifier
);
snd_hda_bus_reboot_notify
(
chip
->
bus
);
azx_stop_chip
(
chip
);
return
NOTIFY_OK
;
}
void
azx_notifier_register
(
struct
azx
*
chip
)
{
chip
->
reboot_notifier
.
notifier_call
=
azx_halt
;
register_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
EXPORT_SYMBOL_GPL
(
azx_notifier_register
);
void
azx_notifier_unregister
(
struct
azx
*
chip
)
{
if
(
chip
->
reboot_notifier
.
notifier_call
)
unregister_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
EXPORT_SYMBOL_GPL
(
azx_notifier_unregister
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"Common HDA driver funcitons"
);
sound/pci/hda/hda_controller.h
浏览文件 @
84526820
...
...
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
{
return
substream
->
runtime
->
private_data
;
}
unsigned
int
azx_get_position
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
,
bool
with_check
);
unsigned
int
azx_get_position
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
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_stream_stop
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
...
...
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
int
azx_mixer_create
(
struct
azx
*
chip
);
int
azx_init_stream
(
struct
azx
*
chip
);
void
azx_notifier_register
(
struct
azx
*
chip
);
void
azx_notifier_unregister
(
struct
azx
*
chip
);
#endif
/* __SOUND_HDA_CONTROLLER_H */
sound/pci/hda/hda_intel.c
浏览文件 @
84526820
...
...
@@ -44,7 +44,6 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/reboot.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/clocksource.h>
...
...
@@ -66,6 +65,52 @@
#include "hda_controller.h"
#include "hda_priv.h"
/* position fix mode */
enum
{
POS_FIX_AUTO
,
POS_FIX_LPIB
,
POS_FIX_POSBUF
,
POS_FIX_VIACOMBO
,
POS_FIX_COMBO
,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
/* Defines for Nvidia HDA support */
#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
#define NVIDIA_HDA_ISTRM_COH 0x4d
#define NVIDIA_HDA_OSTRM_COH 0x4c
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
/* Defines for Intel SCH HDA snoop control */
#define INTEL_SCH_HDA_DEVC 0x78
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
/* Define IN stream 0 FIFO size offset in VIA controller */
#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID 0x3288
/* max number of SDs */
/* ICH, ATI and VIA have 4 playback and 4 capture */
#define ICH6_NUM_CAPTURE 4
#define ICH6_NUM_PLAYBACK 4
/* ULI has 6 playback and 5 capture */
#define ULI_NUM_CAPTURE 5
#define ULI_NUM_PLAYBACK 6
/* ATI HDMI may have up to 8 playbacks and 0 capture */
#define ATIHDMI_NUM_CAPTURE 0
#define ATIHDMI_NUM_PLAYBACK 8
/* TERA has 4 playback and 3 capture */
#define TERA_NUM_CAPTURE 3
#define TERA_NUM_PLAYBACK 4
static
int
index
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IDX
;
static
char
*
id
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_STR
;
...
...
@@ -294,8 +339,8 @@ static char *driver_short_names[] = {
* Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
* The values will be lost when the display power well is disabled.
*/
#define
ICH6
_REG_EM4 0x100c
#define
ICH6
_REG_EM5 0x1010
#define
AZX
_REG_EM4 0x100c
#define
AZX
_REG_EM5 0x1010
struct
hda_intel
{
struct
azx
chip
;
...
...
@@ -303,8 +348,28 @@ struct hda_intel {
/* HSW/BDW display HDA controller to restore BCLK from CDCLK */
unsigned
int
bclk_m
;
unsigned
int
bclk_n
;
};
/* for pending irqs */
struct
work_struct
irq_pending_work
;
/* sync probing */
struct
completion
probe_wait
;
struct
work_struct
probe_work
;
/* card list (for power_save trigger) */
struct
list_head
list
;
/* extra flags */
unsigned
int
irq_pending_warned
:
1
;
/* VGA-switcheroo setup */
unsigned
int
use_vga_switcheroo
:
1
;
unsigned
int
vga_switcheroo_registered
:
1
;
unsigned
int
init_failed
:
1
;
/* delayed init failed */
/* secondary power domain for hdmi audio under vga device */
struct
dev_pm_domain
hdmi_pm_domain
;
};
#ifdef CONFIG_X86
static
void
__mark_pages_wc
(
struct
azx
*
chip
,
struct
snd_dma_buffer
*
dmab
,
bool
on
)
...
...
@@ -386,7 +451,7 @@ static void azx_init_pci(struct azx *chip)
*/
if
(
!
(
chip
->
driver_caps
&
AZX_DCAPS_NO_TCSEL
))
{
dev_dbg
(
chip
->
card
->
dev
,
"Clearing TCSEL
\n
"
);
update_pci_byte
(
chip
->
pci
,
ICH6
_PCIREG_TCSEL
,
0x07
,
0
);
update_pci_byte
(
chip
->
pci
,
AZX
_PCIREG_TCSEL
,
0x07
,
0
);
}
/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
...
...
@@ -434,11 +499,44 @@ static void azx_init_pci(struct azx *chip)
}
}
/* calculate runtime delay from LPIB */
static
int
azx_get_delay_from_lpib
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
,
unsigned
int
pos
)
{
struct
snd_pcm_substream
*
substream
=
azx_dev
->
substream
;
int
stream
=
substream
->
stream
;
unsigned
int
lpib_pos
=
azx_get_pos_lpib
(
chip
,
azx_dev
);
int
delay
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
delay
=
pos
-
lpib_pos
;
else
delay
=
lpib_pos
-
pos
;
if
(
delay
<
0
)
{
if
(
delay
>=
azx_dev
->
delay_negative_threshold
)
delay
=
0
;
else
delay
+=
azx_dev
->
bufsize
;
}
if
(
delay
>=
azx_dev
->
period_bytes
)
{
dev_info
(
chip
->
card
->
dev
,
"Unstable LPIB (%d >= %d); disabling LPIB delay counting
\n
"
,
delay
,
azx_dev
->
period_bytes
);
delay
=
0
;
chip
->
driver_caps
&=
~
AZX_DCAPS_COUNT_LPIB_DELAY
;
chip
->
get_delay
[
stream
]
=
NULL
;
}
return
bytes_to_frames
(
substream
->
runtime
,
delay
);
}
static
int
azx_position_ok
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
/* called from IRQ */
static
int
azx_position_check
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
int
ok
;
ok
=
azx_position_ok
(
chip
,
azx_dev
);
...
...
@@ -448,7 +546,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
}
else
if
(
ok
==
0
&&
chip
->
bus
&&
chip
->
bus
->
workq
)
{
/* bogus IRQ, process it later */
azx_dev
->
irq_pending
=
1
;
queue_work
(
chip
->
bus
->
workq
,
&
chip
->
irq_pending_work
);
queue_work
(
chip
->
bus
->
workq
,
&
hda
->
irq_pending_work
);
}
return
0
;
}
...
...
@@ -464,6 +562,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
*/
static
int
azx_position_ok
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
{
struct
snd_pcm_substream
*
substream
=
azx_dev
->
substream
;
int
stream
=
substream
->
stream
;
u32
wallclk
;
unsigned
int
pos
;
...
...
@@ -471,7 +571,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
if
(
wallclk
<
(
azx_dev
->
period_wallclk
*
2
)
/
3
)
return
-
1
;
/* bogus (too early) interrupt */
pos
=
azx_get_position
(
chip
,
azx_dev
,
true
);
if
(
chip
->
get_position
[
stream
])
pos
=
chip
->
get_position
[
stream
](
chip
,
azx_dev
);
else
{
/* use the position buffer as default */
pos
=
azx_get_pos_posbuf
(
chip
,
azx_dev
);
if
(
!
pos
||
pos
==
(
u32
)
-
1
)
{
dev_info
(
chip
->
card
->
dev
,
"Invalid position buffer, using LPIB read method instead.
\n
"
);
chip
->
get_position
[
stream
]
=
azx_get_pos_lpib
;
pos
=
azx_get_pos_lpib
(
chip
,
azx_dev
);
chip
->
get_delay
[
stream
]
=
NULL
;
}
else
{
chip
->
get_position
[
stream
]
=
azx_get_pos_posbuf
;
if
(
chip
->
driver_caps
&
AZX_DCAPS_COUNT_LPIB_DELAY
)
chip
->
get_delay
[
stream
]
=
azx_get_delay_from_lpib
;
}
}
if
(
pos
>=
azx_dev
->
bufsize
)
pos
=
0
;
if
(
WARN_ONCE
(
!
azx_dev
->
period_bytes
,
"hda-intel: zero azx_dev->period_bytes"
))
...
...
@@ -489,14 +607,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
*/
static
void
azx_irq_pending_work
(
struct
work_struct
*
work
)
{
struct
azx
*
chip
=
container_of
(
work
,
struct
azx
,
irq_pending_work
);
struct
hda_intel
*
hda
=
container_of
(
work
,
struct
hda_intel
,
irq_pending_work
);
struct
azx
*
chip
=
&
hda
->
chip
;
int
i
,
pending
,
ok
;
if
(
!
chip
->
irq_pending_warned
)
{
if
(
!
hda
->
irq_pending_warned
)
{
dev_info
(
chip
->
card
->
dev
,
"IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.
\n
"
,
chip
->
card
->
number
);
chip
->
irq_pending_warned
=
1
;
hda
->
irq_pending_warned
=
1
;
}
for
(;;)
{
...
...
@@ -554,27 +673,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
return
0
;
}
/* get the current DMA position with correction on VIA chips */
static
unsigned
int
azx_via_get_position
(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
)
{
unsigned
int
link_pos
,
mini_pos
,
bound_pos
;
unsigned
int
mod_link_pos
,
mod_dma_pos
,
mod_mini_pos
;
unsigned
int
fifo_size
;
link_pos
=
azx_sd_readl
(
chip
,
azx_dev
,
SD_LPIB
);
if
(
azx_dev
->
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
/* Playback, no problem using link position */
return
link_pos
;
}
/* Capture */
/* For new chipset,
* use mod to get the DMA position just like old chipset
*/
mod_dma_pos
=
le32_to_cpu
(
*
azx_dev
->
posbuf
);
mod_dma_pos
%=
azx_dev
->
period_bytes
;
/* azx_dev->fifo_size can't get FIFO size of in stream.
* Get from base address + offset.
*/
fifo_size
=
readw
(
chip
->
remap_addr
+
VIA_IN_STREAM0_FIFO_SIZE_OFFSET
);
if
(
azx_dev
->
insufficient
)
{
/* Link position never gather than FIFO size */
if
(
link_pos
<=
fifo_size
)
return
0
;
azx_dev
->
insufficient
=
0
;
}
if
(
link_pos
<=
fifo_size
)
mini_pos
=
azx_dev
->
bufsize
+
link_pos
-
fifo_size
;
else
mini_pos
=
link_pos
-
fifo_size
;
/* Find nearest previous boudary */
mod_mini_pos
=
mini_pos
%
azx_dev
->
period_bytes
;
mod_link_pos
=
link_pos
%
azx_dev
->
period_bytes
;
if
(
mod_link_pos
>=
fifo_size
)
bound_pos
=
link_pos
-
mod_link_pos
;
else
if
(
mod_dma_pos
>=
mod_mini_pos
)
bound_pos
=
mini_pos
-
mod_mini_pos
;
else
{
bound_pos
=
mini_pos
-
mod_mini_pos
+
azx_dev
->
period_bytes
;
if
(
bound_pos
>=
azx_dev
->
bufsize
)
bound_pos
=
0
;
}
/* Calculate real DMA position we want */
return
bound_pos
+
mod_dma_pos
;
}
#ifdef CONFIG_PM
static
DEFINE_MUTEX
(
card_list_lock
);
static
LIST_HEAD
(
card_list
);
static
void
azx_add_card_list
(
struct
azx
*
chip
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
mutex_lock
(
&
card_list_lock
);
list_add
(
&
chip
->
list
,
&
card_list
);
list_add
(
&
hda
->
list
,
&
card_list
);
mutex_unlock
(
&
card_list_lock
);
}
static
void
azx_del_card_list
(
struct
azx
*
chip
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
mutex_lock
(
&
card_list_lock
);
list_del_init
(
&
chip
->
list
);
list_del_init
(
&
hda
->
list
);
mutex_unlock
(
&
card_list_lock
);
}
/* trigger power-save check at writing parameter */
static
int
param_set_xint
(
const
char
*
val
,
const
struct
kernel_param
*
kp
)
{
struct
hda_intel
*
hda
;
struct
azx
*
chip
;
struct
hda_codec
*
c
;
int
prev
=
power_save
;
...
...
@@ -584,7 +762,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
return
ret
;
mutex_lock
(
&
card_list_lock
);
list_for_each_entry
(
chip
,
&
card_list
,
list
)
{
list_for_each_entry
(
hda
,
&
card_list
,
list
)
{
chip
=
&
hda
->
chip
;
if
(
!
chip
->
bus
||
chip
->
disabled
)
continue
;
list_for_each_entry
(
c
,
&
chip
->
bus
->
codec_list
,
list
)
...
...
@@ -789,29 +968,6 @@ static const struct dev_pm_ops azx_pm = {
#endif
/* CONFIG_PM */
/*
* reboot notifier for hang-up problem at power-down
*/
static
int
azx_halt
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
buf
)
{
struct
azx
*
chip
=
container_of
(
nb
,
struct
azx
,
reboot_notifier
);
snd_hda_bus_reboot_notify
(
chip
->
bus
);
azx_stop_chip
(
chip
);
return
NOTIFY_OK
;
}
static
void
azx_notifier_register
(
struct
azx
*
chip
)
{
chip
->
reboot_notifier
.
notifier_call
=
azx_halt
;
register_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
static
void
azx_notifier_unregister
(
struct
azx
*
chip
)
{
if
(
chip
->
reboot_notifier
.
notifier_call
)
unregister_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
static
int
azx_probe_continue
(
struct
azx
*
chip
);
#ifdef SUPPORT_VGA_SWITCHEROO
...
...
@@ -822,10 +978,11 @@ static void azx_vs_set_state(struct pci_dev *pci,
{
struct
snd_card
*
card
=
pci_get_drvdata
(
pci
);
struct
azx
*
chip
=
card
->
private_data
;
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
bool
disabled
;
wait_for_completion
(
&
chip
->
probe_wait
);
if
(
chip
->
init_failed
)
wait_for_completion
(
&
hda
->
probe_wait
);
if
(
hda
->
init_failed
)
return
;
disabled
=
(
state
==
VGA_SWITCHEROO_OFF
);
...
...
@@ -839,7 +996,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
"Start delayed initialization
\n
"
);
if
(
azx_probe_continue
(
chip
)
<
0
)
{
dev_err
(
chip
->
card
->
dev
,
"initialization error
\n
"
);
chip
->
init_failed
=
true
;
hda
->
init_failed
=
true
;
}
}
}
else
{
...
...
@@ -869,9 +1026,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
{
struct
snd_card
*
card
=
pci_get_drvdata
(
pci
);
struct
azx
*
chip
=
card
->
private_data
;
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
wait_for_completion
(
&
chip
->
probe_wait
);
if
(
chip
->
init_failed
)
wait_for_completion
(
&
hda
->
probe_wait
);
if
(
hda
->
init_failed
)
return
false
;
if
(
chip
->
disabled
||
!
chip
->
bus
)
return
true
;
...
...
@@ -883,11 +1041,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
static
void
init_vga_switcheroo
(
struct
azx
*
chip
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
struct
pci_dev
*
p
=
get_bound_vga
(
chip
->
pci
);
if
(
p
)
{
dev_info
(
chip
->
card
->
dev
,
"Handle VGA-switcheroo audio client
\n
"
);
chip
->
use_vga_switcheroo
=
1
;
hda
->
use_vga_switcheroo
=
1
;
pci_dev_put
(
p
);
}
}
...
...
@@ -899,9 +1058,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
static
int
register_vga_switcheroo
(
struct
azx
*
chip
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
int
err
;
if
(
!
chip
->
use_vga_switcheroo
)
if
(
!
hda
->
use_vga_switcheroo
)
return
0
;
/* FIXME: currently only handling DIS controller
* is there any machine with two switchable HDMI audio controllers?
...
...
@@ -911,11 +1071,11 @@ static int register_vga_switcheroo(struct azx *chip)
chip
->
bus
!=
NULL
);
if
(
err
<
0
)
return
err
;
chip
->
vga_switcheroo_registered
=
1
;
hda
->
vga_switcheroo_registered
=
1
;
/* register as an optimus hdmi audio power domain */
vga_switcheroo_init_domain_pm_optimus_hdmi_audio
(
chip
->
card
->
dev
,
&
chip
->
hdmi_pm_domain
);
&
hda
->
hdmi_pm_domain
);
return
0
;
}
#else
...
...
@@ -931,7 +1091,6 @@ static int azx_free(struct azx *chip)
{
struct
pci_dev
*
pci
=
chip
->
pci
;
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
int
i
;
if
((
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
)
...
...
@@ -942,13 +1101,13 @@ static int azx_free(struct azx *chip)
azx_notifier_unregister
(
chip
);
chip
->
init_failed
=
1
;
/* to be sure */
complete_all
(
&
chip
->
probe_wait
);
hda
->
init_failed
=
1
;
/* to be sure */
complete_all
(
&
hda
->
probe_wait
);
if
(
use_vga_switcheroo
(
chip
))
{
if
(
use_vga_switcheroo
(
hda
))
{
if
(
chip
->
disabled
&&
chip
->
bus
)
snd_hda_unlock_devices
(
chip
->
bus
);
if
(
chip
->
vga_switcheroo_registered
)
if
(
hda
->
vga_switcheroo_registered
)
vga_switcheroo_unregister_client
(
chip
->
pci
);
}
...
...
@@ -1084,6 +1243,30 @@ static int check_position_fix(struct azx *chip, int fix)
return
POS_FIX_AUTO
;
}
static
void
assign_position_fix
(
struct
azx
*
chip
,
int
fix
)
{
static
azx_get_pos_callback_t
callbacks
[]
=
{
[
POS_FIX_AUTO
]
=
NULL
,
[
POS_FIX_LPIB
]
=
azx_get_pos_lpib
,
[
POS_FIX_POSBUF
]
=
azx_get_pos_posbuf
,
[
POS_FIX_VIACOMBO
]
=
azx_via_get_position
,
[
POS_FIX_COMBO
]
=
azx_get_pos_lpib
,
};
chip
->
get_position
[
0
]
=
chip
->
get_position
[
1
]
=
callbacks
[
fix
];
/* combo mode uses LPIB only for playback */
if
(
fix
==
POS_FIX_COMBO
)
chip
->
get_position
[
1
]
=
NULL
;
if
(
fix
==
POS_FIX_POSBUF
&&
(
chip
->
driver_caps
&
AZX_DCAPS_COUNT_LPIB_DELAY
))
{
chip
->
get_delay
[
0
]
=
chip
->
get_delay
[
1
]
=
azx_get_delay_from_lpib
;
}
}
/*
* black-lists for probe_mask
*/
...
...
@@ -1209,7 +1392,8 @@ static void azx_check_snoop_available(struct azx *chip)
static
void
azx_probe_work
(
struct
work_struct
*
work
)
{
azx_probe_continue
(
container_of
(
work
,
struct
azx
,
probe_work
));
struct
hda_intel
*
hda
=
container_of
(
work
,
struct
hda_intel
,
probe_work
);
azx_probe_continue
(
&
hda
->
chip
);
}
/*
...
...
@@ -1252,19 +1436,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
check_msi
(
chip
);
chip
->
dev_index
=
dev
;
chip
->
jackpoll_ms
=
jackpoll_ms
;
INIT_WORK
(
&
chip
->
irq_pending_work
,
azx_irq_pending_work
);
INIT_LIST_HEAD
(
&
chip
->
pcm_list
);
INIT_LIST_HEAD
(
&
chip
->
list
);
INIT_WORK
(
&
hda
->
irq_pending_work
,
azx_irq_pending_work
);
INIT_LIST_HEAD
(
&
hda
->
list
);
init_vga_switcheroo
(
chip
);
init_completion
(
&
chip
->
probe_wait
);
init_completion
(
&
hda
->
probe_wait
);
chip
->
position_fix
[
0
]
=
chip
->
position_fix
[
1
]
=
check_position_fix
(
chip
,
position_fix
[
dev
]);
/* combo mode uses LPIB for playback */
if
(
chip
->
position_fix
[
0
]
==
POS_FIX_COMBO
)
{
chip
->
position_fix
[
0
]
=
POS_FIX_LPIB
;
chip
->
position_fix
[
1
]
=
POS_FIX_AUTO
;
}
assign_position_fix
(
chip
,
check_position_fix
(
chip
,
position_fix
[
dev
]));
check_probe_mask
(
chip
,
dev
);
...
...
@@ -1293,7 +1471,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
}
/* continue probing in work context as may trigger request module */
INIT_WORK
(
&
chip
->
probe_work
,
azx_probe_work
);
INIT_WORK
(
&
hda
->
probe_work
,
azx_probe_work
);
*
rchip
=
chip
;
...
...
@@ -1351,7 +1529,7 @@ static int azx_first_init(struct azx *chip)
NULL
);
if
(
p_smbus
)
{
if
(
p_smbus
->
revision
<
0x30
)
gcap
&=
~
ICH6
_GCAP_64OK
;
gcap
&=
~
AZX
_GCAP_64OK
;
pci_dev_put
(
p_smbus
);
}
}
...
...
@@ -1359,7 +1537,7 @@ static int azx_first_init(struct azx *chip)
/* disable 64bit DMA address on some devices */
if
(
chip
->
driver_caps
&
AZX_DCAPS_NO_64BIT
)
{
dev_dbg
(
card
->
dev
,
"Disabling 64bit DMA
\n
"
);
gcap
&=
~
ICH6
_GCAP_64OK
;
gcap
&=
~
AZX
_GCAP_64OK
;
}
/* disable buffer size rounding to 128-byte multiples if supported */
...
...
@@ -1375,7 +1553,7 @@ static int azx_first_init(struct azx *chip)
}
/* allow 64bit DMA address if supported by H/W */
if
((
gcap
&
ICH6
_GCAP_64OK
)
&&
!
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
64
)))
if
((
gcap
&
AZX
_GCAP_64OK
)
&&
!
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
64
)))
pci_set_consistent_dma_mask
(
pci
,
DMA_BIT_MASK
(
64
));
else
{
pci_set_dma_mask
(
pci
,
DMA_BIT_MASK
(
32
));
...
...
@@ -1615,6 +1793,7 @@ static int azx_probe(struct pci_dev *pci,
{
static
int
dev
;
struct
snd_card
*
card
;
struct
hda_intel
*
hda
;
struct
azx
*
chip
;
bool
schedule_probe
;
int
err
;
...
...
@@ -1638,6 +1817,7 @@ static int azx_probe(struct pci_dev *pci,
if
(
err
<
0
)
goto
out_free
;
card
->
private_data
=
chip
;
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
pci_set_drvdata
(
pci
,
card
);
...
...
@@ -1674,11 +1854,11 @@ static int azx_probe(struct pci_dev *pci,
#endif
if
(
schedule_probe
)
schedule_work
(
&
chip
->
probe_work
);
schedule_work
(
&
hda
->
probe_work
);
dev
++
;
if
(
chip
->
disabled
)
complete_all
(
&
chip
->
probe_wait
);
complete_all
(
&
hda
->
probe_wait
);
return
0
;
out_free:
...
...
@@ -1694,6 +1874,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
static
int
azx_probe_continue
(
struct
azx
*
chip
)
{
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
struct
pci_dev
*
pci
=
chip
->
pci
;
int
dev
=
chip
->
dev_index
;
int
err
;
...
...
@@ -1767,13 +1948,13 @@ static int azx_probe_continue(struct azx *chip)
power_down_all_codecs
(
chip
);
azx_notifier_register
(
chip
);
azx_add_card_list
(
chip
);
if
((
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
)
||
chip
->
use_vga_switcheroo
)
if
((
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
)
||
hda
->
use_vga_switcheroo
)
pm_runtime_put_noidle
(
&
pci
->
dev
);
out_free:
if
(
err
<
0
)
chip
->
init_failed
=
1
;
complete_all
(
&
chip
->
probe_wait
);
hda
->
init_failed
=
1
;
complete_all
(
&
hda
->
probe_wait
);
return
err
;
}
...
...
sound/pci/hda/hda_priv.h
浏览文件 @
84526820
...
...
@@ -22,107 +22,87 @@
/*
* registers
*/
#define
ICH6
_REG_GCAP 0x00
#define
ICH6_GCAP_64OK
(1 << 0)
/* 64bit address support */
#define
ICH6_GCAP_NSDO
(3 << 1)
/* # of serial data out signals */
#define
ICH6
_GCAP_BSS (31 << 3)
/* # of bidirectional streams */
#define
ICH6
_GCAP_ISS (15 << 8)
/* # of input streams */
#define
ICH6
_GCAP_OSS (15 << 12)
/* # of output streams */
#define
ICH6
_REG_VMIN 0x02
#define
ICH6
_REG_VMAJ 0x03
#define
ICH6
_REG_OUTPAY 0x04
#define
ICH6
_REG_INPAY 0x06
#define
ICH6
_REG_GCTL 0x08
#define
ICH6
_GCTL_RESET (1 << 0)
/* controller reset */
#define
ICH6
_GCTL_FCNTRL (1 << 1)
/* flush control */
#define
ICH6
_GCTL_UNSOL (1 << 8)
/* accept unsol. response enable */
#define
ICH6
_REG_WAKEEN 0x0c
#define
ICH6
_REG_STATESTS 0x0e
#define
ICH6
_REG_GSTS 0x10
#define
ICH6_GSTS_FSTS
(1 << 1)
/* flush status */
#define
ICH6
_REG_INTCTL 0x20
#define
ICH6
_REG_INTSTS 0x24
#define
ICH6_REG_WALLCLK
0x30
/* 24Mhz source */
#define
ICH6
_REG_OLD_SSYNC 0x34
/* SSYNC for old ICH */
#define
ICH6
_REG_SSYNC 0x38
#define
ICH6
_REG_CORBLBASE 0x40
#define
ICH6
_REG_CORBUBASE 0x44
#define
ICH6
_REG_CORBWP 0x48
#define
ICH6
_REG_CORBRP 0x4a
#define
ICH6
_CORBRP_RST (1 << 15)
/* read pointer reset */
#define
ICH6_REG_CORBCTL
0x4c
#define
ICH6
_CORBCTL_RUN (1 << 1)
/* enable DMA */
#define
ICH6
_CORBCTL_CMEIE (1 << 0)
/* enable memory error irq */
#define
ICH6_REG_CORBSTS
0x4d
#define
ICH6
_CORBSTS_CMEI (1 << 0)
/* memory error indication */
#define
ICH6
_REG_CORBSIZE 0x4e
#define
ICH6
_REG_RIRBLBASE 0x50
#define
ICH6
_REG_RIRBUBASE 0x54
#define
ICH6
_REG_RIRBWP 0x58
#define
ICH6
_RIRBWP_RST (1 << 15)
/* write pointer reset */
#define
ICH6_REG_RINTCNT
0x5a
#define
ICH6_REG_RIRBCTL
0x5c
#define
ICH6
_RBCTL_IRQ_EN (1 << 0)
/* enable IRQ */
#define
ICH6
_RBCTL_DMA_EN (1 << 1)
/* enable DMA */
#define
ICH6
_RBCTL_OVERRUN_EN (1 << 2)
/* enable overrun irq */
#define
ICH6_REG_RIRBSTS
0x5d
#define
ICH6_RBSTS_IRQ
(1 << 0)
/* response irq */
#define
ICH6
_RBSTS_OVERRUN (1 << 2)
/* overrun irq */
#define
ICH6
_REG_RIRBSIZE 0x5e
#define
ICH6
_REG_IC 0x60
#define
ICH6
_REG_IR 0x64
#define
ICH6
_REG_IRS 0x68
#define
ICH6_IRS_VALID
(1<<1)
#define
ICH6
_IRS_BUSY (1<<0)
#define
ICH6_REG_DPLBASE
0x70
#define
ICH6_REG_DPUBASE
0x74
#define
ICH6
_DPLBASE_ENABLE 0x1
/* Enable position buffer */
#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
ICH6
_REG_SD_CTL 0x00
#define
ICH6
_REG_SD_STS 0x03
#define
ICH6_REG_SD_LPIB
0x04
#define
ICH6
_REG_SD_CBL 0x08
#define
ICH6
_REG_SD_LVI 0x0c
#define
ICH6
_REG_SD_FIFOW 0x0e
#define
ICH6
_REG_SD_FIFOSIZE 0x10
#define
ICH6
_REG_SD_FORMAT 0x12
#define
ICH6
_REG_SD_BDLPL 0x18
#define
ICH6
_REG_SD_BDLPU 0x1c
#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
ICH6_PCIREG_TCSEL
0x44
#define
AZX_PCIREG_TCSEL
0x44
/*
* other constants
*/
/* max number of SDs */
/* ICH, ATI and VIA have 4 playback and 4 capture */
#define ICH6_NUM_CAPTURE 4
#define ICH6_NUM_PLAYBACK 4
/* ULI has 6 playback and 5 capture */
#define ULI_NUM_CAPTURE 5
#define ULI_NUM_PLAYBACK 6
/* ATI HDMI may have up to 8 playbacks and 0 capture */
#define ATIHDMI_NUM_CAPTURE 0
#define ATIHDMI_NUM_PLAYBACK 8
/* TERA has 4 playback and 3 capture */
#define TERA_NUM_CAPTURE 3
#define TERA_NUM_PLAYBACK 4
/* this number is statically defined for simplicity */
#define MAX_AZX_DEV 16
/* 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)
...
...
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define SD_STS_FIFO_READY 0x20
/* FIFO ready */
/* INTCTL and INTSTS */
#define
ICH6
_INT_ALL_STREAM 0xff
/* all stream interrupts */
#define
ICH6
_INT_CTRL_EN 0x40000000
/* controller interrupt enable bit */
#define
ICH6
_INT_GLOBAL_EN 0x80000000
/* global interrupt enable bit */
#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
ICH6
_MAX_CORB_ENTRIES 256
#define
ICH6
_MAX_RIRB_ENTRIES 256
#define
AZX
_MAX_CORB_ENTRIES 256
#define
AZX
_MAX_RIRB_ENTRIES 256
/* driver quirks (capabilities) */
/* bits 0-7 are used for indicating driver type */
...
...
@@ -191,35 +171,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_DCAPS_I915_POWERWELL (1 << 27)
/* HSW i915 powerwell support */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)
/* CORBRP clears itself after reset */
/* position fix mode */
enum
{
POS_FIX_AUTO
,
POS_FIX_LPIB
,
POS_FIX_POSBUF
,
POS_FIX_VIACOMBO
,
POS_FIX_COMBO
,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
/* Defines for Nvidia HDA support */
#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
#define NVIDIA_HDA_ISTRM_COH 0x4d
#define NVIDIA_HDA_OSTRM_COH 0x4c
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
/* Defines for Intel SCH HDA snoop control */
#define INTEL_SCH_HDA_DEVC 0x78
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
/* Define IN stream 0 FIFO size offset in VIA controller */
#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID 0x3288
/* HD Audio class code */
#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
...
...
@@ -324,6 +275,9 @@ struct azx_pcm {
struct
list_head
list
;
};
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
snd_card
*
card
;
struct
pci_dev
*
pci
;
...
...
@@ -342,6 +296,10 @@ struct azx {
/* Register interaction. */
const
struct
hda_controller_ops
*
ops
;
/* position adjustment callbacks */
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
;
...
...
@@ -350,7 +308,6 @@ struct azx {
/* locks */
spinlock_t
reg_lock
;
struct
mutex
open_mutex
;
/* Prevents concurrent open/close operations */
struct
completion
probe_wait
;
/* streams (x num_streams) */
struct
azx_dev
*
azx_dev
;
...
...
@@ -377,7 +334,6 @@ struct azx {
#endif
/* flags */
int
position_fix
[
2
];
/* for both playback/capture streams */
const
int
*
bdl_pos_adj
;
int
poll_count
;
unsigned
int
running
:
1
;
...
...
@@ -385,46 +341,23 @@ struct azx {
unsigned
int
single_cmd
:
1
;
unsigned
int
polling_mode
:
1
;
unsigned
int
msi
:
1
;
unsigned
int
irq_pending_warned
:
1
;
unsigned
int
probing
:
1
;
/* codec probing phase */
unsigned
int
snoop
:
1
;
unsigned
int
align_buffer_size
:
1
;
unsigned
int
region_requested
:
1
;
/* VGA-switcheroo setup */
unsigned
int
use_vga_switcheroo
:
1
;
unsigned
int
vga_switcheroo_registered
:
1
;
unsigned
int
init_failed
:
1
;
/* delayed init failed */
unsigned
int
disabled
:
1
;
/* disabled by VGA-switcher */
/* for debugging */
unsigned
int
last_cmd
[
AZX_MAX_CODECS
];
/* for pending irqs */
struct
work_struct
irq_pending_work
;
struct
work_struct
probe_work
;
/* reboot notifier (for mysterious hangup problem at power-down) */
struct
notifier_block
reboot_notifier
;
/* card list (for power_save trigger) */
struct
list_head
list
;
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct
azx_dev
saved_azx_dev
;
#endif
/* secondary power domain for hdmi audio under vga device */
struct
dev_pm_domain
hdmi_pm_domain
;
};
#ifdef CONFIG_SND_VERBOSE_PRINTK
#define SFX
/* nop */
#else
#define SFX "hda-intel "
#endif
#ifdef CONFIG_X86
#define azx_snoop(chip) ((chip)->snoop)
#else
...
...
@@ -436,29 +369,29 @@ struct azx {
*/
#define azx_writel(chip, reg, value) \
((chip)->ops->reg_writel(value, (chip)->remap_addr +
ICH6
_REG_##reg))
((chip)->ops->reg_writel(value, (chip)->remap_addr +
AZX
_REG_##reg))
#define azx_readl(chip, reg) \
((chip)->ops->reg_readl((chip)->remap_addr +
ICH6
_REG_##reg))
((chip)->ops->reg_readl((chip)->remap_addr +
AZX
_REG_##reg))
#define azx_writew(chip, reg, value) \
((chip)->ops->reg_writew(value, (chip)->remap_addr +
ICH6
_REG_##reg))
((chip)->ops->reg_writew(value, (chip)->remap_addr +
AZX
_REG_##reg))
#define azx_readw(chip, reg) \
((chip)->ops->reg_readw((chip)->remap_addr +
ICH6
_REG_##reg))
((chip)->ops->reg_readw((chip)->remap_addr +
AZX
_REG_##reg))
#define azx_writeb(chip, reg, value) \
((chip)->ops->reg_writeb(value, (chip)->remap_addr +
ICH6
_REG_##reg))
((chip)->ops->reg_writeb(value, (chip)->remap_addr +
AZX
_REG_##reg))
#define azx_readb(chip, reg) \
((chip)->ops->reg_readb((chip)->remap_addr +
ICH6
_REG_##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 +
ICH6
_REG_##reg))
((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 +
ICH6
_REG_##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 +
ICH6
_REG_##reg))
((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 +
ICH6
_REG_##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 +
ICH6
_REG_##reg))
((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 +
ICH6
_REG_##reg))
((chip)->ops->reg_readb((dev)->sd_addr +
AZX
_REG_##reg))
#endif
/* __SOUND_HDA_PRIV_H */
sound/pci/hda/hda_tegra.c
浏览文件 @
84526820
...
...
@@ -29,7 +29,6 @@
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/time.h>
...
...
@@ -294,30 +293,6 @@ static const struct dev_pm_ops hda_tegra_pm = {
SET_SYSTEM_SLEEP_PM_OPS
(
hda_tegra_suspend
,
hda_tegra_resume
)
};
/*
* reboot notifier for hang-up problem at power-down
*/
static
int
hda_tegra_halt
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
buf
)
{
struct
azx
*
chip
=
container_of
(
nb
,
struct
azx
,
reboot_notifier
);
snd_hda_bus_reboot_notify
(
chip
->
bus
);
azx_stop_chip
(
chip
);
return
NOTIFY_OK
;
}
static
void
hda_tegra_notifier_register
(
struct
azx
*
chip
)
{
chip
->
reboot_notifier
.
notifier_call
=
hda_tegra_halt
;
register_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
static
void
hda_tegra_notifier_unregister
(
struct
azx
*
chip
)
{
if
(
chip
->
reboot_notifier
.
notifier_call
)
unregister_reboot_notifier
(
&
chip
->
reboot_notifier
);
}
/*
* destructor
*/
...
...
@@ -326,7 +301,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
int
i
;
struct
azx
*
chip
=
device
->
device_data
;
hda_tegra
_notifier_unregister
(
chip
);
azx
_notifier_unregister
(
chip
);
if
(
chip
->
initialized
)
{
for
(
i
=
0
;
i
<
chip
->
num_streams
;
i
++
)
...
...
@@ -480,8 +455,6 @@ static int hda_tegra_create(struct snd_card *card,
INIT_LIST_HEAD
(
&
chip
->
pcm_list
);
INIT_LIST_HEAD
(
&
chip
->
list
);
chip
->
position_fix
[
0
]
=
POS_FIX_AUTO
;
chip
->
position_fix
[
1
]
=
POS_FIX_AUTO
;
chip
->
codec_probe_mask
=
-
1
;
chip
->
single_cmd
=
false
;
...
...
@@ -559,7 +532,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
chip
->
running
=
1
;
power_down_all_codecs
(
chip
);
hda_tegra
_notifier_register
(
chip
);
azx
_notifier_register
(
chip
);
return
0
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录