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
fc0daafe
Commit
fc0daafe
authored
Mar 20, 2015
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/hda-power' into for-next
parents
b24062bd
5ccf835c
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
427 additions
and
802 deletions
+427
-802
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_beep.c
+16
-13
sound/pci/hda/hda_beep.h
sound/pci/hda/hda_beep.h
+1
-0
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.c
+4
-0
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+2
-0
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.c
+383
-97
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_generic.h
+4
-1
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_realtek.c
+0
-41
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_sigmatel.c
+5
-0
sound/pci/hda/patch_via.c
sound/pci/hda/patch_via.c
+12
-650
No files found.
sound/pci/hda/hda_beep.c
View file @
fc0daafe
...
...
@@ -33,30 +33,36 @@ enum {
DIGBEEP_HZ_MAX
=
12000000
,
/* 12 KHz */
};
static
void
snd_hda_generate_beep
(
struct
work_struct
*
work
)
/* generate or stop tone */
static
void
generate_tone
(
struct
hda_beep
*
beep
,
int
tone
)
{
struct
hda_beep
*
beep
=
container_of
(
work
,
struct
hda_beep
,
beep_work
);
struct
hda_codec
*
codec
=
beep
->
codec
;
int
tone
;
if
(
!
beep
->
enabled
)
return
;
tone
=
beep
->
tone
;
if
(
tone
&&
!
beep
->
playing
)
{
snd_hda_power_up
(
codec
);
if
(
beep
->
power_hook
)
beep
->
power_hook
(
beep
,
true
);
beep
->
playing
=
1
;
}
/* generate tone */
snd_hda_codec_write
(
codec
,
beep
->
nid
,
0
,
AC_VERB_SET_BEEP_CONTROL
,
tone
);
if
(
!
tone
&&
beep
->
playing
)
{
beep
->
playing
=
0
;
if
(
beep
->
power_hook
)
beep
->
power_hook
(
beep
,
false
);
snd_hda_power_down
(
codec
);
}
}
static
void
snd_hda_generate_beep
(
struct
work_struct
*
work
)
{
struct
hda_beep
*
beep
=
container_of
(
work
,
struct
hda_beep
,
beep_work
);
if
(
beep
->
enabled
)
generate_tone
(
beep
,
beep
->
tone
);
}
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
*
* The tone frequency of beep generator on IDT/STAC codecs is
...
...
@@ -130,10 +136,7 @@ static void turn_off_beep(struct hda_beep *beep)
cancel_work_sync
(
&
beep
->
beep_work
);
if
(
beep
->
playing
)
{
/* turn off beep */
snd_hda_codec_write
(
beep
->
codec
,
beep
->
nid
,
0
,
AC_VERB_SET_BEEP_CONTROL
,
0
);
beep
->
playing
=
0
;
snd_hda_power_down
(
beep
->
codec
);
generate_tone
(
beep
,
0
);
}
}
...
...
sound/pci/hda/hda_beep.h
View file @
fc0daafe
...
...
@@ -40,6 +40,7 @@ struct hda_beep {
unsigned
int
playing
:
1
;
struct
work_struct
beep_work
;
/* scheduled task for beep event */
struct
mutex
mutex
;
void
(
*
power_hook
)(
struct
hda_beep
*
beep
,
bool
on
);
};
#ifdef CONFIG_SND_HDA_INPUT_BEEP
...
...
sound/pci/hda/hda_codec.c
View file @
fc0daafe
...
...
@@ -1502,6 +1502,8 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
if
(
!
p
)
return
;
if
(
codec
->
patch_ops
.
stream_pm
)
codec
->
patch_ops
.
stream_pm
(
codec
,
nid
,
true
);
if
(
codec
->
pcm_format_first
)
update_pcm_format
(
codec
,
p
,
nid
,
format
);
update_pcm_stream_id
(
codec
,
p
,
nid
,
stream_tag
,
channel_id
);
...
...
@@ -1570,6 +1572,8 @@ static void really_cleanup_stream(struct hda_codec *codec,
);
memset
(
q
,
0
,
sizeof
(
*
q
));
q
->
nid
=
nid
;
if
(
codec
->
patch_ops
.
stream_pm
)
codec
->
patch_ops
.
stream_pm
(
codec
,
nid
,
false
);
}
/* clean up the all conflicting obsolete streams */
...
...
sound/pci/hda/hda_codec.h
View file @
fc0daafe
...
...
@@ -200,6 +200,7 @@ struct hda_codec_ops {
int
(
*
check_power_status
)(
struct
hda_codec
*
codec
,
hda_nid_t
nid
);
#endif
void
(
*
reboot_notify
)(
struct
hda_codec
*
codec
);
void
(
*
stream_pm
)(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
bool
on
);
};
/* record for amp information cache */
...
...
@@ -370,6 +371,7 @@ struct hda_codec {
unsigned
int
cached_write
:
1
;
/* write only to caches */
unsigned
int
dp_mst
:
1
;
/* support DP1.2 Multi-stream transport */
unsigned
int
dump_coef
:
1
;
/* dump processing coefs in codec proc file */
unsigned
int
power_mgmt
:
1
;
/* advanced PM for each widget */
#ifdef CONFIG_PM
unsigned
int
d3_stop_clk
:
1
;
/* support D3 operation without BCLK */
atomic_t
in_pm
;
/* suspend/resume being performed */
...
...
sound/pci/hda/hda_generic.c
View file @
fc0daafe
...
...
@@ -140,6 +140,9 @@ static void parse_user_hints(struct hda_codec *codec)
val
=
snd_hda_get_bool_hint
(
codec
,
"single_adc_amp"
);
if
(
val
>=
0
)
codec
->
single_adc_amp
=
!!
val
;
val
=
snd_hda_get_bool_hint
(
codec
,
"power_mgmt"
);
if
(
val
>=
0
)
codec
->
power_mgmt
=
!!
val
;
val
=
snd_hda_get_bool_hint
(
codec
,
"auto_mute"
);
if
(
val
>=
0
)
...
...
@@ -648,12 +651,24 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
unsigned
int
dir
,
unsigned
int
idx
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
int
type
=
get_wcaps_type
(
get_wcaps
(
codec
,
nid
));
int
i
,
n
;
if
(
nid
==
codec
->
afg
)
return
true
;
for
(
n
=
0
;
n
<
spec
->
paths
.
used
;
n
++
)
{
struct
nid_path
*
path
=
snd_array_elem
(
&
spec
->
paths
,
n
);
if
(
!
path
->
active
)
continue
;
if
(
codec
->
power_mgmt
)
{
if
(
!
path
->
stream_enabled
)
continue
;
/* ignore unplugged paths except for DAC/ADC */
if
(
!
path
->
pin_enabled
&&
type
!=
AC_WID_AUD_OUT
&&
type
!=
AC_WID_AUD_IN
)
continue
;
}
for
(
i
=
0
;
i
<
path
->
depth
;
i
++
)
{
if
(
path
->
path
[
i
]
==
nid
)
{
if
(
dir
==
HDA_OUTPUT
||
path
->
idx
[
i
]
==
idx
)
...
...
@@ -807,6 +822,44 @@ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
}
}
/* sync power of each widget in the the given path */
static
hda_nid_t
path_power_update
(
struct
hda_codec
*
codec
,
struct
nid_path
*
path
,
bool
allow_powerdown
)
{
hda_nid_t
nid
,
changed
=
0
;
int
i
,
state
;
for
(
i
=
0
;
i
<
path
->
depth
;
i
++
)
{
nid
=
path
->
path
[
i
];
if
(
nid
==
codec
->
afg
)
continue
;
if
(
!
allow_powerdown
||
is_active_nid_for_any
(
codec
,
nid
))
state
=
AC_PWRST_D0
;
else
state
=
AC_PWRST_D3
;
if
(
!
snd_hda_check_power_state
(
codec
,
nid
,
state
))
{
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
state
);
changed
=
nid
;
/* here we assume that widget attributes (e.g. amp,
* pinctl connection) don't change with local power
* state change. If not, need to sync the cache.
*/
}
}
return
changed
;
}
/* do sync with the last power state change */
static
void
sync_power_state_change
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
if
(
nid
)
{
msleep
(
10
);
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_POWER_STATE
,
0
);
}
}
/**
* snd_hda_activate_path - activate or deactivate the given path
* @codec: the HDA codec
...
...
@@ -825,15 +878,13 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
if
(
!
enable
)
path
->
active
=
false
;
/* make sure the widget is powered up */
if
(
enable
&&
(
spec
->
power_down_unused
||
codec
->
power_mgmt
))
path_power_update
(
codec
,
path
,
codec
->
power_mgmt
);
for
(
i
=
path
->
depth
-
1
;
i
>=
0
;
i
--
)
{
hda_nid_t
nid
=
path
->
path
[
i
];
if
(
enable
&&
spec
->
power_down_unused
)
{
/* make sure the widget is powered up */
if
(
!
snd_hda_check_power_state
(
codec
,
nid
,
AC_PWRST_D0
))
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D0
);
}
if
(
enable
&&
path
->
multi
[
i
])
snd_hda_codec_update_cache
(
codec
,
nid
,
0
,
AC_VERB_SET_CONNECT_SEL
,
...
...
@@ -853,28 +904,10 @@ EXPORT_SYMBOL_GPL(snd_hda_activate_path);
static
void
path_power_down_sync
(
struct
hda_codec
*
codec
,
struct
nid_path
*
path
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
bool
changed
=
false
;
int
i
;
if
(
!
spec
->
power_down_unused
||
path
->
active
)
if
(
!
(
spec
->
power_down_unused
||
codec
->
power_mgmt
)
||
path
->
active
)
return
;
for
(
i
=
0
;
i
<
path
->
depth
;
i
++
)
{
hda_nid_t
nid
=
path
->
path
[
i
];
if
(
!
snd_hda_check_power_state
(
codec
,
nid
,
AC_PWRST_D3
)
&&
!
is_active_nid_for_any
(
codec
,
nid
))
{
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D3
);
changed
=
true
;
}
}
if
(
changed
)
{
msleep
(
10
);
snd_hda_codec_read
(
codec
,
path
->
path
[
0
],
0
,
AC_VERB_GET_POWER_STATE
,
0
);
}
sync_power_state_change
(
codec
,
path_power_update
(
codec
,
path
,
true
));
}
/* turn on/off EAPD on the given pin */
...
...
@@ -1574,6 +1607,7 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
return
0
;
/* print_nid_path(codec, "output-aamix", path); */
path
->
active
=
false
;
/* unused as default */
path
->
pin_enabled
=
true
;
/* static route */
return
snd_hda_get_path_idx
(
codec
,
path
);
}
...
...
@@ -2998,6 +3032,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
}
path
->
active
=
true
;
path
->
stream_enabled
=
true
;
/* no DAC/ADC involved */
err
=
add_loopback_list
(
spec
,
mix_nid
,
idx
);
if
(
err
<
0
)
return
err
;
...
...
@@ -3009,6 +3044,8 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
if
(
path
)
{
print_nid_path
(
codec
,
"loopback-merge"
,
path
);
path
->
active
=
true
;
path
->
pin_enabled
=
true
;
/* static route */
path
->
stream_enabled
=
true
;
/* no DAC/ADC involved */
spec
->
loopback_merge_path
=
snd_hda_get_path_idx
(
codec
,
path
);
}
...
...
@@ -3810,6 +3847,7 @@ static void parse_digital(struct hda_codec *codec)
continue
;
print_nid_path
(
codec
,
"digout"
,
path
);
path
->
active
=
true
;
path
->
pin_enabled
=
true
;
/* no jack detection */
spec
->
digout_paths
[
i
]
=
snd_hda_get_path_idx
(
codec
,
path
);
set_pin_target
(
codec
,
pin
,
PIN_OUT
,
false
);
if
(
!
nums
)
{
...
...
@@ -3837,6 +3875,7 @@ static void parse_digital(struct hda_codec *codec)
if
(
path
)
{
print_nid_path
(
codec
,
"digin"
,
path
);
path
->
active
=
true
;
path
->
pin_enabled
=
true
;
/* no jack */
spec
->
dig_in_nid
=
dig_nid
;
spec
->
digin_path
=
snd_hda_get_path_idx
(
codec
,
path
);
set_pin_target
(
codec
,
pin
,
PIN_IN
,
false
);
...
...
@@ -3896,6 +3935,206 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
return
1
;
}
/* power up/down widgets in the all paths that match with the given NID
* as terminals (either start- or endpoint)
*
* returns the last changed NID, or zero if unchanged.
*/
static
hda_nid_t
set_path_power
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
pin_state
,
int
stream_state
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
hda_nid_t
last
,
changed
=
0
;
struct
nid_path
*
path
;
int
n
;
for
(
n
=
0
;
n
<
spec
->
paths
.
used
;
n
++
)
{
path
=
snd_array_elem
(
&
spec
->
paths
,
n
);
if
(
path
->
path
[
0
]
==
nid
||
path
->
path
[
path
->
depth
-
1
]
==
nid
)
{
bool
pin_old
=
path
->
pin_enabled
;
bool
stream_old
=
path
->
stream_enabled
;
if
(
pin_state
>=
0
)
path
->
pin_enabled
=
pin_state
;
if
(
stream_state
>=
0
)
path
->
stream_enabled
=
stream_state
;
if
(
path
->
pin_enabled
!=
pin_old
||
path
->
stream_enabled
!=
stream_old
)
{
last
=
path_power_update
(
codec
,
path
,
true
);
if
(
last
)
changed
=
last
;
}
}
}
return
changed
;
}
/* power up/down the paths of the given pin according to the jack state;
* power = 0/1 : only power up/down if it matches with the jack state,
* < 0 : force power up/down to follow the jack sate
*
* returns the last changed NID, or zero if unchanged.
*/
static
hda_nid_t
set_pin_power_jack
(
struct
hda_codec
*
codec
,
hda_nid_t
pin
,
int
power
)
{
bool
on
;
if
(
!
codec
->
power_mgmt
)
return
0
;
on
=
snd_hda_jack_detect_state
(
codec
,
pin
)
!=
HDA_JACK_NOT_PRESENT
;
if
(
power
>=
0
&&
on
!=
power
)
return
0
;
return
set_path_power
(
codec
,
pin
,
on
,
-
1
);
}
static
void
pin_power_callback
(
struct
hda_codec
*
codec
,
struct
hda_jack_callback
*
jack
,
bool
on
)
{
if
(
jack
&&
jack
->
tbl
->
nid
)
sync_power_state_change
(
codec
,
set_pin_power_jack
(
codec
,
jack
->
tbl
->
nid
,
on
));
}
/* callback only doing power up -- called at first */
static
void
pin_power_up_callback
(
struct
hda_codec
*
codec
,
struct
hda_jack_callback
*
jack
)
{
pin_power_callback
(
codec
,
jack
,
true
);
}
/* callback only doing power down -- called at last */
static
void
pin_power_down_callback
(
struct
hda_codec
*
codec
,
struct
hda_jack_callback
*
jack
)
{
pin_power_callback
(
codec
,
jack
,
false
);
}
/* set up the power up/down callbacks */
static
void
add_pin_power_ctls
(
struct
hda_codec
*
codec
,
int
num_pins
,
const
hda_nid_t
*
pins
,
bool
on
)
{
int
i
;
hda_jack_callback_fn
cb
=
on
?
pin_power_up_callback
:
pin_power_down_callback
;
for
(
i
=
0
;
i
<
num_pins
&&
pins
[
i
];
i
++
)
{
if
(
is_jack_detectable
(
codec
,
pins
[
i
]))
snd_hda_jack_detect_enable_callback
(
codec
,
pins
[
i
],
cb
);
else
set_path_power
(
codec
,
pins
[
i
],
true
,
-
1
);
}
}
/* enabled power callback to each available I/O pin with jack detections;
* the digital I/O pins are excluded because of the unreliable detectsion
*/
static
void
add_all_pin_power_ctls
(
struct
hda_codec
*
codec
,
bool
on
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
struct
auto_pin_cfg
*
cfg
=
&
spec
->
autocfg
;
int
i
;
if
(
!
codec
->
power_mgmt
)
return
;
add_pin_power_ctls
(
codec
,
cfg
->
line_outs
,
cfg
->
line_out_pins
,
on
);
if
(
cfg
->
line_out_type
!=
AUTO_PIN_HP_OUT
)
add_pin_power_ctls
(
codec
,
cfg
->
hp_outs
,
cfg
->
hp_pins
,
on
);
if
(
cfg
->
line_out_type
!=
AUTO_PIN_SPEAKER_OUT
)
add_pin_power_ctls
(
codec
,
cfg
->
speaker_outs
,
cfg
->
speaker_pins
,
on
);
for
(
i
=
0
;
i
<
cfg
->
num_inputs
;
i
++
)
add_pin_power_ctls
(
codec
,
1
,
&
cfg
->
inputs
[
i
].
pin
,
on
);
}
/* sync path power up/down with the jack states of given pins */
static
void
sync_pin_power_ctls
(
struct
hda_codec
*
codec
,
int
num_pins
,
const
hda_nid_t
*
pins
)
{
int
i
;
for
(
i
=
0
;
i
<
num_pins
&&
pins
[
i
];
i
++
)
if
(
is_jack_detectable
(
codec
,
pins
[
i
]))
set_pin_power_jack
(
codec
,
pins
[
i
],
-
1
);
}
/* sync path power up/down with pins; called at init and resume */
static
void
sync_all_pin_power_ctls
(
struct
hda_codec
*
codec
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
struct
auto_pin_cfg
*
cfg
=
&
spec
->
autocfg
;
int
i
;
if
(
!
codec
->
power_mgmt
)
return
;
sync_pin_power_ctls
(
codec
,
cfg
->
line_outs
,
cfg
->
line_out_pins
);
if
(
cfg
->
line_out_type
!=
AUTO_PIN_HP_OUT
)
sync_pin_power_ctls
(
codec
,
cfg
->
hp_outs
,
cfg
->
hp_pins
);
if
(
cfg
->
line_out_type
!=
AUTO_PIN_SPEAKER_OUT
)
sync_pin_power_ctls
(
codec
,
cfg
->
speaker_outs
,
cfg
->
speaker_pins
);
for
(
i
=
0
;
i
<
cfg
->
num_inputs
;
i
++
)
sync_pin_power_ctls
(
codec
,
1
,
&
cfg
->
inputs
[
i
].
pin
);
}
/* add fake paths if not present yet */
static
int
add_fake_paths
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
num_pins
,
const
hda_nid_t
*
pins
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
struct
nid_path
*
path
;
int
i
;
for
(
i
=
0
;
i
<
num_pins
;
i
++
)
{
if
(
!
pins
[
i
])
break
;
if
(
get_nid_path
(
codec
,
nid
,
pins
[
i
],
0
))
continue
;
path
=
snd_array_new
(
&
spec
->
paths
);
if
(
!
path
)
return
-
ENOMEM
;
memset
(
path
,
0
,
sizeof
(
*
path
));
path
->
depth
=
2
;
path
->
path
[
0
]
=
nid
;
path
->
path
[
1
]
=
pins
[
i
];
path
->
active
=
true
;
}
return
0
;
}
/* create fake paths to all outputs from beep */
static
int
add_fake_beep_paths
(
struct
hda_codec
*
codec
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
struct
auto_pin_cfg
*
cfg
=
&
spec
->
autocfg
;
hda_nid_t
nid
=
spec
->
beep_nid
;
int
err
;
if
(
!
codec
->
power_mgmt
||
!
nid
)
return
0
;
err
=
add_fake_paths
(
codec
,
nid
,
cfg
->
line_outs
,
cfg
->
line_out_pins
);
if
(
err
<
0
)
return
err
;
if
(
cfg
->
line_out_type
!=
AUTO_PIN_HP_OUT
)
{
err
=
add_fake_paths
(
codec
,
nid
,
cfg
->
hp_outs
,
cfg
->
hp_pins
);
if
(
err
<
0
)
return
err
;
}
if
(
cfg
->
line_out_type
!=
AUTO_PIN_SPEAKER_OUT
)
{
err
=
add_fake_paths
(
codec
,
nid
,
cfg
->
speaker_outs
,
cfg
->
speaker_pins
);
if
(
err
<
0
)
return
err
;
}
return
0
;
}
/* power up/down beep widget and its output paths */
static
void
beep_power_hook
(
struct
hda_beep
*
beep
,
bool
on
)
{
set_path_power
(
beep
->
codec
,
beep
->
nid
,
-
1
,
on
);
}
/*
* Jack detections for HP auto-mute and mic-switch
...
...
@@ -3933,6 +4172,10 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
if
(
!
nid
)
break
;
oldval
=
snd_hda_codec_get_pin_target
(
codec
,
nid
);
if
(
oldval
&
PIN_IN
)
continue
;
/* no mute for inputs */
if
(
spec
->
auto_mute_via_amp
)
{
struct
nid_path
*
path
;
hda_nid_t
mute_nid
;
...
...
@@ -3947,29 +4190,33 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
spec
->
mute_bits
|=
(
1ULL
<<
mute_nid
);
else
spec
->
mute_bits
&=
~
(
1ULL
<<
mute_nid
);
set_pin_eapd
(
codec
,
nid
,
!
mute
);
continue
;
}
else
{
/* don't reset VREF value in case it's controlling
* the amp (see alc861_fixup_asus_amp_vref_0f())
*/
if
(
spec
->
keep_vref_in_automute
)
val
=
oldval
&
~
PIN_HP
;
else
val
=
0
;
if
(
!
mute
)
val
|=
oldval
;
/* here we call update_pin_ctl() so that the pinctl is
* changed without changing the pinctl target value;
* the original target value will be still referred at
* the init / resume again
*/
update_pin_ctl
(
codec
,
nid
,
val
);
}
oldval
=
snd_hda_codec_get_pin_target
(
codec
,
nid
);
if
(
oldval
&
PIN_IN
)
continue
;
/* no mute for inputs */
/* don't reset VREF value in case it's controlling
* the amp (see alc861_fixup_asus_amp_vref_0f())
*/
if
(
spec
->
keep_vref_in_automute
)
val
=
oldval
&
~
PIN_HP
;
else
val
=
0
;
if
(
!
mute
)
val
|=
oldval
;
/* here we call update_pin_ctl() so that the pinctl is changed
* without changing the pinctl target value;
* the original target value will be still referred at the
* init / resume again
*/
update_pin_ctl
(
codec
,
nid
,
val
);
set_pin_eapd
(
codec
,
nid
,
!
mute
);
if
(
codec
->
power_mgmt
)
{
bool
on
=
!
mute
;
if
(
on
)
on
=
snd_hda_jack_detect_state
(
codec
,
nid
)
!=
HDA_JACK_NOT_PRESENT
;
set_path_power
(
codec
,
nid
,
on
,
-
1
);
}
}
}
...
...
@@ -4465,6 +4712,21 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
}
}
/**
* snd_hda_gen_stream_pm - Stream power management callback
* @codec: the HDA codec
* @nid: audio widget
* @on: power on/off flag
*
* Set this in patch_ops.stream_pm. Only valid with power_mgmt flag.
*/
void
snd_hda_gen_stream_pm
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
bool
on
)
{
if
(
codec
->
power_mgmt
)
set_path_power
(
codec
,
nid
,
-
1
,
on
);
}
EXPORT_SYMBOL_GPL
(
snd_hda_gen_stream_pm
);
/**
* snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
* set up the hda_gen_spec
...
...
@@ -4549,6 +4811,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
if
(
err
<
0
)
return
err
;
/* add power-down pin callbacks at first */
add_all_pin_power_ctls
(
codec
,
false
);
spec
->
const_channel_count
=
spec
->
ext_channel_count
;
/* check the multiple speaker and headphone pins */
if
(
cfg
->
line_out_type
!=
AUTO_PIN_SPEAKER_OUT
)
...
...
@@ -4618,6 +4883,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
}
}
/* add power-up pin callbacks at last */
add_all_pin_power_ctls
(
codec
,
true
);
/* mute all aamix input initially */
if
(
spec
->
mixer_nid
)
mute_all_mixer_nid
(
codec
,
spec
->
mixer_nid
);
...
...
@@ -4625,13 +4893,19 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
dig_only:
parse_digital
(
codec
);
if
(
spec
->
power_down_unused
)
if
(
spec
->
power_down_unused
||
codec
->
power_mgmt
)
codec
->
power_filter
=
snd_hda_gen_path_power_filter
;
if
(
!
spec
->
no_analog
&&
spec
->
beep_nid
)
{
err
=
snd_hda_attach_beep_device
(
codec
,
spec
->
beep_nid
);
if
(
err
<
0
)
return
err
;
if
(
codec
->
beep
&&
codec
->
power_mgmt
)
{
err
=
add_fake_beep_paths
(
codec
);
if
(
err
<
0
)
return
err
;
codec
->
beep
->
power_hook
=
beep_power_hook
;
}
}
return
1
;
...
...
@@ -5137,6 +5411,33 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
strlcat
(
str
,
sfx
,
len
);
}
/* copy PCM stream info from @default_str, and override non-NULL entries
* from @spec_str and @nid
*/
static
void
setup_pcm_stream
(
struct
hda_pcm_stream
*
str
,
const
struct
hda_pcm_stream
*
default_str
,
const
struct
hda_pcm_stream
*
spec_str
,
hda_nid_t
nid
)
{
*
str
=
*
default_str
;
if
(
nid
)
str
->
nid
=
nid
;
if
(
spec_str
)
{
if
(
spec_str
->
substreams
)
str
->
substreams
=
spec_str
->
substreams
;
if
(
spec_str
->
channels_min
)
str
->
channels_min
=
spec_str
->
channels_min
;
if
(
spec_str
->
channels_max
)
str
->
channels_max
=
spec_str
->
channels_max
;
if
(
spec_str
->
rates
)
str
->
rates
=
spec_str
->
rates
;
if
(
spec_str
->
formats
)
str
->
formats
=
spec_str
->
formats
;
if
(
spec_str
->
maxbps
)
str
->
maxbps
=
spec_str
->
maxbps
;
}
}
/**
* snd_hda_gen_build_pcms - build PCM streams based on the parsed results
* @codec: the HDA codec
...
...
@@ -5147,7 +5448,6 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
struct
hda_pcm
*
info
;
const
struct
hda_pcm_stream
*
p
;
bool
have_multi_adcs
;
if
(
spec
->
no_analog
)
...
...
@@ -5162,11 +5462,10 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
spec
->
pcm_rec
[
0
]
=
info
;
if
(
spec
->
multiout
.
num_dacs
>
0
)
{
p
=
spec
->
stream_analog_playback
;
if
(
!
p
)
p
=
&
pcm_analog_playback
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
].
nid
=
spec
->
multiout
.
dac_nids
[
0
];
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
],
&
pcm_analog_playback
,
spec
->
stream_analog_playback
,
spec
->
multiout
.
dac_nids
[
0
]);
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
].
channels_max
=
spec
->
multiout
.
max_channels
;
if
(
spec
->
autocfg
.
line_out_type
==
AUTO_PIN_SPEAKER_OUT
&&
...
...
@@ -5175,15 +5474,11 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
snd_pcm_2_1_chmaps
;
}
if
(
spec
->
num_adc_nids
)
{
p
=
spec
->
stream_analog_capture
;
if
(
!
p
)
{
if
(
spec
->
dyn_adc_switch
)
p
=
&
dyn_adc_pcm_analog_capture
;
else
p
=
&
pcm_analog_capture
;
}
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
].
nid
=
spec
->
adc_nids
[
0
];
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
],
(
spec
->
dyn_adc_switch
?
&
dyn_adc_pcm_analog_capture
:
&
pcm_analog_capture
),
spec
->
stream_analog_capture
,
spec
->
adc_nids
[
0
]);
}
skip_analog:
...
...
@@ -5202,20 +5497,16 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
info
->
pcm_type
=
spec
->
dig_out_type
;
else
info
->
pcm_type
=
HDA_PCM_TYPE_SPDIF
;
if
(
spec
->
multiout
.
dig_out_nid
)
{
p
=
spec
->
stream_digital_playback
;
if
(
!
p
)
p
=
&
pcm_digital_playback
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
].
nid
=
spec
->
multiout
.
dig_out_nid
;
}
if
(
spec
->
dig_in_nid
)
{
p
=
spec
->
stream_digital_capture
;
if
(
!
p
)
p
=
&
pcm_digital_capture
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
].
nid
=
spec
->
dig_in_nid
;
}
if
(
spec
->
multiout
.
dig_out_nid
)
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
],
&
pcm_digital_playback
,
spec
->
stream_digital_playback
,
spec
->
multiout
.
dig_out_nid
);
if
(
spec
->
dig_in_nid
)
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
],
&
pcm_digital_capture
,
spec
->
stream_digital_capture
,
spec
->
dig_in_nid
);
}
if
(
spec
->
no_analog
)
...
...
@@ -5236,31 +5527,24 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
if
(
!
info
)
return
-
ENOMEM
;
spec
->
pcm_rec
[
2
]
=
info
;
if
(
spec
->
alt_dac_nid
)
{
p
=
spec
->
stream_analog_alt_playback
;
if
(
!
p
)
p
=
&
pcm_analog_alt_playback
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
].
nid
=
spec
->
alt_dac_nid
;
}
else
{
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
pcm_null_stream
;
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
].
nid
=
0
;
}
if
(
spec
->
alt_dac_nid
)
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
],
&
pcm_analog_alt_playback
,
spec
->
stream_analog_alt_playback
,
spec
->
alt_dac_nid
);
else
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_PLAYBACK
],
&
pcm_null_stream
,
NULL
,
0
);
if
(
have_multi_adcs
)
{
p
=
spec
->
stream_analog_alt_capture
;
if
(
!
p
)
p
=
&
pcm_analog_alt_capture
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
]
=
*
p
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
].
nid
=
spec
->
adc_nids
[
1
];
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
],
&
pcm_analog_alt_capture
,
spec
->
stream_analog_alt_capture
,
spec
->
adc_nids
[
1
]);
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
].
substreams
=
spec
->
num_adc_nids
-
1
;
}
else
{
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
]
=
pcm_null_stream
;
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
].
nid
=
0
;
setup_pcm_stream
(
&
info
->
stream
[
SNDRV_PCM_STREAM_CAPTURE
],
&
pcm_null_stream
,
NULL
,
0
);
}
}
...
...
@@ -5468,6 +5752,8 @@ int snd_hda_gen_init(struct hda_codec *codec)
clear_unsol_on_unused_pins
(
codec
);
sync_all_pin_power_ctls
(
codec
);
/* call init functions of standard auto-mute helpers */
update_automute_all
(
codec
);
...
...
sound/pci/hda/hda_generic.h
View file @
fc0daafe
...
...
@@ -46,7 +46,9 @@ struct nid_path {
unsigned
char
idx
[
MAX_NID_PATH_DEPTH
];
unsigned
char
multi
[
MAX_NID_PATH_DEPTH
];
unsigned
int
ctls
[
NID_PATH_NUM_CTLS
];
/* NID_PATH_XXX_CTL */
bool
active
;
bool
active
:
1
;
/* activated by driver */
bool
pin_enabled
:
1
;
/* pins are enabled */
bool
stream_enabled
:
1
;
/* stream is active */
};
/* mic/line-in auto switching entry */
...
...
@@ -340,5 +342,6 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
unsigned
int
snd_hda_gen_path_power_filter
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
power_state
);
void
snd_hda_gen_stream_pm
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
bool
on
);
#endif
/* __SOUND_HDA_GENERIC_H */
sound/pci/hda/patch_realtek.c
View file @
fc0daafe
...
...
@@ -2602,53 +2602,12 @@ static int patch_alc268(struct hda_codec *codec)
* ALC269
*/
static
int
playback_pcm_open
(
struct
hda_pcm_stream
*
hinfo
,
struct
hda_codec
*
codec
,
struct
snd_pcm_substream
*
substream
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
return
snd_hda_multi_out_analog_open
(
codec
,
&
spec
->
multiout
,
substream
,
hinfo
);
}
static
int
playback_pcm_prepare
(
struct
hda_pcm_stream
*
hinfo
,
struct
hda_codec
*
codec
,
unsigned
int
stream_tag
,
unsigned
int
format
,
struct
snd_pcm_substream
*
substream
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
return
snd_hda_multi_out_analog_prepare
(
codec
,
&
spec
->
multiout
,
stream_tag
,
format
,
substream
);
}
static
int
playback_pcm_cleanup
(
struct
hda_pcm_stream
*
hinfo
,
struct
hda_codec
*
codec
,
struct
snd_pcm_substream
*
substream
)
{
struct
hda_gen_spec
*
spec
=
codec
->
spec
;
return
snd_hda_multi_out_analog_cleanup
(
codec
,
&
spec
->
multiout
);
}
static
const
struct
hda_pcm_stream
alc269_44k_pcm_analog_playback
=
{
.
substreams
=
1
,
.
channels_min
=
2
,
.
channels_max
=
8
,
.
rates
=
SNDRV_PCM_RATE_44100
,
/* fixed rate */
/* NID is set in alc_build_pcms */
.
ops
=
{
.
open
=
playback_pcm_open
,
.
prepare
=
playback_pcm_prepare
,
.
cleanup
=
playback_pcm_cleanup
},
};
static
const
struct
hda_pcm_stream
alc269_44k_pcm_analog_capture
=
{
.
substreams
=
1
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_44100
,
/* fixed rate */
/* NID is set in alc_build_pcms */
};
/* different alc269-variants */
...
...
sound/pci/hda/patch_sigmatel.c
View file @
fc0daafe
...
...
@@ -4394,6 +4394,7 @@ static const struct hda_codec_ops stac_patch_ops = {
#ifdef CONFIG_PM
.
suspend
=
stac_suspend
,
#endif
.
stream_pm
=
snd_hda_gen_stream_pm
,
.
reboot_notify
=
stac_shutup
,
};
...
...
@@ -4487,6 +4488,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
return
err
;
spec
=
codec
->
spec
;
codec
->
power_mgmt
=
1
;
spec
->
linear_tone_beep
=
0
;
spec
->
gen
.
mixer_nid
=
0x1d
;
spec
->
have_spdif_mux
=
1
;
...
...
@@ -4592,6 +4594,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
codec
->
epss
=
0
;
/* longer delay needed for D3 */
spec
=
codec
->
spec
;
codec
->
power_mgmt
=
1
;
spec
->
linear_tone_beep
=
0
;
spec
->
gen
.
own_eapd_ctl
=
1
;
spec
->
gen
.
power_down_unused
=
1
;
...
...
@@ -4641,6 +4644,7 @@ static int patch_stac92hd95(struct hda_codec *codec)
codec
->
epss
=
0
;
/* longer delay needed for D3 */
spec
=
codec
->
spec
;
codec
->
power_mgmt
=
1
;
spec
->
linear_tone_beep
=
0
;
spec
->
gen
.
own_eapd_ctl
=
1
;
spec
->
gen
.
power_down_unused
=
1
;
...
...
@@ -4682,6 +4686,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
return
err
;
spec
=
codec
->
spec
;
codec
->
power_mgmt
=
1
;
spec
->
linear_tone_beep
=
0
;
spec
->
gen
.
own_eapd_ctl
=
1
;
spec
->
gen
.
power_down_unused
=
1
;
...
...
sound/pci/hda/patch_via.c
View file @
fc0daafe
...
...
@@ -99,7 +99,6 @@ struct via_spec {
/* HP mode source */
unsigned
int
dmic_enabled
;
unsigned
int
no_pin_power_ctl
;
enum
VIA_HDA_CODEC
codec_type
;
/* analog low-power control */
...
...
@@ -108,9 +107,6 @@ struct via_spec {
/* work to check hp jack state */
int
hp_work_active
;
int
vt1708_jack_detect
;
void
(
*
set_widgets_power_state
)(
struct
hda_codec
*
codec
);
unsigned
int
dac_stream_tag
[
4
];
};
static
enum
VIA_HDA_CODEC
get_codec_type
(
struct
hda_codec
*
codec
);
...
...
@@ -133,11 +129,12 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
/* VT1708BCE & VT1708S are almost same */
if
(
spec
->
codec_type
==
VT1708BCE
)
spec
->
codec_type
=
VT1708S
;
spec
->
no_pin_power_ctl
=
1
;
spec
->
gen
.
indep_hp
=
1
;
spec
->
gen
.
keep_eapd_on
=
1
;
spec
->
gen
.
pcm_playback_hook
=
via_playback_pcm_hook
;
spec
->
gen
.
add_stereo_mix_input
=
HDA_HINT_STEREO_MIX_AUTO
;
codec
->
power_mgmt
=
1
;
spec
->
gen
.
power_down_unused
=
1
;
return
spec
;
}
...
...
@@ -229,90 +226,6 @@ static void vt1708_update_hp_work(struct hda_codec *codec)
vt1708_stop_hp_work
(
codec
);
}
static
void
set_widgets_power_state
(
struct
hda_codec
*
codec
)
{
#if 0 /* FIXME: the assumed connections don't match always with the
* actual routes by the generic parser, so better to disable
* the control for safety.
*/
struct via_spec *spec = codec->spec;
if (spec->set_widgets_power_state)
spec->set_widgets_power_state(codec);
#endif
}
static
void
update_power_state
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
parm
)
{
if
(
snd_hda_check_power_state
(
codec
,
nid
,
parm
))
return
;
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
parm
);
}
static
void
update_conv_power_state
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
parm
,
unsigned
int
index
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
unsigned
int
format
;
if
(
snd_hda_check_power_state
(
codec
,
nid
,
parm
))
return
;
format
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_CONV
,
0
);
if
(
format
&&
(
spec
->
dac_stream_tag
[
index
]
!=
format
))
spec
->
dac_stream_tag
[
index
]
=
format
;
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
parm
);
if
(
parm
==
AC_PWRST_D0
)
{
format
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_CONV
,
0
);
if
(
!
format
&&
(
spec
->
dac_stream_tag
[
index
]
!=
format
))
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_CHANNEL_STREAMID
,
spec
->
dac_stream_tag
[
index
]);
}
}
static
bool
smart51_enabled
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
return
spec
->
gen
.
ext_channel_count
>
2
;
}
static
bool
is_smart51_pins
(
struct
hda_codec
*
codec
,
hda_nid_t
pin
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
i
;
for
(
i
=
0
;
i
<
spec
->
gen
.
multi_ios
;
i
++
)
if
(
spec
->
gen
.
multi_io
[
i
].
pin
==
pin
)
return
true
;
return
false
;
}
static
void
set_pin_power_state
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
unsigned
int
*
affected_parm
)
{
unsigned
parm
;
unsigned
def_conf
=
snd_hda_codec_get_pincfg
(
codec
,
nid
);
unsigned
no_presence
=
(
def_conf
&
AC_DEFCFG_MISC
)
>>
AC_DEFCFG_MISC_SHIFT
&
AC_DEFCFG_MISC_NO_PRESENCE
;
/* do not support pin sense */
struct
via_spec
*
spec
=
codec
->
spec
;
unsigned
present
=
0
;
no_presence
|=
spec
->
no_pin_power_ctl
;
if
(
!
no_presence
)
present
=
snd_hda_jack_detect
(
codec
,
nid
);
if
((
smart51_enabled
(
codec
)
&&
is_smart51_pins
(
codec
,
nid
))
||
((
no_presence
||
present
)
&&
get_defcfg_connect
(
def_conf
)
!=
AC_JACK_PORT_NONE
))
{
*
affected_parm
=
AC_PWRST_D0
;
/* if it's connected */
parm
=
AC_PWRST_D0
;
}
else
parm
=
AC_PWRST_D3
;
update_power_state
(
codec
,
nid
,
parm
);
}
static
int
via_pin_power_ctl_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
...
...
@@ -323,8 +236,7 @@ static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
via_spec
*
spec
=
codec
->
spec
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
!
spec
->
no_pin_power_ctl
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
codec
->
power_mgmt
;
return
0
;
}
...
...
@@ -333,12 +245,12 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
{
struct
hda_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
struct
via_spec
*
spec
=
codec
->
spec
;
unsigned
int
val
=
!
ucontrol
->
value
.
enumerated
.
item
[
0
];
bool
val
=
!
!
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
val
==
spec
->
no_pin_power_ctl
)
if
(
val
==
codec
->
power_mgmt
)
return
0
;
spec
->
no_pin_power_ctl
=
val
;
s
et_widgets_power_state
(
codec
)
;
codec
->
power_mgmt
=
val
;
s
pec
->
gen
.
power_down_unused
=
val
;
analog_low_current_mode
(
codec
);
return
1
;
}
...
...
@@ -383,7 +295,7 @@ static void __analog_low_current_mode(struct hda_codec *codec, bool force)
bool
enable
;
unsigned
int
verb
,
parm
;
if
(
spec
->
no_pin_power_ctl
)
if
(
!
codec
->
power_mgmt
)
enable
=
false
;
else
enable
=
is_aa_path_mute
(
codec
)
&&
!
spec
->
gen
.
active_streams
;
...
...
@@ -440,8 +352,7 @@ static int via_build_controls(struct hda_codec *codec)
if
(
err
<
0
)
return
err
;
if
(
spec
->
set_widgets_power_state
)
spec
->
mixers
[
spec
->
num_mixers
++
]
=
via_pin_power_ctl_enum
;
spec
->
mixers
[
spec
->
num_mixers
++
]
=
via_pin_power_ctl_enum
;
for
(
i
=
0
;
i
<
spec
->
num_mixers
;
i
++
)
{
err
=
snd_hda_add_new_ctls
(
codec
,
spec
->
mixers
[
i
]);
...
...
@@ -485,7 +396,6 @@ static int via_suspend(struct hda_codec *codec)
static
int
via_check_power_status
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
set_widgets_power_state
(
codec
);
analog_low_current_mode
(
codec
);
vt1708_update_hp_work
(
codec
);
return
snd_hda_check_amp_list_power
(
codec
,
&
spec
->
gen
.
loopback
,
nid
);
...
...
@@ -573,34 +483,6 @@ static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
{}
/* terminator */
};
static
void
via_jack_powerstate_event
(
struct
hda_codec
*
codec
,
struct
hda_jack_callback
*
tbl
)
{
set_widgets_power_state
(
codec
);
}
static
void
via_set_jack_unsol_events
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
struct
auto_pin_cfg
*
cfg
=
&
spec
->
gen
.
autocfg
;
hda_nid_t
pin
;
int
i
;
for
(
i
=
0
;
i
<
cfg
->
line_outs
;
i
++
)
{
pin
=
cfg
->
line_out_pins
[
i
];
if
(
pin
&&
is_jack_detectable
(
codec
,
pin
))
snd_hda_jack_detect_enable_callback
(
codec
,
pin
,
via_jack_powerstate_event
);
}
for
(
i
=
0
;
i
<
cfg
->
num_inputs
;
i
++
)
{
pin
=
cfg
->
line_out_pins
[
i
];
if
(
pin
&&
is_jack_detectable
(
codec
,
pin
))
snd_hda_jack_detect_enable_callback
(
codec
,
pin
,
via_jack_powerstate_event
);
}
}
static
const
struct
badness_table
via_main_out_badness
=
{
.
no_primary_dac
=
0x10000
,
.
no_dac
=
0x4000
,
...
...
@@ -634,7 +516,9 @@ static int via_parse_auto_config(struct hda_codec *codec)
if
(
err
<
0
)
return
err
;
via_set_jack_unsol_events
(
codec
);
/* disable widget PM at start for compatibility */
codec
->
power_mgmt
=
0
;
spec
->
gen
.
power_down_unused
=
0
;
return
0
;
}
...
...
@@ -647,7 +531,6 @@ static int via_init(struct hda_codec *codec)
snd_hda_sequence_write
(
codec
,
spec
->
init_verbs
[
i
]);
/* init power states */
set_widgets_power_state
(
codec
);
__analog_low_current_mode
(
codec
,
true
);
snd_hda_gen_init
(
codec
);
...
...
@@ -767,78 +650,6 @@ static int patch_vt1709(struct hda_codec *codec)
return
0
;
}
static
void
set_widgets_power_state_vt1708B
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
imux_is_smixer
;
unsigned
int
parm
;
int
is_8ch
=
0
;
if
((
spec
->
codec_type
!=
VT1708B_4CH
)
&&
(
codec
->
vendor_id
!=
0x11064397
))
is_8ch
=
1
;
/* SW0 (17h) = stereo mixer */
imux_is_smixer
=
(
snd_hda_codec_read
(
codec
,
0x17
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
((
spec
->
codec_type
==
VT1708S
)
?
5
:
0
));
/* inputs */
/* PW 1/2/5 (1ah/1bh/1eh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x1a
,
&
parm
);
set_pin_power_state
(
codec
,
0x1b
,
&
parm
);
set_pin_power_state
(
codec
,
0x1e
,
&
parm
);
if
(
imux_is_smixer
)
parm
=
AC_PWRST_D0
;
/* SW0 (17h), AIW 0/1 (13h/14h) */
update_power_state
(
codec
,
0x17
,
parm
);
update_power_state
(
codec
,
0x13
,
parm
);
update_power_state
(
codec
,
0x14
,
parm
);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x19
,
&
parm
);
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1b
,
&
parm
);
update_power_state
(
codec
,
0x18
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* PW6 (22h), SW2 (26h), AOW2 (24h) */
if
(
is_8ch
)
{
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x22
,
&
parm
);
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1a
,
&
parm
);
update_power_state
(
codec
,
0x26
,
parm
);
update_power_state
(
codec
,
0x24
,
parm
);
}
else
if
(
codec
->
vendor_id
==
0x11064397
)
{
/* PW7(23h), SW2(27h), AOW2(25h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x23
,
&
parm
);
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1a
,
&
parm
);
update_power_state
(
codec
,
0x27
,
parm
);
update_power_state
(
codec
,
0x25
,
parm
);
}
/* PW 3/4/7 (1ch/1dh/23h) */
parm
=
AC_PWRST_D3
;
/* force to D0 for internal Speaker */
set_pin_power_state
(
codec
,
0x1c
,
&
parm
);
set_pin_power_state
(
codec
,
0x1d
,
&
parm
);
if
(
is_8ch
)
set_pin_power_state
(
codec
,
0x23
,
&
parm
);
/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
update_power_state
(
codec
,
0x16
,
imux_is_smixer
?
AC_PWRST_D0
:
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
if
(
is_8ch
)
{
update_power_state
(
codec
,
0x25
,
parm
);
update_power_state
(
codec
,
0x27
,
parm
);
}
else
if
(
codec
->
vendor_id
==
0x11064397
&&
spec
->
gen
.
indep_hp_enabled
)
update_power_state
(
codec
,
0x25
,
parm
);
}
static
int
patch_vt1708S
(
struct
hda_codec
*
codec
);
static
int
patch_vt1708B
(
struct
hda_codec
*
codec
)
{
...
...
@@ -863,9 +674,6 @@ static int patch_vt1708B(struct hda_codec *codec)
}
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1708B
;
return
0
;
}
...
...
@@ -931,8 +739,6 @@ static int patch_vt1708S(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt1708S_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1708B
;
return
0
;
}
...
...
@@ -946,36 +752,6 @@ static const struct hda_verb vt1702_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt1702
(
struct
hda_codec
*
codec
)
{
int
imux_is_smixer
=
snd_hda_codec_read
(
codec
,
0x13
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
3
;
unsigned
int
parm
;
/* inputs */
/* PW 1/2/5 (14h/15h/18h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x14
,
&
parm
);
set_pin_power_state
(
codec
,
0x15
,
&
parm
);
set_pin_power_state
(
codec
,
0x18
,
&
parm
);
if
(
imux_is_smixer
)
parm
=
AC_PWRST_D0
;
/* SW0 (13h) = stereo mixer (idx 3) */
/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
update_power_state
(
codec
,
0x13
,
parm
);
update_power_state
(
codec
,
0x12
,
parm
);
update_power_state
(
codec
,
0x1f
,
parm
);
update_power_state
(
codec
,
0x20
,
parm
);
/* outputs */
/* PW 3/4 (16h/17h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x17
,
&
parm
);
set_pin_power_state
(
codec
,
0x16
,
&
parm
);
/* MW0 (1ah), AOW 0/1 (10h/1dh) */
update_power_state
(
codec
,
0x1a
,
imux_is_smixer
?
AC_PWRST_D0
:
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
update_power_state
(
codec
,
0x1d
,
parm
);
}
static
int
patch_vt1702
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
;
...
...
@@ -1005,8 +781,6 @@ static int patch_vt1702(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt1702_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1702
;
return
0
;
}
...
...
@@ -1021,71 +795,6 @@ static const struct hda_verb vt1718S_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt1718S
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
imux_is_smixer
;
unsigned
int
parm
,
parm2
;
/* MUX6 (1eh) = stereo mixer */
imux_is_smixer
=
snd_hda_codec_read
(
codec
,
0x1e
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
5
;
/* inputs */
/* PW 5/6/7 (29h/2ah/2bh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x29
,
&
parm
);
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
if
(
imux_is_smixer
)
parm
=
AC_PWRST_D0
;
/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
update_power_state
(
codec
,
0x1e
,
parm
);
update_power_state
(
codec
,
0x1f
,
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* outputs */
/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x27
,
&
parm
);
update_power_state
(
codec
,
0x1a
,
parm
);
parm2
=
parm
;
/* for pin 0x0b */
/* PW2 (26h), AOW2 (ah) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x26
,
&
parm
);
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
update_power_state
(
codec
,
0xa
,
parm
);
/* PW0 (24h), AOW0 (8h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x24
,
&
parm
);
if
(
!
spec
->
gen
.
indep_hp_enabled
)
/* check for redirected HP */
set_pin_power_state
(
codec
,
0x28
,
&
parm
);
update_power_state
(
codec
,
0x8
,
parm
);
if
(
!
spec
->
gen
.
indep_hp_enabled
&&
parm2
!=
AC_PWRST_D3
)
parm
=
parm2
;
update_power_state
(
codec
,
0xb
,
parm
);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
update_power_state
(
codec
,
0x21
,
imux_is_smixer
?
AC_PWRST_D0
:
parm
);
/* PW1 (25h), AOW1 (9h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x25
,
&
parm
);
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
update_power_state
(
codec
,
0x9
,
parm
);
if
(
spec
->
gen
.
indep_hp_enabled
)
{
/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x28
,
&
parm
);
update_power_state
(
codec
,
0x1b
,
parm
);
update_power_state
(
codec
,
0x34
,
parm
);
update_power_state
(
codec
,
0xc
,
parm
);
}
}
/* Add a connection to the primary DAC from AA-mixer for some codecs
* This isn't listed from the raw info, but the chip has a secret connection.
*/
...
...
@@ -1146,9 +855,6 @@ static int patch_vt1718S(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt1718S_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1718S
;
return
0
;
}
...
...
@@ -1188,7 +894,6 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
snd_hda_codec_write
(
codec
,
0x26
,
0
,
AC_VERB_SET_CONNECT_SEL
,
index
);
spec
->
dmic_enabled
=
index
;
set_widgets_power_state
(
codec
);
return
1
;
}
...
...
@@ -1223,95 +928,6 @@ static const struct hda_verb vt1716S_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt1716S
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
imux_is_smixer
;
unsigned
int
parm
;
unsigned
int
mono_out
,
present
;
/* SW0 (17h) = stereo mixer */
imux_is_smixer
=
(
snd_hda_codec_read
(
codec
,
0x17
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
5
);
/* inputs */
/* PW 1/2/5 (1ah/1bh/1eh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x1a
,
&
parm
);
set_pin_power_state
(
codec
,
0x1b
,
&
parm
);
set_pin_power_state
(
codec
,
0x1e
,
&
parm
);
if
(
imux_is_smixer
)
parm
=
AC_PWRST_D0
;
/* SW0 (17h), AIW0(13h) */
update_power_state
(
codec
,
0x17
,
parm
);
update_power_state
(
codec
,
0x13
,
parm
);
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x1e
,
&
parm
);
/* PW11 (22h) */
if
(
spec
->
dmic_enabled
)
set_pin_power_state
(
codec
,
0x22
,
&
parm
);
else
update_power_state
(
codec
,
0x22
,
AC_PWRST_D3
);
/* SW2(26h), AIW1(14h) */
update_power_state
(
codec
,
0x26
,
parm
);
update_power_state
(
codec
,
0x14
,
parm
);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x19
,
&
parm
);
/* Smart 5.1 PW2(1bh) */
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1b
,
&
parm
);
update_power_state
(
codec
,
0x18
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* PW7 (23h), SW3 (27h), AOW3 (25h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x23
,
&
parm
);
/* Smart 5.1 PW1(1ah) */
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1a
,
&
parm
);
update_power_state
(
codec
,
0x27
,
parm
);
/* Smart 5.1 PW5(1eh) */
if
(
smart51_enabled
(
codec
))
set_pin_power_state
(
codec
,
0x1e
,
&
parm
);
update_power_state
(
codec
,
0x25
,
parm
);
/* Mono out */
/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
present
=
snd_hda_jack_detect
(
codec
,
0x1c
);
if
(
present
)
mono_out
=
0
;
else
{
present
=
snd_hda_jack_detect
(
codec
,
0x1d
);
if
(
!
spec
->
gen
.
indep_hp_enabled
&&
present
)
mono_out
=
0
;
else
mono_out
=
1
;
}
parm
=
mono_out
?
AC_PWRST_D0
:
AC_PWRST_D3
;
update_power_state
(
codec
,
0x28
,
parm
);
update_power_state
(
codec
,
0x29
,
parm
);
update_power_state
(
codec
,
0x2a
,
parm
);
/* PW 3/4 (1ch/1dh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x1c
,
&
parm
);
set_pin_power_state
(
codec
,
0x1d
,
&
parm
);
/* HP Independent Mode, power on AOW3 */
if
(
spec
->
gen
.
indep_hp_enabled
)
update_power_state
(
codec
,
0x25
,
parm
);
/* force to D0 for internal Speaker */
/* MW0 (16h), AOW0 (10h) */
update_power_state
(
codec
,
0x16
,
imux_is_smixer
?
AC_PWRST_D0
:
parm
);
update_power_state
(
codec
,
0x10
,
mono_out
?
AC_PWRST_D0
:
parm
);
}
static
int
patch_vt1716S
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
;
...
...
@@ -1339,8 +955,6 @@ static int patch_vt1716S(struct hda_codec *codec)
spec
->
mixers
[
spec
->
num_mixers
++
]
=
vt1716S_mono_out_mixer
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1716S
;
return
0
;
}
...
...
@@ -1366,98 +980,6 @@ static const struct hda_verb vt1802_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt2002P
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
imux_is_smixer
;
unsigned
int
parm
;
unsigned
int
present
;
/* MUX9 (1eh) = stereo mixer */
imux_is_smixer
=
snd_hda_codec_read
(
codec
,
0x1e
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
3
;
/* inputs */
/* PW 5/6/7 (29h/2ah/2bh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x29
,
&
parm
);
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
parm
=
AC_PWRST_D0
;
/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
update_power_state
(
codec
,
0x1e
,
parm
);
update_power_state
(
codec
,
0x1f
,
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* outputs */
/* AOW0 (8h)*/
update_power_state
(
codec
,
0x8
,
parm
);
if
(
spec
->
codec_type
==
VT1802
)
{
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x28
,
&
parm
);
update_power_state
(
codec
,
0x18
,
parm
);
update_power_state
(
codec
,
0x38
,
parm
);
}
else
{
/* PW4 (26h), MW4 (1ch), MUX4(37h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x26
,
&
parm
);
update_power_state
(
codec
,
0x1c
,
parm
);
update_power_state
(
codec
,
0x37
,
parm
);
}
if
(
spec
->
codec_type
==
VT1802
)
{
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x25
,
&
parm
);
update_power_state
(
codec
,
0x15
,
parm
);
update_power_state
(
codec
,
0x35
,
parm
);
}
else
{
/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x25
,
&
parm
);
update_power_state
(
codec
,
0x19
,
parm
);
update_power_state
(
codec
,
0x35
,
parm
);
}
if
(
spec
->
gen
.
indep_hp_enabled
)
update_power_state
(
codec
,
0x9
,
AC_PWRST_D0
);
/* Class-D */
/* PW0 (24h), MW0(18h/14h), MUX0(34h) */
present
=
snd_hda_jack_detect
(
codec
,
0x25
);
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x24
,
&
parm
);
parm
=
present
?
AC_PWRST_D3
:
AC_PWRST_D0
;
if
(
spec
->
codec_type
==
VT1802
)
update_power_state
(
codec
,
0x14
,
parm
);
else
update_power_state
(
codec
,
0x18
,
parm
);
update_power_state
(
codec
,
0x34
,
parm
);
/* Mono Out */
present
=
snd_hda_jack_detect
(
codec
,
0x26
);
parm
=
present
?
AC_PWRST_D3
:
AC_PWRST_D0
;
if
(
spec
->
codec_type
==
VT1802
)
{
/* PW15 (33h), MW8(1ch), MUX8(3ch) */
update_power_state
(
codec
,
0x33
,
parm
);
update_power_state
(
codec
,
0x1c
,
parm
);
update_power_state
(
codec
,
0x3c
,
parm
);
}
else
{
/* PW15 (31h), MW8(17h), MUX8(3bh) */
update_power_state
(
codec
,
0x31
,
parm
);
update_power_state
(
codec
,
0x17
,
parm
);
update_power_state
(
codec
,
0x3b
,
parm
);
}
/* MW9 (21h) */
if
(
imux_is_smixer
||
!
is_aa_path_mute
(
codec
))
update_power_state
(
codec
,
0x21
,
AC_PWRST_D0
);
else
update_power_state
(
codec
,
0x21
,
AC_PWRST_D3
);
}
/*
* pin fix-up
*/
...
...
@@ -1541,8 +1063,6 @@ static int patch_vt2002P(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt2002P_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt2002P
;
return
0
;
}
...
...
@@ -1556,81 +1076,6 @@ static const struct hda_verb vt1812_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt1812
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
unsigned
int
parm
;
unsigned
int
present
;
/* inputs */
/* PW 5/6/7 (29h/2ah/2bh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x29
,
&
parm
);
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
parm
=
AC_PWRST_D0
;
/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
update_power_state
(
codec
,
0x1e
,
parm
);
update_power_state
(
codec
,
0x1f
,
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* outputs */
/* AOW0 (8h)*/
update_power_state
(
codec
,
0x8
,
AC_PWRST_D0
);
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x28
,
&
parm
);
update_power_state
(
codec
,
0x18
,
parm
);
update_power_state
(
codec
,
0x38
,
parm
);
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x25
,
&
parm
);
update_power_state
(
codec
,
0x15
,
parm
);
update_power_state
(
codec
,
0x35
,
parm
);
if
(
spec
->
gen
.
indep_hp_enabled
)
update_power_state
(
codec
,
0x9
,
AC_PWRST_D0
);
/* Internal Speaker */
/* PW0 (24h), MW0(14h), MUX0(34h) */
present
=
snd_hda_jack_detect
(
codec
,
0x25
);
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x24
,
&
parm
);
if
(
present
)
{
update_power_state
(
codec
,
0x14
,
AC_PWRST_D3
);
update_power_state
(
codec
,
0x34
,
AC_PWRST_D3
);
}
else
{
update_power_state
(
codec
,
0x14
,
AC_PWRST_D0
);
update_power_state
(
codec
,
0x34
,
AC_PWRST_D0
);
}
/* Mono Out */
/* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
present
=
snd_hda_jack_detect
(
codec
,
0x28
);
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x31
,
&
parm
);
if
(
present
)
{
update_power_state
(
codec
,
0x1c
,
AC_PWRST_D3
);
update_power_state
(
codec
,
0x3c
,
AC_PWRST_D3
);
update_power_state
(
codec
,
0x3e
,
AC_PWRST_D3
);
}
else
{
update_power_state
(
codec
,
0x1c
,
AC_PWRST_D0
);
update_power_state
(
codec
,
0x3c
,
AC_PWRST_D0
);
update_power_state
(
codec
,
0x3e
,
AC_PWRST_D0
);
}
/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x33
,
&
parm
);
update_power_state
(
codec
,
0x1d
,
parm
);
update_power_state
(
codec
,
0x3d
,
parm
);
}
/* patch for vt1812 */
static
int
patch_vt1812
(
struct
hda_codec
*
codec
)
{
...
...
@@ -1657,8 +1102,6 @@ static int patch_vt1812(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt1812_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt1812
;
return
0
;
}
...
...
@@ -1674,84 +1117,6 @@ static const struct hda_verb vt3476_init_verbs[] = {
{
}
};
static
void
set_widgets_power_state_vt3476
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
=
codec
->
spec
;
int
imux_is_smixer
;
unsigned
int
parm
,
parm2
;
/* MUX10 (1eh) = stereo mixer */
imux_is_smixer
=
snd_hda_codec_read
(
codec
,
0x1e
,
0
,
AC_VERB_GET_CONNECT_SEL
,
0x00
)
==
4
;
/* inputs */
/* PW 5/6/7 (29h/2ah/2bh) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x29
,
&
parm
);
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
if
(
imux_is_smixer
)
parm
=
AC_PWRST_D0
;
/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
update_power_state
(
codec
,
0x1e
,
parm
);
update_power_state
(
codec
,
0x1f
,
parm
);
update_power_state
(
codec
,
0x10
,
parm
);
update_power_state
(
codec
,
0x11
,
parm
);
/* outputs */
/* PW3 (27h), MW3(37h), AOW3 (bh) */
if
(
spec
->
codec_type
==
VT1705CF
)
{
parm
=
AC_PWRST_D3
;
update_power_state
(
codec
,
0x27
,
parm
);
update_power_state
(
codec
,
0x37
,
parm
);
}
else
{
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x27
,
&
parm
);
update_power_state
(
codec
,
0x37
,
parm
);
}
/* PW2 (26h), MW2(36h), AOW2 (ah) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x26
,
&
parm
);
update_power_state
(
codec
,
0x36
,
parm
);
if
(
smart51_enabled
(
codec
))
{
/* PW7(2bh), MW7(3bh), MUX7(1Bh) */
set_pin_power_state
(
codec
,
0x2b
,
&
parm
);
update_power_state
(
codec
,
0x3b
,
parm
);
update_power_state
(
codec
,
0x1b
,
parm
);
}
update_conv_power_state
(
codec
,
0xa
,
parm
,
2
);
/* PW1 (25h), MW1(35h), AOW1 (9h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x25
,
&
parm
);
update_power_state
(
codec
,
0x35
,
parm
);
if
(
smart51_enabled
(
codec
))
{
/* PW6(2ah), MW6(3ah), MUX6(1ah) */
set_pin_power_state
(
codec
,
0x2a
,
&
parm
);
update_power_state
(
codec
,
0x3a
,
parm
);
update_power_state
(
codec
,
0x1a
,
parm
);
}
update_conv_power_state
(
codec
,
0x9
,
parm
,
1
);
/* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x28
,
&
parm
);
update_power_state
(
codec
,
0x38
,
parm
);
update_power_state
(
codec
,
0x18
,
parm
);
if
(
spec
->
gen
.
indep_hp_enabled
)
update_conv_power_state
(
codec
,
0xb
,
parm
,
3
);
parm2
=
parm
;
/* for pin 0x0b */
/* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
parm
=
AC_PWRST_D3
;
set_pin_power_state
(
codec
,
0x24
,
&
parm
);
update_power_state
(
codec
,
0x34
,
parm
);
if
(
!
spec
->
gen
.
indep_hp_enabled
&&
parm2
!=
AC_PWRST_D3
)
parm
=
parm2
;
update_conv_power_state
(
codec
,
0x8
,
parm
,
0
);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
update_power_state
(
codec
,
0x3f
,
imux_is_smixer
?
AC_PWRST_D0
:
parm
);
}
static
int
patch_vt3476
(
struct
hda_codec
*
codec
)
{
struct
via_spec
*
spec
;
...
...
@@ -1775,9 +1140,6 @@ static int patch_vt3476(struct hda_codec *codec)
spec
->
init_verbs
[
spec
->
num_iverbs
++
]
=
vt3476_init_verbs
;
codec
->
patch_ops
=
via_patch_ops
;
spec
->
set_widgets_power_state
=
set_widgets_power_state_vt3476
;
return
0
;
}
...
...
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