Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
8d085d3c
Commit
8d085d3c
authored
Feb 23, 2015
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/hda-cleanup' into for-next
parents
88cacc57
781c7b96
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
493 additions
and
568 deletions
+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
No files found.
sound/pci/hda/hda_codec.c
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
deleted
100644 → 0
View file @
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
View file @
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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment