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
e7e3950a
Commit
e7e3950a
authored
Mar 11, 2005
by
Jaroslav Kysela
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/home/perex/bk/linux-sound/linux-sound
into suse.cz:/home/perex/bk/linux-sound/work
parents
ece8df79
4eaf05ae
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
290 additions
and
150 deletions
+290
-150
include/sound/ac97_codec.h
include/sound/ac97_codec.h
+14
-0
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_codec.c
+129
-150
sound/pci/ac97/ac97_local.h
sound/pci/ac97/ac97_local.h
+16
-0
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_patch.c
+130
-0
sound/pci/ac97/ac97_patch.h
sound/pci/ac97/ac97_patch.h
+1
-0
No files found.
include/sound/ac97_codec.h
View file @
e7e3950a
...
...
@@ -366,6 +366,13 @@
#define AC97_DOUBLE_RATE (1<<5)
/* supports double rate playback */
#define AC97_HAS_NO_MASTER_VOL (1<<6)
/* no Master volume */
#define AC97_HAS_NO_PCM_VOL (1<<7)
/* no PCM volume */
#define AC97_DEFAULT_POWER_OFF (1<<8)
/* no RESET write */
#define AC97_MODEM_PATCH (1<<9)
/* modem patch */
#define AC97_HAS_NO_REC_GAIN (1<<10)
/* no Record gain */
#define AC97_HAS_NO_PHONE (1<<11)
/* no PHONE volume */
#define AC97_HAS_NO_PC_BEEP (1<<12)
/* no PC Beep volume */
#define AC97_HAS_NO_VIDEO (1<<13)
/* no Video volume */
#define AC97_HAS_NO_CD (1<<14)
/* no CD volume */
/* rates indexes */
#define AC97_RATES_FRONT_DAC 0
...
...
@@ -580,4 +587,11 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
int
snd_ac97_pcm_close
(
struct
ac97_pcm
*
pcm
);
int
snd_ac97_pcm_double_rate_rules
(
snd_pcm_runtime_t
*
runtime
);
struct
ac97_enum
{
unsigned
char
reg
;
unsigned
char
shift_l
;
unsigned
char
shift_r
;
unsigned
short
mask
;
const
char
**
texts
;
};
#endif
/* __SOUND_AC97_CODEC_H */
sound/pci/ac97/ac97_codec.c
View file @
e7e3950a
...
...
@@ -56,6 +56,7 @@ typedef struct {
const
char
*
name
;
int
(
*
patch
)(
ac97_t
*
ac97
);
int
(
*
mpatch
)(
ac97_t
*
ac97
);
unsigned
int
flags
;
}
ac97_codec_id_t
;
static
const
ac97_codec_id_t
snd_ac97_codec_id_vendors
[]
=
{
...
...
@@ -162,6 +163,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{
0x574d4C05
,
0xffffffff
,
"WM9705/WM9710"
,
patch_wolfson05
,
NULL
},
{
0x574d4C09
,
0xffffffff
,
"WM9709"
,
NULL
,
NULL
},
{
0x574d4C12
,
0xffffffff
,
"WM9711/WM9712"
,
patch_wolfson11
,
NULL
},
{
0x574d4c13
,
0xffffffff
,
"WM9713/WM9714"
,
patch_wolfson13
,
NULL
,
AC97_DEFAULT_POWER_OFF
},
{
0x594d4800
,
0xffffffff
,
"YMF743"
,
NULL
,
NULL
},
{
0x594d4802
,
0xffffffff
,
"YMF752"
,
NULL
,
NULL
},
{
0x594d4803
,
0xffffffff
,
"YMF753"
,
patch_yamaha_ymf753
,
NULL
},
...
...
@@ -442,108 +444,52 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
* Controls
*/
/* input mux */
static
int
snd_ac97_info_mux
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
int
snd_ac97_info_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
{
static
char
*
texts
[
8
]
=
{
"Mic"
,
"CD"
,
"Video"
,
"Aux"
,
"Line"
,
"Mix"
,
"Mix Mono"
,
"Phone"
};
struct
ac97_enum
*
e
=
(
struct
ac97_enum
*
)
kcontrol
->
private_value
;
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
uinfo
->
count
=
2
;
uinfo
->
value
.
enumerated
.
items
=
8
;
if
(
uinfo
->
value
.
enumerated
.
item
>
7
)
uinfo
->
value
.
enumerated
.
item
=
7
;
strcpy
(
uinfo
->
value
.
enumerated
.
name
,
texts
[
uinfo
->
value
.
enumerated
.
item
]);
return
0
;
}
static
int
snd_ac97_get_mux
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
short
val
;
uinfo
->
count
=
e
->
shift_l
==
e
->
shift_r
?
1
:
2
;
uinfo
->
value
.
enumerated
.
items
=
e
->
mask
;
val
=
snd_ac97_read_cache
(
ac97
,
AC97_REC_SEL
);
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
(
val
>>
8
)
&
7
;
ucontrol
->
value
.
enumerated
.
item
[
1
]
=
(
val
>>
0
)
&
7
;
if
(
uinfo
->
value
.
enumerated
.
item
>
e
->
mask
-
1
)
uinfo
->
value
.
enumerated
.
item
=
e
->
mask
-
1
;
strcpy
(
uinfo
->
value
.
enumerated
.
name
,
e
->
texts
[
uinfo
->
value
.
enumerated
.
item
])
;
return
0
;
}
static
int
snd_ac97_put_mux
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
int
snd_ac97_get_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
struct
ac97_enum
*
e
=
(
struct
ac97_enum
*
)
kcontrol
->
private_value
;
unsigned
short
val
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
7
||
ucontrol
->
value
.
enumerated
.
item
[
1
]
>
7
)
return
-
EINVAL
;
val
=
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
<<
8
)
|
(
ucontrol
->
value
.
enumerated
.
item
[
1
]
<<
0
);
return
snd_ac97_update
(
ac97
,
AC97_REC_SEL
,
val
);
}
/* standard stereo enums */
#define AC97_ENUM_DOUBLE(xname, reg, shift, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
.get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
.private_value = reg | (shift << 8) | (invert << 24) }
static
int
snd_ac97_info_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
)
{
static
char
*
texts1
[
2
]
=
{
"pre 3D"
,
"post 3D"
};
static
char
*
texts2
[
2
]
=
{
"Mix"
,
"Mic"
};
static
char
*
texts3
[
2
]
=
{
"Mic1"
,
"Mic2"
};
char
**
texts
=
NULL
;
int
reg
=
kcontrol
->
private_value
&
0xff
;
int
shift
=
(
kcontrol
->
private_value
>>
8
)
&
0xff
;
switch
(
reg
)
{
case
AC97_GENERAL_PURPOSE
:
switch
(
shift
)
{
case
15
:
texts
=
texts1
;
break
;
case
9
:
texts
=
texts2
;
break
;
case
8
:
texts
=
texts3
;
break
;
}
}
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
uinfo
->
count
=
1
;
uinfo
->
value
.
enumerated
.
items
=
2
;
if
(
uinfo
->
value
.
enumerated
.
item
>
1
)
uinfo
->
value
.
enumerated
.
item
=
1
;
strcpy
(
uinfo
->
value
.
enumerated
.
name
,
texts
[
uinfo
->
value
.
enumerated
.
item
]);
return
0
;
}
val
=
snd_ac97_read_cache
(
ac97
,
e
->
reg
);
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
(
val
>>
e
->
shift_l
)
&
(
e
->
mask
-
1
);
if
(
e
->
shift_l
!=
e
->
shift_r
)
ucontrol
->
value
.
enumerated
.
item
[
1
]
=
(
val
>>
e
->
shift_r
)
&
(
e
->
mask
-
1
);
static
int
snd_ac97_get_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
short
val
;
int
reg
=
kcontrol
->
private_value
&
0xff
;
int
shift
=
(
kcontrol
->
private_value
>>
8
)
&
0xff
;
int
invert
=
(
kcontrol
->
private_value
>>
24
)
&
0xff
;
val
=
(
snd_ac97_read_cache
(
ac97
,
reg
)
>>
shift
)
&
1
;
if
(
invert
)
val
^=
1
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
val
;
return
0
;
}
static
int
snd_ac97_put_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
int
snd_ac97_put_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
)
{
ac97_t
*
ac97
=
snd_kcontrol_chip
(
kcontrol
);
struct
ac97_enum
*
e
=
(
struct
ac97_enum
*
)
kcontrol
->
private_value
;
unsigned
short
val
;
int
reg
=
kcontrol
->
private_value
&
0xff
;
int
shift
=
(
kcontrol
->
private_value
>>
8
)
&
0xff
;
int
invert
=
(
kcontrol
->
private_value
>>
24
)
&
0xff
;
unsigned
short
mask
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
1
)
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
e
->
mask
-
1
)
return
-
EINVAL
;
val
=
!!
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
invert
)
val
=
!
val
;
return
snd_ac97_update_bits
(
ac97
,
reg
,
1
<<
shift
,
val
<<
shift
);
val
=
ucontrol
->
value
.
enumerated
.
item
[
0
]
<<
e
->
shift_l
;
mask
=
(
e
->
mask
-
1
)
<<
e
->
shift_l
;
if
(
e
->
shift_l
!=
e
->
shift_r
)
{
if
(
ucontrol
->
value
.
enumerated
.
item
[
1
]
>
e
->
mask
-
1
)
return
-
EINVAL
;
val
|=
ucontrol
->
value
.
enumerated
.
item
[
1
]
<<
e
->
shift_r
;
mask
|=
(
e
->
mask
-
1
)
<<
e
->
shift_r
;
}
return
snd_ac97_update_bits
(
ac97
,
e
->
reg
,
mask
,
val
);
}
/* save/restore ac97 v2.3 paging */
...
...
@@ -635,11 +581,6 @@ int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
return
err
;
}
#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
.get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
static
const
snd_kcontrol_new_t
snd_ac97_controls_master_mono
[
2
]
=
{
AC97_SINGLE
(
"Master Mono Playback Switch"
,
AC97_MASTER_MONO
,
15
,
1
,
1
),
AC97_SINGLE
(
"Master Mono Playback Volume"
,
AC97_MASTER_MONO
,
0
,
31
,
1
)
...
...
@@ -659,14 +600,21 @@ static const snd_kcontrol_new_t snd_ac97_controls_mic_boost =
AC97_SINGLE
(
"Mic Boost (+20dB)"
,
AC97_MIC
,
6
,
1
,
0
);
static
const
snd_kcontrol_new_t
snd_ac97_control_capture_src
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Capture Source"
,
.
info
=
snd_ac97_info_mux
,
.
get
=
snd_ac97_get_mux
,
.
put
=
snd_ac97_put_mux
,
static
const
char
*
std_rec_sel
[]
=
{
"Mic"
,
"CD"
,
"Video"
,
"Aux"
,
"Line"
,
"Mix"
,
"Mix Mono"
,
"Phone"
};
static
const
char
*
std_3d_path
[]
=
{
"pre 3D"
,
"post 3D"
};
static
const
char
*
std_mix
[]
=
{
"Mix"
,
"Mic"
};
static
const
char
*
std_mic
[]
=
{
"Mic1"
,
"Mic2"
};
static
const
struct
ac97_enum
std_enum
[]
=
{
AC97_ENUM_DOUBLE
(
AC97_REC_SEL
,
8
,
0
,
8
,
std_rec_sel
),
AC97_ENUM_SINGLE
(
AC97_GENERAL_PURPOSE
,
15
,
2
,
std_3d_path
),
AC97_ENUM_SINGLE
(
AC97_GENERAL_PURPOSE
,
9
,
2
,
std_mix
),
AC97_ENUM_SINGLE
(
AC97_GENERAL_PURPOSE
,
8
,
2
,
std_mic
),
};
static
const
snd_kcontrol_new_t
snd_ac97_control_capture_src
=
AC97_ENUM
(
"Capture Source"
,
std_enum
[
0
]);
static
const
snd_kcontrol_new_t
snd_ac97_control_capture_vol
=
AC97_DOUBLE
(
"Capture Volume"
,
AC97_REC_GAIN
,
8
,
0
,
15
,
0
);
...
...
@@ -686,12 +634,12 @@ typedef enum {
}
ac97_general_index_t
;
static
const
snd_kcontrol_new_t
snd_ac97_controls_general
[
7
]
=
{
AC97_ENUM
_DOUBLE
(
"PCM Out Path & Mute"
,
AC97_GENERAL_PURPOSE
,
15
,
0
),
AC97_ENUM
(
"PCM Out Path & Mute"
,
std_enum
[
1
]
),
AC97_SINGLE
(
"Simulated Stereo Enhancement"
,
AC97_GENERAL_PURPOSE
,
14
,
1
,
0
),
AC97_SINGLE
(
"3D Control - Switch"
,
AC97_GENERAL_PURPOSE
,
13
,
1
,
0
),
AC97_SINGLE
(
"Loudness (bass boost)"
,
AC97_GENERAL_PURPOSE
,
12
,
1
,
0
),
AC97_ENUM
_DOUBLE
(
"Mono Output Select"
,
AC97_GENERAL_PURPOSE
,
9
,
0
),
AC97_ENUM
_DOUBLE
(
"Mic Select"
,
AC97_GENERAL_PURPOSE
,
8
,
0
),
AC97_ENUM
(
"Mono Output Select"
,
std_enum
[
2
]
),
AC97_ENUM
(
"Mic Select"
,
std_enum
[
3
]
),
AC97_SINGLE
(
"ADC/DAC Loopback"
,
AC97_GENERAL_PURPOSE
,
7
,
1
,
0
)
};
...
...
@@ -1360,8 +1308,9 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build PC Speaker controls */
if
((
ac97
->
flags
&
AC97_HAS_PC_BEEP
)
||
snd_ac97_try_volume_mix
(
ac97
,
AC97_PC_BEEP
))
{
if
(
!
(
ac97
->
flags
&
AC97_HAS_NO_PC_BEEP
)
&&
((
ac97
->
flags
&
AC97_HAS_PC_BEEP
)
||
snd_ac97_try_volume_mix
(
ac97
,
AC97_PC_BEEP
)))
{
for
(
idx
=
0
;
idx
<
2
;
idx
++
)
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_controls_pc_beep
[
idx
],
ac97
)))
<
0
)
return
err
;
...
...
@@ -1370,9 +1319,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build Phone controls */
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_PHONE
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"Phone Playback"
,
AC97_PHONE
,
ac97
))
<
0
)
return
err
;
if
(
!
(
ac97
->
flags
&
AC97_HAS_NO_PHONE
))
{
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_PHONE
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"Phone Playback"
,
AC97_PHONE
,
ac97
))
<
0
)
return
err
;
}
}
/* build MIC controls */
...
...
@@ -1390,15 +1341,19 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build CD controls */
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_CD
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"CD Playback"
,
AC97_CD
,
ac97
))
<
0
)
return
err
;
if
(
!
(
ac97
->
flags
&
AC97_HAS_NO_CD
))
{
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_CD
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"CD Playback"
,
AC97_CD
,
ac97
))
<
0
)
return
err
;
}
}
/* build Video controls */
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_VIDEO
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"Video Playback"
,
AC97_VIDEO
,
ac97
))
<
0
)
return
err
;
if
(
!
(
ac97
->
flags
&
AC97_HAS_NO_VIDEO
))
{
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_VIDEO
))
{
if
((
err
=
snd_ac97_cmix_new
(
card
,
"Video Playback"
,
AC97_VIDEO
,
ac97
))
<
0
)
return
err
;
}
}
/* build Aux controls */
...
...
@@ -1444,17 +1399,18 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build Capture controls */
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_control_capture_src
,
ac97
)))
<
0
)
return
err
;
if
(
snd_ac97_try_bit
(
ac97
,
AC97_REC_GAIN
,
15
))
{
if
((
err
=
snd_ac97_cmute_new
(
card
,
"Capture Switch"
,
AC97_REC_GAIN
,
ac97
))
<
0
)
if
(
!
(
ac97
->
flags
&
AC97_HAS_NO_REC_GAIN
))
{
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_control_capture_src
,
ac97
)))
<
0
)
return
err
;
if
(
snd_ac97_try_bit
(
ac97
,
AC97_REC_GAIN
,
15
))
{
if
((
err
=
snd_ac97_cmute_new
(
card
,
"Capture Switch"
,
AC97_REC_GAIN
,
ac97
))
<
0
)
return
err
;
}
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_control_capture_vol
,
ac97
)))
<
0
)
return
err
;
snd_ac97_write_cache
(
ac97
,
AC97_REC_SEL
,
0x0000
);
snd_ac97_write_cache
(
ac97
,
AC97_REC_GAIN
,
0x0000
);
}
if
((
err
=
snd_ctl_add
(
card
,
snd_ac97_cnew
(
&
snd_ac97_control_capture_vol
,
ac97
)))
<
0
)
return
err
;
snd_ac97_write_cache
(
ac97
,
AC97_REC_SEL
,
0x0000
);
snd_ac97_write_cache
(
ac97
,
AC97_REC_GAIN
,
0x0000
);
/* build MIC Capture controls */
if
(
snd_ac97_try_volume_mix
(
ac97
,
AC97_REC_GAIN_MIC
))
{
for
(
idx
=
0
;
idx
<
2
;
idx
++
)
...
...
@@ -1672,6 +1628,18 @@ static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97)
return
result
;
}
/* look for the codec id table matching with the given id */
static
const
ac97_codec_id_t
*
look_for_codec_id
(
const
ac97_codec_id_t
*
table
,
unsigned
int
id
)
{
const
ac97_codec_id_t
*
pid
;
for
(
pid
=
table
;
pid
->
id
;
pid
++
)
if
(
pid
->
id
==
(
id
&
pid
->
mask
))
return
pid
;
return
NULL
;
}
void
snd_ac97_get_name
(
ac97_t
*
ac97
,
unsigned
int
id
,
char
*
name
,
int
modem
)
{
const
ac97_codec_id_t
*
pid
;
...
...
@@ -1680,35 +1648,30 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
printable
(
id
>>
24
),
printable
(
id
>>
16
),
printable
(
id
>>
8
));
for
(
pid
=
snd_ac97_codec_id_vendors
;
pid
->
id
;
pid
++
)
if
(
pid
->
id
==
(
id
&
pid
->
mask
))
{
strcpy
(
name
,
pid
->
name
);
if
(
ac97
)
{
if
(
!
modem
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
else
if
(
modem
&&
pid
->
mpatch
)
pid
->
mpatch
(
ac97
);
}
goto
__vendor_ok
;
}
return
;
pid
=
look_for_codec_id
(
snd_ac97_codec_id_vendors
,
id
);
if
(
!
pid
)
return
;
__vendor_ok:
for
(
pid
=
snd_ac97_codec_ids
;
pid
->
id
;
pid
++
)
if
(
pid
->
id
==
(
id
&
pid
->
mask
))
{
strcat
(
name
,
" "
);
strcat
(
name
,
pid
->
name
);
if
(
pid
->
mask
!=
0xffffffff
)
sprintf
(
name
+
strlen
(
name
),
" rev %d"
,
id
&
~
pid
->
mask
);
if
(
ac97
)
{
if
(
!
modem
&&
pid
->
patch
)
pid
->
patch
(
ac97
);
else
if
(
modem
&&
pid
->
mpatch
)
pid
->
mpatch
(
ac97
);
}
return
;
strcpy
(
name
,
pid
->
name
);
if
(
ac97
&&
pid
->
patch
)
{
if
((
modem
&&
(
pid
->
flags
&
AC97_MODEM_PATCH
))
||
(
!
modem
&&
!
(
pid
->
flags
&
AC97_MODEM_PATCH
)))
pid
->
patch
(
ac97
);
}
pid
=
look_for_codec_id
(
snd_ac97_codec_ids
,
id
);
if
(
pid
)
{
strcat
(
name
,
" "
);
strcat
(
name
,
pid
->
name
);
if
(
pid
->
mask
!=
0xffffffff
)
sprintf
(
name
+
strlen
(
name
),
" rev %d"
,
id
&
~
pid
->
mask
);
if
(
ac97
&&
pid
->
patch
)
{
if
((
modem
&&
(
pid
->
flags
&
AC97_MODEM_PATCH
))
||
(
!
modem
&&
!
(
pid
->
flags
&
AC97_MODEM_PATCH
)))
pid
->
patch
(
ac97
);
}
sprintf
(
name
+
strlen
(
name
),
" id %x"
,
id
&
0xff
);
}
else
sprintf
(
name
+
strlen
(
name
),
" id %x"
,
id
&
0xff
);
}
/**
...
...
@@ -1850,6 +1813,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
char
name
[
64
];
unsigned
long
end_time
;
unsigned
int
reg
;
const
ac97_codec_id_t
*
pid
;
static
snd_device_ops_t
ops
=
{
.
dev_free
=
snd_ac97_dev_free
,
};
...
...
@@ -1900,6 +1864,14 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
goto
__access_ok
;
}
ac97
->
id
=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID1
)
<<
16
;
ac97
->
id
|=
snd_ac97_read
(
ac97
,
AC97_VENDOR_ID2
);
if
(
ac97
->
id
&&
ac97
->
id
!=
(
unsigned
int
)
-
1
)
{
pid
=
look_for_codec_id
(
snd_ac97_codec_ids
,
ac97
->
id
);
if
(
pid
&&
(
pid
->
flags
&
AC97_DEFAULT_POWER_OFF
))
goto
__access_ok
;
}
snd_ac97_write
(
ac97
,
AC97_RESET
,
0
);
/* reset to defaults */
if
(
bus
->
ops
->
wait
)
bus
->
ops
->
wait
(
ac97
);
...
...
@@ -1926,6 +1898,9 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
snd_ac97_free
(
ac97
);
return
-
EIO
;
}
pid
=
look_for_codec_id
(
snd_ac97_codec_ids
,
ac97
->
id
);
if
(
pid
)
ac97
->
flags
|=
pid
->
flags
;
/* test for AC'97 */
if
(
!
(
ac97
->
scaps
&
AC97_SCAP_SKIP_AUDIO
)
&&
!
(
ac97
->
scaps
&
AC97_SCAP_AUDIO
))
{
...
...
@@ -1964,10 +1939,12 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
if
(
ac97_is_audio
(
ac97
))
{
/* nothing should be in powerdown mode */
snd_ac97_write_cache
(
ac97
,
AC97_POWERDOWN
,
0
);
snd_ac97_write_cache
(
ac97
,
AC97_RESET
,
0
);
/* reset to defaults */
udelay
(
100
);
if
(
!
(
ac97
->
flags
&
AC97_DEFAULT_POWER_OFF
))
{
snd_ac97_write_cache
(
ac97
,
AC97_RESET
,
0
);
/* reset to defaults */
udelay
(
100
);
snd_ac97_write_cache
(
ac97
,
AC97_POWERDOWN
,
0
);
}
/* nothing should be in powerdown mode */
snd_ac97_write_cache
(
ac97
,
AC97_POWERDOWN
,
0
);
snd_ac97_write_cache
(
ac97
,
AC97_GENERAL_PURPOSE
,
0
);
end_time
=
jiffies
+
(
HZ
/
10
);
do
{
...
...
@@ -2234,9 +2211,11 @@ void snd_ac97_resume(ac97_t *ac97)
}
snd_ac97_write
(
ac97
,
AC97_POWERDOWN
,
0
);
snd_ac97_write
(
ac97
,
AC97_RESET
,
0
);
udelay
(
100
);
snd_ac97_write
(
ac97
,
AC97_POWERDOWN
,
0
);
if
(
!
(
ac97
->
flags
&
AC97_DEFAULT_POWER_OFF
))
{
snd_ac97_write
(
ac97
,
AC97_RESET
,
0
);
udelay
(
100
);
snd_ac97_write
(
ac97
,
AC97_POWERDOWN
,
0
);
}
snd_ac97_write
(
ac97
,
AC97_GENERAL_PURPOSE
,
0
);
snd_ac97_write
(
ac97
,
AC97_POWERDOWN
,
ac97
->
regs
[
AC97_POWERDOWN
]);
...
...
sound/pci/ac97/ac97_local.h
View file @
e7e3950a
...
...
@@ -32,6 +32,19 @@
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
.get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
.private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
.get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
.mask = xmask, .texts = xtexts }
#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
#define AC97_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
.get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
.private_value = (unsigned long)&xenum }
/* ac97_codec.c */
extern
const
char
*
snd_ac97_stereo_enhancements
[];
...
...
@@ -49,6 +62,9 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *
void
snd_ac97_rename_vol_ctl
(
ac97_t
*
ac97
,
const
char
*
src
,
const
char
*
dst
);
void
snd_ac97_restore_status
(
ac97_t
*
ac97
);
void
snd_ac97_restore_iec958
(
ac97_t
*
ac97
);
int
snd_ac97_info_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_info_t
*
uinfo
);
int
snd_ac97_get_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
);
int
snd_ac97_put_enum_double
(
snd_kcontrol_t
*
kcontrol
,
snd_ctl_elem_value_t
*
ucontrol
);
int
snd_ac97_update_bits_nolock
(
ac97_t
*
ac97
,
unsigned
short
reg
,
unsigned
short
mask
,
unsigned
short
value
);
...
...
sound/pci/ac97/ac97_patch.c
View file @
e7e3950a
...
...
@@ -305,6 +305,136 @@ int patch_wolfson11(ac97_t * ac97)
return
0
;
}
static
const
char
*
wm9713_mic_mixer
[]
=
{
"Stereo"
,
"Mic1"
,
"Mic2"
,
"Mute"
};
static
const
char
*
wm9713_rec_mux
[]
=
{
"Stereo"
,
"Left"
,
"Right"
,
"Mute"
};
static
const
char
*
wm9713_rec_src_l
[]
=
{
"Mic1"
,
"Mic2"
,
"Line L"
,
"Mono In"
,
"HP Mix L"
,
"Spk Mix"
,
"Mono Mix"
,
"Zh"
};
static
const
char
*
wm9713_rec_src_r
[]
=
{
"Mic1"
,
"Mic2"
,
"Line R"
,
"Mono In"
,
"HP Mix R"
,
"Spk Mix"
,
"Mono Mix"
,
"Zh"
};
static
const
struct
ac97_enum
wm9713_enum
[]
=
{
AC97_ENUM_SINGLE
(
AC97_LINE
,
3
,
4
,
wm9713_mic_mixer
),
AC97_ENUM_SINGLE
(
AC97_VIDEO
,
14
,
4
,
wm9713_rec_mux
),
AC97_ENUM_SINGLE
(
AC97_VIDEO
,
9
,
4
,
wm9713_rec_mux
),
AC97_ENUM_SINGLE
(
AC97_VIDEO
,
3
,
8
,
wm9713_rec_src_l
),
AC97_ENUM_SINGLE
(
AC97_VIDEO
,
0
,
8
,
wm9713_rec_src_r
),
};
static
const
snd_kcontrol_new_t
wm13_snd_ac97_controls_line_in
[]
=
{
AC97_DOUBLE
(
"Line In Volume"
,
AC97_PC_BEEP
,
8
,
0
,
31
,
1
),
AC97_SINGLE
(
"Line In to Headphone Mute"
,
AC97_PC_BEEP
,
15
,
1
,
1
),
AC97_SINGLE
(
"Line In to Speaker Mute"
,
AC97_PC_BEEP
,
14
,
1
,
1
),
AC97_SINGLE
(
"Line In to Mono Mute"
,
AC97_PC_BEEP
,
13
,
1
,
1
),
};
static
const
snd_kcontrol_new_t
wm13_snd_ac97_controls_dac
[]
=
{
AC97_DOUBLE
(
"DAC Volume"
,
AC97_PHONE
,
8
,
0
,
31
,
1
),
AC97_SINGLE
(
"DAC to Headphone Mute"
,
AC97_PHONE
,
15
,
1
,
1
),
AC97_SINGLE
(
"DAC to Speaker Mute"
,
AC97_PHONE
,
14
,
1
,
1
),
AC97_SINGLE
(
"DAC to Mono Mute"
,
AC97_PHONE
,
13
,
1
,
1
),
};
static
const
snd_kcontrol_new_t
wm13_snd_ac97_controls_mic
[]
=
{
AC97_SINGLE
(
"MICA Volume"
,
AC97_MIC
,
8
,
31
,
1
),
AC97_SINGLE
(
"MICB Volume"
,
AC97_MIC
,
0
,
31
,
1
),
AC97_SINGLE
(
"MICA to Mono Mute"
,
AC97_LINE
,
7
,
1
,
1
),
AC97_SINGLE
(
"MICB to Mono Mute"
,
AC97_LINE
,
6
,
1
,
1
),
AC97_SINGLE
(
"MIC Boost (+20dB)"
,
AC97_LINE
,
5
,
1
,
1
),
AC97_ENUM
(
"MIC Headphone Routing"
,
wm9713_enum
[
0
]),
AC97_SINGLE
(
"MIC Headphone Mixer Volume"
,
AC97_LINE
,
0
,
7
,
1
)
};
static
const
snd_kcontrol_new_t
wm13_snd_ac97_controls_adc
[]
=
{
AC97_SINGLE
(
"ADC Mute"
,
AC97_CD
,
15
,
1
,
1
),
AC97_DOUBLE
(
"Gain Step Size (1.5dB/0.75dB)"
,
AC97_CD
,
14
,
6
,
1
,
1
),
AC97_DOUBLE
(
"ADC Volume"
,
AC97_CD
,
8
,
0
,
15
,
0
),
AC97_SINGLE
(
"ADC Zero Cross"
,
AC97_CD
,
7
,
1
,
1
),
};
static
const
snd_kcontrol_new_t
wm13_snd_ac97_controls_recsel
[]
=
{
AC97_ENUM
(
"Record to Headphone Path"
,
wm9713_enum
[
1
]),
AC97_SINGLE
(
"Record to Headphone Volume"
,
AC97_VIDEO
,
11
,
7
,
0
),
AC97_ENUM
(
"Record to Mono Path"
,
wm9713_enum
[
2
]),
AC97_SINGLE
(
"Record to Mono Boost (+20dB)"
,
AC97_VIDEO
,
8
,
1
,
0
),
AC97_SINGLE
(
"Record ADC Boost (+20dB)"
,
AC97_VIDEO
,
6
,
1
,
0
),
AC97_ENUM
(
"Record Select Left"
,
wm9713_enum
[
3
]),
AC97_ENUM
(
"Record Select Right"
,
wm9713_enum
[
4
]),
};
static
int
patch_wolfson_wm9713_specific
(
ac97_t
*
ac97
)
{
int
err
,
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm13_snd_ac97_controls_line_in
);
i
++
)
{
if
((
err
=
snd_ctl_add
(
ac97
->
bus
->
card
,
snd_ac97_cnew
(
&
wm13_snd_ac97_controls_line_in
[
i
],
ac97
)))
<
0
)
return
err
;
}
snd_ac97_write_cache
(
ac97
,
AC97_PC_BEEP
,
0x0808
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm13_snd_ac97_controls_dac
);
i
++
)
{
if
((
err
=
snd_ctl_add
(
ac97
->
bus
->
card
,
snd_ac97_cnew
(
&
wm13_snd_ac97_controls_dac
[
i
],
ac97
)))
<
0
)
return
err
;
}
snd_ac97_write_cache
(
ac97
,
AC97_PHONE
,
0x0808
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm13_snd_ac97_controls_mic
);
i
++
)
{
if
((
err
=
snd_ctl_add
(
ac97
->
bus
->
card
,
snd_ac97_cnew
(
&
wm13_snd_ac97_controls_mic
[
i
],
ac97
)))
<
0
)
return
err
;
}
snd_ac97_write_cache
(
ac97
,
AC97_MIC
,
0x0808
);
snd_ac97_write_cache
(
ac97
,
AC97_LINE
,
0x00da
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm13_snd_ac97_controls_adc
);
i
++
)
{
if
((
err
=
snd_ctl_add
(
ac97
->
bus
->
card
,
snd_ac97_cnew
(
&
wm13_snd_ac97_controls_adc
[
i
],
ac97
)))
<
0
)
return
err
;
}
snd_ac97_write_cache
(
ac97
,
AC97_CD
,
0x0808
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm13_snd_ac97_controls_recsel
);
i
++
)
{
if
((
err
=
snd_ctl_add
(
ac97
->
bus
->
card
,
snd_ac97_cnew
(
&
wm13_snd_ac97_controls_recsel
[
i
],
ac97
)))
<
0
)
return
err
;
}
snd_ac97_write_cache
(
ac97
,
AC97_VIDEO
,
0xd612
);
snd_ac97_write_cache
(
ac97
,
AC97_REC_GAIN
,
0x1ba0
);
return
0
;
}
#ifdef CONFIG_PM
static
void
patch_wolfson_wm9713_suspend
(
ac97_t
*
ac97
)
{
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MID
,
0xfeff
);
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MSTATUS
,
0xffff
);
}
static
void
patch_wolfson_wm9713_resume
(
ac97_t
*
ac97
)
{
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MID
,
0xda00
);
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MSTATUS
,
0x3810
);
snd_ac97_write_cache
(
ac97
,
AC97_POWERDOWN
,
0x0
);
}
#endif
static
struct
snd_ac97_build_ops
patch_wolfson_wm9713_ops
=
{
.
build_specific
=
patch_wolfson_wm9713_specific
,
#ifdef CONFIG_PM
.
suspend
=
patch_wolfson_wm9713_suspend
,
.
resume
=
patch_wolfson_wm9713_resume
#endif
};
int
patch_wolfson13
(
ac97_t
*
ac97
)
{
ac97
->
build_ops
=
&
patch_wolfson_wm9713_ops
;
ac97
->
flags
|=
AC97_HAS_NO_REC_GAIN
|
AC97_STEREO_MUTES
|
AC97_HAS_NO_PHONE
|
AC97_HAS_NO_PC_BEEP
|
AC97_HAS_NO_VIDEO
|
AC97_HAS_NO_CD
;
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MID
,
0xda00
);
snd_ac97_write_cache
(
ac97
,
AC97_EXTENDED_MSTATUS
,
0x3810
);
snd_ac97_write_cache
(
ac97
,
AC97_POWERDOWN
,
0x0
);
return
0
;
}
/*
* Tritech codec
*/
...
...
sound/pci/ac97/ac97_patch.h
View file @
e7e3950a
...
...
@@ -28,6 +28,7 @@ int patch_wolfson03(ac97_t * ac97);
int
patch_wolfson04
(
ac97_t
*
ac97
);
int
patch_wolfson05
(
ac97_t
*
ac97
);
int
patch_wolfson11
(
ac97_t
*
ac97
);
int
patch_wolfson13
(
ac97_t
*
ac97
);
int
patch_tritech_tr28028
(
ac97_t
*
ac97
);
int
patch_sigmatel_stac9700
(
ac97_t
*
ac97
);
int
patch_sigmatel_stac9708
(
ac97_t
*
ac97
);
...
...
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