Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
8d085d3c
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
8d085d3c
编写于
2月 23, 2015
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/hda-cleanup' into for-next
上级
88cacc57
781c7b96
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
493 addition
and
568 deletion
+493
-568
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.c
+21
-66
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+10
-12
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.c
+51
-45
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_controller.h
+392
-5
sound/pci/hda/hda_i915.c
sound/pci/hda/hda_i915.c
+1
-1
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+11
-12
sound/pci/hda/hda_intel.h
sound/pci/hda/hda_intel.h
+1
-1
sound/pci/hda/hda_local.h
sound/pci/hda/hda_local.h
+0
-17
sound/pci/hda/hda_priv.h
sound/pci/hda/hda_priv.h
+0
-406
sound/pci/hda/hda_tegra.c
sound/pci/hda/hda_tegra.c
+6
-3
未找到文件。
sound/pci/hda/hda_codec.c
浏览文件 @
8d085d3c
...
...
@@ -762,10 +762,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
return
0
;
trace_hda_unsol_event
(
bus
,
res
,
res_ex
);
unsol
=
bus
->
unsol
;
if
(
!
unsol
)
return
0
;
unsol
=
&
bus
->
unsol
;
wp
=
(
unsol
->
wp
+
1
)
%
HDA_UNSOL_QUEUE_SIZE
;
unsol
->
wp
=
wp
;
...
...
@@ -784,9 +781,8 @@ EXPORT_SYMBOL_GPL(snd_hda_queue_unsol_event);
*/
static
void
process_unsol_events
(
struct
work_struct
*
work
)
{
struct
hda_bus_unsolicited
*
unsol
=
container_of
(
work
,
struct
hda_bus_unsolicited
,
work
);
struct
hda_bus
*
bus
=
unsol
->
bus
;
struct
hda_bus
*
bus
=
container_of
(
work
,
struct
hda_bus
,
unsol
.
work
);
struct
hda_bus_unsolicited
*
unsol
=
&
bus
->
unsol
;
struct
hda_codec
*
codec
;
unsigned
int
rp
,
caddr
,
res
;
...
...
@@ -804,27 +800,6 @@ static void process_unsol_events(struct work_struct *work)
}
}
/*
* initialize unsolicited queue
*/
static
int
init_unsol_queue
(
struct
hda_bus
*
bus
)
{
struct
hda_bus_unsolicited
*
unsol
;
if
(
bus
->
unsol
)
/* already initialized */
return
0
;
unsol
=
kzalloc
(
sizeof
(
*
unsol
),
GFP_KERNEL
);
if
(
!
unsol
)
{
dev_err
(
bus
->
card
->
dev
,
"can't allocate unsolicited queue
\n
"
);
return
-
ENOMEM
;
}
INIT_WORK
(
&
unsol
->
work
,
process_unsol_events
);
unsol
->
bus
=
bus
;
bus
->
unsol
=
unsol
;
return
0
;
}
/*
* destructor
*/
...
...
@@ -836,7 +811,6 @@ static void snd_hda_bus_free(struct hda_bus *bus)
WARN_ON
(
!
list_empty
(
&
bus
->
codec_list
));
if
(
bus
->
workq
)
flush_workqueue
(
bus
->
workq
);
kfree
(
bus
->
unsol
);
if
(
bus
->
ops
.
private_free
)
bus
->
ops
.
private_free
(
bus
);
if
(
bus
->
workq
)
...
...
@@ -861,14 +835,12 @@ static int snd_hda_bus_dev_disconnect(struct snd_device *device)
/**
* snd_hda_bus_new - create a HDA bus
* @card: the card entry
* @temp: the template for hda_bus information
* @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
,
const
struct
hda_bus_template
*
temp
,
struct
hda_bus
**
busp
)
struct
hda_bus
**
busp
)
{
struct
hda_bus
*
bus
;
int
err
;
...
...
@@ -877,11 +849,6 @@ int snd_hda_bus_new(struct snd_card *card,
.
dev_free
=
snd_hda_bus_dev_free
,
};
if
(
snd_BUG_ON
(
!
temp
))
return
-
EINVAL
;
if
(
snd_BUG_ON
(
!
temp
->
ops
.
command
||
!
temp
->
ops
.
get_response
))
return
-
EINVAL
;
if
(
busp
)
*
busp
=
NULL
;
...
...
@@ -892,15 +859,10 @@ int snd_hda_bus_new(struct snd_card *card,
}
bus
->
card
=
card
;
bus
->
private_data
=
temp
->
private_data
;
bus
->
pci
=
temp
->
pci
;
bus
->
modelname
=
temp
->
modelname
;
bus
->
power_save
=
temp
->
power_save
;
bus
->
ops
=
temp
->
ops
;
mutex_init
(
&
bus
->
cmd_mutex
);
mutex_init
(
&
bus
->
prepare_mutex
);
INIT_LIST_HEAD
(
&
bus
->
codec_list
);
INIT_WORK
(
&
bus
->
unsol
.
work
,
process_unsol_events
);
snprintf
(
bus
->
workq_name
,
sizeof
(
bus
->
workq_name
),
"hd-audio%d"
,
card
->
number
);
...
...
@@ -1702,12 +1664,6 @@ int snd_hda_codec_configure(struct hda_codec *codec)
return
err
;
}
if
(
codec
->
patch_ops
.
unsol_event
)
{
err
=
init_unsol_queue
(
codec
->
bus
);
if
(
err
<
0
)
return
err
;
}
/* audio codec should override the mixer name */
if
(
codec
->
afg
||
!*
codec
->
bus
->
card
->
mixername
)
snprintf
(
codec
->
bus
->
card
->
mixername
,
...
...
@@ -2192,11 +2148,10 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
static
int
codec_amp_update
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
ch
,
int
direction
,
int
idx
,
int
mask
,
int
val
,
bool
init_only
)
bool
init_only
,
bool
cache_only
)
{
struct
hda_amp_info
*
info
;
unsigned
int
caps
;
unsigned
int
cache_only
;
if
(
snd_BUG_ON
(
mask
&
~
0xff
))
mask
&=
0xff
;
...
...
@@ -2214,7 +2169,7 @@ static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
return
0
;
}
info
->
vol
[
ch
]
=
val
;
cache_only
=
info
->
head
.
dirty
=
codec
->
cached_write
;
info
->
head
.
dirty
|=
cache_only
;
caps
=
info
->
amp_caps
;
mutex_unlock
(
&
codec
->
hash_mutex
);
if
(
!
cache_only
)
...
...
@@ -2238,7 +2193,8 @@ static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int
snd_hda_codec_amp_update
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
ch
,
int
direction
,
int
idx
,
int
mask
,
int
val
)
{
return
codec_amp_update
(
codec
,
nid
,
ch
,
direction
,
idx
,
mask
,
val
,
false
);
return
codec_amp_update
(
codec
,
nid
,
ch
,
direction
,
idx
,
mask
,
val
,
false
,
codec
->
cached_write
);
}
EXPORT_SYMBOL_GPL
(
snd_hda_codec_amp_update
);
...
...
@@ -2285,7 +2241,8 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
int
snd_hda_codec_amp_init
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
ch
,
int
dir
,
int
idx
,
int
mask
,
int
val
)
{
return
codec_amp_update
(
codec
,
nid
,
ch
,
dir
,
idx
,
mask
,
val
,
true
);
return
codec_amp_update
(
codec
,
nid
,
ch
,
dir
,
idx
,
mask
,
val
,
true
,
codec
->
cached_write
);
}
EXPORT_SYMBOL_GPL
(
snd_hda_codec_amp_init
);
...
...
@@ -2427,8 +2384,8 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
maxval
=
get_amp_max_value
(
codec
,
nid
,
dir
,
0
);
if
(
val
>
maxval
)
val
=
maxval
;
return
snd_hda_codec_amp_update
(
codec
,
nid
,
ch
,
dir
,
idx
,
HDA_AMP_VOLMASK
,
val
);
return
codec_amp_update
(
codec
,
nid
,
ch
,
dir
,
idx
,
HDA_AMP_VOLMASK
,
val
,
false
,
!
hda_codec_is_power_on
(
codec
)
);
}
/**
...
...
@@ -2478,14 +2435,12 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
long
*
valp
=
ucontrol
->
value
.
integer
.
value
;
int
change
=
0
;
snd_hda_power_up
(
codec
);
if
(
chs
&
1
)
{
change
=
update_amp_value
(
codec
,
nid
,
0
,
dir
,
idx
,
ofs
,
*
valp
);
valp
++
;
}
if
(
chs
&
2
)
change
|=
update_amp_value
(
codec
,
nid
,
1
,
dir
,
idx
,
ofs
,
*
valp
);
snd_hda_power_down
(
codec
);
return
change
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_mixer_amp_volume_put
);
...
...
@@ -3153,19 +3108,19 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
long
*
valp
=
ucontrol
->
value
.
integer
.
value
;
int
change
=
0
;
snd_hda_power_up
(
codec
);
if
(
chs
&
1
)
{
change
=
snd_hda_codec_amp_update
(
codec
,
nid
,
0
,
dir
,
idx
,
HDA_AMP_MUTE
,
*
valp
?
0
:
HDA_AMP_MUTE
);
change
=
codec_amp_update
(
codec
,
nid
,
0
,
dir
,
idx
,
HDA_AMP_MUTE
,
*
valp
?
0
:
HDA_AMP_MUTE
,
false
,
!
hda_codec_is_power_on
(
codec
));
valp
++
;
}
if
(
chs
&
2
)
change
|=
snd_hda_codec_amp_update
(
codec
,
nid
,
1
,
dir
,
idx
,
HDA_AMP_MUTE
,
*
valp
?
0
:
HDA_AMP_MUTE
);
change
|=
codec_amp_update
(
codec
,
nid
,
1
,
dir
,
idx
,
HDA_AMP_MUTE
,
*
valp
?
0
:
HDA_AMP_MUTE
,
false
,
!
hda_codec_is_power_on
(
codec
));
hda_call_check_power_status
(
codec
,
nid
);
snd_hda_power_down
(
codec
);
return
change
;
}
EXPORT_SYMBOL_GPL
(
snd_hda_mixer_amp_switch_put
);
...
...
sound/pci/hda/hda_codec.h
浏览文件 @
8d085d3c
...
...
@@ -66,7 +66,6 @@ struct hda_beep;
struct
hda_codec
;
struct
hda_pcm
;
struct
hda_pcm_stream
;
struct
hda_bus_unsolicited
;
/* NID type */
typedef
u16
hda_nid_t
;
...
...
@@ -101,13 +100,14 @@ struct hda_bus_ops {
#endif
};
/* template to pass to the bus constructor */
struct
hda_bus_template
{
void
*
private_data
;
struct
pci_dev
*
pci
;
const
char
*
modelname
;
int
*
power_save
;
struct
hda_bus_ops
ops
;
/* unsolicited event handler */
#define HDA_UNSOL_QUEUE_SIZE 64
struct
hda_bus_unsolicited
{
/* ring buffer */
u32
queue
[
HDA_UNSOL_QUEUE_SIZE
*
2
];
unsigned
int
rp
,
wp
;
/* workqueue */
struct
work_struct
work
;
};
/*
...
...
@@ -119,7 +119,6 @@ struct hda_bus_template {
struct
hda_bus
{
struct
snd_card
*
card
;
/* copied from template */
void
*
private_data
;
struct
pci_dev
*
pci
;
const
char
*
modelname
;
...
...
@@ -136,7 +135,7 @@ struct hda_bus {
struct
mutex
prepare_mutex
;
/* unsolicited event queue */
struct
hda_bus_unsolicited
*
unsol
;
struct
hda_bus_unsolicited
unsol
;
char
workq_name
[
16
];
struct
workqueue_struct
*
workq
;
/* common workqueue for codecs */
...
...
@@ -420,8 +419,7 @@ enum {
/*
* constructors
*/
int
snd_hda_bus_new
(
struct
snd_card
*
card
,
const
struct
hda_bus_template
*
temp
,
struct
hda_bus
**
busp
);
int
snd_hda_bus_new
(
struct
snd_card
*
card
,
struct
hda_bus
**
busp
);
int
snd_hda_codec_new
(
struct
hda_bus
*
bus
,
unsigned
int
codec_addr
,
struct
hda_codec
**
codecp
);
int
snd_hda_codec_configure
(
struct
hda_codec
*
codec
);
...
...
sound/pci/hda/hda_controller.c
浏览文件 @
8d085d3c
...
...
@@ -30,7 +30,6 @@
#include <linux/reboot.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_priv.h"
#include "hda_controller.h"
#define CREATE_TRACE_POINTS
...
...
@@ -1681,7 +1680,7 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
int
i
;
#ifdef CONFIG_PM
if
(
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
)
if
(
azx_has_pm_runtime
(
chip
)
)
if
(
!
pm_runtime_active
(
chip
->
card
->
dev
))
return
IRQ_NONE
;
#endif
...
...
@@ -1784,7 +1783,7 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
{
struct
azx
*
chip
=
bus
->
private_data
;
if
(
!
(
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
))
if
(
!
azx_has_pm_runtime
(
chip
))
return
;
if
(
power_up
)
...
...
@@ -1815,41 +1814,65 @@ static int get_jackpoll_interval(struct azx *chip)
return
j
;
}
/* Codec initialization */
int
azx_codec_create
(
struct
azx
*
chip
,
const
char
*
model
,
unsigned
int
max_slots
,
int
*
power_save_to
)
{
struct
hda_bus_template
bus_temp
;
int
c
,
codecs
,
err
;
memset
(
&
bus_temp
,
0
,
sizeof
(
bus_temp
));
bus_temp
.
private_data
=
chip
;
bus_temp
.
modelname
=
model
;
bus_temp
.
pci
=
chip
->
pci
;
bus_temp
.
ops
.
command
=
azx_send_cmd
;
bus_temp
.
ops
.
get_response
=
azx_get_response
;
bus_temp
.
ops
.
attach_pcm
=
azx_attach_pcm_stream
;
bus_temp
.
ops
.
bus_reset
=
azx_bus_reset
;
static
struct
hda_bus_ops
bus_ops
=
{
.
command
=
azx_send_cmd
,
.
get_response
=
azx_get_response
,
.
attach_pcm
=
azx_attach_pcm_stream
,
.
bus_reset
=
azx_bus_reset
,
#ifdef CONFIG_PM
bus_temp
.
power_save
=
power_save_to
;
bus_temp
.
ops
.
pm_notify
=
azx_power_notify
;
.
pm_notify
=
azx_power_notify
,
#endif
#ifdef CONFIG_SND_HDA_DSP_LOADER
bus_temp
.
ops
.
load_dsp_prepare
=
azx_load_dsp_prepare
;
bus_temp
.
ops
.
load_dsp_trigger
=
azx_load_dsp_trigger
;
bus_temp
.
ops
.
load_dsp_cleanup
=
azx_load_dsp_cleanup
;
.
load_dsp_prepare
=
azx_load_dsp_prepare
,
.
load_dsp_trigger
=
azx_load_dsp_trigger
,
.
load_dsp_cleanup
=
azx_load_dsp_cleanup
,
#endif
};
err
=
snd_hda_bus_new
(
chip
->
card
,
&
bus_temp
,
&
chip
->
bus
);
/* HD-audio bus initialization */
int
azx_bus_create
(
struct
azx
*
chip
,
const
char
*
model
,
int
*
power_save_to
)
{
struct
hda_bus
*
bus
;
int
err
;
err
=
snd_hda_bus_new
(
chip
->
card
,
&
bus
);
if
(
err
<
0
)
return
err
;
chip
->
bus
=
bus
;
bus
->
private_data
=
chip
;
bus
->
pci
=
chip
->
pci
;
bus
->
modelname
=
model
;
bus
->
ops
=
bus_ops
;
#ifdef CONFIG_PM
bus
->
power_save
=
power_save_to
;
#endif
if
(
chip
->
driver_caps
&
AZX_DCAPS_RIRB_DELAY
)
{
dev_dbg
(
chip
->
card
->
dev
,
"Enable delay in RIRB handling
\n
"
);
chip
->
bus
->
needs_damn_long_delay
=
1
;
bus
->
needs_damn_long_delay
=
1
;
}
/* AMD chipsets often cause the communication stalls upon certain
* sequence like the pin-detection. It seems that forcing the synced
* access works around the stall. Grrr...
*/
if
(
chip
->
driver_caps
&
AZX_DCAPS_SYNC_WRITE
)
{
dev_dbg
(
chip
->
card
->
dev
,
"Enable sync_write for stable communication
\n
"
);
bus
->
sync_write
=
1
;
bus
->
allow_bus_reset
=
1
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
azx_bus_create
);
/* Probe codecs */
int
azx_probe_codecs
(
struct
azx
*
chip
,
unsigned
int
max_slots
)
{
struct
hda_bus
*
bus
=
chip
->
bus
;
int
c
,
codecs
,
err
;
codecs
=
0
;
if
(
!
max_slots
)
max_slots
=
AZX_DEFAULT_CODECS
;
...
...
@@ -1877,21 +1900,11 @@ int azx_codec_create(struct azx *chip, const char *model,
}
}
/* AMD chipsets often cause the communication stalls upon certain
* sequence like the pin-detection. It seems that forcing the synced
* access works around the stall. Grrr...
*/
if
(
chip
->
driver_caps
&
AZX_DCAPS_SYNC_WRITE
)
{
dev_dbg
(
chip
->
card
->
dev
,
"Enable sync_write for stable communication
\n
"
);
chip
->
bus
->
sync_write
=
1
;
chip
->
bus
->
allow_bus_reset
=
1
;
}
/* Then create codec instances */
for
(
c
=
0
;
c
<
max_slots
;
c
++
)
{
if
((
chip
->
codec_mask
&
(
1
<<
c
))
&
chip
->
codec_probe_mask
)
{
struct
hda_codec
*
codec
;
err
=
snd_hda_codec_new
(
chip
->
bus
,
c
,
&
codec
);
err
=
snd_hda_codec_new
(
bus
,
c
,
&
codec
);
if
(
err
<
0
)
continue
;
codec
->
jackpoll_interval
=
get_jackpoll_interval
(
chip
);
...
...
@@ -1905,7 +1918,7 @@ int azx_codec_create(struct azx *chip, const char *model,
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
azx_
codec_create
);
EXPORT_SYMBOL_GPL
(
azx_
probe_codecs
);
/* configure each codec instance */
int
azx_codec_configure
(
struct
azx
*
chip
)
...
...
@@ -1918,13 +1931,6 @@ int azx_codec_configure(struct azx *chip)
}
EXPORT_SYMBOL_GPL
(
azx_codec_configure
);
/* mixer creation - all stuff is implemented in hda module */
int
azx_mixer_create
(
struct
azx
*
chip
)
{
return
snd_hda_build_controls
(
chip
->
bus
);
}
EXPORT_SYMBOL_GPL
(
azx_mixer_create
);
static
bool
is_input_stream
(
struct
azx
*
chip
,
unsigned
char
index
)
{
...
...
sound/pci/hda/hda_controller.h
浏览文件 @
8d085d3c
...
...
@@ -15,10 +15,399 @@
#ifndef __SOUND_HDA_CONTROLLER_H
#define __SOUND_HDA_CONTROLLER_H
#include <linux/timecounter.h>
#include <linux/interrupt.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/initval.h>
#include "hda_codec.h"
#include "hda_priv.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_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 */
#define AZX_DCAPS_NO_TCSEL (1 << 8)
/* No Intel TCSEL bit */
#define AZX_DCAPS_NO_MSI (1 << 9)
/* No MSI support */
#define AZX_DCAPS_SNOOP_MASK (3 << 10)
/* snoop type mask */
#define AZX_DCAPS_SNOOP_OFF (1 << 12)
/* snoop default off */
#define AZX_DCAPS_RIRB_DELAY (1 << 13)
/* Long delay in read loop */
#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14)
/* Put a delay before read */
#define AZX_DCAPS_CTX_WORKAROUND (1 << 15)
/* X-Fi workaround */
#define AZX_DCAPS_POSFIX_LPIB (1 << 16)
/* Use LPIB as default */
#define AZX_DCAPS_POSFIX_VIA (1 << 17)
/* Use VIACOMBO as default */
#define AZX_DCAPS_NO_64BIT (1 << 18)
/* No 64bit address */
#define AZX_DCAPS_SYNC_WRITE (1 << 19)
/* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20)
/* Old SSYNC reg for ICH */
#define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21)
/* no buffer size alignment */
/* 22 unused */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)
/* BDLE in 4k boundary */
#define AZX_DCAPS_REVERSE_ASSIGN (1 << 24)
/* Assign devices in reverse order */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25)
/* Take LPIB as delay */
#define AZX_DCAPS_PM_RUNTIME (1 << 26)
/* runtime PM support */
#define AZX_DCAPS_I915_POWERWELL (1 << 27)
/* HSW i915 powerwell support */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)
/* CORBRP clears itself after reset */
#define AZX_DCAPS_NO_MSI64 (1 << 29)
/* Stick to 32-bit MSIs */
#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30)
/* capture and playback use separate stream tag */
enum
{
AZX_SNOOP_TYPE_NONE
,
AZX_SNOOP_TYPE_SCH
,
AZX_SNOOP_TYPE_ATI
,
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
;
unsigned
int
irq_pending
:
1
;
unsigned
int
prepared
:
1
;
unsigned
int
locked
:
1
;
/*
* For VIA:
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
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 */
};
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
);
int
(
*
substream_free_pages
)(
struct
azx
*
chip
,
struct
snd_pcm_substream
*
substream
);
void
(
*
pcm_mmap_prepare
)(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
area
);
/* Check if current position is acceptable */
int
(
*
position_check
)(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
};
struct
azx_pcm
{
struct
azx
*
chip
;
struct
snd_pcm
*
pcm
;
struct
hda_codec
*
codec
;
struct
hda_pcm_stream
*
hinfo
[
2
];
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
;
int
dev_index
;
/* chip type specific */
int
driver_type
;
unsigned
int
driver_caps
;
int
playback_streams
;
int
playback_index_offset
;
int
capture_streams
;
int
capture_index_offset
;
int
num_streams
;
const
int
*
jackpoll_ms
;
/* per-card jack poll interval */
/* 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
;
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
/* flags */
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
;
unsigned
int
probing
:
1
;
/* codec probing phase */
unsigned
int
snoop
:
1
;
unsigned
int
align_buffer_size
:
1
;
unsigned
int
region_requested
:
1
;
unsigned
int
disabled
:
1
;
/* disabled by VGA-switcher */
/* for debugging */
unsigned
int
last_cmd
[
AZX_MAX_CODECS
];
/* reboot notifier (for mysterious hangup problem at power-down) */
struct
notifier_block
reboot_notifier
;
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct
azx_dev
saved_azx_dev
;
#endif
};
#ifdef CONFIG_X86
#define azx_snoop(chip) ((chip)->snoop)
#else
#define azx_snoop(chip) true
#endif
/*
* macros for easy use
*/
#define azx_writel(chip, reg, value) \
((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
#define azx_readl(chip, 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 + AZX_REG_##reg))
#define azx_readw(chip, 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 + AZX_REG_##reg))
#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))
#define azx_has_pm_runtime(chip) \
(!AZX_DCAPS_PM_RUNTIME || ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME))
/* PCM setup */
static
inline
struct
azx_dev
*
get_azx_dev
(
struct
snd_pcm_substream
*
substream
)
...
...
@@ -43,11 +432,9 @@ void azx_enter_link_reset(struct azx *chip);
irqreturn_t
azx_interrupt
(
int
irq
,
void
*
dev_id
);
/* Codec interface */
int
azx_codec_create
(
struct
azx
*
chip
,
const
char
*
model
,
unsigned
int
max_slots
,
int
*
power_save_to
);
int
azx_bus_create
(
struct
azx
*
chip
,
const
char
*
model
,
int
*
power_save_to
);
int
azx_probe_codecs
(
struct
azx
*
chip
,
unsigned
int
max_slots
);
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
);
...
...
sound/pci/hda/hda_i915.c
浏览文件 @
8d085d3c
...
...
@@ -22,7 +22,7 @@
#include <linux/component.h>
#include <drm/i915_component.h>
#include <sound/core.h>
#include "hda_
priv
.h"
#include "hda_
controller
.h"
#include "hda_intel.h"
/* Intel HSW/BDW display HDA controller Extended Mode registers.
...
...
sound/pci/hda/hda_intel.c
浏览文件 @
8d085d3c
...
...
@@ -62,7 +62,6 @@
#include <linux/firmware.h>
#include "hda_codec.h"
#include "hda_controller.h"
#include "hda_priv.h"
#include "hda_intel.h"
/* position fix mode */
...
...
@@ -852,7 +851,7 @@ static int azx_runtime_suspend(struct device *dev)
if
(
chip
->
disabled
||
hda
->
init_failed
)
return
0
;
if
(
!
(
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
))
if
(
!
azx_has_pm_runtime
(
chip
))
return
0
;
/* enable controller wake up event */
...
...
@@ -885,7 +884,7 @@ static int azx_runtime_resume(struct device *dev)
if
(
chip
->
disabled
||
hda
->
init_failed
)
return
0
;
if
(
!
(
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
))
if
(
!
azx_has_pm_runtime
(
chip
))
return
0
;
if
(
chip
->
driver_caps
&
AZX_DCAPS_I915_POWERWELL
)
{
...
...
@@ -928,8 +927,7 @@ static int azx_runtime_idle(struct device *dev)
if
(
chip
->
disabled
||
hda
->
init_failed
)
return
0
;
if
(
!
power_save_controller
||
!
(
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
))
if
(
!
power_save_controller
||
!
azx_has_pm_runtime
(
chip
))
return
-
EBUSY
;
return
0
;
...
...
@@ -1071,8 +1069,7 @@ static int azx_free(struct azx *chip)
struct
hda_intel
*
hda
=
container_of
(
chip
,
struct
hda_intel
,
chip
);
int
i
;
if
((
chip
->
driver_caps
&
AZX_DCAPS_PM_RUNTIME
)
&&
chip
->
running
)
if
(
azx_has_pm_runtime
(
chip
)
&&
chip
->
running
)
pm_runtime_get_noresume
(
&
pci
->
dev
);
azx_del_card_list
(
chip
);
...
...
@@ -1896,12 +1893,14 @@ static int azx_probe_continue(struct azx *chip)
#endif
/* create codec instances */
err
=
azx_
codec_create
(
chip
,
model
[
dev
],
azx_max_codecs
[
chip
->
driver_type
],
power_save_addr
)
;
err
=
azx_
bus_create
(
chip
,
model
[
dev
],
power_save_addr
);
if
(
err
<
0
)
goto
out_free
;
err
=
azx_probe_codecs
(
chip
,
azx_max_codecs
[
chip
->
driver_type
]);
if
(
err
<
0
)
goto
out_free
;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
if
(
chip
->
fw
)
{
err
=
snd_hda_load_patch
(
chip
->
bus
,
chip
->
fw
->
size
,
...
...
@@ -1926,7 +1925,7 @@ static int azx_probe_continue(struct azx *chip)
goto
out_free
;
/* create mixer controls */
err
=
azx_mixer_create
(
chip
);
err
=
snd_hda_build_controls
(
chip
->
bus
);
if
(
err
<
0
)
goto
out_free
;
...
...
@@ -1938,7 +1937,7 @@ 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
)
||
hda
->
use_vga_switcheroo
)
if
(
azx_has_pm_runtime
(
chip
)
||
hda
->
use_vga_switcheroo
)
pm_runtime_put_noidle
(
&
pci
->
dev
);
out_free:
...
...
sound/pci/hda/hda_intel.h
浏览文件 @
8d085d3c
...
...
@@ -17,7 +17,7 @@
#define __SOUND_HDA_INTEL_H
#include <drm/i915_component.h>
#include "hda_
priv
.h"
#include "hda_
controller
.h"
struct
hda_intel
{
struct
azx
chip
;
...
...
sound/pci/hda/hda_local.h
浏览文件 @
8d085d3c
...
...
@@ -466,23 +466,6 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
const
struct
snd_hda_pin_quirk
*
pin_quirk
,
const
struct
hda_fixup
*
fixlist
);
/*
* unsolicited event handler
*/
#define HDA_UNSOL_QUEUE_SIZE 64
struct
hda_bus_unsolicited
{
/* ring buffer */
u32
queue
[
HDA_UNSOL_QUEUE_SIZE
*
2
];
unsigned
int
rp
,
wp
;
/* workqueue */
struct
work_struct
work
;
struct
hda_bus
*
bus
;
};
/* helper macros to retrieve pin default-config values */
#define get_defcfg_connect(cfg) \
((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
...
...
sound/pci/hda/hda_priv.h
已删除
100644 → 0
浏览文件 @
88cacc57
/*
* Common defines for the alsa driver code base for HD Audio.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __SOUND_HDA_PRIV_H
#define __SOUND_HDA_PRIV_H
#include <linux/timecounter.h>
#include <sound/core.h>
#include <sound/pcm.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_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 */
#define AZX_DCAPS_NO_TCSEL (1 << 8)
/* No Intel TCSEL bit */
#define AZX_DCAPS_NO_MSI (1 << 9)
/* No MSI support */
#define AZX_DCAPS_SNOOP_MASK (3 << 10)
/* snoop type mask */
#define AZX_DCAPS_SNOOP_OFF (1 << 12)
/* snoop default off */
#define AZX_DCAPS_RIRB_DELAY (1 << 13)
/* Long delay in read loop */
#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14)
/* Put a delay before read */
#define AZX_DCAPS_CTX_WORKAROUND (1 << 15)
/* X-Fi workaround */
#define AZX_DCAPS_POSFIX_LPIB (1 << 16)
/* Use LPIB as default */
#define AZX_DCAPS_POSFIX_VIA (1 << 17)
/* Use VIACOMBO as default */
#define AZX_DCAPS_NO_64BIT (1 << 18)
/* No 64bit address */
#define AZX_DCAPS_SYNC_WRITE (1 << 19)
/* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20)
/* Old SSYNC reg for ICH */
#define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21)
/* no buffer size alignment */
/* 22 unused */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)
/* BDLE in 4k boundary */
#define AZX_DCAPS_REVERSE_ASSIGN (1 << 24)
/* Assign devices in reverse order */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25)
/* Take LPIB as delay */
#define AZX_DCAPS_PM_RUNTIME (1 << 26)
/* runtime PM support */
#define AZX_DCAPS_I915_POWERWELL (1 << 27)
/* HSW i915 powerwell support */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)
/* CORBRP clears itself after reset */
#define AZX_DCAPS_NO_MSI64 (1 << 29)
/* Stick to 32-bit MSIs */
#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30)
/* capture and playback use separate stream tag */
enum
{
AZX_SNOOP_TYPE_NONE
,
AZX_SNOOP_TYPE_SCH
,
AZX_SNOOP_TYPE_ATI
,
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
;
unsigned
int
irq_pending
:
1
;
unsigned
int
prepared
:
1
;
unsigned
int
locked
:
1
;
/*
* For VIA:
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
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 */
};
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
);
int
(
*
substream_free_pages
)(
struct
azx
*
chip
,
struct
snd_pcm_substream
*
substream
);
void
(
*
pcm_mmap_prepare
)(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
area
);
/* Check if current position is acceptable */
int
(
*
position_check
)(
struct
azx
*
chip
,
struct
azx_dev
*
azx_dev
);
};
struct
azx_pcm
{
struct
azx
*
chip
;
struct
snd_pcm
*
pcm
;
struct
hda_codec
*
codec
;
struct
hda_pcm_stream
*
hinfo
[
2
];
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
;
int
dev_index
;
/* chip type specific */
int
driver_type
;
unsigned
int
driver_caps
;
int
playback_streams
;
int
playback_index_offset
;
int
capture_streams
;
int
capture_index_offset
;
int
num_streams
;
const
int
*
jackpoll_ms
;
/* per-card jack poll interval */
/* 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
;
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
/* flags */
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
;
unsigned
int
probing
:
1
;
/* codec probing phase */
unsigned
int
snoop
:
1
;
unsigned
int
align_buffer_size
:
1
;
unsigned
int
region_requested
:
1
;
unsigned
int
disabled
:
1
;
/* disabled by VGA-switcher */
/* for debugging */
unsigned
int
last_cmd
[
AZX_MAX_CODECS
];
/* reboot notifier (for mysterious hangup problem at power-down) */
struct
notifier_block
reboot_notifier
;
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct
azx_dev
saved_azx_dev
;
#endif
};
#ifdef CONFIG_X86
#define azx_snoop(chip) ((chip)->snoop)
#else
#define azx_snoop(chip) true
#endif
/*
* macros for easy use
*/
#define azx_writel(chip, reg, value) \
((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
#define azx_readl(chip, 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 + AZX_REG_##reg))
#define azx_readw(chip, 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 + AZX_REG_##reg))
#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))
#endif
/* __SOUND_HDA_PRIV_H */
sound/pci/hda/hda_tegra.c
浏览文件 @
8d085d3c
...
...
@@ -37,7 +37,6 @@
#include "hda_codec.h"
#include "hda_controller.h"
#include "hda_priv.h"
/* Defines for Nvidia Tegra HDA support */
#define HDA_BAR0 0x8000
...
...
@@ -503,7 +502,11 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto
out_free
;
/* create codec instances */
err
=
azx_codec_create
(
chip
,
NULL
,
0
,
&
power_save
);
err
=
azx_bus_create
(
chip
,
NULL
,
&
power_save
);
if
(
err
<
0
)
goto
out_free
;
err
=
azx_probe_codecs
(
chip
,
0
);
if
(
err
<
0
)
goto
out_free
;
...
...
@@ -517,7 +520,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto
out_free
;
/* create mixer controls */
err
=
azx_mixer_create
(
chip
);
err
=
snd_hda_build_controls
(
chip
->
bus
);
if
(
err
<
0
)
goto
out_free
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录